temporal_extent.py 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623
  1. """!@package grass.temporal
  2. @brief GRASS Python scripting module (temporal GIS functions)
  3. Temporal GIS related temporal extent functions to be used in Python scripts and tgis packages.
  4. Usage:
  5. @code
  6. import grass.temporal as tgis
  7. tgis.raster_temporal_extent()
  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. from base import *
  17. ###############################################################################
  18. class abstract_temporal_extent(sql_database_interface):
  19. """!This is the abstract time base class for relative and absolute time objects"""
  20. def __init__(self, table=None, ident=None, start_time=None, end_time=None):
  21. sql_database_interface.__init__(self, table, ident)
  22. self.set_id(ident)
  23. self.set_start_time(start_time)
  24. self.set_end_time(end_time)
  25. def starts(self, extent):
  26. """!Return True if this time object starts at the start of the provided time object and finishes within it
  27. A |-----|
  28. B |---------|
  29. """
  30. if self.D["end_time"] == None or extent.D["end_time"] == None :
  31. return False
  32. if self.D["start_time"] == extent.D["start_time"] and self.D["end_time"] < extent.D["end_time"]:
  33. return True
  34. else:
  35. return False
  36. def started(self, extent):
  37. """!Return True if this time object is started at the start of the provided time object
  38. A |---------|
  39. B |-----|
  40. """
  41. if self.D["end_time"] == None or extent.D["end_time"] == None :
  42. return False
  43. if self.D["start_time"] == extent.D["start_time"] and self.D["end_time"] > extent.D["end_time"]:
  44. return True
  45. else:
  46. return False
  47. def finishes(self, extent):
  48. """!Return True if this time object finishes at the end and within of the provided time object
  49. A |-----|
  50. B |---------|
  51. """
  52. if self.D["end_time"] == None or extent.D["end_time"] == None :
  53. return False
  54. if self.D["end_time"] == extent.D["end_time"] and self.D["start_time"] > extent.D["start_time"] :
  55. return True
  56. else:
  57. return False
  58. def finished(self, extent):
  59. """!Return True if this time object finished at the end of the provided time object
  60. A |---------|
  61. B |-----|
  62. """
  63. if self.D["end_time"] == None or extent.D["end_time"] == None :
  64. return False
  65. if self.D["end_time"] == extent.D["end_time"] and self.D["start_time"] < extent.D["start_time"] :
  66. return True
  67. else:
  68. return False
  69. def after(self, extent):
  70. """!Return True if this time object is temporal located after the provided time object
  71. A |---------|
  72. B |---------|
  73. """
  74. if extent.D["end_time"] == None:
  75. if self.D["start_time"] > extent.D["start_time"]:
  76. return True
  77. else:
  78. return False
  79. if self.D["start_time"] > extent.D["end_time"]:
  80. return True
  81. else:
  82. return False
  83. def before(self, extent):
  84. """!Return True if this time object is temporal located before the provided time object
  85. A |---------|
  86. B |---------|
  87. """
  88. if self.D["end_time"] == None:
  89. if self.D["start_time"] < extent.D["start_time"]:
  90. return True
  91. else:
  92. return False
  93. if self.D["end_time"] < extent.D["start_time"]:
  94. return True
  95. else:
  96. return False
  97. def adjacent(self, extent):
  98. """!Return True if this time object is a meeting neighbour the provided time object
  99. A |---------|
  100. B |---------|
  101. A |---------|
  102. B |---------|
  103. """
  104. if self.D["end_time"] == None and extent.D["end_time"] == None :
  105. return False
  106. if (self.D["start_time"] == extent.D["end_time"]) or (self.D["end_time"] == extent.D["start_time"]):
  107. return True
  108. else:
  109. return False
  110. def follows(self, extent):
  111. """!Return True if this time object is temporal follows the provided time object
  112. A |---------|
  113. B |---------|
  114. """
  115. if extent.D["end_time"] == None :
  116. return False
  117. if self.D["start_time"] == extent.D["end_time"]:
  118. return True
  119. else:
  120. return False
  121. def precedes(self, extent):
  122. """!Return True if this time object is temporal precedes the provided time object
  123. A |---------|
  124. B |---------|
  125. """
  126. if self.D["end_time"] == None:
  127. return False
  128. if self.D["end_time"] == extent.D["start_time"]:
  129. return True
  130. else:
  131. return False
  132. def during(self, extent):
  133. """!Return True if this time object is temporal located during the provided time object
  134. A |-------|
  135. B |---------|
  136. """
  137. # Check single point of time in interval
  138. if extent.D["end_time"] == None:
  139. return False
  140. # Check single point of time in interval
  141. if self.D["end_time"] == None:
  142. if self.D["start_time"] > extent.D["start_time"] and self.D["start_time"] < extent.D["end_time"]:
  143. return True
  144. else:
  145. return False
  146. if self.D["start_time"] > extent.D["start_time"] and self.D["end_time"] < extent.D["end_time"]:
  147. return True
  148. else:
  149. return False
  150. def contains(self, extent):
  151. """!Return True if this time object contains the provided time object
  152. A |---------|
  153. B |-------|
  154. """
  155. # Check single point of time in interval
  156. if self.D["end_time"] == None:
  157. return False
  158. # Check single point of time in interval
  159. if extent.D["end_time"] == None:
  160. if self.D["start_time"] < extent.D["start_time"] and self.D["end_time"] > extent.D["start_time"]:
  161. return True
  162. else:
  163. return False
  164. if self.D["start_time"] < extent.D["start_time"] and self.D["end_time"] > extent.D["end_time"]:
  165. return True
  166. else:
  167. return False
  168. def equivalent(self, extent):
  169. """!Return True if this time object is temporal located equivalent the provided time object
  170. A |---------|
  171. B |---------|
  172. """
  173. if self.D["end_time"] == None and extent.D["end_time"] == None :
  174. if self.D["start_time"] == extent.D["start_time"]:
  175. return True
  176. else:
  177. return False
  178. if self.D["end_time"] == None or extent.D["end_time"] == None :
  179. return False
  180. if self.D["start_time"] == extent.D["start_time"] and self.D["end_time"] == extent.D["end_time"]:
  181. return True
  182. else:
  183. return False
  184. def overlaps(self, extent):
  185. """!Return True if this time object is temporal overlaps the provided time object
  186. A |---------|
  187. B |---------|
  188. """
  189. if self.D["end_time"] == None or extent.D["end_time"] == None :
  190. return False
  191. if self.D["start_time"] < extent.D["start_time"] and self.D["end_time"] < extent.D["end_time"] and\
  192. self.D["end_time"] > extent.D["start_time"]:
  193. return True
  194. else:
  195. return False
  196. def overlapped(self, extent):
  197. """!Return True if this time object is temporal overlapped by the provided time object
  198. A |---------|
  199. B |---------|
  200. """
  201. if self.D["end_time"] == None or extent.D["end_time"] == None :
  202. return False
  203. if self.D["start_time"] > extent.D["start_time"] and self.D["end_time"] > extent.D["end_time"] and\
  204. self.D["start_time"] < extent.D["end_time"]:
  205. return True
  206. else:
  207. return False
  208. def temporal_relation(self, extent):
  209. """!Returns the temporal relation between temporal objects
  210. Temporal relationships are implemented after [Allen and Ferguson 1994 Actions and Events in Interval Temporal Logic]
  211. """
  212. # First check for correct time
  213. if not self.D.has_key("start_time"):
  214. return None
  215. if not self.D.has_key("end_time"):
  216. return None
  217. if not extent.D.has_key("start_time"):
  218. return None
  219. if not extent.D.has_key("end_time"):
  220. return None
  221. if self.D["start_time"] == None or extent.D["start_time"] == None:
  222. return None
  223. if self.equivalent(extent):
  224. return "equivalent"
  225. if self.during(extent):
  226. return "during"
  227. if self.contains(extent):
  228. return "contains"
  229. if self.overlaps(extent):
  230. return "overlaps"
  231. if self.overlapped(extent):
  232. return "overlapped"
  233. if self.after(extent):
  234. return "after"
  235. if self.before(extent):
  236. return "before"
  237. if self.starts(extent):
  238. return "starts"
  239. if self.finishes(extent):
  240. return "finishes"
  241. if self.started(extent):
  242. return "started"
  243. if self.finished(extent):
  244. return "finished"
  245. if self.follows(extent):
  246. return "follows"
  247. if self.precedes(extent):
  248. return "precedes"
  249. return None
  250. def set_id(self, ident):
  251. """!Convenient method to set the unique identifier (primary key)"""
  252. self.ident = ident
  253. self.D["id"] = ident
  254. def set_start_time(self, start_time):
  255. """!Set the valid start time of the extent"""
  256. self.D["start_time"] = start_time
  257. def set_end_time(self, end_time):
  258. """!Set the valid end time of the extent"""
  259. self.D["end_time"] = end_time
  260. def get_id(self):
  261. """!Convenient method to get the unique identifier (primary key)
  262. @return None if not found
  263. """
  264. if self.D.has_key("id"):
  265. return self.D["id"]
  266. else:
  267. return None
  268. def get_start_time(self):
  269. """!Get the valid start time of the extent
  270. @return None if not found"""
  271. if self.D.has_key("start_time"):
  272. return self.D["start_time"]
  273. else:
  274. return None
  275. def get_end_time(self):
  276. """!Get the valid end time of the extent
  277. @return None if not found"""
  278. if self.D.has_key("end_time"):
  279. return self.D["end_time"]
  280. else:
  281. return None
  282. def print_info(self):
  283. """!Print information about this class in human readable style"""
  284. # 0123456789012345678901234567890
  285. print " | Start time:................. " + str(self.get_start_time())
  286. print " | End time:................... " + str(self.get_end_time())
  287. def print_shell_info(self):
  288. """!Print information about this class in shell style"""
  289. print "start_time=" + str(self.get_start_time())
  290. print "end_time=" + str(self.get_end_time())
  291. ###############################################################################
  292. class absolute_temporal_extent(abstract_temporal_extent):
  293. """!This is the absolute time class for all maps and spacetime datasets
  294. start_time and end_time must be of type datetime
  295. """
  296. def __init__(self, table=None, ident=None, start_time=None, end_time=None, timezone=None):
  297. abstract_temporal_extent.__init__(self, table, ident, start_time, end_time)
  298. self.set_timezone(timezone)
  299. def set_timezone(self, timezone):
  300. """!Set the timezone of the map, the timezone is of type string.
  301. Timezones are not supported yet, instead the timezone is set in the datetime string as offset in minutes.
  302. """
  303. self.D["timezone"] = timezone
  304. def get_timezone(self):
  305. """!Get the timezone of the map
  306. Timezones are not supported yet, instead the timezone is set in the datetime string as offset in minutes.
  307. @return None if not found"""
  308. if self.D.has_key("timezone"):
  309. return self.D["timezone"]
  310. else:
  311. return None
  312. def print_info(self):
  313. """!Print information about this class in human readable style"""
  314. # 0123456789012345678901234567890
  315. print " +-------------------- Absolute time -----------------------------------------+"
  316. abstract_temporal_extent.print_info(self)
  317. #print " | Timezone:................... " + str(self.get_timezone())
  318. def print_shell_info(self):
  319. """!Print information about this class in shell style"""
  320. abstract_temporal_extent.print_shell_info(self)
  321. #print "timezone=" + str(self.get_timezone())
  322. ###############################################################################
  323. class raster_absolute_time(absolute_temporal_extent):
  324. def __init__(self, ident=None, start_time=None, end_time=None, timezone=None):
  325. absolute_temporal_extent.__init__(self, "raster_absolute_time", ident, start_time, end_time, timezone)
  326. class raster3d_absolute_time(absolute_temporal_extent):
  327. def __init__(self, ident=None, start_time=None, end_time=None, timezone=None):
  328. absolute_temporal_extent.__init__(self, "raster3d_absolute_time", ident, start_time, end_time, timezone)
  329. class vector_absolute_time(absolute_temporal_extent):
  330. def __init__(self, ident=None, start_time=None, end_time=None, timezone=None):
  331. absolute_temporal_extent.__init__(self, "vector_absolute_time", ident, start_time, end_time, timezone)
  332. ###############################################################################
  333. class stds_absolute_time(absolute_temporal_extent):
  334. def __init__(self, table=None, ident=None, start_time=None, end_time=None, granularity=None, timezone=None, map_time=None):
  335. absolute_temporal_extent.__init__(self, table, ident, start_time, end_time, timezone)
  336. self.set_granularity(granularity)
  337. self.set_map_time(map_time)
  338. def set_granularity(self, granularity):
  339. """!Set the granularity of the space time dataset"""
  340. self.D["granularity"] = granularity
  341. def set_map_time(self, map_time):
  342. """!Set the type of the map time
  343. Registered maps may have different types of time:
  344. Single point of time "point"
  345. Time intervals "interval"
  346. Or single point and interval time "mixed"
  347. This variable will be set automatically when maps are registered.
  348. """
  349. self.D["map_time"] = map_time
  350. def get_granularity(self):
  351. """!Get the granularity of the space time dataset
  352. @return None if not found"""
  353. if self.D.has_key("granularity"):
  354. return self.D["granularity"]
  355. else:
  356. return None
  357. def get_map_time(self):
  358. """!Get the type of the map time
  359. Registered maps may have different types of time:
  360. Single point of time "point"
  361. Time intervals "interval"
  362. Or single point and interval time "mixed"
  363. This variable will be set automatically when maps are registered.
  364. """
  365. if self.D.has_key("map_time"):
  366. return self.D["map_time"]
  367. else:
  368. return None
  369. def print_info(self):
  370. """!Print information about this class in human readable style"""
  371. absolute_temporal_extent.print_info(self)
  372. # 0123456789012345678901234567890
  373. print " | Granularity:................ " + str(self.get_granularity())
  374. print " | Temporal type of maps:...... " + str(self.get_map_time())
  375. def print_shell_info(self):
  376. """!Print information about this class in shell style"""
  377. absolute_temporal_extent.print_shell_info(self)
  378. print "granularity=" + str(self.get_granularity())
  379. print "map_time=" + str(self.get_map_time())
  380. ###############################################################################
  381. class strds_absolute_time(stds_absolute_time):
  382. def __init__(self, ident=None, start_time=None, end_time=None, granularity=None, timezone=None):
  383. stds_absolute_time.__init__(self, "strds_absolute_time", ident, start_time, end_time, granularity, timezone)
  384. class str3ds_absolute_time(stds_absolute_time):
  385. def __init__(self, ident=None, start_time=None, end_time=None, granularity=None, timezone=None):
  386. stds_absolute_time.__init__(self, "str3ds_absolute_time", ident, start_time, end_time, granularity, timezone)
  387. class stvds_absolute_time(stds_absolute_time):
  388. def __init__(self, ident=None, start_time=None, end_time=None, granularity=None, timezone=None):
  389. stds_absolute_time.__init__(self, "stvds_absolute_time", ident, start_time, end_time, granularity, timezone)
  390. ###############################################################################
  391. class relative_temporal_extent(abstract_temporal_extent):
  392. """!This is the relative time class for all maps and spacetime datasets
  393. start_time and end_time must be of type integer
  394. """
  395. def __init__(self, table=None, ident=None, start_time=None, end_time=None, unit=None):
  396. abstract_temporal_extent.__init__(self, table, ident, start_time, end_time)
  397. self.D["unit"] = unit
  398. def set_unit(self, unit):
  399. """!Set the unit of the relative time. Valid units are:
  400. * years
  401. * months
  402. * days
  403. * hours
  404. * minutes
  405. * seconds
  406. """
  407. self.D["unit"] = unit
  408. def get_unit(self):
  409. """!Get the unit of the relative time
  410. @return None if not found"""
  411. if self.D.has_key("unit"):
  412. return self.D["unit"]
  413. else:
  414. return None
  415. def temporal_relation(self, map):
  416. """!Returns the temporal relation between temporal objects
  417. Temporal relationships are implemented after [Allen and Ferguson 1994 Actions and Events in Interval Temporal Logic]
  418. """
  419. # Check units for relative time
  420. if not self.D.has_key("unit"):
  421. return None
  422. if not map.D.has_key("unit"):
  423. return None
  424. # Units must be equal
  425. if self.D["unit"] != map.D["unit"]:
  426. return None
  427. return abstract_temporal_extent.temporal_relation(self, map)
  428. def print_info(self):
  429. """!Print information about this class in human readable style"""
  430. # 0123456789012345678901234567890
  431. print " +-------------------- Relative time -----------------------------------------+"
  432. abstract_temporal_extent.print_info(self)
  433. print " | Relative time unit:......... " + str(self.get_unit())
  434. def print_shell_info(self):
  435. """!Print information about this class in shell style"""
  436. abstract_temporal_extent.print_shell_info(self)
  437. print "unit=" + str(self.get_unit())
  438. ###############################################################################
  439. class raster_relative_time(relative_temporal_extent):
  440. def __init__(self, ident=None, start_time=None, end_time=None):
  441. relative_temporal_extent.__init__(self, "raster_relative_time", ident, start_time, end_time)
  442. class raster3d_relative_time(relative_temporal_extent):
  443. def __init__(self, ident=None, start_time=None, end_time=None):
  444. relative_temporal_extent.__init__(self, "raster3d_relative_time", ident, start_time, end_time)
  445. class vector_relative_time(relative_temporal_extent):
  446. def __init__(self, ident=None, start_time=None, end_time=None):
  447. relative_temporal_extent.__init__(self, "vector_relative_time", ident, start_time, end_time)
  448. ###############################################################################
  449. class stds_relative_time(relative_temporal_extent):
  450. def __init__(self, table=None, ident=None, start_time=None, end_time=None, granularity=None, map_time=None):
  451. relative_temporal_extent.__init__(self, table, ident, start_time, end_time)
  452. self.set_granularity(granularity)
  453. self.set_map_time(map_time)
  454. def set_granularity(self, granularity):
  455. """!Set the granularity of the space time dataset"""
  456. self.D["granularity"] = granularity
  457. def set_map_time(self, map_time):
  458. """!Set the type of the map time
  459. Registered maps may have different types of time:
  460. Single point of time "point"
  461. Time intervals "interval"
  462. Or single point and interval time "mixed"
  463. This variable will be set automatically when maps are registered.
  464. """
  465. self.D["map_time"] = map_time
  466. def get_granularity(self):
  467. """!Get the granularity of the space time dataset
  468. @return None if not found"""
  469. if self.D.has_key("granularity"):
  470. return self.D["granularity"]
  471. else:
  472. return None
  473. def get_map_time(self):
  474. """!Get the type of the map time
  475. Registered maps may have different types of time:
  476. Single point of time "point"
  477. Time intervals "interval"
  478. Or single point and interval time "mixed"
  479. This variable will be set automatically when maps are registered.
  480. """
  481. if self.D.has_key("map_time"):
  482. return self.D["map_time"]
  483. else:
  484. return None
  485. def print_info(self):
  486. """!Print information about this class in human readable style"""
  487. relative_temporal_extent.print_info(self)
  488. # 0123456789012345678901234567890
  489. print " | Granularity:................ " + str(self.get_granularity())
  490. print " | Temporal type of maps:...... " + str(self.get_map_time())
  491. def print_shell_info(self):
  492. """!Print information about this class in shell style"""
  493. relative_temporal_extent.print_shell_info(self)
  494. print "granularity=" + str(self.get_granularity())
  495. print "map_time=" + str(self.get_map_time())
  496. ###############################################################################
  497. class strds_relative_time(stds_relative_time):
  498. def __init__(self, ident=None, start_time=None, end_time=None, granularity=None):
  499. stds_relative_time.__init__(self, "strds_relative_time", ident, start_time, end_time, granularity)
  500. class str3ds_relative_time(stds_relative_time):
  501. def __init__(self, ident=None, start_time=None, end_time=None, granularity=None):
  502. stds_relative_time.__init__(self, "str3ds_relative_time", ident, start_time, end_time, granularity)
  503. class stvds_relative_time(stds_relative_time):
  504. def __init__(self, ident=None, start_time=None, end_time=None, granularity=None):
  505. stds_relative_time.__init__(self, "stvds_relative_time", ident, start_time, end_time, granularity)