Esempio n. 1
0
def check_crs(crs):

    """
    Checks a CRS instance

    Args:
        crs (``CRS`` | int | dict | str): The CRS instance.

    Returns:
        ``rasterio.crs.CRS``
    """

    if isinstance(crs, pyproj.crs.crs.CRS):
        dst_crs = CRS.from_proj4(crs.to_proj4())
    elif isinstance(crs, CRS):
        dst_crs = crs
    elif isinstance(crs, int):
        dst_crs = CRS.from_epsg(crs)
    elif isinstance(crs, dict):
        dst_crs = CRS.from_dict(crs)
    elif isinstance(crs, str):

        if crs.startswith('+proj'):
            dst_crs = CRS.from_proj4(crs)
        else:
            dst_crs = CRS.from_string(crs)

    else:
        logger.exception('  The CRS was not understood.')
        raise TypeError

    return dst_crs
def make_geotiff(grid_x, grid_y, points, data_to_grid,name,epsg_data,no_data):
    
    #grid the data. The linear grid help id nan's. 
    nan_grid = griddata(points, data_to_grid, (grid_x, grid_y), method='linear')
    data_grid = griddata(points, data_to_grid, (grid_x, grid_y), method='nearest')
    sum_data = np.sum([nan_grid*0,data_grid], axis=0)
    
    #set areas without data and with very large displacements to the no_data value
    a = np.isnan(sum_data)*no_data
    x_list = np.arange(0,sum_data.flatten().size,1)
    b1 = x_list[abs(sum_data.flatten()) > np.median(abs(data_to_grid))*5];
    b2 = x_list[a.flatten()==no_data];
    data_grid_flatten= data_grid.flatten()
    data_grid_flatten[b1]=no_data
    data_grid_flatten[b2]=no_data
    
    
    #reshape, as expected for geotiffs
    data_grid1= data_grid_flatten.reshape( data_grid.shape)
    data_grid1_ta=np.rot90(data_grid1)
    
    #create the affine transform 
    aff=Affine.translation(min(x)-window_compare/2, max(y)+window_compare/2)*Affine.scale(window_compare,-window_compare)

    #coordinate system for geotiffs 
    a,b=data_grid1.shape
    epsg_code = 'epsg:'+str(epsg_data)
    c=CRS.from_dict(init=epsg_code)

    d = {'driver' : 'GTiff','dtype' : 'float64','nodata': no_data, 'width': a+1, 'height' : b+1,'count':1,'crs':c,'transform':aff}

    with rio.open(name, 'w', **d) as outf:
        outf.write(data_grid1_ta, 1)
    return    
Esempio n. 3
0
    def _reproject_polygon(self, dst_crs):
        """
        Reproject polygon objects to destination projection.

        fiona transform geom object does not handle shapely objects but
        "GeoJSON-like" dictionaries instead.
        """
        # get epsg
        src_crs = self.src_crs
        if isinstance(src_crs, int):
            # assume epsg number
            epsg = src_crs
            src_crs = CRS.from_epsg(epsg)
        elif isinstance(src_crs, dict):
            src_crs = CRS.from_dict(**src_crs)
            epsg = src_crs.to_epsg()
        elif isinstance(src_crs, CRS):
            epsg = src_crs.to_epsg()
        else:
            src_crs = CRS.from_string(src_crs)
            epsg = src_crs.to_epsg()

        if dst_crs.to_epsg() != epsg:
            if isinstance(self.polygon, MultiPolygon):
                coords = [
                    list(geom.exterior.coords) for geom in self.polygon.geoms
                ]
                type_str = 'MultiPolygon'
                transformed_poly = transform_geom(src_crs, dst_crs, {
                    'type': type_str,
                    'coordinates': coords
                })
                # convert all polygon features back to shapely polygons
                polygons = [
                    Polygon(transformed_poly[i]["coordinates"][0])
                    for i in range(len(transformed_poly))
                ]
                # join all shapely polygons to a single layer
                self.polygon = unary_union(MultiPolygon(polygons))
            else:
                coords = [list(self.polygon.exterior.coords)]
                type_str = 'Polygon'
                transformed_poly = transform_geom(src_crs, dst_crs, {
                    'type': type_str,
                    'coordinates': coords
                })
                self.polygon = Polygon(transformed_poly['coordinates'][0])
Esempio n. 4
0
    def test_areas_rasterio(self):
        """Test all areas have valid projections with rasterio."""
        try:
            from rasterio.crs import CRS
        except ImportError:
            return unittest.skip("Missing rasterio dependency")
        if not hasattr(CRS, 'from_dict'):
            return unittest.skip("RasterIO 1.0+ required")

        from pyresample import parse_area_file
        from satpy.resample import get_area_file
        all_areas = parse_area_file(get_area_file())
        for area_obj in all_areas:
            if getattr(area_obj, 'optimize_projection', False):
                # the PROJ.4 is known to not be valid on this DynamicAreaDef
                continue
            proj_dict = area_obj.proj_dict
            _ = CRS.from_dict(proj_dict)
Esempio n. 5
0
def get_profile(lon, lat, crs, size=SIZE):
    x, y = transform(Proj(init='epsg:4326'), Proj(init=crs), lon, lat)
    x, y = int(round(x)), int(round(y))
    xmin = x - HALF_SIZE
    ymin = y - HALF_SIZE
    return {
        'compress': 'lzw',
        'count': len(INPUT_BANDS),
        'crs': CRS.from_dict(init=crs),
        'driver': 'GTiff',
        'dtype': 'uint16',
        'height': SIZE,
        'interleave': 'pixel',
        'nodata': None,
        'tiled': False,
        'transform': Affine(RES, 0, xmin, 0, -RES, ymin),
        'width': SIZE
    }
Esempio n. 6
0
def check_crs(crs):

    """
    Checks a CRS instance

    Args:
        crs (``CRS`` | int | dict | str): The CRS instance.

    Returns:
        ``rasterio.crs.CRS``
    """

    import warnings

    with rio.Env():

        with warnings.catch_warnings():

            warnings.simplefilter('ignore', UserWarning)

            if isinstance(crs, pyproj.crs.crs.CRS):
                dst_crs = CRS.from_proj4(crs.to_proj4())
            elif isinstance(crs, CRS):
                dst_crs = crs
            elif isinstance(crs, int):
                dst_crs = CRS.from_epsg(crs)
            elif isinstance(crs, dict):
                dst_crs = CRS.from_dict(crs)
            elif isinstance(crs, str):

                if crs.startswith('+proj'):
                    dst_crs = CRS.from_proj4(crs)
                else:
                    dst_crs = CRS.from_string(crs.replace('+init=', ''))

            else:
                logger.exception('  The CRS was not understood.')
                raise TypeError

    return dst_crs
Esempio n. 7
0
    def test_areas_rasterio(self):
        """Test all areas have valid projections with rasterio."""
        try:
            from rasterio.crs import CRS
        except ImportError:
            return unittest.skip("Missing rasterio dependency")
        if not hasattr(CRS, 'from_dict'):
            return unittest.skip("RasterIO 1.0+ required")

        import numpy as np
        import xarray as xr
        from pyresample import parse_area_file
        from pyresample.geometry import SwathDefinition

        from satpy.resample import get_area_file

        lons = np.array([[0, 0.1, 0.2], [0.05, 0.15, 0.25]])
        lats = np.array([[0, 0.1, 0.2], [0.05, 0.15, 0.25]])
        lons = xr.DataArray(lons)
        lats = xr.DataArray(lats)
        swath_def = SwathDefinition(lons, lats)
        all_areas = parse_area_file(get_area_file())
        for area_obj in all_areas:
            if hasattr(area_obj, 'freeze'):
                try:
                    area_obj = area_obj.freeze(lonslats=swath_def)
                except RuntimeError:
                    # we didn't provide enough info to freeze, hard to guess
                    # in a generic test so just skip this area
                    continue
            proj_dict = area_obj.proj_dict
            if proj_dict.get('proj') in ('ob_tran', 'nsper') and \
                    'wktext' not in proj_dict:
                # FIXME: rasterio doesn't understand ob_tran unless +wktext
                # See: https://github.com/pyproj4/pyproj/issues/357
                # pyproj 2.0+ seems to drop wktext from PROJ dict
                continue
            _ = CRS.from_dict(proj_dict)
