예제 #1
0
    def test_write_html_with_bibliography(self):
        csl_file_path = gv.resources_path.joinpath('apa.csl')
        css_file_path = gv.resources_path.joinpath('buttondown.css')
        rel=Text("Some Text")
        rel+=Newline()
        e=BibtexEntry.from_doi(doi="10.1139/x91-133")
        print("#################################################")
        print(e)
        print("#################################################")
        rel+=Citation(e,parentheses=True)
        rel+=Text("This is some text between the citations")
        rel+=Newline()
        rel+=Citation(BibtexEntry.from_doi(doi="10.1556/Select.2.2001.1-2.14"))
        rel+=Text("This is some text after the citation")
        rel+=Newline()
        rel+=Text("This is second citation of the first paper")
        #rel+=Citation(BibtexEntry.from_doi(doi="10.1139/x91-133"),parentheses=True)

        html_file_path="text_with_citation.html"
        bibtex_file_name="text_with_citation.bibtex"
        print('#######################################')
        rel.write_pandoc_html(html_file_path,csl_file_path,css_file_path)
        
        self.assertTrue(Path(html_file_path).exists())
        # check that the bibtex file is there
        self.assertTrue(Path(bibtex_file_name).exists())
        # check deduplication
        # read the bibtexfile with bibtexparser and 
        # make sure that only two entries are present 
        # which presupposes that the parser does not deduplicate
        et=entry_list_from_file(bibtex_file_name)
        self.assertEqual(len(et),2)
예제 #2
0
 def test_TableRow(self):
     var("x")
     expr=sqrt(2/x)
     tr=TableRow([Text("first col $name",name="test")+Math("a=$a",a=expr),Math("2*a=$a$a",a=expr)])
     self.assertEqual(
         tr.pandoc_markdown(),
         r"first col test$a=\sqrt{2}\cdot\sqrt{\frac{1}{x}}$|$2*a=\sqrt{2}\cdot\sqrt{\frac{1}{x}}\sqrt{2}\cdot\sqrt{\frac{1}{x}}$"
     )
예제 #3
0
 def test_ReportElementList(self):
     var("x")
     expr=sqrt(2/x)
     rel=ReportElementList([Text("name=:$n",n="Markus"),Math("a=$a",a=expr)])
     self.assertEqual(
         rel.pandoc_markdown(),
         r"name=:Markus$a=\sqrt{2}\cdot\sqrt{\frac{1}{x}}$"
     )
예제 #4
0
    def test_Text(self):
        t=Text(remove_indentation("""\
                                     ---
                                     title: Model $title
                                     author: $entryAuthor
                                     ---
                                  """), title="Model title", entryAuthor="Veronika")
        target_string = remove_indentation("""\
                          ---
                          title: Model Model title
                          author: Veronika
                          ---
                          """)
        self.assertEqual(t.pandoc_markdown(), target_string)

        desc = "Reference to $F_NSC$, not to $F_{x}$"
        t = Text("$d", d=desc)
        target_string = "Reference to $F_{NSC}$, not to $F_{x}$"
        self.assertEqual(t.pandoc_markdown(), target_string)
예제 #5
0
 def test_add(self):
     var("x")
     expr=sqrt(2/x)
     rel=Text("name=:$n",n="Markus")+Math("a=$a",a=expr)
     self.assertEqual(
         rel.pandoc_markdown(),
         r"name=:Markus$a=\sqrt{2}\cdot\sqrt{\frac{1}{x}}$"
     )
     # add a case where lists are added to lists
     rel2=rel+rel
     self.assertEqual(
         rel2.pandoc_markdown(),
         r"name=:Markus$a=\sqrt{2}\cdot\sqrt{\frac{1}{x}}$name=:Markus$a=\sqrt{2}\cdot\sqrt{\frac{1}{x}}$"
     )
     # add a case where a Report element is  added to a list
     rel3=rel+Text("Markus")
     self.assertEqual(
         rel3.pandoc_markdown(),
         r"name=:Markus$a=\sqrt{2}\cdot\sqrt{\frac{1}{x}}$Markus"
     )
