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

« back to all changes in this revision

Viewing changes to lib/python/temporal/temporal_extent.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
"""
 
2
Temporal extent classes
 
3
 
 
4
Usage:
 
5
 
 
6
.. code-block:: python
 
7
 
 
8
    >>> import grass.temporal as tgis
 
9
    >>> from datetime import datetime
 
10
    >>> tgis.init()
 
11
    >>> t = tgis.RasterRelativeTime()
 
12
    >>> t = tgis.RasterAbsoluteTime()
 
13
 
 
14
 
 
15
(C) 2012-2013 by the GRASS Development Team
 
16
This program is free software under the GNU General Public
 
17
License (>=v2). Read the file COPYING that comes with GRASS
 
18
for details.
 
19
 
 
20
:authors: Soeren Gebbert
 
21
"""
 
22
from base import *
 
23
 
 
24
###############################################################################
 
25
 
 
26
 
 
27
class TemporalExtent(SQLDatabaseInterface):
 
28
    """This is the abstract time base class for relative and absolute time
 
29
    objects.
 
30
 
 
31
    It abstract class implements the interface to absolute and relative time.
 
32
    Absolute time is represented by datetime time stamps,
 
33
    relative time is represented by a unit an integer value.
 
34
 
 
35
    This class implements temporal topology relationships computation
 
36
    after [Allen and Ferguson 1994 Actions and Events in Interval Temporal Logic].
 
37
 
 
38
    Usage:
 
39
 
 
40
    .. code-block:: python
 
41
 
 
42
        >>> init()
 
43
        >>> A = TemporalExtent(table="raster_absolute_time",
 
44
        ... ident="soil@PERMANENT", start_time=datetime(2001, 01, 01),
 
45
        ... end_time=datetime(2005,01,01) )
 
46
        >>> A.id
 
47
        'soil@PERMANENT'
 
48
        >>> A.start_time
 
49
        datetime.datetime(2001, 1, 1, 0, 0)
 
50
        >>> A.end_time
 
51
        datetime.datetime(2005, 1, 1, 0, 0)
 
52
        >>> A.print_info()
 
53
         | Start time:................. 2001-01-01 00:00:00
 
54
         | End time:................... 2005-01-01 00:00:00
 
55
        >>> A.print_shell_info()
 
56
        start_time=2001-01-01 00:00:00
 
57
        end_time=2005-01-01 00:00:00
 
58
        >>> # relative time
 
59
        >>> A = TemporalExtent(table="raster_absolute_time",
 
60
        ... ident="soil@PERMANENT", start_time=0, end_time=1 )
 
61
        >>> A.id
 
62
        'soil@PERMANENT'
 
63
        >>> A.start_time
 
64
        0
 
65
        >>> A.end_time
 
66
        1
 
67
        >>> A.print_info()
 
68
         | Start time:................. 0
 
69
         | End time:................... 1
 
70
        >>> A.print_shell_info()
 
71
        start_time=0
 
72
        end_time=1
 
73
 
 
74
    """
 
75
    def __init__(self, table=None, ident=None, start_time=None, end_time=None):
 
76
 
 
77
        SQLDatabaseInterface.__init__(self, table, ident)
 
78
 
 
79
        self.set_id(ident)
 
80
        self.set_start_time(start_time)
 
81
        self.set_end_time(end_time)
 
82
 
 
83
    def intersect(self, extent):
 
84
        """Intersect this temporal extent with the provided temporal extent and
 
85
           return a new temporal extent with the new start and end time
 
86
 
 
87
           :param extent: The temporal extent to intersect with
 
88
           :return: The new temporal extent with start and end time,
 
89
                   or None in case of no intersection
 
90
 
 
91
           Usage:
 
92
 
 
93
           .. code-block:: python
 
94
 
 
95
               >>> A = TemporalExtent(start_time=5, end_time=6 )
 
96
               >>> inter = A.intersect(A)
 
97
               >>> inter.print_info()
 
98
                | Start time:................. 5
 
99
                | End time:................... 6
 
100
 
 
101
               >>> A = TemporalExtent(start_time=5, end_time=6 )
 
102
               >>> B = TemporalExtent(start_time=5, end_time=7 )
 
103
               >>> inter = A.intersect(B)
 
104
               >>> inter.print_info()
 
105
                | Start time:................. 5
 
106
                | End time:................... 6
 
107
               >>> inter = B.intersect(A)
 
108
               >>> inter.print_info()
 
109
                | Start time:................. 5
 
110
                | End time:................... 6
 
111
 
 
112
               >>> A = TemporalExtent(start_time=3, end_time=6 )
 
113
               >>> B = TemporalExtent(start_time=5, end_time=7 )
 
114
               >>> inter = A.intersect(B)
 
115
               >>> inter.print_info()
 
116
                | Start time:................. 5
 
117
                | End time:................... 6
 
118
               >>> inter = B.intersect(A)
 
119
               >>> inter.print_info()
 
120
                | Start time:................. 5
 
121
                | End time:................... 6
 
122
 
 
123
               >>> A = TemporalExtent(start_time=3, end_time=8 )
 
124
               >>> B = TemporalExtent(start_time=5, end_time=6 )
 
125
               >>> inter = A.intersect(B)
 
126
               >>> inter.print_info()
 
127
                | Start time:................. 5
 
128
                | End time:................... 6
 
129
               >>> inter = B.intersect(A)
 
130
               >>> inter.print_info()
 
131
                | Start time:................. 5
 
132
                | End time:................... 6
 
133
 
 
134
               >>> A = TemporalExtent(start_time=5, end_time=8 )
 
135
               >>> B = TemporalExtent(start_time=3, end_time=6 )
 
136
               >>> inter = A.intersect(B)
 
137
               >>> inter.print_info()
 
138
                | Start time:................. 5
 
139
                | End time:................... 6
 
140
               >>> inter = B.intersect(A)
 
141
               >>> inter.print_info()
 
142
                | Start time:................. 5
 
143
                | End time:................... 6
 
144
 
 
145
               >>> A = TemporalExtent(start_time=5, end_time=None )
 
146
               >>> B = TemporalExtent(start_time=3, end_time=6 )
 
147
               >>> inter = A.intersect(B)
 
148
               >>> inter.print_info()
 
149
                | Start time:................. 5
 
150
                | End time:................... None
 
151
               >>> inter = B.intersect(A)
 
152
               >>> inter.print_info()
 
153
                | Start time:................. 5
 
154
                | End time:................... None
 
155
 
 
156
               >>> A = TemporalExtent(start_time=5, end_time=8 )
 
157
               >>> B = TemporalExtent(start_time=3, end_time=4 )
 
158
               >>> inter = A.intersect(B)
 
159
               >>> print inter
 
160
               None
 
161
 
 
162
               >>> A = TemporalExtent(start_time=5, end_time=8 )
 
163
               >>> B = TemporalExtent(start_time=3, end_time=None )
 
164
               >>> inter = A.intersect(B)
 
165
               >>> print inter
 
166
               None
 
167
 
 
168
        """
 
169
        relation = self.temporal_relation(extent)
 
170
 
 
171
        if relation == "after" or relation == "before":
 
172
            return None
 
173
 
 
174
        if self.D["end_time"] is None:
 
