Port Unique Values algorithm to new API

Improvements:
- by default output a table with unique values, instead of a HTML
file. This allows the values to be more easily used in follow up
analysis (e.g. in a model). HTML output is still available, but
not output by default
This commit is contained in:
Nyall Dawson 2017-07-15 22:07:12 +10:00
parent 82edbab814
commit ea06500caf
5 changed files with 111 additions and 25 deletions

View File

@ -89,12 +89,12 @@ from .SpatialiteExecuteSQL import SpatialiteExecuteSQL
from .SumLines import SumLines
from .SymmetricalDifference import SymmetricalDifference
from .Union import Union
from .UniqueValues import UniqueValues
from .VectorSplit import VectorSplit
from .VoronoiPolygons import VoronoiPolygons
from .ZonalStatistics import ZonalStatistics
# from .ExtractByLocation import ExtractByLocation
# from .UniqueValues import UniqueValues
# from .ExportGeometryInfo import ExportGeometryInfo
# from .SinglePartsToMultiparts import SinglePartsToMultiparts
# from .ExtractNodes import ExtractNodes
@ -184,7 +184,7 @@ class QGISAlgorithmProvider(QgsProcessingProvider):
def getAlgs(self):
# algs = [
# UniqueValues(),
#
# ExportGeometryInfo(),
# SinglePartsToMultiparts(),
# ExtractNodes(),
@ -283,6 +283,7 @@ class QGISAlgorithmProvider(QgsProcessingProvider):
SumLines(),
SymmetricalDifference(),
Union(),
UniqueValues(),
VectorSplit(),
VoronoiPolygons(),
ZonalStatistics()

View File

@ -31,25 +31,32 @@ import codecs
from qgis.PyQt.QtGui import QIcon
from qgis.core import QgsProcessingUtils, QgsFeatureSink
from qgis.core import (QgsCoordinateReferenceSystem,
QgsWkbTypes,
QgsFeature,
QgsFeatureSink,
QgsFields,
QgsProcessingParameterField,
QgsProcessingParameterFeatureSource,
QgsProcessingParameterFeatureSink,
QgsProcessingOutputNumber,
QgsProcessingOutputString,
QgsProcessingParameterFileDestination,
QgsProcessingOutputHtml)
from processing.algs.qgis.QgisAlgorithm import QgisAlgorithm
from processing.core.parameters import ParameterVector
from processing.core.parameters import ParameterTableField
from processing.core.outputs import OutputHTML
from processing.core.outputs import OutputNumber
from processing.core.outputs import OutputString
pluginPath = os.path.split(os.path.split(os.path.dirname(__file__))[0])[0]
class UniqueValues(QgisAlgorithm):
INPUT_LAYER = 'INPUT_LAYER'
INPUT = 'INPUT'
FIELD_NAME = 'FIELD_NAME'
TOTAL_VALUES = 'TOTAL_VALUES'
UNIQUE_VALUES = 'UNIQUE_VALUES'
OUTPUT = 'OUTPUT'
OUTPUT_HTML_FILE = 'OUTPUT_HTML_FILE'
def icon(self):
return QIcon(os.path.join(pluginPath, 'images', 'ftools', 'unique.png'))
@ -61,14 +68,18 @@ class UniqueValues(QgisAlgorithm):
super().__init__()
def initAlgorithm(self, config=None):
self.addParameter(ParameterVector(self.INPUT_LAYER,
self.tr('Input layer')))
self.addParameter(ParameterTableField(self.FIELD_NAME,
self.tr('Target field'),
self.INPUT_LAYER, ParameterTableField.DATA_TYPE_ANY))
self.addOutput(OutputHTML(self.OUTPUT, self.tr('Unique values')))
self.addOutput(OutputNumber(self.TOTAL_VALUES, self.tr('Total unique values')))
self.addOutput(OutputString(self.UNIQUE_VALUES, self.tr('Unique values')))
self.addParameter(QgsProcessingParameterFeatureSource(self.INPUT,
self.tr('Input layer')))
self.addParameter(QgsProcessingParameterField(self.FIELD_NAME,
self.tr('Target field'),
parentLayerParameterName=self.INPUT, type=QgsProcessingParameterField.Any))
self.addParameter(QgsProcessingParameterFeatureSink(self.OUTPUT, self.tr('Unique values'), optional=True, defaultValue=''))
self.addParameter(QgsProcessingParameterFileDestination(self.OUTPUT_HTML_FILE, self.tr('HTML report'), self.tr('HTML files (*.html)'), None, True))
self.addOutput(QgsProcessingOutputHtml(self.OUTPUT_HTML_FILE, self.tr('HTML report')))
self.addOutput(QgsProcessingOutputNumber(self.TOTAL_VALUES, self.tr('Total unique values')))
self.addOutput(QgsProcessingOutputString(self.UNIQUE_VALUES, self.tr('Unique values')))
def name(self):
return 'listuniquevalues'
@ -77,14 +88,36 @@ class UniqueValues(QgisAlgorithm):
return self.tr('List unique values')
def processAlgorithm(self, parameters, context, feedback):
layer = QgsProcessingUtils.mapLayerFromString(self.getParameterValue(self.INPUT_LAYER), context)
fieldName = self.getParameterValue(self.FIELD_NAME)
outputFile = self.getOutputValue(self.OUTPUT)
values = QgsProcessingUtils.uniqueValues(layer, layer.fields().lookupField(fieldName), context)
self.createHTML(outputFile, values)
self.setOutputValue(self.TOTAL_VALUES, len(values))
self.setOutputValue(self.UNIQUE_VALUES, ';'.join([str(v) for v in
values]))
source = self.parameterAsSource(parameters, self.INPUT, context)
field_name = self.parameterAsString(parameters, self.FIELD_NAME, context)
values = source.uniqueValues(source.fields().lookupField(field_name))
fields = QgsFields()
field = source.fields()[source.fields().lookupField(field_name)]
field.setName('VALUES')
fields.append(field)
(sink, dest_id) = self.parameterAsSink(parameters, self.OUTPUT, context,
fields, QgsWkbTypes.NoGeometry, QgsCoordinateReferenceSystem())
results = {}
if sink:
for value in values:
if feedback.isCanceled():
break
f = QgsFeature()
f.setAttributes([value])
sink.addFeature(f, QgsFeatureSink.FastInsert)
results[self.OUTPUT] = dest_id
output_file = self.parameterAsFileOutput(parameters, self.OUTPUT_HTML_FILE, context)
if output_file:
self.createHTML(output_file, values)
results[self.OUTPUT_HTML_FILE] = output_file
results[self.TOTAL_VALUES] = len(values)
results[self.UNIQUE_VALUES] = ';'.join([str(v) for v in
values])
return results
def createHTML(self, outputFile, algData):
with codecs.open(outputFile, 'w', encoding='utf-8') as f:

