Ejemplo n.º 1
0
    def test_find_complex_band(self):
        a = np.random.randn(100,100)
        vrt1 = VRT.from_array(a)
        vrt2 = VRT.from_array(a.astype(np.complex64))

        vrt3 = VRT.from_gdal_dataset(vrt1.dataset)
        vrt3.create_bands([{'src': {'SourceFilename': vrt1.filename}},
                           {'src': {'SourceFilename': vrt2.filename}}])

        self.assertEqual(vrt1._find_complex_band(), None)
        self.assertEqual(vrt2._find_complex_band(), 1)
        self.assertEqual(vrt3._find_complex_band(), 2)
Ejemplo n.º 2
0
 def test_from_filenames(self):
     lon, lat = np.meshgrid(np.linspace(0,5,10), np.linspace(10,20,30))
     x_vrt = VRT.from_array(lon)
     y_vrt = VRT.from_array(lat)
     g = Geolocation.from_filenames(x_vrt.filename, y_vrt.filename)
     self.assertIsInstance(g, Geolocation)
     self.assertEqual(g.data['X_DATASET'], x_vrt.filename)
     self.assertEqual(g.data['Y_DATASET'], y_vrt.filename)
     self.assertEqual(g.data['LINE_OFFSET'], '0')
     self.assertEqual(g.data['LINE_STEP'], '1')
     self.assertEqual(g.data['PIXEL_OFFSET'], '0')
     self.assertEqual(g.data['PIXEL_STEP'], '1')
Ejemplo n.º 3
0
    def vrts_from_arrays(self, data, variable_names, pol='', resize=True, resample_alg=2):
        """ Convert input dict with arrays into dict with VRTs

        Parameters
        ----------
        data : dict
            2D arrays with data from LUT
        variable_names : list of str
            variable names that should be converted to VRTs
        pol : str
            HH, HV, etc
        resize : bool
            Shall VRT be zoomed to full size?
        resample_alg : int
            Index of resampling algorithm. See VRT.get_resized_vrt()

        Returns
        -------
        vrts : dict with (resized) VRTs

        """
        vrts = {}
        for var_name in variable_names:
            vrts[var_name+pol] = VRT.from_array(data[var_name+pol])
            if resize:
                vrts[var_name+pol] = vrts[var_name+pol].get_resized_vrt(self.dataset.RasterXSize,
                                                                        self.dataset.RasterYSize,
                                                                        resample_alg)
        return vrts
Ejemplo n.º 4
0
    def vrts_from_arrays(self,
                         data,
                         variable_names,
                         pol='',
                         resize=True,
                         resample_alg=2):
        """ Convert input dict with arrays into dict with VRTs

        Parameters:
        ----------_
        data : dict
            2D arrays with data from LUT
        variable_names : list of str
            variable names that should be converted to VRTs
        pol : str
            HH, HV, etc
        resize : bool
            Shall VRT be zoomed to full size?
        resample_alg : int
            Index of resampling algorithm. See VRT.get_resized_vrt()

        Returns:
        --------
        vrts : dict with (resized) VRTs

        """
        vrts = {}
        for var_name in variable_names:
            vrts[var_name + pol] = VRT.from_array(data[var_name + pol])
            if resize:
                vrts[var_name + pol] = vrts[var_name + pol].get_resized_vrt(
                    self.dataset.RasterXSize, self.dataset.RasterYSize,
                    resample_alg)
        return vrts
Ejemplo n.º 5
0
 def test_create_band(self):
     array = gdal.Open(self.test_file_gcps).ReadAsArray()[1, 10:, :]
     vrt1 = VRT.from_array(array)
     vrt2 = VRT(x_size=array.shape[1], y_size=array.shape[0])
     self.assertEqual(vrt2.dataset.RasterCount, 0)
     vrt2.create_band({'SourceFilename': vrt1.filename})
     self.assertEqual(vrt2.dataset.RasterCount, 1)
Ejemplo n.º 6
0
 def test_create_band(self):
     array = gdal.Open(self.test_file_gcps).ReadAsArray()[1, 10:, :]
     vrt1 = VRT.from_array(array)
     vrt2 = VRT(x_size=array.shape[1], y_size=array.shape[0])
     self.assertEqual(vrt2.dataset.RasterCount, 0)
     vrt2.create_band({'SourceFilename': vrt1.filename})
     self.assertEqual(vrt2.dataset.RasterCount, 1)
Ejemplo n.º 7
0
    def test_split_complex_bands(self):
        a = np.random.randn(100, 100)
        vrt1 = VRT.from_array(a.astype(np.complex64))
        vrt2 = VRT.from_array(a)
        vrt3 = VRT.from_array(a.astype(np.complex64))

        vrt4 = VRT.from_gdal_dataset(vrt1.dataset)
        vrt4.create_bands([{
            'src': {
                'SourceFilename': vrt1.filename
            },
            'dst': {
                'name': 'vrt1'
            }
        }, {
            'src': {
                'SourceFilename': vrt2.filename
            },
            'dst': {
                'name': 'vrt2'
            }
        }, {
            'src': {
                'SourceFilename': vrt3.filename
            },
            'dst': {
                'name': 'vrt3'
            }
        }])

        vrt4.split_complex_bands()

        self.assertEqual(vrt4.dataset.RasterCount, 5)
        self.assertEqual(
            vrt4.dataset.GetRasterBand(1).GetMetadataItem(str('name')), 'vrt2')
        self.assertEqual(
            vrt4.dataset.GetRasterBand(2).GetMetadataItem(str('name')),
            'vrt1_real')
        self.assertEqual(
            vrt4.dataset.GetRasterBand(3).GetMetadataItem(str('name')),
            'vrt1_imag')
        self.assertEqual(
            vrt4.dataset.GetRasterBand(4).GetMetadataItem(str('name')),
            'vrt3_real')
        self.assertEqual(
            vrt4.dataset.GetRasterBand(5).GetMetadataItem(str('name')),
            'vrt3_imag')
Ejemplo n.º 8
0
    def test_from_array(self):
        array = gdal.Open(self.test_file_gcps).ReadAsArray()[1, 10:, :]
        vrt = VRT.from_array(array)

        self.assertEqual(vrt.dataset.RasterXSize, array.shape[1])
        self.assertEqual(vrt.dataset.RasterYSize, array.shape[0])
        self.assertEqual(vrt.dataset.RasterCount, 1)
        self.assertIn('filename', list(vrt.dataset.GetMetadata().keys()))
        self.assertEqual(gdal.Unlink(vrt.filename.replace('.vrt', '.raw')), 0)
Ejemplo n.º 9
0
    def set_gcps(self, lon, lat, gdal_dataset):
        """ Set gcps """
        self.band_vrts['new_lon_VRT'] = VRT.from_array(lon)
        self.dataset.SetGCPs(VRT._lonlat2gcps(lon, lat, n_gcps=400), NSR().wkt)

        # Add geolocation from correct longitudes and latitudes
        self._add_geolocation(
                Geolocation(self.band_vrts['new_lon_VRT'], self, x_band=1, y_band=self._latitude_band_number(gdal_dataset))
            )
Ejemplo n.º 10
0
    def set_gcps(self, lon, lat, gdal_dataset):
        """ Set gcps """
        self.band_vrts['new_lon_VRT'] = VRT.from_array(lon)
        self.dataset.SetGCPs(VRT._lonlat2gcps(lon, lat, n_gcps=400), NSR().wkt)

        # Add geolocation from correct longitudes and latitudes
        self._add_geolocation(
                Geolocation(self.band_vrts['new_lon_VRT'], self, x_band=1, y_band=self._latitude_band_number(gdal_dataset))
            )
Ejemplo n.º 11
0
    def test_get_super_vrt_and_copy(self):
        array = np.zeros((10,10))
        vrt = VRT.from_array(array)
        vrt = vrt.get_super_vrt()
        vrt = vrt.copy()
        data = vrt.dataset.ReadAsArray()

        self.assertFalse(data is None)
        self.assertTrue(np.all(data == array))
Ejemplo n.º 12
0
    def test_get_super_vrt_and_copy(self):
        array = np.zeros((10,10))
        vrt = VRT.from_array(array)
        vrt = vrt.get_super_vrt()
        vrt = vrt.copy()
        data = vrt.dataset.ReadAsArray()

        self.assertFalse(data is None)
        self.assertTrue(np.all(data == array))
Ejemplo n.º 13
0
    def test_from_array(self):
        array = gdal.Open(self.test_file_gcps).ReadAsArray()[1, 10:, :]
        vrt = VRT.from_array(array)

        self.assertEqual(vrt.dataset.RasterXSize, array.shape[1])
        self.assertEqual(vrt.dataset.RasterYSize, array.shape[0])
        self.assertEqual(vrt.dataset.RasterCount, 1)
        self.assertIn('filename', list(vrt.dataset.GetMetadata().keys()))
        self.assertEqual(gdal.Unlink(vrt.filename.replace('.vrt', '.raw')), 0)
Ejemplo n.º 14
0
    def test_split_complex_bands(self):
        a = np.random.randn(100,100)
        vrt1 = VRT.from_array(a.astype(np.complex64))
        vrt2 = VRT.from_array(a)
        vrt3 = VRT.from_array(a.astype(np.complex64))

        vrt4 = VRT.from_gdal_dataset(vrt1.dataset)
        vrt4.create_bands([{'src': {'SourceFilename': vrt1.filename}, 'dst': {'name': 'vrt1'}},
                           {'src': {'SourceFilename': vrt2.filename}, 'dst': {'name': 'vrt2'}},
                           {'src': {'SourceFilename': vrt3.filename}, 'dst': {'name': 'vrt3'}}])

        vrt4.split_complex_bands()

        self.assertEqual(vrt4.dataset.RasterCount,5)
        self.assertEqual(vrt4.dataset.GetRasterBand(1).GetMetadataItem(str('name')), 'vrt2')
        self.assertEqual(vrt4.dataset.GetRasterBand(2).GetMetadataItem(str('name')), 'vrt1_real')
        self.assertEqual(vrt4.dataset.GetRasterBand(3).GetMetadataItem(str('name')), 'vrt1_imag')
        self.assertEqual(vrt4.dataset.GetRasterBand(4).GetMetadataItem(str('name')), 'vrt3_real')
        self.assertEqual(vrt4.dataset.GetRasterBand(5).GetMetadataItem(str('name')), 'vrt3_imag')
Ejemplo n.º 15
0
    def test_find_complex_band(self):
        a = np.random.randn(100, 100)
        vrt1 = VRT.from_array(a)
        vrt2 = VRT.from_array(a.astype(np.complex64))

        vrt3 = VRT.from_gdal_dataset(vrt1.dataset)
        vrt3.create_bands([{
            'src': {
                'SourceFilename': vrt1.filename
            }
        }, {
            'src': {
                'SourceFilename': vrt2.filename
            }
        }])

        self.assertEqual(vrt1._find_complex_band(), None)
        self.assertEqual(vrt2._find_complex_band(), 1)
        self.assertEqual(vrt3._find_complex_band(), 2)
Ejemplo n.º 16
0
    def add_look_direction_band(self):
        lon, lat = self.get_full_size_GCPs()
        """
        TODO: Also in mapper_sentinel1_l1.py... Use this code there..
        """
        sat_heading = initial_bearing(lon[:-1, :], lat[:-1, :], lon[1:, :],
                                      lat[1:, :])
        look_direction = scipy.ndimage.interpolation.zoom(
            np.mod(sat_heading + 90, 360),
            (np.shape(lon)[0] / (np.shape(lon)[0] - 1.), 1))

        # Decompose, to avoid interpolation errors around 0 <-> 360
        look_direction_u = np.sin(np.deg2rad(look_direction))
        look_direction_v = np.cos(np.deg2rad(look_direction))
        look_u_VRT = VRT.from_array(look_direction_u)
        look_v_VRT = VRT.from_array(look_direction_v)
        lookVRT = VRT.from_lonlat(lon, lat)
        lookVRT.create_band([{
            'SourceFilename': look_u_VRT.filename,
            'SourceBand': 1
        }, {
            'SourceFilename': look_v_VRT.filename,
            'SourceBand': 1
        }], {'PixelFunctionType': 'UVToDirectionTo'})

        # Blow up to full size
        lookVRT = lookVRT.get_resized_vrt(self.dataset.RasterXSize,
                                          self.dataset.RasterYSize, 1)

        # Store VRTs so that they are accessible later
        self.band_vrts['look_u_VRT'] = look_u_VRT
        self.band_vrts['look_v_VRT'] = look_v_VRT
        self.band_vrts['lookVRT'] = lookVRT

        src = {
            'SourceFilename': self.band_vrts['lookVRT'].filename,
            'SourceBand': 1
        }
        dst = {'wkv': 'sensor_azimuth_angle', 'name': 'look_direction'}
        self.create_band(src, dst)
        self.dataset.FlushCache()
        """ End repetition """
Ejemplo n.º 17
0
    def test_export(self):
        array = gdal.Open(self.test_file_gcps).ReadAsArray()[1, 10:, :]
        vrt = VRT.from_array(array)
        vrt.export(self.tmp_filename)
        self.assertTrue(self.tmp_filename)
        tree = ET.parse(self.tmp_filename)
        root = tree.getroot()

        self.assertEqual(root.tag, 'VRTDataset')
        self.assertIn('rasterXSize', list(root.keys()))
        self.assertIn('rasterYSize', list(root.keys()))

        self.assertEqual([e.tag for e in root], ['Metadata', 'VRTRasterBand'])
Ejemplo n.º 18
0
    def test_export(self):
        array = gdal.Open(self.test_file_gcps).ReadAsArray()[1, 10:, :]
        vrt = VRT.from_array(array)
        vrt.export(self.tmp_filename)
        self.assertTrue(self.tmp_filename)
        tree = ET.parse(self.tmp_filename)
        root = tree.getroot()

        self.assertEqual(root.tag, 'VRTDataset')
        self.assertIn('rasterXSize', list(root.keys()))
        self.assertIn('rasterYSize', list(root.keys()))

        self.assertEqual([e.tag for e in root], ['Metadata', 'VRTRasterBand'])
