[GRASS-SVN] r69189 - grass-addons/grass7/imagery/i.segment.stats
svn_grass at osgeo.org
svn_grass at osgeo.org
Sun Aug 21 10:51:39 PDT 2016
Author: mlennert
Date: 2016-08-21 10:51:39 -0700 (Sun, 21 Aug 2016)
New Revision: 69189
Modified:
grass-addons/grass7/imagery/i.segment.stats/i.segment.stats.html
grass-addons/grass7/imagery/i.segment.stats/i.segment.stats.py
Log:
i.segment.stats: switch to r.object.geometry for area measures, more robuts error handling
Modified: grass-addons/grass7/imagery/i.segment.stats/i.segment.stats.html
===================================================================
--- grass-addons/grass7/imagery/i.segment.stats/i.segment.stats.html 2016-08-21 17:34:49 UTC (rev 69188)
+++ grass-addons/grass7/imagery/i.segment.stats/i.segment.stats.html 2016-08-21 17:51:39 UTC (rev 69189)
@@ -8,7 +8,9 @@
<p>
Available statistics are those related to the shape and size of the areas
-(see the <a href="v.to.db.html">v.to.db</a> man page for more information
+(see the
+<a href="<a href="https://grass.osgeo.org/grass70/manuals/addons/r.object.geometry.html">r.object.geometry</a>
+addon man page for more information
on the statistics) and aggregated statistics of pixel values of other
raster maps (see <a href="v.univar.html">v.univar</a> for details).
@@ -26,9 +28,12 @@
<p>
This module is a simple front-end to <a href="v.univar.html">v.univar</a>
-and <a href="v.to.db.html">v.to.db</a>. If other statistics are desired,
-these should probably be implemented in those (or other) modules which
-can then be called from this module.
+and the
+<a href="<a href="https://grass.osgeo.org/grass70/manuals/addons/r.object.geometry.html">r.object.geometry</a>
+add-on. It is the user's responsibility to install the
+latter using <a href="g.extension.html">g.extension</a>. If other statistics
+are desired, these should probably be implemented in those (or other) modules
+which can then be called from this module.
<p>
Problems can arise in the calculation of some form statistics for certain
@@ -36,7 +41,12 @@
<a href="r.clump.html">r.clump</a> on the input raster file before running
<em>i.segment.stats</em>.
+<p>
+When treating files with a large number objects, creating the vector map
+can be very time-consuming. In that case, it might be easier to only work
+with the csv-format output.
+
<h2>EXAMPLE</h2>
<div class="code"><pre>
@@ -51,10 +61,14 @@
<em>
<a href="i.segment.html">i.segment</a>,
-<a href="v.to.db.html">v.to.db</a>,
<a href="v.univar.html">v.univar</a>,
<a href="v.rast.stats.html">v.rast.stats</a>
</em>
+<p>
+<em>
+<a href="https://grass.osgeo.org/grass70/manuals/addons/r.object.geometry.html">r.object.geometry (Addon)</a>
+<a href="https://grass.osgeo.org/grass70/manuals/addons/v.class.mlR.html">v.class.mlR (Addon)</a>
+</em>
<h2>AUTHOR</h2>
Moritz Lennert
Modified: grass-addons/grass7/imagery/i.segment.stats/i.segment.stats.py
===================================================================
--- grass-addons/grass7/imagery/i.segment.stats/i.segment.stats.py 2016-08-21 17:34:49 UTC (rev 69188)
+++ grass-addons/grass7/imagery/i.segment.stats/i.segment.stats.py 2016-08-21 17:51:39 UTC (rev 69189)
@@ -50,8 +50,8 @@
#% label: Area measurements to include in the output
#% required: no
#% multiple: yes
-#% options: area,perimeter,compact,fd
-#% answer: area,perimeter,compact,fd
+#% options: area,perimeter,compact_circle,compact_square,fd
+#% answer: area,perimeter,compact_circle,fd
#% guisection: shape_statistics
#%end
#%option G_OPT_F_OUTPUT
@@ -79,18 +79,21 @@
import atexit
import collections
import math
-import grass.script as grass
+import grass.script as gscript
def cleanup():
- if grass.find_file(temporary_vect, element='vector')['name']:
- grass.run_command('g.remove', flags='f', type_='vector',
+ if temporary_vect:
+ if gscript.find_file(temporary_vect, element='vector')['name']:
+ gscript.run_command('g.remove', flags='f', type_='vector',
name=temporary_vect, quiet=True)
if insert_sql:
os.remove(insert_sql)
+ os.remove(stats_temp_file)
+
def main():
@@ -99,6 +102,14 @@
vectormap = options['vectormap'] if options['vectormap'] else []
rasters = options['rasters'].split(',') if options['rasters'] else []
area_measures = options['area_measures'].split(',') if options['area_measures'] else []
+ r_object_geometry = True
+ if area_measures:
+ if not gscript.find_program('r.object.geometry', '--help'):
+ message = _("You need to install the addon 'r.object.geometry' to be able")
+ message += _(" to calculate area measures. Ignoring these measures for now")
+ gscript.warning(message)
+ r_object_geometry = False
+
raster_statistics = options['raster_statistics'].split(',') if options['raster_statistics'] else []
output_header = ['cat']
@@ -106,59 +117,100 @@
global insert_sql
insert_sql = None
-
global temporary_vect
- temporary_vect = 'segmstat_tmp_vect_%d' % os.getpid()
+ temporary_vect = None
raster_stat_dict = {'zone': 0, 'min': 4, 'third_quart': 16, 'max': 5, 'sum':
12, 'null_cells': 3, 'median': 15, 'label': 1, 'first_quart': 14,
'range': 6, 'mean_of_abs': 8, 'stddev': 9, 'non_null_cells': 2,
'coeff_var': 11, 'variance': 10, 'sum_abs': 13, 'perc_90': 17,
'mean': 7}
+
+ geometry_stat_dict = {'cat': 0, 'area': 1, 'perimeter': 2,
+ 'compact_square': 3, 'compact_circle': 4, 'fd' : 5}
if flags['r']:
- grass.use_temp_region()
- grass.run_command('g.region', raster=segment_map)
+ gscript.use_temp_region()
+ gscript.run_command('g.region', raster=segment_map)
- grass.run_command('r.to.vect',
- input_=segment_map,
- output=temporary_vect,
- type_='area',
- flags='vt')
+ global stats_temp_file
+ stats_temp_file = gscript.tempfile()
+ if area_measures and r_object_geometry:
+ gscript.message(_("Calculating geometry statistics"))
+ output_header += area_measures
+ stat_indices = [geometry_stat_dict[x] for x in area_measures]
+ gscript.run_command('r.object.geometry',
+ input_=segment_map,
+ output=stats_temp_file,
+ overwrite=True,
+ quiet=True)
+
+ firstline = True
+ with open(stats_temp_file, 'r') as fin:
+ for line in fin:
+ if firstline:
+ firstline = False
+ continue
+ values = line.rstrip().split('|')
+ output_dict[values[0]] = [values[x] for x in stat_indices]
- for area_measure in area_measures:
- output_header.append(area_measure)
- res=grass.read_command('v.to.db', map_=temporary_vect,
- option=area_measure, column=area_measure,
- flags='p').splitlines()[1:]
- for element in res:
- values = element.split('|')
- output_dict[values[0]].append(values[1])
-
for raster in rasters:
- if not grass.find_file(raster, element='raster')['name']:
- grass.message(_("Cannot find raster %s" % raster))
+ gscript.message(_("Calculating statistics for raster %s" % raster))
+ if not gscript.find_file(raster, element='raster')['name']:
+ gscript.message(_("Cannot find raster %s" % raster))
continue
rastername=raster.split('@')[0]
output_header += [rastername + "_" + x for x in raster_statistics]
stat_indices = [raster_stat_dict[x] for x in raster_statistics]
- res=grass.read_command('r.univar',
- map_=raster,
- zones=segment_map,
- flags='et').splitlines()[1:]
- for element in res:
- values = element.split('|')
- output_dict[values[0]] = output_dict[values[0]]+ [values[x] for x in stat_indices]
+ gscript.run_command('r.univar',
+ map_=raster,
+ zones=segment_map,
+ output=stats_temp_file,
+ flags='et',
+ overwrite=True,
+ quiet=True)
+ firstline = True
+ with open(stats_temp_file, 'r') as fin:
+ for line in fin:
+ if firstline:
+ firstline = False
+ continue
+ values = line.rstrip().split('|')
+ values = line.rstrip().split('|')
+ if area_measures:
+ output_dict[values[0]] = output_dict[values[0]]+ [values[x] for x in stat_indices]
+ else:
+ output_dict[values[0]] = [values[x] for x in stat_indices]
+
+ message = _("Some values could not be calculated for the objects below. ")
+ message += _("These objects are thus not included in the results. ")
+ message += _("HINT: Check some of the raster maps for null values ")
+ message += _("and possibly fill these values with r.fillnulls.")
+ error_objects = []
+
if csvfile:
with open(csvfile, 'wb') as f:
f.write(",".join(output_header)+"\n")
for key in output_dict:
- f.write(key+","+",".join(output_dict[key])+"\n")
+ if len(output_dict[key]) + 1 == len(output_header):
+ f.write(key+","+",".join(output_dict[key])+"\n")
+ else:
+ error_objects.append(key)
f.close()
if vectormap:
- insert_sql = grass.tempfile()
+ gscript.message(_("Creating vector map"))
+ temporary_vect = 'segmstat_tmp_vect_%d' % os.getpid()
+ gscript.run_command('r.to.vect',
+ input_=segment_map,
+ output=temporary_vect,
+ type_='area',
+ flags='vt',
+ overwrite=True,
+ quiet=True)
+
+ insert_sql = gscript.tempfile()
fsql = open(insert_sql, 'w')
fsql.write('BEGIN TRANSACTION;\n')
create_statement = 'CREATE TABLE ' + vectormap + ' (cat int, '
@@ -167,17 +219,28 @@
create_statement += output_header[-1] + ' double precision);\n'
fsql.write(create_statement)
for key in output_dict:
- sql = "INSERT INTO " + vectormap + " VALUES (" + key+","+",".join(output_dict[key])+");\n"
- sql = sql.replace('inf', 'NULL')
- fsql.write(sql)
+ if len(output_dict[key]) + 1 == len(output_header):
+ sql = "INSERT INTO " + vectormap + " VALUES (" + key+","+",".join(output_dict[key])+");\n"
+ sql = sql.replace('inf', 'NULL')
+ fsql.write(sql)
+ else:
+ if not csvfile:
+ error_objects.append(key)
+
fsql.write('END TRANSACTION;')
fsql.close()
- grass.run_command('g.copy', vector=temporary_vect+','+vectormap)
- grass.run_command('db.execute', input=insert_sql)
- grass.run_command('v.db.connect', map_=vectormap, table=vectormap)
+ gscript.run_command('g.copy', vector=temporary_vect+','+vectormap, quiet=True)
+ gscript.run_command('db.execute', input=insert_sql, quiet=True)
+ gscript.run_command('v.db.connect', map_=vectormap, table=vectormap, quiet=True)
+ if error_objects:
+ object_string = ', '.join(error_objects)
+ message += _("\n\nObjects with errors: %s" % object_string)
+ gscript.warning(message)
+
+
if __name__ == "__main__":
- options, flags = grass.parser()
+ options, flags = gscript.parser()
atexit.register(cleanup)
main()
More information about the grass-commit
mailing list