t.rast.to.vect.py 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. ############################################################################
  4. #
  5. # MODULE: t.rast.to.vect
  6. # AUTHOR(S): Soeren Gebbert
  7. #
  8. # PURPOSE: Converts a space time raster dataset into a space time vector dataset.
  9. #
  10. # COPYRIGHT: (C) 2015-2017 by the GRASS Development Team
  11. #
  12. # This program is free software; you can redistribute it and/or modify
  13. # it under the terms of the GNU General Public License as published by
  14. # the Free Software Foundation; either version 2 of the License, or
  15. # (at your option) any later version.
  16. #
  17. # This program is distributed in the hope that it will be useful,
  18. # but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  20. # GNU General Public License for more details.
  21. #
  22. #############################################################################
  23. #%module
  24. #% description: Converts a space time raster dataset into a space time vector dataset
  25. #% keyword: temporal
  26. #% keyword: conversion
  27. #% keyword: raster
  28. #% keyword: vector
  29. #% keyword: time
  30. #%end
  31. #%option G_OPT_STRDS_INPUT
  32. #%end
  33. #%option G_OPT_STVDS_OUTPUT
  34. #%end
  35. #%option G_OPT_T_WHERE
  36. #%end
  37. #%option
  38. #% key: type
  39. #% type: string
  40. #% description: Output feature type
  41. #% required: yes
  42. #% multiple: no
  43. #% options: point,line,area
  44. #%end
  45. #%option
  46. #% key: basename
  47. #% type: string
  48. #% label: Basename of the new generated output maps
  49. #% description: A numerical suffix separated by an underscore will be attached to create a unique identifier
  50. #% required: yes
  51. #% multiple: no
  52. #%end
  53. #%option
  54. #% key: suffix
  55. #% type: string
  56. #% description: Suffix to add at basename: set 'gran' for granularity, 'time' for the full time format, 'num' for numerical suffix with a specific number of digits (default %05)
  57. #% answer: gran
  58. #% required: no
  59. #% multiple: no
  60. #%end
  61. #%option
  62. #% key: column
  63. #% type: string
  64. #% description: Name of attribute column to store value
  65. #% required: no
  66. #% multiple: no
  67. #% answer: value
  68. #%end
  69. #%option
  70. #% key: nprocs
  71. #% type: integer
  72. #% description: Number of r.to.vect processes to run in parallel, more than 1 process works only in conjunction with flag -t
  73. #% required: no
  74. #% multiple: no
  75. #% answer: 1
  76. #%end
  77. #%flag
  78. #% key: n
  79. #% description: Register empty vector maps
  80. #%end
  81. #%flag
  82. #% key: t
  83. #% description: Do not create attribute tables
  84. #%end
  85. #%flag
  86. #% key: s
  87. #% description: Smooth corners of area features
  88. #%end
  89. #%flag
  90. #% key: z
  91. #% label: Write raster values as z coordinate
  92. #% description: Table is not created. Currently supported only for points.
  93. #%end
  94. #%flag
  95. #% key: b
  96. #% label: Do not build vector topology
  97. #% description: Name must be SQL compliant
  98. #%end
  99. #%flag
  100. #% key: v
  101. #% description: Use raster values as categories instead of unique sequence (CELL only)
  102. #%end
  103. import sys
  104. import copy
  105. import grass.script as gscript
  106. ############################################################################
  107. def main(options, flags):
  108. # lazy imports
  109. import grass.temporal as tgis
  110. import grass.pygrass.modules as pymod
  111. # Get the options
  112. input = options["input"]
  113. output = options["output"]
  114. where = options["where"]
  115. base = options["basename"]
  116. method = options["type"]
  117. nprocs = int(options["nprocs"])
  118. column = options["column"]
  119. time_suffix = options["suffix"]
  120. register_null = flags["n"]
  121. t_flag = flags["t"]
  122. s_flag = flags["s"]
  123. v_flag = flags["v"]
  124. b_flag = flags["b"]
  125. z_flag = flags["z"]
  126. # Make sure the temporal database exists
  127. tgis.init()
  128. # We need a database interface
  129. dbif = tgis.SQLDatabaseInterfaceConnection()
  130. dbif.connect()
  131. overwrite = gscript.overwrite()
  132. sp = tgis.open_old_stds(input, "strds", dbif)
  133. maps = sp.get_registered_maps_as_objects(where=where, dbif=dbif)
  134. if not maps:
  135. dbif.close()
  136. gscript.warning(_("Space time raster dataset <%s> is empty") % sp.get_id())
  137. return
  138. # Check the new stvds
  139. new_sp = tgis.check_new_stds(output, "stvds", dbif=dbif,
  140. overwrite=overwrite)
  141. # Setup the flags
  142. flags = ""
  143. if t_flag is True:
  144. flags += "t"
  145. if s_flag is True:
  146. flags += "s"
  147. if v_flag is True:
  148. flags += "v"
  149. if b_flag is True:
  150. flags += "b"
  151. if z_flag is True:
  152. flags += "z"
  153. # Configure the r.to.vect module
  154. to_vector_module = pymod.Module("r.to.vect", input="dummy",
  155. output="dummy", run_=False,
  156. finish_=False, flags=flags,
  157. type=method, overwrite=overwrite,
  158. quiet=True)
  159. # The module queue for parallel execution, except if attribute tables should
  160. # be created. Then force single process use
  161. if t_flag is False:
  162. if nprocs > 1:
  163. nprocs = 1
  164. gscript.warning(_("The number of parellel r.to.vect processes was "\
  165. "reduced to 1 because of the table attribute "\
  166. "creation"))
  167. process_queue = pymod.ParallelModuleQueue(int(nprocs))
  168. count = 0
  169. num_maps = len(maps)
  170. new_maps = []
  171. # run r.to.vect all selected maps
  172. for map in maps:
  173. count += 1
  174. if sp.get_temporal_type() == 'absolute' and time_suffix == 'gran':
  175. suffix = tgis.create_suffix_from_datetime(map.temporal_extent.get_start_time(),
  176. sp.get_granularity())
  177. map_name = "{ba}_{su}".format(ba=base, su=suffix)
  178. elif sp.get_temporal_type() == 'absolute' and time_suffix == 'time':
  179. suffix = tgis.create_time_suffix(map)
  180. map_name = "{ba}_{su}".format(ba=base, su=suffix)
  181. else:
  182. map_name = tgis.create_numeric_suffix(base, count, time_suffix)
  183. new_map = tgis.open_new_map_dataset(map_name, None, type="vector",
  184. temporal_extent=map.get_temporal_extent(),
  185. overwrite=overwrite, dbif=dbif)
  186. new_maps.append(new_map)
  187. mod = copy.deepcopy(to_vector_module)
  188. mod(input=map.get_id(), output=new_map.get_id())
  189. sys.stderr.write(mod.get_bash() + "\n")
  190. process_queue.put(mod)
  191. if count%10 == 0:
  192. gscript.percent(count, num_maps, 1)
  193. # Wait for unfinished processes
  194. process_queue.wait()
  195. # Open the new space time vector dataset
  196. ttype, stype, title, descr = sp.get_initial_values()
  197. new_sp = tgis.open_new_stds(output, "stvds", ttype, title,
  198. descr, stype, dbif, overwrite)
  199. # collect empty maps to remove them
  200. num_maps = len(new_maps)
  201. empty_maps = []
  202. # Register the maps in the database
  203. count = 0
  204. for map in new_maps:
  205. count += 1
  206. if count%10 == 0:
  207. gscript.percent(count, num_maps, 1)
  208. # Do not register empty maps
  209. map.load()
  210. if map.metadata.get_number_of_primitives() == 0:
  211. if not register_null:
  212. empty_maps.append(map)
  213. continue
  214. # Insert map in temporal database
  215. map.insert(dbif)
  216. new_sp.register_map(map, dbif)
  217. # Update the spatio-temporal extent and the metadata table entries
  218. new_sp.update_from_registered_maps(dbif)
  219. gscript.percent(1, 1, 1)
  220. # Remove empty maps
  221. if len(empty_maps) > 0:
  222. names = ""
  223. count = 0
  224. for map in empty_maps:
  225. if count == 0:
  226. count += 1
  227. names += "%s" % (map.get_name())
  228. else:
  229. names += ",%s" % (map.get_name())
  230. gscript.run_command("g.remove", flags='f', type='vector', name=names,
  231. quiet=True)
  232. dbif.close()
  233. ############################################################################
  234. if __name__ == "__main__":
  235. options, flags = gscript.parser()
  236. main(options, flags)