segment.py 4.6 KB

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