175
            return TemporalExtent(start_time=self.D["start_time"])
 
176
 
 
177
        if extent.D["end_time"] is None:
 
178
            return TemporalExtent(start_time=extent.D["start_time"])
 
179
 
 
180
        start = None
 
181
        end = None
 
182
 
 
183
        if self.D["start_time"] > extent.D["start_time"]:
 
184
            start = self.D["start_time"]
 
185
        else:
 
186
            start = extent.D["start_time"]
 
187
 
 
188
        if self.D["end_time"] > extent.D["end_time"]:
 
189
            end = extent.D["end_time"]
 
190
        else:
 
191
            end = self.D["end_time"]
 
192
 
 
193
        if issubclass(type(self), RelativeTemporalExtent):
 
194
            return RelativeTemporalExtent(start_time=start, end_time=end,
 
195
                                          unit=self.get_unit())
 
196
        elif issubclass(type(self), AbsoluteTemporalExtent):
 
197
            return AbsoluteTemporalExtent(start_time=start, end_time=end)
 
198
        elif issubclass(type(self), TemporalExtent):
 
199
            return TemporalExtent(start_time=start, end_time=end)
 
200
 
 
201
    def disjoint_union(self, extent):
 
202
        """Creates a disjoint union with this temporal extent and the provided one.
 
203
           Return a new temporal extent with the new start and end time.
 
204
 
 
205
           :param extent: The temporal extent to create a union with
 
206
           :return: The new temporal extent with start and end time
 
207
 
 
208
           Usage:
 
209
 
 
210
           .. code-block:: python
 
211
 
 
212
               >>> A = TemporalExtent(start_time=5, end_time=6 )
 
213
               >>> inter = A.intersect(A)
 
214
               >>> inter.print_info()
 
215
                | Start time:................. 5
 
216
                | End time:................... 6
 
217
 
 
218
               >>> A = TemporalExtent(start_time=5, end_time=6 )
 
219
               >>> B = TemporalExtent(start_time=5, end_time=7 )
 
220
               >>> inter = A.disjoint_union(B)
 
221
               >>> inter.print_info()
 
222
                | Start time:................. 5
 
223
                | End time:................... 7
 
224
               >>> inter = B.disjoint_union(A)
 
225
               >>> inter.print_info()
 
226
                | Start time:................. 5
 
227
                | End time:................... 7
 
228
 
 
229
               >>> A = TemporalExtent(start_time=3, end_time=6 )
 
230
               >>> B = TemporalExtent(start_time=5, end_time=7 )
 
231
               >>> inter = A.disjoint_union(B)
 
232
               >>> inter.print_info()
 
233
                | Start time:................. 3
 
234
                | End time:................... 7
 
235
               >>> inter = B.disjoint_union(A)
 
236
               >>> inter.print_info()
 
237
                | Start time:................. 3
 
238
                | End time:................... 7
 
239
 
 
240
               >>> A = TemporalExtent(start_time=3, end_time=8 )
 
241
               >>> B = TemporalExtent(start_time=5, end_time=6 )
 
242
               >>> inter = A.disjoint_union(B)
 
243
               >>> inter.print_info()
 
244
                | Start time:................. 3
 
245
                | End time:................... 8
 
246
               >>> inter = B.disjoint_union(A)
 
247
               >>> inter.print_info()
 
248
                | Start time:................. 3
 
249
                | End time:................... 8
 
250
 
 
251
               >>> A = TemporalExtent(start_time=5, end_time=8 )
 
252
               >>> B = TemporalExtent(start_time=3, end_time=6 )
 
253
               >>> inter = A.disjoint_union(B)
 
254
               >>> inter.print_info()
 
255
                | Start time:................. 3
 
256
                | End time:................... 8
 
257
               >>> inter = B.disjoint_union(A)
 
258
               >>> inter.print_info()
 
259
                | Start time:................. 3
 
260
                | End time:................... 8
 
261
 
 
262
               >>> A = TemporalExtent(start_time=5, end_time=None )
 
263
               >>> B = TemporalExtent(start_time=3, end_time=6 )
 
264
               >>> inter = A.disjoint_union(B)
 
265
               >>> inter.print_info()
 
266
                | Start time:................. 3
 
267
                | End time:................... 6
 
268
               >>> inter = B.disjoint_union(A)
 
269
               >>> inter.print_info()
 
270
                | Start time:................. 3
 
271
                | End time:................... 6
 
272
 
 
273
               >>> A = TemporalExtent(start_time=5, end_time=8 )
 
274
               >>> B = TemporalExtent(start_time=3, end_time=4 )
 
275
               >>> inter = A.disjoint_union(B)
 
276
               >>> inter.print_info()
 
277
                | Start time:................. 3
 
278
                | End time:................... 8
 
279
               >>> inter = B.disjoint_union(A)
 
280
               >>> inter.print_info()
 
281
                | Start time:................. 3
 
282
                | End time:................... 8
 
283
               >>> A = TemporalExtent(start_time=5, end_time=8 )
 
284
               >>> B = TemporalExtent(start_time=3, end_time=None )
 
285
               >>> inter = A.disjoint_union(B)
 
286
               >>> inter.print_info()
 
287
                | Start time:................. 3
 
288
                | End time:................... 8
 
289
               >>> inter = B.disjoint_union(A)
 
290
               >>> inter.print_info()
 
291
                | Start time:................. 3
 
292
                | End time:................... 8
 
293
               >>> A = TemporalExtent(start_time=5, end_time=None )
 
294
               >>> B = TemporalExtent(start_time=3, end_time=8 )
 
295
               >>> inter = A.disjoint_union(B)
 
296
               >>> inter.print_info()
 
297
                | Start time:................. 3
 
298
                | End time:................... 8
 
299
               >>> inter = B.disjoint_union(A)
 
300
               >>> inter.print_info()
 
301
                | Start time:................. 3
 
302
                | End time:................... 8
 
303
               >>> A = TemporalExtent(start_time=5, end_time=None )
 
304
               >>> B = TemporalExtent(start_time=3, end_time=None )
 
305
               >>> inter = A.disjoint_union(B)
 
306
               >>> inter.print_info()
 
307
                | Start time:................. 3
 
308
                | End time:................... 5
 
309
               >>> inter = B.disjoint_union(A)
 
310
               >>> inter.print_info()
 
311
                | Start time:................. 3
 
312
                | End time:................... 5
 
313
 
 
314
               >>> A = RelativeTemporalExtent(start_time=5, end_time=None, unit="years" )
 
315
               >>> B = RelativeTemporalExtent(start_time=3, end_time=None, unit="years" )
 
316
               >>> inter = A.disjoint_union(B)
 
317
               >>> inter.print_info()
 
318
                +-------------------- Relative time -----------------------------------------+
 
319
                | Start time:................. 3
 
320
                | End time:................... 5
 
321
                | Relative time unit:......... years
 
322
 
 
323
               >>> inter = B.disjoint_union(A)
 
324
               >>> inter.print_info()
 
325
                +-------------------- Relative time -----------------------------------------+
 
326
                | Start time:................. 3
 
327
                | End time:................... 5
 
328
                | Relative time unit:......... years
 
329
 
 
330
 
 
331
               >>> from datetime import datetime as dt
 
332
               >>> A = AbsoluteTemporalExtent(start_time=dt(2001,1,10), end_time=dt(2003,1,1))
 
333
               >>> B = AbsoluteTemporalExtent(start_time=dt(2005,1,10), end_time=dt(2008,1,1))
 
334
               >>> inter = A.disjoint_union(B)
 
335
               >>> inter.print_info()
 
336
                +-------------------- Absolute time -----------------------------------------+
 
337
                | Start time:................. 2001-01-10 00:00:00
 
338
                | End time:................... 2008-01-01 00:00:00
 
339
 
 
340
               >>> inter = B.disjoint_union(A)
 
341
               >>> inter.print_info()
 
342
                +-------------------- Absolute time -----------------------------------------+
 
343
                | Start time:................. 2001-01-10 00:00:00
 
344
                | End time:................... 2008-01-01 00:00:00
 
345
 
 
346
        """
 
