Skip to content

Commit

Permalink
Add runs summary as Markdown table
Browse files Browse the repository at this point in the history
  • Loading branch information
mole99 committed Oct 8, 2024
1 parent 9f31695 commit d7918be
Showing 1 changed file with 184 additions and 0 deletions.
184 changes: 184 additions & 0 deletions cace/parameter/parameter_ngspice.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,9 @@
success,
warn,
err,
console,
)
from rich.markdown import Markdown


@register_parameter('ngspice')
Expand Down Expand Up @@ -742,6 +744,31 @@ def __getattr__(self, attr):
if self.get_argument('collate'):
conditions[collate_variable] = collate_condition

# Create the simulation summary
simulation_summary = self.create_simulation_summary(
conditions,
condition_sets,
variables,
script_variables,
simulation_values,
)

# Get path for the simulation summary
outpath_sim_summary = os.path.join(
self.param_dir, f'simulation_summary.md'
)

# Save the simulation summary
with open(outpath_sim_summary, 'w') as f:
f.write(simulation_summary)

info(
f'Parameter {self.param["name"]}: Saving simulation summary as \'[repr.filename][link=file://{os.path.abspath(outpath_sim_summary)}]{os.path.relpath(outpath_sim_summary)}[/link][/repr.filename]\'…'
)

# Print the simulation summary in the console
console.print(Markdown(simulation_summary))

# Create a plot if specified
if 'plot' in self.param:
# Create the plots and save them
Expand All @@ -754,6 +781,163 @@ def __getattr__(self, attr):
collate_variable,
)

def create_simulation_summary(
self,
conditions,
condition_sets,
variables,
script_variables,
simulation_values,
):
"""
Create a summary for all simulation runs in Markdown
"""

summary_table = f'# Simulation Summary for {self.param["display"]}\n\n'

# Find all conditions with more than one value,
# these change between simulations
conditions_in_summary = []
for condition in conditions.values():
if len(condition.values) > 1:
conditions_in_summary.append(condition.name)

# Print the header
header_entries = []
header_separators = []

# First entry is the simulation run
header_entries.append('run')
header_separators.append(':--')

for cond in conditions_in_summary:
header_entries.append(str(cond))
header_separators.append('-' * max(len(str(cond)) - 1, 1) + ':')

# Get resulting variables (check for None)
for variable in variables:
if variable != None:
header_entries.append(str(variable))
header_separators.append(
'-' * max(len(str(variable)) - 1, 1) + ':'
)

# Get postprocessed variables
for variable in script_variables:
header_entries.append(str(variable))
header_separators.append(
'-' * max(len(str(variable)) - 1, 1) + ':'
)

# Add header and separators
summary_table += f'| {" | ".join(header_entries)} |\n'
summary_table += f'| {" | ".join(header_separators)} |\n'

# Generate the entries
max_digits = len(str(len(condition_sets)))
max_entries_list = 3
for index, (condition_set, sim_values) in enumerate(
zip(condition_sets, simulation_values)
):
body_entries = []
body_entries.append(f'run_{index:0{max_digits}d}')

for cond in conditions_in_summary:
if isinstance(condition_set[cond], list):
if len(condition_set[cond]) == 1:
body_entries.append(
self.decimal2readable(condition_set[cond][0])
)
continue

values = condition_set[cond][
0 : min(max_entries_list, len(condition_set[cond]))
]
values = [self.decimal2readable(value) for value in values]
if len(condition_set[cond]) > max_entries_list:
values.append('…')
body_entries.append(f'[{", ".join(values)}]')
else:
body_entries.append(
self.decimal2readable(condition_set[cond])
)

for variable in variables:
if variable != None:
if isinstance(simulation_values[index][variable], list):
if len(simulation_values[index][variable]) == 1:
body_entries.append(
self.decimal2readable(
simulation_values[index][variable][0]
)
)
continue

values = simulation_values[index][variable][
0 : min(
max_entries_list,
len(simulation_values[index][variable]),
)
]
values = [
self.decimal2readable(value) for value in values
]
if (
len(simulation_values[index][variable])
> max_entries_list
):
values.append('…')
body_entries.append(f'[{", ".join(values)}]')
else:
body_entries.append(
self.decimal2readable(
simulation_values[index][variable]
)
)

for variable in script_variables:
if isinstance(simulation_values[index][variable], list):
if len(simulation_values[index][variable]) == 1:
body_entries.append(
self.decimal2readable(
simulation_values[index][variable][0]
)
)
continue

values = simulation_values[index][variable][
0 : min(
max_entries_list,
len(simulation_values[index][variable]),
)
]
values = [self.decimal2readable(value) for value in values]
if (
len(simulation_values[index][variable])
> max_entries_list
):
values.append('…')
body_entries.append(f'[{", ".join(values)}]')
else:
body_entries.append(
self.decimal2readable(
simulation_values[index][variable]
)
)

summary_table += f'| {" | ".join(body_entries)} |\n'

return summary_table

def decimal2readable(self, decimal: float | str):
if isinstance(decimal, str):
return decimal

if decimal < 0.1 or decimal > 100000:
return f'{decimal:.3e}'
else:
return f'{decimal:.3f}'

def get_num_steps(self):
return self.num_sims

Expand Down

0 comments on commit d7918be

Please sign in to comment.