Ejemplo n.º 19
0
    def test_init(self):
        lon, lat = np.meshgrid(np.linspace(0, 5, 10), np.linspace(10, 20, 30))
        x_vrt = VRT.from_array(lon)
        y_vrt = VRT.from_array(lat)

        ga = Geolocation(x_vrt, y_vrt)

        self.assertIsInstance(ga, Geolocation)
        self.assertEqual(ga.data['X_DATASET'], x_vrt.filename)
        self.assertEqual(ga.data['Y_DATASET'], y_vrt.filename)
        self.assertEqual(ga.data['LINE_OFFSET'], '0')
        self.assertEqual(ga.data['LINE_STEP'], '1')
        self.assertEqual(ga.data['PIXEL_OFFSET'], '0')
        self.assertEqual(ga.data['PIXEL_STEP'], '1')
        srs = osr.SpatialReference()
        status = srs.ImportFromWkt(ga.data['SRS'])
        self.assertEqual(status, 0)
        self.assertEqual(srs.ExportToProj4().strip(),
                         '+proj=longlat +datum=WGS84 +no_defs')
        self.assertEqual(ga.data['X_BAND'], '1')
        self.assertEqual(ga.data['Y_BAND'], '1')
        self.assertEqual(ga.x_vrt, x_vrt)
        self.assertEqual(ga.y_vrt, y_vrt)
Ejemplo n.º 20
0
    def test_init(self):
        lon, lat = np.meshgrid(np.linspace(0,5,10), np.linspace(10,20,30))
        x_vrt = VRT.from_array(lon)
        y_vrt = VRT.from_array(lat)

        ga = Geolocation(x_vrt, y_vrt)

        self.assertIsInstance(ga, Geolocation)
        self.assertEqual(ga.data['X_DATASET'], x_vrt.filename)
        self.assertEqual(ga.data['Y_DATASET'], y_vrt.filename)
        self.assertEqual(ga.data['LINE_OFFSET'], '0')
        self.assertEqual(ga.data['LINE_STEP'], '1')
        self.assertEqual(ga.data['PIXEL_OFFSET'], '0')
        self.assertEqual(ga.data['PIXEL_STEP'], '1')
        self.assertEqual(ga.data['SRS'], 'GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",'
                                         '6378137,298.257223563,AUTHORITY["EPSG","7030"]],AUT'
                                         'HORITY["EPSG","6326"]],PRIMEM["Greenwich",0,AUTHORI'
                                         'TY["EPSG","8901"]],UNIT["degree",0.0174532925199433'
                                         ',AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4326"]]')
        self.assertEqual(ga.data['X_BAND'], '1')
        self.assertEqual(ga.data['Y_BAND'], '1')
        self.assertEqual(ga.x_vrt, x_vrt)
        self.assertEqual(ga.y_vrt, y_vrt)
Ejemplo n.º 21
0
    def __init__(self,
                 filename,
                 gdal_dataset,
                 metadata,
                 quartile=0,
                 *args,
                 **kwargs):

        super(Mapper, self).__init__(filename, gdal_dataset, metadata, *args,
                                     **kwargs)

        intervals = [0, 1, 2, 3]
        if not quartile in intervals:
            raise ValueError('quartile must be one of [0,1,2,3]')

        y_size = self.dataset.RasterYSize / 4
        y_offset = [y_size * qq for qq in intervals][quartile]

        # Crop
        self.set_offset_size('y', y_offset, y_size)

        # Add quartile to metadata
        self.dataset.SetMetadataItem('quartile', str(quartile))

        # Create band of times
        # TODO: resolve nansat issue #263 (https://github.com/nansencenter/nansat/issues/263)
        #import ipdb; ipdb.set_trace()
        tt = self.times()[int(y_offset):int(y_offset + y_size)]
        self.dataset.SetMetadataItem('time_coverage_start',
                                     tt[0].astype(datetime).isoformat())
        self.dataset.SetMetadataItem('time_coverage_end',
                                     tt[-1].astype(datetime).isoformat())
        time_stamps = (tt - tt[0]) / np.timedelta64(1, 's')
        self.band_vrts['time'] = VRT.from_array(
            np.tile(time_stamps, (self.dataset.RasterXSize, 1)).transpose())
        self.create_band(src={
            'SourceFilename': self.band_vrts['time'].filename,
            'SourceBand': 1,
        },
                         dst={
                             'name':
                             'timestamp',
                             'time_coverage_start':
                             tt[0].astype(datetime).isoformat(),
                             'units':
                             'seconds since time_coverage_start',
                         })
Ejemplo n.º 22
0
    def create_VRT_from_ADS(self, adsName, zoomSize=500):
        """ Create VRT with a band from Envisat ADS metadata

        Read offsets of the <adsName> ADS.
        Read 2D matrix of binary values from ADS from file.
        Zoom array with ADS data to <zoomSize>. Zooming is needed to create smooth matrices. Array
        is zoomed to small size because it is stred in memory. Later the VRT with zoomed array is
        VRT.get_resized_vrt() in order to match the size of the Nansat object.

        Create VRT from the ADS array.

        Parameters
        ----------
            adsName : str
                name of variable from ADS to read. should match allADSParams
            zoomSize :  int, optional, 500
                size, to which original matrix from ADSR is zoomed using
                scipy.zoom

        Returns
        -------
            adsVrt : VRT, vrt with a band created from ADS array

        """
        adsHeight = self.dsOffsetDict["NUM_DSR"]
        adsParams = self.allADSParams['list'][adsName]
        array = self.get_array_from_ADS(adsName)

        if not IMPORT_SCIPY:
            raise NansatReadError(
                'ENVISAT data cannot be read because scipy is not installed...'
            )

        # zoom the array
        array = scipy.ndimage.interpolation.zoom(array,
                                                 zoomSize / float(adsHeight),
                                                 order=1)

        # create VRT from the array
        adsVrt = VRT.from_array(array=array)
        # add "name" and "units" to band metadata
        bandMetadata = {"name": adsName, "units": adsParams['units']}
        adsVrt.dataset.GetRasterBand(1).SetMetadata(bandMetadata)

        return adsVrt
Ejemplo n.º 23
0
    def test_make_source_bands_xml(self):
        array = gdal.Open(self.test_file_gcps).ReadAsArray()[1, 10:, :]
        vrt1 = VRT.from_array(array)
        src1 = {'SourceFilename': vrt1.filename}
        src2 = VRT._make_source_bands_xml(src1)
        self.assertIn('XML', src2)
        self.assertEqual(src2['SourceFilename'], vrt1.filename)
        self.assertEqual(src2['SourceBand'], 1)
        self.assertEqual(src2['LUT'], '')
        self.assertEqual(src2['NODATA'], '')
        self.assertEqual(src2['SourceType'], 'ComplexSource')
        self.assertEqual(src2['ScaleRatio'], 1.0)
        self.assertEqual(src2['ScaleOffset'], 0.0)
        self.assertEqual(src2['DataType'], 1)
        self.assertEqual(src2['xSize'], 200)
        self.assertEqual(src2['ySize'], 190)

        with self.assertRaises(KeyError):
            src2 = VRT._make_source_bands_xml({})
Ejemplo n.º 24
0
    def test_make_source_bands_xml(self):
        array = gdal.Open(self.test_file_gcps).ReadAsArray()[1, 10:, :]
        vrt1 = VRT.from_array(array)
        src1 = {'SourceFilename': vrt1.filename}
        src2 = VRT._make_source_bands_xml(src1)
        self.assertIn('XML', src2)
        self.assertEqual(src2['SourceFilename'], vrt1.filename)
        self.assertEqual(src2['SourceBand'], 1)
        self.assertEqual(src2['LUT'], '')
        self.assertEqual(src2['NODATA'], '')
        self.assertEqual(src2['SourceType'], 'ComplexSource')
        self.assertEqual(src2['ScaleRatio'], 1.0)
        self.assertEqual(src2['ScaleOffset'], 0.0)
        self.assertEqual(src2['DataType'], 1)
        self.assertEqual(src2['xSize'], 200)
        self.assertEqual(src2['ySize'], 190)

        with self.assertRaises(KeyError):
            src2 = VRT._make_source_bands_xml({})
Ejemplo n.º 25
0
    def add_incidence_angle_band(self):
        # Get GCP variables
        pixel = self.ds['GCP_pixel_' + self.ds.polarisation[:2]][:].data
        line = self.ds['GCP_line_' + self.ds.polarisation[:2]][:].data
        inci = self.ds['GCP_incidenceAngle_' +
                       self.ds.polarisation[:2]][:].data
        inci = inci.reshape(
            np.unique(line[:].data).shape[0],
            np.unique(pixel[:].data).shape[0])

        # Add incidence angle band
        inciVRT = VRT.from_array(inci)
        inciVRT = inciVRT.get_resized_vrt(self.dataset.RasterXSize,
                                          self.dataset.RasterYSize, 1)
        self.band_vrts['inciVRT'] = inciVRT
        src = {
            'SourceFilename': self.band_vrts['inciVRT'].filename,
            'SourceBand': 1
        }
        dst = {'wkv': 'angle_of_incidence', 'name': 'incidence_angle'}
        self.create_band(src, dst)
        self.dataset.FlushCache()
Ejemplo n.º 26
0
    def __init__(self, filename, gdal_dataset, metadata, quartile=0, *args, **kwargs):

        super(Mapper, self).__init__(filename, gdal_dataset, metadata, *args, **kwargs)

        intervals = [0,1,2,3]
        if not quartile in intervals:
            raise ValueError('quartile must be one of [0,1,2,3]')

        y_size = self.dataset.RasterYSize/4
        y_offset = [y_size*qq for qq in intervals][quartile]

        # Crop
        self.set_offset_size('y', y_offset, y_size)

        # Add quartile to metadata
        self.dataset.SetMetadataItem('quartile', str(quartile))

        # Create band of times
        # TODO: resolve nansat issue #263 (https://github.com/nansencenter/nansat/issues/263)
        #import ipdb; ipdb.set_trace()
        tt = self.times()[int(y_offset) : int(y_offset + y_size)]
        self.dataset.SetMetadataItem('time_coverage_start', tt[0].astype(datetime).isoformat())
        self.dataset.SetMetadataItem('time_coverage_end', tt[-1].astype(datetime).isoformat())
        time_stamps = (tt - tt[0]) / np.timedelta64(1, 's')
        self.band_vrts['time'] = VRT.from_array(
                np.tile(time_stamps, (self.dataset.RasterXSize, 1)).transpose()
            )
        self.create_band(
                src = {
                    'SourceFilename': self.band_vrts['time'].filename,
                    'SourceBand': 1,
                },
                dst = {
                    'name': 'timestamp',
                    'time_coverage_start': tt[0].astype(datetime).isoformat(),
                    'units': 'seconds since time_coverage_start',
                }
            )
Ejemplo n.º 27
0
 def test_create_band_name_existing_name(self):
     self.mock_pti['get_wkv_variable'].side_effect = IndexError
     vrt = VRT.from_array(np.zeros((10,10)))
     vrt.dataset.GetRasterBand(1).SetMetadata({'name':'band1'})
     self.assertEqual(vrt._create_band_name({'name': 'band1'}), ('band1_0000', {}))
Ejemplo n.º 28
0
 def test_get_shifted_vrt(self):
     deg = -10
     vrt1 = VRT.from_array(np.zeros((180,360)))
     vrt1.dataset.SetProjection(NSR().wkt)
     vrt2 = vrt1.get_shifted_vrt(deg)
     self.assertEqual(vrt1.dataset.GetGeoTransform()[0]+deg, vrt2.dataset.GetGeoTransform()[0])
Ejemplo n.º 29
0
    def test_copy_vrt_with_band(self):
        array = gdal.Open(self.test_file_gcps).ReadAsArray()[1, 10:, :]
        vrt1 = VRT.from_array(array)
        vrt2 = vrt1.copy()

        self.assertEqual(vrt2.dataset.RasterCount, 1)
