abstract_dataset.py 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415
  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 build_id(name, mapset, layer=None):
  75. """!Build and return the id (primary key) based on name, mapset and layer of a dataset.
  76. @param name: The name of the map
  77. @param mapset: The name of the mapset
  78. @param layer: The name of the layer (optional)
  79. Return None in case the name can not be build (name or mapset are None)
  80. """
  81. if not name or not mapset:
  82. return None
  83. # Make sure to extract the pure mapname
  84. pure_name = name.split("@")[0].split(":")[0]
  85. if layer:
  86. return "%s:%s@%s"%(name, layer, mapset)
  87. else:
  88. return "%s@%s"%(name, mapset)
  89. return None
  90. def get_valid_time(self):
  91. """!Returns a tuple of the start, the end valid time, this can be either datetime or double values
  92. @return A tuple of (start_time, end_time)
  93. """
  94. start = None
  95. end = None
  96. if self.is_time_absolute():
  97. start = self.absolute_time.get_start_time()
  98. end = self.absolute_time.get_end_time()
  99. if self.is_time_relative():
  100. start = self.relative_time.get_start_time()
  101. end = self.relative_time.get_end_time()
  102. return (start, end)
  103. def get_absolute_time(self):
  104. """!Returns a tuple of the start, the end valid time and the timezone of the map
  105. @return A tuple of (start_time, end_time, timezone)
  106. """
  107. start = self.absolute_time.get_start_time()
  108. end = self.absolute_time.get_end_time()
  109. tz = self.absolute_time.get_timezone()
  110. return (start, end, tz)
  111. def get_relative_time(self):
  112. """!Returns the relative time interval (start_time, end_time, unit) or None if not present"""
  113. start = self.relative_time.get_start_time()
  114. end = self.relative_time.get_end_time()
  115. unit = self.relative_time.get_unit()
  116. return (start, end, unit)
  117. def get_relative_time_unit(self):
  118. """!Returns the relative time unit or None if not present"""
  119. unit = self.relative_time.get_unit()
  120. return unit
  121. def check_relative_time_unit(self, unit):
  122. """!Check if unit is of type years, months, days, hours, minutes or seconds
  123. Return True if success or False otherwise
  124. """
  125. # Check unit
  126. units = ["years","months","days","hours","minutes","seconds"]
  127. if unit not in units:
  128. return False
  129. return True
  130. def get_temporal_type(self):
  131. """!Return the temporal type of this dataset"""
  132. return self.base.get_ttype()
  133. def get_spatial_extent(self):
  134. """!Return a tuple of spatial extent (north, south, east, west, top, bottom) """
  135. north = self.spatial_extent.get_north()
  136. south = self.spatial_extent.get_south()
  137. east = self.spatial_extent.get_east()
  138. west = self.spatial_extent.get_west()
  139. top = self.spatial_extent.get_top()
  140. bottom = self.spatial_extent.get_bottom()
  141. return (north, south, east, west, top, bottom)
  142. def select(self, dbif=None):
  143. """!Select temporal dataset entry from database and fill up the internal structure"""
  144. dbif, connect = init_dbif(dbif)
  145. self.base.select(dbif)
  146. if self.is_time_absolute():
  147. self.absolute_time.select(dbif)
  148. if self.is_time_relative():
  149. self.relative_time.select(dbif)
  150. self.spatial_extent.select(dbif)
  151. self.metadata.select(dbif)
  152. if connect:
  153. dbif.close()
  154. def is_in_db(self, dbif=None):
  155. """!Check if the temporal dataset entry is in the database
  156. @param dbif: The database interface to be used
  157. """
  158. return self.base.is_in_db(dbif)
  159. def delete(self):
  160. """!Delete temporal dataset entry from database if it exists"""
  161. raise IOError("This method must be implemented in the subclasses")
  162. def insert(self, dbif=None, execute=True):
  163. """!Insert temporal dataset entry into database from the internal structure
  164. @param dbif: The database interface to be used
  165. @param execute: If True the SQL statements will be executed.
  166. If False the prepared SQL statements are returned and must be executed by the caller.
  167. """
  168. dbif, connect = init_dbif(dbif)
  169. # Build the INSERT SQL statement
  170. statement = self.base.get_insert_statement_mogrified(dbif)
  171. if self.is_time_absolute():
  172. statement += self.absolute_time.get_insert_statement_mogrified(dbif)
  173. if self.is_time_relative():
  174. statement += self.relative_time.get_insert_statement_mogrified(dbif)
  175. statement += self.spatial_extent.get_insert_statement_mogrified(dbif)
  176. statement += self.metadata.get_insert_statement_mogrified(dbif)
  177. if execute == True:
  178. dbif.execute_transaction(statement)
  179. if connect:
  180. dbif.close()
  181. return ""
  182. if connect:
  183. dbif.close()
  184. return statement
  185. def update(self, dbif=None, execute=True):
  186. """!Update temporal dataset entry of database from the internal structure
  187. excluding None variables
  188. @param dbif: The database interface to be used
  189. @param execute: If True the SQL statements will be executed.
  190. If False the prepared SQL statements are returned and must be executed by the caller.
  191. """
  192. dbif, connect = init_dbif(dbif)
  193. # Build the UPDATE SQL statement
  194. statement = self.base.get_update_statement_mogrified(dbif)
  195. if self.is_time_absolute():
  196. statement += self.absolute_time.get_update_statement_mogrified(dbif)
  197. if self.is_time_relative():
  198. statement += self.relative_time.get_update_statement_mogrified(dbif)
  199. statement += self.spatial_extent.get_update_statement_mogrified(dbif)
  200. statement += self.metadata.get_update_statement_mogrified(dbif)
  201. if execute == True:
  202. dbif.execute_transaction(statement)
  203. if connect:
  204. dbif.close()
  205. return ""
  206. if connect:
  207. dbif.close()
  208. return statement
  209. def update_all(self, dbif=None, execute=True):
  210. """!Update temporal dataset entry of database from the internal structure
  211. and include None varuables.
  212. @param dbif: The database interface to be used
  213. @param execute: If True the SQL statements will be executed.
  214. If False the prepared SQL statements are returned and must be executed by the caller.
  215. """
  216. dbif, connect = init_dbif(dbif)
  217. # Build the UPDATE SQL statement
  218. statement = self.base.get_update_all_statement_mogrified(dbif)
  219. if self.is_time_absolute():
  220. statement += self.absolute_time.get_update_all_statement_mogrified(dbif)
  221. if self.is_time_relative():
  222. statement += self.relative_time.get_update_all_statement_mogrified(dbif)
  223. statement += self.spatial_extent.get_update_all_statement_mogrified(dbif)
  224. statement += self.metadata.get_update_all_statement_mogrified(dbif)
  225. if execute == True:
  226. dbif.execute_transaction(statement)
  227. if connect:
  228. dbif.close()
  229. return ""
  230. if connect:
  231. dbif.close()
  232. return statement
  233. def set_time_to_absolute(self):
  234. self.base.set_ttype("absolute")
  235. def set_time_to_relative(self):
  236. self.base.set_ttype("relative")
  237. def is_time_absolute(self):
  238. if self.base.D.has_key("temporal_type"):
  239. return self.base.get_ttype() == "absolute"
  240. else:
  241. return None
  242. def is_time_relative(self):
  243. if self.base.D.has_key("temporal_type"):
  244. return self.base.get_ttype() == "relative"
  245. else:
  246. return None
  247. def temporal_relation(self, map):
  248. """!Return the temporal relation of this and the provided temporal map"""
  249. if self.is_time_absolute() and map.is_time_absolute():
  250. return self.absolute_time.temporal_relation(map.absolute_time)
  251. if self.is_time_relative() and map.is_time_relative():
  252. return self.relative_time.temporal_relation(map.relative_time)
  253. return None
  254. ###############################################################################
  255. class abstract_dataset_comparison_key_start_time(object):
  256. """!This comparison key can be used to sort lists of abstract datasets by start time
  257. Example:
  258. # Return all maps in a space time raster dataset as map objects
  259. map_list = strds.get_registered_maps_as_objects()
  260. # Sort the maps in the list by start time
  261. sorted_map_list = sorted(map_list, key=abstract_dataset_comparison_key_start_time)
  262. """
  263. def __init__(self, obj, *args):
  264. self.obj = obj
  265. def __lt__(self, other):
  266. startA, endA = self.obj.get_valid_time()
  267. startB, endB = other.obj.get_valid_time()
  268. return startA < startB
  269. def __gt__(self, other):
  270. startA, endA = self.obj.get_valid_time()
  271. startB, endB = other.obj.get_valid_time()
  272. return startA > startB
  273. def __eq__(self, other):
  274. startA, endA = self.obj.get_valid_time()
  275. startB, endB = other.obj.get_valid_time()
  276. return startA == startB
  277. def __le__(self, other):
  278. startA, endA = self.obj.get_valid_time()
  279. startB, endB = other.obj.get_valid_time()
  280. return startA <= startB
  281. def __ge__(self, other):
  282. startA, endA = self.obj.get_valid_time()
  283. startB, endB = other.obj.get_valid_time()
  284. return startA >= startB
  285. def __ne__(self, other):
  286. startA, endA = self.obj.get_valid_time()
  287. startB, endB = other.obj.get_valid_time()
  288. return startA != startB
  289. ###############################################################################
  290. class abstract_dataset_comparison_key_end_time(object):
  291. """!This comparison key can be used to sort lists of abstract datasets by end time
  292. Example:
  293. # Return all maps in a space time raster dataset as map objects
  294. map_list = strds.get_registered_maps_as_objects()
  295. # Sort the maps in the list by end time
  296. sorted_map_list = sorted(map_list, key=abstract_dataset_comparison_key_end_time)
  297. """
  298. def __init__(self, obj, *args):
  299. self.obj = obj
  300. def __lt__(self, other):
  301. startA, endA = self.obj.get_valid_time()
  302. startB, endB = other.obj.get_valid_time()
  303. return endA < endB
  304. def __gt__(self, other):
  305. startA, endA = self.obj.get_valid_time()
  306. startB, endB = other.obj.get_valid_time()
  307. return endA > endB
  308. def __eq__(self, other):
  309. startA, endA = self.obj.get_valid_time()
  310. startB, endB = other.obj.get_valid_time()
  311. return endA == endB
  312. def __le__(self, other):
  313. startA, endA = self.obj.get_valid_time()
  314. startB, endB = other.obj.get_valid_time()
  315. return endA <= endB
  316. def __ge__(self, other):
  317. startA, endA = self.obj.get_valid_time()
  318. startB, endB = other.obj.get_valid_time()
  319. return endA >= endB
  320. def __ne__(self, other):
  321. startA, endA = self.obj.get_valid_time()
  322. startB, endB = other.obj.get_valid_time()
  323. return endA != endB