123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655 |
- """@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-block:: python
- >>> 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 {:,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**
- >>> 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 None then A
- C = A*
- >>> expression = 'C = if(td(A) == 5, A, B)'
- >>> p.parse(expression, 'stvds')
- td(A)
- td(A) == 5
- A* = if condition None then A else B
- C = A*
- >>> expression = 'C = if(td(A) == 5 || start_date(A) > "2010-01-01", A, B)'
- >>> p.parse(expression, 'stvds')
- td(A)
- td(A) == 5
- start_date A > "2010-01-01"
- None || None
- A* = if condition None then A else B
- C = A*
- """
- try:
- import ply.lex as lex
- import ply.yacc as yacc
- except:
- pass
- import os
- import copy
- import grass.pygrass.modules as pymod
- from space_time_datasets import *
- from factory import *
- from open_stds import *
- from temporal_operator import *
- ##############################################################################
- class TemporalAlgebraLexer(object):
- """Lexical analyzer for the GRASS GIS temporal algebra"""
- # Functions that defines an if condition, temporal buffering, snapping and
- # selection of maps with temporal extent.
- conditional_functions = {
- 'if' : 'IF',
- 'buff_t': 'BUFF_T',
- 'tsnap' : 'TSNAP',
- 'tshift' : 'TSHIFT',
- 'tmap' : 'TMAP',
- }
-
- # 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\| ]*([,])?([lrudi]|left|right|union|disjoint|intersect)?\}'
- t_T_HASH_OPERATOR = r'\{[#][,]?[a-zA-Z\| ]*([,])?([lrudi]|left|right|union|disjoint|intersect)?\}'
- t_T_COMP_OPERATOR = r'\{(\|\||&&)[,][a-zA-Z\| ]*[,]?[\|&]?([,])?([lrudi]|left|right|union|disjoint|intersect)?\}'
- 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 FatalError(Exception):
- def __init__(self, msg):
- self.value = msg
- def __str__(self):
- return 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, register_null = False, nprocs = 1):
- 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()
- self.register_null = register_null
- self.removable_maps = {}
- self.m_mremove = pymod.Module('g.remove')
- self.m_copy = pymod.Module('g.copy')
- self.nprocs = nprocs
- self.use_granularity = False
- def __del__(self):
- if self.dbif.connected:
- self.dbif.close()
-
- def setup_common_granularity(self, expression, stdstype = 'strds', lexer = None):
- """Configure the temporal algebra to use the common granularity of all
- space time datasets in the expression to generate the map lists.
-
- This function will analyze the expression to detect space time datasets
- and computes the common granularity from all granularities.
-
- This granularity is then be used to generate the map lists. Hence, all
- maps from all STDS will have equidistant temporal extents. The only meaningful
- temporal relation is "equal".
-
- :param expression: The algebra expression to analyze
-
- :param lexer: The temporal algebra lexer (select, raster, voxel, vector) that should be used to
- parse the expression, default is TemporalAlgebraLexer
-
- :return: True if successful, False otherwise
-
- """
- l = lexer
- # Split the expression to ignore the left part
- expressions = expression.split("=")[1:]
- expression = " ".join(expressions)
-
- # Check if spatio-temporal operators are present in the expression
- if "{" in expression or "}" in expression:
- self.msgr.error(_("Spatio temporal operators are not supported in granularity algebra mode"))
- return False
-
- # detect all STDS
- if l is None:
- l = TemporalAlgebraLexer()
- l.build()
- l.lexer.input(expression)
-
- name_list = []
- tokens = []
-
- count = 0
- while True:
- tok = l.lexer.token()
- if not tok: break
-
- # Ignore map layer
- tokens.append(tok.type)
- ignore = False
- if count > 1:
- if tokens[count - 2] == "MAP" or tokens[count - 2] == "TMAP":
- ignore = True
-
- if tok.type == "NAME" and ignore == False:
- name_list.append(tok.value)
- count += 1
-
- grans = []
- ttypes = {}
- dbif, connected = init_dbif(self.dbif)
-
- for name in name_list:
- stds = open_old_stds(name, stdstype, dbif)
- # We need valid temporal topology
- if stds.check_temporal_topology() is False:
- self.msgr.error(_("All input space time datasets must have a valid temporal topology."))
- return False
- grans.append(stds.get_granularity())
- ttypes[stds.get_temporal_type()] = stds.get_temporal_type()
-
- # Only one temporal type is allowed
- if len(ttypes) > 1:
- self.msgr.error(_("All input space time datasets must have the same temporal type."))
- return False
-
- # Compute the common granularity
- if "absolute" in ttypes.keys():
- self.granularity = compute_common_absolute_time_granularity(grans)
- else:
- self.granularity = compute_common_relative_time_granularity(grans)
-
- self.use_granularity = True
-
- return True
- def parse(self, expression, stdstype = 'strds', maptype = 'rast', mapclass = RasterDataset,
- 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.maptype = maptype
- self.mapclass = mapclass
- self.basename = basename
- self.expression = expression
- self.parser.parse(expression)
- def generate_map_name(self):
- """Generate an unique map name and register it in the objects map list
- The 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, rename = True,
- remove = False):
- """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
- :param bool_op: The boolean operator specifying the spatial extent
- operation (intersection, union, disjoint union)
- :param copy: Specifies if the temporal extent of mapB should be
- copied to mapA
- :param rename: Specifies if the generated map get a random name or get
- the id from the base map.
- :param remove: Set this True if this map is an intermediate or empty map that should be removed
- :return: Map object
- """
- # 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)
- if not rename:
- name = base_map.get_id()
- map_new.set_id(name)
- if remove is True:
- self.removable_maps[name] = map_new
- # Make sure to set the uid that is used in several dictionaries
- map_new.uid = name
- return map_new
- def overlay_map_extent(self, mapA, mapB, bool_op = None, temp_op = 'l',
- 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, right reference)
- Left reference is the default temporal extent behaviour.
- :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
- if "condition_value" in dir(mapB):
- mapA.condition_value = mapB.condition_value
- 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 == 'i':
- temp_ext = mapA.temporal_intersection(mapB)
- if temp_ext != None:
- mapA.set_temporal_extent(temp_ext)
- else:
- returncode = 0
- elif temp_op == 'u':
- temp_ext = mapA.temporal_union(mapB)
- if temp_ext != None:
- mapA.set_temporal_extent(temp_ext)
- else:
- returncode = 0
- elif temp_op == 'd':
- temp_ext = mapA.temporal_disjoint_union(mapB)
- if temp_ext != None:
- mapA.set_temporal_extent(temp_ext)
- else:
- returncode = 0
- elif temp_op == 'r':
- temp_ext = mapB.get_temporal_extent()
- if temp_ext != None:
- mapA.set_temporal_extent(temp_ext)
- else:
- returncode = 0
- return(returncode)
- def set_temporal_extent_list(self, maplist, topolist = ["EQUAL"], temporal = 'l' ):
- """ Change temporal extent of map list based on temporal relations to
- other map list and given temporal operator.
- :param maplist: List of map objects for which relations has been build
- correctely.
- :param topolist: List of strings of temporal relations.
- :param temporal: The temporal operator specifying the temporal
- extent operation (intersection, union, disjoint
- union, right reference, left reference).
- :return: Map list with specified temporal extent.
- """
- resultdict = {}
-
- for map_i in maplist:
- # Loop over temporal related maps and create overlay modules.
- tbrelations = map_i.get_temporal_relations()
- # Generate an intermediate map for the result map list.
- map_new = self.generate_new_map(base_map=map_i, bool_op = 'and',
- copy = True, rename = True)
- # Combine temporal and spatial extents of intermediate map with related maps.
- for topo in topolist:
- if topo in tbrelations.keys():
- for map_j in (tbrelations[topo]):
- if temporal == 'r':
- # Generate an intermediate map for the result map list.
- map_new = self.generate_new_map(base_map=map_i, bool_op = 'and',
- copy = True, rename = True)
- # Create overlayed map extent.
- returncode = self.overlay_map_extent(map_new, map_j, 'and', \
- temp_op = temporal)
- # Stop the loop if no temporal or spatial relationship exist.
- if returncode == 0:
- break
- # Append map to result map list.
- elif returncode == 1:
- print(map_new.get_id() + " " + str(map_new.get_temporal_extent_as_tuple()))
- print(map_new.condition_value)
- # print(map_new.cmd_list)
- # resultlist.append(map_new)
- resultdict[map_new.get_id()] = map_new
-
- # Create r.mapcalc expression string for the operation.
- #cmdstring = self.build_command_string(s_expr_a = map_new,
- # s_expr_b = map_j,
- # operator = function)
- # Conditional append of module command.
- #map_new.cmd_list = cmdstring
- if returncode == 0:
- break
- # Append map to result map list.
- #if returncode == 1:
- # resultlist.append(map_new)
- # Get sorted map objects as values from result dictionoary.
- resultlist = resultdict.values()
- resultlist = sorted(resultlist, key = AbstractDatasetComparisonKeyStartTime)
-
- return(resultlist)
-
- ######################### Temporal functions ##############################
- def remove_maps(self):
- """Removes empty or intermediate maps of different type.
- """
-
- map_names = {}
- map_names["raster"] = []
- map_names["raster3d"] = []
- map_names["vector"] = []
-
- if self.removable_maps:
- for map in self.removable_maps.values():
- map_names[map.get_type()].append(map.get_name())
-
- for key in map_names.keys():
- if map_names[key]:
- self.msgr.message(_("Removing un-needed or empty %s maps"%(key)))
- self._remove_maps(map_names[key], key)
- def _remove_maps(self, namelist, map_type):
- """Remove maps of specific type
-
- :param namelist: List of map names to be removed
- :param map_type: The type of the maps (rast, rast3d or vect)
- """
- max = 100
- chunklist = [namelist[i:i + max] for i in range(0, len(namelist), max)]
- for chunk in chunklist:
- stringlist = ",".join(chunk)
-
- # Transform the map type
- if map_type == "raster":
- map_type = "rast"
- if map_type == "raster3d":
- map_type = "rast3d"
- if map_type == "vector":
- map_type = "vect"
- if self.run:
- m = copy.deepcopy(self.m_mremove)
- m.inputs["type"].value = map_type
- m.inputs["name"].value = stringlist
- m.flags["f"].value = True
- print m.get_bash()
- m.run()
- def check_stds(self, input, clear = False, stds_type = None):
- """ 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.
- :param stds_type: The type of the space time dataset to be opened, if not provided
- then self.stdstype will be used
- :return: List of maps.
- """
- if isinstance(input, str):
- # Check for mapset in given stds input.
- if input.find("@") >= 0:
- id_input = input
- else:
- id_input = input + "@" + self.mapset
- # Create empty spacetime dataset.
- if stds_type:
- stds = dataset_factory(stds_type, id_input)
- else:
- 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)
- if self.use_granularity:
- # We create the maplist out of the map array from none-gap objects
- maplist = []
- map_array = stds.get_registered_maps_as_objects_by_granularity(gran=self.granularity, dbif=self.dbif)
- for entry in map_array:
- # Ignore gap objects
- if entry[0].get_id() is not None:
- maplist.append(entry[0])
- else:
- 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))
- elif isinstance(input, self.mapclass):
- # Check if the input is a single map and return it as list with one entry.
- maplist = [input]
-
- elif isinstance(input, list):
- 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 = []
- else:
- self.msgr.fatal(_("Wrong type of input"))
-
- # We generate a unique map id that will be used
- # in the topology analysis, since the maplist can
- # contain maps with equal map ids
- for map in maplist:
- map.uid = self.generate_map_name()
- if self.debug:
- print map.get_name(), map.uid, map.get_temporal_extent_as_tuple()
-
- return(maplist)
- def get_temporal_topo_list(self, maplistA, maplistB = None, topolist = ["EQUAL"],
- assign_val = False, count_map = False, compare_bool = False,
- compop = None, aggregate = None):
- """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.
- :param compare_bool: Boolean for comparing boolean map values based on
- related map list and compariosn operator.
- :param compop: Comparison operator, && or ||.
- :param aggregate: Aggregation operator for relation map list, & or |.
-
- :return: List of maps from maplistA that fulfil the topological relationships
- to maplistB specified in topolist.
- .. code-block:: python
- # 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)
- ... mapA.uid = idA
- ... idB = "b%i@B"%(i)
- ... mapB = tgis.RasterDataset(idB)
- ... mapB.uid = 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)
- ... mapA.uid = idA
- ... idB = "b%i@B"%(i)
- ... mapB = tgis.RasterDataset(idB)
- ... mapB.uid = 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)
- ... mapA.uid = idA
- ... idB = "b%i@B"%(i)
- ... mapB = tgis.RasterDataset(idB)
- ... mapB.uid = 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.uid = idA
- ... mapA.map_value = True
- ... idB = "b%i@B"%(i)
- ... mapB = tgis.RasterDataset(idB)
- ... mapB.uid = 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())
- """
- 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.
- for map_i in maplistA:
- tbrelations = map_i.get_temporal_relations()
- if assign_val:
- self.assign_bool_value(map_i, tbrelations, topolist)
- elif compare_bool:
- self.compare_bool_value(map_i, tbrelations, compop, aggregate, topolist)
- for topo in topolist:
- if topo.upper() in tbrelations.keys():
- 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
- # Use unique identifier, since map names may be equal
- resultdict[map_i.uid] = map_i
- resultlist = resultdict.values()
-
- # Sort list of maps chronological.
- resultlist = sorted(resultlist, key = AbstractDatasetComparisonKeyStartTime)
-
- return(resultlist)
-
- def assign_bool_value(self, map_i, tbrelations, topolist = ["EQUAL"]):
- """ Function to assign boolean map value based on the map_values from the
- compared map list by topological relationships.
-
- :param map_i: Map object with temporal extent.
- :param tbrelations: List of temporal relation to map_i.
- :param topolist: List of strings for given temporal relations.
-
- :return: Map object with conditional value that has been assigned by
- relation maps that fulfil the topological relationships to
- maplistB specified in topolist.
- """
- condition_value_list = []
- for topo in topolist:
- if topo.upper() in tbrelations.keys():
- #relationmaplist = tbrelations[complementdict[topo.upper()]]
- relationmaplist = tbrelations[topo.upper()]
- for relationmap in relationmaplist:
- for boolean in relationmap.condition_value:
- if isinstance(boolean, bool):
- condition_value_list.append(boolean)
- if self.debug:
- print(str(relationmap.get_temporal_extent_as_tuple()) + str(boolean))
- if all(condition_value_list):
- resultbool = True
- else:
- resultbool = False
- map_i.condition_value = [resultbool]
-
- return(resultbool)
- def compare_bool_value(self, map_i, tbrelations, compop, aggregate, topolist = ["EQUAL"]):
- """ Function to evaluate two map lists with boolean values by boolean
- comparison operator.
-
- :param map_i: Map object with temporal extent.
- :param tbrelations: List of temporal relation to map_i.
- :param topolist: List of strings for given temporal relations.
- :param compop: Comparison operator, && or ||.
- :param aggregate: Aggregation operator for relation map list, & or |.
-
- :return: Map object with conditional value that has been evaluated by
- comparison operators.
- """
- # Build conditional list with elements from related maps and given relation operator.
- leftbool = map_i.condition_value[0]
- condition_value_list = [leftbool]
- count = 0
- for topo in topolist:
- if topo.upper() in tbrelations.keys():
- relationmaplist = tbrelations[topo.upper()]
- if count == 0:
- condition_value_list.append(compop[0])
- condition_value_list.append('(')
- for relationmap in relationmaplist:
- for boolean in relationmap.condition_value:
- if isinstance(boolean, bool):
- if count > 0:
- condition_value_list.append(aggregate)
- condition_value_list.append(boolean)
- count = count + 1
- if count > 0:
- condition_value_list.append(')')
- # Convert conditional list to concatenated string and evaluate booleans.
- condition_value_str = ''.join(map(str, condition_value_list))
- if self.debug:
- print(condition_value_str)
- resultbool = eval(condition_value_str)
- if self.debug:
- print(resultbool)
- # Add boolean value to result list.
- map_i.condition_value = [resultbool]
-
- return(resultbool)
-
- def eval_toperator(self, operator, optype = 'relation'):
- """This function evaluates a string containing temporal operations.
- :param operator: String of temporal operations, e.g. {!=,equal|during,l}.
- :param optype: String to define operator type.
-
- :return :List of temporal relations (equal, during), the given function
- (!:) and the interval/instances (l).
-
- .. code-block:: python
-
- >>> import grass.temporal as tgis
- >>> tgis.init()
- >>> p = tgis.TemporalOperatorParser()
- >>> operator = "{+, during}"
- >>> p.parse(operator, optype = 'raster')
- >>> print(p.relations, p.temporal, p.function)
- (['during'], 'l', '+')
- """
- p = TemporalOperatorParser()
- p.parse(operator, optype)
- p.relations = [rel.upper() for rel in p.relations]
-
- return(p.relations, p.temporal, p.function, p.aggregate)
- 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-block:: python
- >>> 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)
- ... mapA.uid = idA
- ... idB = "b%i@B"%(i)
- ... mapB = tgis.RasterDataset(idB)
- ... mapB.uid = 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
- """
- 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 = assign_val)
- 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 = 'l', 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: l, r, d, i, u.
- :param topolist: List of topological relations.
- :return: List of maps with the new temporal extends.
- .. code-block:: python
- >>> 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)
- ... mapA.uid = idA
- ... idB = "b%i@B"%(i)
- ... mapB = tgis.RasterDataset(idB)
- ... mapB.uid = 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 = "u", 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
- """
- 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()
- map_extent = map_i.get_temporal_extent()
- map_start = map_extent.get_start_time()
- map_end = map_extent.get_end_time()
- unchanged = True
- for topo in topolist:
- if topo.upper() in tbrelations.keys():
- relationmaplist = tbrelations[topo.upper()]
- for relationmap in relationmaplist:
- newextent = None
- if toperator == "i":
- newextent = map_i.temporal_intersection(relationmap)
- elif toperator == "u":
- newextent = map_i.temporal_union(relationmap)
- elif toperator == "d":
- newextent = map_i.temporal_disjoint_union(relationmap)
- elif toperator == "l":
- newextent = map_i.get_temporal_extent()
- elif toperator == "r":
- newextent = relationmap.get_temporal_extent()
- if newextent != None:
- start = newextent.get_start_time()
- end = newextent.get_end_time()
- #print(map_i.get_id() + ' - start: ' + str(start) + ' end: ' + str(end))
- # Track changes in temporal extents of maps.
- if map_start != start or map_end != end :
- unchanged = False
- 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
- else:
- if self.debug:
- print('Topologic relation: ' + topo.upper() + ' not found.')
- resultdict[map_i.get_id()] = map_i
- if unchanged == True:
- if self.debug:
- print('Leave temporal extend of result map: ' + map_i.get_map_id() + ' unchanged.')
-
- 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-block:: python
-
- >>> 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)
- ... mapA.uid = 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
- """
- 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 in two steps.
- At first it combines stepwise the single conditions by their relations with LALR.
- In this prossess sub condition map lists will be created which will include
- information of the underlying single conditions. Important: The temporal
- relations between conditions are evaluated by implicit aggregation.
- In the second step the aggregated condition map list will be compared with the
- map list of conclusion statements by the given temporal relation.
-
- The result is writen as 'condition_value' attribute to the resulting map objects.
- These attribute consists of boolean expressions and operators which can be
- evaluated with the eval_condition_list function.
- [True, '||', False, '&&', True]
- 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.
-
- :param topolist: List of temporal relations between the conditions and the
- conclusions.
-
- :return: Map list with conditional values for all temporal expressions.
- """
-
- # Evaluate the temporal variable expression and compute the temporal combination
- # of conditions.
-
- # Check if the input expression is a valid single global variable.
- if isinstance(tvarexpr, GlobalTemporalVar) and tvarexpr.get_type() == "global" :
- # Use method eval_global_var to evaluate expression.
- resultlist = self.eval_global_var(tvarexpr, thenlist)
- # Check if a given list is a list of maps.
- elif 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)
- elif len(tvarexpr) % 2 != 0:
- # Define variables for map list comparisons.
- left_obj = []
- operator = []
- right_obj =[]
- count = 0
- #self.msgr.fatal("Condition list is not complete. Elements missing")
- for iter in range(len(tvarexpr)):
- expr = tvarexpr[iter]
- operator = tvarexpr[iter +1]
- relexpr = tvarexpr[iter +2]
- if all([issubclass(type(ele), list) for ele in [expr, relexpr]]):
- resultlist = self.get_temporal_topo_list(expr, relexpr)
- # 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.
- """
- 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 = []
- # Loop through map list and evaluate conditional values.
- for map_i in maplist:
- if "condition_value" in dir(map_i):
- # Get condition values from map object.
- conditionlist = 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)
- if self.debug:
- print(map_i.get_map_id() + ' ' + str(map_i.condition_value))
- else:
- inverselist.append(map_i)
- 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:
- dbif, connected = init_dbif(self.dbif)
- if isinstance(t[3], list):
- num = len(t[3])
- count = 0
- register_list = []
- if num > 0:
- process_queue = pymod.ParallelModuleQueue(int(self.nprocs))
- for map_i in t[3]:
- # Test if temporal extents have been changed by temporal
- # relation operators (i|r).
- map_i_extent = map_i.get_temporal_extent_as_tuple()
- map_test = map_i.get_new_instance(map_i.get_id())
- map_test.select(dbif)
- map_test_extent = map_test.get_temporal_extent_as_tuple()
- if map_test_extent != map_i_extent:
- # Create new map with basename
- newident = self.basename + "_" + str(count)
- map_result = map_i.get_new_instance(newident + "@" + self.mapset)
- if map_test.map_exists() and self.overwrite == False:
- self.msgr.fatal("Error raster maps with basename %s exist. Use --o flag to overwrite existing file" \
- %(mapname))
- map_result.set_temporal_extent(map_i.get_temporal_extent())
- map_result.set_spatial_extent(map_i.get_spatial_extent())
- # Attention we attach a new attribute
- map_result.is_new = True
- register_list.append(map_result)
- # Copy the map
- if map_i.get_type() == 'raster':
- m = copy.deepcopy(self.m_copy)
- m.inputs["rast"].value = map_i.get_id(), newident
- m.flags["overwrite"].value = self.overwrite
- process_queue.put(m)
- elif map_i.get_type() == 'raster3d':
- m = copy.deepcopy(self.m_copy)
- m.inputs["rast3d"].value = map_i.get_id(), newident
- m.flags["overwrite"].value = self.overwrite
- process_queue.put(m)
- elif map_i.get_type() == 'vector':
- m = copy.deepcopy(self.m_copy)
- m.inputs["vect"].value = map_i.get_id(), newident
- m.flags["overwrite"].value = self.overwrite
- process_queue.put(m)
- else:
- register_list.append(map_i)
- count += 1
- # Wait for running processes
- process_queue.wait()
-
- # Open connection to temporal database.
- # Create result space time dataset.
- resultstds = open_new_stds(t[1], self.stdstype, \
- 'absolute', t[1], t[1], \
- 'mean', self.dbif, \
- overwrite = self.overwrite)
- for map_i in register_list:
- # Get meta data from grass database.
- map_i.load()
- # Check if temporal extents have changed and a new map was created
- if hasattr(map_i, "is_new") is True:
- # Do not register empty maps if not required
- # In case of a null map continue, do not register null maps
- if map_i.metadata.get_min() is None and \
- map_i.metadata.get_max() is None:
- if not self.register_null:
- self.removable_maps[map_i.get_name()] = map_i
- continue
- if map_i.is_in_db(dbif) and self.overwrite:
- # Update map in temporal database.
- map_i.update_all(dbif)
- elif map_i.is_in_db(dbif) and self.overwrite == False:
- # Raise error if map exists and no overwrite flag is given.
- self.msgr.fatal("Error map %s exist in temporal database. Use overwrite flag. : \n%s" \
- %(map_i.get_map_id(), cmd.popen.stderr))
- else:
- # Insert map into temporal database.
- map_i.insert(dbif)
- # Register map in result space time dataset.
- success = resultstds.register_map(map_i, dbif)
- resultstds.update_from_registered_maps(dbif)
- elif num == 0:
- self.msgr.warning('Empty result space time dataset. No map has \
- been registered in %s' %(t[1] ))
- # Open connection to temporal database.
- # Create result space time dataset.
- resultstds = open_new_stds(t[1], self.stdstype, \
- 'absolute', t[1], t[1], \
- 'mean', dbif, \
- overwrite = self.overwrite)
- 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_expr_tmap_function(self, t):
- # Add a single map.
- # Only the spatial extent of the map is evaluated.
- # Temporal extent is not existing.
- # Examples:
- # R = tmap(A)
- """
- expr : TMAP LPAREN stds RPAREN
- """
- if self.run:
- # Check input map.
- input = t[3]
- 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 map dataset.
- map_i = dataset_factory(self.maptype, id_input)
- # Check for occurence of space time dataset.
- if map_i.map_exists() == False:
- raise FatalError(_("%s map <%s> not found in GRASS spatial database") %
- (map_i.get_type(), id_input))
- else:
- # Select dataset entry from database.
- map_i.select(dbif=self.dbif)
- else:
- raise FatalError(_("Wrong map type <%s> . TMAP only supports single maps that are registered in the temporal GRASS database") %
- (map_i.get_type()))
- # Return map object.
- t[0] = [map_i]
- else:
- t[0] = "tmap(", t[3] , ")"
- if self.debug:
- print "tmap(", t[3] , ")"
- def p_t_hash(self,t):
- """
- t_hash_var : stds HASH stds
- """
- 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
- """
- if self.run:
- maplistA = self.check_stds(t[1])
- maplistB = self.check_stds(t[3])
- topolist = self.eval_toperator(t[2], optype = 'hash')[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_td_hash(self, t):
- # Examples:
- # A # B == 2
- # td(A) < 31
- """
- t_var_expr : t_td_var comp_op number
- | t_hash_var comp_op number
- """
- if self.run:
- maplist = self.check_stds(t[1])
- comp_op = t[2]
- value = str(t[3])
- for map_i in maplist:
- # Evaluate time diferences and hash operator statements for each map.
- try:
- td = map_i.map_value[0].td
- boolname = eval(str(td) + comp_op + 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
- except:
- self.msgr.fatal("Error: the given expression does not contain a correct time difference object.")
-
- t[0] = maplist
-
- if self.debug:
- print t[1], t[2], t[3]
- def p_t_var_expr_number(self, t):
- # Examples:
- # start_month(A) > 2
- # start_day(B) < 14
- # start_day(B) < start_month(A)
- """
- t_var_expr : t_var LPAREN stds RPAREN comp_op number
- | t_var LPAREN expr RPAREN comp_op number
- """
- # TODO: Implement comparison operator for map lists.
- #| t_var LPAREN stds RPAREN comp_op t_var LPAREN stds RPAREN
- #| t_var LPAREN stds RPAREN comp_op t_var LPAREN expr RPAREN
- #| t_var LPAREN expr RPAREN comp_op t_var LPAREN expr RPAREN
- #| t_var LPAREN expr RPAREN comp_op t_var LPAREN stds RPAREN
- # TODO: Implement statement in backward direction:
- # number comp_op t_var LPAREN stds RPAREN
- if self.run:
- maplist = self.check_stds(t[3])
- gvar = GlobalTemporalVar()
- gvar.tfunc = t[1]
- gvar.compop = t[5]
- gvar.value = t[6]
- # Evaluate temporal variable for given maplist.
- resultlist = self.eval_global_var(gvar, maplist)
- t[0] = resultlist
- if self.debug:
- print t[1], t[3], t[5], t[6]
- def p_t_var_expr_time(self, t):
- # Examples:
- # start_time(A) == "12:30:00"
- # start_date(B) <= "2001-01-01"
- # start_datetime(C) > "2001-01-01 12:30:00"
- # TODO: Implement statement in backward direction:
- # TIME comp_op START_TIME LPAREN stds RPAREN
- """
- t_var_expr : START_TIME LPAREN stds RPAREN comp_op TIME
- | START_DATE LPAREN stds RPAREN comp_op DATE
- | START_DATETIME LPAREN stds RPAREN comp_op DATETIME
- | END_TIME LPAREN stds RPAREN comp_op TIME
- | END_DATE LPAREN stds RPAREN comp_op DATE
- | END_DATETIME LPAREN stds RPAREN comp_op DATETIME
- | START_TIME LPAREN expr RPAREN comp_op TIME
- | START_DATE LPAREN expr RPAREN comp_op DATE
- | START_DATETIME LPAREN expr RPAREN comp_op DATETIME
- | END_TIME LPAREN expr RPAREN comp_op TIME
- | END_DATE LPAREN expr RPAREN comp_op DATE
- | END_DATETIME LPAREN expr RPAREN comp_op DATETIME
- """
- if self.run:
- # Check input maplist.
- maplist = self.check_stds(t[3])
- # Build global temporal variable.
- gvar = GlobalTemporalVar()
- gvar.tfunc = t[1]
- gvar.compop = t[5]
- gvar.value = t[6]
- # Evaluate temporal variable for given maplist.
- resultlist = self.eval_global_var(gvar, maplist)
-
- t[0] = resultlist
- if self.debug:
- print t[1], t[3], t[5], t[6]
- 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:
- # Check input maplists and operators.
- tvarexprA = t[1]
- tvarexprB = t[4]
- relations = ["EQUAL"]
- temporal = "l"
- function = t[2] + t[3]
- aggregate = t[2]
- # Build conditional values based on topological relationships.
- complist = self.get_temporal_topo_list(tvarexprA, tvarexprB, topolist = relations,
- compare_bool = True, compop = function[0], aggregate = aggregate)
- # Set temporal extent based on topological relationships.
- resultlist = self.set_temporal_extent_list(complist, topolist = relations,
- temporal = temporal)
-
- t[0] = resultlist
- 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]
- # Evaluate temporal comparison operator.
- relations, temporal, function, aggregate = self.eval_toperator(t[2], optype = 'boolean')
- # Build conditional values based on topological relationships.
- complist = self.get_temporal_topo_list(tvarexprA, tvarexprB, topolist = relations,
- compare_bool = True, compop = function[0], aggregate = aggregate)
- # Set temporal extent based on topological relationships.
- resultlist = self.set_temporal_extent_list(complist, topolist = relations,
- temporal = temporal)
- t[0] = resultlist
- 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 str(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], optype = 'select')
- # 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], optype = 'relation')[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], optype = 'relation')[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()
|