abstract_dataset.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391
  1. # -*- coding: utf-8 -*-
  2. """!@package grass.temporal
  3. @brief GRASS Python scripting module (temporal GIS functions)
  4. Temporal GIS related functions to be used in temporal GIS Python library package.
  5. Usage:
  6. @code
  7. import grass.temporal as tgis
  8. ...
  9. @endcode
  10. (C) 2008-2011 by the GRASS Development Team
  11. This program is free software under the GNU General Public
  12. License (>=v2). Read the file COPYING that comes with GRASS
  13. for details.
  14. @author Soeren Gebbert
  15. """
  16. import uuid
  17. import copy
  18. from temporal_extent import *
  19. from spatial_extent import *
  20. from metadata import *
  21. class abstract_dataset(object):
  22. """!This is the base class for all datasets (raster, vector, raster3d, strds, stvds, str3ds)"""
  23. def reset(self, ident):
  24. """!Reset the internal structure and set the identifier
  25. @param ident: The identifier of the dataset
  26. """
  27. raise IOError("This method must be implemented in the subclasses")
  28. def get_type(self):
  29. """!Return the type of this class"""
  30. raise IOError("This method must be implemented in the subclasses")
  31. def get_new_instance(self, ident):
  32. """!Return a new instance with the type of this class
  33. @param ident: The identifier of the dataset
  34. """
  35. raise IOError("This method must be implemented in the subclasses")
  36. def spatial_overlapping(self, dataset):
  37. """!Return True if the spatial extents are overlapping"""
  38. raise IOError("This method must be implemented in the subclasses")
  39. def spatial_relation(self, dataset):
  40. """Return the spatial relationship between self and dataset"""
  41. raise IOError("This method must be implemented in the subclasses")
  42. def print_info(self):
  43. """!Print information about this class in human readable style"""
  44. raise IOError("This method must be implemented in the subclasses")
  45. def print_shell_info(self):
  46. """!Print information about this class in shell style"""
  47. raise IOError("This method must be implemented in the subclasses")
  48. def print_self(self):
  49. """!Print the content of the internal structure to stdout"""
  50. self.base.print_self()
  51. if self.is_time_absolute():
  52. self.absolute_time.print_self()
  53. if self.is_time_relative():
  54. self.relative_time.print_self()
  55. self.spatial_extent.print_self()
  56. self.metadata.print_self()
  57. def set_id(self, ident):
  58. self.base.set_id(ident)
  59. if self.is_time_absolute():
  60. self.absolute_time.set_id(ident)
  61. if self.is_time_relative():
  62. self.relative_time.set_id(ident)
  63. self.spatial_extent.set_id(ident)
  64. self.metadata.set_id(ident)
  65. def get_id(self):
  66. """!Return the unique identifier of the dataset"""
  67. return self.base.get_id()
  68. def get_name(self):
  69. """!Return the name"""
  70. return self.base.get_name()
  71. def get_mapset(self):
  72. """!Return the mapset"""
  73. return self.base.get_mapset()
  74. def get_valid_time(self):
  75. """!Returns a tuple of the start, the end valid time, this can be either datetime or double values
  76. @return A tuple of (start_time, end_time)
  77. """
  78. start = None
  79. end = None
  80. if self.is_time_absolute():
  81. start = self.absolute_time.get_start_time()
  82. end = self.absolute_time.get_end_time()
  83. if self.is_time_relative():
  84. start = self.relative_time.get_start_time()
  85. end = self.relative_time.get_end_time()
  86. return (start, end)
  87. def get_absolute_time(self):
  88. """!Returns a tuple of the start, the end valid time and the timezone of the map
  89. @return A tuple of (start_time, end_time, timezone)
  90. """
  91. start = self.absolute_time.get_start_time()
  92. end = self.absolute_time.get_end_time()
  93. tz = self.absolute_time.get_timezone()
  94. return (start, end, tz)
  95. def get_relative_time(self):
  96. """!Returns the relative time interval (start_time, end_time, unit) or None if not present"""
  97. start = self.relative_time.get_start_time()
  98. end = self.relative_time.get_end_time()
  99. unit = self.relative_time.get_unit()
  100. return (start, end, unit)
  101. def get_relative_time_unit(self):
  102. """!Returns the relative time unit or None if not present"""
  103. unit = self.relative_time.get_unit()
  104. return unit
  105. def check_relative_time_unit(self, unit):
  106. """!Check if unit is of type years, months, days, hours, minutes or seconds
  107. Return True if success or False otherwise
  108. """
  109. # Check unit
  110. units = ["years","months","days","hours","minutes","seconds"]
  111. if unit not in units:
  112. return False
  113. return True
  114. def get_temporal_type(self):
  115. """!Return the temporal type of this dataset"""
  116. return self.base.get_ttype()
  117. def get_spatial_extent(self):
  118. """!Return a tuple of spatial extent (north, south, east, west, top, bottom) """
  119. north = self.spatial_extent.get_north()
  120. south = self.spatial_extent.get_south()
  121. east = self.spatial_extent.get_east()
  122. west = self.spatial_extent.get_west()
  123. top = self.spatial_extent.get_top()
  124. bottom = self.spatial_extent.get_bottom()
  125. return (north, south, east, west, top, bottom)
  126. def select(self, dbif=None):
  127. """!Select temporal dataset entry from database and fill up the internal structure"""
  128. dbif, connect = init_dbif(dbif)
  129. self.base.select(dbif)
  130. if self.is_time_absolute():
  131. self.absolute_time.select(dbif)
  132. if self.is_time_relative():
  133. self.relative_time.select(dbif)
  134. self.spatial_extent.select(dbif)
  135. self.metadata.select(dbif)
  136. if connect:
  137. dbif.close()
  138. def is_in_db(self, dbif=None):
  139. """!Check if the temporal dataset entry is in the database
  140. @param dbif: The database interface to be used
  141. """
  142. return self.base.is_in_db(dbif)
  143. def delete(self):
  144. """!Delete temporal dataset entry from database if it exists"""
  145. raise IOError("This method must be implemented in the subclasses")
  146. def insert(self, dbif=None, execute=True):
  147. """!Insert temporal dataset entry into database from the internal structure
  148. @param dbif: The database interface to be used
  149. @param execute: If True the SQL statements will be executed.
  150. If False the prepared SQL statements are returned and must be executed by the caller.
  151. """
  152. dbif, connect = init_dbif(dbif)
  153. # Build the INSERT SQL statement
  154. statement = self.base.get_insert_statement_mogrified(dbif)
  155. if self.is_time_absolute():
  156. statement += self.absolute_time.get_insert_statement_mogrified(dbif)
  157. if self.is_time_relative():
  158. statement += self.relative_time.get_insert_statement_mogrified(dbif)
  159. statement += self.spatial_extent.get_insert_statement_mogrified(dbif)
  160. statement += self.metadata.get_insert_statement_mogrified(dbif)
  161. if execute == True:
  162. dbif.execute_transaction(statement)
  163. if connect:
  164. dbif.close()
  165. return ""
  166. if connect:
  167. dbif.close()
  168. return statement
  169. def update(self, dbif=None, execute=True):
  170. """!Update temporal dataset entry of database from the internal structure
  171. excluding None variables
  172. @param dbif: The database interface to be used
  173. @param execute: If True the SQL statements will be executed.
  174. If False the prepared SQL statements are returned and must be executed by the caller.
  175. """
  176. dbif, connect = init_dbif(dbif)
  177. # Build the UPDATE SQL statement
  178. statement = self.base.get_update_statement_mogrified(dbif)
  179. if self.is_time_absolute():
  180. statement += self.absolute_time.get_update_statement_mogrified(dbif)
  181. if self.is_time_relative():
  182. statement += self.relative_time.get_update_statement_mogrified(dbif)
  183. statement += self.spatial_extent.get_update_statement_mogrified(dbif)
  184. statement += self.metadata.get_update_statement_mogrified(dbif)
  185. if execute == True:
  186. dbif.execute_transaction(statement)
  187. if connect:
  188. dbif.close()
  189. return ""
  190. if connect:
  191. dbif.close()
  192. return statement
  193. def update_all(self, dbif=None, execute=True):
  194. """!Update temporal dataset entry of database from the internal structure
  195. and include None varuables.
  196. @param dbif: The database interface to be used
  197. @param execute: If True the SQL statements will be executed.
  198. If False the prepared SQL statements are returned and must be executed by the caller.
  199. """
  200. dbif, connect = init_dbif(dbif)
  201. # Build the UPDATE SQL statement
  202. statement = self.base.get_update_all_statement_mogrified(dbif)
  203. if self.is_time_absolute():
  204. statement += self.absolute_time.get_update_all_statement_mogrified(dbif)
  205. if self.is_time_relative():
  206. statement += self.relative_time.get_update_all_statement_mogrified(dbif)
  207. statement += self.spatial_extent.get_update_all_statement_mogrified(dbif)
  208. statement += self.metadata.get_update_all_statement_mogrified(dbif)
  209. if execute == True:
  210. dbif.execute_transaction(statement)
  211. if connect:
  212. dbif.close()
  213. return ""
  214. if connect:
  215. dbif.close()
  216. return statement
  217. def set_time_to_absolute(self):
  218. self.base.set_ttype("absolute")
  219. def set_time_to_relative(self):
  220. self.base.set_ttype("relative")
  221. def is_time_absolute(self):
  222. if self.base.D.has_key("temporal_type"):
  223. return self.base.get_ttype() == "absolute"
  224. else:
  225. return None
  226. def is_time_relative(self):
  227. if self.base.D.has_key("temporal_type"):
  228. return self.base.get_ttype() == "relative"
  229. else:
  230. return None
  231. def temporal_relation(self, map):
  232. """!Return the temporal relation of this and the provided temporal map"""
  233. if self.is_time_absolute() and map.is_time_absolute():
  234. return self.absolute_time.temporal_relation(map.absolute_time)
  235. if self.is_time_relative() and map.is_time_relative():
  236. return self.relative_time.temporal_relation(map.relative_time)
  237. return None
  238. ###############################################################################
  239. class abstract_dataset_comparison_key_start_time(object):
  240. """!This comparison key can be used to sort lists of abstract datasets by start time
  241. Example:
  242. # Return all maps in a space time raster dataset as map objects
  243. map_list = strds.get_registered_maps_as_objects()
  244. # Sort the maps in the list by start time
  245. sorted_map_list = sorted(map_list, key=abstract_dataset_comparison_key_start_time)
  246. """
  247. def __init__(self, obj, *args):
  248. self.obj = obj
  249. def __lt__(self, other):
  250. startA, endA = self.obj.get_valid_time()
  251. startB, endB = other.obj.get_valid_time()
  252. return startA < startB
  253. def __gt__(self, other):
  254. startA, endA = self.obj.get_valid_time()
  255. startB, endB = other.obj.get_valid_time()
  256. return startA > startB
  257. def __eq__(self, other):
  258. startA, endA = self.obj.get_valid_time()
  259. startB, endB = other.obj.get_valid_time()
  260. return startA == startB
  261. def __le__(self, other):
  262. startA, endA = self.obj.get_valid_time()
  263. startB, endB = other.obj.get_valid_time()
  264. return startA <= startB
  265. def __ge__(self, other):
  266. startA, endA = self.obj.get_valid_time()
  267. startB, endB = other.obj.get_valid_time()
  268. return startA >= startB
  269. def __ne__(self, other):
  270. startA, endA = self.obj.get_valid_time()
  271. startB, endB = other.obj.get_valid_time()
  272. return startA != startB
  273. ###############################################################################
  274. class abstract_dataset_comparison_key_end_time(object):
  275. """!This comparison key can be used to sort lists of abstract datasets by end time
  276. Example:
  277. # Return all maps in a space time raster dataset as map objects
  278. map_list = strds.get_registered_maps_as_objects()
  279. # Sort the maps in the list by end time
  280. sorted_map_list = sorted(map_list, key=abstract_dataset_comparison_key_end_time)
  281. """
  282. def __init__(self, obj, *args):
  283. self.obj = obj
  284. def __lt__(self, other):
  285. startA, endA = self.obj.get_valid_time()
  286. startB, endB = other.obj.get_valid_time()
  287. return endA < endB
  288. def __gt__(self, other):
  289. startA, endA = self.obj.get_valid_time()
  290. startB, endB = other.obj.get_valid_time()
  291. return endA > endB
  292. def __eq__(self, other):
  293. startA, endA = self.obj.get_valid_time()
  294. startB, endB = other.obj.get_valid_time()
  295. return endA == endB
  296. def __le__(self, other):
  297. startA, endA = self.obj.get_valid_time()
  298. startB, endB = other.obj.get_valid_time()
  299. return endA <= endB
  300. def __ge__(self, other):
  301. startA, endA = self.obj.get_valid_time()
  302. startB, endB = other.obj.get_valid_time()
  303. return endA >= endB
  304. def __ne__(self, other):
  305. startA, endA = self.obj.get_valid_time()
  306. startB, endB = other.obj.get_valid_time()
  307. return endA != endB