123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153 |
- #
- # AUTHOR(S): Caitlin Haedrich <caitlin DOT haedrich AT gmail>
- #
- # PURPOSE: This module contains utility functions for InteractiveMap.
- #
- # COPYRIGHT: (C) 2021-2022 Caitlin Haedrich, and by the GRASS Development Team
- #
- # This program is free software under the GNU General Public
- # License (>=v2). Read the file COPYING that comes with GRASS
- # for details.
- """Utility functions warpping existing processes in a suitable way"""
- import os
- import grass.script as gs
- def get_region(env=None):
- """Returns current computational region as dictionary.
- Additionally, it adds long key names.
- """
- region = gs.region(env=env)
- region["east"] = region["e"]
- region["west"] = region["w"]
- region["north"] = region["n"]
- region["south"] = region["s"]
- return region
- def get_location_proj_string(env=None):
- """Returns projection of environment in PROJ.4 format"""
- out = gs.read_command("g.proj", flags="jf", env=env)
- return out.strip()
- def reproject_region(region, from_proj, to_proj):
- """Reproject boundary of region from one projection to another.
- :param dict region: region to reproject as a dictionary with long key names
- output of get_region
- :param str from_proj: PROJ.4 string of region; output of get_location_proj_string
- :param str in_proj: PROJ.4 string of target location;
- output of get_location_proj_string
- :return dict region: reprojected region as a dictionary with long key names
- """
- region = region.copy()
- proj_input = (
- f"{region['east']} {region['north']}\n{region['west']} {region['south']}"
- )
- proc = gs.start_command(
- "m.proj",
- input="-",
- separator=" , ",
- proj_in=from_proj,
- proj_out=to_proj,
- flags="d",
- stdin=gs.PIPE,
- stdout=gs.PIPE,
- stderr=gs.PIPE,
- )
- proc.stdin.write(gs.encode(proj_input))
- proc.stdin.close()
- proc.stdin = None
- proj_output, stderr = proc.communicate()
- if proc.returncode:
- raise RuntimeError("reprojecting region: m.proj error: " + stderr)
- enws = gs.decode(proj_output).split(os.linesep)
- elon, nlat, unused = enws[0].split(" ")
- wlon, slat, unused = enws[1].split(" ")
- region["east"] = elon
- region["north"] = nlat
- region["west"] = wlon
- region["south"] = slat
- return region
- 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 setup_location(name, path, epsg, src_env):
- """Setup temporary location with different projection but
- same computational region as source location
- :param str name: name of new location
- :param path path: path to new location's database
- :param str epsg: EPSG code
- :param dict src_env: source environment
- :return str rcfile: name of new locations rcfile
- :return dict new_env: new environment
- """
- # Create new environment
- rcfile, new_env = gs.create_environment(path, name, "PERMANENT")
- # Location and mapset
- gs.create_location(path, name, epsg=epsg, overwrite=True)
- # Reproject region
- region = get_region(env=src_env)
- from_proj = get_location_proj_string(src_env)
- to_proj = get_location_proj_string(env=new_env)
- new_region = reproject_region(region, from_proj, to_proj)
- # Set region to match original region extent
- gs.run_command(
- "g.region",
- n=new_region["north"],
- s=new_region["south"],
- e=new_region["east"],
- w=new_region["west"],
- env=new_env,
- )
- return rcfile, new_env
- def get_map_name_from_d_command(module, **kwargs):
- """Returns map name from display command.
- Assumes only positional parameters.
- When more maps are present (e.g., d.rgb), it returns only 1.
- Returns empty string if fails to find it.
- """
- special = {"d.his": "hue", "d.legend": "raster", "d.rgb": "red", "d.shade": "shade"}
- parameter = special.get(module, "map")
- return kwargs.get(parameter, "")
|