Ejemplo n.º 30
0
    def __init__(self, inputFileName, gdalDataset, gdalMetadata,
                 xmlonly=False,  **kwargs):
        ''' Create Radarsat2 VRT '''
        fPathName, fExt = os.path.splitext(inputFileName)

        if zipfile.is_zipfile(inputFileName):
            # Open zip file using VSI
            fPath, fName = os.path.split(fPathName)
            filename = '/vsizip/%s/%s' % (inputFileName, fName)
            if not 'RS' in fName[0:2]:
                raise WrongMapperError('%s: Provided data is not Radarsat-2'
                        %fName)
            gdalDataset = gdal.Open(filename)
            gdalMetadata = gdalDataset.GetMetadata()
        else:
            filename = inputFileName

        #if it is not RADARSAT-2, return
        if (not gdalMetadata or not 'SATELLITE_IDENTIFIER' in list(gdalMetadata.keys())):
            raise WrongMapperError(filename)
        elif gdalMetadata['SATELLITE_IDENTIFIER'] != 'RADARSAT-2':
            raise WrongMapperError(filename)

        if zipfile.is_zipfile(inputFileName):
            # Open product.xml to get additional metadata
            zz = zipfile.ZipFile(inputFileName)
            productXmlName = os.path.join(os.path.basename(inputFileName).split('.')[0],'product.xml')
            productXml = zz.open(productXmlName).read()
        else:
            # product.xml to get additionali metadata
            productXmlName = os.path.join(filename,'product.xml')
            if not os.path.isfile(productXmlName):
                raise WrongMapperError(filename)
            productXml = open(productXmlName).read()

        if not IMPORT_SCIPY:
            raise NansatReadError('Radarsat-2 data cannot be read because scipy is not installed')

        # parse product.XML
        rs2_0 = Node.create(productXml)

        if xmlonly:
            self.init_from_xml(rs2_0)
            return

        # Get additional metadata from product.xml
        rs2_1 = rs2_0.node('sourceAttributes')
        rs2_2 = rs2_1.node('radarParameters')
        if rs2_2['antennaPointing'].lower() == 'right':
            antennaPointing = 90
        else:
            antennaPointing = -90
        rs2_3 = rs2_1.node('orbitAndAttitude').node('orbitInformation')
        passDirection = rs2_3['passDirection']

        # create empty VRT dataset with geolocation only
        self._init_from_gdal_dataset(gdalDataset)

        #define dictionary of metadata and band specific parameters
        pol = []
        metaDict = []

        # Get the subdataset with calibrated sigma0 only
        for dataset in gdalDataset.GetSubDatasets():
            if dataset[1] == 'Sigma Nought calibrated':
                s0dataset = gdal.Open(dataset[0])
                s0datasetName = dataset[0][:]
                band = s0dataset.GetRasterBand(1)
                s0datasetPol = band.GetMetadata()['POLARIMETRIC_INTERP']
                for i in range(1, s0dataset.RasterCount+1):
                    iBand = s0dataset.GetRasterBand(i)
                    polString = iBand.GetMetadata()['POLARIMETRIC_INTERP']
                    suffix = polString
                    # The nansat data will be complex
                    # if the SAR data is of type 10
                    dtype = iBand.DataType
                    if dtype == 10:
                        # add intensity band
                        metaDict.append(
                            {'src': {'SourceFilename':
                                     ('RADARSAT_2_CALIB:SIGMA0:'
                                      + filename + '/product.xml'),
                                     'SourceBand': i,
                                     'DataType': dtype},
                             'dst': {'wkv': 'surface_backwards_scattering_coefficient_of_radar_wave',
                                     'PixelFunctionType': 'intensity',
                                     'SourceTransferType': gdal.GetDataTypeName(dtype),
                                     'suffix': suffix,
                                     'polarization': polString,
                                     'dataType': 6}})
                        # modify suffix for adding the compled band below
                        suffix = polString+'_complex'
                    pol.append(polString)
                    metaDict.append(
                        {'src': {'SourceFilename': ('RADARSAT_2_CALIB:SIGMA0:'
                                                    + filename
                                                    + '/product.xml'),
                                 'SourceBand': i,
                                 'DataType': dtype},
                         'dst': {'wkv': 'surface_backwards_scattering_coefficient_of_radar_wave',
                                 'suffix': suffix,
                                 'polarization': polString}})

            if dataset[1] == 'Beta Nought calibrated':
                b0dataset = gdal.Open(dataset[0])
                b0datasetName = dataset[0][:]
                for j in range(1, b0dataset.RasterCount+1):
                    jBand = b0dataset.GetRasterBand(j)
                    polString = jBand.GetMetadata()['POLARIMETRIC_INTERP']
                    if polString == s0datasetPol:
                        b0datasetBand = j

        ###############################
        # Add SAR look direction
        ###############################
        d = Domain(ds=gdalDataset)
        lon, lat = d.get_geolocation_grids(100)

        '''
        (GDAL?) Radarsat-2 data is stored with maximum latitude at first
        element of each column and minimum longitude at first element of each
        row (e.g. np.shape(lat)=(59,55) -> latitude maxima are at lat[0,:],
        and longitude minima are at lon[:,0])

        In addition, there is an interpolation error for direct estimate along
        azimuth. We therefore estimate the heading along range and add 90
        degrees to get the "satellite" heading.

        '''
        if str(passDirection).upper() == 'DESCENDING':
            sat_heading = initial_bearing(lon[:, :-1], lat[:, :-1],
                                          lon[:, 1:], lat[:, 1:]) + 90
        elif str(passDirection).upper() == 'ASCENDING':
            sat_heading = initial_bearing(lon[:, 1:], lat[:, 1:],
                                          lon[:, :-1], lat[:, :-1]) + 90
        else:
            print('Can not decode pass direction: ' + str(passDirection))

        # Calculate SAR look direction
        look_direction = sat_heading + antennaPointing
        # Interpolate to regain lost row
        look_direction = np.mod(look_direction, 360)
        look_direction = scipy.ndimage.interpolation.zoom(
            look_direction, (1, 11./10.))
        # Decompose, to avoid interpolation errors around 0 <-> 360
        look_direction_u = np.sin(np.deg2rad(look_direction))
        look_direction_v = np.cos(np.deg2rad(look_direction))
        look_u_VRT = VRT.from_array(look_direction_u)
        look_v_VRT = VRT.from_array(look_direction_v)

        # Note: If incidence angle and look direction are stored in
        #       same VRT, access time is about twice as large
        lookVRT = VRT.from_lonlat(lon, lat)
        lookVRT.create_band(
            [{'SourceFilename': look_u_VRT.filename, 'SourceBand': 1},
             {'SourceFilename': look_v_VRT.filename, 'SourceBand': 1}],
            {'PixelFunctionType': 'UVToDirectionTo'})

        # Blow up to full size
        lookVRT = lookVRT.get_resized_vrt(gdalDataset.RasterXSize, gdalDataset.RasterYSize)
        # Store VRTs so that they are accessible later
        self.band_vrts['look_u_VRT'] = look_u_VRT
        self.band_vrts['look_v_VRT'] = look_v_VRT
        self.band_vrts['lookVRT'] = lookVRT

        # Add band to full sized VRT
        lookFileName = self.band_vrts['lookVRT'].filename
        metaDict.append({'src': {'SourceFilename': lookFileName,
                                 'SourceBand': 1},
                         'dst': {'wkv': 'sensor_azimuth_angle',
                                 'name': 'look_direction'}})

        ###############################
        # Create bands
        ###############################
        self.create_bands(metaDict)

        ###################################################
        # Add derived band (incidence angle) calculated
        # using pixel function "BetaSigmaToIncidence":
        ###################################################
        src = [{'SourceFilename': b0datasetName,
                'SourceBand':  b0datasetBand,
                'DataType': dtype},
               {'SourceFilename': s0datasetName,
                'SourceBand': 1,
                'DataType': dtype}]
        dst = {'wkv': 'angle_of_incidence',
               'PixelFunctionType': 'BetaSigmaToIncidence',
               'SourceTransferType': gdal.GetDataTypeName(dtype),
               '_FillValue': -10000,   # NB: this is also hard-coded in
                                       #     pixelfunctions.c
               'dataType': 6,
               'name': 'incidence_angle'}

        self.create_band(src, dst)
        self.dataset.FlushCache()

        ###################################################################
        # Add sigma0_VV - pixel function of sigma0_HH and beta0_HH
        # incidence angle is calculated within pixel function
        # It is assummed that HH is the first band in sigma0 and
        # beta0 sub datasets
        ###################################################################
        if 'VV' not in pol and 'HH' in pol:
            s0datasetNameHH = pol.index('HH')+1
            src = [{'SourceFilename': s0datasetName,
                    'SourceBand': s0datasetNameHH,
                    'DataType': 6},
                   {'SourceFilename': b0datasetName,
                    'SourceBand': b0datasetBand,
                    'DataType': 6}]
            dst = {'wkv': 'surface_backwards_scattering_coefficient_of_radar_wave',
                   'PixelFunctionType': 'Sigma0HHBetaToSigma0VV',
                   'polarization': 'VV',
                   'suffix': 'VV'}
            self.create_band(src, dst)
            self.dataset.FlushCache()

        ############################################
        # Add SAR metadata
        ############################################
        if antennaPointing == 90:
            self.dataset.SetMetadataItem('ANTENNA_POINTING', 'RIGHT')
        if antennaPointing == -90:
            self.dataset.SetMetadataItem('ANTENNA_POINTING', 'LEFT')
        self.dataset.SetMetadataItem('ORBIT_DIRECTION',
                                     str(passDirection).upper())

        # set valid time
        self.dataset.SetMetadataItem('time_coverage_start',
                                     (parse(gdalMetadata['FIRST_LINE_TIME']).
                                      isoformat()))
        self.dataset.SetMetadataItem('time_coverage_end',
                                     (parse(gdalMetadata['LAST_LINE_TIME']).
                                      isoformat()))

        # Get dictionary describing the instrument and platform according to
        # the GCMD keywords
        mm = pti.get_gcmd_instrument('sar')
        ee = pti.get_gcmd_platform('radarsat-2')

        # TODO: Validate that the found instrument and platform are indeed what we
        # want....

        self.dataset.SetMetadataItem('instrument', json.dumps(mm))
        self.dataset.SetMetadataItem('platform', json.dumps(ee))
Ejemplo n.º 31
0
    def __init__(self, filename, gdalDataset, gdalMetadata, **kwargs):

        '''
        Parameters
        -----------
        filename : string

        gdalDataset : gdal dataset

        gdalMetadata : gdal metadata

        '''

        self.setup_ads_parameters(filename, gdalMetadata)

        if self.product[0:4] != "ASA_":
            raise WrongMapperError

        if not IMPORT_SCIPY:
            raise NansatReadError('ASAR data cannot be read because scipy is not installed')

        # get channel string (remove '/', since NetCDF
        # does not support that in metadata)
        polarization = [{'channel': gdalMetadata['SPH_MDS1_TX_RX_POLAR']
                        .replace("/", ""), 'bandNum': 1}]
        # if there is the 2nd band, get channel string
        if 'SPH_MDS2_TX_RX_POLAR' in gdalMetadata.keys():
            channel = gdalMetadata['SPH_MDS2_TX_RX_POLAR'].replace("/", "")
            if not(channel.isspace()):
                polarization.append({'channel': channel,
                                     'bandNum': 2})

        # create empty VRT dataset with geolocation only
        self._init_from_gdal_dataset(gdalDataset, metadata=gdalMetadata)

        # get calibration constant
        gotCalibration = True
        try:
            for iPolarization in polarization:
                metaKey = ('MAIN_PROCESSING_PARAMS_ADS_CALIBRATION_FACTORS.%d.EXT_CAL_FACT'
                           % (iPolarization['bandNum']))
                iPolarization['calibrationConst'] = float(
                    gdalDataset.GetMetadataItem(metaKey, 'records'))
        except:
            try:
                for iPolarization in polarization:
                    # Apparently some ASAR files have calibration
                    # constant stored in another place
                    metaKey = ('MAIN_PROCESSING_PARAMS_ADS_0_CALIBRATION_FACTORS.%d.EXT_CAL_FACT'
                               % (iPolarization['bandNum']))
                    iPolarization['calibrationConst'] = float(
                        gdalDataset.GetMetadataItem(metaKey, 'records'))
            except:
                self.logger.warning('Cannot get calibrationConst')
                gotCalibration = False

        # add dictionary for raw counts
        metaDict = []
        for iPolarization in polarization:
            iBand = gdalDataset.GetRasterBand(iPolarization['bandNum'])
            dtype = iBand.DataType
            shortName = 'RawCounts_%s' %iPolarization['channel']
            bandName = shortName
            dstName = 'raw_counts_%s' % iPolarization['channel']
            if (8 <= dtype and dtype < 12):
                bandName = shortName+'_complex'
                dstName = dstName + '_complex'

            metaDict.append({'src': {'SourceFilename': filename,
                                     'SourceBand': iPolarization['bandNum']},
                             'dst': {'name': dstName}})


            '''
            metaDict.append({'src': {'SourceFilename': filename,
                                     'SourceBand': iPolarization['bandNum']},
                             'dst': {'name': 'raw_counts_%s'
                                     % iPolarization['channel']}})
            '''
            # if raw data is complex, add the intensity band
            if (8 <= dtype and dtype < 12):
                # choose pixelfunction type
                if (dtype == 8 or dtype == 9):
                    pixelFunctionType = 'IntensityInt'
                else:
                    pixelFunctionType = 'intensity'
                # get data type of the intensity band
                intensityDataType = {'8': 3, '9': 4,
                                     '10': 5, '11': 6}.get(str(dtype), 4)
                # add intensity band
                metaDict.append(
                    {'src': {'SourceFilename': filename,
                             'SourceBand': iPolarization['bandNum'],
                             'DataType': dtype},
                     'dst': {'name': 'raw_counts_%s'
                                     % iPolarization['channel'],
                             'PixelFunctionType': pixelFunctionType,
                             'SourceTransferType': gdal.GetDataTypeName(dtype),
                             'dataType': intensityDataType}})

        #####################################################################
        # Add incidence angle and look direction through small VRT objects
        #####################################################################
        lon = self.get_array_from_ADS('first_line_longs')
        lat = self.get_array_from_ADS('first_line_lats')
        inc = self.get_array_from_ADS('first_line_incidence_angle')

        # Calculate SAR look direction (ASAR is always right-looking)
        look_direction = initial_bearing(lon[:, :-1], lat[:, :-1],
                                             lon[:, 1:], lat[:, 1:])
        # Interpolate to regain lost row
        look_direction = scipy.ndimage.interpolation.zoom(
            look_direction, (1, 11./10.))
        # Decompose, to avoid interpolation errors around 0 <-> 360
        look_direction_u = np.sin(np.deg2rad(look_direction))
        look_direction_v = np.cos(np.deg2rad(look_direction))
        look_u_VRT = VRT.from_array(look_direction_u)
        look_v_VRT = VRT.from_array(look_direction_v)

        # Note: If incidence angle and look direction are stored in
        #       same VRT, access time is about twice as large
        incVRT = VRT.from_array(inc)
        lookVRT = VRT.from_lonlat(lon, lat)
        lookVRT.create_band([{'SourceFilename': look_u_VRT.filename,
                               'SourceBand': 1},
                              {'SourceFilename': look_v_VRT.filename,
                               'SourceBand': 1}],
                             {'PixelFunctionType': 'UVToDirectionTo'})

        # Blow up bands to full size
        incVRT = incVRT.get_resized_vrt(gdalDataset.RasterXSize, gdalDataset.RasterYSize)
        lookVRT = lookVRT.get_resized_vrt(gdalDataset.RasterXSize, gdalDataset.RasterYSize)
        # Store VRTs so that they are accessible later
        self.band_vrts = {'incVRT': incVRT,
                        'look_u_VRT': look_u_VRT,
                        'look_v_VRT': look_v_VRT,
                        'lookVRT': lookVRT}

        # Add band to full sized VRT
        incFileName = self.band_vrts['incVRT'].filename
        lookFileName = self.band_vrts['lookVRT'].filename
        metaDict.append({'src': {'SourceFilename': incFileName,
                                 'SourceBand': 1},
                         'dst': {'wkv': 'angle_of_incidence',
                                 'name': 'incidence_angle'}})
        metaDict.append({'src': {'SourceFilename': lookFileName,
                                 'SourceBand': 1},
                         'dst': {'wkv': 'sensor_azimuth_angle',
                                 'name': 'look_direction'}})

        ####################
        # Add Sigma0-bands
        ####################
        if gotCalibration:
            for iPolarization in polarization:
                # add dictionary for sigma0, ice and water
                short_names = ['sigma0', 'sigma0_normalized_ice',
                               'sigma0_normalized_water']
                wkt = [
                    'surface_backwards_scattering_coefficient_of_radar_wave',
                    'surface_backwards_scattering_coefficient_of_radar_wave_normalized_over_ice',
                    'surface_backwards_scattering_coefficient_of_radar_wave_normalized_over_water']
                sphPass = [gdalMetadata['SPH_PASS'], '', '']
                sourceFileNames = [filename, incFileName]

                pixelFunctionTypes = ['RawcountsIncidenceToSigma0',
                                      'Sigma0NormalizedIce']
                if iPolarization['channel'] == 'HH':
                    pixelFunctionTypes.append('Sigma0HHNormalizedWater')
                elif iPolarization['channel'] == 'VV':
                    pixelFunctionTypes.append('Sigma0VVNormalizedWater')

                # add pixelfunction bands to metaDict
                for iPixFunc in range(len(pixelFunctionTypes)):
                    srcFiles = []
                    for j, jFileName in enumerate(sourceFileNames):
                        sourceFile = {'SourceFilename': jFileName}
                        if j == 0:
                            sourceFile['SourceBand'] = iPolarization['bandNum']
                            # if ASA_full_incAng,
                            # set 'ScaleRatio' into source file dict
                            sourceFile['ScaleRatio'] = np.sqrt(
                                1.0 / iPolarization['calibrationConst'])
                        else:
                            sourceFile['SourceBand'] = 1
                        srcFiles.append(sourceFile)

                    metaDict.append({
                        'src': srcFiles,
                        'dst': {'short_name': short_names[iPixFunc],
                                'wkv': wkt[iPixFunc],
                                'PixelFunctionType': (
                                pixelFunctionTypes[iPixFunc]),
                                'polarization': iPolarization['channel'],
                                'suffix': iPolarization['channel'],
                                'pass': sphPass[iPixFunc],
                                'dataType': 6}})

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

        # Add oribit and look information to metadata domain
        # ASAR is always right-looking
        self.dataset.SetMetadataItem('ANTENNA_POINTING', 'RIGHT')
        self.dataset.SetMetadataItem('ORBIT_DIRECTION',
                        gdalMetadata['SPH_PASS'].upper().strip())

        ###################################################################
        # Estimate sigma0_VV from sigma0_HH
        ###################################################################
        polarizations = []
        for pp in polarization:
            polarizations.append(pp['channel'])
        if 'VV' not in polarizations and 'HH' in polarizations:
            srcFiles = []
            for j, jFileName in enumerate(sourceFileNames):
                sourceFile = {'SourceFilename': jFileName}
                if j == 0:
                    sourceFile['SourceBand'] = iPolarization['bandNum']
                    # if ASA_full_incAng,
                    # set 'ScaleRatio' into source file dict
                    sourceFile['ScaleRatio'] = np.sqrt(
                        1.0 / iPolarization['calibrationConst'])
                else:
                    sourceFile['SourceBand'] = 1
                srcFiles.append(sourceFile)
            dst = {'wkv': (
                   'surface_backwards_scattering_coefficient_of_radar_wave'),
                   'PixelFunctionType': 'Sigma0HHToSigma0VV',
                   'polarization': 'VV',
                   'suffix': 'VV'}
            self.create_band(srcFiles, dst)
            self.dataset.FlushCache()

        # set time
        self._set_envisat_time(gdalMetadata)

        # When using TPS for reprojection, use only every 3rd GCP
        # to improve performance (tradeoff vs accuracy)
        self.dataset.SetMetadataItem('skip_gcps', '3')

        self.dataset.SetMetadataItem('time_coverage_start',
                                     (parse(gdalMetadata['MPH_SENSING_START']).
                                      isoformat()))
        self.dataset.SetMetadataItem('time_coverage_end',
                                     (parse(gdalMetadata['MPH_SENSING_STOP']).
                                      isoformat()))

        # Get dictionary describing the instrument and platform according to
        # the GCMD keywords
        mm = pti.get_gcmd_instrument('asar')
        ee = pti.get_gcmd_platform('envisat')

        # TODO: Validate that the found instrument and platform are indeed what
        # we want....

        self.dataset.SetMetadataItem('instrument', json.dumps(mm))
        self.dataset.SetMetadataItem('platform', json.dumps(ee))
