def test_dtypes(): assert Dtype('Float32').gdalint == 6 assert Dtype(6).gdalstr == 'Float32' assert Dtype('uint32').gdalstr == 'UInt32' with pytest.raises(ValueError): Dtype('foobar') with pytest.raises(ValueError): Dtype(999) with pytest.raises(TypeError): Dtype(None)
def __init__(self, filename, units='DN'): if isinstance(filename, list): combined = sum([Dataset(x, units) for x in filename]) self.__init__(combined) elif isinstance(filename, Dataset): for attr, value in vars(filename).items(): setattr(self, attr, value) elif isinstance(filename, str): # map pyroSAR sensor identifiers to platform and instrument codes sensor_lookup = { 'ASAR': ('ENVISAT', 'ASAR'), 'ERS1': ('ERS-1', 'SAR'), 'ERS2': ('ERS-2', 'SAR'), 'PSR1': ('ALOS-1', 'PALSAR'), 'PSR2': ('ALOS-2', 'PALSAR-2'), 'S1A': ('SENTINEL-1', 'C-SAR'), 'S1B': ('SENTINEL-1', 'C-SAR'), 'TSX1': ('TERRASAR-X_1', 'SAR'), 'TDX1': ('TANDEM-X_1', 'SAR') } # extract basic metadata attributes from the filename and register them to the object meta = parse_datasetname(filename) if meta is None: raise ValueError( 'could not identify dataset: {}'.format(filename)) for key, val in meta.items(): setattr(self, key, val) # define acquisition start and end time; Currently both are set to the acquisition start time, # which is contained in the filename # Time will only be correct if the full scene was processed, start and end time of s subset will # differ. Thus, accurately setting both is not seen as too relevant. self.from_dt = strftime('%Y-%m-%dT%H:%M:%S', strptime(self.start, '%Y%m%dT%H%M%S')) self.to_dt = strftime('%Y-%m-%dT%H:%M:%S', strptime(self.start, '%Y%m%dT%H%M%S')) # match the sensor ID from the filename to a platform and instrument if self.sensor not in sensor_lookup.keys(): raise ValueError('unknown sensor: {}'.format(self.sensor)) self.platform, self.instrument = sensor_lookup[self.sensor] # extract general geo metadata from the GTiff information with Raster(filename) as ras: self.dtype = Dtype(ras.dtype).numpystr self.nodata = ras.nodata self.format = ras.format self.xres, self.yres = ras.res self.crs = 'EPSG:{}'.format(ras.epsg) self.is_projected = ras.projcs is not None self.extent = self.__extent_convert(ras.geo, 'x', 'y') # reproject the raster bounding box to EPSG 4326 and store its extent with ras.bbox() as bbox: bbox.reproject(4326) self.extent_4326 = self.__extent_convert( bbox.extent, 'lon', 'lat') # create dictionary for resolution metadata depending on CRS characteristics resolution_keys = ('x', 'y') if self.is_projected else ('longitude', 'latitude') self.resolution = dict(zip(resolution_keys, (self.xres, self.yres))) # check whether the data type is supported pattern = '(?:(?:u|)int(?:8|16|32|64)|float(?:32|64))' if not re.search(pattern, self.dtype): raise ValueError('unsupported data type {}'.format(self.dtype)) # determine the dataset units if isinstance(units, str): units = units elif isinstance(units, dict): try: units = units[self.polarization] except KeyError: raise KeyError( "parameter 'units' does not contain key '{}'".format( self.polarization)) else: raise TypeError( "parameter 'units' must be of type str or dict") # create the measurement entry from collected metadata; # this is intended for easy access by class Product self.measurements = { self.polarization: { 'dtype': self.dtype, 'name': self.polarization, 'nodata': self.nodata, 'filename': filename, 'units': units } } else: raise TypeError('filename must be of type str, list or Dataset')