예제 #6
0
 def test_Table(self):
     # we create a table by giving the firs row
     headers_row=TableRow([Text("name of first column"),Text("name of second column")])
     # and the formats as a list of strings
     formats=["c","l"]
     t=Table("first Table", headers_row,formats)
     var("x")
     expr=sqrt(2/x)
     t.add_row(TableRow([Math("a=$a",a=expr),Math("b=$b",b=2*expr)]))
     res=t.pandoc_markdown()
     self.maxDiff = None
     # the (partly invisible)  spaces at the end of the lins are important since they
     # are interpreted by pandoc as newlines
     ref=r"""  
       
     name of first column|name of second column  
     :-----:|:-----  
     $a=\sqrt{2}\cdot\sqrt{\frac{1}{x}}$|$b=2\cdot\sqrt{2}\cdot\sqrt{\frac{1}{x}}$  
       Table: first Table  
     """
     ref=ref.replace("        ","") # do not use remove_indentation() since it will also remove the needed spaces
     self.assertEqual(res,ref)
예제 #7
0
 def test_write_html_with_picture(self):
     csl_file_path = gv.resources_path.joinpath('apa.csl')
     css_file_path = gv.resources_path.joinpath('buttondown.css')
     rel=Text("some text before the first picture")
     fig=plt.figure()
     x_values=[2*pi/100*i for i in range(0,100)]
     y_values=[sin(x) for x in x_values]
     fig.add_subplot(1,1,1).plot(x_values,y_values)
     
     fig2=plt.figure()
     n=1000
     x=np.array([i/(2*n) for i in range(-n,n)],dtype="float")
     y=np.exp(-x**2/2)
     ax0=fig2.add_subplot(1,1,1)
     number_of_bins=20
     ax0.hist(y, number_of_bins, normed=1, histtype='stepfilled', facecolor='g', alpha=0.75)
     rel+=MatplotlibFigure(fig,"Label","caption text2 ") 
     rel+=Newline()
     
     rel+=Text("some text before the second picture")
     rel+=MatplotlibFigure(fig2,"differentLabel","caption text 2") 
     # now refer to the figures from the text
     html_file_path="text_with_figure.html"
     rel.write_pandoc_html(html_file_path,csl_file_path,css_file_path)
예제 #8
0
 def test_iadd(self):
     var("x")
     expr=sqrt(2/x)
     rel=Text("name=:$n",n="Markus")
     rel+=Math("a=$a",a=expr)
     self.assertEqual(
         rel.pandoc_markdown(),
         r"name=:Markus$a=\sqrt{2}\cdot\sqrt{\frac{1}{x}}$"
     )
     # add a case where lists are added to lists
     rel2=rel
     rel2+=rel
     self.assertEqual(
         rel2.pandoc_markdown(),
         r"name=:Markus$a=\sqrt{2}\cdot\sqrt{\frac{1}{x}}$name=:Markus$a=\sqrt{2}\cdot\sqrt{\frac{1}{x}}$"
     )
예제 #9
0
 def test_write_pandoc_markdown(self):
     var("x")
     expr=sqrt(2/x)
     rel=Text("name=:$n",n="Markus")+Math("a=$a",a=expr)
     rel.write_pandoc_markdown(Path("report.md"))
예제 #10
0
 def test_mul(self):
     rel = Text("x")*3
     self.assertEqual(rel.pandoc_markdown(), "xxx")
