~ubuntu-branches/ubuntu/vivid/grass/vivid-proposed

« back to all changes in this revision

Viewing changes to lib/python/temporal/temporal_algebra.py

  • Committer: Package Import Robot
  • Author(s): Bas Couwenberg
  • Date: 2015-02-20 23:12:08 UTC
  • mfrom: (8.2.6 experimental)
  • Revision ID: package-import@ubuntu.com-20150220231208-1u6qvqm84v430b10
Tags: 7.0.0-1~exp1
* New upstream release.
* Update python-ctypes-ternary.patch to use if/else instead of and/or.
* Drop check4dev patch, rely on upstream check.
* Add build dependency on libpq-dev to grass-dev for libpq-fe.h.
* Drop patches applied upstream, refresh remaining patches.
* Update symlinks for images switched from jpg to png.

Show diffs side-by-side

added added

removed removed

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