Esempio n. 8
0
 def test_meta_of_rasterio(self):
     expected_general = {
         'driver': 'GTiff',
         'dtype': 'uint16',
         'nodata': None,
         'width': 9,
         'height': 8,
         'count': 7,
         'crs': CRS.from_dict(init='epsg:32618'),
     }
     self.assertEqual(expected_general['driver'],
                      self.landsat5.meta['driver'])
     self.assertEqual(expected_general['dtype'],
                      self.landsat5.meta['dtype'])
     self.assertEqual(expected_general['nodata'],
                      self.landsat5.meta['nodata'])
     self.assertEqual(expected_general['width'],
                      self.landsat5.meta['width'])
     self.assertEqual(expected_general["height"],
                      self.landsat5.meta["height"])
     self.assertEqual(expected_general["count"],
                      self.landsat5.meta["count"])
     self.assertEqual(expected_general["crs"], self.landsat5.meta["crs"])
Esempio n. 9
0
def main():
    #-- Read the system arguments listed after the program
    long_options = ['DIR=', 'FILTER=', 'DX=', 'DY=']
    optlist, arglist = getopt.getopt(sys.argv[1:], 'D:F:X:Y:', long_options)

    #-- Set default settings
    ddir = os.path.join(os.path.expanduser('~'),'GL_learning_data',\
     'geocoded_v1','stitched.dir',\
     'atrous_32init_drop0.2_customLossR727.dir','shapefiles.dir')
    FILTER = 6000
    dx = 100.
    dy = 100.
    for opt, arg in optlist:
        if opt in ("-D", "--DIR"):
            ddir = os.path.expanduser(arg)
        elif opt in ("-F", "--FILTER"):
            if arg not in ['NONE', 'none', 'None', 'N', 'n', 0]:
                FILTER = float(arg)
        elif opt in ('-X', '--DX'):
            dx = float(arg)
        elif opt in ('-Y', '--DY'):
            dy = float(arg)

    flt_str = '_%.1fkm' % (FILTER / 1000)

    #-- Get list of files
    fileList = os.listdir(ddir)
    pred_list = [
        f for f in fileList
        if (f.endswith('%s.shp' % flt_str) and ('ERR' not in f))
    ]
    print(pred_list)
    print(ddir)
    #-- read one error scene to get projection
    gdf = gpd.read_file(os.path.join(ddir, pred_list[0]))
    crs_wkt = CRS.from_dict(gdf.crs).to_wkt()

    #-- go through shapefiles and shift them by half a pixel
    for f in pred_list:
        gdf = gpd.read_file(os.path.join(ddir, f))
        for g in range(len(gdf['geometry'])):
            #-- get coordinates
            x, y = gdf['geometry'][g].coords.xy
            #-- convert to numpy array
            x = np.array(x)
            y = np.array(y)
            #-- add offset
            x -= dx / 2
            y += dy / 2
            #-- make new linestring
            ll = LineString(zip(x, y))
            #-- replace original geometry
            gdf['geometry'][g] = ll
        try:
            #-- save update geodataframe to file
            gdf.to_file(os.path.join(ddir, f),
                        driver='ESRI Shapefile',
                        crs_wkt=crs_wkt)
        except:
            print('empty file.')
            print(f)
            pass
Esempio n. 10
0
# ROI information
dir_location = os.path.join(dir_data, location)
if not os.path.exists(dir_location):
    os.mkdir(dir_location)
x_min, y_min, x_max, y_max = df_communities.loc[df_communities["NAAM"] == location, "geometry"].to_numpy()[0].bounds
x_min, y_min = np.floor([x_min, y_min])
x_max, y_max = np.ceil([x_max, y_max])
x_max += (s1_resolution - ((x_max - x_min) % s1_resolution))
y_max += (s1_resolution - ((y_max - y_min) % s1_resolution))
roi_extent = (x_min, y_min, x_max, y_max)
roi_extent_wgs = transformer_utm_wgs.transform(x_min, y_min) + transformer_utm_wgs.transform(x_max, y_max)
roi_shape = (int((x_max - x_min) / s1_resolution), int((y_max - y_min) / s1_resolution))  # width, height
roi_transform = rasterio.transform.from_bounds(*roi_extent, *roi_shape)
roi_metadata = {
    "crs": CRS.from_dict(init=utm),
    "transform": roi_transform,
    "width": roi_shape[0],
    "height": roi_shape[1]
}
pixel_resolution_x = roi_transform[0]
pixel_resolution_y = -roi_transform[4]

# Tree & PW presence data
print("{} - Gathering LC data...".format(dt.now()))
trees_filename = os.path.join(dir_location, "Trees.tif")
if not os.path.exists(trees_filename):
    trees = caf.mosaic_tiles(dir_lc, *roi_extent, roi_transform, *roi_shape, utm, "int8", nd_pres, query_string="Trees",
                             kbl_dir=dir_kbl, kbl_scale=0, resampling="max", fill_nodata=False,
                             mosaic_filename=trees_filename)
else:
Esempio n. 11
0
    def _parse_parameter_file(self):
        self.num_particles = {}
        with rasterio.open(self.parameter_filename, "r") as f:
            for key in f.meta.keys():
                v = f.meta[key]
                self.parameters[key] = v
            self.parameters["res"] = f.res
            self.parameters["profile"] = f.profile
        self.current_time = 0

        # overwrite crs if one is provided by user
        if not (self.crs is None):
            # make sure user provided CRS is valid CRS object
            if not isinstance(self.crs, CRS):
                if isinstance(self.crs, int):
                    # assume epsg number
                    self.crs = CRS.from_epsg(self.crs)
                elif isinstance(self.crs, dict):
                    self.crs = CRS.from_dict(**self.crs)
                else:
                    self.crs = CRS.from_string(self.crs)

            # get reprojected transform
            left_edge = self.parameters["transform"] * (0, 0)
            right_edge = self.parameters["transform"] * (
                self.parameters["width"], self.parameters["height"])
            transform, width, height = warp.calculate_default_transform(
                self.parameters["crs"],
                self.crs,
                self.parameters["width"],
                self.parameters["height"],
                left=left_edge[0],
                bottom=left_edge[1],
                right=right_edge[0],
                top=right_edge[1],
                # resolution=self.parameters["transform"][0]
                dst_width=self.parameters["width"],
                dst_height=self.parameters["height"]
            )  # current solution can create rectangular pixels
            # xs, ys = warp.transform(
            #     self.parameters["crs"],
            #     dst_crs,
            #     [left_edge[0], right_edge[0]],
            #     [left_edge[1], right_edge[1]],
            #     zs=None
            # )
            # update parameters
            self.parameters["res"] = (transform[0], -transform[4])
            self.parameters["crs"] = self.crs
            self.parameters["transform"] = transform
            self.parameters["width"] = width
            self.parameters["height"] = height
        else:
            # if no crs has be provided replace None with base image CRS
            self.crs = self.parameters["crs"]

        # get units and conversion factor to metres
        self.parameters["units"] = self.parameters["crs"].linear_units
        # for non-projected crs this is unknown
        if self.parameters["units"] == 'unknown':
            mylog.warning(f"Dataset CRS {self.parameters['crs']} "
                          "units are 'unknown'. Using meters.")
            self.parameters["units"] = 'm'  # just a place holder
        else:
            mylog.info(f"Dataset CRS {self.parameters['crs']} "
                       f"units are '{self.parameters['units']}'. ")
        # set domain
        width = self.parameters["width"]
        height = self.parameters["height"]
        transform = self.parameters["transform"]
        self.dimensionality = 3
        self.domain_dimensions = np.array([width, height, 1], dtype=np.int32)

        rast_left = np.concatenate([transform * (0, 0), [0]])
        rast_right = np.concatenate([transform * (width, height), [1]])
        # save dimensions that need to be flipped
        self._flip_axes = np.where(rast_left > rast_right)[0]
        self.domain_left_edge = self.arr(
            np.min([rast_left, rast_right], axis=0), self.parameters["units"])
        self.domain_right_edge = self.arr(
            np.max([rast_left, rast_right], axis=0), self.parameters["units"])
        self.resolution = self.arr(self.parameters["res"],
                                   self.parameters["units"])
