예제 #1
0
    def translate(self, var):
        """Returns TranslatedVarlistEntry instance, with populated coordinate
        axes. Units of scalar coord slices are translated to the units of the
        conventions' coordinates. Includes logic to translate and rename scalar 
        coords/slices, e.g. VarlistEntry for 'ua' (intrinsically 4D) @ 500mb 
        could produce a TranslatedVarlistEntry for 'u500' (3D slice), depending 
        on naming convention.
        """
        if var.use_exact_name:
            # HACK; dataclass.asdict says VarlistEntry has no _id attribute & not sure why
            fl_entry = {f.name: getattr(var, f.name, util.NOTSET) \
                for f in dc.fields(TranslatedVarlistEntry) if hasattr(var, f.name)}
            new_name = var.name
        else:
            fl_entry = self.from_CF(var.standard_name, var.axes_set)
            new_name = fl_entry.name
        
        new_dims = [self.translate_coord(dim) for dim in var.dims]
        new_scalars = [self.translate_coord(dim) for dim in var.scalar_coords]
        if len(new_scalars) > 1:
            raise NotImplementedError()
        elif len(new_scalars) == 1:
            assert not var.use_exact_name
            # change translated name to request the slice instead of the full var
            # keep the scalar_coordinate value attribute on the translated var
            new_name = fl_entry.scalar_name(var.scalar_coords[0], new_scalars[0])

        return util.coerce_to_dataclass(
            fl_entry, TranslatedVarlistEntry, 
            name=new_name, coords=(new_dims + new_scalars), convention=self.name
        )
예제 #2
0
def coordinate_from_struct(d, class_dict=None, **kwargs):
    """Attempt to instantiate the correct :class:`DMCoordinate` class based on
    information in dict *d* (read from JSON file).

    *class_dict* is an optional dict mapping axes identifiers to the
    :class:`DMCoordinate` child classes to instantiate. Default is to use
    :class:`DMLongitudeCoordinate` for 'X', etc.

    TODO: implement full cf_xarray/MetPy heuristics.
    """
    if class_dict is None:
        class_dict = {
            'X': DMLongitudeCoordinate,
            'Y': DMLatitudeCoordinate,
            'Z': DMVerticalCoordinate,
            'T': DMGenericTimeCoordinate,
            'OTHER': DMCoordinate
        }
    standard_names = {
        'longitude': 'X',
        'latitude': 'Y',
        'time': 'T'
    }
    try:
        ax = 'OTHER'
        if 'axis' in d:
            ax = d['axis']
        elif d.get('standard_name', "") in standard_names:
            ax = standard_names[d['standard_name']]
        return util.coerce_to_dataclass(d, class_dict[ax], **kwargs)
    except Exception:
        raise ValueError(f"Couldn't parse coordinate: {repr(d)}")
예제 #3
0
    def from_struct(cls, d, parent):
        """Parse the "dimensions", "data" and "varlist" sections of the POD's
        settings.jsonc file when instantiating a new :class:`Diagnostic` object.

        Args:
            d (:py:obj:`dict`): Contents of the POD's settings.jsonc file.

        Returns:
            :py:obj:`dict`, keys are names of the dimensions in POD's convention,
            values are :class:`PodDataDimension` objects.
        """
        def _pod_dimension_from_struct(name, dd, v_settings):
            class_dict = {
                'X': VarlistLongitudeCoordinate,
                'Y': VarlistLatitudeCoordinate,
                'Z': VarlistVerticalCoordinate,
                'T': VarlistPlaceholderTimeCoordinate,
                'OTHER': VarlistCoordinate
            }
            try:
                return data_model.coordinate_from_struct(
                    dd, class_dict=class_dict, name=name,
                    **(v_settings.time_settings)
                )
            except Exception:
                raise ValueError(f"Couldn't parse dimension entry for {name}: {dd}")

        def _iter_shallow_alternates(var):
            """Iterator over all VarlistEntries referenced as alternates. Doesn't
            traverse alternates of alternates, etc.
            """
            for alt_vs in var.alternates:
                yield from alt_vs

        vlist_settings = util.coerce_to_dataclass(
            d.get('data', dict()), VarlistSettings)
        globals_d = vlist_settings.global_settings

        assert 'dimensions' in d
        dims_d = {k: _pod_dimension_from_struct(k, v, vlist_settings) \
            for k,v in d['dimensions'].items()}

        assert 'varlist' in d
        vlist_vars = {
            k: VarlistEntry.from_struct(globals_d, dims_d, name=k, parent=parent, **v) \
            for k,v in d['varlist'].items()
        }
        for v in vlist_vars.values():
            # validate & replace names of alt vars with references to VE objects
            for altv_name in _iter_shallow_alternates(v):
                if altv_name not in vlist_vars:
                    raise ValueError((f"Unknown variable name {altv_name} listed "
                        f"in alternates for varlist entry {v.name}."))
            linked_alts = []
            for alts in v.alternates:
                linked_alts.append([vlist_vars[v_name] for v_name in alts])
            v.alternates = linked_alts
        return cls(contents = list(vlist_vars.values()))
예제 #4
0
 def from_instances(cls, *t_coords):
     """Create new instance from "union" of attributes of t_coords.
     """
     if not t_coords:
         raise ValueError()
     t_coords = [util.coerce_to_dataclass(t, cls) for t in t_coords]
     t0 = t_coords.pop(0)
     if any(t != t0 for t in t_coords):
         raise ValueError("mismatch")
     return t0