__init__.py 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680
  1. # -*- coding: utf-8 -*-
  2. """
  3. Created on Fri May 25 12:56:33 2012
  4. @author: pietro
  5. """
  6. import ctypes
  7. import numpy as np
  8. #
  9. # import GRASS modules
  10. #
  11. from grass.script import fatal, warning
  12. from grass.script import core as grasscore
  13. #from grass.script import core
  14. #import grass.lib as grasslib
  15. import grass.lib.gis as libgis
  16. import grass.lib.raster as libraster
  17. import grass.lib.segment as libseg
  18. import grass.lib.rowio as librowio
  19. #
  20. # import pygrass modules
  21. #
  22. from pygrass.errors import OpenError, must_be_open
  23. from pygrass.region import Region
  24. #
  25. # import raster classes
  26. #
  27. from abstract import RasterAbstractBase
  28. from raster_type import TYPE as RTYPE, RTYPE_STR
  29. from buffer import Buffer
  30. from segment import Segment
  31. from rowio import RowIO
  32. from category import Category
  33. from history import History
  34. class RasterRow(RasterAbstractBase):
  35. """Raster_row_access": Inherits: "Raster_abstract_base" and implements
  36. the default row access of the Rast library.
  37. * Implements row access using row id
  38. * The get_row() method must accept a Row object as argument that will
  39. be used for value storage, so no new buffer will be allocated
  40. * Implements sequential writing of rows
  41. * Implements indexed value read only access using the [row][col]
  42. operator
  43. * Implements the [row] read method that returns a new Row object
  44. * Writing is limited using the put_row() method which accepts a
  45. Row as argument
  46. * No mathematical operation like __add__ and stuff for the Raster
  47. object (only for rows), since r.mapcalc is more sophisticated and
  48. faster
  49. Examples
  50. --------
  51. ::
  52. >>> elev = RasterRow('elevation')
  53. >>> elev.exist()
  54. True
  55. >>> elev.is_open()
  56. False
  57. >>> elev.cols
  58. >>> elev.open()
  59. >>> elev.is_open()
  60. True
  61. >>> type(elev.cols)
  62. <type 'int'>
  63. >>> elev.has_cats()
  64. False
  65. >>> elev.mode
  66. 'r'
  67. >>> elev.mtype
  68. 'FCELL'
  69. >>> elev.num_cats()
  70. 0
  71. >>> elev.range
  72. (55.578792572021484, 156.32986450195312)
  73. Each Raster map have an attribute call ``cats`` that allow user
  74. to interact with the raster categories. ::
  75. >>> land = RasterRow('landcover_1m')
  76. >>> land.open()
  77. >>> land.cats
  78. []
  79. >>> land.read_cats()
  80. >>> land.cats
  81. [('pond', 1, None),
  82. ('forest', 2, None),
  83. ('developed', 3, None),
  84. ('bare', 4, None),
  85. ('paved road', 5, None),
  86. ('dirt road', 6, None),
  87. ('vineyard', 7, None),
  88. ('agriculture', 8, None),
  89. ('wetland', 9, None),
  90. ('bare ground path', 10, None),
  91. ('grass', 11, None)]
  92. """
  93. def __init__(self, name, *args, **kargs):
  94. super(RasterRow, self).__init__(name, *args, **kargs)
  95. # mode = "r", method = "row",
  96. @must_be_open
  97. def get_row(self, row, row_buffer=None):
  98. """Private method that return the row using the read mode
  99. call the `Rast_get_row` C function.
  100. >>> elev = RasterRow('elevation')
  101. >>> elev.open()
  102. >>> elev[0] # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE
  103. Buffer([ 141.99613953, 141.27848816, 141.37904358, ..., 58.40825272,
  104. 58.30711365, 58.18310547], dtype=float32)
  105. >>> elev.get_row(0) # doctest: +ELLIPSIS +NORMALIZE_WHITESPACE
  106. Buffer([ 141.99613953, 141.27848816, 141.37904358, ..., 58.40825272,
  107. 58.30711365, 58.18310547], dtype=float32)
  108. """
  109. if row_buffer is None:
  110. row_buffer = Buffer((self._cols,), self.mtype)
  111. libraster.Rast_get_row(self._fd, row_buffer.p, row, self._gtype)
  112. return row_buffer
  113. @must_be_open
  114. def put_row(self, row):
  115. """Private method to write the row sequentially.
  116. """
  117. libraster.Rast_put_row(self._fd, row.p, self._gtype)
  118. def open(self, mode='r', mtype='CELL', overwrite=False):
  119. """Open the raster if exist or created a new one.
  120. Parameters
  121. ------------
  122. mode: string
  123. Specify if the map will be open with read or write mode ('r', 'w')
  124. type: string
  125. If a new map is open, specify the type of the map(`CELL`, `FCELL`,
  126. `DCELL`)
  127. overwrite: Boolean
  128. Use this flag to set the overwrite mode of existing raster maps
  129. if the map already exist, automatically check the type and set:
  130. * self.mtype
  131. Set all the privite, attributes:
  132. * self._fd;
  133. * self._gtype
  134. * self._rows and self._cols
  135. """
  136. self.mode = mode
  137. self.mtype = mtype
  138. self.overwrite = overwrite
  139. # check if exist and instantiate all the private attributes
  140. if self.exist():
  141. if self.mode == 'r':
  142. # the map exist, read mode
  143. self._fd = libraster.Rast_open_old(self.name, self.mapset)
  144. self._gtype = libraster.Rast_get_map_type(self._fd)
  145. self.mtype = RTYPE_STR[self._gtype]
  146. elif self.overwrite:
  147. if self._gtype is None:
  148. raise OpenError(_("Raster type not defined"))
  149. self._fd = libraster.Rast_open_new(self.name, self._gtype)
  150. else:
  151. str_err = _("Raster map <{0}> already exists")
  152. raise OpenError(str_err.format(self))
  153. else:
  154. # Create a new map
  155. if self.mode == 'r':
  156. # check if we are in read mode
  157. str_err = _("The map does not exist, I can't open in 'r' mode")
  158. raise OpenError(str_err)
  159. self._fd = libraster.Rast_open_new(self.name, self._gtype)
  160. # read rows and cols from the active region
  161. self._rows = libraster.Rast_window_rows()
  162. self._cols = libraster.Rast_window_cols()
  163. class RasterRowIO(RasterRow):
  164. """Raster_row_cache_access": The same as "Raster_row_access" but uses
  165. the ROWIO library for cached row access
  166. """
  167. def __init__(self, name, *args, **kargs):
  168. self.rowio = RowIO()
  169. super(RasterRowIO, self).__init__(name, *args, **kargs)
  170. def open(self, mode='r', mtype='CELL', overwrite=False):
  171. super(RasterRowIO, self).open(mode, mtype, overwrite)
  172. self.rowio.open(self._fd, self.rows, self.cols, self.mtype)
  173. @must_be_open
  174. def close(self):
  175. self.rowio.release()
  176. libraster.Rast_close(self._fd)
  177. # update rows and cols attributes
  178. self._rows = None
  179. self._cols = None
  180. self._fd = None
  181. @must_be_open
  182. def get_row(self, row, row_buffer=None):
  183. """This method returns the row using:
  184. * the read mode and
  185. * `rowcache` method
  186. """
  187. if row_buffer is None:
  188. row_buffer = Buffer((self._cols,), self.mtype)
  189. rowio_buf = librowio.Rowio_get(ctypes.byref(self.rowio.crowio), row)
  190. ctypes.memmove(row_buffer.p, rowio_buf, self.rowio.row_size)
  191. return row_buffer
  192. class RasterSegment(RasterAbstractBase):
  193. """Raster_segment_access": Inherits "Raster_abstract_base" and uses the
  194. segment library for cached randomly reading and writing access.
  195. * Implements the [row][col] operator for read and write access using
  196. segement_get() and segment_put() functions internally
  197. * Implements row read and write access with the [row] operator using
  198. segment_get_row() segment_put_row() internally
  199. * Implements the get_row() and put_row() method using
  200. segment_get_row() segment_put_row() internally
  201. * Implements the flush_segment() method
  202. * Implements the copying of raster maps to segments and vice verse
  203. * Overwrites the open and close methods
  204. * No mathematical operation like __add__ and stuff for the Raster
  205. object (only for rows), since r.mapcalc is more sophisticated and
  206. faster
  207. """
  208. def __init__(self, name, srows=64, scols=64, maxmem=100,
  209. *args, **kargs):
  210. self.segment = Segment(srows, scols, maxmem)
  211. super(RasterSegment, self).__init__(name, *args, **kargs)
  212. def _get_mode(self):
  213. return self._mode
  214. def _set_mode(self, mode):
  215. if mode.lower() not in ('r', 'w', 'rw'):
  216. str_err = _("Mode type: {0} not supported ('r', 'w','rw')")
  217. raise ValueError(str_err.format(mode))
  218. self._mode = mode
  219. mode = property(fget=_get_mode, fset=_set_mode)
  220. def __setitem__(self, key, row):
  221. """Return the row of Raster object, slice allowed."""
  222. if isinstance(key, slice):
  223. #Get the start, stop, and step from the slice
  224. return [self.put_row(ii, row)
  225. for ii in xrange(*key.indices(len(self)))]
  226. elif isinstance(key, tuple):
  227. x, y = key
  228. return self.put(x, y, row)
  229. elif isinstance(key, int):
  230. if key < 0: # Handle negative indices
  231. key += self._rows
  232. if key >= self._rows:
  233. raise IndexError(_("Index out of range: %r.") % key)
  234. return self.put_row(key, row)
  235. else:
  236. raise TypeError("Invalid argument type.")
  237. @must_be_open
  238. def map2segment(self):
  239. """Transform an existing map to segment file.
  240. """
  241. row_buffer = Buffer((self._cols), self.mtype)
  242. for row in xrange(self._rows):
  243. libraster.Rast_get_row(
  244. self._fd, row_buffer.p, row, self._gtype)
  245. libseg.segment_put_row(ctypes.byref(self.segment.cseg),
  246. row_buffer.p, row)
  247. @must_be_open
  248. def segment2map(self):
  249. """Transform the segment file to a map.
  250. """
  251. row_buffer = Buffer((self._cols), self.mtype)
  252. for row in xrange(self._rows):
  253. libseg.segment_get_row(ctypes.byref(self.segment.cseg),
  254. row_buffer.p, row)
  255. libraster.Rast_put_row(self._fd, row_buffer.p, self._gtype)
  256. @must_be_open
  257. def get_row(self, row, row_buffer=None):
  258. """Return the row using the `segment.get_row` method
  259. Parameters
  260. ------------
  261. row: integer
  262. Specify the row number;
  263. row_buffer: Buffer object, optional
  264. Specify the Buffer object that will be instantiate.
  265. """
  266. if row_buffer is None:
  267. row_buffer = Buffer((self._cols), self.mtype)
  268. libseg.segment_get_row(
  269. ctypes.byref(self.segment.cseg), row_buffer.p, row)
  270. return row_buffer
  271. @must_be_open
  272. def put_row(self, row, row_buffer):
  273. """Write the row using the `segment.put_row` method
  274. Parameters
  275. ------------
  276. row: integer
  277. Specify the row number;
  278. row_buffer: Buffer object
  279. Specify the Buffer object that will be write to the map.
  280. """
  281. libseg.segment_put_row(ctypes.byref(self.segment.cseg),
  282. row_buffer.p, row)
  283. @must_be_open
  284. def get(self, row, col):
  285. """Return the map value using the `segment.get` method
  286. Parameters
  287. ------------
  288. row: integer
  289. Specify the row number;
  290. col: integer
  291. Specify the column number.
  292. """
  293. libseg.segment_get(ctypes.byref(self.segment.cseg),
  294. ctypes.byref(self.segment.val), row, col)
  295. return self.segment.val.value
  296. @must_be_open
  297. def put(self, row, col, val):
  298. """Write the value to the map using the `segment.put` method
  299. Parameters
  300. ------------
  301. row: integer
  302. Specify the row number;
  303. col: integer
  304. Specify the column number.
  305. val: value
  306. Specify the value that will be write to the map cell.
  307. """
  308. self.segment.val.value = val
  309. libseg.segment_put(ctypes.byref(self.segment.cseg),
  310. ctypes.byref(self.segment.val), row, col)
  311. def open(self, mode='r', mtype='DCELL', overwrite=False):
  312. """Open the map, if the map already exist: determine the map type
  313. and copy the map to the segment files;
  314. else, open a new segment map.
  315. Parameters
  316. ------------
  317. mode: string, optional
  318. Specify if the map will be open with read, write or read/write
  319. mode ('r', 'w', 'rw')
  320. mtype: string, optional
  321. Specify the map type, valid only for new maps: CELL, FCELL, DCELL;
  322. overwrite: Boolean, optional
  323. Use this flag to set the overwrite mode of existing raster maps
  324. """
  325. # read rows and cols from the active region
  326. self._rows = libraster.Rast_window_rows()
  327. self._cols = libraster.Rast_window_cols()
  328. self.overwrite = overwrite
  329. self.mode = mode
  330. self.mtype = mtype
  331. if self.exist():
  332. if ((self.mode == "w" or self.mode == "rw") and
  333. self.overwrite is False):
  334. str_err = _("Raster map <{0}> already exists. Use overwrite.")
  335. fatal(str_err.format(self))
  336. # We copy the raster map content into the segments
  337. if self.mode == "rw" or self.mode == "r":
  338. self._fd = libraster.Rast_open_old(self.name, self.mapset)
  339. self._gtype = libraster.Rast_get_map_type(self._fd)
  340. self.mtype = RTYPE_STR[self._gtype]
  341. # initialize the segment, I need to determine the mtype of the
  342. # map
  343. # before to open the segment
  344. self.segment.open(self)
  345. self.map2segment()
  346. self.segment.flush()
  347. if self.mode == "rw":
  348. warning(_(WARN_OVERWRITE.format(self)))
  349. # Close the file descriptor and open it as new again
  350. libraster.Rast_close(self._fd)
  351. self._fd = libraster.Rast_open_new(
  352. self.name, self._gtype)
  353. # Here we simply overwrite the existing map without content copying
  354. elif self.mode == "w":
  355. #warning(_(WARN_OVERWRITE.format(self)))
  356. self._gtype = RTYPE[self.mtype]['grass type']
  357. self.segment.open(self)
  358. self._fd = libraster.Rast_open_new(self.name, self._gtype)
  359. else:
  360. if self.mode == "r":
  361. str_err = _("Raster map <{0}> does not exists")
  362. raise OpenError(str_err.format(self.name))
  363. self._gtype = RTYPE[self.mtype]['grass type']
  364. self.segment.open(self)
  365. self._fd = libraster.Rast_open_new(self.name, self._gtype)
  366. @must_be_open
  367. def close(self, rm_temp_files=True):
  368. """Close the map, copy the segment files to the map.
  369. Parameters
  370. ------------
  371. rm_temp_files: bool
  372. If True all the segments file will be removed.
  373. """
  374. if self.mode == "w" or self.mode == "rw":
  375. self.segment.flush()
  376. self.segment2map()
  377. if rm_temp_files:
  378. self.segment.close()
  379. else:
  380. self.segment.release()
  381. libraster.Rast_close(self._fd)
  382. # update rows and cols attributes
  383. self._rows = None
  384. self._cols = None
  385. self._fd = None
  386. FLAGS = {1: {'b': 'i', 'i': 'i', 'u': 'i'},
  387. 2: {'b': 'i', 'i': 'i', 'u': 'i'},
  388. 4: {'f': 'f', 'i': 'i', 'b': 'i', 'u': 'i'},
  389. 8: {'f': 'd'}, }
  390. class RasterNumpy(np.memmap, RasterAbstractBase):
  391. """Raster_cached_narray": Inherits "Raster_abstract_base" and
  392. "numpy.memmap". Its purpose is to allow numpy narray like access to
  393. raster maps without loading the map into the main memory.
  394. * Behaves like a numpy array and supports all kind of mathematical
  395. operations: __add__, ...
  396. * Overrides the open and close methods
  397. * Be aware of the 2Gig file size limit
  398. >>> import pygrass
  399. >>> elev = pygrass.raster.RasterNumpy('elevation')
  400. >>> elev.open()
  401. >>> elev[:5, :3]
  402. RasterNumpy([[ 141.99613953, 141.27848816, 141.37904358],
  403. [ 142.90461731, 142.39450073, 142.68611145],
  404. [ 143.81854248, 143.54707336, 143.83972168],
  405. [ 144.56524658, 144.58493042, 144.86477661],
  406. [ 144.99488831, 145.22894287, 145.57142639]], dtype=float32)
  407. >>> el = elev < 144
  408. >>> el[:5, :3]
  409. RasterNumpy([[ True, True, True],
  410. [ True, True, True],
  411. [ True, True, True],
  412. [False, False, False],
  413. [False, False, False]], dtype=bool)
  414. >>> el._write()
  415. 0
  416. """
  417. def __new__(cls, name, mapset="", mtype='CELL', mode='r+',
  418. overwrite=False):
  419. reg = Region()
  420. shape = (reg.rows, reg.cols)
  421. mapset = libgis.G_find_raster(name, mapset)
  422. gtype = None
  423. if mapset:
  424. # map exist, set the map type
  425. gtype = libraster.Rast_map_type(name, mapset)
  426. mtype = RTYPE_STR[gtype]
  427. filename = grasscore.tempfile()
  428. obj = np.memmap.__new__(cls, filename=filename,
  429. dtype=RTYPE[mtype]['numpy'],
  430. mode=mode,
  431. shape=shape)
  432. obj.mtype = mtype.upper()
  433. obj.gtype = gtype if gtype else RTYPE[mtype]['grass type']
  434. obj._rows = reg.rows
  435. obj._cols = reg.cols
  436. obj.filename = filename
  437. obj._name = name
  438. obj.mapset = mapset
  439. obj.reg = reg
  440. obj.overwrite = overwrite
  441. return obj
  442. def __array_finalize__(self, obj):
  443. if hasattr(obj, '_mmap'):
  444. self._mmap = obj._mmap
  445. self.filename = grasscore.tempfile()
  446. self.offset = obj.offset
  447. self.mode = obj.mode
  448. self._rows = obj._rows
  449. self._cols = obj._cols
  450. self._name = None
  451. self.mapset = ''
  452. self.reg = obj.reg
  453. self.overwrite = obj.overwrite
  454. self.mtype = obj.mtype
  455. self._fd = obj._fd
  456. else:
  457. self._mmap = None
  458. def _get_mode(self):
  459. return self._mode
  460. def _set_mode(self, mode):
  461. if mode.lower() not in ('r', 'w+', 'r+', 'c'):
  462. raise ValueError(_("Mode type: {0} not supported.").format(mode))
  463. self._mode = mode
  464. mode = property(fget=_get_mode, fset=_set_mode)
  465. def __array_wrap__(self, out_arr, context=None):
  466. """See:
  467. http://docs.scipy.org/doc/numpy/user/
  468. basics.subclassing.html#array-wrap-for-ufuncs"""
  469. if out_arr.dtype.kind in 'bui':
  470. # there is not support for boolean maps, so convert into integer
  471. out_arr = out_arr.astype(np.int32)
  472. out_arr.mtype = 'CELL'
  473. #out_arr.p = out_arr.ctypes.data_as(out_arr.pointer_type)
  474. return np.ndarray.__array_wrap__(self, out_arr, context)
  475. def __init__(self, name, *args, **kargs):
  476. ## Private attribute `_fd` that return the file descriptor of the map
  477. #self._fd = None
  478. rows, cols = self.rows, self.cols
  479. RasterAbstractBase.__init__(self, name)
  480. self._rows, self._cols = rows, cols
  481. def __unicode__(self):
  482. return RasterAbstractBase.__unicode__(self)
  483. def __str__(self):
  484. return self.__unicode__()
  485. def _get_flags(self, size, kind):
  486. if size in FLAGS:
  487. if kind in FLAGS[size]:
  488. return size, FLAGS[size][kind]
  489. else:
  490. raise ValueError(_('Invalid type {0}'.forma(kind)))
  491. else:
  492. raise ValueError(_('Invalid size {0}'.format(size)))
  493. def _read(self):
  494. """!Read raster map into array
  495. @return 0 on success
  496. @return non-zero code on failure
  497. """
  498. self.null = None
  499. size, kind = self._get_flags(self.dtype.itemsize, self.dtype.kind)
  500. kind = 'f' if kind == 'd' else kind
  501. ret = grasscore.run_command('r.out.bin', flags=kind,
  502. input=self._name, output=self.filename,
  503. bytes=size, null=self.null,
  504. quiet=True)
  505. return ret
  506. def _write(self):
  507. """
  508. r.in.bin input=/home/pietro/docdat/phd/thesis/gis/north_carolina/user1/.tmp/eraclito/14325.0 output=new title='' bytes=1,anull='' --verbose --overwrite north=228500.0 south=215000.0 east=645000.0 west=630000.0 rows=1350 cols=1500
  509. """
  510. self.tofile(self.filename)
  511. size, kind = self._get_flags(self.dtype.itemsize, self.dtype.kind)
  512. #print size, kind
  513. if kind == 'i':
  514. kind = None
  515. size = 4
  516. size = None if kind == 'f' else size
  517. # To be set in the future
  518. self.title = None
  519. self.null = None
  520. #import pdb; pdb.set_trace()
  521. if self.mode in ('w+', 'r+'):
  522. if not self._name:
  523. import os
  524. self._name = "doctest_%i" % os.getpid()
  525. ret = grasscore.run_command('r.in.bin', flags=kind,
  526. input=self.filename, output=self._name,
  527. title=self.title, bytes=size,
  528. anull=self.null,
  529. overwrite=self.overwrite,
  530. verbose=True,
  531. north=self.reg.north,
  532. south=self.reg.south,
  533. east=self.reg.east,
  534. west=self.reg.west,
  535. rows=self.reg.rows,
  536. cols=self.reg.cols)
  537. return ret
  538. def open(self, mtype='', null=None, overwrite=None):
  539. """Open the map, if the map already exist: determine the map type
  540. and copy the map to the segment files;
  541. else, open a new segment map.
  542. Parameters
  543. ------------
  544. mtype: string, optional
  545. Specify the map type, valid only for new maps: CELL, FCELL, DCELL;
  546. """
  547. if overwrite is not None:
  548. self.overwrite = overwrite
  549. self.null = null
  550. # rows and cols already set in __new__
  551. if self.exist():
  552. self._read()
  553. else:
  554. if mtype:
  555. self.mtype = mtype
  556. self._gtype = RTYPE[self.mtype]['grass type']
  557. # set _fd, because this attribute is used to check
  558. # if the map is open or not
  559. self._fd = 1
  560. def close(self):
  561. self._write()
  562. np.memmap._close(self)
  563. grasscore.try_remove(self.filename)
  564. self._fd = None
  565. def random_map_only_columns(mapname, mtype, overwrite=True, factor=100):
  566. region = Region()
  567. random_map = RasterRow(mapname)
  568. row_buf = Buffer((region.cols, ), mtype,
  569. buffer=(np.random.random(region.cols,) * factor).data)
  570. random_map.open('w', mtype, overwrite)
  571. for _ in xrange(region.rows):
  572. random_map.put_row(row_buf)
  573. random_map.close()
  574. return random_map
  575. def random_map(mapname, mtype, overwrite=True, factor=100):
  576. region = Region()
  577. random_map = RasterRow(mapname)
  578. random_map.open('w', mtype, overwrite)
  579. for _ in xrange(region.rows):
  580. row_buf = Buffer((region.cols, ), mtype,
  581. buffer=(np.random.random(region.cols,) * factor).data)
  582. random_map.put_row(row_buf)
  583. random_map.close()
  584. return random_map
  585. if __name__ == "__main__":
  586. import doctest
  587. doctest.testmod()