Exemple #1
0
 def validate(self, value):
     if value is not None:
         try:
             get_units_object(value)
         except ValueError:
             msg = 'Units not recognized by conversion backend: {}'.format(value)
             raise DefinitionValidationError(self.__class__, msg)
Exemple #2
0
    def test_cfunits_conform(self):
        units_kelvin = get_units_object('kelvin')

        # Conversion of celsius units to kelvin.
        attrs = {k: 1 for k in NETCDF_ATTRIBUTES_TO_REMOVE_ON_VALUE_CHANGE}
        var = Variable(name='tas', units='celsius', value=self.value, attrs=attrs)
        self.assertEqual(len(var.attrs), 4)
        var.cfunits_conform(units_kelvin)
        self.assertNumpyAll(var.value, np.ma.array([278.15] * 3))
        self.assertEqual(var.cfunits, units_kelvin)
        self.assertEqual(var.units, 'kelvin')
        self.assertEqual(len(var.attrs), 0)

        # If there are no units associated with a variable, conforming the units should fail.
        var = Variable(name='tas', units=None, value=self.value)
        with self.assertRaises(NoUnitsError):
            var.cfunits_conform(units_kelvin)

        # Conversion should fail for nonequivalent units.
        var = Variable(name='tas', units='kelvin', value=self.value)
        with self.assertRaises(ValueError):
            var.cfunits_conform(get_units_object('grams'))

        # The data type should always be updated to match the output from CF units backend.
        av = Variable(value=np.array([4, 5, 6]), dtype=int)
        self.assertEqual(av.dtype, np.dtype(int))
        with self.assertRaises(NoUnitsError):
            av.cfunits_conform('K')
        av.units = 'celsius'
        av.cfunits_conform('K')
        self.assertIsNone(av._dtype)
        self.assertEqual(av.dtype, av.value.dtype)
Exemple #3
0
 def validate(self, value):
     if value is not None:
         try:
             get_units_object(value)
         except ValueError:
             msg = 'Units not recognized by conversion backend: {}'.format(
                 value)
             raise DefinitionValidationError(self.__class__, msg)
Exemple #4
0
 def test_validate_units_bad_units(self):
     field = self.get_field(with_value=True)
     field['tmax'].units = 'celsius'
     self.assertEqual(field['tmax'].cfunits, get_units_object('celsius'))
     fnu = MockNeedsUnits(field=field)
     with self.assertRaises(UnitsValidationError):
         fnu.execute()
Exemple #5
0
 def test_validate_units_bad_units(self):
     field = self.get_field(with_value=True)
     field.variables['tmax'].units = 'celsius'
     self.assertEqual(field.variables['tmax'].cfunits, get_units_object('celsius'))
     fnu = FooNeedsUnits(field=field)
     with self.assertRaises(UnitsValidationError):
         fnu.execute()
Exemple #6
0
    def test_init(self):
        cc = ConformUnitsTo()
        self.assertEqual(cc.value, None)

        cc = ConformUnitsTo('kelvin')
        self.assertEqual(cc.value, 'kelvin')

        cc = ConformUnitsTo('not_a_unit')
        self.assertEqual(cc.value, 'not_a_unit')

        cc = ConformUnitsTo(get_units_object('celsius'))
        target = get_are_units_equal((cc.value, get_units_object('celsius')))
        self.assertTrue(target)

        cc = ConformUnitsTo('hPa')
        target = get_are_units_equal((cc.value, get_units_object('hPa')))
        self.assertTrue(target)
Exemple #7
0
 def test_validate_units_bad_units(self):
     field = self.get_field(with_value=True)
     tgd = field.temporal.get_grouping(['month'])
     field.variables['tmax'].units = 'celsius'
     self.assertEqual(field.variables['tmax'].cfunits, get_units_object('celsius'))
     fnu = FooNeedsUnitsSet(field=field,tgd=tgd)
     with self.assertRaises(UnitsValidationError):
         fnu.execute()
Exemple #8
0
 def test_validate_units_bad_units(self):
     field = self.get_field(with_value=True)
     tgd = field.temporal.get_grouping(['month'])
     field['tmax'].units = 'celsius'
     self.assertEqual(field['tmax'].cfunits, get_units_object('celsius'))
     fnu = MockNeedsUnitsSet(field=field, tgd=tgd)
     with self.assertRaises(UnitsValidationError):
         fnu.execute()
