pygrass_raster.rst 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. .. _raster-label:
  2. Introduction to Raster classes
  3. ==============================
  4. Details about the architecture can be found in the `GRASS GIS 7 Programmer's Manual: GRASS Raster Library <http://grass.osgeo.org/programming7/rasterlib.html>`_
  5. PyGRASS uses 4 different Raster classes, that respect the 4 different approaches
  6. of GRASS-C API. The classes use a standardized interface to keep methods
  7. consistent between them. The read access is row wise for :ref:`RasterRow-label`
  8. and :ref:`RasterRowIO-label` and additionally
  9. cached in the RowIO class. Both classes write sequentially.
  10. RowIO is row cached, :ref:`RasterSegment-label` and :ref:`RasterNumpy-label`
  11. are tile cached for reading and writing; therefore, random access is possible.
  12. Hence RasterRow and RasterRowIO should be used for fast (cached)
  13. row read access and RasterRow for fast sequential writing.
  14. RasterSegment and RasterNumpy should be used for random access.
  15. ========================== ======================= ======== ============
  16. Class Name C library Read Write
  17. ========================== ======================= ======== ============
  18. :ref:`RasterRow-label` `Raster library`_ randomly sequentially
  19. :ref:`RasterRowIO-label` `RowIO library`_ cached no
  20. :ref:`RasterSegment-label` `Segmentation library`_ cached randomly
  21. :ref:`RasterNumpy-label` `numpy.memmap`_ cached randomly
  22. ========================== ======================= ======== ============
  23. These classes share common methods and attributes to address
  24. common tasks as rename, remove, open, close, exist, is_open.
  25. In the following example we instantiate a RasterRow object. ::
  26. >>> from grass.pygrass import raster
  27. >>> elev = raster.RasterRow('elevation')
  28. >>> elev.name
  29. 'elevation'
  30. >>> print(elev)
  31. elevation@PERMANENT
  32. >>> elev.exist()
  33. True
  34. >>> elev.is_open()
  35. False
  36. >>> new = raster.RasterRow('new')
  37. >>> new.exist()
  38. False
  39. >>> new.is_open()
  40. False
  41. We can rename the map: ::
  42. >>> # setting the attribute
  43. >>> new.name = 'new_map'
  44. >>> print(new)
  45. new_map
  46. >>> # or using the rename methods
  47. >>> new.rename('new')
  48. >>> print(new)
  49. new
  50. .. _RasterRow-label:
  51. RasterRow
  52. ---------
  53. The PyGrass :class:`~pygrass.raster.RasterRow` class allow user to open maps row
  54. by row in either read or write mode using the `Raster library`_. Reading and writing
  55. to the same map at the same time is not supported. For this functionality,
  56. please see the :ref:`RasterSegment-label` and :ref:`RasterNumpy-label` classes.
  57. The RasterRow class allows map rows to be read in any order, but map rows can
  58. only be written in sequential order. Therefore, each now row written to a map is
  59. added to the file as the last row. ::
  60. >>> raster = reload(raster)
  61. >>> elev = raster.RasterRow('elevation')
  62. >>> # the cols attribute is set from the current region only when the map is open
  63. >>> elev.cols
  64. >>> elev.open()
  65. >>> elev.is_open()
  66. True
  67. >>> elev.cols
  68. 1500
  69. >>> # we can read the elevation map, row by row
  70. >>> for row in elev[:5]: print(row[:3])
  71. [ 141.99613953 141.27848816 141.37904358]
  72. [ 142.90461731 142.39450073 142.68611145]
  73. [ 143.81854248 143.54707336 143.83972168]
  74. [ 144.56524658 144.58493042 144.86477661]
  75. [ 144.99488831 145.22894287 145.57142639]
  76. >>> # we can open a new map in write mode
  77. >>> new = raster.RasterRow('new')
  78. >>> new.open('w', 'CELL')
  79. >>> # for each elev row we can perform computation, and write the result into
  80. >>> # the new map
  81. >>> for row in elev:
  82. ... new.put_row(row < 144)
  83. ...
  84. >>> # close the maps
  85. >>> new.close()
  86. >>> elev.close()
  87. >>> # check if the map exist
  88. >>> new.exist()
  89. True
  90. >>> # we can open the map in read mode
  91. >>> new.open('r')
  92. >>> for row in new[:5]: print(row[:3])
  93. [1 1 1]
  94. [1 1 1]
  95. [1 1 1]
  96. [0 0 0]
  97. [0 0 0]
  98. >>> new.close()
  99. >>> new.remove()
  100. >>> new.exist()
  101. False
  102. .. _RasterRowIO-label:
  103. RasterRowIO
  104. -----------
  105. The :class:`~pygrass.raster.RasterRowIO` class uses the GRASS `RowIO library`_, and implements a row
  106. cache. The RasterRowIO class only supports reading rasters; because raster rows
  107. can only be written in sequential order, writing by row id is not
  108. supported by design. Hence, the rowio lib can only be used to cache rows
  109. for reading, and any write access should use the :ref:`RasterRow-label` class. ::
  110. >>> raster = reload(raster)
  111. >>> elev = raster.RasterRowIO('elevation')
  112. >>> elev.open('r')
  113. >>> for row in elev[:5]: print(row[:3])
  114. [ 141.99613953 141.27848816 141.37904358]
  115. [ 142.90461731 142.39450073 142.68611145]
  116. [ 143.81854248 143.54707336 143.83972168]
  117. [ 144.56524658 144.58493042 144.86477661]
  118. [ 144.99488831 145.22894287 145.57142639]
  119. >>> elev.close()
  120. .. _RasterSegment-label:
  121. RasterSegment
  122. -------------
  123. The :class:`~pygrass.raster.RasterSegment` class uses the GRASS `Segmentation library`_. The class divides
  124. a raster map into small tiles stored on disk. Initialization of this class is
  125. therefore intensive. However, this class has lower memory requirements, as GRASS
  126. loads only currently-accessed tiles into memory. The segment library allow
  127. opening maps in a read-write mode. ::
  128. >>> raster = reload(raster)
  129. >>> elev = raster.RasterSegment('elevation')
  130. >>> elev.open()
  131. >>> for row in elev[:5]: print(row[:3])
  132. [ 141.99613953 141.27848816 141.37904358]
  133. [ 142.90461731 142.39450073 142.68611145]
  134. [ 143.81854248 143.54707336 143.83972168]
  135. [ 144.56524658 144.58493042 144.86477661]
  136. [ 144.99488831 145.22894287 145.57142639]
  137. >>> new = raster.RasterSegment('new')
  138. >>> new.open('w', 'CELL')
  139. >>> for irow in xrange(elev.rows):
  140. ... new[irow] = elev[irow] < 144
  141. ...
  142. >>> for row in new[:5]: print(row[:3])
  143. [1 1 1]
  144. [1 1 1]
  145. [1 1 1]
  146. [0 0 0]
  147. [0 0 0]
  148. Due to the unique behavior of this class, the RasterSegment class defines two
  149. methods to read a map:
  150. * ``get_row`` calls the C function ``segment_get_row`` and returns a buffer
  151. object with the row. ::
  152. >>> # call explicity the method
  153. >>> elev_row0 = elev.get_row(0)
  154. >>> # call implicity the method
  155. >>> elev_row0 = elev[0]
  156. * ``get`` calls the C function ``segment_get`` and returns the value of the
  157. map cell. ::
  158. >>> # call explicity the method
  159. >>> elev_val_0_0 = elev.get(0, 0)
  160. >>> # call implicity the method
  161. >>> elev_val_0_0 = elev[0, 0]
  162. Similarly, writing to a map uses two methods: ``put_row`` to write a row and
  163. ``put`` to write a single value to the map. ::
  164. >>> # compare the cell value get using the ``get`` method, and take the first
  165. >>> # value of the row with the ``get_row`` method
  166. >>> # the methods are used internally by the index operators
  167. >>> elev[0, 0] == elev[0][0]
  168. True
  169. >>> # write a new value to a cell,
  170. >>> new[0, 0] = 10 # ``put`` is used internally by the index operators
  171. >>> new[0, 0]
  172. 10
  173. >>> new.close()
  174. >>> new.exist()
  175. True
  176. >>> new.remove()
  177. >>> elev.close()
  178. >>> elev.remove()
  179. .. _RasterNumpy-label:
  180. RasterNumpy
  181. -----------
  182. The :class:`~pygrass.raster.RasterNumpy` class, is based on the `numpy.memmap`_ class
  183. (refer to the linked documentation for details). If an existing map is opened,
  184. small sections will be loaded into memory as accessed, but GRASS does not need to
  185. load the whole file into memory. Memmap is a subclass of the `numpy.ndarray`
  186. class, so RasterNumpy will behave like a numpy array and can be used with numpy
  187. array operations. ::
  188. >>> raster = reload(raster)
  189. >>> elev = raster.RasterNumpy('elevation', 'PERMANENT')
  190. >>> elev.open('r')
  191. >>> # in this case RasterNumpy is an extention of the numpy class
  192. >>> # therefore you may use all the fancy things of numpy.
  193. >>> elev[:5, :3]
  194. RasterNumpy([[ 141.99613953, 141.27848816, 141.37904358],
  195. [ 142.90461731, 142.39450073, 142.68611145],
  196. [ 143.81854248, 143.54707336, 143.83972168],
  197. [ 144.56524658, 144.58493042, 144.86477661],
  198. [ 144.99488831, 145.22894287, 145.57142639]], dtype=float32)
  199. >>> el = elev < 144
  200. >>> el[:5, :3]
  201. RasterNumpy([[1, 1, 1],
  202. [1, 1, 1],
  203. [1, 1, 1],
  204. [0, 0, 0],
  205. [0, 0, 0]], dtype=int32)
  206. >>> el.name == None
  207. True
  208. >>> # give a name to the new map
  209. >>> el.name = 'new'
  210. >>> el.exist()
  211. False
  212. >>> el.close()
  213. >>> el.exist()
  214. True
  215. >>> el.remove()
  216. .. _Raster library: http://grass.osgeo.org/programming7/rasterlib.html
  217. .. _RowIO library: http://grass.osgeo.org/programming7/rowiolib.html
  218. .. _Segmentation library: http://grass.osgeo.org/programming7/segmentlib.html
  219. .. _numpy.memmap: http://docs.scipy.org/doc/numpy/reference/generated/numpy.memmap.html