QGIS/python/plugins/sextante/ftools/BasicStatistics.py
2012-09-15 18:30:32 +03:00

191 lines
7.8 KiB
Python

from sextante.core.GeoAlgorithm import GeoAlgorithm
import os.path
from PyQt4 import QtGui
from PyQt4.QtCore import *
from PyQt4.QtGui import *
from qgis.core import *
from sextante.parameters.ParameterVector import ParameterVector
from sextante.core.QGisLayers import QGisLayers
from sextante.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException
from sextante.ftools import ftools_utils
import math
from sextante.outputs.OutputHTML import OutputHTML
from sextante.parameters.ParameterTableField import ParameterTableField
from sextante.parameters.ParameterBoolean import ParameterBoolean
class BasicStatistics(GeoAlgorithm):
INPUT = "INPUT"
OUTPUT = "OUTPUT"
FIELD = "FIELD"
USE_SELECTION = "USE_SELECTION"
def getIcon(self):
return QtGui.QIcon(os.path.dirname(__file__) + "/icons/basic_statistics.png")
def createHTML(self, outputFile, lstStats):
f = open(outputFile, "w")
for s in lstStats:
f.write("<p>" + str(s) + "</p>")
f.close()
def processAlgorithm(self, progress):
outputFile = self.getOutputValue(BasicStatistics.OUTPUT)
vlayer = QGisLayers.getObjectFromUri(self.getParameterValue(BasicStatistics.INPUT))
attfield = self.getParameterValue(BasicStatistics.FIELD)
useSelection = self.getParameterValue(BasicStatistics.USE_SELECTION)
vprovider = vlayer.dataProvider()
allAttrs = vprovider.attributeIndexes()
vprovider.select( allAttrs )
index = vprovider.fieldNameIndex(attfield)
feat = QgsFeature()
sumVal = 0.0
meanVal = 0.0
nVal = 0.0
values = []
first = True
nElement = 0
# determine selected field type
if ftools_utils.getFieldType( vlayer, attfield ) in ('String', 'varchar', 'char', 'text'):
fillVal = 0
emptyVal = 0
if useSelection: # only selected features
selection = vlayer.selectedFeatures()
nFeat = vlayer.selectedFeatureCount()
for f in selection:
atMap = f.attributeMap()
lenVal = float( len( atMap[ index ].toString() ) )
if first:
minVal = lenVal
maxVal = lenVal
first = False
else:
if lenVal < minVal: minVal = lenVal
if lenVal > maxVal: maxVal = lenVal
if lenVal != 0.00:
fillVal += 1
else:
emptyVal += 1
values.append( lenVal )
sumVal = sumVal + lenVal
nElement += 1
progress.setPercentage(int(nElement/nFeat * 100))
else: # there is no selection, process the whole layer
nFeat = vprovider.featureCount()
if nFeat > 0:
vprovider.select( allAttrs )
while vprovider.nextFeature( feat ):
atMap = feat.attributeMap()
lenVal = float( len( atMap[ index ].toString() ) )
if first:
minVal = lenVal
maxVal = lenVal
first = False
else:
if lenVal < minVal: minVal = lenVal
if lenVal > maxVal: maxVal = lenVal
if lenVal != 0.00:
fillVal += 1
else:
emptyVal += 1
values.append( lenVal )
sumVal = sumVal + lenVal
nElement += 1
progress.setPercentage(int(nElement/nFeat * 100))
nVal= float( len( values ) )
if nVal > 0:
meanVal = sumVal / nVal
lstStats = []
lstStats.append( "Max. len:" + unicode( maxVal ) )
lstStats.append( "Min. len:" + unicode( minVal ) )
lstStats.append( "Mean. len:" + unicode( meanVal ) )
lstStats.append( "Filled:" + unicode( fillVal ) )
lstStats.append( "Empty:" + unicode( emptyVal ) )
lstStats.append( "N:" + unicode( nVal ) )
self.createHTML(outputFile, lstStats)
else:
raise GeoAlgorithmExecutionException("Error:No features selected!")
else: # numeric field
stdVal = 0.00
cvVal = 0.00
rangeVal = 0.00
medianVal = 0.00
maxVal = 0.00
minVal = 0.00
if useSelection: # only selected features
selection = vlayer.selectedFeatures()
nFeat = vlayer.selectedFeatureCount()
uniqueVal = ftools_utils.getUniqueValuesCount( vlayer, index, True )
for f in selection:
atMap = f.attributeMap()
value = float( atMap[ index ].toDouble()[ 0 ] )
if first:
minVal = value
maxVal = value
first = False
else:
if value < minVal: minVal = value
if value > maxVal: maxVal = value
values.append( value )
sumVal = sumVal + value
nElement += 1
progress.setPercentage(int(nElement/nFeat * 100))
else: # there is no selection, process the whole layer
nFeat = vprovider.featureCount()
uniqueVal = ftools_utils.getUniqueValuesCount( vlayer, index, False )
if nFeat > 0:
vprovider.select( allAttrs )
while vprovider.nextFeature( feat ):
atMap = feat.attributeMap()
value = float( atMap[ index ].toDouble()[ 0 ] )
if first:
minVal = value
maxVal = value
first = False
else:
if value < minVal: minVal = value
if value > maxVal: maxVal = value
values.append( value )
sumVal = sumVal + value
nElement += 1
nVal= float( len( values ) )
if nVal > 0.00:
rangeVal = maxVal - minVal
meanVal = sumVal / nVal
if meanVal != 0.00:
for val in values:
stdVal += ( ( val - meanVal ) * ( val - meanVal ) )
stdVal = math.sqrt( stdVal / nVal )
cvVal = stdVal / meanVal
if nVal > 1:
lstVal = values
lstVal.sort()
if ( nVal % 2 ) == 0:
medianVal = 0.5 * ( lstVal[ int( ( nVal - 1 ) / 2 ) ] + lstVal[ int( ( nVal ) / 2 ) ] )
else:
medianVal = lstVal[ int( ( nVal + 1 ) / 2 - 1 ) ]
lstStats = []
lstStats.append( "Mean:" + unicode( meanVal ) )
lstStats.append( "StdDev:" + unicode( stdVal ) )
lstStats.append( "Sum:" + unicode( sumVal) )
lstStats.append( "Min:" + unicode( minVal ) )
lstStats.append( "Max:" + unicode( maxVal ) )
lstStats.append( "N:" + unicode( nVal ) )
lstStats.append( "CV:" + unicode( cvVal ) )
lstStats.append( "Number of unique values:" + unicode( uniqueVal ) )
lstStats.append( "Range:" + unicode( rangeVal ) )
lstStats.append( "Median:" + unicode( medianVal ) )
self.createHTML(outputFile, lstStats)
else:
raise GeoAlgorithmExecutionException("Error:No features selected!")
def defineCharacteristics(self):
self.name = "Basic statistics"
self.group = "Analysis tools"
self.addParameter(ParameterVector(BasicStatistics.INPUT, "Input layer", ParameterVector.VECTOR_TYPE_ANY))
self.addParameter(ParameterTableField(BasicStatistics.FIELD, "Field", BasicStatistics.INPUT))
self.addParameter(ParameterBoolean(BasicStatistics.USE_SELECTION, "Use selection", False))
self.addOutput(OutputHTML(BasicStatistics.OUTPUT, "Statistics"))