Example #1
0
 def get(self,format_time=True):
     
     def _get_temporal_adds_(ref_attrs):
         ## calendar should default to standard if it is not present.
         calendar = ref_attrs.get('calendar',None) or self.t_calendar
         
         return({'units':self.t_units or ref_attrs['units'],
                 'calendar':calendar,
                 'format_time':format_time})
     
     ## parameters for the loading loop
     to_load = {'temporal':{'cls':NcTemporalDimension,'adds':_get_temporal_adds_,'axis':'T','name_uid':'tid','name_value':'time'},
                'level':{'cls':NcVectorDimension,'adds':None,'axis':'Z','name_uid':'lid','name_value':'level'},
                'row':{'cls':NcVectorDimension,'adds':None,'axis':'Y','name_uid':'row_id','name_value':'row'},
                'col':{'cls':NcVectorDimension,'adds':None,'axis':'X','name_uid':'col_id','name_value':'col'},
                'realization':{'cls':NcVectorDimension,'adds':None,'axis':'R','name_uid':'rlz_id','name_value':'rlz'}}
     loaded = {}
     
     for k,v in to_load.iteritems():
         ## this is the string axis representation
         axis_value = v['axis'] or v['cls']._axis
         ## pull the axis information out of the dimension map
         ref_axis = self._source_metadata['dim_map'].get(axis_value)
         ## if the axis is not represented, fill it with none. this happens
         ## when a dataset does not have a vertical level or projection axis
         ## for example.
         if ref_axis is None:
             fill = None
         else:
             ref_variable = self._source_metadata['variables'].get(ref_axis['variable'])
             
             ## for data with a projection/realization axis there may be no 
             ## associated variable.
             try:
                 ref_variable['axis'] = ref_axis
             except TypeError:
                 if axis_value == 'R' and ref_variable is None:
                     ref_variable = {'axis':ref_axis,'name':ref_axis['dimension'],'attrs':{}}
             
             ## extract the data length to use when creating the source index
             ## arrays.
             length = self._source_metadata['dimensions'][ref_axis['dimension']]['len']
             src_idx = np.arange(0,length)
             
             ## assemble parameters for creating the dimension class then initialize
             ## the class.
             kwds = dict(name_uid=v['name_uid'],name_value=v['name_value'],src_idx=src_idx,
                         data=self,meta=ref_variable,axis=axis_value,name=ref_variable.get('name'))
             if v['adds'] is not None:
                 kwds.update(v['adds'](ref_variable['attrs']))
             kwds.update({'name':ref_variable.get('name')})
             fill = v['cls'](**kwds)
             
         loaded[k] = fill
         
     assert_raise(set(('temporal','row','col')).issubset(set([k for k,v in loaded.iteritems() if v != None])),
                  logger='request',exc=ValueError('Target variable must at least have temporal, row, and column dimensions.'))
         
     grid = SpatialGridDimension(row=loaded['row'],col=loaded['col'])
     crs = None
     if self.s_crs is not None:
         crs = self.s_crs
     else:
         crs = self._get_crs_()
     if crs is None:
         ocgis_lh('No "grid_mapping" attribute available assuming WGS84: {0}'.format(self.uri),
                  'request',logging.WARN)
         crs = CFWGS84()
         
     ## rotated pole coordinate systems require transforming the coordinates to
     ## WGS84 before they may be loaded.
     if isinstance(crs,CFRotatedPole):
         msg = 'CFRotatedPole projection found. Transforming coordinates to WGS84 and replacing the CRS with CFWGS84'
         ocgis_lh(msg=msg,logger='request.nc',level=logging.WARN)
         grid = get_rotated_pole_spatial_grid_dimension(crs,grid)
         crs = CFWGS84()
         
     spatial = SpatialDimension(name_uid='gid',grid=grid,crs=crs,abstraction=self.s_abstraction)
     
     variable_meta = self._source_metadata['variables'][self.variable]
     variable_units = variable_meta['attrs'].get('units')
     variable = Variable(self.variable,self.alias,variable_units,meta=variable_meta,
                         data=self)
     vc = VariableCollection(variables=[variable])
     
     ret = NcField(variables=vc,spatial=spatial,temporal=loaded['temporal'],level=loaded['level'],
                   realization=loaded['realization'],meta=self._source_metadata,uid=self.did)
     
     ## apply any subset parameters after the field is loaded
     if self.time_range is not None:
         ret = ret.get_between('temporal',min(self.time_range),max(self.time_range))
     if self.time_region is not None:
         ret = ret.get_time_region(self.time_region)
     if self.level_range is not None:
         ret = ret.get_between('level',min(self.level_range),max(self.level_range))
         
     return(ret)
