def _getDatatype(driver): tnames = tuple( driver.GetMetadata_Dict()["DMD_CREATIONDATATYPES"].split(" ")) types = tuple(gdal.GetDataTypeByName(t) for t in tnames) tdict = tuple((gdal.GetDataTypeSize(t), t) for t in types) otype = max(tdict, key=lambda x: x[0])[-1] return np.dtype(_TYPEMAP[otype])
def merge_bands(cls, rasters, resolution="highest", gdal_driver=gdal.GetDriverByName("Gtiff"), data_type=gdal.GetDataTypeByName('Float32'), no_data=-999): """ Create one single raster from multiple bands Description ----------- Create one raster from multiple bands using gdal Parameters ---------- rasters: Collection Collection of RasterBase instances resolution: str GDAL resolution option ("highest", "lowest", "average") gdal_driver: osgeo.gdal.Driver data_type: int GDAL data type no_data: int or float no data value in output raster """ return _merge_bands(cls, rasters, resolution, gdal_driver, data_type, no_data)
def merge(cls, rasters, bounds=None, output_format="Gtiff", data_type=gdal.GetDataTypeByName('Float32'), no_data=-999): """ Merge multiple rasters Description ----------- Parameters ---------- rasters: Collection Collection of RasterBase instances bounds: tuple bounds of the new merged raster output_format:str raster file output format (Gtiff, etc.) data_type: int GDAL data type no_data: int or float output no data value in merged raster Returns ------- """ return _merge(cls, rasters, bounds, output_format, data_type, no_data)
def compute(self, *args): def get_band(name): layer = self.dict_of_bands[name][1] b_num = self.dict_of_bands[name][2] band = layer.get_parent().get_dataset().GetRasterBand(b_num + 1) return band def create_new_layer(pview, player, w, h): """Creates new raster layer like <player> with width = w and height = h""" gview.app.view_manager.set_active_view(pview) pview.viewarea.set_active_layer(player) target_ds = player.get_parent().get_dataset() rl_mode_value = player.get_mode() new_layer = gview.GvRasterLayer( \ gview.GvRaster(dataset = target_ds,real=1), \ rl_mode = rl_mode_value) pview.viewarea.list_layers().append(new_layer) return new_layer # extract computing parameters b1_name = self.list_of_bands[self.s1_list.get_history()] b2_name = self.list_of_bands[self.s2_list.get_history()] if b1_name <> None: if self.switch_new_view.get_active(): gview.app.new_view() op_index = self.operation.get_history() type_index = self.types.get_history() a = float(self.a_const.get_text()) b = float(self.b_const.get_text()) c = float(self.c_const.get_text()) b1 = get_band(b1_name) b2 = get_band(b2_name) type = \ gdal.GetDataTypeByName(self.types_list[self.types.get_history()]) self.numtype = gdalnumeric.GDALTypeCodeToNumericTypeCode(type) if self.numtype == None: gvutils.error("Error! Type " + self.numtype + " is not supported!") return FALSE proto_ds = self.dict_of_bands[b1_name][1].get_parent().get_dataset( ) op_func = self.operations_dict[self.op][1] self.out_buf = Numeric.zeros((b1.YSize, b1.XSize), self.numtype) try: op_func(s1=b1, s2=b2, a=a, b=b, c=c) except: gvutils.error("Try to change coefficients.") return FALSE res_ds = gdalnumeric.OpenArray(self.out_buf, proto_ds) gview.app.open_gdal_dataset(res_ds) self.close() else: gvutils.error("Source1 and Source2 have to differ!") return FALSE
def create_paux_header(self,filename,datatype): (path, ext) = os.path.splitext(filename) auxname = path + ".aux" if os.path.isfile(auxname): resp = GtkExtra.message_box('Confirmation', \ auxname + ' exists. Overwrite?', ('Yes','No')) if resp == 'No': return # Take the image parameters header = long(self.header_entry.get_text()) width = long(self.width_entry.get_text()) height = long(self.height_entry.get_text()) bands = long(self.bands_entry.get_text()) aux_type_dict={'Byte':'8U','Int16':'16S','UInt16':'16U', 'Float32':'32R'} aux_type_list = ['8U', '16S', '16U', '32R'] type = aux_type_dict[datatype] gdaltype = gdal.GetDataTypeByName(datatype) interleaving = self.interleave_list[self.interleave_menu.get_history()] datasize = gdal.GetDataTypeSize(gdaltype) / 8 # Calculate offsets pixel_offset = [] line_offset = [] image_offset = [] if interleaving is 'Pixel': for i in range(bands): pixel_offset.append(datasize * bands) line_offset.append(datasize * width * bands) image_offset.append(header + datasize * i) elif interleaving is 'Band': for i in range(bands): pixel_offset.append(datasize) line_offset.append(datasize * width) image_offset.append(header + datasize * width * height * i) elif interleaving is 'Line': for i in range(bands): pixel_offset.append(datasize) line_offset.append(datasize * width * bands) image_offset.append(header + datasize * width * i) else: raise 'Unsupported interleaving type!' aux_swap_list = ['Swapped', 'Unswapped'] swap = aux_swap_list[self.swap_menu.get_history()] # Write out the auxilary file aux = open(auxname, "wt") aux.write("AuxilaryTarget: " + os.path.basename(filename) + '\n') aux.write("RawDefinition: " + str(width) + ' ' \ + str(height) + ' ' + str(bands) + '\n') for i in range(bands): aux.write("ChanDefinition-" + str(i + 1) + ': ' + type + ' ' \ + str(image_offset[i]) + ' ' + str(pixel_offset[i]) \ + ' ' + str(line_offset[i]) + ' ' + swap + '\n') aux.close() aux = None
def gdal_translate(dest, src, *args, **kwargs): try: # If outputType is specified, convert it to gdal datatype kwargs['outputType'] = gdal.GetDataTypeByName(kwargs['outputType']) except KeyError: # If outputType not specified, no conversion is necessary and GDAL will # use default arguments. pass opts = gdal.TranslateOptions(*args, **kwargs) return gdal.Translate(dest, src, options=opts)
def raster_calculation(cls, rasters, fhandle, window_size=100, gdal_driver=gdal.GetDriverByName("Gtiff"), data_type=gdal.GetDataTypeByName('Float32'), no_data=-999, nb_processes=mp.cpu_count(), chunksize=MP_CHUNK_SIZE, description="Calculate raster expression"): """ Raster expression calculation Description ----------- Calculate raster expression stated in "fhandle" such as: fhandle(raster1, raster2, etc.) Calculation is made for each band. Parameters ---------- rasters: list or tuple collection of RasterBase instances fhandle: function expression to calculate (must accept a collection of arrays) window_size: int or (int, int) size of window/chunk to set in memory during calculation * unique value * tuple of 2D coordinates (width, height) gdal_driver: osgeo.gdal.Driver GDAL driver (output format) data_type: int GDAL data type for output raster no_data: int or float no data value in resulting raster nb_processes: int number of processes for multiprocessing pool chunksize: int chunk size used in map/imap multiprocessing function description: str Progress bar description Returns ------- RasterBase New temporary instance """ return _raster_calculation(cls, rasters, fhandle, window_size, gdal_driver, data_type, no_data, nb_processes, chunksize, description)
def rasterize(cls, layer, projection, x_size, y_size, geo_transform, burn_values=None, attribute=None, gdal_driver=gdal.GetDriverByName("Gtiff"), nb_band=1, data_type=gdal.GetDataTypeByName("Float32"), no_data=-999, all_touched=True): """ Rasterize geographic layer Parameters ---------- layer: geopandas.GeoDataFrame or gistools.layer.GeoLayer Geographic layer to be rasterized projection: str Projection as a WKT string x_size: int Raster width y_size: int Raster height geo_transform: tuple burn_values: list[float] or list[int], default None List of values to be burnt in each band, excusive with attribute attribute: str, default None Layer's attribute to be used for values to be burnt in raster, excusive with burn_values gdal_driver: osgeo.gdal.Driver, default GeoTiff GDAL driver nb_band: int, default 1 Number of bands data_type: int, default "Float32" GDAL data type no_data: int or float, default -999 No data value all_touched: bool Returns ------- """ return _rasterize(cls, layer, burn_values, attribute, gdal_driver, projection, x_size, y_size, nb_band, geo_transform, data_type, no_data, all_touched)
def windowing(self, f_handle, window_size, method, band=None, data_type=gdal.GetDataTypeByName('Float32'), no_data=None, chunk_size=100000, nb_processes=mp.cpu_count()): """ Apply function within sliding/block window Description ----------- Parameters ---------- f_handle: function window_size: int size of window method: str sliding window method ('block' or 'moving') band: int raster band data_type: int gdal data type no_data: list or tuple raster no data chunk_size: int data chunk size for multiprocessing nb_processes: int number of processes for multiprocessing Return ------ RasterBase New instance """ if band is None: band = 1 if no_data is None: no_data = self.no_data return _windowing(self, f_handle, band, window_size, method, data_type, no_data, chunk_size, nb_processes)
def _return_classification(raster, nb_classes, *args, **kwargs): with RasterTempFile(raster._gdal_driver.GetMetadata() ['DMD_EXTENSION']) as out_file: out_ds = _gdal_temp_dataset(out_file.path, raster._gdal_driver, raster._gdal_dataset.GetProjection(), raster.x_size, raster.y_size, 1, raster.geo_transform, gdal.GetDataTypeByName('Int16'), no_data=CLASSIFICATION_NO_DATA) labels = classification(raster, nb_classes, out_ds, *args, **kwargs) # Close dataset out_ds = None new_raster = raster.__class__(out_file.path) new_raster._temp_file = out_file return new_raster
def create_vrt_lines(self,filename): image_offset = long(self.header_entry.get_text()) width = long(self.width_entry.get_text()) height = long(self.height_entry.get_text()) bands = long(self.bands_entry.get_text()) interleaving = self.interleave_list[self.interleave_menu.get_history()] dtype = self.type_list[self.type_menu.get_history()] gdaltype = gdal.GetDataTypeByName(dtype) datasize = gdal.GetDataTypeSize(gdaltype) / 8 byteorder = ['LSB','MSB'][self.swap_menu.get_history()] vrtdsc = vrtutils.VRTDatasetConstructor(width,height) if interleaving == 'Pixel': pixoff = datasize*bands lineoff = pixoff*width for idx in range(bands): imoff = image_offset + idx*datasize vrtdsc.AddRawBand(filename, dtype, byteorder, imoff, pixoff, lineoff) elif interleaving == 'Line': pixoff=datasize lineoff=datasize*width*bands for idx in range(bands): imoff = image_offset + idx*lineoff vrtdsc.AddRawBand(filename, dtype, byteorder, imoff, pixoff, lineoff) else: pixoff=datasize lineoff=datasize*width for idx in range(bands): imoff = image_offset + datasize*width*height*idx vrtdsc.AddRawBand(filename, dtype, byteorder, imoff, pixoff, lineoff) return vrtdsc.GetVRTLines()
def _op(raster1, out_file, raster2, op_type): """ Basic arithmetic operations """ out_ds = _gdal_temp_dataset(out_file, raster1._gdal_driver, raster1._gdal_dataset.GetProjection(), raster1.x_size, raster1.y_size, raster1.nb_band, raster1.geo_transform, gdal.GetDataTypeByName('Float32'), raster1.no_data) for band in range(1, raster1.nb_band + 1): for window in get_block_windows(1000, raster1.x_size, raster1.y_size): array1 = raster1._gdal_dataset.GetRasterBand(band).ReadAsArray( *window).astype("float32") try: array2 = raster2._gdal_dataset.GetRasterBand(band).ReadAsArray( *window).astype("float32") except AttributeError: array2 = raster2 # If second input is not a raster but a scalar if op_type == "add": result = array1 + array2 elif op_type == "sub": result = array1 - array2 elif op_type == "mul": result = array1 * array2 elif op_type == "truediv": result = array1 / array2 else: result = None out_ds.GetRasterBand(band).WriteArray(result, window[0], window[1]) # Close dataset out_ds = None
def mask(self, mask, gdal_driver=gdal.GetDriverByName("Gtiff"), data_type=gdal.GetDataTypeByName('Float32'), all_touched=True, no_data=-999, window_size=100, nb_processes=mp.cpu_count(), chunksize=MP_CHUNK_SIZE): """ Apply mask to raster Parameters ---------- mask: geopandas.geodataframe or gistools.layer.GeoLayer Mask layer as a GeoDataFrame or GeoLayer gdal_driver: osgeo.gdal.Driver Driver used to write data to file data_type: int GDAL data type all_touched: bool if True, all touched pixels within layer boundaries are burnt, when clipping raster by mask no_data: int or float output no data value in masked raster window_size: int or list[int, int] Size of window for raster calculation nb_processes: int Number of processes for multiprocessing chunksize: int chunk size used in imap multiprocessing function Returns ------- """ return _raster_mask(self, mask, gdal_driver, data_type, no_data, all_touched, window_size, nb_processes, chunksize)
def compute(self, *args): import re ex_exp = self.expression type = gdal.GetDataTypeByName( self.types_list[self.types.get_history()]) numtype = gdalnumeric.GDALTypeCodeToNumericTypeCode(type) if numtype == None: gvutils.error("Error! Type " + numtype + " is not supported!") return FALSE fun_names_dict = {} fun_names_dict["max"] = ("maximum", 2) fun_names_dict["min"] = ("minimum", 2) fun_names_dict["asin"] = ("arcsin", 1) fun_names_dict["acos"] = ("arccos", 1) fun_names_dict["atan"] = ("arctan", 1) fun_names_dict["AND"] = ("bitwise_and", 2) fun_names_dict["OR"] = ("bitwise_or", 2) fun_names_dict["XOR"] = ("bitwise_xor", 2) fun_names_dict["inv"] = ("invert", 1) fun_names_dict["LShift"] = ("left_shift", 2) fun_names_dict["RShift"] = ("right_shift", 1) fun_names_dict['NDVI'] = ("self.NDVI", 2) sh_names_list = fun_names_dict.keys() for item in sh_names_list: ex_exp = re.sub(item, fun_names_dict[item][0], ex_exp) test_exp = ex_exp test_array = Numeric.zeros((1, 5), numtype) for i in range(len(self.list_of_bands)): patt_i = "%" + str(i + 1) repl_i = "sb[" + str(i) + "]" ex_exp = re.sub(patt_i, repl_i, ex_exp) test_exp = re.sub(patt_i, "test_array", test_exp) ex_exp = "rb=" + ex_exp test_exp = "test_res=" + test_exp try: exec test_exp except: gvutils.error("Illegal expression!") return FALSE if self.switch_new_view.get_active(): gview.app.new_view() b1_name = self.list_of_bands[self.s1_list.get_history()] band_list = [] for i in range(len(self.list_of_bands)): band_list.append(self.get_band(self.list_of_bands[i])) b1 = self.get_band(b1_name) proto_ds = self.dict_of_bands[b1_name][1].get_parent().get_dataset() self.out_buf = Numeric.zeros((b1.YSize, b1.XSize), numtype) sb = range(len(self.list_of_bands)) for y in range(b1.YSize): for i in range(len(self.list_of_bands)): sb[i] = \ gdalnumeric.BandReadAsArray(band_list[i],0,y,b1.XSize,1)[0] try: exec ex_exp except: gvutils.error("ZeroDivide?") return FALSE self.out_buf[y, 0:] = clip_result(numtype, rb).astype(numtype) res_ds = gdalnumeric.OpenArray(self.out_buf, proto_ds) gview.app.open_gdal_dataset(res_ds)
def processAlgorithm(self, parameters, context, feedback): source = self.parameterAsSource(parameters, self.INPUT, context) res = self.parameterAsDouble(parameters, self.RES, context) outwidth = self.parameterAsOutputLayer(parameters, self.OUTPUT, context) PINF = -3.402823466e+38 ext = source.sourceExtent() Xmin = ext.xMinimum() + res Xmax = ext.xMaximum() - res Ymin = ext.yMinimum() + res Ymax = ext.yMaximum() - res SizeX = Xmax - Xmin SizeY = Ymax - Ymin Nx = int(round(SizeX / res) + 1) Ny = int(round(SizeY / res) + 1) StepX = SizeX / (Nx - 1) StepY = SizeY / (Ny - 1) outRasterSRS = osr.SpatialReference() srs = source.sourceCrs() wkt = srs.toWkt() outRasterSRS.ImportFromWkt(wkt) opts = gdal.RasterizeOptions(outputBounds=[Xmin, Ymin, Xmax, Ymax], xRes=res, yRes=res, format="GTiff", burnValues=[1], outputSRS=outRasterSRS) QgsMessageLog.logMessage(outwidth) QgsMessageLog.logMessage(source.sourceName()) rasterized = "/Users/tsamsonov/GitHub/raster-space/rasterized.tif" gdal.Rasterize( rasterized, "/Users/tsamsonov/GitHub/raster-space/output/buildings_dem_s.shp", options=opts) src_ds = gdal.Open(rasterized) srcband = src_ds.GetRasterBand(1) drv = gdal.GetDriverByName('GTiff') outdist = '/Users/tsamsonov/GitHub/raster-space/dist.tif' dst_ds = drv.Create('/Users/tsamsonov/GitHub/raster-space/dist.tif', src_ds.RasterXSize, src_ds.RasterYSize, 1, gdal.GetDataTypeByName('Float32')) dst_ds.SetGeoTransform(src_ds.GetGeoTransform()) dst_ds.SetProjection(src_ds.GetProjectionRef()) dstband = dst_ds.GetRasterBand(1) # In this example I'm using target pixel values of 100 and 300. I'm also using Distance units as GEO but you can change that to PIXELS. gdal.ComputeProximity(srcband, dstband, ["DISTUNITS=GEO"]) dstband.FlushCache() dist = gdal.Open(outdist) if dist is None: QgsMessageLog.logMessage('Unable to open ' + outwidth) else: QgsMessageLog.logMessage(str(dist.RasterCount)) # npdist = np.array(dstband.ReadAsArray()) npdist = np.array(srcband.ReadAsArray()) # length testing QgsMessageLog.logMessage(str(npdist.shape)) npwid = np.full(npdist.shape, 0) QgsMessageLog.logMessage(str(npwid.shape)) nodata = -1 # npres = rspace.estimate_width(npdist, npwid, StepX, nodata) npres = rspace.estimate_length(npdist, npwid, StepX, nodata, 2048, 2000) QgsMessageLog.logMessage(str(StepX)) QgsMessageLog.logMessage(str(np.min(npdist))) QgsMessageLog.logMessage(str(np.max(npdist))) QgsMessageLog.logMessage(rspace.__file__) res = drv.Create(outwidth, src_ds.RasterXSize, src_ds.RasterYSize, 1, gdal.GetDataTypeByName('Float32')) res.SetGeoTransform(src_ds.GetGeoTransform()) res.SetProjection(src_ds.GetProjectionRef()) outband = res.GetRasterBand(1) outband.WriteArray(npres, 0, 0) outband.FlushCache() outband.SetNoDataValue(-1) return {self.OUTPUT: source}
def processAlgorithm(self, parameters, context, feedback): source = self.parameterAsRasterLayer(parameters, self.INPUT, context) output = self.parameterAsOutputLayer(parameters, self.OUTPUT, context) PINF = -3.402823466e+38 outRasterSRS = osr.SpatialReference() srs = source.crs() wkt = srs.toWkt() outRasterSRS.ImportFromWkt(wkt) src_ds = gdal.Open(source.dataProvider().dataSourceUri()) srcband = src_ds.GetRasterBand(1) StepX = src_ds.GetGeoTransform()[1] drv = gdal.GetDriverByName('GTiff') outdist = '/Users/tsamsonov/GitHub/raster-space/dist.tif' dst_ds = drv.Create(outdist, src_ds.RasterXSize, src_ds.RasterYSize, 1, gdal.GetDataTypeByName('Float32')) dst_ds.SetGeoTransform(src_ds.GetGeoTransform()) dst_ds.SetProjection(src_ds.GetProjectionRef()) dstband = dst_ds.GetRasterBand(1) # In this example I'm using target pixel values of 100 and 300. I'm also using Distance units as GEO but you can change that to PIXELS. gdal.ComputeProximity(srcband, dstband, ["DISTUNITS=GEO"]) dstband.FlushCache() dist = gdal.Open(outdist) if dist is None: QgsMessageLog.logMessage('Unable to open ' + outdist) else: QgsMessageLog.logMessage(str(dist.RasterCount)) npblocks = np.array(srcband.ReadAsArray()) # length testing npdist = np.array(dstband.ReadAsArray()) # length testing npwid0 = np.full(npdist.shape, 0) nplen0 = np.full(npdist.shape, 0) nodata = -1 npwid = rspace.estimate_width(npdist, npwid0, StepX, nodata) nplen = np.array( rspace.estimate_length(npblocks, npwid, StepX, nodata, 720, 12000)).reshape((4, npdist.shape[0], npdist.shape[1])) QgsMessageLog.logMessage(rspace.__file__) res = drv.Create(output, src_ds.RasterXSize, src_ds.RasterYSize, 5, gdal.GetDataTypeByName('Float32')) res.SetGeoTransform(src_ds.GetGeoTransform()) res.SetProjection(src_ds.GetProjectionRef()) outband = res.GetRasterBand(1) outband.WriteArray(npwid, 0, 0) outband = res.GetRasterBand(2) outband.WriteArray(nplen[0, :], 0, 0) outband = res.GetRasterBand(3) outband.WriteArray(nplen[1, :], 0, 0) outband = res.GetRasterBand(4) outband.WriteArray(nplen[2, :], 0, 0) outband = res.GetRasterBand(5) outband.WriteArray(nplen[3, :], 0, 0) outband.FlushCache() outband.SetNoDataValue(-1) return {self.OUTPUT: source}
elif arg == '-createonly': createonly = 1 elif arg == '-separate': separate = 1 elif arg == '-seperate': separate = 1 elif arg == '-pct': copy_pct = 1 elif arg == '-ot': i = i + 1 band_type = gdal.GetDataTypeByName(argv[i]) if band_type == gdal.GDT_Unknown: print 'Unknown GDAL data type: ', argv[i] sys.exit(1) elif arg == '-init': i = i + 1 pre_init = float(argv[i]) elif arg == '-n': i = i + 1 nodata = float(argv[i]) elif arg == '-f': # for backward compatibility. i = i + 1
def gdal_merge( out_file, input_files, format = 'GTiff', ul_lr = None, psize = None, separate = False, copy_pct = False, nodata = None, a_nodata = None, create_options = [], pre_init=[], band_type = 'Float32', createonly = False, bTargetAlignedPixels = False): start_time = time.time() gdal.AllRegister() band_type = gdal.GetDataTypeByName( band_type ) if band_type == gdal.GDT_Unknown: print('Unknown GDAL data type: %s' %band_type) return False if ul_lr: ulx = float(ul_lr[0]) uly = float(ul_lr[1]) lrx = float(ul_lr[2]) lry = float(ul_lr[3]) if len(input_files) == 0: print('No input files selected.') return False Driver = gdal.GetDriverByName(format) if Driver is None: print('Format driver %s not found, pick a supported driver.' % format) return False DriverMD = Driver.GetMetadata() if 'DCAP_CREATE' not in DriverMD: print('Format driver %s does not support creation and piecewise writing.\nPlease select a format that does, such as GTiff (the default) or HFA (Erdas Imagine).' % format) return False # Collect information on all the source files. file_infos = names_to_fileinfos( input_files ) if ul_lr is None: ulx = file_infos[0].ulx uly = file_infos[0].uly lrx = file_infos[0].lrx lry = file_infos[0].lry for fi in file_infos: ulx = min(ulx, fi.ulx) uly = max(uly, fi.uly) lrx = max(lrx, fi.lrx) lry = min(lry, fi.lry) if psize is None: psize = [file_infos[0].geotransform[1],file_infos[0].geotransform[5]] if band_type is None: band_type = file_infos[0].band_type # Try opening as an existing file. gdal.PushErrorHandler( 'CPLQuietErrorHandler' ) t_fh = gdal.Open( out_file, gdal.GA_Update ) gdal.PopErrorHandler() # Create output file if it does not already exist. if t_fh is None: if bTargetAlignedPixels: ulx = math.floor(ulx / psize[0]) * psize[0] lrx = math.ceil(lrx / psize[0]) * psize[0] lry = math.floor(lry / -psize[1]) * -psize[1] uly = math.ceil(uly / -psize[1]) * -psize[1] geotransform = [ulx, psize[0], 0, uly, 0, psize[1]] xsize = int((lrx - ulx) / geotransform[1] + 0.5) ysize = int((lry - uly) / geotransform[5] + 0.5) if separate != 0: bands=0 for fi in file_infos: bands=bands + fi.bands else: bands = file_infos[0].bands t_fh = Driver.Create( out_file, xsize, ysize, bands, band_type, create_options ) if t_fh is None: print('Creation failed, terminating gdal_merge.') return False t_fh.SetGeoTransform( geotransform ) t_fh.SetProjection( file_infos[0].projection ) if copy_pct: t_fh.GetRasterBand(1).SetRasterColorTable(file_infos[0].ct) else: if separate != 0: bands=0 for fi in file_infos: bands=bands + fi.bands if t_fh.RasterCount < bands : print('Existing output file has less bands than the input files. You should delete it before. Terminating gdal_merge.') return False else: bands = min(file_infos[0].bands,t_fh.RasterCount) # Do we need to set nodata value ? if a_nodata is not None: for i in range(t_fh.RasterCount): t_fh.GetRasterBand(i+1).SetNoDataValue(a_nodata) # Do we need to pre-initialize the whole mosaic file to some value? if pre_init is not None: if t_fh.RasterCount <= len(pre_init): for i in range(t_fh.RasterCount): t_fh.GetRasterBand(i+1).Fill( pre_init[i] ) elif len(pre_init) == 1: for i in range(t_fh.RasterCount): t_fh.GetRasterBand(i+1).Fill( pre_init[0] ) # Copy data from source files into output file. t_band = 1 if quiet == 0 and verbose == 0: progress( 0.0 ) fi_processed = 0 for fi in file_infos: if createonly != 0: continue if verbose != 0: print("") print("Processing file %5d of %5d, %6.3f%% completed in %d minutes." % (fi_processed+1,len(file_infos), fi_processed * 100.0 / len(file_infos), int(round((time.time() - start_time)/60.0)) )) fi.report() if separate == 0 : for band in range(1, bands+1): fi.copy_into( t_fh, band, band, nodata ) else: for band in range(1, fi.bands+1): fi.copy_into( t_fh, band, t_band, nodata ) t_band = t_band+1 fi_processed = fi_processed+1 if quiet == 0 and verbose == 0: progress( fi_processed / float(len(file_infos)) ) # Force file to be closed. t_fh = None return True
def calc_ndvi(srcfp, dstfp, args): # ndvi nodata value ndvi_nodata = -9999 # tolerance for floating point equality tol = 0.00001 # get basenames for src and dst files, get xml metadata filenames srcdir, srcfn = os.path.split(srcfp) dstdir, dstfn = os.path.split(dstfp) bn, ext = os.path.splitext(srcfn) src_xml = os.path.join(srcdir, bn + '.xml') dst_xml = os.path.join(dstdir, bn + '_ndvi.xml') #### Get working dir if args.wd is not None: wd = args.wd else: wd = dstdir if not os.path.isdir(wd): try: os.makedirs(wd) except OSError: pass logger.info("Working Dir: %s", wd) print("Image: {}".format(srcfn)) ## copy source image to working directory srcfp_local = os.path.join(wd, srcfn) if not os.path.isfile(srcfp_local): shutil.copy2(srcfp, srcfp_local) ## open image and get band numbers ds = gdal.Open(srcfp_local) if ds: bands = ds.RasterCount if bands == 8: red_band_num = 5 nir_band_num = 7 elif bands == 4: red_band_num = 3 nir_band_num = 4 else: logger.error("Cannot calculate NDVI from a %i band image: %s", bands, srcfp_local) return 1 else: logger.error("Cannot open target image: %s", srcfp_local) return 1 ## check for input data type - must be float or int datatype = ds.GetRasterBand(1).DataType if datatype not in [1, 2, 3, 4, 5, 6, 7]: logger.error("Invalid input data type %s", datatype) return 1 ## get the raster dimensions nx = ds.RasterXSize ny = ds.RasterYSize ## open output file for write and copy proj/geotransform info if not os.path.isfile(dstfp): dstfp_local = os.path.join(wd, os.path.basename(dstfp)) gtiff_options = ['TILED=YES', 'COMPRESS=LZW', 'BIGTIFF=IF_SAFER'] driver = gdal.GetDriverByName('GTiff') out_ds = driver.Create(dstfp_local, nx, ny, 1, gdal.GetDataTypeByName(args.outtype), gtiff_options) if out_ds: out_ds.SetGeoTransform(ds.GetGeoTransform()) out_ds.SetProjection(ds.GetProjection()) ndvi_band = out_ds.GetRasterBand(1) ndvi_band.SetNoDataValue(float(ndvi_nodata)) else: logger.error("Couldn't open for write: %s", dstfp_local) return 1 ## for red and nir bands, get band data, nodata values, and natural block size ## if NoData is None default it to zero. red_band = ds.GetRasterBand(red_band_num) if red_band is None: logger.error("Can't load band %i from %s", red_band_num, srcfp_local) return 1 red_nodata = red_band.GetNoDataValue() if red_nodata is None: logger.info("Defaulting red band nodata to zero") red_nodata = 0.0 (red_xblocksize, red_yblocksize) = red_band.GetBlockSize() nir_band = ds.GetRasterBand(nir_band_num) if nir_band is None: logger.error("Can't load band %i from %s", nir_band_num, srcfp_local) return 1 nir_nodata = nir_band.GetNoDataValue() if nir_nodata is None: logger.info("Defaulting nir band nodata to zero") nir_nodata = 0.0 (nir_xblocksize, nir_yblocksize) = nir_band.GetBlockSize() ## if different block sizes choose the smaller of the two xblocksize = min([red_xblocksize, nir_xblocksize]) yblocksize = min([red_yblocksize, nir_yblocksize]) ## calculate the number of x and y blocks to read/write nxblocks = int(math.floor(nx + xblocksize - 1) / xblocksize) nyblocks = int(math.floor(ny + yblocksize - 1) / yblocksize) ## blocks loop yblockrange = range(nyblocks) xblockrange = range(nxblocks) for yblock in yblockrange: ## y offset for ReadAsArray yoff = yblock * yblocksize ## get block actual y size in case of partial block at edge if yblock < nyblocks - 1: block_ny = yblocksize else: block_ny = ny - (yblock * yblocksize) for xblock in xblockrange: ## x offset for ReadAsArray xoff = xblock * xblocksize ## get block actual x size in case of partial block at edge if xblock < (nxblocks - 1): block_nx = xblocksize else: block_nx = nx - (xblock * xblocksize) ## read a block from each band red_array = red_band.ReadAsArray(xoff, yoff, block_nx, block_ny) nir_array = nir_band.ReadAsArray(xoff, yoff, block_nx, block_ny) ## generate mask for red nodata, nir nodata, and ## (red+nir) less than tol away from zero red_mask = (red_array == red_nodata) if red_array[red_mask] != []: nir_mask = (nir_array == nir_nodata) if nir_array[nir_mask] != []: divzero_mask = abs(nir_array + red_array) < tol if red_array[divzero_mask] != []: ndvi_mask = red_mask | nir_mask | divzero_mask else: ndvi_mask = red_mask | nir_mask else: divzero_mask = abs(nir_array + red_array) < tol if red_array[divzero_mask] != []: ndvi_mask = red_mask | divzero_mask else: ndvi_mask = red_mask else: nir_mask = (nir_array == nir_nodata) if nir_array[nir_mask] != []: divzero_mask = abs(nir_array + red_array) < tol if red_array[divzero_mask] != []: ndvi_mask = nir_mask | divzero_mask else: ndvi_mask = nir_mask else: divzero_mask = abs(nir_array + red_array) < tol if red_array[divzero_mask] != []: ndvi_mask = divzero_mask else: ndvi_mask = numpy.full_like(red_array, fill_value=0, dtype=numpy.bool) ## declare ndvi array, init to nodata value ndvi_array = numpy.full_like(red_array, fill_value=ndvi_nodata, dtype=numpy.float32) ## cast bands to float for calc red_asfloat = numpy.array(red_array, dtype=numpy.float32) red_array = None nir_asfloat = numpy.array(nir_array, dtype=numpy.float32) nir_array = None ## calculate ndvi if ndvi_array[~ndvi_mask] != []: ndvi_array[~ndvi_mask] = numpy.divide(numpy.subtract(nir_asfloat[~ndvi_mask], red_asfloat[~ndvi_mask]), numpy.add(nir_asfloat[~ndvi_mask], red_asfloat[~ndvi_mask])) red_asfloat = None nir_asfloat = None ## scale and cast to int if outtype integer if args.outtype == 'Int16': ndvi_scaled = numpy.full_like(ndvi_array, fill_value=ndvi_nodata, dtype=numpy.int16) if ndvi_scaled[~ndvi_mask] != []: ndvi_scaled[~ndvi_mask] = numpy.array(ndvi_array[~ndvi_mask]*1000.0, dtype=numpy.int16) ndvi_array = ndvi_scaled ndvi_scaled = None ndvi_mask = None ## write valid portion of ndvi array to output file ndvi_band.WriteArray(ndvi_array, xoff, yoff) ndvi_array = None out_ds = None ds = None if os.path.isfile(dstfp_local): ## add pyramids cmd = 'gdaladdo "{}" 2 4 8 16'.format(dstfp_local) taskhandler.exec_cmd(cmd) ## copy to dst if wd != dstdir: shutil.copy2(dstfp_local, dstfp) ## copy xml to dst if os.path.isfile(src_xml): shutil.copy2(src_xml, dst_xml) else: logger.warning("xml %s not found", src_xml) ## Delete Temp Files temp_files = [srcfp_local] wd_files = [dstfp_local] if not args.save_temps: for f in temp_files: try: os.remove(f) except Exception as e: logger.warning('Could not remove %s: %s', os.path.basename(f), e) if wd != dstdir: for f in wd_files: try: os.remove(f) except Exception as e: logger.warning('Could not remove %s: %s', os.path.basename(f), e) else: logger.error("pgc_ndvi.py: %s was not created", dstfp_local) return 1 else: logger.info("pgc_ndvi.py: file %s already exists", dstfp) ## copy xml to dst if missing if not os.path.isfile(dst_xml): shutil.copy2(src_xml, dst_xml) return 0
def ParseType(type): gdal_dt = gdal.GetDataTypeByName(type) if gdal_dt is GDT_Unknown: gdal_dt = GDT_Byte return gdal_dt
def guess_cb(self, *args): """Guess image geometry parameters.""" def correlation(array1, array2): """Calculate correlation coefficient of two arrays.""" n_elems = float(array1.shape[0]) M1 = Numeric.add.reduce(array1) M2 = Numeric.add.reduce(array2) D1 = Numeric.add.reduce(array1 * array1) - M1 * M1 / n_elems D2 = Numeric.add.reduce(array2 * array2) - M2 * M2 / n_elems K = (Numeric.add.reduce(array1 * array2) - M1 * M2 / n_elems) / math.sqrt(D1 * D2) return K header = long(self.header_entry.get_text()) width = long(self.width_entry.get_text()) height = long(self.height_entry.get_text()) bands = long(self.bands_entry.get_text()) gdaltype = \ gdal.GetDataTypeByName(self.type_list[self.type_menu.get_history()]) numtype = gdalnumeric.GDALTypeCodeToNumericTypeCode(gdaltype) depth = gdal.GetDataTypeSize(gdaltype) / 8 filename = self.open_entry.get_text() if os.path.isfile(filename) == 0: gvutils.error('Input file '+filename+' does not exist!') return filesize = os.stat(filename)[ST_SIZE] if filesize < header: gvutils.error('Specified header size larger then file size!') return imagesize = (filesize - header) / bands / depth if width != 0 and height == 0: height = imagesize / width elif width == 0 and height != 0: width = imagesize / height else: rawfile = open(filename, 'rb') longt = 40.0 # maximum possible height/width ratio cor_coef = 0.0 w = long(math.sqrt(imagesize / longt)) w_max = long(math.sqrt(imagesize * longt)) if (self.swap_menu.get_history() == 0 \ and sys.byteorder == 'little') or \ (self.swap_menu.get_history() == 1 and sys.byteorder == 'big'): swap = 0 else: swap = 1 while w < w_max: if imagesize % w == 0: scanlinesize = w * depth h = imagesize / w rawfile.seek(header + h / 2 * scanlinesize) buf1 = rawfile.read(scanlinesize) buf2 = rawfile.read(scanlinesize) a1 = Numeric.fromstring(buf1, numtype) a2 = Numeric.fromstring(buf2, numtype) if swap: a1.byteswapped() a2.byteswapped() try: tmp = correlation(a1.astype(Numeric.Float32), a2.astype(Numeric.Float32)) except: # catch 0 division errors gvutils.error('Unable to guess image geometry!') return if tmp > cor_coef: cor_coef = tmp width = w height = h w += 1 self.width_entry.set_text(str(width)) self.height_entry.set_text(str(height))
def gdal_calc(calculation, raster_output, rasters, bands=None, nodata=None, allBands=False, output_type=None, format='GTiff'): """ Adopted from GDAL 1.10 gdal_calc.py script. :param calculation: equation to calculate, such as A + (B / 2) :param raster_output: Raster file to save output as :param rasters: array of rasters, should equal # of letters in calculation :param bands: array of band numbers, one for each raster in rasters array :param nodata: NoDataValue to use in output raster :param allBands: use all bands of specified raster by index :param output_type: data type for output raster ('Float32', 'Uint16', etc) :return: gdal Dataset """ calculation = re.sub(r'(logical_|bitwise_)', r'numpy.\1', calculation) # set up some lists to store data for each band datasets = [get_dataset(raster) for raster in rasters] if not bands: bands = [1 for raster in rasters] datatypes = [] datatype_nums = [] nodata_vals = [] dimensions = None alpha_list = string.ascii_uppercase[:len(rasters)] # loop through input files - checking dimensions for i, (raster, alpha, band) in enumerate(zip(datasets, alpha_list, bands)): raster_band = raster.GetRasterBand(band) datatypes.append(gdal.GetDataTypeName(raster_band.DataType)) datatype_nums.append(raster_band.DataType) nodata_vals.append(raster_band.GetNoDataValue()) # check that the dimensions of each layer are the same as the first if dimensions: if dimensions != [ datasets[i].RasterXSize, datasets[i].RasterYSize ]: datasets[i] = gdal_resize(raster, dimensions, datasets[0].GetProjection(), datasets[0].GetGeoTransform()) else: dimensions = [datasets[0].RasterXSize, datasets[0].RasterYSize] # process allBands option allbandsindex = None allbandscount = 1 if allBands: allbandscount = datasets[allbandsindex].RasterCount if allbandscount <= 1: allbandsindex = None ################################################################ # set up output file ################################################################ # open output file exists # remove existing file and regenerate if os.path.isfile(raster_output): os.remove(raster_output) # create a new file logger.debug("Generating output file %s" % (raster_output)) # find data type to use if not output_type: # use the largest type of the input files output_type = gdal.GetDataTypeName(max(datatype_nums)) # create file output_driver = gdal.GetDriverByName('MEM') output_dataset = output_driver.Create('', dimensions[0], dimensions[1], allbandscount, gdal.GetDataTypeByName(output_type)) # set output geo info based on first input layer output_dataset.SetGeoTransform(datasets[0].GetGeoTransform()) output_dataset.SetProjection(datasets[0].GetProjection()) if nodata is None: nodata = ndv_lookup[output_type] for i in range(1, allbandscount + 1): output_band = output_dataset.GetRasterBand(i) output_band.SetNoDataValue(nodata) # write to band output_band = None ################################################################ # find block size to chop grids into bite-sized chunks ################################################################ # use the block size of the first layer to read efficiently block_size = datasets[0].GetRasterBand(bands[0]).GetBlockSize() # store these numbers in variables that may change later n_x_valid = block_size[0] n_y_valid = block_size[1] # find total x and y blocks to be read n_x_blocks = int((dimensions[0] + block_size[0] - 1) / block_size[0]) n_y_blocks = int((dimensions[1] + block_size[1] - 1) / block_size[1]) buffer_size = block_size[0] * block_size[1] ################################################################ # start looping through each band in allbandscount ################################################################ for band_num in range(1, allbandscount + 1): ################################################################ # start looping through blocks of data ################################################################ # loop through X-lines for x in range(0, n_x_blocks): # in the rare (impossible?) case that the blocks don't fit perfectly # change the block size of the final piece if x == n_x_blocks - 1: n_x_valid = dimensions[0] - x * block_size[0] buffer_size = n_x_valid * n_y_valid # find X offset x_offset = x * block_size[0] # reset buffer size for start of Y loop n_y_valid = block_size[1] buffer_size = n_x_valid * n_y_valid # loop through Y lines for y in range(0, n_y_blocks): # change the block size of the final piece if y == n_y_blocks - 1: n_y_valid = dimensions[1] - y * block_size[1] buffer_size = n_x_valid * n_y_valid # find Y offset y_offset = y * block_size[1] # create empty buffer to mark where nodata occurs nodatavalues = numpy.zeros(buffer_size) nodatavalues.shape = (n_y_valid, n_x_valid) # fetch data for each input layer for i, alpha in enumerate(alpha_list): # populate lettered arrays with values if allbandsindex is not None and allbandsindex == i: this_band = band_num else: this_band = bands[i] band_vals = BandReadAsArray( datasets[i].GetRasterBand(this_band), xoff=x_offset, yoff=y_offset, win_xsize=n_x_valid, win_ysize=n_y_valid) # fill in nodata values nodatavalues = 1 * numpy.logical_or( nodatavalues == 1, band_vals == nodata_vals[i]) # create an array of values for this block exec("%s=band_vals" % alpha) band_vals = None # try the calculation on the array blocks try: calc_result = eval(calculation) except Exception as e: logger.error("eval of calculation %s failed" % calculation) raise e # propogate nodata values # (set nodata cells to 0 then add nodata value to these cells) calc_result = ((1 * (nodatavalues == 0)) * calc_result) + \ (nodata * nodatavalues) # write data block to the output file output_band = output_dataset.GetRasterBand(band_num) BandWriteArray(output_band, calc_result, xoff=x_offset, yoff=y_offset) if raster_output: output_driver = gdal.GetDriverByName(format) outfile = output_driver.CreateCopy(raster_output, output_dataset, False) logger.debug(str(outfile)) return output_dataset
from urllib.request import urlretrieve import tempfile import os from tqdm import tqdm from pyrasta.raster import DigitalElevationModel from pyrasta.utils import digitize, TqdmUpTo import gdal CGIAR_ARCHIVE_FORMAT = "zip" CGIAR_URL = "http://srtm.csi.cgiar.org/wp-content/uploads/files/srtm_5x5/TIFF" CGIAR_NO_DATA = -32768 CGIAR_DATA_TYPE = gdal.GetDataTypeByName('Int16') def _download_srtm_tile(tile_name): """ Download and extract SRTM tile archive Description ----------- Parameters ---------- tile_name: str SRTM tile name """ zip_name, tif_name = tile_name + "." + CGIAR_ARCHIVE_FORMAT, tile_name + '.tif' url = os.path.join(CGIAR_URL, zip_name)