Source code for model_package.Calibrate.summarize_calibration_results_from_csv

#!python
import argparse
import os
import pathlib
import sys
import yaml

import matplotlib.pyplot
import numpy
import pandas
import seaborn

import calibration_tools

[docs] def write_plastic_material_card(output_file, input_dict): '''Write elastic micromorphic material card :param str output_file: The root filename of the output yaml file :param dict input_dict: A dictionary containing calibrated parameters Returns: Writes ``output_file``.yml ''' multiplier = 10 defaults = { 'cu0': 1.e8, 'Hu': 1e-8, 'cchi0': 1.e8, 'Hchi': 1e-8, 'cnablachi0': 1.e8, 'Hnablachi': 1e-8, 'lambda': 0.0, 'mu': 0.0, 'eta': 0.0, 'tau': 0.0, 'kappa': 0.0, 'nu': 0.0, 'sigma': 0.0, 'tau1': 0.0, 'tau2': 0.0, 'tau3': 0.0, 'tau4': 0.0, 'tau5': 0.0, 'tau6': 0.0, 'tau7': 0.0001, 'tau8': 0.0, 'tau9': 0.0, 'tau10': 0.0, 'tau11': 0.0, 'int_params_a': 0.5, 'int_params_b': 1e-9} # Use defaults if a parameter is not specified for key in defaults.keys(): if key not in input_dict.keys(): input_dict[key] = defaults[key] output_dict = {} # plastic output_dict['line 01'] = f"2 {input_dict['cu0']} {input_dict['Hu']}" output_dict['line 02'] = f"2 {input_dict['cchi0']} {input_dict['Hchi']}" output_dict['line 03'] = f"2 {input_dict['cnablachi0']} {input_dict['Hnablachi']}" output_dict['line 04'] = "2 0. 0." output_dict['line 05'] = "2 0. 0." output_dict['line 06'] = "2 0. 0." output_dict['line 07'] = "2 0. 0." output_dict['line 08'] = "2 0. 0." output_dict['line 09'] = "2 0. 0." # elastic output_dict['line 10'] = f"2 {input_dict['lambda']} {input_dict['mu']}" output_dict['line 11'] = f"5 {input_dict['eta']} {input_dict['tau']} {input_dict['kappa']} {input_dict['nu']} {input_dict['sigma']}" output_dict['line 12'] = f"11 {input_dict['tau1']} {input_dict['tau2']} {input_dict['tau3']} {input_dict['tau4']} {input_dict['tau5']} {input_dict['tau6']} {input_dict['tau7']} {input_dict['tau8']} {input_dict['tau9']} {input_dict['tau10']} {input_dict['tau11']}" output_dict['line 13'] = f"2 {input_dict['tau']} {input_dict['sigma']}" # integration output_dict['line 14'] = '0.5 0.5 0.5 1e-9 1e-9' output_dict['obj_func_value'] = 0.0 with open(f'{output_file}.yml', 'w') as f: yaml.dump(output_dict, f) return 0
[docs] def make_summary_csv(summary_csv, parameter_df): '''Make a csv file summarizing the mean, min, max, and standard deviation of calibrated parameters :param str summary_csv: Filename to store summary statistics of calibrated parameters :param dict results_dict: Results dictionary containing list of parameters with each key corresponding to a parameter name :returns: ``summary_csv`` ''' params, means, medians, mins, maxs, devs = [], [], [], [], [], [] fields = list(parameter_df.columns) fields.remove('element') for key in fields: # get stats params.append(key) means.append(numpy.mean(parameter_df[key])) medians.append(numpy.median(parameter_df[key])) mins.append(numpy.min(parameter_df[key])) maxs.append(numpy.max(parameter_df[key])) devs.append(numpy.std(parameter_df[key])) # output df = pandas.DataFrame({'param': params, 'mean': means, 'median': medians, 'min': mins, 'max': maxs, 'dev': devs}) df.to_csv(summary_csv, header=True, sep=',', index=False) return 0
[docs] def kde(rootname, parameter_df, type, kde_best_parameters=None): '''Create a kernel density estimate (KDE) plot for each calibrated parameter :param str rootname: The rootname of the output plot :param dict results_dict: Dictionary containing list of parameter results with each key corresponding to a parameter :param str type: A string specifying the type of KDE to plot. 'kde' gives a regular KDE plot. 'hist' gives a KDE plot with histograms shown :param str kde_best_parameters: Optional root filename to output a yaml file containing the "best" parameters sampled from the kernel density estimate associated with "kde_best" :returns: ``{rootname}_{key}_{type}.PNG`` for each key in `results_dict`, write ``{kde_best_parameters}.yml`` if requested ''' output_parameters = {} fields = list(parameter_df.columns) fields.remove('element') for key in fields: matplotlib.pyplot.figure() if type != 'best': if type == 'kde': ax = seaborn.displot(parameter_df[key], kind='kde', color='red', fill=True) elif type == 'hist': ax = seaborn.displot(parameter_df[key], kde=True, color='red', fill=True) ax.set(xlabel=f'parameter {key}', ylabel='KDE') matplotlib.pyplot.title(key) matplotlib.pyplot.tight_layout() matplotlib.pyplot.savefig(f'{rootname}_{key}_{type}.PNG') else: try: ax = seaborn.kdeplot(parameter_df[key], color='red', fill=False) xs, ys = ax.lines[-1].get_data() ax.fill_between(xs, ys, color='red', alpha=0.1) mode_idx = numpy.argmax(ys) output_parameters[key] = xs[mode_idx] best_value = f'{xs[mode_idx]:.6f}' ax.set(xlabel=f'parameter {key}', ylabel='KDE') matplotlib.pyplot.title(f'Best {key} = {best_value}') matplotlib.pyplot.tight_layout() matplotlib.pyplot.savefig(f'{rootname}_{key}.png') except: pass matplotlib.pyplot.close() # output if kde_best_parameters: #write_elastic_material_card(kde_best_parameters, output_parameters) write_plastic_material_card(kde_best_parameters, output_parameters) return 0
[docs] def summarize_calibration_results(parameter_csv, summary_csv=None, kde_hist_plot=None, kde_plot=None, kde_best=None, kde_best_parameters=None, boundary_csv=None): '''Main function to drive parameter summary and output :param list parameter_sets: List of yaml files containing calibration results :param int case: The calibration "case". 1: two parameter, 2: 7 parameter,\ 3: 7 parameter plus tau7, 4: all 18 parameters :param str results_csv: Optional filename to store all calibrated parameter values :param str summary_csv: Optional filename to store summary statistics of calibrated parameters :param str kde_hist_plot: Optional root filename to plot kernel density estimate of each calibrated parameter with histogram :param str kde_plot: Optional root filename to plot kernel density estimate of each calibrated parameter :param str kde_best_parameters: Optional root filename to output a yaml file containing the "best" parameters sampled from the kernel density estimate associated with "kde_best" ''' parameter_df = pandas.read_csv(parameter_csv) # if boundary_csv provided, modify paramter_df to replace those calibrations with "best" parameter results if boundary_csv: boundary_elements_df = pandas.read_csv(boundary_csv) boundary_elements = list(boundary_elements_df['boundary_elements'].values) for index in parameter_df.index: if int(parameter_df.loc[index]['element']) in boundary_elements: print(f'element {parameter_df.loc[index]["element"]} and index {index} in boundary elements!') parameter_df = parameter_df.drop(index) if summary_csv: make_summary_csv(summary_csv, parameter_df) if kde_hist_plot: kde(kde_hist_plot, parameter_df, 'hist') if kde_plot: kde(kde_plot, parameter_df, 'kde') if kde_best: kde(kde_best, parameter_df, 'best', kde_best_parameters) return 0
def get_parser(): script_name = pathlib.Path(__file__) prog = f"python {script_name.name} " cli_description = "Summarize results of parameter calibration from a calibration map csv" parser = argparse.ArgumentParser(description=cli_description, prog=prog) parser.add_argument('--parameter-csv', type=str, required=True, help='Specify the list of yaml files containing calibration results') parser.add_argument('--summary-csv', type=str, required=False, help='Optional filename to store summary statistics of calibrated parameters') parser.add_argument('--kde-hist-plot', type=str, required=False, help='Optional root filename to plot kernel density estimate of each calibrated parameter with histogram') parser.add_argument('--kde-plot', type=str, required=False, help='Optional root filename to plot kernel density estimate of each calibrated parameter') parser.add_argument('--kde-best', type=str, required=False, help='Optional root filename to plot kernel density estimate of each calibrated parameter with maximum value in title') parser.add_argument('--kde-best-parameters', type=str, required=False, default=None, help='Optional root filename to output a yaml file containing the "best" parameters sampled from the kernel density estimate associated with "--kde-best"') parser.add_argument('--boundary-csv', type=str, required=False, default=None, help='A csv file containing list of boundary elements') return parser if __name__ == '__main__': parser = get_parser() args, unknown = parser.parse_known_args() sys.exit(summarize_calibration_results(parameter_csv=args.parameter_csv, summary_csv=args.summary_csv, kde_hist_plot=args.kde_hist_plot, kde_plot=args.kde_plot, kde_best=args.kde_best, kde_best_parameters=args.kde_best_parameters, boundary_csv=args.boundary_csv, ))