Skip to content

Commit

Permalink
Further work on scripts
Browse files Browse the repository at this point in the history
  • Loading branch information
mole99 committed Sep 30, 2024
1 parent 0222a2b commit 5554f85
Show file tree
Hide file tree
Showing 20 changed files with 79 additions and 28 deletions.
3 changes: 2 additions & 1 deletion cace/common/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -694,7 +694,8 @@ def run_subprocess(
text=True,
) as process:

dbg(input)
if input != None:
dbg(f'input: {input}')
stdout, stderr = process.communicate(input)
returncode = process.returncode

Expand Down
17 changes: 10 additions & 7 deletions cace/parameter/parameter.py
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,7 @@ def get_result(self, name: str):
return None

def cancel(self, no_cb):
info(f'Parameter {self.pname}: Canceled')
info(f'Parameter {self.pname}: Canceled.')
self.canceled = True

if self.subproc_handle:
Expand Down Expand Up @@ -366,7 +366,8 @@ def run_subprocess(self, proc, args=[], env=None, input=None, cwd=None):

self.subproc_handle = process

dbg(input)
if input != None:
dbg(f'input: {input}')
stdout, stderr = process.communicate(input)
returncode = process.returncode

Expand Down Expand Up @@ -497,14 +498,14 @@ def evaluate_result(self):

# Scale value with unit
if unit:
dbg(f'{unit} {value}')
dbg(f'scaling {value} with {unit}')
value = spice_unit_convert(
(
str(unit),
str(value),
)
)

