Docker-in-Docker (DinD) capabilities of public runners deactivated. More info

graphs.py 7.4 KB
Newer Older
1
""" Controllers for building graphs using pandas library
LE GAC Renaud's avatar
LE GAC Renaud committed
2 3

"""
4 5 6 7
from citations_tools import (PLOT_CITATIONS_AVG,
                             PLOT_CITATIONS_HINDEX,
                             PLOT_CITATIONS_OVERVIEW,
                             PLOT_CITATIONS_TOTAL)
8
from gluon import current
LE GAC Renaud's avatar
LE GAC Renaud committed
9
from gluon.storage import Storage
10 11 12
from graph_tools import (FROM_TO,
                         LABELY_YEAR,
                         linechart,
13
                         mplstyle,
14
                         stackchart)
LE GAC Renaud's avatar
LE GAC Renaud committed
15
from matplotlib.figure import Figure
LE GAC Renaud's avatar
LE GAC Renaud committed
16
from models.selector import YEAR_SUBMIT
17 18


19
def citations():
20 21 22 23 24 25 26 27
    """Generate figures with citations plots.

    Returns:
        dict:
            * fig1 (matplotlib.Figure)
            * fig2 (matplotlib.Figure)
            * fig3 (matplotlib.Figure)
            * fig4 (matplotlib.Figure)
28 29

    """
30
    import pandas as pd
31
    import matplotlib as mpl
32 33 34 35 36 37

    from citations_tools import (estimator_versus_time,
                                 get_acl,
                                 h_index,
                                 histogram)

38
    from plugin_dbui import Selector
39
    from reporting_tools import repr_team_project
40

41
    mplstyle()
42 43 44 45 46 47 48 49

    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'

50 51 52 53 54 55 56
    pd.set_option("display.width", None)
    pd.set_option("display.max_rows", 500)

    # ........................................................................
    #
    # user criteria
    #
57 58
    selector = Selector(
        virtdb.graph_citation_selector,
59
        exclude_fields=("graphs", "year_start", "year_end"))
60

61 62
    year_start = selector.year_start
    year_end = selector.year_end
63

64 65 66 67
    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)
68

69 70
    elif isinstance(year_start, int):
        selector.append_query(db.publications.year == year_start)
71

72 73 74 75
    # ........................................................................
    #
    # prepare list of publications per scan
    #
76
    acl = get_acl(db, selector)
77

78 79 80
    cols = ["id_publication", "scan", "citations"]
    idx = ["id_publication"]
    fgroupby = False
81 82

    df = (acl[cols].set_index(idx))
83 84 85 86 87

    dct = {}
    for scan in acl.scan.unique():
        dct[scan] = (df[df.scan <= scan]
                     .citations
88
                     .groupby(idx).max())
89 90 91 92 93 94 95 96 97 98 99 100 101

    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
    #
102 103
    if selector.graphs == T(PLOT_CITATIONS_OVERVIEW):
        fig = histogram(df[last_scan], last_scan, legend)
104 105 106 107 108

    # ........................................................................
    #
    # Sum of citations as a function of time
    #
109 110 111 112 113 114 115 116
    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")
117 118 119 120 121

    # ........................................................................
    #
    # Average citations per article as a function of time
    #
122 123 124 125 126 127
    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")
128 129 130 131 132

    # ........................................................................
    #
    # h-index as a function of time
    #
133 134 135 136
    elif selector.graphs == T(PLOT_CITATIONS_HINDEX):

        data = (df.groupby(level=1).agg(h_index).T if fgroupby
                else df.apply(h_index))
137

138 139 140 141
        fig = estimator_versus_time(data,
                                    last_scan,
                                    legend,
                                    xtitle="h-index")
142 143 144 145 146

    # ........................................................................
    #
    # rendering
    #
147 148
    response.view = f"graphs/index.{request.extension}"
    dct = dict(fig=fig)
149
    return dct
150 151


LE GAC Renaud's avatar
LE GAC Renaud committed
152
def dashboard():
153
    """Return a pre-configure linechart for public used.
154
    Cumulative distribution for the publications are shown for
155
    the current year.
156

157 158 159 160
    Returns:
        dict:
            * fig (matplotlib.Figure)

161
    """
162
    current_year = request.now.year
163
    dashboard_start = current.app.dashboard_start_year
164 165 166 167 168 169 170 171 172 173 174

    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 = ""
175

176 177 178 179
    # figure layout and style
    mplstyle()
    fig = Figure()
    ax1, ax2 = fig.subplots(nrows=1, ncols=2, sharey=True)
180

181
    # the number of publications per year except for the current year
182 183
    # the starting value is defined in the preferences of the application
    min_year = ("" if dashboard_start is None else str(dashboard_start))
184 185 186
    max_year = str(current_year - 1)

    selector.Graph_selectorCumulative = "false"
187
    selector.Graph_selectorTime = T(YEAR_SUBMIT)
188 189
    selector.Graph_selectorYear_start = min_year
    selector.Graph_selectorYear_end = max_year
190

191 192
    title = T(FROM_TO) % (min_year, max_year)
    ylabel = T(LABELY_YEAR)
193

194 195 196 197 198 199
    linechart(db,
              selector,
              target=ax1,
              xlabel="",
              ylabel=ylabel,
              title=title)
200

201 202 203
    # the cumulative sum of publications for the current year on a month
    year = str(current_year)
    selector.Graph_selectorCumulative = "true"
204
    selector.Graph_selectorTime = T(YEAR_SUBMIT)
205 206 207
    selector.Graph_selectorYear_start = year
    selector.Graph_selectorYear_end = ""

208
    title = T("In %s") % year
209
    linechart(db, selector, target=ax2, title=title)
210 211 212

    # delegate the rendering to the view
    response.view = "graphs/index.html"
213
    return dict(fig=fig)
214 215


216
def publications_versus_time():
217
    """Generate graph showing the number of publication per month / year
218
    either as a line chart or as a stacked histograms.
219

220
    """
221 222 223 224
    # user criteria and graph configuration
    selector = request.vars
    graph = db.graphs[selector.Graph_selectorId_graphs]
    axis = graph.stack_axis
LE GAC Renaud's avatar
LE GAC Renaud committed
225

226 227 228 229 230 231 232 233 234 235
    # 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)
236

237
    # delegate the rendering to the view
238 239
    response.view = f"graphs/index.{request.extension}"
    return dict(fig=fig)