Exemple #1
0
    def test_config_set_res(self):

        with gw.config.update(ref_res=100):

            with gw.open(l8_224078_20200518) as src:
                self.assertEqual(src.gw.celly, 100)

        with gw.open(l8_224078_20200518) as src:
            self.assertEqual(src.gw.celly, 30)
Exemple #2
0
    def test_with_config(self):

        with gw.config.update():

            with gw.open(l8_224078_20200518) as src:
                self.assertTrue(src.gw.config['with_config'])

        with gw.open(l8_224078_20200518) as src:
            self.assertFalse(src.gw.config['with_config'])
Exemple #3
0
    def test_single_image_single_band(self):

        with gw.open(l8_224078_20200518_B2) as src:
            df = gw.extract(src, aoi, band_names=['blue'])

        self.assertTrue(
            np.allclose(df.blue.values, l8_224078_20200518_B2_values))
Exemple #4
0
    def test_config_bands_set_none(self):

        with gw.config.update(sensor=None):

            with gw.open(l8_224078_20200518) as src:
                self.assertEqual(','.join(map(str, src.band.values.tolist())),
                                 '1,2,3')
Exemple #5
0
    def test_config_bands_set(self):

        with gw.config.update(sensor='bgr'):

            with gw.open(l8_224078_20200518) as src:
                self.assertEqual(','.join(src.band.values.tolist()),
                                 'blue,green,red')
Exemple #6
0
    def test_config_bands_set_override(self):

        with gw.config.update(sensor='bgr'):

            with gw.open(l8_224078_20200518, band_names=['b1', 'b2',
                                                         'b3']) as src:
                self.assertEqual(','.join(src.band.values.tolist()),
                                 'b1,b2,b3')
Exemple #7
0
    def test_transform(self):

        with gw.open(l8_224078_20200518) as src:

            self.assertEqual(
                'epsg:4326',
                src.gw.transform_crs(dst_crs=4326,
                                     dst_width=src.gw.ncols,
                                     dst_height=src.gw.nrows,
                                     coords_only=True).crs.to_string().lower())
Exemple #8
0
    def test_single_image_multi_band(self):

        with gw.open(l8_224078_20200518) as src:
            df = gw.extract(src, aoi, band_names=['blue', 'green', 'red'])

        self.assertTrue(
            np.allclose(df.blue.values, l8_224078_20200518_values[0, :]))
        self.assertTrue(
            np.allclose(df.green.values, l8_224078_20200518_values[1, :]))
        self.assertTrue(
            np.allclose(df.red.values, l8_224078_20200518_values[2, :]))
Exemple #9
0
    def test_warnings_ignore(self):

        with LogCapture() as log:

            with gw.config.update(sensor='l7', ignore_warnings=True):

                with gw.open(l8_224078_20200518) as src:
                    pass

            self.assertNotIn((
                'geowombat.backends.xarray_', 'WARNING',
                "  The new bands, ['blue', 'green', 'red', 'nir', 'swir1', 'swir2'], do not match the sensor bands, [1, 2, 3]."
            ), log)
Exemple #10
0
    def test_config_defaults(self):

        with gw.open(l8_224078_20200518) as src:

            self.assertEqual(src.gw.config['scale_factor'], 1)

            for config_default in ['with_config', 'ignore_warnings']:
                self.assertFalse(src.gw.config[config_default])

            for config_default in [
                    'sensor', 'nodata', 'ref_image', 'ref_bounds', 'ref_crs',
                    'ref_res', 'ref_tar', 'compress'
            ]:
                self.assertIsNone(src.gw.config[config_default])