def read_raster(file_name, band=[1], src_crs=None, window=False, geometry=False,
                dst_crs=False, transform=None, width=None, height=None,
                resampling=Resampling.nearest):
    """ Read raster of bands and set 0 values to the masked ones. Each
    band is an event. Select region using window or geometry. Reproject
    input by proving dst_crs and/or (transform, width, height). Returns matrix
    in 2d: band x coordinates in 1d (evtl. reshape to band x height x width)

    Parameters:
        file_name (str): name of the file
        band (list(int), optional): band number to read. Default: 1
        window (rasterio.windows.Window, optional): window to read
        geometry (shapely.geometry, optional): consider pixels only in shape
        dst_crs (crs, optional): reproject to given crs
        transform (rasterio.Affine): affine transformation to apply
        wdith (float): number of lons for transform
        height (float): number of lats for transform
        resampling (rasterio.warp,.Resampling optional): resampling
            function used for reprojection to dst_crs

    Returns:
        dict (meta), np.array (band x coordinates_in_1d)
    """
    LOGGER.info('Reading %s', file_name)
    if os.path.splitext(file_name)[1] == '.gz':
        file_name = '/vsigzip/' + file_name
    with rasterio.Env():
        with rasterio.open(file_name, 'r') as src:
            if src_crs is None:
                src_meta = CRS.from_dict(DEF_CRS) if not src.crs else src.crs
            else:
                src_meta = src_crs
            if dst_crs or transform:
                LOGGER.debug('Reprojecting ...')
                if not dst_crs:
                    dst_crs = src_meta
                if not transform:
                    transform, width, height = calculate_default_transform(\
                        src_meta, dst_crs, src.width, src.height, *src.bounds)
                dst_meta = src.meta.copy()
                dst_meta.update({'crs': dst_crs,
                                 'transform': transform,
                                 'width': width,
                                 'height': height
                                })
                kwargs = {}
                if src.meta['nodata']:
                    kwargs['src_nodata'] = src.meta['nodata']
                    kwargs['dst_nodata'] = src.meta['nodata']
                intensity = np.zeros((len(band), height, width))
                for idx_band, i_band in enumerate(band):
                    reproject(source=src.read(i_band),
                              destination=intensity[idx_band, :],
                              src_transform=src.transform,
                              src_crs=src_meta,
                              dst_transform=transform,
                              dst_crs=dst_crs,
                              resampling=resampling,
                              **kwargs)
                    if dst_meta['nodata'] and np.isnan(dst_meta['nodata']):
                        intensity[idx_band, :][np.isnan(intensity[idx_band, :])] = 0
                    else:
                        intensity[idx_band, :][intensity[idx_band, :] == dst_meta['nodata']] = 0
                meta = dst_meta
                return meta, intensity.reshape((len(band), meta['height']*meta['width']))

            meta = src.meta.copy()
            if geometry:
                inten, mask_trans = mask(src, geometry, crop=True, indexes=band)
                if meta['nodata'] and np.isnan(meta['nodata']):
                    inten[np.isnan(inten)] = 0
                else:
                    inten[inten == meta['nodata']] = 0
                meta.update({"height": inten.shape[1],
                             "width": inten.shape[2],
                             "transform": mask_trans})
            else:
                masked_array = src.read(band, window=window, masked=True)
                inten = masked_array.data
                inten[masked_array.mask] = 0
                if window:
                    meta.update({"height": window.height, \
                        "width": window.width, \
                        "transform": rasterio.windows.transform(window, src.transform)})
            if not meta['crs']:
                meta['crs'] = CRS.from_dict(DEF_CRS)
            intensity = inten[range(len(band)), :]
            return meta, intensity.reshape((len(band), meta['height']*meta['width']))
Esempio n. 13
0
def test_issue1620():
    """Different forms of EPSG:3857 are equal"""
    assert CRS.from_wkt(
        'PROJCS["WGS 84 / Pseudo-Mercator",GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4326"]],PROJECTION["Mercator_1SP"],PARAMETER["central_meridian",0],PARAMETER["scale_factor",1],PARAMETER["false_easting",0],PARAMETER["false_northing",0],UNIT["metre",1,AUTHORITY["EPSG","9001"]],AXIS["X",EAST],AXIS["Y",NORTH],EXTENSION["PROJ4","+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs"],AUTHORITY["EPSG","3857"]]'
    ) == CRS.from_dict(init='epsg:3857')
Esempio n. 14
0
def test_issue1620():
    """Different forms of EPSG:3857 are equal"""
    assert CRS.from_wkt('PROJCS["WGS 84 / Pseudo-Mercator",GEOGCS["WGS 84",DATUM["WGS_1984",SPHEROID["WGS 84",6378137,298.257223563,AUTHORITY["EPSG","7030"]],AUTHORITY["EPSG","6326"]],PRIMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","4326"]],PROJECTION["Mercator_1SP"],PARAMETER["central_meridian",0],PARAMETER["scale_factor",1],PARAMETER["false_easting",0],PARAMETER["false_northing",0],UNIT["metre",1,AUTHORITY["EPSG","9001"]],AXIS["X",EAST],AXIS["Y",NORTH],EXTENSION["PROJ4","+proj=merc +a=6378137 +b=6378137 +lat_ts=0.0 +lon_0=0.0 +x_0=0.0 +y_0=0 +k=1.0 +units=m +nadgrids=@null +wktext +no_defs"],AUTHORITY["EPSG","3857"]]') == CRS.from_dict(init='epsg:3857')
Esempio n. 15
0
                            len(col_dan_1km_ind), len(row_dan_1km_ind))
kwargs_1km_sub = {
    'driver':
    'GTiff',
    'dtype':
    'float32',
    'nodata':
    0.0,
    'width':
    len(lon_world_ease_1km),
    'height':
    len(lat_world_ease_1km),
    'count':
    1,
    'crs':
    CRS.from_dict(init='epsg:6933'),
    'transform':
    Affine(1000.89502334956, 0.0, -17367530.44516138, 0.0, -1000.89502334956,
           7314540.79258289)
}
smap_sm_dan_1km_output = sub_n_reproj(smap_sm_dan_1km_sub, kwargs_1km_sub,
                                      sub_window_dan_1km, output_crs)

masked_ds_dan_1km, mask_transform_ds_dan_1km = mask(
    dataset=smap_sm_dan_1km_output, shapes=crop_shape, crop=True)
masked_ds_dan_1km[np.where(masked_ds_dan_1km == 0)] = np.nan

sub_window_dan_9km = Window(col_dan_9km_ind[0], row_dan_9km_ind[0],
                            len(col_dan_9km_ind), len(row_dan_9km_ind))
