Exemplo n.º 1
0
def convert_cfunits(from_value,
                    from_unit,
                    wanted_unit=None,
                    suppress_unit=False):
    """ Use the cfunits-python package to handle the interaction with udunits2 """
    try:
        from cfunits import Units
    except ImportError:
        raise Exception("cfunits option relies on cfunits-python package")
    ZERO = False
    if float(from_value) == 0:
        # special Zero handling
        if from_unit != '1':
            warnings.warn("""Found a 0, udunits2 breaks,
            so we are assuming that this is not a non-zero based conversion like temperature"""
                          )
        ZERO = True
        from_value = 1.
    if wanted_unit:
        return Units.conform(from_value, Units(from_unit), Units(wanted_unit))
    out = Units(" ".join((str(from_value), from_unit))).format()
    split_out = out.split(' ')
    if len(split_out) == 1:
        out = (1., split_out[0])
    else:
        if ZERO:
            out = (0.0, split_out[1])
        else:
            out = (float(split_out[0]), split_out[1])

    if suppress_unit:
        return out[0]
    return out
Exemplo n.º 2
0
def gallon2liter(value):
    if value:
        return Units.conform(int(value),
                             Units('gallon / day'),
                             Units('liter / second'),
                             inplace=True)
    return 0.0
Exemplo n.º 3
0
    def get_value(self,
                  name,
                  out=None,
                  units=None,
                  angle=None,
                  at=None,
                  method=None):
        if out is None:
            grid = self.get_var_grid(name)
            dtype = self.get_var_type(name)
            if dtype == "":
                raise ValueError("{name} not understood".format(name=name))
            loc = self.get_var_grid_loc(name)
            out = np.empty(self.get_grid_dim(grid, loc), dtype=dtype)

        self.bmi.get_value(name, out)

        if name in self._interpolators and at is not None:
            out[:] = self._interpolators[name].interpolate(at)

        from_units = Units(self.get_var_units(name))
        if units is not None:
            to_units = Units(units)
        else:
            to_units = from_units

        if units is not None and from_units != to_units:
            Units.conform(out, from_units, to_units, inplace=True)

        # if units is not None:
        #     try:
        #         from_units = self.get_var_units(name)
        #     except AttributeError, NotImplementedError:
        #         pass
        #     else:
        #         Units.conform(out, Units(from_units), Units(units),
        #                       inplace=True)

        if angle not in ("azimuth", "math", None):
            raise ValueError("angle not understood")

        if angle == "azimuth" and "azimuth" not in name:
            transform_math_to_azimuth(out, to_units)
        elif angle == "math" and "azimuth" in name:
            transform_azimuth_to_math(out, to_units)

        return out
Exemplo n.º 4
0
    def get_value(self,
                  name,
                  out=None,
                  units=None,
                  angle=None,
                  at=None,
                  method=None):
        if out is None:
            grid = self.get_var_grid(name)
            dtype = self.get_var_type(name)
            if dtype == '':
                raise ValueError('{name} not understood'.format(name=name))
            out = np.empty(self.get_grid_size(grid), dtype=dtype)

        bmi_call(self.bmi.get_value, name, out)

        if name in self._interpolators and at is not None:
            out[:] = self._interpolators[name].interpolate(at)

        from_units = Units(self.get_var_units(name))
        if units is not None:
            to_units = Units(units)
        else:
            to_units = from_units

        if units is not None and from_units != to_units:
            Units.conform(out, from_units, to_units, inplace=True)

        # if units is not None:
        #     try:
        #         from_units = self.get_var_units(name)
        #     except AttributeError, NotImplementedError:
        #         pass
        #     else:
        #         Units.conform(out, Units(from_units), Units(units),
        #                       inplace=True)

        if angle not in ('azimuth', 'math', None):
            raise ValueError('angle not understood')

        if angle == 'azimuth' and 'azimuth' not in name:
            transform_math_to_azimuth(out, to_units)
        elif angle == 'math' and 'azimuth' in name:
            transform_azimuth_to_math(out, to_units)

        return out
Exemplo n.º 5
0
 def wrap(self, units=None):
     time = val_or_raise(func, (self._base, ))
     if units is not None:
         try:
             from_units = Units(self.get_time_units())
             to_units = Units(units)
         except AttributeError, NotImplementedError:
             pass
         else:
             if not from_units.equals(to_units):
                 time = Units.conform(time, from_units, to_units)
Exemplo n.º 6
0
    def wrap(self, name, out=None, units=None):
        """Get a value by name.

        Parameters
        ----------
        name : str
            CSDMS standard name.
        out : ndarray, optional
            Buffer to place values.
        units : str, optional
            Convert units of the returned values.

        Returns
        -------
        ndarray
            Array of values (or *out*, if provided).
        """
        if out is None:
            grid = self.get_var_grid(name)
            dtype = self.get_var_type(name)
            if dtype == '':
                print self.get_output_var_names()
                raise ValueError('{name} not understood'.format(name=name))
            out = np.empty(self.get_grid_size(grid), dtype=dtype)

        val_or_raise(func, (self._base, name, out))

        if units is not None:
            try:
                from_units = self.get_var_units(name)
            except AttributeError, NotImplementedError:
                pass
            else:
                Units.conform(out,
                              Units(from_units),
                              Units(units),
                              inplace=True)