Exemple #9
0
 def test_execute_units_are_maintained(self):
     field = self.get_field(with_value=True, month_count=2)
     units_kelvin = get_units_object('kelvin')
     self.assertEqual(field['tmax'].cfunits, units_kelvin)
     grouping = ['month']
     tgd = field.temporal.get_grouping(grouping)
     mu = Mean(field=field, tgd=tgd, alias='my_mean', calc_sample_size=False, dtype=np.float64)
     dvc = mu.execute()
     self.assertEqual(dvc['my_mean'].cfunits, units_kelvin)
Exemple #10
0
    def test_cfunits_conform(self):
        vdim = VectorDimension(value=[5., 10., 15.], units='celsius')
        vdim.set_extrapolated_bounds()
        vdim.cfunits_conform(get_units_object('kelvin'))
        self.assertNumpyAll(vdim.bounds, np.array([[275.65, 280.65], [280.65, 285.65], [285.65, 290.65]]))

        # Test conforming without bounds.
        vdim = VectorDimension(value=[5., 10., 15.], units='celsius')
        vdim.cfunits_conform('kelvin')
        self.assertNumpyAll(vdim.value, np.array([278.15, 283.15, 288.15]))
Exemple #11
0
    def test_get_field_t_conform_units_to(self):
        """
        Test conforming time units is appropriately passed to field object.
        """

        uri = self.test_data.get_uri('cancm4_tas')
        target = get_units_object('days since 1949-1-1', calendar='365_day')
        rd = RequestDataset(uri=uri, t_conform_units_to=target)
        field = rd.get()
        self.assertEqual(field.temporal.conform_units_to, target)
Exemple #12
0
    def test_get_are_units_equal(self):
        units = [get_units_object('celsius'), get_units_object('kelvin'), get_units_object('fahrenheit')]
        self.assertFalse(get_are_units_equal(units))

        units = [get_units_object('celsius'), get_units_object('celsius'), get_units_object('celsius')]
        self.assertTrue(get_are_units_equal(units))

        units = [get_units_object('celsius')]
        with self.assertRaises(ValueError):
            get_are_units_equal(units)
Exemple #13
0
    def test_init(self):
        cc = ConformUnitsTo()
        self.assertEqual(cc.value, None)

        if env.USE_CFUNITS:
            cc = ConformUnitsTo('kelvin')
            self.assertEqual(cc.value, 'kelvin')

            with self.assertRaises(DefinitionValidationError):
                ConformUnitsTo('not_a_unit')

            cc = ConformUnitsTo(get_units_object('celsius'))
            target = get_are_units_equal((cc.value, get_units_object('celsius')))
            self.assertTrue(target)

            cc = ConformUnitsTo('hPa')
            target = get_are_units_equal((cc.value, get_units_object('hPa')))
            self.assertTrue(target)
        else:
            with self.assertRaises(ImportError):
                ConformUnitsTo('celsius')
Exemple #14
0
    def test_init(self):
        self.assertEqual(AbstractVariable.__bases__, (Attributes,))

        av = AbstractVariable(value=self.value)
        self.assertNumpyAll(av.value, self.value)
        self.assertIsNone(av.alias)
        self.assertIsNone(av.conform_units_to)

        fav = AbstractVariable(name='foo')
        self.assertEqual(fav.alias, 'foo')

        # Test data types also pulled from value if present.
        dtype = float
        fav = AbstractVariable(value=self.value, dtype=dtype)
        self.assertEqual(fav.dtype, self.value.dtype)
        self.assertIsNone(fav._dtype)

        # Use string-based units.
        var = Variable(name='tas', units='celsius', value=self.value)
        self.assertEqual(var.units, 'celsius')
        self.assertEqual(var.cfunits, get_units_object('celsius'))
        self.assertNotEqual(var.cfunits, get_units_object('kelvin'))
        self.assertTrue(get_are_units_equivalent((var.cfunits, get_units_object('kelvin'))))

        # Use constructor with units objects v. string.
        var = Variable(name='tas', units=get_units_object('celsius'), value=self.value)
        self.assertEqual(var.units, 'celsius')
        self.assertEqual(var.cfunits, get_units_object('celsius'))

        # Test without units.
        var = Variable(name='tas', units=None, value=self.value)
        self.assertEqual(var.units, None)
        self.assertEqual(var.cfunits, get_units_object(None))