Example #2
0
    def get_field(self, format_time=True, interpolate_spatial_bounds=False):
        """
        :param bool format_time:
        :param bool interpolate_spatial_bounds:
        :raises ValueError:
        """

        def _get_temporal_adds_(ref_attrs):
            ## calendar should default to standard if it is not present and the
            ## t_calendar overload is not used.
            calendar = self.rd.t_calendar or ref_attrs.get('calendar', None) or 'standard'

            return ({'units': self.rd.t_units or ref_attrs['units'],
                     'calendar': calendar,
                     'format_time': format_time})

        ## this dictionary contains additional keyword arguments for the row
        ## and column dimensions.
        adds_row_col = {'interpolate_bounds': interpolate_spatial_bounds}

        ## parameters for the loading loop
        to_load = {'temporal': {'cls': NcTemporalDimension, 'adds': _get_temporal_adds_, 'axis': 'T', 'name_uid': 'tid',
                                'name_value': 'time'},
                   'level': {'cls': NcVectorDimension, 'adds': None, 'axis': 'Z', 'name_uid': 'lid',
                             'name_value': 'level'},
                   'row': {'cls': NcVectorDimension, 'adds': adds_row_col, 'axis': 'Y', 'name_uid': 'row_id',
                           'name_value': 'row'},
                   'col': {'cls': NcVectorDimension, 'adds': adds_row_col, 'axis': 'X', 'name_uid': 'col_id',
                           'name_value': 'col'},
                   'realization': {'cls': NcVectorDimension, 'adds': None, 'axis': 'R', 'name_uid': 'rlz_id',
                                   'name_value': 'rlz'}}
        loaded = {}

        for k, v in to_load.iteritems():
            ## this is the string axis representation
            axis_value = v['axis'] or v['cls']._axis
            ## pull the axis information out of the dimension map
            ref_axis = self.rd.source_metadata['dim_map'].get(axis_value)
            ref_axis = self.rd.source_metadata['dim_map'].get(axis_value)
            ## if the axis is not represented, fill it with none. this happens
            ## when a dataset does not have a vertical level or projection axis
            ## for example.
            if ref_axis is None:
                fill = None
            else:
                ref_variable = self.rd.source_metadata['variables'].get(ref_axis['variable'])

                ## for data with a projection/realization axis there may be no
                ## associated variable.
                try:
                    ref_variable['axis'] = ref_axis
                except TypeError:
                    if axis_value == 'R' and ref_variable is None:
                        ref_variable = {'axis': ref_axis, 'name': ref_axis['dimension'], 'attrs': {}}

                ## extract the data length to use when creating the source index
                ## arrays.
                length = self.rd.source_metadata['dimensions'][ref_axis['dimension']]['len']
                src_idx = np.arange(0, length, dtype=constants.np_int)

                ## get the target data type for the dimension
                try:
                    dtype = np.dtype(ref_variable['dtype'])
                ## the realization dimension may not be a associated with a variable
                except KeyError:
                    if k == 'realization' and ref_variable['axis']['variable'] is None:
                        dtype = None
                    else:
                        raise

                ## assemble parameters for creating the dimension class then initialize
                ## the class.
                kwds = dict(name_uid=v['name_uid'], name_value=v['name_value'], src_idx=src_idx,
                            data=self.rd, meta=ref_variable, axis=axis_value, name=ref_variable.get('name'),
                            dtype=dtype)

                ## there may be additional parameters for each dimension.
                if v['adds'] is not None:
                    try:
                        kwds.update(v['adds'](ref_variable['attrs']))
                    ## adds may not be a callable object. assume they are a
                    ## dictionary.
                    except TypeError:
                        kwds.update(v['adds'])
                kwds.update({'name': ref_variable.get('name')})
                fill = v['cls'](**kwds)

            loaded[k] = fill

        assert_raise(set(('temporal', 'row', 'col')).issubset(set([k for k, v in loaded.iteritems() if v != None])),
                     logger='request',
                     exc=ValueError('Target variable must at least have temporal, row, and column dimensions.'))

        grid = SpatialGridDimension(row=loaded['row'], col=loaded['col'])

        # crs = None
        # if rd.crs is not None:
        #     crs = rd.crs
        # else:
        #     crs = rd._get_crs_(rd._variable[0])
        # if crs is None:
        #     ocgis_lh('No "grid_mapping" attribute available assuming WGS84: {0}'.format(rd.uri),
        #              'request', logging.WARN)
        #     crs = CFWGS84()

        spatial = SpatialDimension(name_uid='gid', grid=grid, crs=self.rd.crs, abstraction=self.rd.s_abstraction)

        vc = VariableCollection()
        for vdict in self.rd:
            variable_meta = deepcopy(self.rd._source_metadata['variables'][vdict['variable']])
            variable_units = vdict['units'] or variable_meta['attrs'].get('units')
            dtype = np.dtype(variable_meta['dtype'])
            fill_value = variable_meta['fill_value']
            variable = Variable(vdict['variable'], vdict['alias'], units=variable_units, meta=variable_meta,
                                data=self.rd, conform_units_to=vdict['conform_units_to'], dtype=dtype,
                                fill_value=fill_value)
            vc.add_variable(variable)

        ret = NcField(variables=vc, spatial=spatial, temporal=loaded['temporal'], level=loaded['level'],
                      realization=loaded['realization'], meta=deepcopy(self.rd._source_metadata), uid=self.rd.did,
                      name=self.rd.name)

        ## apply any subset parameters after the field is loaded
        if self.rd.time_range is not None:
            ret = ret.get_between('temporal', min(self.rd.time_range), max(self.rd.time_range))
        if self.rd.time_region is not None:
            ret = ret.get_time_region(self.rd.time_region)
        if self.rd.level_range is not None:
            try:
                ret = ret.get_between('level', min(self.rd.level_range), max(self.rd.level_range))
            except AttributeError:
                ## there may be no level dimension
                if ret.level == None:
                    msg = ("A level subset was requested but the target dataset does not have a level dimension. The "
                           "dataset's alias is: {0}".format(self.rd.alias))
                    raise (ValueError(msg))
                else:
                    raise

        return ret
