3
############################################################################
5
# MODULE: r.reclass.area
7
# Converted to Python by Glynn Clements
8
# Added rmarea method by Luca Delucchi
9
# PURPOSE: Reclasses a raster map greater or less than user specified area size (in hectares)
10
# COPYRIGHT: (C) 1999,2008,2014 by the GRASS Development Team
12
# This program is free software under the GNU General Public
13
# License (>=v2). Read the file COPYING that comes with GRASS
16
#############################################################################
17
# 10/2013: added option to use a pre-clumped input map (Eric Goddard)
18
# 8/2012: added fp maps support, cleanup, removed tabs AK
19
# 3/2007: added label support MN
20
# 3/2004: added parser support MN
21
# 11/2001 added mapset support markus
23
# 2000: updated to GRASS 5
24
# 1998 from NRCS, slightly modified for GRASS 4.2.1
27
#% description: Reclasses a raster map greater or less than user specified area size (in hectares).
29
#% keyword: statistics
30
#% keyword: aggregation
33
#%option G_OPT_R_INPUT
36
#%option G_OPT_R_OUTPUT
42
#% description: Value option that sets the area size limit (in hectares)
50
#% description: Lesser or greater than specified value
51
#% options: lesser,greater
59
#% description: Method used for reclassification
60
#% options: reclass,rmarea
67
#% description: Input map is clumped
72
#% description: Clumps including diagonal neighbors
78
import grass.script as grass
83
def reclass(inf, outf, lim, clump, diag, les):
91
s = grass.read_command("g.region", flags='p')
92
kv = grass.parse_key_val(s, sep=':')
93
s = kv['projection'].strip().split()
95
grass.fatal(_("xy-locations are not supported"))
96
grass.fatal(_("Need projected data with grids in meters"))
98
if not grass.find_file(infile)['name']:
99
grass.fatal(_("Raster map <%s> not found") % infile)
101
if clumped and diagonal:
102
grass.fatal(_("flags c and d are mutually exclusive"))
107
clumpfile = "%s.clump.%s" % (infile.split('@')[0], outfile)
108
TMPRAST.append(clumpfile)
110
if not grass.overwrite():
111
if grass.find_file(clumpfile)['name']:
112
grass.fatal(_("Temporary raster map <%s> exists") % clumpfile)
114
grass.message(_("Generating a clumped raster file including "
115
"diagonal neighbors..."))
116
grass.run_command('r.clump', flags='d', input=infile,
119
grass.message(_("Generating a clumped raster file ..."))
120
grass.run_command('r.clump', input=infile, output=clumpfile)
123
grass.message(_("Generating a reclass map with area size less than "
124
"or equal to %f hectares...") % limit)
126
grass.message(_("Generating a reclass map with area size greater "
127
"than or equal to %f hectares...") % limit)
129
recfile = outfile + '.recl'
130
TMPRAST.append(recfile)
133
if grass.raster_info(infile)['datatype'] in ('FCELL', 'DCELL'):
135
p1 = grass.pipe_command('r.stats', flags=sflags, input=(clumpfile, infile),
137
p2 = grass.feed_command('r.reclass', input=clumpfile, output=recfile,
140
for line in p1.stdout:
141
f = line.rstrip(os.linesep).split(';')
144
hectares = float(f[4]) * 0.0001
146
test = hectares <= limit
148
test = hectares >= limit
150
rules += "%s = %s %s\n" % (f[0], f[2], f[3])
152
p2.stdin.write(rules)
156
if p2.returncode != 0:
158
grass.fatal(_("No areas of size less than or equal to %f "
159
"hectares found.") % limit)
161
grass.fatal(_("No areas of size greater than or equal to %f "
162
"hectares found.") % limit)
163
grass.mapcalc("$outfile = $recfile", outfile=outfile, recfile=recfile)
166
def rmarea(infile, outfile, thresh, coef):
167
# transform user input from hectares to map units (kept this for future)
168
# thresh = thresh * 10000.0 / (float(coef)**2)
169
# grass.debug("Threshold: %d, coeff linear: %s, coef squared: %d" % (thresh, coef, (float(coef)**2)), 0)
171
# transform user input from hectares to meters because currently v.clean
172
# rmarea accept only meters as threshold
173
thresh = thresh * 10000.0
174
vectfile = "%s_vect_%s" % (infile.split('@')[0], outfile)
175
TMPRAST.append(vectfile)
176
grass.run_command('r.to.vect', input=infile, output=vectfile, type='area')
177
cleanfile = "%s_clean_%s" % (infile.split('@')[0], outfile)
178
TMPRAST.append(cleanfile)
179
grass.run_command('v.clean', input=vectfile, output=cleanfile,
180
tool='rmarea', threshold=thresh)
182
grass.run_command('v.to.rast', input=cleanfile, output=outfile,
183
use='attr', attrcolumn='value')
187
infile = options['input']
188
value = options['value']
189
mode = options['mode']
190
outfile = options['output']
192
method = options['method']
194
diagonal = flags['d']
196
# check for unsupported locations
197
in_proj = grass.parse_command('g.proj', flags='g')
198
if in_proj['unit'].lower() == 'degree':
199
grass.fatal(_("Latitude-longitude locations are not supported"))
200
if in_proj['name'].lower() == 'xy_location_unprojected':
201
grass.fatal(_("xy-locations are not supported"))
203
# check lesser and greater parameters
205
if mode == 'greater' and method == 'rmarea':
206
grass.fatal(_("You have to specify mode='lesser' with method='rmarea'"))
208
if not grass.find_file(infile)['name']:
209
grass.fatal(_("Raster map <%s> not found") % infile)
211
if method == 'reclass':
212
reclass(infile, outfile, limit, clumped, diagonal, mode == 'lesser')
213
elif method == 'rmarea':
214
rmarea(infile, outfile, limit, in_proj['meters'])
216
grass.message(_("Generating output raster map <%s>...") % outfile)
220
"""!Delete temporary maps"""
221
TMPRAST.reverse() # reclassed map first
223
if method == 'rmarea':
224
grass.run_command("g.remove", flags='f', type='vector', name=mapp,
227
grass.run_command("g.remove", flags='f', type='raster', name=mapp,
230
if __name__ == "__main__":
231
options, flags = grass.parser()
232
atexit.register(cleanup)