kwargs_9km_sub = {
    'driver':
import re

import torch
from torch.autograd import Variable
import torch.backends.cudnn as cudnn
import torch.nn as nn

from util.visualizer import Visualizer
import networks.networks as networks

from .mtl_test import MTL_Test as GenericTestModel

from rasterio.crs import CRS
from rasterio.transform import Affine
GEN_META = {'driver': 'GTiff', 'dtype': 'float32', 'nodata': None, 'width': 3816, 'height': 2550, 'count': 1, 'transform': Affine(1.0, 0.0, 0.0, 0.0, 1.0, 0.0), 'crs': CRS.from_dict(init='epsg:26915')}


class TestModel(GenericTestModel):
    def initialize(self, opt):
        GenericTestModel.initialize(self, opt)
        self.get_color_palette()

    def name(self):
        return 'Raster Test Model'

    def get_color_palette(self):
        if self.opt.dataset_name == 'dfc':
            self.opt.color_palette = [  
                                        [0, 0, 0], [0, 205, 0], [127, 255, 0], [46, 139, 87], [0, 139, 0], [0, 70, 0], [160, 82, 45], [0, 255, 255], [255, 255, 255], [216, 191, 216], [255, 0, 0], [170, 160, 150], [128, 128, 128], [160, 0, 0], [80, 0, 0], [232, 161, 24], [255, 255, 0], [238, 154, 0], [255, 0, 255], [0, 0, 255], [176, 196, 222]
                                        ]
Esempio n. 17
0
from util.visualizer import Visualizer
import networks.networks as networks

from .mtl_test import MTL_Test as GenericTestModel

from rasterio.crs import CRS
from rasterio.transform import Affine

OUT_META_SEM = [{
    'driver': 'GTiff',
    'dtype': 'uint8',
    'nodata': None,
    'width': 1192,
    'height': 1202,
    'count': 1,
    'crs': CRS.from_dict(init='epsg:26915'),
    'transform': Affine(0.5, 0.0, 271460.0, 0.0, -0.5, 3290290.0)
}, {
    'driver': 'GTiff',
    'dtype': 'uint8',
    'nodata': None,
    'width': 1192,
    'height': 1202,
    'count': 1,
    'crs': CRS.from_dict(init='epsg:26915'),
    'transform': Affine(0.5, 0.0, 271460.0, 0.0, -0.5, 3290891.0)
}, {
    'driver': 'GTiff',
    'dtype': 'uint8',
    'nodata': None,
    'width': 1192,
Esempio n. 18
0
def warp(filename,
         resampling='nearest',
         bounds=None,
         crs=None,
         res=None,
         nodata=0,
         warp_mem_limit=512,
         num_threads=1,
         tap=False):
    """
    Warps an image to a VRT object

    Args:
        filename (str): The input file name.
        resampling (Optional[str]): The resampling method. Choices are ['average', 'bilinear', 'cubic',
            'cubic_spline', 'gauss', 'lanczos', 'max', 'med', 'min', 'mode', 'nearest'].
        bounds (Optional[tuple]): The extent bounds to warp to.
        crs (Optional[object]): The CRS to warp to.
        res (Optional[tuple]): The cell resolution to warp to.
        nodata (Optional[int or float]): The 'no data' value.
        warp_mem_limit (Optional[int]): The memory limit (in MB) for the ``rasterio.vrt.WarpedVRT`` function.
        num_threads (Optional[int]): The number of warp worker threads.
        tap (Optional[bool]): Whether to target align pixels.

    Returns:
        ``rasterio.vrt.WarpedVRT``
    """

    with rio.open(filename) as src:

        if res:
            dst_res = res
        else:
            dst_res = src.res

        if crs:

            if isinstance(crs, CRS):
                dst_crs = crs
            elif isinstance(crs, int):
                dst_crs = CRS.from_epsg(crs)
            elif isinstance(crs, dict):
                dst_crs = CRS.from_dict(crs)
            elif isinstance(crs, str):

                if crs.startswith('+proj'):
                    dst_crs = CRS.from_proj4(crs)
                else:
                    dst_crs = CRS.from_string(crs)

            else:
                logger.exception('  The CRS was not understood.')

        else:
            dst_crs = src.crs

        dst_transform, dst_width, dst_height = calculate_default_transform(
            src.crs,
            dst_crs,
            src.width,
            src.height,
            left=src.bounds.left,
            bottom=src.bounds.bottom,
            right=src.bounds.right,
            top=src.bounds.top,
            resolution=dst_res)

        # Check if the data need to be subset
        if bounds and (bounds != src.bounds):

            if isinstance(bounds, str):

                if bounds.startswith('BoundingBox'):

                    bounds_str = bounds.replace('BoundingBox(', '').split(',')

                    for str_ in bounds_str:

                        if str_.strip().startswith('left='):
                            left_coord = float(
                                str_.strip().split('=')[1].replace(')', ''))
                        elif str_.strip().startswith('bottom='):
                            bottom_coord = float(
                                str_.strip().split('=')[1].replace(')', ''))
                        elif str_.strip().startswith('right='):
                            right_coord = float(
                                str_.strip().split('=')[1].replace(')', ''))
                        elif str_.strip().startswith('top='):
                            top_coord = float(
                                str_.strip().split('=')[1].replace(')', ''))

                    bounds = BoundingBox(left=left_coord,
                                         bottom=bottom_coord,
                                         right=right_coord,
                                         top=top_coord)

                else:
                    logger.exception('  The bounds were not accepted.')

            left, bottom, right, top = bounds

            # Keep the CRS but subset the data
            dst_transform, dst_width, dst_height = calculate_default_transform(
                dst_crs,
                dst_crs,
                dst_width,
                dst_height,
                left=left,
                bottom=bottom,
                right=right,
                top=top,
                resolution=dst_res)

            dst_width = int((right - left) / dst_res[0])
            dst_height = int((top - bottom) / dst_res[1])

        else:
            bounds = src.bounds

        # Do not warp if all the key metadata match the reference information
        if (src.bounds == bounds) and (src.res == dst_res) and (
                src.crs == dst_crs) and (src.width
                                         == dst_width) and (src.height
                                                            == dst_height):
            output = filename
        else:

            if tap:

                # Align the cells
                dst_transform, dst_width, dst_height = aligned_target(
                    dst_transform, dst_width, dst_height, dst_res)

            vrt_options = {
                'resampling': getattr(Resampling, resampling),
                'crs': dst_crs,
                'transform': dst_transform,
                'height': dst_height,
                'width': dst_width,
                'nodata': nodata,
                'warp_mem_limit': warp_mem_limit,
                'warp_extras': {
                    'multi': True,
                    'warp_option': 'NUM_THREADS={:d}'.format(num_threads)
                }
            }

            with WarpedVRT(src, **vrt_options) as vrt:
                output = vrt

    return output
Esempio n. 19
0
    def write_raster(
        self,
        output_filename: PathLike,
        variable: str,
        time: datetime,
        fill_value=LEAFLET_NODATA_VALUE,
        driver: str = 'GTiff',
        crop: bool = True,
    ):
        """
        Writes interpolated raster of given variable to output path.
        :param output_filename: path of raster file to create
        :param variable: name of variable
        :param time: time from which to retrieve data
        :param fill_value: desired fill value of output
        :param driver: strings of valid GDAL driver (currently one of 'GTiff', 'GPKG', or 'AAIGrid')
        :param crop: whether to crop to study area extent
        """

        if not isinstance(output_filename, Path):
            output_filename = Path(output_filename)

        output_data = self.data(variable, time, crop).values

        if output_data is not None:
            if crop:
                transform = self.study_area_transform
            else:
                transform = self.global_grid_transform

            gdal_args = {
                'transform':
                transform,
                'height':
                output_data.shape[0],
                'width':
                output_data.shape[1],
                'count':
                1,
                'dtype':
                rasterio.float32,
                'crs':
                CRS.from_dict(OUTPUT_CRS),
                'nodata':
                numpy.array([fill_value]).astype(output_data.dtype).item(),
            }

            if driver == 'AAIGrid':
                file_extension = 'asc'
                gdal_args.update({'FORCE_CELLSIZE': 'YES'})
            elif driver == 'GPKG':
                file_extension = 'gpkg'
            else:
                file_extension = 'tiff'
                gdal_args.update(TIFF_CREATION_OPTIONS)

            output_filename = f'{output_filename.stem}.{file_extension}'

            LOGGER.info(f'Writing {output_filename}')
            with rasterio.open(output_filename, 'w', driver,
                               **gdal_args) as output_raster:
                output_raster.write(output_data, 1)
                if driver == 'GTiff':
                    output_raster.build_overviews(
                        PyOFS.overview_levels(output_data.shape),
                        Resampling['average'])
                    output_raster.update_tags(ns='rio_overview',
                                              resampling='average')
Esempio n. 20
0
    def write_rasters(
        self,
        output_dir: PathLike,
        variables: list,
        time: datetime,
        filename_prefix: str = None,
        filename_suffix: str = None,
        fill_value=LEAFLET_NODATA_VALUE,
        driver: str = 'GTiff',
        crop: bool = True,
    ):
        """
        Write averaged raster data of given variables to given output directory.
        :param output_dir: path to directory
        :param variables: variable names to use
        :param time: time from which to retrieve data
        :param filename_prefix: prefix for filenames
        :param filename_suffix: suffix for filenames
        :param fill_value: desired fill value of output
        :param driver: strings of valid GDAL driver (currently one of 'GTiff', 'GPKG', or 'AAIGrid')
        :param crop: whether to crop to study area extent
        """

        if not isinstance(output_dir, Path):
            output_dir = Path(output_dir)

        if variables is None:
            variables = DATA_VARIABLES[self.source]

        if filename_prefix is None:
            filename_prefix = 'rtofs'
        filename_suffix = f'_{filename_suffix}' if filename_suffix is not None else ''

        if self.time_interval == 'daily':
            time = time.replace(hour=0, minute=0, second=0, microsecond=0)

        time_delta = int((time - self.model_time) / timedelta(days=1))
        direction = 'forecast' if time_delta >= 0 else 'nowcast'
        time_delta_string = f'{direction[0]}{abs(time_delta) + 1 if direction == "forecast" else abs(time_delta):03}'

        variable_means = {}
        for variable in variables:
            if variable not in ['dir', 'mag']:
                try:
                    variable_means[variable] = self.data(variable, time, crop)
                except KeyError:
                    LOGGER.warning(
                        f'variable "{variable}" not found in RTOFS dataset')
                except Exception as error:
                    LOGGER.warning(error)

        variable_means = {
            variable: variable_mean.values
            for variable, variable_mean in variable_means.items()
            if variable_mean is not None
        }

        if 'dir' in variables or 'mag' in variables:
            u_name = 'ssu'
            v_name = 'ssv'

            if u_name not in variable_means:
                u_data = self.data(u_name, time, crop)
                u_data = u_data.values if u_data is not None else None
            else:
                u_data = variable_means[u_name]

            if v_name not in variable_means:
                v_data = self.data(v_name, time, crop)
                v_data = v_data.values if v_data is not None else None
            else:
                v_data = variable_means[v_name]

            if 'anim' in filename_suffix:
                variable_means['dir'] = u_data
                variable_means['mag'] = v_data

            else:
                # calculate direction and magnitude of vector in degrees (0-360) and in metres per second
                variable_means['dir'] = (numpy.arctan2(u_data, v_data) +
                                         numpy.pi) * (180 / numpy.pi)
                variable_means['mag'] = numpy.sqrt(u_data**2 + v_data**2)

        # write interpolated grids to raster files
        for variable, variable_mean in variable_means.items():
            if variable_mean is not None and variable_mean.size > 0:
                if crop:
                    transform = self.study_area_transform
                else:
                    transform = self.global_grid_transform

                if fill_value is not None:
                    variable_mean[numpy.isnan(variable_mean)] = fill_value

                gdal_args = {
                    'transform':
                    transform,
                    'height':
                    variable_mean.shape[0],
                    'width':
                    variable_mean.shape[1],
                    'count':
                    1,
                    'dtype':
                    rasterio.float32,
                    'crs':
                    CRS.from_dict(OUTPUT_CRS),
                    'nodata':
                    numpy.array([fill_value
                                 ]).astype(variable_mean.dtype).item(),
                }

                if driver == 'AAIGrid':
                    file_extension = 'asc'
                    gdal_args.update({'FORCE_CELLSIZE': 'YES'})
                elif driver == 'GPKG':
                    file_extension = 'gpkg'
                else:
                    file_extension = 'tiff'
                    gdal_args.update(TIFF_CREATION_OPTIONS)

                output_filename = f'{filename_prefix}_{variable}_{self.model_time:%Y%m%d}_{time_delta_string}{filename_suffix}.{file_extension}'
                output_filename = output_dir / output_filename

                LOGGER.info(f'Writing {output_filename}')
                with rasterio.open(output_filename, 'w', driver,
                                   **gdal_args) as output_raster:
                    output_raster.write(variable_mean, 1)
                    if driver == 'GTiff':
                        output_raster.build_overviews(
                            PyOFS.overview_levels(variable_mean.shape),
                            Resampling['average'])
                        output_raster.update_tags(ns='rio_overview',
                                                  resampling='average')
Esempio n. 21
0
def test_crs_from_json_dict():
    aeqd_crs = CRS(proj="aeqd", lon_0=-80, lat_0=40.5)
    assert CRS.from_dict(aeqd_crs.to_dict(projjson=True)) == aeqd_crs
Esempio n. 22
0
    def __init__(self, filename, ds=None, field_parameters=None, crs=None):
        validate_object(ds, Dataset)
        validate_object(field_parameters, dict)
        self.src_crs = crs
        if isinstance(filename, str):
            self.filename = filename

            # read shapefile with fiona
            with fiona.open(filename, "r") as shapefile:
                shapes_from_file = [
                    feature["geometry"] for feature in shapefile
                ]
                self.src_crs = CRS.from_dict(**shapefile.crs)  # shapefile crs

            # save number of polygons
            self._number_features = len(shapes_from_file)

            # reproject to datasets crs
            for i in range(self._number_features):
                shapes_from_file[i] = transform_geom(
                    f'EPSG:{self.src_crs.to_epsg()}',
                    f'EPSG:{ds.parameters["crs"].to_epsg()}',
                    shapes_from_file[i])
            # convert all polygon features in shapefile to list of shapely polygons
            polygons = [
                Polygon(shapes_from_file[i]["coordinates"][0])
                for i in range(self._number_features)
            ]
            # fix invalid MultiPolygons
            m = MultiPolygon(polygons)
            # join all shapely polygons to a single layer
            self.polygon = unary_union(m)

        elif isinstance(filename, Polygon):
            # only one polygon
            self._number_features = 1
            self.polygon = filename
            if not (self.src_crs is None):
                self._reproject_polygon(ds.parameters['crs'])

        elif isinstance(filename, MultiPolygon):
            # only one polygon
            self._number_features = len(filename.geoms)
            self.polygon = unary_union(filename)
            if not (self.src_crs is None):
                self._reproject_polygon(ds.parameters['crs'])

        elif isinstance(filename, list):
            # assume list of shapely polygons
            self._number_features = len(filename)
            # fix invalid MultiPolygons
            m = MultiPolygon(filename)
            # join all shapely polygons to a single layer
            self.polygon = unary_union(m)
            if not (self.src_crs is None):
                self._reproject_polygon(ds.parameters['crs'])

        mylog.info(
            f"Number of features in poly object: {self._number_features}")

        # define coordinates of center
        self.center = [
            self.polygon.centroid.coords.xy[0][0],
            self.polygon.centroid.coords.xy[1][0],
        ]

        data_source = None
        super().__init__(self.center, ds, field_parameters, data_source)
Esempio n. 23
0
    def prepare_points(self,
                       data,
                       aoi,
                       frac=1.0,
                       all_touched=False,
                       id_column='id',
                       mask=None,
                       n_jobs=8,
                       verbose=0):

        if isinstance(aoi, gpd.GeoDataFrame):
            df = aoi
        else:

            if isinstance(aoi, str):

                if not os.path.isfile(aoi):
                    logger.exception('  The AOI file does not exist.')

                df = gpd.read_file(aoi)

            else:
                logger.exception(
                    '  The AOI must be a vector file or a GeoDataFrame.')

        # Re-project the data to match the image CRS
        if isinstance(df.crs, str):

            if df.crs.lower().startswith('+proj'):

                if data.crs != df.crs:
                    df = df.to_crs(data.crs)

        elif isinstance(df.crs, int):

            if data.crs != CRS.from_epsg(df.crs).to_proj4():
                df = df.to_crs(data.crs)

        else:

            if data.crs != CRS.from_dict(df.crs).to_proj4():
                df = df.to_crs(data.crs)

        if verbose > 0:
            logger.info('  Checking geometry validity ...')

        # Ensure all geometry is valid
        df = df[df['geometry'].apply(lambda x_: x_ is not None)]

        if verbose > 0:
            logger.info('  Checking geometry extent ...')

        # Remove data outside of the image bounds
        if type(df.iloc[0].geometry) == Polygon:

            df = gpd.overlay(df,
                             gpd.GeoDataFrame(data=[0],
                                              geometry=[data.gw.meta.geometry],
                                              crs=df.crs),
                             how='intersection')

        else:

            # Clip points to the image bounds
            df = df[df.geometry.intersects(data.gw.unary_union)]

        if isinstance(mask, Polygon) or isinstance(mask, gpd.GeoDataFrame):

            if isinstance(mask, gpd.GeoDataFrame):

                if CRS.from_dict(mask.crs).to_proj4() != CRS.from_dict(
                        df.crs).to_proj4():
                    mask = mask.to_crs(df.crs)

            if verbose > 0:
                logger.info('  Clipping geometry ...')

            df = df[df.within(mask)]

            if df.empty:
                logger.exception(
                    '  No geometry intersects the user-provided mask.')

        # Subset the DataArray
        # minx, miny, maxx, maxy = df.total_bounds
        #
        # obj_subset = self._obj.gw.subset(left=float(minx)-self._obj.res[0],
        #                                  top=float(maxy)+self._obj.res[0],
        #                                  right=float(maxx)+self._obj.res[0],
        #                                  bottom=float(miny)-self._obj.res[0])

        # Convert polygons to points
        if type(df.iloc[0].geometry) == Polygon:

            if verbose > 0:
                logger.info('  Converting polygons to points ...')

            df = self.polygons_to_points(data,
                                         df,
                                         frac=frac,
                                         all_touched=all_touched,
                                         id_column=id_column,
                                         n_jobs=n_jobs)

        # Ensure a unique index
        df.index = list(range(0, df.shape[0]))

        return df
Esempio n. 24
0
# Subplot maps
# Load in watershed shapefile boundaries
shapefile_dan = fiona.open(path_shp_dan + '/' + shp_dan_file, 'r')
crop_shape_dan = [feature["geometry"] for feature in shapefile_dan]
shp_dan_extent = list(shapefile_dan.bounds)

output_crs = 'EPSG:4326'

# Subset and reproject the amsr2 SM data at watershed
# 1 km
masked_ds_dan_1km_all = []
for n in range(amsr2_1km_data_stack.shape[0]):
    sub_window_dan_1km = Window(col_dan_1km_ind[0], row_dan_1km_ind[0], len(col_dan_1km_ind), len(row_dan_1km_ind))
    kwargs_1km_sub = {'driver': 'GTiff', 'dtype': 'float32', 'nodata': 0.0, 'width': len(lon_world_ease_1km),
                      'height': len(lat_world_ease_1km), 'count': 1, 'crs': CRS.from_dict(init='epsg:6933'),
                      'transform': Affine(1000.89502334956, 0.0, -17367530.44516138, 0.0, -1000.89502334956, 7314540.79258289)}
    amsr2_sm_dan_1km_output = sub_n_reproj(amsr2_1km_data_stack[n, :, :], kwargs_1km_sub, sub_window_dan_1km, output_crs)

    masked_ds_dan_1km, mask_transform_ds_dan_1km = mask(dataset=amsr2_sm_dan_1km_output, shapes=crop_shape_dan, crop=True)
    masked_ds_dan_1km[np.where(masked_ds_dan_1km == 0)] = np.nan
    masked_ds_dan_1km = masked_ds_dan_1km.squeeze()

    masked_ds_dan_1km_all.append(masked_ds_dan_1km)

masked_ds_dan_1km_all = np.asarray(masked_ds_dan_1km_all)


# 9 km
masked_ds_dan_9km_all = []
for n in range(amsr2_9km_data_stack.shape[0]):
Esempio n. 25
0
def test_equality_from_dict(epsg_code):
    assert CRS.from_dict(init='epsg:{}'.format(epsg_code)) == CRS.from_dict(init='epsg:{}'.format(epsg_code))
Esempio n. 26
0
    def clip(self, data, df, query=None, mask_data=False, expand_by=0):
        """
        Clips a DataArray by vector polygon geometry

        Args:
            data (DataArray): The ``xarray.DataArray`` to subset.
            df (GeoDataFrame or str): The ``geopandas.GeoDataFrame`` or filename to clip to.
            query (Optional[str]): A query to apply to ``df``.
            mask_data (Optional[bool]): Whether to mask values outside of the ``df`` geometry envelope.
            expand_by (Optional[int]): Expand the clip array bounds by ``expand_by`` pixels on each side.

        Returns:
             ``xarray.DataArray``

        Examples:
            >>> import geowombat as gw
            >>>
            >>> with gw.open('image.tif') as ds:
            >>>     ds = gw.clip(ds, df, query="Id == 1")
            >>>
            >>> # or
            >>>
            >>> with gw.open('image.tif') as ds:
            >>>     ds = ds.gw.clip(df, query="Id == 1")
        """

        if isinstance(df, str) and os.path.isfile(df):
            df = gpd.read_file(df)

        if query:
            df = df.query(query)

        try:

            if data.crs.strip() != CRS.from_dict(df.crs).to_proj4().strip():

                # Re-project the DataFrame to match the image CRS
                df = df.to_crs(data.crs)

        except:

            if data.crs.strip() != CRS.from_proj4(df.crs).to_proj4().strip():
                df = df.to_crs(data.crs)

        row_chunks = data.gw.row_chunks
        col_chunks = data.gw.col_chunks

        left, bottom, right, top = df.total_bounds

        # Align the geometry array grid
        align_transform, align_width, align_height = align_bounds(
            left, bottom, right, top, data.res)

        # Get the new bounds
        new_left, new_bottom, new_right, new_top = array_bounds(
            align_height, align_width, align_transform)

        if expand_by > 0:

            new_left -= data.gw.cellx * expand_by
            new_bottom -= data.gw.celly * expand_by
            new_right += data.gw.cellx * expand_by
            new_top += data.gw.celly * expand_by

        # Subset the array
        data = self.subset(data,
                           left=new_left,
                           bottom=new_bottom,
                           right=new_right,
                           top=new_top)

        if mask_data:

            # Rasterize the geometry and store as a DataArray
            mask = xr.DataArray(data=da.from_array(
                features.rasterize(list(df.geometry.values),
                                   out_shape=(align_height, align_width),
                                   transform=align_transform,
                                   fill=0,
                                   out=None,
                                   all_touched=True,
                                   default_value=1,
                                   dtype='int32'),
                chunks=(row_chunks, col_chunks)),
                                dims=['y', 'x'],
                                coords={
                                    'y': data.y.values,
                                    'x': data.x.values
                                })

            # Return the clipped array
            return data.where(mask == 1)

        else:
            return data
Esempio n. 27
0
def test_equality_from_dict(epsg_code):
    assert CRS.from_dict(init='epsg:{}'.format(epsg_code)) == CRS.from_dict(
        init='epsg:{}'.format(epsg_code))
Esempio n. 28
0
    def mask(data, df, query=None, keep='in'):
        """
        Masks a DataArray by vector polygon geometry

        Args:
            data (DataArray): The ``xarray.DataArray`` to mask.
            df (GeoDataFrame or str): The ``geopandas.GeoDataFrame`` or filename to use for masking.
            query (Optional[str]): A query to apply to ``df``.
            keep (Optional[str]): If ``keep`` = 'in', mask values outside of the geometry (keep inside).
                Otherwise, if ``keep`` = 'out', mask values inside (keep outside).

        Returns:
             ``xarray.DataArray``

        Examples:
            >>> import geowombat as gw
            >>>
            >>> with gw.open('image.tif') as ds:
            >>>     ds = ds.gw.mask(df)
        """

        if isinstance(df, str) and os.path.isfile(df):
            df = gpd.read_file(df)

        if query:
            df = df.query(query)

        try:

            if data.crs.strip() != CRS.from_dict(df.crs).to_proj4().strip():

                # Re-project the DataFrame to match the image CRS
                df = df.to_crs(data.crs)

        except:

            if data.crs.strip() != CRS.from_proj4(df.crs).to_proj4().strip():
                df = df.to_crs(data.crs)

        # Rasterize the geometry and store as a DataArray
        mask = xr.DataArray(data=da.from_array(
            features.rasterize(list(df.geometry.values),
                               out_shape=(data.gw.nrows, data.gw.ncols),
                               transform=data.transform,
                               fill=0,
                               out=None,
                               all_touched=True,
                               default_value=1,
                               dtype='int32'),
            chunks=(data.gw.row_chunks, data.gw.col_chunks)),
                            dims=['y', 'x'],
                            coords={
                                'y': data.y.values,
                                'x': data.x.values
                            })

        # Return the masked array
        if keep == 'out':
            return data.where(mask != 1)
        else:
            return data.where(mask == 1)
Esempio n. 29
0
    def write_rasters(
        self,
        output_dir: PathLike,
        variables: Collection[str] = ('sst', 'sses'),
        filename_prefix: str = 'abi',
        fill_value: float = LEAFLET_NODATA_VALUE,
        driver: str = 'GTiff',
        correct_sses: bool = False,
    ):
        """
        Write ABI rasters to file using data from given variables.

        :param output_dir: path to output directory
        :param variables: variable names to write
        :param filename_prefix: prefix for output filenames
        :param fill_value: desired fill value of output
        :param driver: strings of valid GDAL driver (currently one of 'GTiff', 'GPKG', or 'AAIGrid')
        :param correct_sses: whether to subtract SSES bias from SST
        """

        if not isinstance(output_dir, Path):
            output_dir = Path(output_dir)

        for variable in variables:
            input_data = self.data(variable, correct_sses)

            if variable == 'sses':
                fill_value = 0

            if input_data is not None and not numpy.isnan(input_data).all():
                if fill_value is not None:
                    input_data[numpy.isnan(input_data)] = fill_value

                gdal_args = {
                    'height': input_data.shape[0],
                    'width': input_data.shape[1],
                    'count': 1,
                    'dtype': rasterio.float32,
                    'crs': CRS.from_dict(OUTPUT_CRS),
                    'transform': ABIDataset.study_area_transform,
                    'nodata': fill_value,
                }

                if driver == 'AAIGrid':
                    file_extension = 'asc'
                    gdal_args.update({'FORCE_CELLSIZE': 'YES'})
                elif driver == 'GPKG':
                    file_extension = 'gpkg'
                else:
                    file_extension = 'tiff'
                    gdal_args.update(TIFF_CREATION_OPTIONS)

                output_filename = output_dir / f'{filename_prefix}_{variable}.{file_extension}'

                # use rasterio to write to raster with GDAL args
                LOGGER.info(f'Writing to {output_filename}')
                with rasterio.open(output_filename, 'w', driver,
                                   **gdal_args) as output_raster:
                    output_raster.write(input_data, 1)
                    if driver == 'GTiff':
                        output_raster.build_overviews(
                            PyOFS.overview_levels(input_data.shape),
                            Resampling['average'])
                        output_raster.update_tags(ns='rio_overview',
                                                  resampling='average')
Esempio n. 30
0
def warp_to_transform(src_filename,
                      dst_transform,
                      dst_width,
                      dst_height,
                      dst_crs_init,
                      src_band=1,
                      return_nodata=False,
                      resampling="nearest"):
    """ 
    Warp content of src_filename to match transform
    
    Inputs
    src_filename: str
        path to source file
    dst_transform: rasterio transform
        destination transform
    dst_width: int
        destination width (no. of columns)
    dst_height: int
        destination height (no. of rows)
    dst_crs_init: str
        destination CRS (format "EPSG:code")
    src_band: int
        index of band to warp, starting from 1 (default = 1)
    return_nodata: bool
        whether to return no data value (default = False)
    resampling: str
        resampling mode, one of ["nearest", "average", "cubic", "bilinear", "min", "max"]
    Outputs
    dst_array: nd array
        warped array
    nd_value: float
        no data value warped array (onli if return_nodata = True)
    """
    if resampling == "nearest":
        resampling = Resampling.nearest
    elif resampling == "average":
        resampling = Resampling.average
    elif resampling == "cubic":
        resampling = Resampling.cubic
    elif resampling == "bilinear":
        resampling = Resampling.bilinear
    elif resampling == "min":
        resampling = Resampling.min
    elif resampling == "max":
        resampling = Resampling.max
    else:
        print(
            "Warning: Resampling method not recognized, switching to default 'nearest'"
        )
        resampling = Resampling.nearest
    if type(src_band) is list:
        num_bands = len(src_band)
    else:
        num_bands = 1
    with rasterio.open(src_filename) as src:
        if src.nodata is None:
            nd_value = 0
        else:
            nd_value = src.nodata
        if num_bands == 1:
            dst_array = np.ones(
                (dst_height, dst_width), dtype=src.meta["dtype"]) * nd_value
        else:
            dst_array = np.ones((num_bands, dst_height, dst_width),
                                dtype=src.meta["dtype"]) * nd_value
        warp.reproject(rasterio.band(src, src_band),
                       destination=dst_array,
                       dst_transform=dst_transform,
                       dst_crs=CRS.from_dict(init=dst_crs_init),
                       dst_resolution=dst_transform[0],
                       resampling=resampling)
    if return_nodata:
        return dst_array, nd_value
    return dst_array
Esempio n. 31
0
    def prepare_points(self,
                       data,
                       aoi,
                       frac=1.0,
                       min_frac_area=None,
                       all_touched=False,
                       id_column='id',
                       mask=None,
                       n_jobs=8,
                       verbose=0,
                       **kwargs):

        if isinstance(aoi, gpd.GeoDataFrame):
            df = aoi
        else:

            if isinstance(aoi, str):

                if not os.path.isfile(aoi):
                    logger.exception('  The AOI file does not exist.')
                    raise OSError

                df = gpd.read_file(aoi)

            else:
                logger.exception(
                    '  The AOI must be a vector file or a GeoDataFrame.')
                raise TypeError

        if id_column not in df.columns.tolist():
            df.loc[:, id_column] = df.index.values

        df_crs = check_crs(df.crs).to_proj4()
        data_crs = check_crs(data.crs).to_proj4()

        # Re-project the data to match the image CRS
        if data_crs != df_crs:
            df = df.to_crs(data_crs)

        if verbose > 0:
            logger.info('  Checking geometry validity ...')

        # Ensure all geometry is valid
        df = df[df['geometry'].apply(lambda x_: x_ is not None)]

        if verbose > 0:
            logger.info('  Checking geometry extent ...')

        # Remove data outside of the image bounds
        if (type(df.iloc[0].geometry) == Polygon) or (type(df.iloc[0].geometry)
                                                      == MultiPolygon):

            df = gpd.overlay(df,
                             gpd.GeoDataFrame(data=[0],
                                              geometry=[data.gw.geometry],
                                              crs=df_crs),
                             how='intersection').drop(columns=[0])

        else:

            # Clip points to the image bounds
            df = df[df.geometry.intersects(data.gw.geometry)]

        if isinstance(mask, Polygon) or isinstance(
                mask, MultiPolygon) or isinstance(mask, gpd.GeoDataFrame):

            if isinstance(mask, gpd.GeoDataFrame):

                if CRS.from_dict(mask.crs).to_proj4() != df_crs:
                    mask = mask.to_crs(df_crs)

            if verbose > 0:
                logger.info('  Clipping geometry ...')

            df = df[df.within(mask)]

            if df.empty:
                logger.exception(
                    '  No geometry intersects the user-provided mask.')
                raise LookupError

        if not df.empty:

            # Convert polygons to points
            if (type(df.iloc[0].geometry) == Polygon) or (type(
                    df.iloc[0].geometry) == MultiPolygon):

                if verbose > 0:
                    logger.info('  Converting polygons to points ...')

                df = self.polygons_to_points(data,
                                             df,
                                             frac=frac,
                                             min_frac_area=min_frac_area,
                                             all_touched=all_touched,
                                             id_column=id_column,
                                             n_jobs=n_jobs,
                                             **kwargs)

            if not df.empty:

                # Ensure a unique index
                df.index = list(range(0, df.shape[0]))

        return df
Esempio n. 32
0
class Terrain(object):

    latlon_crs = CRS.from_dict(init='epsg:4326')

    def __init__(self, latlon_bounds, fpath='terrain.tif'):
        """Create container for manipulating GeoTIFF data in the
        specified region

        Usage
        =====
        latlon_bounds : list or tuple
            Latitude/longitude corresponding to west, south, east, and
            north bounds, used to define the source transformation.
        fpath : str, optional
            Where to save downloaded GeoTIFF (*.tif) data.
        """
        self.bounds = list(latlon_bounds)
        self._get_utm_crs()  # from bounds
        self.tiffdata = fpath
        self.have_terrain = False
        if not hasattr(self, 'have_metadata'):
            # set attribute if it hasn't been set already
            self.have_metadata = False

    def _get_utm_crs(self, datum='WGS84', ellps='WGS84'):
        """Get coordinate system from zone number associated with the
        longitude of the northwest corner

        Parameters
        ==========
        datum : str, optional
            Origin of destination coordinate system, used to describe
            PROJ.4 string; default is WGS84.
        ellps : str, optional
            Ellipsoid defining the shape of the earth in the destination
            coordinate system, used to describe PROJ.4 string; default
            is WGS84.
        """
        #west, south, east, north = self.bounds
        self.zone_number = int((self.bounds[0] + 180) / 6) + 1
        proj = '+proj=utm +zone={:d} '.format(self.zone_number) \
             + '+datum={:s} +units=m +no_defs '.format(datum) \
             + '+ellps={:s} +towgs84=0,0,0'.format(ellps)
        self.utm_crs = CRS.from_proj4(proj)

    def _get_bounds_from_metadata(self):
        """This is a stub"""
        assert self.have_metadata
        raise NotImplementedError()

    def to_terrain(self, dx, dy=None, resampling=warp.Resampling.bilinear):
        """Load geospatial raster data and reproject onto specified grid

        Usage
        =====
        dx,dy : float
            Grid spacings [m]. If dy is not specified, then uniform
            spacing is assumed.
        resampling : warp.Resampling value, optional
            See `list(warp.Resampling)`.
        """
        if dy is None:
            dy = dx

        # load raster
        if not os.path.isfile(self.tiffdata):
            raise FileNotFoundError('Need to download()')
        dem_raster = rasterio.open(self.tiffdata)

        # get source coordinate reference system, transform
        west, south, east, north = self.bounds
        src_height, src_width = dem_raster.shape
        src_crs = dem_raster.crs
        src_transform = transform.from_bounds(*self.bounds, src_width,
                                              src_height)
        src = dem_raster.read(1)

        # calculate destination coordinate reference system, transform
        dst_crs = self.utm_crs
        print('Projecting from', src_crs, 'to', dst_crs)
        # - get origin (the _upper_ left corner) from bounds
        orix, oriy = self.to_xy(north, west)
        origin = (orix, oriy)
        self.origin = origin
        dst_transform = transform.from_origin(*origin, dx, dy)
        # - get extents from lower right corner
        SE_x, SE_y = self.to_xy(south, east)
        Lx = SE_x - orix
        Ly = oriy - SE_y
        Nx = int(Lx / dx)
        Ny = int(Ly / dy)

        # reproject to uniform grid in the UTM CRS
        dem_array = np.empty((Ny, Nx))
        warp.reproject(src,
                       dem_array,
                       src_transform=src_transform,
                       src_crs=src_crs,
                       dst_transform=dst_transform,
                       dst_crs=dst_crs,
                       resampling=resampling)
        utmx = orix + np.arange(0, Nx * dx, dx)
        utmy = oriy + np.arange((-Ny + 1) * dy, dy, dy)
        self.x, self.y = np.meshgrid(utmx, utmy, indexing='ij')
        self.z = np.flipud(dem_array).T

        self.zfun = RectBivariateSpline(utmx, utmy, self.z)
        self.have_terrain = True

        return self.x, self.y, self.z

    def to_latlon(self, x, y):
        """Transform uniform grid to lat/lon space"""
        if not hasattr(x, '__iter__'):
            assert ~hasattr(x, '__iter__')
            x = [x]
            y = [y]
        xlon, xlat = warp.transform(self.utm_crs, self.latlon_crs, x, y)
        try:
            shape = x.shape
        except AttributeError:
            xlat = xlat[0]
            xlon = xlon[0]
        else:
            xlat = np.reshape(xlat, shape)
            xlon = np.reshape(xlon, shape)
        return xlat, xlon

    def to_xy(self, lat, lon, xref=None, yref=None):
        """Transform lat/lon to UTM space"""
        if not hasattr(lat, '__iter__'):
            assert ~hasattr(lat, '__iter__')
            lat = [lat]
            lon = [lon]
        x, y = warp.transform(self.latlon_crs, self.utm_crs, lon, lat)
        try:
            shape = lon.shape
        except AttributeError:
            x = x[0]
            y = y[0]
        else:
            x = np.reshape(x, shape)
            y = np.reshape(y, shape)
        if xref is not None:
            x -= xref
        if yref is not None:
            y -= yref
        return x, y

    def xtransect(self, xy=None, latlon=None, wdir=270.0, xrange=(None, None)):
        """Get terrain transect along x for a slice aligned with the
        specified wind direction and going through a specified reference
        point (defined by xy or latlon)

        Usage
        =====
        xy : list or tuple
            Reference location in the UTM coordinate reference system [m]
        latlon : list-like
            Reference location in latitude and longitude [deg]
        wdir : float
            Wind direction with which the slice is aligned [deg]
        xrange : list or tuple, optional
            Range of x values over which slice (or None to use min/max)
        """
        assert self.have_terrain, 'Need to call to_terrain()'
        assert ((xy is not None) ^
                (latlon is not None)), 'Specify xy or latlon'
        if xy:
            refloc = xy
        elif latlon:
            x, y = self.to_xy(*latlon)
            refloc = (x, y)
        ang = 270 - wdir
        print('Slice through', refloc, 'at', ang, 'deg')
        ang *= np.pi / 180.

        # direction specific code
        imin = 0 if (xrange[0] is None) else np.where(
            self.x <= xrange[0])[0][-1]
        imax = None if (xrange[1] is None) else np.where(
            self.x > xrange[1])[0][0]
        x = self.x[imin:imax, 0]
        y = np.tan(ang) * (x - refloc[0]) + refloc[1]
        z = self.zfun(x, y, grid=False)

        return x - refloc[0], z

    def ytransect(self, xy=None, latlon=None, wdir=180.0, yrange=(None, None)):
        """Get terrain transect along x for a slice aligned with the
        specified wind direction and going through a specified reference
        point (defined by xy or latlon)

        Usage
        =====
        xy : list or tuple
            Reference location in the UTM coordinate reference system [m]
        latlon : list-like
            Reference location in latitude and longitude [deg]
        wdir : float
            Wind direction with which the slice is aligned [deg]
        xrange : list or tuple, optional
            Range of x values over which slice (or None to use min/max)
        """
        assert self.have_terrain, 'Need to call to_terrain()'
        assert ((xy is not None) ^
                (latlon is not None)), 'Specify xy or latlon'
        if xy:
            refloc = xy
        elif latlon:
            x, y = self.to_xy(*latlon)
            refloc = (x, y)
        ang = 180 - wdir
        print('Slice through', refloc, 'at', ang, 'deg')
        ang *= np.pi / 180.

        # direction specific code
        jmin = 0 if (yrange[0] is None) else np.where(
            self.y <= yrange[0])[1][-1]
        jmax = None if (yrange[1] is None) else np.where(
            self.y > yrange[1])[1][0]
        y = self.y[0, jmin:jmax]
        x = refloc[0] - np.tan(ang) * (y - refloc[1])
        z = self.zfun(x, y, grid=False)

        return y - refloc[1], z