123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373 |
- """!@package grass.temporal
- Temporal algebra parser class
- (C) 2014 by the GRASS Development Team
- This program is free software under the GNU General Public
- License (>=v2). Read the file COPYING that comes with GRASS
- for details.
- @authors Thomas Leppelt and Soeren Gebbert
- @code
- >>> import grass.temporal as tgis
- >>> tgis.init(True)
- >>> p = tgis.TemporalAlgebraLexer()
- >>> p.build()
- >>> p.debug = True
- >>> expression = "C = A : B"
- >>> p.test(expression)
- C = A : B
- LexToken(NAME,'C',1,0)
- LexToken(EQUALS,'=',1,2)
- LexToken(NAME,'A',1,4)
- LexToken(T_SELECT,':',1,6)
- LexToken(NAME,'B',1,8)
- >>> expression = "C = test1 !: test2"
- >>> p.test(expression)
- C = test1 !: test2
- LexToken(NAME,'C',1,0)
- LexToken(EQUALS,'=',1,2)
- LexToken(NAME,'test1',1,4)
- LexToken(T_NOT_SELECT,'!:',1,10)
- LexToken(NAME,'test2',1,13)
- >>> expression = "C = test1 {equal,:} test2"
- >>> p.test(expression)
- C = test1 {equal,:} test2
- LexToken(NAME,'C',1,0)
- LexToken(EQUALS,'=',1,2)
- LexToken(NAME,'test1',1,4)
- LexToken(T_SELECT_OPERATOR,'{equal,:}',1,10)
- LexToken(NAME,'test2',1,20)
- >>> expression = "C = test1 {equal,!:} test2"
- >>> p.test(expression)
- C = test1 {equal,!:} test2
- LexToken(NAME,'C',1,0)
- LexToken(EQUALS,'=',1,2)
- LexToken(NAME,'test1',1,4)
- LexToken(T_SELECT_OPERATOR,'{equal,!:}',1,10)
- LexToken(NAME,'test2',1,21)
- >>> expression = "C = test1 # test2"
- >>> p.test(expression)
- C = test1 # test2
- LexToken(NAME,'C',1,0)
- LexToken(EQUALS,'=',1,2)
- LexToken(NAME,'test1',1,4)
- LexToken(HASH,'#',1,10)
- LexToken(NAME,'test2',1,12)
- >>> expression = "C = test1 {#} test2"
- >>> p.test(expression)
- C = test1 {#} test2
- LexToken(NAME,'C',1,0)
- LexToken(EQUALS,'=',1,2)
- LexToken(NAME,'test1',1,4)
- LexToken(T_HASH_OPERATOR,'{#}',1,10)
- LexToken(NAME,'test2',1,14)
- >>> expression = "C = test1 {equal,#} test2"
- >>> p.test(expression)
- C = test1 {equal,#} test2
- LexToken(NAME,'C',1,0)
- LexToken(EQUALS,'=',1,2)
- LexToken(NAME,'test1',1,4)
- LexToken(T_HASH_OPERATOR,'{equal,#}',1,10)
- LexToken(NAME,'test2',1,20)
- >>> expression = "C = test1 {equal|during,#} test2"
- >>> p.test(expression)
- C = test1 {equal|during,#} test2
- LexToken(NAME,'C',1,0)
- LexToken(EQUALS,'=',1,2)
- LexToken(NAME,'test1',1,4)
- LexToken(T_HASH_OPERATOR,'{equal|during,#}',1,10)
- LexToken(NAME,'test2',1,27)
- >>> expression = "E = test1 : test2 !: test1"
- >>> p.test(expression)
- E = test1 : test2 !: test1
- LexToken(NAME,'E',1,0)
- LexToken(EQUALS,'=',1,2)
- LexToken(NAME,'test1',1,4)
- LexToken(T_SELECT,':',1,10)
- LexToken(NAME,'test2',1,12)
- LexToken(T_NOT_SELECT,'!:',1,18)
- LexToken(NAME,'test1',1,21)
- >>> expression = 'D = buff_t(test1,"10 months")'
- >>> p.test(expression)
- D = buff_t(test1,"10 months")
- LexToken(NAME,'D',1,0)
- LexToken(EQUALS,'=',1,2)
- LexToken(BUFF_T,'buff_t',1,4)
- LexToken(LPAREN,'(',1,10)
- LexToken(NAME,'test1',1,11)
- LexToken(COMMA,',',1,16)
- LexToken(QUOTE,'"',1,17)
- LexToken(INT,10,1,18)
- LexToken(NAME,'months',1,21)
- LexToken(QUOTE,'"',1,27)
- LexToken(RPAREN,')',1,28)
- >>> expression = 'H = tsnap(test1)'
- >>> p.test(expression)
- H = tsnap(test1)
- LexToken(NAME,'H',1,0)
- LexToken(EQUALS,'=',1,2)
- LexToken(TSNAP,'tsnap',1,4)
- LexToken(LPAREN,'(',1,9)
- LexToken(NAME,'test1',1,10)
- LexToken(RPAREN,')',1,15)
- >>> expression = 'H = tsnap(test2 {during,:} buff_t(test1, "1 days"))'
- >>> p.test(expression)
- H = tsnap(test2 {during,:} buff_t(test1, "1 days"))
- LexToken(NAME,'H',1,0)
- LexToken(EQUALS,'=',1,2)
- LexToken(TSNAP,'tsnap',1,4)
- LexToken(LPAREN,'(',1,9)
- LexToken(NAME,'test2',1,10)
- LexToken(T_SELECT_OPERATOR,'{during,:}',1,16)
- LexToken(BUFF_T,'buff_t',1,27)
- LexToken(LPAREN,'(',1,33)
- LexToken(NAME,'test1',1,34)
- LexToken(COMMA,',',1,39)
- LexToken(QUOTE,'"',1,41)
- LexToken(INT,1,1,42)
- LexToken(NAME,'days',1,44)
- LexToken(QUOTE,'"',1,48)
- LexToken(RPAREN,')',1,49)
- LexToken(RPAREN,')',1,50)
- >>> expression = 'H = tshift(test2 {during,:} buff_t(test1, "1 days"), "1 months")'
- >>> p.test(expression)
- H = tshift(test2 {during,:} buff_t(test1, "1 days"), "1 months")
- LexToken(NAME,'H',1,0)
- LexToken(EQUALS,'=',1,2)
- LexToken(TSHIFT,'tshift',1,4)
- LexToken(LPAREN,'(',1,10)
- LexToken(NAME,'test2',1,11)
- LexToken(T_SELECT_OPERATOR,'{during,:}',1,17)
- LexToken(BUFF_T,'buff_t',1,28)
- LexToken(LPAREN,'(',1,34)
- LexToken(NAME,'test1',1,35)
- LexToken(COMMA,',',1,40)
- LexToken(QUOTE,'"',1,42)
- LexToken(INT,1,1,43)
- LexToken(NAME,'days',1,45)
- LexToken(QUOTE,'"',1,49)
- LexToken(RPAREN,')',1,50)
- LexToken(COMMA,',',1,51)
- LexToken(QUOTE,'"',1,53)
- LexToken(INT,1,1,54)
- LexToken(NAME,'months',1,56)
- LexToken(QUOTE,'"',1,62)
- LexToken(RPAREN,')',1,63)
- >>> expression = 'H = tshift(A , 10)'
- >>> p.test(expression)
- H = tshift(A , 10)
- LexToken(NAME,'H',1,0)
- LexToken(EQUALS,'=',1,2)
- LexToken(TSHIFT,'tshift',1,4)
- LexToken(LPAREN,'(',1,10)
- LexToken(NAME,'A',1,11)
- LexToken(COMMA,',',1,13)
- LexToken(INT,10,1,15)
- LexToken(RPAREN,')',1,17)
- >>> expression = 'H = if(td(A) > 10, A)'
- >>> p.test(expression)
- H = if(td(A) > 10, A)
- LexToken(NAME,'H',1,0)
- LexToken(EQUALS,'=',1,2)
- LexToken(IF,'if',1,4)
- LexToken(LPAREN,'(',1,6)
- LexToken(TD,'td',1,7)
- LexToken(LPAREN,'(',1,9)
- LexToken(NAME,'A',1,10)
- LexToken(RPAREN,')',1,11)
- LexToken(GREATER,'>',1,13)
- LexToken(INT,10,1,15)
- LexToken(COMMA,',',1,17)
- LexToken(NAME,'A',1,19)
- LexToken(RPAREN,')',1,20)
- >>> expression = 'H = if(td(A) > 10, A, B)'
- >>> p.test(expression)
- H = if(td(A) > 10, A, B)
- LexToken(NAME,'H',1,0)
- LexToken(EQUALS,'=',1,2)
- LexToken(IF,'if',1,4)
- LexToken(LPAREN,'(',1,6)
- LexToken(TD,'td',1,7)
- LexToken(LPAREN,'(',1,9)
- LexToken(NAME,'A',1,10)
- LexToken(RPAREN,')',1,11)
- LexToken(GREATER,'>',1,13)
- LexToken(INT,10,1,15)
- LexToken(COMMA,',',1,17)
- LexToken(NAME,'A',1,19)
- LexToken(COMMA,',',1,20)
- LexToken(NAME,'B',1,22)
- LexToken(RPAREN,')',1,23)
- >>> expression = 'I = if(equals,td(A) > 10 {equals,||} td(B) < 10, A)'
- >>> p.test(expression)
- I = if(equals,td(A) > 10 {equals,||} td(B) < 10, A)
- LexToken(NAME,'I',1,0)
- LexToken(EQUALS,'=',1,2)
- LexToken(IF,'if',1,4)
- LexToken(LPAREN,'(',1,6)
- LexToken(NAME,'equals',1,7)
- LexToken(COMMA,',',1,13)
- LexToken(TD,'td',1,14)
- LexToken(LPAREN,'(',1,16)
- LexToken(NAME,'A',1,17)
- LexToken(RPAREN,')',1,18)
- LexToken(GREATER,'>',1,20)
- LexToken(INT,10,1,22)
- LexToken(T_COMP_OPERATOR,'{equals,||}',1,25)
- LexToken(TD,'td',1,37)
- LexToken(LPAREN,'(',1,39)
- LexToken(NAME,'B',1,40)
- LexToken(RPAREN,')',1,41)
- LexToken(LOWER,'<',1,43)
- LexToken(INT,10,1,45)
- LexToken(COMMA,',',1,47)
- LexToken(NAME,'A',1,49)
- LexToken(RPAREN,')',1,50)
- >>> expression = 'I = if(equals,td(A) > 10 || start_day() < 10, A)'
- >>> p.test(expression)
- I = if(equals,td(A) > 10 || start_day() < 10, A)
- LexToken(NAME,'I',1,0)
- LexToken(EQUALS,'=',1,2)
- LexToken(IF,'if',1,4)
- LexToken(LPAREN,'(',1,6)
- LexToken(NAME,'equals',1,7)
- LexToken(COMMA,',',1,13)
- LexToken(TD,'td',1,14)
- LexToken(LPAREN,'(',1,16)
- LexToken(NAME,'A',1,17)
- LexToken(RPAREN,')',1,18)
- LexToken(GREATER,'>',1,20)
- LexToken(INT,10,1,22)
- LexToken(OR,'|',1,25)
- LexToken(OR,'|',1,26)
- LexToken(START_DAY,'start_day',1,28)
- LexToken(LPAREN,'(',1,37)
- LexToken(RPAREN,')',1,38)
- LexToken(LOWER,'<',1,40)
- LexToken(INT,10,1,42)
- LexToken(COMMA,',',1,44)
- LexToken(NAME,'A',1,46)
- LexToken(RPAREN,')',1,47)
- >>> expression = 'E = if({equals},td(A) >= 4 {contain,&&} td(B) == 2, C : D)'
- >>> p.test(expression)
- E = if({equals},td(A) >= 4 {contain,&&} td(B) == 2, C : D)
- LexToken(NAME,'E',1,0)
- LexToken(EQUALS,'=',1,2)
- LexToken(IF,'if',1,4)
- LexToken(LPAREN,'(',1,6)
- LexToken(T_REL_OPERATOR,'{equals}',1,7)
- LexToken(COMMA,',',1,15)
- LexToken(TD,'td',1,16)
- LexToken(LPAREN,'(',1,18)
- LexToken(NAME,'A',1,19)
- LexToken(RPAREN,')',1,20)
- LexToken(GREATER_EQUALS,'>=',1,22)
- LexToken(INT,4,1,25)
- LexToken(T_COMP_OPERATOR,'{contain,&&}',1,27)
- LexToken(TD,'td',1,40)
- LexToken(LPAREN,'(',1,42)
- LexToken(NAME,'B',1,43)
- LexToken(RPAREN,')',1,44)
- LexToken(CEQUALS,'==',1,46)
- LexToken(INT,2,1,49)
- LexToken(COMMA,',',1,50)
- LexToken(NAME,'C',1,52)
- LexToken(T_SELECT,':',1,54)
- LexToken(NAME,'D',1,56)
- LexToken(RPAREN,')',1,57)
- >>> expression = 'F = if({equals},A {equal,#}, B, C : D)'
- >>> p.test(expression)
- F = if({equals},A {equal,#}, B, C : D)
- LexToken(NAME,'F',1,0)
- LexToken(EQUALS,'=',1,2)
- LexToken(IF,'if',1,4)
- LexToken(LPAREN,'(',1,6)
- LexToken(T_REL_OPERATOR,'{equals}',1,7)
- LexToken(COMMA,',',1,15)
- LexToken(NAME,'A',1,16)
- LexToken(T_HASH_OPERATOR,'{equal,#}',1,18)
- LexToken(COMMA,',',1,27)
- LexToken(NAME,'B',1,29)
- LexToken(COMMA,',',1,30)
- LexToken(NAME,'C',1,32)
- LexToken(T_SELECT,':',1,34)
- LexToken(NAME,'D',1,36)
- LexToken(RPAREN,')',1,37)
- >>> p = tgis.TemporalAlgebraParser()
- >>> p.run = False
- >>> p.debug = True
- >>> expression = "D = A : (B !: C)"
- >>> p.parse(expression)
- B* = B !: C
- A* = A : B*
- D = A*
- >>> expression = "D = A {!:} B {during,:} C"
- >>> print(expression)
- D = A {!:} B {during,:} C
- >>> p.parse(expression)
- A* = A {!:} B
- A** = A* {during,:} C
- D = A**
- >>> expression = "D = A {:} B {during,!:} C"
- >>> print(expression)
- D = A {:} B {during,!:} C
- >>> p.parse(expression)
- A* = A {:} B
- A** = A* {during,!:} C
- D = A**
- >>> expression = "D = A {:} (B {during,!:} (C : E))"
- >>> print(expression)
- D = A {:} (B {during,!:} (C : E))
- >>> p.parse(expression)
- C* = C : E
- B* = B {during,!:} C*
- A* = A {:} B*
- D = A*
- >>> p.run = False
- >>> p.debug = False
- >>> expression = "C = test1 : test2"
- >>> print(expression)
- C = test1 : test2
- >>> p.parse(expression, 'stvds')
- >>> expression = 'D = buff_t(test1,"10 months")'
- >>> print(expression)
- D = buff_t(test1,"10 months")
- >>> p.parse(expression, 'stvds')
- >>> expression = 'E = test2 {during,:} buff_t(test1,"1 days")'
- >>> print(expression)
- E = test2 {during,:} buff_t(test1,"1 days")
- >>> p.parse(expression, 'stvds')
- >>> expression = 'F = test2 {equal,:} buff_t(test1,"1 days")'
- >>> print(expression)
- F = test2 {equal,:} buff_t(test1,"1 days")
- >>> p.parse(expression, 'stvds')
- >>> p.debug = True
- >>> expression = 'H = tsnap(test2 {during,:} buff_t(test1, "1 days"))'
- >>> p.parse(expression, 'stvds')
- test1* = buff_t( test1 , " 1 days " )
- test2* = test2 {during,:} test1*
- test2** = tsnap( test2* )
- H = test2**
- >>> expression = 'H = tshift(test2 {during,:} test1, "1 days")'
- >>> p.parse(expression, 'stvds')
- test2* = test2 {during,:} test1
- test2** = tshift( test2* , " 1 days " )
- H = test2**
- >>> expression = 'H = tshift(H, 3)'
- >>> p.parse(expression, 'stvds')
- H* = tshift( H , 3 )
- H = H*
- >>> expression = 'C = if(td(A) == 2, A)'
- >>> p.parse(expression, 'stvds')
- td(A)
- td(A) == 2
- A* = if condition True then A
- C = A*
- >>> expression = 'C = if(td(A) == 5, A, B)'
- >>> p.parse(expression, 'stvds')
- td(A)
- td(A) == 5
- A* = if condition True then A else B
- C = A*
- >>> expression = 'C = if(td(A) == 5 || start_date() > "2010-01-01", A, B)'
- >>> p.parse(expression, 'stvds')
- td(A)
- td(A) == 5
- start_date > "2010-01-01"
- True || True
- A* = if condition True then A else B
- C = A*
- @endcode
- """
- try:
- import ply.lex as lex
- import ply.yacc as yacc
- except:
- pass
- import os
- from space_time_datasets import *
- from factory import *
- from open_stds import *
- import copy
- from grass.exceptions import FatalError
- ##############################################################################
- class TemporalAlgebraLexer(object):
- """!Lexical analyzer for the GRASS GIS temporal algebra"""
- # Functions that defines an if condition, temporal buffering and snapping
- conditional_functions = {
- 'if' : 'IF',
- 'buff_t': 'BUFF_T',
- 'tsnap' : 'TSNAP',
- 'tshift' : 'TSHIFT',
- }
- # Variables with date and time strings
- datetime_functions = {
- 'start_time' : 'START_TIME', # start time as HH::MM:SS
- 'start_date' : 'START_DATE', # start date as yyyy-mm-DD
- 'start_datetime' : 'START_DATETIME', # start datetime as yyyy-mm-DD HH:MM:SS
- 'end_time' : 'END_TIME', # end time as HH:MM:SS
- 'end_date' : 'END_DATE', # end date as yyyy-mm-DD
- 'end_datetime' : 'END_DATETIME', # end datetime as yyyy-mm-DD HH:MM:SS
- }
- # Time functions
- time_functions = {
- 'td' : 'TD', # The size of the current
- # sample time interval in days and
- # fraction of days for absolute time,
- # and in relative units in case of relative time.
- #'start_td' : 'START_TD', # The time difference between the start
- # time of the sample space time raster
- # dataset and the start time of the
- # current sample interval or instance.
- # The time is measured in days and
- # fraction of days for absolute time,
- # and in relative units in case of relative time.
- #'end_td' : 'END_TD', # The time difference between the
- # start time of the sample
- # space time raster dataset and the
- # end time of the current sample interval.
- # The time is measured in days and
- # fraction of days for absolute time,
- # and in relative units in case of relative time.
- # The end_time() will be represented by null() in case of a time instance.
- 'start_doy' : 'START_DOY', # Day of year (doy) from the start time [1 - 366]
- 'start_dow' : 'START_DOW', # Day of week (dow) from the start time [1 - 7], the start of the week is Monday == 1
- 'start_year' : 'START_YEAR', # The year of the start time [0 - 9999]
- 'start_month' : 'START_MONTH', # The month of the start time [1 - 12]
- 'start_week' : 'START_WEEK', # Week of year of the start time [1 - 54]
- 'start_day' : 'START_DAY', # Day of month from the start time [1 - 31]
- 'start_hour' : 'START_HOUR', # The hour of the start time [0 - 23]
- 'start_minute': 'START_MINUTE', # The minute of the start time [0 - 59]
- 'start_second': 'START_SECOND', # The second of the start time [0 - 59]
- 'end_doy' : 'END_DOY', # Day of year (doy) from the end time [1 - 366]
- 'end_dow' : 'END_DOW', # Day of week (dow) from the end time [1 - 7], the start of the week is Monday == 1
- 'end_year' : 'END_YEAR', # The year of the end time [0 - 9999]
- 'end_month' : 'END_MONTH', # The month of the end time [1 - 12]
- 'end_week' : 'END_WEEK', # Week of year of the end time [1 - 54]
- 'end_day' : 'END_DAY', # Day of month from the start time [1 - 31]
- 'end_hour' : 'END_HOUR', # The hour of the end time [0 - 23]
- 'end_minute' : 'END_MINUTE', # The minute of the end time [0 - 59]
- 'end_second' : 'END_SECOND', # The second of the end time [0 - 59]
- }
- # This is the list of token names.
- tokens = (
- 'DATETIME',
- 'TIME',
- 'DATE',
- 'INT',
- 'FLOAT',
- 'LPAREN',
- 'RPAREN',
- 'COMMA',
- 'CEQUALS',
- 'EQUALS',
- 'UNEQUALS',
- 'LOWER',
- 'LOWER_EQUALS',
- 'GREATER',
- 'GREATER_EQUALS',
- 'HASH',
- 'OR',
- 'AND',
- 'T_SELECT_OPERATOR',
- 'T_HASH_OPERATOR',
- 'T_COMP_OPERATOR',
- 'T_REL_OPERATOR',
- 'T_SELECT',
- 'T_NOT_SELECT',
- 'NAME',
- 'QUOTE',
- )
- # Build the token list
- tokens = tokens + tuple(datetime_functions.values()) \
- + tuple(time_functions.values()) \
- + tuple(conditional_functions.values())
- # Regular expression rules for simple tokens
- t_T_SELECT_OPERATOR = r'\{([a-zA-Z\| ]+[,])?([\|&+=]?[!]?[:])\}'
- t_T_HASH_OPERATOR = r'\{([a-zA-Z\| ]+[,])?[#]\}'
- t_T_COMP_OPERATOR = r'\{([a-zA-Z\| ]+[,])?(\|\||&&)\}'
- t_T_REL_OPERATOR = r'\{([a-zA-Z\| ])+\}'
- t_T_SELECT = r':'
- t_T_NOT_SELECT = r'!:'
- t_LPAREN = r'\('
- t_RPAREN = r'\)'
- t_COMMA = r','
- t_CEQUALS = r'=='
- t_EQUALS = r'='
- t_UNEQUALS = r'!='
- t_LOWER = r'<'
- t_LOWER_EQUALS = r'<='
- t_GREATER = r'>'
- t_GREATER_EQUALS = r'>='
- t_HASH = r'\#'
- t_OR = r'[\|]'
- t_AND = r'[&]'
- t_QUOTE = r'[\"\']'
- # These are the things that should be ignored.
- t_ignore = ' \t'
- # Read time string and convert it into a date object
- def t_DATETIME(self, t):
- 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)"'
- # t.value = int(t.value)
- return t
- # Read date string and convert it into a date object
- def t_DATE(self, t):
- r'"\d\d\d\d-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])"'
- # t.value = int(t.value)
- return t
- # Read time string and convert it into a date object
- def t_TIME(self, t):
- 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)"'
- # t.value = int(t.value)
- return t
- # Read in a float. This rule has to be done before the int rule.
- def t_FLOAT(self, t):
- r'-?\d+\.\d*(e-?\d+)?'
- t.value = float(t.value)
- return t
- # Read in an int.
- def t_INT(self, t):
- r'-?\d+'
- t.value = int(t.value)
- return t
- # Read in a list of maps.
- def t_LIST(self, t):
- r'[\[][.]*[\]]'
- t.value = list(t.value)
- return t
- # Ignore comments.
- # def t_comment(self, t):
- # r'^[#][^\n]*'
- # pass
- # Track line numbers.
- def t_newline(self, t):
- r'\n+'
- t.lineno += len(t.value)
- def t_NAME(self, t):
- r'[a-zA-Z_][a-zA-Z_0-9]*'
- self.temporal_symbol(t)
- return t
- # Parse symbols
- def temporal_symbol(self, t):
- # Check for reserved words
- if t.value in TemporalAlgebraLexer.time_functions.keys():
- t.type = TemporalAlgebraLexer.time_functions.get(t.value)
- elif t.value in TemporalAlgebraLexer.datetime_functions.keys():
- t.type = TemporalAlgebraLexer.datetime_functions.get(t.value)
- elif t.value in TemporalAlgebraLexer.conditional_functions.keys():
- t.type = TemporalAlgebraLexer.conditional_functions.get(t.value)
- else:
- t.type = 'NAME'
- return t
- # Handle errors.
- def t_error(self, t):
- raise SyntaxError("syntax error on line %d near '%s'" %
- (t.lineno, t.value))
- # Build the lexer
- def build(self,**kwargs):
- self.lexer = lex.lex(module=self, optimize=False, debug=False, **kwargs)
- # Just for testing
- def test(self,data):
- self.name_list = {}
- print(data)
- self.lexer.input(data)
- while True:
- tok = self.lexer.token()
- if not tok: break
- print tok
- ###############################################################################
- class GlobalTemporalVar(object):
- """ This class handles global temporal variable conditional expressions,
- like start_doy() == 3.
- The three parts of the statement are stored separately in
- tfunc (START_DOY), compop (==) and value (3).
- But also boolean values, time differences and relation operators for comparison in
- if-statements can be stored in this class.
- """
- def __init__(self):
- self.tfunc = None
- self.compop = None
- self.value = None
- self.boolean = None
- self.relationop = None
- self.topology = []
- self.td = None
- def get_type(self):
- if self.tfunc != None and self.compop != None and self.value != None:
- return("global")
- elif self.boolean != None:
- return("boolean")
- elif self.relationop != None and self.topology != []:
- return("operator")
- elif self.td != None:
- return("timediff")
- def get_type_value(self):
- typename = self.get_type()
- valuelist = []
- if typename == "global":
- valuelist = [self.tfunc, self.compop, self.value]
- elif typename == "operator":
- valuelist.append(self.topology)
- valuelist.append(self.relationop)
- elif typename == "boolean":
- valuelist = self.boolean
- elif typename == "timediff":
- valuelist.append(self.td)
- return(valuelist)
- def __str__(self):
- return str(self.tfunc) + str(self.compop) + str(self.value)
- ###############################################################################
- class TemporalAlgebraParser(object):
- """The temporal algebra class"""
- # Get the tokens from the lexer class
- tokens = TemporalAlgebraLexer.tokens
- # Setting equal precedence level for select and hash operations.
- precedence = (
- ('left', 'T_SELECT_OPERATOR', 'T_SELECT', 'T_NOT_SELECT'), # 1
- ('left', 'AND', 'OR', 'T_COMP_OPERATOR'), #2
- )
- def __init__(self, pid=None, run = True, debug = False, spatial = False, null = False):
- self.run = run
- self.debug = debug
- self.pid = pid
- # Intermediate vector map names
- self.names = {}
- # Count map names
- self.spatial = spatial
- self.null = null
- self.mapset = get_current_mapset()
- self.temporaltype = None
- self.msgr = get_tgis_message_interface()
- self.dbif = SQLDatabaseInterfaceConnection()
- self.dbif.connect()
- def __del__(self):
- if self.dbif.connected:
- self.dbif.close()
- def parse(self, expression, stdstype = 'strds', basename = None, overwrite=False):
- self.lexer = TemporalAlgebraLexer()
- self.lexer.build()
- self.parser = yacc.yacc(module=self, debug=self.debug)
- self.overwrite = overwrite
- self.count = 0
- self.stdstype = stdstype
- self.basename = basename
- self.expression = expression
- self.parser.parse(expression)
- def generate_map_name(self):
- """!Generate an unique intermediate vector map name
- and register it in the objects map list for later removement.
- The vector map names are unique between processes. Do not use the
- same object for map name generation in multiple threads.
- """
- self.count += 1
- if self.pid != None:
- pid = self.pid
- else:
- pid = os.getpid()
- name = "tmp_map_name_%i_%i"%(pid, self.count)
- self.names[name] = name
- return name
- def generate_new_map(self, base_map, bool_op = 'and', copy = True):
- """!Generate a new map using the spatio-temporal extent of the base map
- @param base_map This map is used to create the new map
- """
- # Generate an intermediate name for the result map list.
- name = self.generate_map_name()
- # Check for mapset in given stds input.
- mapname = name + "@" + self.mapset
- # Create new map based on the related map list.
- map_new = base_map.get_new_instance(mapname)
- # Set initial map extend of new vector map.
- self.overlay_map_extent(map_new, base_map, bool_op = bool_op, copy = copy)
- return map_new
- def overlay_map_extent(self, mapA, mapB, bool_op = None, temp_op = '=',
- copy = False):
- """!Compute the spatio-temporal extent of two topological related maps
- @param mapA The first map
- @param mapB The second maps
- @param bool_op The boolean operator specifying the spatial extent
- operation (intersection, union, disjoint union)
- @param temp_op The temporal operator specifying the temporal
- extent operation (intersection, union, disjoint union)
- @param copy Specifies if the temporal extent of mapB should be
- copied to mapA
- @return 0 if there is no overlay
- """
- returncode = 1
- if copy:
- map_extent_temporal = mapB.get_temporal_extent()
- map_extent_spatial = mapB.get_spatial_extent()
- # Set initial map extend of new vector map.
- mapA.set_spatial_extent(map_extent_spatial)
- mapA.set_temporal_extent(map_extent_temporal)
- if "cmd_list" in dir(mapB):
- mapA.cmd_list = mapB.cmd_list
- else:
- # Calculate spatial extent for different overlay operations.
- if bool_op == 'and':
- overlay_ext = mapA.spatial_intersection(mapB)
- if overlay_ext != None:
- mapA.set_spatial_extent(overlay_ext)
- else:
- returncode = 0
- elif bool_op in ['or', 'xor']:
- overlay_ext = mapA.spatial_union(mapB)
- if overlay_ext != None:
- mapA.set_spatial_extent(overlay_ext)
- else:
- returncode = 0
- elif bool_op == 'disor':
- overlay_ext = mapA.spatial_disjoint_union(mapB)
- if overlay_ext != None:
- mapA.set_spatial_extent(overlay_ext)
- else:
- returncode = 0
- # Calculate temporal extent for different temporal operators.
- if temp_op == '&':
- temp_ext = mapA.temporal_intersection(mapB)
- if temp_ext != None:
- mapA.set_temporal_extent(temp_ext)
- else:
- returncode = 0
- elif temp_op == '|':
- temp_ext = mapA.temporal_union(mapB)
- if temp_ext != None:
- mapA.set_temporal_extent(temp_ext)
- else:
- returncode = 0
- elif temp_op == '+':
- temp_ext = mapA.temporal_disjoint_union(mapB)
- if temp_ext != None:
- mapA.set_temporal_extent(temp_ext)
- else:
- returncode = 0
- return(returncode)
- ######################### Temporal functions ##############################
- def check_stds(self, input, clear = False):
- """! Check if input space time dataset exist in database and return its map list.
- @param input Name of space time data set as string or list of maps.
- @param clear Reset the stored conditional values to empty list.
- @return List of maps.
- """
- if not isinstance(input, list):
- # Check for mapset in given stds input.
- if input.find("@") >= 0:
- id_input = input
- else:
- id_input = input + "@" + self.mapset
- # Create empty spacetime dataset.
- stds = dataset_factory(self.stdstype, id_input)
- # Check for occurence of space time dataset.
- if stds.is_in_db(dbif=self.dbif) == False:
- raise FatalError(_("Space time %s dataset <%s> not found") %
- (stds.get_new_map_instance(None).get_type(), id_input))
- else:
- # Select temporal dataset entry from database.
- stds.select(dbif=self.dbif)
- maplist = stds.get_registered_maps_as_objects(dbif=self.dbif)
- # Create map_value as empty list item.
- for map_i in maplist:
- if "map_value" not in dir(map_i):
- map_i.map_value = []
- if "condition_value" not in dir(map_i):
- map_i.condition_value = []
- # Set and check global temporal type variable and map.
- if map_i.is_time_absolute() and self.temporaltype == None:
- self.temporaltype = 'absolute'
- elif map_i.is_time_relative() and self.temporaltype == None:
- self.temporaltype = 'relative'
- elif map_i.is_time_absolute() and self.temporaltype == 'relative':
- self.msgr.fatal(_("Wrong temporal type of space time dataset <%s> \
- <%s> time is required") %
- (id_input, self.temporaltype))
- elif map_i.is_time_relative() and self.temporaltype == 'absolute':
- self.msgr.fatal(_("Wrong temporal type of space time dataset <%s> \
- <%s> time is required") %
- (id_input, self.temporaltype))
- else:
- maplist = input
- # Create map_value as empty list item.
- for map_i in maplist:
- if "map_value" not in dir(map_i):
- map_i.map_value = []
- elif clear:
- map_i.map_value = []
- if "condition_value" not in dir(map_i):
- map_i.condition_value = []
- elif clear:
- map_i.condition_value = []
- return(maplist)
- def get_temporal_topo_list(self, maplistA, maplistB = None, topolist = ["EQUAL"],
- assign_val = False, count_map = False):
- """!Build temporal topology for two space time data sets, copy map objects
- for given relation into map list.
- @param maplistA List of maps.
- @param maplistB List of maps.
- @param topolist List of strings of temporal relations.
- @param assign_val Boolean for assigning a boolean map value based on
- the map_values from the compared map list by
- topological relationships.
- @param count_map Boolean if the number of topological related maps
- should be returned.
- @return List of maps from maplistA that fulfil the topological relationships
- to maplistB specified in topolist.
- @code
- # Example with two lists of maps
- >>> import grass.temporal as tgis
- >>> tgis.init(True)
- >>> l = tgis.TemporalAlgebraParser()
- >>> # Create two list of maps with equal time stamps
- >>> mapsA = []
- >>> mapsB = []
- >>> for i in range(10):
- ... idA = "a%i@B"%(i)
- ... mapA = tgis.RasterDataset(idA)
- ... idB = "b%i@B"%(i)
- ... mapB = tgis.RasterDataset(idB)
- ... check = mapA.set_relative_time(i, i + 1, "months")
- ... check = mapB.set_relative_time(i, i + 1, "months")
- ... mapsA.append(mapA)
- ... mapsB.append(mapB)
- >>> resultlist = l.get_temporal_topo_list(mapsA, mapsB, ['EQUAL'])
- >>> for map in resultlist:
- ... if map.get_equal():
- ... relations = map.get_equal()
- ... print "Map %s has equal relation to map %s"%(map.get_name(),
- ... relations[0].get_name())
- Map a0 has equal relation to map b0
- Map a1 has equal relation to map b1
- Map a2 has equal relation to map b2
- Map a3 has equal relation to map b3
- Map a4 has equal relation to map b4
- Map a5 has equal relation to map b5
- Map a6 has equal relation to map b6
- Map a7 has equal relation to map b7
- Map a8 has equal relation to map b8
- Map a9 has equal relation to map b9
- >>> resultlist = l.get_temporal_topo_list(mapsA, mapsB, ['DURING'])
- >>> print(resultlist)
- []
- >>> # Create two list of maps with equal time stamps
- >>> mapsA = []
- >>> mapsB = []
- >>> for i in range(10):
- ... idA = "a%i@B"%(i)
- ... mapA = tgis.RasterDataset(idA)
- ... idB = "b%i@B"%(i)
- ... mapB = tgis.RasterDataset(idB)
- ... check = mapA.set_relative_time(i, i + 1, "months")
- ... check = mapB.set_relative_time(i, i + 2, "months")
- ... mapsA.append(mapA)
- ... mapsB.append(mapB)
- >>> resultlist = l.get_temporal_topo_list(mapsA, mapsB, ['starts','during'])
- >>> for map in resultlist:
- ... if map.get_starts():
- ... relations = map.get_starts()
- ... print "Map %s has start relation to map %s"%(map.get_name(),
- ... relations[0].get_name())
- Map a0 has start relation to map b0
- Map a1 has start relation to map b1
- Map a2 has start relation to map b2
- Map a3 has start relation to map b3
- Map a4 has start relation to map b4
- Map a5 has start relation to map b5
- Map a6 has start relation to map b6
- Map a7 has start relation to map b7
- Map a8 has start relation to map b8
- Map a9 has start relation to map b9
- >>> for map in resultlist:
- ... if map.get_during():
- ... relations = map.get_during()
- ... print "Map %s has during relation to map %s"%(map.get_name(),
- ... relations[0].get_name())
- Map a0 has during relation to map b0
- Map a1 has during relation to map b0
- Map a2 has during relation to map b1
- Map a3 has during relation to map b2
- Map a4 has during relation to map b3
- Map a5 has during relation to map b4
- Map a6 has during relation to map b5
- Map a7 has during relation to map b6
- Map a8 has during relation to map b7
- Map a9 has during relation to map b8
- >>> # Create two list of maps with equal time stamps and map_value method.
- >>> mapsA = []
- >>> mapsB = []
- >>> for i in range(10):
- ... idA = "a%i@B"%(i)
- ... mapA = tgis.RasterDataset(idA)
- ... idB = "b%i@B"%(i)
- ... mapB = tgis.RasterDataset(idB)
- ... check = mapA.set_relative_time(i, i + 1, "months")
- ... check = mapB.set_relative_time(i, i + 1, "months")
- ... mapB.map_value = True
- ... mapsA.append(mapA)
- ... mapsB.append(mapB)
- >>> # Create two list of maps with equal time stamps
- >>> mapsA = []
- >>> mapsB = []
- >>> for i in range(10):
- ... idA = "a%i@B"%(i)
- ... mapA = tgis.RasterDataset(idA)
- ... mapA.map_value = True
- ... idB = "b%i@B"%(i)
- ... mapB = tgis.RasterDataset(idB)
- ... mapB.map_value = False
- ... check = mapA.set_absolute_time(datetime(2000,1,i+1),
- ... datetime(2000,1,i + 2))
- ... check = mapB.set_absolute_time(datetime(2000,1,i+6),
- ... datetime(2000,1,i + 7))
- ... mapsA.append(mapA)
- ... mapsB.append(mapB)
- >>> resultlist = l.get_temporal_topo_list(mapsA, mapsB)
- >>> for map in resultlist:
- ... print(map.get_id())
- a5@B
- a6@B
- a7@B
- a8@B
- a9@B
- >>> resultlist = l.get_temporal_topo_list(mapsA, mapsB, ['during'])
- >>> for map in resultlist:
- ... print(map.get_id())
- @endcode
- """
- topologylist = ["EQUAL", "FOLLOWS", "PRECEDES", "OVERLAPS", "OVERLAPPED", \
- "DURING", "STARTS", "FINISHES", "CONTAINS", "STARTED", \
- "FINISHED"]
- complementdict = {"EQUAL": "EQUAL", "FOLLOWS" : "PRECEDES",
- "PRECEDES" : "FOLLOWS", "OVERLAPS" : "OVERLAPPED",
- "OVERLAPPED" : "OVERLAPS", "DURING" : "CONTAINS",
- "CONTAINS" : "DURING", "STARTS" : "STARTED",
- "STARTED" : "STARTS", "FINISHES" : "FINISHED",
- "FINISHED" : "FINISHES"}
- resultdict = {}
- # Check if given temporal relation are valid.
- for topo in topolist:
- if topo.upper() not in topologylist:
- raise SyntaxError("Unpermitted temporal relation name '" + topo + "'")
- # Create temporal topology for maplistA to maplistB.
- tb = SpatioTemporalTopologyBuilder()
- # Dictionary with different spatial variables used for topology builder.
- spatialdict = {'strds' : '2D', 'stvds' : '2D', 'str3ds' : '3D'}
- # Build spatial temporal topology
- if self.spatial:
- tb.build(maplistA, maplistB, spatial = spatialdict[self.stdstype])
- else:
- tb.build(maplistA, maplistB)
- # Iterate through maps in maplistA and search for relationships given
- # in topolist.
- # TODO: Better implementation with less nesting
- for map_i in maplistA:
- tbrelations = map_i.get_temporal_relations()
- for topo in topolist:
- if topo.upper() in tbrelations.keys():
- if assign_val:
- mapvaluelist = []
- if complementdict[topo.upper()] in tbrelations:
- relationmaplist = tbrelations[complementdict[topo.upper()]]
- for relationmap in relationmaplist:
- if "map_value" in dir(relationmap):
- for element in relationmap.map_value:
- if isinstance(element, GlobalTemporalVar):
- if element.get_type() == "boolean":
- mapvaluelist.append(element.boolean)
- if all(mapvaluelist):
- resultbool = True
- else:
- resultbool = False
- if "condition_value" in dir(map_i):
- if isinstance(map_i.condition_value, list):
- map_i.condition_value.append(resultbool)
- if count_map:
- relationmaplist = tbrelations[topo.upper()]
- gvar = GlobalTemporalVar()
- gvar.td = len(relationmaplist)
- if "map_value" in dir(map_i):
- map_i.map_value.append(gvar)
- else:
- map_i.map_value = gvar
- resultdict[map_i.get_id()] = map_i
- resultlist = resultdict.values()
- # Sort list of maps chronological.
- resultlist = sorted(resultlist, key = AbstractDatasetComparisonKeyStartTime)
- return(resultlist)
- def eval_toperator(self, operator):
- """!This function evaluates a string containing temporal operations.
- @param operator String of temporal operations, e.g. {equal|during,=!:}.
- @return List of temporal relations (equal, during), the given function
- (!:) and the interval/instances (=).
- @code
- >>> import grass.temporal as tgis
- >>> tgis.init()
- >>> p = tgis.TemporalAlgebraParser()
- >>> operator = "{equal,:}"
- >>> p.eval_toperator(operator)
- (['equal'], '=', ':')
- >>> operator = "{equal|during,:}"
- >>> p.eval_toperator(operator)
- (['equal', 'during'], '=', ':')
- >>> operator = "{equal,!:}"
- >>> p.eval_toperator(operator)
- (['equal'], '=', '!:')
- >>> operator = "{equal|during,!:}"
- >>> p.eval_toperator(operator)
- (['equal', 'during'], '=', '!:')
- >>> operator = "{equal|during,=!:}"
- >>> p.eval_toperator(operator)
- (['equal', 'during'], '=', '!:')
- >>> operator = "{equal|during|starts,#}"
- >>> p.eval_toperator(operator)
- (['equal', 'during', 'starts'], '=', '#')
- >>> operator = "{!:}"
- >>> p.eval_toperator(operator)
- (['equal'], '=', '!:')
- >>> operator = "{=:}"
- >>> p.eval_toperator(operator)
- (['equal'], '=', ':')
- >>> operator = "{#}"
- >>> p.eval_toperator(operator)
- (['equal'], '=', '#')
- >>> operator = "{equal|during}"
- >>> p.eval_toperator(operator)
- (['equal', 'during'], '=', '')
- >>> operator = "{equal}"
- >>> p.eval_toperator(operator)
- (['equal'], '=', '')
- >>> operator = "{equal,||}"
- >>> p.eval_toperator(operator)
- (['equal'], '=', '||')
- >>> operator = "{equal|during,&&}"
- >>> p.eval_toperator(operator)
- (['equal', 'during'], '=', '&&')
- @endcode
- """
- topologylist = ["EQUAL", "FOLLOWS", "PRECEDES", "OVERLAPS", "OVERLAPPED", \
- "DURING", "STARTS", "FINISHES", "CONTAINS", "STARTED", \
- "FINISHED"]
- functionlist = [":", "!:", "#"]
- intervallist = ["=", "|", "&", "+"]
- comparelist = ["||", "&&"]
- relations = []
- interval = '='
- function = ''
- op = operator.strip('{}')
- oplist = op.split(',')
- if len(oplist) > 1:
- relationlist = oplist[0].split('|')
- for relation in relationlist:
- if relation.upper() in topologylist and relation not in relations:
- relations.append(relation)
- else:
- raise SyntaxError("invalid syntax")
- opright = oplist[1]
- if opright in comparelist:
- function = opright
- elif opright[0] in intervallist:
- interval = opright[0]
- if opright[1:] in functionlist:
- function = opright[1:]
- else:
- raise SyntaxError("invalid syntax")
- elif opright in functionlist:
- function = opright
- else:
- raise SyntaxError("invalid syntax")
- elif all([rel.upper() in topologylist for rel in oplist[0].split('|')]):
- relations = oplist[0].split('|')
- else:
- relations = ['equal']
- opstr = str(oplist[0])
- if opstr[0] in intervallist:
- interval = opstr[0]
- if opstr[1:] in functionlist:
- function = opstr[1:]
- else:
- raise SyntaxError("invalid syntax")
- elif opstr in functionlist:
- function = opstr
- #else:
- #raise SyntaxError("invalid syntax")
- return(relations, interval, function)
- def perform_temporal_selection(self, maplistA, maplistB, topolist = ["EQUAL"],
- inverse = False, assign_val = False):
- """!This function performs temporal selection operation.
- @param maplistA List of maps representing the left side of a temporal
- expression.
- @param maplistB List of maps representing the right side of a temporal
- expression.
- @param topolist List of strings of temporal relations.
- @param inverse Boolean value that specifies if the selection should be
- inverted.
- @param assign_val Boolean for assigning a boolean map value based on
- the map_values from the compared map list by
- topological relationships.
- @return List of selected maps from maplistA.
- @code
- >>> import grass.temporal as tgis
- >>> tgis.init()
- >>> l = tgis.TemporalAlgebraParser()
- >>> # Example with two lists of maps
- >>> # Create two list of maps with equal time stamps
- >>> mapsA = []
- >>> mapsB = []
- >>> for i in range(10):
- ... idA = "a%i@B"%(i)
- ... mapA = tgis.RasterDataset(idA)
- ... idB = "b%i@B"%(i)
- ... mapB = tgis.RasterDataset(idB)
- ... check = mapA.set_relative_time(i, i + 1, "months")
- ... check = mapB.set_relative_time(i + 5, i + 6, "months")
- ... mapsA.append(mapA)
- ... mapsB.append(mapB)
- >>> resultlist = l.perform_temporal_selection(mapsA, mapsB, ['EQUAL'],
- ... False)
- >>> for map in resultlist:
- ... if map.get_equal():
- ... relations = map.get_equal()
- ... print "Map %s has equal relation to map %s"%(map.get_name(),
- ... relations[0].get_name())
- Map a5 has equal relation to map b0
- Map a6 has equal relation to map b1
- Map a7 has equal relation to map b2
- Map a8 has equal relation to map b3
- Map a9 has equal relation to map b4
- >>> resultlist = l.perform_temporal_selection(mapsA, mapsB, ['EQUAL'],
- ... True)
- >>> for map in resultlist:
- ... if not map.get_equal():
- ... print "Map %s has no equal relation to mapset mapsB"%(map.get_name())
- Map a0 has no equal relation to mapset mapsB
- Map a1 has no equal relation to mapset mapsB
- Map a2 has no equal relation to mapset mapsB
- Map a3 has no equal relation to mapset mapsB
- Map a4 has no equal relation to mapset mapsB
- @endcode
- """
- if not inverse:
- topolist = self.get_temporal_topo_list(maplistA, maplistB, topolist,
- assign_val = assign_val)
- resultlist = topolist
- else:
- topolist = self.get_temporal_topo_list(maplistA, maplistB, topolist,
- assign_val = False)
- resultlist = []
- for map_i in maplistA:
- if map_i not in topolist:
- resultlist.append(map_i)
- if assign_val:
- if "condition_value" in dir(map_i):
- map_i.condition_value.append(False)
- # Sort list of maps chronological.
- resultlist = sorted(resultlist, key = AbstractDatasetComparisonKeyStartTime)
- return(resultlist)
- def set_granularity(self, maplistA, maplistB, toperator = '=', topolist = ["EQUAL"]):
- """!This function sets the temporal extends of a list of maps based on
- another map list.
- @param maplistB List of maps.
- @param maplistB List of maps.
- @param toperator String containing the temporal operator: =, +, &, |.
- @param topolist List of topological relations.
- @return List of maps with the new temporal extends.
- @code
- >>> import grass.temporal as tgis
- >>> tgis.init()
- >>> p = tgis.TemporalAlgebraParser()
- >>> # Create two list of maps with equal time stamps
- >>> mapsA = []
- >>> mapsB = []
- >>> for i in range(10):
- ... idA = "a%i@B"%(i)
- ... mapA = tgis.RasterDataset(idA)
- ... idB = "b%i@B"%(i)
- ... mapB = tgis.RasterDataset(idB)
- ... check = mapA.set_relative_time(i, i + 1, "months")
- ... check = mapB.set_relative_time(i*2, i*2 + 2, "months")
- ... mapsA.append(mapA)
- ... mapsB.append(mapB)
- >>> resultlist = p.set_granularity(mapsA, mapsB, toperator = "|", topolist = ["during"])
- >>> for map in resultlist:
- ... start,end,unit = map.get_relative_time()
- ... print(map.get_id() + ' - start: ' + str(start) + ' end: ' + str(end))
- a1@B - start: 0 end: 2
- a0@B - start: 0 end: 2
- a3@B - start: 2 end: 4
- a2@B - start: 2 end: 4
- a5@B - start: 4 end: 6
- a4@B - start: 4 end: 6
- a7@B - start: 6 end: 8
- a6@B - start: 6 end: 8
- a9@B - start: 8 end: 10
- a8@B - start: 8 end: 10
- @endcode
- """
- topologylist = ["EQUAL", "FOLLOWS", "PRECEDES", "OVERLAPS", "OVERLAPPED", \
- "DURING", "STARTS", "FINISHES", "CONTAINS", "STARTED", \
- "FINISHED"]
- for topo in topolist:
- if topo.upper() not in topologylist:
- raise SyntaxError("Unpermitted temporal relation name '" + topo + "'")
- # Create temporal topology for maplistA to maplistB.
- tb = SpatioTemporalTopologyBuilder()
- # Dictionary with different spatial variables used for topology builder.
- spatialdict = {'strds' : '2D', 'stvds' : '2D', 'str3ds' : '3D'}
- # Build spatial temporal topology for maplistB to maplistB.
- if self.spatial:
- tb.build(maplistA, maplistB, spatial = spatialdict[self.stdstype])
- else:
- tb.build(maplistA, maplistB)
- resultdict = {}
- # Iterate through maps in maplistA and search for relationships given
- # in topolist.
- for map_i in maplistA:
- tbrelations = map_i.get_temporal_relations()
- for topo in topolist:
- if topo.upper() in tbrelations.keys():
- relationmaplist = tbrelations[topo.upper()]
- for relationmap in relationmaplist:
- newextend = None
- if toperator == "&":
- newextend = map_i.temporal_intersection(relationmap)
- elif toperator == "|":
- newextend = map_i.temporal_union(relationmap)
- elif toperator == "+":
- newextend = map_i.temporal_disjoint_union(relationmap)
- elif toperator == "=":
- resultdict[map_i.get_id()] = map_i
- if newextend != None:
- start = newextend.get_start_time()
- end = newextend.get_end_time()
- #print(map_i.get_id() + ' - start: ' + str(start) + ' end: ' + str(end))
- if map_i.is_time_absolute():
- map_i.set_absolute_time(start, end)
- else:
- relunit = map_i.get_relative_time_unit()
- map_i.set_relative_time(int(start), int(end), relunit)
- resultdict[map_i.get_id()] = map_i
- resultlist = resultdict.values()
- # Sort list of maps chronological.
- resultlist = sorted(resultlist, key = AbstractDatasetComparisonKeyStartTime)
- # Get relations to maplistB per map in A.
- # Loop over all relations from list
- # temporal extent = map.temporal_intersection(map)
- # if temporal extend is None = delete map.
- return(resultlist)
- def get_temporal_func_dict(self, map):
- """! This function creates a dictionary containing temporal functions for a
- map dataset with time stamp.
- @param map Map object with time stamps.
- @return Dictionary with temporal functions for given input map.
- @code
- >>> import grass.temporal as tgis
- >>> import datetime
- >>> tgis.init()
- >>> l = tgis.TemporalAlgebraParser()
- >>> # Example with one list of maps
- >>> # Create one list of maps with equal time stamps
- >>> for i in range(1):
- ... idA = "a%i@B"%(i)
- ... mapA = tgis.RasterDataset(idA)
- ... check = mapA.set_absolute_time(datetime.datetime(2000,1,1),
- ... datetime.datetime(2000,10,1))
- ... tfuncdict = l.get_temporal_func_dict(mapA)
- >>> print(tfuncdict["START_YEAR"])
- 2000
- >>> print(tfuncdict["START_TIME"])
- 00:00:00
- >>> print(tfuncdict["START_DATE"])
- 2000-01-01
- >>> print(tfuncdict["START_DATETIME"])
- 2000-01-01 00:00:00
- @endcode
- """
- tvardict = {"START_DOY" : None, "START_DOW" : None, "START_YEAR" : None,
- "START_MONTH" : None, "START_WEEK" : None, "START_DAY" : None,
- "START_HOUR" : None, "START_MINUTE" : None, "START_SECOND" : None,
- "END_DOY" : None, "END_DOW" : None, "END_YEAR" : None,
- "END_MONTH" : None, "END_WEEK" : None, "END_DAY" : None,
- "END_HOUR" : None, "END_MINUTE" : None, "END_SECOND" : None,
- "START_DATE" : None, "START_DATETIME" : None, "START_TIME" : None,
- "END_DATE" : None, "END_DATETIME" : None, "END_TIME" : None}
- # Compute temporal function only for maps with absolute time reference.
- if map.is_time_absolute:
- # Get datetime of map.
- start, end = map.get_absolute_time()
- # Compute DOY via time deltas.
- yearstart = datetime(start.year, 1, 1)
- yearend = datetime(end.year, 1, 1)
- deltastart = start - yearstart
- deltaend = end - yearend
- # Evaluate datetime objects and fill in into dict.
- tvardict["START_DOY"] = deltastart.days + 1
- tvardict["START_DOW"] = start.isoweekday()
- tvardict["START_YEAR"] = start.year
- tvardict["START_MONTH"] = start.month
- tvardict["START_WEEK"] = start.isocalendar()[1]
- tvardict["START_DAY"] = start.day
- tvardict["START_HOUR"] = start.hour
- tvardict["START_MINUTE"] = start.minute
- tvardict["START_SECOND"] = start.second
- tvardict["END_DOY"] = deltaend.days + 1
- tvardict["END_DOW"] = end.isoweekday()
- tvardict["END_YEAR"] = end.year
- tvardict["END_MONTH"] = end.month
- tvardict["END_WEEK"] = end.isocalendar()[1]
- tvardict["END_DAY"] = end.day
- tvardict["END_HOUR"] = end.hour
- tvardict["END_MINUTE"] = end.minute
- tvardict["END_SECOND"] = end.second
- tvardict["START_DATE"] = start.date()
- tvardict["START_DATETIME"] = start
- tvardict["START_TIME"] = start.time()
- tvardict["END_DATE"] = end.date()
- tvardict["END_DATETIME"] = end
- tvardict["END_TIME"] = end.time()
- if not map.is_time_absolute:
- tvardict["START_DATE"] = start.date()
- tvardict["START_DATETIME"] = start
- tvardict["START_TIME"] = start.time()
- tvardict["END_DATE"] = end.date()
- tvardict["END_DATETIME"] = end
- tvardict["END_TIME"] = end.time()
- #core.fatal(_("The temporal functions for map <%s> only supported for absolute"\
- # "time." % (str(map.get_id()))))
- return(tvardict)
- def eval_datetime_str(self, tfuncval, comp, value):
- # Evaluate date object comparison expression.
- if comp == "<":
- boolname = eval(str(tfuncval < value))
- elif comp == ">":
- boolname = eval(str(tfuncval > value))
- elif comp == "==":
- boolname = eval(str(tfuncval == value))
- elif comp == "<=":
- boolname = eval(str(tfuncval <= value))
- elif comp == ">=":
- boolname = eval(str(tfuncval >= value))
- elif comp == "!=":
- boolname = eval(str(tfuncval != value))
- return(boolname)
- def eval_global_var(self, gvar, maplist):
- """! This function evaluates a global variable expression for a map list.
- For example: start_day() > 5 , end_month() == 2.
- @param gvar Object of type GlobalTemporalVar containing temporal.
- @param maplist List of map objects.
- @return List of maps from maplist with added conditional boolean values.
- """
- boollist = []
- # Loop over maps of input map list.
- for map_i in maplist:
- # Get dictionary with temporal variables for the map.
- tfuncdict = self.get_temporal_func_dict(map_i)
- # Get value from global variable.
- value = gvar.value
- # Get comparison operator from global variable, like <, >, <=, >=, ==, !=
- comp_op = gvar.compop
- # Get temporal function name for global variable.
- tfunc = gvar.tfunc.upper()
- # Get value for function name from dictionary.
- tfuncval = tfuncdict[tfunc]
- # Check if value has to be transfered to datetime object for comparison.
- if tfunc in ["START_DATE", "END_DATE"]:
- timeobj = datetime.strptime(value.replace("\"",""), '%Y-%m-%d')
- value = timeobj.date()
- boolname = self.eval_datetime_str(tfuncval, comp_op, value)
- elif tfunc in ["START_TIME", "END_TIME"]:
- timeobj = datetime.strptime(value.replace("\"",""), '%H:%M:%S')
- value = timeobj.time()
- boolname = self.eval_datetime_str(tfuncval, comp_op, value)
- elif tfunc in ["START_DATETIME", "END_DATETIME"]:
- timeobj = datetime.strptime(value.replace("\"",""), '%Y-%m-%d %H:%M:%S')
- value = timeobj
- boolname = self.eval_datetime_str(tfuncval, comp_op, value)
- else:
- boolname = eval(str(tfuncval) + comp_op + str(value))
- # Add conditional boolean value to the map.
- if "condition_value" in dir(map_i):
- map_i.condition_value.append(boolname)
- else:
- map_i.condition_value = boolname
- return(maplist)
- def eval_map_list(self, maplist ,thenlist, topolist = ["EQUAL"]):
- """! This function transfers boolean values from temporal expression
- from one map list to another by their topology. These boolean
- values are added to the maps as condition_value.
- @param maplist List of map objects containing boolean map values.
- @param thenlist List of map objects where the boolean values
- should be added.
- @return List of maps from thenlist with added conditional boolean values.
- """
- # Get topology of then statement map list in relation to the other maplist
- # and assign boolean values of the maplist to the thenlist.
- containlist = self.perform_temporal_selection(thenlist, maplist,
- assign_val = True,
- topolist = topolist)
- # Inverse selection of maps from thenlist and assigning False values.
- excludelist = self.perform_temporal_selection(thenlist, maplist,
- assign_val = True,
- inverse = True,
- topolist = topolist)
- # Combining the selection and inverse selection list.
- resultlist = containlist + excludelist
- return(resultlist)
- def build_condition_list(self, tvarexpr, thenlist, topolist = ["EQUAL"]):
- """! This function evaluates temporal variable expressions of a conditional
- expression related to the map list of the then statement.
- Global variables or map lists with booleans are compared to the topology
- of the conclusion map list and a conditional list will be appended to
- every map. It contain the boolean expressions from these comparisons
- and optional operators to combine several temporal expressions, like
- "&&" or "||".
- For example: td(A) == 1 && start_day() > 5 --> [True || False]
- (for one map.condition_value in a then map list)
- @param tvarexpr List of GlobalTemporalVar objects and map lists.
- The list is constructed by the TemporalAlgebraParser
- in order of expression evaluation in the parser.
- @param thenlist Map list object of the conclusion statement.
- It will be compared and evaluated by the conditions.
- @return Map list with conditional values for all temporal expressions.
- @code
- >>> import grass.temporal as tgis
- >>> tgis.init()
- >>> p = tgis.TemporalAlgebraParser()
- >>> # Example with two lists of maps
- >>> # Create two list of maps with equal time stamps
- >>> mapsA = []
- >>> mapsB = []
- >>> for i in range(10):
- ... idA = "a%i@B"%(i)
- ... mapA = tgis.RasterDataset(idA)
- ... idB = "b%i@B"%(i)
- ... mapB = tgis.RasterDataset(idB)
- ... check = mapA.set_absolute_time(datetime(2000,1,i + 1),
- ... datetime(2000,1,i + 2))
- ... check = mapB.set_absolute_time(datetime(2000,1,i + 6),
- ... datetime(2000,1,i + 7))
- ... mapsA.append(mapA)
- ... mapsB.append(mapB)
- >>> mapsA = p.check_stds(mapsA)
- >>> mapsB = p.check_stds(mapsB)
- >>> # Create global expression object.
- >>> gvarA = tgis.GlobalTemporalVar()
- >>> gvarA.tfunc = "start_day"
- >>> gvarA.compop = ">"
- >>> gvarA.value = 5
- >>> gvarB = tgis.GlobalTemporalVar()
- >>> gvarB.tfunc = "start_day"
- >>> gvarB.compop = "<="
- >>> gvarB.value = 8
- >>> gvarOP = tgis.GlobalTemporalVar()
- >>> gvarOP.relationop = "&&"
- >>> gvarOP.topology.append("EQUAL")
- >>> tvarexpr = gvarA
- >>> result = p.build_condition_list(tvarexpr, mapsA)
- >>> for map_i in result:
- ... print(map_i.get_map_id() + ' ' + str(map_i.condition_value))
- a0@B [False]
- a1@B [False]
- a2@B [False]
- a3@B [False]
- a4@B [False]
- a5@B [True]
- a6@B [True]
- a7@B [True]
- a8@B [True]
- a9@B [True]
- >>> tvarexpr = [gvarA, gvarOP, gvarB]
- >>> result = p.build_condition_list(tvarexpr, mapsB)
- >>> for map_i in result:
- ... print(map_i.get_map_id() + ' ' + str(map_i.condition_value))
- b0@B [True, ['EQUAL'], '&&', True]
- b1@B [True, ['EQUAL'], '&&', True]
- b2@B [True, ['EQUAL'], '&&', True]
- b3@B [True, ['EQUAL'], '&&', False]
- b4@B [True, ['EQUAL'], '&&', False]
- b5@B [True, ['EQUAL'], '&&', False]
- b6@B [True, ['EQUAL'], '&&', False]
- b7@B [True, ['EQUAL'], '&&', False]
- b8@B [True, ['EQUAL'], '&&', False]
- b9@B [True, ['EQUAL'], '&&', False]
- @endcode
- """
- # Check if the input expression is a valid single global variable.
- if not isinstance(tvarexpr, list):
- if isinstance(tvarexpr, GlobalTemporalVar):
- if tvarexpr.get_type() == "global":
- # Use method eval_global_var to evaluate expression.
- resultlist = self.eval_global_var(tvarexpr, thenlist)
- else:
- # Check if a given list is a list of maps.
- if all([issubclass(type(ele), AbstractMapDataset) for ele in tvarexpr]):
- # Use method eval_map_list to evaluate map_list in comparison to thenlist.
- resultlist = self.eval_map_list(tvarexpr, thenlist, topolist)
- # Loop through the list, search for map lists or global variables.
- for expr in tvarexpr:
- if isinstance(expr, list):
- if all([issubclass(type(ele), AbstractMapDataset) for ele in expr]):
- # Use method eval_map_list to evaluate map_list
- resultlist = self.eval_map_list(expr, thenlist, topolist)
- else:
- # Recursive function call to look into nested list elements.
- self.build_condition_list(expr, thenlist)
- elif isinstance(expr, GlobalTemporalVar):
- # Use according functions for different global variable types.
- if expr.get_type() == "operator":
- if all(["condition_value" in dir(map_i) for map_i in thenlist]):
- # Add operator string to the condition list.
- [map_i.condition_value.extend(expr.get_type_value()) for map_i in thenlist]
- if expr.get_type() == "global":
- # Use method eval_global_var to evaluate expression.
- resultlist = self.eval_global_var(expr, thenlist)
- # Sort resulting list of maps chronological.
- resultlist = sorted(resultlist, key = AbstractDatasetComparisonKeyStartTime)
- return(resultlist)
- def eval_condition_list(self, maplist, inverse = False):
- """! This function evaluates conditional values of a map list.
- A recursive function is used to evaluate comparison statements
- from left to right in the given conditional list.
- For example: [True, '||', False, '&&', True] -> True
- [True, '||', False, '&&', False] -> False
- [True, '&&', False, '&&', True] -> False
- [False, '||', True, '||', False] -> True
- [False, '&&', True, '&&', True] -> False
- [True, '&&', True, '&&', True] -> True
- [True, '&&', True] -> True
- [True, '&&', False] -> False
- [False, '||', True] -> True
- @param tvarexpr List of GlobalTemporalVar objects and map lists.
- The list is constructed by the TemporalAlgebraParser
- in order of expression evaluation in the parser.
- @return Map list with conditional values for all temporal expressions.
- @code
- >>> import grass.temporal as tgis
- >>> tgis.init()
- >>> p = tgis.TemporalAlgebraParser()
- >>> # Example with two lists of maps
- >>> # Create two list of maps with equal time stamps
- >>> mapsA = []
- >>> mapsB = []
- >>> for i in range(10):
- ... idA = "a%i@B"%(i)
- ... mapA = tgis.RasterDataset(idA)
- ... idB = "b%i@B"%(i)
- ... mapB = tgis.RasterDataset(idB)
- ... check = mapA.set_absolute_time(datetime(2000,1,i + 1),
- ... datetime(2000,1,i + 2))
- ... check = mapB.set_absolute_time(datetime(2000,1,i + 6),
- ... datetime(2000,1,i + 7))
- ... mapsA.append(mapA)
- ... mapsB.append(mapB)
- >>> mapsA = p.check_stds(mapsA)
- >>> mapsB = p.check_stds(mapsB)
- >>> # Create global expression object.
- >>> gvarA = tgis.GlobalTemporalVar()
- >>> gvarA.tfunc = "start_day"
- >>> gvarA.compop = ">"
- >>> gvarA.value = 5
- >>> gvarB = tgis.GlobalTemporalVar()
- >>> gvarB.tfunc = "start_day"
- >>> gvarB.compop = "<="
- >>> gvarB.value = 8
- >>> gvarOP = tgis.GlobalTemporalVar()
- >>> gvarOP.relationop = "&&"
- >>> gvarOP.topology.append("EQUAL")
- >>> tvarexpr = [mapsA, gvarOP,gvarA]
- @endcode
- """
- def recurse_compare(conditionlist):
- for ele in conditionlist:
- if ele == '||':
- ele_index = conditionlist.index(ele)
- topolist = conditionlist.pop(ele_index -1)
- right = conditionlist.pop(ele_index)
- left = conditionlist.pop(ele_index - 2)
- if any([left, right]):
- result = True
- else:
- result = False
- conditionlist[ele_index - 2] = result
- recurse_compare(conditionlist)
- if ele == '&&':
- ele_index = conditionlist.index(ele)
- topolist = conditionlist.pop(ele_index -1)
- right = conditionlist.pop(ele_index)
- left = conditionlist.pop(ele_index - 2)
- if all([left, right]):
- result = True
- else:
- result = False
- conditionlist[ele_index - 2] = result
- recurse_compare(conditionlist)
- resultlist = conditionlist
- return(resultlist)
- resultlist = []
- inverselist = []
- for map_i in maplist:
- if "condition_value" in dir(map_i):
- # Get condition values from map object.
- conditionlist = map_i.condition_value
- #print(map_i.get_map_id() + ' ' + str(map_i.condition_value))
- # Evaluate conditions in list with recursive function.
- resultbool = recurse_compare(conditionlist)
- # Set conditional value of map to resulting boolean.
- map_i.condition_value = resultbool
- # Add all maps that fulfill the conditions to result list.
- if resultbool[0]:
- resultlist.append(map_i)
- else:
- inverselist.append(map_i)
- #print(map_i.get_map_id() + ' ' + str(map_i.condition_value))
- if inverse:
- return(inverselist)
- else:
- return(resultlist)
- ###########################################################################
- def p_statement_assign(self, t):
- # The expression should always return a list of maps.
- """
- statement : stds EQUALS expr
- """
- if self.run:
- resultstds = open_new_stds(t[1], self.stdstype, \
- self.temporaltype, "", "", \
- 'mean', dbif=self.dbif, \
- overwrite = self.overwrite)
- if isinstance(t[3], list):
- num = len(t[3])
- count = 0
- if num > 0:
- dbif, connected = init_dbif(None)
- for map in t[3]:
- map.select(dbif=dbif)
- #map.update()
- resultstds.register_map(map, dbif=dbif)
- count += 1
- if count % 10 == 0:
- self.msgr.percent(count, num, 1)
- resultstds.update_from_registered_maps(dbif=dbif)
- if connected:
- dbif.close()
- t[0] = t[3]
- else:
- t[0] = t[3]
- if self.debug:
- print t[1], "=", t[3]
- def p_stds_1(self, t):
- # Definition of a space time dataset
- """
- stds : NAME
- """
- t[0] = t[1]
- def p_paren_expr(self, t):
- """ expr : LPAREN expr RPAREN"""
- t[0] = t[2]
- def p_number(self,t):
- """number : INT
- | FLOAT
- """
- t[0] = t[1]
- def p_t_hash(self,t):
- """
- t_hash_var : stds HASH stds
- | stds HASH expr
- | expr HASH stds
- | expr HASH expr
- """
- if self.run:
- maplistA = self.check_stds(t[1])
- maplistB = self.check_stds(t[3])
- resultlist = self.get_temporal_topo_list(maplistA, maplistB,
- count_map = True)
- t[0] = resultlist
- def p_t_hash2(self,t):
- """
- t_hash_var : stds T_HASH_OPERATOR stds
- | stds T_HASH_OPERATOR expr
- | expr T_HASH_OPERATOR stds
- | expr T_HASH_OPERATOR expr
- """
- if self.run:
- maplistA = self.check_stds(t[1])
- maplistB = self.check_stds(t[3])
- topolist = self.eval_toperator(t[2])[0]
- resultlist = self.get_temporal_topo_list(maplistA, maplistB, topolist,
- count_map = True)
- t[0] = resultlist
- def p_t_td_var(self, t):
- """
- t_td_var : TD LPAREN stds RPAREN
- | TD LPAREN expr RPAREN
- """
- if self.run:
- maplist = self.check_stds(t[3])
- for map_i in maplist:
- if map_i.is_time_absolute:
- start, end = map_i.get_absolute_time()
- if end != None:
- td = time_delta_to_relative_time(end - start)
- else:
- start, end, unit = current.get_relative_time()
- if end != None:
- td = end - start
- if "map_value" in dir(map_i):
- gvar = GlobalTemporalVar()
- gvar.td = td
- map_i.map_value.append(gvar)
- else:
- map_i.map_value = gvar
- t[0] = maplist
- else:
- t[0] = "td(" + str(t[3]) + ")"
- if self.debug:
- print "td(" + str(t[3]) + ")"
- def p_t_time_var(self, t):
- # Temporal variables that return a double or integer value
- """
- t_var : START_DOY
- | START_DOW
- | START_YEAR
- | START_MONTH
- | START_WEEK
- | START_DAY
- | START_HOUR
- | START_MINUTE
- | START_SECOND
- | END_DOY
- | END_DOW
- | END_YEAR
- | END_MONTH
- | END_WEEK
- | END_DAY
- | END_HOUR
- | END_MINUTE
- | END_SECOND
- """
- t[0] = t[1]
- def p_compare_op(self, t):
- # Compare operators that are supported for temporal expressions
- """
- comp_op : CEQUALS
- | UNEQUALS
- | LOWER
- | LOWER_EQUALS
- | GREATER
- | GREATER_EQUALS
- """
- t[0] = t[1]
- def p_t_var_expr(self, t):
- # Examples:
- # start_month() > 2
- # start_day() < 14
- # start_day() < start_month()
- # td() < 31
- """
- t_var_expr : t_var LPAREN RPAREN comp_op number
- | t_var LPAREN RPAREN comp_op t_var
- | t_td_var comp_op number
- | t_td_var comp_op t_var
- | t_hash_var comp_op number
- | t_hash_var comp_op t_var
- """
- if self.run:
- if len(t) == 4:
- maplist = self.check_stds(t[1])
- comp_op = t[2]
- for map_i in maplist:
- for obj in map_i.map_value:
- if isinstance(obj, GlobalTemporalVar):
- td = obj.td
- boolnum = eval(str(td) + comp_op + str(t[3]))
- gvar = GlobalTemporalVar()
- gvar.boolean = boolnum
- if obj.get_type() == "timediff":
- index = map_i.map_value.index(obj)
- map_i.map_value[index] = gvar
- t[0] = maplist
- if len(t) == 6:
- if isinstance(t[1], GlobalTemporalVar):
- pass
- gvar = GlobalTemporalVar()
- gvar.tfunc = t[1]
- gvar.compop = t[4]
- gvar.value = t[5]
- t[0] = gvar
- else:
- t[0] = True
- if self.debug:
- if len(t) == 6:
- print t[1], t[4], t[5]
- if len(t) == 4:
- print t[1], t[2], t[3]
- def p_t_var_expr_time1(self, t):
- # Examples:
- # start_time() == "12:30:00"
- # start_date() <= "2001-01-01"
- # start_datetime() > "2001-01-01 12:30:00"
- """
- t_var_expr : START_TIME LPAREN RPAREN comp_op TIME
- | START_DATE LPAREN RPAREN comp_op DATE
- | START_DATETIME LPAREN RPAREN comp_op DATETIME
- | END_TIME LPAREN RPAREN comp_op TIME
- | END_DATE LPAREN RPAREN comp_op DATE
- | END_DATETIME LPAREN RPAREN comp_op DATETIME
- """
- if self.run:
- gvar = GlobalTemporalVar()
- gvar.tfunc = t[1]
- gvar.compop = t[4]
- gvar.value = t[5]
- t[0] = gvar
- else:
- t[0] = True
- if self.debug:
- print t[1], t[4], t[5]
- def p_t_var_expr_time2(self, t):
- """
- t_var_expr : TIME comp_op START_TIME LPAREN RPAREN
- | DATE comp_op START_DATE LPAREN RPAREN
- | DATETIME comp_op START_DATETIME LPAREN RPAREN
- | TIME comp_op END_TIME LPAREN RPAREN
- | DATE comp_op END_DATE LPAREN RPAREN
- | DATETIME comp_op END_DATETIME LPAREN RPAREN
- """
- if self.run:
- reverseop = {"<" : ">", ">" : "<", "<=" : ">=", ">=" : "<=",
- "==" : "==", "!=" : "!="}
- gvar = GlobalTemporalVar()
- gvar.tfunc = t[3]
- gvar.compop = reverseop[t[2]]
- gvar.value = t[1]
- t[0] = gvar
- else:
- t[0] = True
- if self.debug:
- print(t[4])
- print t[1], t[4], t[5]
- def p_t_var_expr_comp(self, t):
- """
- t_var_expr : t_var_expr AND AND t_var_expr
- | t_var_expr OR OR t_var_expr
- """
- if self.run:
- tvarexprA = t[1]
- tvarexprB = t[4]
- operator = GlobalTemporalVar()
- operator.relationop = t[2] + t[3]
- operator.topology.append("EQUAL")
- resultlist = []
- resultlist.append(tvarexprA)
- resultlist.append(operator)
- resultlist.append(tvarexprB)
- t[0] = resultlist
- else:
- t[0] = True
- if self.debug:
- print t[1], t[2] + t[3], t[4]
- def p_t_var_expr_comp_op(self, t):
- """
- t_var_expr : t_var_expr T_COMP_OPERATOR t_var_expr
- """
- if self.run:
- tvarexprA = t[1]
- tvarexprB = t[3]
- operator = GlobalTemporalVar()
- toperator = self.eval_toperator(t[2])[0]
- relationop = toperator[2]
- relations = toperator[0]
- operator.relationop = relationop
- operator.topology.extend(relations)
- resultlist = []
- resultlist.append(tvarexprA)
- resultlist.append(operator)
- resultlist.append(tvarexprB)
- t[0] = resultlist
- else:
- t[0] = True
- if self.debug:
- print t[1], t[2], t[3]
- def p_expr_t_select(self, t):
- # Temporal equal selection
- # The temporal topology relation equals is implicit
- # Examples:
- # A : B # Select the part of A that is temporally equal B
- """
- expr : stds T_SELECT stds
- | expr T_SELECT stds
- | stds T_SELECT expr
- | expr T_SELECT expr
- """
- if self.run:
- # Setup database connection.
- # Check input stds.
- maplistA = self.check_stds(t[1])
- maplistB = self.check_stds(t[3])
- # Perform selection.
- selectlist = self.perform_temporal_selection(maplistA, maplistB)
- # Return map list.
- t[0] = selectlist
- else:
- t[0] = t[1] + "*"
- if self.debug:
- print t[1] + "* = ", t[1], t[2], t[3]
- def p_expr_t_not_select(self, t):
- # Temporal equal selection
- # The temporal topology relation equals is implicit
- # Examples:
- # A !: B # Select the part of A that is temporally unequal to B
- """
- expr : stds T_NOT_SELECT stds
- | expr T_NOT_SELECT stds
- | stds T_NOT_SELECT expr
- | expr T_NOT_SELECT expr
- """
- if self.run:
- # Check input stds.
- maplistA = self.check_stds(t[1])
- maplistB = self.check_stds(t[3])
- # Perform negative selection.
- selectlist = self.perform_temporal_selection(maplistA, maplistB,
- inverse = True)
- # Return map list.
- t[0] = selectlist
- else:
- t[0] = t[1] + "*"
- if self.debug:
- print t[1] + "* = ", t[1], t[2], t[3]
- def p_expr_t_select_operator(self, t):
- # Temporal equal selection
- # The temporal topology relation equals is implicit
- # Examples:
- # A {!:} B # Select the part of A that is temporally unequal to B
- # A {:} B # Select the part of A that is temporally equal B
- # A {equals, !:} B # Select the part of A that is temporally unequal to B
- # A {during, !:} B # Select the part of A that is temporally not during B
- # A {overlaps, :} B # Select the part of A that temporally overlaps B
- # A {overlaps|equals, :} B # Select the part of A that temporally overlaps or equals B
- """
- expr : stds T_SELECT_OPERATOR stds
- | expr T_SELECT_OPERATOR stds
- | stds T_SELECT_OPERATOR expr
- | expr T_SELECT_OPERATOR expr
- """
- if self.run:
- # Check input stds.
- maplistA = self.check_stds(t[1])
- maplistB = self.check_stds(t[3])
- # Evaluate temporal operator.
- operators = self.eval_toperator(t[2])
- # Check for negative selection.
- if operators[2] == "!:":
- negation = True
- else:
- negation = False
- # Perform selection.
- selectlist = self.perform_temporal_selection(maplistA, maplistB,
- topolist = operators[0], inverse = negation)
- selectlist = self.set_granularity(selectlist, maplistB, operators[1],
- operators[0])
- # Return map list.
- t[0] = selectlist
- else:
- t[0] = t[1] + "*"
- if self.debug:
- print t[1] + "* = ", t[1], t[2], t[3]
- def p_expr_condition_if(self, t):
- # Examples
- # if( start_date() < "2005-06-01", A:B)
- """
- expr : IF LPAREN t_var_expr COMMA stds RPAREN
- | IF LPAREN t_var_expr COMMA expr RPAREN
- """
- if self.run:
- # Get stds/map list of then statement.
- thenlist = self.check_stds(t[5])
- # Get temporal conditional statement.
- tvarexpr = t[3]
- thencond = self.build_condition_list(tvarexpr, thenlist)
- thenresult = self.eval_condition_list(thencond)
- # Clear the map and conditional values of the map list.
- resultlist = self.check_stds(thenresult, clear = True)
- # Return resulting map list.
- t[0] = resultlist
- else:
- t[0] = t[5] + "*"
- if self.debug:
- print str(t[5]) + "* = ", "if condition", str(t[3]), ' then ', str(t[5])
- def p_expr_condition_if_relation(self, t):
- # Examples
- # if({equal} start_date() < "2005-06-01", A:B)
- """
- expr : IF LPAREN T_REL_OPERATOR COMMA t_var_expr COMMA stds RPAREN
- | IF LPAREN T_REL_OPERATOR COMMA t_var_expr COMMA expr RPAREN
- """
- if self.run:
- # Get stds/map list of then statement.
- thenlist = self.check_stds(t[7])
- # Get temporal conditional statement.
- tvarexpr = t[5]
- topolist = self.eval_toperator(t[3])[0]
- thencond = self.build_condition_list(tvarexpr, thenlist, topolist)
- thenresult = self.eval_condition_list(thencond)
- # Clear the map and conditional values of the map list.
- resultlist = self.check_stds(thenresult, clear = True)
- # Return resulting map list.
- t[0] = resultlist
- else:
- t[0] = t[7] + "*"
- if self.debug:
- print "result* = ", "if ", str(t[3]), "condition", str(t[5]), " then ", str(t[7])
- def p_expr_condition_elif(self, t):
- # Examples
- # if( start_date() < "2005-06-01", if(start_time() < "12:30:00", A:B), A!:B)
- """
- expr : IF LPAREN t_var_expr COMMA stds COMMA stds RPAREN
- | IF LPAREN t_var_expr COMMA stds COMMA expr RPAREN
- | IF LPAREN t_var_expr COMMA expr COMMA stds RPAREN
- | IF LPAREN t_var_expr COMMA expr COMMA expr RPAREN
- """
- if self.run:
- # Get stds/map list of then statement.
- thenlist = self.check_stds(t[5])
- elselist = self.check_stds(t[7])
- # Get temporal conditional statement for then and else expressions.
- tvarexpr = t[3]
- thencond = self.build_condition_list(tvarexpr, thenlist)
- thenresult = self.eval_condition_list(thencond)
- elsecond = self.build_condition_list(tvarexpr, elselist)
- elseresult = self.eval_condition_list(elsecond, inverse = True)
- # Combine and sort else and then statement to result map list.
- combilist = thenresult + elseresult
- resultlist = sorted(combilist, key = AbstractDatasetComparisonKeyStartTime)
- # Clear the map and conditional values of the map list.
- resultlist = self.check_stds(resultlist, clear = True)
- # Return resulting map list.
- t[0] = resultlist
- else:
- t[0] = t[5] + "*"
- if self.debug:
- print str(t[5]) + "* = ", "if condition", str(t[3]), " then ", str(t[5]), ' else ', str(t[7])
- def p_expr_condition_elif_relation(self, t):
- # Examples
- # if({equal}, start_date() < "2005-06-01", if(start_time() < "12:30:00", A:B), A!:B)
- # The then and else statement using the same topological relationships.
- # Feature request: Independent relationships for then and else to conditions.
- """
- expr : IF LPAREN T_REL_OPERATOR COMMA t_var_expr COMMA stds COMMA stds RPAREN
- | IF LPAREN T_REL_OPERATOR COMMA t_var_expr COMMA stds COMMA expr RPAREN
- | IF LPAREN T_REL_OPERATOR COMMA t_var_expr COMMA expr COMMA stds RPAREN
- | IF LPAREN T_REL_OPERATOR COMMA t_var_expr COMMA expr COMMA expr RPAREN
- """
- if self.run:
- # Get stds/map list of then statement.
- thenlist = self.check_stds(t[7])
- elselist = self.check_stds(t[9])
- # Get temporal conditional statement.
- tvarexpr = t[5]
- topolist = self.eval_toperator(t[3])[0]
- thencond = self.build_condition_list(tvarexpr, thenlist, topolist)
- thenresult = self.eval_condition_list(thencond)
- elsecond = self.build_condition_list(tvarexpr, elselist, topolist)
- elseresult = self.eval_condition_list(elsecond, inverse = True)
- # Combine and sort else and then statement to result map list.
- combilist = thenresult + elseresult
- resultlist = sorted(combilist, key = AbstractDatasetComparisonKeyStartTime)
- # Clear the map and conditional values of the map list.
- resultlist = self.check_stds(resultlist, clear = True)
- # Return resulting map list.
- t[0] = resultlist
- else:
- if t[5]:
- t[0] = str(t[7])
- else:
- t[0] = str(t[9])
- if self.debug:
- if t[5]:
- print str(t[7]), "* = ", "if condition", str(t[5]), " then ", str(t[7]), ' else ', str(t[9])
- else:
- print str(t[9]), "* = ", "if condition", str(t[5]), " then ", str(t[7]), ' else ', str(t[9])
- def p_expr_t_buff(self, t):
- # Examples
- # buff_t(A : B, "10 minutes") # Select the part of A that is temporally
- # equal to B and create a buffer of 10 minutes around
- """
- expr : BUFF_T LPAREN stds COMMA QUOTE number NAME QUOTE RPAREN
- | BUFF_T LPAREN expr COMMA QUOTE number NAME QUOTE RPAREN
- | BUFF_T LPAREN stds COMMA number RPAREN
- | BUFF_T LPAREN expr COMMA number RPAREN
- """
- if self.run:
- # Check input stds.
- bufflist = self.check_stds(t[3])
- for map in bufflist:
- # Get increment format.
- if len(t) == 10:
- increment = str(t[6]) + " " + t[7]
- elif len(t) == 7:
- increment = str(t[5])
- # Perform buffering.
- map.temporal_buffer(increment)
- t[0] = bufflist
- else:
- t[0] = t[3] + "*"
- if self.debug:
- if len(t) == 10:
- print str(t[3]) + "* = buff_t(", str(t[3]), "," , '"', str(t[6]), str(t[7]), '"', ")"
- elif len(t) == 7:
- print str(t[3]) + "* = buff_t(", str(t[3]), ",", str(t[5]), ")"
- def p_expr_t_snap(self, t):
- # Examples
- # tsnap(A : B) # Snap the maps of A temporally.
- """
- expr : TSNAP LPAREN stds RPAREN
- | TSNAP LPAREN expr RPAREN
- """
- if self.run:
- # Check input stds.
- maplist = self.check_stds(t[3])
- # Perform snapping.
- snaplist = AbstractSpaceTimeDataset.snap_map_list(maplist)
- t[0] = snaplist
- else:
- t[0] = t[3] + "*"
- if self.debug:
- print str(t[3]) + "* = tsnap(", str(t[3]), ")"
- def p_expr_t_shift(self, t):
- # Examples
- # tshift(A : B, "10 minutes") # Shift the selection from A temporally
- # by 10 minutes.
- """
- expr : TSHIFT LPAREN stds COMMA QUOTE number NAME QUOTE RPAREN
- | TSHIFT LPAREN expr COMMA QUOTE number NAME QUOTE RPAREN
- | TSHIFT LPAREN stds COMMA number RPAREN
- | TSHIFT LPAREN expr COMMA number RPAREN
- """
- if self.run:
- # Check input stds.
- maplist = self.check_stds(t[3])
- # Get increment format.
- if len(t) == 10:
- increment = str(t[6]) + " " + t[7]
- elif len(t) == 7:
- increment = str(t[5])
- # Perform shifting.
- shiftlist = AbstractSpaceTimeDataset.shift_map_list(maplist, increment)
- t[0] = shiftlist
- else:
- t[0] = t[3] + "*"
- if self.debug:
- if len(t) == 10:
- print str(t[3]) + "* = tshift(", str(t[3]), "," , '"', str(t[6]), str(t[7]), '"', ")"
- elif len(t) == 7:
- print str(t[3]) + "* = tshift(", str(t[3]), ",", str(t[5]), ")"
- # Handle errors.
- def p_error(self, t):
- if t:
- raise SyntaxError("syntax error on line %d, token %s near '%s' expression '%s'" %
- (t.lineno, t.type, t.value, self.expression))
- else:
- raise SyntaxError("Unexpected syntax error")
- ###############################################################################
- if __name__ == "__main__":
- import doctest
- doctest.testmod()
|