|
| 1 | +#!/usr/bin/env python |
| 2 | +# -*- coding: utf-8 -*- |
| 3 | + |
| 4 | +""" |
| 5 | +*************************************************************************** |
| 6 | + GRASS Direct test - to be run in GRASS shell |
| 7 | + |
| 8 | + - collects list of raster layers |
| 9 | + - exports GRASS layers on low resolution to temporary GeoTIFFs |
| 10 | + - runs GRASS modules in standard and direct mode and compares results |
| 11 | + - writes out report |
| 12 | +*************************************************************************** |
| 13 | +""" |
| 14 | +__author__ = 'Radim Blazek' |
| 15 | +__date__ = 'December 2012' |
| 16 | +__copyright__ = '(C) 2012, Radim Blazek' |
| 17 | +__revision__ = '$Format:%H$' |
| 18 | + |
| 19 | +import os, sys, glob, subprocess, time, re |
| 20 | + |
| 21 | +class Test: |
| 22 | + def __init__(self): |
| 23 | + if not os.environ.has_key("GISBASE") or not os.environ.has_key("GISRC"): |
| 24 | + print "This script must be run in GRASS shell." |
| 25 | + sys.exit ( 1 ) |
| 26 | + |
| 27 | + if not os.environ.has_key("QGIS_PREFIX_PATH"): |
| 28 | + print "QGIS_PREFIX_PATH environment variable not set." |
| 29 | + sys.exit ( 1 ) |
| 30 | + |
| 31 | + self.size = 10 |
| 32 | + self.reportStr = "" |
| 33 | + pass |
| 34 | + |
| 35 | + # add message to HTML report |
| 36 | + def report( self, msg ): |
| 37 | + self.reportStr += msg + "\n" |
| 38 | + |
| 39 | + def writeReport( self ): |
| 40 | + print self.reportStr |
| 41 | + |
| 42 | + def test(self): |
| 43 | + print "GRASS Direct test" |
| 44 | + |
| 45 | + |
| 46 | + |
| 47 | + tmp_dir = os.path.abspath( "qgis-grass-test-%s" % time.strftime('%y%m%d-%H%M%S') ) |
| 48 | + tmp_dir = os.path.abspath( "qgis-grass-test-debug" ) # debug |
| 49 | + print "Output will be written to %s" % tmp_dir |
| 50 | + |
| 51 | + files_dir = "%s/tif" % tmp_dir |
| 52 | + #os.makedirs( files_dir ) |
| 53 | + |
| 54 | + # get list of raster layers |
| 55 | + print "Getting list of rasters ..." |
| 56 | + rasters = self.srun( ["g.mlist", "type=rast"] ).splitlines() |
| 57 | + max_rasters = 1 |
| 58 | + print "%s rasters found, using first %s" % ( len( rasters), max_rasters ) |
| 59 | + rasters = rasters[0:1] |
| 60 | + |
| 61 | + print "Exporting rasters" |
| 62 | + for raster in rasters: |
| 63 | + print raster |
| 64 | + output = "%s/%s.tif" % ( files_dir, raster ) |
| 65 | + self.srun( ["g.region", "rast=%s" % raster, "cols=%s" % self.size, "rows=%s" % self.size ] ) |
| 66 | + self.srun( ["r.out.gdal", "input=%s" % raster, "output=%s" % output] ) |
| 67 | + |
| 68 | + # run modules |
| 69 | + count = 0 |
| 70 | + for module in self.modules(): |
| 71 | + for raster in rasters: |
| 72 | + module = re.sub(" *", " ", module ) |
| 73 | + module_name = module.split(" ")[0] |
| 74 | + # --- native --- |
| 75 | + self.srun( ["g.region", "rast=%s" % raster, "cols=%s" % self.size, "rows=%s" % self.size ] ) |
| 76 | + output = "qgistest1" |
| 77 | + # clean old |
| 78 | + self.srun( ["g.remove", "-f", "rast=%s" % output ] ) |
| 79 | + # substitute rasters |
| 80 | + native_args = module.replace("R1",raster).replace("RO1",output).split(" "); |
| 81 | + (code, out, err) = self.run( native_args ) |
| 82 | + if code != 0: |
| 83 | + self.report( "Native failed: %s" % " ".join(native_args) ) |
| 84 | + # export |
| 85 | + native_output_file = "%s/%s-%s-native.tif" % ( files_dir, module_name, raster ) |
| 86 | + self.srun( ["r.out.gdal", "input=%s" % output, "output=%s" % native_output_file] ) |
| 87 | + self.srun( ["g.remove", "-f", "rast=%s" % output ] ) |
| 88 | + |
| 89 | + # --- direct --- |
| 90 | + direct_input_file = "%s/%s.tif" % ( files_dir, raster ) |
| 91 | + direct_output_file = "%s/%s-%s-direct.tif" % ( files_dir, module_name, raster ) |
| 92 | + |
| 93 | + # substitute rasters |
| 94 | + direct_args = module.replace("R1",direct_input_file).replace("RO1",direct_output_file).split(" "); |
| 95 | + env = os.environ |
| 96 | + |
| 97 | + # CRS |
| 98 | + proj = self.srun( ["g.proj", "-j"] ) |
| 99 | + longlat = True if proj.find("+proj=longlat") != -1 else False |
| 100 | + proj = proj.splitlines() |
| 101 | + proj = " ".join ( proj ) |
| 102 | + print proj |
| 103 | + env['QGIS_GRASS_CRS'] = proj |
| 104 | + |
| 105 | + # set GRASS region as environment variable |
| 106 | + reg = self.srun( ["g.region", "-g"] ) |
| 107 | + reg_dict = dict(item.split("=") for item in reg.splitlines()) |
| 108 | + reg_var= { 'n': 'north', 's': 'south', 'e': 'east', 'w':'west', 'nsres': 'n-s resol', 'ewres': 'e-w resol' } |
| 109 | + if longlat: |
| 110 | + region = "proj:3;zone:-1" # longlat |
| 111 | + else: |
| 112 | + region = "proj:99;zone:-1" # other projection |
| 113 | + for k,v in reg_dict.iteritems(): |
| 114 | + if k == 'cells': continue |
| 115 | + kn = k |
| 116 | + if reg_var.has_key( k ) : kn = reg_var[k] |
| 117 | + region += ";%s:%s" % ( kn, v ) |
| 118 | + print region |
| 119 | + env['GRASS_REGION'] = region |
| 120 | + |
| 121 | + # add path to fake GRASS gis library |
| 122 | + env['LD_LIBRARY_PATH'] = "%s/lib/qgis/plugins/:%s" % (env['QGIS_PREFIX_PATH'], env['LD_LIBRARY_PATH'] ) |
| 123 | + (code, out, err) = self.run( direct_args, env ) |
| 124 | + print "code = %s" % code |
| 125 | + if code != 0: |
| 126 | + self.report( "Direct failed: %s\n%s\n%s" % (" ".join(direct_args), out, err) ) |
| 127 | + # TODO: compare native x direct output |
| 128 | + |
| 129 | + def run( self, args, env=None, input = None, exit_on_error = False ): |
| 130 | + cmd = " ".join(args) |
| 131 | + print cmd |
| 132 | + p = subprocess.Popen( args, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE, env=env) |
| 133 | + com = p.communicate( input ) |
| 134 | + p.wait() |
| 135 | + |
| 136 | + if p.returncode != 0 and exit_on_error: |
| 137 | + msg = "Failed:\n" + str(com[0]) + "\n" + str(com[1]) |
| 138 | + raise Exception( msg ) |
| 139 | + |
| 140 | + return (p.returncode, com[0], com[1] ) # return stdout |
| 141 | + |
| 142 | + # simple run |
| 143 | + def srun( self, args ): |
| 144 | + return self.run(args, None, None, True)[1] |
| 145 | + |
| 146 | + def modules(self ): |
| 147 | + # R1 - input raster 1 |
| 148 | + # RO1 - output raster 1 |
| 149 | + modules = [ |
| 150 | + "r.slope.aspect elevation=R1 aspect=RO1" |
| 151 | + ] |
| 152 | + return modules |
| 153 | + |
| 154 | +if __name__ == '__main__': |
| 155 | + test = Test() |
| 156 | + test.test() |
| 157 | + test.writeReport() |
0 commit comments