Source code for log2Report.generateReport

"""
    Generate a markdown report for data provided in dictionary

"""

# Load modules
import logging
import pathlib
import shutil
import pandas as pd
from tabulate import tabulate
from datetime import datetime

# create local logger
# change log level in calling module to DEBUG to see log messages
log = logging.getLogger(__name__)


[docs]def copyPlots2ReportDir(reportDir, plotDict): """ copy the plots to report directory The plots are in a dictionary: plotDict = {'plot1': PurePath to plot1, 'plot2': PurePath to plot2...} Parameters ----------- reportDir: pathlib path path to directory where to copy the plots to plotDict: dict dict of the location of the plots to copy """ if not isinstance(reportDir, pathlib.PurePath): reportDir = pathlib.Path(reportDir) for key in plotDict: if key != 'type': if isinstance(plotDict[key], pathlib.PurePath): plotPath = plotDict[key] plotName = reportDir / plotPath.name shutil.copy2(plotPath, plotName) log.debug('Copied: %s to %s' % (plotPath, plotName))
[docs]def addLineBlock(titleString, reportDKey, pfile, italicFont=False, onlyFirstLine=False): """ add lineblock to report Parameters ----------- titleString: str string that shall be added reportDKey: dict dictionary with info for string pfile: file italicFont: bool if True write value in italic onlyFirstLine: bool if first item in reportDKey is added to pfile - break """ for value in reportDKey: if value != 'type': if italicFont: pfile.write('%s *%s* \n' % (titleString, reportDKey[value])) else: pfile.write('%s %s \n' % (titleString, reportDKey[value])) pfile.write(' \n') if onlyFirstLine: break
[docs]def writeReportFile(reportD, pfile): """ Create markdown report with blocks, tables, list according to type key Parameters ---------- reportD : dict report dictionary pfile : file object file where markdown format report is written to """ # Loop through keys and perform action according to value found in type for key in reportD: subKey = 'type' # HEADER BLOCK # Title if reportD[key][subKey] == 'title': addLineBlock('#', reportD[key], pfile, onlyFirstLine=True) # Avalanche name if reportD[key][subKey] == 'avaName': addLineBlock('### Avalanche directory:', reportD[key], pfile, italicFont=True) # Simulation name if reportD[key][subKey] == 'simName': addLineBlock('### Simulation name:', reportD[key], pfile, italicFont=True) # Time info if reportD[key][subKey] == 'time': addLineBlock('### Date:', reportD[key], pfile, onlyFirstLine=True) # PARAMETER BLOCK # Table listing all the key : value pairs in rows if reportD[key][subKey] == 'list': pfile.write('### %s \n' % key) pfile.write(' \n') pfile.write('| Parameters | Values | \n') pfile.write('| ---------- | ------ | \n') for value in reportD[key]: if value != 'type': pfile.write('| %s | %s | \n' % (value, reportD[key][value])) pfile.write(' \n') # Table listing the key : value pairs in columns if reportD[key][subKey] == 'columns': pfile.write('### %s \n' % key) pfile.write(' \n') for value in reportD[key]: if value != 'type': pfile.write('| %s ' % value) pfile.write('| \n') for value in reportD[key]: if value != 'type': pfile.write('| ----------') pfile.write('| \n') for value in reportD[key]: if value != 'type': pfile.write('| %s ' % reportD[key][value]) pfile.write('| \n') pfile.write(' \n') # Multiline, multicolumn table from pandas Dataframe if reportD[key][subKey] == 'pandasDF': pfile.write('### %s \n' % key) pfile.write(' \n') df = reportD[key]['dataDF'] # only keep necessary columns colNames = list(reportD[key]['column names'].keys()) df = df[colNames] # format floats dataType = df.dtypes for col in colNames: if 'float' in str(dataType[col]): df[col] = df[col].map(lambda x: '{0:.4f}'.format(x)) # rename columns df = df.rename(columns=reportD[key]['column names']) df = df.transpose() nCols = len(reportD[key]['column names']) df.to_markdown(buf=pfile, tablefmt="github", headers=["<!-- -->"]*nCols) pfile.write(' \n') pfile.write(' \n') # IMAGE BLOCK if reportD[key][subKey] == 'image': pfile.write('### %s \n' % key) pfile.write(' \n') for value in reportD[key]: if value != 'type' and isinstance(reportD[key][value], pathlib.Path): pfile.write('##### Figure: %s \n' % value) pfile.write(' \n') pfile.write('![%s](%s) \n' % (value, reportD[key][value].name)) pfile.write(' \n') pfile.write(' \n') # TEXT BLOCK if reportD[key][subKey] == 'text': pfile.write('### %s \n' % key) pfile.write(' \n') for value in reportD[key]: if value != 'type': pfile.write('##### Topic: %s \n' % value) pfile.write(' \n') pfile.write('%s \n' % (reportD[key][value])) pfile.write(' \n')
[docs]def writeReport(outDir, reportDictList, reportOneFile, plotDict='', standaloneReport=False, reportName='fullSimulationReport'): """ Write a report in markdown format for simulations, saved to outDir Parameters ---------- outDir : str path to output directory reportDictList : list list of report dictionaries from simulations reportOneFile : boolean True to write all info in the same file plotDict : dict optional dictionary with info on plots that shall be included in report standaloneReport: bool if True copy plots to reportDir reportName: str report file name, fullSimulationReport is the default value """ if reportOneFile: now = datetime.now() dtString = now.strftime("%Y%m%d_%Hh%Mm%Ss") # Start writing markdown style report reportPath = pathlib.Path(outDir, (reportName + '_' + dtString + '.md')) with open(reportPath, 'w') as pfile: # Loop through all simulations for reportD in reportDictList: if plotDict != '' and ('simName' in reportD): # add plot info to general report Dict reportD['Simulation Results'] = plotDict[reportD['simName']['name']] reportD['Simulation Results'].update({'type': 'image'}) # copy plots to reportDir if standaloneReport: for key in reportD: subKey = 'type' if reportD[key][subKey] == 'image': copyPlots2ReportDir(outDir, reportD[key]) # Write report file writeReportFile(reportD, pfile) else: # Loop through all simulations for reportD in reportDictList: if plotDict != '': # add plot info to general report Dict reportD['Simulation Results'] = plotDict[reportD['simName']['name']] reportD['Simulation Results'].update({'type': 'image'}) # Start writing markdown style report reportPath = pathlib.Path(outDir, ('%s.md' % reportD['simName']['name'])) with open(reportPath, 'w') as pfile: # Write report file writeReportFile(reportD, pfile)