예제 #11
0
파일: reports.py 프로젝트: saru0000/bgc-md
def report_from_model(model):
    #rel = model.get_meta_data_report()
    #rel = Meta(model.long_name, model.name, model.version)
    rel = ReportElementList()
    rel += Header("General Overview", 1)

    reservoir_model = model.reservoir_model
    if reservoir_model:
        plt.rc('text', usetex=True)
        plt.rc('font', family='serif')
        rel += MatplotlibFigure(reservoir_model.figure(logo=True),
                                "Logo",
                                show_label=False,
                                transparent=True)
        #logofig = reservoir_model.figure(logo=True)
        #logofig.savefig('ICBM_logo.svg', transparent=True)
        #plt.show(logofig)
        #print('Logo printed')

    rel += Text(
        r"This report is the result of the use of the python package bgc_md, as means to translate published models to a common language.  The underlying yaml file was created by $curator (Orcid ID: $Oid) on $entryDate, and was last modified on $modDate."
        + "\n",
        curator=model.entryAuthor,
        entryDate=model.entry_creation_date,
        modDate=model.last_modification_date,
        Oid=model.entryAuthor_orc_id,
    )

    if model.model_type == "vegetation_model": modType = "carbon allocation"
    if model.model_type == "soil_model":
        modType = "soil organic matter decomposition"

    if model.approach:
        article = "a"
        if model.approach[0] in "aeiou":
            article = "an"
        modApproach = " with " + article + " " + model.approach + " approach."
    else:
        modApproach = "."

    rel += Header("About the model", 2)
    rel += Text(
        r"The model depicted in this document considers $modType$modApproach It was originally described by ",
        modType=modType,
        modApproach=modApproach)
    rel += Citation(model.bibtex_entry, parentheses=False) + Text(".  \n")

    # fixme: further references
    # include further references
    if model.further_references:
        rel += Header("Further references", 3)
        for ref_dict in model.further_references:
            rel += Citation(ref_dict['bibtex_entry'], parentheses=False)
            if 'desc' in ref_dict.keys():
                rel += Text(": $desc", desc=ref_dict['desc'])
            rel += Text("\n")

    # include the abstract
    if hasattr(model, "abstract"):
        rel += Header("Abstract", 3)
        rel += Text("$abstract", abstract=model.abstract + "\n")

    # include keywords
    if model.keywords:
        rel += Header("Keywords", 3)
        rel += Text("$k\n", k=(", ").join(model.keywords))

    # include principles
    if model.principles:
        rel += Header("Principles", 3)
        rel += Text("$k\n", k=(", ").join(model.principles))

    # include spaceScale:
    if model.spaceScale:
        rel += Header("Space Scale", 3)

        space_scale = model.spaceScale
        if type(space_scale) == type(""):
            space_scale = [space_scale]
        rel += Text("$k\n", k=(", ").join(space_scale))

    # include information on available parameter sets
    if model.parameter_sets:
        desc_exists = False
        colname_list = [Text("Abbreviation")]
        format_list = ["l"]
        for par_set in model.parameter_sets:
            sources_exist = False
            desc_exists = False
            if 'bibtex_entry' in par_set.keys() and par_set['bibtex_entry']:
                sources_exist = True
            if 'desc' in par_set.keys() and par_set['desc']: desc_exists = True

        if desc_exists:
            colname_list.append(Text("Description"))
            format_list.append("l")
        if sources_exist:
            colname_list.append(Text("Source"))
            format_list.append("l")

        # show this section only if additional information to the parameter sets is given
        if len(colname_list) > 1:
            rel += Header("Available parameter values", 3)
            headers_row = TableRow(colname_list)
            T = Table(" Information on given parameter sets", headers_row,
                      format_list)
            for par_set in model.parameter_sets:
                l = [Text(par_set['table_head'])]
                if desc_exists:
                    if par_set['desc']:
                        l.append(Text(par_set['desc']))
                    else:
                        l.append(Text(" "))

                if sources_exist:
                    if par_set['bibtex_entry']:
                        l.append(
                            Citation(par_set['bibtex_entry'],
                                     parentheses=False))
                    else:
                        l.append(Text(" "))

                tr = TableRow(l)
                T.add_row(tr)
            rel += T

    # include information on available initial values sets
    if model.initial_values:
        desc_exists = False
        colname_list = [Text("Abbreviation")]
        format_list = ["l"]
        for par_set in model.initial_values:
            if 'bibtex_entry' in par_set.keys() and par_set['bibtex_entry']:
                sources_exist = True
            if 'desc' in par_set.keys() and par_set['desc']: desc_exists = True

        if desc_exists:
            colname_list.append(Text("Description"))
            format_list.append("l")
        if sources_exist:
            colname_list.append(Text("Source"))
            format_list.append("l")

        # show this section only if additional information to the initial values sets is given
        if len(colname_list) > 1:
            rel += Header("Available initial values", 3)
            headers_row = TableRow(colname_list)
            T = Table(" Information on given sets of initial values",
                      headers_row, format_list)
            for par_set in model.initial_values:
                l = [Text(par_set['table_head'])]
                if desc_exists:
                    if par_set['desc']:
                        l.append(Text(par_set['desc']))
                    else:
                        l.append(Text(" "))

                if sources_exist:
                    if par_set['bibtex_entry']:
                        l.append(
                            Citation(par_set['bibtex_entry'],
                                     parentheses=False))
                    else:
                        l.append(Text(" "))

                tr = TableRow(l)
                T.add_row(tr)
            rel += T

    # show the secions of the model data
    for section_name in model.sections:
        if section_name == 'state_variables':
            rel += Header(model.section_titles[section_name], 1)
            rel += Text(
                "The following table contains the available information regarding this section:"
            )
            rel += model.state_variables_Table()
        elif section_name == 'additional_variables':
            rel += Header(model.section_titles[section_name], 1)
            rel += Text(
                "The following table contains the available information regarding this section:"
            )
            rel += model.additional_variables_Table()
        elif section_name == 'allocation_coefficients':
            rel += Header(model.section_titles[section_name], 1)
            rel += Text(
                "The following table contains the available information regarding this section:"
            )
            rel += model.allocation_coefficients_Table()
        elif section_name == 'components':
            rel += Header(model.section_titles[section_name], 1)
            rel += Text(
                "The following table contains the available information regarding this section:"
            )
            rel += model.components_Table()
        elif section_name == 'parameter_sets':
            # parameter_sets are treated completely differently
            pass
        else:
            # custom section to be included in the report
            rel += Header(model.section_titles[section_name], 1)
            rel += Text(
                "The following table contains the available information regarding this section:"
            )
            rel += model.variables_Table_from_section(section_name,
                                                      parameter_values=True)

    # include pool model plot
    if reservoir_model:
        inputs = reservoir_model.input_fluxes
        outputs = reservoir_model.output_fluxes
        internal_fluxes = reservoir_model.internal_fluxes
        #        inputs, outputs, internal_fluxes = model.fluxes

        rel += Text("\n")
        rel += Header("Pool model representation", 2)

        header = [Text("Pool model"), Text("Fluxes")]
        header_row = TableRow(header)
        T = Text("<table>")
        T += Text("<thead>")
        T += Text("<tr><th></th><th>Flux description</th></tr>")
        T += Text("</thead><tbody>")
        T += Text("<tr>")
        T += Text("<td align=center, style='vertical-align: middle'>")
        fig = reservoir_model.figure(figure_size=(7, 7))
        fig_rel = MatplotlibFigure(fig, "Figure 1",
                                   "Pool model representation")
        #T += fig_rel.pandoc_markdown()
        T += fig_rel
        T += Text("</td><td align=left style='vertical-align: middle'>")

        # write the fluxes to the table
        legend = ReportElementList([])

        # input fluxes
        if len(inputs) > 0:
            legend += Header("Input fluxes", 4)
            for pool, flux in inputs.items():
                legend += Math("$v: $f",
                               v=py2tex_silent(model.state_variables[pool]),
                               f=flux)
                legend += Newline()

        # output fluxes
        if len(outputs) > 0:
            legend += Text("\n")
            legend += Header("Output fluxes", 4)
            for pool, flux in outputs.items():
                legend += Math("$v: $f",
                               v=py2tex_silent(model.state_variables[pool]),
                               f=flux)
                legend += Newline()

        # internal fluxes
        if len(internal_fluxes) > 0:
            legend += Text("\n")
            legend += Header("Internal fluxes", 4)
            if_sorted = [((i, j), f) for (i, j), f in internal_fluxes.items()]
            if_sorted = sorted(if_sorted, key=lambda el: (el[0][0], el[0][1]))
            for (pfrom, pto), flux in if_sorted:
                legend += Math("$pf \\rightarrow $pt: $f",
                               pf=py2tex_silent(model.state_variables[pfrom]),
                               pt=py2tex_silent(model.state_variables[pto]),
                               f=flux)
                legend += Newline()

        T += legend
        T += Text("</td></tr>")
        T += Text("</tbody></table>")

        rel += T

    # include RHS and jacobian
    rel += Header("The right hand side of the ODE", 2)
    rel += Math("$eq", eq=model.rhs)
    rel += Text("\n")
    rel += Header(
        "The Jacobian (derivative of the ODE w.r.t. state variables)", 2)
    rel += Math("$J", J=model.jacobian())

    rel += Text("\n")

    #fixme: suggested steady states
    # check suggested steady states

    #    rhs = model.rhs
    #    sug_ss = model.complete_dict['suggested_steady_states']
    #    sug_ss = {key: sympify(val, locals=model.symbols_by_type) for key, val in sug_ss[0].items()}
    #    sug_ss.update({'alpha': 1, 'beta': 0.5, 'Phi_i': 0, 'Phi_o': 0, 'Phi_up': 0, 'Phi_l': 0, 'A': 5.2, 'r': 2, 's': 1, 'i':1})
    #    ss = rhs.subs(sug_ss)
    #    for i in range(len(ss)):
    #        ss[i] = simplify(ss[i])
    #        print(ss[i])

    # try to calculate the steady states for ten seconds
    # after ten seconds stop it
    q = multiprocessing.Queue()

    def calc_steady_states(q):
        #        rhs = Matrix(list(model.rhs)[1:])
        #        sv = Matrix(list(model.state_vector['expr'])[1:])

        ss = solve(model.rhs, model.state_vector['expr'], dict=True)

        #        ss = solve(rhs, sv, dict=True)
        #        srhs = rhs.subs(ss[0])
        #        for i in range(len(srhs)):
        #            print(simplify(srhs[i]))
        q.put(ss)

    p = multiprocessing.Process(target=calc_steady_states, args=(q, ))
    p.start()
    p.join(10)
    if p.is_alive():
        p.terminate()
        p.join()
        steady_states = []
    else:
        steady_states = q.get()