Exemplo n.º 7
0
    def time_from(self, time, units):
        if units is None:
            return time

        try:
            # units_str = self.time_units
            units_str = self.time_units
        except (AttributeError, NotImplementedError):
            pass
        else:
            to_units = Units(units_str)
            from_units = Units(units)

            if not from_units.equals(to_units):
                time = Units.conform(time, from_units, to_units)

        return time
Exemplo n.º 8
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
         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 = Units.conform(sub.variables['tas'].value, 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)
Exemplo n.º 9
0
def convert_units(input_vals, input_unit, output_unit):
    """
    Convert the units of an array of values
    
    Params
    -------
    input_vals : Numpy array
        Values to convert
    input_unit : str
        Unit corresponding to the input values
    output_unit : str
        Desired unit to covert the values to
    
    Return
    -------
    Numpy array
    """
    conv_vals = Units.conform(input_vals, Units(input_unit),
                              Units(output_unit))
    return conv_vals
Exemplo n.º 10
0
 def conform(*args, **kwargs):
     return cfUnits.conform(*args, **kwargs)
Exemplo n.º 11
0
    def test_Units_conform(self):
        self.assertEqual(Units.conform(0.5, Units('km'), Units('m')), 500)

        self.assertEqual(Units.conform(360, Units('second'), Units('minute')),
                         6)

        x = Units.conform([360], Units('second'), Units('minute'))
        self.assertIsInstance(x, numpy.ndarray)
        self.assertEqual(x.dtype, numpy.dtype('float64'))
        self.assertTrue(numpy.allclose(x, 6))

        x = Units.conform((360, 720), Units('second'), Units('minute'))
        self.assertIsInstance(x, numpy.ndarray)
        self.assertEqual(x.dtype, numpy.dtype('float64'))
        self.assertTrue(numpy.allclose(x, [6, 12]))

        x = Units.conform([360.0, 720.0], Units('second'), Units('minute'))
        self.assertIsInstance(x, numpy.ndarray)
        self.assertEqual(x.dtype, numpy.dtype('float64'))
        self.assertTrue(numpy.allclose(x, [6, 12]))

        x = Units.conform([[360, 720]], Units('second'), Units('minute'))
        self.assertIsInstance(x, numpy.ndarray)
        self.assertEqual(x.dtype, numpy.dtype('float64'))
        self.assertTrue(numpy.allclose(x, [[6, 12]]))

        v = numpy.array([360.0, 720.0])
        x = Units.conform(v, Units('second'), Units('minute'))
        self.assertIsInstance(x, numpy.ndarray)
        self.assertEqual(x.dtype, numpy.dtype('float64'))
        self.assertTrue(numpy.allclose(x, [6, 12]), x)

        v = numpy.array([360, 720])
        x = Units.conform(v, Units('second'), Units('minute'), inplace=True)
        self.assertIsInstance(x, numpy.ndarray)
        self.assertEqual(x.dtype, numpy.dtype('float64'))
        self.assertTrue(numpy.allclose(x, [6, 12]))
        self.assertTrue(numpy.allclose(x, v))

        x = Units.conform(35, Units('degrees_C'), Units('degrees_F'))
        self.assertIsInstance(x, float)
        self.assertTrue(numpy.allclose(x, 95))

        x = Units.conform([35], Units('degrees_C'), Units('degrees_F'))
        self.assertIsInstance(x, numpy.ndarray)
        self.assertEqual(x.dtype, numpy.dtype('float64'))
        self.assertTrue(numpy.allclose(x, 95))

        x = Units.conform(35,
                          Units('degrees_C'),
                          Units('degrees_F'),
                          inplace=True)
        self.assertIsInstance(x, float)
        self.assertTrue(numpy.allclose(x, 95))

        x = Units.conform([35],
                          Units('degrees_C'),
                          Units('degrees_F'),
                          inplace=True)
        self.assertIsInstance(x, numpy.ndarray)
        self.assertEqual(x.dtype, numpy.dtype('float64'))
        self.assertTrue(numpy.allclose(x, 95))

        with self.assertRaises(ValueError):
            Units.conform(1, Units('m'), Units('second'))
Exemplo n.º 12
0
 def _convert(val, from_units, to_units):
     from_units, to_units = Units(from_units), Units(to_units)
     if from_units.equals(to_units):
         return val
     else:
         return Units.conform(val, from_units, to_units)
