__init__.py 25 KB

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