Exemple #11
0
    def coregister(target, reference, **kwargs):
        """
        Co-registers an image, or images, using AROSICS.

        While the required inputs are DataArrays, the intermediate results are stored as NumPy arrays.
        Therefore, memory usage is constrained to the size of the input data. Dask is not used for any of the
        computation in this function.

        Args:
            target (DataArray or str): The target ``xarray.DataArray`` or file name to co-register to ``reference``.
            reference (DataArray or str): The reference ``xarray.DataArray`` or file name used to co-register ``target``.
            kwargs (Optional[dict]): Keyword arguments passed to ``arosics``.

        Reference:
            https://pypi.org/project/arosics

        Returns:
            ``xarray.DataArray``

        Example:
            >>> import geowombat as gw
            >>>
            >>> # Co-register a single image to a reference image
            >>> with gw.open('target.tif') as tar, gw.open('reference.tif') as ref:
            >>>     results = gw.coregister(tar, ref, q=True, ws=(512, 512), max_shift=3, CPUs=4)
            >>>
            >>> # or
            >>>
            >>> results = gw.coregister('target.tif', 'reference.tif', q=True, ws=(512, 512), max_shift=3, CPUs=4)
        """

        import geowombat as gw_

        if not AROSICS_INSTALLED:

            logger.exception(
                '\nAROSICS must be installed to co-register data.\nSee https://pypi.org/project/arosics for details'
            )
            raise NameError

        if isinstance(reference, str):

            if not os.path.isfile(reference):

                logger.exception('  The reference file does not exist.')
                raise OSError

            with gw_.open(reference) as reference:
                pass

        if isinstance(target, str):

            if not os.path.isfile(target):

                logger.exception('  The target file does not exist.')
                raise OSError

            with gw_.open(target) as target:
                pass

        cr = arosics.COREG(reference.filename, target.filename, **kwargs)

        try:
            cr.calculate_spatial_shifts()
        except:

            logger.warning('  Could not co-register the data.')
            return target

        shift_info = cr.correct_shifts()

        left = shift_info['updated geotransform'][0]
        top = shift_info['updated geotransform'][3]

        transform = (target.gw.cellx, 0.0, left, 0.0, -target.gw.celly, top)

        target.attrs['transform'] = transform

        data = shift_info['arr_shifted'].transpose(2, 0, 1)

        ycoords = np.linspace(
            top - target.gw.cellyh,
            top - target.gw.cellyh - (data.shape[1] * target.gw.celly),
            data.shape[1])

        xcoords = np.linspace(
            left + target.gw.cellxh,
            left + target.gw.cellxh + (data.shape[2] * target.gw.cellx),
            data.shape[2])

        return xr.DataArray(data=da.from_array(data,
                                               chunks=(target.gw.band_chunks,
                                                       target.gw.row_chunks,
                                                       target.gw.col_chunks)),
                            dims=('band', 'y', 'x'),
                            coords={
                                'band': target.band.values.tolist(),
                                'y': ycoords,
                                'x': xcoords
                            },
                            attrs=target.attrs)
Exemple #12
0
    def test_has_band(self):

        with gw.open(l8_224078_20200518) as src:
            self.assertTrue(src.gw.has_band)