Exemplo n.º 13
0
    def __init__(self, inputFileName, gdalDataset, gdalMetadata, logLevel=30,
                 rmMetadatas=['NETCDF_VARNAME', '_Unsigned',
                              'ScaleRatio', 'ScaleOffset', 'dods_variable'],
                 **kwargs):
        # Remove 'NC_GLOBAL#' and 'GDAL_' and 'NANSAT_'
        # from keys in gdalDataset
        tmpGdalMetadata = {}
        geoMetadata = {}
        origin_is_nansat = False
        if not gdalMetadata:
            raise WrongMapperError
        for key in gdalMetadata.keys():
            newKey = key.replace('NC_GLOBAL#', '').replace('GDAL_', '')
            if 'NANSAT_' in newKey:
                geoMetadata[newKey.replace('NANSAT_', '')] = gdalMetadata[key]
                origin_is_nansat = True
            else:
                tmpGdalMetadata[newKey] = gdalMetadata[key]
        gdalMetadata = tmpGdalMetadata
        fileExt = os.path.splitext(inputFileName)[1]

        # Get file names from dataset or subdataset
        subDatasets = gdalDataset.GetSubDatasets()
        if len(subDatasets) == 0:
            fileNames = [inputFileName]
        else:
            fileNames = [f[0] for f in subDatasets]

        # add bands with metadata and corresponding values to the empty VRT
        metaDict = []
        xDatasetSource = ''
        yDatasetSource = ''
        firstXSize = 0
        firstYSize = 0
        for _, fileName in enumerate(fileNames):
            subDataset = gdal.Open(fileName)
            # choose the first dataset whith grid
            if (firstXSize == 0 and firstYSize == 0 and
                    subDataset.RasterXSize > 1 and subDataset.RasterYSize > 1):
                firstXSize = subDataset.RasterXSize
                firstYSize = subDataset.RasterYSize
                firstSubDataset = subDataset
                # get projection from the first subDataset
                projection = firstSubDataset.GetProjection()

            # take bands whose sizes are same as the first band.
            if (subDataset.RasterXSize == firstXSize and
                    subDataset.RasterYSize == firstYSize):
                if projection == '':
                    projection = subDataset.GetProjection()
                if ('GEOLOCATION_X_DATASET' in fileName or
                        'longitude' in fileName):
                    xDatasetSource = fileName
                elif ('GEOLOCATION_Y_DATASET' in fileName or
                        'latitude' in fileName):
                    yDatasetSource = fileName
                else:
                    for iBand in range(subDataset.RasterCount):
                        subBand = subDataset.GetRasterBand(iBand+1)
                        bandMetadata = subBand.GetMetadata_Dict()
                        if 'PixelFunctionType' in bandMetadata:
                            bandMetadata.pop('PixelFunctionType')
                        sourceBands = iBand + 1
                        # sourceBands = i*subDataset.RasterCount + iBand + 1

                        # generate src metadata
                        src = {'SourceFilename': fileName,
                               'SourceBand': sourceBands}
                        # set scale ratio and scale offset
                        scaleRatio = bandMetadata.get(
                            'ScaleRatio',
                            bandMetadata.get(
                                'scale',
                                bandMetadata.get('scale_factor', '')))
                        if len(scaleRatio) > 0:
                            src['ScaleRatio'] = scaleRatio
                        scaleOffset = bandMetadata.get(
                            'ScaleOffset',
                            bandMetadata.get(
                                'offset',
                                bandMetadata.get(
                                    'add_offset', '')))
                        if len(scaleOffset) > 0:
                            src['ScaleOffset'] = scaleOffset
                        # sate DataType
                        src['DataType'] = subBand.DataType

                        # generate dst metadata
                        # get all metadata from input band
                        dst = bandMetadata
                        # set wkv and bandname
                        dst['wkv'] = bandMetadata.get('standard_name', '')
                        # first, try the name metadata
                        if 'name' in bandMetadata:
                            bandName = bandMetadata['name']
                        else:
                            # if it doesn't exist get name from NETCDF_VARNAME
                            bandName = bandMetadata.get('NETCDF_VARNAME', '')
                            if len(bandName) == 0:
                                bandName = bandMetadata.get(
                                            'dods_variable', ''
                                            )

                            # remove digits added by gdal in
                            # exporting to netcdf...
                            if (len(bandName) > 0 and origin_is_nansat and
                                    fileExt == '.nc'):
                                if bandName[-1:].isdigit():
                                    bandName = bandName[:-1]
                                if bandName[-1:].isdigit():
                                    bandName = bandName[:-1]

                        # if still no bandname, create one
                        if len(bandName) == 0:
                            bandName = 'band_%03d' % iBand

                        dst['name'] = bandName

                        # remove non-necessary metadata from dst
                        for rmMetadata in rmMetadatas:
                            if rmMetadata in dst:
                                dst.pop(rmMetadata)

                        # append band with src and dst dictionaries
                        metaDict.append({'src': src, 'dst': dst})

        # create empty VRT dataset with geolocation only
        VRT.__init__(self, firstSubDataset, srcMetadata=gdalMetadata)

        # add bands with metadata and corresponding values to the empty VRT
        self._create_bands(metaDict)

        # Create complex data bands from 'xxx_real' and 'xxx_imag' bands
        # using pixelfunctions
        rmBands = []
        for iBandNo in range(self.dataset.RasterCount):
            iBand = self.dataset.GetRasterBand(iBandNo + 1)
            iBandName = iBand.GetMetadataItem('name')
            # find real data band
            if iBandName.find("_real") != -1:
                realBandNo = iBandNo
                realBand = self.dataset.GetRasterBand(realBandNo + 1)
                realDtype = realBand.GetMetadataItem('DataType')
                bandName = iBandName.replace(iBandName.split('_')[-1],
                                             '')[0:-1]
                for jBandNo in range(self.dataset.RasterCount):
                    jBand = self.dataset.GetRasterBand(jBandNo + 1)
                    jBandName = jBand.GetMetadataItem('name')
                    # find an imaginary data band corresponding to the real
                    # data band and create complex data band from the bands
                    if jBandName.find(bandName+'_imag') != -1:
                        imagBandNo = jBandNo
                        imagBand = self.dataset.GetRasterBand(imagBandNo + 1)
                        imagDtype = imagBand.GetMetadataItem('DataType')
                        dst = imagBand.GetMetadata()
                        dst['name'] = bandName
                        dst['PixelFunctionType'] = 'ComplexData'
                        dst['dataType'] = 10
                        src = [{'SourceFilename': fileNames[realBandNo],
                                'SourceBand':  1,
                                'DataType': realDtype},
                               {'SourceFilename': fileNames[imagBandNo],
                                'SourceBand': 1,
                                'DataType': imagDtype}]
                        self._create_band(src, dst)
                        self.dataset.FlushCache()
                        rmBands.append(realBandNo + 1)
                        rmBands.append(imagBandNo + 1)

        # Delete real and imaginary bands
        if len(rmBands) != 0:
            self.delete_bands(rmBands)

        if len(projection) == 0:
            # projection was not set automatically
            # get projection from GCPProjection
            projection = geoMetadata.get('GCPProjection', '')
        if len(projection) == 0:
            # no projection was found in dataset or metadata:
            # generate WGS84 by default
            projection = NSR().wkt
        # fix problem with MET.NO files where a, b given in m and XC/YC in km
        if ('UNIT["kilometre"' in projection and
            ',SPHEROID["Spheroid",6378273,7.331926543631893e-12]' in
                projection):
            projection = projection.replace(
                ',SPHEROID["Spheroid",6378273,7.331926543631893e-12]',
                '')
        # set projection
        self.dataset.SetProjection(self.repare_projection(projection))

        # check if GCPs were added from input dataset
        gcps = firstSubDataset.GetGCPs()
        gcpProjection = firstSubDataset.GetGCPProjection()

        # if no GCPs in input dataset: try to add GCPs from metadata
        if not gcps:
            gcps = self.add_gcps_from_metadata(geoMetadata)
        # if yet no GCPs: try to add GCPs from variables
        if not gcps:
            gcps = self.add_gcps_from_variables(inputFileName)

        if gcps:
            if len(gcpProjection) == 0:
                # get GCP projection and repare
                gcpProjection = self.repare_projection(geoMetadata.
                                                get('GCPProjection', ''))
            # add GCPs to dataset
            self.dataset.SetGCPs(gcps, gcpProjection)
            self.dataset.SetProjection('')
            self._remove_geotransform()

        # Find proper bands and insert GEOLOCATION ARRAY into dataset
        if len(xDatasetSource) > 0 and len(yDatasetSource) > 0:
            self.add_geolocationArray(GeolocationArray(xDatasetSource,
                                                       yDatasetSource))

        elif not gcps:
            # if no GCPs found and not GEOLOCATION ARRAY set:
            #   Set Nansat Geotransform if it is not set automatically
            geoTransform = self.dataset.GetGeoTransform()
            if len(geoTransform) == 0:
                geoTransformStr = geoMetadata.get('GeoTransform',
                                                  '(0|1|0|0|0|0|1)')
                geoTransform = eval(geoTransformStr.replace('|', ','))
                self.dataset.SetGeoTransform(geoTransform)

        subMetadata = firstSubDataset.GetMetadata()


        ### GET START TIME from METADATA
        time_coverage_start = None
        if 'start_time' in gdalMetadata:
            time_coverage_start = parse_time(gdalMetadata['start_time'])
        elif 'start_date' in gdalMetadata:
            time_coverage_start = parse_time(gdalMetadata['start_date'])
        elif 'time_coverage_start' in gdalMetadata:
            time_coverage_start = parse_time(
                                        gdalMetadata['time_coverage_start'])

        ### GET END TIME from METADATA
        time_coverage_end = None
        if 'stop_time' in gdalMetadata:
            time_coverage_start = parse_time(gdalMetadata['stop_time'])
        elif 'stop_date' in gdalMetadata:
            time_coverage_start = parse_time(gdalMetadata['stop_date'])
        elif 'time_coverage_stop' in gdalMetadata:
            time_coverage_start = parse_time(
                                        gdalMetadata['time_coverage_stop'])
        elif 'end_time' in gdalMetadata:
            time_coverage_start = parse_time(gdalMetadata['end_time'])
        elif 'end_date' in gdalMetadata:
            time_coverage_start = parse_time(gdalMetadata['end_date'])
        elif 'time_coverage_end' in gdalMetadata:
            time_coverage_start = parse_time(
                                        gdalMetadata['time_coverage_end'])

        ### GET start time from time variable
        if (time_coverage_start is None and cfunitsInstalled and
                 'time#standard_name' in subMetadata and
                 subMetadata['time#standard_name'] == 'time' and
                 'time#units' in subMetadata and
                 'time#calendar' in subMetadata):
            # get data from netcdf data
            ncFile = netcdf_file(inputFileName, 'r')
            timeLength = ncFile.variables['time'].shape[0]
            timeValueStart = ncFile.variables['time'][0]
            timeValueEnd = ncFile.variables['time'][-1]
            ncFile.close()
            try:
                timeDeltaStart = Units.conform(timeValueStart,
                                  Units(subMetadata['time#units'],
                                        calendar=subMetadata['time#calendar']),
                                  Units('days since 1950-01-01'))
            except ValueError:
                self.logger.error('calendar units are wrong: %s' %
                                  subMetadata['time#calendar'])
            else:
                time_coverage_start = (datetime.datetime(1950,1,1) +
                                   datetime.timedelta(float(timeDeltaStart)))

                if timeLength > 1:
                    timeDeltaEnd = Units.conform(timeValueStart,
                                          Units(subMetadata['time#units'],
                                                calendar=subMetadata['time#calendar']),
                                          Units('days since 1950-01-01'))
                else:
                    timeDeltaEnd = timeDeltaStart + 1
                time_coverage_end = (datetime.datetime(1950,1,1) +
                                     datetime.timedelta(float(timeDeltaEnd)))

        ## finally set values of time_coverage start and end if available
        if time_coverage_start is not None:
            self.dataset.SetMetadataItem('time_coverage_start',
                                    time_coverage_start.isoformat())
        if time_coverage_end is not None:
            self.dataset.SetMetadataItem('time_coverage_end',
                                    time_coverage_end.isoformat())

        if 'sensor' not in gdalMetadata:
            self.dataset.SetMetadataItem('sensor', 'unknown')
        if 'satellite' not in gdalMetadata:
            self.dataset.SetMetadataItem('satellite', 'unknown')
        if 'source_type' not in gdalMetadata:
            self.dataset.SetMetadataItem('source_type', 'unknown')
        if 'platform' not in gdalMetadata:
            self.dataset.SetMetadataItem('platform', 'unknown')
        if 'instrument' not in gdalMetadata:
            self.dataset.SetMetadataItem('instrument', 'unknown')

        self.logger.info('Use generic mapper - OK!')
