1
# -*- coding: utf-8 -*-
1
2
#-----------------------------------------------------------
3
# Random Selection Within Subsets
5
# A QGIS plugin for randomly selecting features from
6
# within multiple user defined subsets based on an input field.
8
# Copyright (C) 2008 Carson Farmer
5
# Copyright (C) 2008-2011 Carson Farmer
10
6
# EMAIL: carson.farmer (at) gmail.com
11
# WEB : www.geog.uvic.ca/spar/carson
7
# WEB : http://www.ftools.ca/fTools.html
9
# A collection of data management and analysis tools for vector data
13
11
#-----------------------------------------------------------
15
13
# licensed under the terms of GNU GPL 2
17
15
# This program is free software; you can redistribute it and/or modify
18
16
# it under the terms of the GNU General Public License as published by
19
17
# the Free Software Foundation; either version 2 of the License, or
20
18
# (at your option) any later version.
22
20
# This program is distributed in the hope that it will be useful,
23
21
# but WITHOUT ANY WARRANTY; without even the implied warranty of
24
22
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25
23
# GNU General Public License for more details.
27
25
# You should have received a copy of the GNU General Public License along
28
26
# with this program; if not, write to the Free Software Foundation, Inc.,
29
27
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
31
#--------------------------------------------------------------------
29
#---------------------------------------------------------------------
32
31
from PyQt4.QtCore import *
33
32
from PyQt4.QtGui import *
33
import random, ftools_utils
35
34
from qgis.core import *
36
35
from ui_frmSubsetSelect import Ui_Dialog
38
37
class Dialog(QDialog, Ui_Dialog):
40
def __init__(self, iface):
41
QDialog.__init__(self)
43
# Set up the user interface from Designer.
45
QObject.connect(self.inShape, SIGNAL("currentIndexChanged(QString)"), self.update)
46
self.setWindowTitle("Random selection within subsets")
48
self.progressBar.setValue(0)
49
mapCanvas = self.iface.mapCanvas()
50
for i in range(mapCanvas.layerCount()):
51
layer = mapCanvas.layer(i)
52
if layer.type() == layer.VectorLayer:
53
self.inShape.addItem(layer.name())
55
def update(self, inputLayer):
57
changedLayer = self.getVectorLayerByName(inputLayer)
58
changedField = self.getFieldList(changedLayer)
59
for i in changedField:
60
self.inField.addItem(unicode(changedField[i].name()))
63
if self.inShape.currentText() == "":
64
QMessageBox.information(self, "Random Selection Within Subsets", "Please specify input vector layer")
65
elif self.inField.currentText() == "":
66
QMessageBox.information(self, "Random Selection Within Subsets", "Please specify an input field")
68
inVect = self.inShape.currentText()
69
uidField = self.inField.currentText()
70
if self.rdoNumber.isChecked():
71
value = self.spnNumber.value()
74
value = self.spnPercent.value()
76
self.compute(inVect, uidField, value, perc, self.progressBar)
77
self.progressBar.setValue(100)
78
self.progressBar.setValue(0)
82
fileDialog = QFileDialog()
83
fileDialog.setConfirmOverwrite(False)
84
outName = fileDialog.getSaveFileName(self, "Output Shapefile",".", "Shapefiles (*.shp)")
85
fileCheck = QFile(outName)
86
if fileCheck.exists():
87
QMessageBox.warning(self, "Random Selection Within Subsets", "Cannot overwrite existing shapefile...")
89
filePath = QFileInfo(outName).absoluteFilePath()
90
if filePath.right(4) != ".shp": filePath = filePath + ".shp"
91
if not outName.isEmpty():
93
self.outShape.insert(filePath)
95
def compute(self, inVect, inField, value, perc, progressBar):
96
vlayer = self.getVectorLayerByName(inVect)
97
vprovider = vlayer.dataProvider()
98
mlayer = self.getMapLayerByName(inVect)
99
allAttrs = vprovider.attributeIndexes()
100
vprovider.select(allAttrs)
101
index = vprovider.fieldNameIndex(inField)
103
#vprovider.uniqueValues(index, unique)
104
unique = self.getUniqueValues(vprovider, int(index))
105
inFeat = QgsFeature()
107
mlayer.removeSelection(True)
108
nFeat = vprovider.featureCount() * len(unique)
110
self.progressBar.setValue(0)
111
self.progressBar.setRange(0, nFeat)
112
if not len(unique) == mlayer.featureCount():
116
while vprovider.nextFeature(inFeat):
117
atMap = inFeat.attributeMap()
118
if atMap[index] == QVariant(i):
122
self.progressBar.setValue(nElement)
123
if perc: selVal = int(round((value / 100.0000) * len(FIDs), 0))
125
if selVal >= len(FIDs): selran = FIDs
126
else: selran = random.sample(FIDs, selVal)
127
selran.extend(mlayer.selectedFeaturesIds())
128
mlayer.setSelectedFeatures(selran)
130
mlayer.setSelectedFeatures(range(0, mlayer.featureCount()))
132
def getVectorLayerByName(self, myName):
133
mc = self.iface.mapCanvas()
134
nLayers = mc.layerCount()
135
for l in range(nLayers):
137
if layer.name() == unicode(myName,'latin1'):
138
vlayer = QgsVectorLayer(unicode(layer.source()), unicode(myName), unicode(layer.dataProvider().name()))
142
QMessageBox.information(self, "Random Selection Within Subsets", "Vector layer is not valid")
144
def getMapLayerByName(self, myName):
145
mc = self.iface.mapCanvas()
146
nLayers = mc.layerCount()
147
for l in range(nLayers):
149
if layer.name() == unicode(myName,'latin1'):
152
def getFieldList(self, vlayer):
153
fProvider = vlayer.dataProvider()
155
allAttrs = fProvider.attributeIndexes()
156
fProvider.select(allAttrs)
157
myFields = fProvider.fields()
160
def getUniqueValues(self, provider, index):
161
allAttrs = provider.attributeIndexes()
162
provider.select(allAttrs)
167
while provider.nextFeature(feat):
168
if not feat.attributeMap()[index].toString() in check:
169
values.append( feat.attributeMap()[index] )
170
check.append( feat.attributeMap()[index].toString() )
39
def __init__(self, iface):
40
QDialog.__init__(self)
42
# Set up the user interface from Designer.
44
QObject.connect(self.inShape, SIGNAL("currentIndexChanged(QString)"), self.update)
45
self.setWindowTitle(self.tr("Random selection within subsets"))
46
self.buttonOk = self.buttonBox_2.button( QDialogButtonBox.Ok )
48
self.progressBar.setValue(0)
49
mapCanvas = self.iface.mapCanvas()
50
layers = ftools_utils.getLayerNames([QGis.Point, QGis.Line, QGis.Polygon])
51
self.inShape.addItems(layers)
53
def update(self, inputLayer):
55
changedLayer = ftools_utils.getVectorLayerByName(inputLayer)
56
changedField = ftools_utils.getFieldList(changedLayer)
57
for i in changedField:
58
self.inField.addItem(unicode(changedField[i].name()))
59
maxFeatures = changedLayer.dataProvider().featureCount()
60
self.spnNumber.setMaximum( maxFeatures )
63
self.buttonOk.setEnabled( False )
64
if self.inShape.currentText() == "":
65
QMessageBox.information(self, self.tr("Random selection within subsets"), self.tr("Please specify input vector layer"))
66
elif self.inField.currentText() == "":
67
QMessageBox.information(self, self.tr("Random selection within subsets"), self.tr("Please specify an input field"))
69
inVect = self.inShape.currentText()
70
uidField = self.inField.currentText()
71
if self.rdoNumber.isChecked():
72
value = self.spnNumber.value()
75
value = self.spnPercent.value()
77
self.compute(inVect, uidField, value, perc, self.progressBar)
78
self.progressBar.setValue(100)
79
self.progressBar.setValue(0)
80
self.buttonOk.setEnabled( True )
82
def compute(self, inVect, inField, value, perc, progressBar):
83
mlayer = ftools_utils.getMapLayerByName(inVect)
84
mlayer.removeSelection(True)
85
vlayer = ftools_utils.getVectorLayerByName(inVect)
86
vprovider = vlayer.dataProvider()
87
allAttrs = vprovider.attributeIndexes()
88
vprovider.select(allAttrs)
89
index = vprovider.fieldNameIndex(inField)
91
#vprovider.uniqueValues(index, unique)
92
unique = ftools_utils.getUniqueValues(vprovider, int(index))
95
nFeat = vprovider.featureCount() * len(unique)
97
self.progressBar.setValue(0)
98
self.progressBar.setRange(0, nFeat)
99
if not len(unique) == mlayer.featureCount():
103
while vprovider.nextFeature(inFeat):
104
atMap = inFeat.attributeMap()
105
if atMap[index] == QVariant(i):
109
self.progressBar.setValue(nElement)
110
if perc: selVal = int(round((value / 100.0000) * len(FIDs), 0))
112
if selVal >= len(FIDs): selFeat = FIDs
113
else: selFeat = random.sample(FIDs, selVal)
114
selran.extend(selFeat)
115
mlayer.setSelectedFeatures(selran)
117
mlayer.setSelectedFeatures(range(0, mlayer.featureCount()))