Exemple #13
0
    def test_height(self):

        with gw.open(l8_224078_20200518) as src, rio.open(
                l8_224078_20200518) as rsrc:
            self.assertEqual(src.gw.ncols, rsrc.width)
    def download_cube(self,
                      sensors,
                      date_range,
                      bounds,
                      bands,
                      crs=None,
                      out_bounds=None,
                      outdir='.',
                      ref_res=None,
                      l57_angles_path=None,
                      l8_angles_path=None,
                      **kwargs):
        """
        Downloads a cube of Landsat and/or Sentinel 2 imagery

        Args:
            sensors (str or list): The sensors, or sensor, to download.
            date_range (list): The date range, given as [date1, date2], where the date format is yyyy-mm-dd.
            bounds (GeoDataFrame, list, or tuple): The geometry bounds (in WGS84 lat/lon) that define the cube extent
                to download. If given as a ``GeoDataFrame``, only the first ``DataFrame`` record will be used.
                If given as a ``tuple`` or a ``list``, the order should be (left, bottom, right, top).
            bands (str or list): The bands to download.
            crs (Optional[str or object]): The output CRS. If ``bounds`` is a ``GeoDataFrame``, the CRS is taken
                from the object.
            out_bounds (Optional[list or tuple]): The output bounds in ``crs``. If not given, the bounds are
                taken from ``bounds``.
            outdir (Optional[str]): The output directory.
            ref_res (Optional[tuple]): A reference cell resolution.
            l57_angles_path (str): The path to the Landsat 5 and 7 angles bin.
            l8_angles_path (str): The path to the Landsat 8 angles bin.
            kwargs (Optional[dict]): Keyword arguments passed to ``to_raster``.

        Examples:
            >>> from geowombat.util import GeoDownloads
            >>> gdl = GeoDownloads()
            >>>
            >>> # Download a Landsat 7 panchromatic cube
            >>> gdl.download_cube(['l7'],
            >>>                   ['2010-01-01', '2010-02-01'],
            >>>                   (-91.57, 40.37, -91.46, 40.42),
            >>>                   ['pan'],
            >>>                   crs="+proj=aea +lat_1=-5 +lat_2=-42 +lat_0=-32 +lon_0=-60 +x_0=0 +y_0=0 +ellps=aust_SA +units=m +no_defs")
            >>>
            >>> # Download a Landsat 7, 8 and Sentinel 2 cube of the visible spectrum
            >>> gdl.download_cube(['l7', 'l8', 's2'],
            >>>                   ['2017-01-01', '2018-01-01'],
            >>>                   (-91.57, 40.37, -91.46, 40.42),
            >>>                   ['blue', 'green', 'red'],
            >>>                   crs={'init': 'epsg:102033'},
            >>>                   readxsize=1024,
            >>>                   readysize=1024,
            >>>                   n_workers=1,
            >>>                   n_threads=8)
        """

        # TODO: parameterize
        # kwargs = dict(readxsize=1024,
        #               readysize=1024,
        #               verbose=1,
        #               separate=False,
        #               n_workers=1,
        #               n_threads=8,
        #               n_chunks=100,
        #               overwrite=False)

        angle_infos = dict()

        rt = RadTransforms()
        br = BRDF()
        la = LinearAdjustments()

        main_path = Path(outdir)
        outdir_brdf = main_path.joinpath('brdf')

        if not main_path.is_dir():
            main_path.mkdir()

        if not outdir_brdf.is_dir():
            outdir_brdf.mkdir()

        if isinstance(sensors, str):
            sensors = [sensors]

        status = Path(outdir).joinpath('status.txt')

        if not status.is_file():

            with open(status.as_posix(), mode='w') as tx:
                pass

        # Get bounds from geometry
        if isinstance(bounds, tuple) or isinstance(bounds, list):

            bounds = Polygon([
                (bounds[0], bounds[3]),  # upper left
                (bounds[2], bounds[3]),  # upper right
                (bounds[2], bounds[1]),  # lower right
                (bounds[0], bounds[1]),  # lower left
                (bounds[0], bounds[3])
            ])  # upper left

            bounds = gpd.GeoDataFrame([0],
                                      geometry=[bounds],
                                      crs={'init': 'epsg:4326'})

        bounds_object = bounds.geometry.values[0]

        if not out_bounds:

            # Project the bounds
            out_bounds = bounds.to_crs(crs).bounds.values[0].tolist()

        # Get WRS file
        data_bin = os.path.realpath(os.path.dirname(__file__))

        data_dir = Path(data_bin).joinpath('../data')

        shp_dict = dict()

        if ('l7' in sensors) or ('l8' in sensors):

            path_tar = Path(data_dir).joinpath('wrs2.tar.gz')
            path_shp = Path(data_dir).joinpath('wrs2_descending.shp')
            wrs = os.path.realpath(path_shp.as_posix())

            if not path_shp.is_file():

                with tarfile.open(os.path.realpath(path_tar.as_posix()),
                                  mode='r:gz') as tf:
                    tf.extractall(data_dir.as_posix())

            df_wrs = gpd.read_file(wrs)
            df_wrs = df_wrs[df_wrs.geometry.intersects(bounds_object)]

            if df_wrs.empty:
                logger.warning('  The geometry bounds is empty.')
                return

            shp_dict['wrs'] = df_wrs

        if 's2' in sensors:

            path_tar = Path(data_dir).joinpath('mgrs.tar.gz')
            path_shp = Path(data_dir).joinpath('sentinel2_grid.shp')
            mgrs = os.path.realpath(path_shp.as_posix())

            if not path_shp.is_file():

                with tarfile.open(os.path.realpath(path_tar.as_posix()),
                                  mode='r:gz') as tf:
                    tf.extractall(data_dir.as_posix())

            df_mgrs = gpd.read_file(mgrs)
            df_mgrs = df_mgrs[df_mgrs.geometry.intersects(bounds_object)]

            if df_mgrs.empty:
                logger.warning('  The geometry bounds is empty.')
                return

            shp_dict['mgrs'] = df_mgrs

        dt1 = datetime.strptime(date_range[0], '%Y-%m-%d')
        dt2 = datetime.strptime(date_range[1], '%Y-%m-%d')

        year = dt1.year
        month = dt1.month

        months = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]

        if month < dt2.month:
            month_range = months[months.index(month):months.index(dt2.month) +
                                 1]
        else:
            month_range = months[
                months.index(month):] + months[:months.index(dt2.month) + 1]

        while True:

            if year > dt2.year:
                break

            for m in month_range:

                yearmonth_query = '{:d}{:02d}'.format(year, m)

                for sensor in sensors:

                    band_associations = self.associations[sensor]

                    # TODO: get path/row and MGRS from geometry
                    # location = '21/H/UD' # or '225/083'

                    if sensor.lower() == 's2':

                        locations = [
                            '{}/{}/{}'.format(dfrow.Name[:2], dfrow.Name[2],
                                              dfrow.Name[3:])
                            for dfi, dfrow in shp_dict['mgrs'].iterrows()
                        ]

                    else:

                        locations = [
                            '{:03d}/{:03d}'.format(int(dfrow.PATH),
                                                   int(dfrow.ROW))
                            for dfi, dfrow in shp_dict['wrs'].iterrows()
                        ]

                    for location in locations:

                        if sensor.lower() == 's2':

                            query = '{LOCATION}/*{YM}*.SAFE/GRANULE/*'.format(
                                LOCATION=location, YM=yearmonth_query)

                        else:

                            query = '{LOCATION}/*{PATHROW}_{YM}*_T*'.format(
                                LOCATION=location,
                                PATHROW=location.replace('/', ''),
                                YM=yearmonth_query)

                        # Query and list available files on the GCP
                        self.list_gcp(sensor, query)

                        if not self.search_dict:

                            logger.warning(
                                '  No results found for {SENSOR} at location {LOC}, year {YEAR:d}, month {MONTH:d}.'
                                .format(SENSOR=sensor,
                                        LOC=location,
                                        YEAR=year,
                                        MONTH=m))

                            continue

                        # Download data
                        if sensor.lower() == 's2':

                            load_bands = sorted([
                                'B{:02d}'.format(band_associations[bd])
                                if bd != 'rededge' else 'B{:02d}A'.format(
                                    band_associations[bd]) for bd in bands
                            ])

                            search_wildcards = ['MTD_TL.xml'] + [
                                bd + '.jp2' for bd in load_bands
                            ]

                            file_info = self.download_gcp(
                                sensor,
                                outdir=outdir,
                                search_wildcards=search_wildcards,
                                check_file=status.as_posix(),
                                verbose=1)

                            # Reorganize the dictionary to combine bands and metadata
                            new_dict_ = dict()
                            for finfo_key, finfo_dict in file_info.items():

                                sub_dict_ = dict()

                                if 'meta' in finfo_dict:

                                    key = finfo_dict['meta'].name

                                    sub_dict_['meta'] = finfo_dict['meta']

                                    for finfo_key_, finfo_dict_ in file_info.items(
                                    ):

                                        if 'meta' not in finfo_dict_:
                                            for bdkey_, bdinfo_ in finfo_dict_.items(
                                            ):
                                                if '_'.join(
                                                        bdinfo_.name.split('_')
                                                    [:-1]) in key:
                                                    sub_dict_[bdkey_] = bdinfo_

                                    new_dict_[finfo_key] = sub_dict_

                            file_info = new_dict_

                        else:

                            del_keys = [
                                k for k, v in self.search_dict.items()
                                if 'gap_mask' in k
                            ]

                            for dk in del_keys:
                                del self.search_dict[dk]

                            load_bands = sorted([
                                'B{:d}'.format(band_associations[bd])
                                for bd in bands
                            ])

                            search_wildcards = [
                                'ANG.txt', 'MTL.txt', 'BQA.TIF'
                            ] + [bd + '.TIF' for bd in load_bands]

                            file_info = self.download_gcp(
                                sensor,
                                outdir=outdir,
                                search_wildcards=search_wildcards,
                                check_file=status.as_posix(),
                                verbose=1)

                        logger.info('  Finished downloading files')

                        # Create pixel angle files
                        # TODO: this can be run in parallel
                        for finfo_key, finfo_dict in file_info.items():

                            brdfp = '_'.join(
                                Path(finfo_dict['meta'].name).name.split('_')
                                [:-1])

                            logger.info('  Processing {} ...'.format(brdfp))

                            out_brdf = outdir_brdf.joinpath(brdfp +
                                                            '.tif').as_posix()

                            if os.path.isfile(out_brdf):
                                logger.warning(
                                    '  The output BRDF file, {}, already exists.'
                                    .format(brdfp))
                                continue

                            with open(status.as_posix(), mode='r') as tx:
                                lines = tx.readlines()

                            if sensor == 's2':
                                outdir_angles = main_path.joinpath(
                                    'angles_{}'.format(
                                        Path(finfo_dict['meta'].name).name.
                                        replace('_MTD_TL.xml', '')))
                            else:
                                outdir_angles = main_path.joinpath(
                                    'angles_{}'.format(
                                        Path(finfo_dict['meta'].name).name.
                                        replace('_MTL.txt', '')))

                            outdir_angles.mkdir(parents=True, exist_ok=True)

                            ref_file = finfo_dict[load_bands[0]].name

                            if sensor.lower() == 's2':

                                angle_info = sentinel_pixel_angles(
                                    finfo_dict['meta'].name,
                                    ref_file,
                                    outdir_angles.as_posix(),
                                    nodata=-32768,
                                    overwrite=False,
                                    verbose=1)

                                if ' '.join(
                                        bands
                                ) == 'blue green red nir1 nir2 nir3 nir rededge swir1 swir2':
                                    rad_sensor = 's2'
                                elif ' '.join(
                                        bands
                                ) == 'blue green red nir swir1 swir2':
                                    rad_sensor = 's2l7'
                                elif ' '.join(bands) == 'blue green red nir':
                                    rad_sensor = 's210'
                                else:
                                    rad_sensor = 's2'

                                bandpass_sensor = angle_info.sensor

                            else:

                                meta = rt.get_landsat_coefficients(
                                    finfo_dict['meta'].name)

                                angle_info = landsat_pixel_angles(
                                    finfo_dict['angle'].name,
                                    ref_file,
                                    outdir_angles.as_posix(),
                                    meta.sensor,
                                    l57_angles_path=l57_angles_path,
                                    l8_angles_path=l8_angles_path,
                                    verbose=1)

                                if (len(bands) == 1) and (bands[0] == 'pan'):
                                    rad_sensor = sensor + bands[0]
                                else:

                                    if (len(bands) == 6) and (meta.sensor
                                                              == 'l8'):
                                        rad_sensor = 'l8l7'
                                    elif (len(bands)
                                          == 7) and (meta.sensor
                                                     == 'l8') and ('pan'
                                                                   in bands):
                                        rad_sensor = 'l8l7mspan'
                                    elif (len(bands)
                                          == 7) and (meta.sensor
                                                     == 'l7') and ('pan'
                                                                   in bands):
                                        rad_sensor = 'l7mspan'
                                    else:
                                        rad_sensor = meta.sensor

                                bandpass_sensor = sensor

                            # Get band names from user
                            load_bands_names = [
                                finfo_dict[bd].name for bd in load_bands
                            ]

                            with gw.config.update(sensor=rad_sensor,
                                                  ref_bounds=out_bounds,
                                                  ref_crs=crs,
                                                  ref_res=ref_res if ref_res
                                                  else load_bands_names[-1]):

                                with gw.open(angle_info.sza,
                                             resampling='cubic') as sza, \
                                        gw.open(angle_info.vza,
                                                resampling='cubic') as vza, \
                                        gw.open(angle_info.saa,
                                                resampling='cubic') as saa, \
                                        gw.open(angle_info.vaa,
                                                resampling='cubic') as vaa:

                                    with gw.open(
                                            load_bands_names,
                                            band_names=bands,
                                            stack_dim='band',
                                            resampling='cubic') as data:  #, \
                                        # gw.open(finfo_dict['qa'].name,
                                        #         band_names=['qa']) as qa:

                                        # Setup the mask
                                        # if sensor.lower() != 's2':
                                        #
                                        #     if sensor.lower() == 'l8':
                                        #         qa_sensor = 'l8-c1'
                                        #     else:
                                        #         qa_sensor = 'l-c1'

                                        # mask = QAMasker(qa,
                                        #                 qa_sensor,
                                        #                 mask_items=['clear',
                                        #                             'fill',
                                        #                             'shadow',
                                        #                             'cloudconf',
                                        #                             'cirrusconf',
                                        #                             'snowiceconf'],
                                        #                 confidence_level='maybe').to_mask()

                                        if sensor.lower() == 's2':

                                            # The S-2 data are in TOAR (0-10000)
                                            toar_scaled = (data * 0.0001).clip(
                                                0, 1).astype('float64')
                                            toar_scaled.attrs = data.attrs.copy(
                                            )

                                            # Convert TOAR to surface reflectance
                                            sr = rt.toar_to_sr(
                                                toar_scaled, sza, saa, vza,
                                                vaa, sensor)

                                        else:

                                            # Convert DN to surface reflectance
                                            sr = rt.dn_to_sr(data,
                                                             sza,
                                                             saa,
                                                             vza,
                                                             vaa,
                                                             sensor=rad_sensor,
                                                             meta=meta)

                                        # BRDF normalization
                                        sr_brdf = br.norm_brdf(
                                            sr,
                                            sza,
                                            saa,
                                            vza,
                                            vaa,
                                            sensor=rad_sensor,
                                            wavelengths=data.band.values.
                                            tolist(),
                                            out_range=10000.0,
                                            nodata=65535)

                                        if bandpass_sensor.lower() in [
                                                'l5', 'l7', 's2a', 's2b'
                                        ]:

                                            # Linear adjust to Landsat 8
                                            sr_brdf = la.bandpass(
                                                sr_brdf,
                                                bandpass_sensor.lower(),
                                                to='l8',
                                                scale_factor=0.0001)

                                        # Mask non-clear pixels
                                        # attrs = sr_brdf.attrs
                                        # sr_brdf = xr.where(mask.sel(band='mask') < 2, sr_brdf, 65535)
                                        # sr_brdf = sr_brdf.transpose('band', 'y', 'x')
                                        # sr_brdf.attrs = attrs

                                        attrs = sr_brdf.attrs.copy()
                                        sr_brdf = sr_brdf.clip(
                                            0, 10000).astype('uint16')
                                        sr_brdf.attrs = attrs.copy()

                                        sr_brdf.gw.to_raster(
                                            out_brdf, **kwargs)

                            angle_infos[finfo_key] = angle_info

                            shutil.rmtree(outdir_angles.as_posix())

                            for k, v in finfo_dict.items():
                                os.remove(v.name)

                            lines.append(finfo_dict['meta'].name + '\n')

                            with open(status.as_posix(), mode='r+') as tx:
                                tx.writelines(lines)

            year += 1