View File

@ -0,0 +1,15 @@
<GMLFeatureClassList>
<GMLFeatureClass>
<Name>unique_values</Name>
<ElementPath>unique_values</ElementPath>
<GeometryType>100</GeometryType>
<DatasetSpecificInfo>
<FeatureCount>3</FeatureCount>
</DatasetSpecificInfo>
<PropertyDefn>
<Name>VALUES</Name>
<ElementPath>VALUES</ElementPath>
<Type>Integer</Type>
</PropertyDefn>
</GMLFeatureClass>
</GMLFeatureClassList>

View File

@ -0,0 +1,24 @@
<?xml version="1.0" encoding="utf-8" ?>
<ogr:FeatureCollection
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation=""
xmlns:ogr="http://ogr.maptools.org/"
xmlns:gml="http://www.opengis.net/gml">
<gml:boundedBy><gml:null>missing</gml:null></gml:boundedBy>
<gml:featureMember>
<ogr:unique_values fid="unique_values.0">
<ogr:VALUES>0</ogr:VALUES>
</ogr:unique_values>
</gml:featureMember>
<gml:featureMember>
<ogr:unique_values fid="unique_values.1">
<ogr:VALUES>1</ogr:VALUES>
</ogr:unique_values>
</gml:featureMember>
<gml:featureMember>
<ogr:unique_values fid="unique_values.2">
<ogr:VALUES>2</ogr:VALUES>
</ogr:unique_values>
</gml:featureMember>
</ogr:FeatureCollection>

View File

@ -241,6 +241,19 @@ tests:
# geometry:
# precision: 7
#
- algorithm: qgis:listuniquevalues
name: Unique values
params:
INPUT:
name: points.gml
type: vector
FIELD_NAME: id2
results:
OUTPUT:
name: expected/unique_values.gml
type: vector
- algorithm: qgis:addautoincrementalfield
name: Add autoincremental field
params: