def merge_dsd( sm: msg.StructureMessage, target: str, others: List[str], fill_value: str = "_Z", ) -> m.DataSet: """‘Merge’ 2 or more data structure definitions.""" dsd_target = sm.structure[target] # Create a temporary DataSet ds = m.DataSet(structured_by=dsd_target) # Count of keys count = 0 for dsd_id in others: # Retrieve the DSD dsd = sm.structure[dsd_id] # Retrieve a constraint that affects this DSD ccs = [cc for cc in sm.constraint.values() if dsd in cc.content] assert len(ccs) <= 1 cc = ccs[0] if len(ccs) and len(ccs[0].data_content_region) else None # Key for the VARIABLE dimension base_key = m.Key(VARIABLE=dsd_id, described_by=dsd_target.dimensions) # Add KeyValues for other dimensions included in the target but not in this DSD for dim in dsd_target.dimensions: if dim.id in base_key.values or dim.id in dsd.dimensions: continue base_key[dim.id] = dim.local_representation.enumerated[fill_value] # Iterate over the possible keys in `dsd`; add to `k` ds.add_obs( m.Observation(dimension=(base_key + key).order(), value=np.NaN) for key in dsd.iter_keys(constraint=cc)) log.info(f"{repr(dsd)}: {len(ds.obs) - count} keys") count = len(ds.obs) log.info(f"Total keys: {len(ds.obs)}\n" + "\n".join(map(lambda o: repr(o.dimension), ds.obs[:5]))) return ds
def _obs_ss(reader, elem): # StructureSpecificData message—all information stored as XML # attributes of the <Observation>. attrib = copy(elem.attrib) # Value of the observation value = attrib.pop("OBS_VALUE", None) # Use the DSD to separate dimensions and attributes dsd = reader.get_single(model.DataStructureDefinition) # Extend the DSD if the user failed to provide it key = dsd.make_key(model.Key, attrib, extend=reader.peek("SS without DSD")) # Remove attributes from the Key to be attached to the Observation aa = key.attrib key.attrib = {} return model.Observation(dimension=key, value=value, attached_attribute=aa)
def _obs(reader, elem): dim_at_obs = reader.get_single(message.Message).observation_dimension dsd = reader.get_single("DataSet").structured_by args = dict() for e in elem.iterchildren(): localname = QName(e).localname if localname == "Attributes": args["attached_attribute"] = reader.pop_single("Attributes") elif localname == "ObsDimension": # Mutually exclusive with ObsKey args["dimension"] = dsd.make_key( model.Key, {dim_at_obs.id: e.attrib["value"]}) elif localname == "ObsKey": # Mutually exclusive with ObsDimension args["dimension"] = reader.pop_single(model.Key) elif localname == "ObsValue": args["value"] = e.attrib["value"] return model.Observation(**args)