def test_clip_raster(self): """Raster layers can be clipped.""" # Create a raster layer layer_name = 'shake' raster_layer = QgsRasterLayer(RASTERPATH, layer_name) message = ('Did not find layer "%s" in path "%s"' % (layer_name, RASTERPATH)) assert raster_layer is not None, message # Create a bounding box bounding_box = [97, -3, 104, 1] # Clip the vector to the bbox result = clip_layer(raster_layer, bounding_box) # Check the output is valid assert os.path.exists(result.source()) # Clip and give a desired resolution for the output # big pixel size size = 0.05 result = clip_layer(raster_layer, bounding_box, size) new_raster_layer = QgsRasterLayer(result.source(), layer_name) assert new_raster_layer.isValid(), 'Resampled raster is not valid' message = ('Resampled raster has incorrect pixel size. Expected: %5f, ' 'Actual: %5f' % (size, new_raster_layer.rasterUnitsPerPixelX())) assert new_raster_layer.rasterUnitsPerPixelX() == size, message
def test_clip_raster(self): """Raster layers can be clipped.""" # Create a raster layer layer_name = 'shake' raster_layer = QgsRasterLayer(RASTERPATH, layer_name) message = ( 'Did not find layer "%s" in path "%s"' % (layer_name, RASTERPATH)) assert raster_layer is not None, message # Create a bounding box bounding_box = [97, -3, 104, 1] # Clip the vector to the bbox result = clip_layer(raster_layer, bounding_box) # Check the output is valid assert os.path.exists(result.source()) # Clip and give a desired resolution for the output # big pixel size size = 0.05 result = clip_layer(raster_layer, bounding_box, size) new_raster_layer = QgsRasterLayer(result.source(), layer_name) assert new_raster_layer.isValid(), 'Resampled raster is not valid' message = ( 'Resampled raster has incorrect pixel size. Expected: %5f, ' 'Actual: %5f' % (size, new_raster_layer.rasterUnitsPerPixelX())) assert new_raster_layer.rasterUnitsPerPixelX() == size, message
def test_clipRaster(self): """Raster layers can be clipped """ # Create a raster layer myName = 'shake' myRasterLayer = QgsRasterLayer(RASTERPATH, myName) message = 'Did not find layer "%s" in path "%s"' % \ (myName, RASTERPATH) assert myRasterLayer is not None, message # Create a bounding box myRect = [97, -3, 104, 1] # Clip the vector to the bbox myResult = clip_layer(myRasterLayer, myRect) # Check the output is valid assert os.path.exists(myResult.source()) # Clip and give a desired resolution for the output mySize = 0.05 myResult = clip_layer(myRasterLayer, myRect, mySize) myNewRasterLayer = QgsRasterLayer(myResult.source(), myName) assert myNewRasterLayer.isValid(), 'Resampled raster is not valid' message = ('Resampled raster has incorrect pixel size.' 'Expected: %f, Actual: %f' % (mySize, myNewRasterLayer.rasterUnitsPerPixelX())) assert myNewRasterLayer.rasterUnitsPerPixelX() == mySize, message
def test_clipRaster(self): """Raster layers can be clipped """ # Create a raster layer myName = 'shake' myRasterLayer = QgsRasterLayer(RASTERPATH, myName) myMessage = 'Did not find layer "%s" in path "%s"' % \ (myName, RASTERPATH) assert myRasterLayer is not None, myMessage # Create a bounding box myRect = [97, -3, 104, 1] # Clip the vector to the bbox myResult = clip_layer(myRasterLayer, myRect) # Check the output is valid assert os.path.exists(myResult.source()) # Clip and give a desired resolution for the output mySize = 0.05 myResult = clip_layer(myRasterLayer, myRect, mySize) myNewRasterLayer = QgsRasterLayer(myResult.source(), myName) assert myNewRasterLayer.isValid(), 'Resampled raster is not valid' myMessage = ('Resampled raster has incorrect pixel size.' 'Expected: %f, Actual: %f' % (mySize, myNewRasterLayer.rasterUnitsPerPixelX())) assert myNewRasterLayer.rasterUnitsPerPixelX() == mySize, myMessage
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 test_clip_raster_small(self): """Raster layers can be clipped in small and precise size. For #710.""" # Create a raster layer layer_name = 'shake' raster_layer = QgsRasterLayer(RASTERPATH, layer_name) message = ( 'Did not find layer "%s" in path "%s"' % (layer_name, RASTERPATH)) assert raster_layer is not None, message # Create a bounding box bounding_box = [97, -3, 104, 1] # Clip the vector to the bbox result = clip_layer(raster_layer, bounding_box) # Check the output is valid assert os.path.exists(result.source()) # Clip and give a desired resolution for the output # small pixel size and high precision # based on pixel size of Flood_Current_Depth_Jakarta_geographic.asc size = 0.00045228819716 result = clip_layer(raster_layer, bounding_box, size) new_raster_layer = QgsRasterLayer(result.source(), layer_name) assert new_raster_layer.isValid(), 'Resampled raster is not valid' message = ( 'Resampled raster has incorrect pixel size. Expected: %.14f, ' 'Actual: %.14f' % ( size, new_raster_layer.rasterUnitsPerPixelX())) result_size = new_raster_layer.rasterUnitsPerPixelX() self.assertAlmostEqual(result_size, size, places=13, msg=message)
def change_resolution(image_path, new_resolution, upsampling_method): """Changes resolution of a given image. The parameters are image_path, new_resolution and upsampling_method. upsampling_method is used for increasing artificially the rosultion in order to use another raster available originally in this resolution Available values for upsampling_method: - 0: Nearest neighbour - 1: Bilinear - 2: Cubic - 3: Cubic spline - 4: Lanczos windowed sinc - 5: Average - 6: Mode - 7: Maximum - 8: Minimum - 9: Median - 10: First quartile - 11: Third quartile""" Image2beUpsampled = QgsRasterLayer(image_path) newImageBaseName = os.path.basename(image_path).replace(str(int(Image2beUpsampled.rasterUnitsPerPixelX())) + 'm', str(new_resolution)+'m') param = {} param['INPUT'] = Image2beUpsampled param['TARGET_CRS'] = Image2beUpsampled.crs() # print("image path: " + image_path) param['OUTPUT'] = os.path.join(os.path.dirname(image_path).replace(os.path.dirname(image_path)[-3:], str(new_resolution)+'m'), newImageBaseName.replace('jp2','tiff')) # print("output path: " + param['OUTPUT'])#,'D:\\test\\R60m\\testOutput10Channel7.tiff') param['RESAMPLING'] = upsampling_method param['TARGET_RESOLUTION'] = new_resolution print("before processing") result = processing.run("gdal:warpreproject",param) print("after processing") #delete a return result['OUTPUT']
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)
def processAlgorithm(self, parameters, context, feedback): """ Here is where the processing itself takes place. """ # Retrieve parameters from the gui OUTPUTFOLDER = self.parameterAsFile(parameters, self.FLOOD_DEPTH_OUTPUT, context) DEM = self.parameterAsRasterLayer(parameters, self.DEM_INPUT, context).source() INUNDPOLYGON = self.parameterAsVectorLayer(parameters, self.FLOOD_POLYGON_INPUT, context).source() # feedback.pushInfo('The output directory is {}'.format(self.parameterAsFile( # parameters, self.FLOOD_DEPTH_OUTPUT, context))) feedback.pushInfo(DEM) # Raster specifications that are needed by JSON inputs # Load the DEM to extract the layer extent and pixel size demLayer = QgsRasterLayer(DEM, 'dem_extent') inundpolygonLayer = QgsVectorLayer(INUNDPOLYGON, 'indund_extent') # Extract the DEM extent in a float format. demExtent = self.floatDemExtent(demLayer) inundpolygonExtent = self.floatDemExtent(inundpolygonLayer) # It is assumed that the unit per pixel size for the X direction is the same for the Y direction demSize = demLayer.rasterUnitsPerPixelX() # End raster specifications that are needed by JSON inputs # JSON input setup clip_input = { "INPUT": DEM, "OUTPUT": os.path.join(OUTPUTFOLDER, 'clippingMask.sdat'), # this will need to change "POLYGONS": INUNDPOLYGON } polygons_to_lines_input = { "LINES": os.path.join(OUTPUTFOLDER, 'polyline.shp'), "POLYGONS": INUNDPOLYGON } rasterize_input = { 'INPUT': os.path.join(OUTPUTFOLDER, 'polyline.shp'), 'FIELD': None, 'BURN': 1, 'UNITS': 1, 'WIDTH': demSize, # width and height should match that of the cell size of the DEM input 'HEIGHT': demSize, 'EXTENT': inundpolygonExtent, # the extent of the area must be given in a comma seperated list ending with an uncommaed CRS within e.g. [EPSG:26712] 'NODATA': 0, 'OPTIONS': '', 'DATA_TYPE': 0, 'INIT': 0, 'INVERT': False, 'OUTPUT': os.path.join(OUTPUTFOLDER, 'rasterLine.tif') } grow_distance_input = { 'input': os.path.join(OUTPUTFOLDER, 'extractElevation.tif'), 'metric': 0, # euclidean distance '-m': False, '-': False, 'distance': os.path.join(OUTPUTFOLDER, 'scratch.tif'), 'value': os.path.join(OUTPUTFOLDER, 'growDistance.tif'), 'GRASS_REGION_PARAMETER': demExtent, 'GRASS_REGION_CELLSIZE_PARAMETER': 0, 'GRASS_RASTER_FORMAT_OPT': '', 'GRASS_RASTER_FORMAT_META': '' } gaussian_filter_input = { 'INPUT': os.path.join(OUTPUTFOLDER, 'waterDepth.tif'), 'MODE': 0, 'RADIUS': 3, 'RESULT': os.path.join(OUTPUTFOLDER, 'waterDepthFiltered.sdat'), 'SIGMA': 1 } # End json input setup #new stuff processing.run( "saga:cliprasterwithpolygon", clip_input, context=context, feedback=feedback ) # create a clipping mask from the DEM to later be used to subtract from the calculated gross waterdepth feedback.setProgress(12) POLYLINE = processing.run( "saga:convertpolygonstolines", polygons_to_lines_input, context=context, feedback=feedback)[ 'LINES'] # convert floodextent to polyline outline feedback.setProgress(24) polyLineExtent = self.floatDemExtent( QgsVectorLayer(POLYLINE, 'line_extent', 'ogr')) feedback.setProgress(36) processing.run( "gdal:rasterize", rasterize_input, context=context, feedback=feedback ) # convert the above polyline to a raster line so that raster opperations may be preformed feedback.setProgress(48) extractElevation = self.rasterCalculator( [rasterize_input['OUTPUT'], DEM], '({0} * {1}) / {0}', 0, 'extractElevation.tif' ) # associate underlying DEM values to rasterized line feedback.setProgress(60) processing.run("grass7:r.grow.distance", grow_distance_input, context=context, feedback=feedback) feedback.setProgress(72) waterDepth = self.rasterCalculator( [clip_input['OUTPUT'], grow_distance_input['value']], '(({1} - {0}) > 0) * ({1} - {0})', 0, fname='waterDepth.tif') # clip grow distance output using clipDEM feedback.setProgress(84) processing.run("saga:gaussianfilter", gaussian_filter_input, context=context, feedback=feedback) feedback.setProgress(100) # # Add results to project layer # waterDepth = QgsRasterLayer(os.path.join(OUTPUTFOLDER,'waterDepth.tif'), 'Water Depth') # QgsProject.instance().addMapLayer(waterDepth) # waterDepthFiltered = QgsRasterLayer(gaussian_filter_input['RESULT'], 'Water Depth Filtered' ) # QgsProject.instance().addMapLayer(waterDepthFiltered) return { 'OUTPUT': os.path.join(OUTPUTFOLDER, 'waterDepthFiltered.sdat') }
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 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()
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)
class GNSS3DCaptureDockWidget(QtGui.QDockWidget, FORM_CLASS): closingPlugin = pyqtSignal() def __init__(self, iface, parent=None): """Constructor.""" super(GNSS3DCaptureDockWidget, self).__init__(parent) # Set up the user interface from Designer. # After setupUI you can access any designer object by doing # self.<objectname>, and you can use autoconnect slots - see # http://qt-project.org/doc/qt-4.8/designer-using-a-ui-file.html # #widgets-and-dialogs-with-auto-connect self.setupUi(self) self.iface = iface self.initialize() def closeEvent(self, event): self.closingPlugin.emit() event.accept() def finishProcess(self): self.capturePointGroupBox.setEnabled(False) self.nameLineEdit.clear() self.numberLineEdit.clear() self.codeLineEdit.clear() self.firstCoordinateLineEdit.clear() self.secondCoordinateLineEdit.clear() self.heightAntennaLineEdit.clear() self.heightGpsLineEdit.clear() self.heightGroundLineEdit.clear() self.heightGeoidLineEdit.clear() self.heightFromGeoidLineEdit.clear() self.configurePushButton.setEnabled(True) self.startPushButton.setEnabled(False) self.finishPushButton.setEnabled(False) def getGeoidInterpolatedValue(self, gpsLongitude, gpsLatitude): geoidPoint = QgsPoint(gpsLongitude, gpsLatitude) geoidPoint = self.crsOperationFromGpsToGeoid.transform(geoidPoint) geoidHeight = constants.CONST_GNSS_3D_CAPTURE_GEOIDS_NO_VALUE if not self.geoidModel.extent().contains(geoidPoint): msgBox = QMessageBox(self) msgBox.setIcon(QMessageBox.Information) msgBox.setWindowTitle(constants.CONST_GNSS_3D_CAPTURE_WINDOW_TITLE) msgBox.setText("Point out of Geoid Model extension:\n", self.geoidModelFileName) msgBox.exec_() return geoidHeight firstCoordinate = geoidPoint.x() secondCoordinate = geoidPoint.y() dbl_column = (firstCoordinate - self.geoidMinimumFirstCoordinate ) / self.geoidStepFirstCoordinate dbl_row = (secondCoordinate - self.geoidMaximumSecondCoordinate ) / self.geoidStepSecondCoordinate inc_column = dbl_column - floor(dbl_column) inc_row = dbl_row - floor(dbl_row) f00 = self.getGeoidPixelValue(firstCoordinate, secondCoordinate) if f00 == constants.CONST_GNSS_3D_CAPTURE_GEOIDS_NO_VALUE: return geoidHeight f10 = self.getGeoidPixelValue( firstCoordinate + self.geoidStepFirstCoordinate, secondCoordinate) if f10 == constants.CONST_GNSS_3D_CAPTURE_GEOIDS_NO_VALUE: return geoidHeight f01 = self.getGeoidPixelValue( firstCoordinate, secondCoordinate + self.geoidStepSecondCoordinate) if f01 == constants.CONST_GNSS_3D_CAPTURE_GEOIDS_NO_VALUE: return geoidHeight f11 = self.getGeoidPixelValue( firstCoordinate + self.geoidStepFirstCoordinate, secondCoordinate + self.geoidStepSecondCoordinate) if f11 == constants.CONST_GNSS_3D_CAPTURE_GEOIDS_NO_VALUE: return geoidHeight geoidHeight = (1.0 - inc_row) * (1.0 - inc_column) * f00 geoidHeight += inc_column * (1.0 - inc_row) * f10 geoidHeight += (1.0 - inc_column) * inc_row * f01 geoidHeight += inc_column * inc_row * f11 return geoidHeight def getGeoidPixelValue(self, gpsLongitude, gpsLatitude): geoidPoint = QgsPoint(gpsLongitude, gpsLatitude) geoidPoint = self.crsOperationFromGpsToGeoid.transform(geoidPoint) geoidHeight = constants.CONST_GNSS_3D_CAPTURE_GEOIDS_NO_VALUE if not self.geoidModel.extent().contains(geoidPoint): msgBox = QMessageBox(self) msgBox.setIcon(QMessageBox.Information) msgBox.setWindowTitle(constants.CONST_GNSS_3D_CAPTURE_WINDOW_TITLE) msgBox.setText("Point out of Geoid Model extension:\n", self.geoidModelFileName) msgBox.exec_() return geoidHeight firstCoordinate = geoidPoint.x() secondCoordinate = geoidPoint.y() ident = self.geoidModel.dataProvider().identify( geoidPoint, QgsRaster.IdentifyFormatValue) if ident.isValid(): values = ident.results() geoidHeight = values[1] else: msgBox = QMessageBox(self) msgBox.setIcon(QMessageBox.Information) msgBox.setWindowTitle(constants.CONST_GNSS_3D_CAPTURE_WINDOW_TITLE) msgBox.setText("Error getting value in Geoid Model:\n", self.geoidModelFileName) msgBox.exec_() return geoidHeight def initialize(self): aux_path_plugin = 'python/plugins/' + constants.CONST_GNSS_3D_CAPTURE_NAME qgisUserDbFilePath = QgsApplication.qgisUserDbFilePath() self.path_plugin = os.path.join( QFileInfo(QgsApplication.qgisUserDbFilePath()).path(), aux_path_plugin) path_file_qsettings = self.path_plugin + '/' + constants.CONST_GNSS_3D_CAPTURE_SETTINGS_FILE_NAME self.settings = QSettings(path_file_qsettings, QSettings.IniFormat) self.lastPath = self.settings.value("last_path") if not self.lastPath: self.lastPath = QDir.currentPath() self.settings.setValue("last_path", self.lastPath) self.settings.sync() self.crsAuthId = self.settings.value("crsAuthId") if not self.crsAuthId: self.crsAuthId = self.iface.mapCanvas().mapRenderer( ).destinationCrs().authid() self.settings.setValue("crsAuthId", self.crsAuthId) self.settings.sync() self.crs = QgsCoordinateReferenceSystem() self.crs.createFromUserInput(self.crsAuthId) if self.crs.geographicFlag(): self.firstCoordinateLabel.setText("Longitude") self.secondCoordinateLabel.setText("Latitude") else: self.firstCoordinateLabel.setText("Easting") self.secondCoordinateLabel.setText("Northing") self.iface.mapCanvas().mapRenderer().setProjectionsEnabled(True) self.startPushButton.setEnabled(False) self.finishPushButton.setEnabled(False) self.capturePointGroupBox.setEnabled(False) QtCore.QObject.connect(self.configurePushButton, QtCore.SIGNAL("clicked(bool)"), self.selectConfigure) # QtCore.QObject.connect(self.crsPushButton,QtCore.SIGNAL("clicked(bool)"),self.selectCrs) # QtCore.QObject.connect(self.geoidCheckBox,QtCore.SIGNAL("clicked(bool)"),self.activateGeoid) QtCore.QObject.connect(self.startPushButton, QtCore.SIGNAL("clicked(bool)"), self.startProcess) QtCore.QObject.connect(self.updatePositionPushButton, QtCore.SIGNAL("clicked(bool)"), self.updatePosition) QtCore.QObject.connect(self.finishPushButton, QtCore.SIGNAL("clicked(bool)"), self.finishProcess) QtCore.QObject.connect(self.savePointPushButton, QtCore.SIGNAL("clicked(bool)"), self.savePoint) QtCore.QObject.connect(self.codePushButton, QtCore.SIGNAL("clicked(bool)"), self.selectCode) QtCore.QObject.connect(self.namePushButton, QtCore.SIGNAL("clicked(bool)"), self.selectName) QtCore.QObject.connect(self.numberPushButton, QtCore.SIGNAL("clicked(bool)"), self.selectNumber) QtCore.QObject.connect(self.heightAntennaPushButton, QtCore.SIGNAL("clicked(bool)"), self.selectAntennaHeight) self.pointNumbers = [] #self.configureDialog = None self.configureDialog = GNSS3DCaptureDialog(self.iface, self.lastPath, self.crs) self.num_format = re.compile(r'^\-?[1-9][0-9]*\.?[0-9]*') def savePoint(self): connectionRegistry = QgsGPSConnectionRegistry().instance() connectionList = connectionRegistry.connectionList() if connectionList == []: msgBox = QMessageBox(self) msgBox.setIcon(QMessageBox.Information) msgBox.setWindowTitle(constants.CONST_GNSS_3D_CAPTURE_WINDOW_TITLE) msgBox.setText( "GPS connection not detected.\nConnect a GPS and try again") msgBox.exec_() return csvFile = QFile(self.csvFileName) if not csvFile.open(QIODevice.Append | QIODevice.Text): msgBox = QMessageBox(self) msgBox.setIcon(QMessageBox.Information) msgBox.setWindowTitle(constants.CONST_GNSS_3D_CAPTURE_WINDOW_TITLE) msgBox.setText("Error opening for writting file:\n" + self.csvFileName) msgBox.exec_() return csvTextStream = QTextStream(csvFile) csvTextStream << "\n" fieldValues = {} fieldNumber = 0 listFieldValues = [] if self.useName: name = self.nameLineEdit.text() csvTextStream << name << "," #fieldValues[fieldNumber]=QVariant(name) fieldValues[fieldNumber] = name fieldNumber = fieldNumber + 1 listFieldValues.append(name) if self.useNumber: number = self.numberLineEdit.text() csvTextStream << number << "," #fieldValues[fieldNumber]=QVariant(number) fieldValues[fieldNumber] = number fieldNumber = fieldNumber + 1 listFieldValues.append(number) GPSInfo = connectionList[0].currentGPSInformation() firstCoordinate = GPSInfo.longitude secondCoordinate = GPSInfo.latitude pointCrsGps = QgsPoint(firstCoordinate, secondCoordinate) pointCrs = self.crsOperationFromGps.transform(pointCrsGps) firstCoordinate = pointCrs.x() secondCoordinate = pointCrs.y() if self.crs.geographicFlag(): strFirstCoordinate = constants.CONST_GNSS_3D_CAPTURE_SAVE_POINT_LONGITUDE_PRECISION.format( firstCoordinate) strSecondCoordinate = constants.CONST_GNSS_3D_CAPTURE_SAVE_POINT_LATITUDE_PRECISION.format( secondCoordinate) else: strFirstCoordinate = constants.CONST_GNSS_3D_CAPTURE_SAVE_POINT_EASTING_PRECISION.format( firstCoordinate) strSecondCoordinate = constants.CONST_GNSS_3D_CAPTURE_SAVE_POINT_NORTHING_PRECISION.format( secondCoordinate) csvTextStream << strFirstCoordinate << "," csvTextStream << strSecondCoordinate #fieldValues[fieldNumber]=QVariant(firstCoordinate) fieldValues[fieldNumber] = firstCoordinate listFieldValues.append(firstCoordinate) fieldNumber = fieldNumber + 1 #fieldValues[fieldNumber]=QVariant(secondCoordinate) fieldValues[fieldNumber] = secondCoordinate listFieldValues.append(secondCoordinate) fieldNumber = fieldNumber + 1 if self.useHeight: antennaHeight = float(self.heightAntennaLineEdit.text()) height = GPSInfo.elevation height = height - antennaHeight if self.useGeoidModel: geoidHeight = self.getGeoidInterpolatedValue( GPSInfo.longitude, GPSInfo.latitude) if geoidHeight == constants.CONST_GNSS_3D_CAPTURE_GEOIDS_NO_VALUE: return height = height - geoidHeight strHeight = constants.CONST_GNSS_3D_CAPTURE_SAVE_POINT_HEIGHT_PRECISION.format( height) csvTextStream << "," << strHeight #fieldValues[fieldNumber]=QVariant(height) fieldValues[fieldNumber] = height listFieldValues.append(height) fieldNumber = fieldNumber + 1 if self.useCode: code = self.codeLineEdit.text() csvTextStream << "," << code #fieldValues[fieldNumber]=QVariant(code) fieldValues[fieldNumber] = code listFieldValues.append(code) csvFile.close() fet = QgsFeature() fet.setGeometry( QgsGeometry.fromPoint(QgsPoint(firstCoordinate, secondCoordinate))) #fet.setAttributeMap(fieldValues) fet.setAttributes(listFieldValues) self.memoryLayerDataProvider.addFeatures([fet]) self.memoryLayer.commitChanges() self.memoryLayerName.triggerRepaint() if self.useNumber: self.pointNumbers.append(int(number)) candidateValue = self.pointNumbers[len(self.pointNumbers) - 1] + 1 if self.pointNumbers.count(candidateValue) != 0: control = True while control: candidateValue = candidateValue + 1 if self.pointNumbers.count(candidateValue) == 0: control = False self.numberLineEdit.setText(str(candidateValue)) self.accept() def selectCode(self): oldText = self.codeLineEdit.text() label = "Input Point Code:" title = constants.CONST_GNSS_3D_CAPTURE_SAVE_POINT_WINDOW_TITLE [text, ok] = QInputDialog.getText(self, title, label, QLineEdit.Normal, oldText) if ok and text: text = text.strip() if not text == oldText: self.codeLineEdit.setText(text) def selectAntennaHeight(self): strCandidateValue = self.heightAntennaLineEdit.text() label = "Input Antenna Height:" title = constants.CONST_GNSS_3D_CAPTURE_SAVE_POINT_WINDOW_TITLE ok = False while not ok: [text, ok] = QInputDialog.getText(self, title, label, QLineEdit.Normal, strCandidateValue) if ok and text: value = 0.0 text = text.strip() if text.isdigit() or re.match(self.num_format, text): value = float(text) if (value < constants. CONST_GNSS_3D_CAPTURE_SAVE_POINT_ANTENNA_HEIGHT_MINIMUM_VALUE or value > constants. CONST_GNSS_3D_CAPTURE_SAVE_POINT_ANTENNA_HEIGHT_MAXIMUM_VALUE ): ok = False else: ok = False if ok: strValue = constants.CONST_GNSS_3D_CAPTURE_SAVE_POINT_ANTENNA_HEIGHT_PRECISION.format( value) self.heightAntennaLineEdit.setText(strValue) self.updatePosition() else: if not ok: ok = True def selectConfigure(self): # if self.configureDialog == None: # self.configureDialog = GNSS3DCaptureDialog(self.iface,self.lastPath,self.crs) # self.configureDialog.show() # show the dialog # result = self.configureDialog.exec_() # Run the dialog # yo =1 # else: # self.configureDialog.show() # show the dialog # result = self.configureDialog.exec_() # Run the dialog # yo =1 # if self.configureDialog.isOk(): self.configureDialog.show() # show the dialog result = self.configureDialog.exec_() # Run the dialog self.csvFileName = self.configureDialog.getCsvFileName() self.lastPath = self.configureDialog.getLastPath() self.crs = self.configureDialog.getCrs() self.useCode = self.configureDialog.getUseCode() self.useName = self.configureDialog.getUseName() self.useHeight = self.configureDialog.getUseHeight() self.useNumber = self.configureDialog.getUseNumber() self.useGeoidModel = self.configureDialog.getUseGeoidModel() self.geoidModelFileName = self.configureDialog.getGeoidModelFileName() if self.crs.isValid(): if self.crs.geographicFlag(): self.firstCoordinateLabel.setText("Longitude") self.secondCoordinateLabel.setText("Latitude") else: self.firstCoordinateLabel.setText("Easting") self.secondCoordinateLabel.setText("Northing") crsAuthId = self.crs.authid() self.settings.setValue("crsAuthId", crsAuthId) self.settings.sync() if self.lastPath: self.settings.setValue("last_path", self.lastPath) self.settings.sync() if self.configureDialog.getIsOk(): self.startPushButton.setEnabled(True) else: self.startPushButton.setEnabled(False) def selectName(self): oldText = self.nameLineEdit.text() label = "Input Point Name:" title = constants.CONST_GNSS_3D_CAPTURE_SAVE_POINT_WINDOW_TITLE [text, ok] = QInputDialog.getText(self, title, label, QLineEdit.Normal, oldText) if ok and text: text = text.strip() if not text == oldText: self.nameLineEdit.setText(text) def selectNumber(self): if self.pointNumbers == []: candidateValue = constants.CONST_GNSS_3D_CAPTURE_SAVE_POINT_FIRST_POINT_NUMBER else: candidateValue = self.pointNumbers(len(self.pointNumbers) - 1) label = "Input Point Number:" title = constants.CONST_GNSS_3D_CAPTURE_SAVE_POINT_WINDOW_TITLE ok = False while not ok: [text, ok] = QInputDialog.getText(self, title, label, QLineEdit.Normal, str(candidateValue)) if ok and text: text = text.strip() if not text.isdigit(): ok = False else: value = int(text) if (value < constants. CONST_GNSS_3D_CAPTURE_SAVE_POINT_POINT_NUMBER_MINIMUM_VALUE or value > constants. CONST_GNSS_3D_CAPTURE_SAVE_POINT_POINT_NUMBER_MAXIMUM_VALUE ): ok = False if ok: self.numberLineEdit.setText(text) else: if not ok: ok = True def startProcess(self): connectionRegistry = QgsGPSConnectionRegistry().instance() connectionList = connectionRegistry.connectionList() if connectionList == []: msgBox = QMessageBox(self) msgBox.setIcon(QMessageBox.Information) msgBox.setWindowTitle(constants.CONST_GNSS_3D_CAPTURE_WINDOW_TITLE) msgBox.setText( "GPS connection not detected.\nConnect a GPS and try again") msgBox.exec_() return GPSInfo = connectionList[0].currentGPSInformation() self.capturePointGroupBox.setEnabled(False) if not self.configureDialog.getIsOk(): msgBox = QMessageBox(self) msgBox.setIcon(QMessageBox.Information) msgBox.setWindowTitle(constants.CONST_GNSS_3D_CAPTURE_WINDOW_TITLE) msgBox.setText("The configuration is not valid") msgBox.exec_() return if self.useCode: self.codePushButton.setEnabled(True) self.codeLineEdit.setEnabled(True) else: self.codePushButton.setEnabled(False) self.codeLineEdit.setEnabled(False) self.codeLineEdit.clear() if self.useName: self.namePushButton.setEnabled(True) self.nameLineEdit.setEnabled(True) else: self.namePushButton.setEnabled(False) self.nameLineEdit.setEnabled(False) self.nameLineEdit.clear() if self.useNumber: self.numberPushButton.setEnabled(True) self.numberLineEdit.setEnabled(True) else: self.numberPushButton.setEnabled(False) self.numberLineEdit.setEnabled(False) self.numberLineEdit.clear() if self.useHeight: self.heightAntennaPushButton.setEnabled(True) self.heightAntennaLineEdit.setEnabled(True) self.antennaHeight = constants.CONST_GNSS_3D_CAPTURE_SAVE_POINT_ANTENNA_HEIGHT_DEFAULT_VALUE strAntennaHeigth = constants.CONST_GNSS_3D_CAPTURE_SAVE_POINT_ANTENNA_HEIGHT_PRECISION.format( self.antennaHeight) self.heightAntennaLineEdit.setText(strAntennaHeigth) self.heightGpsLabel.setEnabled(True) self.heightGpsLineEdit.setEnabled(True) self.heightGroundLabel.setEnabled(True) self.heightGroundLineEdit.setEnabled(True) if self.useGeoidModel and self.geoidModelFileName: self.heightGeoidLabel.setEnabled(True) self.heightGeoidLineEdit.setEnabled(True) self.heightFromGeoidLabel.setEnabled(True) self.heightFromGeoidLineEdit.setEnabled(True) else: self.heightGeoidLabel.setEnabled(False) self.heightGeoidLineEdit.setEnabled(False) self.heightGeoidLineEdit.clear() self.heightFromGeoidLabel.setEnabled(False) self.heightFromGeoidLineEdit.setEnabled(False) self.heightFromGeoidLineEdit.clear() else: self.heightAntennaPushButton.setEnabled(False) self.heightAntennaLineEdit.setEnabled(False) self.heightAntennaLineEdit.clear() self.heightGpsLabel.setEnabled(False) self.heightGpsLineEdit.setEnabled(False) self.heightGpsLineEdit.clear() self.heightGroundLabel.setEnabled(False) self.heightGroundLineEdit.setEnabled(False) self.heightGroundLineEdit.clear() self.heightGeoidLabel.setEnabled(False) self.heightGeoidLineEdit.setEnabled(False) self.heightGeoidLineEdit.clear() self.heightFromGeoidLabel.setEnabled(False) self.heightFromGeoidLineEdit.setEnabled(False) self.heightFromGeoidLineEdit.clear() fileName = self.csvFileName if not fileName: msgBox = QMessageBox(self) msgBox.setIcon(QMessageBox.Information) msgBox.setWindowTitle(constants.CONST_GNSS_3D_CAPTURE_WINDOW_TITLE) msgBox.setText("You must select CSV file") msgBox.exec_() return strDateTime = "" if QFile.exists(fileName): msgBox = QMessageBox(self) msgBox.setIcon(QMessageBox.Information) msgBox.setWindowTitle(constants.CONST_GNSS_3D_CAPTURE_WINDOW_TITLE) text = "Exists CSV file:\n" + fileName msgBox.setText(text) msgBox.setInformativeText( "Do you want to rename it with current date an time?") msgBox.setStandardButtons(QMessageBox.Ok | QMessageBox.Discard | QMessageBox.Cancel) msgBox.setDefaultButton(QMessageBox.Ok) ret = msgBox.exec_() if ret == QMessageBox.Ok: dateTime = QDateTime.currentDateTime() strDateTime = dateTime.toString("yyyy-MM-dd_HH-mm-ss") fileInfo = QFileInfo(fileName) filePath = fileInfo.absolutePath() fileNameWithoutExtension = fileInfo.completeBaseName() fileExtension = fileInfo.completeSuffix() newFileName = filePath + "/" + fileNameWithoutExtension + "_" + strDateTime + "." + fileExtension if not QFile.copy(fileName, newFileName): msgBox = QMessageBox(self) msgBox.setIcon(QMessageBox.Warning) msgBox.setWindowTitle( constants.CONST_GNSS_3D_CAPTURE_WINDOW_TITLE) msgBox.setWindowTitle( constants.CONST_GNSS_3D_CAPTURE_WINDOW_TITLE) msgBox.setText("Error copying existing file:\n" + fileName + "\n" + newFileName) msgBox.exec_() return if not self.crs.isValid(): msgBox = QMessageBox(self) msgBox.setIcon(QMessageBox.Information) msgBox.setWindowTitle(constants.CONST_GNSS_3D_CAPTURE_WINDOW_TITLE) msgBox.setText("You must select the output CRS") msgBox.exec_() return if self.useGeoidModel and self.geoidModelFileName == constants.CONST_GNSS_3D_CAPTURE_COMBOBOX_NO_SELECT_OPTION: msgBox = QMessageBox(self) msgBox.setIcon(QMessageBox.Information) msgBox.setWindowTitle(constants.CONST_GNSS_3D_CAPTURE_WINDOW_TITLE) msgBox.setText( "If you select substract geoide height \n you must select a geoid model" ) msgBox.exec_() return csvFile = QFile(fileName) if not csvFile.open(QIODevice.WriteOnly | QIODevice.Text): msgBox = QMessageBox(self) msgBox.setIcon(QMessageBox.Information) msgBox.setWindowTitle(constants.CONST_GNSS_3D_CAPTURE_WINDOW_TITLE) msgBox.setText("Error opening for writting file:\n" + fileName) msgBox.exec_() return csvTextStream = QTextStream(csvFile) fileInfo = QFileInfo(fileName) self.memoryLayerName = fileInfo.completeBaseName() existsMemoryLayer = None for lyr in QgsMapLayerRegistry.instance().mapLayers().values(): if lyr.name() == self.memoryLayerName: existsMemoryLayer = lyr break if existsMemoryLayer != None: newMemoryLayerName = self.memoryLayerName + "_" + strDateTime existsMemoryLayer.setLayerName(newMemoryLayerName) memoryLayerTypeAndCrs = "Point?crs=" + self.crs.authid() #EPSG:4326" self.memoryLayer = QgsVectorLayer(memoryLayerTypeAndCrs, self.memoryLayerName, "memory") self.memoryLayerDataProvider = self.memoryLayer.dataProvider() memoryLayerFields = [] # add fields firstField = True if self.useName: csvTextStream << "Name" firstField = False memoryLayerFields.append(QgsField("Name", QVariant.String)) if self.useNumber: if not firstField: csvTextStream << "," else: firstField = False csvTextStream << "Number" memoryLayerFields.append(QgsField("Number", QVariant.Int)) if not firstField: csvTextStream << "," else: firstField = False if not self.crs.geographicFlag(): csvTextStream << "Easting" csvTextStream << "," << "Northing" memoryLayerFields.append(QgsField("Easting", QVariant.Double)) memoryLayerFields.append(QgsField("Northing", QVariant.Double)) else: csvTextStream << "Longitude" csvTextStream << "," << "Latitude" memoryLayerFields.append(QgsField("Longitude", QVariant.Double)) memoryLayerFields.append(QgsField("Latitude", QVariant.Double)) if self.useHeight: csvTextStream << "," << "Height" memoryLayerFields.append(QgsField("Height", QVariant.Double)) if self.useCode: csvTextStream << "," << "Code" memoryLayerFields.append(QgsField("Code", QVariant.String)) csvFile.close() self.memoryLayerDataProvider.addAttributes(memoryLayerFields) # self.memoryLayerDataProvider.addAttributes([QgsField("Name", QVariant.String), # QgsField("Number", QVariant.String), # QgsField("FirstCoordinate", QVariant.Double), # QgsField("SecondCoordinate", QVariant.Double), # QgsField("Height", QVariant.Double), # QgsField("Code", QVariant.Int)]) self.memoryLayer.startEditing() self.memoryLayer.commitChanges() qmlFileName = self.path_plugin + "/" + constants.CONST_GNSS_3D_CAPTURE_QML_TEMPLATES_FOLDER + "/" if self.useName: qmlFileName += constants.CONST_GNSS_3D_CAPTURE_QML_TEMPLATES_FOLDER_QML_POINT_NAME_Z elif self.useNumber: qmlFileName += constants.CONST_GNSS_3D_CAPTURE_QML_TEMPLATES_FOLDER_QML_POINT_NUMBER_Z else: qmlFileName += constants.CONST_GNSS_3D_CAPTURE_QML_TEMPLATES_FOLDER_QML_POINT_Z self.memoryLayer.loadNamedStyle(qmlFileName) QgsMapLayerRegistry.instance().addMapLayer(self.memoryLayer) epsgCodeGps = constants.CONST_GNSS_3D_CAPTURE_EPSG_CODE_GPS self.crsGps = QgsCoordinateReferenceSystem(epsgCodeGps) if not self.crsGps.isValid(): msgBox = QMessageBox(self) msgBox.setIcon(QMessageBox.Information) msgBox.setWindowTitle(constants.CONST_GNSS_3D_CAPTURE_WINDOW_TITLE) msgBox.setText("Error creating CRS by EPSG Code: " + str(epsgCodeGps)) msgBox.exec_() self.isValid = False return self.crsOperationFromGps = QgsCoordinateTransform( self.crsGps, self.crs) if self.useHeight: if self.useGeoidModel: if not QFile.exists(self.geoidModelFileName): msgBox = QMessageBox(self) msgBox.setIcon(QMessageBox.Information) msgBox.setWindowTitle( constants.CONST_GNSS_3D_CAPTURE_WINDOW_TITLE) msgBox.setText("Geoid Model file not exists:\n" + self.geoidModelFileName) msgBox.exec_() self.isValid = False return geoidModelFileInfo = QFileInfo(self.geoidModelFileName) geoidModelPath = geoidModelFileInfo.filePath() geoidModelBaseName = geoidModelFileInfo.baseName() self.geoidModel = QgsRasterLayer(geoidModelPath, geoidModelBaseName) self.crsGeoidModel = self.geoidModel.crs() if not self.crsGeoidModel.isValid(): msgBox = QMessageBox(self) msgBox.setIcon(QMessageBox.Information) msgBox.setWindowTitle( constants.CONST_GNSS_3D_CAPTURE_WINDOW_TITLE) msgBox.setText("Error getting Geoid Model CRS:\n" + self.geoidModelFileName) msgBox.exec_() self.isValid = False return self.geoidStepFirstCoordinate = self.geoidModel.rasterUnitsPerPixelX( ) # debe ser positivo self.geoidStepSecondCoordinate = 1.0 * self.geoidModel.rasterUnitsPerPixelX( ) # debe ser positivo self.geoidExtend = self.geoidModel.dataProvider().extent() self.geoidMinimumFirstCoordinate = self.geoidExtend.xMinimum() self.geoidMaximumSecondCoordinate = self.geoidExtend.yMaximum() self.crsOperationFromGpsToGeoid = QgsCoordinateTransform( self.crsGps, self.crsGeoidModel) self.capturePointGroupBox.setEnabled(True) self.configurePushButton.setEnabled(False) self.startPushButton.setEnabled(False) self.finishPushButton.setEnabled(True) if self.useNumber: strFirstNumber = str( constants.CONST_GNSS_3D_CAPTURE_SAVE_POINT_FIRST_POINT_NUMBER) self.numberLineEdit.setText(strFirstNumber) self.updatePosition() def updatePosition(self): connectionRegistry = QgsGPSConnectionRegistry().instance() connectionList = connectionRegistry.connectionList() if connectionList == []: msgBox = QMessageBox(self) msgBox.setIcon(QMessageBox.Information) msgBox.setWindowTitle(constants.CONST_GNSS_3D_CAPTURE_WINDOW_TITLE) msgBox.setText( "GPS connection not detected.\nConnect a GPS and try again") msgBox.exec_() return GPSInfo = connectionList[0].currentGPSInformation() firstCoordinate = GPSInfo.longitude secondCoordinate = GPSInfo.latitude pointCrsGps = QgsPoint(firstCoordinate, secondCoordinate) pointCrs = self.crsOperationFromGps.transform(pointCrsGps) firstCoordinate = pointCrs.x() secondCoordinate = pointCrs.y() if self.crs.geographicFlag(): strFirstCoordinate = constants.CONST_GNSS_3D_CAPTURE_SAVE_POINT_LONGITUDE_PRECISION.format( firstCoordinate) strSecondCoordinate = constants.CONST_GNSS_3D_CAPTURE_SAVE_POINT_LATITUDE_PRECISION.format( secondCoordinate) else: strFirstCoordinate = constants.CONST_GNSS_3D_CAPTURE_SAVE_POINT_EASTING_PRECISION.format( firstCoordinate) strSecondCoordinate = constants.CONST_GNSS_3D_CAPTURE_SAVE_POINT_NORTHING_PRECISION.format( secondCoordinate) self.firstCoordinateLineEdit.setText(strFirstCoordinate) self.secondCoordinateLineEdit.setText(strSecondCoordinate) antennaHeight = float(self.heightAntennaLineEdit.text()) if self.useHeight: height = GPSInfo.elevation heightGround = height - antennaHeight strHeight = constants.CONST_GNSS_3D_CAPTURE_SAVE_POINT_HEIGHT_PRECISION.format( height) self.heightGpsLineEdit.setText(strHeight) strHeightGround = constants.CONST_GNSS_3D_CAPTURE_SAVE_POINT_HEIGHT_PRECISION.format( heightGround) self.heightGroundLineEdit.setText(strHeightGround) if self.useGeoidModel: geoidHeight = self.getGeoidInterpolatedValue( GPSInfo.longitude, GPSInfo.latitude) if geoidHeight == constants.CONST_GNSS_3D_CAPTURE_GEOIDS_NO_VALUE: return strGeoidHeight = constants.CONST_GNSS_3D_CAPTURE_SAVE_POINT_GEOID_HEIGHT_PRECISION.format( geoidHeight) heightFromGeoid = heightGround - geoidHeight strHeightFromGeoid = constants.CONST_GNSS_3D_CAPTURE_SAVE_POINT_HEIGHT_FROM_GEOID_PRECISION.format( heightFromGeoid) self.heightGeoidLineEdit.setText(strGeoidHeight) self.heightFromGeoidLineEdit.setText(strHeightFromGeoid)
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 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))