Exemple #15
0
    def test_has_no_band_coord(self):

        with gw.open(l8_224078_20200518) as src:
            self.assertFalse(src.drop_vars('band').gw.has_band_coord)
Exemple #16
0
    def test_row_chunks(self):

        with gw.open(l8_224078_20200518) as src:
            self.assertEqual(src.gw.row_chunks, 256)
Exemple #17
0
    def test_row_chunks_set(self):

        with gw.open(l8_224078_20200518, chunks=64) as src:
            self.assertEqual(src.gw.row_chunks, 64)
Exemple #18
0
    def test_open_multiple(self):

        with gw.open([l8_224078_20200518, l8_224078_20200518],
                     stack_dim='time') as src:
            self.assertEqual(src.gw.ntime, 2)
Exemple #19
0
    def test_time_chunks(self):

        with gw.open(l8_224078_20200518) as src:
            self.assertEqual(src.gw.time_chunks, 1)
Exemple #20
0
    def test_width(self):

        with gw.open(l8_224078_20200518) as src, rio.open(
                l8_224078_20200518) as rsrc:
            self.assertEqual(src.gw.nrows, rsrc.height)
Exemple #21
0
    def test_dtype(self):

        with gw.open(l8_224078_20200518, dtype='float64') as src:
            self.assertEqual(src.dtype, 'float64')
