def _computeRegions(self, count, startRegion, endRegion=None, zoomValue=None): """Computes regions based on start region and end region or zoom value for each of the animation frames.""" region = dict(gcore.region()) # cast to dict, otherwise deepcopy error if startRegion: region = dict( parse_key_val( gcore.read_command("g.region", flags="gu", region=startRegion), val_type=float, )) del region["cells"] del region["cols"] del region["rows"] if "projection" in region: del region["projection"] if "zone" in region: del region["zone"] regions = [] for i in range(self._mapCount): regions.append(copy.copy(region)) self._regions = regions if not (endRegion or zoomValue): return startRegionDict = parse_key_val( gcore.read_command("g.region", flags="gu", region=startRegion), val_type=float, ) if endRegion: endRegionDict = parse_key_val( gcore.read_command("g.region", flags="gu", region=endRegion), val_type=float, ) for key in ("n", "s", "e", "w", "nsres", "ewres"): values = interpolate(startRegionDict[key], endRegionDict[key], self._mapCount) for value, region in zip(values, regions): region[key] = value elif zoomValue: for i in range(self._mapCount): regions[i]["n"] -= zoomValue[0] * i regions[i]["e"] -= zoomValue[1] * i regions[i]["s"] += zoomValue[0] * i regions[i]["w"] += zoomValue[1] * i # handle cases when north < south and similarly EW if (regions[i]["n"] < regions[i]["s"] or regions[i]["e"] < regions[i]["w"]): regions[i] = regions[i - 1] self._regions = regions
def _computeRegions(self, width, height, count, startRegion, endRegion=None, zoomValue=None): """Computes regions based on start region and end region or zoom value for each of the animation frames.""" currRegion = dict( gcore.region()) # cast to dict, otherwise deepcopy error del currRegion['cells'] del currRegion['cols'] del currRegion['rows'] regions = [] for i in range(self._mapCount): if endRegion or zoomValue: regions.append(copy.copy(currRegion)) else: regions.append(None) if not startRegion: self._regions = regions return startRegionDict = parse_key_val(gcore.read_command('g.region', flags='gu', region=startRegion), val_type=float) if endRegion: endRegionDict = parse_key_val(gcore.read_command('g.region', flags='gu', region=endRegion), val_type=float) for key in ('n', 's', 'e', 'w'): values = interpolate(startRegionDict[key], endRegionDict[key], self._mapCount) for value, region in zip(values, regions): region[key] = value elif zoomValue: for i in range(self._mapCount): regions[i]['n'] -= zoomValue[0] * i regions[i]['e'] -= zoomValue[1] * i regions[i]['s'] += zoomValue[0] * i regions[i]['w'] += zoomValue[1] * i # handle cases when north < south and similarly EW if regions[i]['n'] < regions[i]['s'] or \ regions[i]['e'] < regions[i]['w']: regions[i] = regions[i - 1] for region in regions: mapwidth = abs(region['e'] - region['w']) mapheight = abs(region['n'] - region['s']) region['nsres'] = mapheight / height region['ewres'] = mapwidth / width self._regions = regions
def _computeRegions(self, count, startRegion, endRegion=None, zoomValue=None): """Computes regions based on start region and end region or zoom value for each of the animation frames.""" region = dict(gcore.region()) # cast to dict, otherwise deepcopy error if startRegion: region = dict( parse_key_val(gcore.read_command('g.region', flags='gu', region=startRegion), val_type=float)) del region['cells'] del region['cols'] del region['rows'] if 'projection' in region: del region['projection'] if 'zone' in region: del region['zone'] regions = [] for i in range(self._mapCount): regions.append(copy.copy(region)) self._regions = regions if not (endRegion or zoomValue): return startRegionDict = parse_key_val(gcore.read_command('g.region', flags='gu', region=startRegion), val_type=float) if endRegion: endRegionDict = parse_key_val(gcore.read_command('g.region', flags='gu', region=endRegion), val_type=float) for key in ('n', 's', 'e', 'w', 'nsres', 'ewres'): values = interpolate(startRegionDict[key], endRegionDict[key], self._mapCount) for value, region in zip(values, regions): region[key] = value elif zoomValue: for i in range(self._mapCount): regions[i]['n'] -= zoomValue[0] * i regions[i]['e'] -= zoomValue[1] * i regions[i]['s'] += zoomValue[0] * i regions[i]['w'] += zoomValue[1] * i # handle cases when north < south and similarly EW if regions[i]['n'] < regions[i]['s'] or \ regions[i]['e'] < regions[i]['w']: regions[i] = regions[i - 1] self._regions = regions
def _computeRegions(self, width, height, count, startRegion, endRegion=None, zoomValue=None): """Computes regions based on start region and end region or zoom value for each of the animation frames.""" currRegion = dict(gcore.region()) # cast to dict, otherwise deepcopy error del currRegion['cells'] del currRegion['cols'] del currRegion['rows'] regions = [] for i in range(self._mapCount): if endRegion or zoomValue: regions.append(copy.copy(currRegion)) else: regions.append(None) if not startRegion: self._regions = regions return startRegionDict = parse_key_val(gcore.read_command('g.region', flags='gu', region=startRegion), val_type=float) if endRegion: endRegionDict = parse_key_val(gcore.read_command('g.region', flags='gu', region=endRegion), val_type=float) for key in ('n', 's', 'e', 'w'): values = interpolate(startRegionDict[key], endRegionDict[key], self._mapCount) for value, region in zip(values, regions): region[key] = value elif zoomValue: for i in range(self._mapCount): regions[i]['n'] -= zoomValue[0] * i regions[i]['e'] -= zoomValue[1] * i regions[i]['s'] += zoomValue[0] * i regions[i]['w'] += zoomValue[1] * i # handle cases when north < south and similarly EW if regions[i]['n'] < regions[i]['s'] or \ regions[i]['e'] < regions[i]['w']: regions[i] = regions[i - 1] for region in regions: mapwidth = abs(region['e'] - region['w']) mapheight = abs(region['n'] - region['s']) region['nsres'] = mapheight / height region['ewres'] = mapwidth / width self._regions = regions
def MeasureArea(self, coords): """Calculate area and print to output window. :param coords: list of E, N coordinates """ # TODO: make sure appending first point is needed for m.measure coordinates = coords + [coords[0]] coordinates = ','.join([str(item) for sublist in coordinates for item in sublist]) result = RunCommand( 'm.measure', flags='g', coordinates=coordinates, read=True).strip() result = parse_key_val(result) if 'units' not in result: self._giface.WriteWarning( _("Units not recognized, measurement failed.")) unit = '' else: unit = result['units'].split(',')[1] if 'area' not in result: text = _("Area: {area} {unit}\n").format(area=0, unit=unit) else: text = _("Area: {area} {unit}\n").format( area=result['area'], unit=unit) self._giface.WriteLog(text, notification=Notification.MAKE_VISIBLE)
def linear_regression(self, x, y): """ Simple wrapper around the GRASS GIS module r.regression.line Parameters ---------- x : str Name of GRASS GIS raster map to use as the x-variable. Has to be within the RasterStack object. y : str Name of GRASS GIS raster map to use as the y-variable. Returns ------- dict Containing the regression statistics. """ regr = r.regression_line(mapx=x, mapy=y, flags="g", stdout_=PIPE).outputs.stdout.strip() regr = parse_key_val(regr, sep="=") return regr
def parse_tiles(tiles): # convert r.tileset output into list of dicts tiles = [i.split(';') for i in tiles] tiles = [[parse_key_val(i) for i in t] for t in tiles] tiles_reg = [] for index, tile in enumerate(tiles): tiles_reg.append({}) for param in tile: tiles_reg[index].update(param) return(tiles_reg)
def map_exists(name, type, mapset=None): """Check if map exists :param name: name of the map (without a Mapset) :param type: data type ('raster', 'raster_3d', and 'vector') :param mapset: Mapset (you can use dot to refer to the current Mapset) """ # change type to element used by find file # otherwise, we are not checking the input, # so anything accepted by g.findfile will work # also supporting both short and full names # but this can change in the # future (this function documentation is clear about what's legal) if type == "raster" or type == "rast": type = "cell" elif type == "raster_3d" or type == "rast3d" or type == "raster3d": type = "grid3" elif type == "vect": type = "vector" extra_params = {} if mapset: if mapset == ".": mapset = get_current_mapset() extra_params.update({"mapset": mapset}) # g.findfile returns non-zero when file was not found # so we ignore return code and just focus on stdout process = start_command( "g.findfile", flags="n", element=type, file=name, mapset=mapset, stdout=PIPE, stderr=PIPE, **extra_params, ) output, errors = process.communicate() info = parse_key_val(output) # file is the key questioned in grass.script.core find_file() # return code should be equivalent to checking the output # g.findfile returns non-zero when nothing found but scripts are used to # check the output, so it is unclear what should be or is the actual # g.findfile interface # see also #2475 for discussion about types/files if info["file"]: return True else: return False
def multiple_regression(self, xs, y, estimates=None, residuals=None, overwrite=False): """ Simple wrapper around the GRASS GIS module r.regression.multi Parameters ---------- x : str Name of GRASS GIS raster map to use as the x-variable. Has to be within the RasterStack object. y : str Name of GRASS GIS raster map to use as the y-variable. estimates : str (opt) Optionally specify a name to create a raster map of the regression estimate. residuals : str (opt) Optionally specify a name to create a raste rmap of the residuals. overwrite : bool (default is False) Overwrite existing GRASS GIS rasters for estimates and residuals. Returns ------- dict Containing the regression statistics. """ regr = r.regression_multi( mapx=xs, mapy=y, flags="g", residuals=residuals, estimates=estimates, overwrite=overwrite, stdout_=PIPE, ).outputs.stdout.strip() regr = parse_key_val(regr, sep="=") return regr
def main(): os.environ["GRASS_RENDER_IMMEDIATE"] = "png" os.environ["GRASS_RENDER_FILE"] = options["output"] os.environ["GRASS_RENDER_FILE_COMPRESSION"] = options["compression"] os.environ["GRASS_RENDER_WIDTH"] = options["width"] os.environ["GRASS_RENDER_HEIGHT"] = options["height"] if flags["w"]: # get display region info s = grass.read_command("d.info", flags="g") win = grassutils.parse_key_val(s, val_type=float) monitor_old = None genv = gisenv() if "MONITOR" in genv: monitor_old = genv["MONITOR"] g.gisenv(unset="MONITOR") if options["rgb_column"]: d.vect( map=options["input"], rgb_column=options["rgb_column"], flags="a", quiet=True, ) else: d.vect(map=options["input"]) if monitor_old: g.gisenv(set="MONITOR=%s" % monitor_old) if flags["w"]: wldfile = options["output"].split(".")[0] + ".wld" file_ = open(wldfile, "w") file_.write("%36.15f \n" % win["ewres"]) file_.write("%36.15f \n" % 0.0) file_.write("%36.15f \n" % 0.0) file_.write("%36.15f \n" % (-1 * win["nsres"])) file_.write("%36.15f \n" % (win["w"] + win["ewres"] / 2.0)) file_.write("%36.15f \n" % (win["n"] - win["nsres"] / 2.0)) file_.close()
def main(): os.environ['GRASS_RENDER_IMMEDIATE'] = 'png' os.environ['GRASS_RENDER_FILE'] = options['output'] os.environ['GRASS_RENDER_FILE_COMPRESSION'] = options['compression'] os.environ['GRASS_RENDER_WIDTH'] = options['width'] os.environ['GRASS_RENDER_HEIGHT'] = options['height'] if flags['w']: # get display region info s = grass.read_command('d.info', flags='g') win = grassutils.parse_key_val(s, val_type=float) monitor_old = None genv = gisenv() if 'MONITOR' in genv: monitor_old = genv['MONITOR'] g.gisenv(unset='MONITOR') if options['rgb_column']: d.vect(map=options['input'], rgb_column=options['rgb_column'], flags='a', quiet=True) else: d.vect(map=options['input']) if monitor_old: g.gisenv(set='MONITOR=%s' % monitor_old) if flags['w']: wldfile = options['output'].split('.')[0] + '.wld' file_ = open(wldfile, "w") file_.write("%36.15f \n" % win['ewres']) file_.write("%36.15f \n" % 0.0) file_.write("%36.15f \n" % 0.0) file_.write("%36.15f \n" % (-1 * win['nsres'])) file_.write("%36.15f \n" % (win['w'] + win['ewres'] / 2.0)) file_.write("%36.15f \n" % (win['n'] - win['nsres'] / 2.0)) file_.close()
def test_shell_script_style(self): self.assertDictEqual(parse_key_val(R_UNIVAR_KEYVAL_INT, val_type=int), R_UNIVAR_KEYVAL_INT_DICT)
def main(): fileorig = options['input'] filevect = options['output'] if not filevect: filevect = basename(fileorig, 'txt') #are we in LatLong location? s = grass.read_command("g.proj", flags='j') kv = parse_key_val(s) if kv['+proj'] != 'longlat': grass.fatal(_("This module only operates in LatLong/WGS84 locations")) #### setup temporary file tmpfile = grass.tempfile() coldescs = [("RC", "rc integer"), ("UFI", "uf1 integer"), ("UNI", "uni integer"), ("LAT", "lat double precision"), ("LONG", "lon double precision"), ("DMS_LAT", "dms_lat varchar(6)"), ("DMS_LONG", "dms_long varchar(7)"), ("UTM", "utm varchar(4)"), ("JOG", "jog varchar(7)"), ("FC", "fc varchar(1)"), ("DSG", "dsg varchar(5)"), ("PC", "pc integer"), ("CC1", "cci varchar(2)"), ("ADM1", "adm1 varchar(2)"), ("ADM2", "adm2 varchar(200)"), ("DIM", "dim integer"), ("CC2", "cc2 varchar(2)"), ("NT", "nt varchar(1)"), ("LC", "lc varchar(3)"), ("SHORT_FORM", "shortform varchar(128)"), ("GENERIC", "generic varchar(128)"), ("SORT_NAME", "sortname varchar(200)"), ("FULL_NAME", "fullname varchar(200)"), ("FULL_NAME_ND","funamesd varchar(200)"), ("MODIFY_DATE", "mod_date date")] colnames = [desc[0] for desc in coldescs] coltypes = dict([(desc[0], 'integer' in desc[1]) for desc in coldescs]) header = None num_places = 0 inf = file(fileorig) outf = file(tmpfile, 'wb') for line in inf: fields = line.rstrip('\r\n').split('\t') if not header: header = fields continue vars = dict(zip(header, fields)) fields2 = [] for col in colnames: if col in vars: if coltypes[col] and vars[col] == '': fields2.append('0') else: fields2.append(vars[col]) else: if coltypes[col]: fields2.append('0') else: fields2.append('') line2 = ';'.join(fields2) + '\n' outf.write(line2) num_places += 1 outf.close() inf.close() grass.message(_("Converted %d place names.") % num_places) #TODO: fix dms_lat,dms_long DDMMSS -> DD:MM:SS # Solution: # IN=DDMMSS # DEG=`echo $IN | cut -b1,2` # MIN=`echo $IN | cut -b3,4` # SEC=`echo $IN | cut -b5,6` # DEG_STR="$DEG:$MIN:$SEC" #modifications (to match DBF 10 char column name limit): # short_form -> shortform # sort_name -> sortname # full_name -> fullname # full_name_sd -> funamesd # pump data into GRASS: columns = [desc[1] for desc in coldescs] grass.run_command('v.in.ascii', cat = 0, x = 5, y = 4, sep = ';', input = tmpfile, output = filevect, columns = columns) try_remove(tmpfile) # write cmd history: vgrass.vector_history(filevect)
def main(): elevation = options['elevation'] slope = options['slope'] flat_thres = float(options['flat_thres']) curv_thres = float(options['curv_thres']) filter_size = int(options['filter_size']) counting_size = int(options['counting_size']) nclasses = int(options['classes']) texture = options['texture'] convexity = options['convexity'] concavity = options['concavity'] features = options['features'] # remove mapset from output name in case of overwriting existing map texture = texture.split('@')[0] convexity = convexity.split('@')[0] concavity = concavity.split('@')[0] features = features.split('@')[0] # store current region settings global current_reg current_reg = parse_key_val(g.region(flags='pg', stdout_=PIPE).outputs.stdout) del current_reg['projection'] del current_reg['zone'] del current_reg['cells'] # check for existing mask and backup if found global mask_test mask_test = gs.list_grouped( type='rast', pattern='MASK')[gs.gisenv()['MAPSET']] if mask_test: global original_mask original_mask = temp_map('tmp_original_mask') g.copy(raster=['MASK', original_mask]) # error checking if flat_thres < 0: gs.fatal('Parameter thres cannot be negative') if filter_size % 2 == 0 or counting_size % 2 == 0: gs.fatal( 'Filter or counting windows require an odd-numbered window size') if filter_size >= counting_size: gs.fatal( 'Filter size needs to be smaller than the counting window size') if features != '' and slope == '': gs.fatal('Need to supply a slope raster in order to produce the terrain classification') # Terrain Surface Texture ------------------------------------------------- # smooth the dem gs.message("Calculating terrain surface texture...") gs.message( "1. Smoothing input DEM with a {n}x{n} median filter...".format( n=filter_size)) filtered_dem = temp_map('tmp_filtered_dem') gs.run_command("r.neighbors", input = elevation, method = "median", size = filter_size, output = filtered_dem, flags='c', quiet=True) # extract the pits and peaks based on the threshold pitpeaks = temp_map('tmp_pitpeaks') gs.message("2. Extracting pits and peaks with difference > thres...") r.mapcalc(expression='{x} = if ( abs({dem}-{median})>{thres}, 1, 0)'.format( x=pitpeaks, dem=elevation, thres=flat_thres, median=filtered_dem), quiet=True) # calculate density of pits and peaks gs.message("3. Using resampling filter to create terrain texture...") window_radius = (counting_size-1)/2 y_radius = float(current_reg['ewres'])*window_radius x_radius = float(current_reg['nsres'])*window_radius resample = temp_map('tmp_density') r.resamp_filter(input=pitpeaks, output=resample, filter=['bartlett','gauss'], radius=[x_radius,y_radius], quiet=True) # convert to percentage gs.message("4. Converting to percentage...") r.mask(raster=elevation, overwrite=True, quiet=True) r.mapcalc(expression='{x} = float({y} * 100)'.format(x=texture, y=resample), quiet=True) r.mask(flags='r', quiet=True) r.colors(map=texture, color='haxby', quiet=True) # Terrain convexity/concavity --------------------------------------------- # surface curvature using lacplacian filter gs.message("Calculating terrain convexity and concavity...") gs.message("1. Calculating terrain curvature using laplacian filter...") # grow the map to remove border effects and run laplacian filter dem_grown = temp_map('tmp_elevation_grown') laplacian = temp_map('tmp_laplacian') g.region(n=float(current_reg['n']) + (float(current_reg['nsres']) * filter_size), s=float(current_reg['s']) - (float(current_reg['nsres']) * filter_size), w=float(current_reg['w']) - (float(current_reg['ewres']) * filter_size), e=float(current_reg['e']) + (float(current_reg['ewres']) * filter_size)) r.grow(input=elevation, output=dem_grown, radius=filter_size, quiet=True) r.mfilter( input=dem_grown, output=laplacian, filter=string_to_rules(laplacian_matrix(filter_size)), quiet=True) # extract convex and concave pixels gs.message("2. Extracting convexities and concavities...") convexities = temp_map('tmp_convexities') concavities = temp_map('tmp_concavities') r.mapcalc( expression='{x} = if({laplacian}>{thres}, 1, 0)'\ .format(x=convexities, laplacian=laplacian, thres=curv_thres), quiet=True) r.mapcalc( expression='{x} = if({laplacian}<-{thres}, 1, 0)'\ .format(x=concavities, laplacian=laplacian, thres=curv_thres), quiet=True) # calculate density of convexities and concavities gs.message("3. Using resampling filter to create surface convexity/concavity...") resample_convex = temp_map('tmp_convex') resample_concav = temp_map('tmp_concav') r.resamp_filter(input=convexities, output=resample_convex, filter=['bartlett','gauss'], radius=[x_radius,y_radius], quiet=True) r.resamp_filter(input=concavities, output=resample_concav, filter=['bartlett','gauss'], radius=[x_radius,y_radius], quiet=True) # convert to percentages gs.message("4. Converting to percentages...") g.region(**current_reg) r.mask(raster=elevation, overwrite=True, quiet=True) r.mapcalc(expression='{x} = float({y} * 100)'.format(x=convexity, y=resample_convex), quiet=True) r.mapcalc(expression='{x} = float({y} * 100)'.format(x=concavity, y=resample_concav), quiet=True) r.mask(flags='r', quiet=True) # set colors r.colors_stddev(map=convexity, quiet=True) r.colors_stddev(map=concavity, quiet=True) # Terrain classification Flowchart----------------------------------------- if features != '': gs.message("Performing terrain surface classification...") # level 1 produces classes 1 thru 8 # level 2 produces classes 5 thru 12 # level 3 produces classes 9 thru 16 if nclasses == 8: levels = 1 if nclasses == 12: levels = 2 if nclasses == 16: levels = 3 classif = [] for level in range(levels): # mask previous classes x:x+4 if level != 0: min_cla = (4*(level+1))-4 clf_msk = temp_map('tmp_clf_mask') rules = '1:{0}:1'.format(min_cla) r.recode( input=classif[level-1], output=clf_msk, rules=string_to_rules(rules), overwrite=True) r.mask(raster=clf_msk, flags='i', quiet=True, overwrite=True) # image statistics smean = r.univar( map=slope, flags='g', stdout_=PIPE).outputs.stdout.split(os.linesep) smean = [i for i in smean if i.startswith('mean=') is True][0].split('=')[1] cmean = r.univar( map=convexity, flags='g', stdout_=PIPE).outputs.stdout.split(os.linesep) cmean = [i for i in cmean if i.startswith('mean=') is True][0].split('=')[1] tmean = r.univar( map=texture, flags='g', stdout_=PIPE).outputs.stdout.split(os.linesep) tmean = [i for i in tmean if i.startswith('mean=') is True][0].split('=')[1] classif.append(temp_map('tmp_classes')) if level != 0: r.mask(flags='r', quiet=True) classification(level+1, slope, smean, texture, tmean, convexity, cmean, classif[level]) # combine decision trees merged = [] for level in range(0, levels): if level > 0: min_cla = (4*(level+1))-4 merged.append(temp_map('tmp_merged')) r.mapcalc( expression='{x} = if({a}>{min}, {b}, {a})'.format( x=merged[level], min=min_cla, a=merged[level-1], b=classif[level])) else: merged.append(classif[level]) g.rename(raster=[merged[-1], features], quiet=True) del TMP_RAST[-1] # Write metadata ---------------------------------------------------------- history = 'r.terrain.texture ' for key,val in options.iteritems(): history += key + '=' + str(val) + ' ' r.support(map=texture, title=texture, description='generated by r.terrain.texture', history=history) r.support(map=convexity, title=convexity, description='generated by r.terrain.texture', history=history) r.support(map=concavity, title=concavity, description='generated by r.terrain.texture', history=history) if features != '': r.support(map=features, title=features, description='generated by r.terrain.texture', history=history) # write color and category rules to tempfiles r.category( map=features, rules=string_to_rules(categories(nclasses)), separator='pipe') r.colors( map=features, rules=string_to_rules(colors(nclasses)), quiet=True) return 0
def main(): coords = options['coordinates'] input = options['input'] output = options['output'] fs = options['separator'] proj_in = options['proj_in'] proj_out = options['proj_out'] ll_in = flags['i'] ll_out = flags['o'] decimal = flags['d'] copy_input = flags['e'] include_header = flags['c'] #### check for cs2cs if not grass.find_program('cs2cs'): grass.fatal(_("cs2cs program not found, install PROJ.4 first: http://proj.maptools.org")) #### check for overenthusiasm if proj_in and ll_in: grass.fatal(_("Choose only one input parameter method")) if proj_out and ll_out: grass.fatal(_("Choose only one output parameter method")) if ll_in and ll_out: grass.fatal(_("Choise only one auto-projection parameter method")) if output and not grass.overwrite() and os.path.exists(output): grass.fatal(_("Output file already exists")) if not coords and not input: grass.fatal(_("One of <coordinates> and <input> must be given")) if coords and input: grass.fatal(_("Options <coordinates> and <input> are mutually exclusive")) #### parse field separator # FIXME: input_x,y needs to split on multiple whitespace between them if fs == ',': ifs = ofs = ',' else: try: ifs, ofs = fs.split(',') except ValueError: ifs = ofs = fs ifs = separator(ifs) ofs = separator(ofs) #### set up projection params s = grass.read_command("g.proj", flags='j') kv = parse_key_val(s) if "XY location" in kv['+proj'] and (ll_in or ll_out): grass.fatal(_("Unable to project to or from a XY location")) in_proj = None if ll_in: in_proj = "+proj=longlat +datum=WGS84" grass.verbose("Assuming LL WGS84 as input, current projection as output ") if ll_out: in_proj = grass.read_command('g.proj', flags = 'jf') if proj_in: in_proj = proj_in if not in_proj: grass.verbose("Assuming current location as input") in_proj = grass.read_command('g.proj', flags = 'jf') in_proj = in_proj.strip() grass.verbose("Input parameters: '%s'" % in_proj) out_proj = None if ll_out: out_proj = "+proj=longlat +datum=WGS84" grass.verbose("Assuming current projection as input, LL WGS84 as output ") if ll_in: out_proj = grass.read_command('g.proj', flags = 'jf') if proj_out: out_proj = proj_out if not out_proj: grass.fatal(_("Missing output projection parameters ")) out_proj = out_proj.strip() grass.verbose("Output parameters: '%s'" % out_proj) #### set up input file if coords: x, y = coords.split(',') tmpfile = grass.tempfile() fd = open(tmpfile, "w") fd.write("%s%s%s\n" % (x, ifs, y)) fd.close() inf = file(tmpfile) else: if input == '-': infile = None inf = sys.stdin else: infile = input if not os.path.exists(infile): grass.fatal(_("Unable to read input data")) inf = file(infile) grass.debug("input file=[%s]" % infile) #### set up output file if not output: outfile = None outf = sys.stdout else: outfile = output outf = open(outfile, 'w') grass.debug("output file=[%s]" % outfile) #### set up output style if not decimal: outfmt = ["-w5"] else: outfmt = ["-f", "%.8f"] if not copy_input: copyinp = [] else: copyinp = ["-E"] #### do the conversion # Convert cs2cs DMS format to GRASS DMS format: # cs2cs | sed -e 's/d/:/g' -e "s/'/:/g" -e 's/"//g' cmd = ['cs2cs'] + copyinp + outfmt + in_proj.split() + ['+to'] + out_proj.split() p = grass.Popen(cmd, stdin = grass.PIPE, stdout = grass.PIPE) tr = TrThread(ifs, inf, p.stdin) tr.start() if not copy_input: if include_header: outf.write("x%sy%sz\n" % (ofs, ofs)) for line in p.stdout: try: xy, z = line.split(' ', 1) x, y = xy.split('\t') except ValueError: grass.fatal(line) outf.write('%s%s%s%s%s\n' % \ (x.strip(), ofs, y.strip(), ofs, z.strip())) else: if include_header: outf.write("input_x%sinput_y%sx%sy%sz\n" % (ofs, ofs, ofs, ofs)) for line in p.stdout: inXYZ, x, rest = line.split('\t') inX, inY = inXYZ.split(' ')[:2] y, z = rest.split(' ', 1) outf.write('%s%s%s%s%s%s%s%s%s\n' % \ (inX.strip(), ofs, inY.strip(), ofs, x.strip(), \ ofs, y.strip(), ofs, z.strip())) p.wait() if p.returncode != 0: grass.warning(_("Projection transform probably failed, please investigate"))
def main(): fileorig = options['input'] filevect = options['output'] if not filevect: filevect = basename(fileorig, 'txt') #are we in LatLong location? s = grass.read_command("g.proj", flags='j') kv = parse_key_val(s) if kv['+proj'] != 'longlat': grass.fatal(_("This module only operates in LatLong/WGS84 locations")) #### setup temporary file tmpfile = grass.tempfile() coldescs = [("RC", "rc integer"), ("UFI", "uf1 integer"), ("UNI", "uni integer"), ("LAT", "lat double precision"), ("LONG", "lon double precision"), ("DMS_LAT", "dms_lat varchar(6)"), ("DMS_LONG", "dms_long varchar(7)"), ("UTM", "utm varchar(4)"), ("JOG", "jog varchar(7)"), ("FC", "fc varchar(1)"), ("DSG", "dsg varchar(5)"), ("PC", "pc integer"), ("CC1", "cci varchar(2)"), ("ADM1", "adm1 varchar(2)"), ("ADM2", "adm2 varchar(200)"), ("DIM", "dim integer"), ("CC2", "cc2 varchar(2)"), ("NT", "nt varchar(1)"), ("LC", "lc varchar(3)"), ("SHORT_FORM", "shortform varchar(128)"), ("GENERIC", "generic varchar(128)"), ("SORT_NAME", "sortname varchar(200)"), ("FULL_NAME", "fullname varchar(200)"), ("FULL_NAME_ND", "funamesd varchar(200)"), ("MODIFY_DATE", "mod_date date")] colnames = [desc[0] for desc in coldescs] coltypes = dict([(desc[0], 'integer' in desc[1]) for desc in coldescs]) header = None num_places = 0 inf = file(fileorig) outf = file(tmpfile, 'wb') for line in inf: fields = line.rstrip('\r\n').split('\t') if not header: header = fields continue vars = dict(zip(header, fields)) fields2 = [] for col in colnames: if col in vars: if coltypes[col] and vars[col] == '': fields2.append('0') else: fields2.append(vars[col]) else: if coltypes[col]: fields2.append('0') else: fields2.append('') line2 = ';'.join(fields2) + '\n' outf.write(line2) num_places += 1 outf.close() inf.close() grass.message(_("Converted %d place names.") % num_places) #TODO: fix dms_lat,dms_long DDMMSS -> DD:MM:SS # Solution: # IN=DDMMSS # DEG=`echo $IN | cut -b1,2` # MIN=`echo $IN | cut -b3,4` # SEC=`echo $IN | cut -b5,6` # DEG_STR="$DEG:$MIN:$SEC" #modifications (to match DBF 10 char column name limit): # short_form -> shortform # sort_name -> sortname # full_name -> fullname # full_name_sd -> funamesd # pump data into GRASS: columns = [desc[1] for desc in coldescs] grass.run_command('v.in.ascii', cat=0, x=5, y=4, sep=';', input=tmpfile, output=filevect, columns=columns) try_remove(tmpfile) # write cmd history: vgrass.vector_history(filevect)
def main(): coords = options["coordinates"] input = options["input"] output = options["output"] fs = options["separator"] proj_in = options["proj_in"] proj_out = options["proj_out"] ll_in = flags["i"] ll_out = flags["o"] decimal = flags["d"] copy_input = flags["e"] include_header = flags["c"] # check for cs2cs if not gcore.find_program("cs2cs"): gcore.fatal( _("cs2cs program not found, install PROJ first: \ https://proj.org")) # parse field separator # FIXME: input_x,y needs to split on multiple whitespace between them if fs == ",": ifs = ofs = "," else: try: ifs, ofs = fs.split(",") except ValueError: ifs = ofs = fs ifs = separator(ifs) ofs = separator(ofs) # set up projection params s = gcore.read_command("g.proj", flags="j") kv = parse_key_val(s) if "XY location" in kv["+proj"] and (ll_in or ll_out): gcore.fatal(_("Unable to project to or from a XY location")) in_proj = None if ll_in: in_proj = "+proj=longlat +datum=WGS84" gcore.verbose( "Assuming LL WGS84 as input, current projection as output ") if ll_out: in_proj = gcore.read_command("g.proj", flags="jf") if proj_in: if "+" in proj_in: in_proj = proj_in else: gcore.fatal(_("Invalid PROJ.4 input specification")) if not in_proj: gcore.verbose("Assuming current location as input") in_proj = gcore.read_command("g.proj", flags="jf") in_proj = in_proj.strip() gcore.verbose("Input parameters: '%s'" % in_proj) out_proj = None if ll_out: out_proj = "+proj=longlat +datum=WGS84" gcore.verbose( "Assuming current projection as input, LL WGS84 as output ") if ll_in: out_proj = gcore.read_command("g.proj", flags="jf") if proj_out: if "+" in proj_out: out_proj = proj_out else: gcore.fatal(_("Invalid PROJ.4 output specification")) if not out_proj: gcore.fatal(_("Missing output projection parameters ")) out_proj = out_proj.strip() gcore.verbose("Output parameters: '%s'" % out_proj) # set up input file if coords: x, y = coords.split(",") tmpfile = gcore.tempfile() fd = open(tmpfile, "w") fd.write("%s%s%s\n" % (x, ifs, y)) fd.close() inf = open(tmpfile) else: if input == "-": infile = None inf = sys.stdin else: infile = input if not os.path.exists(infile): gcore.fatal(_("Unable to read input data")) inf = open(infile) gcore.debug("input file=[%s]" % infile) # set up output file if not output: outfile = None outf = sys.stdout else: outfile = output outf = open(outfile, "w") gcore.debug("output file=[%s]" % outfile) # set up output style if not decimal: outfmt = ["-w5"] else: outfmt = ["-f", "%.8f"] if not copy_input: copyinp = [] else: copyinp = ["-E"] # do the conversion # Convert cs2cs DMS format to GRASS DMS format: # cs2cs | sed -e 's/d/:/g' -e "s/'/:/g" -e 's/"//g' cmd = ["cs2cs" ] + copyinp + outfmt + in_proj.split() + ["+to"] + out_proj.split() p = gcore.Popen(cmd, stdin=gcore.PIPE, stdout=gcore.PIPE) tr = TrThread(ifs, inf, p.stdin) tr.start() if not copy_input: if include_header: outf.write("x%sy%sz\n" % (ofs, ofs)) for line in p.stdout: try: xy, z = decode(line).split(" ", 1) x, y = xy.split("\t") except ValueError: gcore.fatal(line) outf.write("%s%s%s%s%s\n" % (x.strip(), ofs, y.strip(), ofs, z.strip())) else: if include_header: outf.write("input_x%sinput_y%sx%sy%sz\n" % (ofs, ofs, ofs, ofs)) for line in p.stdout: inXYZ, x, rest = decode(line).split("\t") inX, inY = inXYZ.split(" ")[:2] y, z = rest.split(" ", 1) outf.write("%s%s%s%s%s%s%s%s%s\n" % ( inX.strip(), ofs, inY.strip(), ofs, x.strip(), ofs, y.strip(), ofs, z.strip(), )) p.wait() if p.returncode != 0: gcore.warning( _("Projection transform probably failed, please investigate"))
def main(): fileorig = options["input"] filevect = options["output"] if not filevect: filevect = basename(fileorig, "txt") # are we in LatLong location? s = grass.read_command("g.proj", flags="j") kv = parse_key_val(s) if kv["+proj"] != "longlat": grass.fatal(_("This module only operates in LatLong/WGS84 locations")) #### setup temporary file tmpfile = grass.tempfile() coldescs = [ ("RC", "rc integer"), ("UFI", "uf1 integer"), ("UNI", "uni integer"), ("LAT", "lat double precision"), ("LONG", "lon double precision"), ("DMS_LAT", "dms_lat integer"), ("DMS_LONG", "dms_long integer"), ("MGRS", "mgrs varchar(15)"), ("JOG", "jog varchar(7)"), ("FC", "fc varchar(1)"), ("DSG", "dsg varchar(6)"), ("PC", "pc integer"), ("CC1", "cci varchar(255)"), ("ADM1", "adm1 varchar(2)"), ("POP", "pop integer"), ("ELEV", "elev double precision"), ("CC2", "cc2 varchar(255)"), ("NT", "nt varchar(2)"), ("LC", "lc varchar(3)"), ("SHORT_FORM", "shortform varchar(128)"), ("GENERIC", "generic varchar(128)"), ("SORT_NAME_RO", "sortnamero varchar(255)"), ("FULL_NAME_RO", "fullnamero varchar(255)"), ("FULL_NAME_ND_RO", "funamesdro varchar(255)"), ("SORT_NAME_RG", "sortnamerg varchar(255)"), ("FULL_NAME_RG", "fullnamerg varchar(255)"), ("FULL_NAME_ND_RG", "funamesdrg varchar(255)"), ("NOTE", "note varchar(4000)"), ("MODIFY_DATE", "mod_date date"), ("DISPLAY", "display varchar(255)"), ("NAME_RANK", "namerank integer"), ("NAME_LINK", "namelink integer"), ("TRANSL_CD", "translcd varchar(32)"), ("NM_MODIFY_DATE", "nmmodifydate varchar(10)"), ] colnames = [desc[0] for desc in coldescs] coltypes = dict([(desc[0], "integer" in desc[1]) for desc in coldescs]) header = None num_places = 0 inf = open(fileorig) outf = open(tmpfile, "wb") for line in inf: fields = line.rstrip("\r\n").split("\t") if not header: header = fields continue vars = dict(zip(header, fields)) fields2 = [] for col in colnames: if col in vars: if coltypes[col] and vars[col] == "": fields2.append("0") else: fields2.append(vars[col]) else: if coltypes[col]: fields2.append("0") else: fields2.append("") line2 = ";".join(fields2) + "\n" outf.write(line2) num_places += 1 outf.close() inf.close() grass.message(_("Converted %d place names.") % num_places) # TODO: fix dms_lat,dms_long DDMMSS -> DD:MM:SS # Solution: # IN=DDMMSS # DEG=`echo $IN | cut -b1,2` # MIN=`echo $IN | cut -b3,4` # SEC=`echo $IN | cut -b5,6` # DEG_STR="$DEG:$MIN:$SEC" # modifications (to match DBF 10 char column name limit): # short_form -> shortform # sort_name -> sortname # full_name -> fullname # full_name_sd -> funamesd # pump data into GRASS: columns = [desc[1] for desc in coldescs] grass.run_command( "v.in.ascii", cat=0, x=5, y=4, sep=";", input=tmpfile, output=filevect, columns=columns, ) try_remove(tmpfile) # write cmd history: vgrass.vector_history(filevect)
def main(): shell = flags['g'] serial = flags['s'] bands = options['input'].split(',') if len(bands) < 4: grass.fatal(_("At least four input maps required")) output = options['output'] # calculate the Stddev for TM bands grass.message(_("Calculating standard deviations for all bands...")) stddev = {} if serial: for band in bands: grass.verbose("band %d" % band) s = grass.read_command('r.univar', flags='g', map=band) kv = parse_key_val(s) stddev[band] = float(kv['stddev']) else: # run all bands in parallel if "WORKERS" in os.environ: workers = int(os.environ["WORKERS"]) else: workers = len(bands) proc = {} pout = {} # spawn jobs in the background n = 0 for band in bands: proc[band] = grass.pipe_command('r.univar', flags='g', map=band) if n % workers is 0: # wait for the ones launched so far to finish for bandp in bands[:n]: if not proc[bandp].stdout.closed: pout[bandp] = proc[bandp].communicate()[0] proc[bandp].wait() n = n + 1 # wait for jobs to finish, collect the output for band in bands: if not proc[band].stdout.closed: pout[band] = proc[band].communicate()[0] proc[band].wait() # parse the results for band in bands: kv = parse_key_val(pout[band]) stddev[band] = float(kv['stddev']) grass.message(_("Calculating Correlation Matrix...")) correlation = {} s = grass.read_command('r.covar', flags='r', map=[band for band in bands], quiet=True) # We need to skip the first line, since r.covar prints the number of values lines = s.splitlines() for i, row in zip(bands, lines[1:]): for j, cell in zip(bands, row.split(' ')): correlation[i, j] = float(cell) # Calculate all combinations grass.message(_("Calculating OIF for all band combinations...")) oif = [] for p in perms(bands): oif.append((oifcalc(stddev, correlation, *p), p)) oif.sort(reverse=True) grass.verbose(_("The Optimum Index Factor analysis result " \ "(best combination shown first):")) if shell: fmt = "%s,%s,%s:%.4f\n" else: fmt = "%s, %s, %s: %.4f\n" if not output or output == '-': for v, p in oif: sys.stdout.write(fmt % (p + (v,))) else: outf = file(output, 'w') for v, p in oif: outf.write(fmt % (p + (v,))) outf.close()
def main(): coords = options['coordinates'] input = options['input'] output = options['output'] fs = options['separator'] proj_in = options['proj_in'] proj_out = options['proj_out'] ll_in = flags['i'] ll_out = flags['o'] decimal = flags['d'] copy_input = flags['e'] include_header = flags['c'] # check for cs2cs if not gcore.find_program('cs2cs'): gcore.fatal( _("cs2cs program not found, install PROJ.4 first: \ http://proj.maptools.org")) # check for overenthusiasm if proj_in and ll_in: gcore.fatal(_("Choose only one input parameter method")) if proj_out and ll_out: gcore.fatal(_("Choose only one output parameter method")) if ll_in and ll_out: gcore.fatal(_("Choose only one auto-projection parameter method")) if output and not gcore.overwrite() and os.path.exists(output): gcore.fatal(_("Output file already exists")) if not coords and not input: gcore.fatal(_("One of <coordinates> and <input> must be given")) if coords and input: gcore.fatal( _("Options <coordinates> and <input> are mutually exclusive")) # parse field separator # FIXME: input_x,y needs to split on multiple whitespace between them if fs == ',': ifs = ofs = ',' else: try: ifs, ofs = fs.split(',') except ValueError: ifs = ofs = fs ifs = separator(ifs) ofs = separator(ofs) # set up projection params s = gcore.read_command("g.proj", flags='j') kv = parse_key_val(s) if "XY location" in kv['+proj'] and (ll_in or ll_out): gcore.fatal(_("Unable to project to or from a XY location")) in_proj = None if ll_in: in_proj = "+proj=longlat +datum=WGS84" gcore.verbose( "Assuming LL WGS84 as input, current projection as output ") if ll_out: in_proj = gcore.read_command('g.proj', flags='jf') if proj_in: if '+' in proj_in: in_proj = proj_in else: gcore.fatal(_("Invalid PROJ.4 input specification")) if not in_proj: gcore.verbose("Assuming current location as input") in_proj = gcore.read_command('g.proj', flags='jf') in_proj = in_proj.strip() gcore.verbose("Input parameters: '%s'" % in_proj) out_proj = None if ll_out: out_proj = "+proj=longlat +datum=WGS84" gcore.verbose( "Assuming current projection as input, LL WGS84 as output ") if ll_in: out_proj = gcore.read_command('g.proj', flags='jf') if proj_out: if '+' in proj_out: out_proj = proj_out else: gcore.fatal(_("Invalid PROJ.4 output specification")) if not out_proj: gcore.fatal(_("Missing output projection parameters ")) out_proj = out_proj.strip() gcore.verbose("Output parameters: '%s'" % out_proj) # set up input file if coords: x, y = coords.split(',') tmpfile = gcore.tempfile() fd = open(tmpfile, "w") fd.write("%s%s%s\n" % (x, ifs, y)) fd.close() inf = file(tmpfile) else: if input == '-': infile = None inf = sys.stdin else: infile = input if not os.path.exists(infile): gcore.fatal(_("Unable to read input data")) inf = file(infile) gcore.debug("input file=[%s]" % infile) # set up output file if not output: outfile = None outf = sys.stdout else: outfile = output outf = open(outfile, 'w') gcore.debug("output file=[%s]" % outfile) # set up output style if not decimal: outfmt = ["-w5"] else: outfmt = ["-f", "%.8f"] if not copy_input: copyinp = [] else: copyinp = ["-E"] # do the conversion # Convert cs2cs DMS format to GRASS DMS format: # cs2cs | sed -e 's/d/:/g' -e "s/'/:/g" -e 's/"//g' cmd = ['cs2cs'] + copyinp + outfmt + \ in_proj.split() + ['+to'] + out_proj.split() p = gcore.Popen(cmd, stdin=gcore.PIPE, stdout=gcore.PIPE) tr = TrThread(ifs, inf, p.stdin) tr.start() if not copy_input: if include_header: outf.write("x%sy%sz\n" % (ofs, ofs)) for line in p.stdout: try: xy, z = line.split(' ', 1) x, y = xy.split('\t') except ValueError: gcore.fatal(line) outf.write('%s%s%s%s%s\n' % (x.strip(), ofs, y.strip(), ofs, z.strip())) else: if include_header: outf.write("input_x%sinput_y%sx%sy%sz\n" % (ofs, ofs, ofs, ofs)) for line in p.stdout: inXYZ, x, rest = line.split('\t') inX, inY = inXYZ.split(' ')[:2] y, z = rest.split(' ', 1) outf.write('%s%s%s%s%s%s%s%s%s\n' % (inX.strip(), ofs, inY.strip(), ofs, x.strip(), ofs, y.strip(), ofs, z.strip())) p.wait() if p.returncode != 0: gcore.warning( _("Projection transform probably failed, please investigate"))
def main(): options, flags = gcore.parser() location = options["location"] mapset = options["mapset"] dbase = options["dbase"] resolution = options["resolution"] if resolution: resolution = float(resolution) method = options["method"] curr_region = flags["r"] transform_z = flags["z"] overwrite = flags["o"] if not curr_region: gcore.use_temp_region() atexit.register(gcore.del_temp_region) if overwrite or gcore.overwrite(): overwrite = True else: overwrite = False # # r.proj # parameters = dict(location=location, mapset=mapset, flags="l", overwrite=overwrite) if dbase: parameters.update(dict(dbase=dbase)) # first run r.proj to see if it works try: gcore.run_command("r.proj", quiet=True, **parameters) except CalledModuleError: gcore.fatal( _("Module r.proj failed. Please check the error messages above.")) # run again to get the raster maps rasters = gcore.read_command("r.proj", **parameters) rasters = rasters.strip().split() gcore.info( _("{num} raster maps will be reprojected from mapset <{mapsetS}> " "to mapset <{mapsetT}>.").format(num=len(rasters), mapsetS=mapset, mapsetT=gcore.gisenv()["MAPSET"])) parameters = dict(location=location, mapset=mapset, method=method, overwrite=overwrite) if resolution: parameters.update(dict(resolution=resolution)) if dbase: parameters.update(dict(dbase=dbase)) for raster in rasters: if not curr_region: bounds = gcore.read_command("r.proj", input=raster, flags="g", **parameters) bounds = parse_key_val(bounds, vsep=" ") gcore.run_command("g.region", **bounds) gcore.run_command("r.proj", input=raster, **parameters) # # v.proj # parameters = dict(location=location, mapset=mapset, flags="l", overwrite=overwrite) if dbase: parameters.update(dict(dbase=dbase)) # first run v.proj to see if it works try: gcore.run_command("v.proj", quiet=True, **parameters) except CalledModuleError: gcore.fatal( _("Module v.proj failed. Please check the error messages above.")) # run again to get the vector maps vectors = gcore.read_command("v.proj", **parameters) vectors = vectors.strip().split() gcore.info( _("{num} vectors maps will be reprojected from mapset <{mapsetS}> " "to mapset <{mapsetT}>.").format(num=len(vectors), mapsetS=mapset, mapsetT=gcore.gisenv()["MAPSET"])) parameters = dict(location=location, mapset=mapset, overwrite=overwrite) if transform_z: parameters.update(dict(flags="z")) for vector in vectors: gcore.run_command("v.proj", input=vector, **parameters)
def main(): shell = flags['g'] serial = flags['s'] bands = options['input'].split(',') if len(bands) < 4: grass.fatal(_("At least four input maps required")) output = options['output'] # calculate the Stddev for TM bands grass.message(_("Calculating standard deviations for all bands...")) stddev = {} if serial: for band in bands: grass.verbose("band %d" % band) s = grass.read_command('r.univar', flags='g', map=band) kv = parse_key_val(s) stddev[band] = float(kv['stddev']) else: # run all bands in parallel if "WORKERS" in os.environ: workers = int(os.environ["WORKERS"]) else: workers = len(bands) proc = {} pout = {} # spawn jobs in the background n = 0 for band in bands: proc[band] = grass.pipe_command('r.univar', flags='g', map=band) if n % workers is 0: # wait for the ones launched so far to finish for bandp in bands[:n]: if not proc[bandp].stdout.closed: pout[bandp] = proc[bandp].communicate()[0] proc[bandp].wait() n = n + 1 # wait for jobs to finish, collect the output for band in bands: if not proc[band].stdout.closed: pout[band] = proc[band].communicate()[0] proc[band].wait() # parse the results for band in bands: kv = parse_key_val(pout[band]) stddev[band] = float(kv['stddev']) grass.message(_("Calculating Correlation Matrix...")) correlation = {} s = grass.read_command('r.covar', flags='r', map=[band for band in bands], quiet=True) # We need to skip the first line, since r.covar prints the number of values lines = s.splitlines() for i, row in zip(bands, lines[1:]): for j, cell in zip(bands, row.split(' ')): correlation[i, j] = float(cell) # Calculate all combinations grass.message(_("Calculating OIF for all band combinations...")) oif = [] for p in perms(bands): oif.append((oifcalc(stddev, correlation, *p), p)) oif.sort(reverse=True) grass.verbose( _("The Optimum Index Factor analysis result " "(best combination shown first):")) if shell: fmt = "%s,%s,%s:%.4f\n" else: fmt = "%s, %s, %s: %.4f\n" if not output or output == '-': for v, p in oif: sys.stdout.write(fmt % (p + (v, ))) else: outf = file(output, 'w') for v, p in oif: outf.write(fmt % (p + (v, ))) outf.close()
def plot(self, reg=None, cmap=None, norm=None, figsize=None, title_fontsize=8, label_fontsize=6, legend_fontsize=6, share_legend=False, names=None, fig_kwds=None, legend_kwds=None, subplots_kwds=None): """Plot a Raster object as a raster matrix Parameters ---------- reg : grass.pygrass.gis.region.Region The region used for the plotting extent. cmap : str (opt), default=None Specify a single cmap to apply to all of the RasterLayers. This overrides the color map that is assigned the GRASS GIS raster. norm : matplotlib.colors.Normalize (opt), default=None A matplotlib.colors.Normalize to apply to all of the rasters. This overrides any color maps that are associated to each GRASS GIS raster. figsize : tuple (opt), default=None Size of the resulting matplotlib.figure.Figure. out_shape : tuple, default=(100, 100) Number of rows, cols to read from the raster datasets for plotting. title_fontsize : any number, default=8 Size in pts of titles. label_fontsize : any number, default=6 Size in pts of axis ticklabels. legend_fontsize : any number, default=6 Size in pts of legend ticklabels. share_legend : bool, default=False Optionally share a single legend between the plots. This assumes that all of the GRASS GIS rasters are using the same color scale, and the color scale used for plotting is taken from the last raster in the RasterStack. names : list (opt), default=None Optionally supply a list of names for each RasterLayer to override the default layer names for the titles. fig_kwds : dict (opt), default=None Additional arguments to pass to the matplotlib.pyplot.figure call when creating the figure object. legend_kwds : dict (opt), default=None Additional arguments to pass to the matplotlib.pyplot.colorbar call when creating the colorbar object. subplots_kwds : dict (opt), default=None Additional arguments to pass to the matplotlib.pyplot.subplots_adjust function. These are used to control the spacing and position of each subplot, and can include {left=None, bottom=None, right=None, top=None, wspace=None, hspace=None}. Returns ------- axs : numpy.ndarray array of matplotlib.axes._subplots.AxesSubplot or a single matplotlib.axes._subplots.AxesSubplot if Raster object contains only a single layer. """ # some checks if reg is None: raise AttributeError("argument `reg` requires a region object.") if norm: if not isinstance(norm, mpl.colors.Normalize): raise AttributeError( "norm argument should be a \ matplotlib.colors.Normalize object") # override grass raster colors if cmap: cmaps = [cmap for i in range(self.count)] if norm: norms = [norm for i in range(self.count)] else: norms = [None for i in range(self.count)] else: scales = [convert_grass_color(name) for name in self.names] cmaps, norms = zip(*scales) # override map titles if names is None: names = [] for src in self.iloc: nm = gr.info( src.fullname(), flags="e", stdout_=PIPE).outputs.stdout title = parse_key_val(nm)["title"] title = title.replace('"', "") names.append(title) else: if len(names) != self.count: raise AttributeError("arguments 'names' needs to be the same " "length as the number of RasterLayer " "objects") if fig_kwds is None: fig_kwds = {} if legend_kwds is None: legend_kwds = {} if subplots_kwds is None: subplots_kwds = {} if figsize: fig_kwds["figsize"] = figsize # estimate required number of rows and columns in figure rows = int(np.sqrt(self.count)) cols = int(math.ceil(np.sqrt(self.count))) if rows * cols < self.count: rows += 1 fig, axs = plt.subplots(rows, cols, **fig_kwds) if isinstance(axs, np.ndarray): # axs.flat is an iterator over the row-order flattened axs array for ax, n, cmap, norm, name in zip( axs.flat, range(self.count), cmaps, norms, names ): arr = self.read(index=n) arr = arr.squeeze() ax.set_title(name, fontsize=title_fontsize, y=1.00) extent = [reg.west, reg.east, reg.south, reg.north] im = ax.imshow(arr, extent=extent, cmap=cmap, norm=norm) if share_legend is False: divider = make_axes_locatable(ax) if "orientation" not in legend_kwds.keys(): legend_kwds["orientation"] = "vertical" if legend_kwds["orientation"] == "vertical": legend_pos = "right" elif legend_kwds["orientation"] == "horizontal": legend_pos = "bottom" cax = divider.append_axes(legend_pos, size="10%", pad=0.1) cbar = plt.colorbar(im, cax=cax, **legend_kwds) cbar.ax.tick_params(labelsize=legend_fontsize) # hide tick labels by default when multiple rows or cols ax.axes.get_xaxis().set_ticklabels([]) ax.axes.get_yaxis().set_ticklabels([]) # show y-axis tick labels on first subplot if n == 0 and rows > 1: ticks_loc = ax.get_yticks().tolist() ax.yaxis.set_major_locator(mticker.FixedLocator(ticks_loc)) ax.set_yticklabels( ax.yaxis.get_majorticklocs().astype("int"), fontsize=label_fontsize) if n == 0 and rows == 1: ticks_loc = ax.get_xticks().tolist() ax.xaxis.set_major_locator(mticker.FixedLocator(ticks_loc)) ax.set_xticklabels( ax.xaxis.get_majorticklocs().astype("int"), fontsize=label_fontsize) ticks_loc = ax.get_yticks().tolist() ax.yaxis.set_major_locator(mticker.FixedLocator(ticks_loc)) ax.set_yticklabels( ax.yaxis.get_majorticklocs().astype("int"), fontsize=label_fontsize) if rows > 1 and n == (rows * cols) - cols: ticks_loc = ax.get_xticks().tolist() ax.xaxis.set_major_locator(mticker.FixedLocator(ticks_loc)) ax.set_xticklabels( ax.xaxis.get_majorticklocs().astype("int"), fontsize=label_fontsize) for ax in axs.flat[axs.size - 1: self.count - 1: -1]: ax.set_visible(False) if share_legend is True: cbar_ax = fig.add_axes([0.9, 0.15, 0.03, 0.7]) cbar = fig.colorbar(im, cax=cbar_ax, **legend_kwds) cbar.ax.tick_params(labelsize=legend_fontsize) plt.subplots_adjust(**subplots_kwds) else: arr = self.read(index=0) arr = arr.squeeze() cmap = cmaps[0] norm = norms[0] axs.set_title(names[0], fontsize=title_fontsize, y=1.00) extent = [reg.west, reg.east, reg.south, reg.north] im = axs.imshow(arr, extent=extent, cmap=cmap, norm=norm) divider = make_axes_locatable(axs) if "orientation" not in legend_kwds.keys(): legend_kwds["orientation"] = "vertical" if legend_kwds["orientation"] == "vertical": legend_pos = "right" elif legend_kwds["orientation"] == "horizontal": legend_pos = "bottom" cax = divider.append_axes(legend_pos, size="10%", pad=0.1) cbar = plt.colorbar(im, cax=cax, **legend_kwds) cbar.ax.tick_params(labelsize=legend_fontsize) return axs