Exemple #15
0
    def test_init(self):
        cc = ConformUnitsTo()
        self.assertEqual(cc.value, None)

        if env.USE_CFUNITS:
            cc = ConformUnitsTo('kelvin')
            self.assertEqual(cc.value, 'kelvin')

            with self.assertRaises(DefinitionValidationError):
                ConformUnitsTo('not_a_unit')

            cc = ConformUnitsTo(get_units_object('celsius'))
            target = get_are_units_equal(
                (cc.value, get_units_object('celsius')))
            self.assertTrue(target)

            cc = ConformUnitsTo('hPa')
            target = get_are_units_equal((cc.value, get_units_object('hPa')))
            self.assertTrue(target)
        else:
            with self.assertRaises(ImportError):
                ConformUnitsTo('celsius')
Exemple #16
0
 def test_execute_units_are_maintained(self):
     field = self.get_field(with_value=True, month_count=2)
     units_kelvin = get_units_object('kelvin')
     self.assertEqual(field['tmax'].cfunits, units_kelvin)
     grouping = ['month']
     tgd = field.temporal.get_grouping(grouping)
     mu = Mean(field=field,
               tgd=tgd,
               alias='my_mean',
               calc_sample_size=False,
               dtype=np.float64)
     dvc = mu.execute()
     self.assertEqual(dvc['my_mean'].cfunits, units_kelvin)
Exemple #17
0
    def test_get_are_units_equal(self):
        units = [
            get_units_object('celsius'),
            get_units_object('kelvin'),
            get_units_object('fahrenheit')
        ]
        self.assertFalse(get_are_units_equal(units))

        units = [
            get_units_object('celsius'),
            get_units_object('celsius'),
            get_units_object('celsius')
        ]
        self.assertTrue(get_are_units_equal(units))

        units = [get_units_object('celsius')]
        with self.assertRaises(ValueError):
            get_are_units_equal(units)
Exemple #18
0
    def test_calculate(self):
        klasses = list(itersubclasses(AbstractIcclimPercentileArrayIndice))
        # There are six classes to test.
        self.assertEqual(len(klasses), 6)

        for mod in (1, 2):
            field = self.get_field(ntime=365)
            # Values less than 1 mm/day will be masked inside icclim.
            # var = field.variables.first()
            var = field.get_by_tag(TagName.DATA_VARIABLES)[0]
            var.get_value()[:] = var.get_value() * mod
            tgd = field.temporal.get_grouping(['month'])

            for klass in klasses:
                c = klass(field=field, tgd=tgd)
                res = c.execute()
                self.assertIsInstance(res, VariableCollection)
                dv = res.first()
                # Output units are always mm/day.
                if isinstance(c, IcclimR75pTOT):
                    self.assertTrue(get_are_units_equivalent((dv.cfunits, get_units_object('mm/day'))))
Exemple #19
0
 def test_get_field_with_overloaded_units(self):
     rd = self.test_data.get_rd('cancm4_tas', kwds={'conform_units_to': 'celsius'})
     preload = [False, True]
     for pre in preload:
         field = rd.get()
         # Conform units argument needs to be attached to a field variable.
         units_celsius = get_units_object('celsius')
         self.assertEqual(field.variables['tas']._conform_units_to, units_celsius)
         sub = field.get_time_region({'year': [2009], 'month': [5]})
         if pre:
             # If we wanted to load the data prior to subset then do so and manually perform the units conversion.
             to_test = sub.variables['tas'].value.copy()
             get_conformed_units(to_test, sub.variables['tas'].cfunits, units_celsius)
         # Assert the conform attribute makes it though the subset
         self.assertEqual(sub.variables['tas']._conform_units_to, units_celsius)
         value = sub.variables['tas'].value
         self.assertAlmostEqual(np.ma.mean(value), 5.921925206338206)
         self.assertAlmostEqual(np.ma.median(value), 10.745431900024414)
         if pre:
             # Assert the manually converted array matches the loaded value.
             self.assertNumpyAll(to_test, value)
Exemple #20
0
 def test_cfunits_conform_masked_array(self):
     # Assert mask is respected by unit conversion.
     value = np.ma.array(data=[5, 5, 5], mask=[False, True, False])
     var = Variable(name='tas', units=get_units_object('celsius'), value=value)
     var.cfunits_conform(get_units_object('kelvin'))
     self.assertNumpyAll(np.ma.array([278.15, 278.15, 278.15], mask=[False, True, False]), var.value)