Ejemplo n.º 32
0
    def test_copy_vrt_with_band(self):
        array = gdal.Open(self.test_file_gcps).ReadAsArray()[1, 10:, :]
        vrt1 = VRT.from_array(array)
        vrt2 = vrt1.copy()

        self.assertEqual(vrt2.dataset.RasterCount, 1)
Ejemplo n.º 33
0
    def __init__(self, filename, gdalDataset, gdalMetadata, **kwargs):
        '''
        Parameters
        -----------
        filename : string

        gdalDataset : gdal dataset

        gdalMetadata : gdal metadata

        '''

        self.setup_ads_parameters(filename, gdalMetadata)

        if self.product[0:4] != "ASA_":
            raise WrongMapperError

        if not IMPORT_SCIPY:
            raise NansatReadError(
                'ASAR data cannot be read because scipy is not installed')

        # get channel string (remove '/', since NetCDF
        # does not support that in metadata)
        polarization = [{
            'channel':
            gdalMetadata['SPH_MDS1_TX_RX_POLAR'].replace("/", ""),
            'bandNum':
            1
        }]
        # if there is the 2nd band, get channel string
        if 'SPH_MDS2_TX_RX_POLAR' in gdalMetadata.keys():
            channel = gdalMetadata['SPH_MDS2_TX_RX_POLAR'].replace("/", "")
            if not (channel.isspace()):
                polarization.append({'channel': channel, 'bandNum': 2})

        # create empty VRT dataset with geolocation only
        self._init_from_gdal_dataset(gdalDataset, metadata=gdalMetadata)

        # get calibration constant
        gotCalibration = True
        try:
            for iPolarization in polarization:
                metaKey = (
                    'MAIN_PROCESSING_PARAMS_ADS_CALIBRATION_FACTORS.%d.EXT_CAL_FACT'
                    % (iPolarization['bandNum']))
                iPolarization['calibrationConst'] = float(
                    gdalDataset.GetMetadataItem(metaKey, 'records'))
        except:
            try:
                for iPolarization in polarization:
                    # Apparently some ASAR files have calibration
                    # constant stored in another place
                    metaKey = (
                        'MAIN_PROCESSING_PARAMS_ADS_0_CALIBRATION_FACTORS.%d.EXT_CAL_FACT'
                        % (iPolarization['bandNum']))
                    iPolarization['calibrationConst'] = float(
                        gdalDataset.GetMetadataItem(metaKey, 'records'))
            except:
                self.logger.warning('Cannot get calibrationConst')
                gotCalibration = False

        # add dictionary for raw counts
        metaDict = []
        for iPolarization in polarization:
            iBand = gdalDataset.GetRasterBand(iPolarization['bandNum'])
            dtype = iBand.DataType
            shortName = 'RawCounts_%s' % iPolarization['channel']
            bandName = shortName
            dstName = 'raw_counts_%s' % iPolarization['channel']
            if (8 <= dtype and dtype < 12):
                bandName = shortName + '_complex'
                dstName = dstName + '_complex'

            metaDict.append({
                'src': {
                    'SourceFilename': filename,
                    'SourceBand': iPolarization['bandNum']
                },
                'dst': {
                    'name': dstName
                }
            })
            '''
            metaDict.append({'src': {'SourceFilename': filename,
                                     'SourceBand': iPolarization['bandNum']},
                             'dst': {'name': 'raw_counts_%s'
                                     % iPolarization['channel']}})
            '''
            # if raw data is complex, add the intensity band
            if (8 <= dtype and dtype < 12):
                # choose pixelfunction type
                if (dtype == 8 or dtype == 9):
                    pixelFunctionType = 'IntensityInt'
                else:
                    pixelFunctionType = 'intensity'
                # get data type of the intensity band
                intensityDataType = {
                    '8': 3,
                    '9': 4,
                    '10': 5,
                    '11': 6
                }.get(str(dtype), 4)
                # add intensity band
                metaDict.append({
                    'src': {
                        'SourceFilename': filename,
                        'SourceBand': iPolarization['bandNum'],
                        'DataType': dtype
                    },
                    'dst': {
                        'name': 'raw_counts_%s' % iPolarization['channel'],
                        'PixelFunctionType': pixelFunctionType,
                        'SourceTransferType': gdal.GetDataTypeName(dtype),
                        'dataType': intensityDataType
                    }
                })

        #####################################################################
        # Add incidence angle and look direction through small VRT objects
        #####################################################################
        lon = self.get_array_from_ADS('first_line_longs')
        lat = self.get_array_from_ADS('first_line_lats')
        inc = self.get_array_from_ADS('first_line_incidence_angle')

        # Calculate SAR look direction (ASAR is always right-looking)
        look_direction = initial_bearing(lon[:, :-1], lat[:, :-1], lon[:, 1:],
                                         lat[:, 1:])
        # Interpolate to regain lost row
        look_direction = scipy.ndimage.interpolation.zoom(
            look_direction, (1, 11. / 10.))
        # Decompose, to avoid interpolation errors around 0 <-> 360
        look_direction_u = np.sin(np.deg2rad(look_direction))
        look_direction_v = np.cos(np.deg2rad(look_direction))
        look_u_VRT = VRT.from_array(look_direction_u)
        look_v_VRT = VRT.from_array(look_direction_v)

        # Note: If incidence angle and look direction are stored in
        #       same VRT, access time is about twice as large
        incVRT = VRT.from_array(inc)
        lookVRT = VRT.from_lonlat(lon, lat)
        lookVRT.create_band([{
            'SourceFilename': look_u_VRT.filename,
            'SourceBand': 1
        }, {
            'SourceFilename': look_v_VRT.filename,
            'SourceBand': 1
        }], {'PixelFunctionType': 'UVToDirectionTo'})

        # Blow up bands to full size
        incVRT = incVRT.get_resized_vrt(gdalDataset.RasterXSize,
                                        gdalDataset.RasterYSize)
        lookVRT = lookVRT.get_resized_vrt(gdalDataset.RasterXSize,
                                          gdalDataset.RasterYSize)
        # Store VRTs so that they are accessible later
        self.band_vrts = {
            'incVRT': incVRT,
            'look_u_VRT': look_u_VRT,
            'look_v_VRT': look_v_VRT,
            'lookVRT': lookVRT
        }

        # Add band to full sized VRT
        incFileName = self.band_vrts['incVRT'].filename
        lookFileName = self.band_vrts['lookVRT'].filename
        metaDict.append({
            'src': {
                'SourceFilename': incFileName,
                'SourceBand': 1
            },
            'dst': {
                'wkv': 'angle_of_incidence',
                'name': 'incidence_angle'
            }
        })
        metaDict.append({
            'src': {
                'SourceFilename': lookFileName,
                'SourceBand': 1
            },
            'dst': {
                'wkv': 'sensor_azimuth_angle',
                'name': 'look_direction'
            }
        })

        ####################
        # Add Sigma0-bands
        ####################
        if gotCalibration:
            for iPolarization in polarization:
                # add dictionary for sigma0, ice and water
                short_names = [
                    'sigma0', 'sigma0_normalized_ice',
                    'sigma0_normalized_water'
                ]
                wkt = [
                    'surface_backwards_scattering_coefficient_of_radar_wave',
                    'surface_backwards_scattering_coefficient_of_radar_wave_normalized_over_ice',
                    'surface_backwards_scattering_coefficient_of_radar_wave_normalized_over_water'
                ]
                sphPass = [gdalMetadata['SPH_PASS'], '', '']
                sourceFileNames = [filename, incFileName]

                pixelFunctionTypes = [
                    'RawcountsIncidenceToSigma0', 'Sigma0NormalizedIce'
                ]
                if iPolarization['channel'] == 'HH':
                    pixelFunctionTypes.append('Sigma0HHNormalizedWater')
                elif iPolarization['channel'] == 'VV':
                    pixelFunctionTypes.append('Sigma0VVNormalizedWater')

                # add pixelfunction bands to metaDict
                for iPixFunc in range(len(pixelFunctionTypes)):
                    srcFiles = []
                    for j, jFileName in enumerate(sourceFileNames):
                        sourceFile = {'SourceFilename': jFileName}
                        if j == 0:
                            sourceFile['SourceBand'] = iPolarization['bandNum']
                            # if ASA_full_incAng,
                            # set 'ScaleRatio' into source file dict
                            sourceFile['ScaleRatio'] = np.sqrt(
                                1.0 / iPolarization['calibrationConst'])
                        else:
                            sourceFile['SourceBand'] = 1
                        srcFiles.append(sourceFile)

                    metaDict.append({
                        'src': srcFiles,
                        'dst': {
                            'short_name': short_names[iPixFunc],
                            'wkv': wkt[iPixFunc],
                            'PixelFunctionType':
                            (pixelFunctionTypes[iPixFunc]),
                            'polarization': iPolarization['channel'],
                            'suffix': iPolarization['channel'],
                            'pass': sphPass[iPixFunc],
                            'dataType': 6
                        }
                    })

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

        # Add oribit and look information to metadata domain
        # ASAR is always right-looking
        self.dataset.SetMetadataItem('ANTENNA_POINTING', 'RIGHT')
        self.dataset.SetMetadataItem('ORBIT_DIRECTION',
                                     gdalMetadata['SPH_PASS'].upper().strip())

        ###################################################################
        # Estimate sigma0_VV from sigma0_HH
        ###################################################################
        polarizations = []
        for pp in polarization:
            polarizations.append(pp['channel'])
        if 'VV' not in polarizations and 'HH' in polarizations:
            srcFiles = []
            for j, jFileName in enumerate(sourceFileNames):
                sourceFile = {'SourceFilename': jFileName}
                if j == 0:
                    sourceFile['SourceBand'] = iPolarization['bandNum']
                    # if ASA_full_incAng,
                    # set 'ScaleRatio' into source file dict
                    sourceFile['ScaleRatio'] = np.sqrt(
                        1.0 / iPolarization['calibrationConst'])
                else:
                    sourceFile['SourceBand'] = 1
                srcFiles.append(sourceFile)
            dst = {
                'wkv':
                ('surface_backwards_scattering_coefficient_of_radar_wave'),
                'PixelFunctionType': 'Sigma0HHToSigma0VV',
                'polarization': 'VV',
                'suffix': 'VV'
            }
            self.create_band(srcFiles, dst)
            self.dataset.FlushCache()

        # set time
        self._set_envisat_time(gdalMetadata)

        # When using TPS for reprojection, use only every 3rd GCP
        # to improve performance (tradeoff vs accuracy)
        self.dataset.SetMetadataItem('skip_gcps', '3')

        self.dataset.SetMetadataItem(
            'time_coverage_start',
            (parse(gdalMetadata['MPH_SENSING_START']).isoformat()))
        self.dataset.SetMetadataItem(
            'time_coverage_end',
            (parse(gdalMetadata['MPH_SENSING_STOP']).isoformat()))

        # Get dictionary describing the instrument and platform according to
        # the GCMD keywords
        mm = pti.get_gcmd_instrument('asar')
        ee = pti.get_gcmd_platform('envisat')

        # TODO: Validate that the found instrument and platform are indeed what
        # we want....

        self.dataset.SetMetadataItem('instrument', json.dumps(mm))
        self.dataset.SetMetadataItem('platform', json.dumps(ee))
