def testFilterNeedsGeometry(self): renderer = QgsGraduatedSymbolRenderer() renderer.setClassAttribute("value") self.assertFalse(renderer.filterNeedsGeometry()) renderer.setClassAttribute("$area") self.assertTrue(renderer.filterNeedsGeometry()) renderer.setClassAttribute("value - $area") self.assertTrue(renderer.filterNeedsGeometry())
def testUsedAttributes(self): renderer = QgsGraduatedSymbolRenderer() ctx = QgsRenderContext() # attribute can contain either attribute name or an expression. # Sometimes it is not possible to distinguish between those two, # e.g. "a - b" can be both a valid attribute name or expression. # Since we do not have access to fields here, the method should return both options. renderer.setClassAttribute("value") self.assertEqual(renderer.usedAttributes(ctx), {"value"}) renderer.setClassAttribute("value - 1") self.assertEqual(renderer.usedAttributes(ctx), {"value", "value - 1"}) renderer.setClassAttribute("valuea - valueb") self.assertEqual(renderer.usedAttributes(ctx), {"valuea", "valuea - valueb", "valueb"})
def addNetworkLayer(self, progressBar, layerName, scenariosExpression, networkExpression, variable, level, projectPath, group, networkLinkShapePath, method, expressionNetworkText, color): """ @summary: Get operators dictionary @param layerName: Layer name @type layerName: String @param scenariosExpression: Scenarios expression @type scenariosExpression: Stack object @param networkExpression: Network expression @type networkExpression: Stack object @param variable: Variable to evaluate @type variable: String @param level: Level to evaluate (Total, Routes, Operators) @type level: Level object @param projectPath: Project path @type projectPath: String @param group: Project group @type group: Layer group @param networkLinkShapePath: Network link shape path @type networkLinkShapePath: String @return: Result of the layer creation """ if scenariosExpression is None: QMessageBox.warning(None, "Network expression", "There is not scenarios information.") print("There is not scenarios information.") return False result, resultData, minValue, maxValue = self.network_data_access.create_network_memory( layerName, scenariosExpression, networkExpression, variable, level, projectPath) progressBar.setValue(15) registry = QgsProject.instance() layersCount = len(registry.mapLayers()) if result: # Source shape, name of the new shape, providerLib layer = QgsVectorLayer(networkLinkShapePath, layerName + "_network", 'ogr') epsg = layer.crs().postgisSrid() intMethod = 0 if method == "Color" else 1 progressBar.setValue(20) if not layer.isValid(): return False feats = [feat for feat in layer.getFeatures()] # Create a vector layer with data on Memory memoryLayer = QgsVectorLayer("LineString?crs=epsg:" + str(epsg), layerName + "_network", "memory") registry.addMapLayer(memoryLayer) memory_data = memoryLayer.dataProvider() joinedFieldName = "Result" shpField = "Id" attr = layer.dataProvider().fields().toList() attr += [QgsField(joinedFieldName, QVariant.Double)] progressBar.setValue(25) memory_data.addAttributes(attr) memory_data.addFeatures(feats) memoryLayer.startEditing() num = 30 progressBar.setValue(num) progressInterval = 70 / len(resultData) for rowItem in np.nditer(resultData): value = 0 num += progressInterval progressBar.setValue(num) it = memoryLayer.getFeatures("LINKID = '{0}'".format( str(rowItem['Id']).replace("b", "").replace("'", ""))) for id_feature in it: memoryLayer.changeAttributeValue( id_feature.id(), memory_data.fieldNameIndex(joinedFieldName), QVariant(round(float(rowItem['Result']), 2))) memoryLayer.commitChanges() rowCounter = len(resultData) myStyle = QgsStyle().defaultStyle() defaultColorRampNames = myStyle.colorRampNames() ramp = myStyle.colorRamp(defaultColorRampNames[0]) ranges = [] nCats = ramp.count() rng = maxValue - minValue nCats = 8 scale = QgsMapUnitScale(minValue, maxValue) if method == "Color": color1 = list( map(lambda x: int(x), color['color1'].split(",")[0:3])) color2 = list( map(lambda x: int(x), color['color2'].split(",")[0:3])) interpolatedColors = HP.linear_gradient(color1, color2, nCats) for i in range(0, nCats): v0 = minValue + rng / float(nCats) * i v1 = minValue + rng / float(nCats) * (i + 1) if method == "Color": line = QgsSimpleLineSymbolLayer( QColor(interpolatedColors['r'][i], interpolatedColors['g'][i], interpolatedColors['b'][i])) #line.setOffsetUnit(2) line.setOffset(0.55) #line.setWidthUnit(2) line.setWidth(0.7) symbol = QgsLineSymbol() symbol.changeSymbolLayer(0, line) myRange = QgsRendererRange(v0, v1, symbol, "") elif method == "Size": qcolor = QColor() qcolor.setRgb(color) line = QgsSimpleLineSymbolLayer(qcolor) #line.setOffsetUnit(2) line.setOffset(0.2) #line.setWidthUnit(2) #line.setWidth(1) # Symbol # symbolLine = QgsSimpleMarkerSymbolLayer(QgsSimpleMarkerSymbolLayerBase.ArrowHead) # Mark line # markLine = QgsMarkerLineSymbolLayer() # markLine.setPlacement(4) symbolo = QgsLineSymbol() symbolo.changeSymbolLayer(0, line) # symbolo.appendSymbolLayer(line) myRange = QgsRendererRange(v0, v1, symbolo, "") ranges.append(myRange) # The first parameter refers to the name of the field that contains the calculated value (expression) modeRender = QgsGraduatedSymbolRenderer.Mode(2) renderer = QgsGraduatedSymbolRenderer(joinedFieldName, ranges) renderer.setMode(modeRender) if method == "Size": renderer.setSymbolSizes(0.200000, 2.60000) else: renderer.setSourceColorRamp(ramp) renderer.setGraduatedMethod(intMethod) #renderer.updateClasses(memoryLayer, modeRender, 8) memoryLayer.setRenderer(renderer) typeLayer = "network" networkExpressionText = str(scenariosExpression) # Create XML File ".qtranus" with the parameters of the executions if FileMXML.if_exist_xml_layers(projectPath): if FileMXML.if_exist_layer(projectPath, memoryLayer.id()): FileMXML.update_xml_file(memoryLayer.name(), memoryLayer.id(), scenariosExpression, variable, networkExpression, projectPath, expressionNetworkText, method, level, color) else: FileMXML.add_layer_xml_file(memoryLayer.name(), memoryLayer.id(), scenariosExpression, variable, networkExpression, projectPath, expressionNetworkText, shpField, typeLayer, method, level, color) else: FileMXML.create_xml_file(memoryLayer.name(), memoryLayer.id(), scenariosExpression, variable, networkExpression, projectPath, expressionNetworkText, shpField, typeLayer, method, level, color) #group.insertLayer((layersCount+1), memoryLayer) progressBar.setValue(100) return True
def testQgsGraduatedSymbolRenderer_3(self): """Test QgsGraduatedSymbolRenderer: Reading attribute data, calculating classes """ # Create a renderer renderer = QgsGraduatedSymbolRenderer() symbol = createMarkerSymbol() renderer.setSourceSymbol(symbol.clone()) # Test retrieving data values from a layer ml = createMemoryLayer((1.2, 0.5, 5.0, 1.0, 1.0, 1.2)) renderer.setClassAttribute("value") # Equal interval calculations renderer.updateClasses(ml, renderer.EqualInterval, 3) self.assertEqual(dumpRangeBreaks(renderer.ranges()), '(0.5000-2.0000,2.0000-3.5000,3.5000-5.0000,)', 'Equal interval classification not correct') # Quantile classes renderer.updateClasses(ml, renderer.Quantile, 3) self.assertEqual(dumpRangeBreaks(renderer.ranges()), '(0.5000-1.0000,1.0000-1.2000,1.2000-5.0000,)', 'Quantile classification not correct') renderer.updateClasses(ml, renderer.Quantile, 4) self.assertEqual( dumpRangeBreaks(renderer.ranges()), '(0.5000-1.0000,1.0000-1.1000,1.1000-1.2000,1.2000-5.0000,)', 'Quantile classification not correct')
def testQgsGraduatedSymbolRenderer_2(self): """Test QgsGraduatedSymbolRenderer: Adding /removing/editing classes """ # Create a renderer renderer = QgsGraduatedSymbolRenderer() symbol = createMarkerSymbol() renderer.setSourceSymbol(symbol.clone()) symbol.setColor(QColor(255, 0, 0)) # Add class without start and end ranges renderer.addClass(symbol.clone()) renderer.addClass(symbol.clone()) renderer.updateRangeLabel(1, 'Second range') renderer.updateRangeLowerValue(1, 10.0) renderer.updateRangeUpperValue(1, 25.0) renderer.updateRangeRenderState(1, False) symbol.setColor(QColor(0, 0, 255)) renderer.updateRangeSymbol(1, symbol.clone()) # Add as a rangeobject symbol.setColor(QColor(0, 255, 0)) range = QgsRendererRange(20.0, 25.5, symbol.clone(), 'Third range', False) renderer.addClassRange(range) # Add class by lower and upper renderer.addClassLowerUpper(25.5, 30.5) # (Update label for sorting tests) renderer.updateRangeLabel(3, 'Another range') self.assertEqual( dumpRangeLabels(renderer.ranges()), '(0.0 - 0.0,Second range,Third range,Another range,)', 'Added ranges labels not correct') self.assertEqual( dumpRangeBreaks(renderer.ranges()), '(0.0000-0.0000,10.0000-25.0000,20.0000-25.5000,25.5000-30.5000,)', 'Added ranges lower/upper values not correct') # Check that clone function works renderer2 = renderer.clone() self.assertEqual(dumpGraduatedRenderer(renderer), dumpGraduatedRenderer(renderer2), "clone function doesn't replicate renderer properly") # Check save and reload from Dom works doc = QDomDocument() element = renderer.save(doc, QgsReadWriteContext()) renderer2 = QgsGraduatedSymbolRenderer.create(element, QgsReadWriteContext()) self.assertEqual( dumpGraduatedRenderer(renderer), dumpGraduatedRenderer(renderer2), "Save/create from DOM doesn't replicate renderer properly") # Check sorting renderer.sortByLabel() self.assertEqual( dumpRangeList(renderer.ranges(), labelsOnly=True), '(0.0 - 0.0,Another range,Second range,Third range,)', 'sortByLabel not correct') renderer.sortByValue() self.assertEqual( dumpRangeBreaks(renderer.ranges()), '(0.0000-0.0000,10.0000-25.0000,20.0000-25.5000,25.5000-30.5000,)', 'sortByValue not correct') renderer.sortByValue(Qt.DescendingOrder) self.assertEqual( dumpRangeBreaks(renderer.ranges()), '(25.5000-30.5000,20.0000-25.5000,10.0000-25.0000,0.0000-0.0000,)', 'sortByValue descending not correct') # Check deleting renderer.deleteClass(2) self.assertEqual(dumpRangeBreaks(renderer.ranges()), '(25.5000-30.5000,20.0000-25.5000,0.0000-0.0000,)', 'deleteClass not correct') renderer.deleteAllClasses() self.assertEqual(len(renderer.ranges()), 0, "deleteAllClasses didn't delete all")
def testQgsGraduatedSymbolRenderer_1(self): """Test QgsGraduatedSymbolRenderer: Basic get/set functions """ # Create a renderer renderer = QgsGraduatedSymbolRenderer() symbol = createMarkerSymbol() renderer.setSourceSymbol(symbol.clone()) self.assertEqual(symbol.dump(), renderer.sourceSymbol().dump(), "Get/set renderer source symbol") attr = '"value"*"value"' renderer.setClassAttribute(attr) self.assertEqual(attr, renderer.classAttribute(), "Get/set renderer class attribute") for m in ( QgsGraduatedSymbolRenderer.Custom, QgsGraduatedSymbolRenderer.EqualInterval, QgsGraduatedSymbolRenderer.Quantile, QgsGraduatedSymbolRenderer.Jenks, QgsGraduatedSymbolRenderer.Pretty, QgsGraduatedSymbolRenderer.StdDev, ): renderer.setMode(m) self.assertEqual(m, renderer.mode(), "Get/set renderer mode") format = createLabelFormat() renderer.setLabelFormat(format) self.assertEqual(dumpLabelFormat(format), dumpLabelFormat(renderer.labelFormat()), "Get/set renderer label format") ramp = createColorRamp() renderer.setSourceColorRamp(ramp) self.assertEqual(dumpColorRamp(ramp), dumpColorRamp(renderer.sourceColorRamp()), "Get/set renderer color ramp") renderer.setSourceColorRamp(ramp) self.assertEqual(dumpColorRamp(ramp), dumpColorRamp(renderer.sourceColorRamp()), "Get/set renderer color ramp") # test for classificatio with varying size renderer.setGraduatedMethod(QgsGraduatedSymbolRenderer.GraduatedSize) renderer.setSourceColorRamp(None) renderer.addClassLowerUpper(0, 2) renderer.addClassLowerUpper(2, 4) renderer.addClassLowerUpper(4, 6) renderer.setSymbolSizes(2, 13) self.assertEqual(renderer.maxSymbolSize(), 13) self.assertEqual(renderer.minSymbolSize(), 2) refSizes = [2, (13 + 2) * .5, 13] ctx = QgsRenderContext() for idx, symbol in enumerate(renderer.symbols(ctx)): self.assertEqual(symbol.size(), refSizes[idx])
def processAlgorithm(self, parameters, context, feedback): # Couche buffer : input_featuresource = self.parameterAsSource(parameters, 'INPUT', context) # Buffer distance : bufferdist = self.parameterAsDouble(parameters, 'BUFFERDIST', context) # Check for cancelation if feedback.isCanceled(): return {} buffer_result = processing.run( 'native:buffer', { # Here we pass on the original parameter values of INPUT # and BUFFER_OUTPUT to the buffer algorithm. 'INPUT': parameters['INPUT'], 'OUTPUT': parameters['BUFFER_OUTPUT'], 'DISTANCE': bufferdist, 'SEGMENTS': 10, 'DISSOLVE': True, 'END_CAP_STYLE': 0, 'JOIN_STYLE': 0, 'MITER_LIMIT': 10 }, # Because the buffer algorithm is being run as a step in # another larger algorithm, the is_child_algorithm option # should be set to True is_child_algorithm=True, # # It's important to pass on the context and feedback objects to # child algorithms, so that they can properly give feedback to # users and handle cancelation requests. context=context, feedback=feedback) # Check for cancelation if feedback.isCanceled(): return {} # Selection de la couche cable : cables = QgsVectorLayer( "/Users/pierre-loupgarrigues/Python JupyterLab/M2/pyqgis/Evaluation_pyqgis/data/cables.shp", "cables", "ogr") cables = iface.activeLayer() # Séléction des cables en fonction des paramètres choisis : cables.selectByExpression( " \"capacite\" > '{}' AND \"mode_pose\" = '{}' ".format( parameters[self.CAPACITE], parameters[self.MODE_DE_POSE])) # Vérification : selectionCapacite = self.parameterAsDouble(parameters, 'CAPACITE', context) print(selectionCapacite) # Vérification : selectionModeDePose = self.parameterAsString(parameters, 'MODE_DE_POSE', context) print(selectionModeDePose) # Sauvegarde de la séléction des cables : cables_selection = processing.run( 'qgis:saveselectedfeatures', { 'INPUT': cables, #'OUTPUT':'memory:' 'OUTPUT': parameters['CABLES_OUTPUT'] }, context=context, feedback=feedback, is_child_algorithm=True) mes_cables = cables_selection['OUTPUT'] ### SYMBOLOGIE GRADUEE nb_prises = ( ('Faible', 0, 9, 'green'), ('Moyen_1', 10, 25, 'yellow'), ('Moyen_2', 26, 100, 'orange'), ('Eleve', 101, 1000000, 'red'), ) # creation ranges = [] for label, lower, upper, color in nb_prises: symbol = QgsSymbol.defaultSymbol(cables.geometryType()) symbol.setColor(QColor(color)) rng = QgsRendererRange(lower, upper, symbol, label) ranges.append(rng) # create the renderer and assign it to a layer expression = 'nb_prises' # field name renderer = QgsGraduatedSymbolRenderer(expression, ranges) cables.setRenderer(renderer) # Return the results return { 'BUFFER_OUTPUT': buffer_result['OUTPUT'], 'CABLES_OUTPUT': cables_selection['OUTPUT'] }
def testQgsGraduatedSymbolRenderer_2(self): """Test QgsGraduatedSymbolRenderer: Adding /removing/editing classes """ # Create a renderer renderer = QgsGraduatedSymbolRenderer() symbol = createMarkerSymbol() renderer.setSourceSymbol(symbol.clone()) symbol.setColor(QColor(255, 0, 0)) # Add class without start and end ranges renderer.addClass(symbol.clone()) renderer.addClass(symbol.clone()) renderer.updateRangeLabel(1, 'Second range') renderer.updateRangeLowerValue(1, 10.0) renderer.updateRangeUpperValue(1, 25.0) renderer.updateRangeRenderState(1, False) symbol.setColor(QColor(0, 0, 255)) renderer.updateRangeSymbol(1, symbol.clone()) # Add as a rangeobject symbol.setColor(QColor(0, 255, 0)) range = QgsRendererRange(20.0, 25.5, symbol.clone(), 'Third range', False) renderer.addClassRange(range) # Add class by lower and upper renderer.addClassLowerUpper(25.5, 30.5) # (Update label for sorting tests) renderer.updateRangeLabel(3, 'Another range') self.assertEqual( dumpRangeLabels(renderer.ranges()), '(0.0 - 0.0,Second range,Third range,Another range,)', 'Added ranges labels not correct') self.assertEqual( dumpRangeBreaks(renderer.ranges()), '(0.0000-0.0000,10.0000-25.0000,20.0000-25.5000,25.5000-30.5000,)', 'Added ranges lower/upper values not correct') # Check that clone function works renderer2 = renderer.clone() self.assertEqual( dumpGraduatedRenderer(renderer), dumpGraduatedRenderer(renderer2), "clone function doesn't replicate renderer properly" ) # Check save and reload from Dom works doc = QDomDocument() element = renderer.save(doc, QgsReadWriteContext()) renderer2 = QgsGraduatedSymbolRenderer.create(element, QgsReadWriteContext()) self.assertEqual( dumpGraduatedRenderer(renderer), dumpGraduatedRenderer(renderer2), "Save/create from DOM doesn't replicate renderer properly" ) # Check sorting renderer.sortByLabel() self.assertEqual( dumpRangeList(renderer.ranges(), labelsOnly=True), '(0.0 - 0.0,Another range,Second range,Third range,)', 'sortByLabel not correct') renderer.sortByValue() self.assertEqual( dumpRangeBreaks(renderer.ranges()), '(0.0000-0.0000,10.0000-25.0000,20.0000-25.5000,25.5000-30.5000,)', 'sortByValue not correct') renderer.sortByValue(Qt.DescendingOrder) self.assertEqual( dumpRangeBreaks(renderer.ranges()), '(25.5000-30.5000,20.0000-25.5000,10.0000-25.0000,0.0000-0.0000,)', 'sortByValue descending not correct') # Check deleting renderer.deleteClass(2) self.assertEqual( dumpRangeBreaks(renderer.ranges()), '(25.5000-30.5000,20.0000-25.5000,0.0000-0.0000,)', 'deleteClass not correct') renderer.deleteAllClasses() self.assertEqual(len(renderer.ranges()), 0, "deleteAllClasses didn't delete all")
def testQgsGraduatedSymbolRenderer_3(self): """Test QgsGraduatedSymbolRenderer: Reading attribute data, calculating classes """ # Create a renderer renderer = QgsGraduatedSymbolRenderer() symbol = createMarkerSymbol() renderer.setSourceSymbol(symbol.clone()) # Test retrieving data values from a layer ml = createMemoryLayer((1.2, 0.5, 5.0, 1.0, 1.0, 1.2)) # ... by attribute renderer.setClassAttribute("value") self.assertEqual(renderer.classAttribute(), "value", "Error in set/get classAttribute") data = renderer.getDataValues(ml) datastr = ':'.join([str(x) for x in data]) self.assertEqual(datastr, '1.2:0.5:5.0:1.0:1.0:1.2', "Error returning field data") # ... by expression renderer.setClassAttribute('"value"*"value"') self.assertEqual(renderer.classAttribute(), '"value"*"value"', "Error in set/get classAttribute") data = renderer.getDataValues(ml) datastr = ':'.join([str(x) for x in data]) self.assertEqual(datastr, '1.44:0.25:25.0:1.0:1.0:1.44', "Error returning field expression") renderer.setClassAttribute("value") # Equal interval calculations renderer.updateClasses(ml, renderer.EqualInterval, 3) self.assertEqual(dumpRangeBreaks(renderer.ranges()), '(0.5000-2.0000,2.0000-3.5000,3.5000-5.0000,)', 'Equal interval classification not correct') # Quantile classes renderer.updateClasses(ml, renderer.Quantile, 3) self.assertEqual(dumpRangeBreaks(renderer.ranges()), '(0.5000-1.0000,1.0000-1.2000,1.2000-5.0000,)', 'Quantile classification not correct') renderer.updateClasses(ml, renderer.Quantile, 4) self.assertEqual( dumpRangeBreaks(renderer.ranges()), '(0.5000-1.0000,1.0000-1.1000,1.1000-1.2000,1.2000-5.0000,)', 'Quantile classification not correct')
def testQgsGraduatedSymbolRenderer_1(self): """Test QgsGraduatedSymbolRenderer: Basic get/set functions """ # Create a renderer renderer = QgsGraduatedSymbolRenderer() symbol = createMarkerSymbol() renderer.setSourceSymbol(symbol.clone()) self.assertEqual(symbol.dump(), renderer.sourceSymbol().dump(), "Get/set renderer source symbol") attr = '"value"*"value"' renderer.setClassAttribute(attr) self.assertEqual(attr, renderer.classAttribute(), "Get/set renderer class attribute") for m in ( QgsGraduatedSymbolRenderer.Custom, QgsGraduatedSymbolRenderer.EqualInterval, QgsGraduatedSymbolRenderer.Quantile, QgsGraduatedSymbolRenderer.Jenks, QgsGraduatedSymbolRenderer.Pretty, QgsGraduatedSymbolRenderer.StdDev, ): renderer.setMode(m) self.assertEqual(m, renderer.mode(), "Get/set renderer mode") format = createLabelFormat() renderer.setLabelFormat(format) self.assertEqual(dumpLabelFormat(format), dumpLabelFormat(renderer.labelFormat()), "Get/set renderer label format") ramp = createColorRamp() renderer.setSourceColorRamp(ramp) self.assertEqual(dumpColorRamp(ramp), dumpColorRamp(renderer.sourceColorRamp()), "Get/set renderer color ramp") renderer.setInvertedColorRamp(True) self.assertTrue(renderer.invertedColorRamp(), "Get/set renderer inverted color ramp") renderer.setInvertedColorRamp(False) self.assertFalse(renderer.invertedColorRamp(), "Get/set renderer inverted color ramp") value = '"value"*2' exp = QgsSymbolLayerUtils.fieldOrExpressionToExpression(value) valuestr = QgsSymbolLayerUtils.fieldOrExpressionFromExpression(exp) renderer.setRotationField(value) self.assertEqual(valuestr, renderer.rotationField(), "Get/set renderer rotation field") value = '"value"*3' exp = QgsSymbolLayerUtils.fieldOrExpressionToExpression(value) valuestr = QgsSymbolLayerUtils.fieldOrExpressionFromExpression(exp) renderer.setSizeScaleField(value) self.assertEqual(valuestr, renderer.sizeScaleField(), "Get/set renderer size scale field") renderer.setSourceColorRamp(ramp) self.assertEqual(dumpColorRamp(ramp), dumpColorRamp(renderer.sourceColorRamp()), "Get/set renderer color ramp") for sm in ( QgsSymbol.ScaleArea, QgsSymbol.ScaleDiameter, ): renderer.setScaleMethod(sm) self.assertEqual(str(sm), str(renderer.scaleMethod()), "Get/set renderer scale method") # test for classificatio with varying size renderer.setGraduatedMethod(QgsGraduatedSymbolRenderer.GraduatedSize) renderer.setSourceColorRamp(None) renderer.addClassLowerUpper(0, 2) renderer.addClassLowerUpper(2, 4) renderer.addClassLowerUpper(4, 6) renderer.setSymbolSizes(2, 13) self.assertEqual(renderer.maxSymbolSize(), 13) self.assertEqual(renderer.minSymbolSize(), 2) refSizes = [2, (13 + 2) * .5, 13] ctx = QgsRenderContext() for idx, symbol in enumerate(renderer.symbols2(ctx)): self.assertEqual(symbol.size(), refSizes[idx])
def testQgsGraduatedSymbolRenderer_3(self): """Test QgsGraduatedSymbolRenderer: Reading attribute data, calculating classes """ # Create a renderer renderer = QgsGraduatedSymbolRenderer() symbol = createMarkerSymbol() renderer.setSourceSymbol(symbol.clone()) # Test retrieving data values from a layer ml = createMemoryLayer((1.2, 0.5, 5.0, 1.0, 1.0, 1.2)) # ... by attribute renderer.setClassAttribute("value") self.assertEqual(renderer.classAttribute(), "value", "Error in set/get classAttribute") data = renderer.getDataValues(ml) datastr = ':'.join([str(x) for x in data]) self.assertEqual(datastr, '1.2:0.5:5.0:1.0:1.0:1.2', "Error returning field data") # ... by expression renderer.setClassAttribute('"value"*"value"') self.assertEqual(renderer.classAttribute(), '"value"*"value"', "Error in set/get classAttribute") data = renderer.getDataValues(ml) datastr = ':'.join([str(x) for x in data]) self.assertEqual(datastr, '1.44:0.25:25.0:1.0:1.0:1.44', "Error returning field expression") renderer.setClassAttribute("value") # Equal interval calculations renderer.updateClasses(ml, renderer.EqualInterval, 3) self.assertEqual( dumpRangeBreaks(renderer.ranges()), '(0.5000-2.0000,2.0000-3.5000,3.5000-5.0000,)', 'Equal interval classification not correct') # Quantile classes renderer.updateClasses(ml, renderer.Quantile, 3) self.assertEqual( dumpRangeBreaks(renderer.ranges()), '(0.5000-1.0000,1.0000-1.2000,1.2000-5.0000,)', 'Quantile classification not correct') renderer.updateClasses(ml, renderer.Quantile, 4) self.assertEqual( dumpRangeBreaks(renderer.ranges()), '(0.5000-1.0000,1.0000-1.1000,1.1000-1.2000,1.2000-5.0000,)', 'Quantile classification not correct')
def testQgsGraduatedSymbolRenderer_1(self): """Test QgsGraduatedSymbolRenderer: Basic get/set functions """ # Create a renderer renderer = QgsGraduatedSymbolRenderer() symbol = createMarkerSymbol() renderer.setSourceSymbol(symbol.clone()) self.assertEqual(symbol.dump(), renderer.sourceSymbol().dump(), "Get/set renderer source symbol") attr = '"value"*"value"' renderer.setClassAttribute(attr) self.assertEqual(attr, renderer.classAttribute(), "Get/set renderer class attribute") for m in ( QgsGraduatedSymbolRenderer.Custom, QgsGraduatedSymbolRenderer.EqualInterval, QgsGraduatedSymbolRenderer.Quantile, QgsGraduatedSymbolRenderer.Jenks, QgsGraduatedSymbolRenderer.Pretty, QgsGraduatedSymbolRenderer.StdDev, ): renderer.setMode(m) self.assertEqual(m, renderer.mode(), "Get/set renderer mode") format = createLabelFormat() renderer.setLabelFormat(format) self.assertEqual( dumpLabelFormat(format), dumpLabelFormat(renderer.labelFormat()), "Get/set renderer label format") ramp = createColorRamp() renderer.setSourceColorRamp(ramp) self.assertEqual( dumpColorRamp(ramp), dumpColorRamp(renderer.sourceColorRamp()), "Get/set renderer color ramp") renderer.setInvertedColorRamp(True) self.assertTrue(renderer.invertedColorRamp(), "Get/set renderer inverted color ramp") renderer.setInvertedColorRamp(False) self.assertFalse(renderer.invertedColorRamp(), "Get/set renderer inverted color ramp") value = '"value"*2' exp = QgsSymbolLayerUtils.fieldOrExpressionToExpression(value) valuestr = QgsSymbolLayerUtils.fieldOrExpressionFromExpression(exp) renderer.setRotationField(value) self.assertEqual(valuestr, renderer.rotationField(), "Get/set renderer rotation field") value = '"value"*3' exp = QgsSymbolLayerUtils.fieldOrExpressionToExpression(value) valuestr = QgsSymbolLayerUtils.fieldOrExpressionFromExpression(exp) renderer.setSizeScaleField(value) self.assertEqual(valuestr, renderer.sizeScaleField(), "Get/set renderer size scale field") renderer.setSourceColorRamp(ramp) self.assertEqual( dumpColorRamp(ramp), dumpColorRamp(renderer.sourceColorRamp()), "Get/set renderer color ramp") for sm in ( QgsSymbol.ScaleArea, QgsSymbol.ScaleDiameter, ): renderer.setScaleMethod(sm) self.assertEqual(str(sm), str(renderer.scaleMethod()), "Get/set renderer scale method") # test for classificatio with varying size renderer.setGraduatedMethod(QgsGraduatedSymbolRenderer.GraduatedSize) renderer.setSourceColorRamp(None) renderer.addClassLowerUpper(0, 2) renderer.addClassLowerUpper(2, 4) renderer.addClassLowerUpper(4, 6) renderer.setSymbolSizes(2, 13) self.assertEqual(renderer.maxSymbolSize(), 13) self.assertEqual(renderer.minSymbolSize(), 2) refSizes = [2, (13 + 2) * .5, 13] ctx = QgsRenderContext() for idx, symbol in enumerate(renderer.symbols2(ctx)): self.assertEqual(symbol.size(), refSizes[idx])
class LayerBase(QgsVectorLayer): """QGIS layer base class (read-only memory based). :param fileName: path to input file :param storageFormat: storage format for layer (Memory or SQLite) """ def __init__(self, fileName, storageFormat): self._fileName = fileName self._layerName = os.path.splitext(os.path.basename(self._fileName))[0] self.storageFormat = storageFormat # create point layer (WGS-84, EPSG:4326) super(LayerBase, self).__init__('Point?crs=epsg:4326', self._layerName, "memory") self._aliases = [] # list of attribute aliases self._provider = self.dataProvider() # import errors self._errs = {} # layer is empty, no data loaded self._loaded = False self.metadata = None # layer type not defined self.layerType = None # style self._style = Style() self._renderer = None def load(self, reader): """Load input data by specified reader. :param reader: reader class used for reading input data """ if self._loaded: return # data already loaded # create progress bar widget progressMessageBar = iface.messageBar().createMessage( self.tr("Loading data...")) progress = QtWidgets.QProgressBar() progress.setMaximum(100) progressMessageBar.layout().addWidget(progress) iface.messageBar().pushWidget(progressMessageBar, Qgis.Info) # load items as new point features (inform user about progress) i = 0 count = reader.count() start = time.clock() prev = None # previous feature self.startEditing() for item in reader: i += 1 if i == 1 and not self._aliases: # set attributes from data item if needed self._aliases = self._setAttrbsDefs( limit=item.keys(), defs=reader.attributeDefs()) feat = self._item2feat(item) if not feat: # error appeared continue feat.setId(i) self.addFeature(feat) if i % 100 == 0: percent = i / float(count) * 100 progress.setValue(percent) # add features (attributes recalculated if requested) self.commitChanges() if self.storageFormat != "memory": self._writeToOgrDataSource() self.reload() # finish import endtime = time.clock() - start progress.setValue(100) iface.messageBar().clearWidgets() if self._errs: # report errors if any iface.messageBar().pushMessage( self.tr("Info"), self. tr("{} invalid measurement(s) skipped (see message log for details)" ).format(sum(self._errs.values())), level=Qgis.Info, duration=5) for attr in list(self._errs.keys()): QgsMessageLog.logMessage( "{}: {} measurement(s) skipped (invalid {})".format( self._fileName, self._errs[attr], attr), tag=PLUGIN_NAME) # inform user about successful import iface.messageBar().pushMessage( self.tr("Data loaded"), self.tr("{} features loaded (in {:.2f} sec).").format( self.featureCount(), endtime), level=Qgis.Success, duration=3) # data loaded (avoid multiple imports) self._loaded = True # switch to read-only mode self.setReadOnly(True) def _writeToOgrDataSource(self): fileExt = self.storageFormat.lower() filePath = os.path.splitext(self._fileName)[0] + '.{}'.format(fileExt) writer, msg = QgsVectorFileWriter.writeAsVectorFormat( self, filePath, self._provider.encoding(), self._provider.crs(), driverName=self.storageFormat) if writer != QgsVectorFileWriter.NoError: raise LoadError( self.tr("Unable to create SQLite datasource: {}").format(msg)) # set datasource to new OGR datasource self.setDataSource(filePath, self._layerName, 'ogr') self._provider = self.dataProvider() # create metadata layer if self.metadata and 'table' in self.metadata: ds = ogr.Open(filePath, True) layer_name = self.metadata['table'] layer = ds.GetLayerByName(layer_name) if layer is None: layer = ds.CreateLayer(layer_name, None, ogr.wkbNone) layer_defn = layer.GetLayerDefn() if 'columns' in self.metadata: for key in self.metadata['columns']: field = ogr.FieldDefn(key, ogr.OFTString) layer.CreateField(field) feat = ogr.Feature(layer_defn) for key, value in list(self.metadata['columns'].items()): feat.SetField(key, value) layer.CreateFeature(feat) feat = None def _addError(self, etype): """Add error message. :param etype: error type (HDOP, SAT, ...) """ if etype not in self._errs: self._errs[etype] = 0 self._errs[etype] += 1 def _item2feat(self, item): """Create QgsFeature from data item. """ raise NotImplementedError() def _setAttrbsDefs(self, limit=[], defs=None): """Set attributes definition from CSV file if available. :param limit: limit to list of attributes :returns: list of aliases """ def addAttribute(row, attrbs, aliases): attrbs.append( QgsField(row['attribute'], eval("QVariant.{}".format(row['qtype'])))) if 'alias' in row and row['alias']: aliases.append(row['alias'].replace('_', ' ')) def processAttributes(csv_attrbs, limit): attrbs = [] aliases = [] if limit: # limit attributes based on input file (first feature) - ERS/PEI format specific for name in limit: # first try full name match found = False for row in csv_attrbs: if row['attribute'] == name: addAttribute(row, attrbs, aliases) found = True break if found: continue for row in csv_attrbs: # full name match is not required see # https://gitlab.com/opengeolabs/qgis-radiation-toolbox-plugin/issues/41#note_136183930 if row['attribute'] == name[:len( row['attribute'] )] or name == row['attribute'][:len(name)]: row_modified = copy.copy(row) row_modified[ 'attribute'] = name # force (full) attribute name from input file if row_modified['alias']: row_modified['alias'] = '{} ({})'.format( name, row_modified['alias']) addAttribute(row_modified, attrbs, aliases) break else: # add all attributes for row in csv_attrbs: addAttribute(row, attrbs, aliases) return attrbs, aliases if not defs: # predefined attributes (CSV file) # Safecast, ERS csv_file = self._attributesCSVFile() if not os.path.exists(csv_file): return [] with open(csv_file) as fd: csv_attrbs = list(csv.DictReader(fd, delimiter=';')) attrbs, aliases = processAttributes(csv_attrbs, limit) else: # data-driven attributes # PEI attrbs, aliases = processAttributes(defs, limit) if limit and len(attrbs) != len(limit): raise LoadError("Number of attributes differs {} vs {}".format( len(attrbs), len(limit))) if aliases and self.storageFormat != "memory": aliases.insert(0, "FID") # set attributes self._provider.addAttributes(attrbs) self.updateFields() return aliases def setAliases(self): """Set aliases """ for i in range(0, len(self._aliases)): self.setFieldAlias(i, self._aliases[i]) def setStyle(self, idx): """Set layer style. :param int idx: style (combobox) index """ try: style = self._style[idx] except (IndexError, KeyError): return None if 'file' in style: # QML style stylePath = style['file'] if not os.path.isfile(stylePath): raise StyleError( self.tr("Style '{}' not found").format(stylePath)) self.loadNamedStyle(stylePath) elif 'colorramp' in style: if not self._renderer: # symbol (store transparent) symbol = QgsSymbol.defaultSymbol(self.geometryType()) symbol.symbolLayer(0).setStrokeColor(QColor("transparent")) # renderer self._renderer = QgsGraduatedSymbolRenderer() self._renderer.setSourceSymbol(symbol) print(self._renderer.sourceSymbol()) self._renderer.setClassAttribute(style['attribute']) self._renderer.setMode( QgsGraduatedSymbolRenderer.EqualInterval) self._renderer.updateClasses( self, QgsGraduatedSymbolRenderer.EqualInterval, style['classes']) self.setRenderer(self._renderer) self._renderer.updateColorRamp(style['colorramp']) else: raise StyleError(self.tr("Undefined style")) def style(self): """Get style. :return: style class """ return self._style def _attributesCSVFile(self): return os.path.join( os.path.dirname(__file__), os.path.splitext(inspect.getfile(self.__class__))[0] + '.csv')
def _apply_symbology_fixed_divisions(self, layer, field, tbl_name, schema, min_v, max_v, steps): """Finds the amount of levels that is necessary to describe the layer, a maximum of 20 different levels is set. Parameters ---------- layer: QgsVectorLayer field: str tbl_name: str schema: str min_v: float max_v: float steps: int """ str_values = False if min_v is not None and max_v is not None: distinct_values = list(np.arange(min_v, max_v, steps)) elif not str_values: distinct = self.db.get_distinct(tbl_name, field, schema) if len(distinct) == 1: return distinct_values = [] distinct_count = [] for value, count in distinct: if value is None: continue distinct_values.append(value) distinct_count.append(count) if len(distinct_values) > 20: distinct_values.sort() temp_list = [] for val in range(0, len(distinct_values), int(np.floor(len(distinct_values)/20))): temp_list.append(distinct_values[val]) if temp_list[-1] != distinct_values[-1]: temp_list.append(distinct_values[-1]) distinct_values = temp_list if isinstance(distinct_values[0], str): str_values = True colors = self._create_colors(len(distinct_values)) if len(distinct_values) > 19 and not str_values: range_list = [] for i in range(len(distinct_values) - 1): red, green, blue = colors[i] range_list.append(self._make_symbology(layer, distinct_values[i], distinct_values[i + 1], str(distinct_values[i]) + ' - ' + str(distinct_values[i + 1]), QColor(int(red*255),int(green*255), int(blue*255), 128) ) ) renderer = QgsGraduatedSymbolRenderer(field, range_list) renderer.setMode(QgsGraduatedSymbolRenderer.Custom ) else: categories = [] for i in range(len(distinct_values)): symbol = QgsSymbol.defaultSymbol(layer.geometryType()) red, green, blue = colors[i] symbol.setColor(QColor(int(red*255),int(green*255), int(blue*255), 128)) symbol.symbolLayer(0).setStrokeColor(QColor(int(red*255),int(green*255), int(blue*255), 128)) category = QgsRendererCategory(str(distinct_values[i]), symbol, str(distinct_values[i])) categories.append(category) renderer = QgsCategorizedSymbolRenderer(field, categories) #renderer.setMode(QgsCategorizedSymbolRenderer.Custom) layer.setRenderer(renderer)
def test_legend_key_to_expression(self): renderer = QgsGraduatedSymbolRenderer() renderer.setClassAttribute('field_name') exp, ok = renderer.legendKeyToExpression('xxxx', None) self.assertFalse(ok) # no categories exp, ok = renderer.legendKeyToExpression('0', None) self.assertFalse(ok) symbol_a = createMarkerSymbol() renderer.addClassRange(QgsRendererRange(1, 2, symbol_a, 'a')) symbol_b = createMarkerSymbol() renderer.addClassRange(QgsRendererRange(5, 6, symbol_b, 'b')) symbol_c = createMarkerSymbol() renderer.addClassRange(QgsRendererRange(15.5, 16.5, symbol_c, 'c', False)) exp, ok = renderer.legendKeyToExpression('0', None) self.assertTrue(ok) self.assertEqual(exp, "(field_name >= 1) AND (field_name <= 2)") exp, ok = renderer.legendKeyToExpression('1', None) self.assertTrue(ok) self.assertEqual(exp, "(field_name >= 5) AND (field_name <= 6)") exp, ok = renderer.legendKeyToExpression('2', None) self.assertTrue(ok) self.assertEqual(exp, "(field_name >= 15.5) AND (field_name <= 16.5)") exp, ok = renderer.legendKeyToExpression('3', None) self.assertFalse(ok) layer = QgsVectorLayer("Point?field=field_name:double&field=fldint:integer", "addfeat", "memory") # with layer exp, ok = renderer.legendKeyToExpression('2', layer) self.assertTrue(ok) self.assertEqual(exp, """("field_name" >= 15.5) AND ("field_name" <= 16.5)""") # with expression as attribute renderer.setClassAttribute('log("field_name")') exp, ok = renderer.legendKeyToExpression('0', None) self.assertTrue(ok) self.assertEqual(exp, """(log("field_name") >= 1) AND (log("field_name") <= 2)""") exp, ok = renderer.legendKeyToExpression('1', None) self.assertTrue(ok) self.assertEqual(exp, """(log("field_name") >= 5) AND (log("field_name") <= 6)""") exp, ok = renderer.legendKeyToExpression('2', None) self.assertTrue(ok) self.assertEqual(exp, """(log("field_name") >= 15.5) AND (log("field_name") <= 16.5)""") exp, ok = renderer.legendKeyToExpression('2', layer) self.assertTrue(ok) self.assertEqual(exp, """(log("field_name") >= 15.5) AND (log("field_name") <= 16.5)""")
def testUsedAttributes(self): renderer = QgsGraduatedSymbolRenderer() ctx = QgsRenderContext() # attribute can contain either attribute name or an expression. # Sometimes it is not possible to distinguish between those two, # e.g. "a - b" can be both a valid attribute name or expression. # Since we do not have access to fields here, the method should return both options. renderer.setClassAttribute("value") self.assertEqual(renderer.usedAttributes(ctx), {"value"}) renderer.setClassAttribute("value - 1") self.assertEqual(renderer.usedAttributes(ctx), {"value", "value - 1"}) renderer.setClassAttribute("valuea - valueb") self.assertEqual(renderer.usedAttributes(ctx), {"valuea", "valuea - valueb", "valueb"})
def testQgsGraduatedSymbolRenderer_1(self): """Test QgsGraduatedSymbolRenderer: Basic get/set functions """ # Create a renderer renderer = QgsGraduatedSymbolRenderer() symbol = createMarkerSymbol() renderer.setSourceSymbol(symbol.clone()) self.assertEqual(symbol.dump(), renderer.sourceSymbol().dump(), "Get/set renderer source symbol") attr = '"value"*"value"' renderer.setClassAttribute(attr) self.assertEqual(attr, renderer.classAttribute(), "Get/set renderer class attribute") for m in ( QgsGraduatedSymbolRenderer.Custom, QgsGraduatedSymbolRenderer.EqualInterval, QgsGraduatedSymbolRenderer.Quantile, QgsGraduatedSymbolRenderer.Jenks, QgsGraduatedSymbolRenderer.Pretty, QgsGraduatedSymbolRenderer.StdDev, ): renderer.setMode(m) self.assertEqual(m, renderer.mode(), "Get/set renderer mode") format = createLabelFormat() renderer.setLabelFormat(format) self.assertEqual( dumpLabelFormat(format), dumpLabelFormat(renderer.labelFormat()), "Get/set renderer label format") ramp = createColorRamp() renderer.setSourceColorRamp(ramp) self.assertEqual( dumpColorRamp(ramp), dumpColorRamp(renderer.sourceColorRamp()), "Get/set renderer color ramp") renderer.setSourceColorRamp(ramp) self.assertEqual( dumpColorRamp(ramp), dumpColorRamp(renderer.sourceColorRamp()), "Get/set renderer color ramp") # test for classificatio with varying size renderer.setGraduatedMethod(QgsGraduatedSymbolRenderer.GraduatedSize) renderer.setSourceColorRamp(None) renderer.addClassLowerUpper(0, 2) renderer.addClassLowerUpper(2, 4) renderer.addClassLowerUpper(4, 6) renderer.setSymbolSizes(2, 13) self.assertEqual(renderer.maxSymbolSize(), 13) self.assertEqual(renderer.minSymbolSize(), 2) refSizes = [2, (13 + 2) * .5, 13] ctx = QgsRenderContext() for idx, symbol in enumerate(renderer.symbols(ctx)): self.assertEqual(symbol.size(), refSizes[idx])
def testFilterNeedsGeometry(self): renderer = QgsGraduatedSymbolRenderer() renderer.setClassAttribute("value") self.assertFalse(renderer.filterNeedsGeometry()) renderer.setClassAttribute("$area") self.assertTrue(renderer.filterNeedsGeometry()) renderer.setClassAttribute("value - $area") self.assertTrue(renderer.filterNeedsGeometry())
def testQgsGraduatedSymbolRenderer_3(self): """Test QgsGraduatedSymbolRenderer: Reading attribute data, calculating classes """ # Create a renderer renderer = QgsGraduatedSymbolRenderer() symbol = createMarkerSymbol() renderer.setSourceSymbol(symbol.clone()) # Test retrieving data values from a layer ml = createMemoryLayer((1.2, 0.5, 5.0, 1.0, 1.0, 1.2)) renderer.setClassAttribute("value") # Equal interval calculations renderer.updateClasses(ml, renderer.EqualInterval, 3) self.assertEqual( dumpRangeBreaks(renderer.ranges()), '(0.5000-2.0000,2.0000-3.5000,3.5000-5.0000,)', 'Equal interval classification not correct') # Quantile classes renderer.updateClasses(ml, renderer.Quantile, 3) self.assertEqual( dumpRangeBreaks(renderer.ranges()), '(0.5000-1.0000,1.0000-1.2000,1.2000-5.0000,)', 'Quantile classification not correct') renderer.updateClasses(ml, renderer.Quantile, 4) self.assertEqual( dumpRangeBreaks(renderer.ranges()), '(0.5000-1.0000,1.0000-1.1000,1.1000-1.2000,1.2000-5.0000,)', 'Quantile classification not correct')
def processAlgorithm(self, parameters, context, feedback): project = QgsProject() project.setFileName( os.path.join(parameters[self.FOLDER], "all-outputs-qgis.qgs")) project.setCrs(QgsCoordinateReferenceSystem('EPSG:27700')) def getMaxValue(layer, fieldname): maxfound = float("-inf") for f in layer.getFeatures(): attr = f.attribute(fieldname) assert attr >= 0 if attr > maxfound: maxfound = attr return maxfound with open( os.path.join(parameters[self.FOLDER], "all-town-metadata.json")) as f: metadata = json.load(f) classmethods = { 'quantile': QgsClassificationQuantile, 'jenks': QgsClassificationJenks, 'equal': QgsClassificationEqualInterval } html = "" output = [] views_sorted_by_mode = sorted(metadata["views"], key=lambda v: v["mode"]) for view in views_sorted_by_mode: keysymbol = u'🔑' viewname = view["label"] keysign = "" if viewname.find(keysymbol) != -1: viewname = viewname.replace(keysymbol, '', 1) keysign = "*** " viewname = keysign + view["mode"] + " " + viewname html += f""" <h2>{viewname}</h2> {view["description"]} <ul> """ for layer in view["layers"]: layername = viewname + " - " + layer["scalar_field_units"] layerpath = os.path.join(parameters[self.FOLDER], layer["file"]) vlayer = QgsVectorLayer(layerpath, layername, "ogr") if not vlayer.isValid(): feedback.pushInfo("Layer failed to load: " + layerpath) else: context.temporaryLayerStore().addMapLayer(vlayer) html += f"""<li><b>file:</b> {layer["file"]}""" if "symbol_field" in layer: html += f"""<ul> <li><b>symbol field:</b> {layer["symbol_field"]} </ul> """ categories = [] scalar_fieldname = layer["scalar_field"] maxvalue = getMaxValue(vlayer, scalar_fieldname) feedback.pushInfo("Max value for %s is %f" % (scalar_fieldname, maxvalue)) for formality in ["I", "F"]: for severity, colour in [(3, 'red'), (2, 'yellow'), (1, 'green')]: colour = { ("I", "red"): "#FF0000", ("I", "yellow"): "#FFFF00", ("I", "green"): "#00FF00", ("F", "red"): "#FF9999", ("F", "yellow"): "#FFFF66", ("F", "green"): "#99FF99", }[(formality, colour)] symbol_code = "%s%d" % (formality, severity) if formality == "F": symbol = QgsMarkerSymbol.createSimple({ 'color': colour, 'size': '3', 'outline_color': '#888888' }) else: assert (formality == "I") symbol = QgsMarkerSymbol.createSimple({ 'color': colour, 'size': '3', 'outline_color': '#000000', 'name': 'star' }) objTransf = QgsSizeScaleTransformer( QgsSizeScaleTransformer.Flannery, 0, #minvalue maxvalue, #maxvalue 3, #minsize 10, #maxsize 0, #nullsize 1) #exponent objProp = QgsProperty() objProp.setField(scalar_fieldname) objProp.setTransformer(objTransf) symbol.setDataDefinedSize(objProp) label = { "F": "Formal", "I": "Informal" }[formality] + " " + { 3: "Major", 2: "Secondary", 1: "Tertiary" }[severity] cat = QgsRendererCategory( symbol_code, symbol, label, True) categories.append(cat) renderer = QgsCategorizedSymbolRenderer( "Crossings", categories) renderer.setClassAttribute(layer["symbol_field"]) vlayer.setRenderer(renderer) else: html += f"""<ul> <li><b>field:</b> {layer["scalar_field"]} <li><b>units:</b> {layer["scalar_field_units"]} <li><b>recommended classification:</b> {layer["classes"]} </ul> """ default_style = QgsStyle().defaultStyle() color_ramp = default_style.colorRamp('bt') renderer = QgsGraduatedSymbolRenderer() renderer.setClassAttribute(layer["scalar_field"]) classmethod = classmethods[layer["classes"]]() renderer.setClassificationMethod(classmethod) renderer.updateClasses(vlayer, 5) renderer.updateColorRamp(color_ramp) vlayer.setRenderer(renderer) project.addMapLayer(vlayer) feedback.pushInfo("Loaded " + layerpath) html += "</ul>" project.write() town = views_sorted_by_mode[0]["town"] with open(os.path.join(parameters[self.FOLDER], "metadata.html"), "w") as htmlfile: htmlfile.write( f"<html><head><title>{town} metadata</title></head><body><h1>{town}</h1>{html}</body></html>" ) return {self.OUTPUT: output}