347
 
 
348
        start = None
 
349
        end = None
 
350
 
 
351
        if self.D["start_time"] < extent.D["start_time"]:
 
352
            start = self.D["start_time"]
 
353
        else:
 
354
            start = extent.D["start_time"]
 
355
 
 
356
        # End time handling
 
357
        if self.D["end_time"] is None and extent.D["end_time"] is None:
 
358
            if self.D["start_time"] > extent.D["start_time"]:
 
359
                end = self.D["start_time"]
 
360
            else:
 
361
                end = extent.D["start_time"]
 
362
        elif self.D["end_time"] is None:
 
363
            if self.D["start_time"] > extent.D["end_time"]:
 
364
                end = self.D["start_time"]
 
365
            else:
 
366
                end = extent.D["end_time"]
 
367
        elif extent.D["end_time"] is None:
 
368
            if self.D["end_time"] > extent.D["start_time"]:
 
369
                end = self.D["end_time"]
 
370
            else:
 
371
                end = extent.D["start_time"]
 
372
        elif self.D["end_time"] < extent.D["end_time"]:
 
373
            end = extent.D["end_time"]
 
374
        else:
 
375
            end = self.D["end_time"]
 
376
 
 
377
        if issubclass(type(self), RelativeTemporalExtent):
 
378
            return RelativeTemporalExtent(start_time=start, end_time=end,
 
379
                                          unit=self.get_unit())
 
380
        elif issubclass(type(self), AbsoluteTemporalExtent):
 
381
            return AbsoluteTemporalExtent(start_time=start, end_time=end)
 
382
        elif issubclass(type(self), TemporalExtent):
 
383
            return TemporalExtent(start_time=start, end_time=end)
 
384
 
 
385
    def union(self, extent):
 
386
        """Creates a union with this temporal extent and the provided one.
 
387
           Return a new temporal extent with the new start and end time.
 
388
 
 
389
           :param extent: The temporal extent to create a union with
 
390
           :return: The new temporal extent with start and end time,
 
391
                    or None in case the temporal extents are unrelated
 
392
                    (before or after)
 
393
 
 
394
           .. code-block:: python
 
395
 
 
396
               >>> A = TemporalExtent(start_time=5, end_time=8 )
 
397
               >>> B = TemporalExtent(start_time=3, end_time=4 )
 
398
               >>> inter = A.intersect(B)
 
399
               >>> print inter
 
400
               None
 
401
 
 
402
               >>> A = TemporalExtent(start_time=5, end_time=8 )
 
403
               >>> B = TemporalExtent(start_time=3, end_time=None )
 
404
               >>> inter = A.intersect(B)
 
405
               >>> print inter
 
406
               None
 
407
 
 
408
        """
 
409
 
 
410
        relation = self.temporal_relation(extent)
 
411
 
 
412
        if relation == "after" or relation == "before":
 
413
            return None
 
414
 
 
415
        return self.disjoint_union(extent)
 
416
 
 
417
    def starts(self, extent):
 
418
        """Return True if this temporal extent (A) starts at the start of the
 
419
           provided temporal extent (B) and finishes within it
 
420
           ::
 
421
 
 
422
               A  |-----|
 
423
               B  |---------|
 
424
 
 
425
 
 
426
           :param extent: The temporal extent object with which this extent
 
427
                          starts
 
428
 
 
429
           Usage:
 
430
 
 
431
           .. code-block:: python
 
432
 
 
433
               >>> A = TemporalExtent(start_time=5, end_time=6 )
 
434
               >>> B = TemporalExtent(start_time=5, end_time=7 )
 
435
               >>> A.starts(B)
 
436
               True
 
437
               >>> B.starts(A)
 
438
               False
 
439
 
 
440
        """
 
441
        if self.D["end_time"] is None or extent.D["end_time"] is None:
 
442
            return False
 
443
 
 
444
        if self.D["start_time"] == extent.D["start_time"] and \
 
445
           self.D["end_time"] < extent.D["end_time"]:
 
446
            return True
 
447
        else:
 
448
            return False
 
449
 
 
450
    def started(self, extent):
 
451
        """Return True if this temporal extent (A) started at the start of the
 
452
           provided temporal extent (B) and finishes after it
 
453
           ::
 
454
 
 
455
               A  |---------|
 
456
               B  |-----|
 
457
 
 
458
           :param extent: The temporal extent object with which this extent
 
459
                          started
 
460
 
 
461
           Usage:
 
462
 
 
463
           .. code-block:: python
 
464
 
 
465
               >>> A = TemporalExtent(start_time=5, end_time=7 )
 
466
               >>> B = TemporalExtent(start_time=5, end_time=6 )
 
467
               >>> A.started(B)
 
468
               True
 
469
               >>> B.started(A)
 
470
               False
 
471
 
 
472
        """
 
473
        if self.D["end_time"] is None or extent.D["end_time"] is None:
 
474
            return False
 
475
 
 
476
        if self.D["start_time"] == extent.D["start_time"] and \
 
477
           self.D["end_time"] > extent.D["end_time"]:
 
478
            return True
 
479
        else:
 
480
            return False
 
481
 
 
482
    def finishes(self, extent):
 
483
        """Return True if this temporal extent (A) starts after the start of
 
484
           the provided temporal extent (B) and finishes with it
 
485
           ::
 
486
 
 
487
               A      |-----|
 
488
               B  |---------|
 
489
 
 
490
           :param extent: The temporal extent object with which this extent
 
491
                          finishes
 
492
 
 
493
           Usage:
 
494
 
 
495
           .. code-block:: python
 
496
 
 
497
               >>> A = TemporalExtent(start_time=6, end_time=7 )
 
498
               >>> B = TemporalExtent(start_time=5, end_time=7 )
 
499
               >>> A.finishes(B)
 
500
               True
 
501
               >>> B.finishes(A)
 
502
               False
 
503
 
 
504
        """
 
505
        if self.D["end_time"] is None or extent.D["end_time"] is None:
 
506
            return False
 
507
 
 
508
        if self.D["end_time"] == extent.D["end_time"] and \
 
509
           self.D["start_time"] > extent.D["start_time"]:
 
510
            return True
 
511
        else:
 
512
            return False
 
513
 
 
514
    def finished(self, extent):
 