Exemplo n.º 14
0
    def __init__(self,
                 inputFileName,
                 gdalDataset,
                 gdalMetadata,
                 logLevel=30,
                 rmMetadatas=[
                     'NETCDF_VARNAME', '_Unsigned', 'ScaleRatio',
                     'ScaleOffset', 'dods_variable'
                 ],
                 **kwargs):
        # Remove 'NC_GLOBAL#' and 'GDAL_' and 'NANSAT_'
        # from keys in gdalDataset
        tmpGdalMetadata = {}
        geoMetadata = {}
        origin_is_nansat = False
        if not gdalMetadata:
            raise WrongMapperError
        for key in gdalMetadata.keys():
            newKey = key.replace('NC_GLOBAL#', '').replace('GDAL_', '')
            if 'NANSAT_' in newKey:
                geoMetadata[newKey.replace('NANSAT_', '')] = gdalMetadata[key]
                origin_is_nansat = True
            else:
                tmpGdalMetadata[newKey] = gdalMetadata[key]
        gdalMetadata = tmpGdalMetadata
        fileExt = os.path.splitext(inputFileName)[1]

        # Get file names from dataset or subdataset
        subDatasets = gdalDataset.GetSubDatasets()
        if len(subDatasets) == 0:
            fileNames = [inputFileName]
        else:
            fileNames = [f[0] for f in subDatasets]

        # add bands with metadata and corresponding values to the empty VRT
        metaDict = []
        xDatasetSource = ''
        yDatasetSource = ''
        firstXSize = 0
        firstYSize = 0
        for _, fileName in enumerate(fileNames):
            subDataset = gdal.Open(fileName)
            # choose the first dataset whith grid
            if (firstXSize == 0 and firstYSize == 0
                    and subDataset.RasterXSize > 1
                    and subDataset.RasterYSize > 1):
                firstXSize = subDataset.RasterXSize
                firstYSize = subDataset.RasterYSize
                firstSubDataset = subDataset
                # get projection from the first subDataset
                projection = firstSubDataset.GetProjection()

            # take bands whose sizes are same as the first band.
            if (subDataset.RasterXSize == firstXSize
                    and subDataset.RasterYSize == firstYSize):
                if projection == '':
                    projection = subDataset.GetProjection()
                if ('GEOLOCATION_X_DATASET' in fileName
                        or 'longitude' in fileName):
                    xDatasetSource = fileName
                elif ('GEOLOCATION_Y_DATASET' in fileName
                      or 'latitude' in fileName):
                    yDatasetSource = fileName
                else:
                    for iBand in range(subDataset.RasterCount):
                        subBand = subDataset.GetRasterBand(iBand + 1)
                        bandMetadata = subBand.GetMetadata_Dict()
                        if 'PixelFunctionType' in bandMetadata:
                            bandMetadata.pop('PixelFunctionType')
                        sourceBands = iBand + 1
                        # sourceBands = i*subDataset.RasterCount + iBand + 1

                        # generate src metadata
                        src = {
                            'SourceFilename': fileName,
                            'SourceBand': sourceBands
                        }
                        # set scale ratio and scale offset
                        scaleRatio = bandMetadata.get(
                            'ScaleRatio',
                            bandMetadata.get(
                                'scale', bandMetadata.get('scale_factor', '')))
                        if len(scaleRatio) > 0:
                            src['ScaleRatio'] = scaleRatio
                        scaleOffset = bandMetadata.get(
                            'ScaleOffset',
                            bandMetadata.get(
                                'offset', bandMetadata.get('add_offset', '')))
                        if len(scaleOffset) > 0:
                            src['ScaleOffset'] = scaleOffset
                        # sate DataType
                        src['DataType'] = subBand.DataType

                        # generate dst metadata
                        # get all metadata from input band
                        dst = bandMetadata
                        # set wkv and bandname
                        dst['wkv'] = bandMetadata.get('standard_name', '')
                        # first, try the name metadata
                        if 'name' in bandMetadata:
                            bandName = bandMetadata['name']
                        else:
                            # if it doesn't exist get name from NETCDF_VARNAME
                            bandName = bandMetadata.get('NETCDF_VARNAME', '')
                            if len(bandName) == 0:
                                bandName = bandMetadata.get(
                                    'dods_variable', '')

                            # remove digits added by gdal in
                            # exporting to netcdf...
                            if (len(bandName) > 0 and origin_is_nansat
                                    and fileExt == '.nc'):
                                if bandName[-1:].isdigit():
                                    bandName = bandName[:-1]
                                if bandName[-1:].isdigit():
                                    bandName = bandName[:-1]

                        # if still no bandname, create one
                        if len(bandName) == 0:
                            bandName = 'band_%03d' % iBand

                        dst['name'] = bandName

                        # remove non-necessary metadata from dst
                        for rmMetadata in rmMetadatas:
                            if rmMetadata in dst:
                                dst.pop(rmMetadata)

                        # append band with src and dst dictionaries
                        metaDict.append({'src': src, 'dst': dst})

        # create empty VRT dataset with geolocation only
        VRT.__init__(self, firstSubDataset, srcMetadata=gdalMetadata)

        # add bands with metadata and corresponding values to the empty VRT
        self._create_bands(metaDict)

        # Create complex data bands from 'xxx_real' and 'xxx_imag' bands
        # using pixelfunctions
        rmBands = []
        for iBandNo in range(self.dataset.RasterCount):
            iBand = self.dataset.GetRasterBand(iBandNo + 1)
            iBandName = iBand.GetMetadataItem('name')
            # find real data band
            if iBandName.find("_real") != -1:
                realBandNo = iBandNo
                realBand = self.dataset.GetRasterBand(realBandNo + 1)
                realDtype = realBand.GetMetadataItem('DataType')
                bandName = iBandName.replace(iBandName.split('_')[-1],
                                             '')[0:-1]
                for jBandNo in range(self.dataset.RasterCount):
                    jBand = self.dataset.GetRasterBand(jBandNo + 1)
                    jBandName = jBand.GetMetadataItem('name')
                    # find an imaginary data band corresponding to the real
                    # data band and create complex data band from the bands
                    if jBandName.find(bandName + '_imag') != -1:
                        imagBandNo = jBandNo
                        imagBand = self.dataset.GetRasterBand(imagBandNo + 1)
                        imagDtype = imagBand.GetMetadataItem('DataType')
                        dst = imagBand.GetMetadata()
                        dst['name'] = bandName
                        dst['PixelFunctionType'] = 'ComplexData'
                        dst['dataType'] = 10
                        src = [{
                            'SourceFilename': fileNames[realBandNo],
                            'SourceBand': 1,
                            'DataType': realDtype
                        }, {
                            'SourceFilename': fileNames[imagBandNo],
                            'SourceBand': 1,
                            'DataType': imagDtype
                        }]
                        self._create_band(src, dst)
                        self.dataset.FlushCache()
                        rmBands.append(realBandNo + 1)
                        rmBands.append(imagBandNo + 1)

        # Delete real and imaginary bands
        if len(rmBands) != 0:
            self.delete_bands(rmBands)

        if len(projection) == 0:
            # projection was not set automatically
            # get projection from GCPProjection
            projection = geoMetadata.get('GCPProjection', '')
        if len(projection) == 0:
            # no projection was found in dataset or metadata:
            # generate WGS84 by default
            projection = NSR().wkt
        # fix problem with MET.NO files where a, b given in m and XC/YC in km
        if ('UNIT["kilometre"' in projection
                and ',SPHEROID["Spheroid",6378273,7.331926543631893e-12]'
                in projection):
            projection = projection.replace(
                ',SPHEROID["Spheroid",6378273,7.331926543631893e-12]', '')
        # set projection
        self.dataset.SetProjection(self.repare_projection(projection))

        # check if GCPs were added from input dataset
        gcps = firstSubDataset.GetGCPs()
        gcpProjection = firstSubDataset.GetGCPProjection()

        # if no GCPs in input dataset: try to add GCPs from metadata
        if not gcps:
            gcps = self.add_gcps_from_metadata(geoMetadata)
        # if yet no GCPs: try to add GCPs from variables
        if not gcps:
            gcps = self.add_gcps_from_variables(inputFileName)

        if gcps:
            if len(gcpProjection) == 0:
                # get GCP projection and repare
                gcpProjection = self.repare_projection(
                    geoMetadata.get('GCPProjection', ''))
            # add GCPs to dataset
            self.dataset.SetGCPs(gcps, gcpProjection)
            self.dataset.SetProjection('')
            self._remove_geotransform()

        # Find proper bands and insert GEOLOCATION ARRAY into dataset
        if len(xDatasetSource) > 0 and len(yDatasetSource) > 0:
            self.add_geolocationArray(
                GeolocationArray(xDatasetSource, yDatasetSource))

        elif not gcps:
            # if no GCPs found and not GEOLOCATION ARRAY set:
            #   Set Nansat Geotransform if it is not set automatically
            geoTransform = self.dataset.GetGeoTransform()
            if len(geoTransform) == 0:
                geoTransformStr = geoMetadata.get('GeoTransform',
                                                  '(0|1|0|0|0|0|1)')
                geoTransform = eval(geoTransformStr.replace('|', ','))
                self.dataset.SetGeoTransform(geoTransform)

        subMetadata = firstSubDataset.GetMetadata()

        ### GET START TIME from METADATA
        time_coverage_start = None
        if 'start_time' in gdalMetadata:
            time_coverage_start = parse_time(gdalMetadata['start_time'])
        elif 'start_date' in gdalMetadata:
            time_coverage_start = parse_time(gdalMetadata['start_date'])
        elif 'time_coverage_start' in gdalMetadata:
            time_coverage_start = parse_time(
                gdalMetadata['time_coverage_start'])

        ### GET END TIME from METADATA
        time_coverage_end = None
        if 'stop_time' in gdalMetadata:
            time_coverage_start = parse_time(gdalMetadata['stop_time'])
        elif 'stop_date' in gdalMetadata:
            time_coverage_start = parse_time(gdalMetadata['stop_date'])
        elif 'time_coverage_stop' in gdalMetadata:
            time_coverage_start = parse_time(
                gdalMetadata['time_coverage_stop'])
        elif 'end_time' in gdalMetadata:
            time_coverage_start = parse_time(gdalMetadata['end_time'])
        elif 'end_date' in gdalMetadata:
            time_coverage_start = parse_time(gdalMetadata['end_date'])
        elif 'time_coverage_end' in gdalMetadata:
            time_coverage_start = parse_time(gdalMetadata['time_coverage_end'])

        ### GET start time from time variable
        if (time_coverage_start is None and cfunitsInstalled
                and 'time#standard_name' in subMetadata
                and subMetadata['time#standard_name'] == 'time'
                and 'time#units' in subMetadata
                and 'time#calendar' in subMetadata):
            # get data from netcdf data
            ncFile = netcdf_file(inputFileName, 'r')
            timeLength = ncFile.variables['time'].shape[0]
            timeValueStart = ncFile.variables['time'][0]
            timeValueEnd = ncFile.variables['time'][-1]
            ncFile.close()
            try:
                timeDeltaStart = Units.conform(
                    timeValueStart,
                    Units(subMetadata['time#units'],
                          calendar=subMetadata['time#calendar']),
                    Units('days since 1950-01-01'))
            except ValueError:
                self.logger.error('calendar units are wrong: %s' %
                                  subMetadata['time#calendar'])
            else:
                time_coverage_start = (
                    datetime.datetime(1950, 1, 1) +
                    datetime.timedelta(float(timeDeltaStart)))

                if timeLength > 1:
                    timeDeltaEnd = Units.conform(
                        timeValueStart,
                        Units(subMetadata['time#units'],
                              calendar=subMetadata['time#calendar']),
                        Units('days since 1950-01-01'))
                else:
                    timeDeltaEnd = timeDeltaStart + 1
                time_coverage_end = (datetime.datetime(1950, 1, 1) +
                                     datetime.timedelta(float(timeDeltaEnd)))

        ## finally set values of time_coverage start and end if available
        if time_coverage_start is not None:
            self.dataset.SetMetadataItem('time_coverage_start',
                                         time_coverage_start.isoformat())
        if time_coverage_end is not None:
            self.dataset.SetMetadataItem('time_coverage_end',
                                         time_coverage_end.isoformat())

        if 'sensor' not in gdalMetadata:
            self.dataset.SetMetadataItem('sensor', 'unknown')
        if 'satellite' not in gdalMetadata:
            self.dataset.SetMetadataItem('satellite', 'unknown')
        if 'source_type' not in gdalMetadata:
            self.dataset.SetMetadataItem('source_type', 'unknown')
        if 'platform' not in gdalMetadata:
            self.dataset.SetMetadataItem('platform', 'unknown')
        if 'instrument' not in gdalMetadata:
            self.dataset.SetMetadataItem('instrument', 'unknown')

        self.logger.info('Use generic mapper - OK!')