Ejemplo n.º 34
0
    def __init__(self, inputFileName, gdalDataset, gdalMetadata,
                 xmlonly=False,  **kwargs):
        ''' Create Radarsat2 VRT '''
        fPathName, fExt = os.path.splitext(inputFileName)

        if zipfile.is_zipfile(inputFileName):
            # Open zip file using VSI
            fPath, fName = os.path.split(fPathName)
            filename = '/vsizip/%s/%s' % (inputFileName, fName)
            if not 'RS' in fName[0:2]:
                raise WrongMapperError('%s: Provided data is not Radarsat-2'
                                       % fName)
            gdalDataset = gdal.Open(filename)
            gdalMetadata = gdalDataset.GetMetadata()
        else:
            filename = inputFileName

        # if it is not RADARSAT-2, return
        if (not gdalMetadata or not 'SATELLITE_IDENTIFIER' in list(gdalMetadata.keys())):
            raise WrongMapperError(filename)
        elif gdalMetadata['SATELLITE_IDENTIFIER'] != 'RADARSAT-2':
            raise WrongMapperError(filename)

        if zipfile.is_zipfile(inputFileName):
            # Open product.xml to get additional metadata
            zz = zipfile.ZipFile(inputFileName)
            productXmlName = os.path.join(os.path.basename(
                inputFileName).split('.')[0], 'product.xml')
            productXml = zz.open(productXmlName).read()
        else:
            # product.xml to get additionali metadata
            productXmlName = os.path.join(filename, 'product.xml')
            if not os.path.isfile(productXmlName):
                raise WrongMapperError(filename)
            productXml = open(productXmlName).read()

        if not IMPORT_SCIPY:
            raise NansatReadError('Radarsat-2 data cannot be read because scipy is not installed')

        # parse product.XML
        rs2_0 = Node.create(productXml)

        if xmlonly:
            self.init_from_xml(rs2_0, filename)
            return

        # Get additional metadata from product.xml
        rs2_1 = rs2_0.node('sourceAttributes')
        rs2_2 = rs2_1.node('radarParameters')
        if rs2_2['antennaPointing'].lower() == 'right':
            antennaPointing = 90
        else:
            antennaPointing = -90
        rs2_3 = rs2_1.node('orbitAndAttitude').node('orbitInformation')
        passDirection = rs2_3['passDirection']

        # create empty VRT dataset with geolocation only
        self._init_from_gdal_dataset(gdalDataset)
        self.dataset.SetGCPs(self.dataset.GetGCPs(), NSR().wkt)

        # define dictionary of metadata and band specific parameters
        pol = []
        metaDict = []

        # Get the subdataset with calibrated sigma0 only
        for dataset in gdalDataset.GetSubDatasets():
            if dataset[1] == 'Sigma Nought calibrated':
                s0dataset = gdal.Open(dataset[0])
                s0datasetName = dataset[0][:]
                band = s0dataset.GetRasterBand(1)
                s0datasetPol = band.GetMetadata()['POLARIMETRIC_INTERP']
                for i in range(1, s0dataset.RasterCount+1):
                    iBand = s0dataset.GetRasterBand(i)
                    polString = iBand.GetMetadata()['POLARIMETRIC_INTERP']
                    suffix = polString
                    # The nansat data will be complex
                    # if the SAR data is of type 10
                    dtype = iBand.DataType
                    if dtype == 10:
                        # add intensity band
                        metaDict.append(
                            {'src': {'SourceFilename':
                                     ('RADARSAT_2_CALIB:SIGMA0:'
                                      + filename + '/product.xml'),
                                     'SourceBand': i,
                                     'DataType': dtype},
                             'dst': {'wkv': 'surface_backwards_scattering_coefficient_of_radar_wave',
                                     'PixelFunctionType': 'intensity',
                                     'SourceTransferType': gdal.GetDataTypeName(dtype),
                                     'suffix': suffix,
                                     'polarization': polString,
                                     'dataType': 6}})
                        # modify suffix for adding the compled band below
                        suffix = polString+'_complex'
                    pol.append(polString)
                    metaDict.append(
                        {'src': {'SourceFilename': ('RADARSAT_2_CALIB:SIGMA0:'
                                                    + filename
                                                    + '/product.xml'),
                                 'SourceBand': i,
                                 'DataType': dtype},
                         'dst': {'wkv': 'surface_backwards_scattering_coefficient_of_radar_wave',
                                 'suffix': suffix,
                                 'polarization': polString}})

            if dataset[1] == 'Beta Nought calibrated':
                b0dataset = gdal.Open(dataset[0])
                b0datasetName = dataset[0][:]
                for j in range(1, b0dataset.RasterCount+1):
                    jBand = b0dataset.GetRasterBand(j)
                    polString = jBand.GetMetadata()['POLARIMETRIC_INTERP']
                    if polString == s0datasetPol:
                        b0datasetBand = j

        ###############################
        # Add SAR look direction
        ###############################
        d = Domain(ds=gdalDataset)
        lon, lat = d.get_geolocation_grids(100)

        '''
        (GDAL?) Radarsat-2 data is stored with maximum latitude at first
        element of each column and minimum longitude at first element of each
        row (e.g. np.shape(lat)=(59,55) -> latitude maxima are at lat[0,:],
        and longitude minima are at lon[:,0])

        In addition, there is an interpolation error for direct estimate along
        azimuth. We therefore estimate the heading along range and add 90
        degrees to get the "satellite" heading.

        '''
        if str(passDirection).upper() == 'DESCENDING':
            sat_heading = initial_bearing(lon[:, :-1], lat[:, :-1],
                                          lon[:, 1:], lat[:, 1:]) + 90
        elif str(passDirection).upper() == 'ASCENDING':
            sat_heading = initial_bearing(lon[:, 1:], lat[:, 1:],
                                          lon[:, :-1], lat[:, :-1]) + 90
        else:
            print('Can not decode pass direction: ' + str(passDirection))

        # Calculate SAR look direction
        look_direction = sat_heading + antennaPointing
        # Interpolate to regain lost row
        look_direction = np.mod(look_direction, 360)
        look_direction = scipy.ndimage.interpolation.zoom(
            look_direction, (1, 11./10.))
        # Decompose, to avoid interpolation errors around 0 <-> 360
        look_direction_u = np.sin(np.deg2rad(look_direction))
        look_direction_v = np.cos(np.deg2rad(look_direction))
        look_u_VRT = VRT.from_array(look_direction_u)
        look_v_VRT = VRT.from_array(look_direction_v)

        # Note: If incidence angle and look direction are stored in
        #       same VRT, access time is about twice as large
        lookVRT = VRT.from_lonlat(lon, lat)
        lookVRT.create_band(
            [{'SourceFilename': look_u_VRT.filename, 'SourceBand': 1},
             {'SourceFilename': look_v_VRT.filename, 'SourceBand': 1}],
            {'PixelFunctionType': 'UVToDirectionTo'})

        # Blow up to full size
        lookVRT = lookVRT.get_resized_vrt(gdalDataset.RasterXSize, gdalDataset.RasterYSize)
        # Store VRTs so that they are accessible later
        self.band_vrts['look_u_VRT'] = look_u_VRT
        self.band_vrts['look_v_VRT'] = look_v_VRT
        self.band_vrts['lookVRT'] = lookVRT

        # Add band to full sized VRT
        lookFileName = self.band_vrts['lookVRT'].filename
        metaDict.append({'src': {'SourceFilename': lookFileName,
                                 'SourceBand': 1},
                         'dst': {'wkv': 'sensor_azimuth_angle',
                                 'name': 'look_direction'}})

        ###############################
        # Create bands
        ###############################
        self.create_bands(metaDict)

        ###################################################
        # Add derived band (incidence angle) calculated
        # using pixel function "BetaSigmaToIncidence":
        ###################################################
        src = [{'SourceFilename': b0datasetName,
                'SourceBand':  b0datasetBand,
                'DataType': dtype},
               {'SourceFilename': s0datasetName,
                'SourceBand': 1,
                'DataType': dtype}]
        dst = {'wkv': 'angle_of_incidence',
               'PixelFunctionType': 'BetaSigmaToIncidence',
               'SourceTransferType': gdal.GetDataTypeName(dtype),
               '_FillValue': -10000,   # NB: this is also hard-coded in
                                       #     pixelfunctions.c
               'dataType': 6,
               'name': 'incidence_angle'}

        self.create_band(src, dst)
        self.dataset.FlushCache()

        ###################################################################
        # Add sigma0_VV - pixel function of sigma0_HH and beta0_HH
        # incidence angle is calculated within pixel function
        # It is assummed that HH is the first band in sigma0 and
        # beta0 sub datasets
        ###################################################################
        if 'VV' not in pol and 'HH' in pol:
            s0datasetNameHH = pol.index('HH')+1
            src = [{'SourceFilename': s0datasetName,
                    'SourceBand': s0datasetNameHH,
                    'DataType': 6},
                   {'SourceFilename': b0datasetName,
                    'SourceBand': b0datasetBand,
                    'DataType': 6}]
            dst = {'wkv': 'surface_backwards_scattering_coefficient_of_radar_wave',
                   'PixelFunctionType': 'Sigma0HHBetaToSigma0VV',
                   'polarization': 'VV',
                   'suffix': 'VV'}
            self.create_band(src, dst)
            self.dataset.FlushCache()

        ############################################
        # Add SAR metadata
        ############################################
        if antennaPointing == 90:
            self.dataset.SetMetadataItem('ANTENNA_POINTING', 'RIGHT')
        if antennaPointing == -90:
            self.dataset.SetMetadataItem('ANTENNA_POINTING', 'LEFT')
        self.dataset.SetMetadataItem('ORBIT_DIRECTION',
                                     str(passDirection).upper())

        # set valid time
        self.dataset.SetMetadataItem('time_coverage_start',
                                     (parse(gdalMetadata['FIRST_LINE_TIME']).
                                      isoformat()))
        self.dataset.SetMetadataItem('time_coverage_end',
                                     (parse(gdalMetadata['LAST_LINE_TIME']).
                                      isoformat()))

        # Get dictionary describing the instrument and platform according to
        # the GCMD keywords
        mm = pti.get_gcmd_instrument("C-SAR")
        ee = pti.get_gcmd_platform('radarsat-2')

        # TODO: Validate that the found instrument and platform are indeed what we
        # want....

        self.dataset.SetMetadataItem('instrument', json.dumps(mm))
        self.dataset.SetMetadataItem('platform', json.dumps(ee))
        self.dataset.SetMetadataItem('entry_title', 'Radarsat-2 SAR')
        self.dataset.SetMetadataItem('provider', 'MDA/GSI')
        self.dataset.SetMetadataItem('dataset_parameters', json.dumps(
                                     ['surface_backwards_scattering_coefficient_of_radar_wave']))
        self.dataset.SetMetadataItem('entry_id', os.path.basename(filename))
Ejemplo n.º 35
0
    def __init__(self, filename, gdalDataset, gdalMetadata, latlonGrid=None,
                 mask='', **kwargs):

        ''' Create MER2 VRT

        Parameters
        -----------
        filename : string
        gdalDataset : gdal dataset
        gdalMetadata : gdal metadata
        latlonGrid : numpy 2 layered 2D array with lat/lons of desired grid
        '''
        # test if input files is GLOBCOLOUR L3B
        iDir, iFile = os.path.split(filename)
        iFileName, iFileExt = os.path.splitext(iFile)
        #print 'idir:', iDir, iFile, iFileName[0:5], iFileExt[0:8]
        if (iFileName[0:4] != 'L3b_'
            or iFileExt != '.nc'
            or not os.path.exists(filename)
            or (gdalDataset is not None
                and (len(gdalDataset.GetSubDatasets()) > 0
                     or gdalDataset.RasterCount > 0))):
            raise WrongMapperError

        # define shape of GLOBCOLOUR grid
        GLOBCOLOR_ROWS = 180 * 24
        GLOBCOLOR_COLS = 360 * 24

        # define lon/lat grids for projected var
        if latlonGrid is None:
            latlonGrid = np.mgrid[90:-90:4320j,
                                  -180:180:8640j].astype('float32')
            #latlonGrid = np.mgrid[80:50:900j, -10:30:1200j].astype('float16')
            #latlonGrid = np.mgrid[47:39:300j, 25:45:500j].astype('float32')

        # create empty VRT dataset with geolocation only
        self._init_from_lonlat(latlonGrid[1], latlonGrid[0])

        # get list of similar (same date) files in the directory
        simFilesMask = os.path.join(iDir, iFileName[0:30] + '*' + mask + '.nc')
        simFiles = glob.glob(simFilesMask)
        simFiles.sort()

        metaDict = []
        self.band_vrts = {'mask': [], 'lonlat': []}
        mask = None
        for simFile in simFiles:
            print('sim: ', simFile)
            # copy simFile to a temporary file
            tmpf = tempfile.mkstemp()
            shutil.copyfile(simFile, tmpf[1])
            f = Dataset(tmpf[1])

            # get iBinned, index for converting from binned into GLOBCOLOR-grid
            colBinned = f.variables['col'][:]
            rowBinned = f.variables['row'][:]
            iBinned = (colBinned.astype('uint32') +
                      (rowBinned.astype('uint32') - 1) * GLOBCOLOR_COLS)
            colBinned = None
            rowBinned = None

            # get iRawPro, index for converting
            # from GLOBCOLOR-grid to latlonGrid
            yRawPro = np.rint(1 + (GLOBCOLOR_ROWS - 1) *
                              (latlonGrid[0] + 90) / 180.)
            lon_step_Mat = 24. * np.cos(np.pi * latlonGrid[0] / 180.)
            xRawPro = np.rint(1 + (latlonGrid[1] + 180) * lon_step_Mat)
            iRawPro = xRawPro.astype('uint32') + (yRawPro.astype('uint32') - 1) * GLOBCOLOR_COLS
            yRawPro = None
            xRawPro = None

            for varName in f.variables:
                # find variable with _mean, eg CHL1_mean
                if '_mean' in varName:
                    var = f.variables[varName]
                    break

            # skip variable if no WKV is give in Globcolour
            if varName not in self.varname2wkv:
                continue

            # get WKV
            varWKV = self.varname2wkv[varName]

            # read binned data
            varBinned = var[:]

            # convert to GLOBCOLOR grid
            varRawPro = np.zeros([GLOBCOLOR_ROWS, GLOBCOLOR_COLS], 'float32')
            varRawPro.flat[iBinned] = varBinned

            # convert to latlonGrid
            varPro = varRawPro.flat[iRawPro.flat[:]].reshape(iRawPro.shape)

            # add mask band
            if mask is None:
                mask = np.zeros(varPro.shape, 'uint8')
                mask[:] = 1
                mask[varPro > 0] = 64

                # add VRT with array with data from projected variable
                self.band_vrts['mask'].append(VRT.from_array(mask))

                # add metadata to the dictionary
                metaDict.append({
                    'src': {'SourceFilename': (self.band_vrts['mask'][-1].
                                               filename),
                            'SourceBand':  1},
                    'dst': {'name': 'mask'}})

            # add VRT with array with data from projected variable
            self.band_vrts['lonlat'].append(VRT.from_array(varPro))

            # add metadata to the dictionary
            metaEntry = {
                'src': {'SourceFilename': self.band_vrts['lonlat'][-1].filename,
                        'SourceBand':  1},
                'dst': {'wkv': varWKV, 'original_name': varName}}

            # add wavelength for nLw
            longName = 'Fully normalised water leaving radiance'
            if longName in f.variables[varName].long_name:
                simWavelength = varName.split('L')[1].split('_mean')[0]
                metaEntry['dst']['suffix'] = simWavelength
                metaEntry['dst']['wavelength'] = simWavelength

            # add all metadata from NC-file
            for attr in var.ncattrs():
                metaEntry['dst'][attr] = var.getncattr(attr)

            metaDict.append(metaEntry)

            # add Rrsw band
            metaEntry2 = self.make_rrsw_meta_entry(metaEntry)
            if metaEntry2 is not None:
                metaDict.append(metaEntry2)

            os.remove(tmpf[1])

        instrument = f.title.strip().split(' ')[-2].split('/')[0]
        mm = pti.get_gcmd_instrument(instrument)
        self.dataset.SetMetadataItem('instrument', json.dumps(mm))

        platform = {
            'MODIS' : 'AQUA',
            'MERIS' : 'ENVISAT',
            'SEAWIFS': 'QUICKBIRD',
            'VIIRS' : 'SUOMI-NPP'}[instrument.upper()]
        pp = pti.get_gcmd_platform(platform)
        self.dataset.SetMetadataItem('platform', json.dumps(pp))

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

        # add time
        startDate = datetime.datetime(int(iFileName[4:8]),
                                      int(iFileName[8:10]),
                                      int(iFileName[10:12]))

        # Adding valid time to dataset
        self.dataset.SetMetadataItem('time_coverage_start', startDate.isoformat())
        self.dataset.SetMetadataItem('time_coverage_end', startDate.isoformat())
