temporal_algebra.py 94 KB

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