Skip to content

Commit

Permalink
Fixed:
Browse files Browse the repository at this point in the history
  Histograms for decimal files
  Progress bar
Added:
  Control for number of decimals in histogram
  • Loading branch information
unknown authored and unknown committed Aug 18, 2015
1 parent 08a9e26 commit ca64935
Show file tree
Hide file tree
Showing 4 changed files with 123 additions and 46 deletions.
4 changes: 2 additions & 2 deletions metadata.txt
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@ email=pedro@xl-optim.com
author=Pedro Camargo
qgisMinimumVersion=2.8
description=Raster Statistics toolbox for QGIS
about=This plugin is designed to return basic raster statistics regarding
raster files for polygons in a given layer. It is MANDATORY that the vector
about=This plugin is designed to return basic raster statistics regarding raster files for polygons in a given layer. It is MANDATORY that the vector
layer has a field named ID with unique numbers for result reporting.
In addition to the tools that already exist in QGIS for computing raster statistics, this plugin allows for the computation of histograms for zones and provides a wider range of summary statistics (Average,Mean,Median,Standard deviation,Variance,Minimum and Maximum)
version=0.1
tracker=https://bitbucket.org/pedrocamargo/rasterstats/issues
repository=https://bitbucket.org/pedrocamargo/rasterstats
Expand Down
109 changes: 68 additions & 41 deletions rasterstats_dialogs.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,37 +54,46 @@ def cleanUp(self):


class RunMyRasterStatistics(WorkerThread):
def __init__(self, parentThread, input_zone_polygon, input_value_raster, output_file, histogram):
def __init__(self, parentThread, input_zone_polygon, input_value_raster, output_file, decimals, histogram):
WorkerThread.__init__(self, parentThread)
self.input_zone_polygon = input_zone_polygon
self.input_value_raster = input_value_raster
self.output_file = output_file
self.decimals = decimals
self.histogram = histogram
self.emit(SIGNAL("ProgressValue( PyQt_PyObject )"), 50)

def doWork(self):
# We colect info on the vector file
shp = ogr.Open(self.input_zone_polygon)
lyr = shp.GetLayer()
featList = range(lyr.GetFeatureCount())
statDict = {}

columns=0
tot_feat = float(lyr.GetFeatureCount())
i = 0
columns = 0
for FID in featList:
feat = lyr.GetFeature(FID)
statistics = self.zonal_stats(feat, self.input_zone_polygon, self.input_value_raster, self.histogram)
statistics = self.zonal_stats(feat, self.input_zone_polygon, self.input_value_raster, self.decimals, self.histogram)
statDict[feat.GetField("ID")] = statistics
if self.histogram and statistics is not None:
if columns < statistics.shape[0]:
columns = statistics.shape[0]
#self.emit(SIGNAL("ProgressValue( PyQt_PyObject )"), (evol_bar, self.featcount))
i += 1
self.emit(SIGNAL("ProgressValue( PyQt_PyObject )"), int(100*(float(i)/tot_feat)))


O=open(self.output_file,'w')
if self.histogram:
txt = 'Zone ID'
for i in range(columns):
txt=txt+','+str(i)

if self.decimals > 0:
divide = pow(10, self.decimals)
for i in range(columns):
txt = txt + ',' + str(round(float(i)/divide,self.decimals))
else:
for i in range(columns):
txt = txt + ',' + str(i)
print >>O, txt
else:
print >>O, 'Zone ID,Average,Mean,Median,Standard deviation,Variance,Minimum,Maximum'
Expand All @@ -94,19 +103,21 @@ def doWork(self):
print >>O, txt + ',No data or error in computation'
else:
for i in statDict[ids]:
txt=txt+','+str(i)
txt = txt + ',' + str(i)
for i in range(columns - len(statDict[ids])):
txt = txt + ',0'
print >>O, txt
O.flush()
O.close()
self.emit(SIGNAL("FinishedThreadedProcedure( PyQt_PyObject )"),0)
def zonal_stats(self, feat, input_zone_polygon, input_value_raster, histogram=False):