Ejemplo n.º 36
0
    def __init__(self, filename, gdal_dataset, gdal_metadata, GCP_COUNT=10, timestamp=None, **kwargs):
        filename_name = os.path.split(filename)[-1].split('.')[0]
        # Check if correct mapper
        correct_mapper = False 
        for location in self.SUPPORTED_LOCATIONS:
            # If it matches with one of locateions break the loop and flag True
            if filename_name.startswith(location):
                correct_mapper = True
                break
        if not correct_mapper:
            raise WrongMapperError

        # Import NetCDF4 dataset
        nc_dataset = Dataset(filename)
        # Define projection (depending on the HFR)
        if nc_dataset.getncattr('site') == 'TORU':
            proj4 = '+proj=utm +zone=32 +ellps=WGS84 +datum=WGS84 +units=m +no_defs'
            GRID_PX_SIZE = 1500 # Final raster px size in meters
        elif nc_dataset.getncattr('site') == 'FRUH':
            proj4 = '+proj=utm +zone=34 +ellps=WGS84 +datum=WGS84 +units=m +no_defs'
            GRID_PX_SIZE = 5000 # Final raster px size in meters
        elif nc_dataset.getncattr('site') == 'BERL':
            proj4 = '+proj=utm +zone=35 +ellps=WGS84 +datum=WGS84 +units=m +no_defs'
            GRID_PX_SIZE = 5000 # Final raster px size in meters
        else:
            raise WrongMapperError

        srs = osr.SpatialReference()
        srs.ImportFromProj4(proj4)
        projection = srs.ExportToWkt()
        # Get x grid and y grid
        x_grd, y_grd = self.create_linear_grid(nc_dataset['x'][:], nc_dataset['y'][:], GRID_PX_SIZE)
        raster_x_size, raster_y_size = x_grd.shape
        # Define geotransform
        geotransform = (x_grd.min(), GRID_PX_SIZE, 0.0, y_grd.max(), 0.0, GRID_PX_SIZE * -1)
        # Define x and y size
        self._init_from_dataset_params(raster_x_size, raster_y_size, geotransform, projection)
        # If required timestamp was not specified then extract date from filename and use first time
        if timestamp is None:
            timestamp = self.date_from_filename(filename)
        # Comvert time info from the dataset to the datetime
        timestamps = num2date(nc_dataset['time'][:].data, nc_dataset['time'].units)
        # find band id for the required timestamp
        # Note add 1 because in gdal counting starts from 1 not from 0
        src_timestamp_id = np.where(timestamps == timestamp)[0][0] + 1
        # Iterate through all subdatasets and bands to the dataset
        for subdataset in gdal_dataset.GetSubDatasets():
            # Get name of subdataset
            subdataset_name = subdataset[0].split(':')[2]
            # Check if the subdataset in the accepted 3D vars list
            if subdataset_name not in self.BAND_NAMES:
                continue
            gdal_subdataset = gdal.Open(subdataset[0])
            # need to be float for the nan replasement
            band_data = gdal_subdataset.GetRasterBand(int(src_timestamp_id)).ReadAsArray().astype('float')
            # remove fill value (replace with nan)
            fill_value = int(gdal_subdataset.GetMetadata_Dict()['#'.join([subdataset_name, '_FillValue'])])
            band_data[band_data == fill_value] = np.nan
            # Interpolate data on the regular grid
            band_grid_data = self.band2grid((nc_dataset['x'][:], nc_dataset['y'][:]), 
                                             band_data, (x_grd, y_grd))
            # Create VRT ffor the regridded data
            band_vrt = VRT.from_array(band_grid_data)
            # Add VRT to the list of all dataset vrts
            self.band_vrts[subdataset_name + 'VRT'] = band_vrt
            # Add band to the dataset
            src = {'SourceFilename': self.band_vrts[subdataset_name + 'VRT'].filename, 
                   'SourceBand': 1}
            # Add band specific metadata
            dst = {'name': subdataset_name}
            for key in gdal_subdataset.GetMetadata_Dict().keys():
                if key.startswith(subdataset_name):
                    clean_metadata_name = key.split('#')[1]
                    dst[clean_metadata_name] = gdal_subdataset.GetMetadata_Dict()[key]
            # Create band
            self.create_band(src, dst)
            self.dataset.FlushCache()

        # Set GCMD metadata
        self.dataset.SetMetadataItem('instrument', json.dumps(pti.get_gcmd_instrument('SCR-HF')))
        self.dataset.SetMetadataItem('platform', json.dumps(pti.get_gcmd_platform('CODAR SeaSonde')))
        self.dataset.SetMetadataItem('Data Center', json.dumps(pti.get_gcmd_provider('NO/MET')))
        self.dataset.SetMetadataItem('Entry Title', 'Near-Real Time Surface Ocean Radial Velocity')
        self.dataset.SetMetadataItem('gcmd_location',json.dumps(pti.get_gcmd_location('NORTH SEA')))
        # Set time coverage metadata
        self.dataset.SetMetadataItem('time_coverage_start', timestamp.isoformat())
        self.dataset.SetMetadataItem('time_coverage_end',
                                     (timestamp + timedelta(minutes=59, seconds=59)).isoformat())
        # Set NetCDF dataset metadata
        for key, value in gdal_dataset.GetMetadata_Dict().items():
            self.dataset.SetMetadataItem(key.split('#')[1], value)
Ejemplo n.º 37
0
 def test_create_band_name_existing_name(self):
     self.mock_pti['get_wkv_variable'].side_effect = IndexError
     vrt = VRT.from_array(np.zeros((10,10)))
     vrt.dataset.GetRasterBand(1).SetMetadata({'name':'band1'})
     self.assertEqual(vrt._create_band_name({'name': 'band1'}), ('band1_0000', {}))
Ejemplo n.º 38
0
 def test_get_shifted_vrt(self):
     deg = -10
     vrt1 = VRT.from_array(np.zeros((180,360)))
     vrt1.dataset.SetProjection(NSR().wkt)
     vrt2 = vrt1.get_shifted_vrt(deg)
     self.assertEqual(vrt1.dataset.GetGeoTransform()[0]+deg, vrt2.dataset.GetGeoTransform()[0])
Ejemplo n.º 39
0
    def __init__(self,
                 filename,
                 gdalDataset,
                 gdalMetadata,
                 GCP_COUNT0=5,
                 GCP_COUNT1=20,
                 pixelStep=1,
                 lineStep=1,
                 **kwargs):
        ''' Create VIIRS VRT '''

        if not 'GMTCO_npp_' in filename:
            raise WrongMapperError(filename)
        ifiledir = os.path.split(filename)[0]
        ifiles = glob.glob(ifiledir + 'SVM??_npp_d*_obpg_ops.h5')
        ifiles.sort()

        if not IMPORT_SCIPY:
            raise NansatReadError(
                'VIIRS data cannot be read because scipy is not installed')

        viirsWavelengths = [
            None, 412, 445, 488, 555, 672, 746, 865, 1240, 1378, 1610, 2250,
            3700, 4050, 8550, 10736, 12013
        ]

        # create empty VRT dataset with geolocation only
        xDatasetSource = (
            'HDF5:"%s"://All_Data/VIIRS-MOD-GEO-TC_All/Longitude' % filename)
        xDatasetBand = 1
        xDataset = gdal.Open(xDatasetSource)
        self._init_from_gdal_dataset(xDataset)

        metaDict = []
        for ifile in ifiles:
            ifilename = os.path.split(ifile)[1]
            print(ifilename)
            bNumber = int(ifilename[3:5])
            print(bNumber)
            bWavelength = viirsWavelengths[bNumber]
            print(bWavelength)
            SourceFilename = (
                'HDF5:"%s"://All_Data/VIIRS-M%d-SDR_All/Radiance' %
                (ifile, bNumber))
            print(SourceFilename)
            metaEntry = {
                'src': {
                    'SourceFilename': SourceFilename,
                    'SourceBand': 1
                },
                'dst': {
                    'wkv': 'toa_outgoing_spectral_radiance',
                    'wavelength': str(bWavelength),
                    'suffix': str(bWavelength)
                }
            }
            metaDict.append(metaEntry)

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

        xVRTArray = xDataset.ReadAsArray()
        xVRTArray = gaussian_filter(xVRTArray, 5).astype('float32')
        xVRT = VRT.from_array(xVRTArray)

        yDatasetSource = (
            'HDF5:"%s"://All_Data/VIIRS-MOD-GEO-TC_All/Latitude' % filename)
        yDatasetBand = 1
        yDataset = gdal.Open(yDatasetSource)
        yVRTArray = yDataset.ReadAsArray()
        yVRTArray = gaussian_filter(yVRTArray, 5).astype('float32')
        yVRT = VRT.from_array(yVRTArray)

        # estimate pixel/line step
        self.logger.debug('pixel/lineStep %f %f' % (pixelStep, lineStep))

        # ==== ADD GCPs and Pojection ====
        # get lat/lon matrices
        longitude = xVRT.dataset.GetRasterBand(1).ReadAsArray()
        latitude = yVRT.dataset.GetRasterBand(1).ReadAsArray()

        # estimate step of GCPs
        step0 = max(1, int(float(latitude.shape[0]) / GCP_COUNT0))
        step1 = max(1, int(float(latitude.shape[1]) / GCP_COUNT1))
        self.logger.debug('gcpCount: %d %d %d %d, %d %d', latitude.shape[0],
                          latitude.shape[1], GCP_COUNT0, GCP_COUNT1, step0,
                          step1)

        # generate list of GCPs
        gcps = []
        k = 0
        for i0 in range(0, latitude.shape[0], step0):
            for i1 in range(0, latitude.shape[1], step1):
                # create GCP with X,Y,pixel,line from lat/lon matrices
                lon = float(longitude[i0, i1])
                lat = float(latitude[i0, i1])
                if (lon >= -180 and lon <= 180 and lat >= -90 and lat <= 90):
                    gcp = gdal.GCP(lon, lat, 0, i1 * pixelStep, i0 * lineStep)
                    self.logger.debug('%d %d %d %f %f', k, gcp.GCPPixel,
                                      gcp.GCPLine, gcp.GCPX, gcp.GCPY)
                    gcps.append(gcp)
                    k += 1

        # append GCPs and lat/lon projection to the vsiDataset
        self.dataset.SetGCPs(gcps, NSR().wkt)

        # remove geolocation array
        self._remove_geolocation()