Exemple #21
0
 def test_get_field_units_read_from_file(self):
     rd = self.test_data.get_rd('cancm4_tas')
     field = rd.get()
     self.assertEqual(field.variables['tas'].cfunits, get_units_object('K'))
 def test_cfunits(self):
     units = get_units_object('K')
     self.assertEqual(str(units), 'K')
Exemple #23
0
 def cfunits(self):
     return get_units_object(self.units)
Exemple #24
0
 def test_cfunits(self):
     units = get_units_object('K')
     self.assertEqual(str(units), 'K')
Exemple #25
0
 def test_conform_units_to(self):
     v = AbstractVariable(value=self.value, units='kelvin', conform_units_to='celsius')
     self.assertEqual(v.conform_units_to, get_units_object('celsius'))
Exemple #26
0
 def conform_units_to(self, value):
     if value is not None:
         value = get_units_object(value)
     self._conform_units_to = value
Exemple #27
0
 def test_units_with_bounds(self):
     value = [5., 10., 15.]
     vdim = VectorDimension(value=value, units='celsius',
                            bounds=get_bounds_from_1d(np.array(value)))
     vdim.cfunits_conform(get_units_object('kelvin'))
     self.assertNumpyAll(vdim.bounds, np.array([[275.65, 280.65], [280.65, 285.65], [285.65, 290.65]]))
Exemple #28
0
    def __init__(self,
                 uri=None,
                 variable=None,
                 units=None,
                 time_range=None,
                 time_region=None,
                 time_subset_func=None,
                 level_range=None,
                 conform_units_to=None,
                 crs='auto',
                 t_units=None,
                 t_calendar=None,
                 t_conform_units_to=None,
                 grid_abstraction='auto',
                 grid_is_isomorphic='auto',
                 dimension_map=None,
                 field_name=None,
                 driver=None,
                 regrid_source=True,
                 regrid_destination=False,
                 metadata=None,
                 format_time=True,
                 opened=None,
                 uid=None,
                 rename_variable=None,
                 predicate=None,
                 rotated_pole_priority=False,
                 driver_kwargs=None):
        self._is_init = True

        self._field_name = field_name
        self._level_range = None
        self._time_range = None
        self._time_region = None
        self._time_subset_func = None
        self._driver_kwargs = driver_kwargs

        if rename_variable is not None:
            rename_variable = get_tuple(rename_variable)
        self._rename_variable = rename_variable

        self.rotated_pole_priority = rotated_pole_priority
        self.predicate = predicate
        if dimension_map is not None and isinstance(dimension_map, dict):
            dimension_map = DimensionMap.from_dict(dimension_map)
        self._dimension_map = dimension_map

        self._metadata = deepcopy(metadata)
        self._uri = None
        self.uid = uid

        # This is an "open" file-like object that may be passed in-place of file location parameters.
        self._opened = opened
        if opened is not None and driver is None:
            msg = 'If "opened" is not None, then a "driver" must be provided.'
            ocgis_lh(logger='request',
                     exc=RequestValidationError('driver', msg))

        # Field creation options.
        self.format_time = format_time
        self.grid_abstraction = grid_abstraction
        self.grid_is_isomorphic = grid_is_isomorphic
        # Flag used for regridding to determine if the coordinate system was assigned during initialization.
        self._has_assigned_coordinate_system = False if crs == 'auto' else True

        if uri is None:
            # Fields may be created from pure metadata.
            if metadata is not None:
                # The default OCGIS driver is NetCDF.
                if driver is None:
                    driver = DriverKey.NETCDF_CF
            elif opened is None:
                ocgis_lh(logger='request',
                         exc=RequestValidationError('uri', 'Cannot be None'))
        else:
            self._uri = get_uri(uri)

        if driver is None:
            klass = get_autodiscovered_driver(uri)
        else:
            klass = get_driver(driver)
        self._driver = klass(self)

        if variable is not None:
            variable = get_tuple(variable)
        self._variable = variable

        self.time_range = time_range
        self.time_region = time_region
        self.time_subset_func = time_subset_func
        self.level_range = level_range

        self._crs = deepcopy(crs)

        self.regrid_source = regrid_source
        self.regrid_destination = regrid_destination

        self.units = units
        self.conform_units_to = conform_units_to

        self._is_init = False

        self._validate_time_subset_()

        # Update metadata for time variable.
        tvar = self.dimension_map.get_variable(DMK.TIME)
        if tvar is not None:
            m = self.metadata['variables'][tvar]
            if t_units is not None:
                m['attrs']['units'] = t_units
            if t_calendar is not None:
                m['attrs']['calendar'] = t_calendar
            if t_conform_units_to is not None:
                from ocgis.util.units import get_units_object
                t_calendar = m['attrs'].get(
                    'calendar', constants.DEFAULT_TEMPORAL_CALENDAR)
                t_conform_units_to = get_units_object(t_conform_units_to,
                                                      calendar=t_calendar)
                m['conform_units_to'] = t_conform_units_to
