def vector2arrayinv(self,raster,lsd,invzero): rlayer = QgsRasterLayer(raster, "layer") if not rlayer.isValid(): print("Layer failed to load!") ext=rlayer.extent()#xmin xm = ext.xMinimum() xM = ext.xMaximum() ym = ext.yMinimum() yM = ext.yMaximum() pxlw=rlayer.rasterUnitsPerPixelX() pxlh=(rlayer.rasterUnitsPerPixelY())*(-1) newXNumPxl=(np.ceil(abs(xM-xm)/(rlayer.rasterUnitsPerPixelX()))-1).astype(int) newYNumPxl=(np.ceil(abs(yM-ym)/(rlayer.rasterUnitsPerPixelY()))-1).astype(int) sizex=newXNumPxl sizey=newYNumPxl origine=[xm,yM] driverd = ogr.GetDriverByName('ESRI Shapefile') ds9 = driverd.Open(lsd) layer = ds9.GetLayer() self.ref = layer.GetSpatialRef() count=0 for feature in layer: count+=1 geom = feature.GetGeometryRef() xy=np.array([geom.GetX(),geom.GetY()]) try: XY=np.vstack((XY,xy)) except: XY=xy size=np.array([pxlw,pxlh]) OS=np.array([xm,yM]) NumPxl=(np.ceil(abs((XY-OS)/size)-1)).astype(int)#from 0 first cell print(NumPxl) print(sizey,sizex,'dimensioni inventario') valuess=np.zeros(np.shape(invzero),dtype='float32') try: #print(np.max(NumPxl[0,1])) #print(np.max(NumPxl[0,0])) #print(np.min(NumPxl[0,1])) #print(NumPxl[0,0]) #print(count) for i in range(count): #print(i,'i') if XY[i,1]<=yM and XY[i,1]>=ym and XY[i,0]<=xM and XY[i,0]>=xm: valuess[NumPxl[i,1].astype(int),NumPxl[i,0].astype(int)]=1 except:#only 1 feature if XY[1]<=yM and XY[1]>=ym and XY[0]<=xM and XY[0]>=xm: valuess[NumPxl[1].astype(int),NumPxl[0].astype(int)]=1 fuori = valuess.astype(np.float32) self.array2raster('/tmp/04inventory.tif',pxlw,pxlh,fuori,OS) return fuori
def cutextent(self, in1, in2,raster): rlayer = QgsRasterLayer(raster, "layer") if not rlayer.isValid(): print("Layer failed to load!") ext=rlayer.extent()#xmin xm = ext.xMinimum() xM = ext.xMaximum() ym = ext.yMinimum() yM = ext.yMaximum() pxlw=rlayer.rasterUnitsPerPixelX() pxlh=(rlayer.rasterUnitsPerPixelY())*(-1) newXNumPxl=(np.ceil(abs(xM-xm)/(rlayer.rasterUnitsPerPixelX()))-1).astype(int) newYNumPxl=(np.ceil(abs(yM-ym)/(rlayer.rasterUnitsPerPixelY()))-1).astype(int) sizex=newXNumPxl sizey=newYNumPxl origine=[xm,yM] if os.path.isfile(in2): os.remove(in2) os.system('gdal_translate -a_srs '+str(self.epsg)+' -a_nodata -9999 -of GTiff -ot Float32 -projwin ' +str(xm)+' '+str(yM)+' '+ str(xM) + ' ' + str(ym) + ' -co COMPRESS=DEFLATE -co PREDICTOR=1 -co ZLEVEL=6 '+ in1 +' '+in2)
def raster_nodata(path_raster): rlayer = QgsRasterLayer(path_raster, "raster") extent = rlayer.extent() provider = rlayer.dataProvider() rows = rlayer.rasterUnitsPerPixelY() cols = rlayer.rasterUnitsPerPixelX() block = provider.block(1, extent, rows, cols) no_data = block.noDataValue() return no_data
def test_enum_conversion(self): """Test regression GH #43245""" tmp = QTemporaryDir() origin = os.path.join(TEST_DATA_DIR, 'raster', 'band1_byte_ct_epsg4326.tif') dest = os.path.join(tmp.path(), 'band1_byte_ct_epsg4326.tif') shutil.copyfile(origin, dest) layer = QgsRasterLayer(dest, 'rast', 'gdal') stats = QgsZonalStatistics.calculateStatistics( layer.dataProvider(), QgsGeometry.fromWkt(layer.extent().asWktPolygon()), layer.rasterUnitsPerPixelX(), layer.rasterUnitsPerPixelY(), 1, QgsZonalStatistics.Statistic.Max | QgsZonalStatistics.Statistic.Median) self.assertEqual(sorted(list(stats.keys())), [ QgsZonalStatistics.Statistic.Median, QgsZonalStatistics.Statistic.Max ]) self.assertEqual(stats[QgsZonalStatistics.Statistic.Median], 142.0) self.assertEqual(stats[QgsZonalStatistics.Statistic.Max], 254.0)
class TestQGISRasterTools(unittest.TestCase): def setUp(self): self.raster = QgsRasterLayer(RASTER_BASE + '.tif', 'test') self.provider = self.raster.dataProvider() self.extent = self.raster.extent() self.x_res = self.raster.rasterUnitsPerPixelX() self.y_res = self.raster.rasterUnitsPerPixelY() def test_pixels_to_points(self): points = pixels_to_points( self.raster, threshold_min=1.0, threshold_max=1.5) # There are four such pixels only self.assertEquals(points.featureCount(), 4) for point in points.dataProvider().getFeatures(): point = point.geometry().asPoint() # Move point in center of the pixels and get the value value = self.provider.identify( QgsPoint( point.x() + 0.5 * self.x_res, point.y() - 0.5 * self.y_res), QgsRaster.IdentifyFormatValue, self.extent) value = value.results()[1] self.assertGreater(value, 1.0) self.assertLess(value, 1.5) # Infinite threshold test points = pixels_to_points(self.raster, threshold_min=1.1) self.assertEquals(points.featureCount(), 8) for point in points.dataProvider().getFeatures(): point = point.geometry().asPoint() # Move point in center of the pixels and get the value value = self.provider.identify( QgsPoint( point.x() + 0.5 * self.x_res, point.y() - 0.5 * self.y_res), QgsRaster.IdentifyFormatValue, self.extent) value = value.results()[1] self.assertGreater(value, 1.1) test_pixels_to_points.slow = True def test_polygonize(self): """Test if polygonize works""" geometry = polygonize( self.raster, threshold_min=1.0, threshold_max=1.5) # Result is one square self.assertTrue(geometry.isGeosValid()) self.assertFalse(geometry.isMultipart()) # noinspection PyArgumentEqualDefault geometry = polygonize(self.raster, threshold_min=0.0) # Result is several polygons self.assertTrue(geometry.isGeosValid()) self.assertTrue(geometry.isMultipart()) expected = QgsVectorLayer(VECTOR_BASE + '.shp', 'test', 'ogr') for feature in expected.getFeatures(): # the layer has one feature only expected_geom = feature.geometry() self.assertTrue((geometry.isGeosEqual(expected_geom))) test_polygonize.slow = True def test_clip_raster(self): """Test clip_raster work""" new_raster = clip_raster( self.raster, self.raster.width(), self.raster.height(), self.extent ) self.assertEqual(self.raster.rasterUnitsPerPixelY(), new_raster.rasterUnitsPerPixelY()) self.assertEqual(self.raster.rasterUnitsPerPixelX(), new_raster.rasterUnitsPerPixelX()) self.assertEqual(self.raster.extent(), new_raster.extent()) self.assertEqual(self.raster.width(), new_raster.width()) self.assertEqual(self.raster.height(), new_raster.height()) # Set extent as 1/2 of self.extent center = self.extent.center() x_max, y_max = center.x(), center.y() new_extent = QgsRectangle( self.extent.xMinimum(), self.extent.yMinimum(), x_max, y_max ) new_raster = clip_raster( self.raster, self.raster.width(), self.raster.height(), new_extent ) self.assertAlmostEquals( self.raster.rasterUnitsPerPixelY(), 2 * new_raster.rasterUnitsPerPixelY()) self.assertAlmostEquals( self.raster.rasterUnitsPerPixelX(), 2 * new_raster.rasterUnitsPerPixelX()) self.assertEqual(new_extent, new_raster.extent()) self.assertEqual(self.raster.width(), new_raster.width()) self.assertEqual(self.raster.height(), new_raster.height()) test_clip_raster.slow = True
def get_cellsize(rst, xy=False, bnd=None, gisApi='gdal'): """ Return cellsize of one or more Raster Datasets In the case of groups, the result will be: d = { 'path_to_raster1': cellsize_raster_1, 'path_to_raster2': cellsize_raster_2, 'path_to_raster3': cellsize_raster_3, ..., 'path_to_rastern': cellsize_raster_n, } API'S Available: * gdal; * arcpy; * pygrass """ import os if gisApi == 'gdal': from osgeo import gdal def __get_cellsize(__rst): img = gdal.Open(__rst) (upper_left_x, x_size, x_rotation, upper_left_y, y_rotation, y_size) = img.GetGeoTransform() return int(x_size), int(y_size) def __loop(files, __xy): return {f : __get_cellsize(f) for f in files} if __xy \ else {f : __get_cellsize(f)[0] for f in files} if os.path.exists(rst): if os.path.isfile(rst): xs, ys = __get_cellsize(rst) if not xy: return xs else: return [xs, xy] elif os.path.isdir(rst): from gasp.oss import list_files rsts = list_files(rst, file_format=gdal_drivers().keys()) return __loop(rsts, xy) else: raise ValueError('The path exists but is not a file or dir') else: if type(rst) == list: return __loop(rst, xy) else: raise ValueError(( 'Invalid object rst. Please insert a path to a raster, ' 'a path to a directory with rasters or a list with ' 'rasters path.' )) elif gisApi == 'arcpy': import arcpy from gasp.cpu.arcg.lyr import rst_lyr, checkIfRstIsLayer def _get_cell_arc(_r): # Check if r is a Raster Layer isRaster = checkIfRstIsLayer(_r) lyr = rst_lyr(_r) if not isRaster else _r cellsizeX = arcpy.GetRasterProperties_management( lyr, "CELLSIZEX", "" if not bnd else bnd ) cellsizeY = arcpy.GetRasterProperties_management( lyr, "CELLSIZEY", "" if not bnd else bnd ) if xy: if str(cellsizeY) != str(cellsizeX): raise ValueError(( 'Cellsize is not the same in both dimensions (x, y)' )) else: return int(str(cellsizeX)) else: return int(str(cellsizeX)), int(str(cellsizeY)) def get_cellsize2(rst): describe = arcpy.Describe(rst) return describe.MeanCellWidth, describe.MeanCellHeight def _loop(files): return {f : _get_cell_arc(f) for f in files} if os.path.exists(rst): if os.path.isfile(rst): CELLSIZE = _get_cell_arc(rst) return CELLSIZE elif os.path.isdir(rst): from gasp.oss import list_files rsts = list_files(rst) return _loop(rsts) else: raise ValueError('The path exists but is not a file or dir') else: if type(rst) == list: return _loop(rst) else: raise ValueError(( 'Invalid object rst. Please insert a path to a raster, ' 'a path to a directory with rasters or a list with ' 'rasters path.' )) elif gisApi == 'qgis': from qgis.core import QgsRasterLayer rasterLyr = QgsRasterLayer(rst, "lyr") x = rasterLyr.rasterUnitsPerPixelX() if xy: y = rasterLyr.rasterUnitsPerPixelY() return x, y else: return x elif gisApi == 'pygrass': import grass.script as grass dic = grass.raster.raster_info(rst) return dic['nsres'] else: raise ValueError('The api {} is not available'.format(gisApi))
def fwdet(inundation_polygon, dem, water_depth_output_filename=None): ''' Calculate water depth from a flood extent polygon (e.g. from remote sensing analysis) based on an underlying DEM. Program procedure: 1. Extract a clipping DEM using the inundPolygon and elevation DEM 2. Extract polyline from inundPolygon 3. Convert polyline to raster 4. Associate raster line values with underlying DEM values 5. Use grass7 Grow Distance function to calculate approximated flooding water level 6. Run saga gaussian filter to smooth the the grass7 Grow Distance output Publication: Cohen et al., https://doi.org/10.1111/1752-1688.12609 ''' from os import system from os.path import dirname, join, splitext from shutil import copyfile, copy2 # Qgis imports import processing from qgis.core import QgsRasterLayer, QgsRasterFileWriter, QgsRasterPipe, QgsVectorLayer, QgsProject dem_layer = QgsRasterLayer(dem, 'dem_extent') dem_extent = float_extent(dem_layer) dem_size_x, dem_size_y = dem_layer.rasterUnitsPerPixelX( ), dem_layer.rasterUnitsPerPixelY() # Function input parameter dictionaries inudation_polygon_input = { 'INPUT': inundation_polygon, 'OUTPUT': 'TEMPORARY_OUTPUT', } clip_input = { 'INPUT': dem, 'POLYGONS': inundation_polygon, 'OUTPUT': 'TEMPORARY_OUTPUT', } # End function input parameter dictionaries # Begin processing # Fix inundation polygon geometries flood_extent_polygon = processing.run("native:fixgeometries", inudation_polygon_input)['OUTPUT'] polygons_to_lines_input = { 'INPUT': flood_extent_polygon, 'OUTPUT': 'TEMPORARY_OUTPUT', } # Polygons to polylines proceedure flood_extent_polyline = processing.run("native:polygonstolines", polygons_to_lines_input)['OUTPUT'] # Clip dem to inundation polygon clip_dem = processing.run("saga:cliprasterwithpolygon", clip_input)['OUTPUT'] rasterize_input = { 'INPUT': flood_extent_polyline, 'FIELD': '', 'BURN': 1, 'UNITS': 1, 'WIDTH': dem_size_x, 'HEIGHT': dem_size_y, 'EXTENT': float_extent(flood_extent_polyline), 'NODATA': 0, 'OPTIONS': '', 'DATA_TYPE': 0, 'INIT': None, 'INVERT': False, 'EXTRA': '', 'OUTPUT': 'TEMPORARY_OUTPUT' } flood_extent_rasterized = processing.run("gdal:rasterize", rasterize_input)['OUTPUT'] # associate underlying dem values to lineRaster extracted_elevation = raster_calculator([flood_extent_rasterized, dem], '({0} * {1}) / {0}', 0, 'extracted_elevation.tif') grow_distance_input = { 'input': extracted_elevation, 'metric': 0, '-m': False, '-': False, 'distance': 'TEMPORARY_OUTPUT', 'value': 'TEMPORARY_OUTPUT', 'GRASS_REGION_PARAMETER': None, 'GRASS_REGION_CELLSIZE_PARAMETER': 0, 'GRASS_RASTER_FORMAT_OPT': '', 'GRASS_RASTER_FORMAT_META': '', 'value': join(dirname(extracted_elevation), 'euclidean_nearest.tif') } euclidean_nearest = processing.run("grass7:r.grow.distance", grow_distance_input)['value'] # clip grow distance output using clipDEM flood_water_depth = raster_calculator([clip_dem, euclidean_nearest], '(({1} - {0}) > 0) * ({1} - {0})', 0, 'waterDepth.tif') low_pass_filter_input = { 'INPUT': flood_water_depth, 'SIGMA': 1, 'MODE': 0, 'RADIUS': 3, 'RESULT': 'TEMPORARY_OUTPUT' } low_pass_filter = processing.run("saga:gaussianfilter", low_pass_filter_input)['RESULT'] if water_depth_output_filename: copyfile(flood_water_depth, water_depth_output_filename) low_pass_water_depth_output_filename = '{}_low_pass.{}'.format( splitext(water_depth_output_filename)[0], 'tif') low_pass_outfile_input = { 'INPUT': low_pass_filter, 'TARGET_CRS': None, 'NODATA': None, 'COPY_SUBDATASETS': False, 'OPTIONS': '', 'EXTRA': '', 'DATA_TYPE': 0, 'OUTPUT': low_pass_water_depth_output_filename } processing.run("gdal:translate", low_pass_outfile_input)
def get_cellsize(rst, xy=False, bnd=None, gisApi='gdal'): """ Return cellsize of one or more Raster Datasets In the case of groups, the result will be: d = { 'path_to_raster1': cellsize_raster_1, 'path_to_raster2': cellsize_raster_2, 'path_to_raster3': cellsize_raster_3, ..., 'path_to_rastern': cellsize_raster_n, } API'S Available: * gdal; * pygrass """ import os if gisApi == 'gdal': from osgeo import gdal from gasp.g.prop.img import get_cell_size if type(rst) != list: if os.path.exists(rst) and os.path.isdir(rst): from gasp.pyt.oss import lst_ff rsts = lst_ff(rst, file_format=gdal_drivers.keys()) elif os.path.exists(rst) and os.path.isfile(rst): rsts = [rst] else: raise ValueError( 'Invalid object rst. Please insert a path to a raster, ' 'a path to a directory with rasters or a list with ' 'rasters path.' ) else: rsts = rst cs = {} for r in rsts: imgsrc = gdal.Open(r) cs[r] = get_cell_size( imgsrc) if xy else get_cell_size(imgsrc)[0] return cs[rsts[0]] if len(rsts) == 1 else cs elif gisApi == 'qgis': from qgis.core import QgsRasterLayer rasterLyr = QgsRasterLayer(rst, "lyr") x = rasterLyr.rasterUnitsPerPixelX() if xy: y = rasterLyr.rasterUnitsPerPixelY() return x, y else: return x elif gisApi == 'pygrass': import grass.script as grass dic = grass.raster.raster_info(rst) return dic['nsres'] else: raise ValueError('The api {} is not available'.format(gisApi))
def readRasterLayer(i, allBandData): # pylint: disable=too-many-locals fileInfo = QFileInfo(shared.rasterFileName[i]) fileBaseName = fileInfo.baseName() layer = QgsRasterLayer(shared.rasterFileName[i], fileBaseName) if not layer.isValid(): shared.fpOut.write("Raster layer '" + shared.rasterFileName[i] + "'failed to load") return -1 # Store the title as the first list item allBandData.append(shared.rasterFileTitle[i]) # Get more info xSize = layer.width() ySize = layer.height() cellWidth = layer.rasterUnitsPerPixelX() cellHeight = layer.rasterUnitsPerPixelY() provider = layer.dataProvider() extnt = provider.extent() dpi = provider.dpi() shared.fpOut.write("Raster layer '" + shared.rasterFileTitle[i] + "' loaded with X, Y resolution = " + str(cellWidth) + ", " + str(cellHeight) + " m\n") #shared.fpOut.write(layer.metadata()) #shared.fpOut.write(layer.rasterType()) # Store the above as the second list item allBandData.append( [provider, xSize, ySize, cellWidth, cellHeight, extnt, dpi]) # Now store the data for each band as a QgsRasterBlock nBands = layer.bandCount() for band in range(nBands): #shared.fpOut.write(layer.bandName(i)) bandData = provider.block(band, extnt, xSize, ySize) # Store as a further list item allBandData.append(bandData) # Sort out style #shared.fpOut.write("Style file " + str(i) + " is " + shared.rasterFileStyle[i]) if not shared.rasterFileStyle[i]: # No style file specified, so try the default style for this layer shared.rasterFileStyle[i] = layer.styleURI() #shared.fpOut.write("Trying default style file " + shared.rasterFileStyle[i]) if not layer.loadDefaultStyle(): shared.fpOut.write("Could not load default style '" + shared.rasterFileStyle[i] + "' for raster layer '" + shared.rasterFileTitle[i] + "'") else: # A style file was specified, so try to load it #shared.fpOut.write("Trying style file " + shared.rasterFileStyle[i]) if not layer.loadNamedStyle(shared.rasterFileStyle[i]): shared.fpOut.write("Could not load style '" + shared.rasterFileStyle[i] + "' for raster layer '" + shared.rasterFileTitle[i] + "'") # Set opacity layer.renderer().setOpacity(shared.rasterFileOpacity[i]) # Add this layer to the app's registry QgsProject.instance().addMapLayer(layer) return layer
def run(self): """Run method that performs all the real work""" # show the dialog self.dlg.show() # Run the dialog event loop result = self.dlg.exec_() # See if OK was pressed if result: # Do something useful here - delete the line containing pass and # substitute with your code. """read path from user input""" inputPath = self.dlg.Path.text() """set path for output file and concat file name to path""" outputPath = 'C:\Users\Administrator\Desktop\\' outputName = self.dlg.fileName.text() outputFile = outputPath + outputName """read image and calculate electrical conductivity and electrical Resistivity and set RGB for each pixel which R represent adj Pred Moist, G represents electrical conductivity and B represents electrical resistivity""" """for tiff file output""" if(self.dlg.tiff.isChecked()): oldImage = Image.open(inputPath) rgb_image = oldImage.convert('RGB') newImage = Image.new(oldImage.mode,oldImage.size,'white') for x in xrange(newImage.size[0]): for y in xrange(newImage.size[1]): R, G, B = rgb_image.getpixel((x, y)) sand = (R * 0.4 / 255.0) clay = (G * 0.5 / 255.0) om = (B * 5 / 255.0) predMoist = -0.251 * sand + 0.195 * clay + 0.011 * om + 0.006 * sand * om - 0.027 * clay * om + 0.452 * sand * clay + 0.299 adjPredMoist = predMoist + (1.283 * predMoist * predMoist - 0.374 * predMoist - 0.015) electricalConductivity = 0.000471052 * math.pow(100 * adjPredMoist, 3.458) electricalResistivity = 1000.0 / electricalConductivity newImage.putpixel((x,y),(int(adjPredMoist), int(electricalConductivity), int(electricalResistivity))) newImage.save(outputFile + '.tif') """create raster layer and calculate electrical conductivity and write in ASCII XYZ file which X and Y represent centroid coordinate of each pixel and Z represents electrical conductivity""" """for ASCII XYZ file output""" if(self.dlg.asciiXYZ.isChecked()): raster = QgsRasterLayer(inputPath) w = raster.width() h = raster.height() p = raster.dataProvider() b = p.block(0, p.extent(), w, h) f = file(outputFile + '.xyz', 'w') f.write('X,Y,Z(Electrical Conductivity)\n') pix_x = raster.rasterUnitsPerPixelX() pix_y = raster.rasterUnitsPerPixelY() half_x = pix_x / 2 half_y = pix_y / 2 extent = p.extent() count = 0 y = extent.yMinimum() while y < extent.yMaximum(): y += pix_y count += 1 x = extent.xMinimum() while x < extent.xMaximum(): x += pix_x pos = QgsPoint(x - half_x, y - half_y) R = p.identify(pos, QgsRaster.IdentifyFormatValue).results()[1] G = p.identify(pos, QgsRaster.IdentifyFormatValue).results()[2] B = p.identify(pos, QgsRaster.IdentifyFormatValue).results()[3] sand = (R * 0.4 / 255.0) clay = (G * 0.5 / 255.0) om = (B * 5 / 255.0) predMoist = -0.251 * sand + 0.195 * clay + 0.011 * om + 0.006 * sand * om - 0.027 * clay * om + 0.452 * sand * clay + 0.299 adjPredMoist = predMoist + (1.283 * predMoist * predMoist - 0.374 * predMoist - 0.015) electricalConductivity = 0.000471052 * math.pow(100 * adjPredMoist, 3.458) f.write('%s, %s, %s\n' % (pos.x(),pos.y(), electricalConductivity)) f.close()