515
        """Return True if this temporal extent (A) starts before the start of
 
516
           the provided temporal extent (B) and finishes with it
 
517
           ::
 
518
 
 
519
               A  |---------|
 
520
               B      |-----|
 
521
 
 
522
           :param extent: The temporal extent object with which this extent
 
523
                          finishes
 
524
 
 
525
           Usage:
 
526
 
 
527
           .. code-block:: python
 
528
 
 
529
               >>> A = TemporalExtent(start_time=5, end_time=7 )
 
530
               >>> B = TemporalExtent(start_time=6, end_time=7 )
 
531
               >>> A.finished(B)
 
532
               True
 
533
               >>> B.finished(A)
 
534
               False
 
535
 
 
536
        """
 
537
        if self.D["end_time"] is None or extent.D["end_time"] is None:
 
538
            return False
 
539
 
 
540
        if self.D["end_time"] == extent.D["end_time"] and \
 
541
           self.D["start_time"] < extent.D["start_time"]:
 
542
            return True
 
543
        else:
 
544
            return False
 
545
 
 
546
    def after(self, extent):
 
547
        """Return True if this temporal extent (A) is located after the
 
548
           provided temporal extent (B)
 
549
           ::
 
550
 
 
551
               A             |---------|
 
552
               B  |---------|
 
553
 
 
554
           :param extent: The temporal extent object that is located before
 
555
                          this extent
 
556
 
 
557
           Usage:
 
558
 
 
559
           .. code-block:: python
 
560
 
 
561
               >>> A = TemporalExtent(start_time=8, end_time=9 )
 
562
               >>> B = TemporalExtent(start_time=6, end_time=7 )
 
563
               >>> A.after(B)
 
564
               True
 
565
               >>> B.after(A)
 
566
               False
 
567
 
 
568
        """
 
569
        if extent.D["end_time"] is None:
 
570
            if self.D["start_time"] > extent.D["start_time"]:
 
571
                return True
 
572
            else:
 
573
                return False
 
574
 
 
575
        if self.D["start_time"] > extent.D["end_time"]:
 
576
            return True
 
577
        else:
 
578
            return False
 
579
 
 
580
    def before(self, extent):
 
581
        """Return True if this temporal extent (A) is located before the
 
582
           provided temporal extent (B)
 
583
           ::
 
584
 
 
585
               A  |---------|
 
586
               B             |---------|
 
587
 
 
588
           :param extent: The temporal extent object that is located after
 
589
                          this extent
 
590
 
 
591
           Usage:
 
592
 
 
593
           .. code-block:: python
 
594
 
 
595
               >>> A = TemporalExtent(start_time=6, end_time=7 )
 
596
               >>> B = TemporalExtent(start_time=8, end_time=9 )
 
597
               >>> A.before(B)
 
598
               True
 
599
               >>> B.before(A)
 
600
               False
 
601
 
 
602
        """
 
603
        if self.D["end_time"] is None:
 
604
            if self.D["start_time"] < extent.D["start_time"]:
 
605
                return True
 
606
            else:
 
607
                return False
 
608
 
 
609
        if self.D["end_time"] < extent.D["start_time"]:
 
610
            return True
 
611
        else:
 
612
            return False
 
613
 
 
614
    def adjacent(self, extent):
 
615
        """Return True if this temporal extent (A) is a meeting neighbor the
 
616
           provided temporal extent (B)
 
617
           ::
 
618
 
 
619
               A            |---------|
 
620
               B  |---------|
 
621
               A  |---------|
 
622
               B            |---------|
 
623
 
 
624
           :param extent: The temporal extent object that is a meeting neighbor
 
625
                          of this extent
 
626
 
 
627
           Usage:
 
628
 
 
629
           .. code-block:: python
 
630
 
 
631
               >>> A = TemporalExtent(start_time=5, end_time=7 )
 
632
               >>> B = TemporalExtent(start_time=7, end_time=9 )
 
633
               >>> A.adjacent(B)
 
634
               True
 
635
               >>> B.adjacent(A)
 
636
               True
 
637
               >>> A = TemporalExtent(start_time=5, end_time=7 )
 
638
               >>> B = TemporalExtent(start_time=3, end_time=5 )
 
639
               >>> A.adjacent(B)
 
640
               True
 
641
               >>> B.adjacent(A)
 
642
               True
 
643
 
 
644
        """
 
645
        if self.D["end_time"] is None and extent.D["end_time"] is None:
 
646
            return False
 
647
 
 
648
        if (self.D["start_time"] == extent.D["end_time"]) or \
 
649
           (self.D["end_time"] == extent.D["start_time"]):
 
650
            return True
 
651
        else:
 
652
            return False
 
653
 
 
654
    def follows(self, extent):
 
655
        """Return True if this temporal extent (A) follows the
 
656
           provided temporal extent (B)
 
657
           ::
 
658
 
 
659
               A            |---------|
 
660
               B  |---------|
 
661
 
 
662
           :param extent: The temporal extent object that is the predecessor
 
663
                          of this extent
 
664
 
 
665
           Usage:
 
666
 
 
667
           .. code-block:: python
 
668
 
 
669
               >>> A = TemporalExtent(start_time=5, end_time=7 )
 
670
               >>> B = TemporalExtent(start_time=3, end_time=5 )
 
671
               >>> A.follows(B)
 
672
               True
 
673
               >>> B.follows(A)
 
674
               False
 
675
 
 
676
        """
 
677
        if extent.D["end_time"] is None:
 
678
            return False
 
679
 
 
680
        if self.D["start_time"] == extent.D["end_time"]:
 
681
            return True
 
682
        else:
 
683
            return False
 
684
 
 
685
    def precedes(self, extent):
 
686
        """Return True if this temporal extent (A) precedes the provided
 
687
           temporal extent (B)
 
688
           ::
 
689
 
 
690
               A  |---------|
 
691
               B            |---------|
 
692
 
 
693
 
 
694
           :param extent: The temporal extent object that is the successor
 
695
                          of this extent
 
696
 
 
697
           Usage:
 
698
 
 
699
           .. code-block:: python
 
700
 
 
701
               >>> A = TemporalExtent(start_time=5, end_time=7 )
 
702
               >>> B = TemporalExtent(start_time=7, end_time=9 )
 
703
               >>> A.precedes(B)
 
704
               True
 
705
               >>> B.precedes(A)
 
706
               False
 
707
 
 
708
 
 
709
        """
 
710
        if self.D["end_time"] is None:
 
711
            return False
 
712
 
 
713
        if self.D["end_time"] == extent.D["start_time"]:
 
714
            return True
 
715
        else:
 
716
            return False
 
717
 
 
718
    def during(self, extent):
 
719
        """Return True if this temporal extent (A) is located during the provided
 
720
           temporal extent (B)
 
721
           ::
 
722
 
 
723
               A   |-------|
 
724
               B  |---------|
 
725
 
 
726
           :param extent: The temporal extent object that contains this extent
 
727
 
 
728
           Usage:
 
729
 
 
730
           .. code-block:: python
 
731
 
 
732
               >>> A = TemporalExtent(start_time=5, end_time=7 )
 
733
               >>> B = TemporalExtent(start_time=4, end_time=9 )
 
734
               >>> A.during(B)
 
735
               True
 
736
               >>> B.during(A)
 
737
               False
 
738
 
 
739
        """
 