Example #3
0
    def _get_field_(self, format_time=True):
        """
        :param bool format_time:
        :raises ValueError:
        """

        # reference the request dataset's source metadata
        source_metadata = self.rd.source_metadata

        def _get_temporal_adds_(ref_attrs):
            # calendar should default to standard if it is not present and the t_calendar overload is not used.
            calendar = self.rd.t_calendar or ref_attrs.get("calendar", None) or "standard"

            return {
                "units": self.rd.t_units or ref_attrs["units"],
                "calendar": calendar,
                "format_time": format_time,
                "conform_units_to": self.rd.t_conform_units_to,
            }

        # parameters for the loading loop
        to_load = {
            "temporal": {
                "cls": NcTemporalDimension,
                "adds": _get_temporal_adds_,
                "axis": "T",
                "name_uid": "tid",
                "name": "time",
            },
            "level": {"cls": NcVectorDimension, "adds": None, "axis": "Z", "name_uid": "lid", "name": "level"},
            "row": {"cls": NcVectorDimension, "adds": None, "axis": "Y", "name_uid": "yc_id", "name": "yc"},
            "col": {"cls": NcVectorDimension, "adds": None, "axis": "X", "name_uid": "xc_id", "name": "xc"},
            "realization": {
                "cls": NcVectorDimension,
                "adds": None,
                "axis": "R",
                "name_uid": "rlz_id",
                "name_value": "rlz",
            },
        }

        loaded = {}
        kwds_grid = {}
        has_row_column = True
        for k, v in to_load.iteritems():
            fill = self._get_vector_dimension_(k, v, source_metadata)
            if k != "realization" and not isinstance(fill, NcVectorDimension) and fill is not None:
                assert k in ("row", "col")
                has_row_column = False
                kwds_grid[k] = fill
            loaded[k] = fill

        loaded_keys = set([k for k, v in loaded.iteritems() if v is not None])
        if has_row_column:
            if not {"temporal", "row", "col"}.issubset(loaded_keys):
                raise ValueError("Target variable must at least have temporal, row, and column dimensions.")
            kwds_grid = {"row": loaded["row"], "col": loaded["col"]}
        else:
            shape_src_idx = [source_metadata["dimensions"][xx]["len"] for xx in kwds_grid["row"]["dimensions"]]
            src_idx = {
                "row": np.arange(0, shape_src_idx[0], dtype=np.int32),
                "col": np.arange(0, shape_src_idx[1], dtype=np.int32),
            }
            name_row = kwds_grid["row"]["name"]
            name_col = kwds_grid["col"]["name"]
            kwds_grid = {"name_row": name_row, "name_col": name_col, "data": self.rd, "src_idx": src_idx}

        grid = NcSpatialGridDimension(**kwds_grid)

        spatial = SpatialDimension(name_uid="gid", grid=grid, crs=self.rd.crs, abstraction=self.rd.s_abstraction)

        vc = VariableCollection()
        for vdict in self.rd:
            variable_meta = deepcopy(source_metadata["variables"][vdict["variable"]])
            variable_units = vdict["units"] or variable_meta["attrs"].get("units")
            dtype = np.dtype(variable_meta["dtype"])
            fill_value = variable_meta["fill_value"]
            variable = Variable(
                vdict["variable"],
                vdict["alias"],
                units=variable_units,
                meta=variable_meta,
                data=self.rd,
                conform_units_to=vdict["conform_units_to"],
                dtype=dtype,
                fill_value=fill_value,
                attrs=variable_meta["attrs"].copy(),
            )
            vc.add_variable(variable)

        ret = NcField(
            variables=vc,
            spatial=spatial,
            temporal=loaded["temporal"],
            level=loaded["level"],
            realization=loaded["realization"],
            meta=source_metadata.copy(),
            uid=self.rd.did,
            name=self.rd.name,
            attrs=source_metadata["dataset"].copy(),
        )

        # Apply any subset parameters after the field is loaded.
        if self.rd.time_range is not None:
            ret = ret.get_between("temporal", min(self.rd.time_range), max(self.rd.time_range))
        if self.rd.time_region is not None:
            ret = ret.get_time_region(self.rd.time_region)
        if self.rd.time_subset_func is not None:
            ret = ret.get_time_subset_by_function(self.rd.time_subset_func)
        if self.rd.level_range is not None:
            try:
                ret = ret.get_between("level", min(self.rd.level_range), max(self.rd.level_range))
            except AttributeError:
                # there may be no level dimension
                if ret.level is None:
                    msg = messages.M4.format(self.rd.alias)
                    raise ValueError(msg)
                else:
                    raise

        return ret
