QGIS/python/plugins/sextante/algs/ftools/NearestNeighbourAnalysis.py

118 lines
4.7 KiB
Python

# -*- coding: utf-8 -*-
"""
***************************************************************************
NearestNeighbourAnalysis.py
---------------------
Date : August 2012
Copyright : (C) 2012 by Victor Olaya
Email : volayaf at gmail dot com
***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************
"""
__author__ = 'Victor Olaya'
__date__ = 'August 2012'
__copyright__ = '(C) 2012, Victor Olaya'
# This will get replaced with a git SHA1 when you do a git archive
__revision__ = '$Format:%H$'
import math
from qgis.core import *
from sextante.core.GeoAlgorithm import GeoAlgorithm
from sextante.core.QGisLayers import QGisLayers
from sextante.parameters.ParameterVector import ParameterVector
from sextante.outputs.OutputHTML import OutputHTML
from sextante.outputs.OutputNumber import OutputNumber
from sextante.algs.ftools import FToolsUtils as utils
class NearestNeighbourAnalysis(GeoAlgorithm):
POINTS = "POINTS"
OUTPUT = "OUTPUT"
OBSERVED_MD = "OBSERVED_MD"
EXPECTED_MD = "EXPECTED_MD"
NN_INDEX = "NN_INDEX"
POINT_COUNT = "POINT_COUNT"
Z_SCORE = "Z_SCORE"
#===========================================================================
# def getIcon(self):
# return QtGui.QIcon(os.path.dirname(__file__) + "/icons/neighbour.png")
#===========================================================================
def defineCharacteristics(self):
self.name = "Nearest neighbour analysis"
self.group = "Vector analysis tools"
self.addParameter(ParameterVector(self.POINTS, "Points", ParameterVector.VECTOR_TYPE_POINT))
self.addOutput(OutputHTML(self.OUTPUT, "Result"))
self.addOutput(OutputNumber(self.OBSERVED_MD, "Observed mean distance"))
self.addOutput(OutputNumber(self.EXPECTED_MD, "Expected mean distance"))
self.addOutput(OutputNumber(self.NN_INDEX, "Nearest neighbour index"))
self.addOutput(OutputNumber(self.POINT_COUNT, "Number of points"))
self.addOutput(OutputNumber(self.Z_SCORE, "Z-Score"))
def processAlgorithm(self, progress):
layer = QGisLayers.getObjectFromUri(self.getParameterValue(self.POINTS))
output = self.getOutputValue(self.OUTPUT)
spatialIndex = utils.createSpatialIndex(layer)
neighbour = QgsFeature()
distance = QgsDistanceArea()
sumDist = 0.00
A = layer.extent()
A = float(A.width() * A.height())
current = 0
features = QGisLayers.features(layer)
count = len(features)
total = 100.0 / float(len(features))
for feat in features:
neighbourID = spatialIndex.nearestNeighbor(feat.geometry().asPoint(), 2)[1]
request = QgsFeatureRequest().setFilterFid(neighbourID)
neighbour = layer.getFeatures(request).next()
sumDist += distance.measureLine(neighbour.geometry().asPoint(), feat.geometry().asPoint())
current += 1
progress.setPercentage(int(current * total))
do = float(sumDist) / count
de = float(0.5 / math.sqrt(count / A))
d = float(do / de)
SE = float(0.26136 / math.sqrt(( count ** 2) / A))
zscore = float((do - de) / SE)
data = []
data.append("Observed mean distance: " + unicode(do))
data.append("Expected mean distance: " + unicode(de))
data.append("Nearest neighbour index: " + unicode(d))
data.append("Number of points: " + unicode(count))
data.append("Z-Score: " + unicode(zscore))
self.createHTML(output, data)
self.setOutputValue(self.OBSERVED_MD, float( data[ 0 ].split( ": " )[ 1 ] ) )
self.setOutputValue(self.EXPECTED_MD, float( data[ 1 ].split( ": " )[ 1 ] ) )
self.setOutputValue(self.NN_INDEX, float( data[ 2 ].split( ": " )[ 1 ] ) )
self.setOutputValue(self.POINT_COUNT, float( data[ 3 ].split( ": " )[ 1 ] ) )
self.setOutputValue(self.Z_SCORE, float( data[ 4 ].split( ": " )[ 1 ] ) )
def createHTML(self, outputFile, algData):
f = open(outputFile, "w")
for s in algData:
f.write("<p>" + str(s) + "</p>")
f.close()