temporal_algebra.py 106 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545
  1. """@package grass.temporal
  2. Temporal algebra parser class
  3. (C) 2014 by the GRASS Development Team
  4. This program is free software under the GNU General Public
  5. License (>=v2). Read the file COPYING that comes with GRASS
  6. for details.
  7. :authors: Thomas Leppelt and Soeren Gebbert
  8. .. code-block:: python
  9. >>> import grass.temporal as tgis
  10. >>> tgis.init(True)
  11. >>> p = tgis.TemporalAlgebraLexer()
  12. >>> p.build()
  13. >>> p.debug = True
  14. >>> expression = "C = A : B"
  15. >>> p.test(expression)
  16. C = A : B
  17. LexToken(NAME,'C',1,0)
  18. LexToken(EQUALS,'=',1,2)
  19. LexToken(NAME,'A',1,4)
  20. LexToken(T_SELECT,':',1,6)
  21. LexToken(NAME,'B',1,8)
  22. >>> expression = "C = test1 !: test2"
  23. >>> p.test(expression)
  24. C = test1 !: test2
  25. LexToken(NAME,'C',1,0)
  26. LexToken(EQUALS,'=',1,2)
  27. LexToken(NAME,'test1',1,4)
  28. LexToken(T_NOT_SELECT,'!:',1,10)
  29. LexToken(NAME,'test2',1,13)
  30. >>> expression = "C = test1 {:,equal} test2"
  31. >>> p.test(expression)
  32. C = test1 {:,equal} test2
  33. LexToken(NAME,'C',1,0)
  34. LexToken(EQUALS,'=',1,2)
  35. LexToken(NAME,'test1',1,4)
  36. LexToken(T_SELECT_OPERATOR,'{:,equal}',1,10)
  37. LexToken(NAME,'test2',1,20)
  38. >>> expression = "C = test1 {!:,equal} test2"
  39. >>> p.test(expression)
  40. C = test1 {!:,equal} test2
  41. LexToken(NAME,'C',1,0)
  42. LexToken(EQUALS,'=',1,2)
  43. LexToken(NAME,'test1',1,4)
  44. LexToken(T_SELECT_OPERATOR,'{!:,equal}',1,10)
  45. LexToken(NAME,'test2',1,21)
  46. >>> expression = "C = test1 # test2"
  47. >>> p.test(expression)
  48. C = test1 # test2
  49. LexToken(NAME,'C',1,0)
  50. LexToken(EQUALS,'=',1,2)
  51. LexToken(NAME,'test1',1,4)
  52. LexToken(HASH,'#',1,10)
  53. LexToken(NAME,'test2',1,12)
  54. >>> expression = "C = test1 {#} test2"
  55. >>> p.test(expression)
  56. C = test1 {#} test2
  57. LexToken(NAME,'C',1,0)
  58. LexToken(EQUALS,'=',1,2)
  59. LexToken(NAME,'test1',1,4)
  60. LexToken(T_HASH_OPERATOR,'{#}',1,10)
  61. LexToken(NAME,'test2',1,14)
  62. >>> expression = "C = test1 {#,equal} test2"
  63. >>> p.test(expression)
  64. C = test1 {#,equal} test2
  65. LexToken(NAME,'C',1,0)
  66. LexToken(EQUALS,'=',1,2)
  67. LexToken(NAME,'test1',1,4)
  68. LexToken(T_HASH_OPERATOR,'{#,equal}',1,10)
  69. LexToken(NAME,'test2',1,20)
  70. >>> expression = "C = test1 {#,equal|during} test2"
  71. >>> p.test(expression)
  72. C = test1 {#,equal|during} test2
  73. LexToken(NAME,'C',1,0)
  74. LexToken(EQUALS,'=',1,2)
  75. LexToken(NAME,'test1',1,4)
  76. LexToken(T_HASH_OPERATOR,'{#,equal|during}',1,10)
  77. LexToken(NAME,'test2',1,27)
  78. >>> expression = "E = test1 : test2 !: test1"
  79. >>> p.test(expression)
  80. E = test1 : test2 !: test1
  81. LexToken(NAME,'E',1,0)
  82. LexToken(EQUALS,'=',1,2)
  83. LexToken(NAME,'test1',1,4)
  84. LexToken(T_SELECT,':',1,10)
  85. LexToken(NAME,'test2',1,12)
  86. LexToken(T_NOT_SELECT,'!:',1,18)
  87. LexToken(NAME,'test1',1,21)
  88. >>> expression = 'D = buff_t(test1,"10 months")'
  89. >>> p.test(expression)
  90. D = buff_t(test1,"10 months")
  91. LexToken(NAME,'D',1,0)
  92. LexToken(EQUALS,'=',1,2)
  93. LexToken(BUFF_T,'buff_t',1,4)
  94. LexToken(LPAREN,'(',1,10)
  95. LexToken(NAME,'test1',1,11)
  96. LexToken(COMMA,',',1,16)
  97. LexToken(QUOTE,'"',1,17)
  98. LexToken(INT,10,1,18)
  99. LexToken(NAME,'months',1,21)
  100. LexToken(QUOTE,'"',1,27)
  101. LexToken(RPAREN,')',1,28)
  102. >>> expression = 'H = tsnap(test1)'
  103. >>> p.test(expression)
  104. H = tsnap(test1)
  105. LexToken(NAME,'H',1,0)
  106. LexToken(EQUALS,'=',1,2)
  107. LexToken(TSNAP,'tsnap',1,4)
  108. LexToken(LPAREN,'(',1,9)
  109. LexToken(NAME,'test1',1,10)
  110. LexToken(RPAREN,')',1,15)
  111. >>> expression = 'H = tsnap(test2 {:,during} buff_t(test1, "1 days"))'
  112. >>> p.test(expression)
  113. H = tsnap(test2 {:,during} buff_t(test1, "1 days"))
  114. LexToken(NAME,'H',1,0)
  115. LexToken(EQUALS,'=',1,2)
  116. LexToken(TSNAP,'tsnap',1,4)
  117. LexToken(LPAREN,'(',1,9)
  118. LexToken(NAME,'test2',1,10)
  119. LexToken(T_SELECT_OPERATOR,'{:,during}',1,16)
  120. LexToken(BUFF_T,'buff_t',1,27)
  121. LexToken(LPAREN,'(',1,33)
  122. LexToken(NAME,'test1',1,34)
  123. LexToken(COMMA,',',1,39)
  124. LexToken(QUOTE,'"',1,41)
  125. LexToken(INT,1,1,42)
  126. LexToken(NAME,'days',1,44)
  127. LexToken(QUOTE,'"',1,48)
  128. LexToken(RPAREN,')',1,49)
  129. LexToken(RPAREN,')',1,50)
  130. >>> expression = 'H = tshift(test2 {:,during} buff_t(test1, "1 days"), "1 months")'
  131. >>> p.test(expression)
  132. H = tshift(test2 {:,during} buff_t(test1, "1 days"), "1 months")
  133. LexToken(NAME,'H',1,0)
  134. LexToken(EQUALS,'=',1,2)
  135. LexToken(TSHIFT,'tshift',1,4)
  136. LexToken(LPAREN,'(',1,10)
  137. LexToken(NAME,'test2',1,11)
  138. LexToken(T_SELECT_OPERATOR,'{:,during}',1,17)
  139. LexToken(BUFF_T,'buff_t',1,28)
  140. LexToken(LPAREN,'(',1,34)
  141. LexToken(NAME,'test1',1,35)
  142. LexToken(COMMA,',',1,40)
  143. LexToken(QUOTE,'"',1,42)
  144. LexToken(INT,1,1,43)
  145. LexToken(NAME,'days',1,45)
  146. LexToken(QUOTE,'"',1,49)
  147. LexToken(RPAREN,')',1,50)
  148. LexToken(COMMA,',',1,51)
  149. LexToken(QUOTE,'"',1,53)
  150. LexToken(INT,1,1,54)
  151. LexToken(NAME,'months',1,56)
  152. LexToken(QUOTE,'"',1,62)
  153. LexToken(RPAREN,')',1,63)
  154. >>> expression = 'H = tshift(A , 10)'
  155. >>> p.test(expression)
  156. H = tshift(A , 10)
  157. LexToken(NAME,'H',1,0)
  158. LexToken(EQUALS,'=',1,2)
  159. LexToken(TSHIFT,'tshift',1,4)
  160. LexToken(LPAREN,'(',1,10)
  161. LexToken(NAME,'A',1,11)
  162. LexToken(COMMA,',',1,13)
  163. LexToken(INT,10,1,15)
  164. LexToken(RPAREN,')',1,17)
  165. >>> expression = 'H = if(td(A) > 10, A)'
  166. >>> p.test(expression)
  167. H = if(td(A) > 10, A)
  168. LexToken(NAME,'H',1,0)
  169. LexToken(EQUALS,'=',1,2)
  170. LexToken(IF,'if',1,4)
  171. LexToken(LPAREN,'(',1,6)
  172. LexToken(TD,'td',1,7)
  173. LexToken(LPAREN,'(',1,9)
  174. LexToken(NAME,'A',1,10)
  175. LexToken(RPAREN,')',1,11)
  176. LexToken(GREATER,'>',1,13)
  177. LexToken(INT,10,1,15)
  178. LexToken(COMMA,',',1,17)
  179. LexToken(NAME,'A',1,19)
  180. LexToken(RPAREN,')',1,20)
  181. >>> expression = 'H = if(td(A) > 10, A, B)'
  182. >>> p.test(expression)
  183. H = if(td(A) > 10, A, B)
  184. LexToken(NAME,'H',1,0)
  185. LexToken(EQUALS,'=',1,2)
  186. LexToken(IF,'if',1,4)
  187. LexToken(LPAREN,'(',1,6)
  188. LexToken(TD,'td',1,7)
  189. LexToken(LPAREN,'(',1,9)
  190. LexToken(NAME,'A',1,10)
  191. LexToken(RPAREN,')',1,11)
  192. LexToken(GREATER,'>',1,13)
  193. LexToken(INT,10,1,15)
  194. LexToken(COMMA,',',1,17)
  195. LexToken(NAME,'A',1,19)
  196. LexToken(COMMA,',',1,20)
  197. LexToken(NAME,'B',1,22)
  198. LexToken(RPAREN,')',1,23)
  199. >>> expression = 'I = if(equals,td(A) > 10 {||,equals} td(B) < 10, A)'
  200. >>> p.test(expression)
  201. I = if(equals,td(A) > 10 {||,equals} td(B) < 10, A)
  202. LexToken(NAME,'I',1,0)
  203. LexToken(EQUALS,'=',1,2)
  204. LexToken(IF,'if',1,4)
  205. LexToken(LPAREN,'(',1,6)
  206. LexToken(NAME,'equals',1,7)
  207. LexToken(COMMA,',',1,13)
  208. LexToken(TD,'td',1,14)
  209. LexToken(LPAREN,'(',1,16)
  210. LexToken(NAME,'A',1,17)
  211. LexToken(RPAREN,')',1,18)
  212. LexToken(GREATER,'>',1,20)
  213. LexToken(INT,10,1,22)
  214. LexToken(T_COMP_OPERATOR,'{||,equals}',1,25)
  215. LexToken(TD,'td',1,37)
  216. LexToken(LPAREN,'(',1,39)
  217. LexToken(NAME,'B',1,40)
  218. LexToken(RPAREN,')',1,41)
  219. LexToken(LOWER,'<',1,43)
  220. LexToken(INT,10,1,45)
  221. LexToken(COMMA,',',1,47)
  222. LexToken(NAME,'A',1,49)
  223. LexToken(RPAREN,')',1,50)
  224. >>> expression = 'I = if(equals,td(A) > 10 || start_day() < 10, A)'
  225. >>> p.test(expression)
  226. I = if(equals,td(A) > 10 || start_day() < 10, A)
  227. LexToken(NAME,'I',1,0)
  228. LexToken(EQUALS,'=',1,2)
  229. LexToken(IF,'if',1,4)
  230. LexToken(LPAREN,'(',1,6)
  231. LexToken(NAME,'equals',1,7)
  232. LexToken(COMMA,',',1,13)
  233. LexToken(TD,'td',1,14)
  234. LexToken(LPAREN,'(',1,16)
  235. LexToken(NAME,'A',1,17)
  236. LexToken(RPAREN,')',1,18)
  237. LexToken(GREATER,'>',1,20)
  238. LexToken(INT,10,1,22)
  239. LexToken(OR,'|',1,25)
  240. LexToken(OR,'|',1,26)
  241. LexToken(START_DAY,'start_day',1,28)
  242. LexToken(LPAREN,'(',1,37)
  243. LexToken(RPAREN,')',1,38)
  244. LexToken(LOWER,'<',1,40)
  245. LexToken(INT,10,1,42)
  246. LexToken(COMMA,',',1,44)
  247. LexToken(NAME,'A',1,46)
  248. LexToken(RPAREN,')',1,47)
  249. >>> expression = 'E = if({equals},td(A) >= 4 {&&,contain} td(B) == 2, C : D)'
  250. >>> p.test(expression)
  251. E = if({equals},td(A) >= 4 {&&,contain} td(B) == 2, C : D)
  252. LexToken(NAME,'E',1,0)
  253. LexToken(EQUALS,'=',1,2)
  254. LexToken(IF,'if',1,4)
  255. LexToken(LPAREN,'(',1,6)
  256. LexToken(T_REL_OPERATOR,'{equals}',1,7)
  257. LexToken(COMMA,',',1,15)
  258. LexToken(TD,'td',1,16)
  259. LexToken(LPAREN,'(',1,18)
  260. LexToken(NAME,'A',1,19)
  261. LexToken(RPAREN,')',1,20)
  262. LexToken(GREATER_EQUALS,'>=',1,22)
  263. LexToken(INT,4,1,25)
  264. LexToken(T_COMP_OPERATOR,'{&&,contain}',1,27)
  265. LexToken(TD,'td',1,40)
  266. LexToken(LPAREN,'(',1,42)
  267. LexToken(NAME,'B',1,43)
  268. LexToken(RPAREN,')',1,44)
  269. LexToken(CEQUALS,'==',1,46)
  270. LexToken(INT,2,1,49)
  271. LexToken(COMMA,',',1,50)
  272. LexToken(NAME,'C',1,52)
  273. LexToken(T_SELECT,':',1,54)
  274. LexToken(NAME,'D',1,56)
  275. LexToken(RPAREN,')',1,57)
  276. >>> expression = 'F = if({equals},A {#,equal}, B, C : D)'
  277. >>> p.test(expression)
  278. F = if({equals},A {#,equal}, B, C : D)
  279. LexToken(NAME,'F',1,0)
  280. LexToken(EQUALS,'=',1,2)
  281. LexToken(IF,'if',1,4)
  282. LexToken(LPAREN,'(',1,6)
  283. LexToken(T_REL_OPERATOR,'{equals}',1,7)
  284. LexToken(COMMA,',',1,15)
  285. LexToken(NAME,'A',1,16)
  286. LexToken(T_HASH_OPERATOR,'{#,equal}',1,18)
  287. LexToken(COMMA,',',1,27)
  288. LexToken(NAME,'B',1,29)
  289. LexToken(COMMA,',',1,30)
  290. LexToken(NAME,'C',1,32)
  291. LexToken(T_SELECT,':',1,34)
  292. LexToken(NAME,'D',1,36)
  293. LexToken(RPAREN,')',1,37)
  294. >>> p = tgis.TemporalAlgebraParser()
  295. >>> p.run = False
  296. >>> p.debug = True
  297. >>> expression = "D = A {!:} B {:,during} C"
  298. >>> print(expression)
  299. D = A {!:} B {:,during} C
  300. >>> p.parse(expression)
  301. A* = A {!:} B
  302. A** = A* {:,during} C
  303. D = A**
  304. >>> expression = "D = A {:} B {!:,during} C"
  305. >>> print(expression)
  306. D = A {:} B {!:,during} C
  307. >>> p.parse(expression)
  308. A* = A {:} B
  309. A** = A* {!:,during} C
  310. D = A**
  311. >>> p.run = False
  312. >>> p.debug = False
  313. >>> expression = "C = test1 : test2"
  314. >>> print(expression)
  315. C = test1 : test2
  316. >>> p.parse(expression, 'stvds')
  317. >>> expression = 'D = buff_t(test1,"10 months")'
  318. >>> print(expression)
  319. D = buff_t(test1,"10 months")
  320. >>> p.parse(expression, 'stvds')
  321. >>> expression = 'E = test2 {:,during} buff_t(test1,"1 days")'
  322. >>> print(expression)
  323. E = test2 {:,during} buff_t(test1,"1 days")
  324. >>> p.parse(expression, 'stvds')
  325. >>> expression = 'F = test2 {:,equal} buff_t(test1,"1 days")'
  326. >>> print(expression)
  327. F = test2 {:,equal} buff_t(test1,"1 days")
  328. >>> p.parse(expression, 'stvds')
  329. >>> p.debug = True
  330. >>> expression = 'H = tsnap(test2 {:,during} buff_t(test1, "1 days"))'
  331. >>> p.parse(expression, 'stvds')
  332. test1* = buff_t( test1 , " 1 days " )
  333. test2* = test2 {:,during} test1*
  334. test2** = tsnap( test2* )
  335. H = test2**
  336. >>> expression = 'H = tshift(test2 {:,during} test1, "1 days")'
  337. >>> p.parse(expression, 'stvds')
  338. test2* = test2 {:,during} test1
  339. test2** = tshift( test2* , " 1 days " )
  340. H = test2**
  341. >>> expression = 'H = tshift(H, 3)'
  342. >>> p.parse(expression, 'stvds')
  343. H* = tshift( H , 3 )
  344. H = H*
  345. >>> expression = 'C = if(td(A) == 2, A)'
  346. >>> p.parse(expression, 'stvds')
  347. td(A)
  348. td(A) == 2
  349. A* = if condition None then A
  350. C = A*
  351. >>> expression = 'C = if(td(A) == 5, A, B)'
  352. >>> p.parse(expression, 'stvds')
  353. td(A)
  354. td(A) == 5
  355. A* = if condition None then A else B
  356. C = A*
  357. >>> expression = 'C = if(td(A) == 5 || start_date(A) > "2010-01-01", A, B)'
  358. >>> p.parse(expression, 'stvds')
  359. td(A)
  360. td(A) == 5
  361. start_date A > "2010-01-01"
  362. None || None
  363. A* = if condition None then A else B
  364. C = A*
  365. """
  366. try:
  367. import ply.lex as lex
  368. import ply.yacc as yacc
  369. except:
  370. pass
  371. import os
  372. import copy
  373. import grass.pygrass.modules as pymod
  374. from space_time_datasets import *
  375. from factory import *
  376. from open_stds import *
  377. from temporal_operator import *
  378. ##############################################################################
  379. class TemporalAlgebraLexer(object):
  380. """Lexical analyzer for the GRASS GIS temporal algebra"""
  381. # Functions that defines an if condition, temporal buffering, snapping and
  382. # selection of maps with temporal extent.
  383. conditional_functions = {
  384. 'if' : 'IF',
  385. 'buff_t': 'BUFF_T',
  386. 'tsnap' : 'TSNAP',
  387. 'tshift' : 'TSHIFT',
  388. 'tmap' : 'TMAP',
  389. }
  390. # Variables with date and time strings
  391. datetime_functions = {
  392. 'start_time' : 'START_TIME', # start time as HH::MM:SS
  393. 'start_date' : 'START_DATE', # start date as yyyy-mm-DD
  394. 'start_datetime' : 'START_DATETIME', # start datetime as yyyy-mm-DD HH:MM:SS
  395. 'end_time' : 'END_TIME', # end time as HH:MM:SS
  396. 'end_date' : 'END_DATE', # end date as yyyy-mm-DD
  397. 'end_datetime' : 'END_DATETIME', # end datetime as yyyy-mm-DD HH:MM:SS
  398. }
  399. # Time functions
  400. time_functions = {
  401. 'td' : 'TD', # The size of the current
  402. # sample time interval in days and
  403. # fraction of days for absolute time,
  404. # and in relative units in case of relative time.
  405. #'start_td' : 'START_TD', # The time difference between the start
  406. # time of the sample space time raster
  407. # dataset and the start time of the
  408. # current sample interval or instance.
  409. # The time is measured in days and
  410. # fraction of days for absolute time,
  411. # and in relative units in case of relative time.
  412. #'end_td' : 'END_TD', # The time difference between the
  413. # start time of the sample
  414. # space time raster dataset and the
  415. # end time of the current sample interval.
  416. # The time is measured in days and
  417. # fraction of days for absolute time,
  418. # and in relative units in case of relative time.
  419. # The end_time() will be represented by null() in case of a time instance.
  420. 'start_doy' : 'START_DOY', # Day of year (doy) from the start time [1 - 366]
  421. 'start_dow' : 'START_DOW', # Day of week (dow) from the start time [1 - 7], the start of the week is Monday == 1
  422. 'start_year' : 'START_YEAR', # The year of the start time [0 - 9999]
  423. 'start_month' : 'START_MONTH', # The month of the start time [1 - 12]
  424. 'start_week' : 'START_WEEK', # Week of year of the start time [1 - 54]
  425. 'start_day' : 'START_DAY', # Day of month from the start time [1 - 31]
  426. 'start_hour' : 'START_HOUR', # The hour of the start time [0 - 23]
  427. 'start_minute': 'START_MINUTE', # The minute of the start time [0 - 59]
  428. 'start_second': 'START_SECOND', # The second of the start time [0 - 59]
  429. 'end_doy' : 'END_DOY', # Day of year (doy) from the end time [1 - 366]
  430. 'end_dow' : 'END_DOW', # Day of week (dow) from the end time [1 - 7], the start of the week is Monday == 1
  431. 'end_year' : 'END_YEAR', # The year of the end time [0 - 9999]
  432. 'end_month' : 'END_MONTH', # The month of the end time [1 - 12]
  433. 'end_week' : 'END_WEEK', # Week of year of the end time [1 - 54]
  434. 'end_day' : 'END_DAY', # Day of month from the start time [1 - 31]
  435. 'end_hour' : 'END_HOUR', # The hour of the end time [0 - 23]
  436. 'end_minute' : 'END_MINUTE', # The minute of the end time [0 - 59]
  437. 'end_second' : 'END_SECOND', # The second of the end time [0 - 59]
  438. }
  439. # This is the list of token names.
  440. tokens = (
  441. 'DATETIME',
  442. 'TIME',
  443. 'DATE',
  444. 'INT',
  445. 'FLOAT',
  446. 'LPAREN',
  447. 'RPAREN',
  448. 'COMMA',
  449. 'CEQUALS',
  450. 'EQUALS',
  451. 'UNEQUALS',
  452. 'LOWER',
  453. 'LOWER_EQUALS',
  454. 'GREATER',
  455. 'GREATER_EQUALS',
  456. 'HASH',
  457. 'OR',
  458. 'AND',
  459. 'T_SELECT_OPERATOR',
  460. 'T_HASH_OPERATOR',
  461. 'T_COMP_OPERATOR',
  462. 'T_REL_OPERATOR',
  463. 'T_SELECT',
  464. 'T_NOT_SELECT',
  465. 'NAME',
  466. 'QUOTE',
  467. )
  468. # Build the token list
  469. tokens = tokens + tuple(datetime_functions.values()) \
  470. + tuple(time_functions.values()) \
  471. + tuple(conditional_functions.values())
  472. # Regular expression rules for simple tokens
  473. t_T_SELECT_OPERATOR = r'\{[!]?[:][,]?[a-zA-Z\| ]*([,])?([lrudi]|left|right|union|disjoint|intersect)?\}'
  474. t_T_HASH_OPERATOR = r'\{[#][,]?[a-zA-Z\| ]*([,])?([lrudi]|left|right|union|disjoint|intersect)?\}'
  475. t_T_COMP_OPERATOR = r'\{(\|\||&&)[,][a-zA-Z\| ]*[,]?[\|&]?([,])?([lrudi]|left|right|union|disjoint|intersect)?\}'
  476. t_T_REL_OPERATOR = r'\{([a-zA-Z\| ])+\}'
  477. t_T_SELECT = r':'
  478. t_T_NOT_SELECT = r'!:'
  479. t_LPAREN = r'\('
  480. t_RPAREN = r'\)'
  481. t_COMMA = r','
  482. t_CEQUALS = r'=='
  483. t_EQUALS = r'='
  484. t_UNEQUALS = r'!='
  485. t_LOWER = r'<'
  486. t_LOWER_EQUALS = r'<='
  487. t_GREATER = r'>'
  488. t_GREATER_EQUALS = r'>='
  489. t_HASH = r'\#'
  490. t_OR = r'[\|]'
  491. t_AND = r'[&]'
  492. t_QUOTE = r'[\"\']'
  493. # These are the things that should be ignored.
  494. t_ignore = ' \t'
  495. # Read time string and convert it into a date object
  496. def t_DATETIME(self, t):
  497. r'"\d\d\d\d-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])[ T](0[0-9]|1(0-9)|2[0-4]):(0[0-9]|[1-5][0-9]|60):(0[0-9]|[1-5][0-9]|60)"'
  498. # t.value = int(t.value)
  499. return t
  500. # Read date string and convert it into a date object
  501. def t_DATE(self, t):
  502. r'"\d\d\d\d-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])"'
  503. # t.value = int(t.value)
  504. return t
  505. # Read time string and convert it into a date object
  506. def t_TIME(self, t):
  507. r'"(0[0-9]|1[0-9]|2[0-4]):(0[0-9]|[1-5][0-9]|60):(0[0-9]|[1-5][0-9]|60)"'
  508. # t.value = int(t.value)
  509. return t
  510. # Read in a float. This rule has to be done before the int rule.
  511. def t_FLOAT(self, t):
  512. r'-?\d+\.\d*(e-?\d+)?'
  513. t.value = float(t.value)
  514. return t
  515. # Read in an int.
  516. def t_INT(self, t):
  517. r'-?\d+'
  518. t.value = int(t.value)
  519. return t
  520. # Read in a list of maps.
  521. def t_LIST(self, t):
  522. r'[\[][.]*[\]]'
  523. t.value = list(t.value)
  524. return t
  525. # Ignore comments.
  526. # def t_comment(self, t):
  527. # r'^[#][^\n]*'
  528. # pass
  529. # Track line numbers.
  530. def t_newline(self, t):
  531. r'\n+'
  532. t.lineno += len(t.value)
  533. def t_NAME(self, t):
  534. r'[a-zA-Z_][a-zA-Z_0-9]*'
  535. self.temporal_symbol(t)
  536. return t
  537. # Parse symbols
  538. def temporal_symbol(self, t):
  539. # Check for reserved words
  540. if t.value in TemporalAlgebraLexer.time_functions.keys():
  541. t.type = TemporalAlgebraLexer.time_functions.get(t.value)
  542. elif t.value in TemporalAlgebraLexer.datetime_functions.keys():
  543. t.type = TemporalAlgebraLexer.datetime_functions.get(t.value)
  544. elif t.value in TemporalAlgebraLexer.conditional_functions.keys():
  545. t.type = TemporalAlgebraLexer.conditional_functions.get(t.value)
  546. else:
  547. t.type = 'NAME'
  548. return t
  549. # Handle errors.
  550. def t_error(self, t):
  551. raise SyntaxError("syntax error on line %d near '%s'" %
  552. (t.lineno, t.value))
  553. # Build the lexer
  554. def build(self,**kwargs):
  555. self.lexer = lex.lex(module=self, optimize=False, debug=False, **kwargs)
  556. # Just for testing
  557. def test(self,data):
  558. self.name_list = {}
  559. print(data)
  560. self.lexer.input(data)
  561. while True:
  562. tok = self.lexer.token()
  563. if not tok: break
  564. print tok
  565. ###############################################################################
  566. class GlobalTemporalVar(object):
  567. """ This class handles global temporal variable conditional expressions,
  568. like start_doy() == 3.
  569. The three parts of the statement are stored separately in
  570. tfunc (START_DOY), compop (==) and value (3).
  571. But also boolean values, time differences and relation operators for comparison in
  572. if-statements can be stored in this class.
  573. """
  574. def __init__(self):
  575. self.tfunc = None
  576. self.compop = None
  577. self.value = None
  578. self.boolean = None
  579. self.relationop = None
  580. self.topology = []
  581. self.td = None
  582. def get_type(self):
  583. if self.tfunc != None and self.compop != None and self.value != None:
  584. return("global")
  585. elif self.boolean != None:
  586. return("boolean")
  587. elif self.relationop != None and self.topology != []:
  588. return("operator")
  589. elif self.td != None:
  590. return("timediff")
  591. def get_type_value(self):
  592. typename = self.get_type()
  593. valuelist = []
  594. if typename == "global":
  595. valuelist = [self.tfunc, self.compop, self.value]
  596. elif typename == "operator":
  597. valuelist.append(self.topology)
  598. valuelist.append(self.relationop)
  599. elif typename == "boolean":
  600. valuelist = self.boolean
  601. elif typename == "timediff":
  602. valuelist.append(self.td)
  603. return(valuelist)
  604. def __str__(self):
  605. return str(self.tfunc) + str(self.compop) + str(self.value)
  606. ###############################################################################
  607. class FatalError(Exception):
  608. def __init__(self, msg):
  609. self.value = msg
  610. def __str__(self):
  611. return self.value
  612. ###############################################################################
  613. class TemporalAlgebraParser(object):
  614. """The temporal algebra class"""
  615. # Get the tokens from the lexer class
  616. tokens = TemporalAlgebraLexer.tokens
  617. # Setting equal precedence level for select and hash operations.
  618. precedence = (
  619. ('left', 'T_SELECT_OPERATOR', 'T_SELECT', 'T_NOT_SELECT'), # 1
  620. ('left', 'AND', 'OR', 'T_COMP_OPERATOR'), #2
  621. )
  622. def __init__(self, pid=None, run = True, debug = False, spatial = False,
  623. null = False, register_null = False, nprocs = 1):
  624. self.run = run
  625. self.debug = debug
  626. self.pid = pid
  627. # Intermediate vector map names
  628. self.names = {}
  629. # Count map names
  630. self.spatial = spatial
  631. self.null = null
  632. self.mapset = get_current_mapset()
  633. self.temporaltype = None
  634. self.msgr = get_tgis_message_interface()
  635. self.dbif = SQLDatabaseInterfaceConnection()
  636. self.dbif.connect()
  637. self.register_null = register_null
  638. self.empty_maps = {}
  639. self.m_mremove = pymod.Module('g.remove')
  640. self.m_copy = pymod.Module('g.copy')
  641. self.nprocs = nprocs
  642. self.use_granularity = False
  643. def __del__(self):
  644. if self.dbif.connected:
  645. self.dbif.close()
  646. def setup_common_granularity(self, expression, stdstype = 'strds'):
  647. """Configure the temporal algebra to use the common granularity of all
  648. space time datasets in the expression to generate the map lists.
  649. This function will analyze the expression to detect space time datasets
  650. and computes are common granularity from all granularities.
  651. This granularity is then be used to generate the map lists. Hence, all
  652. maps from all STDS will have equidistant temporal extents. The only meaningful
  653. temporal relation is "equal".
  654. :param expression: The algebra expression to analyze
  655. :return: True if successful, False otherwise
  656. """
  657. # Split the expression to ignore the left part
  658. expression = expression.split("=")[1]
  659. # detect all STDS
  660. l = TemporalAlgebraLexer()
  661. l.build()
  662. l.lexer.input(expression)
  663. self.name_list = []
  664. ignore = False
  665. while True:
  666. tok = l.lexer.token()
  667. if not tok: break
  668. if tok.type == "NAME" and ignore == False:
  669. self.name_list.append(tok.value)
  670. grans = []
  671. ttypes = {}
  672. dbif, connected = init_dbif(self.dbif)
  673. for name in self.name_list:
  674. stds = open_old_stds(name, stdstype, dbif)
  675. # We need valid temporal topology
  676. if stds.check_temporal_topology() is False:
  677. return False
  678. grans.append(stds.get_granularity())
  679. ttypes[stds.get_temporal_type()] = stds.get_temporal_type()
  680. # Only one temporal type is allowed
  681. if len(ttypes) > 1:
  682. return False
  683. # Compute the common granularity
  684. if "absolute" in ttypes.keys():
  685. self.granularity = compute_common_absolute_time_granularity(grans)
  686. else:
  687. self.granularity = compute_common_relative_time_granularity(grans)
  688. self.use_granularity = True
  689. return True
  690. def parse(self, expression, stdstype = 'strds', maptype = 'rast', mapclass = RasterDataset, basename = None, overwrite=False):
  691. self.lexer = TemporalAlgebraLexer()
  692. self.lexer.build()
  693. self.parser = yacc.yacc(module=self, debug=self.debug)
  694. self.overwrite = overwrite
  695. self.count = 0
  696. self.stdstype = stdstype
  697. self.maptype = maptype
  698. self.mapclass = mapclass
  699. self.basename = basename
  700. self.expression = expression
  701. self.parser.parse(expression)
  702. def generate_map_name(self):
  703. """Generate an unique intermediate vector map name
  704. and register it in the objects map list for later removement.
  705. The vector map names are unique between processes. Do not use the
  706. same object for map name generation in multiple threads.
  707. """
  708. self.count += 1
  709. if self.pid != None:
  710. pid = self.pid
  711. else:
  712. pid = os.getpid()
  713. name = "tmp_map_name_%i_%i"%(pid, self.count)
  714. self.names[name] = name
  715. return name
  716. def generate_new_map(self, base_map, bool_op = 'and', copy = True, rename = True):
  717. """Generate a new map using the spatio-temporal extent of the base map
  718. :param base_map: This map is used to create the new map
  719. :param bool_op: The boolean operator specifying the spatial extent
  720. operation (intersection, union, disjoint union)
  721. :param copy: Specifies if the temporal extent of mapB should be
  722. copied to mapA
  723. :param rename: Specifies if the generated map get a random name or get
  724. the id from the base map.
  725. :return: Map object
  726. """
  727. # Generate an intermediate name for the result map list.
  728. name = self.generate_map_name()
  729. # Check for mapset in given stds input.
  730. mapname = name + "@" + self.mapset
  731. # Create new map based on the related map list.
  732. map_new = base_map.get_new_instance(mapname)
  733. # Set initial map extend of new vector map.
  734. self.overlay_map_extent(map_new, base_map, bool_op = bool_op, copy = copy)
  735. if not rename:
  736. name = base_map.get_id()
  737. map_new.set_id(name)
  738. return map_new
  739. def overlay_map_extent(self, mapA, mapB, bool_op = None, temp_op = 'l',
  740. copy = False):
  741. """Compute the spatio-temporal extent of two topological related maps
  742. :param mapA: The first map
  743. :param mapB: The second maps
  744. :param bool_op: The boolean operator specifying the spatial extent
  745. operation (intersection, union, disjoint union)
  746. :param temp_op: The temporal operator specifying the temporal
  747. extent operation (intersection, union, disjoint union, right reference)
  748. Left reference is the default temporal extent behaviour.
  749. :param copy: Specifies if the temporal extent of mapB should be
  750. copied to mapA
  751. :return: 0 if there is no overlay
  752. """
  753. returncode = 1
  754. if copy:
  755. map_extent_temporal = mapB.get_temporal_extent()
  756. map_extent_spatial = mapB.get_spatial_extent()
  757. # Set initial map extend of new vector map.
  758. mapA.set_spatial_extent(map_extent_spatial)
  759. mapA.set_temporal_extent(map_extent_temporal)
  760. if "cmd_list" in dir(mapB):
  761. mapA.cmd_list = mapB.cmd_list
  762. if "condition_value" in dir(mapB):
  763. mapA.condition_value = mapB.condition_value
  764. else:
  765. # Calculate spatial extent for different overlay operations.
  766. if bool_op == 'and':
  767. overlay_ext = mapA.spatial_intersection(mapB)
  768. if overlay_ext != None:
  769. mapA.set_spatial_extent(overlay_ext)
  770. else:
  771. returncode = 0
  772. elif bool_op in ['or', 'xor']:
  773. overlay_ext = mapA.spatial_union(mapB)
  774. if overlay_ext != None:
  775. mapA.set_spatial_extent(overlay_ext)
  776. else:
  777. returncode = 0
  778. elif bool_op == 'disor':
  779. overlay_ext = mapA.spatial_disjoint_union(mapB)
  780. if overlay_ext != None:
  781. mapA.set_spatial_extent(overlay_ext)
  782. else:
  783. returncode = 0
  784. # Calculate temporal extent for different temporal operators.
  785. if temp_op == 'i':
  786. temp_ext = mapA.temporal_intersection(mapB)
  787. if temp_ext != None:
  788. mapA.set_temporal_extent(temp_ext)
  789. else:
  790. returncode = 0
  791. elif temp_op == 'u':
  792. temp_ext = mapA.temporal_union(mapB)
  793. if temp_ext != None:
  794. mapA.set_temporal_extent(temp_ext)
  795. else:
  796. returncode = 0
  797. elif temp_op == 'd':
  798. temp_ext = mapA.temporal_disjoint_union(mapB)
  799. if temp_ext != None:
  800. mapA.set_temporal_extent(temp_ext)
  801. else:
  802. returncode = 0
  803. elif temp_op == 'r':
  804. temp_ext = mapB.get_temporal_extent()
  805. if temp_ext != None:
  806. mapA.set_temporal_extent(temp_ext)
  807. else:
  808. returncode = 0
  809. return(returncode)
  810. def set_temporal_extent_list(self, maplist, topolist = ["EQUAL"], temporal = 'l' ):
  811. """ Change temporal extent of map list based on temporal relations to
  812. other map list and given temporal operator.
  813. :param maplist: List of map objects for which relations has been build
  814. correctely.
  815. :param topolist: List of strings of temporal relations.
  816. :param temporal: The temporal operator specifying the temporal
  817. extent operation (intersection, union, disjoint
  818. union, right reference, left reference).
  819. :return: Map list with specified temporal extent.
  820. """
  821. resultdict = {}
  822. for map_i in maplist:
  823. # Loop over temporal related maps and create overlay modules.
  824. tbrelations = map_i.get_temporal_relations()
  825. # Generate an intermediate map for the result map list.
  826. map_new = self.generate_new_map(base_map=map_i, bool_op = 'and',
  827. copy = True, rename = True)
  828. # Combine temporal and spatial extents of intermediate map with related maps.
  829. for topo in topolist:
  830. if topo in tbrelations.keys():
  831. for map_j in (tbrelations[topo]):
  832. if temporal == 'r':
  833. # Generate an intermediate map for the result map list.
  834. map_new = self.generate_new_map(base_map=map_i, bool_op = 'and',
  835. copy = True, rename = True)
  836. # Create overlayed map extent.
  837. returncode = self.overlay_map_extent(map_new, map_j, 'and', \
  838. temp_op = temporal)
  839. # Stop the loop if no temporal or spatial relationship exist.
  840. if returncode == 0:
  841. break
  842. # Append map to result map list.
  843. elif returncode == 1:
  844. print(map_new.get_id() + " " + str(map_new.get_temporal_extent_as_tuple()))
  845. print(map_new.condition_value)
  846. # print(map_new.cmd_list)
  847. # resultlist.append(map_new)
  848. resultdict[map_new.get_id()] = map_new
  849. # Create r.mapcalc expression string for the operation.
  850. #cmdstring = self.build_command_string(s_expr_a = map_new,
  851. # s_expr_b = map_j,
  852. # operator = function)
  853. # Conditional append of module command.
  854. #map_new.cmd_list = cmdstring
  855. if returncode == 0:
  856. break
  857. # Append map to result map list.
  858. #if returncode == 1:
  859. # resultlist.append(map_new)
  860. # Get sorted map objects as values from result dictionoary.
  861. resultlist = resultdict.values()
  862. resultlist = sorted(resultlist, key = AbstractDatasetComparisonKeyStartTime)
  863. return(resultlist)
  864. ######################### Temporal functions ##############################
  865. def check_stds(self, input, clear = False):
  866. """ Check if input space time dataset exist in database and return its map list.
  867. :param input: Name of space time data set as string or list of maps.
  868. :param clear: Reset the stored conditional values to empty list.
  869. :return: List of maps.
  870. """
  871. if isinstance(input, str):
  872. # Check for mapset in given stds input.
  873. if input.find("@") >= 0:
  874. id_input = input
  875. else:
  876. id_input = input + "@" + self.mapset
  877. # Create empty spacetime dataset.
  878. stds = dataset_factory(self.stdstype, id_input)
  879. # Check for occurence of space time dataset.
  880. if stds.is_in_db(dbif=self.dbif) == False:
  881. raise FatalError(_("Space time %s dataset <%s> not found") %
  882. (stds.get_new_map_instance(None).get_type(), id_input))
  883. else:
  884. # Select temporal dataset entry from database.
  885. stds.select(dbif=self.dbif)
  886. if self.use_granularity:
  887. # We create the maplist out of the map array from none-gap objects
  888. maplist = []
  889. map_array = stds.get_registered_maps_as_objects_by_granularity(gran=self.granularity, dbif=self.dbif)
  890. for entry in map_array:
  891. # Ignore gap objects
  892. if entry[0].get_id() is not None:
  893. maplist.append(entry[0])
  894. print maplist
  895. else:
  896. maplist = stds.get_registered_maps_as_objects(dbif=self.dbif)
  897. # Create map_value as empty list item.
  898. for map_i in maplist:
  899. if "map_value" not in dir(map_i):
  900. map_i.map_value = []
  901. if "condition_value" not in dir(map_i):
  902. map_i.condition_value = []
  903. # Set and check global temporal type variable and map.
  904. if map_i.is_time_absolute() and self.temporaltype == None:
  905. self.temporaltype = 'absolute'
  906. elif map_i.is_time_relative() and self.temporaltype == None:
  907. self.temporaltype = 'relative'
  908. elif map_i.is_time_absolute() and self.temporaltype == 'relative':
  909. self.msgr.fatal(_("Wrong temporal type of space time dataset <%s> \
  910. <%s> time is required") %
  911. (id_input, self.temporaltype))
  912. elif map_i.is_time_relative() and self.temporaltype == 'absolute':
  913. self.msgr.fatal(_("Wrong temporal type of space time dataset <%s> \
  914. <%s> time is required") %
  915. (id_input, self.temporaltype))
  916. elif isinstance(input, self.mapclass):
  917. # Check if the input is a single map and return it as list with one entry.
  918. maplist = [input]
  919. elif isinstance(input, list):
  920. maplist = input
  921. # Create map_value as empty list item.
  922. for map_i in maplist:
  923. if "map_value" not in dir(map_i):
  924. map_i.map_value = []
  925. elif clear:
  926. map_i.map_value = []
  927. if "condition_value" not in dir(map_i):
  928. map_i.condition_value = []
  929. elif clear:
  930. map_i.condition_value = []
  931. else:
  932. self.msgr.fatal(_("Wrong type of input"))
  933. return(maplist)
  934. def get_temporal_topo_list(self, maplistA, maplistB = None, topolist = ["EQUAL"],
  935. assign_val = False, count_map = False, compare_bool = False,
  936. compop = None, aggregate = None):
  937. """Build temporal topology for two space time data sets, copy map objects
  938. for given relation into map list.
  939. :param maplistA: List of maps.
  940. :param maplistB: List of maps.
  941. :param topolist: List of strings of temporal relations.
  942. :param assign_val: Boolean for assigning a boolean map value based on
  943. the map_values from the compared map list by
  944. topological relationships.
  945. :param count_map: Boolean if the number of topological related maps
  946. should be returned.
  947. :param compare_bool: Boolean for comparing boolean map values based on
  948. related map list and compariosn operator.
  949. :param compop: Comparison operator, && or ||.
  950. :param aggregate: Aggregation operator for relation map list, & or |.
  951. :return: List of maps from maplistA that fulfil the topological relationships
  952. to maplistB specified in topolist.
  953. .. code-block:: python
  954. # Example with two lists of maps
  955. >>> import grass.temporal as tgis
  956. >>> tgis.init(True)
  957. >>> l = tgis.TemporalAlgebraParser()
  958. >>> # Create two list of maps with equal time stamps
  959. >>> mapsA = []
  960. >>> mapsB = []
  961. >>> for i in range(10):
  962. ... idA = "a%i@B"%(i)
  963. ... mapA = tgis.RasterDataset(idA)
  964. ... idB = "b%i@B"%(i)
  965. ... mapB = tgis.RasterDataset(idB)
  966. ... check = mapA.set_relative_time(i, i + 1, "months")
  967. ... check = mapB.set_relative_time(i, i + 1, "months")
  968. ... mapsA.append(mapA)
  969. ... mapsB.append(mapB)
  970. >>> resultlist = l.get_temporal_topo_list(mapsA, mapsB, ['EQUAL'])
  971. >>> for map in resultlist:
  972. ... if map.get_equal():
  973. ... relations = map.get_equal()
  974. ... print "Map %s has equal relation to map %s"%(map.get_name(),
  975. ... relations[0].get_name())
  976. Map a0 has equal relation to map b0
  977. Map a1 has equal relation to map b1
  978. Map a2 has equal relation to map b2
  979. Map a3 has equal relation to map b3
  980. Map a4 has equal relation to map b4
  981. Map a5 has equal relation to map b5
  982. Map a6 has equal relation to map b6
  983. Map a7 has equal relation to map b7
  984. Map a8 has equal relation to map b8
  985. Map a9 has equal relation to map b9
  986. >>> resultlist = l.get_temporal_topo_list(mapsA, mapsB, ['DURING'])
  987. >>> print(resultlist)
  988. []
  989. >>> # Create two list of maps with equal time stamps
  990. >>> mapsA = []
  991. >>> mapsB = []
  992. >>> for i in range(10):
  993. ... idA = "a%i@B"%(i)
  994. ... mapA = tgis.RasterDataset(idA)
  995. ... idB = "b%i@B"%(i)
  996. ... mapB = tgis.RasterDataset(idB)
  997. ... check = mapA.set_relative_time(i, i + 1, "months")
  998. ... check = mapB.set_relative_time(i, i + 2, "months")
  999. ... mapsA.append(mapA)
  1000. ... mapsB.append(mapB)
  1001. >>> resultlist = l.get_temporal_topo_list(mapsA, mapsB, ['starts','during'])
  1002. >>> for map in resultlist:
  1003. ... if map.get_starts():
  1004. ... relations = map.get_starts()
  1005. ... print "Map %s has start relation to map %s"%(map.get_name(),
  1006. ... relations[0].get_name())
  1007. Map a0 has start relation to map b0
  1008. Map a1 has start relation to map b1
  1009. Map a2 has start relation to map b2
  1010. Map a3 has start relation to map b3
  1011. Map a4 has start relation to map b4
  1012. Map a5 has start relation to map b5
  1013. Map a6 has start relation to map b6
  1014. Map a7 has start relation to map b7
  1015. Map a8 has start relation to map b8
  1016. Map a9 has start relation to map b9
  1017. >>> for map in resultlist:
  1018. ... if map.get_during():
  1019. ... relations = map.get_during()
  1020. ... print "Map %s has during relation to map %s"%(map.get_name(),
  1021. ... relations[0].get_name())
  1022. Map a0 has during relation to map b0
  1023. Map a1 has during relation to map b0
  1024. Map a2 has during relation to map b1
  1025. Map a3 has during relation to map b2
  1026. Map a4 has during relation to map b3
  1027. Map a5 has during relation to map b4
  1028. Map a6 has during relation to map b5
  1029. Map a7 has during relation to map b6
  1030. Map a8 has during relation to map b7
  1031. Map a9 has during relation to map b8
  1032. >>> # Create two list of maps with equal time stamps and map_value method.
  1033. >>> mapsA = []
  1034. >>> mapsB = []
  1035. >>> for i in range(10):
  1036. ... idA = "a%i@B"%(i)
  1037. ... mapA = tgis.RasterDataset(idA)
  1038. ... idB = "b%i@B"%(i)
  1039. ... mapB = tgis.RasterDataset(idB)
  1040. ... check = mapA.set_relative_time(i, i + 1, "months")
  1041. ... check = mapB.set_relative_time(i, i + 1, "months")
  1042. ... mapB.map_value = True
  1043. ... mapsA.append(mapA)
  1044. ... mapsB.append(mapB)
  1045. >>> # Create two list of maps with equal time stamps
  1046. >>> mapsA = []
  1047. >>> mapsB = []
  1048. >>> for i in range(10):
  1049. ... idA = "a%i@B"%(i)
  1050. ... mapA = tgis.RasterDataset(idA)
  1051. ... mapA.map_value = True
  1052. ... idB = "b%i@B"%(i)
  1053. ... mapB = tgis.RasterDataset(idB)
  1054. ... mapB.map_value = False
  1055. ... check = mapA.set_absolute_time(datetime(2000,1,i+1),
  1056. ... datetime(2000,1,i + 2))
  1057. ... check = mapB.set_absolute_time(datetime(2000,1,i+6),
  1058. ... datetime(2000,1,i + 7))
  1059. ... mapsA.append(mapA)
  1060. ... mapsB.append(mapB)
  1061. >>> resultlist = l.get_temporal_topo_list(mapsA, mapsB)
  1062. >>> for map in resultlist:
  1063. ... print(map.get_id())
  1064. a5@B
  1065. a6@B
  1066. a7@B
  1067. a8@B
  1068. a9@B
  1069. >>> resultlist = l.get_temporal_topo_list(mapsA, mapsB, ['during'])
  1070. >>> for map in resultlist:
  1071. ... print(map.get_id())
  1072. """
  1073. topologylist = ["EQUAL", "FOLLOWS", "PRECEDES", "OVERLAPS", "OVERLAPPED", \
  1074. "DURING", "STARTS", "FINISHES", "CONTAINS", "STARTED", \
  1075. "FINISHED"]
  1076. complementdict = {"EQUAL": "EQUAL", "FOLLOWS" : "PRECEDES",
  1077. "PRECEDES" : "FOLLOWS", "OVERLAPS" : "OVERLAPPED",
  1078. "OVERLAPPED" : "OVERLAPS", "DURING" : "CONTAINS",
  1079. "CONTAINS" : "DURING", "STARTS" : "STARTED",
  1080. "STARTED" : "STARTS", "FINISHES" : "FINISHED",
  1081. "FINISHED" : "FINISHES"}
  1082. resultdict = {}
  1083. # Check if given temporal relation are valid.
  1084. for topo in topolist:
  1085. if topo.upper() not in topologylist:
  1086. raise SyntaxError("Unpermitted temporal relation name '" + topo + "'")
  1087. # Create temporal topology for maplistA to maplistB.
  1088. tb = SpatioTemporalTopologyBuilder()
  1089. # Dictionary with different spatial variables used for topology builder.
  1090. spatialdict = {'strds' : '2D', 'stvds' : '2D', 'str3ds' : '3D'}
  1091. # Build spatial temporal topology
  1092. if self.spatial:
  1093. tb.build(maplistA, maplistB, spatial = spatialdict[self.stdstype])
  1094. else:
  1095. tb.build(maplistA, maplistB)
  1096. # Iterate through maps in maplistA and search for relationships given
  1097. # in topolist.
  1098. for map_i in maplistA:
  1099. tbrelations = map_i.get_temporal_relations()
  1100. if assign_val:
  1101. self.assign_bool_value(map_i, tbrelations, topolist)
  1102. elif compare_bool:
  1103. self.compare_bool_value(map_i, tbrelations, compop, aggregate, topolist)
  1104. for topo in topolist:
  1105. if topo.upper() in tbrelations.keys():
  1106. if count_map:
  1107. relationmaplist = tbrelations[topo.upper()]
  1108. gvar = GlobalTemporalVar()
  1109. gvar.td = len(relationmaplist)
  1110. if "map_value" in dir(map_i):
  1111. map_i.map_value.append(gvar)
  1112. else:
  1113. map_i.map_value = gvar
  1114. resultdict[map_i.get_id()] = map_i
  1115. resultlist = resultdict.values()
  1116. # Sort list of maps chronological.
  1117. resultlist = sorted(resultlist, key = AbstractDatasetComparisonKeyStartTime)
  1118. return(resultlist)
  1119. def assign_bool_value(self, map_i, tbrelations, topolist = ["EQUAL"]):
  1120. """ Function to assign boolean map value based on the map_values from the
  1121. compared map list by topological relationships.
  1122. :param map_i: Map object with temporal extent.
  1123. :param tbrelations: List of temporal relation to map_i.
  1124. :param topolist: List of strings for given temporal relations.
  1125. :return: Map object with conditional value that has been assigned by
  1126. relation maps that fulfil the topological relationships to
  1127. maplistB specified in topolist.
  1128. """
  1129. condition_value_list = []
  1130. for topo in topolist:
  1131. if topo.upper() in tbrelations.keys():
  1132. #relationmaplist = tbrelations[complementdict[topo.upper()]]
  1133. relationmaplist = tbrelations[topo.upper()]
  1134. for relationmap in relationmaplist:
  1135. for boolean in relationmap.condition_value:
  1136. if isinstance(boolean, bool):
  1137. condition_value_list.append(boolean)
  1138. print(str(relationmap.get_temporal_extent_as_tuple()) + str(boolean))
  1139. if all(condition_value_list):
  1140. resultbool = True
  1141. else:
  1142. resultbool = False
  1143. map_i.condition_value = [resultbool]
  1144. return(resultbool)
  1145. def compare_bool_value(self, map_i, tbrelations, compop, aggregate, topolist = ["EQUAL"]):
  1146. """ Function to evaluate two map lists with boolean values by boolean
  1147. comparison operator.
  1148. :param map_i: Map object with temporal extent.
  1149. :param tbrelations: List of temporal relation to map_i.
  1150. :param topolist: List of strings for given temporal relations.
  1151. :param compop: Comparison operator, && or ||.
  1152. :param aggregate: Aggregation operator for relation map list, & or |.
  1153. :return: Map object with conditional value that has been evaluated by
  1154. comparison operators.
  1155. """
  1156. # Build conditional list with elements from related maps and given relation operator.
  1157. leftbool = map_i.condition_value[0]
  1158. condition_value_list = [leftbool]
  1159. count = 0
  1160. for topo in topolist:
  1161. if topo.upper() in tbrelations.keys():
  1162. relationmaplist = tbrelations[topo.upper()]
  1163. if count == 0:
  1164. condition_value_list.append(compop[0])
  1165. condition_value_list.append('(')
  1166. for relationmap in relationmaplist:
  1167. for boolean in relationmap.condition_value:
  1168. if isinstance(boolean, bool):
  1169. if count > 0:
  1170. condition_value_list.append(aggregate)
  1171. condition_value_list.append(boolean)
  1172. count = count + 1
  1173. if count > 0:
  1174. condition_value_list.append(')')
  1175. # Convert conditional list to concatenated string and evaluate booleans.
  1176. condition_value_str = ''.join(map(str, condition_value_list))
  1177. print(condition_value_str)
  1178. resultbool = eval(condition_value_str)
  1179. print(resultbool)
  1180. # Add boolean value to result list.
  1181. map_i.condition_value = [resultbool]
  1182. return(resultbool)
  1183. def eval_toperator(self, operator, optype = 'relation'):
  1184. """This function evaluates a string containing temporal operations.
  1185. :param operator: String of temporal operations, e.g. {!=,equal|during,l}.
  1186. :param optype: String to define operator type.
  1187. :return :List of temporal relations (equal, during), the given function
  1188. (!:) and the interval/instances (l).
  1189. .. code-block:: python
  1190. >>> import grass.temporal as tgis
  1191. >>> tgis.init()
  1192. >>> p = tgis.TemporalOperatorParser()
  1193. >>> operator = "{+, during}"
  1194. >>> p.parse(operator, optype = 'raster')
  1195. >>> print(p.relations, p.temporal, p.function)
  1196. (['during'], 'l', '+')
  1197. """
  1198. p = TemporalOperatorParser()
  1199. p.parse(operator, optype)
  1200. p.relations = [rel.upper() for rel in p.relations]
  1201. return(p.relations, p.temporal, p.function, p.aggregate)
  1202. def perform_temporal_selection(self, maplistA, maplistB, topolist = ["EQUAL"],
  1203. inverse = False, assign_val = False):
  1204. """This function performs temporal selection operation.
  1205. :param maplistA: List of maps representing the left side of a temporal
  1206. expression.
  1207. :param maplistB: List of maps representing the right side of a temporal
  1208. expression.
  1209. :param topolist: List of strings of temporal relations.
  1210. :param inverse: Boolean value that specifies if the selection should be
  1211. inverted.
  1212. :param assign_val: Boolean for assigning a boolean map value based on
  1213. the map_values from the compared map list by
  1214. topological relationships.
  1215. :return: List of selected maps from maplistA.
  1216. .. code-block:: python
  1217. >>> import grass.temporal as tgis
  1218. >>> tgis.init()
  1219. >>> l = tgis.TemporalAlgebraParser()
  1220. >>> # Example with two lists of maps
  1221. >>> # Create two list of maps with equal time stamps
  1222. >>> mapsA = []
  1223. >>> mapsB = []
  1224. >>> for i in range(10):
  1225. ... idA = "a%i@B"%(i)
  1226. ... mapA = tgis.RasterDataset(idA)
  1227. ... idB = "b%i@B"%(i)
  1228. ... mapB = tgis.RasterDataset(idB)
  1229. ... check = mapA.set_relative_time(i, i + 1, "months")
  1230. ... check = mapB.set_relative_time(i + 5, i + 6, "months")
  1231. ... mapsA.append(mapA)
  1232. ... mapsB.append(mapB)
  1233. >>> resultlist = l.perform_temporal_selection(mapsA, mapsB, ['EQUAL'],
  1234. ... False)
  1235. >>> for map in resultlist:
  1236. ... if map.get_equal():
  1237. ... relations = map.get_equal()
  1238. ... print "Map %s has equal relation to map %s"%(map.get_name(),
  1239. ... relations[0].get_name())
  1240. Map a5 has equal relation to map b0
  1241. Map a6 has equal relation to map b1
  1242. Map a7 has equal relation to map b2
  1243. Map a8 has equal relation to map b3
  1244. Map a9 has equal relation to map b4
  1245. >>> resultlist = l.perform_temporal_selection(mapsA, mapsB, ['EQUAL'],
  1246. ... True)
  1247. >>> for map in resultlist:
  1248. ... if not map.get_equal():
  1249. ... print "Map %s has no equal relation to mapset mapsB"%(map.get_name())
  1250. Map a0 has no equal relation to mapset mapsB
  1251. Map a1 has no equal relation to mapset mapsB
  1252. Map a2 has no equal relation to mapset mapsB
  1253. Map a3 has no equal relation to mapset mapsB
  1254. Map a4 has no equal relation to mapset mapsB
  1255. """
  1256. if not inverse:
  1257. topolist = self.get_temporal_topo_list(maplistA, maplistB, topolist,
  1258. assign_val = assign_val)
  1259. resultlist = topolist
  1260. else:
  1261. topolist = self.get_temporal_topo_list(maplistA, maplistB, topolist,
  1262. assign_val = assign_val)
  1263. resultlist = []
  1264. for map_i in maplistA:
  1265. if map_i not in topolist:
  1266. resultlist.append(map_i)
  1267. #if assign_val:
  1268. # if "condition_value" in dir(map_i):
  1269. # map_i.condition_value.append(False)
  1270. # Sort list of maps chronological.
  1271. resultlist = sorted(resultlist, key = AbstractDatasetComparisonKeyStartTime)
  1272. return(resultlist)
  1273. def set_granularity(self, maplistA, maplistB, toperator = 'l', topolist = ["EQUAL"]):
  1274. """This function sets the temporal extends of a list of maps based on
  1275. another map list.
  1276. :param maplistB: List of maps.
  1277. :param maplistB: List of maps.
  1278. :param toperator: String containing the temporal operator: l, r, d, i, u.
  1279. :param topolist: List of topological relations.
  1280. :return: List of maps with the new temporal extends.
  1281. .. code-block:: python
  1282. >>> import grass.temporal as tgis
  1283. >>> tgis.init()
  1284. >>> p = tgis.TemporalAlgebraParser()
  1285. >>> # Create two list of maps with equal time stamps
  1286. >>> mapsA = []
  1287. >>> mapsB = []
  1288. >>> for i in range(10):
  1289. ... idA = "a%i@B"%(i)
  1290. ... mapA = tgis.RasterDataset(idA)
  1291. ... idB = "b%i@B"%(i)
  1292. ... mapB = tgis.RasterDataset(idB)
  1293. ... check = mapA.set_relative_time(i, i + 1, "months")
  1294. ... check = mapB.set_relative_time(i*2, i*2 + 2, "months")
  1295. ... mapsA.append(mapA)
  1296. ... mapsB.append(mapB)
  1297. >>> resultlist = p.set_granularity(mapsA, mapsB, toperator = "u", topolist = ["during"])
  1298. >>> for map in resultlist:
  1299. ... start,end,unit = map.get_relative_time()
  1300. ... print(map.get_id() + ' - start: ' + str(start) + ' end: ' + str(end))
  1301. a1@B - start: 0 end: 2
  1302. a0@B - start: 0 end: 2
  1303. a3@B - start: 2 end: 4
  1304. a2@B - start: 2 end: 4
  1305. a5@B - start: 4 end: 6
  1306. a4@B - start: 4 end: 6
  1307. a7@B - start: 6 end: 8
  1308. a6@B - start: 6 end: 8
  1309. a9@B - start: 8 end: 10
  1310. a8@B - start: 8 end: 10
  1311. """
  1312. topologylist = ["EQUAL", "FOLLOWS", "PRECEDES", "OVERLAPS", "OVERLAPPED", \
  1313. "DURING", "STARTS", "FINISHES", "CONTAINS", "STARTED", \
  1314. "FINISHED"]
  1315. for topo in topolist:
  1316. if topo.upper() not in topologylist:
  1317. raise SyntaxError("Unpermitted temporal relation name '" + topo + "'")
  1318. # Create temporal topology for maplistA to maplistB.
  1319. tb = SpatioTemporalTopologyBuilder()
  1320. # Dictionary with different spatial variables used for topology builder.
  1321. spatialdict = {'strds' : '2D', 'stvds' : '2D', 'str3ds' : '3D'}
  1322. # Build spatial temporal topology for maplistB to maplistB.
  1323. if self.spatial:
  1324. tb.build(maplistA, maplistB, spatial = spatialdict[self.stdstype])
  1325. else:
  1326. tb.build(maplistA, maplistB)
  1327. resultdict = {}
  1328. # Iterate through maps in maplistA and search for relationships given
  1329. # in topolist.
  1330. for map_i in maplistA:
  1331. tbrelations = map_i.get_temporal_relations()
  1332. map_extent = map_i.get_temporal_extent()
  1333. map_start = map_extent.get_start_time()
  1334. map_end = map_extent.get_end_time()
  1335. unchanged = True
  1336. for topo in topolist:
  1337. if topo.upper() in tbrelations.keys():
  1338. relationmaplist = tbrelations[topo.upper()]
  1339. for relationmap in relationmaplist:
  1340. newextent = None
  1341. if toperator == "i":
  1342. newextent = map_i.temporal_intersection(relationmap)
  1343. elif toperator == "u":
  1344. newextent = map_i.temporal_union(relationmap)
  1345. elif toperator == "d":
  1346. newextent = map_i.temporal_disjoint_union(relationmap)
  1347. elif toperator == "l":
  1348. newextent = map_i.get_temporal_extent()
  1349. elif toperator == "r":
  1350. newextent = relationmap.get_temporal_extent()
  1351. if newextent != None:
  1352. start = newextent.get_start_time()
  1353. end = newextent.get_end_time()
  1354. #print(map_i.get_id() + ' - start: ' + str(start) + ' end: ' + str(end))
  1355. # Track changes in temporal extents of maps.
  1356. if map_start != start or map_end != end :
  1357. unchanged = False
  1358. if map_i.is_time_absolute():
  1359. map_i.set_absolute_time(start, end)
  1360. else:
  1361. relunit = map_i.get_relative_time_unit()
  1362. map_i.set_relative_time(int(start), int(end), relunit)
  1363. resultdict[map_i.get_id()] = map_i
  1364. else:
  1365. print('Topologic relation: ' + topo.upper() + ' not found.')
  1366. resultdict[map_i.get_id()] = map_i
  1367. if unchanged == True:
  1368. print('Leave temporal extend of result map: ' + map_i.get_map_id() + ' unchanged.')
  1369. resultlist = resultdict.values()
  1370. # Sort list of maps chronological.
  1371. resultlist = sorted(resultlist, key = AbstractDatasetComparisonKeyStartTime)
  1372. # Get relations to maplistB per map in A.
  1373. # Loop over all relations from list
  1374. # temporal extent = map.temporal_intersection(map)
  1375. # if temporal extend is None = delete map.
  1376. return(resultlist)
  1377. def get_temporal_func_dict(self, map):
  1378. """ This function creates a dictionary containing temporal functions for a
  1379. map dataset with time stamp.
  1380. :param map: Map object with time stamps.
  1381. :return: Dictionary with temporal functions for given input map.
  1382. .. code-block:: python
  1383. >>> import grass.temporal as tgis
  1384. >>> import datetime
  1385. >>> tgis.init()
  1386. >>> l = tgis.TemporalAlgebraParser()
  1387. >>> # Example with one list of maps
  1388. >>> # Create one list of maps with equal time stamps
  1389. >>> for i in range(1):
  1390. ... idA = "a%i@B"%(i)
  1391. ... mapA = tgis.RasterDataset(idA)
  1392. ... check = mapA.set_absolute_time(datetime.datetime(2000,1,1),
  1393. ... datetime.datetime(2000,10,1))
  1394. ... tfuncdict = l.get_temporal_func_dict(mapA)
  1395. >>> print(tfuncdict["START_YEAR"])
  1396. 2000
  1397. >>> print(tfuncdict["START_TIME"])
  1398. 00:00:00
  1399. >>> print(tfuncdict["START_DATE"])
  1400. 2000-01-01
  1401. >>> print(tfuncdict["START_DATETIME"])
  1402. 2000-01-01 00:00:00
  1403. """
  1404. tvardict = {"START_DOY" : None, "START_DOW" : None, "START_YEAR" : None,
  1405. "START_MONTH" : None, "START_WEEK" : None, "START_DAY" : None,
  1406. "START_HOUR" : None, "START_MINUTE" : None, "START_SECOND" : None,
  1407. "END_DOY" : None, "END_DOW" : None, "END_YEAR" : None,
  1408. "END_MONTH" : None, "END_WEEK" : None, "END_DAY" : None,
  1409. "END_HOUR" : None, "END_MINUTE" : None, "END_SECOND" : None,
  1410. "START_DATE" : None, "START_DATETIME" : None, "START_TIME" : None,
  1411. "END_DATE" : None, "END_DATETIME" : None, "END_TIME" : None}
  1412. # Compute temporal function only for maps with absolute time reference.
  1413. if map.is_time_absolute:
  1414. # Get datetime of map.
  1415. start, end = map.get_absolute_time()
  1416. # Compute DOY via time deltas.
  1417. yearstart = datetime(start.year, 1, 1)
  1418. yearend = datetime(end.year, 1, 1)
  1419. deltastart = start - yearstart
  1420. deltaend = end - yearend
  1421. # Evaluate datetime objects and fill in into dict.
  1422. tvardict["START_DOY"] = deltastart.days + 1
  1423. tvardict["START_DOW"] = start.isoweekday()
  1424. tvardict["START_YEAR"] = start.year
  1425. tvardict["START_MONTH"] = start.month
  1426. tvardict["START_WEEK"] = start.isocalendar()[1]
  1427. tvardict["START_DAY"] = start.day
  1428. tvardict["START_HOUR"] = start.hour
  1429. tvardict["START_MINUTE"] = start.minute
  1430. tvardict["START_SECOND"] = start.second
  1431. tvardict["END_DOY"] = deltaend.days + 1
  1432. tvardict["END_DOW"] = end.isoweekday()
  1433. tvardict["END_YEAR"] = end.year
  1434. tvardict["END_MONTH"] = end.month
  1435. tvardict["END_WEEK"] = end.isocalendar()[1]
  1436. tvardict["END_DAY"] = end.day
  1437. tvardict["END_HOUR"] = end.hour
  1438. tvardict["END_MINUTE"] = end.minute
  1439. tvardict["END_SECOND"] = end.second
  1440. tvardict["START_DATE"] = start.date()
  1441. tvardict["START_DATETIME"] = start
  1442. tvardict["START_TIME"] = start.time()
  1443. tvardict["END_DATE"] = end.date()
  1444. tvardict["END_DATETIME"] = end
  1445. tvardict["END_TIME"] = end.time()
  1446. if not map.is_time_absolute:
  1447. tvardict["START_DATE"] = start.date()
  1448. tvardict["START_DATETIME"] = start
  1449. tvardict["START_TIME"] = start.time()
  1450. tvardict["END_DATE"] = end.date()
  1451. tvardict["END_DATETIME"] = end
  1452. tvardict["END_TIME"] = end.time()
  1453. #core.fatal(_("The temporal functions for map <%s> only supported for absolute"\
  1454. # "time." % (str(map.get_id()))))
  1455. return(tvardict)
  1456. def eval_datetime_str(self, tfuncval, comp, value):
  1457. # Evaluate date object comparison expression.
  1458. if comp == "<":
  1459. boolname = eval(str(tfuncval < value))
  1460. elif comp == ">":
  1461. boolname = eval(str(tfuncval > value))
  1462. elif comp == "==":
  1463. boolname = eval(str(tfuncval == value))
  1464. elif comp == "<=":
  1465. boolname = eval(str(tfuncval <= value))
  1466. elif comp == ">=":
  1467. boolname = eval(str(tfuncval >= value))
  1468. elif comp == "!=":
  1469. boolname = eval(str(tfuncval != value))
  1470. return(boolname)
  1471. def eval_global_var(self, gvar, maplist):
  1472. """ This function evaluates a global variable expression for a map list.
  1473. For example: start_day() > 5 , end_month() == 2.
  1474. :param gvar: Object of type GlobalTemporalVar containing temporal.
  1475. :param maplist: List of map objects.
  1476. :return: List of maps from maplist with added conditional boolean values.
  1477. """
  1478. boollist = []
  1479. # Loop over maps of input map list.
  1480. for map_i in maplist:
  1481. # Get dictionary with temporal variables for the map.
  1482. tfuncdict = self.get_temporal_func_dict(map_i)
  1483. # Get value from global variable.
  1484. value = gvar.value
  1485. # Get comparison operator from global variable, like <, >, <=, >=, ==, !=
  1486. comp_op = gvar.compop
  1487. # Get temporal function name for global variable.
  1488. tfunc = gvar.tfunc.upper()
  1489. # Get value for function name from dictionary.
  1490. tfuncval = tfuncdict[tfunc]
  1491. # Check if value has to be transfered to datetime object for comparison.
  1492. if tfunc in ["START_DATE", "END_DATE"]:
  1493. timeobj = datetime.strptime(value.replace("\"",""), '%Y-%m-%d')
  1494. value = timeobj.date()
  1495. boolname = self.eval_datetime_str(tfuncval, comp_op, value)
  1496. elif tfunc in ["START_TIME", "END_TIME"]:
  1497. timeobj = datetime.strptime(value.replace("\"",""), '%H:%M:%S')
  1498. value = timeobj.time()
  1499. boolname = self.eval_datetime_str(tfuncval, comp_op, value)
  1500. elif tfunc in ["START_DATETIME", "END_DATETIME"]:
  1501. timeobj = datetime.strptime(value.replace("\"",""), '%Y-%m-%d %H:%M:%S')
  1502. value = timeobj
  1503. boolname = self.eval_datetime_str(tfuncval, comp_op, value)
  1504. else:
  1505. boolname = eval(str(tfuncval) + comp_op + str(value))
  1506. # Add conditional boolean value to the map.
  1507. if "condition_value" in dir(map_i):
  1508. map_i.condition_value.append(boolname)
  1509. else:
  1510. map_i.condition_value = boolname
  1511. return(maplist)
  1512. def eval_map_list(self, maplist ,thenlist, topolist = ["EQUAL"]):
  1513. """ This function transfers boolean values from temporal expression
  1514. from one map list to another by their topology. These boolean
  1515. values are added to the maps as condition_value.
  1516. :param maplist: List of map objects containing boolean map values.
  1517. :param thenlist: List of map objects where the boolean values
  1518. should be added.
  1519. :return: List of maps from thenlist with added conditional boolean values.
  1520. """
  1521. # Get topology of then statement map list in relation to the other maplist
  1522. # and assign boolean values of the maplist to the thenlist.
  1523. containlist = self.perform_temporal_selection(thenlist, maplist,
  1524. assign_val = True,
  1525. topolist = topolist)
  1526. # Inverse selection of maps from thenlist and assigning False values.
  1527. #excludelist = self.perform_temporal_selection(thenlist, maplist,
  1528. # assign_val = True,
  1529. # inverse = True,
  1530. # topolist = topolist)
  1531. # Combining the selection and inverse selection list.
  1532. resultlist = containlist# + excludelist
  1533. return(resultlist)
  1534. def build_condition_list(self, tvarexpr, thenlist, topolist = ["EQUAL"]):
  1535. """ This function evaluates temporal variable expressions of a conditional
  1536. expression in two steps.
  1537. At first it combines stepwise the single conditions by their relations with LALR.
  1538. In this prossess sub condition map lists will be created which will include
  1539. information of the underlying single conditions. Important: The temporal
  1540. relations between conditions are evaluated by implicit aggregation.
  1541. In the second step the aggregated condition map list will be compared with the
  1542. map list of conclusion statements by the given temporal relation.
  1543. The result is writen as 'condition_value' attribute to the resulting map objects.
  1544. These attribute consists of boolean expressions and operators which can be
  1545. evaluated with the eval_condition_list function.
  1546. [True, '||', False, '&&', True]
  1547. For example: td(A) == 1 && start_day() > 5 --> [True || False]
  1548. (for one map.condition_value in a then map list)
  1549. :param tvarexpr List of GlobalTemporalVar objects and map lists.
  1550. The list is constructed by the TemporalAlgebraParser
  1551. in order of expression evaluation in the parser.
  1552. :param thenlist Map list object of the conclusion statement.
  1553. It will be compared and evaluated by the conditions.
  1554. :param topolist List of temporal relations between the conditions and the
  1555. conclusions.
  1556. :return: Map list with conditional values for all temporal expressions.
  1557. """
  1558. # Evaluate the temporal variable expression and compute the temporal combination
  1559. # of conditions.
  1560. # Check if the input expression is a valid single global variable.
  1561. if isinstance(tvarexpr, GlobalTemporalVar) and tvarexpr.get_type() == "global" :
  1562. # Use method eval_global_var to evaluate expression.
  1563. resultlist = self.eval_global_var(tvarexpr, thenlist)
  1564. # Check if a given list is a list of maps.
  1565. elif all([issubclass(type(ele), AbstractMapDataset) for ele in tvarexpr]):
  1566. # Use method eval_map_list to evaluate map_list in comparison to thenlist.
  1567. resultlist = self.eval_map_list(tvarexpr, thenlist, topolist)
  1568. elif len(tvarexpr) % 2 != 0:
  1569. # Define variables for map list comparisons.
  1570. left_obj = []
  1571. operator = []
  1572. right_obj =[]
  1573. count = 0
  1574. #self.msgr.fatal("Condition list is not complete. Elements missing")
  1575. for iter in range(len(tvarexpr)):
  1576. expr = tvarexpr[iter]
  1577. operator = tvarexpr[iter +1]
  1578. relexpr = tvarexpr[iter +2]
  1579. if all([issubclass(type(ele), list) for ele in [expr, relexpr]]):
  1580. resultlist = self.get_temporal_topo_list(expr, relexpr)
  1581. # Loop through the list, search for map lists or global variables.
  1582. for expr in tvarexpr:
  1583. if isinstance(expr, list):
  1584. if all([issubclass(type(ele), AbstractMapDataset) for ele in expr]):
  1585. # Use method eval_map_list to evaluate map_list
  1586. resultlist = self.eval_map_list(expr, thenlist, topolist)
  1587. else:
  1588. # Recursive function call to look into nested list elements.
  1589. self.build_condition_list(expr, thenlist)
  1590. elif isinstance(expr, GlobalTemporalVar):
  1591. # Use according functions for different global variable types.
  1592. if expr.get_type() == "operator":
  1593. if all(["condition_value" in dir(map_i) for map_i in thenlist]):
  1594. # Add operator string to the condition list.
  1595. [map_i.condition_value.extend(expr.get_type_value()) for map_i in thenlist]
  1596. if expr.get_type() == "global":
  1597. # Use method eval_global_var to evaluate expression.
  1598. resultlist = self.eval_global_var(expr, thenlist)
  1599. # Sort resulting list of maps chronological.
  1600. resultlist = sorted(resultlist, key = AbstractDatasetComparisonKeyStartTime)
  1601. return(resultlist)
  1602. def eval_condition_list(self, maplist, inverse = False):
  1603. """ This function evaluates conditional values of a map list.
  1604. A recursive function is used to evaluate comparison statements
  1605. from left to right in the given conditional list.
  1606. For example: [True, '||', False, '&&', True] -> True
  1607. [True, '||', False, '&&', False] -> False
  1608. [True, '&&', False, '&&', True] -> False
  1609. [False, '||', True, '||', False] -> True
  1610. [False, '&&', True, '&&', True] -> False
  1611. [True, '&&', True, '&&', True] -> True
  1612. [True, '&&', True] -> True
  1613. [True, '&&', False] -> False
  1614. [False, '||', True] -> True
  1615. :param tvarexpr: List of GlobalTemporalVar objects and map lists.
  1616. The list is constructed by the TemporalAlgebraParser
  1617. in order of expression evaluation in the parser.
  1618. :return: Map list with conditional values for all temporal expressions.
  1619. """
  1620. def recurse_compare(conditionlist):
  1621. for ele in conditionlist:
  1622. if ele == '||':
  1623. ele_index = conditionlist.index(ele)
  1624. topolist = conditionlist.pop(ele_index -1)
  1625. right = conditionlist.pop(ele_index)
  1626. left = conditionlist.pop(ele_index - 2)
  1627. if any([left, right]):
  1628. result = True
  1629. else:
  1630. result = False
  1631. conditionlist[ele_index - 2] = result
  1632. recurse_compare(conditionlist)
  1633. if ele == '&&':
  1634. ele_index = conditionlist.index(ele)
  1635. topolist = conditionlist.pop(ele_index -1)
  1636. right = conditionlist.pop(ele_index)
  1637. left = conditionlist.pop(ele_index - 2)
  1638. if all([left, right]):
  1639. result = True
  1640. else:
  1641. result = False
  1642. conditionlist[ele_index - 2] = result
  1643. recurse_compare(conditionlist)
  1644. resultlist = conditionlist
  1645. return(resultlist)
  1646. resultlist = []
  1647. inverselist = []
  1648. # Loop through map list and evaluate conditional values.
  1649. for map_i in maplist:
  1650. if "condition_value" in dir(map_i):
  1651. # Get condition values from map object.
  1652. conditionlist = map_i.condition_value
  1653. # Evaluate conditions in list with recursive function.
  1654. resultbool = recurse_compare(conditionlist)
  1655. # Set conditional value of map to resulting boolean.
  1656. map_i.condition_value = resultbool
  1657. # Add all maps that fulfill the conditions to result list.
  1658. if resultbool[0]:
  1659. resultlist.append(map_i)
  1660. print(map_i.get_map_id() + ' ' + str(map_i.condition_value))
  1661. else:
  1662. inverselist.append(map_i)
  1663. if inverse:
  1664. return(inverselist)
  1665. else:
  1666. return(resultlist)
  1667. ###########################################################################
  1668. def p_statement_assign(self, t):
  1669. # The expression should always return a list of maps.
  1670. """
  1671. statement : stds EQUALS expr
  1672. """
  1673. if self.run:
  1674. if isinstance(t[3], list):
  1675. num = len(t[3])
  1676. count = 0
  1677. changeflag = False
  1678. register_list = []
  1679. if num > 0:
  1680. for map_i in t[3]:
  1681. # Test if temporal extents have been changed by temporal
  1682. # relation oeprators (&|+).
  1683. map_i_extent = map_i.get_temporal_extent_as_tuple()
  1684. map_test = map_i.get_new_instance(map_i.get_id())
  1685. map_test.select()
  1686. map_test_extent = map_test.get_temporal_extent_as_tuple()
  1687. if map_test_extent != map_i_extent:
  1688. changeflag = True
  1689. for map_i in t[3]:
  1690. if changeflag:
  1691. # Check if resultmap names exist in GRASS database.
  1692. mapname = self.basename + "_" + str(count) + "@" + self.mapset
  1693. process_queue = pymod.ParallelModuleQueue(int(self.nprocs))
  1694. if self.stdstype == 'strds':
  1695. map_test = RasterDataset(mapname)
  1696. elif self.stdstype == 'stvds':
  1697. map_test = VectorDataset(mapname)
  1698. if map_test.map_exists() and self.overwrite == False:
  1699. self.msgr.fatal("Error raster maps with basename %s exist. Use --o flag to overwrite existing file" \
  1700. %(mapname))
  1701. # Create new maps with basename.
  1702. newident = self.basename + "_" + str(count)
  1703. map_result = map_i.get_new_instance(newident + "@" + self.mapset)
  1704. map_result.set_temporal_extent(map_i.get_temporal_extent())
  1705. map_result.set_spatial_extent(map_i.get_spatial_extent())
  1706. register_list.append(map_result)
  1707. if self.stdstype == 'strds':
  1708. m = copy.deepcopy(self.m_copy)
  1709. m.inputs["rast"].value = map_i.get_id(), newident
  1710. m.flags["overwrite"].value = self.overwrite
  1711. process_queue.put(m)
  1712. elif self.stdstype == 'stvds':
  1713. m = copy.deepcopy(self.m_copy)
  1714. m.inputs["vect"].value = map_i.get_id(), newident
  1715. m.flags["overwrite"].value = self.overwrite
  1716. process_queue.put(m)
  1717. else:
  1718. register_list.append(map_i)
  1719. count += 1
  1720. if changeflag:
  1721. process_queue.wait()
  1722. # Open connection to temporal database.
  1723. dbif, connect = init_dbif(self.dbif)
  1724. # Create result space time dataset.
  1725. resultstds = open_new_stds(t[1], self.stdstype, \
  1726. 'absolute', t[1], t[1], \
  1727. 'mean', self.dbif, \
  1728. overwrite = self.overwrite)
  1729. for map_i in register_list:
  1730. # Get meta data from grass database.
  1731. map_i.load()
  1732. # Check if temporal extents have changed.
  1733. if changeflag:
  1734. # Do not register empty maps if not required
  1735. # In case of a null map continue, do not register null maps
  1736. if map_i.metadata.get_min() is None and \
  1737. map_i.metadata.get_max() is None:
  1738. if not self.register_null:
  1739. self.empty_maps[map_i.get_name()] = map_i.get_name()
  1740. continue
  1741. if map_i.is_in_db(dbif) and self.overwrite:
  1742. # Update map in temporal database.
  1743. map_i.update_all(dbif)
  1744. elif map_i.is_in_db(dbif) and self.overwrite == False:
  1745. # Raise error if map exists and no overwrite flag is given.
  1746. self.msgr.fatal("Error vector map %s exist in temporal database. Use overwrite flag. : \n%s" \
  1747. %(map_i.get_map_id(), cmd.popen.stderr))
  1748. else:
  1749. # Insert map into temporal database.
  1750. map_i.insert(dbif)
  1751. # Register map in result space time dataset.
  1752. success = resultstds.register_map(map_i, dbif)
  1753. resultstds.update_from_registered_maps(dbif)
  1754. dbif.close()
  1755. elif num == 0:
  1756. self.msgr.warning('Empty result space time dataset. No map has \
  1757. been registered in %s' %(t[1] ))
  1758. # Open connection to temporal database.
  1759. dbif, connect = init_dbif(self.dbif)
  1760. # Create result space time dataset.
  1761. resultstds = open_new_stds(t[1], self.stdstype, \
  1762. 'absolute', t[1], t[1], \
  1763. 'mean', self.dbif, \
  1764. overwrite = self.overwrite)
  1765. dbif.close()
  1766. t[0] = t[3]
  1767. else:
  1768. t[0] = t[3]
  1769. if self.debug:
  1770. print t[1], "=", t[3]
  1771. def p_stds_1(self, t):
  1772. # Definition of a space time dataset
  1773. """
  1774. stds : NAME
  1775. """
  1776. t[0] = t[1]
  1777. def p_paren_expr(self, t):
  1778. """ expr : LPAREN expr RPAREN"""
  1779. t[0] = t[2]
  1780. def p_number(self,t):
  1781. """number : INT
  1782. | FLOAT
  1783. """
  1784. t[0] = t[1]
  1785. def p_expr_tmap_function(self, t):
  1786. # Add a single map.
  1787. # Only the spatial extent of the map is evaluated.
  1788. # Temporal extent is not existing.
  1789. # Examples:
  1790. # R = tmap(A)
  1791. """
  1792. expr : TMAP LPAREN stds RPAREN
  1793. """
  1794. if self.run:
  1795. # Check input map.
  1796. input = t[3]
  1797. if not isinstance(input, list):
  1798. # Check for mapset in given stds input.
  1799. if input.find("@") >= 0:
  1800. id_input = input
  1801. else:
  1802. id_input = input + "@" + self.mapset
  1803. # Create empty map dataset.
  1804. map_i = dataset_factory(self.maptype, id_input)
  1805. # Check for occurence of space time dataset.
  1806. if map_i.map_exists() == False:
  1807. raise FatalError(_("%s map <%s> not found in GRASS spatial database") %
  1808. (map_i.get_type(), id_input))
  1809. else:
  1810. # Select dataset entry from database.
  1811. map_i.select(dbif=self.dbif)
  1812. else:
  1813. raise FatalError(_("Wrong map type <%s> . TMAP only supports single maps that are registered in the temporal GRASS database") %
  1814. (map_i.get_type()))
  1815. # Return map object.
  1816. t[0] = [map_i]
  1817. else:
  1818. t[0] = "tmap(", t[3] , ")"
  1819. if self.debug:
  1820. print "tmap(", t[3] , ")"
  1821. def p_t_hash(self,t):
  1822. """
  1823. t_hash_var : stds HASH stds
  1824. """
  1825. if self.run:
  1826. maplistA = self.check_stds(t[1])
  1827. maplistB = self.check_stds(t[3])
  1828. resultlist = self.get_temporal_topo_list(maplistA, maplistB,
  1829. count_map = True)
  1830. t[0] = resultlist
  1831. def p_t_hash2(self,t):
  1832. """
  1833. t_hash_var : stds T_HASH_OPERATOR stds
  1834. """
  1835. if self.run:
  1836. maplistA = self.check_stds(t[1])
  1837. maplistB = self.check_stds(t[3])
  1838. topolist = self.eval_toperator(t[2], optype = 'hash')[0]
  1839. resultlist = self.get_temporal_topo_list(maplistA, maplistB, topolist,
  1840. count_map = True)
  1841. t[0] = resultlist
  1842. def p_t_td_var(self, t):
  1843. """
  1844. t_td_var : TD LPAREN stds RPAREN
  1845. | TD LPAREN expr RPAREN
  1846. """
  1847. if self.run:
  1848. maplist = self.check_stds(t[3])
  1849. for map_i in maplist:
  1850. if map_i.is_time_absolute:
  1851. start, end = map_i.get_absolute_time()
  1852. if end != None:
  1853. td = time_delta_to_relative_time(end - start)
  1854. else:
  1855. start, end, unit = current.get_relative_time()
  1856. if end != None:
  1857. td = end - start
  1858. if "map_value" in dir(map_i):
  1859. gvar = GlobalTemporalVar()
  1860. gvar.td = td
  1861. map_i.map_value.append(gvar)
  1862. else:
  1863. map_i.map_value = gvar
  1864. t[0] = maplist
  1865. else:
  1866. t[0] = "td(" + str(t[3]) + ")"
  1867. if self.debug:
  1868. print "td(" + str(t[3]) + ")"
  1869. def p_t_time_var(self, t):
  1870. # Temporal variables that return a double or integer value
  1871. """
  1872. t_var : START_DOY
  1873. | START_DOW
  1874. | START_YEAR
  1875. | START_MONTH
  1876. | START_WEEK
  1877. | START_DAY
  1878. | START_HOUR
  1879. | START_MINUTE
  1880. | START_SECOND
  1881. | END_DOY
  1882. | END_DOW
  1883. | END_YEAR
  1884. | END_MONTH
  1885. | END_WEEK
  1886. | END_DAY
  1887. | END_HOUR
  1888. | END_MINUTE
  1889. | END_SECOND
  1890. """
  1891. t[0] = t[1]
  1892. def p_compare_op(self, t):
  1893. # Compare operators that are supported for temporal expressions
  1894. """
  1895. comp_op : CEQUALS
  1896. | UNEQUALS
  1897. | LOWER
  1898. | LOWER_EQUALS
  1899. | GREATER
  1900. | GREATER_EQUALS
  1901. """
  1902. t[0] = t[1]
  1903. def p_t_var_expr_td_hash(self, t):
  1904. # Examples:
  1905. # A # B == 2
  1906. # td(A) < 31
  1907. """
  1908. t_var_expr : t_td_var comp_op number
  1909. | t_hash_var comp_op number
  1910. """
  1911. if self.run:
  1912. maplist = self.check_stds(t[1])
  1913. comp_op = t[2]
  1914. value = str(t[3])
  1915. for map_i in maplist:
  1916. # Evaluate time diferences and hash operator statements for each map.
  1917. try:
  1918. td = map_i.map_value[0].td
  1919. boolname = eval(str(td) + comp_op + value)
  1920. # Add conditional boolean value to the map.
  1921. if "condition_value" in dir(map_i):
  1922. map_i.condition_value.append(boolname)
  1923. else:
  1924. map_i.condition_value = boolname
  1925. except:
  1926. self.msgr.fatal("Error: the given expression does not contain a correct time difference object.")
  1927. t[0] = maplist
  1928. if self.debug:
  1929. print t[1], t[2], t[3]
  1930. def p_t_var_expr_number(self, t):
  1931. # Examples:
  1932. # start_month(A) > 2
  1933. # start_day(B) < 14
  1934. # start_day(B) < start_month(A)
  1935. """
  1936. t_var_expr : t_var LPAREN stds RPAREN comp_op number
  1937. | t_var LPAREN expr RPAREN comp_op number
  1938. """
  1939. # TODO: Implement comparison operator for map lists.
  1940. #| t_var LPAREN stds RPAREN comp_op t_var LPAREN stds RPAREN
  1941. #| t_var LPAREN stds RPAREN comp_op t_var LPAREN expr RPAREN
  1942. #| t_var LPAREN expr RPAREN comp_op t_var LPAREN expr RPAREN
  1943. #| t_var LPAREN expr RPAREN comp_op t_var LPAREN stds RPAREN
  1944. # TODO: Implement statement in backward direction:
  1945. # number comp_op t_var LPAREN stds RPAREN
  1946. if self.run:
  1947. maplist = self.check_stds(t[3])
  1948. gvar = GlobalTemporalVar()
  1949. gvar.tfunc = t[1]
  1950. gvar.compop = t[5]
  1951. gvar.value = t[6]
  1952. # Evaluate temporal variable for given maplist.
  1953. resultlist = self.eval_global_var(gvar, maplist)
  1954. t[0] = resultlist
  1955. if self.debug:
  1956. print t[1], t[3], t[5], t[6]
  1957. def p_t_var_expr_time(self, t):
  1958. # Examples:
  1959. # start_time(A) == "12:30:00"
  1960. # start_date(B) <= "2001-01-01"
  1961. # start_datetime(C) > "2001-01-01 12:30:00"
  1962. # TODO: Implement statement in backward direction:
  1963. # TIME comp_op START_TIME LPAREN stds RPAREN
  1964. """
  1965. t_var_expr : START_TIME LPAREN stds RPAREN comp_op TIME
  1966. | START_DATE LPAREN stds RPAREN comp_op DATE
  1967. | START_DATETIME LPAREN stds RPAREN comp_op DATETIME
  1968. | END_TIME LPAREN stds RPAREN comp_op TIME
  1969. | END_DATE LPAREN stds RPAREN comp_op DATE
  1970. | END_DATETIME LPAREN stds RPAREN comp_op DATETIME
  1971. | START_TIME LPAREN expr RPAREN comp_op TIME
  1972. | START_DATE LPAREN expr RPAREN comp_op DATE
  1973. | START_DATETIME LPAREN expr RPAREN comp_op DATETIME
  1974. | END_TIME LPAREN expr RPAREN comp_op TIME
  1975. | END_DATE LPAREN expr RPAREN comp_op DATE
  1976. | END_DATETIME LPAREN expr RPAREN comp_op DATETIME
  1977. """
  1978. if self.run:
  1979. # Check input maplist.
  1980. maplist = self.check_stds(t[3])
  1981. # Build global temporal variable.
  1982. gvar = GlobalTemporalVar()
  1983. gvar.tfunc = t[1]
  1984. gvar.compop = t[5]
  1985. gvar.value = t[6]
  1986. # Evaluate temporal variable for given maplist.
  1987. resultlist = self.eval_global_var(gvar, maplist)
  1988. t[0] = resultlist
  1989. if self.debug:
  1990. print t[1], t[3], t[5], t[6]
  1991. def p_t_var_expr_comp(self, t):
  1992. """
  1993. t_var_expr : t_var_expr AND AND t_var_expr
  1994. | t_var_expr OR OR t_var_expr
  1995. """
  1996. if self.run:
  1997. # Check input maplists and operators.
  1998. tvarexprA = t[1]
  1999. tvarexprB = t[4]
  2000. relations = ["EQUAL"]
  2001. temporal = "l"
  2002. function = t[2] + t[3]
  2003. aggregate = t[2]
  2004. # Build conditional values based on topological relationships.
  2005. complist = self.get_temporal_topo_list(tvarexprA, tvarexprB, topolist = relations,
  2006. compare_bool = True, compop = function[0], aggregate = aggregate)
  2007. # Set temporal extent based on topological relationships.
  2008. resultlist = self.set_temporal_extent_list(complist, topolist = relations,
  2009. temporal = temporal)
  2010. t[0] = resultlist
  2011. if self.debug:
  2012. print t[1], t[2] + t[3], t[4]
  2013. def p_t_var_expr_comp_op(self, t):
  2014. """
  2015. t_var_expr : t_var_expr T_COMP_OPERATOR t_var_expr
  2016. """
  2017. if self.run:
  2018. tvarexprA = t[1]
  2019. tvarexprB = t[3]
  2020. # Evaluate temporal comparison operator.
  2021. relations, temporal, function, aggregate = self.eval_toperator(t[2], optype = 'boolean')
  2022. # Build conditional values based on topological relationships.
  2023. complist = self.get_temporal_topo_list(tvarexprA, tvarexprB, topolist = relations,
  2024. compare_bool = True, compop = function[0], aggregate = aggregate)
  2025. # Set temporal extent based on topological relationships.
  2026. resultlist = self.set_temporal_extent_list(complist, topolist = relations,
  2027. temporal = temporal)
  2028. t[0] = resultlist
  2029. if self.debug:
  2030. print t[1], t[2], t[3]
  2031. def p_expr_t_select(self, t):
  2032. # Temporal equal selection
  2033. # The temporal topology relation equals is implicit
  2034. # Examples:
  2035. # A : B # Select the part of A that is temporally equal B
  2036. """
  2037. expr : stds T_SELECT stds
  2038. | expr T_SELECT stds
  2039. | stds T_SELECT expr
  2040. | expr T_SELECT expr
  2041. """
  2042. if self.run:
  2043. # Setup database connection.
  2044. # Check input stds.
  2045. maplistA = self.check_stds(t[1])
  2046. maplistB = self.check_stds(t[3])
  2047. # Perform selection.
  2048. selectlist = self.perform_temporal_selection(maplistA, maplistB)
  2049. # Return map list.
  2050. t[0] = selectlist
  2051. else:
  2052. t[0] = t[1] , "*"
  2053. if self.debug:
  2054. print str(t[1]), "* = ", t[1], t[2], t[3]
  2055. def p_expr_t_not_select(self, t):
  2056. # Temporal equal selection
  2057. # The temporal topology relation equals is implicit
  2058. # Examples:
  2059. # A !: B # Select the part of A that is temporally unequal to B
  2060. """
  2061. expr : stds T_NOT_SELECT stds
  2062. | expr T_NOT_SELECT stds
  2063. | stds T_NOT_SELECT expr
  2064. | expr T_NOT_SELECT expr
  2065. """
  2066. if self.run:
  2067. # Check input stds.
  2068. maplistA = self.check_stds(t[1])
  2069. maplistB = self.check_stds(t[3])
  2070. # Perform negative selection.
  2071. selectlist = self.perform_temporal_selection(maplistA, maplistB,
  2072. inverse = True)
  2073. # Return map list.
  2074. t[0] = selectlist
  2075. else:
  2076. t[0] = t[1] + "*"
  2077. if self.debug:
  2078. print t[1] + "* = ", t[1], t[2], t[3]
  2079. def p_expr_t_select_operator(self, t):
  2080. # Temporal equal selection
  2081. # The temporal topology relation equals is implicit
  2082. # Examples:
  2083. # A {!:} B # Select the part of A that is temporally unequal to B
  2084. # A {:} B # Select the part of A that is temporally equal B
  2085. # A {equals, !:} B # Select the part of A that is temporally unequal to B
  2086. # A {during, !:} B # Select the part of A that is temporally not during B
  2087. # A {overlaps, :} B # Select the part of A that temporally overlaps B
  2088. # A {overlaps|equals, :} B # Select the part of A that temporally overlaps or equals B
  2089. """
  2090. expr : stds T_SELECT_OPERATOR stds
  2091. | expr T_SELECT_OPERATOR stds
  2092. | stds T_SELECT_OPERATOR expr
  2093. | expr T_SELECT_OPERATOR expr
  2094. """
  2095. if self.run:
  2096. # Check input stds.
  2097. maplistA = self.check_stds(t[1])
  2098. maplistB = self.check_stds(t[3])
  2099. # Evaluate temporal operator.
  2100. operators = self.eval_toperator(t[2], optype = 'select')
  2101. # Check for negative selection.
  2102. if operators[2] == "!:":
  2103. negation = True
  2104. else:
  2105. negation = False
  2106. # Perform selection.
  2107. selectlist = self.perform_temporal_selection(maplistA, maplistB,
  2108. topolist = operators[0], inverse = negation)
  2109. selectlist = self.set_granularity(selectlist, maplistB, operators[1],
  2110. operators[0])
  2111. # Return map list.
  2112. t[0] = selectlist
  2113. else:
  2114. t[0] = t[1] + "*"
  2115. if self.debug:
  2116. print t[1] + "* = ", t[1], t[2], t[3]
  2117. def p_expr_condition_if(self, t):
  2118. # Examples
  2119. # if( start_date() < "2005-06-01", A:B)
  2120. """
  2121. expr : IF LPAREN t_var_expr COMMA stds RPAREN
  2122. | IF LPAREN t_var_expr COMMA expr RPAREN
  2123. """
  2124. if self.run:
  2125. # Get stds/map list of then statement.
  2126. thenlist = self.check_stds(t[5])
  2127. # Get temporal conditional statement.
  2128. tvarexpr = t[3]
  2129. thencond = self.build_condition_list(tvarexpr, thenlist)
  2130. thenresult = self.eval_condition_list(thencond)
  2131. # Clear the map and conditional values of the map list.
  2132. resultlist = self.check_stds(thenresult, clear = True)
  2133. # Return resulting map list.
  2134. t[0] = resultlist
  2135. else:
  2136. t[0] = t[5] + "*"
  2137. if self.debug:
  2138. print str(t[5]) + "* = ", "if condition", str(t[3]), ' then ', str(t[5])
  2139. def p_expr_condition_if_relation(self, t):
  2140. # Examples
  2141. # if({equal} start_date() < "2005-06-01", A:B)
  2142. """
  2143. expr : IF LPAREN T_REL_OPERATOR COMMA t_var_expr COMMA stds RPAREN
  2144. | IF LPAREN T_REL_OPERATOR COMMA t_var_expr COMMA expr RPAREN
  2145. """
  2146. if self.run:
  2147. # Get stds/map list of then statement.
  2148. thenlist = self.check_stds(t[7])
  2149. # Get temporal conditional statement.
  2150. tvarexpr = t[5]
  2151. topolist = self.eval_toperator(t[3], optype = 'relation')[0]
  2152. thencond = self.build_condition_list(tvarexpr, thenlist, topolist)
  2153. thenresult = self.eval_condition_list(thencond)
  2154. # Clear the map and conditional values of the map list.
  2155. resultlist = self.check_stds(thenresult, clear = True)
  2156. # Return resulting map list.
  2157. t[0] = resultlist
  2158. else:
  2159. t[0] = t[7] + "*"
  2160. if self.debug:
  2161. print "result* = ", "if ", str(t[3]), "condition", str(t[5]), " then ", str(t[7])
  2162. def p_expr_condition_elif(self, t):
  2163. # Examples
  2164. # if( start_date() < "2005-06-01", if(start_time() < "12:30:00", A:B), A!:B)
  2165. """
  2166. expr : IF LPAREN t_var_expr COMMA stds COMMA stds RPAREN
  2167. | IF LPAREN t_var_expr COMMA stds COMMA expr RPAREN
  2168. | IF LPAREN t_var_expr COMMA expr COMMA stds RPAREN
  2169. | IF LPAREN t_var_expr COMMA expr COMMA expr RPAREN
  2170. """
  2171. if self.run:
  2172. # Get stds/map list of then statement.
  2173. thenlist = self.check_stds(t[5])
  2174. elselist = self.check_stds(t[7])
  2175. # Get temporal conditional statement for then and else expressions.
  2176. tvarexpr = t[3]
  2177. thencond = self.build_condition_list(tvarexpr, thenlist)
  2178. thenresult = self.eval_condition_list(thencond)
  2179. elsecond = self.build_condition_list(tvarexpr, elselist)
  2180. elseresult = self.eval_condition_list(elsecond, inverse = True)
  2181. # Combine and sort else and then statement to result map list.
  2182. combilist = thenresult + elseresult
  2183. resultlist = sorted(combilist, key = AbstractDatasetComparisonKeyStartTime)
  2184. # Clear the map and conditional values of the map list.
  2185. resultlist = self.check_stds(resultlist, clear = True)
  2186. # Return resulting map list.
  2187. t[0] = resultlist
  2188. else:
  2189. t[0] = t[5] + "*"
  2190. if self.debug:
  2191. print str(t[5]) + "* = ", "if condition", str(t[3]), " then ", str(t[5]), ' else ', str(t[7])
  2192. def p_expr_condition_elif_relation(self, t):
  2193. # Examples
  2194. # if({equal}, start_date() < "2005-06-01", if(start_time() < "12:30:00", A:B), A!:B)
  2195. # The then and else statement using the same topological relationships.
  2196. # Feature request: Independent relationships for then and else to conditions.
  2197. """
  2198. expr : IF LPAREN T_REL_OPERATOR COMMA t_var_expr COMMA stds COMMA stds RPAREN
  2199. | IF LPAREN T_REL_OPERATOR COMMA t_var_expr COMMA stds COMMA expr RPAREN
  2200. | IF LPAREN T_REL_OPERATOR COMMA t_var_expr COMMA expr COMMA stds RPAREN
  2201. | IF LPAREN T_REL_OPERATOR COMMA t_var_expr COMMA expr COMMA expr RPAREN
  2202. """
  2203. if self.run:
  2204. # Get stds/map list of then statement.
  2205. thenlist = self.check_stds(t[7])
  2206. elselist = self.check_stds(t[9])
  2207. # Get temporal conditional statement.
  2208. tvarexpr = t[5]
  2209. topolist = self.eval_toperator(t[3], optype = 'relation')[0]
  2210. thencond = self.build_condition_list(tvarexpr, thenlist, topolist)
  2211. thenresult = self.eval_condition_list(thencond)
  2212. elsecond = self.build_condition_list(tvarexpr, elselist, topolist)
  2213. elseresult = self.eval_condition_list(elsecond, inverse = True)
  2214. # Combine and sort else and then statement to result map list.
  2215. combilist = thenresult + elseresult
  2216. resultlist = sorted(combilist, key = AbstractDatasetComparisonKeyStartTime)
  2217. # Clear the map and conditional values of the map list.
  2218. resultlist = self.check_stds(resultlist, clear = True)
  2219. # Return resulting map list.
  2220. t[0] = resultlist
  2221. else:
  2222. if t[5]:
  2223. t[0] = str(t[7])
  2224. else:
  2225. t[0] = str(t[9])
  2226. if self.debug:
  2227. if t[5]:
  2228. print str(t[7]), "* = ", "if condition", str(t[5]), " then ", str(t[7]), ' else ', str(t[9])
  2229. else:
  2230. print str(t[9]), "* = ", "if condition", str(t[5]), " then ", str(t[7]), ' else ', str(t[9])
  2231. def p_expr_t_buff(self, t):
  2232. # Examples
  2233. # buff_t(A : B, "10 minutes") # Select the part of A that is temporally
  2234. # equal to B and create a buffer of 10 minutes around
  2235. """
  2236. expr : BUFF_T LPAREN stds COMMA QUOTE number NAME QUOTE RPAREN
  2237. | BUFF_T LPAREN expr COMMA QUOTE number NAME QUOTE RPAREN
  2238. | BUFF_T LPAREN stds COMMA number RPAREN
  2239. | BUFF_T LPAREN expr COMMA number RPAREN
  2240. """
  2241. if self.run:
  2242. # Check input stds.
  2243. bufflist = self.check_stds(t[3])
  2244. for map in bufflist:
  2245. # Get increment format.
  2246. if len(t) == 10:
  2247. increment = str(t[6]) + " " + t[7]
  2248. elif len(t) == 7:
  2249. increment = str(t[5])
  2250. # Perform buffering.
  2251. map.temporal_buffer(increment)
  2252. t[0] = bufflist
  2253. else:
  2254. t[0] = t[3] + "*"
  2255. if self.debug:
  2256. if len(t) == 10:
  2257. print str(t[3]) + "* = buff_t(", str(t[3]), "," , '"', str(t[6]), str(t[7]), '"', ")"
  2258. elif len(t) == 7:
  2259. print str(t[3]) + "* = buff_t(", str(t[3]), ",", str(t[5]), ")"
  2260. def p_expr_t_snap(self, t):
  2261. # Examples
  2262. # tsnap(A : B) # Snap the maps of A temporally.
  2263. """
  2264. expr : TSNAP LPAREN stds RPAREN
  2265. | TSNAP LPAREN expr RPAREN
  2266. """
  2267. if self.run:
  2268. # Check input stds.
  2269. maplist = self.check_stds(t[3])
  2270. # Perform snapping.
  2271. snaplist = AbstractSpaceTimeDataset.snap_map_list(maplist)
  2272. t[0] = snaplist
  2273. else:
  2274. t[0] = t[3] + "*"
  2275. if self.debug:
  2276. print str(t[3]) + "* = tsnap(", str(t[3]), ")"
  2277. def p_expr_t_shift(self, t):
  2278. # Examples
  2279. # tshift(A : B, "10 minutes") # Shift the selection from A temporally
  2280. # by 10 minutes.
  2281. """
  2282. expr : TSHIFT LPAREN stds COMMA QUOTE number NAME QUOTE RPAREN
  2283. | TSHIFT LPAREN expr COMMA QUOTE number NAME QUOTE RPAREN
  2284. | TSHIFT LPAREN stds COMMA number RPAREN
  2285. | TSHIFT LPAREN expr COMMA number RPAREN
  2286. """
  2287. if self.run:
  2288. # Check input stds.
  2289. maplist = self.check_stds(t[3])
  2290. # Get increment format.
  2291. if len(t) == 10:
  2292. increment = str(t[6]) + " " + t[7]
  2293. elif len(t) == 7:
  2294. increment = str(t[5])
  2295. # Perform shifting.
  2296. shiftlist = AbstractSpaceTimeDataset.shift_map_list(maplist, increment)
  2297. t[0] = shiftlist
  2298. else:
  2299. t[0] = t[3] + "*"
  2300. if self.debug:
  2301. if len(t) == 10:
  2302. print str(t[3]) + "* = tshift(", str(t[3]), "," , '"', str(t[6]), str(t[7]), '"', ")"
  2303. elif len(t) == 7:
  2304. print str(t[3]) + "* = tshift(", str(t[3]), ",", str(t[5]), ")"
  2305. # Handle errors.
  2306. def p_error(self, t):
  2307. if t:
  2308. raise SyntaxError("syntax error on line %d, token %s near '%s' expression '%s'" %
  2309. (t.lineno, t.type, t.value, self.expression))
  2310. else:
  2311. raise SyntaxError("Unexpected syntax error")
  2312. ###############################################################################
  2313. if __name__ == "__main__":
  2314. import doctest
  2315. doctest.testmod()