def zonal_stats(self, feat, input_zone_polygon, input_value_raster, decimals, histogram=False):

# Open data
raster = gdal.Open(input_value_raster)
shp = ogr.Open(input_zone_polygon)
lyr = shp.GetLayer()


# Get raster georeference info
transform = raster.GetGeoTransform()
xOrigin = transform[0]
Expand Down Expand Up @@ -174,42 +185,46 @@ def zonal_stats(self, feat, input_zone_polygon, input_value_raster, histogram=Fa
# Rasterize zone polygon to raster
gdal.RasterizeLayer(target_ds, [1], lyr, burn_values=[1])




#try:
a=['Error in computation']
# Read raster as arrays
banddataraster = raster.GetRasterBand(1)
dataraster = banddataraster.ReadAsArray(xoff, yoff, xcount, ycount).astype(np.float)

bandmask = target_ds.GetRasterBand(1)
datamask = bandmask.ReadAsArray(0, 0, xcount, ycount).astype(np.int)

# Calculate statistics of zonal raster`
if histogram:
dataraster=dataraster.astype(np.int)
b = np.bincount((dataraster*datamask).flat, weights=None, minlength=None)
else:
# Mask zone of raster
zoneraster = np.ma.masked_array(dataraster, np.logical_not(datamask))
b = [np.average(zoneraster), np.mean(zoneraster), np.median(zoneraster), np.std(zoneraster), np.var(zoneraster), np.min(zoneraster), np.max(zoneraster)]
a = b
return a
#except:
# print 'Error computing statistics'

try:
# Read raster as arrays
banddataraster = raster.GetRasterBand(1)
dataraster = banddataraster.ReadAsArray(xoff, yoff, xcount, ycount).astype(np.float)

bandmask = target_ds.GetRasterBand(1)
datamask = bandmask.ReadAsArray(0, 0, xcount, ycount).astype(np.int)

# Calculate statistics of zonal raster`
if histogram:
if decimals >0:
dataraster = dataraster * pow(10,decimals)
dataraster = dataraster.astype(np.int)
a = np.bincount((dataraster*datamask).flat, weights=None, minlength=None)
else:
# Mask zone of raster
zoneraster = np.ma.masked_array(dataraster, np.logical_not(datamask))
a = [np.average(zoneraster), np.mean(zoneraster), np.median(zoneraster), np.std(zoneraster), np.var(zoneraster), np.min(zoneraster), np.max(zoneraster)]
return a
except:
print 'Error computing statistics'

class open_rasterstats_class(QtGui.QDialog,Ui_rasterstats_view):
def __init__(self, iface):
QtGui.QDialog.__init__(self)
self.iface = iface
self.setupUi(self)
self.decimals = 0

self.all_inputs = np.zeros(3,np.int32)

self.but_raster.clicked.connect(self.browse_rasterfile)
self.but_vector.clicked.connect(self.browse_vectorfile)
self.but_output.clicked.connect(self.browse_outputfile)


self.histogram.toggled.connect(self.sets_histogram)
self.general.toggled.connect(self.sets_histogram)
self.slider_decimals.valueChanged.connect(self.update_decimals)

self.but_run.clicked.connect(self.run_stats)
self.but_close.clicked.connect(self.closewidget)

Expand Down Expand Up @@ -240,7 +255,20 @@ def browse_outputfile(self):

def closewidget(self):
self.close()


def update_decimals(self):
self.label_decimals.setText('Histogram decimal places: '+str(self.slider_decimals.value()))
self.decimals = self.slider_decimals.value()

def sets_histogram(self):
status = False
if self.histogram.isChecked():
status = True

self.label_decimals.setVisible(status)
self.slider_decimals.setVisible(status)


def ProgressValueFromThread(self, val):
self.progressbar.setValue(val)

Expand All @@ -261,6 +289,5 @@ def run_stats(self):
histogram = True

self.workerThread = RunMyRasterStatistics(qgis.utils.iface.mainWindow(), self.vector_name.text(), self.raster_name.text(),
self.output_file.text(), histogram)
self.runThread()

self.output_file.text(), self.decimals, histogram)
self.runThread()
16 changes: 14 additions & 2 deletions ui_rasterstats_visualizer.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

