Skip to content

Commit 1a67b91

Browse files
committed
refactor basic statistics tool
1 parent ad0ff93 commit 1a67b91

5 files changed

Lines changed: 375 additions & 195 deletions

File tree

‎python/plugins/sextante/ftools/BasicStatistics.py‎

Lines changed: 0 additions & 190 deletions
This file was deleted.
Lines changed: 186 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,186 @@
1+
import os.path
2+
import math
3+
4+
from PyQt4 import QtGui
5+
from PyQt4.QtCore import *
6+
7+
from qgis.core import *
8+
9+
from sextante.core.GeoAlgorithm import GeoAlgorithm
10+
from sextante.core.QGisLayers import QGisLayers
11+
12+
from sextante.parameters.ParameterVector import ParameterVector
13+
from sextante.parameters.ParameterTableField import ParameterTableField
14+
from sextante.parameters.ParameterBoolean import ParameterBoolean
15+
16+
from sextante.outputs.OutputHTML import OutputHTML
17+
from sextante.outputs.OutputNumber import OutputNumber
18+
19+
from sextante.ftools import FToolsUtils as utils
20+
21+
class BasicStatisticsNumbers(GeoAlgorithm):
22+
23+
INPUT_LAYER = "INPUT_LAYER"
24+
FIELD_NAME = "FIELD_NAME"
25+
USE_SELECTION = "USE_SELECTION"
26+
OUTPUT_HTML_FILE = "OUTPUT_HTML_FILE"
27+
28+
CV = "CV"
29+
MIN = "MIN"
30+
MAX = "MAX"
31+
SUM = "SUM"
32+
MEAN = "MEAN"
33+
COUNT = "COUNT"
34+
RANGE = "RANGE"
35+
MEDIAN = "MEDIAN"
36+
UNIQUE = "UNIQUE"
37+
STD_DEV = "STD_DEV"
38+
39+
def getIcon(self):
40+
return QtGui.QIcon(os.path.dirname(__file__) + "/icons/basic_statistics.png")
41+
42+
def defineCharacteristics(self):
43+
self.name = "Basic statistics for numeric fields"
44+
self.group = "Analysis tools"
45+
46+
self.addParameter(ParameterVector(self.INPUT_LAYER, "Input vector layer", ParameterVector.VECTOR_TYPE_ANY, False))
47+
self.addParameter(ParameterTableField(self.FIELD_NAME, "Field to calculate statistics on", self.INPUT_LAYER, ParameterTableField.DATA_TYPE_NUMBER))
48+
self.addParameter(ParameterBoolean(self.USE_SELECTION, "Use selection", False))
49+
50+
self.addOutput(OutputHTML(self.OUTPUT_HTML_FILE, "Statistics for numeric field"))
51+
52+
self.addOutput(OutputNumber(self.CV, "Coefficient of Variation"))
53+
self.addOutput(OutputNumber(self.MIN, "Minimum value"))
54+
self.addOutput(OutputNumber(self.MAX, "Maximum value"))
55+
self.addOutput(OutputNumber(self.SUM, "Sum"))
56+
self.addOutput(OutputNumber(self.MEAN, "Mean value"))
57+
self.addOutput(OutputNumber(self.COUNT, "Count"))
58+
self.addOutput(OutputNumber(self.RANGE, "Range"))
59+
self.addOutput(OutputNumber(self.MEDIAN, "Median"))
60+
self.addOutput(OutputNumber(self.UNIQUE, "Number of unique values"))
61+
self.addOutput(OutputNumber(self.STD_DEV, "Standard deviation"))
62+
63+
def processAlgorithm(self, progress):
64+
layer = QGisLayers.getObjectFromUri(self.getParameterValue(self.INPUT_LAYER))
65+
fieldName = self.getParameterValue(self.FIELD_NAME)
66+
useSelection = self.getParameterValue(self.USE_SELECTION)
67+
68+
outputFile = self.getOutputValue(self.OUTPUT_HTML_FILE)
69+
70+
index = layer.fieldNameIndex(fieldName)
71+
layer.select([index], QgsRectangle(), False)
72+
73+
count = 0
74+
rValue = 0
75+
cvValue = 0
76+
minValue = 0
77+
maxValue = 0
78+
sumValue = 0
79+
meanValue = 0
80+
medianValue = 0
81+
stdDevValue = 0
82+
uniqueValue = 0
83+
84+
isFirst = True
85+
values = []
86+
87+
if useSelection:
88+
selection = layer.selectedFeatures()
89+
count = layer.selectedFeatureCount()
90+
total = 100.0 / float(count)
91+
current = 0
92+
93+
for f in selection:
94+
value = float(f.attributeMap()[index].toDouble()[0])
95+
96+
if isFirst:
97+
minValue = value
98+
maxValue = value
99+
isFirst = False
100+
else:
101+
if value < minValue:
102+
minValue = value
103+
if value > maxValue:
104+
maxValue = value
105+
106+
values.append(value)
107+
sumValue += value
108+
109+
current += 1
110+
progress.setPercentage(int(current * total))
111+
else:
112+
count = layer.featureCount()
113+
total = 100.0 / float(count)
114+
current = 0
115+
116+
ft = QgsFeature()
117+
while layer.nextFeature(ft):
118+
value = float(ft.attributeMap()[index].toDouble()[0])
119+
120+
if isFirst:
121+
minValue = value
122+
maxValue = value
123+
isFirst = False
124+
else:
125+
if value < minValue:
126+
minValue = value
127+
if value > maxValue:
128+
maxValue = value
129+
130+
values.append( value )
131+
sumValue += value
132+
133+
current += 1
134+
progress.setPercentage(int(current * total))
135+
136+
# calculate additional values
137+
rValue = maxValue - minValue
138+
uniqueValue = utils.getUniqueValuesCount(layer, index, useSelection)
139+
140+
if count > 0:
141+
meanValue = sumValue / count
142+
if meanValue != 0.00:
143+
for v in values:
144+
stdDevValue += ((v - meanValue) * (v - meanValue))
145+
stdDevValue = math.sqrt(stdDevValue / count)
146+
cvValue = stdDevValue / meanValue
147+
148+
if count > 1:
149+
tmp = values
150+
tmp.sort()
151+
# calculate median
152+
if (count % 2) == 0:
153+
medianValue = 0.5 * (tmp[(count - 1) / 2] + tmp[count / 2])
154+
else:
155+
medianValue = tmp[(count + 1) / 2 - 1]
156+
157+
data = []
158+
data.append("Count: " + unicode(count))
159+
data.append("Unique values: " + unicode(uniqueValue))
160+
data.append("Minimum value: " + unicode(minValue))
161+
data.append("Maximum value: " + unicode(maxValue))
162+
data.append("Range: " + unicode(rValue))
163+
data.append("Sum: " + unicode(sumValue))
164+
data.append("Mean value: " + unicode(meanValue))
165+
data.append("Median value: " + unicode(medianValue))
166+
data.append("Standard deviation: " + unicode(stdDevValue))
167+
data.append("Coefficient of Variation: " + unicode(cvValue))
168+
169+
self.createHTML(outputFile, data)
170+
171+
self.setOutputValue(self.COUNT, count)
172+
self.setOutputValue(self.UNIQUE, uniqueValue)
173+
self.setOutputValue(self.MIN, minValue)
174+
self.setOutputValue(self.MAX, maxValue)
175+
self.setOutputValue(self.RANGE, rValue)
176+
self.setOutputValue(self.SUM, sumValue)
177+
self.setOutputValue(self.MEAN, meanValue)
178+
self.setOutputValue(self.MEDIAN, medianValue)
179+
self.setOutputValue(self.STD_DEV, stdDevValue)
180+
self.setOutputValue(self.CV, cvValue)
181+
182+
def createHTML(self, outputFile, algData):
183+
f = open(outputFile, "w")
184+
for s in algData:
185+
f.write("<p>" + str(s) + "</p>")
186+
f.close()

0 commit comments

Comments
 (0)