Example #4
0
    def _get_field_(self, format_time=True):
        """
        :param bool format_time:
        :raises ValueError:
        """

        # reference the request dataset's source metadata
        source_metadata = self.rd.source_metadata

        def _get_temporal_adds_(ref_attrs):
            # calendar should default to standard if it is not present and the t_calendar overload is not used.
            calendar = self.rd.t_calendar or ref_attrs.get('calendar', None) or 'standard'

            return {'units': self.rd.t_units or ref_attrs['units'], 'calendar': calendar, 'format_time': format_time,
                    'conform_units_to': self.rd.t_conform_units_to}

        # parameters for the loading loop
        to_load = {'temporal': {'cls': NcTemporalDimension, 'adds': _get_temporal_adds_, 'axis': 'T', 'name_uid': 'tid',
                                'name': 'time'},
                   'level': {'cls': NcVectorDimension, 'adds': None, 'axis': 'Z', 'name_uid': 'lid', 'name': 'level'},
                   'row': {'cls': NcVectorDimension, 'adds': None, 'axis': 'Y', 'name_uid': 'yc_id', 'name': 'yc'},
                   'col': {'cls': NcVectorDimension, 'adds': None, 'axis': 'X', 'name_uid': 'xc_id', 'name': 'xc'},
                   'realization': {'cls': NcVectorDimension, 'adds': None, 'axis': 'R', 'name_uid': 'rlz_id',
                                   'name_value': 'rlz'}}

        loaded = {}
        kwds_grid = {}
        has_row_column = True
        for k, v in to_load.iteritems():
            fill = self._get_vector_dimension_(k, v, source_metadata)
            if k != 'realization' and not isinstance(fill, NcVectorDimension) and fill is not None:
                assert k in ('row', 'col')
                has_row_column = False
                kwds_grid[k] = fill
            loaded[k] = fill

        loaded_keys = set([k for k, v in loaded.iteritems() if v is not None])
        if has_row_column:
            if not {'temporal', 'row', 'col'}.issubset(loaded_keys):
                raise ValueError('Target variable must at least have temporal, row, and column dimensions.')
            kwds_grid = {'row': loaded['row'], 'col': loaded['col']}
        else:
            shape_src_idx = [source_metadata['dimensions'][xx]['len'] for xx in kwds_grid['row']['dimensions']]
            src_idx = {'row': np.arange(0, shape_src_idx[0], dtype=np.int32),
                       'col': np.arange(0, shape_src_idx[1], dtype=np.int32)}
            name_row = kwds_grid['row']['name']
            name_col = kwds_grid['col']['name']
            kwds_grid = {'name_row': name_row, 'name_col': name_col, 'request_dataset': self.rd, 'src_idx': src_idx}

        grid = NcSpatialGridDimension(**kwds_grid)

        spatial = SpatialDimension(name_uid='gid', grid=grid, crs=self.rd.crs, abstraction=self.rd.s_abstraction)

        vc = VariableCollection()
        for vdict in self.rd:
            variable_meta = deepcopy(source_metadata['variables'][vdict['variable']])
            variable_units = vdict['units'] or variable_meta['attrs'].get('units')
            attrs = variable_meta['attrs'].copy()
            if variable_meta['dtype_packed'] is None:
                dtype = np.dtype(variable_meta['dtype'])
                fill_value = variable_meta['fill_value']
            else:
                dtype = np.dtype(variable_meta['dtype_packed'])
                fill_value = variable_meta['fill_value_packed']
                # Remove scale factors and offsets from the metadata.
                attrs.pop('scale_factor')
                attrs.pop('add_offset', None)
                attrs.pop('missing_value', None)
                attrs.pop('_Fill_Value', None)
            variable = Variable(vdict['variable'], vdict['alias'], units=variable_units, meta=variable_meta,
                                request_dataset=self.rd, conform_units_to=vdict['conform_units_to'], dtype=dtype,
                                fill_value=fill_value, attrs=attrs)
            vc.add_variable(variable)

        ret = NcField(variables=vc, spatial=spatial, temporal=loaded['temporal'], level=loaded['level'],
                      realization=loaded['realization'], meta=source_metadata.copy(), uid=self.rd.did,
                      name=self.rd.name, attrs=source_metadata['dataset'].copy())

        # Apply any subset parameters after the field is loaded.
        if self.rd.time_range is not None:
            ret = ret.get_between('temporal', min(self.rd.time_range), max(self.rd.time_range))
        if self.rd.time_region is not None:
            ret = ret.get_time_region(self.rd.time_region)
        if self.rd.time_subset_func is not None:
            ret = ret.get_time_subset_by_function(self.rd.time_subset_func)
        if self.rd.level_range is not None:
            try:
                ret = ret.get_between('level', min(self.rd.level_range), max(self.rd.level_range))
            except AttributeError:
                # there may be no level dimension
                if ret.level is None:
                    msg = messages.M4.format(self.rd.alias)
                    raise ValueError(msg)
                else:
                    raise

        return ret