740
        # Check single point of time in interval
 
741
        if extent.D["end_time"] is None:
 
742
            return False
 
743
 
 
744
        # Check single point of time in interval
 
745
        if self.D["end_time"] is None:
 
746
            if self.D["start_time"] >= extent.D["start_time"] and \
 
747
               self.D["start_time"] < extent.D["end_time"]:
 
748
                return True
 
749
            else:
 
750
                return False
 
751
 
 
752
        if self.D["start_time"] > extent.D["start_time"] and \
 
753
           self.D["end_time"] < extent.D["end_time"]:
 
754
            return True
 
755
        else:
 
756
            return False
 
757
 
 
758
    def contains(self, extent):
 
759
        """Return True if this temporal extent (A) contains the provided
 
760
           temporal extent (B)
 
761
           ::
 
762
 
 
763
               A  |---------|
 
764
               B   |-------|
 
765
 
 
766
           :param extent: The temporal extent object that is located
 
767
                          during this extent
 
768
 
 
769
           Usage:
 
770
 
 
771
           .. code-block:: python
 
772
 
 
773
               >>> A = TemporalExtent(start_time=4, end_time=9 )
 
774
               >>> B = TemporalExtent(start_time=5, end_time=8 )
 
775
               >>> A.contains(B)
 
776
               True
 
777
               >>> B.contains(A)
 
778
               False
 
779
 
 
780
        """
 
781
        # Check single point of time in interval
 
782
        if self.D["end_time"] is None:
 
783
            return False
 
784
 
 
785
        # Check single point of time in interval
 
786
        if extent.D["end_time"] is None:
 
787
            if self.D["start_time"] <= extent.D["start_time"] and \
 
788
               self.D["end_time"] > extent.D["start_time"]:
 
789
                return True
 
790
            else:
 
791
                return False
 
792
 
 
793
        if self.D["start_time"] < extent.D["start_time"] and \
 
794
           self.D["end_time"] > extent.D["end_time"]:
 
795
            return True
 
796
        else:
 
797
            return False
 
798
 
 
799
    def equal(self, extent):
 
800
        """Return True if this temporal extent (A) is equal to the provided
 
801
           temporal extent (B)
 
802
           ::
 
803
 
 
804
               A  |---------|
 
805
               B  |---------|
 
806
 
 
807
           :param extent: The temporal extent object that is equal
 
808
                          during this extent
 
809
 
 
810
           Usage:
 
811
 
 
812
           .. code-block:: python
 
813
 
 
814
               >>> A = TemporalExtent(start_time=5, end_time=6 )
 
815
               >>> B = TemporalExtent(start_time=5, end_time=6 )
 
816
               >>> A.equal(B)
 
817
               True
 
818
               >>> B.equal(A)
 
819
               True
 
820
 
 
821
        """
 
822
        if self.D["end_time"] is None and extent.D["end_time"] is None:
 
823
            if self.D["start_time"] == extent.D["start_time"]:
 
824
                return True
 
825
            else:
 
826
                return False
 
827
 
 
828
        if self.D["end_time"] is None or extent.D["end_time"] is None:
 
829
            return False
 
830
 
 
831
        if self.D["start_time"] == extent.D["start_time"] and \
 
832
           self.D["end_time"] == extent.D["end_time"]:
 
833
            return True
 
834
        else:
 
835
            return False
 
836
 
 
837
    def overlaps(self, extent):
 
838
        """Return True if this temporal extent (A) overlapped the provided
 
839
           temporal extent (B)
 
840
           ::
 
841
 
 
842
               A  |---------|
 
843
               B    |---------|
 
844
 
 
845
           :param extent: The temporal extent object that is overlaps
 
846
                          this extent
 
847
 
 
848
           Usage:
 
849
 
 
850
           .. code-block:: python
 
851
 
 
852
               >>> A = TemporalExtent(start_time=5, end_time=7 )
 
853
               >>> B = TemporalExtent(start_time=6, end_time=8 )
 
854
               >>> A.overlaps(B)
 
855
               True
 
856
               >>> B.overlaps(A)
 
857
               False
 
858
 
 
859
               >>> A = TemporalExtent(start_time=5, end_time=6 )
 
860
               >>> B = TemporalExtent(start_time=6, end_time=8 )
 
861
               >>> A.overlaps(B)
 
862
               False
 
863
               >>> B.overlaps(A)
 
864
               False
 
865
 
 
866
        """
 
867
        if self.D["end_time"] is None or extent.D["end_time"] is None:
 
868
            return False
 
869
 
 
870
        if self.D["start_time"] < extent.D["start_time"] and \
 
871
           self.D["end_time"] < extent.D["end_time"] and \
 
872
           self.D["end_time"] > extent.D["start_time"]:
 
873
            return True
 
874
        else:
 
875
            return False
 
876
 
 
877
    def overlapped(self, extent):
 
878
        """Return True if this temporal extent (A) overlapps the provided
 
879
           temporal extent (B)
 
880
           ::
 
881
 
 
882
               A    |---------|
 
883
               B  |---------|
 
884
 
 
885
 
 
886
           :param extent: The temporal extent object that is overlapped
 
887
                          this extent
 
888
 
 
889
           Usage:
 
890
 
 
891
           .. code-block:: python
 
892
 
 
893
               >>> A = TemporalExtent(start_time=6, end_time=8 )
 
894
               >>> B = TemporalExtent(start_time=5, end_time=7 )
 
895
               >>> A.overlapped(B)
 
896
               True
 
897
               >>> B.overlapped(A)
 
898
               False
 
899
 
 
900
               >>> A = TemporalExtent(start_time=6, end_time=8 )
 
901
               >>> B = TemporalExtent(start_time=5, end_time=6 )
 
902
               >>> A.overlapped(B)
 
903
               False
 
904
               >>> B.overlapped(A)
 
905
               False
 
906
 
 
907
        """
 
908
        if self.D["end_time"] is None or extent.D["end_time"] is None:
 
909
            return False
 
910
 
 
911
        if self.D["start_time"] > extent.D["start_time"] and \
 
912
           self.D["end_time"] > extent.D["end_time"] and \
 
913
           self.D["start_time"] < extent.D["end_time"]:
 
914
            return True
 
915
        else:
 
916
            return False
 
917
 
 
918
    def temporal_relation(self, extent):
 
919
        """Returns the temporal relation between temporal objects
 
920
        Temporal relationships are implemented after
 
921
        [Allen and Ferguson 1994 Actions and Events in Interval Temporal Logic]
 
922
 
 
923
        The following temporal relationships are supported:
 
924
 
 
925
            - equal
 
926
            - during
 
927
            - contains
 
928
            - overlaps
 
929
            - overlapped
 
930
            - after
 
931
            - before
 
932
            - starts
 
933
            - finishes
 
934
            - started
 
935
            - finished
 
936
            - follows
 
937
            - precedes
 
938
 
 
939
        :param extent: The temporal extent
 
940
        :return: The name of the temporal relation or None if no relation
 
941
                 found
 
942
        """
 
943
 
 
944
        # First check for correct time
 
945
        if "start_time" not in self.D:
 
946
            return None
 
