__init__.py 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754
  1. # -*- coding: utf-8 -*-
  2. from __future__ import (nested_scopes, generators, division, absolute_import,
  3. with_statement, print_function, unicode_literals)
  4. import os
  5. import ctypes
  6. import numpy as np
  7. #
  8. # import GRASS modules
  9. #
  10. from grass.script import fatal, warning
  11. from grass.script import core as grasscore
  12. import grass.lib.gis as libgis
  13. import grass.lib.raster as libraster
  14. import grass.lib.rowio as librowio
  15. libgis.G_gisinit('')
  16. #
  17. # import pygrass modules
  18. #
  19. from grass.pygrass.errors import OpenError, must_be_open
  20. from grass.pygrass.gis.region import Region
  21. from grass.pygrass import utils
  22. #
  23. # import raster classes
  24. #
  25. from grass.pygrass.raster.abstract import RasterAbstractBase
  26. from grass.pygrass.raster.raster_type import TYPE as RTYPE, RTYPE_STR
  27. from grass.pygrass.raster.buffer import Buffer
  28. from grass.pygrass.raster.segment import Segment
  29. from grass.pygrass.raster.rowio import RowIO
  30. WARN_OVERWRITE = "Raster map <{0}> already exists and will be overwritten"
  31. test_raster_name="Raster_test_map"
  32. class RasterRow(RasterAbstractBase):
  33. """Raster_row_access": Inherits: "Raster_abstract_base" and implements
  34. the default row access of the Rast library.
  35. * Implements row access using row id
  36. * The get_row() method must accept a Row object as argument that will
  37. be used for value storage, so no new buffer will be allocated
  38. * Implements sequential writing of rows
  39. * Implements indexed value read only access using the [row][col]
  40. operator
  41. * Implements the [row] read method that returns a new Row object
  42. * Writing is limited using the put_row() method which accepts a
  43. Row as argument
  44. * No mathematical operation like __add__ and stuff for the Raster
  45. object (only for rows), since r.mapcalc is more sophisticated and
  46. faster
  47. Examples:
  48. >>> elev = RasterRow(test_raster_name)
  49. >>> elev.exist()
  50. True
  51. >>> elev.is_open()
  52. False
  53. >>> elev.open()
  54. >>> elev.is_open()
  55. True
  56. >>> elev.has_cats()
  57. True
  58. >>> elev.mode
  59. u'r'
  60. >>> elev.mtype
  61. 'CELL'
  62. >>> elev.num_cats()
  63. 16
  64. >>> elev.info.range
  65. (11, 44)
  66. >>> elev.info.cols
  67. 4
  68. >>> elev.info.rows
  69. 4
  70. Editing the history
  71. >>> elev.hist.read()
  72. >>> elev.hist.title = "A test map"
  73. >>> elev.hist.write()
  74. >>> elev.hist.title
  75. 'A test map'
  76. >>> elev.hist.keyword
  77. 'This is a test map'
  78. >>> attrs = list(elev.hist)
  79. >>> attrs[0]
  80. ('name', u'Raster_test_map')
  81. >>> attrs[1]
  82. ('mapset', 'user1')
  83. >>> attrs[2]
  84. ('mtype', '')
  85. >>> attrs[3]
  86. ('creator', 'soeren')
  87. Each Raster map have an attribute call ``cats`` that allow user
  88. to interact with the raster categories.
  89. >>> elev.cats # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE
  90. [('A', 11, None),
  91. ('B', 12, None),
  92. ...
  93. ('P', 44, None)]
  94. >>> elev.cats.labels() # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE
  95. ['A', 'B', 'C', 'D', 'E',
  96. 'F', 'G', 'H', 'I', 'J',
  97. 'K', 'L', 'M', 'n', 'O', 'P']
  98. >>> elev.cats[0]
  99. ('A', 11, None)
  100. >>> elev.cats[2]
  101. ('C', 13, None)
  102. >>> elev.cats[0] = ('AA', 11)
  103. >>> elev.cats[1] = ('BB', 12)
  104. >>> elev.cats.write()
  105. >>> elev.cats.read()
  106. >>> elev.cats[0]
  107. ('AA', 11, None)
  108. >>> elev.cats[1]
  109. ('BB', 12, None)
  110. Open a raster map using the *with statement*:
  111. >>> with RasterRow(test_raster_name) as elev:
  112. ... for row in elev:
  113. ... row
  114. Buffer([11, 21, 31, 41], dtype=int32)
  115. Buffer([12, 22, 32, 42], dtype=int32)
  116. Buffer([13, 23, 33, 43], dtype=int32)
  117. Buffer([14, 24, 34, 44], dtype=int32)
  118. >>> elev.is_open()
  119. False
  120. """
  121. def __init__(self, name, mapset='', *args, **kargs):
  122. super(RasterRow, self).__init__(name, mapset, *args, **kargs)
  123. # mode = "r", method = "row",
  124. @must_be_open
  125. def get_row(self, row, row_buffer=None):
  126. """Private method that return the row using the read mode
  127. call the `Rast_get_row` C function.
  128. :param row: the number of row to obtain
  129. :type row: int
  130. :param row_buffer: Buffer object instance with the right dim and type
  131. :type row_buffer: Buffer
  132. >>> elev = RasterRow(test_raster_name)
  133. >>> elev.open()
  134. >>> elev[0]
  135. Buffer([11, 21, 31, 41], dtype=int32)
  136. >>> elev.get_row(0)
  137. Buffer([11, 21, 31, 41], dtype=int32)
  138. """
  139. if row_buffer is None:
  140. row_buffer = Buffer((self._cols,), self.mtype)
  141. libraster.Rast_get_row(self._fd, row_buffer.p, row, self._gtype)
  142. return row_buffer
  143. @must_be_open
  144. def put_row(self, row):
  145. """Private method to write the row sequentially.
  146. :param row: a Row object to insert into raster
  147. :type row: Buffer object
  148. """
  149. libraster.Rast_put_row(self._fd, row.p, self._gtype)
  150. def open(self, mode=None, mtype=None, overwrite=None):
  151. """Open the raster if exist or created a new one.
  152. :param str mode: Specify if the map will be open with read or write mode
  153. ('r', 'w')
  154. :param str type: If a new map is open, specify the type of the map(`CELL`,
  155. `FCELL`, `DCELL`)
  156. :param bool overwrite: Use this flag to set the overwrite mode of existing
  157. raster maps
  158. if the map already exist, automatically check the type and set:
  159. * self.mtype
  160. Set all the privite, attributes:
  161. * self._fd;
  162. * self._gtype
  163. * self._rows and self._cols
  164. """
  165. self.mode = mode if mode else self.mode
  166. self.mtype = mtype if mtype else self.mtype
  167. self.overwrite = overwrite if overwrite is not None else self.overwrite
  168. if self.mode == 'r':
  169. if self.exist():
  170. self.info.read()
  171. self.cats.mtype = self.mtype
  172. self.cats.read()
  173. self.hist.read()
  174. self._fd = libraster.Rast_open_old(self.name, self.mapset)
  175. self._gtype = libraster.Rast_get_map_type(self._fd)
  176. self.mtype = RTYPE_STR[self._gtype]
  177. else:
  178. str_err = _("The map does not exist, I can't open in 'r' mode")
  179. raise OpenError(str_err)
  180. elif self.mode == 'w':
  181. if self.exist():
  182. if not self.overwrite:
  183. str_err = _("Raster map <{0}> already exists"
  184. " and will be not overwritten")
  185. raise OpenError(str_err.format(self))
  186. if self._gtype is None:
  187. raise OpenError(_("Raster type not defined"))
  188. self._fd = libraster.Rast_open_new(self.name, self._gtype)
  189. else:
  190. raise OpenError("Open mode: %r not supported,"
  191. " valid mode are: r, w")
  192. # read rows and cols from the active region
  193. self._rows = libraster.Rast_window_rows()
  194. self._cols = libraster.Rast_window_cols()
  195. class RasterRowIO(RasterRow):
  196. """Raster_row_cache_access": The same as "Raster_row_access" but uses
  197. the ROWIO library for cached row access
  198. """
  199. def __init__(self, name, *args, **kargs):
  200. self.rowio = RowIO()
  201. super(RasterRowIO, self).__init__(name, *args, **kargs)
  202. def open(self, mode=None, mtype=None, overwrite=False):
  203. """Open the raster if exist or created a new one.
  204. :param mode: specify if the map will be open with read or write mode
  205. ('r', 'w')
  206. :type mode: str
  207. :param type: if a new map is open, specify the type of the map(`CELL`,
  208. `FCELL`, `DCELL`)
  209. :type type: str
  210. :param overwrite: use this flag to set the overwrite mode of existing
  211. raster maps
  212. :type overwrite: bool
  213. """
  214. super(RasterRowIO, self).open(mode, mtype, overwrite)
  215. self.rowio.open(self._fd, self._rows, self._cols, self.mtype)
  216. @must_be_open
  217. def close(self):
  218. """Function to close the raster"""
  219. self.rowio.release()
  220. libraster.Rast_close(self._fd)
  221. # update rows and cols attributes
  222. self._rows = None
  223. self._cols = None
  224. self._fd = None
  225. @must_be_open
  226. def get_row(self, row, row_buffer=None):
  227. """This method returns the row using:
  228. * the read mode and
  229. * `rowcache` method
  230. :param row: the number of row to obtain
  231. :type row: int
  232. :param row_buffer: Specify the Buffer object that will be instantiate
  233. :type row_buffer: Buffer object
  234. >>> elev = RasterRowIO(test_raster_name)
  235. >>> elev.open('r')
  236. >>> for row in elev:
  237. ... row
  238. Buffer([11, 21, 31, 41], dtype=int32)
  239. Buffer([12, 22, 32, 42], dtype=int32)
  240. Buffer([13, 23, 33, 43], dtype=int32)
  241. Buffer([14, 24, 34, 44], dtype=int32)
  242. >>> elev.close()
  243. """
  244. if row_buffer is None:
  245. row_buffer = Buffer((self._cols,), self.mtype)
  246. rowio_buf = librowio.Rowio_get(ctypes.byref(self.rowio.c_rowio), row)
  247. ctypes.memmove(row_buffer.p, rowio_buf, self.rowio.row_size)
  248. return row_buffer
  249. class RasterSegment(RasterAbstractBase):
  250. """Raster_segment_access": Inherits "Raster_abstract_base" and uses the
  251. segment library for cached randomly reading and writing access.
  252. * Implements the [row][col] operator for read and write access using
  253. Segment_get() and Segment_put() functions internally
  254. * Implements row read and write access with the [row] operator using
  255. Segment_get_row() Segment_put_row() internally
  256. * Implements the get_row() and put_row() method using
  257. Segment_get_row() Segment_put_row() internally
  258. * Implements the flush_segment() method
  259. * Implements the copying of raster maps to segments and vice verse
  260. * Overwrites the open and close methods
  261. * No mathematical operation like __add__ and stuff for the Raster
  262. object (only for rows), since r.mapcalc is more sophisticated and
  263. faster
  264. """
  265. def __init__(self, name, srows=64, scols=64, maxmem=100,
  266. *args, **kargs):
  267. self.segment = Segment(srows, scols, maxmem)
  268. super(RasterSegment, self).__init__(name, *args, **kargs)
  269. def _get_mode(self):
  270. return self._mode
  271. def _set_mode(self, mode):
  272. if mode and mode.lower() not in ('r', 'w', 'rw'):
  273. str_err = _("Mode type: {0} not supported ('r', 'w','rw')")
  274. raise ValueError(str_err.format(mode))
  275. self._mode = mode
  276. mode = property(fget=_get_mode, fset=_set_mode,
  277. doc="Set or obtain the opening mode of raster")
  278. def __setitem__(self, key, row):
  279. """Return the row of Raster object, slice allowed."""
  280. if isinstance(key, slice):
  281. #Get the start, stop, and step from the slice
  282. return [self.put_row(ii, row)
  283. for ii in range(*key.indices(len(self)))]
  284. elif isinstance(key, tuple):
  285. x, y = key
  286. return self.put(x, y, row)
  287. elif isinstance(key, int):
  288. if key < 0: # Handle negative indices
  289. key += self._rows
  290. if key >= self._rows:
  291. raise IndexError(_("Index out of range: %r.") % key)
  292. return self.put_row(key, row)
  293. else:
  294. raise TypeError("Invalid argument type.")
  295. @must_be_open
  296. def map2segment(self):
  297. """Transform an existing map to segment file.
  298. """
  299. row_buffer = Buffer((self._cols), self.mtype)
  300. for row in range(self._rows):
  301. libraster.Rast_get_row(
  302. self._fd, row_buffer.p, row, self._gtype)
  303. self.segment.put_row(row, row_buffer)
  304. @must_be_open
  305. def segment2map(self):
  306. """Transform the segment file to a map.
  307. """
  308. row_buffer = Buffer((self._cols), self.mtype)
  309. for row in range(self._rows):
  310. row_buffer = self.segment.get_row(row, row_buffer)
  311. libraster.Rast_put_row(self._fd, row_buffer.p, self._gtype)
  312. @must_be_open
  313. def get_row(self, row, row_buffer=None):
  314. """Return the row using the `segment.get_row` method
  315. :param row: specify the row number
  316. :type row: int
  317. :param row_buffer: specify the Buffer object that will be instantiate
  318. :type row_buffer: Buffer object
  319. >>> elev = RasterRowIO(test_raster_name)
  320. >>> elev.open('r')
  321. >>> for row in elev:
  322. ... row
  323. Buffer([11, 21, 31, 41], dtype=int32)
  324. Buffer([12, 22, 32, 42], dtype=int32)
  325. Buffer([13, 23, 33, 43], dtype=int32)
  326. Buffer([14, 24, 34, 44], dtype=int32)
  327. >>> elev.close()
  328. >>> with RasterSegment(test_raster_name) as elev:
  329. ... for row in elev:
  330. ... row
  331. Buffer([11, 21, 31, 41], dtype=int32)
  332. Buffer([12, 22, 32, 42], dtype=int32)
  333. Buffer([13, 23, 33, 43], dtype=int32)
  334. Buffer([14, 24, 34, 44], dtype=int32)
  335. """
  336. if row_buffer is None:
  337. row_buffer = Buffer((self._cols), self.mtype)
  338. return self.segment.get_row(row, row_buffer)
  339. @must_be_open
  340. def put_row(self, row, row_buffer):
  341. """Write the row using the `segment.put_row` method
  342. :param row: a Row object to insert into raster
  343. :type row: Buffer object
  344. Input and output must have the same type in case of row copy
  345. >>> map_a = RasterSegment(test_raster_name)
  346. >>> map_b = RasterSegment(test_raster_name + "_segment")
  347. >>> map_a.open('r')
  348. >>> map_b.open('w', mtype="CELL", overwrite=True)
  349. >>> for row in xrange(map_a.info.rows):
  350. ... map_b[row] = map_a[row] + 1000
  351. >>> map_a.close()
  352. >>> map_b.close()
  353. >>> map_b = RasterSegment(test_raster_name + "_segment")
  354. >>> map_b.open("r")
  355. >>> for row in map_b:
  356. ... row
  357. Buffer([1011, 1021, 1031, 1041], dtype=int32)
  358. Buffer([1012, 1022, 1032, 1042], dtype=int32)
  359. Buffer([1013, 1023, 1033, 1043], dtype=int32)
  360. Buffer([1014, 1024, 1034, 1044], dtype=int32)
  361. >>> map_b.close()
  362. """
  363. self.segment.put_row(row, row_buffer)
  364. @must_be_open
  365. def get(self, row, col):
  366. """Return the map value using the `segment.get` method
  367. :param row: Specify the row number
  368. :type row: int
  369. :param col: Specify the column number
  370. :type col: int
  371. >>> elev = RasterSegment(test_raster_name)
  372. >>> elev.open('r')
  373. >>> for i in xrange(4):
  374. ... elev.get(i,i)
  375. 11
  376. 22
  377. 33
  378. 44
  379. >>> elev.close()
  380. >>> with RasterSegment(test_raster_name) as elev:
  381. ... elev.get(0,0)
  382. ... elev.get(1,1)
  383. ... elev.get(2,2)
  384. ... elev.get(3,3)
  385. 11
  386. 22
  387. 33
  388. 44
  389. """
  390. return self.segment.get(row, col)
  391. @must_be_open
  392. def put(self, row, col, val):
  393. """Write the value to the map using the `segment.put` method
  394. :param row: Specify the row number
  395. :type row: int
  396. :param col: Specify the column number
  397. :type col: int
  398. :param val: Specify the value that will be write to the map cell
  399. :type val: value
  400. >>> map_a = RasterSegment(test_raster_name)
  401. >>> map_b = RasterSegment(test_raster_name + "_segment")
  402. >>> map_a.open('r')
  403. >>> map_b.open('w', mtype="FCELL", overwrite=True)
  404. >>> for row in xrange(map_a.info.rows):
  405. ... for col in xrange(map_a.info.cols):
  406. ... value = map_a.get(row,col)
  407. ... map_b.put(row,col,value + 100)
  408. >>> map_a.close()
  409. >>> map_b.close()
  410. >>> map_b = RasterSegment(test_raster_name + "_segment")
  411. >>> map_b.open("r")
  412. >>> for row in map_b:
  413. ... row
  414. Buffer([ 111., 121., 131., 141.], dtype=float32)
  415. Buffer([ 112., 122., 132., 142.], dtype=float32)
  416. Buffer([ 113., 123., 133., 143.], dtype=float32)
  417. Buffer([ 114., 124., 134., 144.], dtype=float32)
  418. >>> map_b.close()
  419. """
  420. self.segment.val.value = val
  421. self.segment.put(row, col)
  422. def open(self, mode=None, mtype=None, overwrite=None):
  423. """Open the map, if the map already exist: determine the map type
  424. and copy the map to the segment files;
  425. else, open a new segment map.
  426. :param mode: specify if the map will be open with read, write or
  427. read/write mode ('r', 'w', 'rw')
  428. :type mode: str
  429. :param mtype: specify the map type, valid only for new maps: CELL,
  430. FCELL, DCELL
  431. :type mtype: str
  432. :param overwrite: use this flag to set the overwrite mode of existing
  433. raster maps
  434. :type overwrite: bool
  435. """
  436. # read rows and cols from the active region
  437. self._rows = libraster.Rast_window_rows()
  438. self._cols = libraster.Rast_window_cols()
  439. self.mode = mode if mode else self.mode
  440. self.mtype = mtype if mtype else self.mtype
  441. self.overwrite = overwrite if overwrite is not None else self.overwrite
  442. if self.exist():
  443. self.info.read()
  444. self.cats.mtype = self.mtype
  445. self.cats.read()
  446. self.hist.read()
  447. if ((self.mode == "w" or self.mode == "rw") and
  448. self.overwrite is False):
  449. str_err = _("Raster map <{0}> already exists. Use overwrite.")
  450. fatal(str_err.format(self))
  451. # We copy the raster map content into the segments
  452. if self.mode == "rw" or self.mode == "r":
  453. self._fd = libraster.Rast_open_old(self.name, self.mapset)
  454. self._gtype = libraster.Rast_get_map_type(self._fd)
  455. self.mtype = RTYPE_STR[self._gtype]
  456. # initialize the segment, I need to determine the mtype of the
  457. # map
  458. # before to open the segment
  459. self.segment.open(self)
  460. self.map2segment()
  461. self.segment.flush()
  462. self.cats.read()
  463. self.hist.read()
  464. if self.mode == "rw":
  465. #warning(_(WARN_OVERWRITE.format(self)))
  466. # Close the file descriptor and open it as new again
  467. libraster.Rast_close(self._fd)
  468. self._fd = libraster.Rast_open_new(
  469. self.name, self._gtype)
  470. # Here we simply overwrite the existing map without content copying
  471. elif self.mode == "w":
  472. #warning(_(WARN_OVERWRITE.format(self)))
  473. self._gtype = RTYPE[self.mtype]['grass type']
  474. self.segment.open(self)
  475. self._fd = libraster.Rast_open_new(self.name, self._gtype)
  476. else:
  477. if self.mode == "r":
  478. str_err = _("Raster map <{0}> does not exists")
  479. raise OpenError(str_err.format(self.name))
  480. self._gtype = RTYPE[self.mtype]['grass type']
  481. self.segment.open(self)
  482. self._fd = libraster.Rast_open_new(self.name, self._gtype)
  483. @must_be_open
  484. def close(self, rm_temp_files=True):
  485. """Close the map, copy the segment files to the map.
  486. :param rm_temp_files: if True all the segments file will be removed
  487. :type rm_temp_files: bool
  488. """
  489. if self.mode == "w" or self.mode == "rw":
  490. self.segment.flush()
  491. self.segment2map()
  492. if rm_temp_files:
  493. self.segment.close()
  494. else:
  495. self.segment.release()
  496. libraster.Rast_close(self._fd)
  497. # update rows and cols attributes
  498. self._rows = None
  499. self._cols = None
  500. self._fd = None
  501. def random_map_only_columns(mapname, mtype, overwrite=True, factor=100):
  502. region = Region()
  503. random_map = RasterRow(mapname)
  504. row_buf = Buffer((region.cols, ), mtype,
  505. buffer=(np.random.random(region.cols,) * factor).data)
  506. random_map.open('w', mtype, overwrite)
  507. for _ in range(region.rows):
  508. random_map.put_row(row_buf)
  509. random_map.close()
  510. return random_map
  511. def random_map(mapname, mtype, overwrite=True, factor=100):
  512. region = Region()
  513. random_map = RasterRow(mapname)
  514. random_map.open('w', mtype, overwrite)
  515. for _ in range(region.rows):
  516. row_buf = Buffer((region.cols, ), mtype,
  517. buffer=(np.random.random(region.cols,) * factor).data)
  518. random_map.put_row(row_buf)
  519. random_map.close()
  520. return random_map
  521. def raster2numpy(rastname, mapset=''):
  522. """Return a numpy array from a raster map
  523. :param str rastname: the name of raster map
  524. :parar str mapset: the name of mapset containig raster map
  525. """
  526. with RasterRow(rastname, mapset=mapset, mode='r') as rast:
  527. return np.array(rast)
  528. def raster2numpy_img(rastname, region, color="ARGB", array=None):
  529. """Convert a raster map layer into a string with
  530. 32Bit ARGB, 24Bit RGB or 8Bit Gray little endian encoding.
  531. Return a numpy array from a raster map of type uint8
  532. that contains the colored map data as 32 bit ARGB, 32Bit RGB
  533. or 8 bit image
  534. :param rastname: The name of raster map
  535. :type rastname: string
  536. :param region: The region to be used for raster map reading
  537. :type region: grass.pygrass.gis.region.Region
  538. :param color: "ARGB", "RGB", "GRAY1", "GRAY2"
  539. ARGB -> 32Bit RGB with alpha channel (0xAARRGGBB)
  540. RGB -> 32Bit RGB (0xffRRGGBB)
  541. GRAY1 -> grey scale formular: .33R+ .5G+ .17B
  542. GRAY2 -> grey scale formular: .30R+ .59G+ .11B
  543. :type color: String
  544. :param array: A numpy array (optional) to store the image,
  545. the array needs to setup as follows:
  546. array = np.ndarray((region.rows*region.cols*scale), np.uint8)
  547. scale = 4 in case of ARGB and RGB or scale = 1
  548. in case of Gray scale
  549. :type array: numpy.ndarray
  550. :return: A numpy array of size rows*cols*4 in case of ARGB, RGB and
  551. rows*cols*1 in case of gray scale
  552. Attention: This function will change the computational raster region
  553. of the current process while running.
  554. """
  555. from copy import deepcopy
  556. region_orig = deepcopy(region)
  557. # Set the raster region
  558. region.set_raster_region()
  559. scale = 1
  560. color_mode = 1
  561. if color.upper() == "ARGB":
  562. scale = 4
  563. color_mode = 1
  564. elif color.upper() == "RGB":
  565. scale = 4
  566. color_mode = 2
  567. elif color.upper() == "GRAY1":
  568. scale = 1
  569. color_mode = 3
  570. elif color.upper() == "GRAY2":
  571. scale = 1
  572. color_mode = 4
  573. if array is None:
  574. array = np.ndarray((region.rows*region.cols*scale), np.uint8)
  575. libraster.Rast_map_to_img_str(rastname, color_mode,
  576. array.ctypes.data_as(ctypes.POINTER(ctypes.c_uint8)))
  577. # Restore the raster region
  578. region_orig.set_raster_region()
  579. return array
  580. def numpy2raster(array, mtype, rastname, overwrite=False):
  581. """Save a numpy array to a raster map
  582. :param obj array: a numpy array
  583. :param obj mtype: the datatype of array
  584. :param str rastername: the name of output map
  585. :param bool overwrite: True to overwrite existing map
  586. """
  587. reg = Region()
  588. if (reg.rows, reg.cols) != array.shape:
  589. msg = "Region and array are different: %r != %r"
  590. raise TypeError(msg % ((reg.rows, reg.cols), array.shape))
  591. with RasterRow(rastname, mode='w', mtype=mtype, overwrite=overwrite) as new:
  592. newrow = Buffer((array.shape[1],), mtype=mtype)
  593. for row in array:
  594. newrow[:] = row[:]
  595. new.put_row(newrow)
  596. if __name__ == "__main__":
  597. import doctest
  598. from grass.pygrass import utils
  599. from grass.pygrass.modules import Module
  600. Module("g.region", n=40, s=0, e=40, w=0, res=10)
  601. Module("r.mapcalc", expression="%s = row() + (10 * col())"%(test_raster_name),
  602. overwrite=True)
  603. Module("r.support", map=test_raster_name,
  604. title="A test map",
  605. history="Generated by r.mapcalc",
  606. description="This is a test map")
  607. cats="""11:A
  608. 12:B
  609. 13:C
  610. 14:D
  611. 21:E
  612. 22:F
  613. 23:G
  614. 24:H
  615. 31:I
  616. 32:J
  617. 33:K
  618. 34:L
  619. 41:M
  620. 42:n
  621. 43:O
  622. 44:P"""
  623. Module("r.category", rules="-", map=test_raster_name,
  624. stdin_=cats, separator=":")
  625. doctest.testmod()
  626. """Remove the generated vector map, if exist"""
  627. mset = utils.get_mapset_raster(test_raster_name, mapset='')
  628. if mset:
  629. Module("g.remove", flags='f', type='raster', name=test_raster_name)
  630. mset = utils.get_mapset_raster(test_raster_name + "_segment",
  631. mapset='')
  632. if mset:
  633. Module("g.remove", flags='f', type='raster',
  634. name=test_raster_name + "_segment")