def get_utm_wkt(coordinate, from_wkt): ''' Function to return CRS for UTM zone of specified coordinates. Used to transform coords to metres @param coordinate: single coordinate pair ''' def utm_getZone(longitude): return (int(1 + (longitude + 180.0) / 6.0)) def utm_isNorthern(latitude): if (latitude < 0.0): return 0 else: return 1 coordinate_array = np.array(coordinate).reshape((1, 2)) latlon_coord_trans = get_coordinate_transformation(from_wkt, 'EPSG:4326') latlon_coord = coordinate if latlon_coord_trans is None else latlon_coord_trans.TransformPoints( coordinate_array)[0][0:2] # Set UTM coordinate reference system utm_spatial_ref = SpatialReference() utm_spatial_ref.SetWellKnownGeogCS('WGS84') utm_spatial_ref.SetUTM(utm_getZone(latlon_coord[0]), utm_isNorthern(latlon_coord[1])) return utm_spatial_ref.ExportToWkt()
def gdal_reproject( cls, src: Union[str, gdal.Dataset], output_file: str = None, # The filepath of the output image to write to. src_srs: osr.SpatialReference = None, dst_srs: osr.SpatialReference = None, # Defaults to epsg if None epsg: int = None, error_threshold: float = 0.125, resampling: gdalconst = gdalconst.GRA_NearestNeighbour ) -> Optional["GDALGrid"]: """ Reproject a raster image. """ src_ds = cls.load_raster(src)[0] if dst_srs is None: dst_srs = osr.SpatialReference() dst_srs.ImportFromEPSG(int(epsg)) dst_wkt = dst_srs.ExportToWkt() if not isinstance(resampling, int): resampling = getattr(gdal, resampling) src_wkt = None if src_srs is not None: src_wkt = src_srs.ExportToWkt() reprojected_ds = gdal.AutoCreateWarpedVRT(src_ds, src_wkt, dst_wkt, resampling, error_threshold) if output_file: gdal.GetDriverByName('GTiff').CreateCopy(output_file, reprojected_ds) return GDALGrid(reprojected_ds)
def _nor_roms(xp=3991, yp=2230, dx=800, ylon=70, name='NK800', metric_unit=False): if metric_unit: unit_str = 'UNIT["metre",1,AUTHORITY["EPSG","9001"]]' dx_unit = dx else: unit_str = f'UNIT["Cells",{dx}]]' dx_unit = 1 wkt = f"""PROJCS["{name}", GEOGCS["ETRS89", DATUM["European_Terrestrial_Reference_System_1989", SPHEROID["GRS 1980",6378137,298.257222101, AUTHORITY["EPSG","7019"]], AUTHORITY["EPSG","6258"]], PRIMEM["Greenwich",0, AUTHORITY["EPSG","8901"]], UNIT["degree",0.01745329251994328, AUTHORITY["EPSG","9122"]], AUTHORITY["EPSG","4258"]], PROJECTION["Polar_Stereographic"], PARAMETER["latitude_of_origin",60], PARAMETER["central_meridian",{ylon}], PARAMETER["scale_factor",1], PARAMETER["false_easting",{xp * dx_unit}], PARAMETER["false_northing",{yp * dx_unit}], {unit_str}""" sr = SpatialReference() sr.ImportFromWkt(wkt) return sr
def _inspect_data(self): """ Extract coordinate reference system and min/max values from a GDAL supported raster data file. """ if self._data is None: # TODO: This method is really ugly, but is nice for testing self._data = {} df = gdal.Open(self.filename) # TODO: df may be None? crs = df.GetProjection() if crs: spref = SpatialReference(wkt=crs) # default to epsg:4326 auth = spref.GetAuthorityName(None) or 'epsg' code = spref.GetAuthorityCode(None) or '4326' self._data['crs'] = "%s:%s" % (auth.lower(), code) # LOG.info('Detected CRS: %s', self._data['crs']) else: self._data['crs'] = 'epsg:4326' # use epsg:4326 as default band = df.GetRasterBand(1) self._data['min'], self._data['max'], _, _ = band.GetStatistics( True, False) self._data['nodata'] = band.GetNoDataValue() self._data['datatype'] = band.DataType
def testExpandByPercentage(self): ulx = 374187 uly = 4202663 lrx = 501598 lry = 4100640 srs = SpatialReference() srs.ImportFromEPSG(32612) env = Envelope() env.addPoint(ulx, uly, 0, srs) env.addPoint(lrx, lry, 0, srs) env.expandByPercentage(0.0) self.assertEqual(ulx, env.ulx()) self.assertEqual(uly, env.uly()) self.assertEqual(lrx, env.lrx()) self.assertEqual(lry, env.lry()) percentage = 10 width = 127411.0 height = 163224.55529116935 exWidth = width * percentage / 100 / 2.0 exHeight = height * percentage / 100 / 2.0 exUlx = abs(ulx - exWidth) exUly = abs(uly + exHeight) newUlx, newUly, newLrx, newLry = env.expandByPercentage(percentage) self.assertEqual(exUlx, newUlx) self.assertEqual(exUly, newUly)
def read_raster(path, band_number=1): """ Create a raster dataset from a single raster file Parameters ---------- path: string Path to the raster file. Can be either local or s3/gs. band_number: int The band number to use Returns ------- RasterDataset """ path = fileutils.get_path(path) ds = gdal.Open(path, GA_ReadOnly) xsize = ds.RasterXSize ysize = ds.RasterYSize proj = SpatialReference() proj.ImportFromWkt(ds.GetProjection()) geo_transform = ds.GetGeoTransform() return RasterDataset(ds, xsize, ysize, geo_transform, proj)
def envelope(self): dataset = self.getDataset() xform = dataset.GetGeoTransform() xScale = xform[1] yScale = xform[5] width = dataset.RasterXSize height = dataset.RasterYSize ulx = xform[0] uly = xform[3] lrx = ulx + width * xScale lry = uly + height * yScale envelope = Envelope() # --- # If this file is in 4326, we must swap the x-y to conform with GDAL # 3's strict conformity to the 4326 definition. # --- srs4326 = SpatialReference() srs4326.ImportFromEPSG(4326) if srs4326.IsSame(self._dataset.GetSpatialRef()): envelope.addPoint(uly, ulx, 0, self._dataset.GetSpatialRef()) envelope.addPoint(lry, lrx, 0, self._dataset.GetSpatialRef()) else: envelope.addPoint(ulx, uly, 0, self._dataset.GetSpatialRef()) envelope.addPoint(lrx, lry, 0, self._dataset.GetSpatialRef()) return envelope
def pyproj_crs_to_osgeo(proj_crs: Union[CRS, int]): """ Convert from the pyproj CRS object to osgeo SpatialReference See https://pyproj4.github.io/pyproj/stable/crs_compatibility.html Parameters ---------- proj_crs pyproj CRS or an integer epsg code Returns ------- SpatialReference converted SpatialReference """ if isinstance(proj_crs, int): proj_crs = CRS.from_epsg(proj_crs) osr_crs = SpatialReference() if osgeo.version_info.major < 3: osr_crs.ImportFromWkt(proj_crs.to_wkt(WktVersion.WKT1_GDAL)) else: osr_crs.ImportFromWkt(proj_crs.to_wkt()) return osr_crs
def write_esri_grid_ascii_file(path, data, extent, cellsize, nodata_value=-9999.0): xllcorner, yllcorner, *_ = extent.as_list() nrows, ncols = data.shape header_dict = OrderedDict() header_dict['nrows'] = nrows header_dict['ncols'] = ncols header_dict['xllcorner'] = xllcorner header_dict['yllcorner'] = yllcorner header_dict['cellsize'] = cellsize header_dict['nodata_value'] = nodata_value header = '\n'.join( ['{} {}'.format(key, val) for key, val in header_dict.items()]) numpy.savetxt(path, data, header=header, comments='') # save projection info to adjacent file ref = SpatialReference() ref.ImportFromProj4(extent.projection.srs) with open(path.replace('asc', 'prj'), 'w') as f: f.write(ref.ExportToWkt())
def testConsistentResults(self): ulx = 94.2 uly = 19.4 lrx = 94.6 lry = 19.1 srs = SpatialReference() srs.ImportFromEPSG(4326) srs.SetAxisMappingStrategy(osr.OAMS_TRADITIONAL_GIS_ORDER) env = Envelope() env.addPoint(ulx, uly, 0, srs) env.addPoint(lrx, lry, 0, srs) fpq = FootprintsQuery(FootprintsQueryTestCase._logger) fpq.addAoI(env) numScenes = 27 fpq.setMaximumScenes(numScenes) fpScenes1 = fpq.getScenes() fpScenes2 = fpq.getScenes() self.assertEqual(len(fpScenes1), numScenes) self.assertEqual(len(fpScenes1), len(fpScenes2)) for i in range(len(fpScenes1)): self.assertEqual(fpScenes1[i].fileName(), fpScenes2[i].fileName())
def load_data(self): filename = self.path.split(os.sep)[-1] # Check for VELMA filename matches for pattern in [self.VELMA_FILENAME_BASIC_RE, self.VELMA_FILENAME_NO_LAYER_RE, self.VELMA_FILENAME_SUBDAY_RE, self.VELMA_FILENAME_SUBDAY_NO_LAYER_RE]: match = pattern.match(filename) if match: self._velma_pattern = pattern self.data_name = match.group(1) self._loop = match.group(2) self._has_layer = pattern in [self.VELMA_FILENAME_BASIC_RE, self.VELMA_FILENAME_SUBDAY_RE] if self._has_layer: self._layer = match.group(3) self._is_subday = pattern in [self.VELMA_FILENAME_SUBDAY_RE, self.VELMA_FILENAME_SUBDAY_NO_LAYER_RE] self._is_velma = True break projection = None prj_file = self.path.replace('.asc', '.prj') if os.path.exists(prj_file): with open(prj_file, 'r') as f: ref = SpatialReference() ref.ImportFromWkt(f.read()) projection = Proj(ref.ExportToProj4()) # Capture georeference with rasterio.open(self.path) as src: self.affine = src.transform self.shape = src.shape self.resolution = src.res[0] # Assumed to be square self.extent = Extent(*list(src.bounds), projection=projection) self._nodata_value = src.nodata self.time_info = TemporalInfo() if not self._is_velma: self.data_name = self.path.split(os.sep)[-1].split('.')[0] return timestamps = [] for f in os.listdir(os.path.dirname(os.path.abspath(self.path))): filename = f.split(os.sep)[-1] match = self._velma_pattern.match(filename) # Skip if match is None and if match name or loop is wrong if match and match.group(1) == self.data_name and match.group(2) == self._loop: # Skip if match layer is wrong, if applicable if self._has_layer and match.group(3) != self._layer: continue years = int(match.group(4 if self._has_layer else 3)) days = int(match.group(5 if self._has_layer else 4)) hours = int(match.group(6 if self._has_layer else 5)) if self._is_subday else 0 minutes = int(match.group(7 if self._has_layer else 6)) if self._is_subday else 0 insort(timestamps, datetime.datetime(years, 1, 1, hours, minutes) + datetime.timedelta(days - 1)) self.time_info.timestamps = timestamps
def _extractVars(files, variables, envelope, outDir): srs = SpatialReference() srs.ImportFromEPSG(4326) srs.SetAxisMappingStrategy(osr.OAMS_TRADITIONAL_GIS_ORDER) subFiles = [] for f in files: geoFile = GeospatialImageFile(f, spatialReference=srs) subs = geoFile.getDataset().GetSubDatasets() foundVariables = [] # Look for a variable name in the subdataset name. for sub in subs: datasetName = sub[0] var = datasetName.split(':')[2] if var in variables: foundVariables.append(var) # --- # Copy the original file before operating on it, unless # it already exists in the output directory. # --- name = os.path.basename(os.path.splitext(f)[0]) + \ '_' + \ var + \ '.nc' workingCopy = os.path.join(outDir, name) if not os.path.exists(workingCopy): shutil.copyfile(f, workingCopy) # Extract and clip the subdataset. copyGeoFile = GeospatialImageFile(workingCopy, srs) copyGeoFile.clipReproject(envelope, None, sub[0]) else: copyGeoFile = GeospatialImageFile(workingCopy, srs) subFiles.append(copyGeoFile.fileName()) # Stop, when all variables are found. if len(foundVariables) == len(variables): break # Are any variables missing? if len(foundVariables) != len(variables): missing = [v for v in variables if v not in foundVariables] msg = 'Variables not found in ' + str(f) + ': ' + str(missing) raise RuntimeError(msg) return subFiles
def __setstate__(self, state): srs = SpatialReference() srs.ImportFromProj4(state[GeospatialImageFile.SRS_KEY]) self.__init__(state[GeospatialImageFile.FILE_KEY], srs, state[GeospatialImageFile.SUBDATASET_KEY], state[GeospatialImageFile.LOGGER_KEY])
def gdal(self): if self._gdal is not None: pass elif self._proj4 is not None: self._gdal = SpatialReference() self._gdal.ImportFromProj4(self._proj4) return self._gdal
def testSRS(self): testSRS = SpatialReference() testSRS.ImportFromEPSG(32612) obs = ObservationFile(ObservationFileTestCase._testObsFile, ObservationFileTestCase._species) self.assertTrue(obs.srs().IsSame(testSRS))
def alt_downloader(tile_nr_x, tile_nr_y): # construct url url = www_folder + str(tile_nr_x) + '/' + str(tile_nr_y) + '.asc.zip' try: # create a momemory driver and dataset on it driver = gdal.GetDriverByName('MEM') ds = driver.Create('', TD['NCOLS'], TD['NROWS'], 1, gdal.GDT_Float32) # access the zip file zf = ZipFile(BytesIO(requests.get(url).content)) # read the rasterfile in the format of an array lines = zf.open(zf.infolist()[0]).readlines() # NOTE: # in the following lines we use some properties that the .asc files on our server have: # - carriage returns are used to separate header items and rows # - the header is 6 lines, that is, there is a NO DATA value in line 6 # - the data starts in line 7 (index 6) # these are not required by the standard, c.f. # http://help.arcgis.com/en/arcgisdesktop/10.0/help/index.html#/ESRI_ASCII_raster_format/009t0000000z000000/ # in particular, NO DATA is optional and carriage returns may be replaced by spaces # read the geo transform #as from http://geoexamples.blogspot.com/2012/01/creating-files-in-ogr-and-gdal-with.html: #geotransform = (left x-coordinate, x-cellsize, rotation ?,upper y-coordinate,rotation,y-cellsize) #Xgeo = geotransform[0] + Xpixel*geotransform[1] + Yline*geotransform[2] #Ygeo = geotransform[3] + Xpixel*geotransform[4] + Yline*geotransform[5] #for some reason, y-cellsize must be negative here geo_trafo = (float(lines[2].split()[1]), TD['CELLSIZE'], 0, float(lines[3].split()[1]) + TD['CELLSIZE'] * TD['NROWS'], 0, -TD['CELLSIZE']) ds.SetGeoTransform(geo_trafo) # read and write the data to the dataset arr = list(map(lambda x: list(map(float, x.split())), lines[6:])) zf.close() band = ds.GetRasterBand(1) band.WriteArray(array(arr)) # set the spatial reference system (probably not necessary) proj = SpatialReference() proj.SetWellKnownGeogCS("EPSG:31287") ds.SetProjection(proj.ExportToWkt()) return ds except: return None
def crs_from_gridmapping(grid_mapping): """Create projection from grid_mapping variable""" if 'crs_wkt' not in grid_mapping.attrs: raise NotImplementedError('At present, a "crs_wkt" attr is required') wkt = grid_mapping.attrs['crs_wkt'] sr = SpatialReference() sr.ImportFromWkt(wkt) return sr
def __init__(self,*args,**kwds): self.ocgis = ocgis(self) sr = kwds.pop('sr',None) if sr is None: sr = SpatialReference() sr.ImportFromEPSG(4326) self.ocgis._proj4_str = sr.ExportToProj4() super(SelectionGeometry,self).__init__(*args,**kwds)
def __new__(cls, ds, band_number=1): """ Create an in-memory representation for a single band in a raster. (0,0) in pixel coordinates represents the upper left corner of the raster which corresponds to (min_lon, max_lat). Inherits from ndarray, so you can use it like a numpy array. Parameters ---------- ds: gdal.Dataset band_number: int The band number to use Attributes ---------- data: np.ndarray[xsize, ysize] The raster data """ if not isinstance(ds, gdal.Dataset): path = fileutils.get_path(ds) ds = gdal.Open(path, GA_ReadOnly) band = ds.GetRasterBand(band_number) if band is None: msg = "Unable to load band %d " % band_number msg += "in raster %s" % ds.GetDescription() raise ValueError(msg) gdal_type = band.DataType dtype = np.dtype(GDAL2NP_CONVERSION[gdal_type]) self = np.asarray(band.ReadAsArray().astype(dtype)).view(cls) self.gdal_type = gdal_type proj = SpatialReference() proj.ImportFromWkt(ds.GetProjection()) geo_transform = ds.GetGeoTransform() # Initialize the base class with coordinate information. RasterBase.__init__(self, ds.RasterXSize, ds.RasterYSize, geo_transform, proj) self.nan = band.GetNoDataValue() #self = np.ma.masked_equal(self, band.GetNoDataValue(), copy=False) ctable = band.GetColorTable() if ctable is not None: self.colors = np.array( [ctable.GetColorEntry(i) for i in range(256)], dtype=np.uint8) else: self.colors = None ds = None return self
def srs(self): srs = self._dataset.GetSpatialRef() if not srs: srs = SpatialReference() srs.ImportFromEPSG(4326) srs.SetAxisMappingStrategy(osr.OAMS_TRADITIONAL_GIS_ORDER) return srs
def __setstate__(self, state): multipointWkt = state[Envelope.MULTIPOINT_KEY] copy = ogr.CreateGeometryFromWkt(multipointWkt) self.__dict__.update(copy.__dict__) srsProj4 = state[Envelope.SRS_KEY] srs = SpatialReference() srs.ImportFromProj4(srsProj4) self.AssignSpatialReference(srs)
def _createTestFile(self): testFile = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'TSURF.nc') workingCopy = tempfile.mkstemp(suffix='.nc')[1] shutil.copyfile(testFile, workingCopy) srs = SpatialReference() srs.ImportFromEPSG(4326) return GeospatialImageFile(workingCopy, srs)
def get_identifier(crs): """ Given a CRS, generate a unique idenfier for it. Eg: "EPSG:2193" """ if isinstance(crs, str): crs = SpatialReference(crs) if isinstance(crs, SpatialReference): auth_name = crs.GetAuthorityName(None) auth_code = crs.GetAuthorityCode(None) return f"{auth_name}:{auth_code}" raise RuntimeError(f"Unrecognised CRS: {crs}")
def getListofMerraImages(self, files): # Convert the list of NetCDF files to GeospatialImageFiles list = [] tgt_srs = SpatialReference() tgt_srs.ImportFromEPSG(4326) for file in files: list.append( GeospatialImageFile(os.path.join(self._merraDir, file), tgt_srs)) return list
def extract_epsg(self, proj4string): srs = SpatialReference() rc = srs.ImportFromProj4(proj4string) if rc: raise Exception("Invalid proj4 string: %s" % proj4string) code = srs.GetAttrValue('AUTHORITY', 1) epsg = int(code) QgsMessageLog.logMessage("proj4string %s --> EPSG:%i" % (proj4string, epsg), tag='Import .3d', level=QgsMessageLog.INFO) return epsg
def get_proj4_string(wkt_proj): if not wkt_proj: return None else: a = SpatialReference(wkt_proj) a.MorphFromESRI() res = a.ExportToProj4() return None if \ '+proj=longlat +ellps=WGS84 +no_defs' in res \ or '+proj=longlat +datum=WGS84 +no_defs' in res \ else res
def test_parse(): assert crs_util.parse_name(TEST_WKT) == "WGS 84" assert crs_util.parse_authority(TEST_WKT) == ("EPSG", "4326") assert crs_util.parse_name(AXIS_LAST_WKT) == "WGS 84" assert crs_util.parse_authority(AXIS_LAST_WKT) == ("EPSG", "4326") # Strangely this doesn't entirely work using osgeo: spatial_ref = SpatialReference(TEST_WKT) assert spatial_ref.GetName() == "WGS 84" assert spatial_ref.GetAuthorityName(None) is None assert spatial_ref.GetAuthorityCode(None) is None
def convert_ogr_to_geojson(file_path, file_format): regex_field_name = re.compile("[^a-zA-Z0-9_-ëêàáâãæêéèñòóô]+") in_driver = GetDriverByName(file_format) out_driver = GetDriverByName('MEMORY') f_in = in_driver.Open(file_path) input_layer = f_in.GetLayer() outSpRef = SpatialReference() outSpRef.ImportFromEPSG(4326) coords_transform = CoordinateTransformation(input_layer.GetSpatialRef(), outSpRef) f_out = out_driver.CreateDataSource('') output_layer = f_out.CreateLayer('', outSpRef) input_lyr_defn = input_layer.GetLayerDefn() for i in range(input_lyr_defn.GetFieldCount()): fieldDefn = input_lyr_defn.GetFieldDefn(i) fieldDefn.SetName(regex_field_name.sub('_', fieldDefn.GetNameRef())) output_layer.CreateField(fieldDefn) output_lyr_defn = output_layer.GetLayerDefn() nb_field = output_lyr_defn.GetFieldCount() field_names = [ output_lyr_defn.GetFieldDefn(i).GetNameRef() for i in range(nb_field) ] res = [] for inFeature in input_layer: geom = inFeature.GetGeometryRef() outFeature = OgrFeature(output_lyr_defn) # Don't try to transform empty geometry : if geom: geom.Transform(coords_transform) outFeature.SetGeometry(geom) else: outFeature.SetGeometry(None) outFeature.SetFID(inFeature.GetFID()) for i in range(output_lyr_defn.GetFieldCount()): outFeature.SetField(field_names[i], inFeature.GetField(i)) res.append(outFeature.ExportToJson()) outFeature.Destroy() inFeature.Destroy() f_in.Destroy() f_out.Destroy() return ''.join([ '''{"type":"FeatureCollection","features":[''', ','.join(res), ''']}''' ]).encode()
def testSrs(self): # Build the test file. imageFile = self._createTestFile() # Check the srs. expectedSRS = SpatialReference() expectedSRS.ImportFromEPSG(4326) self.assertTrue(imageFile.srs().IsSame(expectedSRS)) # Delete the test file. os.remove(imageFile.fileName())
def testEnvelope(self): testEnv = Envelope() srs = SpatialReference() srs.ImportFromEPSG(32612) testEnv.addPoint(374187, 4202663, 0, srs) testEnv.addPoint(501598, 4100640, 0, srs) obs = ObservationFile(ObservationFileTestCase._testObsFile, ObservationFileTestCase._species) self.assertTrue(testEnv.Equals(obs.envelope()))