Macro Development
Here we describe how you can develop macros to run.
In the GUI,
the macros are run with the given interface.
In the CRDFileProcessor
,
you can run your own macros using the run_macro
routine:
rimseval.processor.CRDFileProcessor.run_macro()
Templates for macros and example python files can be found on GitHub.
An overview of useful variables can be found in here.
Introduction
A macro requires a specific structure. If you need to import packages, please follow best norms.
Warning
Do not import full packages into the namespace. This could yield to odd behavior down the line.
For example, if you want to use numpy
functions,
you should import is as:
import numpy as np
If you want to import other routines from rimseval
,
use absolute imports.
Your macro can have as many subroutines as you like.
These will all be imported by the macro reader.
You must have a routine called calc
that runs your calculations.
If you have more subroutines,
these need to be called from within your main calculation function.
The following template lines out the start of a macro.
If you use an editor that supports type hints,
autocompletion will work.
Information on type hints can be found
here.
Note the usage of absolute imports to enable type hints.
from rimseval.processor import CRDFileProcessor
def calc(crd: CRDFileProcessor) -> None:
"""Macro template.
:param crd: CRD file processor that will be passed to the macro.
"""
# your code goes here
Basic examples
Below are two examples that show you how to implement, e.g., how to filter on full data sets and how to filter packages.
Example: Filter maximum ions per shot
Here is a re-implementation of the
rimseval.processor.CRDFileProcessor.filter_max_ions_per_shot()
method in the form of a macro.
import numpy as np
from rimseval.processor import CRDFileProcessor
def calc(crd: CRDFileProcessor) -> None:
"""Macro to filter out all shots with more than 3 ions.
:param crd: CRD file processor that will be passed to the macro.
"""
# maximum ions per shot to be filtered out
max_ions = 3
# create a numpy mask that selects the filters we want to filter
shots_rejected = np.where(crd.ions_per_shot > max_ions)[0]
# pass the rejected shots array to the routine that will filter everything
crd.apply_individual_shots_filter(shots_rejected)
As discussed above, the macro must be in the given template form.
We define here a shots_rejected
array (a numpy.ndarray
),
which lists the shots that we want to reject.
Finally,
we pass the array of rejected shots to the in-built function
that processes the shots further and handles everything down the line.
This is the crd.apply_individual_shots_filter()
routine.
More detailed documentation on this routine can be found in
rimseval.processor.CRDFileProcessor.apply_individual_shots_filter()
.
Example: Filter maximum ions per package
Here is a macro that re-implements the maximum number of ions per package filter.
Details on the filter can be found in
rimseval.processor.CRDFileProcessor.filter_max_ions_per_shot()
.
import numpy as np
from rimseval.processor import CRDFileProcessor
def calc(crd: CRDFileProcessor) -> None:
"""Macro to filter out all packages with more than 4 ions.
Here we assume, that you have already created packages using the built-in function.
Package data is therefore available.
:param crd: CRD file processor that will be passed to the macro.
"""
# maximum ions per pkg to be filtered out
max_ions = 4
# calculate total ions in all the packages
total_ions_per_pkg = np.sum(crd.data_pkg, axis=1)
# find packages that need deletion
pkg_to_delete = np.where(total_ions_per_pkg > max_ions)[0]
# now delete the packages that are not needed
crd.data_pkg = np.delete(crd.data_pkg, pkg_to_delete, axis=0)
# update the number of shots per package array: delete entries of deleted packages
crd.nof_shots_pkg = np.delete(crd.nof_shots_pkg, pkg_to_delete, axis=0)
# finally, we need to update the ``crd.data`` and ``crd.nof_shots`` entries
crd.data = np.sum(crd.data_pkg, axis=0)
crd.nof_shots = np.sum(crd.nof_shots_pkg)
First we calculate the sum of ions per package by summing over the crd.data_pkg
array.
Note that we need to specify the axis in this case since we want to sum
over packages, not over the spectra.
Using the numpy.where
function, we then locate packages that meet
the rejection criterion. The pkg_to_delete
variable stores the index of the packages.
Using numpy.delete
, we then delete the rejectable packages from
crd.data_pkg
and crd.nof_shots_pkg
.
Finally, we need to update crd.data
and crd.nof_shots
such that the non-packaged data is updated as well.
Note
Before the macro runs, data must have been packaged using the built-in method.