""" Controllers for building graphs using pandas library """ from citations_tools import (PLOT_CITATIONS_AVG, PLOT_CITATIONS_HINDEX, PLOT_CITATIONS_OVERVIEW, PLOT_CITATIONS_TOTAL) from gluon import current from gluon.storage import Storage from graph_tools import (FROM_TO, LABELY_YEAR, linechart, mplstyle, stackchart) from matplotlib.figure import Figure from models.selector import YEAR_SUBMIT def citations(): """Generate figures with citations plots. Returns: dict: * fig1 (matplotlib.Figure) * fig2 (matplotlib.Figure) * fig3 (matplotlib.Figure) * fig4 (matplotlib.Figure) """ import pandas as pd import matplotlib as mpl from citations_tools import (estimator_versus_time, get_acl, h_index, histogram) from plugin_dbui import Selector from reporting_tools import repr_team_project mplstyle() mpl.rcParams['date.autoformatter.year'] = '%Y' mpl.rcParams['date.autoformatter.month'] = '%b' mpl.rcParams['date.autoformatter.day'] = '%d %b' mpl.rcParams['date.autoformatter.hour'] = '%b %d %H' mpl.rcParams['date.autoformatter.minute'] = '%H:%M' mpl.rcParams['date.autoformatter.second'] = '%H:%M:%S' pd.set_option("display.width", None) pd.set_option("display.max_rows", 500) # ........................................................................ # # user criteria # selector = Selector( virtdb.graph_citation_selector, exclude_fields=("graphs", "year_start", "year_end")) year_start = selector.year_start year_end = selector.year_end if isinstance(year_start, int) and isinstance(year_end, int): query = db.publications.year >= year_start query &= db.publications.year <= year_end selector.append_query(query) elif isinstance(year_start, int): selector.append_query(db.publications.year == year_start) # ........................................................................ # # prepare list of publications per scan # acl = get_acl(db, selector) cols = ["id_publication", "scan", "citations"] idx = ["id_publication"] fgroupby = False df = (acl[cols].set_index(idx)) dct = {} for scan in acl.scan.unique(): dct[scan] = (df[df.scan <= scan] .citations .groupby(idx).max()) df = pd.DataFrame(dct) df = df[sorted(df.columns)] last_scan = df.columns[-1] legend = [ f"{T('period:')} {acl.year.min()} - {acl.year.max()}", f"{T('articles analysed:')} {df[last_scan].count()}"] # ........................................................................ # # histogram citations for the last scan # if selector.graphs == T(PLOT_CITATIONS_OVERVIEW): fig = histogram(df[last_scan], last_scan, legend) # ........................................................................ # # Sum of citations as a function of time # elif selector.graphs == T(PLOT_CITATIONS_TOTAL): data = (df.groupby(level=1).sum().T if fgroupby else df.sum()) fig = estimator_versus_time(data, last_scan, legend, delta=not fgroupby, logy=fgroupby, xtitle="$\sum$ citations") # ........................................................................ # # Average citations per article as a function of time # elif selector.graphs == T(PLOT_CITATIONS_AVG): data = (df.groupby(level=1).mean().T if fgroupby else df.mean()) fig = estimator_versus_time(data, last_scan, legend, xtitle="mean citations / article") # ........................................................................ # # h-index as a function of time # elif selector.graphs == T(PLOT_CITATIONS_HINDEX): data = (df.groupby(level=1).agg(h_index).T if fgroupby else df.apply(h_index)) fig = estimator_versus_time(data, last_scan, legend, xtitle="h-index") # ........................................................................ # # rendering # response.view = f"graphs/index.{request.extension}" dct = dict(fig=fig) return dct def dashboard(): """Return a pre-configure linechart for public used. Cumulative distribution for the publications are shown for the current year. Returns: dict: * fig (matplotlib.Figure) """ current_year = request.now.year dashboard_start = current.app.dashboard_start_year selector = Storage() selector.Graph_selectorCumulative = "true" selector.Graph_selectorId = "" selector.Graph_selectorId_authors_roles = "" selector.Graph_selectorId_graphs = "" selector.Graph_selectorId_projects = "" selector.Graphs_selectorId_teams = "" selector.Graph_selectorTime = "" selector.Graph_selectorYear_start = "" selector.Graph_selectorYear_end = "" # figure layout and style mplstyle() fig = Figure() ax1, ax2 = fig.subplots(nrows=1, ncols=2, sharey=True) # the number of publications per year except for the current year # the starting value is defined in the preferences of the application min_year = ("" if dashboard_start is None else str(dashboard_start)) max_year = str(current_year - 1) selector.Graph_selectorCumulative = "false" selector.Graph_selectorTime = T(YEAR_SUBMIT) selector.Graph_selectorYear_start = min_year selector.Graph_selectorYear_end = max_year title = T(FROM_TO) % (min_year, max_year) ylabel = T(LABELY_YEAR) linechart(db, selector, target=ax1, xlabel="", ylabel=ylabel, title=title) # the cumulative sum of publications for the current year on a month year = str(current_year) selector.Graph_selectorCumulative = "true" selector.Graph_selectorTime = T(YEAR_SUBMIT) selector.Graph_selectorYear_start = year selector.Graph_selectorYear_end = "" title = T("In %s") % year linechart(db, selector, target=ax2, title=title) # delegate the rendering to the view response.view = "graphs/index.html" return dict(fig=fig) def publications_versus_time(): """Generate graph showing the number of publication per month / year either as a line chart or as a stacked histograms. """ # user criteria and graph configuration selector = request.vars graph = db.graphs[selector.Graph_selectorId_graphs] axis = graph.stack_axis # figure and style mplstyle() fig = Figure() ax = fig.subplots(nrows=1, ncols=1) # create the plot if axis: stackchart(db, selector, target=ax) else: linechart(db, selector, target=ax) # delegate the rendering to the view response.view = f"graphs/index.{request.extension}" return dict(fig=fig)