# Form implementation generated from reading ui file 'ui_rasterstats_visualizer.ui'
#
# Created: Fri Aug 14 13:34:41 2015
# Created: Tue Aug 18 14:03:02 2015
# by: PyQt4 UI code generator 4.10.4
#
# WARNING! All changes made in this file will be lost!
Expand Down Expand Up @@ -92,6 +92,17 @@ def setupUi(self, rasterstats_view):
self.progressbar.setProperty("value", 0)
self.progressbar.setTextVisible(True)
self.progressbar.setObjectName(_fromUtf8("progressbar"))
self.slider_decimals = QtGui.QSlider(self.centralwidget)
self.slider_decimals.setGeometry(QtCore.QRect(400, 13, 160, 19))
self.slider_decimals.setMaximum(5)
self.slider_decimals.setPageStep(5)
self.slider_decimals.setOrientation(QtCore.Qt.Horizontal)
self.slider_decimals.setTickPosition(QtGui.QSlider.TicksBelow)
self.slider_decimals.setTickInterval(1)
self.slider_decimals.setObjectName(_fromUtf8("slider_decimals"))
self.label_decimals = QtGui.QLabel(self.centralwidget)
self.label_decimals.setGeometry(QtCore.QRect(250, 13, 141, 20))
self.label_decimals.setObjectName(_fromUtf8("label_decimals"))
#rasterstats_view.setCentralWidget(self.centralwidget)
#self.statusbar = QtGui.QStatusBar(rasterstats_view)
#self.statusbar.setObjectName(_fromUtf8("statusbar"))
Expand All @@ -104,12 +115,13 @@ def retranslateUi(self, rasterstats_view):
rasterstats_view.setWindowTitle(_translate("rasterstats_view", "Raster Statistics", None))
self.but_raster.setText(_translate("rasterstats_view", "Choose Raster file", None))
self.but_close.setText(_translate("rasterstats_view", "Close", None))
self.but_vector.setText(_translate("rasterstats_view", "Choose Raster file", None))
self.but_vector.setText(_translate("rasterstats_view", "Choose Vector file", None))
self.but_run.setText(_translate("rasterstats_view", "Run", None))
self.histogram.setText(_translate("rasterstats_view", "Histogram", None))
self.general.setText(_translate("rasterstats_view", "General stats", None))
self.raster_name.setText(_translate("rasterstats_view", "Raster file", None))
self.vector_name.setText(_translate("rasterstats_view", "Vector file", None))
self.but_output.setText(_translate("rasterstats_view", "Choose output file", None))
self.output_file.setText(_translate("rasterstats_view", "Output file", None))
self.label_decimals.setText(_translate("rasterstats_view", "Histogram decimal places: 0", None))

40 changes: 39 additions & 1 deletion ui_rasterstats_visualizer.ui
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@
</font>
</property>
<property name="text">
<string>Choose Raster file</string>
<string>Choose Vector file</string>
</property>
</widget>
<widget class="QPushButton" name="but_run">
Expand Down Expand Up @@ -228,6 +228,44 @@
<bool>true</bool>
</property>
</widget>
<widget class="QSlider" name="slider_decimals">
<property name="geometry">
<rect>
<x>400</x>
<y>13</y>
<width>160</width>
<height>19</height>
</rect>
</property>
<property name="maximum">
<number>5</number>
</property>
<property name="pageStep">
<number>5</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="tickPosition">
<enum>QSlider::TicksBelow</enum>
</property>
<property name="tickInterval">
<number>1</number>
</property>
</widget>
<widget class="QLabel" name="label_decimals">
<property name="geometry">
<rect>
<x>250</x>
<y>13</y>
<width>141</width>
<height>20</height>
</rect>
</property>
<property name="text">
<string>Histogram decimal places: 0</string>
</property>
</widget>
</widget>
<widget class="QStatusBar" name="statusbar"/>
</widget>
Expand Down

0 comments on commit ca64935

Please sign in to comment.