Source code for pyretis.inout.report.report_path

# -*- coding: utf-8 -*-
# Copyright (c) 2023, PyRETIS Development Team.
# Distributed under the LGPLv2.1+ License. See LICENSE for more info.
"""Method for generating reports from path sampling simulations.

The reports are useful for displaying results from the analysis.

Important methods defined here
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

generate_report_tis (:py:func:`.generate_report_tis`)
    Generate a report for the overall results from a TIS simulation.

generate_report_tis_path (:py:func:`.generate_report_tis_path`)
    Generate a report for a single TIS simulation.

generate_report_retis (:py:func:`.generate_report_retis`)
    Generate a report for the overall results from a RETIS simulation.
"""
import logging
from pyretis.inout.report.markup import (generate_rst_table,
                                         generate_latex_table)
from pyretis.inout.formats.formatter import apply_format, format_number
logger = logging.getLogger(__name__)  # pylint: disable=invalid-name
logger.addHandler(logging.NullHandler())


__all__ = ['generate_report_tis', 'generate_report_tis_path',
           'generate_report_retis']


[docs]def generate_report_tis_path(analysis, output='rst'): """Generate a report for a single TIS simulation. Parameters ---------- analysis : dict This is the output from the analysis. output : string, optional This is the desired output format. It must match one of the formats defined in :py:const:`pyretis.inout.report.report._TEMPLATES`. Default is 'rst' (reStructuredText). Returns ------- out[0] : string The generated report in the desired format. out[1] : string The file extension (i.e. file type) for the generated report. """ result = analysis['pathensemble'] report = {'ensemble': result['out']['ensemble'], 'figures': _get_path_figures(result['figures']), 'tables': {'interfaces': None, 'probability': None, 'path': None, 'efficiency': None}} # Create tables results = [result] tables = report['tables'] tables['interfaces'] = _table_interface(results, fmt=output)[1] tables['probability'] = _table_probability(results, fmt=output)[1] tables['efficiency'] = _table_efficiencies(results, fmt=output)[1] return report
def generate_report_pptis_path(analysis, output='rst'): """Generate a report for a single TIS simulation. Parameters ---------- analysis : dict This is the output from the analysis. output : string, optional This is the desired output format. It must match one of the formats defined in :py:const:`pyretis.inout.report.report._TEMPLATES`. Default is 'rst' (reStructuredText). Returns ------- out[0] : string The generated report in the desired format. out[1] : string The file extension (i.e. file type) for the generated report. """ result = analysis['pathensemble_repptis'] report = {'ensemble': result['out']['ensemble'], 'figures': _get_path_figures(result['figures']), 'tables': {'interfaces': None, 'probability': None, 'path': None, 'efficiency': None}} # Create tables results = [result] tables = report['tables'] tables['interfaces'] = _table_interface(results, fmt=output)[1] tables['probability'] = _table_probability_repptis(results, fmt=output)[1] tables['efficiency'] = _table_efficiencies(results, fmt=output)[1] return report
[docs]def generate_report_tis(analysis, output='rst'): """Generate a report for the over-all results from a TIS simulation. Parameters ---------- analysis : dict This is the output from the analysis. output : string, optional This is the desired output format. It must match one of the formats defined in :py:const:`pyretis.inout.report.report._TEMPLATES`. Default is 'rst' (reStructuredText). Returns ------- out[0] : string The generated report in the desired format. out[1] : string The file extension (i.e. file type) for the generated report. """ report = {'figures': {'tis': [], 'matched': None}, 'tables': {'interfaces': None, 'probability': None, 'path': None, 'efficiency': None}, 'numbers': {'pcross': None, 'perr': None}} results = analysis['pathensemble'] figures = report['figures'] # Add figures: for result in results: figures['tis'].append(_get_path_figures(result['figures'])) # Get matched result: matched_fig = analysis['matched']['figures'] matched_out = analysis['matched']['out'] figures['matched'] = matched_fig.get('matched-probability', None) figures['total'] = matched_fig.get('total-probability', None) figures['progress'] = matched_fig.get('overall-prun', None) figures['error'] = matched_fig.get('overall-err', None) # Get numbers: report['numbers']['pcross'] = format_number(matched_out['prob'], 0.1, 1) report['numbers']['perr'] = format_number(matched_out['relerror'] * 100, 0.1, 100) # Get tables: tables = report['tables'] tables['interfaces'] = _table_interface(results, fmt=output)[1] tables['probability'] = _table_probability(results, fmt=output)[1] tables['efficiency'] = _table_efficiencies(results, fmt=output)[1] return report
[docs]def generate_report_retis(analysis, output='rst'): """Generate a report for the over-all results from a RETIS simulation. Parameters ---------- analysis : dict This is the output from the analysis. output : string, optional This is the desired output format. It must match one of the formats defined in :py:const:`pyretis.inout.report.report._TEMPLATES`. Default is 'rst' (reStructuredText). Returns ------- out[0] : string The generated report in the desired format. out[1] : string The file extension (i.e. file type) for the generated report. """ report = {'figures': {'tis': [], 'matched': None}, 'tables': {'interfaces': None, 'interfaces0': None, 'path0': None, 'probability': None, 'path': None, 'efficiency': None, 'summary': None}, 'numbers': {'pcross': None, 'perr': None, 'flux': None, 'flux-err': None}, 'text': {'flux-unit': None}} result0 = analysis['pathensemble0'] results = [result0] + analysis['pathensemble'] figures = report['figures'] permeability = result0['out'].get('permeability', False) # Add figures: for result in results[1:]: figures['tis'].append(_get_path_figures(result['figures'])) figures['path0'] = _get_path_figures(result0['figures']) # Get matched result: matched_fig = analysis['matched']['figures'] matched_out = analysis['matched']['out'] figures['matched'] = matched_fig.get('matched-probability', None) figures['total'] = matched_fig.get('total-probability', None) figures['progress'] = matched_fig.get('overall-rrun', None) figures['error'] = matched_fig.get('overall-err', None) if permeability: figures['xi'] = analysis['xi']['fig']['xirun'] figures['xierror'] = analysis['xi']['fig']['xierror'] figures['tau'] = analysis['tau']['fig']['taurun'] figures['tauerror'] = analysis['tau']['fig']['tauerror'] figures['tauref'] = analysis['tau']['fig']['tauref'] # Get numbers: numbers = report['numbers'] numbers['pcross'] = format_number(matched_out['prob'], 0.1, 1) numbers['perr'] = format_number(matched_out['relerror'] * 100, 0.1, 100) numbers['flux'] = format_number(analysis['flux']['value'], 0.1, 100) numbers['flux-err'] = format_number(analysis['flux']['error'] * 100, 0.1, 100) numbers['rate'] = format_number(analysis['rate']['value'], 0.1, 100) numbers['rate-err'] = format_number(analysis['rate']['error'] * 100, 0.1, 100) numbers['permeability'] = permeability if permeability: numbers['xi'] = format_number(analysis['xi']['value'], 0.1, 100) numbers['xi-err'] = format_number(analysis['xi']['error'] * 100, 0.1, 100) numbers['tau'] = format_number(analysis['tau']['value'], 0.1, 100) numbers['tau-err'] = format_number(analysis['tau']['error'] * 100, 0.1, 100) numbers['perm'] = format_number(analysis['perm']['value'], 0.1, 100) numbers['perm-err'] = format_number(analysis['perm']['error'] * 100, 0.1, 100) report['text']['flux-unit'] = analysis['flux']['unit'] # Get tables: tables = report['tables'] tables['interfaces'] = _table_interface(results, fmt=output)[1] tables['probability'] = _table_probability(results[1:], fmt=output)[1] tables['efficiency'] = _table_efficiencies(results, fmt=output)[1] tables['summary'] = _table_summary(report, fmt=output)[1] return report
def generate_report_retis0(analysis, output='txt'): """Generate a report for [0^-] in a RETIS/REPTIS simulation. This method is primarily intended for displaying results on the screen during the analysis. Parameters ---------- analysis : dict This is the output of the analysis. output : string, optional This is the desired output format. It must match one of the formats defined in :py:const:`pyretis.inout.report.report._TEMPLATES`. Default is 'rst' (reStructuredText). Returns ------- out[0] : string The generated report in the desired format. out[1] : string The file extension (i.e. file type) for the generated report. """ if output != 'txt': output = 'txt' logger.warning('Report for [0^-] is only indended as "txt"' '\nOutput format "%s" ignored', output) if 'pathensemble' in analysis: result = analysis['pathensemble'] else: result = analysis['pathensemble_repptis'] flux = result['out']['fluxlength'] report = { 'ensemble': result['out']['ensemble'], 'numbers': {'fluxlength': format_number(flux[0], 0, 10000), 'fluxlengtherror': format_number(flux[1] * 100, 0, 100)}, 'tables': {'interfaces0': _table_interface0([result], fmt=output)[1]}, } return report def generate_report_repptis(analysis, output='rst'): """Generate a report for the over-all results from a PPRETIS simulation. Parameters ---------- analysis : dict This is the output from the analysis. output : string, optional This is the desired output format. It must match one of the formats defined in :py:const:`pyretis.inout.report.report._TEMPLATES`. Default is 'rst' (reStructuredText). Returns ------- out[0] : string The generated report in the desired format. out[1] : string The file extension (i.e. file type) for the generated report. """ report = {'figures': {'tis': [], 'matched': None}, 'tables': {'interfaces': None, 'probability': None, 'path': None, 'efficiency': None, 'summary': None}, 'numbers': {'pcross': None, 'perr': None, 'flux': None, 'flux-err': None}, 'text': {'flux-unit': None}} result0 = analysis['pathensemble0'] results = [result0] + analysis['pathensemble'] figures = report['figures'] permeability = result0['out'].get('permeability', False) # Add figures: for result in results[1:]: figures['tis'].append(_get_path_figures(result['figures'])) figures['path0'] = _get_path_figures(result0['figures']) # Get matched result: matched_fig = analysis['matched_fig'] figures['matched'] = matched_fig.get('matched-probability', None) figures['progress'] = matched_fig.get('overall-prun', None) figures['error'] = matched_fig.get('overall-err', None) if permeability: figures['xi'] = analysis['xi']['fig']['xirun'] figures['xierror'] = analysis['xi']['fig']['xierror'] figures['tau'] = analysis['tau']['fig']['taurun'] figures['tauerror'] = analysis['tau']['fig']['tauerror'] figures['tauref'] = analysis['tau']['fig']['tauref'] # Get numbers: numbers = report['numbers'] numbers['pcross'] = format_number(analysis['cross']['value'], 0.1, 1) numbers['perr'] = format_number(analysis['cross']['error'] * 100, 0.1, 100) numbers['flux'] = format_number(analysis['flux']['value'], 0.1, 100) numbers['flux-err'] = format_number(analysis['flux']['error'] * 100, 0.1, 100) numbers['rate'] = format_number(analysis['rate']['value'], 0.1, 100) numbers['rate-err'] = format_number(analysis['rate']['error'] * 100, 0.1, 100) numbers['permeability'] = permeability if permeability: numbers['xi'] = format_number(analysis['xi']['value'], 0.1, 100) numbers['xi-err'] = format_number(analysis['xi']['error'] * 100, 0.1, 100) numbers['tau'] = format_number(analysis['tau']['value'], 0.1, 100) numbers['tau-err'] = format_number(analysis['tau']['error'] * 100, 0.1, 100) numbers['perm'] = format_number(analysis['perm']['value'], 0.1, 100) numbers['perm-err'] = format_number(analysis['perm']['error'] * 100, 0.1, 100) report['text']['flux-unit'] = 'time-unit' # matched['flux']['unit'] # Get tables: tables = report['tables'] tables['interfaces'] = _table_interface_repptis(results, fmt=output)[1] tables['probability'] = _table_probability_repptis(results[1:], fmt=output)[1] tables['efficiency'] = _table_efficiencies(results, fmt=output)[1] tables['summary'] = _table_summary(report, fmt=output)[1] return report
[docs]def _table_interface_repptis(results, fmt='rst'): """Generate the table for the interfaces. This table will display the location of the different interfaces. Parameters ---------- results : list of dicts These are the results of the analysis. fmt : string, optional Determines if we create reStructuredText ('rst') or latex ('tex'). Returns ------- out[0] : list of strings These are the rows of the table. out[1] : string This is a string in the desired format which represents the table. """ table = [] for idx, result in enumerate(results): interf = result['out']['interfaces'] # To set the L interface correctly for PPRETIS if idx > 1: interf0 = results[idx-1]['out']['interfaces'][1] else: interf0 = interf[0] detect = result['out']['detect'] row = [ '{:^8s}'.format(result['out']['ensemble']), apply_format(interf0, '{:^8.4f}'), apply_format(interf[1], '{:^8.4f}'), ] intf2 = interf[2] if detect is None else detect row.append(apply_format(intf2, '{:^8.4f}')) table.append(row) if fmt in ['tex', 'latex']: table_str = generate_latex_table(table, 'Interfaces', ['Ensemble', 'Left', 'Middle', 'Detect'], fixnum={0, 1, 2, 3}) else: table_str = generate_rst_table(table, 'Interfaces', ['Ensemble', 'Left', 'Middle', 'Detect']) table_txt = '\n'.join(table_str) return table, table_txt
[docs]def _table_interface(results, fmt='rst'): """Generate the table for the interfaces. This table will display the location of the different interfaces. Parameters ---------- results : list of dicts These are the results of the analysis. fmt : string, optional Determines if we create reStructuredText ('rst') or latex ('tex'). Returns ------- out[0] : list of strings These are the rows of the table. out[1] : string This is a string in the desired format which represents the table. """ table = [] for result in results: interf = result['out']['interfaces'] row = [ '{:^8s}'.format(result['out']['ensemble']), apply_format(interf[0], '{:^8.4f}'), apply_format(interf[1], '{:^8.4f}'), ] detect = result['out']['detect'] if detect is None: row.append('') else: row.append(apply_format(detect, '{:^8.4f}')) table.append(row) if fmt in ['tex', 'latex']: table_str = generate_latex_table(table, 'Interfaces', ['Ensemble', 'Left', 'Middle', 'Detect'], fixnum={0, 1, 2, 3}) else: table_str = generate_rst_table(table, 'Interfaces', ['Ensemble', 'Left', 'Middle', 'Detect']) table_txt = '\n'.join(table_str) return table, table_txt
[docs]def _table_interface0(results, fmt='rst'): """Generate the table for the [0^-] ensemble. This table will display the location of the different interfaces. Parameters ---------- results : list of dicts These are the results of the analysis. fmt : string, optional Determines if we create reStructuredText ('rst') or latex ('tex'). Returns ------- out[0] : list of strings These are the rows of the table. out[1] : string This is a string in the desired format which represents the table. """ table = [] for result in results: row = ['{:^8s}'.format(result['out']['ensemble'])] interf = result['out']['interfaces'] row.append(apply_format(interf[0], '{:^8.4f}')) row.append(apply_format(interf[1], '{:^8.4f}')) row.append(apply_format(interf[2], '{:^8.4f}')) table.append(row) if fmt in ['tex', 'latex']: table_str = generate_latex_table(table, 'Interfaces', ['Ensemble', 'Left', 'Middle', 'Right'], fixnum={0, 1, 2, 3}) else: table_str = generate_rst_table(table, 'Interfaces', ['Ensemble', 'Left', 'Middle', 'Right']) table_txt = '\n'.join(table_str) return table, table_txt
[docs]def _table_probability(results, fmt='rst'): """Generate the table for the probabilities. This table will display the crossing probabilities with uncertainties. Parameters ---------- results : list of dicts The dictionaries are the results obtained from the analysis. fmt : string, optional Determines if we create reStructuredText ('rst') or latex ('tex'). Returns ------- out[0] : list of strings These are the rows of the table. out[1] : string This is a string in reStructuredText format which represents the table. """ table = [] for result in results: row = [ '{:^8s}'.format(result['out']['ensemble']), apply_format(result['out']['prun'][-1], '{:^10.6f}'), apply_format(result['out']['blockerror'][2], '{:^10.6f}'), apply_format(result['out']['blockerror'][4] * 100, '{:^10.6f}'), ] table.append(row) if fmt in ['tex', 'latex']: table_str = generate_latex_table(table, r'Crossing probabilities', [r'Ensemble', r'$P_\text{cross}$', r'Error', r'Rel. error (\%)'], fixnum={0, 1, 2, 3}) else: table_str = generate_rst_table(table, r'Crossing probabilities', [r'Ensemble', r'Pcross', r'Error', r'Rel. error (%)']) table_txt = '\n'.join(table_str) return table, table_txt
[docs]def _table_probability_repptis(results, fmt='rst'): """Generate the table for the probabilities. This table will display the crossing probabilities with uncertainties. Parameters ---------- results : list of dicts The dictionaries are the results obtained from the analysis. fmt : string, optional Determines if we create reStructuredText ('rst') or latex ('tex'). Returns ------- out[0] : list of strings These are the rows of the table. out[1] : string This is a string in reStructuredText format which represents the table. """ table = [] for result in results: row = [ '{:^8s}'.format(result['out']['ensemble']), apply_format(result['out']['prun_sl'][-1], '{:^10.6f}'), apply_format(result['out']['prun_sr'][-1], '{:^10.6f}'), apply_format(result['out']['blockerror_sl'][2], '{:^10.6f}'), apply_format(result['out']['blockerror_sr'][2], '{:^10.6f}'), ] table.append(row) if fmt in ['tex', 'latex']: str1 = r'$\left\langle p^{ \pm}\right\rangle_{\text {full }}$' str2 = r'$\left\langle p^{ \mp}\right\rangle_{\text {full }}$' table_str = generate_latex_table(table, r'Probabilities', [r'Ensemble', str1, str2, r'Error$^{ \pm}$', r'Error$^{ \mp}$'], fixnum={0, 1, 2, 3, 4}) else: table_str = generate_rst_table(table, r'Probabilities', [r'Ensemble', r'Pcross pm', r'Pcross mp', r'Error', r'Rel. error (%)']) table_txt = '\n'.join(table_str) return table, table_txt
[docs]def _table_efficiencies(results, fmt='rst'): """Generate table for efficiencies. This table will display results for the efficiencies, acceptance ratios and correlation. Parameters ---------- results : list of dicts The dictionaries are the results obtained from the analysis. fmt : string, optional Determines if we create reStructuredText ('rst') or latex ('tex'). Returns ------- out[0] : list of strings These are the rows of the table. out[1] : string This is a string in reStructuredText format which represents the table. """ table = [] for result in results: hist1 = result['out']['pathlength'][0] row = [ '{:^8s}'.format(result['out']['ensemble']), apply_format(result['out']['tis-cycles'], '{:^10.0f}'), apply_format(result['out']['efficiency'][0], '{:^10.6f}'), apply_format(result['out']['efficiency'][1], '{:^10.6f}'), ] row.append(apply_format(hist1[2][0], '{:^10.6f}')) table.append(row) if fmt in ['tex', 'latex']: table_str = generate_latex_table(table, 'Pathensemble data', ['Ensemble', 'TIS cycles', 'Shoot acc. ratio', 'Swap acc. ratio', 'Avg. path length'], fixnum={0, 1, 2, 3, 4, 5}) else: table_str = generate_rst_table(table, 'Pathensemble data', ['Ensemble', 'TIS cycles', 'Shoot acc. ratio', 'Swap acc. ratio', 'Avg. path length']) table_txt = '\n'.join(table_str) return table, table_txt
[docs]def _table_summary(report, fmt='rst'): """Generate table with summary of main results. This table will display results for the crossing probability, the initial flux and rate constant. Parameters ---------- report : dict Dict with current report. We use the information in this dictionary to generate the table. fmt : string, optional Determines if we create reStructuredText ('rst') or latex ('tex'). Returns ------- out[0] : list of strings These are the rows of the table. out[1] : string This is a string in reStructuredText format which represents the table. """ numbers = report['numbers'] text = report['text'] table = [['Crossing probability', numbers['pcross'], numbers['perr']], ['Flux (1/{})'.format(text['flux-unit']), numbers['flux'], numbers['flux-err']], ['Rate constant (1/{})'.format(text['flux-unit']), numbers['rate'], numbers['rate-err']]] if fmt in ['tex', 'latex']: table_str = generate_latex_table(table, 'Summary of main results', ['Property', 'Value', r'Relative error ($\%$)'], fixnum={1, 2}) else: table_str = generate_rst_table(table, 'Summary of main results', ['Property', 'Value', 'Relative error (%)']) table_txt = '\n'.join(table_str) return table, table_txt
[docs]def _get_path_figures(figures): """Return path figures from a dict of figures. This method extracts figures from results and makes them available to the report. Parameters ---------- figures : dict The figures generated by the analysis. Returns ------- path_figures : dict A dict which can be used in the report. """ path_figures = {} for fig in {'pcross', 'prun', 'perror', 'perror_sl', 'perror_sr', 'lpath', 'prun_sl', 'prun_sr', 'shoots'}: for key in figures: if key.endswith(fig): path_figures[fig] = figures[key] return path_figures