array.py 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. """!@package grass.script.array
  2. @brief GRASS Python scripting module (2D and 3D raster with numpy)
  3. Functions to use GRASS 2D and 3D rasters with NumPy.
  4. Usage:
  5. @code
  6. >>> import grass.script as grass
  7. >>> from grass.script import array as garray
  8. >>>
  9. >>> # We create a temporary region that is only valid in this python session
  10. ... grass.use_temp_region()
  11. >>> grass.run_command("g.region", n=80, e=120, t=60, s=0, w=0, b=0, res=20, res3=20)
  12. 0
  13. >>>
  14. >>> # Lets create a raster map numpy array
  15. ... # based at the current region settings
  16. ... map2d_1 = garray.array()
  17. >>>
  18. >>> # Write some data
  19. ... for y in range(map2d_1.shape[0]):
  20. ... for x in range(map2d_1.shape[1]):
  21. ... map2d_1[y][x] = y + x
  22. ...
  23. >>> # Lets have a look at the array
  24. ... print map2d_1
  25. [[ 0. 1. 2. 3. 4. 5.]
  26. [ 1. 2. 3. 4. 5. 6.]
  27. [ 2. 3. 4. 5. 6. 7.]
  28. [ 3. 4. 5. 6. 7. 8.]]
  29. >>> # This will write the numpy array as GRASS raster map
  30. ... # with name map2d_1
  31. ... map2d_1.write(mapname="map2d_1", overwrite=True)
  32. 100%
  33. 0
  34. >>>
  35. >>> # We create a new array and read map2d_1 to modify it
  36. ... map2d_2 = garray.array()
  37. >>> # Don't do map2d_2 = map2d_1 % 3
  38. ... # because: this will overwrite the internal temporary filename
  39. ... map2d_2.read("map2d_1")
  40. 0
  41. >>> map2d_2 %= 3
  42. >>> # Show the result
  43. ... print map2d_2
  44. [[ 0. 1. 2. 0. 1. 2.]
  45. [ 1. 2. 0. 1. 2. 0.]
  46. [ 2. 0. 1. 2. 0. 1.]
  47. [ 0. 1. 2. 0. 1. 2.]]
  48. >>> # Write the result as new raster map with name map2d_2
  49. ... map2d_2.write(mapname="map2d_2", overwrite=True)
  50. 100%
  51. 0
  52. >>>
  53. >>> # Here we create a 3D raster map numpy array
  54. ... # based in the current region settings
  55. ... map3d_1 = garray.array3d()
  56. >>>
  57. >>> # Write some data
  58. ... # Note: the 3D array has map[depth][row][column] order
  59. ... for z in range(map3d_1.shape[0]):
  60. ... for y in range(map3d_1.shape[1]):
  61. ... for x in range(map3d_1.shape[2]):
  62. ... map3d_1[z][y][x] = z + y + x
  63. ...
  64. >>> # Lets have a look at the 3D array
  65. ... print map3d_1
  66. [[[ 0. 1. 2. 3. 4. 5.]
  67. [ 1. 2. 3. 4. 5. 6.]
  68. [ 2. 3. 4. 5. 6. 7.]
  69. [ 3. 4. 5. 6. 7. 8.]]
  70. [[ 1. 2. 3. 4. 5. 6.]
  71. [ 2. 3. 4. 5. 6. 7.]
  72. [ 3. 4. 5. 6. 7. 8.]
  73. [ 4. 5. 6. 7. 8. 9.]]
  74. [[ 2. 3. 4. 5. 6. 7.]
  75. [ 3. 4. 5. 6. 7. 8.]
  76. [ 4. 5. 6. 7. 8. 9.]
  77. [ 5. 6. 7. 8. 9. 10.]]]
  78. >>> # This will write the numpy array as GRASS 3D raster map
  79. ... # with name map3d_1
  80. ... map3d_1.write(mapname="map3d_1", overwrite=True)
  81. Loading floating point data with 8 bytes ... (6x4x3)
  82. 100%
  83. 0
  84. >>> # We create a new 3D array and read map3d_1 to modify it
  85. ... map3d_2 = garray.array3d()
  86. >>> # Don't do map3d_2 = map3d_1 % 3
  87. ... # because: this will overwrite the internal temporary filename
  88. ... map3d_2.read("map3d_1")
  89. 0
  90. >>> map3d_2 %= 3
  91. >>> # Show the result
  92. ... print map3d_2
  93. [[[ 0. 1. 2. 0. 1. 2.]
  94. [ 1. 2. 0. 1. 2. 0.]
  95. [ 2. 0. 1. 2. 0. 1.]
  96. [ 0. 1. 2. 0. 1. 2.]]
  97. [[ 1. 2. 0. 1. 2. 0.]
  98. [ 2. 0. 1. 2. 0. 1.]
  99. [ 0. 1. 2. 0. 1. 2.]
  100. [ 1. 2. 0. 1. 2. 0.]]
  101. [[ 2. 0. 1. 2. 0. 1.]
  102. [ 0. 1. 2. 0. 1. 2.]
  103. [ 1. 2. 0. 1. 2. 0.]
  104. [ 2. 0. 1. 2. 0. 1.]]]
  105. >>> # Write the result as new 3D raster map with name map3d_2
  106. ... map3d_2.write(mapname="map3d_2", overwrite=True)
  107. Loading floating point data with 8 bytes ... (6x4x3)
  108. 100%
  109. 0
  110. @endcode
  111. (C) 2010-2012 by Glynn Clements and the GRASS Development Team
  112. This program is free software under the GNU General Public
  113. License (>=v2). Read the file COPYING that comes with GRASS
  114. for details.
  115. @author Glynn Clements
  116. """
  117. import os
  118. import numpy
  119. from utils import try_remove
  120. import core as grass
  121. ###############################################################################
  122. class array(numpy.memmap):
  123. def __new__(cls, dtype=numpy.double):
  124. """!Define new numpy array
  125. @param cls
  126. @param dtype data type (default: numpy.double)
  127. """
  128. reg = grass.region()
  129. r = reg['rows']
  130. c = reg['cols']
  131. shape = (r, c)
  132. filename = grass.tempfile()
  133. self = numpy.memmap.__new__(
  134. cls,
  135. filename=filename,
  136. dtype=dtype,
  137. mode='w+',
  138. shape=shape)
  139. self.filename = filename
  140. return self
  141. def _close(self):
  142. numpy.memmap._close(self)
  143. if isinstance(self, array):
  144. try_remove(self.filename)
  145. def read(self, mapname, null=None):
  146. """!Read raster map into array
  147. @param mapname name of raster map to be read
  148. @param null null value
  149. @return 0 on success
  150. @return non-zero code on failure
  151. """
  152. kind = self.dtype.kind
  153. size = self.dtype.itemsize
  154. if kind == 'f':
  155. flags = 'f'
  156. elif kind in 'biu':
  157. flags = 'i'
  158. else:
  159. raise ValueError(_('Invalid kind <%s>') % kind)
  160. if size not in [1, 2, 4, 8]:
  161. raise ValueError(_('Invalid size <%d>') % size)
  162. return grass.run_command(
  163. 'r.out.bin',
  164. flags=flags,
  165. input=mapname,
  166. output=self.filename,
  167. bytes=size,
  168. null=null,
  169. quiet=True,
  170. overwrite=True)
  171. def write(self, mapname, title=None, null=None, overwrite=None):
  172. """!Write array into raster map
  173. @param mapname name for raster map
  174. @param title title for raster map
  175. @param null null value
  176. @param overwrite True for overwritting existing raster maps
  177. @return 0 on success
  178. @return non-zero code on failure
  179. """
  180. kind = self.dtype.kind
  181. size = self.dtype.itemsize
  182. if kind == 'f':
  183. if size == 4:
  184. flags = 'f'
  185. elif size == 8:
  186. flags = 'd'
  187. else:
  188. raise ValueError(_('Invalid FP size <%d>') % size)
  189. size = None
  190. elif kind in 'biu':
  191. if size not in [1, 2, 4]:
  192. raise ValueError(_('Invalid integer size <%d>') % size)
  193. flags = None
  194. else:
  195. raise ValueError(_('Invalid kind <%s>') % kind)
  196. reg = grass.region()
  197. return grass.run_command(
  198. 'r.in.bin',
  199. flags=flags,
  200. input=self.filename,
  201. output=mapname,
  202. title=title,
  203. bytes=size,
  204. anull=null,
  205. overwrite=overwrite,
  206. north=reg['n'],
  207. south=reg['s'],
  208. east=reg['e'],
  209. west=reg['w'],
  210. rows=reg['rows'],
  211. cols=reg['cols'])
  212. ###############################################################################
  213. class array3d(numpy.memmap):
  214. def __new__(cls, dtype=numpy.double):
  215. """!Define new 3d numpy array
  216. @param cls
  217. @param dtype data type (default: numpy.double)
  218. """
  219. reg = grass.region(True)
  220. r = reg['rows3']
  221. c = reg['cols3']
  222. d = reg['depths']
  223. shape = (d, r, c)
  224. filename = grass.tempfile()
  225. self = numpy.memmap.__new__(
  226. cls,
  227. filename=filename,
  228. dtype=dtype,
  229. mode='w+',
  230. shape=shape)
  231. self.filename = filename
  232. return self
  233. def _close(self):
  234. numpy.memmap._close(self)
  235. if isinstance(self, array):
  236. try_remove(self.filename)
  237. def read(self, mapname, null=None):
  238. """!Read 3D raster map into array
  239. @param mapname name of 3D raster map to be read
  240. @param null null value
  241. @return 0 on success
  242. @return non-zero code on failure
  243. """
  244. kind = self.dtype.kind
  245. size = self.dtype.itemsize
  246. if kind == 'f':
  247. flags = None # default is double
  248. elif kind in 'biu':
  249. flags = 'i'
  250. else:
  251. raise ValueError(_('Invalid kind <%s>') % kind)
  252. if size not in [1, 2, 4, 8]:
  253. raise ValueError(_('Invalid size <%d>') % size)
  254. return grass.run_command(
  255. 'r3.out.bin',
  256. flags=flags,
  257. input=mapname,
  258. output=self.filename,
  259. bytes=size,
  260. null=null,
  261. quiet=True,
  262. overwrite=True)
  263. def write(self, mapname, null=None, overwrite=None):
  264. """!Write array into 3D raster map
  265. @param mapname name for 3D raster map
  266. @param null null value
  267. @param overwrite True for overwriting existing raster maps
  268. @return 0 on success
  269. @return non-zero code on failure
  270. """
  271. kind = self.dtype.kind
  272. size = self.dtype.itemsize
  273. flags = None
  274. if kind == 'f':
  275. if size != 4 and size != 8:
  276. raise ValueError(_('Invalid FP size <%d>') % size)
  277. elif kind in 'biu':
  278. if size not in [1, 2, 4, 8]:
  279. raise ValueError(_('Invalid integer size <%d>') % size)
  280. flags = 'i'
  281. else:
  282. raise ValueError(_('Invalid kind <%s>') % kind)
  283. reg = grass.region(True)
  284. return grass.run_command(
  285. 'r3.in.bin',
  286. flags=flags,
  287. input=self.filename,
  288. output=mapname,
  289. bytes=size,
  290. null=null,
  291. overwrite=overwrite,
  292. north=reg['n'],
  293. south=reg['s'],
  294. top=reg['t'],
  295. bottom=reg['b'],
  296. east=reg['e'],
  297. west=reg['w'],
  298. depths=reg['depths'],
  299. rows=reg['rows3'],
  300. cols=reg['cols3'])