temporal_extent.py 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137
  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. >>> from datetime import datetime
  8. >>> tgis.init()
  9. >>> t = tgis.RasterRelativeTime()
  10. >>> t = tgis.RasterAbsoluteTime()
  11. @endcode
  12. (C) 2008-2011 by the GRASS Development Team
  13. This program is free software under the GNU General Public
  14. License (>=v2). Read the file COPYING that comes with GRASS
  15. for details.
  16. @author Soeren Gebbert
  17. """
  18. from base import *
  19. ###############################################################################
  20. class AbstractTemporalExtent(SQLDatabaseInterface):
  21. """!This is the abstract time base class for relative and absolute time objects
  22. It abstract class implements the interface to absolute and relative time.
  23. Absolute time is represented by datetime time stamps,
  24. relative time is represented by a unit an integer value.
  25. This class implements temporal topology relationships computation
  26. after [Allen and Ferguson 1994 Actions and Events in Interval Temporal Logic].
  27. Usage:
  28. @code
  29. >>> init()
  30. >>> A = AbstractTemporalExtent(table="raster_absolute_time",
  31. ... ident="soil@PERMANENT", start_time=datetime(2001, 01, 01),
  32. ... end_time=datetime(2005,01,01) )
  33. >>> A.id
  34. 'soil@PERMANENT'
  35. >>> A.start_time
  36. datetime.datetime(2001, 1, 1, 0, 0)
  37. >>> A.end_time
  38. datetime.datetime(2005, 1, 1, 0, 0)
  39. >>> A.print_info()
  40. | Start time:................. 2001-01-01 00:00:00
  41. | End time:................... 2005-01-01 00:00:00
  42. >>> A.print_shell_info()
  43. start_time=2001-01-01 00:00:00
  44. end_time=2005-01-01 00:00:00
  45. >>> # relative time
  46. >>> A = AbstractTemporalExtent(table="raster_absolute_time",
  47. ... ident="soil@PERMANENT", start_time=0, end_time=1 )
  48. >>> A.id
  49. 'soil@PERMANENT'
  50. >>> A.start_time
  51. 0
  52. >>> A.end_time
  53. 1
  54. >>> A.print_info()
  55. | Start time:................. 0
  56. | End time:................... 1
  57. >>> A.print_shell_info()
  58. start_time=0
  59. end_time=1
  60. @endcode
  61. """
  62. def __init__(self, table=None, ident=None, start_time=None, end_time=None):
  63. SQLDatabaseInterface.__init__(self, table, ident)
  64. self.set_id(ident)
  65. self.set_start_time(start_time)
  66. self.set_end_time(end_time)
  67. def starts(self, extent):
  68. """!Return True if this temporal extent (A) starts at the start of the
  69. provided temporal extent (B) and finishes within it
  70. @verbatim
  71. A |-----|
  72. B |---------|
  73. @endverbatim
  74. @param extent: The temporal extent object with which this extent starts
  75. Usage:
  76. @code
  77. >>> A = AbstractTemporalExtent(start_time=5, end_time=6 )
  78. >>> B = AbstractTemporalExtent(start_time=5, end_time=7 )
  79. >>> A.starts(B)
  80. True
  81. >>> B.starts(A)
  82. False
  83. @endcode
  84. """
  85. if self.D["end_time"] is None or extent.D["end_time"] is None:
  86. return False
  87. if self.D["start_time"] == extent.D["start_time"] and \
  88. self.D["end_time"] < extent.D["end_time"]:
  89. return True
  90. else:
  91. return False
  92. def started(self, extent):
  93. """!Return True if this temporal extent (A) started at the start of the
  94. provided temporal extent (B) and finishes after it
  95. @verbatim
  96. A |---------|
  97. B |-----|
  98. @endverbatim
  99. @param extent: The temporal extent object with which this extent started
  100. Usage:
  101. @code
  102. >>> A = AbstractTemporalExtent(start_time=5, end_time=7 )
  103. >>> B = AbstractTemporalExtent(start_time=5, end_time=6 )
  104. >>> A.started(B)
  105. True
  106. >>> B.started(A)
  107. False
  108. @endcode
  109. """
  110. if self.D["end_time"] is None or extent.D["end_time"] is None:
  111. return False
  112. if self.D["start_time"] == extent.D["start_time"] and \
  113. self.D["end_time"] > extent.D["end_time"]:
  114. return True
  115. else:
  116. return False
  117. def finishes(self, extent):
  118. """!Return True if this temporal extent (A) starts after the start of the
  119. provided temporal extent (B) and finishes with it
  120. @verbatim
  121. A |-----|
  122. B |---------|
  123. @endverbatim
  124. @param extent: The temporal extent object with which this extent finishes
  125. Usage:
  126. @code
  127. >>> A = AbstractTemporalExtent(start_time=6, end_time=7 )
  128. >>> B = AbstractTemporalExtent(start_time=5, end_time=7 )
  129. >>> A.finishes(B)
  130. True
  131. >>> B.finishes(A)
  132. False
  133. @endcode
  134. """
  135. if self.D["end_time"] is None or extent.D["end_time"] is None:
  136. return False
  137. if self.D["end_time"] == extent.D["end_time"] and \
  138. self.D["start_time"] > extent.D["start_time"]:
  139. return True
  140. else:
  141. return False
  142. def finished(self, extent):
  143. """!Return True if this temporal extent (A) starts before the start of the
  144. provided temporal extent (B) and finishes with it
  145. @verbatim
  146. A |---------|
  147. B |-----|
  148. @endverbatim
  149. @param extent: The temporal extent object with which this extent finishes
  150. Usage:
  151. @code
  152. >>> A = AbstractTemporalExtent(start_time=5, end_time=7 )
  153. >>> B = AbstractTemporalExtent(start_time=6, end_time=7 )
  154. >>> A.finished(B)
  155. True
  156. >>> B.finished(A)
  157. False
  158. @endcode
  159. """
  160. if self.D["end_time"] is None or extent.D["end_time"] is None:
  161. return False
  162. if self.D["end_time"] == extent.D["end_time"] and \
  163. self.D["start_time"] < extent.D["start_time"]:
  164. return True
  165. else:
  166. return False
  167. def after(self, extent):
  168. """!Return True if this temporal extent (A) is located after the
  169. provided temporal extent (B)
  170. @verbatim
  171. A |---------|
  172. B |---------|
  173. @endverbatim
  174. @param extent: The temporal extent object that is located before this extent
  175. Usage:
  176. @code
  177. >>> A = AbstractTemporalExtent(start_time=8, end_time=9 )
  178. >>> B = AbstractTemporalExtent(start_time=6, end_time=7 )
  179. >>> A.after(B)
  180. True
  181. >>> B.after(A)
  182. False
  183. @endcode
  184. """
  185. if extent.D["end_time"] is None:
  186. if self.D["start_time"] > extent.D["start_time"]:
  187. return True
  188. else:
  189. return False
  190. if self.D["start_time"] > extent.D["end_time"]:
  191. return True
  192. else:
  193. return False
  194. def before(self, extent):
  195. """!Return True if this temporal extent (A) is located before the
  196. provided temporal extent (B)
  197. @verbatim
  198. A |---------|
  199. B |---------|
  200. @endverbatim
  201. @param extent: The temporal extent object that is located after this extent
  202. Usage:
  203. @code
  204. >>> A = AbstractTemporalExtent(start_time=6, end_time=7 )
  205. >>> B = AbstractTemporalExtent(start_time=8, end_time=9 )
  206. >>> A.before(B)
  207. True
  208. >>> B.before(A)
  209. False
  210. @endcode
  211. """
  212. if self.D["end_time"] is None:
  213. if self.D["start_time"] < extent.D["start_time"]:
  214. return True
  215. else:
  216. return False
  217. if self.D["end_time"] < extent.D["start_time"]:
  218. return True
  219. else:
  220. return False
  221. def adjacent(self, extent):
  222. """!Return True if this temporal extent (A) is a meeting neighbor the
  223. provided temporal extent (B)
  224. @verbatim
  225. A |---------|
  226. B |---------|
  227. A |---------|
  228. B |---------|
  229. @endverbatim
  230. @param extent: The temporal extent object that is a meeting neighbor
  231. of this extent
  232. Usage:
  233. @code
  234. >>> A = AbstractTemporalExtent(start_time=5, end_time=7 )
  235. >>> B = AbstractTemporalExtent(start_time=7, end_time=9 )
  236. >>> A.adjacent(B)
  237. True
  238. >>> B.adjacent(A)
  239. True
  240. >>> A = AbstractTemporalExtent(start_time=5, end_time=7 )
  241. >>> B = AbstractTemporalExtent(start_time=3, end_time=5 )
  242. >>> A.adjacent(B)
  243. True
  244. >>> B.adjacent(A)
  245. True
  246. @endcode
  247. """
  248. if self.D["end_time"] is None and extent.D["end_time"] is None:
  249. return False
  250. if (self.D["start_time"] == extent.D["end_time"]) or \
  251. (self.D["end_time"] == extent.D["start_time"]):
  252. return True
  253. else:
  254. return False
  255. def follows(self, extent):
  256. """!Return True if this temporal extent (A) follows the
  257. provided temporal extent (B)
  258. @verbatim
  259. A |---------|
  260. B |---------|
  261. @endverbatim
  262. @param extent: The temporal extent object that is the predecessor
  263. of this extent
  264. Usage:
  265. @code
  266. >>> A = AbstractTemporalExtent(start_time=5, end_time=7 )
  267. >>> B = AbstractTemporalExtent(start_time=3, end_time=5 )
  268. >>> A.follows(B)
  269. True
  270. >>> B.follows(A)
  271. False
  272. @endcode
  273. """
  274. if extent.D["end_time"] is None:
  275. return False
  276. if self.D["start_time"] == extent.D["end_time"]:
  277. return True
  278. else:
  279. return False
  280. def precedes(self, extent):
  281. """!Return True if this temporal extent (A) precedes the provided
  282. temporal extent (B)
  283. @verbatim
  284. A |---------|
  285. B |---------|
  286. @endverbatim
  287. @param extent: The temporal extent object that is the successor
  288. of this extent
  289. Usage:
  290. @code
  291. >>> A = AbstractTemporalExtent(start_time=5, end_time=7 )
  292. >>> B = AbstractTemporalExtent(start_time=7, end_time=9 )
  293. >>> A.precedes(B)
  294. True
  295. >>> B.precedes(A)
  296. False
  297. @endcode
  298. """
  299. if self.D["end_time"] is None:
  300. return False
  301. if self.D["end_time"] == extent.D["start_time"]:
  302. return True
  303. else:
  304. return False
  305. def during(self, extent):
  306. """!Return True if this temporal extent (A) is located during the provided
  307. temporal extent (B)
  308. @verbatim
  309. A |-------|
  310. B |---------|
  311. @endverbatim
  312. @param extent: The temporal extent object that contains this extent
  313. Usage:
  314. @code
  315. >>> A = AbstractTemporalExtent(start_time=5, end_time=7 )
  316. >>> B = AbstractTemporalExtent(start_time=4, end_time=9 )
  317. >>> A.during(B)
  318. True
  319. >>> B.during(A)
  320. False
  321. @endcode
  322. """
  323. # Check single point of time in interval
  324. if extent.D["end_time"] is None:
  325. return False
  326. # Check single point of time in interval
  327. if self.D["end_time"] is None:
  328. if self.D["start_time"] > extent.D["start_time"] and \
  329. self.D["start_time"] < extent.D["end_time"]:
  330. return True
  331. else:
  332. return False
  333. if self.D["start_time"] > extent.D["start_time"] and \
  334. self.D["end_time"] < extent.D["end_time"]:
  335. return True
  336. else:
  337. return False
  338. def contains(self, extent):
  339. """!Return True if this temporal extent (A) contains the provided
  340. temporal extent (B)
  341. @verbatim
  342. A |---------|
  343. B |-------|
  344. @endverbatim
  345. @param extent: The temporal extent object that is located
  346. during this extent
  347. Usage:
  348. @code
  349. >>> A = AbstractTemporalExtent(start_time=4, end_time=9 )
  350. >>> B = AbstractTemporalExtent(start_time=5, end_time=8 )
  351. >>> A.contains(B)
  352. True
  353. >>> B.contains(A)
  354. False
  355. @endcode
  356. """
  357. # Check single point of time in interval
  358. if self.D["end_time"] is None:
  359. return False
  360. # Check single point of time in interval
  361. if extent.D["end_time"] is None:
  362. if self.D["start_time"] < extent.D["start_time"] and \
  363. self.D["end_time"] > extent.D["start_time"]:
  364. return True
  365. else:
  366. return False
  367. if self.D["start_time"] < extent.D["start_time"] and \
  368. self.D["end_time"] > extent.D["end_time"]:
  369. return True
  370. else:
  371. return False
  372. def equal(self, extent):
  373. """!Return True if this temporal extent (A) is equal to the provided
  374. temporal extent (B)
  375. @verbatim
  376. A |---------|
  377. B |---------|
  378. @endverbatim
  379. @param extent: The temporal extent object that is equal
  380. during this extent
  381. Usage:
  382. @code
  383. >>> A = AbstractTemporalExtent(start_time=5, end_time=6 )
  384. >>> B = AbstractTemporalExtent(start_time=5, end_time=6 )
  385. >>> A.equal(B)
  386. True
  387. >>> B.equal(A)
  388. True
  389. @endcode
  390. """
  391. if self.D["end_time"] is None and extent.D["end_time"] is None:
  392. if self.D["start_time"] == extent.D["start_time"]:
  393. return True
  394. else:
  395. return False
  396. if self.D["end_time"] is None or extent.D["end_time"] is None:
  397. return False
  398. if self.D["start_time"] == extent.D["start_time"] and \
  399. self.D["end_time"] == extent.D["end_time"]:
  400. return True
  401. else:
  402. return False
  403. def overlapped(self, extent):
  404. """!Return True if this temporal extent (A) overlapped the provided
  405. temporal extent (B)
  406. @verbatim
  407. A |---------|
  408. B |---------|
  409. @endverbatim
  410. @param extent: The temporal extent object that is overlaps
  411. this extent
  412. Usage:
  413. @code
  414. >>> A = AbstractTemporalExtent(start_time=5, end_time=7 )
  415. >>> B = AbstractTemporalExtent(start_time=6, end_time=8 )
  416. >>> A.overlapped(B)
  417. True
  418. >>> B.overlapped(A)
  419. False
  420. @endcode
  421. """
  422. if self.D["end_time"] is None or extent.D["end_time"] is None:
  423. return False
  424. if self.D["start_time"] < extent.D["start_time"] and \
  425. self.D["end_time"] < extent.D["end_time"] and \
  426. self.D["end_time"] > extent.D["start_time"]:
  427. return True
  428. else:
  429. return False
  430. def overlaps(self, extent):
  431. """!Return True if this temporal extent (A) overlapps the provided
  432. temporal extent (B)
  433. @verbatim
  434. A |---------|
  435. B |---------|
  436. @endverbatim
  437. @param extent: The temporal extent object that is overlapped
  438. this extent
  439. Usage:
  440. @code
  441. >>> A = AbstractTemporalExtent(start_time=6, end_time=8 )
  442. >>> B = AbstractTemporalExtent(start_time=5, end_time=7 )
  443. >>> A.overlaps(B)
  444. True
  445. >>> B.overlaps(A)
  446. False
  447. @endcode
  448. """
  449. if self.D["end_time"] is None or extent.D["end_time"] is None:
  450. return False
  451. if self.D["start_time"] > extent.D["start_time"] and \
  452. self.D["end_time"] > extent.D["end_time"] and \
  453. self.D["start_time"] < extent.D["end_time"]:
  454. return True
  455. else:
  456. return False
  457. def temporal_relation(self, extent):
  458. """!Returns the temporal relation between temporal objects
  459. Temporal relationships are implemented after
  460. [Allen and Ferguson 1994 Actions and Events in Interval Temporal Logic]
  461. The following temporal relationships are supported:
  462. - equal
  463. - during
  464. - contains
  465. - overlaps
  466. - overlapped
  467. - after
  468. - before
  469. - starts
  470. - finishes
  471. - started
  472. - finished
  473. - follows
  474. - precedes
  475. @param extent: The temporal extent
  476. @return The name of the temporal relation or None if no relation found
  477. """
  478. # First check for correct time
  479. if "start_time" not in self.D:
  480. return None
  481. if "end_time" not in self.D:
  482. return None
  483. if "start_time" not in extent.D:
  484. return None
  485. if "end_time" not in extent.D:
  486. return None
  487. # Return None if the start_time is undefined
  488. if self.D["start_time"] is None or extent.D["start_time"] is None:
  489. return None
  490. if self.equal(extent):
  491. return "equal"
  492. if self.during(extent):
  493. return "during"
  494. if self.contains(extent):
  495. return "contains"
  496. if self.overlaps(extent):
  497. return "overlaps"
  498. if self.overlapped(extent):
  499. return "overlapped"
  500. if self.after(extent):
  501. return "after"
  502. if self.before(extent):
  503. return "before"
  504. if self.starts(extent):
  505. return "starts"
  506. if self.finishes(extent):
  507. return "finishes"
  508. if self.started(extent):
  509. return "started"
  510. if self.finished(extent):
  511. return "finished"
  512. if self.follows(extent):
  513. return "follows"
  514. if self.precedes(extent):
  515. return "precedes"
  516. return None
  517. def set_id(self, ident):
  518. """!Convenient method to set the unique identifier (primary key)"""
  519. self.ident = ident
  520. self.D["id"] = ident
  521. def set_start_time(self, start_time):
  522. """!Set the valid start time of the extent"""
  523. self.D["start_time"] = start_time
  524. def set_end_time(self, end_time):
  525. """!Set the valid end time of the extent"""
  526. self.D["end_time"] = end_time
  527. def get_id(self):
  528. """!Convenient method to get the unique identifier (primary key)
  529. @return None if not found
  530. """
  531. if "id" in self.D:
  532. return self.D["id"]
  533. else:
  534. return None
  535. def get_start_time(self):
  536. """!Get the valid start time of the extent
  537. @return None if not found"""
  538. if "start_time" in self.D:
  539. return self.D["start_time"]
  540. else:
  541. return None
  542. def get_end_time(self):
  543. """!Get the valid end time of the extent
  544. @return None if not found"""
  545. if "end_time" in self.D:
  546. return self.D["end_time"]
  547. else:
  548. return None
  549. # Set the properties
  550. id = property(fget=get_id, fset=set_id)
  551. start_time = property(fget=get_start_time, fset=set_start_time)
  552. end_time = property(fget=get_end_time, fset=set_end_time)
  553. def print_info(self):
  554. """!Print information about this class in human readable style"""
  555. # 0123456789012345678901234567890
  556. print " | Start time:................. " + str(self.get_start_time())
  557. print " | End time:................... " + str(self.get_end_time())
  558. def print_shell_info(self):
  559. """!Print information about this class in shell style"""
  560. print "start_time=" + str(self.get_start_time())
  561. print "end_time=" + str(self.get_end_time())
  562. ###############################################################################
  563. class AbsoluteTemporalExtent(AbstractTemporalExtent):
  564. """!This is the absolute time class for all maps and spacetime datasets
  565. start_time and end_time must be of type datetime
  566. """
  567. def __init__(self, table=None, ident=None, start_time=None, end_time=None,
  568. timezone=None):
  569. AbstractTemporalExtent.__init__(
  570. self, table, ident, start_time, end_time)
  571. self.set_timezone(timezone)
  572. def set_timezone(self, timezone):
  573. """!Set the timezone of the map, the timezone is of type string.
  574. Timezones are not supported yet, instead the timezone
  575. is set in the datetime string as offset in minutes.
  576. """
  577. self.D["timezone"] = timezone
  578. def get_timezone(self):
  579. """!Get the timezone of the map
  580. Timezones are not supported yet, instead the timezone
  581. is set in the datetime string as offset in minutes.
  582. @return None if not found"""
  583. if "timezone" in self.D:
  584. return self.D["timezone"]
  585. else:
  586. return None
  587. timezone = property(fget=get_timezone, fset=set_timezone)
  588. def print_info(self):
  589. """!Print information about this class in human readable style"""
  590. # 0123456789012345678901234567890
  591. print " +-------------------- Absolute time -----------------------------------------+"
  592. AbstractTemporalExtent.print_info(self)
  593. #print " | Timezone:................... " + str(self.get_timezone())
  594. def print_shell_info(self):
  595. """!Print information about this class in shell style"""
  596. AbstractTemporalExtent.print_shell_info(self)
  597. #print "timezone=" + str(self.get_timezone())
  598. ###############################################################################
  599. class RasterAbsoluteTime(AbsoluteTemporalExtent):
  600. def __init__(self, ident=None, start_time=None, end_time=None,
  601. timezone=None):
  602. AbsoluteTemporalExtent.__init__(self, "raster_absolute_time",
  603. ident, start_time, end_time, timezone)
  604. class Raster3DAbsoluteTime(AbsoluteTemporalExtent):
  605. def __init__(self, ident=None, start_time=None, end_time=None,
  606. timezone=None):
  607. AbsoluteTemporalExtent.__init__(self, "raster3d_absolute_time",
  608. ident, start_time, end_time, timezone)
  609. class VectorAbsoluteTime(AbsoluteTemporalExtent):
  610. def __init__(self, ident=None, start_time=None, end_time=None,
  611. timezone=None):
  612. AbsoluteTemporalExtent.__init__(self, "vector_absolute_time",
  613. ident, start_time, end_time, timezone)
  614. ###############################################################################
  615. class STDSAbsoluteTime(AbsoluteTemporalExtent):
  616. """!This class implements the absolute time extent for space time dataset
  617. In addition to the existing functionality the granularity and the
  618. map_time are added.
  619. Usage:
  620. @code
  621. >>> init()
  622. >>> A = STDSAbsoluteTime(table="strds_absolute_time",
  623. ... ident="strds@PERMANENT", start_time=datetime(2001, 01, 01),
  624. ... end_time=datetime(2005,01,01), granularity="1 days",
  625. ... map_time="interval")
  626. >>> A.id
  627. 'strds@PERMANENT'
  628. >>> A.start_time
  629. datetime.datetime(2001, 1, 1, 0, 0)
  630. >>> A.end_time
  631. datetime.datetime(2005, 1, 1, 0, 0)
  632. >>> A.granularity
  633. '1 days'
  634. >>> A.map_time
  635. 'interval'
  636. >>> A.print_info()
  637. +-------------------- Absolute time -----------------------------------------+
  638. | Start time:................. 2001-01-01 00:00:00
  639. | End time:................... 2005-01-01 00:00:00
  640. | Granularity:................ 1 days
  641. | Temporal type of maps:...... interval
  642. >>> A.print_shell_info()
  643. start_time=2001-01-01 00:00:00
  644. end_time=2005-01-01 00:00:00
  645. granularity=1 days
  646. map_time=interval
  647. @endcode
  648. """
  649. def __init__(self, table=None, ident=None, start_time=None, end_time=None,
  650. granularity=None, timezone=None, map_time=None):
  651. AbsoluteTemporalExtent.__init__(
  652. self, table, ident, start_time, end_time, timezone)
  653. self.set_granularity(granularity)
  654. self.set_map_time(map_time)
  655. def set_granularity(self, granularity):
  656. """!Set the granularity of the space time dataset"""
  657. self.D["granularity"] = granularity
  658. def set_map_time(self, map_time):
  659. """!Set the type of the map time
  660. Registered maps may have different types of time:
  661. - Single point of time "point"
  662. - Time intervals "interval"
  663. - Single point and interval time "mixed"
  664. This variable will be set automatically when maps are registered.
  665. """
  666. self.D["map_time"] = map_time
  667. def get_granularity(self):
  668. """!Get the granularity of the space time dataset
  669. @return None if not found"""
  670. if "granularity" in self.D:
  671. return self.D["granularity"]
  672. else:
  673. return None
  674. def get_map_time(self):
  675. """!Get the type of the map time
  676. Registered maps may have different types of time:
  677. Single point of time "point"
  678. Time intervals "interval"
  679. Or single point and interval time "mixed"
  680. This variable will be set automatically when maps are registered.
  681. """
  682. if "map_time" in self.D:
  683. return self.D["map_time"]
  684. else:
  685. return None
  686. # Properties
  687. granularity = property(fget=get_granularity, fset=set_granularity)
  688. map_time = property(fget=get_map_time, fset=set_map_time)
  689. def print_info(self):
  690. """!Print information about this class in human readable style"""
  691. AbsoluteTemporalExtent.print_info(self)
  692. # 0123456789012345678901234567890
  693. print " | Granularity:................ " + str(self.get_granularity())
  694. print " | Temporal type of maps:...... " + str(self.get_map_time())
  695. def print_shell_info(self):
  696. """!Print information about this class in shell style"""
  697. AbsoluteTemporalExtent.print_shell_info(self)
  698. print "granularity=" + str(self.get_granularity())
  699. print "map_time=" + str(self.get_map_time())
  700. ###############################################################################
  701. class STRDSAbsoluteTime(STDSAbsoluteTime):
  702. def __init__(self, ident=None, start_time=None, end_time=None,
  703. granularity=None, timezone=None):
  704. STDSAbsoluteTime.__init__(self, "strds_absolute_time",
  705. ident, start_time, end_time, granularity, timezone)
  706. class STR3DSAbsoluteTime(STDSAbsoluteTime):
  707. def __init__(self, ident=None, start_time=None, end_time=None,
  708. granularity=None, timezone=None):
  709. STDSAbsoluteTime.__init__(self, "str3ds_absolute_time",
  710. ident, start_time, end_time, granularity, timezone)
  711. class STVDSAbsoluteTime(STDSAbsoluteTime):
  712. def __init__(self, ident=None, start_time=None, end_time=None,
  713. granularity=None, timezone=None):
  714. STDSAbsoluteTime.__init__(self, "stvds_absolute_time",
  715. ident, start_time, end_time, granularity, timezone)
  716. ###############################################################################
  717. class RelativeTemporalExtent(AbstractTemporalExtent):
  718. """!This is the relative time class for all maps and space time datasets
  719. start_time and end_time must be of type integer
  720. Usage:
  721. @code
  722. >>> init()
  723. >>> A = RelativeTemporalExtent(table="raster_relative_time",
  724. ... ident="soil@PERMANENT", start_time=0, end_time=1, unit="years")
  725. >>> A.id
  726. 'soil@PERMANENT'
  727. >>> A.start_time
  728. 0
  729. >>> A.end_time
  730. 1
  731. >>> A.unit
  732. 'years'
  733. >>> A.print_info()
  734. +-------------------- Relative time -----------------------------------------+
  735. | Start time:................. 0
  736. | End time:................... 1
  737. | Relative time unit:......... years
  738. >>> A.print_shell_info()
  739. start_time=0
  740. end_time=1
  741. unit=years
  742. @endcode
  743. """
  744. def __init__(self, table=None, ident=None, start_time=None, end_time=None,
  745. unit=None):
  746. AbstractTemporalExtent.__init__(
  747. self, table, ident, start_time, end_time)
  748. self.D["unit"] = unit
  749. def set_unit(self, unit):
  750. """!Set the unit of the relative time. Valid units are:
  751. - years
  752. - months
  753. - days
  754. - hours
  755. - minutes
  756. - seconds
  757. """
  758. self.D["unit"] = unit
  759. def get_unit(self):
  760. """!Get the unit of the relative time
  761. @return None if not found"""
  762. if "unit" in self.D:
  763. return self.D["unit"]
  764. else:
  765. return None
  766. def temporal_relation(self, map):
  767. """!Returns the temporal relation between temporal objects
  768. Temporal relationships are implemented after
  769. [Allen and Ferguson 1994 Actions and Events in Interval Temporal Logic]
  770. """
  771. # Check units for relative time
  772. if "unit" not in self.D:
  773. return None
  774. if "unit" not in map.D:
  775. return None
  776. # Units must be equal
  777. if self.D["unit"] != map.D["unit"]:
  778. return None
  779. return AbstractTemporalExtent.temporal_relation(self, map)
  780. # Properties
  781. unit = property(fget=get_unit, fset=set_unit)
  782. def print_info(self):
  783. """!Print information about this class in human readable style"""
  784. # 0123456789012345678901234567890
  785. print " +-------------------- Relative time -----------------------------------------+"
  786. AbstractTemporalExtent.print_info(self)
  787. print " | Relative time unit:......... " + str(self.get_unit())
  788. def print_shell_info(self):
  789. """!Print information about this class in shell style"""
  790. AbstractTemporalExtent.print_shell_info(self)
  791. print "unit=" + str(self.get_unit())
  792. ###############################################################################
  793. class RasterRelativeTime(RelativeTemporalExtent):
  794. def __init__(self, ident=None, start_time=None, end_time=None):
  795. RelativeTemporalExtent.__init__(
  796. self, "raster_relative_time", ident, start_time, end_time)
  797. class Raster3DRelativeTime(RelativeTemporalExtent):
  798. def __init__(self, ident=None, start_time=None, end_time=None):
  799. RelativeTemporalExtent.__init__(self,
  800. "raster3d_relative_time", ident, start_time, end_time)
  801. class VectorRelativeTime(RelativeTemporalExtent):
  802. def __init__(self, ident=None, start_time=None, end_time=None):
  803. RelativeTemporalExtent.__init__(
  804. self, "vector_relative_time", ident, start_time, end_time)
  805. ###############################################################################
  806. class STDSRelativeTime(RelativeTemporalExtent):
  807. """!This is the relative time class for all maps and space time datasets
  808. start_time and end_time must be of type integer
  809. Usage:
  810. @code
  811. >>> init()
  812. >>> A = STDSRelativeTime(table="strds_relative_time",
  813. ... ident="strds@PERMANENT", start_time=0, end_time=1, unit="years",
  814. ... granularity=5, map_time="interval")
  815. >>> A.id
  816. 'strds@PERMANENT'
  817. >>> A.start_time
  818. 0
  819. >>> A.end_time
  820. 1
  821. >>> A.unit
  822. 'years'
  823. >>> A.granularity
  824. 5
  825. >>> A.map_time
  826. 'interval'
  827. >>> A.print_info()
  828. +-------------------- Relative time -----------------------------------------+
  829. | Start time:................. 0
  830. | End time:................... 1
  831. | Relative time unit:......... years
  832. | Granularity:................ 5
  833. | Temporal type of maps:...... interval
  834. >>> A.print_shell_info()
  835. start_time=0
  836. end_time=1
  837. unit=years
  838. granularity=5
  839. map_time=interval
  840. @endcode
  841. """
  842. def __init__(self, table=None, ident=None, start_time=None, end_time=None,
  843. unit=None, granularity=None, map_time=None):
  844. RelativeTemporalExtent.__init__(
  845. self, table, ident, start_time, end_time, unit)
  846. self.set_granularity(granularity)
  847. self.set_map_time(map_time)
  848. def set_granularity(self, granularity):
  849. """!Set the granularity of the space time dataset"""
  850. self.D["granularity"] = granularity
  851. def set_map_time(self, map_time):
  852. """!Set the type of the map time
  853. Registered maps may have different types of time:
  854. Single point of time "point"
  855. Time intervals "interval"
  856. Or single point and interval time "mixed"
  857. This variable will be set automatically when maps are registered.
  858. """
  859. self.D["map_time"] = map_time
  860. def get_granularity(self):
  861. """!Get the granularity of the space time dataset
  862. @return None if not found"""
  863. if "granularity" in self.D:
  864. return self.D["granularity"]
  865. else:
  866. return None
  867. def get_map_time(self):
  868. """!Get the type of the map time
  869. Registered maps may have different types of time:
  870. Single point of time "point"
  871. Time intervals "interval"
  872. Or single point and interval time "mixed"
  873. This variable will be set automatically when maps are registered.
  874. """
  875. if "map_time" in self.D:
  876. return self.D["map_time"]
  877. else:
  878. return None
  879. # Properties
  880. granularity = property(fget=get_granularity, fset=set_granularity)
  881. map_time = property(fget=get_map_time, fset=set_map_time)
  882. def print_info(self):
  883. """!Print information about this class in human readable style"""
  884. RelativeTemporalExtent.print_info(self)
  885. # 0123456789012345678901234567890
  886. print " | Granularity:................ " + str(self.get_granularity())
  887. print " | Temporal type of maps:...... " + str(self.get_map_time())
  888. def print_shell_info(self):
  889. """!Print information about this class in shell style"""
  890. RelativeTemporalExtent.print_shell_info(self)
  891. print "granularity=" + str(self.get_granularity())
  892. print "map_time=" + str(self.get_map_time())
  893. ###############################################################################
  894. class STRDSRelativeTime(STDSRelativeTime):
  895. def __init__(self, ident=None, start_time=None, end_time=None,
  896. granularity=None):
  897. STDSRelativeTime.__init__(self, "strds_relative_time",
  898. ident, start_time, end_time, granularity)
  899. class STR3DSRelativeTime(STDSRelativeTime):
  900. def __init__(self, ident=None, start_time=None, end_time=None,
  901. granularity=None):
  902. STDSRelativeTime.__init__(self, "str3ds_relative_time",
  903. ident, start_time, end_time, granularity)
  904. class STVDSRelativeTime(STDSRelativeTime):
  905. def __init__(self, ident=None, start_time=None, end_time=None,
  906. granularity=None):
  907. STDSRelativeTime.__init__(self, "stvds_relative_time",
  908. ident, start_time, end_time, granularity)
  909. ###############################################################################
  910. if __name__ == "__main__":
  911. import doctest
  912. doctest.testmod()