Skip to content
Permalink
Browse files

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
  • Loading branch information
nyalldawson committed Jul 15, 2017
1 parent 82edbab commit ea06500cafb9a4e8735f9ac64b028faacaf6474e
@@ -89,12 +89,12 @@
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 @@ def __init__(self):

def getAlgs(self):
# algs = [
# UniqueValues(),
#
# ExportGeometryInfo(),
# SinglePartsToMultiparts(),
# ExtractNodes(),
@@ -283,6 +283,7 @@ def getAlgs(self):
SumLines(),
SymmetricalDifference(),
Union(),
UniqueValues(),
VectorSplit(),
VoronoiPolygons(),
ZonalStatistics()
@@ -31,25 +31,32 @@

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 @@ def __init__(self):
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 @@ def displayName(self):
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:
@@ -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>
@@ -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>
@@ -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:

0 comments on commit ea06500

Please sign in to comment.
You can’t perform that action at this time.