Requirements and dependencies in pyCIF#
pyCIF automatically links plugins with each other depending on requirements specified in the source of the plugins and on elements of the configuration file.
For instance, the observation operator needs to run the numerical model at some point.
For this reason, the model plugin that will be run is attached to the
obsoper plugin.
In the code of obsoper, the model can thus simply be called as follows:
def obsoper(self):
# Running the model
self.model.run(**args, **kwargs)
Another example is a model plugin that needs information about its corresponding domain plugin:
def some-model-method(self):
# Fetching domain information
nlon = self.domain.nlon
nlat = self.domain.nlat
Types of dependencies#
There are two main types of dependencies in pyCIF:
plugin Acalls methods fromplugin BFor that reason, methods must have a standardized format for arguments and outputs, as specified in the corresponding pages of the documentation.
plugin Aneeds data fromplugin BSimilarly, data format needs to follow a specified standardized format
Below is an example graph of dependencies corresponding to the pyCIF configuration file here:
In this example, blue boxes are plugins that are explicitly defined in the configuration file.
Red boxes are implicitly deduced from default values as specified in individual plugins
(see here).
Black arrows stand for method dependencies, while red ones are data dependencies.
Thus, for instance, the obsoper plugin is required by the mode plugin while it is not specified in the Yaml file.
pyCIF automatically initializes the default dependency: obsoper (standard, std).
Definition of dependencies#
Information about requirements are specified in the __init__.py file of your plugin.
To define requirements, one has to include a dictionary called requirements in the __init__.py file.
Keys of the dictionary are other plugins needed for the execution of the parent plugin.
In the example below, the parent plugin will be attached a domain plugin as attribute,
later callable using self.domain.
requirements = {
"domain": {
[...]
}
}
Note
The possible keys in each key of the requirements dictionary are detailed below.
Please note that it is possible to give extra keys that will be used to define arguments of the corresponding plugin.
For instance, in the case above, one can write:
requirements = {
"domain": {
"some_extra_key": "grub"
}
}
Then, one will be able to call self.domain.some_extra_key in the internal
functions of the corresponding plugin.
Moreover, the keys defined in that manner can be used to alter the way the domain
will initialize itself.
Warning
The following keys are reserved by the dependency mechanism and are consumed internally. They will not be forwarded as attributes to the attached plugin, so they cannot be used as custom extra keys:
name, version, type, any, subplug, preftree, empty, newplg
Behaviour with dependencies#
A given plugin might need to use another plugin in different ways, which will determine how the Yaml configuration
should be written and how missing requirements will be dealt with.
The expected usage of dependencies is determined through the definition of each corresponding key of the dictionary
requirements.
The possible arguments to provide to each key of the dictionary are the following:
name/version/type/subtype: name/version/type/subtype of the required plugin; type and subtype are optional if the key corresponds to a type of plugins. For instance, if the key isdomain, there is no need to repeat the type.
any: any plugin fitting the required type is fine
subplug: authorizes to search for required plugins not only at the root level of the yaml.
preftree(to be defined ifsubplugis True): when several plugins fit the requirement, select the one whose YAML tree path contains thepreftreesubstring. Among matching candidates, the one at the shallowest level (shortest path) is chosen. If no candidate matchespreftree, pyCIF falls through to theemptyfallback rather than raising an error.
empty: an empty plugin is defined according to thename/version/type/subtypeif none is available in the Yaml. This can be used when only functions of the required plugin are necessary and no data.
newplg: force initializing a new plugin instance instead of reusing the existing one from the Yaml.
The resolution of each requirement is implemented in
_fetch_requirement()
(see the API reference).
In practice, it follows a strict priority chain (first match wins):
Child attribute — a plugin explicitly defined as a child of the parent plugin in the Yaml (i.e., a sub-paragraph of the parent’s Yaml block).
Level-0 reference — a plugin defined at the root level of the Yaml file (i.e., a top-level paragraph such as
model,domain, etc.).Unambiguous sub-reference (
subplug: Trueonly) — if there is exactly one plugin of the required type anywhere in the Yaml tree, use it.Disambiguated sub-reference (
subplug: Trueonly) — if several candidates exist, select the one whose Yaml path best matchespreftree(shallowest path wins).Empty fallback (
empty: True) — load the registered default plugin of the requiredname/version/type, or instantiate a bare subclass if none is registered.Error — if none of the above conditions can be satisfied, a
PluginErroris raised.
The diagram below summarises this priority chain:
Note
Steps 1 and 2 establish a precedence: a child plugin defined inline under the parent plugin
in the Yaml shadows a top-level plugin of the same type.
This matters when, for example, a model defines its own domain that differs from a
domain defined at the root level.
Once a candidate is found, pyCIF decides whether to attach it directly or replace it with the registered default:
If
anyis True and the candidate has a valid plugin identity, attach it as-is.If
anyis False, attach it only if itsname/version/type/subtypematch the requirement exactly.If
anyis False and the candidate does not match, butemptyis True, attach an empty plugin from the registered default instead.If
emptyis True andanyis True but no named candidate was found, attach a bare empty class instance with only default class attributes.
Warning
The dual options subplug/preftree should be avoided as much as possible as it means that
your plugin is critically dependent on other external plugins.
There are usually ways to avoid such implementation.
Dynamic requirements with set_requirements#
Before looping over the requirements dictionary, pyCIF calls the method
set_requirements() on the plugin instance.
Plugins can override this method to modify their own requirements at runtime,
for example to activate or skip a dependency based on a Yaml parameter already loaded:
def set_requirements(self):
# Add a chemistry plugin only when the model has species
if getattr(self, "use_chemistry", False):
self.requirements["chemistry"] = {
"name": "standard", "version": "std", "empty": True
}
The base implementation of set_requirements does nothing.
This hook is intended for advanced plugin developers who need conditional dependencies.
Cheat sheet for checking plugins dependencies in yaml files#
The following list can be obtained by running the following python commands.
from pycif.utils.classes.baseclass import Plugin
Plugin.print_registered(print_rst=True, print_requirement=True)
Available plugins#
List of all available plugins and requirements for each class:
- chemistry
- controlvect
- datastream
- field
- CHIMERE, icbc
- Requires:
- domain:
name: CHIMERE
version: std
any: False
empty: False
- ICON-ART, icbc
- Requires:
- domain:
name: ICON-ART
version: std
any: False
empty: False
- LMDZ, chemfield
- Requires:
- domain:
name: LMDZ
version: std
any: False
empty: False
- LMDZ, chemfield-dynamico
- Requires:
- domain:
name: LMDZ
version: dynamico
any: False
empty: False
- LMDZ, chemfield-regular
- Requires:
- domain:
name: LMDZ
version: regular
any: False
empty: False
- LMDZ, inicond-dynamico
- Requires:
- domain:
name: LMDZ
version: dynamico
any: False
empty: False
- LMDZ, inicond-regular
- Requires:
- domain:
name: LMDZ
version: regular
any: False
empty: False
- LMDZ, photochem
- Requires:
- domain:
name: LMDZ
version: std
any: False
empty: False
- LMDZ, prescrconcs
- Requires:
- domain:
name: LMDZ
version: std
any: False
empty: False
- LMDZ, prodloss3d
- Requires:
- domain:
name: LMDZ
version: std
any: False
empty: False
- flux
- CHIMERE, AEMISSIONS
- Requires:
- domain:
name: CHIMERE
version: std
any: False
empty: False
- FLEXPART, nc
- Requires:
- domain:
name: FLEXPART
version: std
any: False
empty: False
- ICON-ART, sflx
- Requires:
- domain:
name: ICON-ART
version: std
any: False
empty: False
- LMDZ, netcdf-dynamico
- Requires:
- domain:
name: LMDZ
version: dynamico
any: False
empty: False
- LMDZ, netcdf-regular
- Requires:
- domain:
name: LMDZ
version: regular
any: False
empty: False
- LMDZ, sflx
- Requires:
- domain:
name: LMDZ
version: std
any: False
empty: False
- dummy, txt
- Requires:
- domain:
name: dummy
version: std
any: False
empty: False
- wrfchem, std
- Requires:
- domain:
name: wrfchem
version: std
any: False
empty: False
- meteo
- CHIMERE, std
- Requires:
- domain:
name: CHIMERE
version: std
any: False
empty: False
- LMDZ, mass-fluxes
- Requires:
- model:
name: LMDZ
version: reg-ico
any: False
empty: False
- dummy, csv
- Requires:
- domain:
name: dummy
version: std
any: False
empty: False
- datavect
- standard, std
- Requires:
- domain:
name: None
version: None
any: True
empty: True
- model:
name: None
version: None
any: True
empty: True
- components:
name: None
version: None
any: True
empty: True
- domain
- measurements
- random, param
- Requires:
- domain:
name: None
version: None
any: True
empty: False
- minimizer
- M1QN3, std
- Requires:
- simulator:
name: gausscost
version: std
any: True
empty: True
- congrad, std
- Requires:
- simulator:
name: gausscost
version: std
any: True
empty: True
- scipy, conjugate
- Requires:
- simulator:
name: gausscost
version: std
any: True
empty: True
- scipy, std
- Requires:
- simulator:
name: gausscost
version: std
any: True
empty:
- mode
- 4dvar, std
- Requires:
- obsvect:
name: standard
version: std
any: True
empty: False
- controlvect:
name: standard
version: std
any: True
empty: True
- obsoperator:
name: standard
version: std
any: True
empty: True
- minimizer:
name: M1QN3
version: std
any: True
empty: True
- simulator:
name: gausscost
version: std
any: True
empty: True
- platform:
name: None
version: None
any: True
empty: True
- EnSRF, std
- Requires:
- obsvect:
name: standard
version: std
any: True
empty: False
- controlvect:
name: standard
version: std
any: True
empty: True
- obsoperator:
name: standard
version: std
any: True
empty: True
- platform:
name: None
version: None
any: True
empty: True
- adj-tl_test, std
- Requires:
- obsvect:
name: standard
version: std
any: True
empty: False
- controlvect:
name: standard
version: std
any: True
empty: True
- obsoperator:
name: standard
version: std
any: True
empty: True
- simulator:
name: gausscost
version: std
any: True
empty: True
- analytic, std
- Requires:
- obsvect:
name: standard
version: std
any: True
empty: False
- controlvect:
name: standard
version: std
any: True
empty: True
- obsoperator:
name: standard
version: std
any: True
empty: True
- platform:
name: None
version: None
any: True
empty: True
- co2mvs, std
- Requires:
- controlvect:
name: standard
version: std
any: True
empty: True
- obsoperator:
name: standard
version: std
any: False
empty: True
- platform:
name: None
version: None
any: True
empty: True
- footprint, std
- Requires:
- controlvect:
name: standard
version: std
any: True
empty: True
- obsvect:
name: standard
version: std
any: True
empty: True
- obsoperator:
name: standard
version: std
any: False
empty: True
- forward, std
- Requires:
- controlvect:
name: standard
version: std
any: True
empty: True
- obsoperator:
name: standard
version: std
any: False
empty: True
- post-proc, std
- Requires:
- obsvect:
name: standard
version: std
any: True
empty: True
- controlvect:
name: standard
version: std
any: True
empty: True
- obsoperator:
name: standard
version: std
any: True
empty: True
- response-functions, std
- Requires:
- platform:
name: None
version: None
any: True
empty: True
- model:
name: None
version: None
any: True
empty: False
- obsoperator:
name: standard
version: std
any: True
empty: True
- obsvect:
name: standard
version: std
any: True
empty: False
- controlvect:
name: standard
version: std
any: True
empty: True
- datavect:
name: standard
version: std
any: True
empty: True
- model
- CHIMERE, acc
- Requires:
- domain:
name: CHIMERE
version: std
any: False
empty: False
- chemistry:
name: CHIMERE
version: gasJtab
any: False
empty: False
- flux:
name: CHIMERE
version: AEMISSIONS
any: False
empty: True
- bioflux:
name: CHIMERE
version: AEMISSIONS
any: False
empty: True
- meteo:
name: CHIMERE
version: std
any: False
empty: True
- latcond:
name: CHIMERE
version: icbc
any: False
empty: True
- topcond:
name: CHIMERE
version: icbc
any: False
empty: True
- inicond:
name: CHIMERE
version: icbc
any: False
empty: True
- CHIMERE, std
- Requires:
- domain:
name: CHIMERE
version: std
any: False
empty: False
- chemistry:
name: CHIMERE
version: gasJtab
any: False
empty: False
- flux:
name: CHIMERE
version: AEMISSIONS
any: False
empty: True
- bioflux:
name: CHIMERE
version: AEMISSIONS
any: False
empty: True
- meteo:
name: CHIMERE
version: std
any: False
empty: True
- latcond:
name: CHIMERE
version: icbc
any: False
empty: True
- topcond:
name: CHIMERE
version: icbc
any: False
empty: True
- inicond:
name: CHIMERE
version: icbc
any: False
empty: True
- LMDZ, acc
- Requires:
- domain:
name: LMDZ
version: std
any: False
empty: False
- flux:
name: LMDZ
version: sflx
any: False
empty: True
- chemistry:
name: CHIMERE
version: gasJtab
any: False
empty: False
- emis_species:
name: LMDZ
version: bin
any: False
empty: True
- meteo:
name: LMDZ
version: mass-fluxes-acc
any: False
empty: True
- inicond:
name: LMDZ
version: ic
any: False
empty: True
- prescrconcs:
name: LMDZ
version: prescrconcs
any: False
empty: True
- kinetic:
name: LMDZ
version: photochem
any: False
empty: True
- prodloss3d:
name: LMDZ
version: prodloss3d
any: False
empty: True
- LMDZ, std
- Requires:
- domain:
name: LMDZ
version: std
any: False
empty: False
- flux:
name: LMDZ
version: sflx
any: False
empty: True
- chemistry:
name: CHIMERE
version: gasJtab
any: False
empty: False
- emis_species:
name: LMDZ
version: bin
any: False
empty: True
- meteo:
name: LMDZ
version: mass-fluxes
any: False
empty: True
- inicond:
name: LMDZ
version: ic
any: False
empty: True
- prescrconcs:
name: LMDZ
version: prescrconcs
any: False
empty: True
- kinetic:
name: LMDZ
version: photochem
any: False
empty: True
- prodloss3d:
name: LMDZ
version: prodloss3d
any: False
empty: True
- wrfchem, std
- Requires:
- obsoperator
- random, std
- Requires:
- obsvect:
name: standard
version: std
any: True
empty: True
- controlvect:
name: standard
version: std
any: True
empty: True
- datavect:
name: standard
version: std
any: True
empty: True
- platform:
name: None
version: None
any: True
empty: True
- standard, std
- Requires:
- model:
name: None
version: None
any: True
empty: False
- obsvect:
name: standard
version: std
any: True
empty: True
- controlvect:
name: standard
version: std
any: True
empty: True
- datavect:
name: standard
version: std
any: True
empty: True
- platform:
name: None
version: None
any: True
empty: True
- obsparser
- obsvect
- platform
- ECMWF, ecs
- Requires:
- model:
name: None
version: None
any: True
empty: True
- EMPA, daint
- Requires:
- model:
name: None
version: None
any: True
empty: True
- ESPRI, spirit-nvidia
- Requires:
- model:
name: None
version: None
any: True
empty: True
- FMI, Puhti
- Requires:
- model:
name: None
version: None
any: True
empty: True
- JEAN-ZAY, std
- Requires:
- model:
name: None
version: None
any: True
empty: True
- LAERO, nuwa
- Requires:
- model:
name: None
version: None
any: True
empty: True
- LSCE, obelix
- Requires:
- model:
name: None
version: None
any: True
empty: True
- LSCE, obelix-nvidia
- Requires:
- model:
name: None
version: None
any: True
empty: True
- TGCC-CCRT, AMD
- Requires:
- model:
name: None
version: None
any: True
empty: True
- TGCC-CCRT, nvidia
- Requires:
- model:
name: None
version: None
any: True
empty: True
- TGCC-CCRT, std
- Requires:
- model:
name: None
version: None
any: True
empty: True
- docker, cif
- Requires:
- model:
name: None
version: None
any: True
empty: True
- docker, nvidia
- Requires:
- model:
name: None
version: None
any: True
empty: True
- simulator
- dummy_txt, std
- Requires:
- controlvect:
name: None
version: None
any: True
empty: False
- gausscost, FLEXPART
- Requires:
- controlvect:
name: None
version: None
any: True
empty: False
- obsvect:
name: None
version: None
any: True
empty: False
- obsoperator:
name: standard
version: std
any: True
empty: True
- gausscost, std
- Requires:
- controlvect:
name: standard
version: std
any: True
empty: True
- obsvect:
name: standard
version: std
any: True
empty: False
- obsoperator:
name: standard
version: std
any: True
empty: True
- transform
- basic
- background, std
- Requires:
- datavect:
name: None
version: None
any: True
empty: False
- product, std
- Requires:
- model:
name: None
version: None
any: True
empty: False
- complex
- conc2ratio, std
- Requires:
- model:
name: None
version: None
any: True
empty: False
- diagmet, std
- Requires:
- model:
name: CHIMERE
version: std
any: False
empty: False
- ratio2conc, std
- Requires:
- model:
name: None
version: None
any: True
empty: False
- system
- dump2format, std
- Requires:
- domain:
name: None
version: None
any: True
empty: True
- fromcontrol, std
- Requires:
- model:
name: None
version: None
any: True
empty: True
- obsvect:
name: standard
version: std
any: True
empty: True
- controlvect:
name: standard
version: std
any: True
empty: True
- run_model, std
- Requires:
- model:
name: None
version: None
any: True
empty: False
- toobsvect, std
- Requires:
- obsvect:
name: standard
version: std
any: True
empty: True
- controlvect:
name: standard
version: std
any: True
empty: True