Ejemplo n.º 40
0
    def __init__(self, filename, gdalDataset, gdalMetadata, latlonGrid=None,
                 mask='', **kwargs):

        ''' Create MER2 VRT

        Parameters
        -----------
        filename : string
        gdalDataset : gdal dataset
        gdalMetadata : gdal metadata
        latlonGrid : numpy 2 layered 2D array with lat/lons of desired grid
        '''
        # test if input files is GLOBCOLOUR L3B
        iDir, iFile = os.path.split(filename)
        iFileName, iFileExt = os.path.splitext(iFile)
        #print 'idir:', iDir, iFile, iFileName[0:5], iFileExt[0:8]
        if (iFileName[0:4] != 'L3b_'
            or iFileExt != '.nc'
            or not os.path.exists(filename)
            or (gdalDataset is not None
                and (len(gdalDataset.GetSubDatasets()) > 0
                     or gdalDataset.RasterCount > 0))):
            raise WrongMapperError

        # define shape of GLOBCOLOUR grid
        GLOBCOLOR_ROWS = 180 * 24
        GLOBCOLOR_COLS = 360 * 24

        # define lon/lat grids for projected var
        if latlonGrid is None:
            latlonGrid = np.mgrid[90:-90:4320j,
                                  -180:180:8640j].astype('float32')
            #latlonGrid = np.mgrid[80:50:900j, -10:30:1200j].astype('float16')
            #latlonGrid = np.mgrid[47:39:300j, 25:45:500j].astype('float32')

        # create empty VRT dataset with geolocation only
        self._init_from_lonlat(latlonGrid[1], latlonGrid[0])

        # get list of similar (same date) files in the directory
        simFilesMask = os.path.join(iDir, iFileName[0:30] + '*' + mask + '.nc')
        simFiles = glob.glob(simFilesMask)
        simFiles.sort()

        metaDict = []
        self.band_vrts = {'mask': [], 'lonlat': []}
        mask = None
        for simFile in simFiles:
            print('sim: ', simFile)
            # copy simFile to a temporary file
            tmpf = tempfile.mkstemp()
            shutil.copyfile(simFile, tmpf[1])
            f = Dataset(tmpf[1])

            # get iBinned, index for converting from binned into GLOBCOLOR-grid
            colBinned = f.variables['col'][:]
            rowBinned = f.variables['row'][:]
            iBinned = (colBinned.astype('uint32') +
                      (rowBinned.astype('uint32') - 1) * GLOBCOLOR_COLS)
            colBinned = None
            rowBinned = None

            # get iRawPro, index for converting
            # from GLOBCOLOR-grid to latlonGrid
            yRawPro = np.rint(1 + (GLOBCOLOR_ROWS - 1) *
                              (latlonGrid[0] + 90) / 180.)
            lon_step_Mat = 24. * np.cos(np.pi * latlonGrid[0] / 180.)
            xRawPro = np.rint(1 + (latlonGrid[1] + 180) * lon_step_Mat)
            iRawPro = xRawPro.astype('uint32') + (yRawPro.astype('uint32') - 1) * GLOBCOLOR_COLS
            yRawPro = None
            xRawPro = None

            for varName in f.variables:
                # find variable with _mean, eg CHL1_mean
                if '_mean' in varName:
                    var = f.variables[varName]
                    break

            # skip variable if no WKV is give in Globcolour
            if varName not in self.varname2wkv:
                continue

            # get WKV
            varWKV = self.varname2wkv[varName]

            # read binned data
            varBinned = var[:]

            # convert to GLOBCOLOR grid
            varRawPro = np.zeros([GLOBCOLOR_ROWS, GLOBCOLOR_COLS], 'float32')
            varRawPro.flat[iBinned] = varBinned

            # convert to latlonGrid
            varPro = varRawPro.flat[iRawPro.flat[:]].reshape(iRawPro.shape)

            # add mask band
            if mask is None:
                mask = np.zeros(varPro.shape, 'uint8')
                mask[:] = 1
                mask[varPro > 0] = 64

                # add VRT with array with data from projected variable
                self.band_vrts['mask'].append(VRT.from_array(mask))

                # add metadata to the dictionary
                metaDict.append({
                    'src': {'SourceFilename': (self.band_vrts['mask'][-1].
                                               filename),
                            'SourceBand':  1},
                    'dst': {'name': 'mask'}})

            # add VRT with array with data from projected variable
            self.band_vrts['lonlat'].append(VRT.from_array(varPro))

            # add metadata to the dictionary
            metaEntry = {
                'src': {'SourceFilename': self.band_vrts['lonlat'][-1].filename,
                        'SourceBand':  1},
                'dst': {'wkv': varWKV, 'original_name': varName}}

            # add wavelength for nLw
            longName = 'Fully normalised water leaving radiance'
            if longName in f.variables[varName].long_name:
                simWavelength = varName.split('L')[1].split('_mean')[0]
                metaEntry['dst']['suffix'] = simWavelength
                metaEntry['dst']['wavelength'] = simWavelength

            # add all metadata from NC-file
            for attr in var.ncattrs():
                metaEntry['dst'][attr] = var.getncattr(attr)

            metaDict.append(metaEntry)

            # add Rrsw band
            metaEntry2 = self.make_rrsw_meta_entry(metaEntry)
            if metaEntry2 is not None:
                metaDict.append(metaEntry2)

            os.remove(tmpf[1])

        instrument = f.title.strip().split(' ')[-2].split('/')[0]
        mm = pti.get_gcmd_instrument(instrument)
        self.dataset.SetMetadataItem('instrument', json.dumps(mm))

        platform = {
            'MODIS' : 'AQUA',
            'MERIS' : 'ENVISAT',
            'SEAWIFS': 'QUICKBIRD',
            'VIIRS' : 'SUOMI-NPP'}[instrument.upper()]
        pp = pti.get_gcmd_platform(platform)
        self.dataset.SetMetadataItem('platform', json.dumps(pp))

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

        # add time
        startDate = datetime.datetime(int(iFileName[4:8]),
                                      int(iFileName[8:10]),
                                      int(iFileName[10:12]))

        # Adding valid time to dataset
        self.dataset.SetMetadataItem('time_coverage_start', startDate.isoformat())
        self.dataset.SetMetadataItem('time_coverage_end', startDate.isoformat())
Ejemplo n.º 41
0
    def __init__(self,
                 filename,
                 gdalDataset,
                 gdalMetadata,
                 fast=False,
                 **kwargs):
        if kwargs.get('manifestonly', False):
            fast = True
            NansatFutureWarning(
                'manifestonly option will be deprecated. Use: fast=True')

        if not os.path.split(filename.rstrip('/'))[1][:3] in ['S1A', 'S1B']:
            raise WrongMapperError('%s: Not Sentinel 1A or 1B' % filename)

        if not IMPORT_SCIPY:
            raise NansatReadError(
                'Sentinel-1 data cannot be read because scipy is not installed'
            )

        if zipfile.is_zipfile(filename):
            zz = zipfile.PyZipFile(filename)
            # Assuming the file names are consistent, the polarization
            # dependent data should be sorted equally such that we can use the
            # same indices consistently for all the following lists
            # THIS IS NOT THE CASE...
            mds_files = [
                '/vsizip/%s/%s' % (filename, fn) for fn in zz.namelist()
                if 'measurement/s1' in fn
            ]
            calibration_files = [
                '/vsizip/%s/%s' % (filename, fn) for fn in zz.namelist()
                if 'annotation/calibration/calibration-s1' in fn
            ]
            noise_files = [
                '/vsizip/%s/%s' % (filename, fn) for fn in zz.namelist()
                if 'annotation/calibration/noise-s1' in fn
            ]
            annotation_files = [
                '/vsizip/%s/%s' % (filename, fn) for fn in zz.namelist()
                if 'annotation/s1' in fn
            ]
            manifest_files = [
                '/vsizip/%s/%s' % (filename, fn) for fn in zz.namelist()
                if 'manifest.safe' in fn
            ]
            zz.close()
        else:
            mds_files = glob.glob('%s/measurement/s1*' % filename)
            calibration_files = glob.glob(
                '%s/annotation/calibration/calibration-s1*' % filename)
            noise_files = glob.glob('%s/annotation/calibration/noise-s1*' %
                                    filename)
            annotation_files = glob.glob('%s/annotation/s1*' % filename)
            manifest_files = glob.glob('%s/manifest.safe' % filename)

        if (not mds_files or not calibration_files or not noise_files
                or not annotation_files or not manifest_files):
            raise WrongMapperError(filename)

        # convert list of MDS files into dictionary. Keys - polarizations in upper case.
        mds_files = {
            os.path.basename(ff).split('-')[3].upper(): ff
            for ff in mds_files
        }
        polarizations = list(mds_files.keys())

        # read annotation files
        annotation_data = self.read_annotation(annotation_files)
        if not fast:
            annotation_data = Mapper.correct_geolocation_data(annotation_data)

        # read manifest file
        manifest_data = self.read_manifest_data(manifest_files[0])

        # very fast constructor without any bands only with some metadata and geolocation
        self._init_empty(manifest_data, annotation_data)

        # skip adding bands in the fast mode and RETURN
        if fast:
            return

        # Open data files with GDAL
        gdalDatasets = {}
        for pol in polarizations:
            gdalDatasets[pol] = gdal.Open(mds_files[pol])

            if not gdalDatasets[pol]:
                raise WrongMapperError('%s: No Sentinel-1 datasets found' %
                                       mds_files[pol])

        # Check metadata to confirm it is Sentinel-1 L1
        metadata = gdalDatasets[polarizations[0]].GetMetadata()

        # create full size VRTs with incidenceAngle and elevationAngle
        annotation_vrts = self.vrts_from_arrays(
            annotation_data, ['incidenceAngle', 'elevationAngle'])
        self.band_vrts.update(annotation_vrts)

        # create full size VRTS with calibration LUT
        calibration_names = ['sigmaNought', 'betaNought']
        calibration_list_tag = 'calibrationVectorList'
        for calibration_file in calibration_files:
            pol = '_' + os.path.basename(calibration_file).split(
                '-')[4].upper()
            xml = self.read_vsi(calibration_file)
            calibration_data = self.read_calibration(xml, calibration_list_tag,
                                                     calibration_names, pol)
            calibration_vrts = self.vrts_from_arrays(calibration_data,
                                                     calibration_names, pol,
                                                     True, 1)
            self.band_vrts.update(calibration_vrts)

        # create full size VRTS with noise LUT
        for noise_file in noise_files:
            pol = '_' + os.path.basename(noise_file).split('-')[4].upper()
            xml = self.read_vsi(noise_file)
            if '<noiseVectorList' in xml:
                noise_list_tag = 'noiseVectorList'
                noise_name = 'noiseLut'
            elif '<noiseRangeVectorList' in xml:
                noise_list_tag = 'noiseRangeVectorList'
                noise_name = 'noiseRangeLut'
            noise_data = self.read_calibration(xml, noise_list_tag,
                                               [noise_name], pol)
            noise_vrts = self.vrts_from_arrays(noise_data, [noise_name], pol,
                                               True, 1)
            self.band_vrts.update(noise_vrts)

        #### Create metaDict: dict with metadata for all bands
        metaDict = []
        bandNumberDict = {}
        bnmax = 0
        for pol in polarizations:
            dsPath, dsName = os.path.split(mds_files[pol])
            name = 'DN_%s' % pol
            # A dictionary of band numbers is needed for the pixel function
            # bands further down. This is not the best solution. It would be
            # better to have a function in VRT that returns the number given a
            # band name. This function exists in Nansat but could perhaps be
            # moved to VRT? The existing nansat function could just call the
            # VRT one...
            bandNumberDict[name] = bnmax + 1
            bnmax = bandNumberDict[name]
            band = gdalDatasets[pol].GetRasterBand(1)
            dtype = band.DataType
            metaDict.append({
                'src': {
                    'SourceFilename': mds_files[pol],
                    'SourceBand': 1,
                    'DataType': dtype,
                },
                'dst': {
                    'name': name,
                },
            })
        # add bands with metadata and corresponding values to the empty VRT
        self.create_bands(metaDict)
        '''
        Calibration should be performed as

        s0 = DN^2/sigmaNought^2,

        where sigmaNought is from e.g.
        annotation/calibration/calibration-s1a-iw-grd-hh-20140811t151231-20140811t151301-001894-001cc7-001.xml,
        and DN is the Digital Numbers in the tiff files.

        Also the noise should be subtracted.

        See
        https://sentinel.esa.int/web/sentinel/sentinel-1-sar-wiki/-/wiki/Sentinel%20One/Application+of+Radiometric+Calibration+LUT

        The noise correction/subtraction is implemented in an independent package "sentinel1denoised"
        See
        https://github.com/nansencenter/sentinel1denoised
        '''

        # Get look direction
        longitude, latitude = self.transform_points(
            calibration_data['pixel'].flatten(),
            calibration_data['line'].flatten())
        longitude.shape = calibration_data['pixel'].shape
        latitude.shape = calibration_data['pixel'].shape
        sat_heading = initial_bearing(longitude[:-1, :], latitude[:-1, :],
                                      longitude[1:, :], latitude[1:, :])
        look_direction = scipy.ndimage.interpolation.zoom(
            np.mod(sat_heading + 90, 360),
            (np.shape(longitude)[0] / (np.shape(longitude)[0] - 1.), 1))

        # Decompose, to avoid interpolation errors around 0 <-> 360
        look_direction_u = np.sin(np.deg2rad(look_direction))
        look_direction_v = np.cos(np.deg2rad(look_direction))
        look_u_VRT = VRT.from_array(look_direction_u)
        look_v_VRT = VRT.from_array(look_direction_v)
        lookVRT = VRT.from_lonlat(longitude, latitude)
        lookVRT.create_band([{
            'SourceFilename': look_u_VRT.filename,
            'SourceBand': 1
        }, {
            'SourceFilename': look_v_VRT.filename,
            'SourceBand': 1
        }], {'PixelFunctionType': 'UVToDirectionTo'})

        # Blow up to full size
        lookVRT = lookVRT.get_resized_vrt(self.dataset.RasterXSize,
                                          self.dataset.RasterYSize, 1)

        # Store VRTs so that they are accessible later
        self.band_vrts['look_u_VRT'] = look_u_VRT
        self.band_vrts['look_v_VRT'] = look_v_VRT
        self.band_vrts['lookVRT'] = lookVRT

        metaDict = []
        # Add bands to full size VRT
        for pol in polarizations:
            name = 'sigmaNought_%s' % pol
            bandNumberDict[name] = bnmax + 1
            bnmax = bandNumberDict[name]
            metaDict.append({
                'src': {
                    'SourceFilename': (self.band_vrts[name].filename),
                    'SourceBand': 1
                },
                'dst': {
                    'name': name
                }
            })
            name = 'noise_%s' % pol
            bandNumberDict[name] = bnmax + 1
            bnmax = bandNumberDict[name]
            metaDict.append({
                'src': {
                    'SourceFilename':
                    self.band_vrts['%s_%s' % (noise_name, pol)].filename,
                    'SourceBand': 1
                },
                'dst': {
                    'name': name
                }
            })

        name = 'look_direction'
        bandNumberDict[name] = bnmax + 1
        bnmax = bandNumberDict[name]
        metaDict.append({
            'src': {
                'SourceFilename': self.band_vrts['lookVRT'].filename,
                'SourceBand': 1
            },
            'dst': {
                'wkv': 'sensor_azimuth_angle',
                'name': name
            }
        })

        for pol in polarizations:
            dsPath, dsName = os.path.split(mds_files[pol])
            name = 'sigma0_%s' % pol
            bandNumberDict[name] = bnmax + 1
            bnmax = bandNumberDict[name]
            metaDict.append({
                'src': [{
                    'SourceFilename': self.filename,
                    'SourceBand': bandNumberDict['DN_%s' % pol],
                }, {
                    'SourceFilename':
                    self.band_vrts['sigmaNought_%s' % pol].filename,
                    'SourceBand':
                    1
                }],
                'dst': {
                    'wkv':
                    'surface_backwards_scattering_coefficient_of_radar_wave',
                    'PixelFunctionType': 'Sentinel1Calibration',
                    'polarization': pol,
                    'suffix': pol,
                },
            })
            name = 'beta0_%s' % pol
            bandNumberDict[name] = bnmax + 1
            bnmax = bandNumberDict[name]
            metaDict.append({
                'src': [{
                    'SourceFilename': self.filename,
                    'SourceBand': bandNumberDict['DN_%s' % pol]
                }, {
                    'SourceFilename':
                    self.band_vrts['betaNought_%s' % pol].filename,
                    'SourceBand':
                    1
                }],
                'dst': {
                    'wkv':
                    'surface_backwards_brightness_coefficient_of_radar_wave',
                    'PixelFunctionType': 'Sentinel1Calibration',
                    'polarization': pol,
                    'suffix': pol,
                },
            })

        self.create_bands(metaDict)

        # Add incidence angle as band
        name = 'incidence_angle'
        bandNumberDict[name] = bnmax + 1
        bnmax = bandNumberDict[name]
        src = {
            'SourceFilename': self.band_vrts['incidenceAngle'].filename,
            'SourceBand': 1
        }
        dst = {'wkv': 'angle_of_incidence', 'name': name}
        self.create_band(src, dst)
        self.dataset.FlushCache()

        # Add elevation angle as band
        name = 'elevation_angle'
        bandNumberDict[name] = bnmax + 1
        bnmax = bandNumberDict[name]
        src = {
            'SourceFilename': self.band_vrts['elevationAngle'].filename,
            'SourceBand': 1
        }
        dst = {'wkv': 'angle_of_elevation', 'name': name}
        self.create_band(src, dst)
        self.dataset.FlushCache()

        # Add sigma0_VV
        if 'VV' not in polarizations and 'HH' in polarizations:
            name = 'sigma0_VV'
            bandNumberDict[name] = bnmax + 1
            bnmax = bandNumberDict[name]
            src = [{
                'SourceFilename': self.filename,
                'SourceBand': bandNumberDict['DN_HH'],
            }, {
                'SourceFilename': (self.band_vrts['sigmaNought_HH'].filename),
                'SourceBand':
                1,
            }, {
                'SourceFilename': self.band_vrts['incidenceAngle'].filename,
                'SourceBand': 1
            }]
            dst = {
                'wkv':
                'surface_backwards_scattering_coefficient_of_radar_wave',
                'PixelFunctionType': 'Sentinel1Sigma0HHToSigma0VV',
                'polarization': 'VV',
                'suffix': 'VV'
            }
            self.create_band(src, dst)
            self.dataset.FlushCache()
