utils.py 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. #
  2. # AUTHOR(S): Caitlin Haedrich <caitlin DOT haedrich AT gmail>
  3. #
  4. # PURPOSE: This module contains utility functions for InteractiveMap.
  5. #
  6. # COPYRIGHT: (C) 2021 Caitlin Haedrich, and by the GRASS Development Team
  7. #
  8. # This program is free software under the GNU General Public
  9. # License (>=v2). Read the file COPYING that comes with GRASS
  10. # for details.
  11. import os
  12. import grass.script as gs
  13. def get_region(env=None):
  14. """Returns current computational region as dictionary.
  15. Adds long key names.
  16. """
  17. region = gs.region(env=env)
  18. region["east"] = region["e"]
  19. region["west"] = region["w"]
  20. region["north"] = region["n"]
  21. region["south"] = region["s"]
  22. return region
  23. def get_location_proj_string(env=None):
  24. """Returns projection of environment in PROJ.4 format"""
  25. out = gs.read_command("g.proj", flags="jf", env=env)
  26. return out.strip()
  27. def reproject_region(region, from_proj, to_proj):
  28. """Reproject boundary of region from one projection to another.
  29. :param dict region: region to reproject as a dictionary with long key names
  30. output of get_region
  31. :param str from_proj: PROJ.4 string of region; output of get_location_proj_string
  32. :param str in_proj: PROJ.4 string of target location;
  33. output of get_location_proj_string
  34. :return dict region: reprojected region as a dictionary with long key names
  35. """
  36. region = region.copy()
  37. proj_input = "{east} {north}\n{west} {south}".format(**region)
  38. proc = gs.start_command(
  39. "m.proj",
  40. input="-",
  41. separator=" , ",
  42. proj_in=from_proj,
  43. proj_out=to_proj,
  44. flags="d",
  45. stdin=gs.PIPE,
  46. stdout=gs.PIPE,
  47. stderr=gs.PIPE,
  48. )
  49. proc.stdin.write(gs.encode(proj_input))
  50. proc.stdin.close()
  51. proc.stdin = None
  52. proj_output, stderr = proc.communicate()
  53. if proc.returncode:
  54. raise RuntimeError("reprojecting region: m.proj error: " + stderr)
  55. enws = gs.decode(proj_output).split(os.linesep)
  56. elon, nlat, unused = enws[0].split(" ")
  57. wlon, slat, unused = enws[1].split(" ")
  58. region["east"] = elon
  59. region["north"] = nlat
  60. region["west"] = wlon
  61. region["south"] = slat
  62. return region
  63. def estimate_resolution(raster, mapset, location, dbase, env):
  64. """Estimates resolution of reprojected raster.
  65. :param str raster: name of raster
  66. :param str mapset: mapset of raster
  67. :param str location: name of source location
  68. :param str dbase: path to source database
  69. :param dict env: target environment
  70. :return float estimate: estimated resolution of raster in destination
  71. environment
  72. """
  73. output = gs.read_command(
  74. "r.proj",
  75. flags="g",
  76. input=raster,
  77. mapset=mapset,
  78. location=location,
  79. dbase=dbase,
  80. env=env,
  81. ).strip()
  82. params = gs.parse_key_val(output, vsep=" ")
  83. output = gs.read_command("g.region", flags="ug", env=env, **params)
  84. output = gs.parse_key_val(output, val_type=float)
  85. cell_ns = (output["n"] - output["s"]) / output["rows"]
  86. cell_ew = (output["e"] - output["w"]) / output["cols"]
  87. estimate = (cell_ew + cell_ns) / 2.0
  88. return estimate
  89. def setup_location(name, path, epsg, src_env):
  90. """Setup temporary location with different projection but
  91. same computational region as source location
  92. :param str name: name of new location
  93. :param path path: path to new location's database
  94. :param str epsg: EPSG code
  95. :param dict src_env: source environment
  96. :return str rcfile: name of new locations rcfile
  97. :return dict new_env: new environment
  98. """
  99. # Create new environment
  100. rcfile, new_env = gs.create_environment(path, name, "PERMANENT")
  101. # Location and mapset
  102. gs.create_location(path, name, epsg=epsg, overwrite=True)
  103. # Reproject region
  104. region = get_region(env=src_env)
  105. from_proj = get_location_proj_string(src_env)
  106. to_proj = get_location_proj_string(env=new_env)
  107. new_region = reproject_region(region, from_proj, to_proj)
  108. # Set region to match original region extent
  109. gs.run_command(
  110. "g.region",
  111. n=new_region["north"],
  112. s=new_region["south"],
  113. e=new_region["east"],
  114. w=new_region["west"],
  115. env=new_env,
  116. )
  117. return rcfile, new_env
  118. def get_map_name_from_d_command(module, **kwargs):
  119. """Returns map name from display command.
  120. Assumes only positional parameters.
  121. When more maps are present (e.g., d.rgb), it returns only 1.
  122. Returns empty string if fails to find it.
  123. """
  124. special = {"d.his": "hue", "d.legend": "raster", "d.rgb": "red", "d.shade": "shade"}
  125. parameter = special.get(module, "map")
  126. return kwargs.get(parameter, "")