Factory#
Defines ExperimentFactory and Loader related classes.
- class phileas.factory.Loader(name: str, instruments_factory: ExperimentFactory)[source]#
Bases:
ABCClass used to initiate a connection to an instrument, and then configure it. In order to add the support for a new instrument, you should subclass it and register it in an
ExperimentFactory.- name: ClassVar[str]#
Name of the loader, which is usually the name of the loaded instrument. It is to be matched with the bench configuration
loaderfield.
- interfaces: ClassVar[set[str]]#
Interfaces the loaded instrument supports. Interfaces are arbitrary names referred to in the experiment configuration file, allowing to choose which bench instrument is used for which experiment instrument, depending on its
interfacefield.
- instruments_factory: ExperimentFactory#
Reference to the instrument factory which has instantiated the loader. This allows loaders to have access, among other things, to already instantiated instruments.
- abstract initiate_connection(configuration: dict) Any[source]#
Initialize a connection to a given instrument, given its bench configuration, and return it.
- abstract configure(instrument: Any, configuration: dict)[source]#
Configure an instrument - whose connection has already been initiated - using its experiment configuration. The instrument should be modified, and is not returned.
- get_effective_configuration(instrument: Any, configuration: None | dict[str, phileas.iteration.base.DataTree] = None) dict[str, phileas.iteration.base.DataTree][source]#
Returns the effective configuration of an instrument. The purpose of this method is to be called after
configure(), in order to verify that the required parameters have been properly applied. It might be useful in different situations, for example:the instrument might have a parameter with which the driver uses a best effort approach. If the user requests an unsupported value, it automatically chooses a supported value. For example, the only integer values might be supported, and the driver rounds the user-supplied parameter.
Setting a parameter might not be deterministic. For example, the effective position of a piezoelectric actuator differs from its target.
The user manually configures an instrument, and wants to get its configuration back. In this case,
dump_state()might also be interesting.
If
configurationis not supplied, the entire configuration of the instrument is returned. It should have the same structure as the argument ofconfigure().Otherwise, if
configurationis supplied, its values are replaced with the effective parameter values. This is typically used to verify the value of a configuration that has just been applied withconfigure(). Note that, in this case,configurationmight be modified, and it is likely thatget_effective_configuration (instrument, configuration) is configuration.It is not necessary to implement this method.
- get_id(instrument: Any) str[source]#
Returns a unique identifier of an instrument. Two physically different instruments are expected to have different identifiers.
- dump_state(instrument: Any) phileas.iteration.base.DataTree[source]#
Dump the state of an instrument. It should, as much as possible, represent the exact state of the instrument. It should contain the value of parameters that can be configured with
configure(), but also other ones. These might include, among others, calibration values, the exact mode which is used, firmware and driver versions, etc.The purpose of this state is to enable comparing similar instruments, to find out if they can be swapped or how to make them interchangeable.
It is not necessary to implement this method. However, when it is implemented, together with
restore_state(), it allows to guarantee that the instrument always starts in the same state. It can also be used to capture a manual configuration, in order to replicate it later.
- restore_state(instrument: Any, state: phileas.iteration.base.DataTree)[source]#
Put the instrument in a previously recorded state. See
dump_state().
- classmethod get_markdown_documentation() str[source]#
Generate a markdown documentation of the loader, which is based on the docstrings of the
initiate_connection()andconfigure()methods.
- phileas.factory.build_loader(name_: str, interfaces_: set[str], initiate_connection: Callable[[dict], Any], configure: Callable[[Any, dict], None]) type[Loader][source]#
Build a loader class from its name, interfaces and different methods. Note that using this function does not allow a loader instance to access the instrument factory that uses it.
- phileas.factory.register_default_loader(loader: type[Loader] | tuple[str, set[str], Callable[[dict], Any], Callable[[Any, dict], None]]) type[Loader] | tuple[str, set[str], Callable[[dict], Any], Callable[[Any, dict], None]][source]#
Register a loader to be added on init by every new
ExperimentFactory. See_add_loader()for the specifications of the arguments.This function can either be used directly, or as a class decorator.
- class phileas.factory.BenchInstrument(name: 'str', loader: 'Loader', configuration: 'dict[Key, DataTree]', instrument: 'Any | None' = None)[source]#
Bases:
object
- class phileas.factory.ExperimentInstrument(name: 'str', interface: 'str', bench_instrument: 'BenchInstrument', configuration: 'dict[str, Any]')[source]#
Bases:
object
- class phileas.factory.InstrumentState(loader: str, interfaces: list[str], configuration: phileas.iteration.base.DataTree, id: str | None, state: phileas.iteration.base.DataTree)[source]#
Bases:
objectSerializable state of a
BenchInstrument.- configuration: DataTree#
Configuration applied to the instrument.
- id: str | None#
Identifier of the instrument, see
Loader.get_id().
- state: DataTree#
State of the instrument, see
Loader.dump_state().
- class phileas.factory.BenchState(version: str, instruments: dict[str, InstrumentState])[source]#
Bases:
objectSerializable state of a whole bench.
- instruments: dict[str, InstrumentState]#
Instruments of the bench.
- to_yaml(destination: Path | None = None) str | None[source]#
Serialize a bench state to YAML. If you supply a path in
destination, directly write the state to the file located there. Otherwise, return a string.
- classmethod from_yaml(source: str | Path) BenchState[source]#
Deserialize a bench state from YAML. If you supply a path in
source, read the state from the file located there. Otherwise, read the string.
- class phileas.factory.Filter[source]#
Bases:
ABCClass used to store an expression tree representing the filtering expressions stored in the
filterentry of the experiment configuration.- abstract verifies(instrument: BenchInstrument) bool[source]#
Checks whether a bench instrument satisfies the filter.
- static build_filter(filter_entry: dict[str, Any] | list[dict]) Filter[source]#
Filter parser, which is given the
filterentry of the experiment configuration file, and returns the corresponding expression tree.Todo
Only parsing single-level dict is supported for now. Parsing nested filters should be implemented.
- class phileas.factory.AttributeFilter(field: str, value: Any)[source]#
Bases:
FilterFilter checking that a bench instrument has the expected entry value in its configuration. This is one of the leaves of the filters expression tree.
- verifies(instrument: BenchInstrument) bool[source]#
Checks whether a bench instrument satisfies the filter.
- class phileas.factory.ConstantFilter(value: bool)[source]#
Bases:
FilterLiteral filter.
- verifies(instrument: BenchInstrument) bool[source]#
Checks whether a bench instrument satisfies the filter.
- class phileas.factory.FiltersCombination(filter1: Filter, filter2: Filter, operation: Callable[[bool, bool], bool])[source]#
Bases:
FilterFilters combination based on a binary operator.
- verifies(instrument: BenchInstrument) bool[source]#
Checks whether a bench instrument satisfies the filter.
- class phileas.factory.Connection(src: 'str', src_port: 'list[str]', dst: 'str', dst_port: 'list[str]', attr: 'str')[source]#
Bases:
object
- class phileas.factory.ExperimentFactory(bench: Path | str | dict[str, phileas.iteration.base.DataTree], experiment: Path | str | IterationTree)[source]#
Bases:
object- The experiment factory is used to
parse configuration files, cleaning them of reserved keywords;
match the experiment instruments to their bench instruments and loaders;
initiate the connection to the instruments, and configure them.
- bench_file: Path | None#
If the bench configuration is supplied by file, stores its path. Otherwise, stores
None.
- experiment_instruments: dict[str, Any]#
Instruments whose connection has been initiated, configured or not.
- experiment_file: Path | None#
If the experiment configuration is supplied by file, stores its path. Otherwise, stores
None.
- experiment_config: IterationTree#
Experiment configuration stripped of the reserved keyword entries.
- initiate_connections()[source]#
Lazily initiate the connections of all the bench instruments, ie. only those that are matched to an experiment instrument are handled.
- get_bench_instrument(name: str) Any[source]#
Return the bench instrument whose name is specified, using its loader
initiate_connection()method to create it. If the connection to the instrument has already been initiated, the instrument is simply returned.This is the only way a bench instrument should be retrieved.
- configure_instrument(name: str, configuration: dict | None = None)[source]#
Configure an experiment instrument using the given configuration, and the
configure()method of its loader. If no configuration is given, use the instrument default configuration from the experiment configuration.
- configure_experiment(configuration: dict | None = None)[source]#
Configure multiple instruments at once, using the
configure()method of their respective loaders, and the entry ofconfigurationmatching their name. Ifconfigurationmisses the entry of an instrument, the instrument won’t be configured.If no configuration is given, the default experiment configuration is used to configure the instruments. In this case, all the instruments are configured.
- get_effective_instrument_configuration(name: str, configuration: dict | None = None) dict[str, phileas.iteration.base.DataTree][source]#
Return the effective configuration of an instrument. See
Loader.get_effective_configuration().
- get_effective_experiment_configuration(configuration: dict | None = None) dict[str, dict[str, phileas.iteration.base.DataTree]][source]#
Return the effective configuration of the whole bench. If
configurationis not supplied, get the configuration of each instrument of the bench. Otherwise, only retrieves the configuration of instrument which have an entry. The value of the entry is passed toLoader.get_effective_configuration(). If the entry does notcorrespond to an instrument, or its loader does not implement
get_effective_configuration(), it is ignored.
- dump_bench_state(full: bool = True) BenchState[source]#
Dumps the state of the whole bench.
When not
full, do not dump the state of the instruments. However, retrieve its loader and ID information.
- restore_bench_state(state: BenchState, strict: bool = True)[source]#
Restores the a bench state. If
strict, requires the following serialized values to match with their bench values:the list of the instruments names,
Additionally, every loader is required to implement
Loader.restore_state().Otherwise, if
not strict, the state of all the instruments with matching names andInstrumentState.loaderis restored. Others are ignored.- Raises:
ValueError – if the state cannot be restored due to stored state incompatibilities.
- register_loader(loader: type[Loader] | tuple[str, set[str], Callable[[phileas.iteration.base.DataTree], Any], Callable[[Any, phileas.iteration.base.DataTree], Any]])[source]#
Register a new loader for this factory. See
_add_loader()for the specifications of the arguments.