Ejemplo n.º 42
0
    def __init__(self, filename, gdalDataset, gdalMetadata, fast=False, fixgcp=True, **kwargs):
        if not os.path.split(filename.rstrip('/'))[1][:3] in ['S1A', 'S1B']:
            raise WrongMapperError('%s: Not Sentinel 1A or 1B' %filename)

        if not IMPORT_SCIPY:
            raise NansatReadError('Sentinel-1 data cannot be read because scipy is not installed')

        if zipfile.is_zipfile(filename):
            zz = zipfile.PyZipFile(filename)
            # Assuming the file names are consistent, the polarization
            # dependent data should be sorted equally such that we can use the
            # same indices consistently for all the following lists
            # THIS IS NOT THE CASE...
            mds_files = ['/vsizip/%s/%s' % (filename, fn)
                        for fn in zz.namelist() if 'measurement/s1' in fn]
            calibration_files = ['/vsizip/%s/%s' % (filename, fn)
                        for fn in zz.namelist()
                        if 'annotation/calibration/calibration-s1' in fn]
            noise_files = ['/vsizip/%s/%s' % (filename, fn)
                          for fn in zz.namelist()
                          if 'annotation/calibration/noise-s1' in fn]
            annotation_files = ['/vsizip/%s/%s' % (filename, fn)
                               for fn in zz.namelist()
                               if 'annotation/s1' in fn]
            manifest_files = ['/vsizip/%s/%s' % (filename, fn)
                            for fn in zz.namelist()
                            if 'manifest.safe' in fn]
            zz.close()
        else:
            mds_files = glob.glob('%s/measurement/s1*' % filename)
            calibration_files = glob.glob('%s/annotation/calibration/calibration-s1*'
                                 % filename)
            noise_files = glob.glob('%s/annotation/calibration/noise-s1*'
                                   % filename)
            annotation_files = glob.glob('%s/annotation/s1*'
                                        % filename)
            manifest_files = glob.glob('%s/manifest.safe' % filename)

        if (not mds_files or not calibration_files or not noise_files or
            not annotation_files or not manifest_files):
            raise WrongMapperError(filename)

        # convert list of MDS files into dictionary. Keys - polarizations in upper case.
        mds_files = {os.path.basename(ff).split('-')[3].upper():ff for ff in mds_files}
        polarizations = list(mds_files.keys())

        # read annotation files
        self.annotation_data = self.read_annotation(annotation_files)
        if not fast and fixgcp:
            self.correct_geolocation_data()

        # read manifest file
        manifest_data = self.read_manifest_data(manifest_files[0])

        # very fast constructor without any bands only with some metadata and geolocation
        self._init_empty(manifest_data, self.annotation_data)

        # skip adding bands in the fast mode and RETURN
        if fast:
            return

        # Open data files with GDAL
        gdalDatasets = {}
        for pol in polarizations:
            gdalDatasets[pol] = gdal.Open(mds_files[pol])

            if not gdalDatasets[pol]:
                raise WrongMapperError('%s: No Sentinel-1 datasets found' % mds_files[pol])

        # Check metadata to confirm it is Sentinel-1 L1
        metadata = gdalDatasets[polarizations[0]].GetMetadata()

        # create full size VRTs with incidenceAngle and elevationAngle
        annotation_vrts = self.vrts_from_arrays(self.annotation_data,
                                                ['incidenceAngle', 'elevationAngle'])
        self.band_vrts.update(annotation_vrts)

        # create full size VRTS with calibration LUT
        calibration_names = ['sigmaNought', 'betaNought']
        calibration_list_tag = 'calibrationVectorList'
        for calibration_file in calibration_files:
            pol = '_' + os.path.basename(calibration_file).split('-')[4].upper()
            xml = self.read_vsi(calibration_file)
            calibration_data = self.read_calibration(xml, calibration_list_tag, calibration_names, pol)
            calibration_vrts = self.vrts_from_arrays(calibration_data, calibration_names, pol, True, 1)
            self.band_vrts.update(calibration_vrts)

        # create full size VRTS with noise LUT
        for noise_file in noise_files:
            pol = '_' + os.path.basename(noise_file).split('-')[4].upper()
            xml = self.read_vsi(noise_file)
            if '<noiseVectorList' in xml:
                noise_list_tag = 'noiseVectorList'
                noise_name = 'noiseLut'
            elif '<noiseRangeVectorList' in xml:
                noise_list_tag = 'noiseRangeVectorList'
                noise_name = 'noiseRangeLut'
            noise_data = self.read_calibration(xml, noise_list_tag, [noise_name], pol)
            noise_vrts = self.vrts_from_arrays(noise_data, [noise_name], pol, True, 1)
            self.band_vrts.update(noise_vrts)

        #### Create metaDict: dict with metadata for all bands
        metaDict = []
        bandNumberDict = {}
        bnmax = 0
        for pol in polarizations:
            dsPath, dsName = os.path.split(mds_files[pol])
            name = 'DN_%s' % pol
            # A dictionary of band numbers is needed for the pixel function
            # bands further down. This is not the best solution. It would be
            # better to have a function in VRT that returns the number given a
            # band name. This function exists in Nansat but could perhaps be
            # moved to VRT? The existing nansat function could just call the
            # VRT one...
            bandNumberDict[name] = bnmax + 1
            bnmax = bandNumberDict[name]
            band = gdalDatasets[pol].GetRasterBand(1)
            dtype = band.DataType
            metaDict.append({
                'src': {
                    'SourceFilename': mds_files[pol],
                    'SourceBand': 1,
                    'DataType': dtype,
                },
                'dst': {
                    'name': name,
                },
            })
        # add bands with metadata and corresponding values to the empty VRT
        self.create_bands(metaDict)

        '''
        Calibration should be performed as

        s0 = DN^2/sigmaNought^2,

        where sigmaNought is from e.g.
        annotation/calibration/calibration-s1a-iw-grd-hh-20140811t151231-20140811t151301-001894-001cc7-001.xml,
        and DN is the Digital Numbers in the tiff files.

        Also the noise should be subtracted.

        See
        https://sentinel.esa.int/web/sentinel/sentinel-1-sar-wiki/-/wiki/Sentinel%20One/Application+of+Radiometric+Calibration+LUT

        The noise correction/subtraction is implemented in an independent package "sentinel1denoised"
        See
        https://github.com/nansencenter/sentinel1denoised
        '''

        # Get look direction
        longitude, latitude = self.transform_points(calibration_data['pixel'].flatten(),
                                                    calibration_data['line'].flatten())
        longitude.shape = calibration_data['pixel'].shape
        latitude.shape = calibration_data['pixel'].shape
        sat_heading = initial_bearing(longitude[:-1, :],
                                      latitude[:-1, :],
                                      longitude[1:, :],
                                      latitude[1:, :])
        look_direction = scipy.ndimage.interpolation.zoom(
            np.mod(sat_heading + 90, 360),
            (np.shape(longitude)[0] / (np.shape(longitude)[0]-1.), 1))

        # Decompose, to avoid interpolation errors around 0 <-> 360
        look_direction_u = np.sin(np.deg2rad(look_direction))
        look_direction_v = np.cos(np.deg2rad(look_direction))
        look_u_VRT = VRT.from_array(look_direction_u)
        look_v_VRT = VRT.from_array(look_direction_v)
        lookVRT = VRT.from_lonlat(longitude, latitude)
        lookVRT.create_band([{'SourceFilename': look_u_VRT.filename,
                               'SourceBand': 1},
                              {'SourceFilename': look_v_VRT.filename,
                               'SourceBand': 1}],
                             {'PixelFunctionType': 'UVToDirectionTo'}
                             )

        # Blow up to full size
        lookVRT = lookVRT.get_resized_vrt(self.dataset.RasterXSize, self.dataset.RasterYSize, 1)

        # Store VRTs so that they are accessible later
        self.band_vrts['look_u_VRT'] = look_u_VRT
        self.band_vrts['look_v_VRT'] = look_v_VRT
        self.band_vrts['lookVRT'] = lookVRT

        metaDict = []
        # Add bands to full size VRT
        for pol in polarizations:
            name = 'sigmaNought_%s' % pol
            bandNumberDict[name] = bnmax+1
            bnmax = bandNumberDict[name]
            metaDict.append(
                {'src': {'SourceFilename':
                         (self.band_vrts[name].filename),
                         'SourceBand': 1
                         },
                 'dst': {'name': name
                         }
                 })
            name = 'noise_%s' % pol
            bandNumberDict[name] = bnmax+1
            bnmax = bandNumberDict[name]
            metaDict.append({
                'src': {
                    'SourceFilename': self.band_vrts['%s_%s' % (noise_name, pol)].filename,
                    'SourceBand': 1
                },
                'dst': {
                    'name': name
                }
            })

        name = 'look_direction'
        bandNumberDict[name] = bnmax+1
        bnmax = bandNumberDict[name]
        metaDict.append({
            'src': {
                'SourceFilename': self.band_vrts['lookVRT'].filename,
                'SourceBand': 1
            },
            'dst': {
                'wkv': 'sensor_azimuth_angle',
                'name': name
            }
        })

        for pol in polarizations:
            dsPath, dsName = os.path.split(mds_files[pol])
            name = 'sigma0_%s' % pol
            bandNumberDict[name] = bnmax+1
            bnmax = bandNumberDict[name]
            metaDict.append(
                {'src': [{'SourceFilename': self.filename,
                          'SourceBand': bandNumberDict['DN_%s' % pol],
                          },
                         {'SourceFilename': self.band_vrts['sigmaNought_%s' % pol].filename,
                          'SourceBand': 1
                          }
                         ],
                 'dst': {'wkv': 'surface_backwards_scattering_coefficient_of_radar_wave',
                         'PixelFunctionType': 'Sentinel1Calibration',
                         'polarization': pol,
                         'suffix': pol,
                         },
                 })
            name = 'beta0_%s' % pol
            bandNumberDict[name] = bnmax+1
            bnmax = bandNumberDict[name]
            metaDict.append(
                {'src': [{'SourceFilename': self.filename,
                          'SourceBand': bandNumberDict['DN_%s' % pol]
                          },
                         {'SourceFilename': self.band_vrts['betaNought_%s' % pol].filename,
                          'SourceBand': 1
                          }
                         ],
                 'dst': {'wkv': 'surface_backwards_brightness_coefficient_of_radar_wave',
                         'PixelFunctionType': 'Sentinel1Calibration',
                         'polarization': pol,
                         'suffix': pol,
                         },
                 })

        self.create_bands(metaDict)

        # Add incidence angle as band
        name = 'incidence_angle'
        bandNumberDict[name] = bnmax+1
        bnmax = bandNumberDict[name]
        src = {'SourceFilename': self.band_vrts['incidenceAngle'].filename,
               'SourceBand': 1}
        dst = {'wkv': 'angle_of_incidence',
               'name': name}
        self.create_band(src, dst)
        self.dataset.FlushCache()

        # Add elevation angle as band
        name = 'elevation_angle'
        bandNumberDict[name] = bnmax+1
        bnmax = bandNumberDict[name]
        src = {'SourceFilename': self.band_vrts['elevationAngle'].filename,
               'SourceBand': 1}
        dst = {'wkv': 'angle_of_elevation',
               'name': name}
        self.create_band(src, dst)
        self.dataset.FlushCache()

        # Add sigma0_VV
        if 'VV' not in polarizations and 'HH' in polarizations:
            name = 'sigma0_VV'
            bandNumberDict[name] = bnmax+1
            bnmax = bandNumberDict[name]
            src = [{'SourceFilename': self.filename,
                    'SourceBand': bandNumberDict['DN_HH'],
                    },
                   {'SourceFilename': (self.band_vrts['sigmaNought_HH'].
                                       filename),
                    'SourceBand': 1,
                    },
                   {'SourceFilename': self.band_vrts['incidenceAngle'].filename,
                    'SourceBand': 1}
                   ]
            dst = {'wkv': 'surface_backwards_scattering_coefficient_of_radar_wave',
                   'PixelFunctionType': 'Sentinel1Sigma0HHToSigma0VV',
                   'polarization': 'VV',
                   'suffix': 'VV'}
            self.create_band(src, dst)
            self.dataset.FlushCache()