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 tpes of dependencies in pyCIF:
plugin A
calls methods fromplugin B
For that reason, methods must have a standardized format for arguments and outputs, as specified in the corresponding pages of the documentation.
plugin A
needs data fromplugin B
Similarly, data format needs to follow a specified standardized format
Below is an example graph of dependencies corresponding to the pyCIF configuration file here:
digraph G { size ="4,4"; mode [shape=box, label="Mode:\nforward",style=filled,color=".7 .3 1.0"]; /*this is a comment*/ model [shape=box, label="Model:\ndummy",style=filled,color=".7 .3 1.0"]; /*this is a comment*/ controlvect [shape=box, label="Control vector:\nstandard",style=filled,color=".7 .3 1.0"]; obsoper [shape=box, label="Obs operator:\nstandard",style=filled,color=red]; obsvect [shape=box, label="Obs vector:\nstandard",style=filled,color=red]; domain [shape=box, label="Domain:\ndummy",style=filled,color=".7 .3 1.0"]; meteo [shape=box, label="Meteo:\ndummy",style=filled,color=".7 .3 1.0"]; measurements [shape=box, label="Measurements:\nrandom",style=filled,color=".7 .3 1.0"]; fluxes [shape=box, label="Fluxes:\ndummy",style=filled,color=red]; /*METHOD DEPENDENCIES*/ edge [style=bold]; mode -> obsoper; obsoper -> obsvect; obsoper -> controlvect; obsoper -> model; /*DATA DEPENDENCIES*/ edge [color=red]; obsvect -> measurements; controlvect -> model; controlvect -> domain; obsvect -> model; mode -> controlvect; obsvect -> measurements; model -> meteo; model -> domain; model -> fluxes; }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 defined 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.
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 ifsubplug
si True): if there are several plugins fitting the requirement in the yaml, choose the one in the preferred tree directory. For instance, if the parent plugin requires adomain
and severaldomain
are defined, e.g., at the root level and at some sub-level of another plugin, if one of the two fitspreftree
, this one is selected; otherwise, an error is returned due to ambiguous choice
empty
: an empty plugin is defined according to thename
/version
/type
/subtype
if 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 instead of looking for an existing plugin from the yaml
In practice, the requirement selection process follows the steps:
pyCIF looks in the Yaml for all possible plugins fitting the parameters
name
/version
/type
/subtype
/empty
/subplug
.
- Four possible outcomes:
the only one matching is returned,
an empty plugin is returned if there is no match,
if there are several matches and
subplug
is True: returns the one matchingpreftree
,an exception is returned if there are ambiguous choices
if there is one match:
if
any
is True, attaches the fetched oneif
any
is False, attaches the fetched one if it corresponds to the specifiedname
/version
/type
/subtype
if
any
is False and the fetched one does not correspond to the specifiedname
/version
/type
/subtype
, butempty
is True, attaches an empty plugin from the defaultif there is no match:
if
empty
is True andany
is False, attaches an empty plugin from the defaultif
empty
is True andany
is True, attaches an empty class plugin, with only the 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 external other plugins.
There are usually ways to avoid such implementation.
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, 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, 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:
- domain:
name: LMDZ
version: std
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, std
- Requires:
- simulator:
name: gausscost
version: std
any: True
empty: True
- 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
- 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
- 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
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
- FLEXINVERT, 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
- 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
- FMI, Puhti
- 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
- simulator
- dummy_txt, std
- 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, 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
- 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