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)
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}}$" )
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}}$" )
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)
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" )
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)
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)
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}}$" )
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"))
def test_mul(self): rel = Text("x")*3 self.assertEqual(rel.pandoc_markdown(), "xxx")
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)