Source code for pycif.plugins.obsoperators.standard.transforms.init_obsvect_transformations
import copy
import itertools
from .utils import add_default
from .....utils.classes.transforms import Transform
[docs]
def init_obsvect_transformations(
self, all_transforms,
obsvect,
backup_comps, mapper):
"""Initialize transforms on the observation-vector side.
Appends a ``toobsvect`` transform to the pipeline for every observed
species (component/tracer pair where ``param.isobs`` is ``True``).
For ``satellites`` components, a
:doc:`satellites </documentation/plugins/transforms/complex/satellites>`
transform is inserted immediately before the corresponding ``toobsvect``
step.
Then reads ``obsvect.transform_pipe`` and prepends each of its transforms
**before** all other transforms in *all_transforms*, preserving the
user-defined order.
Args:
self (ObsOperator): the obs-operator plugin instance. On return,
``self.mainpipe`` is populated with the IDs of the newly inserted
``toobsvect`` (and ``satellites``) transforms.
all_transforms: the :class:`~pycif.utils.classes.transforms.Transform`
object holding all transforms; modified in-place.
obsvect (ObsVect): observation-vector object; its ``transform_pipe``
and ``datavect`` are read to determine which transforms to insert.
backup_comps (dict): backed-up component definitions forwarded to
:func:`~.utils.add_default.add_default`.
mapper (dict): the pipeline mapper dictionary; updated in-place.
"""
# Initializes the overall transform pipe
if not hasattr(obsvect, "transform_pipe"):
obsvect.transform_pipe = Transform.from_dict({})
transforms = obsvect.transform_pipe
transfs_ids = getattr(transforms, "attributes", [])
components = obsvect.datavect.components
comps = components.attributes
obs_mapper = obsvect.ini_mapper(obsvect)
# mainpipe_outputs_keys = list(all_outputs.keys())
# all_outputs.update(obs_mapper["outputs"])
# Add default transformations after to other transforms
for comp in self.datavect.components.attributes:
component = getattr(components, comp)
# Fetch parameters
# If no parameters, handle the component as a whole
if not hasattr(component, "parameters"):
continue
else:
params = component.parameters
parameters = params.attributes[:]
for trcr in parameters:
param = getattr(params, trcr, component)
# Do nothing if not in observation vector
if not param.isobs:
continue
# Add toobsvect default transformation
yml_dict = {
"plugin": {
"name": "toobsvect",
"version": "std",
"type": "transform",
"newplg": True,
},
"component": comp,
"parameter": trcr,
"orig_parameter_plg": param,
"orig_component_plg": component,
**{attr: getattr(param, attr)
for attr in getattr(param, "attributes", [])
if attr != "plugin"}
}
new_transf, toobsvect_id = add_default.add_default(
self,
all_transforms,
yml_dict,
position="last",
mapper=mapper,
init=True,
backup_comps=backup_comps,
)
itransf_tooobs = all_transforms.attributes.index(toobsvect_id)
self.mainpipe.append(toobsvect_id)
# Default satellite transformation
new_transf, new_id = None, ""
if comp == "satellites":
yml_dict = {
"plugin": {
"name": "satellites",
"version": "std",
"type": "transform",
},
"component": [comp],
"parameter": [trcr],
"orig_parameter_plg": param,
"orig_component_plg": component,
"successor": toobsvect_id,
**{attr: getattr(param, attr)
for attr in getattr(param, "attributes", [])
if attr != "plugin"}
}
ref_successor = {(comp, trcr): toobsvect_id}
new_transf, new_id = add_default.add_default(
self,
all_transforms,
yml_dict,
position="index",
index=itransf_tooobs,
mapper=mapper,
init=True,
backup_comps=backup_comps,
successor=ref_successor
)
self.mainpipe.insert(-1, new_id)
# Loops backwards on available transformations and update inputs/outputs
# According to model outputs
ref_index = 0
for transf_id in transfs_ids[::-1]:
transform = f"{transf_id}_after"
# Initializes mapper if not already done
if transform in mapper:
continue
# Replacing the transform by a transform class
# if not already initialized
transf = getattr(transforms, transf_id)
if transf is None:
transf = Transform.from_dict({}, orig_name=transform)
yml_dict = transf.to_dict(transf, full_output=True)
_, new_id = add_default.add_default(
self,
all_transforms,
yml_dict,
position="first",
index=ref_index,
mapper=mapper,
init=True,
backup_comps=backup_comps,
transform_id=transform
)
ref_index = all_transforms.attributes.index(new_id)
self.mainpipe.insert(0, new_id)
# # Keep in memory transformations on the controlvect side
# all_transforms.obsvectpipe = \
# [tr for tr in all_transforms.attributes
# if tr not in all_transforms.mainpipe + all_transforms.controlpipe]