Changeset 44444


Ignore:
Timestamp:
Nov 27, 2010, 12:16:04 AM (14 years ago)
Author:
mmetz
Message:

fix region alignment, table key column, -nan, enable translations, and speed up the module

File:
1 edited

Legend:

Unmodified
Added
Removed
  • grass/trunk/scripts/v.rast.stats/v.rast.stats.py

    r44443 r44444  
    44#
    55# MODULE:       v.rast.stats
    6 # AUTHOR(S):    Markus Neteler, converted to Python by Glynn Clements
     6# AUTHOR(S):    Markus Neteler
     7#               converted to Python by Glynn Clements
     8#               speed up by Markus Metz
    79# PURPOSE:      Calculates univariate statistics from a GRASS raster map
    810#               only for areas covered by vector objects on a per-category base
     
    7981
    8082def cleanup():
    81     grass.run_command('g.remove', rast = '%s_%s' % (vector, tmpname), quiet = True)
     83    grass.run_command('g.remove', rast = rastertmp, quiet = True)
    8284    grass.run_command('g.remove', rast = 'MASK', quiet = True, stderr = nuldev)
    8385    if mask_found:
     
    8890
    8991def main():
    90     global tmp, sqltmp, tmpname, nuldev, vector, mask_found
     92    global tmp, sqltmp, tmpname, nuldev, vector, mask_found, rastertmp
    9193    mask_found = False
    9294    #### setup temporary files
     
    120122    vector = vs[0]
    121123
    122     #check the input raster map
     124    rastertmp = "%s_%s" % (vector, tmpname)
     125
     126    # check the input raster map
    123127    if not grass.find_file(raster, 'cell')['file']:
    124128        grass.fatal(_("Raster map <%s> not found") % raster)
    125129
    126     #check presence of raster MASK, put it aside
     130    # check presence of raster MASK, put it aside
    127131    mask_found = bool(grass.find_file('MASK', 'cell')['file'])
    128132    if mask_found:
     
    130134        grass.run_command('g.rename', rast = ('MASK', tmpname + "_origmask"), quiet = True)
    131135
    132     #get RASTER resolution of map which we want to query:
    133     #fetch separated to permit for non-square cells (latlong etc)
    134     kv = grass.raster_info(map = raster)
    135     nsres = kv['nsres']
    136     ewres = kv['ewres']
    137 
    138     #save current settings:
     136    # save current settings:
    139137    grass.use_temp_region()
    140138
    141     #Temporarily setting raster resolution to $RASTER resolution
    142     #keep boundary settings
    143     grass.run_command('g.region', flags = 'a', nsres = nsres, ewres = ewres)
    144 
    145     #prepare raster MASK
    146     if grass.run_command('v.to.rast', input = vector, output = "%s_%s" % (vector, tmpname),
     139    # Temporarily aligning region resolution to $RASTER resolution
     140    # keep boundary settings
     141    grass.run_command('g.region', align = raster)
     142
     143    # prepare raster MASK
     144    if grass.run_command('v.to.rast', input = vector, output = rastertmp,
    147145                         use = 'cat', quiet = True) != 0:
    148146        grass.fatal(_("An error occurred while converting vector to raster"))
    149147
    150     #dump cats to file to avoid "too many argument" problem:
    151     p = grass.pipe_command('r.category', map = '%s_%s' % (vector, tmpname), fs = ';', quiet = True)
     148    # dump cats to file to avoid "too many argument" problem:
     149    p = grass.pipe_command('r.category', map = rastertmp, fs = ';', quiet = True)
    152150    cats = []
    153151    for line in p.stdout:
     
    155153    p.wait()
    156154
    157     #echo "List of categories found: $CATSLIST"
    158155    number = len(cats)
    159156    if number < 1:
    160157        grass.fatal(_("No categories found in raster map"))
    161158
    162     #check if DBF driver used, in this case cut to 10 chars col names:
     159    # check if DBF driver used, in this case cut to 10 chars col names:
    163160    try:
    164161        fi = grass.vector_db(map = vector)[int(layer)]
     
    168165    dbfdriver = fi['driver'] == 'dbf'
    169166
    170     #Find out which table is linked to the vector map on the given layer
     167    # Find out which table is linked to the vector map on the given layer
    171168    if not fi['table']:
    172169        grass.fatal(_('There is no table connected to this map. Run v.db.connect or v.db.addtable first.'))
     
    192189    addcols = []
    193190    for i in basecols + extracols:
    194         #check if column already present
     191        # check if column already present
    195192        currcolumn = ("%s_%s" % (colprefix, i))
    196193        if dbfdriver:
     
    199196        if currcolumn in grass.vector_columns(vector, layer).keys():
    200197            if not flags['c']:
    201                 grass.fatal(("Cannot create column <%s> (already present). " % currcolumn) +
    202                             "Use -c flag to update values in this column.")
     198                grass.fatal((_("Cannot create column <%s> (already present). ") % currcolumn) +
     199                            _("Use -c flag to update values in this column."))
    203200        else:
    204201            if i == "n":
     
    213210            grass.fatal(_("Adding columns failed. Exiting."))
    214211
    215     #loop over cats and calculate statistics:
     212    # calculate statistics:
    216213    grass.message(_("Processing data (%d categories)...") % number)
    217214
    218215    # get rid of any earlier attempts
    219216    grass.try_remove(sqltmp)
     217
     218    colnames = []
     219    for var in basecols + extracols:
     220        colname = '%s_%s' % (colprefix, var)
     221        if dbfdriver:
     222            colname = colname[:10]
     223        colnames.append(colname)
     224
     225    ntabcols = len(colnames)
    220226
    221227    # do extended stats?
     
    224230    else:
    225231        extstat = ""
    226 
     232       
    227233    f = file(sqltmp, 'w')
    228     currnum = 1
    229 
    230     for i in cats:
    231         grass.message(_("Processing category %s (%d/%d)...") % (i, currnum, number))
    232         grass.run_command('g.remove', rast = 'MASK', quiet = True, stderr = nuldev)
    233         grass.mapcalc("MASK = if($name == $i, 1, null())",
    234                       name = "%s_%s" % (vector, tmpname), i = i)
    235 
    236         #n, min, max, range, mean, stddev, variance, coeff_var, sum
    237         # How to test r.univar $? exit status? using -e creates the real possibility of out-of-memory errors
    238         s = grass.read_command('r.univar', flags = 'g' + extstat, map = raster, percentile = percentile)
    239         vars = grass.parse_key_val(s)
    240 
    241         vars['cf_var'] = vars['coeff_var']
    242 
    243         if flags['e'] and dbfdriver:
    244             percvar = 'percentile_' + percentile
    245             vars[perccol] = vars[percvar]
    246 
    247         for var in basecols + extracols:
    248             value = vars[var]
    249             if value.lower() == 'nan':
     234
     235    # do the stats
     236    p = grass.pipe_command('r.univar', flags = 't' + 'g' + extstat, map = raster,
     237                      zones = rastertmp, percentile = percentile, fs = ';')
     238
     239    first_line = 1
     240    for line in p.stdout:
     241        if first_line:
     242            first_line = 0
     243            continue
     244
     245        vars = line.rstrip('\r\n').split(';')
     246
     247        f.write("UPDATE %s SET" % fi['table'])
     248        i = 2
     249        first_var = 1
     250        for colname in colnames:
     251            value = vars[i]
     252            # convert nan, +nan, -nan to NULL
     253            if value.lower().endswith('nan'):
    250254                value = 'NULL'
    251             colname = '%s_%s' % (colprefix, var)
    252             if dbfdriver:
    253                 colname = colname[:10]
    254             f.write("UPDATE %s SET %s=%s WHERE cat=%s;\n" % (fi['table'], colname, value, i))
    255 
    256         currnum += 1
    257 
     255            if not first_var:
     256                f.write(" , ")
     257            else:
     258                first_var = 0
     259            f.write(" %s=%s" % (colname, value))
     260            i += 1
     261            # skip n_null_cells, mean_of_abs, sum_of_abs
     262            if i == 3 or i == 8 or i == 13:
     263                i += 1
     264
     265        f.write(" WHERE %s=%s;\n" % (fi['key'], vars[0]))
     266
     267    p.wait()
    258268    f.close()
    259269
     
    261271    exitcode = grass.run_command('db.execute', input = sqltmp,
    262272                                 database = fi['database'], driver = fi['driver'])
     273
     274    grass.run_command('g.remove', rast = 'MASK', quiet = True, stderr = nuldev)
     275
     276    if exitcode == 0:
     277        grass.message((_("Statistics calculated from raster map <%s>") % raster) +
     278                      (_(" and uploaded to attribute table of vector map <%s>.") % vector))
     279    else:
     280        grass.warning(_("Failed to upload statistics to attribute table of vector map <%s>.") % vector)
    263281   
    264     grass.run_command('g.remove', rast = 'MASK', quiet = True, stderr = nuldev)
    265 
    266     if exitcode == 0:
    267         grass.message(("Statistics calculated from raster map <%s>" % raster) +
    268                       (" and uploaded to attribute table of vector map <%s>." % vector))
    269282   
    270283    sys.exit(exitcode)
Note: See TracChangeset for help on using the changeset viewer.