array.py 9.9 KB

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