Exemple #22
0
    def test_open_path(self):

        with gw.open(Path(l8_224078_20200518)) as src:
            self.assertEqual(src.gw.nbands, 3)
Exemple #23
0
    def test_has_no_time_coord(self):

        with gw.open([l8_224078_20200518, l8_224078_20200518],
                     stack_dim='time') as src:
            self.assertFalse(src.drop_vars('time').gw.has_time_coord)
Exemple #24
0
    def test_has_time(self):

        with gw.open([l8_224078_20200518, l8_224078_20200518],
                     stack_dim='time') as src:
            self.assertTrue(src.gw.has_time)
Exemple #25
0
    def test_open_type_xarray(self):

        with gw.open(l8_224078_20200518) as src:
            self.assertIsInstance(src, xr.DataArray)
Exemple #26
0
    def test_count(self):

        with gw.open(l8_224078_20200518) as src, rio.open(
                l8_224078_20200518) as rsrc:
            self.assertEqual(src.gw.nbands, rsrc.count)
Exemple #27
0
    def test_config_bands(self):

        with gw.open(l8_224078_20200518) as src:
            self.assertEqual(','.join(map(str, src.band.values.tolist())),
                             '1,2,3')
Exemple #28
0
    def test_open_type_dask(self):

        with gw.open(l8_224078_20200518) as src:
            self.assertIsInstance(src.data, dask.array.core.Array)