#    rhs = model.rhs
#    srhs = rhs.subs(steady_states[0])
#    for i in range(len(srhs)):
#        print(simplify(srhs[i]))

# check if steady states have all state variables
#    formal_steady_states = []
#    for ss in steady_states:
#        if len(ss) == len(model.state_vector['expr']):
#            formal_steady_states.append(simplify(ss))

    formal_steady_states = steady_states
    if formal_steady_states:
        rel += Header("Steady state formulas", 2)
        for ss in formal_steady_states:
            for sv_symbol in model.state_vector['expr']:
                if sv_symbol in ss.keys():
                    ss[sv_symbol] = simplify(ss[sv_symbol])
                else:
                    ss[sv_symbol] = sv_symbol

                rel += Math("$name = $value",
                            name=sv_symbol,
                            value=ss[sv_symbol]) + Newline()
            rel += Newline()

    # include parameter set information: steady states, eigenvalues, damping ratios
#    complete_parameter_sets = [par_set for par_set in model.parameter_sets if check_parameter_set_complete(par_set, model.state_vector, model.time_symbol, model.state_vector_derivative)]

    if model.time_symbol:
        time_symbol = model.time_symbol['symbol']
    else:
        time_symbol = None

    complete_parameter_sets = model.parameter_sets
    if formal_steady_states and complete_parameter_sets:
        rel += Text("\n")
        rel += Header(
            "Steady states (potentially incomplete), according jacobian eigenvalues, damping ratio",
            2)
        for par_set in complete_parameter_sets:
            header_str = "Parameter set: " + par_set['table_head']
            rel += Header(header_str, 3)

            rhs = model.rhs
            steady_states = solve(rhs.subs(par_set['values']),
                                  model.state_vector['expr'],
                                  dict=True)
            #steady_states = solve(rhs, model.state_vector['expr'], dict=True)
            for ss in steady_states:
                # check if steady state calculation could solve for all state variables
                #                if len(ss) == len(model.state_vector['expr']):
                ss_list = []
                for sv_symbol in model.state_vector['expr']:
                    if sv_symbol in ss.keys():
                        ss_expr = ss[sv_symbol]
                    else:
                        ss_expr = sv_symbol

                    if time_symbol in ss_expr.free_symbols:
                        # take limit of time to infinity if steady state still depends on time
                        ss_expr = limit(ss_expr, time_symbol, oo)
                        rel += Text("\nTaken limit ") + Math(
                            "$sv($t)", sv=sv_symbol, t=time_symbol)
                        rel += Text(" for ") + Math("$t", t=time_symbol)
                        rel += Text(" to infinity.\n\n")

                    sv_name = key_from_dict_by_value(model.symbols_by_type,
                                                     sv_symbol)

                    ss_list.append({
                        'name': sv_name,
                        'symbol': sv_symbol,
                        'value': ss_expr
                    })

                for i in range(len(ss_list)):
                    if ss_list[i]['value'].free_symbols == set():
                        if ss_list[i]['value'] < 0:
                            rel += Text('<font color="FF0000">')
                            rel += Math(ss_list[i]['name'] + ": $v",
                                        v=round(ss_list[i]['value'], 3))
                            rel += Text('</font>')
                        else:
                            rel += Math(ss_list[i]['name'] + ": $v",
                                        v=round(ss_list[i]['value'], 3))
                    else:
                        rel += Math(ss_list[i]['name'] + ": $v",
                                    v=ss_list[i]['value'])

                    if i < len(ss_list) - 1:
                        rel += Text(", ")

                rel += Newline() * 2

                dic = par_set['values']
                for i in range(len(ss_list)):
                    dic[ss_list[i]['name']] = ss_list[i]['value']

                jacobian = model.jacobian().subs(dic)
                if jacobian.free_symbols == set():
                    evs = [complex(v) for v in jacobian.eigenvals().keys()]
                else:
                    evs = [v for v in jacobian.eigenvals().keys()]

                for i in range(len(evs)):
                    ev = evs[i]

                    if jacobian.free_symbols == set():
                        if ev.imag == 0:
                            ev = ev.real

                        lamda_i = Symbol('lamda_' + str(i + 1))
                        rel += Math("$s: $v", s=lamda_i,
                                    v="{:.3f}".format(ev)) + Newline()

                        if ev.imag != 0:
                            rho = -ev.real / np.sqrt(ev.real**2 + ev.imag**2)
                            rel += Math("$s: $v",
                                        s=Symbol("rho_" + str(i + 1)),
                                        v="{:-3f}".format(rho)) + Newline()
                    else:
                        lamda_i = Symbol('lamda_' + str(i + 1))
                        rel += Math("$s: $v", s=lamda_i,
                                    v=ev.evalf(4)) + Newline()

                        #if ev.imag != 0:
                        #    rho = -ev.real/np.sqrt(ev.real**2+ev.imag**2)
                        #    rel += Math("$s: $v", s = Symbol("rho_"+ str(i+1)), v = "{:-3f}".format(rho)) + Newline()

                rel += Text("\n") * 2

    #fixme