Exemplo n.º 15
0
    def test_Units_conform(self):
        """Tests the `conform` class method on `Units`."""
        self.assertEqual(Units.conform(0.5, Units("km"), Units("m")), 500)

        self.assertEqual(Units.conform(360, Units("second"), Units("minute")),
                         6)

        x = Units.conform([360], Units("second"), Units("minute"))
        self.assertIsInstance(x, numpy.ndarray)
        self.assertEqual(x.dtype, numpy.dtype("float64"))
        self.assertTrue(numpy.allclose(x, 6))

        x = Units.conform((360, 720), Units("second"), Units("minute"))
        self.assertIsInstance(x, numpy.ndarray)
        self.assertEqual(x.dtype, numpy.dtype("float64"))
        self.assertTrue(numpy.allclose(x, [6, 12]))

        x = Units.conform([360.0, 720.0], Units("second"), Units("minute"))
        self.assertIsInstance(x, numpy.ndarray)
        self.assertEqual(x.dtype, numpy.dtype("float64"))
        self.assertTrue(numpy.allclose(x, [6, 12]))

        x = Units.conform([[360, 720]], Units("second"), Units("minute"))
        self.assertIsInstance(x, numpy.ndarray)
        self.assertEqual(x.dtype, numpy.dtype("float64"))
        self.assertTrue(numpy.allclose(x, [[6, 12]]))

        v = numpy.array([360.0, 720.0])
        x = Units.conform(v, Units("second"), Units("minute"))
        self.assertIsInstance(x, numpy.ndarray)
        self.assertEqual(x.dtype, numpy.dtype("float64"))
        self.assertTrue(numpy.allclose(x, [6, 12]), x)

        v = numpy.array([360, 720])
        x = Units.conform(v, Units("second"), Units("minute"), inplace=True)
        self.assertIsInstance(x, numpy.ndarray)
        self.assertEqual(x.dtype, numpy.dtype("float64"))
        self.assertTrue(numpy.allclose(x, [6, 12]))
        self.assertTrue(numpy.allclose(x, v))

        x = Units.conform(35, Units("degrees_C"), Units("degrees_F"))
        self.assertIsInstance(x, float)
        self.assertTrue(numpy.allclose(x, 95))

        x = Units.conform([35], Units("degrees_C"), Units("degrees_F"))
        self.assertIsInstance(x, numpy.ndarray)
        self.assertEqual(x.dtype, numpy.dtype("float64"))
        self.assertTrue(numpy.allclose(x, 95))

        x = Units.conform(35,
                          Units("degrees_C"),
                          Units("degrees_F"),
                          inplace=True)
        self.assertIsInstance(x, float)
        self.assertTrue(numpy.allclose(x, 95))

        x = Units.conform([35],
                          Units("degrees_C"),
                          Units("degrees_F"),
                          inplace=True)
        self.assertIsInstance(x, numpy.ndarray)
        self.assertEqual(x.dtype, numpy.dtype("float64"))
        self.assertTrue(numpy.allclose(x, 95))

        with self.assertRaises(ValueError):
            Units.conform(1, Units("m"), Units("second"))
Exemplo n.º 16
0
 def test_Units_conform(self):
     self.assertTrue(Units.conform(0.5, Units('km'), Units('m')) == 500)
     self.assertTrue(
         Units.conform(360, Units('second'), Units('minute')) == 6)
     with self.assertRaises(ValueError):
         Units.conform(1, Units('m'), Units('second'))