def testSetDataSource(self): """Test change data source""" temp_dir = QTemporaryDir() options = QgsDataProvider.ProviderOptions() myPath = os.path.join(unitTestDataPath('raster'), 'band1_float32_noct_epsg4326.tif') myFileInfo = QFileInfo(myPath) myBaseName = myFileInfo.baseName() layer = QgsRasterLayer(myPath, myBaseName) renderer = QgsSingleBandGrayRenderer(layer.dataProvider(), 2) image = layer.previewAsImage(QSize(400, 400)) self.assertFalse(image.isNull()) self.assertTrue( image.save(os.path.join(temp_dir.path(), 'expected.png'), "PNG")) layer.setDataSource(myPath.replace('4326.tif', '4326-BAD_SOURCE.tif'), 'bad_layer', 'gdal', options) self.assertFalse(layer.isValid()) image = layer.previewAsImage(QSize(400, 400)) self.assertTrue(image.isNull()) layer.setDataSource(myPath.replace('4326-BAD_SOURCE.tif', '4326.tif'), 'bad_layer', 'gdal', options) self.assertTrue(layer.isValid()) image = layer.previewAsImage(QSize(400, 400)) self.assertFalse(image.isNull()) self.assertTrue( image.save(os.path.join(temp_dir.path(), 'actual.png'), "PNG")) self.assertTrue( filecmp.cmp(os.path.join(temp_dir.path(), 'actual.png'), os.path.join(temp_dir.path(), 'expected.png')), False)
def set_raster_renderer_to_singleband(layer: QgsRasterLayer, band: int = 1) -> None: """ Set raster renderer to singleband :param layer: raster layer :param band: band number starting from 1 """ # https://gis.stackexchange.com/a/377631/123927 and # https://gis.stackexchange.com/a/157573/123927 provider: QgsRasterDataProvider = layer.dataProvider() renderer: QgsSingleBandGrayRenderer = QgsSingleBandGrayRenderer( layer.dataProvider(), band ) stats: QgsRasterBandStats = provider.bandStatistics( band, QgsRasterBandStats.All, layer.extent(), 0 ) min_val = max(stats.minimumValue, 0) max_val = max(stats.maximumValue, 0) enhancement = QgsContrastEnhancement(renderer.dataType(band)) contrast_enhancement = QgsContrastEnhancement.StretchToMinimumMaximum enhancement.setContrastEnhancementAlgorithm(contrast_enhancement, True) enhancement.setMinimumValue(min_val) enhancement.setMaximumValue(max_val) layer.setRenderer(renderer) layer.renderer().setContrastEnhancement(enhancement) layer.triggerRepaint()
def test_syncToLayer_SingleBandGray(self): lyr = self.multibandRasterLayer() lyr.setRenderer(QgsSingleBandGrayRenderer(lyr.dataProvider(), 2)) c = QgsMapCanvas() w = QgsRendererRasterPropertiesWidget(lyr, c) assert isinstance(w.currentRenderWidget().renderer(), QgsSingleBandGrayRenderer) assert w.currentRenderWidget().renderer().grayBand() == 2 lyr.renderer().setGrayBand(1) w.syncToLayer(lyr) assert w.currentRenderWidget().renderer().grayBand() == 1
def update_pc_style(self): """Update the grey style using mean+-5*std for all principal components """ for view_widget in MainAnalysisDialog.view_widgets: if view_widget.pc_id is not None: src_ds = gdal.Open(str(get_file_path_of_layer(view_widget.render_widget.layer)), gdal.GA_ReadOnly) ds = src_ds.GetRasterBand(1).ReadAsArray().flatten().astype(np.float32) ds = ds[ds != 0] try: mean = np.mean(ds) std = np.std(ds) except: continue renderer = QgsSingleBandGrayRenderer(view_widget.render_widget.layer.dataProvider(), 1) ce = QgsContrastEnhancement(view_widget.render_widget.layer.dataProvider().dataType(0)) ce.setContrastEnhancementAlgorithm(QgsContrastEnhancement.StretchToMinimumMaximum) ce.setMinimumValue(mean - 5*std) ce.setMaximumValue(mean + 5*std) renderer.setContrastEnhancement(ce) view_widget.render_widget.layer.setRenderer(renderer) del src_ds, ds
def postProcessAlgorithm(self, context, feedback): output = QgsProcessingUtils.mapLayerFromString(self.output_model, context) provider = output.dataProvider() stats = provider.bandStatistics(1,QgsRasterBandStats.All,output.extent(),0) mean, sd = stats.mean, stats.stdDev rnd = QgsSingleBandGrayRenderer(provider, 1) ce = QgsContrastEnhancement(provider.dataType(1)) ce.setContrastEnhancementAlgorithm(QgsContrastEnhancement.StretchToMinimumMaximum) ce.setMinimumValue(mean-3*sd) ce.setMaximumValue(min(1, mean+2*sd)) rnd.setContrastEnhancement(ce) output.setRenderer(rnd) output.triggerRepaint() return {self.OUTPUT: self.output_model}
def fix_style(layer: QgsRasterLayer) -> None: ''' Sets a sensible default style for loaded raster layers and fix up other issues. By default QGIS uses MultiBandColor renderer if there are multiple bands. (See https://github.com/qgis/QGIS/blob/final-3_0_1/src/core/raster/qgsrasterlayer.cpp#L729). This function picks the right renderers, either a palette or gray-band renderer. Also, fake categories/classes that exist due to GDAL limitations are removed. Search for UNUSED_CATEGORY_LABEL to find details. ''' provider = layer.dataProvider() # type: QgsRasterDataProvider color_interp = provider.colorInterpretation(1) is_palette = color_interp == QgsRaster.PaletteIndex # See the link below on how to create default-type renderers. # https://github.com/qgis/QGIS/blob/final-3_0_1/src/core/raster/qgsrasterrendererregistry.cpp#L128-L137 renderer = layer.renderer() # type: QgsRasterRenderer new_renderer = None if is_palette: # For paletted layers we always re-create the renderer even if it is already a # paletted renderer. This is because we need to remove the UNUSED categories. color_table = provider.colorTable(1) classes = QgsPalettedRasterRenderer.colorTableToClassData(color_table) if not any(c.label == gis4wrf.core.UNUSED_CATEGORY_LABEL for c in classes): return new_classes = filter( lambda c: c.label != gis4wrf.core.UNUSED_CATEGORY_LABEL, classes) new_renderer = QgsPalettedRasterRenderer(renderer.input(), 1, new_classes) layer.setRenderer(new_renderer) else: if not isinstance(renderer, QgsSingleBandGrayRenderer): new_renderer = QgsSingleBandGrayRenderer(renderer.input(), 1) layer.setRenderer(new_renderer) layer.setDefaultContrastEnhancement( ) # must be *after* setting the renderer
def testTransparency(self): myPath = os.path.join(unitTestDataPath('raster'), 'band1_float32_noct_epsg4326.tif') myFileInfo = QFileInfo(myPath) myBaseName = myFileInfo.baseName() myRasterLayer = QgsRasterLayer(myPath, myBaseName) myMessage = 'Raster not loaded: %s' % myPath assert myRasterLayer.isValid(), myMessage renderer = QgsSingleBandGrayRenderer(myRasterLayer.dataProvider(), 1) myRasterLayer.setRenderer(renderer) myRasterLayer.setContrastEnhancement( QgsContrastEnhancement.StretchToMinimumMaximum, QgsRasterMinMaxOrigin.MinMax) myContrastEnhancement = myRasterLayer.renderer().contrastEnhancement() # print ("myContrastEnhancement.minimumValue = %.17g" % # myContrastEnhancement.minimumValue()) # print ("myContrastEnhancement.maximumValue = %.17g" % # myContrastEnhancement.maximumValue()) # Unfortunately the minimum/maximum values calculated in C++ and Python # are slightly different (e.g. 3.3999999521443642e+38 x # 3.3999999521444001e+38) # It is not clear where the precision is lost. # We set the same values as C++. myContrastEnhancement.setMinimumValue(-3.3319999287625854e+38) myContrastEnhancement.setMaximumValue(3.3999999521443642e+38) #myType = myRasterLayer.dataProvider().dataType(1); #myEnhancement = QgsContrastEnhancement(myType); myTransparentSingleValuePixelList = [] rasterTransparency = QgsRasterTransparency() myTransparentPixel1 = \ QgsRasterTransparency.TransparentSingleValuePixel() myTransparentPixel1.min = -2.5840000772112106e+38 myTransparentPixel1.max = -1.0879999684602689e+38 myTransparentPixel1.percentTransparent = 50 myTransparentSingleValuePixelList.append(myTransparentPixel1) myTransparentPixel2 = \ QgsRasterTransparency.TransparentSingleValuePixel() myTransparentPixel2.min = 1.359999960575336e+37 myTransparentPixel2.max = 9.520000231087593e+37 myTransparentPixel2.percentTransparent = 70 myTransparentSingleValuePixelList.append(myTransparentPixel2) rasterTransparency.setTransparentSingleValuePixelList( myTransparentSingleValuePixelList) rasterRenderer = myRasterLayer.renderer() assert rasterRenderer rasterRenderer.setRasterTransparency(rasterTransparency) QgsProject.instance().addMapLayers([myRasterLayer, ]) myMapSettings = QgsMapSettings() myMapSettings.setLayers([myRasterLayer]) myMapSettings.setExtent(myRasterLayer.extent()) myChecker = QgsRenderChecker() myChecker.setControlName("expected_raster_transparency") myChecker.setMapSettings(myMapSettings) myResultFlag = myChecker.runTest("raster_transparency_python") assert myResultFlag, "Raster transparency rendering test failed"
def testSingleBandGrayRenderer(self): # check with StretchToMinimumMaximum rasterRenderer = QgsSingleBandGrayRenderer( self.raster_layer.dataProvider(), 3) self.raster_layer.setRenderer(rasterRenderer) self.raster_layer.setContrastEnhancement( algorithm=QgsContrastEnhancement.StretchToMinimumMaximum, limits=QgsRasterMinMaxOrigin.MinMax) maximum = self.raster_layer.renderer().contrastEnhancement( ).maximumValue() minmum = self.raster_layer.renderer().contrastEnhancement( ).minimumValue() self.assertEqual(minmum, 51) self.assertEqual(maximum, 172) # check default values dom, root = self.rendererToSld(self.raster_layer.renderer()) self.assertNoOpacity(root) self.assertChannelBand(root, 'sld:GrayChannel', '3') elements = root.elementsByTagName('sld:ContrastEnhancement') self.assertEqual(len(elements), 1) enhancement = elements.at(0).toElement() self.assertFalse(enhancement.isNull()) normalize = enhancement.firstChildElement('sld:Normalize') self.assertFalse(normalize.isNull()) self.assertVendorOption(normalize, 'algorithm', 'StretchToMinimumMaximum') self.assertVendorOption(normalize, 'minValue', '51') self.assertVendorOption(normalize, 'maxValue', '172') elements = root.elementsByTagName('sld:ColorMap') self.assertEqual(len(elements), 1) colorMap = elements.at(0).toElement() self.assertFalse(colorMap.isNull()) colorMapEntries = colorMap.elementsByTagName('sld:ColorMapEntry') self.assertEqual(len(colorMapEntries), 2) clorMap1 = colorMapEntries.at(0) self.assertEqual(clorMap1.attributes().namedItem('color').nodeValue(), '#000000') self.assertEqual( clorMap1.attributes().namedItem('quantity').nodeValue(), '0') clorMap2 = colorMapEntries.at(1) self.assertEqual(clorMap2.attributes().namedItem('color').nodeValue(), '#ffffff') self.assertEqual( clorMap2.attributes().namedItem('quantity').nodeValue(), '255') # check when StretchAndClipToMinimumMaximum # then min/max have always to be the real one and not that set in the contrastEnhancement self.raster_layer.setContrastEnhancement( algorithm=QgsContrastEnhancement.StretchAndClipToMinimumMaximum, limits=QgsRasterMinMaxOrigin.MinMax) minmum = self.raster_layer.renderer().contrastEnhancement( ).setMinimumValue(100) maximum = self.raster_layer.renderer().contrastEnhancement( ).maximumValue() minmum = self.raster_layer.renderer().contrastEnhancement( ).minimumValue() self.assertEqual(minmum, 100) self.assertEqual(maximum, 172) dom, root = self.rendererToSld(self.raster_layer.renderer()) self.assertNoOpacity(root) self.assertChannelBand(root, 'sld:GrayChannel', '3') elements = root.elementsByTagName('sld:ContrastEnhancement') self.assertEqual(len(elements), 1) enhancement = elements.at(0).toElement() self.assertFalse(enhancement.isNull()) normalize = enhancement.firstChildElement('sld:Normalize') self.assertFalse(normalize.isNull()) self.assertVendorOption(normalize, 'minValue', '51') self.assertVendorOption(normalize, 'maxValue', '172') elements = root.elementsByTagName('sld:ColorMap') self.assertEqual(len(elements), 1) colorMap = elements.at(0).toElement() self.assertFalse(colorMap.isNull()) colorMapEntries = colorMap.elementsByTagName('sld:ColorMapEntry') self.assertEqual(len(colorMapEntries), 4) clorMap1 = colorMapEntries.at(0) self.assertEqual(clorMap1.attributes().namedItem('color').nodeValue(), '#000000') self.assertEqual( clorMap1.attributes().namedItem('quantity').nodeValue(), '100') self.assertEqual( clorMap1.attributes().namedItem('opacity').nodeValue(), '0') clorMap2 = colorMapEntries.at(1) self.assertEqual(clorMap2.attributes().namedItem('color').nodeValue(), '#000000') self.assertEqual( clorMap2.attributes().namedItem('quantity').nodeValue(), '100') clorMap3 = colorMapEntries.at(2) self.assertEqual(clorMap3.attributes().namedItem('color').nodeValue(), '#ffffff') self.assertEqual( clorMap3.attributes().namedItem('quantity').nodeValue(), '172') clorMap4 = colorMapEntries.at(3) self.assertEqual(clorMap4.attributes().namedItem('color').nodeValue(), '#ffffff') self.assertEqual( clorMap4.attributes().namedItem('quantity').nodeValue(), '172') self.assertEqual( clorMap4.attributes().namedItem('opacity').nodeValue(), '0') # check when ClipToMinimumMaximum # then min/max have always to be the real one and not that set in the contrastEnhancement self.raster_layer.setContrastEnhancement( algorithm=QgsContrastEnhancement.ClipToMinimumMaximum, limits=QgsRasterMinMaxOrigin.MinMax) minmum = self.raster_layer.renderer().contrastEnhancement( ).setMinimumValue(100) maximum = self.raster_layer.renderer().contrastEnhancement( ).maximumValue() minmum = self.raster_layer.renderer().contrastEnhancement( ).minimumValue() self.assertEqual(minmum, 100) self.assertEqual(maximum, 172) dom, root = self.rendererToSld(self.raster_layer.renderer()) self.assertNoOpacity(root) self.assertChannelBand(root, 'sld:GrayChannel', '3') elements = root.elementsByTagName('sld:ContrastEnhancement') self.assertEqual(len(elements), 1) enhancement = elements.at(0).toElement() self.assertFalse(enhancement.isNull()) normalize = enhancement.firstChildElement('sld:Normalize') self.assertFalse(normalize.isNull()) self.assertVendorOption(normalize, 'minValue', '51') self.assertVendorOption(normalize, 'maxValue', '172') elements = root.elementsByTagName('sld:ColorMap') self.assertEqual(len(elements), 1) colorMap = elements.at(0).toElement() self.assertFalse(colorMap.isNull()) colorMapEntries = colorMap.elementsByTagName('sld:ColorMapEntry') self.assertEqual(len(colorMapEntries), 4) clorMap1 = colorMapEntries.at(0) self.assertEqual(clorMap1.attributes().namedItem('color').nodeValue(), '#000000') self.assertEqual( clorMap1.attributes().namedItem('quantity').nodeValue(), '100') self.assertEqual( clorMap1.attributes().namedItem('opacity').nodeValue(), '0') clorMap2 = colorMapEntries.at(1) self.assertEqual(clorMap2.attributes().namedItem('color').nodeValue(), '#000000') self.assertEqual( clorMap2.attributes().namedItem('quantity').nodeValue(), '100') clorMap3 = colorMapEntries.at(2) self.assertEqual(clorMap3.attributes().namedItem('color').nodeValue(), '#ffffff') self.assertEqual( clorMap3.attributes().namedItem('quantity').nodeValue(), '172') clorMap4 = colorMapEntries.at(3) self.assertEqual(clorMap4.attributes().namedItem('color').nodeValue(), '#ffffff') self.assertEqual( clorMap4.attributes().namedItem('quantity').nodeValue(), '172') self.assertEqual( clorMap4.attributes().namedItem('opacity').nodeValue(), '0')
def testBilinearResample(self): path = os.path.join(unitTestDataPath(), 'landsat.tif') raster_layer = QgsRasterLayer(path, 'test') self.assertTrue(raster_layer.isValid()) extent = QgsRectangle(785994.37761193525511771, 3346249.2209800467826426, 786108.49096253968309611, 3346362.94137834152206779) renderer = QgsSingleBandGrayRenderer(raster_layer.dataProvider(), 1) filter = QgsRasterResampleFilter(renderer) # default (nearest neighbour) resampling block = filter.block(1, extent, 2, 2) self.checkBlockContents(block, [[124, 127], [125, 126]]) block = filter.block(1, extent, 4, 4) self.checkBlockContents(block, [[124, 124, 127, 127], [124, 124, 127, 127], [125, 125, 126, 126], [125, 125, 126, 126]]) block = filter.block(1, extent, 8, 8) self.checkBlockContents(block, [[124, 124, 124, 124, 127, 127, 127, 127], [124, 124, 124, 124, 127, 127, 127, 127], [124, 124, 124, 124, 127, 127, 127, 127], [124, 124, 124, 124, 127, 127, 127, 127], [125, 125, 125, 125, 126, 126, 126, 126], [125, 125, 125, 125, 126, 126, 126, 126], [125, 125, 125, 125, 126, 126, 126, 126], [125, 125, 125, 125, 126, 126, 126, 126]]) # with resampling filter.setZoomedInResampler(QgsBilinearRasterResampler()) block = filter.block(1, extent, 2, 2) self.checkBlockContents(block, [[124, 127], [125, 126]]) block = filter.block(1, extent, 4, 4) self.checkBlockContents(block, [[124, 124, 126, 126], [124, 124, 125, 126], [124, 124, 125, 126], [125, 125, 125, 126]]) block = filter.block(1, extent, 8, 8) self.checkBlockContents(block, [[124, 124, 124, 125, 125, 126, 126, 126], [124, 124, 124, 125, 125, 126, 126, 126], [124, 124, 124, 124, 125, 125, 126, 126], [124, 124, 124, 124, 125, 125, 126, 126], [124, 124, 124, 124, 125, 125, 126, 126], [124, 124, 124, 124, 125, 125, 126, 126], [125, 125, 125, 125, 125, 125, 126, 126], [125, 125, 125, 125, 125, 125, 126, 126]]) # with oversampling extent = QgsRectangle(785878.92593475803732872, 3346136.27493690419942141, 786223.56509550288319588, 3346477.7564090033993125) block = filter.block(1, extent, 2, 2) self.checkBlockContents(block, [[127, 126], [125, 126]]) block = filter.block(1, extent, 4, 4) self.checkBlockContents(block, [[125, 127, 127, 127], [126, 127, 127, 126], [125, 126, 126, 126], [127, 125, 125, 125]]) block = filter.block(1, extent, 8, 8) self.checkBlockContents(block, [[126, 126, 126, 126, 125, 125, 125, 126], [126, 126, 125, 125, 125, 126, 126, 126], [126, 125, 124, 124, 125, 126, 126, 126], [126, 125, 124, 124, 125, 126, 126, 126], [125, 125, 124, 124, 124, 126, 126, 126], [125, 125, 125, 125, 125, 126, 126, 126], [125, 125, 125, 125, 125, 126, 126, 126], [125, 125, 126, 126, 125, 125, 125, 125]]) filter.setMaxOversampling(2) block = filter.block(1, extent, 2, 2) self.checkBlockContents(block, [[127, 126], [125, 126]]) block = filter.block(1, extent, 4, 4) self.checkBlockContents(block, [[125, 127, 127, 127], [126, 127, 127, 126], [125, 126, 126, 126], [127, 125, 125, 125]]) block = filter.block(1, extent, 8, 8) self.checkBlockContents(block, [[126, 126, 126, 126, 125, 125, 125, 126], [126, 126, 125, 125, 125, 126, 126, 126], [126, 125, 124, 124, 125, 126, 126, 126], [126, 125, 124, 124, 125, 126, 126, 126], [125, 125, 124, 124, 124, 126, 126, 126], [125, 125, 125, 125, 125, 126, 126, 126], [125, 125, 125, 125, 125, 126, 126, 126], [125, 125, 126, 126, 125, 125, 125, 125]]) filter.setMaxOversampling(4) block = filter.block(1, extent, 2, 2) self.checkBlockContents(block, [[127, 126], [125, 126]]) block = filter.block(1, extent, 4, 4) self.checkBlockContents(block, [[125, 127, 127, 127], [126, 127, 127, 126], [125, 126, 126, 126], [127, 125, 125, 125]]) block = filter.block(1, extent, 8, 8) self.checkBlockContents(block, [[126, 126, 126, 126, 125, 125, 125, 126], [126, 126, 125, 125, 125, 126, 126, 126], [126, 125, 124, 124, 125, 126, 126, 126], [126, 125, 124, 124, 125, 126, 126, 126], [125, 125, 124, 124, 124, 126, 126, 126], [125, 125, 125, 125, 125, 126, 126, 126], [125, 125, 125, 125, 125, 126, 126, 126], [125, 125, 126, 126, 125, 125, 125, 125]])
def apply_styles(self, layer, cap=None): if not layer: return fname = os.path.basename(layer.dataProvider().dataSourceUri()) if cap == None: if ('Composite' not in fname) and ('Blurred' not in fname): radius = self.fname2usmradius(fname) cap = self.usm_cap(radius) ## Pesudocolor method <- It works except legend ## #shader, colorramp = QgsRasterShader(), QgsColorRampShader() #colorramp.setClassificationMode(1) #colorramp.setColorRampType(QgsColorRampShader.Interpolated) #colorramp.setColorRampItemList([ \ # QgsColorRampShader.ColorRampItem(-100, QColor(0,0,0)), \ # QgsColorRampShader.ColorRampItem(100, QColor(255,255,255))]) #shader.setRasterShaderFunction(colorramp) #render = QgsSingleBandPseudoColorRenderer(usmlayer.dataProvider(), usmlayer.type(), shader) #usmlayer.setRenderer(render) #usmlayer.renderer().setClassificationMin(-100) #usmlayer.renderer().setClassificationMin(100) ## Grayscale method ## render = QgsSingleBandGrayRenderer(layer.dataProvider(), layer.type()) ## Create a custom QGIS style file (QML) path_defaultQML = os.path.join( os.path.dirname(os.path.realpath(__file__)), 'USM_styletemplate.qml') path_tmpQML = os.path.join(os.path.dirname(os.path.realpath(__file__)), 'tmp.qml') tree = ET.parse(path_defaultQML) root = tree.getroot() minval = root.find( './pipe/rasterrenderer/contrastEnhancement/minValue') maxval = root.find( './pipe/rasterrenderer/contrastEnhancement/maxValue') minval.text, maxval.text = str(-1 * cap), str(cap) tree.write(path_tmpQML) ## Another failed atteampt to set minmax #fp = QFile(path_tmpQML); fp.open(QIODevice.ReadOnly) #doc = QDomDocument(); doc.setContent(fp); fp.close() #elem = doc.documentElement() #QDOMElement #contrast = QgsContrastEnhancement() #contrast.readXml(elem) #contrast.setContrastEnhancementAlgorithm(QgsContrastEnhancement.StretchToMinimumMaximum, False) #contrast.setMaximumValue(100, False); contrast.setMinimumValue(-100, True) # <- Completely broken #render.setContrastEnhancement(contrast) #render.setGradient(QgsSingleBandGrayRenderer.BlackToWhite) #usmlayer.setRenderer(render) ## Another failed attempt to set minmax ## #bounds = QgsRasterMinMaxOrigin() #bounds.setExtent(QgsRasterMinMaxOrigin.WholeRaster) #bounds.setLimits(QgsRasterMinMaxOrigin.StdDev) #bounds.setStatAccuracy(QgsRasterMinMaxOrigin.Estimated) #usmlayer.renderer().setMinMaxOrigin(bounds) ## Then import it to the layer layer.setBlendMode(QPainter.CompositionMode_Overlay) layer.loadNamedStyle(path_tmpQML) layer.setCrs(self.dlg.mMapLayerComboBox.currentLayer().crs()) layer.emitStyleChanged() # <- Broken? layer.triggerRepaint()