dbg(f'result: {value}')
if result != None:
dbg(
f'Checking result {result} against value {value} with limit {limit}.'
Expand Down Expand Up @@ -893,7 +894,7 @@ def makeplot(
not 'yaxis' in self.param['plot'][plot_name]
and not 'xaxis' in self.param['plot'][plot_name]
):
err('Neither yaxis nor xaxis specified.')
err(f'Neither yaxis nor xaxis specified in plot {plot_name}.')

xvariable = None
if 'xaxis' in self.param['plot'][plot_name]:
Expand Down Expand Up @@ -1181,7 +1182,7 @@ def makeplot(
elif xvariable in conditions:
xvalues = conditions[xvariable].values
else:
err(f'Unknown variable: {xvariable}')
err(f'Unknown variable: {xvariable} in plot {plot_name}.')
return None

xvalues_list.append(xvalues)
Expand All @@ -1196,7 +1197,9 @@ def makeplot(
elif yvariable in condition_set:
yvalues.append(condition_set[yvariable])
else:
err(f'Unknown variable: {yvariable}')
err(
f'Unknown variable: {yvariable} in plot {plot_name}.'
)
return None

yvalues_list.append(yvalues)
Expand Down
66 changes: 49 additions & 17 deletions cace/parameter/parameter_ngspice.py
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ def __init__(
**kwargs,
)

self.add_argument(Argument('template', None, True))
self.add_argument(Argument('template', None, True)) # TODO typing
self.add_argument(Argument('collate', None, False))
self.add_argument(Argument('format', None, False))
self.add_argument(Argument('suffix', None, False))
Expand Down Expand Up @@ -153,7 +153,7 @@ def pre_start(self):

def implementation(self):

info(f'Parameter {self.param["name"]}: Generating simulation files.')
info(f'Parameter {self.param["name"]}: Generating simulation files')

variables = self.get_argument('variables')

Expand Down Expand Up @@ -236,10 +236,11 @@ def implementation(self):
dbg(f'Total number of simulations: {self.num_sims}')

# If "collate" is set this means we need to merge
# the results of this variable
# This is done by removing it from the conditions
# and
# the results were all conditions but the collate conditions is the same
# This is useful for MC simulations, where the results of different iterations,
# but under the same conditions (e.g. temperature) should be collated.

# First remove the collate condition from the conditions
if self.get_argument('collate'):
collate_variable = self.get_argument('collate')
info(f'Collating results using condition "{collate_variable}"')
Expand All @@ -249,7 +250,7 @@ def implementation(self):
dbg(collate_condition)
else:
err(
f'Couldn\'t find collate variable "{collate_variable}" in conditions.'
f'Couldn\'t find condition "{collate_variable}" used for collating the results.'
)

# Generate the condition sets for each simulation
Expand Down Expand Up @@ -467,7 +468,7 @@ def implementation(self):
# Run all simulations
jobs = []

info(f'Parameter {self.param["name"]}: Running simulations.')
info(f'Parameter {self.param["name"]}: Running simulations')

self.cancel_point()

Expand Down Expand Up @@ -566,7 +567,7 @@ def implementation(self):

self.cancel_point()

info(f'Parameter {self.param["name"]}: Collecting results.')
info(f'Parameter {self.param["name"]}: Collecting results')

# Get the result
max_digits = len(str(len(condition_sets)))
Expand Down Expand Up @@ -605,9 +606,6 @@ def implementation(self):
)

# Read the result file

collated_results = {}

if format == 'ascii':

result_file = os.path.join(
Expand All @@ -634,12 +632,18 @@ def implementation(self):
collated_values[
variables[_index]
].append(float(entry))

dbg(f'collated_values: {collated_values}')

else:
err(f'Unsupported format for the simulation result.')

dbg(f'collated values: {collated_values}')

if self.get_argument('collate'):
condition_set[collate_variable] = collate_values

dbg(f'collated condition: {condition_set[collate_variable]}')

dbg(f'Extending final result…')

for variable in variables:
if variable != None:
# Extend the final result
Expand All @@ -654,6 +658,10 @@ def implementation(self):
self.datasheet['paths']['scripts'], script
)

info(
f"Running user-defined script '[repr.filename][link=file://{os.path.abspath(script_path)}]{os.path.relpath(script_path)}[/link][/repr.filename]'…"
)

if not os.path.isfile(script_path):
err(f'No such user script {script_path}.')
self.result_type = ResultType.ERROR
Expand All @@ -663,9 +671,33 @@ def implementation(self):
user_script = SourceFileLoader(
'user_script', script_path
).load_module()
collated_values = user_script.postprocess(
collated_values, condition_set
)

class CustomPrint:
def __enter__(self):
self._stdout = sys.stdout
sys.stdout = self
return self

def __exit__(self, *args):
sys.stdout = self._stdout

def write(self, text):
text = text.rstrip()
if len(text) == 0:
return
info(f'User script: {text}')

def flush(self):
self._stdout.flush()

def __getattr__(self, attr):
return getattr(self._stdout, attr)

with CustomPrint() as output:
collated_values = user_script.postprocess(
collated_values, condition_set
)

except Exception as e:
err(f'Error in user script: {e}')
self.result_type = ResultType.ERROR
Expand Down
2 changes: 2 additions & 0 deletions default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
# Python
matplotlib,
numpy,
scipy,
pillow,
tkinter,
rich,
Expand Down Expand Up @@ -77,6 +78,7 @@
# Python
matplotlib
numpy
scipy
pillow
volare
tkinter
Expand Down
2 changes: 1 addition & 1 deletion docs/source/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ Follow the navigation element below (or check the sidebar on the left) to get st
getting_started/index
usage/index
reference_manual/index
tutorial/index
tutorials/index
examples/index
dev/index
```
4 changes: 3 additions & 1 deletion docs/source/reference_manual/tools.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,10 @@ Arguments:
- `format`: `<'ascii'>` The file format of the ngspice result. Currently only `ascii` is supported.
- `suffix`: `<string>` File extension of the result file. For example: `.data`.
- `variables`: `<List[string|null]>` A list of results inside the result file. Use `null` to ignore a column.
- `script` (optional): `<string>` Name of a Python script in the script folder. It will be executed on the results of each simulation.
- `script_variables` (optional): `<List[string|null]>` A list of results generated by the specified Python script. These results are available in addition to the ones specified under `variables`. TODO

Results: The results depend on the `variables` argument.
Results: The results depend on the `variables` and optionally the `script_variables` arguments.

## `magic_drc`

Expand Down
2 changes: 2 additions & 0 deletions docs/source/tutorials/custom_scripts.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Tutorial - Using Custom Scripts to Preprocess Simulation Results

File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
9 changes: 9 additions & 0 deletions docs/source/tutorials/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Tutorials

```{toctree}
:glob:
:maxdepth: 2
ota_5t
custom_scripts
```
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Tutorial
# Tutorial - CACE Setup for a 5T-OTA

This tutorial will guide you step by step through the creation of a simple 5-transistor OTA and the CACE setup for it.
It is assumed that you have already set up CACE and its dependencies.
Expand Down

0 comments on commit 5554f85

Please sign in to comment.