segment.py 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. """
  2. Created on Mon Jun 11 18:02:27 2012
  3. @author: pietro
  4. """
  5. import ctypes
  6. import grass.lib.gis as libgis
  7. import grass.lib.raster as libraster
  8. import grass.lib.segment as libseg
  9. from grass.pygrass.raster.raster_type import TYPE as RTYPE
  10. class Segment(object):
  11. def __init__(self, srows=64, scols=64, maxmem=100):
  12. self.srows = srows
  13. self.scols = scols
  14. self.maxmem = maxmem
  15. self.c_seg = ctypes.pointer(libseg.SEGMENT())
  16. def rows(self):
  17. return libraster.Rast_window_rows()
  18. def cols(self):
  19. return libraster.Rast_window_cols()
  20. def nseg(self):
  21. rows = self.rows()
  22. cols = self.cols()
  23. return int(
  24. ((rows + self.srows - 1) / self.srows)
  25. * ((cols + self.scols - 1) / self.scols)
  26. )
  27. def segments_in_mem(self):
  28. if self.maxmem > 0 and self.maxmem < 100:
  29. seg_in_mem = (self.maxmem * self.nseg()) / 100
  30. else:
  31. seg_in_mem = 4 * (self.rows() / self.srows + self.cols() / self.scols + 2)
  32. if seg_in_mem == 0:
  33. seg_in_mem = 1
  34. return seg_in_mem
  35. def open(self, mapobj):
  36. """Open a segment it is necessary to pass a RasterSegment object."""
  37. self.val = RTYPE[mapobj.mtype]["grass def"]()
  38. size = ctypes.sizeof(RTYPE[mapobj.mtype]["ctypes"])
  39. file_name = libgis.G_tempfile()
  40. libseg.Segment_open(
  41. self.c_seg,
  42. file_name,
  43. self.rows(),
  44. self.cols(),
  45. self.srows,
  46. self.scols,
  47. size,
  48. self.nseg(),
  49. )
  50. self.flush()
  51. def format(self, mapobj, file_name="", fill=True):
  52. """The segmentation routines require a disk file to be used for paging
  53. segments in and out of memory. This routine formats the file open for
  54. write on file descriptor fd for use as a segment file.
  55. """
  56. if file_name == "":
  57. file_name = libgis.G_tempfile()
  58. mapobj.temp_file = open(file_name, "w")
  59. size = ctypes.sizeof(RTYPE[mapobj.mtype]["ctypes"])
  60. if fill:
  61. libseg.Segment_format(
  62. mapobj.temp_file.fileno(),
  63. self.rows(),
  64. self.cols(),
  65. self.srows,
  66. self.scols,
  67. size,
  68. )
  69. else:
  70. libseg.Segment_format_nofill(
  71. mapobj.temp_file.fileno(),
  72. self.rows(),
  73. self.cols(),
  74. self.srows,
  75. self.scols,
  76. size,
  77. )
  78. # TODO: why should I close and then re-open it?
  79. mapobj.temp_file.close()
  80. def init(self, mapobj, file_name=""):
  81. if file_name == "":
  82. file_name = mapobj.temp_file.name
  83. mapobj.temp_file = open(file_name, "w")
  84. libseg.Segment_init(self.c_seg, mapobj.temp_file.fileno(), self.segments_in_mem)
  85. def get_row(self, row_index, buf):
  86. """Return the row using, the `segment` method"""
  87. libseg.Segment_get_row(self.c_seg, buf.p, row_index)
  88. return buf
  89. def put_row(self, row_index, buf):
  90. """Write the row using the `segment` method"""
  91. libseg.Segment_put_row(self.c_seg, buf.p, row_index)
  92. def get(self, row_index, col_index):
  93. """Return the value of the map"""
  94. libseg.Segment_get(self.c_seg, ctypes.byref(self.val), row_index, col_index)
  95. return self.val.value
  96. def put(self, row_index, col_index):
  97. """Write the value to the map"""
  98. libseg.Segment_put(self.c_seg, ctypes.byref(self.val), row_index, col_index)
  99. def get_seg_number(self, row_index, col_index):
  100. """Return the segment number"""
  101. return row_index / self.srows * self.cols / self.scols + col_index / self.scols
  102. def flush(self):
  103. """Flush pending updates to disk.
  104. Forces all pending updates generated by Segment_put() to be written to
  105. the segment file seg. Must be called after the final Segment_put()
  106. to force all pending updates to disk. Must also be called before the
  107. first call to Segment_get_row."""
  108. libseg.Segment_flush(self.c_seg)
  109. def close(self):
  110. """Free memory allocated to segment and delete temp file."""
  111. libseg.Segment_close(self.c_seg)
  112. def release(self):
  113. """Free memory allocated to segment.
  114. Releases the allocated memory associated with the segment file seg.
  115. Note: Does not close the file. Does not flush the data which may be
  116. pending from previous Segment_put() calls."""
  117. libseg.Segment_release(self.c_seg)