Source code for openquake.calculators.reportwriter
# -*- coding: utf-8 -*-# vim: tabstop=4 shiftwidth=4 softtabstop=4## Copyright (C) 2015-2025 GEM Foundation## OpenQuake is free software: you can redistribute it and/or modify it# under the terms of the GNU Affero General Public License as published# by the Free Software Foundation, either version 3 of the License, or# (at your option) any later version.## OpenQuake is distributed in the hope that it will be useful,# but WITHOUT ANY WARRANTY; without even the implied warranty of# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the# GNU Affero General Public License for more details.## You should have received a copy of the GNU Affero General Public License# along with OpenQuake. If not, see <http://www.gnu.org/licenses/>.# 2015.06.26 13:21:50 CEST"""Utilities to build a report writer generating a .rst report for a calculation"""importosimportsysimportgetpassimportloggingimportnumpyimportpandasfromopenquake.baselib.python3compatimportencode,decodefromopenquake.commonlibimportlogsfromopenquake.calculatorsimportviews
[docs]classReportWriter(object):""" A particularly smart view over the datastore """title={'params':'Parameters','inputs':'Input files','required_params_per_trt':'Required parameters per tectonic region type','ruptures_events':'Specific information for event based','job_info':'Data transfer','biggest_ebr_gmf':'Maximum memory allocated for the GMFs','avglosses_data_transfer':'Estimated data transfer for the avglosses','exposure_info':'Exposure model','slow_sources':'Slowest sources','task:start_classical:0':'Fastest task','task:start_classical:-1':'Slowest task','task_info':'Information about the tasks','weight_by_src':'Computation times by source typology','performance':'Slowest operations',}def__init__(self,dstore):self.dstore=dstoreself.oq=oq=dstore['oqparam']self.text=(decode(oq.description)+'\n'+'='*len(oq.description))try:num_rlzs=dstore['full_lt'].get_num_paths()exceptKeyError:num_rlzs='?'versions=sorted(dstore['/'].attrs.items())self.text+='\n\n'+views.text_table(versions)self.text+='\n\nnum_sites = %d, num_levels = %d, num_rlzs = %s'%(len(dstore['sitecol']),oq.imtls.sizeifoq.imtlselse0,num_rlzs)
[docs]defadd(self,name,obj=None):"""Add the view named `name` to the report text"""ifobj:text='\n::\n\n'+indent(str(obj))else:res=views.view(name,self.dstore)ifisinstance(res,(numpy.ndarray,pandas.DataFrame)):text=views.text_table(res)else:text=resiftext:title=self.title[name]line='-'*len(title)self.text+='\n'.join(['\n\n'+title,line,text])
[docs]defmake_report(self,show_inputs=True):"""Build the report and return a restructed text string"""oq,ds=self.oq,self.dstoreifshow_inputs:fornamein('params','inputs'):self.add(name)if'full_lt'inds:self.add('required_params_per_trt')if'rup_data'inds:self.add('ruptures_events')ifoq.calculation_modein('event_based_risk',):self.add('avglosses_data_transfer')if'exposure'inoq.inputs:self.add('exposure_info')if'source_info'inds:self.add('slow_sources')self.add('weight_by_src')if'task_info'inds:self.add('task_info')tasks=set(ds['task_info']['taskname'])if'start_classical'intasks:self.add('task:start_classical:0')self.add('task:start_classical:-1')self.add('job_info')if'performance_data'inds:self.add('performance')returnself.text
[docs]defsave(self,fname):"""Save the report"""withopen(fname,'wb')asf:f.write(encode(self.text))
[docs]defbuild_report(job_ini,output_dir=None):""" Write a `report.csv` file with information about the calculation without running it :param job_ini: full pathname of the job.ini file :param output_dir: the directory where the report is written (default the input directory) """withlogs.init('job',job_ini,user_name=getpass.getuser())aslog:oq=log.get_oqparam()if'source_model_logic_tree'inoq.inputs:oq.calculation_mode='preclassical'oq.ground_motion_fields=Falseoutput_dir=output_diroros.path.dirname(job_ini)fromopenquake.calculatorsimportbase# uglycalc=base.calculators(oq,log.calc_id)calc.save_params()# needed to save oqparam# some taken is care so that the real calculation is not run:# the goal is to extract information about the source management onlycalc.pre_execute()ifoq.calculation_mode=='preclassical':csm=calc.execute()calc.post_execute(csm)logging.info('Making the .rst report')rw=ReportWriter(calc.datastore)rw.make_report()report=(os.path.join(output_dir,'report.rst')ifoutput_direlsecalc.datastore.export_path('report.rst'))try:rw.save(report)exceptIOErrorasexc:# permission errorsys.stderr.write(str(exc)+'\n')returnreport