Exemple #29
0
    def get_mean_altitude(data,
                          out_dir,
                          username=None,
                          key_file=None,
                          code_file=None,
                          chunks=512,
                          n_jobs=1,
                          delete_downloaded=False):

        if not username:
            username = data.gw.nasa_earthdata_user

        if not key_file:
            key_file = data.gw.nasa_earthdata_key

        if not code_file:
            code_file = data.gw.nasa_earthdata_code

        if not username or not key_file or not code_file:
            logger.exception(
                '  The NASA EarthData username, secret key file, and secret code file must be provided to download SRTM data.'
            )
            raise AttributeError

        if not Path(out_dir).is_dir():
            Path(out_dir).mkdir(parents=True, exist_ok=True)

        srtm_grid_path_temp = Path(
            out_dir) / f'srtm30m_bounding_boxes_{_random_id(9)}.gpkg'

        shutil.copy(str(srtm30m_bounding_boxes), str(srtm_grid_path_temp))

        srtm_df = gpd.read_file(srtm_grid_path_temp)

        srtm_grid_path_temp.unlink()

        srtm_df_int = srtm_df[srtm_df.geometry.intersects(
            data.gw.geodataframe.to_crs(epsg=4326).geometry.values[0])]

        nedd = NASAEarthdataDownloader(username, key_file, code_file)

        hgt_files = []
        zip_paths = []

        for dfn in srtm_df_int.dataFile.values.tolist():

            zip_file = f"{out_dir}/NASADEM_HGT_{dfn.split('.')[0].lower()}.zip"

            nedd.download_srtm(dfn.split('.')[0].lower(), zip_file)

            src_zip = f"zip+file://{zip_file}!/{Path(zip_file).stem.split('_')[-1]}.hgt"

            hgt_files.append(Path(zip_file))
            zip_paths.append(src_zip)

        if len(zip_paths) == 1:
            zip_paths = zip_paths[0]
            mosaic = False
        else:
            mosaic = True

        with gw.open(zip_paths, mosaic=mosaic, chunks=chunks) as src:

            mean_elev = src.transpose('band', 'y', 'x')\
                                .mean().data\
                                .compute(num_workers=n_jobs)

        if delete_downloaded:

            for fn in hgt_files:
                fn.unlink()

        return mean_elev
Exemple #30
0
    def test_crs(self):

        with gw.open(l8_224078_20200518) as src:
            self.assertEqual(src.crs, '+init=epsg:32621')