947
        if "end_time" not in self.D:
 
948
            return None
 
949
        if "start_time" not in extent.D:
 
950
            return None
 
951
        if "end_time" not in extent.D:
 
952
            return None
 
953
        # Return None if the start_time is undefined
 
954
        if self.D["start_time"] is None or extent.D["start_time"] is None:
 
955
            return None
 
956
 
 
957
        if self.equal(extent):
 
958
            return "equal"
 
959
        if self.during(extent):
 
960
            return "during"
 
961
        if self.contains(extent):
 
962
            return "contains"
 
963
        if self.overlaps(extent):
 
964
            return "overlaps"
 
965
        if self.overlapped(extent):
 
966
            return "overlapped"
 
967
        if self.after(extent):
 
968
            return "after"
 
969
        if self.before(extent):
 
970
            return "before"
 
971
        if self.starts(extent):
 
972
            return "starts"
 
973
        if self.finishes(extent):
 
974
            return "finishes"
 
975
        if self.started(extent):
 
976
            return "started"
 
977
        if self.finished(extent):
 
978
            return "finished"
 
979
        if self.follows(extent):
 
980
            return "follows"
 
981
        if self.precedes(extent):
 
982
            return "precedes"
 
983
        return None
 
984
 
 
985
    def set_id(self, ident):
 
986
        """Convenient method to set the unique identifier (primary key)"""
 
987
        self.ident = ident
 
988
        self.D["id"] = ident
 
989
 
 
990
    def set_start_time(self, start_time):
 
991
        """Set the valid start time of the extent"""
 
992
        self.D["start_time"] = start_time
 
993
 
 
994
    def set_end_time(self, end_time):
 
995
        """Set the valid end time of the extent"""
 
996
        self.D["end_time"] = end_time
 
997
 
 
998
    def get_id(self):
 
999
        """Convenient method to get the unique identifier (primary key)
 
1000
           :return: None if not found
 
1001
        """
 
1002
        if "id" in self.D:
 
1003
            return self.D["id"]
 
1004
        else:
 
1005
            return None
 
1006
 
 
1007
    def get_start_time(self):
 
1008
        """Get the valid start time of the extent
 
1009
           :return: None if not found"""
 
1010
        if "start_time" in self.D:
 
1011
            return self.D["start_time"]
 
1012
        else:
 
1013
            return None
 
1014
 
 
1015
    def get_end_time(self):
 
1016
        """Get the valid end time of the extent
 
1017
           :return: None if not found"""
 
1018
        if "end_time" in self.D:
 
1019
            return self.D["end_time"]
 
1020
        else:
 
1021
            return None
 
1022
 
 
1023
    # Set the properties
 
1024
    id = property(fget=get_id, fset=set_id)
 
1025
    start_time = property(fget=get_start_time, fset=set_start_time)
 
1026
    end_time = property(fget=get_end_time, fset=set_end_time)
 
1027
 
 
1028
    def print_info(self):
 
1029
        """Print information about this class in human readable style"""
 
1030
        #      0123456789012345678901234567890
 
1031
        print " | Start time:................. " + str(self.get_start_time())
 
1032
        print " | End time:................... " + str(self.get_end_time())
 
1033
 
 
1034
    def print_shell_info(self):
 
1035
        """Print information about this class in shell style"""
 
1036
        print "start_time=" + str(self.get_start_time())
 
1037
        print "end_time=" + str(self.get_end_time())
 
1038
 
 
1039
###############################################################################
 
1040
 
 
1041
 
 
1042
class AbsoluteTemporalExtent(TemporalExtent):
 
1043
    """This is the absolute time class for all maps and spacetime datasets
 
1044
 
 
1045
        start_time and end_time must be of type datetime
 
1046
    """
 
1047
    def __init__(self, table=None, ident=None, start_time=None, end_time=None):
 
1048
 
 
1049
        TemporalExtent.__init__(
 
1050
            self, table, ident, start_time, end_time)
 
1051
 
 
1052
    def print_info(self):
 
1053
        """Print information about this class in human readable style"""
 
1054
        #      0123456789012345678901234567890
 
1055
        print " +-------------------- Absolute time -----------------------------------------+"
 
1056
        TemporalExtent.print_info(self)
 
1057
 
 
1058
    def print_shell_info(self):
 
1059
        """Print information about this class in shell style"""
 
1060
        TemporalExtent.print_shell_info(self)
 
1061
 
 
1062
###############################################################################
 
1063
 
 
1064
 
 
1065
class RasterAbsoluteTime(AbsoluteTemporalExtent):
 
1066
    def __init__(self, ident=None, start_time=None, end_time=None):
 
1067
        AbsoluteTemporalExtent.__init__(self, "raster_absolute_time",
 
1068
                                        ident, start_time, end_time)
 
1069
 
 
1070
 
 
1071
class Raster3DAbsoluteTime(AbsoluteTemporalExtent):
 
1072
    def __init__(self, ident=None, start_time=None, end_time=None):
 
1073
        AbsoluteTemporalExtent.__init__(self, "raster3d_absolute_time",
 
1074
                                        ident, start_time, end_time)
 
1075
 
 
1076
 
 
1077
class VectorAbsoluteTime(AbsoluteTemporalExtent):
 
1078
    def __init__(self, ident=None, start_time=None, end_time=None):
 
1079
        AbsoluteTemporalExtent.__init__(self, "vector_absolute_time",
 
1080
                                        ident, start_time, end_time)
 
1081
 
 
1082
###############################################################################
 
1083
 
 
1084
 
 
1085
class STDSAbsoluteTime(AbsoluteTemporalExtent):
 
1086
    """This class implements the absolute time extent for space time dataset
 
1087
 
 
1088
        In addition to the existing functionality the granularity and the
 
1089
        map_time are added.
 
1090
 
 
1091
        Usage:
 
1092
 
 
1093
        .. code-block:: python
 
1094
 
 
1095
            >>> init()
 
1096
            >>> A = STDSAbsoluteTime(table="strds_absolute_time",
 
1097
            ... ident="strds@PERMANENT", start_time=datetime(2001, 01, 01),
 
1098
            ... end_time=datetime(2005,01,01), granularity="1 days",
 
1099
            ... map_time="interval")
 
1100
            >>> A.id
 
1101
            'strds@PERMANENT'
 
1102
            >>> A.start_time
 
1103
            datetime.datetime(2001, 1, 1, 0, 0)
 
1104
            >>> A.end_time
 
1105
            datetime.datetime(2005, 1, 1, 0, 0)
 
1106
            >>> A.granularity
 
1107
            '1 days'
 
1108
            >>> A.map_time
 
1109
            'interval'
 
1110
            >>> A.print_info()
 
1111
             +-------------------- Absolute time -----------------------------------------+
 
1112
             | Start time:................. 2001-01-01 00:00:00
 
1113
             | End time:................... 2005-01-01 00:00:00
 
1114
             | Granularity:................ 1 days
 
1115
             | Temporal type of maps:...... interval
 
1116
            >>> A.print_shell_info()
 
1117
            start_time=2001-01-01 00:00:00
 
1118
            end_time=2005-01-01 00:00:00
 
1119
            granularity=1 days
 
1120
            map_time=interval
 
1121
 
 
1122
    """
 
