raster.py 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. """
  2. Raster related functions to be used in Python scripts.
  3. Usage:
  4. ::
  5. from grass.script import raster as grass
  6. grass.raster_history(map)
  7. (C) 2008-2011 by the GRASS Development Team
  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. .. sectionauthor:: Glynn Clements
  12. .. sectionauthor:: Martin Landa <landa.martin gmail.com>
  13. """
  14. from __future__ import absolute_import
  15. import os
  16. import sys
  17. import string
  18. import time
  19. from .core import (
  20. gisenv,
  21. find_file,
  22. tempfile,
  23. run_command,
  24. read_command,
  25. write_command,
  26. feed_command,
  27. warning,
  28. fatal,
  29. )
  30. from grass.exceptions import CalledModuleError
  31. from .utils import encode, float_or_dms, parse_key_val, try_remove
  32. if sys.version_info.major >= 3:
  33. unicode = str
  34. def raster_history(map, overwrite=False, env=None):
  35. """Set the command history for a raster map to the command used to
  36. invoke the script (interface to `r.support`).
  37. :param str map: map name
  38. :param env: environment
  39. :return: True on success
  40. :return: False on failure
  41. """
  42. current_mapset = gisenv(env)["MAPSET"]
  43. if find_file(name=map, env=env)["mapset"] == current_mapset:
  44. if overwrite is True:
  45. historyfile = tempfile(env=env)
  46. f = open(historyfile, "w")
  47. f.write(os.environ["CMDLINE"])
  48. f.close()
  49. run_command("r.support", map=map, loadhistory=historyfile, env=env)
  50. try_remove(historyfile)
  51. else:
  52. run_command("r.support", map=map, history=os.environ["CMDLINE"], env=env)
  53. return True
  54. warning(
  55. _(
  56. "Unable to write history for <%(map)s>. "
  57. "Raster map <%(map)s> not found in current mapset."
  58. % {"map": map, "map": map}
  59. )
  60. )
  61. return False
  62. def raster_info(map, env=None):
  63. """Return information about a raster map (interface to
  64. `r.info -gre`). Example:
  65. >>> raster_info('elevation') # doctest: +ELLIPSIS
  66. {'creator': '"helena"', 'cols': '1500' ... 'south': 215000.0}
  67. :param str map: map name
  68. :param env: environment
  69. :return: parsed raster info
  70. """
  71. def float_or_null(s):
  72. if s == "NULL":
  73. return None
  74. else:
  75. return float(s)
  76. s = read_command("r.info", flags="gre", map=map, env=env)
  77. kv = parse_key_val(s)
  78. for k in ["min", "max"]:
  79. kv[k] = float_or_null(kv[k])
  80. for k in ["north", "south", "east", "west"]:
  81. kv[k] = float(kv[k])
  82. for k in ["nsres", "ewres"]:
  83. kv[k] = float_or_dms(kv[k])
  84. return kv
  85. def mapcalc(
  86. exp, quiet=False, verbose=False, overwrite=False, seed=None, env=None, **kwargs
  87. ):
  88. """Interface to r.mapcalc.
  89. :param str exp: expression
  90. :param bool quiet: True to run quietly (<tt>--q</tt>)
  91. :param bool verbose: True to run verbosely (<tt>--v</tt>)
  92. :param bool overwrite: True to enable overwriting the output (<tt>--o</tt>)
  93. :param seed: an integer used to seed the random-number generator for the
  94. rand() function, or 'auto' to generate a random seed
  95. :param dict env: dictionary of environment variables for child process
  96. :param kwargs:
  97. """
  98. if seed == "auto":
  99. seed = hash((os.getpid(), time.time())) % (2**32)
  100. t = string.Template(exp)
  101. e = t.substitute(**kwargs)
  102. try:
  103. write_command(
  104. "r.mapcalc",
  105. file="-",
  106. stdin=e,
  107. env=env,
  108. seed=seed,
  109. quiet=quiet,
  110. verbose=verbose,
  111. overwrite=overwrite,
  112. )
  113. except CalledModuleError:
  114. fatal(_("An error occurred while running r.mapcalc" " with expression: %s") % e)
  115. def mapcalc_start(
  116. exp, quiet=False, verbose=False, overwrite=False, seed=None, env=None, **kwargs
  117. ):
  118. """Interface to r.mapcalc, doesn't wait for it to finish, returns Popen object.
  119. >>> output = 'newele'
  120. >>> input = 'elevation'
  121. >>> expr1 = '"%s" = "%s" * 10' % (output, input)
  122. >>> expr2 = '...' # etc.
  123. >>> # launch the jobs:
  124. >>> p1 = mapcalc_start(expr1)
  125. >>> p2 = mapcalc_start(expr2)
  126. ...
  127. >>> # wait for them to finish:
  128. >>> p1.wait()
  129. 0
  130. >>> p2.wait()
  131. 1
  132. >>> run_command('g.remove', flags='f', type='raster', name=output)
  133. :param str exp: expression
  134. :param bool quiet: True to run quietly (<tt>--q</tt>)
  135. :param bool verbose: True to run verbosely (<tt>--v</tt>)
  136. :param bool overwrite: True to enable overwriting the output (<tt>--o</tt>)
  137. :param seed: an integer used to seed the random-number generator for the
  138. rand() function, or 'auto' to generate a random seed
  139. :param dict env: dictionary of environment variables for child process
  140. :param kwargs:
  141. :return: Popen object
  142. """
  143. if seed == "auto":
  144. seed = hash((os.getpid(), time.time())) % (2**32)
  145. t = string.Template(exp)
  146. e = t.substitute(**kwargs)
  147. p = feed_command(
  148. "r.mapcalc",
  149. file="-",
  150. env=env,
  151. seed=seed,
  152. quiet=quiet,
  153. verbose=verbose,
  154. overwrite=overwrite,
  155. )
  156. p.stdin.write(encode(e))
  157. p.stdin.close()
  158. return p
  159. def raster_what(map, coord, env=None, localized=False):
  160. """Interface to r.what
  161. >>> raster_what('elevation', [[640000, 228000]])
  162. [{'elevation': {'color': '255:214:000', 'label': '', 'value': '102.479'}}]
  163. :param str map: the map name
  164. :param list coord: a list of list containing all the point that you want
  165. query
  166. :param env:
  167. """
  168. if isinstance(map, (bytes, unicode)):
  169. map_list = [map]
  170. else:
  171. map_list = map
  172. coord_list = list()
  173. if isinstance(coord, tuple):
  174. coord_list.append("%f,%f" % (coord[0], coord[1]))
  175. else:
  176. for e, n in coord:
  177. coord_list.append("%f,%f" % (e, n))
  178. sep = "|"
  179. # separator '|' not included in command
  180. # because | is causing problems on Windows
  181. # change separator?
  182. ret = read_command(
  183. "r.what",
  184. flags="rf",
  185. map=",".join(map_list),
  186. coordinates=",".join(coord_list),
  187. null=_("No data"),
  188. quiet=True,
  189. env=env,
  190. )
  191. data = list()
  192. if not ret:
  193. return data
  194. if localized:
  195. labels = (_("value"), _("label"), _("color"))
  196. else:
  197. labels = ("value", "label", "color")
  198. for item in ret.splitlines():
  199. line = item.split(sep)[3:]
  200. for i, map_name in enumerate(map_list):
  201. tmp_dict = {}
  202. tmp_dict[map_name] = {}
  203. for j in range(len(labels)):
  204. tmp_dict[map_name][labels[j]] = line[i * len(labels) + j]
  205. data.append(tmp_dict)
  206. return data