Exemple #29
0
    def __init__(self, uri=None, variable=None, units=None, time_range=None, time_region=None,
                 time_subset_func=None, level_range=None, conform_units_to=None, crs='auto', t_units=None,
                 t_calendar=None, t_conform_units_to=None, grid_abstraction='auto', grid_is_isomorphic='auto',
                 dimension_map=None, field_name=None, driver=None, regrid_source=True, regrid_destination=False,
                 metadata=None, format_time=True, opened=None, uid=None, rename_variable=None, predicate=None,
                 rotated_pole_priority=False, driver_kwargs=None, decomp_type=DecompositionType.OCGIS):
        self._is_init = True

        self._field_name = field_name
        self._level_range = None
        self._time_range = None
        self._time_region = None
        self._time_subset_func = None
        self._driver_kwargs = driver_kwargs
        self._decomp_type = decomp_type

        if rename_variable is not None:
            rename_variable = get_tuple(rename_variable)
        self._rename_variable = rename_variable

        self.rotated_pole_priority = rotated_pole_priority
        self.predicate = predicate
        if dimension_map is not None and isinstance(dimension_map, dict):
            dimension_map = DimensionMap.from_dict(dimension_map)
        self._dimension_map = dimension_map

        self._metadata = deepcopy(metadata)
        self._uri = None
        self.uid = uid

        # This is an "open" file-like object that may be passed in-place of file location parameters.
        self._opened = opened
        if opened is not None and driver is None:
            msg = 'If "opened" is not None, then a "driver" must be provided.'
            ocgis_lh(logger='request', exc=RequestValidationError('driver', msg))

        # Field creation options.
        self.format_time = format_time
        self.grid_abstraction = grid_abstraction
        self.grid_is_isomorphic = grid_is_isomorphic
        # Flag used for regridding to determine if the coordinate system was assigned during initialization.
        self._has_assigned_coordinate_system = False if crs == 'auto' else True

        if uri is None:
            # Fields may be created from pure metadata.
            if metadata is not None:
                # The default OCGIS driver is NetCDF.
                if driver is None:
                    driver = DriverKey.NETCDF_CF
            elif opened is None:
                ocgis_lh(logger='request', exc=RequestValidationError('uri', 'Cannot be None'))
        else:
            self._uri = get_uri(uri)

        if driver is None:
            klass = get_autodiscovered_driver(uri)
        else:
            klass = get_driver(driver)
        self._driver = klass(self)

        if variable is not None:
            variable = get_tuple(variable)
        self._variable = variable

        self.time_range = time_range
        self.time_region = time_region
        self.time_subset_func = time_subset_func
        self.level_range = level_range

        self._crs = deepcopy(crs)

        self.regrid_source = regrid_source
        self.regrid_destination = regrid_destination

        self.units = units
        self.conform_units_to = conform_units_to

        self._is_init = False

        self._validate_time_subset_()

        # Update metadata for time variable.
        tvar = self.dimension_map.get_variable(DMK.TIME)
        if tvar is not None:
            m = self.metadata['variables'][tvar]
            if t_units is not None:
                m['attrs']['units'] = t_units
            if t_calendar is not None:
                m['attrs']['calendar'] = t_calendar
            if t_conform_units_to is not None:
                from ocgis.util.units import get_units_object
                t_calendar = m['attrs'].get('calendar', constants.DEFAULT_TEMPORAL_CALENDAR)
                t_conform_units_to = get_units_object(t_conform_units_to, calendar=t_calendar)
                m['conform_units_to'] = t_conform_units_to