1123
    def __init__(self, table=None, ident=None, start_time=None, end_time=None,
 
1124
                 granularity=None, map_time=None):
 
1125
        AbsoluteTemporalExtent.__init__(
 
1126
            self, table, ident, start_time, end_time)
 
1127
 
 
1128
        self.set_granularity(granularity)
 
1129
        self.set_map_time(map_time)
 
1130
 
 
1131
    def set_granularity(self, granularity):
 
1132
        """Set the granularity of the space time dataset"""
 
1133
        self.D["granularity"] = granularity
 
1134
 
 
1135
    def set_map_time(self, map_time):
 
1136
        """Set the type of the map time
 
1137
 
 
1138
           Registered maps may have different types of time:
 
1139
 
 
1140
           - Single point of time "point"
 
1141
           - Time intervals "interval"
 
1142
           - Single point and interval time "mixed"
 
1143
 
 
1144
           This variable will be set automatically when maps are registered.
 
1145
        """
 
1146
        self.D["map_time"] = map_time
 
1147
 
 
1148
    def get_granularity(self):
 
1149
        """Get the granularity of the space time dataset
 
1150
           :return: None if not found"""
 
1151
        if "granularity" in self.D:
 
1152
            return self.D["granularity"]
 
1153
        else:
 
1154
            return None
 
1155
 
 
1156
    def get_map_time(self):
 
1157
        """Get the type of the map time
 
1158
 
 
1159
           Registered maps may have different types of time:
 
1160
 
 
1161
           - Single point of time "point"
 
1162
           - Time intervals "interval"
 
1163
           - Single point and interval time "mixed"
 
1164
 
 
1165
           This variable will be set automatically when maps are registered.
 
1166
        """
 
1167
        if "map_time" in self.D:
 
1168
            return self.D["map_time"]
 
1169
        else:
 
1170
            return None
 
1171
 
 
1172
    # Properties
 
1173
    granularity = property(fget=get_granularity, fset=set_granularity)
 
1174
    map_time = property(fget=get_map_time, fset=set_map_time)
 
1175
 
 
1176
    def print_info(self):
 
1177
        """Print information about this class in human readable style"""
 
1178
        AbsoluteTemporalExtent.print_info(self)
 
1179
        #      0123456789012345678901234567890
 
1180
        print " | Granularity:................ " + str(self.get_granularity())
 
1181
        print " | Temporal type of maps:...... " + str(self.get_map_time())
 
1182
 
 
1183
    def print_shell_info(self):
 
1184
        """Print information about this class in shell style"""
 
1185
        AbsoluteTemporalExtent.print_shell_info(self)
 
1186
        print "granularity=" + str(self.get_granularity())
 
1187
        print "map_time=" + str(self.get_map_time())
 
1188
 
 
1189
###############################################################################
 
1190
 
 
1191
 
 
1192
class STRDSAbsoluteTime(STDSAbsoluteTime):
 
1193
    def __init__(self, ident=None, start_time=None, end_time=None,
 
1194
                 granularity=None):
 
1195
        STDSAbsoluteTime.__init__(self, "strds_absolute_time",
 
1196
                                  ident, start_time, end_time, granularity)
 
1197
 
 
1198
 
 
1199
class STR3DSAbsoluteTime(STDSAbsoluteTime):
 
1200
    def __init__(self, ident=None, start_time=None, end_time=None,
 
1201
                 granularity=None):
 
1202
        STDSAbsoluteTime.__init__(self, "str3ds_absolute_time",
 
1203
                                  ident, start_time, end_time, granularity)
 
1204
 
 
1205
 
 
1206
class STVDSAbsoluteTime(STDSAbsoluteTime):
 
1207
    def __init__(self, ident=None, start_time=None, end_time=None,
 
1208
                 granularity=None):
 
1209
        STDSAbsoluteTime.__init__(self, "stvds_absolute_time",
 
1210
                                  ident, start_time, end_time, granularity)
 
1211
 
 
1212
###############################################################################
 
1213
 
 
1214
 
 
1215
class RelativeTemporalExtent(TemporalExtent):
 
1216
    """This is the relative time class for all maps and space time datasets
 
1217
 
 
1218
        start_time and end_time must be of type integer
 
1219
 
 
1220
        Usage:
 
1221
 
 
1222
        .. code-block:: python
 
1223
 
 
1224
            >>> init()
 
1225
            >>> A = RelativeTemporalExtent(table="raster_relative_time",
 
1226
            ... ident="soil@PERMANENT", start_time=0, end_time=1, unit="years")
 
1227
            >>> A.id
 
1228
            'soil@PERMANENT'
 
1229
            >>> A.start_time
 
1230
            0
 
1231
            >>> A.end_time
 
1232
            1
 
1233
            >>> A.unit
 
1234
            'years'
 
1235
            >>> A.print_info()
 
1236
             +-------------------- Relative time -----------------------------------------+
 
1237
             | Start time:................. 0
 
1238
             | End time:................... 1
 
1239
             | Relative time unit:......... years
 
1240
            >>> A.print_shell_info()
 
1241
            start_time=0
 
1242
            end_time=1
 
1243
            unit=years
 
1244
 
 
1245
    """
 
1246
    def __init__(self, table=None, ident=None, start_time=None, end_time=None,
 
1247
                 unit=None):
 
1248
 
 
1249
        TemporalExtent.__init__(
 
1250
            self, table, ident, start_time, end_time)
 
1251
        self.set_unit(unit)
 
1252
 
 
1253
    def set_unit(self, unit):
 
1254
        """Set the unit of the relative time. Valid units are:
 
1255
 
 
1256
           - years
 
1257
           - months
 
1258
           - days
 
1259
           - hours
 
1260
           - minutes
 
1261
           - seconds
 
1262
        """
 
1263
        self.D["unit"] = unit
 
1264
 
 
1265
    def get_unit(self):
 
1266
        """Get the unit of the relative time
 
1267
           :return: None if not found"""
 
1268
        if "unit" in self.D:
 
1269
            return self.D["unit"]
 
1270
        else:
 
1271
            return None
 
1272
 
 
1273
    def temporal_relation(self, map):
 
1274
        """Returns the temporal relation between temporal objects
 
1275
           Temporal relationships are implemented after
 
1276
           [Allen and Ferguson 1994 Actions and Events in Interval Temporal Logic]
 
1277
        """
 
1278
 
 
1279
        # Check units for relative time
 
1280
        if "unit" not in self.D:
 
1281
            return None
 
1282
        if "unit" not in map.D:
 
1283
            return None
 
1284
 
 
1285
        # Units must be equal
 
1286
        if self.D["unit"] != map.D["unit"]:
 
1287
            return None
 
1288
 
 
1289
        return TemporalExtent.temporal_relation(self, map)
 
1290
 
 
1291
    # Properties
 
1292
    unit = property(fget=get_unit, fset=set_unit)
 
1293
 
 
1294
    def print_info(self):
 
1295
        """Print information about this class in human readable style"""
 
1296
        #      0123456789012345678901234567890
 
1297
        print " +-------------------- Relative time -----------------------------------------+"
 
1298
        TemporalExtent.print_info(self)
 