#    steady_states=solve(model.rhs, model.state_vector['expr'], dict=True)

# include model simulations
    if reservoir_model and model.model_runs:
        rel += Header("Model simulations", 2)

        model_runs = model.model_runs
        for i, mr in enumerate(model_runs):
            comb = model.model_run_combinations[i]
            par_set = comb['par_set']['values']

            run_data_str_basis = "Initial values: " + comb['IV']['table_head']
            run_data_str_basis += ", Parameter set: " + comb['par_set'][
                'table_head']

            # plot solutions
            fig = plt.figure(figsize=(7, 3 * len(model.state_vector["expr"])),
                             tight_layout=True)
            #            time_unit = model.df.get_by_cond('unit', 'name', model.time_symbol['name'])
            #            units = [model.df.get_by_cond('unit', 'name', sv.name) for sv in model.state_vector['expr']]
            #            mr.plot_sols(fig, time_unit, units)
            # fixme:mm-30.01.2018            mr.plot_sols(fig)

            label = "Model run " + str(i + 1) + " - solutions"
            run_data_str = run_data_str_basis + ", Time step: " + str(
                comb['run_time']['step_size'])
            rel += MatplotlibFigure(fig, label, run_data_str)

            # plot phase planes
            fig = plt.figure(figsize=(3 * len(model.state_vector["expr"]), 7),
                             tight_layout=True)
            #            mr.plot_phase_planes(fig, units)
            mr.plot_phase_planes(fig)

            label = "Model run " + str(i + 1) + " - phase planes"
            run_data_str = run_data_str_basis + ", Start: " + str(
                comb['run_time']['start'])
            run_data_str += ", End: " + str(comb['run_time']['end'])
            run_data_str += ", Time step: " + str(
                comb['run_time']['step_size'])
            rel += MatplotlibFigure(fig, label, run_data_str)

            # plot external input
            #            fig = plt.figure(figsize=(7,3), tight_layout=True)
            #            label = "Model run " + str(i+1) + " - external input"
            #            mr.plot_external_input_fluxes(fig)
            #            rel += MatplotlibFigure(fig, label, run_data_str)

            # plot system-age distributions
            fig = plt.figure(figsize=(10, 15), tight_layout=True)
            #            fig = plt.figure(figsize=(6,6), tight_layout=True)
            tsi = TimeStepIterator.from_ode_reservoir_model_run(mr)

            age_dist_hist = TsTpMassFieldsPerPoolPerTimeStep.from_time_step_iterator(
                tsi)
            print("Calculation done, creating plot.")
            age_dist_hist.matrix_plot3d(
                "plot_system_age_distributions_with_bins",
                fig,
                title="System age distribution",
                mr=mr)
            print("Plot created.")

            label = "Model run " + str(i + 1) + " - system-age-distributions"

            rel += MatplotlibFigure(fig, label, run_data_str_basis)
            #fig.show()
            #input()

    # include references
    rel += Text("\n")
    rel += Header("References", 1)
    return (rel)