def __getDbInfos(self): """Create a dictionnary with all db params needed by v.in.ogr.""" try: dbString = grass.parse_key_val(grass.read_command('db.connect', flags='p'), sep=':')['database'] p = re.compile(',') dbElems = p.split(dbString) host = grass.parse_key_val(dbElems[0], sep='=')['host'] db = grass.parse_key_val(dbElems[1], sep='=')['dbname'] loginLine = self.executeCommand('sed -n "/pg ' + dbElems[0] + ','\ + dbElems[1] + ' /p" ' + self.grassloginfile, toLog = False, shell = True) p = re.compile(' ') loginElems = p.split(loginLine) user = loginElems[-2].strip() password = loginElems[-1].strip() dbParamsDict = { 'host': host, 'db': db, 'user': user, 'pwd': password } return dbParamsDict except: raise GrassPostGisImporterError( "Error while trying to retrieve database information.")
def estimate_resolution(raster, mapset, location, dbase, env): """Estimates resolution of reprojected raster. :param str raster: name of raster :param str mapset: mapset of raster :param str location: name of source location :param str dbase: path to source database :param dict env: target environment :return float estimate: estimated resolution of raster in destination environment """ output = gs.read_command( "r.proj", flags="g", input=raster, mapset=mapset, location=location, dbase=dbase, env=env, ).strip() params = gs.parse_key_val(output, vsep=" ") output = gs.read_command("g.region", flags="ug", env=env, **params) output = gs.parse_key_val(output, val_type=float) cell_ns = (output["n"] - output["s"]) / output["rows"] cell_ew = (output["e"] - output["w"]) / output["cols"] estimate = (cell_ew + cell_ns) / 2.0 return estimate
def _estimateResolution(self): output = RunCommand( "r.proj", flags="g", quiet=False, read=True, input=self.iLayer, dbase=self.iGisdbase, location=self.iLocation, mapset=self.iMapset, env=self.oEnv, ).strip() params = parse_key_val(output, vsep=" ") output = RunCommand( "g.region", flags="ug", quiet=False, read=True, env=self.oEnv, parse=lambda x: parse_key_val(x, val_type=float), **params, ) cell_ns = (output["n"] - output["s"]) / output["rows"] cell_ew = (output["e"] - output["w"]) / output["cols"] estimate = (cell_ew + cell_ns) / 2.0 self.resolution.SetValue(str(estimate)) self.params = params
def _handler(self, request, response): from subprocess import PIPE import grass.script as gs from grass.pygrass.modules import Module from grass.exceptions import CalledModuleError start1 = request.inputs['start1'][0].data end1 = request.inputs['end1'][0].data self.check_date(start1) self.check_date(end1) start2 = request.inputs['start2'][0].data end2 = request.inputs['end2'][0].data self.check_date(start2) self.check_date(end2) output1 = 'stcVH' output2 = 'stcVV' # be silent os.environ['GRASS_VERBOSE'] = '0' try: Module( 't.rast.series', input='stcubeVH@PERMANENT', output=output1, method='average', where="start_time > '{start}' and start_time < '{end}'".format( start=start1, end=end1)) Module( 't.rast.series', input='stcubeVV@PERMANENT', output=output2, method='average', where="start_time > '{start}' and start_time < '{end}'".format( start=start2, end=end2)) except CalledModuleError: raise Exception('Unable to compute statistics') ret = Module('r.univar', flags='g', map=output1, stdout_=PIPE) ret2 = Module('r.univar', flags='g', map=output2, stdout_=PIPE) stats1 = gs.parse_key_val(ret.outputs.stdout) stats2 = gs.parse_key_val(ret2.outputs.stdout) outstr1 = 'Min1: {0:.1f};Max1: {1:.1f};Mean1: {2:.1f}'.format( float(stats1['min']), float(stats1['max']), float(stats1['mean'])) outstr2 = 'Min2: {0:.1f};Max2: {1:.1f};Mean2: {2:.1f}'.format( float(stats2['min']), float(stats2['max']), float(stats2['mean'])) response.outputs['stats1'].data = outstr1 response.outputs['stats2'].data = outstr2 return response
def _estimateResolution(self): output = RunCommand('r.proj', flags='g', quiet=False, read=True, input=self.iLayer, dbase=self.iGisdbase, location=self.iLocation, mapset=self.iMapset, env=self.oEnv).strip() params = parse_key_val(output, vsep=' ') output = RunCommand('g.region', flags='ug', quiet=False, read=True, env=self.oEnv, parse=lambda x: parse_key_val(x, val_type=float), **params) cell_ns = (output['n'] - output['s']) / output['rows'] cell_ew = (output['e'] - output['w']) / output['cols'] estimate = (cell_ew + cell_ns) / 2. self.resolution.SetValue(str(estimate)) self.params = params
def output_headers(river, xsections, outfile): """ Prepare the output sdf file, and add header section """ # Start header section ver=grass.read_command('g.version') dt=str(datetime.date.today()) outfile.write("# RAS geometry file create on: "+dt+"\n") outfile.write("# exported from GRASS GIS version: "+ver+"\n\n") outfile.write("BEGIN HEADER:\n") proj=grass.read_command('g.proj',flags="g") d=grass.parse_key_val(proj) if d['units'] == "metres": units="METRIC" elif d['units'] == "feet": units="US CUSTOMARY" else: units="" outfile.write(" UNITS: "+ units + "\n") outfile.write(" DTM TYPE: GRID\n") outfile.write(" STREAM LAYER: "+ river +"\n") outfile.write(" CROSS-SECTION LAYER: "+ xsections +"\n") # write out the extents info = grass.read_command('v.info', map=river, flags="g") d=grass.parse_key_val(info) xmin=d['west'] xmax=d['east'] ymin=d['south'] ymax=d['north'] outfile.write(" BEGIN SPATIALEXTENT: \n") outfile.write(" Xmin: "+ xmin +"\n") outfile.write(" Xmax: "+ xmax +"\n") outfile.write(" Ymin: "+ ymin +"\n") outfile.write(" Ymax: "+ ymax +"\n") outfile.write(" END SPATIALEXTENT: \n") # write out how many reaches and cross sections info = grass.read_command('v.info', map=river, flags="t") d = grass.parse_key_val(info) num_reaches=d['lines'] outfile.write(" NUMBER OF REACHES: "+ num_reaches +"\n") info = grass.read_command('v.info', map=xsections, flags="t") d=grass.parse_key_val(info) num_xsects=d['lines'] outfile.write(" NUMBER OF CROSS-SECTIONS: "+ num_xsects +"\n") outfile.write("END HEADER:\n\n")
def output_headers(river, xsections, outfile): """ Prepare the output sdf file, and add header section """ # Start header section ver = grass.read_command('g.version') dt = str(datetime.date.today()) outfile.write("# RAS geometry file create on: " + dt + "\n") outfile.write("# exported from GRASS GIS version: " + ver + "\n\n") outfile.write("BEGIN HEADER:\n") proj = grass.read_command('g.proj', flags="g") d = grass.parse_key_val(proj) if d['units'] == "metres": units = "METRIC" elif d['units'] == "feet": units = "US CUSTOMARY" else: units = "" outfile.write(" UNITS: " + units + "\n") outfile.write(" DTM TYPE: GRID\n") outfile.write(" STREAM LAYER: " + river + "\n") outfile.write(" CROSS-SECTION LAYER: " + xsections + "\n") # write out the extents info = grass.read_command('v.info', map=river, flags="g") d = grass.parse_key_val(info) xmin = d['west'] xmax = d['east'] ymin = d['south'] ymax = d['north'] outfile.write(" BEGIN SPATIALEXTENT: \n") outfile.write(" Xmin: " + xmin + "\n") outfile.write(" Xmax: " + xmax + "\n") outfile.write(" Ymin: " + ymin + "\n") outfile.write(" Ymax: " + ymax + "\n") outfile.write(" END SPATIALEXTENT: \n") # write out how many reaches and cross sections info = grass.read_command('v.info', map=river, flags="t") d = grass.parse_key_val(info) num_reaches = d['lines'] outfile.write(" NUMBER OF REACHES: " + num_reaches + "\n") info = grass.read_command('v.info', map=xsections, flags="t") d = grass.parse_key_val(info) num_xsects = d['lines'] outfile.write(" NUMBER OF CROSS-SECTIONS: " + num_xsects + "\n") outfile.write("END HEADER:\n\n")
def map_exists(name, element, env, mapset=None): """Check is map is present in the mapset given in the environment :param name: name of the map :param element: data type ('raster', 'raster_3d', and 'vector') :param env environment created by function gscript.create_environment """ if not mapset: mapset = gscript.run_command("g.mapset", flags="p", env=env).strip() # change type to element used by find file if element == "raster": element = "cell" elif element == "raster_3d": element = "grid3" # g.findfile returns non-zero when file was not found # se we ignore return code and just focus on stdout process = gscript.start_command( "g.findfile", flags="n", element=element, file=name, mapset=mapset, stdout=gscript.PIPE, stderr=gscript.PIPE, env=env, ) output, errors = process.communicate() info = gscript.parse_key_val(output, sep="=") # file is the key questioned in grass.script.core find_file() # return code should be equivalent to checking the output if info["file"]: return True else: return False
def setCPRJ(map): center = [] info_region = grass.read_command('g.region', flags='ael', rast='%s' % (map)) dict_region = grass.parse_key_val(info_region, ':') lon = dict_region['center longitude'] lat = dict_region['center latitude'] lon = str(lon) lat = str(lat) lon = lon.replace(':', " ") lat = lat.replace(':', " ") if lat[-1] == 'N': signlat = 1 if lat[-1] == 'S': signlat = -1 if lon[-1] == 'E': signlon = 1 if lon[-1] == 'W': signlon = -1 lat = lat[:-1] lon = lon[:-1] lat = [float(i) for i in lat.split()] lon = [float(i) for i in lon.split()] lat = (lat[0] + (lat[1] / 60) + lat[2] / 3600) * float(signlat) lon = (lon[0] + (lon[1] / 60) + lon[2] / 3600) * float(signlon) ns = float(dict_region['north-south extent']) we = float(dict_region['east-west extent']) distance = (ns + we) / 2 center.append(lat) center.append(lon) center.append(distance) return center
def parseRast(self): '''Read metadata from r.info #self.md_grass dictionary of metadata from v.info #self.md_abstract string created by merge information from 'description' and 'source' ''' map=str(self.map).partition('@')[0] rinfo = Module('r.info', map, flags='gre', quiet=True, stdout_=PIPE) self.md_grass = parse_key_val(rinfo.outputs.stdout) # convert date to ISO format self._createISODate('date') # create abstract if self.md_grass['description'] != '""': self.md_abstract = self.md_grass['description'] + '; ' if self.md_grass['source1'] != '""': self.md_abstract += self.md_grass['source1'] + '; ' if self.md_grass['source2'] != '""': self.md_abstract += self.md_grass['source2'] + '; ' self.md_abstract += 'Total cells: ' + self.md_grass['cells'] + '; ' self.md_abstract += 'A range of values: min: ' + \ self.md_grass['min'] + ' max: ' + self.md_grass['max'] self.md_abstract.translate("""&<>"'""")
def _getRegionParams(self,opt_region): """!Get region parameters from region specified or active default region @return region_params as a dictionary """ self._debug("_getRegionParameters", "started") if opt_region: reg_spl = opt_region.strip().split('@', 1) reg_mapset = '.' if len(reg_spl) > 1: reg_mapset = reg_spl[1] if not gscript.find_file(name = reg_spl[0], element = 'windows', mapset = reg_mapset)['name']: gscript.fatal(_("Region <%s> not found") % opt_region) if opt_region: s = gscript.read_command('g.region', quiet = True, flags = 'ug', region = opt_region) region_params = gscript.parse_key_val(s, val_type = float) gscript.verbose("Using region parameters for region %s" %opt_region) else: region_params = gscript.region() gscript.verbose("Using current grass region") self._debug("_getRegionParameters", "finished") return region_params
def parse_alias(alias_file): """Parse alias file if provided""" if alias_file: if not os.access(alias_file, os.R_OK): gscript.fatal( _("Alias file <{}> not found or not readable".format( alias_file))) with open(alias_file, "r") as a_f: alias_dict = gscript.parse_key_val(a_f.read(), sep=",") else: alias_dict = None if alias_dict: for alias, full_name in alias_dict.items(): # Skip invaid lines if not alias or not full_name: continue # Check if environmental parameter map(s) exist if "@" in full_name: raster, mapset = full_name.split("@") else: raster, mapset = full_name, "" raster_map = RasterRow(full_name) # raster, mapset) mapset = "." if not mapset else mapset if not raster_map.exist(): gscript.fatal( _("Could not find environmental parameter raster map <{}> in mapset <{}>." .format(raster, mapset))) return alias_dict
def setCPRJ(map): center = [] info_region = grass.read_command('g.region', flags = 'ael', rast = '%s' % (map)) dict_region = grass.parse_key_val(info_region, ':') lon = dict_region['center longitude'] lat = dict_region['center latitude'] lon = str(lon) lat = str(lat) lon = lon.replace(':', " ") lat = lat.replace(':', " ") if lat[-1] == 'N': signlat = 1 if lat[-1] == 'S': signlat = -1 if lon[-1] == 'E': signlon = 1 if lon[-1] == 'W': signlon = -1 lat = lat[:-1] lon = lon[:-1] lat = [float(i) for i in lat.split()] lon = [float(i) for i in lon.split()] lat = (lat[0] + (lat[1] / 60) + lat[2] / 3600) * float(signlat) lon = (lon[0] + (lon[1] / 60) + lon[2] / 3600) * float(signlon) ns = float(dict_region['north-south extent']) we = float(dict_region['east-west extent']) distance = (ns + we) / 2 center.append(lat) center.append(lon) center.append(distance) return center
def map_exists(element, name, mapset): """Check is map is present in the mapset given in the environment :param name: name of the map :param element: data type ('raster', 'raster_3d', and 'vector') """ # change type to element used by find file if element == 'raster': element = 'cell' elif element == 'raster_3d': element = 'grid3' # g.findfile returns non-zero when file was not found # se we ignore return code and just focus on stdout process = gscript.start_command( 'g.findfile', flags='n', element=element, file=name, mapset=mapset, stdout=gscript.PIPE, stderr=gscript.PIPE) output, errors = process.communicate() info = gscript.parse_key_val(output, sep='=') # file is the key questioned in grass.script.core find_file() # return code should be equivalent to checking the output if info['file']: return True else: return False
def _getRegionParams(self,opt_region): """!Get region parameters from region specified or active default region @return region_params as a dictionary """ self._debug("_getRegionParameters", "started") if opt_region: reg_spl = opt_region.strip().split('@', 1) reg_mapset = '.' if len(reg_spl) > 1: reg_mapset = reg_spl[1] if not grass.find_file(name = reg_spl[0], element = 'windows', mapset = reg_mapset)['name']: grass.fatal(_("Region <%s> not found") % opt_region) if opt_region: s = grass.read_command('g.region', quiet = True, flags = 'ug', region = opt_region) region_params = grass.parse_key_val(s, val_type = float) grass.verbose("Using region parameters for region %s" % opt_region) else: region_params = grass.region() grass.verbose("Using current grass region") self._debug("_getRegionParameters", "finished") return region_params
def parseVect(self): '''Read metadata from v.info @var self.md_grass dictionary of metadata from v.info ''' # parse md from v.info flags=-g -e -t vinfo = Module('v.info', self.map, flags='get', quiet=True, stdout_=PIPE) self.md_grass = parse_key_val(vinfo.outputs.stdout) # parse md from v.info flag=h (history of map in grass) rinfo_h = Module('v.info', self.map, flags='h', quiet=True, stdout_=PIPE) md_h_grass = rinfo_h.outputs.stdout buf = StringIO.StringIO(md_h_grass) line = buf.readline().splitlines() while str(line) != '[]': if str(line[0]).strip() != "": self.md_vinfo_h += line[0] + '\n' line = buf.readline().splitlines() buf.close() # convert GRASS parsed date format to iso format # if date format is diverse from standard, use them self._createISODate('source_date')
def main(): check_date(options['start']) check_date(options['end']) # be silent os.environ['GRASS_VERBOSE'] = '0' try: Module('t.rast.series', input=options['input'], output=output, method='average', where="start_time > '{start}' and start_time < '{end}'".format( start=options['start'], end=options['end'] )) except CalledModuleError: gs.fatal('Unable to compute statistics') ret = Module('r.univar', flags='g', map=output, stdout_=PIPE ) stats = gs.parse_key_val(ret.outputs.stdout) print('Min: {0:.1f}'.format(float(stats['min']))) print('Max: {0:.1f}'.format(float(stats['max']))) print('Mean: {0:.1f}'.format(float(stats['mean'])))
def parseTemporal(self): env = grass.gisenv() mapset = env['MAPSET'] self.map = "%s@%s" % (self.map, mapset) tinfo = Module('t.info', self.map, flags='g', type=self.type, stdout_=PIPE) self.md_grass = parse_key_val(tinfo.outputs.stdout) tinfoHist = Module('t.info', input=self.map, quiet=True, flags='h', type=self.type, stdout_=PIPE) md_h_grass = tinfoHist.outputs.stdout buf = StringIO.StringIO(md_h_grass) line = buf.readline().splitlines() while line: if str(line[0]).strip() != "": self.md_vinfo_h += line[0] + '\n' line = buf.readline().splitlines() buf.close()
def parseRast(self): """Read metadata from r.info #self.md_grass dictionary of metadata from v.info #self.md_abstract string created by merge information from 'description' and 'source' """ map = str(self.map).partition("@")[0] rinfo = Module("r.info", map, flags="gre", quiet=True, stdout_=PIPE) self.md_grass = parse_key_val(rinfo.outputs.stdout) # convert date to ISO format self._createISODate("date") # create abstract if self.md_grass["description"] != '""': self.md_abstract = self.md_grass["description"] + "; " if self.md_grass["source1"] != '""': self.md_abstract += self.md_grass["source1"] + "; " if self.md_grass["source2"] != '""': self.md_abstract += self.md_grass["source2"] + "; " self.md_abstract += "Total cells: " + self.md_grass["cells"] + "; " self.md_abstract += ( "A range of values: min: " + self.md_grass["min"] + " max: " + self.md_grass["max"] ) self.md_abstract.translate("""&<>"'""")
def parseTemporal(self): env = grass.gisenv() mapset = env["MAPSET"] if self.map.find("@") < 0: self.map = "{}@{}".format(self.map, mapset) tinfo = Module("t.info", self.map, flags="g", type=self.type, stdout_=PIPE) self.md_grass = parse_key_val(tinfo.outputs.stdout) tinfoHist = Module( "t.info", input=self.map, quiet=True, flags="h", type=self.type, stdout_=PIPE, ) md_h_grass = tinfoHist.outputs.stdout buf = io.StringIO(md_h_grass) line = buf.readline().splitlines() while line: if str(line[0]).strip() != "": self.md_vinfo_h += line[0] + "\n" line = buf.readline().splitlines() buf.close()
def map_exists(name, element, mapset=None, env=None): """Check is map is present in the mapset given in the environment :param name: Name of the map :param element: Data type ('raster', 'raster_3d', and 'vector') :param env: Environment created by function grass.script.create_environment :param mapset: Mapset name, "." for current mapset only, None for all mapsets in the search path """ # change type to element used by find file if element == "raster": element = "cell" elif element == "raster_3d": element = "grid3" # g.findfile returns non-zero when file was not found # se we ignore return code and just focus on stdout process = gs.start_command( "g.findfile", flags="n", element=element, file=name, mapset=mapset, stdout=gs.PIPE, stderr=gs.PIPE, env=env, ) output, unused_errors = process.communicate() info = gs.parse_key_val(output, sep="=") # file is the key questioned in grass.script.core find_file() # return code should be equivalent to checking the output if info["file"]: return True return False
def get_aoi_box(vector=None): args = {} if vector: args['vector'] = vector # are we in LatLong location? s = gs.read_command("g.proj", flags='j') kv = gs.parse_key_val(s) if '+proj' not in kv: gs.fatal( 'Unable to get AOI bounding box: unprojected location not supported' ) if kv['+proj'] != 'longlat': info = gs.parse_command('g.region', flags='uplg', **args) return 'POLYGON(({nw_lon} {nw_lat}, {ne_lon} {ne_lat}, {se_lon} {se_lat}, {sw_lon} {sw_lat}, {nw_lon} {nw_lat}))'.format( nw_lat=info['nw_lat'], nw_lon=info['nw_long'], ne_lat=info['ne_lat'], ne_lon=info['ne_long'], sw_lat=info['sw_lat'], sw_lon=info['sw_long'], se_lat=info['se_lat'], se_lon=info['se_long']) else: info = gs.parse_command('g.region', flags='upg', **args) return 'POLYGON(({nw_lon} {nw_lat}, {ne_lon} {ne_lat}, {se_lon} {se_lat}, {sw_lon} {sw_lat}, {nw_lon} {nw_lat}))'.format( nw_lat=info['n'], nw_lon=info['w'], ne_lat=info['n'], ne_lon=info['e'], sw_lat=info['s'], sw_lon=info['w'], se_lat=info['s'], se_lon=info['e'])
def _draw3dFigure(self): """Draws 3d view (spatio-temporal extents). Only for matplotlib versions >= 1.0.0. Earlier versions cannot draw time ticks and alpha and it has a slightly different API. """ self.axes3d.clear() self.axes3d.grid(False) # self.axes3d.grid(True) if self.temporalType == 'absolute': convert = mdates.date2num else: convert = lambda x: x colors = cycle(COLORS) plots = [] for name in self.datasets: name = name[0] + '@' + name[1] startZ = convert(self.timeData[name]['start_datetime']) mapType = self.timeData[name]['temporalMapType'] if mapType == 'interval': dZ = convert(self.timeData[name]['end_datetime']) - startZ else: dZ = [0] * len(startZ) startX = self.timeData[name]['west'] dX = self.timeData[name]['east'] - np.array(startX) startY = self.timeData[name]['south'] dY = self.timeData[name]['north'] - np.array(startY) color = next(colors) plots.append( self.axes3d.bar3d(startX, startY, startZ, dX, dY, dZ, color=color, alpha=ALPHA)) params = grass.read_command('g.proj', flags='g') params = grass.parse_key_val(params) if 'unit' in params: self.axes3d.set_xlabel(_("X [%s]") % params['unit']) self.axes3d.set_ylabel(_("Y [%s]") % params['unit']) else: self.axes3d.set_xlabel(_("X")) self.axes3d.set_ylabel(_("Y")) if self.temporalType == 'absolute': if check_version(1, 1, 0): self.axes3d.zaxis_date() self.axes3d.set_zlabel(_('Time')) self.axes3d.mouse_init() self.canvas.draw()
def get_topology(self,map): vinfo = Module('v.info', self.map, flags='t', quiet=True, stdout_=PIPE) features = parse_key_val(vinfo.outputs.stdout)
def projinfo(): units = grass.read_command("g.proj", flags='p') units = units.replace('-','') units = grass.parse_key_val(units, ':') units_key = units.keys() for i in units_key : key_value = str(units[i]).strip() units[i] = key_value return units
def projinfo(): units = grass.read_command("g.proj", flags='p') units = units.replace('-', '') units = grass.parse_key_val(units, ':') units_key = units.keys() for i in units_key: key_value = str(units[i]).strip() units[i] = key_value return units
def _initializeParameters(self, options, flags): self._debug("_initialize_parameters", "started") # initialization of module parameters (options, flags) self.o_url = options['url'].strip() + "?" self.o_layers = options['layers'].strip() self.o_output = options['output'] self.o_wds_version = options['wfs_version'] self.projection_name = "SRSNAME" self.o_wfs_version = options['wfs_version'] self.o_urlparams = options['urlparams'].strip() self.o_srs = int(options['srs']) if self.o_srs <= 0: grass.fatal(_("Invalid EPSG code %d") % self.o_srs) try: self.o_maximum_features = int(options['maximum_features']) if int(options['maximum_features']) < 1: grass.fatal( _('Invalid maximum number of features (must be >1)')) except ValueError: self.o_maximum_features = None # read projection info self.proj_location = grass.read_command('g.proj', flags='jf').rstrip('\n') self.proj_srs = grass.read_command('g.proj', flags='jf', epsg=str(self.o_srs)).rstrip('\n') if not self.proj_srs or not self.proj_location: grass.fatal(_("Unable to get projection info")) # set region self.o_region = options['region'] if self.o_region: if not grass.find_file( name=self.o_region, element='windows', mapset='.')['name']: grass.fatal(_("Region <%s> not found") % self.o_region) if self.o_region: s = grass.read_command('g.region', quiet=True, flags='ug', region=self.o_region) self.region = grass.parse_key_val(s, val_type=float) else: self.region = grass.region() self.ogr_drv_format = "ESRI Shapefile" self._debug("_initialize_parameters", "finished")
def _initializeParameters(self, options, flags): self._debug("_initialize_parameters", "started") # initialization of module parameters (options, flags) self.o_url = options["url"].strip() + "?" self.o_layers = options["layers"].strip() self.o_output = options["output"] self.o_wds_version = options["wfs_version"] self.projection_name = "SRSNAME" self.o_wfs_version = options["wfs_version"] self.o_urlparams = options["urlparams"].strip() self.o_srs = int(options["srs"]) if self.o_srs <= 0: grass.fatal(_("Invalid EPSG code %d") % self.o_srs) try: self.o_maximum_features = int(options["maximum_features"]) if int(options["maximum_features"]) < 1: grass.fatal(_("Invalid maximum number of features (must be >1)")) except ValueError: self.o_maximum_features = None # read projection info self.proj_location = grass.read_command("g.proj", flags="jf").rstrip("\n") self.proj_srs = grass.read_command( "g.proj", flags="jf", epsg=str(self.o_srs) ).rstrip("\n") if not self.proj_srs or not self.proj_location: grass.fatal(_("Unable to get projection info")) # set region self.o_region = options["region"] if self.o_region: if not grass.find_file(name=self.o_region, element="windows", mapset=".")[ "name" ]: grass.fatal(_("Region <%s> not found") % self.o_region) if self.o_region: s = grass.read_command( "g.region", quiet=True, flags="ug", region=self.o_region ) self.region = grass.parse_key_val(s, val_type=float) else: self.region = grass.region() self.ogr_drv_format = "ESRI Shapefile" self._debug("_initialize_parameters", "finished")
def get_percentile(map, percentiles): # todo: generalize for any list length val1 = percentiles[0] val2 = percentiles[1] values = '%s,%s' % (val1, val2) s = grass.read_command('r.univar', flags='ge', map=map, percentile=values) kv = grass.parse_key_val(s) # cleanse to match what the key name will become val_str1 = ('percentile_%.15g' % float(val1)).replace('.', '_') val_str2 = ('percentile_%.15g' % float(val2)).replace('.', '_') return (float(kv[val_str1]), float(kv[val_str2]))
def get_percentile(map, percentiles): # todo: generalize for any list length val1 = percentiles[0] val2 = percentiles[1] values = '%s,%s' % (val1, val2) s = grass.read_command('r.univar', flags = 'ge', map = map, percentile = values) kv = grass.parse_key_val(s) # cleanse to match what the key name will become val_str1 = ('percentile_%.15g' % float(val1)).replace('.','_') val_str2 = ('percentile_%.15g' % float(val2)).replace('.','_') return (float(kv[val_str1]), float(kv[val_str2]))
def main(): river = options['river'] stations = options['stations'] xsections = options['xsections'] elev = options['elevation'] output = options['output'] res = options['resolution'] # do input maps exist in CURRENT mapset? mapset = grass.gisenv()['MAPSET'] if not grass.find_file(river, element='vector', mapset=mapset)['file']: grass.fatal(_("Vector map <%s> not found in current mapset") % river) if not grass.find_file(stations, element='vector', mapset=mapset)['file']: grass.fatal( _("Vector map <%s> not found in current mapset") % stations) if not grass.find_file(xsections, element='vector', mapset=mapset)['file']: grass.fatal( _("Vector map <%s> not found in current mapset") % xsections) if not grass.find_file(elev, element='raster', mapset=mapset)['file']: grass.fatal(_("Raster map <%s> not found in current mapset") % elev) if not res: # No resolution given, use the resolution of the elevation raster info = grass.read_command('r.info', map=elev, flags="g") d = grass.parse_key_val(info) res = d['ewres'] # Assume ewres=nsres # Be sure region is set to dtm layer grass.run_command('g.region', raster=elev, res=res, quiet=True, flags="a") # Prepare output file if ".sdf" == output.lower()[-4]: sdf = output else: sdf = output + ".sdf" sdf_file = open(sdf, 'w') # The work starts here output_headers(river, xsections, sdf_file) grass.message("Headers written to %s" % sdf) output_centerline(river, stations, elev, sdf_file) grass.message("River network written to %s" % sdf) output_xsections(xsections, sdf_file, elev, res, river) grass.message("Cross sections written to %s" % sdf) sdf_file.close() # Replace newline chars with CR-NL for windows? replace_nl = True if flags['u']: replace_nl = False cleanup(sdf, replace_nl) return 0
def _draw3dFigure(self): """Draws 3d view (spatio-temporal extents). Only for matplotlib versions >= 1.0.0. Earlier versions cannot draw time ticks and alpha and it has a slightly different API. """ self.axes3d.clear() self.axes3d.grid(False) # self.axes3d.grid(True) if self.temporalType == 'absolute': convert = mdates.date2num else: convert = lambda x: x colors = cycle(COLORS) plots = [] for name in self.datasets: name = name[0] + '@' + name[1] startZ = convert(self.timeData[name]['start_datetime']) mapType = self.timeData[name]['temporalMapType'] if mapType == 'interval': dZ = convert(self.timeData[name]['end_datetime']) - startZ else: dZ = [0] * len(startZ) startX = self.timeData[name]['west'] dX = self.timeData[name]['east'] - np.array(startX) startY = self.timeData[name]['south'] dY = self.timeData[name]['north'] - np.array(startY) color = colors.next() plots.append(self.axes3d.bar3d(startX, startY, startZ, dX, dY, dZ, color=color, alpha=ALPHA)) params = grass.read_command('g.proj', flags='g') params = grass.parse_key_val(params) if 'unit' in params: self.axes3d.set_xlabel(_("X [%s]") % params['unit']) self.axes3d.set_ylabel(_("Y [%s]") % params['unit']) else: self.axes3d.set_xlabel(_("X")) self.axes3d.set_ylabel(_("Y")) if self.temporalType == 'absolute': if check_version(1, 1, 0): self.axes3d.zaxis_date() self.axes3d.set_zlabel(_('Time')) self.axes3d.mouse_init() self.canvas.draw()
def create_xsection_intersects(invect, outvect): """ Run v.clean on the cross section vector to find all intersection points using the error=... option with tool=break to create a point vector """ proc=os.getpid() dummy="dummy_out_" + str(proc) grass.run_command('v.clean', input=invect, output=dummy, error=outvect, tool="break", quiet=True, overwrite=True) info = grass.read_command('v.info', map=outvect, flags="t") d=grass.parse_key_val(info) grass.run_command('g.remove',type='vect', name=dummy, flags="f") return int(d['points'])
def general(pnt, dem, treesmap, buildmap, treesheigh, buildheigh, obsabselev): #raster points Module("v.to.rast", input=pnt, output="xxrastpnt", type="point", use="val", overwrite=True, quiet=True) #altering DEM in case there are buldings and trees map (to obtain a sort of DSM) and in case observer is not flying the dem is kept to the ground level at observer positions if treesmap and buildmap: Module("v.to.rast", input=treesmap, output=treesmap, use="attr", attribute_column=treesheigh, overwrite=True, quiet=True) Module("v.to.rast", input=buildmap, output=buildmap, use="attr", attribute_column=buildheigh, overwrite=True, quiet=True) Module("r.mapcalc", expression="{A} = if(isnull({B}),{C},{B})".format(A="zztreesbuildingmap",B=buildmap,C=treesmap), overwrite=True, quiet=True) Module("r.mapcalc", expression="{B} = if(isnull({A}),{C},{C}+{A})".format(A="zztreesbuildingmap", B="zz"+dem+"_modified_full", C=dem), overwrite=True, quiet=True) Module("r.mapcalc", expression="{B} = if(isnull({A}),{D},{C})".format(A="xxrastpnt", B="zz"+dem+"_modified",C=dem,D="zz"+dem+"_modified_full"), overwrite=True, quiet=True) if obsabselev: dem="zz"+dem+"_modified_full" else: dem="zz"+dem+"_modified" elif treesmap and not buildmap: Module("v.to.rast", input=treesmap, output=treesmap, use="attr", attribute_column=treesheigh, overwrite=True, quiet=True) Module("r.mapcalc", expression="{B} = if(isnull({A}),{C},{C}+{A})".format(A=treesmap, B="zz"+dem+"_modified_full", C=dem), overwrite=True, quiet=True) Module("r.mapcalc", expression="{B} = if(isnull({A}),{D},{C})".format(A="xxrastpnt", B="zz"+dem+"_modified",C=dem,D="zz"+dem+"_modified_full"), overwrite=True, quiet=True) if obsabselev: dem="zz"+dem+"_modified_full" else: dem="zz"+dem+"_modified" elif buildmap and not treesmap: Module("v.to.rast", input=buildmap, output=buildmap, use="attr", attribute_column=buildheigh, overwrite=True, quiet=True) Module("r.mapcalc", expression="{B} = if(isnull({A}),{C},{C}+{A})".format(A=buildmap, B="zz"+dem+"_modified_full", C=dem), overwrite=True, quiet=True) Module("r.mapcalc", expression="{B} = if(isnull({A}),{D},{C})".format(A="xxrastpnt", B="zz"+dem+"_modified",C=dem,D="zz"+dem+"_modified_full"), overwrite=True, quiet=True) if obsabselev: dem="zz"+dem+"_modified_full" else: dem="zz"+dem+"_modified" #preparing the maps of the orientation of the DEM Module("r.slope.aspect", elevation=dem, slope="zzslope", aspect="zzaspect", overwrite=True, quiet=True) #evaluation of the azimuth layer Module("r.mapcalc", expression="zzazimuth = (450-zzaspect) - int( (450-zzaspect) / 360) * 360", overwrite=True, quiet=True) #evaluation of the layer of the vertical component of the versor perpendicular to the terrain slope Module("r.mapcalc", expression="zzc_dem = cos(zzslope)", overwrite=True, quiet=True) #evaluation of the layer of the north component of the versor perpendicular to the terrain slope Module("r.mapcalc", expression="zzb_dem = sin(zzslope)*cos(zzazimuth)", overwrite=True, quiet=True) #evaluation of the layer of the east component of the versor perpendicular to the terrain slope Module("r.mapcalc", expression="zza_dem = sin(zzslope)*sin(zzazimuth)", overwrite=True, quiet=True) #creating a list of the categories of the available points in the input layer ret = Module('v.info', flags='t', map=pnt, stdout_=PIPE) stats = parse_key_val(ret.outputs.stdout) npnt=stats['points'] ctg2=Module("v.category", flags="g", input=pnt, option="print", type="point", stdout_=PIPE) ctg=ctg2.outputs.stdout.splitlines() #exporting variables for other functions general.ctg=ctg general.npnt=npnt general.dem=dem
def main(): river = options['river'] stations = options['stations'] xsections = options['xsections'] elev = options['elevation'] output = options['output'] res = options['resolution'] # do input maps exist in CURRENT mapset? mapset = grass.gisenv()['MAPSET'] if not grass.find_file(river, element = 'vector', mapset = mapset)['file']: grass.fatal(_("Vector map <%s> not found in current mapset") % river) if not grass.find_file(stations, element = 'vector', mapset = mapset)['file']: grass.fatal(_("Vector map <%s> not found in current mapset") % stations) if not grass.find_file(xsections, element = 'vector', mapset = mapset)['file']: grass.fatal(_("Vector map <%s> not found in current mapset") % xsections) if not grass.find_file(elev, element = 'raster', mapset = mapset)['file']: grass.fatal(_("Raster map <%s> not found in current mapset") % elev) if not res: # No resolution given, use the resolution of the elevation raster info = grass.read_command('r.info', map=elev, flags="g") d=grass.parse_key_val(info) res=d['ewres'] # Assume ewres=nsres # Be sure region is set to dtm layer grass.run_command('g.region', raster=elev, res=res, quiet=True, flags="a") # Prepare output file if ".sdf" == output.lower()[-4]: sdf=output else: sdf=output+".sdf" sdf_file=open(sdf, 'w') # The work starts here output_headers(river, xsections, sdf_file) grass.message("Headers written to %s" % sdf) output_centerline(river, stations, elev, sdf_file) grass.message("River network written to %s" % sdf) output_xsections(xsections, sdf_file, elev, res, river) grass.message("Cross sections written to %s" % sdf) sdf_file.close() # Replace newline chars with CR-NL for windows? replace_nl = True if flags['u']: replace_nl = False cleanup(sdf, replace_nl) return 0
def get_aoi(vector=None): args = {} if vector: args["input"] = vector if gs.vector_info_topo(vector)["areas"] <= 0: gs.fatal(_("No areas found in AOI map <{}>...").format(vector)) elif gs.vector_info_topo(vector)["areas"] > 1: gs.warning( _("More than one area found in AOI map <{}>. \ Using only the first area...").format(vector)) # are we in LatLong location? s = gs.read_command("g.proj", flags="j") kv = gs.parse_key_val(s) if "+proj" not in kv: gs.fatal(_("Unable to get AOI: unprojected location not supported")) geom_dict = gs.parse_command("v.out.ascii", format="wkt", **args) num_vertices = len(str(geom_dict.keys()).split(",")) geom = [key for key in geom_dict][0] if kv["+proj"] != "longlat": gs.message( _("Generating WKT from AOI map ({} vertices)...").format( num_vertices)) if num_vertices > 500: gs.fatal( _("AOI map has too many vertices to be sent via HTTP GET (sentinelsat). \ Use 'v.generalize' to simplify the boundaries")) coords = geom.replace("POLYGON((", "").replace("))", "").split(", ") poly = "POLYGON((" poly_coords = [] for coord in coords: coord_latlon = gs.parse_command("m.proj", coordinates=coord.replace( " ", ","), flags="od") for key in coord_latlon: poly_coords.append((" ").join(key.split("|")[0:2])) poly += (", ").join(poly_coords) + "))" # Note: poly must be < 2000 chars incl. sentinelsat request (see RFC 2616 HTTP/1.1) if len(poly) > 1850: gs.fatal( _("AOI map has too many vertices to be sent via HTTP GET (sentinelsat). \ Use 'v.generalize' to simplify the boundaries")) else: gs.message(_("Sending WKT from AOI map to ESA...")) return poly else: return geom
def get_aoi(vector=None): args = {} if vector: args['input'] = vector if gs.vector_info_topo(vector)['areas'] <= 0: gs.fatal(_("No areas found in AOI map <{}>...").format(vector)) elif gs.vector_info_topo(vector)['areas'] > 1: gs.warning( _("More than one area found in AOI map <{}>. \ Using only the first area...").format(vector)) # are we in LatLong location? s = gs.read_command("g.proj", flags='j') kv = gs.parse_key_val(s) if '+proj' not in kv: gs.fatal('Unable to get AOI: unprojected location not supported') geom_dict = gs.parse_command('v.out.ascii', format='wkt', **args) num_vertices = len(str(geom_dict.keys()).split(',')) geom = [key for key in geom_dict][0] if kv['+proj'] != 'longlat': gs.message( _("Generating WKT from AOI map ({} vertices)...").format( num_vertices)) if num_vertices > 500: gs.fatal( _("AOI map has too many vertices to be sent via HTTP GET (sentinelsat). \ Use 'v.generalize' to simplify the boundaries")) coords = geom.replace('POLYGON((', '').replace('))', '').split(', ') poly = 'POLYGON((' poly_coords = [] for coord in coords: coord_latlon = gs.parse_command('m.proj', coordinates=coord.replace( ' ', ','), flags='od') for key in coord_latlon: poly_coords.append((' ').join(key.split('|')[0:2])) poly += (', ').join(poly_coords) + '))' # Note: poly must be < 2000 chars incl. sentinelsat request (see RFC 2616 HTTP/1.1) if len(poly) > 1850: gs.fatal( _("AOI map has too many vertices to be sent via HTTP GET (sentinelsat). \ Use 'v.generalize' to simplify the boundaries")) else: gs.message(_("Sending WKT from AOI map to ESA...")) return poly else: return geom
def create_river_network(invect, outvect): """ Prepare the input river network vector by: possibly smoothing the line, and adding several columns to the vector attribute table. THe added columns include start and end points for output to HEC-RAS """ thresh = options['threshold'] layer = options['layer'] if (flags['s']): # Perform smoothing of the input vector grass.run_command('v.generalize', input=invect, output=outvect, _method='snakes', threshold=thresh, overwrite=True, quiet=True) # Add a reach length column to the river vector # First check if column exists columns_exist = grass.vector_columns(outvect, int(layer)).keys() if not "reach_len" in columns_exist: grass.run_command('v.db.addcolumn', map=outvect, columns="reach_len DOUBLE PRECISION", quiet=True) # Also add columns for start and end point of each reach if not "start_x" in columns_exist: grass.run_command('v.db.addcolumn', map=outvect, columns="start_x DOUBLE PRECISION", quiet=True) if not "start_y" in columns_exist: grass.run_command('v.db.addcolumn', map=outvect, columns="start_y DOUBLE PRECISION", quiet=True) if not "start_elev" in columns_exist: grass.run_command('v.db.addcolumn', map=outvect, columns="start_elev DOUBLE PRECISION", quiet=True) if not "end_x" in columns_exist: grass.run_command('v.db.addcolumn', map=outvect, columns="end_x DOUBLE PRECISION", quiet=True) if not "end_y" in columns_exist: grass.run_command('v.db.addcolumn', map=outvect, columns="end_y DOUBLE PRECISION", quiet=True) if not "end_elev" in columns_exist: grass.run_command('v.db.addcolumn', map=outvect, columns="end_elev DOUBLE PRECISION", quiet=True) # Now update those columns grass.run_command('v.to.db',map=outvect, option="length", columns="reach_len", quiet=True) grass.run_command('v.to.db',map=outvect, option="start", columns="start_x,start_y",quiet=True) grass.run_command('v.to.db',map=outvect, option="end", columns="end_x,end_y", quiet=True) d=grass.read_command('v.db.select',map=outvect, separator="=", columns="cat,reach_len", flags="c") # Initialize dict of reach categories with their lengths # Each key in the dictionary is the cat of a river reach # each value is the length of that reach reach_cats=grass.parse_key_val(d, val_type=float) return reach_cats
def GetRegionParams(opt_region): # set region if opt_region: reg_spl = opt_region.strip().split('@', 1) reg_mapset = '.' if len(reg_spl) > 1: reg_mapset = reg_spl[1] if not grass.find_file(name=reg_spl[0], element='windows', mapset=reg_mapset)['name']: grass.fatal(_("Region <%s> not found") % opt_region) if opt_region: s = grass.read_command('g.region', quiet=True, flags='ug', region=opt_region) region_params = grass.parse_key_val(s, val_type=float) else: region_params = grass.region() return region_params
def region(self): # set the computive region reg = grass.read_command("g.region", flags='p') kv = grass.parse_key_val(reg, sep=':') reg_N = float(kv['north']) reg_W = float(kv['west']) reg_S = float(kv['south']) reg_E = float(kv['east']) nsres = float(kv['nsres']) ewres = float(kv['ewres']) # set variables self.cols = int(kv['cols']) self.rows = int(kv['rows']) self.area = (reg_N-reg_S)*(reg_E-reg_W) self.ALG = 'nn' # set the working region for nnbathy (it's cell-center oriented) self.nn_n = reg_N - nsres/2 self.nn_s = reg_S + nsres/2 self.nn_w = reg_W + ewres/2 self.nn_e = reg_E - ewres/2 self.null = "NaN" self.ctype = "double"
def reclass(inf, outf, lim, clump, diag, les): infile = inf outfile = outf lesser = les limit = lim clumped = clump diagonal = diag s = grass.read_command("g.region", flags='p') kv = grass.parse_key_val(s, sep=':') s = kv['projection'].strip().split() if s == '0': grass.fatal(_("xy-locations are not supported")) grass.fatal(_("Need projected data with grids in meters")) if not grass.find_file(infile)['name']: grass.fatal(_("Raster map <%s> not found") % infile) if clumped and diagonal: grass.fatal(_("flags c and d are mutually exclusive")) if clumped: clumpfile = infile else: clumpfile = "%s.clump.%s" % (infile.split('@')[0], outfile) TMPRAST.append(clumpfile) if not grass.overwrite(): if grass.find_file(clumpfile)['name']: grass.fatal(_("Temporary raster map <%s> exists") % clumpfile) if diagonal: grass.message(_("Generating a clumped raster file including " "diagonal neighbors...")) grass.run_command('r.clump', flags='d', input=infile, output=clumpfile) else: grass.message(_("Generating a clumped raster file ...")) grass.run_command('r.clump', input=infile, output=clumpfile) if lesser: grass.message(_("Generating a reclass map with area size less than " "or equal to %f hectares...") % limit) else: grass.message(_("Generating a reclass map with area size greater " "than or equal to %f hectares...") % limit) recfile = outfile + '.recl' TMPRAST.append(recfile) sflags = 'aln' if grass.raster_info(infile)['datatype'] in ('FCELL', 'DCELL'): sflags += 'i' p1 = grass.pipe_command('r.stats', flags=sflags, input=(clumpfile, infile), sep=';') p2 = grass.feed_command('r.reclass', input=clumpfile, output=recfile, rules='-') rules = '' for line in p1.stdout: f = line.rstrip(os.linesep).split(';') if len(f) < 5: continue hectares = float(f[4]) * 0.0001 if lesser: test = hectares <= limit else: test = hectares >= limit if test: rules += "%s = %s %s\n" % (f[0], f[2], f[3]) if rules: p2.stdin.write(rules) p1.wait() p2.stdin.close() p2.wait() if p2.returncode != 0: if lesser: grass.fatal(_("No areas of size less than or equal to %f " "hectares found.") % limit) else: grass.fatal(_("No areas of size greater than or equal to %f " "hectares found.") % limit) grass.mapcalc("$outfile = $recfile", outfile=outfile, recfile=recfile)
def main(): infile = options['input'] outfile = options['output'] #### setup temporary file tmpfile = grass.tempfile() #are we in LatLong location? s = grass.read_command("g.proj", flags='j') kv = grass.parse_key_val(s) if kv['+proj'] != 'longlat': grass.fatal(_("This module only operates in LatLong/WGS84 locations")) # input test if not os.access(infile, os.R_OK): grass.fatal(_("File <%s> not found") % infile) # DBF doesn't support lengthy text fields kv = grass.db_connection() dbfdriver = kv['driver'] == 'dbf' if dbfdriver: grass.warning(_("Since DBF driver is used, the content of the 'alternatenames' column might be cut with respect to the original Geonames.org column content")) #let's go #change TAB to vertical bar num_places = 0 inf = file(infile) outf = file(tmpfile, 'wb') for line in inf: fields = line.rstrip('\r\n').split('\t') line2 = '|'.join(fields) + '\n' outf.write(line2) num_places += 1 outf.close() inf.close() grass.message(_("Converted %d place names.") % num_places) # pump data into GRASS: # http://download.geonames.org/export/dump/readme.txt # The main 'geoname' table has the following fields : # --------------------------------------------------- # geonameid : integer id of record in geonames database # name : name of geographical point (utf8) varchar(200) # asciiname : name of geographical point in plain ascii characters, varchar(200) # alternatenames : alternatenames, comma separated varchar(4000) # latitude : latitude in decimal degrees (wgs84) # longitude : longitude in decimal degrees (wgs84) # feature class : see http://www.geonames.org/export/codes.html, char(1) # feature code : see http://www.geonames.org/export/codes.html, varchar(10) # country code : ISO-3166 2-letter country code, 2 characters # cc2 : alternate country codes, comma separated, ISO-3166 2-letter country code, 60 characters # admin1 code : fipscode (subject to change to iso code), isocode for the us and ch, see file admin1Codes.txt for display names of this code; varchar(20) # admin2 code : code for the second administrative division, a county in the US, see file admin2Codes.txt; varchar(80) # admin3 code : code for third level administrative division, varchar(20) # admin4 code : code for fourth level administrative division, varchar(20) # population : integer # elevation : in meters, integer # gtopo30 : average elevation of 30'x30' (ca 900mx900m) area in meters, integer # timezone : the timezone id (see file http://download.geonames.org/export/dump/timeZones.txt) # modification date : date of last modification in yyyy-MM-dd format # geonameid|name|asciiname|alternatenames|latitude|longitude|featureclass|featurecode|countrycode|cc2|admin1code|admin2code|admin3code|admin4code|population|elevation|gtopo30|timezone|modificationdate # TODO: elevation seems to contain spurious char stuff :( # debug: # head -n 3 ${TMPFILE}.csv # use different column names limited to 10 chars for dbf if dbfdriver: columns = ['geonameid integer', 'name varchar(200)', 'asciiname varchar(200)', 'altname varchar(4000)', 'latitude double precision', 'longitude double precision', 'featrclass varchar(1)', 'featrcode varchar(10)', 'cntrycode varchar(2)', 'cc2 varchar(60)', 'admin1code varchar(20)', 'admin2code varchar(20)', 'admin3code varchar(20)', 'admin4code varchar(20)', 'population integer', 'elevation varchar(5)', 'gtopo30 integer', 'timezone varchar(50)', 'mod_date date'] else: columns = ['geonameid integer', 'name varchar(200)', 'asciiname varchar(200)', 'alternatename varchar(4000)', 'latitude double precision', 'longitude double precision', 'featureclass varchar(1)', 'featurecode varchar(10)', 'countrycode varchar(2)', 'cc2 varchar(60)', 'admin1code varchar(20)', 'admin2code varchar(20)', 'admin3code varchar(20)', 'admin4code varchar(20)', 'population integer', 'elevation varchar(5)', 'gtopo30 integer', 'timezone varchar(50)', 'modification date'] grass.run_command('v.in.ascii', cat = 0, x = 6, y = 5, fs = '|', input = tmpfile, output = outfile, columns = columns) grass.try_remove(tmpfile) # write cmd history: grass.vector_history(outfile)
def main(): global GISDBASE #------------------------------------------------- #------- GETTING PARAMETERS ---------------------- #------ because of smalltalk migration, variable names #------ with mixed capitals are kept hRes=float(ensureopt('hres',10)) vRes=float(ensureopt('vres',1)) pointDist=float(ensureopt('pointdist',20)) endHeight=float(ensureopt('endheight',100)) depth=float(ensureopt('depth',5)) startHeight=float(ensureopt('startheight',1000)) basedtm=ensureopt('dtm',"...") limitRunLayers=int(ensureopt('limitrunlayers',2000)) chWidth=float(ensureopt('bottomwidth',100)) chMaxWidth=float(ensureopt('maxwidth',300)) # forced calculation sideRatio=float(chMaxWidth-chWidth)/2/depth reliefRes=float(ensureopt('dtmres',10)) linevector=ensureopt('linevector','...') #mandatory so given for sure workPath=TMPDIR # for os.path.join(,) # In smalltalk original startCover was the line vector name # it will be better this way (basename): if len(options['basename'])<1: startCover = linevector.split("@")[0] # str(os.getpid())+"_r_trench_result" else: startCover = options['basename'] #------------------------------------------------- #--------------END OF GETTING PARAMS-------------- #------------------------------------------------- #------------------------------------------------- #------------------------------------------------- grass.run_command("g.region", vector=linevector, overwrite=True) grass.run_command("g.region",n="n+1000",w="w-1000",e="e+1000",s="s-1000", res=hRes, overwrite=True) grass.run_command("g.region", save='l_work_' + startCover +'.region', overwrite=True) grass.run_command("v.to.points", input=linevector ,type="line", output='l_'+startCover+"_points", dmax=pointDist, overwrite=True) filename = os.path.join(workPath,startCover+".ascii") grass.run_command("v.out.ascii",input='l_'+startCover +"_points", layer=2, type="point", output=filename , columns="cat,lcat,along", format="point", overwrite=True) lines = [] inFile = open(filename,'rU') for line in inFile.read().splitlines(): lines.append(line.split("|")) inFile.close() length = float(lines[-1][4]) grass.verbose("Path length: "+str(length)) filename = os.path.join(workPath, startCover+'_'+'profileXY.csv') grass.verbose("Profile: "+str(filename)) outFile = open(filename,"w") for each in lines: tmp = (each [0]) + ',' + (each [1])+ "\n" outFile.write(tmp) outFile.close() # next line should be more exact because with full trapeziod a wider area is necessary. # actually, we don't know at this point how big the deepest cut will be !!! ??? # grass.run_command('v.buffer', overwrite=True, input=linevector, type="line", output='l_'+startCover+'_maxbuf', distance=str(float(chMaxWidth) / float(2))) grass.run_command('r.mask', overwrite=True, vector='l_'+startCover+'_maxbuf') grass.run_command('r.mapcalc', expression='l_'+startCover+'_maxbuf = '+basedtm,overwrite=True) s = grass.read_command('r.univar', overwrite=True, map='l_'+startCover+'_maxbuf') kv = grass.parse_key_val(s, sep=':') maxH = float(kv['maximum']) maxH = maxH+vRes grass.verbose("Maximum height: "+str(maxH)) grass.run_command('r.mask', flags="r") vLevels = int(round(((maxH-endHeight)/vRes))) + 2 grass.verbose("Number of levels: "+str(vLevels)) hSeries = [] # WINDOWS??? os.system('rm '+os.path.join(workPath,'l_*.pascii')) db = {} for n in range(1,vLevels): hSeries.append(round ((n-1)*vRes+endHeight)) db[n]= [] quo = (endHeight-startHeight)/length grass.verbose("Start height: "+str(startHeight)) grass.verbose("End height: "+str(endHeight)) grass.verbose("Slope ratio (in meters / meter): "+str(quo)) for aLine in lines: tmp = (quo*float(aLine[4]))+startHeight level = int(round(((tmp - endHeight)/vRes) + 1)) layer = hSeries[level-1] # python arrays run from 0 #print "---------------"+str(aLine)+" level: "+str(level) db[level].append([aLine[0],aLine[1],aLine[2],chWidth/2]) for levelUp in range(level+1,vLevels): bufferWidth = ((chWidth/2)+((levelUp - level)*vRes*sideRatio)) if bufferWidth <= (chMaxWidth/2): db[levelUp].append([aLine[0],aLine[1],aLine[2],bufferWidth]) for aKey in db: #print "---------------"+str(aKey) filename = os.path.join(workPath,'l_'+startCover+'_'+str(aKey).zfill(5)+'.pascii') outFile = open(filename,"w") for each in db[aKey]: tmp = str(each [0])+ '|' + str(each [1])+ '|' + str(each [2])+ '|' + str(each [3]) + "\n" outFile.write(tmp) outFile.close() grass.run_command('g.region', region='l_work_'+startCover+'.region') grass.run_command('g.region', res=str(hRes)) #creating buffer for raster masking grass.run_command('v.buffer',overwrite=True, input=linevector, type='line', output='l_'+startCover+'_buf200', distance=200) grass.run_command('r.mask', overwrite=True, vector='l_'+startCover+'_buf200') for n in range(1,min(vLevels,limitRunLayers)): if len(db[n])>0: basename = 'l_'+startCover+'_'+str(n).zfill(5) grass.run_command('v.in.ascii', flags="n", overwrite=True, input=os.path.join(workPath,basename+'.pascii'), output=basename, columns="x double precision, y double precision, cat int, width double precision", cat=3) grass.run_command('v.buffer', flags="t", overwrite=True, input=basename, layer=1, type="point", output=basename+'_buf', column="width", tolerance=0.01) grass.run_command('v.db.addcolumn', map=basename+'_buf', col='level int') grass.run_command('v.db.update', map=basename+'_buf', column="level", value=str(hSeries[n-1])) grass.run_command('v.to.rast', overwrite=True, input=basename+'_buf', type="area", output=basename+'_buf_diss', use="attr", attribute_column="level") #CALCULATING FINAL RESULT grass.run_command('r.mask', flags='r') grass.run_command('g.region', region='l_work_'+startCover+'.region') grass.run_command('g.region', res=str(hRes)) grass.run_command('r.mapcalc', expression='source = '+basedtm, overwrite=True) for n in range(1,min(vLevels,limitRunLayers)): if len(db[n])>0: basename = 'l_'+startCover+'_'+str(n).zfill(5) grass.verbose("Applying: "+basename) grass.run_command('r.mapcalc', expression='temp = if (isnull('+basename+'_buf_diss),source,if ( '+basename+'_buf_diss < source , '+basename+'_buf_diss, source))', overwrite=True) grass.run_command('g.rename', overwrite=True, raster='temp,source') grass.run_command('r.mapcalc', expression= 'dtm_'+startCover+' = if (isnull(source),'+basedtm+',source)', overwrite=True) grass.run_command('r.colors', map='dtm_'+startCover, color='bgyr') grass.run_command('g.region', res=str(reliefRes)) grass.run_command('r.relief', overwrite=True, input='dtm_'+startCover,output='dtm_'+startCover+'_shaded', altitude=60, azimuth=45) grass.verbose("Calculating volume difference") grass.run_command('g.region', raster='dtm_'+startCover) grass.run_command('g.region', res=str(hRes)) grass.run_command('r.mask', overwrite=True, vector='l_'+startCover+'_buf200') grass.run_command('r.mapcalc', overwrite=True, expression='diff_'+startCover+' = '+basedtm+' - dtm_'+startCover) s = grass.read_command('r.univar', overwrite=True, map='diff_'+startCover) kv = grass.parse_key_val(s, sep=':') sum = float(kv['sum']) grass.run_command('r.mask', flags="r") # WRITE LOG FILE filename = startCover+".txt" s = grass.read_command('g.region', flags="p3") kv = grass.parse_key_val(s, sep=':') xres = float(kv['nsres']) yres = float(kv['ewres']) m3 = xres * yres * sum mt = m3 * 2.7 * 1000 liebherr = mt / 350 visontaev = mt / 1000 / 4200 outFile = open(filename,"w") tmp=[] tmp.append("Path: "+linevector+" >> "+startCover+"\n") tmp.append("M3: "+str(m3)+"\n") tmp.append("Limestone tons: "+str(mt)+"\n") tmp.append("Kt limestone: "+str(mt/1000.0)+"\n") tmp.append("Liebherr T 282B: "+str(liebherr)+"\n") tmp.append("Visonta year "+str(visontaev)+"\n") for each in tmp: grass.message(each) outFile.write(each) outFile.close() grass.run_command('g.remove', flags="f", type="all", pattern='l_*'+startCover+'*') return 0
def main(): global tmpmap tmpmap = None map = options['map'] zero = flags['z'] bands = flags['b'] if not zero: s = gscript.read_command('r.univar', flags='g', map=map) kv = gscript.parse_key_val(s) global mean, stddev mean = float(kv['mean']) stddev = float(kv['stddev']) if not bands: # smooth free floating blue/white/red rules = '\n'.join(["0% blue", "%f blue" % z(-2), "%f white" % mean, "%f red" % z(+2), "100% red"]) else: # banded free floating black/red/yellow/green/yellow/red/black # reclass with labels only works for category (integer) based maps # r.reclass input="$GIS_OPT_MAP" output="${GIS_OPT_MAP}.stdevs" << # EOF # >3 S.D. outliers colored black so they show up in d.histogram w/ white background rules = '\n'.join(["0% black", "%f black" % z(-3), "%f red" % z(-3), "%f red" % z(-2), "%f yellow" % z(-2), "%f yellow" % z(-1), "%f green" % z(-1), "%f green" % z(+1), "%f yellow" % z(+1), "%f yellow" % z(+2), "%f red" % z(+2), "%f red" % z(+3), "%f black" % z(+3), "100% black"]) else: tmpmap = "r_col_stdev_abs_%d" % os.getpid() gscript.mapcalc("$tmp = abs($map)", tmp=tmpmap, map=map) # data centered on 0 (e.g. map of deviations) info = gscript.raster_info(tmpmap) maxv = info['max'] # current r.univar truncates percentage to the base integer s = gscript.read_command('r.univar', flags='eg', map=map, percentile=[95.45, 68.2689, 99.7300]) kv = gscript.parse_key_val(s) stddev1 = float(kv['percentile_68_2689']) stddev2 = float(kv['percentile_95_45']) stddev3 = float(kv['percentile_99_73']) if not bands: # zero centered smooth blue/white/red rules = '\n'.join(["%f blue" % -maxv, "%f blue" % -stddev2, "0 white", "%f red" % stddev2, "%f red" % maxv]) else: # zero centered banded black/red/yellow/green/yellow/red/black # >3 S.D. outliers colored black so they show up in d.histogram w/ white background rules = '\n'.join(["%f black" % -maxv, "%f black" % -stddev3, "%f red" % -stddev3, "%f red" % -stddev2, "%f yellow" % -stddev2, "%f yellow" % -stddev1, "%f green" % -stddev1, "%f green" % stddev1, "%f yellow" % stddev1, "%f yellow" % stddev2, "%f red" % stddev2, "%f red" % stddev3, "%f black" % stddev3, "%f black" % maxv, ]) gscript.write_command('r.colors', map=map, rules='-', stdin=rules)
def main(): # User inputs friction = options['friction'] # Input friction raster inpoints = options['points'] # Input point layer rastout = options['rastout'] # Output least cost path raster radius = int(options['radius']) # Point search radius n_closepoints = int(options['nearpoints']) # Number of closest points vectout = options['vectout'] # Vector layer output knight = "k" if flags['k'] else "" # Knight's move flag costatt = "e" if flags['c'] else "" # Calculate total cost values for paths and add them to attribute table # Check no vector or raster output is chosen, raise an error if (not vectout) and (not rastout): grass.message("No output chosen!") sys.exit() # Check overwrite settings # If output raster file exists, but overwrite option isn't selected if not grass.overwrite(): if grass.find_file(rastout)['name']: grass.message(_("Output raster map <%s> already exists") % rastout) sys.exit() # If output vector file exists, but overwrite option isn't selected if not grass.overwrite(): if grass.find_file(vectout, element = 'vector')['name']: grass.message(_("Output vector map <%s> already exists") % vectout) sys.exit() # If overwrite is chosen, remove the previous layers before any action (to lessen the probability of some random errors) if grass.overwrite(): grass.run_command("g.remove", rast = rastout, vect = vectout, quiet = True) # Get a region resolution to be used in cost attribute calculation, because the default will be in map units if vectout and (costatt == "e"): # Get raster calculation region information regiondata = grass.read_command("g.region", flags = 'p') regvalues = grass.parse_key_val(regiondata, sep= ':') # Assign variables for necessary region info bits nsres = float(regvalues['nsres']) ewres = float(regvalues['ewres']) regionres = (nsres + ewres) / 2.0 rescoefficient = regionres # Get process id (pid) and create temporary layer names which are also added to tmp_rlayers list pid = os.getpid() # Process ID, used for getting unique temporary filenames costmap1 = "tmp_cost_%d" % pid # Cost surface for point 1 tmp_rlayers.append(costmap1) costmap2 = "tmp_cost_%d_%i" % (pid, 2) # Cost surface from point 2 (parallel process) tmp_rlayers.append(costmap2) costdir1 = "tmp_costdir_%d" % pid # Temporary cost direction raster 1 tmp_rlayers.append(costdir1) costdir2 = "tmp_costdir_%d_%i" % (pid, 2) # Temporary cost direction raster 2 tmp_rlayers.append(costdir2) lcpmap1 = "tmp_lcp_%d" % pid # Least cost path map from costmap1 tmp_rlayers.append(lcpmap1) lcpmap2 = "tmp_lcp_%d_%i" % (pid, 2) # Least cost path map from costmap2 (parallel process) tmp_rlayers.append(lcpmap2) lcptemp = "tmp_lcptemp_%d" % pid # Temporary file for mapcalc tmp_rlayers.append(lcptemp) region = "tmp_region_%d" % pid # Temporary vector layer of computational region tmp_vlayers.append(region) points = "tmp_points_%d" % pid # Temporary point layer which holds points only inside the region tmp_vlayers.append(points) if vectout: # if vector output is needed, create the temporary vectorlayers too vectdrain1 = "tmp_vectdrain_%d" % pid tmp_vlayers.append(vectdrain1) vectdrain2 = "tmp_vectdrain2_%d" % pid tmp_vlayers.append(vectdrain2) # Make sure input data points are inside raster computational region: create a region polygon and select points that are inside it grass.run_command('v.in.region', overwrite = True, output = region) grass.run_command('v.select', overwrite = True, flags = "tc", ainput = inpoints, atype = 'point', binput = region, btype = 'area', output = points , operator = 'within') # Create a new PointLayerInfo class instance using input point layer and get the categories list as well as total feature count of the layer pointlayer = PointLayerInfo(points) points_cats = pointlayer.featcats # A list() of layer feature categories points_featcount = pointlayer.featcount # integer of feature count in point layer points_coordsdict = pointlayer.coordsdict # dict() of point coordinates as tuple (x,y) # Create an empty dictionaries for storing cost distances between points costdict1 = dict() costdict2 = dict() # Create the first mapcalc process, so that it can be checked and stopped in the loop without using more complicated ways mapcalc = grass.Popen("") lcp1 = grass.Popen("") lcp2 = grass.Popen("") # The main loop for least cost path creation. For each point a cost surface is created, least cost paths created and then added to the general output file. Loop uses a range which has as many items as there are points in the input point layer. To make use of parallel processing, the step is 2, although the "item" is always the first of the selected pair. for item in range(0,points_featcount,2): # Get category number of the point from the point_cats list cat1 = points_cats[item] # Set p2 (i.e. using second or parallel process) to be False by default and make it True if there are enough points left to do so. In that case set it to true and also get the category number of the point from the point_cats list p2 = False if item+1 < points_featcount: p2 = True cat2 = points_cats[item+1] # Create a new PointLayerInfo object from input point layer with centerpoint (from which distances area measured in the class) feature as currently selected point cat point1 = PointLayerInfo(points, cat1) if p2: # The same for p2 if needed point2 = PointLayerInfo(points, cat2) # begin cost surface process with the start coordinate of currently selected point. Do the same for second process costsurf1 = grass.start_command('r.cost', flags=knight, overwrite=True, input=friction, output=costmap1, outdir=costdir1, start_coordinates=point1.centercoord()) if p2: costsurf2 = grass.start_command('r.cost', flags=knight, overwrite=True, input=friction, output=costmap2, outdir=costdir2, start_coordinates=point2.centercoord()) # Create the drainlist (list of feature coordinates where lcp from current point is made to) depending on whether radius and/or n_closepoints are used. Drainlist point coordinates will be used for r.drain. See PointLayerInfo class below for explanation of the process. if radius and n_closepoints: # If radius and n_closepoints are used drainlist1 = point1.near_points_in_radius(n_closepoints, radius) if p2: drainlist2 = point2.near_points_in_radius(n_closepoints, radius) elif radius: # If radius is used drainlist1 = point1.points_in_radius(radius) if p2: drainlist2 = point2.points_in_radius(radius) elif n_closepoints: # If n_closepoints is used drainlist1 = point1.near_points(n_closepoints) if p2: drainlist2 = point2.near_points(n_closepoints) else: # If neither radius or n_closepoints are used drainlist1 = point1.cats_without_centerpoint() if p2: drainlist2 = point2.cats_without_centerpoint() # Do the least cost path calculation procedures drain_coords1 = "" # An empty string that will be populated with point coordinates which in turn will be used for r.drain start coordinates for drainpoint in drainlist1: # Iterate through all points in drainlist drain_x, drain_y = point1.coordsdict[drainpoint] # variables are assigned coordinate values from the coordinate dictionary drain_coords1 = drain_coords1 + str(drain_x) + "," + str(drain_y) + "," # Add those coordinates to the string that is usable by r.drain if p2: # The same thing for second process, see previous section for comments drain_coords2 = "" for drainpoint in drainlist2: drain_x, drain_y = point2.coordsdict[drainpoint] drain_coords2 = drain_coords2 + str(drain_x) + "," + str(drain_y) + "," # Wait for the previous processes to finish their processing costsurf1.wait() costsurf2.wait() mapcalc.wait() # If vector output is needed, do the r.drain for each point in the drainlist separately to get the cost values if vectout: if costatt == "e": for drainpoint in drainlist1: # Each point cat in the drainlist is being iterated drain_x, drain_y = point1.coordsdict[drainpoint] # Currently selected point's coordinates drain_onecoord = str(str(drain_x) + "," + str(drain_y)) # The coordinate to be used in r.drain on the next line grass.run_command('r.drain', overwrite=True, flags="ad", input=costmap1, indir=costdir1, output = lcpmap1, start_coordinates = drain_onecoord) # Get raster max value (=total cost value for one path) and store it in dictionary with point cat being its key rastinfo = grass.raster_info(lcpmap1) costdict1[drainpoint] = rescoefficient * rastinfo['min'] if p2: # Same procedure as in the previous section for parallel process for drainpoint in drainlist2: drain_x, drain_y = point2.coordsdict[drainpoint] drain_onecoord = str(str(drain_x) + "," + str(drain_y)) grass.run_command('r.drain', overwrite=True, flags="ad", input=costmap2, indir=costdir2, output = lcpmap2, start_coordinates = drain_onecoord) rastinfo = grass.raster_info(lcpmap2) costdict2[drainpoint] = rescoefficient * rastinfo['min'] # Finally create the vector layer with all paths from the current point. It also (whether we want it or not) creates a raster output if len(drainlist1) > 0: lcp1 = grass.start_command('r.drain', overwrite=True, flags="d", input=costmap1, indir=costdir1, output = lcpmap1, vector_output = vectdrain1,start_coordinates=drain_coords1) if p2 and (len(drainlist2) > 0): lcp2 = grass.start_command('r.drain', overwrite=True, flags="d", input=costmap2, indir=costdir2, output = lcpmap2, vector_output = vectdrain2,start_coordinates=drain_coords2) # If raster output is needed, but path maps have not been made yet (i.e. vectout must be False) then make those if not vectout and (len(drainlist1) > 0): lcp1 = grass.start_command('r.drain', overwrite=True, flags="d", input=costmap1, indir=costdir1, output = lcpmap1, start_coordinates=drain_coords1) if p2 and (len(drainlist2) > 0): lcp2 = grass.start_command('r.drain', overwrite=True, flags="d", input=costmap2, indir=costdir2, output = lcpmap2, start_coordinates=drain_coords2) # Wait for the lcp processes to finish lcp1.wait() lcp2.wait() # If raster output is needed, do the mapcalc stuff: merge the path rasters if rastout: if len(drainlist1) == 0: lcpmap1 = 0 if len(drainlist2) == 0: lcpmap2 = 0 if cat1 == points_cats[0]: # If it's the very first iteration if p2: # Technically this should not be False in any situation, but let it be here for additional safety # Add lcpmap1 and lcpmap2 together mapcalc = grass.mapcalc_start("$outmap = if(isnull($tempmap1),0,1) + if(isnull($tempmap2),0,1)", outmap = rastout, tempmap1 = lcpmap1, tempmap2 = lcpmap2, overwrite=True) else: # Just in case mapcalc = grass.mapcalc_start("$outmap = if(isnull($tempmap1),0,1)", outmap = rastout, tempmap1 = lcpmap1, overwrite=True) else: # Rename the cumulative lcp map from previous iteration so that mapcalc can use it (x=x+y logic doesn't work with mapcalc) grass.run_command('g.rename', rast = rastout + ',' + lcptemp, overwrite=True) # rastout = Previous LCP + Current LCP if p2: mapcalc = grass.mapcalc_start("$outmap = $inmap + if(isnull($tempmap1),0,1) + if(isnull($tempmap2),0,1)", inmap = lcptemp, outmap = rastout, tempmap1 = lcpmap1, tempmap2 = lcpmap2) else: mapcalc = grass.mapcalc_start("$outmap = $inmap + if(isnull($tempmap1),0,1)", inmap = lcptemp, outmap = rastout, tempmap1 = lcpmap1) # If vector output is needed, do all necessary things like merging the vectors and getting values for attribute table (if specified) if vectout: if costatt == "e": # Only if cost attributes are needed if len(drainlist1) > 0: # Process 1 # Add attribute table to the vector path layer grass.run_command('v.db.addtable', map = vectdrain1) # Get path Euclidean distances and add them to the new column in attribute table. Also add the current point cat to the attribute "from_point" grass.run_command('v.db.addcolumn', map = vectdrain1, columns = "length double precision, from_point int, to_point int, cost double precision") grass.run_command('v.to.db', map = vectdrain1, type = "line", option = "length", columns = "length") grass.run_command('v.db.update', map = vectdrain1, column = "from_point", value = str(cat1)) # Same as previous section but for process 2 if p2 and (len(drainlist2) > 0): grass.run_command('v.db.addtable', map = vectdrain2) grass.run_command('v.db.addcolumn', map = vectdrain2, columns = "length double precision, from_point int, to_point int, cost double precision") grass.run_command('v.to.db', map = vectdrain2, type = "line", option = "length", columns = "length") grass.run_command('v.db.update', map = vectdrain2, column = "from_point", value = str(cat2)) # A loop to update the path attribute values to the attribute table if len(drainlist1) > 0: drainseq = 1 # This is just a helper counter because for newly created vector layer the cats start from 1 and just go successively, so no need to introduce any unnecessary catlist for drainpoint in drainlist1: # Update to_point column with values from drainlist grass.run_command('v.db.update', map = vectdrain1, column = "to_point", value = str(drainpoint), where = "cat = " + str(drainseq)) # Update the cost column using costdict created earlier grass.run_command('v.db.update', map = vectdrain1, column = "cost", value = costdict1[drainpoint], where = "cat = " + str(drainseq)) drainseq += 1 # The same for process 2 if p2 and (len(drainlist2) > 0): drainseq = 1 # Reset the counter for drainpoint in drainlist2: grass.run_command('v.db.update', map = vectdrain2, column = "to_point", value = str(drainpoint), where = "cat = " + str(drainseq)) grass.run_command('v.db.update', map = vectdrain2, column = "cost", value = costdict2[drainpoint], where = "cat = " + str(drainseq)) drainseq += 1 # Patch vector layers # For both processes, first make sure that drainlists for current iteration are not empty. If they are not (i.e. the drainlist for current iteration > 0), then drain vectors will be used in v.patch, otherwise empty strings will be used in patching. This is to make sure that vectors from previous iterations are not used. if len(drainlist1) > 0: vect1 = vectdrain1 else: vect1 = "" if len(drainlist2) > 0: vect2 = vectdrain2 else: vect2 = "" # If BOTH drain processes resulted in vectors, create a comma character to be used in v.patch (input parameter must be a string type and layers should be separated by comma) if (len(drainlist1) > 0) and (len(drainlist2) > 0): comma = "," else: comma = "" # Finally do the patching if cat1 == points_cats[0]: # If it's the very first iteration if p2: # If iteration has 2 points grass.run_command('v.patch', overwrite = True, flags=costatt, input = vect1 + comma + vect2, output = vectout) else: # Technically this should never be called (because not having 2 points per iteration can happen only for the very last iteration), but I'll leave it here just in case or for future reference grass.run_command('g.rename', overwrite = True, vect = vect1 + "," + vectout) else: if grass.find_file(vectout, element='vector')['name']: # Check whether vectout exists or not (this can happen when the first iteration did not produce any vectors, i.e. search radius was too small). If it does exist, add "a" (append) flag to v.patch, otherwise omit it. append = costatt + "a" else: append = costatt # Choose between two patching scenarios: 1 or 2 process versions. if p2: grass.run_command('v.patch', overwrite = True, flags=append, input = vect1 + comma + vect2, output = vectout) else: grass.run_command('v.patch', overwrite = True, flags=append, input = vect1, output = vectout) # Make 0 values of raster into NULLs if rastout: mapcalc.wait() nullproc = grass.run_command('r.null', map = rastout, setnull = "0") grass.message("All done!")
def _initializeParameters(self, options, flags): self._debug("_initialize_parameters", "started") # inicialization of module parameters (options, flags) self.flags = flags if self.flags['t']: self.transparent = 'TRUE' else: self.transparent = 'FALSE' self.o_mapserver_url = options['mapserver'].strip() + "?" self.o_layers = options['layers'].strip() self.o_styles = options['styles'].strip() self.o_output = options['output'] self.o_method = options['method'] self.o_bgcolor = options['bgcolor'].strip() if self.o_bgcolor != "" and not flags["d"]: grass.warning(_("Parameter bgcolor ignored, use -d flag")) self.o_urlparams = options['urlparams'].strip() if self.o_urlparams != "" and not flags["d"]: grass.warning(_("Parameter urlparams ignored, use -d flag")) self.o_wms_version = options['wms_version'] if self.o_wms_version == "1.3.0": self.projection_name = "CRS" else: self.projection_name = "SRS" self.o_format = options['format'] if self.o_format == "geotiff": self.mime_format = "image/geotiff" elif self.o_format == "tiff": self.mime_format = "image/tiff" elif self.o_format == "png": self.mime_format = "image/png" elif self.o_format == "jpeg": self.mime_format = "image/jpeg" if flags['t']: grass.warning(_("JPEG format does not support transparency")) elif self.o_format == "gif": self.mime_format = "image/gif" else: grass.fatal(_("Unsupported image format %s") % self.o_format) self.o_srs = int(options['srs']) if self.o_srs <= 0: grass.fatal(_("Invalid EPSG code %d") % self.o_srs) # read projection info self.proj_location = grass.read_command('g.proj', flags ='jf').rstrip('\n') self.proj_srs = grass.read_command('g.proj', flags = 'jf', epsg = str(self.o_srs) ).rstrip('\n') if not self.proj_srs or not self.proj_location: grass.fatal(_("Unable to get projection info")) # set region self.o_region = options['region'] if self.o_region: if not grass.find_file(name = self.o_region, element = 'windows', mapset = '.' )['name']: grass.fatal(_("Region <%s> not found") % self.o_region) if self.o_region: s = grass.read_command('g.region', quiet = True, flags = 'ug', region = self.o_region) self.region = grass.parse_key_val(s, val_type = float) else: self.region = grass.region() min_tile_size = 100 self.o_maxcols = int(options['maxcols']) if self.o_maxcols <= min_tile_size: grass.fatal(_("Maxcols must be greater than 100")) self.o_maxrows = int(options['maxrows']) if self.o_maxrows <= min_tile_size: grass.fatal(_("Maxrows must be greater than 100")) # setting optimal tile size according to maxcols and maxrows constraint and region cols and rows self.tile_cols = int(self.region['cols'] / ceil(self.region['cols'] / float(self.o_maxcols))) self.tile_rows = int(self.region['rows'] / ceil(self.region['rows'] / float(self.o_maxrows))) # suffix for existing mask (during overriding will be saved # into raster named:self.o_output + this suffix) self.original_mask_suffix = "_temp_MASK" # check names of temporary rasters, which module may create maps = [] for suffix in ('.red', '.green', '.blue', '.alpha', self.original_mask_suffix ): rast = self.o_output + suffix if grass.find_file(rast, element = 'cell', mapset = '.')['file']: maps.append(rast) if len(maps) != 0: grass.fatal(_("Please change output name, or change names of these rasters: %s, " "module needs to create this temporary maps during runing") % ",".join(maps)) # default format for GDAL library self.gdal_drv_format = "GTiff" self._debug("_initialize_parameters", "finished")
def main(): # Get user inputs friction_original = options['friction'] # Input friction map out = options['out'] # Output totalcost raster maxcost = options['maxcost'] # Max cost distance in cost units knight = "k" if flags["k"] else "" # Use Knight's move in r.cost instead Queen's move (a bit slower, but more accurate) mempercent = int(options['mempercent']) # Percent of map to keep in memory in r.cost calculation # Error if no valid friction surface is given if not grass.find_file(friction_original)['name']: grass.message(_("Friction surface <%s> not found") % friction_original) sys.exit() # Calculate cost distances / edge effect distances from the friction map. Result is in map units info = grass.raster_info(friction_original) # Read and get raster info edgeeffect_min = float(maxcost) / float(info['max']) # Minimum cost distance / edge effect distance edgeeffect_max = float(maxcost) / float(info['min']) # Maximum cost distance / edge effect distance # If "Only calculate edge effect" is selected if flags['e']: grass.message("Minimum distance / edge effect: " + str(edgeeffect_min)) grass.message("Maximum distance / edge effect: " + str(edgeeffect_max)) sys.exit() # If output file exists, but overwrite option isn't selected if not grass.overwrite(): if grass.find_file(out)['name']: grass.message(_("Output raster map <%s> already exists") % out) sys.exit() # Get raster calculation region information regiondata = grass.read_command("g.region", flags = 'p') regvalues = grass.parse_key_val(regiondata, sep= ':') # Assign variables for necessary region info bits nsres = float(regvalues['nsres']) ewres = float(regvalues['ewres']) # Calculate the mean resolution meanres = (nsres + ewres) / 2.0 # Create a list holding cell coordinates coordinatelist = [] # An empty list that will be populated with coordinates rasterdata = grass.read_command('r.stats', flags="1gn", input = friction_original) # Read input raster coordinates rastervalues = rasterdata.split() # Split the values from r.stats into list entries # rastervalues list is structured like that: [x1, y1, rastervalue1, x2, y2, rastervalue2 ... xn, yn, rastervaluen], so iterate through that list with step of 3 and write a new list that has coordinates in a string: ["x1,y1", "x2,y2" ... "xn,yn"] for val in xrange(0,len(rastervalues),3): coordinatelist.append(rastervalues[val] + "," + rastervalues[val+1]) # This is the number of cells (and hence cost surfaces) to be used n_coords = len(coordinatelist) # Create temporary filenames with unique process id in their name. Add each name to the tmp_layers list. pid = os.getpid() cost1 = str("tmp_totalcost_cost1_%d" % pid) tmp_layers.append(cost1) cost2 = str("tmp_totalcost_cost2_%d" % pid) tmp_layers.append(cost2) cost3 = str("tmp_totalcost_cost3_%d" % pid) tmp_layers.append(cost3) cost4 = str("tmp_totalcost_cost4_%d" % pid) tmp_layers.append(cost4) friction = str("tmp_friction_%d" % pid) tmp_layers.append(friction) calctemp = str("tmp_calctemp_%d" % pid) tmp_layers.append(calctemp) # Assuming the friction values are per map unit (not per cell), the raster should be multiplied with region resolution. This is because r.cost just uses cell values and adds them - slightly different approach compared to ArcGIS which compensates for the resolution automatically. The result is then divided by maxcost so that r.cost max_cost value can be fixed to 1 (it doesn't accept floating point values, hence the workaround). grass.mapcalc("$outmap = $inmap * $res / $mcost", outmap = friction, inmap = friction_original, res = meanres, mcost = maxcost) # Do the main loop for c in xrange(0, n_coords, 4): # Iterate through the numbers of cells with the step of 4 # Start four r.cost processes with different coordinates. The first process (costproc1) is always made, but the other 3 have the condition that there exists a successive coordinate in the list. This is because the used step of 4 in the loop. In case there are no coordinates left, assign the redundant cost outputs null-values so they wont be included in the map calc. try: costproc1 = grass.start_command('r.cost', overwrite = True, flags = knight, input = friction, output = cost1, start_coordinates = coordinatelist[c], max_cost = 1, percent_memory = mempercent) if c+1 < n_coords: costproc2 = grass.start_command('r.cost', overwrite = True, flags = knight, input = friction, output = cost2, start_coordinates = coordinatelist[c+1], max_cost = 1, percent_memory = mempercent) else: cost2 = "null()" if c+2 < n_coords: costproc3 = grass.start_command('r.cost', overwrite = True, flags = knight, input = friction, output = cost3, start_coordinates = coordinatelist[c+2], max_cost = 1, percent_memory = mempercent) else: cost3 = "null()" if c+3 < n_coords: costproc4 = grass.start_command('r.cost', overwrite = True, flags = knight, input = friction, output = cost4, start_coordinates = coordinatelist[c+3], max_cost = 1, percent_memory = mempercent) else: cost4 = "null()" except: grass.message("Error with r.cost: " + str(sys.exc_info()[0])) sys.exit() # For the very first iteration just add those first r.cost results together if c == 0: # Wait for the r.cost processes to stop before moving on costproc1.wait() costproc2.wait() costproc3.wait() costproc4.wait() # Do the map algebra: merge the cost surfaces try: grass.mapcalc("$outmap = if(isnull($tempmap1),0,1) + if(isnull($tempmap2),0,1) + if(isnull($tempmap3),0,1) + if(isnull($tempmap4),0,1)", outmap = out, tempmap1 = cost1, tempmap2 = cost2, tempmap3 = cost3, tempmap4 = cost4, overwrite=True) except: grass.message("Error with mapcalc: " + str(sys.exc_info()[0])) sys.exit() # If it's not the first iteration... else: # Rename the output of previous mapcalc iteration so that it can be used in the mapcalc expression (x = x + y logic doesn't work apparently) try: # If pygrass gets fixed, replace g.rename with those commented out pygrass-based lines as they seem to be a bit faster (are they really?) #map = pygrass.raster.RasterRow(out) #map.name = calctemp grass.run_command('g.rename', overwrite = True, rast = out + "," + calctemp) except: grass.message("Error: " + str(sys.exc_info()[0])) sys.exit() # Wait for the r.cost processes to stop before moving on costproc1.wait() costproc2.wait() costproc3.wait() costproc4.wait() # Merge the r.cost results and the cumulative map from previous iteration try: grass.mapcalc("$outmap = if(isnull($inmap),0,$inmap) + if(isnull($tempmap1),0,1) + if(isnull($tempmap2),0,1) + if(isnull($tempmap3),0,1) + if(isnull($tempmap4),0,1)", inmap = calctemp, outmap = out, tempmap1 = cost1, tempmap2 = cost2, tempmap3 = cost3, tempmap4 = cost4, overwrite=True) except: grass.message("Error with mapcalc: " + str(sys.exc_info()[0])) sys.exit() # Finally print the edge effect values grass.message("---------------------------------------------") grass.message("Minimum distance / edge effect: " + str(edgeeffect_min)) grass.message("Maximum distance / edge effect: " + str(edgeeffect_max))
def export_png_in_projection(src_mapset_name, map_name, output_file, epsg_code, routpng_flags, compression, wgs84_file, use_region=True): """ :param use_region: use computation region and not map extent """ if use_region: src_region = get_region() src_proj_string = get_location_proj_string() # TODO: change only location and not gisdbase? # we rely on the tmp dir having enough space for our map tgt_gisdbase = tempfile.mkdtemp() # this is not needed if we use mkdtemp but why not tgt_location = 'r.out.png.proj_location_%s' % epsg_code # because we are using PERMANENT we don't have to create mapset explicitly tgt_mapset_name = 'PERMANENT' src_mapset = Mapset(name=src_mapset_name, use_current=True) assert src_mapset.exists() # get source (old) and set target (new) GISRC enviromental variable # TODO: set environ only for child processes could be enough and it would # enable (?) parallel runs src_gisrc = os.environ['GISRC'] tgt_gisrc = gsetup.write_gisrc(tgt_gisdbase, tgt_location, tgt_mapset_name) os.environ['GISRC'] = tgt_gisrc # we do this only after we obtained region, so it was applied # and we don't need it in the temporary (tgt) mapset if os.environ.get('WIND_OVERRIDE'): old_temp_region = os.environ['WIND_OVERRIDE'] del os.environ['WIND_OVERRIDE'] else: old_temp_region = None tgt_mapset = Mapset(tgt_gisdbase, tgt_location, tgt_mapset_name) try: # the function itself is not safe for other (backgroud) processes # (e.g. GUI), however we already switched GISRC for us # and child processes, so we don't influece others gs.create_location(dbase=tgt_gisdbase, location=tgt_location, epsg=epsg_code, datum=None, datum_trans=None) assert tgt_mapset.exists() # we need to make the mapset change in the current GISRC (tgt) # note that the C library for this process still holds the # path to the old GISRC file (src) tgt_mapset.set_as_current(gisrc=tgt_gisrc) # setting region if use_region: # respecting computation region of the src location # by previous use g.region in src location # and m.proj and g.region now # respecting MASK of the src location would be hard # null values in map are usually enough tgt_proj_string = get_location_proj_string() tgt_region = reproject_region(src_region, from_proj=src_proj_string, to_proj=tgt_proj_string) # uses g.region thus and sets region only for child processes # which is enough now # TODO: unlike the other branch, this keeps the current # resolution which is not correct set_region(tgt_region) else: # find out map extent to import everything # using only classic API because of some problems with pygrass # on ms windows rproj_out = gs.read_command('r.proj', input=map_name, dbase=src_mapset.database, location=src_mapset.location, mapset=src_mapset.name, output=map_name, flags='g') a = gs.parse_key_val(rproj_out, sep='=', vsep=' ') gs.run_command('g.region', **a) # map import gs.message("Reprojecting...") gs.run_command('r.proj', input=map_name, dbase=src_mapset.database, location=src_mapset.location, mapset=src_mapset.name, output=map_name, quiet=True) # actual export gs.message("Rendering...") raster_to_png(map_name, output_file, compression=compression, routpng_flags=routpng_flags) # outputting file with WGS84 coordinates if wgs84_file: gs.verbose("Projecting coordinates to LL WGS 84...") with open(wgs84_file, 'w') as data_file: if use_region: # map which is smaller than region is imported in its own # small extent, but we export image in region, so we need # bounds to be for region, not map # hopefully this is consistent with r.out.png behavior data_file.write( map_extent_to_file_content( proj_to_wgs84(get_region())) + '\n') else: # use map to get extent # the result is actually the same as using map # if region is the same as map (use_region == False) data_file.write( map_extent_to_file_content( get_map_extent_for_location(map_name)) + '\n') finally: # juts in case we need to do something in the old location # our callers probably do os.environ['GISRC'] = src_gisrc if old_temp_region: os.environ['WIND_OVERRIDE'] = old_temp_region # set current in library src_mapset.set_as_current(gisrc=src_gisrc) # delete the whole gisdbase # delete file by file to ensure that we are deleting only our things # exception will be raised when removing non-empty directory tgt_mapset.delete() os.rmdir(tgt_mapset.location_path) # dir created by tempfile.mkdtemp() needs to be romved manually os.rmdir(tgt_gisdbase) # we have to remove file created by tempfile.mkstemp function # in write_gisrc function os.remove(tgt_gisrc)
def main(): global tile, tmpdir, in_temp in_temp = False input = options['input'] output = options['output'] one = flags['1'] #are we in LatLong location? s = grass.read_command("g.proj", flags='j') kv = grass.parse_key_val(s) if kv['+proj'] != 'longlat': grass.fatal(_("This module only operates in LatLong locations")) # use these from now on: infile = input while infile[-4:].lower() in ['.hgt', '.zip']: infile = infile[:-4] (fdir, tile) = os.path.split(infile) if not output: tileout = tile else: tileout = output zipfile = infile + ".hgt.zip" hgtfile = os.path.join(fdir, tile[:7] + ".hgt") if os.path.isfile(zipfile): #### check if we have unzip if not grass.find_program('unzip'): grass.fatal(_('The "unzip" program is required, please install it first')) # really a ZIP file? # make it quiet in a safe way (just in case -qq isn't portable) tenv = os.environ.copy() tenv['UNZIP'] = '-qq' if grass.call(['unzip', '-t', zipfile], env = tenv) != 0: grass.fatal(_("'%s' does not appear to be a valid zip file.") % zipfile) is_zip = True elif os.path.isfile(hgtfile): # try and see if it's already unzipped is_zip = False else: grass.fatal(_("File '%s' or '%s' not found") % (zipfile, hgtfile)) #make a temporary directory tmpdir = grass.tempfile() grass.try_remove(tmpdir) os.mkdir(tmpdir) if is_zip: shutil.copyfile(zipfile, os.path.join(tmpdir, tile + ".hgt.zip")) else: shutil.copyfile(hgtfile, os.path.join(tmpdir, tile + ".hgt")) #change to temporary directory os.chdir(tmpdir) in_temp = True zipfile = tile + ".hgt.zip" hgtfile = tile[:7] + ".hgt" bilfile = tile + ".bil" if is_zip: #unzip & rename data file: grass.message(_("Extracting '%s'...") % infile) if grass.call(['unzip', zipfile], env = tenv) != 0: grass.fatal(_("Unable to unzip file.")) grass.message(_("Converting input file to BIL...")) os.rename(hgtfile, bilfile) north = tile[0] ll_latitude = int(tile[1:3]) east = tile[3] ll_longitude = int(tile[4:7]) # are we on the southern hemisphere? If yes, make LATITUDE negative. if north == "S": ll_latitude *= -1 # are we west of Greenwich? If yes, make LONGITUDE negative. if east == "W": ll_longitude *= -1 # Calculate Upper Left from Lower Left ulxmap = "%.1f" % ll_longitude # SRTM90 tile size is 1 deg: ulymap = "%.1f" % (ll_latitude + 1) if not one: tmpl = tmpl3sec else: grass.message(_("Attempting to import 1-arcsec data.")) tmpl = tmpl1sec header = tmpl % (ulxmap, ulymap) hdrfile = tile + '.hdr' outf = file(hdrfile, 'w') outf.write(header) outf.close() #create prj file: To be precise, we would need EGS96! But who really cares... prjfile = tile + '.prj' outf = file(prjfile, 'w') outf.write(proj) outf.close() try: grass.run_command('r.in.gdal', input=bilfile, out=tileout) except: grass.fatal(_("Unable to import data")) # nice color table grass.run_command('r.colors', map = tileout, color = 'srtm') # write cmd history: grass.raster_history(tileout) grass.message(_("Done: generated map ") + tileout) grass.message(_("(Note: Holes in the data can be closed with 'r.fillnulls' using splines)"))
def get_map_extent_for_location(map_name): info_out = gs.read_command('r.info', map=map_name, flags='g') info = gs.parse_key_val(info_out, sep='=') return proj_to_wgs84(info)
def get_percentile(map, percentile): s = grass.read_command("r.univar", flags="ge", map=map, percentile=percentile) kv = grass.parse_key_val(s) return float(kv["percentile_%s" % percentile])
def main(): infile = options['input'] lesser = options['lesser'] greater = options['greater'] outfile = options['output'] s = grass.read_command("g.region", flags = 'p') kv = grass.parse_key_val(s, sep = ':') s = kv['projection'].strip().split() if s == '0': grass.fatal(_("xy-locations are not supported")) grass.fatal(_("Need projected data with grids in meters")) if not lesser and not greater: grass.fatal(_("You have to specify either lesser= or greater=")) if lesser and greater: grass.fatal(_("lesser= and greater= are mutually exclusive")) if lesser: limit = float(lesser) if greater: limit = float(greater) if not grass.find_file(infile)['name']: grass.fatal(_("Raster map <%s> not found") % infile) clumpfile = "%s.clump.%s" % (infile.split('@')[0], outfile) if not grass.overwrite(): if grass.find_file(clumpfile)['name']: grass.fatal(_("Temporary raster map <%s> exists") % clumpfile) grass.message(_("Generating a clumped raster file ...")) grass.run_command('r.clump', input = infile, output = clumpfile) if lesser: grass.message(_("Generating a reclass map with area size less than or equal to %f hectares...") % limit) else: grass.message(_("Generating a reclass map with area size greater than or equal to %f hectares...") % limit) recfile = outfile + '.recl' p1 = grass.pipe_command('r.stats', flags = 'aln', input = (clumpfile, infile), fs = '|') p2 = grass.feed_command('r.reclass', input = clumpfile, output = recfile, rules = '-') for line in p1.stdout: f = line.rstrip('\r\n').split('|') if len(f) < 5: continue hectares = float(f[4]) * 0.0001 if lesser: test = hectares <= limit else: test = hectares >= limit if test: p2.stdin.write("%s = %s %s\n" % (f[0], f[2], f[3])) p1.wait() p2.stdin.close() p2.wait() grass.message(_("Generating output raster map <%s>...") % outfile) grass.mapcalc("$outfile = $recfile", outfile = outfile, recfile = recfile) grass.run_command('g.remove', rast = [recfile, clumpfile], quiet = True)
def main(): global tmp_graph, tmp_group, tmp_psmap, tmp_psleg, tmp_gisleg breakpoints = options['breakpoints'] colorscheme = options['colorscheme'] column = options['column'] endcolor = options['endcolor'] group = options['group'] layer = options['layer'] linecolor = options['linecolor'] map = options['map'] maxsize = options['maxsize'] monitor = options['monitor'] nint = options['nint'] pointcolor = options['pointcolor'] psmap = options['psmap'] size = options['size'] startcolor = options['startcolor'] themecalc = options['themecalc'] themetype = options['themetype'] type = options['type'] where = options['where'] icon = options['icon'] flag_f = flags['f'] flag_g = flags['g'] flag_l = flags['l'] flag_m = flags['m'] flag_s = flags['s'] flag_u = flags['u'] layer = int(layer) nint = int(nint) size = float(size) maxsize = float(maxsize) # check column type inf = grass.vector_columns(map, layer) if column not in inf: grass.fatal(_("No such column <%s>") % column) coltype = inf[column]['type'].lower() if coltype not in ["integer", "double precision"]: grass.fatal(_("Column <%s> is of type <%s> which is not numeric.") % (column, coltype)) # create temporary file to hold d.graph commands for legend tmp_graph = grass.tempfile() # Create temporary file to commands for GIS Manager group tmp_group = grass.tempfile() # Create temporary file for commands for ps.map map file tmp_psmap = grass.tempfile() # Create temporary file for commands for ps.map legend file tmp_psleg = grass.tempfile() # create file to hold elements for GIS Manager legend tmp_gisleg = grass.tempfile() # Set display variables for group atype = int(type == "area") ptype = int(type == "point") ctype = int(type == "centroid") ltype = int(type == "line") btype = int(type == "boundary") # if running in the GUI, do not create a graphic legend in an xmon if flag_s: flag_l = False # if running in GUI, turn off immediate mode rendering so that the # iterated d.vect commands will composite using the display driver os.environ['GRASS_PNG_READ'] = 'TRUE' os.environ['GRASS_PNG_AUTO_WRITE'] = 'FALSE' db = grass.vector_db(map)[1] if not db or not db['table']: grass.fatal(_("No table connected or layer <%s> does not exist.") % layer) table = db['table'] database = db['database'] driver = db['driver'] # update color values to the table? if flag_u: # test, if the column GRASSRGB is in the table s = grass.read_command('db.columns', table = table, database = database, driver = driver) if 'grassrgb' not in s.splitlines(): msg(locals(), _("Creating column 'grassrgb' in table <$table>")) sql = "ALTER TABLE %s ADD COLUMN grassrgb varchar(11)" % table grass.write_command('db.execute', database = database, driver = driver, stdin = sql) # Group name if not group: group = "themes" f_group = file(tmp_group, 'w') f_group.write("Group %s\n" % group) # Calculate statistics for thematic intervals if type == "line": stype = "line" else: stype = ["point", "centroid"] if not where: where = None stats = grass.read_command('v.univar', flags = 'eg', map = map, type = stype, column = column, where = where, layer = layer) stats = grass.parse_key_val(stats) min = float(stats['min']) max = float(stats['max']) mean = float(stats['mean']) sd = float(stats['population_stddev']) q1 = float(stats['first_quartile']) q2 = float(stats['median']) q3 = float(stats['third_quartile']) q4 = max ptsize = size if breakpoints and themecalc != "custom_breaks": grass.warning(_("Custom breakpoints ignored due to themecalc setting.")) # set interval for each thematic map calculation type if themecalc == "interval": numint = nint step = float(max - min) / numint breakpoints = [min + i * step for i in xrange(numint + 1)] annotations = "" elif themecalc == "std_deviation": # 2 standard deviation units on either side of mean, # plus min to -2 sd units and +2 sd units to max, if applicable breakpoints = [min] + [i for i in [(mean + i * sd) for i in [-2,-1,0,1,2]] if min < i < max] + [max] annotations = [""] + [("%dsd" % i) for (i, j) in [(i, mean + i * sd) for i in [-2,-1,0,1,2]] if (min < j < max)] + [""] annotations = ";".join(annotations) numint = len(breakpoints) - 1 elif themecalc == "quartiles": numint=4 # one for each quartile breakpoints = [min, q1, q2, q3, max] annotations = " %f; %f; %f; %f" % (q1, q2, q3, q4) elif themecalc == "custom_breaks": if not breakpoints: breakpoints = sys.stdin.read() breakpoints = [int(x) for x in breakpoints.split()] numint = len(breakpoints) - 1 annotations = "" else: grass.fatal(_("Unknown themecalc type <%s>") % themecalc) pointstep = (maxsize - ptsize) / (numint - 1) # Prepare legend cuts for too large numint if numint > max_leg_items: xupper = int(numint - max_leg_items / 2) + 1 xlower = int(max_leg_items / 2) + 1 else: xupper = 0 xlower = 0 # legend title f_graph = file(tmp_graph, 'w') out(f_graph, locals(), """\ color 0:0:0 size 2 2 move 1 95 text Thematic map legend for column $column of map $map size 1.5 1.8 move 4 90 text Value range: $min - $max """) f_gisleg = file(tmp_gisleg, 'w') out(f_gisleg, locals(), """\ title - - - {Thematic map legend for column $column of map $map} """) f_psleg = file(tmp_psleg, 'w') out(f_psleg, locals(), """\ text 1% 95% Thematic map legend for column $column of map $map ref bottom left end text 4% 90% Value range: $min - $max ref bottom left end """) msg(locals(), _("Thematic map legend for column $column of map $map")) msg(locals(), _("Value range: $min - $max")) colorschemes = { "blue-red": ("0:0:255", "255:0:0"), "red-blue": ("255:0:0", "0:0:255"), "green-red": ("0:255:0", "255:0:0"), "red-green": ("255:0:0", "0:255:0"), "blue-green": ("0:0:255", "0:255:0"), "green-blue": ("0:255:0", "0:0:255"), "cyan-yellow": ("0:255:255", "255:255:0"), "yellow-cyan": ("255:255:0", "0:255:255"), "custom_gradient": (startcolor, endcolor) } # open file for psmap instructions f_psmap = file(tmp_psmap, 'w') # graduated color thematic mapping if themetype == "graduated_colors": if colorscheme in colorschemes: startc, endc = colorschemes[colorscheme] # set color schemes for graduated color maps elif colorscheme == "single_color": if themetype == "graduated_points": startc = endc = linecolor else: startc = endc = pointcolor else: grass.fatal(_("This should not happen: parser error. Unknown color scheme %s") % colorscheme) color = __builtins__.map(int, startc.split(":")) endcolor = __builtins__.map(int, endc.split(":")) #The number of color steps is one less then the number of classes nclrstep = numint - 1 clrstep = [(a - b) / nclrstep for a, b in zip(color, endcolor)] themecolor = startc # display graduated color themes if themecalc == "interval": out(f_graph, locals(), """\ move 4 87 text Mapped by $numint intervals of $step """) out(f_gisleg, locals(), """\ subtitle - - - {Mapped by $numint intervals of $step} """) out(f_psleg, locals(), """\ text 4% 87% Mapped by $numint intervals of $step ref bottom left end """) msg(locals(), _("Mapped by $numint intervals of $step")) # display graduated color themes for standard deviation units if themecalc == "std_deviation": out(f_graph, locals(), """\ move 4 87 text Mapped by standard deviation units of $sd (mean = $mean) """) out(f_gisleg, locals(), """\ subtitle - - - {Mapped by standard deviation units of $sd (mean = $mean)} """) out(f_psleg, locals(), """\ text 4% 87% Mapped by standard deviation units of $sd (mean = $mean) ref bottom left end """) msg(locals(), _("Mapped by standard deviation units of $sd (mean = $mean)")) # display graduated color themes for quartiles if themecalc == "quartiles": out(f_graph, locals(), """\ move 4 87 text Mapped by quartiles (median = $q2) """) out(f_gisleg, locals(), """\ subtitle - - - {Mapped by quartiles (median = $q2)} """) out(f_psleg, locals(), """\ text 4% 87% Mapped by quartiles (median = $q2) ref bottom left end """) msg(locals(), _("Mapped by quartiles (median = $q2)")) f_graph.write("""\ move 4 83 text Color move 14 83 text Value move 4 80 text ===== move 14 80 text ============ """) f_psleg.write("""\ text 4% 83% Color ref bottom left end text 14% 83% Value ref bottom left end text 4% 80% ===== ref bottom left end text 14% 80% ============ ref bottom left end """) sys.stdout.write("Color(R:G:B)\tValue\n") sys.stdout.write("============\t==========\n") line1 = 78 line2 = 76 line3 = 75 i = 1 first = True while i < numint: if flag_m: # math notation if first: closebracket = "]" openbracket = "[" mincomparison = ">=" first = False else: closebracket = "]" openbracket = "]" mincomparison = ">" else: closebracket = "" openbracket = "" if first: mincomparison = ">=" first = False else: mincomparison = ">" themecolor = ":".join(__builtins__.map(str,color)) if flag_f: linecolor = "none" else: if type in ["line", "boundary"]: linecolor = themecolor else: linecolor = linecolor rangemin = __builtins__.min(breakpoints) rangemax = __builtins__.max(breakpoints) if not annotations: extranote = "" else: extranote = annotations[i] if i < xlower or i >= xupper: xline1 = line2 + 2 xline3 = line2 - 1 out(f_graph, locals(), """\ color $themecolor polygon 5 $xline1 8 $xline1 8 $xline3 5 $xline3 color $linecolor move 5 $xline1 draw 8 $xline1 draw 8 $xline3 draw 5 $xline3 draw 5 $xline1 move 14 $line2 color 0:0:0 text $openbracket$rangemin - $rangemax$closebracket $extranote """) else: if i == xlower: out(f_graph, locals(), """\ color 0:0:0 move 10 $line2 text ... """) else: #undo next increment line2 += 4 if i < xlower or i >= xupper: out(f_gisleg, locals(), """\ area $themecolor $linecolor - {$openbracket$rangemin - $rangemax$closebracket $extranote} """) if type in ["line", "boundary"]: out(f_psleg, locals(), """\ line 5% $xline1% 8% $xline1% color $linecolor end text 14% $xline1% $openbracket$rangemin - $rangemax$closebracket $extranote ref center left end """) elif type in ["point", "centroid"]: out(f_psleg, locals(), """\ point 8% $xline1% color $linecolor fcolor $themecolor size $size symbol $icon end text 14% $xline1% $openbracket$rangemin - $rangemax$closebracket $extranote ref center left end """) else: out(f_psleg, locals(), """\ rectangle 5% $xline1% 8% $xline3% color 0:0:0 fcolor $themecolor end text 14% $xline3% $openbracket$rangemin - $rangemax$closebracket DCADCA $extranote ref bottom left end """) else: if i == xlower: out(f_psleg, locals(), """\ color 0:0:0 text 14% $xline3% ... ref bottom left end """) f_gisleg.write("text - - - {...}\n") sys.stdout.write(subs(locals(), "$themecolor\t\t$openbracket$rangemin - $rangemax$closebracket $extranote\n")) if not where: sqlwhere = subs(locals(), "$column $mincomparison $rangemin AND $column <= $rangemax") else: sqlwhere = subs(locals(), "$column $mincomparison $rangemin AND $column <= $rangemax AND $where") # update color to database? if flag_u: sql = subs(locals(), "UPDATE $table SET GRASSRGB = '$themecolor' WHERE $sqlwhere") grass.write_command('db.execute', database = database, driver = driver, stdin = sql) # Create group for GIS Manager if flag_g: # change rgb colors to hex xthemecolor = "#%02X%02X%02X" % tuple(__builtins__.map(int, themecolor.split(":"))) #xlinecolor=`echo $linecolor | awk -F: '{printf("#%02X%02X%02X\n",$1,$2,$3)}'` if "$linecolor" == "black": xlinecolor = "#000000" else: xlinecolor = xthemecolor # create group entry out(f_group, locals(), """\ _check 1 Vector $column = $rangemin - $rangemax _check 1 map $map display_shape 1 display_cat 0 display_topo 0 display_dir 0 display_attr 0 type_point $ptype type_line $ltype type_boundary $btype type_centroid $ctype type_area $atype type_face 0 color $xlinecolor fcolor $xthemecolor width $ptsize _use_fcolor 1 lcolor #000000 sqlcolor 0 icon $icon size $ptsize field $layer lfield $layer attribute xref left yref center lsize 8 cat where $sqlwhere _query_text 0 _query_edit 1 _use_where 1 minreg maxreg _width 0.1 End """) # display theme vector map grass.run_command('d.vect', map = map, type = type, layer = layer, where = sqlwhere, color = linecolor, fcolor = themecolor, icon = icon, size = ptsize) if type in ["line", "boundary"]: out(f_psmap, locals(), """\ vlines $map type $type layer $layer where $sqlwhere color $linecolor label $rangemin - $rangemax end """) elif type in ["point", "centroid"]: out(f_psmap, locals(), """\ vpoints $map type $type layer $layer where $sqlwhere color $linecolor fcolor $themecolor symbol $icon label $rangemin - $rangemax end """) else: out(f_psmap, locals(), """\ vareas $map layer $layer where $sqlwhere color $linecolor fcolor $themecolor label $rangemin - $rangemax end """) # increment for next theme i += 1 if i == numint: color = endcolor else: color = [a - b for a, b in zip(color, clrstep)] line1 -= 4 line2 -= 4 line3 -= 4 #graduated points and line widths thematic mapping if themetype in ["graduated_points", "graduated_lines"]: #display graduated points/lines by intervals if themecalc == "interval": out(f_graph, locals(), """\ move 4 87 text Mapped by $numint intervals of $step """) out(f_gisleg, locals(), """\ subtitle - - - {Mapped by $numint intervals of $step} """) out(f_psleg, locals(), """\ text 4% 87% Mapped by $numint intervals of $step ref bottom left end """) msg(locals(), _("Mapped by $numint intervals of $step")) # display graduated points/lines for standard deviation units if themecalc == "std_deviation": out(f_graph, locals(), """\ move 4 87 text Mapped by standard deviation units of $sd (mean = $mean) """) out(f_gisleg, locals(), """\ subtitle - - - {Mapped by standard deviation units of $sd (mean = $mean)} """) out(f_psleg, locals(), """\ text 4% 87% Mapped by standard deviation units of $sd (mean = $mean) ref bottom left end """) msg(locals(), _("Mapped by standard deviation units of $sd (mean = $mean)")) # display graduated points/lines for quartiles if themecalc == "quartiles": out(f_graph, locals(), """\ move 4 87 text Mapped by quartiles (median = $q2) """) out(f_gisleg, locals(), """\ subtitle - - - {Mapped by quartiles (median = $q2)} """) out(f_psleg, locals(), """\ text 4% 87% Mapped by quartiles (median = $q2) ref bottom left end """) msg(locals(), _("Mapped by quartiles (median = $q2)")) line1 = 76 line2 = 75 out(f_graph, locals(), """\ move 4 83 text Size/width move 25 83 text Value move 4 80 text ============== move 25 80 text ============== """) out(f_psleg, locals(), """\ text 4% 83% Icon size ref bottom left end text 25% 83% Value ref bottom left end text 4% 80% ============ ref bottom left end text 25% 80% ============ ref bottom left end """) sys.stdout.write("Size/width\tValue\n") sys.stdout.write("==========\t=====\n") themecolor = pointcolor if flag_f: linecolor = "none" i = numint ptsize = maxsize while i >= 1: if flag_m: # math notation if i == 1: closebracket = "]" openbracket = "[" mincomparison = ">=" else: closebracket = "]" openbracket = "]" mincomparison = ">" else: closebracket = "" openbracket = "" if i == 1: mincomparison = ">=" else: mincomparison = ">" themecolor = pointcolor if flag_f: linecolor = "none" rangemin = __builtins__.min(breakpoints) rangemax = __builtins__.max(breakpoints) if not annotations: extranote = "" else: extranote = annotations[i] iconsize = int(ptsize / 2) lineht = int(ptsize / 4) if lineht < 4: lineht = 4 if i < xlower or i >= xupper: if themetype == "graduated_lines": out(f_graph, locals(), """\ color $linecolor """) out(f_gisleg, locals(), """\ line $themecolor $linecolor $ptsize {$openbracket$rangemin - $rangemax$closebracket $extranote} """) else: out(f_graph, locals(), """\ color $themecolor """) out(f_gisleg, locals(), """\ point $themecolor $linecolor $ptsize {$openbracket$rangemin - $rangemax$closebracket $extranote} """) out(f_graph, locals(), """\ icon + $iconsize 5 $line1 color 0:0:0 move 10 $line2 text $ptsize pts move 25 $line2 text $openbracket$rangemin - $rangemax$closebracket $extranote """) else: if i == xlower: out(f_graph, locals(), """\ color 0:0:0 move 10 $line2 text ... """) out(f_gisleg, locals(), """\ text - - - ... """) else: # undo future line increment line2 += lineht if i < xlower or i >= xupper: out(f_psleg, locals(), """\ point 8% $line1% color $linecolor fcolor $themecolor size $iconsize symbol $icon end text 25% $line1% $openbracket$rangemin - $rangemax$closebracket $extranote ref center left end """) else: if i == xlower: out(f_psleg, locals(), """\ text 25% $xline1% ... ref center left end """) sys.stdout.write(subs(locals(), "$ptsize\t\t$openbracket$rangemin - $rangemax$closebracket $extranote\n")) if not where: sqlwhere = subs(locals(), "$column $mincomparison $rangemin AND $column <= $rangemax") else: sqlwhere = subs(locals(), "$column $mincomparison $rangemin AND $column <= $rangemax AND $where") # update color to database? if flag_u: sql = subs(locals(), "UPDATE $table SET grassrgb = '$themecolor' WHERE $sqlwhere") grass.write_command('db.execute', database = database, driver = driver, stdin = sql) # Create group for GIS Manager if flag_g: # change rgb colors to hex xthemecolor = "#%02X%02X%02X" % tuple(__builtins__.map(int,themecolor.split(":"))) xlinecolor = "#000000" # create group entry out(f_group, locals(), """\ _check 1 Vector $column = $rangemin - $rangemax _check 1 map $map display_shape 1 display_cat 0 display_topo 0 display_dir 0 display_attr 0 type_point $ptype type_line $ltype type_boundary $btype type_centroid $ctype type_area $atype type_face 0 color $xlinecolor width $ptsize fcolor $xthemecolor _use_fcolor 1 lcolor #000000 sqlcolor 0 icon $icon size $ptsize field $layer lfield $layer attribute xref left yref center lsize 8 cat where $sqlwhere _query_text 0 _query_edit 1 _use_where 1 minreg maxreg _width 0.1 End """) #graduates line widths or point sizes if themetype == "graduated_lines": grass.run_command('d.vect', map = map, type = type, layer = layer, where = sqlwhere, color = linecolor, fcolor = themecolor, icon = icon, size = ptsize, width = ptsize) else: grass.run_command('d.vect', map = map, type = type, layer = layer, where = sqlwhere, color = linecolor, fcolor = themecolor, icon = icon, size = ptsize) out(f_psmap, locals(), """\ vpoints $map type $type layer $layer where $sqlwhere color $linecolor fcolor $themecolor symbol $icon size $ptsize label $rangemin - $rangemax end """) ptsize -= pointstep line1 -= lineht line2 -= lineht i -= 1 # Create graphic legend f_graph.close() if flag_l: grass.run_command('d.erase') grass.run_command('d.graph', input = tmp_graph) # Create group file for GIS Manager f_group.write("End\n") f_group.close() if flag_g: shutil.copyfile(tmp_group, "%s.dm" % group) # Create ps.map map file f_psmap.write("end\n") f_psmap.close() if psmap: shutil.copyfile(tmp_psmap, "%s.psmap" % psmap) # Create ps.map legend file f_psleg.write("end\n") f_psleg.close() if psmap: shutil.copyfile(tmp_psleg, "%s_legend.psmap" % psmap) # Create text file to use with d.graph in GIS Manager f_gisleg.close() if flag_s: tmpdir = os.path.dirname(tmp_gisleg) tlegfile = os.path.join(tmpdir, "gismlegend.txt") shutil.copyfile(tmp_gisleg, tlegfile)
def main(): global TMPLOC, SRCGISRC, GISDBASE, TMP_REG_NAME GDALdatasource = options['input'] output = options['output'] method = options['resample'] memory = options['memory'] bands = options['band'] tgtres = options['resolution'] title = options["title"] if options['resolution_value']: if tgtres != 'value': grass.fatal(_("To set custom resolution value, select 'value' in resolution option")) tgtres_value = float(options['resolution_value']) if tgtres_value <= 0: grass.fatal(_("Resolution value can't be smaller than 0")) elif tgtres == 'value': grass.fatal(_("Please provide the resolution for the imported dataset or change to 'estimated' resolution")) grassenv = grass.gisenv() tgtloc = grassenv['LOCATION_NAME'] tgtmapset = grassenv['MAPSET'] GISDBASE = grassenv['GISDBASE'] tgtgisrc = os.environ['GISRC'] SRCGISRC = grass.tempfile() TMPLOC = 'temp_import_location_' + str(os.getpid()) f = open(SRCGISRC, 'w') f.write('MAPSET: PERMANENT\n') f.write('GISDBASE: %s\n' % GISDBASE) f.write('LOCATION_NAME: %s\n' % TMPLOC) f.write('GUI: text\n') f.close() tgtsrs = grass.read_command('g.proj', flags='j', quiet=True) # create temp location from input without import grass.verbose(_("Creating temporary location for <%s>...") % GDALdatasource) parameters = dict(input=GDALdatasource, output=output, memory=memory, flags='c', title=title, location=TMPLOC, quiet=True) if bands: parameters['band'] = bands try: grass.run_command('r.in.gdal', **parameters) except CalledModuleError: grass.fatal(_("Unable to read GDAL dataset <%s>") % GDALdatasource) # switch to temp location os.environ['GISRC'] = str(SRCGISRC) # switch to target location os.environ['GISRC'] = str(tgtgisrc) # try r.in.gdal directly first additional_flags = 'l' if flags['l'] else '' if flags['o']: additional_flags += 'o' if flags['o'] or grass.run_command('r.in.gdal', input=GDALdatasource, flags='j', errors='status', quiet=True) == 0: parameters = dict(input=GDALdatasource, output=output, memory=memory, flags='k' + additional_flags) if bands: parameters['band'] = bands try: grass.run_command('r.in.gdal', **parameters) grass.verbose(_("Input <%s> successfully imported without reprojection") % GDALdatasource) return 0 except CalledModuleError as e: grass.fatal(_("Unable to import GDAL dataset <%s>") % GDALdatasource) # make sure target is not xy if grass.parse_command('g.proj', flags='g')['name'] == 'xy_location_unprojected': grass.fatal(_("Coordinate reference system not available for current location <%s>") % tgtloc) # switch to temp location os.environ['GISRC'] = str(SRCGISRC) # make sure input is not xy if grass.parse_command('g.proj', flags='g')['name'] == 'xy_location_unprojected': grass.fatal(_("Coordinate reference system not available for input <%s>") % GDALdatasource) # import into temp location grass.verbose(_("Importing <%s> to temporary location...") % GDALdatasource) parameters = dict(input=GDALdatasource, output=output, memory=memory, flags='k' + additional_flags) if bands: parameters['band'] = bands try: grass.run_command('r.in.gdal', **parameters) except CalledModuleError: grass.fatal(_("Unable to import GDAL dataset <%s>") % GDALdatasource) outfiles = grass.list_grouped('raster')['PERMANENT'] # is output a group? group = False path = os.path.join(GISDBASE, TMPLOC, 'group', output) if os.path.exists(path): group = True path = os.path.join(GISDBASE, TMPLOC, 'group', output, 'POINTS') if os.path.exists(path): grass.fatal(_("Input contains GCPs, rectification is required")) # switch to target location os.environ['GISRC'] = str(tgtgisrc) region = grass.region() rflags = None if flags['n']: rflags = 'n' for outfile in outfiles: n = region['n'] s = region['s'] e = region['e'] w = region['w'] grass.use_temp_region() if options['extent'] == 'input': # r.proj -g try: tgtextents = grass.read_command('r.proj', location=TMPLOC, mapset='PERMANENT', input=outfile, flags='g', memory=memory, quiet=True) except CalledModuleError: grass.fatal(_("Unable to get reprojected map extent")) try: srcregion = grass.parse_key_val(tgtextents, val_type=float, vsep=' ') n = srcregion['n'] s = srcregion['s'] e = srcregion['e'] w = srcregion['w'] except ValueError: # import into latlong, expect 53:39:06.894826N srcregion = grass.parse_key_val(tgtextents, vsep=' ') n = grass.float_or_dms(srcregion['n'][:-1]) * \ (-1 if srcregion['n'][-1] == 'S' else 1) s = grass.float_or_dms(srcregion['s'][:-1]) * \ (-1 if srcregion['s'][-1] == 'S' else 1) e = grass.float_or_dms(srcregion['e'][:-1]) * \ (-1 if srcregion['e'][-1] == 'W' else 1) w = grass.float_or_dms(srcregion['w'][:-1]) * \ (-1 if srcregion['w'][-1] == 'W' else 1) grass.run_command('g.region', n=n, s=s, e=e, w=w) # v.in.region in tgt vreg = TMP_REG_NAME = 'vreg_tmp_' + str(os.getpid()) grass.run_command('v.in.region', output=vreg, quiet=True) grass.del_temp_region() # reproject to src # switch to temp location os.environ['GISRC'] = str(SRCGISRC) try: grass.run_command('v.proj', input=vreg, output=vreg, location=tgtloc, mapset=tgtmapset, quiet=True) except CalledModuleError: grass.fatal(_("Unable to reproject to source location")) # set region from region vector grass.run_command('g.region', raster=outfile) grass.run_command('g.region', vector=vreg) # align to first band grass.run_command('g.region', align=outfile) # get number of cells cells = grass.region()['cells'] estres = math.sqrt((n - s) * (e - w) / cells) # remove from source location for multi bands import grass.run_command('g.remove', type='vector', name=vreg, flags='f', quiet=True) os.environ['GISRC'] = str(tgtgisrc) grass.run_command('g.remove', type='vector', name=vreg, flags='f', quiet=True) grass.message(_("Estimated target resolution for input band <{out}>: {res}").format(out=outfile, res=estres)) if flags['e']: continue if options['extent'] == 'input': grass.use_temp_region() grass.run_command('g.region', n=n, s=s, e=e, w=w) res = None if tgtres == 'estimated': res = estres elif tgtres == 'value': res = tgtres_value grass.message(_("Using given resolution for input band <{out}>: {res}").format(out=outfile, res=res)) # align to requested resolution grass.run_command('g.region', res=res, flags='a') else: curr_reg = grass.region() grass.message(_("Using current region resolution for input band " "<{out}>: nsres={ns}, ewres={ew}").format(out=outfile, ns=curr_reg['nsres'], ew=curr_reg['ewres'])) # r.proj grass.message(_("Reprojecting <%s>...") % outfile) try: grass.run_command('r.proj', location=TMPLOC, mapset='PERMANENT', input=outfile, method=method, resolution=res, memory=memory, flags=rflags, quiet=True) except CalledModuleError: grass.fatal(_("Unable to to reproject raster <%s>") % outfile) if grass.raster_info(outfile)['min'] is None: grass.fatal(_("The reprojected raster <%s> is empty") % outfile) if options['extent'] == 'input': grass.del_temp_region() if flags['e']: return 0 if group: grass.run_command('i.group', group=output, input=','.join(outfiles)) # TODO: write metadata with r.support return 0
def main(): global temp_dist, temp_src input = options['input'] output = options['output'] distances = options['distances'] units = options['units'] zero = flags['z'] tmp = str(os.getpid()) temp_dist = "r.buffer.tmp.%s.dist" % tmp temp_src = "r.buffer.tmp.%s.src" % tmp #check if input file exists if not grass.find_file(input)['file']: grass.fatal(_("<%s> does not exist.") % input) scale = scales[units] distances = distances.split(',') distances1 = [scale * float(d) for d in distances] distances2 = [d * d for d in distances1] s = grass.read_command("g.proj", flags='j') kv = grass.parse_key_val(s) if kv['+proj'] == 'longlat': metric = 'geodesic' else: metric = 'squared' grass.run_command('r.grow.distance', input = input, metric = metric, distance = temp_dist) if zero: exp = "$temp_src = if($input == 0,null(),1)" else: exp = "$temp_src = if(isnull($input),null(),1)" grass.message(_("Extracting buffers (1/2)...")) grass.mapcalc(exp, temp_src = temp_src, input = input) exp = "$output = if(!isnull($input),$input,%s)" for n, dist2 in enumerate(distances2): exp %= "if($dist <= %f,%d,%%s)" % (dist2,n + 2) exp %= "null()" grass.message(_("Extracting buffers (2/2)...")) grass.mapcalc(exp, output = output, input = temp_src, dist = temp_dist) p = grass.feed_command('r.category', map = output, rules = '-') p.stdin.write("1:distances calculated from these locations\n") d0 = "0" for n, d in enumerate(distances): p.stdin.write("%d:%s-%s %s\n" % (n + 2, d0, d, units)) d0 = d p.stdin.close() p.wait() grass.run_command('r.colors', map = output, color = 'rainbow') # write cmd history: grass.raster_history(output)
def create_lcp_corridors(friction, pairs, locs, lcp_network): """ Loop thru all pairs of localities in the pairs list FOr each pair, find the indexes, codes and X-Y coords of that pair from the localities list, Use r.cost to make cost maps using the coordinate paramter Combine each pair of cost maps to create the corridor Get the minimum for each corridor using r.univar, Use that minimum to make a reclass file with values: min = 5 Min value min + 5% = 3 Two percent above min + 8% = 1 Five percent above * = NULL NULL Run r.reclass to create uniform reclass rasters for each pair """ grass.message(" === Creating corridors ===") cnt = 0 for i in range(len(pairs)): id1, id2 = pairs[i][0], pairs[i][1] this_pair = str(id1)+","+str(id2) for j in range(len(locs)): # Find the locality code that matches each index id1 and id2 # Get X-Y coords for each locality if int(locs[j][1]) == id1: code1 = locs[j][2] x1, y1 = locs[j][3], locs[j][4] elif int(locs[j][1]) == id2: code2 = locs[j][2] x2, y2 = locs[j][3], locs[j][4] # Some pairs might not be in the sampling sites list at all. # Check if both codes are found before continuing try: code1 and code2 except NameError: grass.message("The pair: "+this_pair+" is not in the localities list. Ignoring...") else: # Create both cost maps (one for each locality in the pair) cnt += 1 cost1, cost2 = "cost_"+code1, "cost_"+code2 start1=x1+","+y1 start2=x2+","+y2 grass.run_command('r.cost', input=friction, output=cost1, coordinate=start1, overwrite=True, quiet=True) grass.run_command('r.cost', input=friction, output=cost2, coordinate=start2, overwrite=True, quiet=True) # Now combine the cost maps into a corridor corridor = "corr_"+code1+"_"+code2 corridor_expr = corridor+"=round("+cost1+"+"+cost2+")" grass.mapcalc(corridor_expr, overwrite=True) # Get minimum value from the corridor map u = grass.read_command('r.univar', map=corridor, flags="g", quiet=True) udict = grass.parse_key_val(u) min = float(udict['min']) one_pc = min*1.01 three_pc = min*1.03 five_pc = min*1.05 # Create reclass file tmp_reclass = grass.tempfile() trc = open(tmp_reclass, "w") # Convert to int for output to the reclass file trc.write(str(int(min))+" thru "+str(int(one_pc)) + " = 5 \t Minimum\n") trc.write(str(int(one_pc)) + " thru " + str(int(three_pc)) + " = 3 \t Three percent\n") trc.write(str(int(three_pc)) + " thru " +str(int(five_pc)) + " = 1 \t Five percent\n") trc.write("* = NULL \t NULL\n") trc.close() # Now create reclass raster lcp = "lcp_"+code1+"_"+code2 grass.run_command('r.reclass',input=corridor,output=lcp, rule=tmp_reclass, overwrite=True, quiet=True) grass.run_command('r.colors', map=lcp, color="ryg", quiet=True) # Get rid of tmp reclass file and cost raster os.unlink(tmp_reclass) grass.run_command('g.mremove', rast="cost_*", quiet=True, flags="f") # Now merge all lcp_* maps lcp_maps = grass.read_command('g.mlist', type="rast", pattern="lcp_*", separator=",").rstrip() grass.run_command('r.series',input = lcp_maps, output = lcp_network, method="sum", overwrite=True, quiet=True) grass.run_command('r.colors', map=lcp_network, color="ryg", quiet=True) return cnt