1299
        print " | Relative time unit:......... " + str(self.get_unit())
 
1300
 
 
1301
    def print_shell_info(self):
 
1302
        """Print information about this class in shell style"""
 
1303
        TemporalExtent.print_shell_info(self)
 
1304
        print "unit=" + str(self.get_unit())
 
1305
 
 
1306
###############################################################################
 
1307
 
 
1308
 
 
1309
class RasterRelativeTime(RelativeTemporalExtent):
 
1310
    def __init__(self, ident=None, start_time=None, end_time=None,
 
1311
                 unit=None):
 
1312
        RelativeTemporalExtent.__init__(self, "raster_relative_time", ident,
 
1313
                                        start_time, end_time, unit)
 
1314
 
 
1315
 
 
1316
class Raster3DRelativeTime(RelativeTemporalExtent):
 
1317
    def __init__(self, ident=None, start_time=None, end_time=None,
 
1318
                 unit=None):
 
1319
        RelativeTemporalExtent.__init__(self, "raster3d_relative_time", ident,
 
1320
                                        start_time, end_time, unit)
 
1321
 
 
1322
 
 
1323
class VectorRelativeTime(RelativeTemporalExtent):
 
1324
    def __init__(self, ident=None, start_time=None, end_time=None,
 
1325
                 unit=None):
 
1326
        RelativeTemporalExtent.__init__(
 
1327
            self, "vector_relative_time", ident, start_time, end_time, unit)
 
1328
 
 
1329
###############################################################################
 
1330
 
 
1331
 
 
1332
class STDSRelativeTime(RelativeTemporalExtent):
 
1333
    """This is the relative time class for all maps and space time datasets
 
1334
 
 
1335
        start_time and end_time must be of type integer
 
1336
 
 
1337
        Usage:
 
1338
 
 
1339
        .. code-block:: python
 
1340
 
 
1341
            >>> init()
 
1342
            >>> A = STDSRelativeTime(table="strds_relative_time",
 
1343
            ... ident="strds@PERMANENT", start_time=0, end_time=1, unit="years",
 
1344
            ... granularity=5, map_time="interval")
 
1345
            >>> A.id
 
1346
            'strds@PERMANENT'
 
1347
            >>> A.start_time
 
1348
            0
 
1349
            >>> A.end_time
 
1350
            1
 
1351
            >>> A.unit
 
1352
            'years'
 
1353
            >>> A.granularity
 
1354
            5
 
1355
            >>> A.map_time
 
1356
            'interval'
 
1357
            >>> A.print_info()
 
1358
             +-------------------- Relative time -----------------------------------------+
 
1359
             | Start time:................. 0
 
1360
             | End time:................... 1
 
1361
             | Relative time unit:......... years
 
1362
             | Granularity:................ 5
 
1363
             | Temporal type of maps:...... interval
 
1364
            >>> A.print_shell_info()
 
1365
            start_time=0
 
1366
            end_time=1
 
1367
            unit=years
 
1368
            granularity=5
 
1369
            map_time=interval
 
1370
 
 
1371
    """
 
1372
    def __init__(self, table=None, ident=None, start_time=None, end_time=None,
 
1373
                 unit=None, granularity=None, map_time=None):
 
1374
        RelativeTemporalExtent.__init__(
 
1375
            self, table, ident, start_time, end_time, unit)
 
1376
 
 
1377
        self.set_granularity(granularity)
 
1378
        self.set_map_time(map_time)
 
1379
 
 
1380
    def set_granularity(self, granularity):
 
1381
        """Set the granularity of the space time dataset"""
 
1382
        self.D["granularity"] = granularity
 
1383
 
 
1384
    def set_map_time(self, map_time):
 
1385
        """Set the type of the map time
 
1386
 
 
1387
           Registered maps may have different types of time:
 
1388
 
 
1389
           - Single point of time "point"
 
1390
           - Time intervals "interval"
 
1391
           - Single point and interval time "mixed"
 
1392
 
 
1393
           This variable will be set automatically when maps are registered.
 
1394
        """
 
1395
        self.D["map_time"] = map_time
 
1396
 
 
1397
    def get_granularity(self):
 
1398
        """Get the granularity of the space time dataset
 
1399
           :return: None if not found"""
 
1400
        if "granularity" in self.D:
 
1401
            return self.D["granularity"]
 
1402
        else:
 
1403
            return None
 
1404
 
 
1405
    def get_map_time(self):
 
1406
        """Get the type of the map time
 
1407
 
 
1408
           Registered maps may have different types of time:
 
1409
 
 
1410
           - Single point of time "point"
 
1411
           - Time intervals "interval"
 
1412
           - Single point and interval time "mixed"
 
1413
 
 
1414
           This variable will be set automatically when maps are registered.
 
1415
        """
 
1416
        if "map_time" in self.D:
 
1417
            return self.D["map_time"]
 
1418
        else:
 
1419
            return None
 
1420
 
 
1421
    # Properties
 
1422
    granularity = property(fget=get_granularity, fset=set_granularity)
 
1423
    map_time = property(fget=get_map_time, fset=set_map_time)
 
1424
 
 
1425
    def print_info(self):
 
1426
        """Print information about this class in human readable style"""
 
1427
        RelativeTemporalExtent.print_info(self)
 
1428
        #      0123456789012345678901234567890
 
1429
        print " | Granularity:................ " + str(self.get_granularity())
 
1430
        print " | Temporal type of maps:...... " + str(self.get_map_time())
 
1431
 
 
1432
    def print_shell_info(self):
 
1433
        """Print information about this class in shell style"""
 
1434
        RelativeTemporalExtent.print_shell_info(self)
 
1435
        print "granularity=" + str(self.get_granularity())
 
1436
        print "map_time=" + str(self.get_map_time())
 
1437
 
 
1438
###############################################################################
 
1439
 
 
1440
 
 
1441
class STRDSRelativeTime(STDSRelativeTime):
 
1442
    def __init__(self, ident=None, start_time=None, end_time=None,
 
1443
                 unit=None, granularity=None, map_time=None):
 
1444
        STDSRelativeTime.__init__(self, "strds_relative_time", ident,
 
1445
                                  start_time, end_time, unit, granularity,
 
1446
                                  map_time)
 
1447
 
 
1448
 
 
1449
class STR3DSRelativeTime(STDSRelativeTime):
 
1450
    def __init__(self, ident=None, start_time=None, end_time=None,
 
1451
                 unit=None, granularity=None, map_time=None):
 
1452
        STDSRelativeTime.__init__(self, "str3ds_relative_time", ident,
 
1453
                                  start_time, end_time, unit, granularity,
 
1454
                                  map_time)
 
1455
 
 
1456
 
 
1457
class STVDSRelativeTime(STDSRelativeTime):
 
1458
    def __init__(self, ident=None, start_time=None, end_time=None,
 
1459
                 unit=None, granularity=None, map_time=None):
 
1460
        STDSRelativeTime.__init__(self, "stvds_relative_time", ident,
 
1461
                                  start_time, end_time, unit, granularity,
 
1462
                                  map_time)
 
1463
 
 
1464
###############################################################################
 
1465
 
 
1466
if __name__ == "__main__":
 
1467
    import doctest
 
1468
    doctest.testmod()