abstract_temporal_dataset.py 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574
  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. >>> import grass.temporal as tgis
  7. >>> tmr = tgis.AbstractTemporalDataset()
  8. (C) 2008-2011 by the GRASS Development Team
  9. This program is free software under the GNU General Public
  10. License (>=v2). Read the file COPYING that comes with GRASS
  11. for details.
  12. @author Soeren Gebbert
  13. """
  14. from abstract_dataset import *
  15. from datetime_math import *
  16. class AbstractTemporalDataset(AbstractDataset):
  17. """!This class implements a temporal topology access structure for an abstract dataset
  18. This object will be set up by temporal topology creation method provided by the
  19. TemporallyTopologyBuilder.
  20. If correctly initialize the calls next() and prev()
  21. let the user walk temporally forward and backward in time.
  22. The following temporal relations with access methods are supported:
  23. * equal
  24. * follows
  25. * precedes
  26. * overlaps
  27. * overlapped
  28. * during (including starts, finishes)
  29. * contains (including started, finished)
  30. * starts
  31. * started
  32. * finishes
  33. * finished
  34. @code:
  35. # We have build the temporal topology and we know the first map
  36. start = first
  37. while start:
  38. # Print all maps this map temporally contains
  39. dlist = start.get_contains()
  40. for map in dlist:
  41. map.print_info()
  42. start = start.next()
  43. @endcode
  44. Usage:
  45. @code
  46. >>> tmr = AbstractTemporalDataset()
  47. >>> tmr.print_topology_info()
  48. +-------------------- Temporal Topology -------------------------------------+
  49. >>> tmr.print_topology_shell_info()
  50. @endcode
  51. """
  52. def __init__(self):
  53. AbstractDataset.__init__(self)
  54. self.reset_topology()
  55. def reset_topology(self):
  56. """!Reset any information about temporal topology"""
  57. self._topology = {}
  58. self._has_topology = False
  59. def get_number_of_relations(self):
  60. """! Return a dictionary in which the keys are the relation names and the value
  61. are the number of relations.
  62. The following relations are available:
  63. * equal
  64. * follows
  65. * precedes
  66. * overlaps
  67. * overlapped
  68. * during (including starts, finishes)
  69. * contains (including started, finished)
  70. * starts
  71. * started
  72. * finishes
  73. * finished
  74. To access topological information the temporal topology must be build first
  75. using the TemporalTopologyBuilder.
  76. @return the dictionary with relations as keys and number as values or None in case the topology wasn't build
  77. """
  78. if self._has_topology == False:
  79. return None
  80. relations = {}
  81. try:
  82. relations["equal"] = len(self._topology["EQUAL"])
  83. except:
  84. relations["equal"] = 0
  85. try:
  86. relations["follows"] = len(self._topology["FOLLOWS"])
  87. except:
  88. relations["follows"] = 0
  89. try:
  90. relations["precedes"] = len(self._topology["PRECEDES"])
  91. except:
  92. relations["precedes"] = 0
  93. try:
  94. relations["overlaps"] = len(self._topology["OVERLAPS"])
  95. except:
  96. relations["overlaps"] = 0
  97. try:
  98. relations["overlapped"] = len(self._topology["OVERLAPPED"])
  99. except:
  100. relations["overlapped"] = 0
  101. try:
  102. relations["during"] = len(self._topology["DURING"])
  103. except:
  104. relations["during"] = 0
  105. try:
  106. relations["contains"] = len(self._topology["CONTAINS"])
  107. except:
  108. relations["contains"] = 0
  109. try:
  110. relations["starts"] = len(self._topology["STARTS"])
  111. except:
  112. relations["starts"] = 0
  113. try:
  114. relations["started"] = len(self._topology["STARTED"])
  115. except:
  116. relations["started"] = 0
  117. try:
  118. relations["finishes"] = len(self._topology["FINISHES"])
  119. except:
  120. relations["finishes"] = 0
  121. try:
  122. relations["finished"] = len(self._topology["FINISHED"])
  123. except:
  124. relations["finished"] = 0
  125. return relations
  126. def set_topology_build_true(self):
  127. """!Same as name"""
  128. self._has_topology = True
  129. def set_topology_build_false(self):
  130. """!Same as name"""
  131. self._has_topology = False
  132. def is_topology_build(self):
  133. """!Check if the temporal topology was build"""
  134. return self._has_topology
  135. def set_next(self, map_):
  136. """!Set the map that is temporally as closest located after this map.
  137. Temporally located means that the start time of the "next" map is
  138. temporally located AFTER the start time of this map, but temporally
  139. near than other maps of the same dataset.
  140. @param map_: This object should be of type AbstractMapDataset
  141. or derived classes
  142. """
  143. self._topology["NEXT"] = map_
  144. def set_prev(self, map_):
  145. """!Set the map that is temporally as closest located before this map.
  146. Temporally located means that the start time of the "previous" map is
  147. temporally located BEFORE the start time of this map, but temporally
  148. near than other maps of the same dataset.
  149. @param map_: This object should be of type AbstractMapDataset
  150. or derived classes
  151. """
  152. self._topology["PREV"] = map_
  153. def next(self):
  154. """!Return the map with a start time temporally located after
  155. the start time of this map, but temporal closer than other maps
  156. @return A map object or None
  157. """
  158. if "NEXT" not in self._topology:
  159. return None
  160. return self._topology["NEXT"]
  161. def prev(self):
  162. """!Return the map with a start time temporally located before
  163. the start time of this map, but temporal closer than other maps
  164. @return A map object or None
  165. """
  166. if "PREV" not in self._topology:
  167. return None
  168. return self._topology["PREV"]
  169. def append_equivalent(self, map_):
  170. """!Append a map with equivalent temporal extent as this map
  171. @param map_: This object should be of type AbstractMapDataset
  172. or derived classes
  173. """
  174. if "EQUAL" not in self._topology:
  175. self._topology["EQUAL"] = []
  176. self._topology["EQUAL"].append(map_)
  177. def get_equivalent(self):
  178. """!Return a list of map objects with equivalent temporal extent as this map
  179. @return A list of map objects or None
  180. """
  181. if "EQUAL" not in self._topology:
  182. return None
  183. return self._topology["EQUAL"]
  184. def append_starts(self, map_):
  185. """!Append a map that this map temporally starts with
  186. @param map_: This object should be of type AbstractMapDataset
  187. or derived classes
  188. """
  189. if "STARTS" not in self._topology:
  190. self._topology["STARTS"] = []
  191. self._topology["STARTS"].append(map_)
  192. def get_starts(self):
  193. """!Return a list of map objects that this map temporally starts with
  194. @return A list of map objects or None
  195. """
  196. if "STARTS" not in self._topology:
  197. return None
  198. return self._topology["STARTS"]
  199. def append_started(self, map_):
  200. """!Append a map that this map temporally started with
  201. @param map_: This object should be of type AbstractMapDataset
  202. or derived classes
  203. """
  204. if "STARTED" not in self._topology:
  205. self._topology["STARTED"] = []
  206. self._topology["STARTED"].append(map_)
  207. def get_started(self):
  208. """!Return a list of map objects that this map temporally started with
  209. @return A list of map objects or None
  210. """
  211. if "STARTED" not in self._topology:
  212. return None
  213. return self._topology["STARTED"]
  214. def append_finishes(self, map_):
  215. """!Append a map that this map temporally finishes with
  216. @param map_: This object should be of type AbstractMapDataset
  217. or derived classes
  218. """
  219. if "FINISHES" not in self._topology:
  220. self._topology["FINISHES"] = []
  221. self._topology["FINISHES"].append(map_)
  222. def get_finishes(self):
  223. """!Return a list of map objects that this map temporally finishes with
  224. @return A list of map objects or None
  225. """
  226. if "FINISHES" not in self._topology:
  227. return None
  228. return self._topology["FINISHES"]
  229. def append_finished(self, map_):
  230. """!Append a map that this map temporally finished with
  231. @param map_: This object should be of type AbstractMapDataset
  232. or derived classes
  233. """
  234. if "FINISHED" not in self._topology:
  235. self._topology["FINISHED"] = []
  236. self._topology["FINISHED"].append(map_)
  237. def get_finished(self):
  238. """!Return a list of map objects that this map temporally finished with
  239. @return A list of map objects or None
  240. """
  241. if "FINISHED" not in self._topology:
  242. return None
  243. return self._topology["FINISHED"]
  244. def append_overlaps(self, map_):
  245. """!Append a map that this map temporally overlaps
  246. @param map_: This object should be of type AbstractMapDataset
  247. or derived classes
  248. """
  249. if "OVERLAPS" not in self._topology:
  250. self._topology["OVERLAPS"] = []
  251. self._topology["OVERLAPS"].append(map_)
  252. def get_overlaps(self):
  253. """!Return a list of map objects that this map temporally overlaps
  254. @return A list of map objects or None
  255. """
  256. if "OVERLAPS" not in self._topology:
  257. return None
  258. return self._topology["OVERLAPS"]
  259. def append_overlapped(self, map_):
  260. """!Append a map that this map temporally overlapped
  261. @param map_: This object should be of type AbstractMapDataset
  262. or derived classes
  263. """
  264. if "OVERLAPPED" not in self._topology:
  265. self._topology["OVERLAPPED"] = []
  266. self._topology["OVERLAPPED"].append(map_)
  267. def get_overlapped(self):
  268. """!Return a list of map objects that this map temporally overlapped
  269. @return A list of map objects or None
  270. """
  271. if "OVERLAPPED" not in self._topology:
  272. return None
  273. return self._topology["OVERLAPPED"]
  274. def append_follows(self, map_):
  275. """!Append a map that this map temporally follows
  276. @param map_: This object should be of type AbstractMapDataset
  277. or derived classes
  278. """
  279. if "FOLLOWS" not in self._topology:
  280. self._topology["FOLLOWS"] = []
  281. self._topology["FOLLOWS"].append(map_)
  282. def get_follows(self):
  283. """!Return a list of map objects that this map temporally follows
  284. @return A list of map objects or None
  285. """
  286. if "FOLLOWS" not in self._topology:
  287. return None
  288. return self._topology["FOLLOWS"]
  289. def append_precedes(self, map_):
  290. """!Append a map that this map temporally precedes
  291. @param map_: This object should be of type AbstractMapDataset
  292. or derived classes
  293. """
  294. if "PRECEDES" not in self._topology:
  295. self._topology["PRECEDES"] = []
  296. self._topology["PRECEDES"].append(map_)
  297. def get_precedes(self):
  298. """!Return a list of map objects that this map temporally precedes
  299. @return A list of map objects or None
  300. """
  301. if "PRECEDES" not in self._topology:
  302. return None
  303. return self._topology["PRECEDES"]
  304. def append_during(self, map_):
  305. """!Append a map that this map is temporally located during
  306. This includes temporal relationships starts and finishes
  307. @param map_: This object should be of type
  308. AbstractMapDataset or derived classes
  309. """
  310. if "DURING" not in self._topology:
  311. self._topology["DURING"] = []
  312. self._topology["DURING"].append(map_)
  313. def get_during(self):
  314. """!Return a list of map objects that this map is temporally located during
  315. This includes temporally relationships starts and finishes
  316. @return A list of map objects or None
  317. """
  318. if "DURING" not in self._topology:
  319. return None
  320. return self._topology["DURING"]
  321. def append_contains(self, map_):
  322. """!Append a map that this map temporally contains
  323. This includes temporal relationships started and finished
  324. @param map_: This object should be of type AbstractMapDataset
  325. or derived classes
  326. """
  327. if "CONTAINS" not in self._topology:
  328. self._topology["CONTAINS"] = []
  329. self._topology["CONTAINS"].append(map_)
  330. def get_contains(self):
  331. """!Return a list of map objects that this map temporally contains
  332. This includes temporal relationships started and finished
  333. @return A list of map objects or None
  334. """
  335. if "CONTAINS" not in self._topology:
  336. return None
  337. return self._topology["CONTAINS"]
  338. def _generate_map_list_string(self, map_list, line_wrap=True):
  339. count = 0
  340. string = ""
  341. for map_ in map_list:
  342. if line_wrap and count > 0 and count % 3 == 0:
  343. string += "\n | ............................ "
  344. count = 0
  345. if count == 0:
  346. string += map_.get_id()
  347. else:
  348. string += ",%s" % map_.get_id()
  349. count += 1
  350. return string
  351. # Set the properties
  352. equivalent = property(fget=get_equivalent,
  353. fset=append_equivalent)
  354. follows = property(fget=get_follows,
  355. fset=append_follows)
  356. precedes = property(fget=get_precedes,
  357. fset=append_precedes)
  358. overlaps = property(fget=get_overlaps,
  359. fset=append_overlaps)
  360. overlapped = property(fget=get_overlapped,
  361. fset=append_overlapped)
  362. during = property(fget=get_during,
  363. fset=append_during)
  364. contains = property(fget=get_contains,
  365. fset=append_contains)
  366. starts = property(fget=get_starts,
  367. fset=append_starts)
  368. started = property(fget=get_started,
  369. fset=append_started)
  370. finishes = property(fget=get_finishes,
  371. fset=append_finishes)
  372. finished = property(fget=get_finished,
  373. fset=append_finished)
  374. def print_topology_info(self):
  375. """!Print information about this class in human readable style"""
  376. _next = self.next()
  377. _prev = self.prev()
  378. _equal = self.get_equivalent()
  379. _follows = self.get_follows()
  380. _precedes = self.get_precedes()
  381. _overlaps = self.get_overlaps()
  382. _overlapped = self.get_overlapped()
  383. _during = self.get_during()
  384. _contains = self.get_contains()
  385. _starts = self.get_starts()
  386. _started = self.get_started()
  387. _finishes = self.get_finishes()
  388. _finished = self.get_finished()
  389. print " +-------------------- Temporal Topology -------------------------------------+"
  390. # 0123456789012345678901234567890
  391. if _next is not None:
  392. print " | Next: ...................... " + str(_next.get_id())
  393. if _prev is not None:
  394. print " | Previous: .................. " + str(_prev.get_id())
  395. if _equal is not None:
  396. print " | Equivalent: ................ " + \
  397. self._generate_map_list_string(_equal)
  398. if _follows is not None:
  399. print " | Follows: ................... " + \
  400. self._generate_map_list_string(_follows)
  401. if _precedes is not None:
  402. print " | Precedes: .................. " + \
  403. self._generate_map_list_string(_precedes)
  404. if _overlaps is not None:
  405. print " | Overlaps: .................. " + \
  406. self._generate_map_list_string(_overlaps)
  407. if _overlapped is not None:
  408. print " | Overlapped: ................ " + \
  409. self._generate_map_list_string(_overlapped)
  410. if _during is not None:
  411. print " | During: .................... " + \
  412. self._generate_map_list_string(_during)
  413. if _contains is not None:
  414. print " | Contains: .................. " + \
  415. self._generate_map_list_string(_contains)
  416. if _starts is not None:
  417. print " | Starts:.. .................. " + \
  418. self._generate_map_list_string(_starts)
  419. if _started is not None:
  420. print " | Started:. .................. " + \
  421. self._generate_map_list_string(_started)
  422. if _finishes is not None:
  423. print " | Finishes:................... " + \
  424. self._generate_map_list_string(_finishes)
  425. if _finished is not None:
  426. print " | Finished:................... " + \
  427. self._generate_map_list_string(_finished)
  428. def print_topology_shell_info(self):
  429. """!Print information about this class in shell style"""
  430. _next = self.next()
  431. _prev = self.prev()
  432. _equal = self.get_equivalent()
  433. _follows = self.get_follows()
  434. _precedes = self.get_precedes()
  435. _overlaps = self.get_overlaps()
  436. _overlapped = self.get_overlapped()
  437. _during = self.get_during()
  438. _contains = self.get_contains()
  439. _starts = self.get_starts()
  440. _started = self.get_started()
  441. _finishes = self.get_finishes()
  442. _finished = self.get_finished()
  443. if _next is not None:
  444. print "next=" + _next.get_id()
  445. if _prev is not None:
  446. print "prev=" + _prev.get_id()
  447. if _equal is not None:
  448. print "equivalent=" + self._generate_map_list_string(_equal, False)
  449. if _follows is not None:
  450. print "follows=" + self._generate_map_list_string(_follows, False)
  451. if _precedes is not None:
  452. print "precedes=" + self._generate_map_list_string(
  453. _precedes, False)
  454. if _overlaps is not None:
  455. print "overlaps=" + self._generate_map_list_string(
  456. _overlaps, False)
  457. if _overlapped is not None:
  458. print "overlapped=" + \
  459. self._generate_map_list_string(_overlapped, False)
  460. if _during is not None:
  461. print "during=" + self._generate_map_list_string(_during, False)
  462. if _contains is not None:
  463. print "contains=" + self._generate_map_list_string(
  464. _contains, False)
  465. if _starts is not None:
  466. print "starts=" + \
  467. self._generate_map_list_string(_starts)
  468. if _started is not None:
  469. print "started=" + \
  470. self._generate_map_list_string(_started)
  471. if _finishes is not None:
  472. print "finishes=" + \
  473. self._generate_map_list_string(_finishes)
  474. if _finished is not None:
  475. print "finished=" + \
  476. self._generate_map_list_string(_finished)
  477. ###############################################################################
  478. if __name__ == "__main__":
  479. import doctest
  480. doctest.testmod()