12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100 |
- """
- Class to build the spatio-temporal topology between map lists
- Usage:
- .. code-block:: python
- import grass.temporal as tgis
- tgis.print_temporal_relations(maps)
- (C) 2012-2013 by the GRASS Development Team
- This program is free software under the GNU General Public
- License (>=v2). Read the file COPYING that comes with GRASS
- for details.
- :authors: Soeren Gebbert
- """
- from __future__ import print_function
- # i18N
- import gettext
- from datetime import datetime
- from .core import init_dbif
- from .abstract_dataset import AbstractDatasetComparisonKeyStartTime
- from .datetime_math import time_delta_to_relative_time_seconds
- import grass.lib.vector as vector
- import grass.lib.rtree as rtree
- import grass.lib.gis as gis
- ###############################################################################
- class SpatioTemporalTopologyBuilder(object):
- """This class is designed to build the spatio-temporal topology
- of spatio-temporally related abstract dataset objects.
- The abstract dataset objects must be provided as a single list, or in
- two lists.
- Example:
- .. code-block:: python
- # We have a space time raster dataset and build a map list
- # from all registered maps ordered by start time
- maps = strds.get_registered_maps_as_objects()
- # Now lets build the temporal topology of the maps in the list
- tb = SpatioTemporalTopologyBuilder()
- tb.build(maps)
- dbif, connected = init_dbif(None)
- for map in tb:
- map.select(dbif)
- map.print_info()
- # Same can be done with the existing map list
- # But be aware that this is might not be temporally ordered
- for map in maps:
- map.select(dbf)
- map.print_info()
- # Using the next and previous methods, we can iterate over the
- # topological related maps in this way
- first = tb.get_first()
- while first:
- first.print_topology_info()
- first = first.next()
- # Dictionary like accessed
- map = tb["name@mapset"]
- >>> # Example with two lists of maps
- >>> import grass.temporal as tgis
- >>> import datetime
- >>> # Create two list of maps with equal time stamps
- >>> mapsA = []
- >>> mapsB = []
- >>> for i in range(4):
- ... idA = "a%i@B"%(i)
- ... mapA = tgis.RasterDataset(idA)
- ... idB = "b%i@B"%(i)
- ... mapB = tgis.RasterDataset(idB)
- ... check = mapA.set_relative_time(i, i + 1, "months")
- ... check = mapB.set_relative_time(i, i + 1, "months")
- ... mapsA.append(mapA)
- ... mapsB.append(mapB)
- >>> # Build the topology between the two map lists
- >>> tb = SpatioTemporalTopologyBuilder()
- >>> tb.build(mapsA, mapsB, None)
- >>> # Check relations of mapsA
- >>> for map in mapsA:
- ... if map.get_equal():
- ... relations = map.get_equal()
- ... print("Map %s has equal relation to map %s"%(map.get_name(),
- ... relations[0].get_name()))
- Map a0 has equal relation to map b0
- Map a1 has equal relation to map b1
- Map a2 has equal relation to map b2
- Map a3 has equal relation to map b3
- >>> # Check relations of mapsB
- >>> for map in mapsB:
- ... if map.get_equal():
- ... relations = map.get_equal()
- ... print("Map %s has equal relation to map %s"%(map.get_name(),
- ... relations[0].get_name()))
- Map b0 has equal relation to map a0
- Map b1 has equal relation to map a1
- Map b2 has equal relation to map a2
- Map b3 has equal relation to map a3
- >>> mapsA = []
- >>> mapsB = []
- >>> for i in range(4):
- ... idA = "a%i@B"%(i)
- ... mapA = tgis.RasterDataset(idA)
- ... idB = "b%i@B"%(i)
- ... mapB = tgis.RasterDataset(idB)
- ... check = mapA.set_relative_time(i, i + 1, "months")
- ... check = mapB.set_relative_time(i + 1, i + 2, "months")
- ... mapsA.append(mapA)
- ... mapsB.append(mapB)
- >>> # Build the topology between the two map lists
- >>> tb = SpatioTemporalTopologyBuilder()
- >>> tb.build(mapsA, mapsB, None)
- >>> # Check relations of mapsA
- >>> for map in mapsA:
- ... print(map.get_temporal_extent_as_tuple())
- ... m = map.get_temporal_relations()
- ... for key in m.keys():
- ... if key not in ["NEXT", "PREV"]:
- ... print((key, m[key][0].get_temporal_extent_as_tuple()))
- (0, 1)
- ('PRECEDES', (1, 2))
- (1, 2)
- ('PRECEDES', (2, 3))
- ('EQUAL', (1, 2))
- (2, 3)
- ('FOLLOWS', (1, 2))
- ('PRECEDES', (3, 4))
- ('EQUAL', (2, 3))
- (3, 4)
- ('FOLLOWS', (2, 3))
- ('EQUAL', (3, 4))
- ('PRECEDES', (4, 5))
- >>> mapsA = []
- >>> mapsB = []
- >>> for i in range(4):
- ... idA = "a%i@B"%(i)
- ... mapA = tgis.RasterDataset(idA)
- ... idB = "b%i@B"%(i)
- ... mapB = tgis.RasterDataset(idB)
- ... start = datetime.datetime(2000 + i, 1, 1)
- ... end = datetime.datetime(2000 + i + 1, 1, 1)
- ... check = mapA.set_absolute_time(start, end)
- ... start = datetime.datetime(2000 + i + 1, 1, 1)
- ... end = datetime.datetime(2000 + i + 2, 1, 1)
- ... check = mapB.set_absolute_time(start, end)
- ... mapsA.append(mapA)
- ... mapsB.append(mapB)
- >>> # Build the topology between the two map lists
- >>> tb = SpatioTemporalTopologyBuilder()
- >>> tb.build(mapsA, mapsB, None)
- >>> # Check relations of mapsA
- >>> for map in mapsA:
- ... print(map.get_temporal_extent_as_tuple())
- ... m = map.get_temporal_relations()
- ... for key in m.keys():
- ... if key not in ["NEXT", "PREV"]:
- ... print((key, m[key][0].get_temporal_extent_as_tuple()))
- (datetime.datetime(2000, 1, 1, 0, 0), datetime.datetime(2001, 1, 1, 0, 0))
- ('PRECEDES', (datetime.datetime(2001, 1, 1, 0, 0), datetime.datetime(2002, 1, 1, 0, 0)))
- (datetime.datetime(2001, 1, 1, 0, 0), datetime.datetime(2002, 1, 1, 0, 0))
- ('PRECEDES', (datetime.datetime(2002, 1, 1, 0, 0), datetime.datetime(2003, 1, 1, 0, 0)))
- ('EQUAL', (datetime.datetime(2001, 1, 1, 0, 0), datetime.datetime(2002, 1, 1, 0, 0)))
- (datetime.datetime(2002, 1, 1, 0, 0), datetime.datetime(2003, 1, 1, 0, 0))
- ('FOLLOWS', (datetime.datetime(2001, 1, 1, 0, 0), datetime.datetime(2002, 1, 1, 0, 0)))
- ('PRECEDES', (datetime.datetime(2003, 1, 1, 0, 0), datetime.datetime(2004, 1, 1, 0, 0)))
- ('EQUAL', (datetime.datetime(2002, 1, 1, 0, 0), datetime.datetime(2003, 1, 1, 0, 0)))
- (datetime.datetime(2003, 1, 1, 0, 0), datetime.datetime(2004, 1, 1, 0, 0))
- ('FOLLOWS', (datetime.datetime(2002, 1, 1, 0, 0), datetime.datetime(2003, 1, 1, 0, 0)))
- ('EQUAL', (datetime.datetime(2003, 1, 1, 0, 0), datetime.datetime(2004, 1, 1, 0, 0)))
- ('PRECEDES', (datetime.datetime(2004, 1, 1, 0, 0), datetime.datetime(2005, 1, 1, 0, 0)))
- >>> mapsA = []
- >>> mapsB = []
- >>> for i in range(4):
- ... idA = "a%i@B"%(i)
- ... mapA = tgis.RasterDataset(idA)
- ... idB = "b%i@B"%(i)
- ... mapB = tgis.RasterDataset(idB)
- ... start = datetime.datetime(2000 + i, 1, 1)
- ... end = datetime.datetime(2000 + i + 1, 1, 1)
- ... check = mapA.set_absolute_time(start, end)
- ... start = datetime.datetime(2000 + i, 1, 1)
- ... end = datetime.datetime(2000 + i + 3, 1, 1)
- ... check = mapB.set_absolute_time(start, end)
- ... mapsA.append(mapA)
- ... mapsB.append(mapB)
- >>> # Build the topology between the two map lists
- >>> tb = SpatioTemporalTopologyBuilder()
- >>> tb.build(mapsA, mapsB, None)
- >>> # Check relations of mapsA
- >>> for map in mapsA:
- ... print(map.get_temporal_extent_as_tuple())
- ... m = map.get_temporal_relations()
- ... for key in m.keys():
- ... if key not in ["NEXT", "PREV"]:
- ... print((key, m[key][0].get_temporal_extent_as_tuple()))
- (datetime.datetime(2000, 1, 1, 0, 0), datetime.datetime(2001, 1, 1, 0, 0))
- ('DURING', (datetime.datetime(2000, 1, 1, 0, 0), datetime.datetime(2003, 1, 1, 0, 0)))
- ('STARTS', (datetime.datetime(2000, 1, 1, 0, 0), datetime.datetime(2003, 1, 1, 0, 0)))
- ('PRECEDES', (datetime.datetime(2001, 1, 1, 0, 0), datetime.datetime(2004, 1, 1, 0, 0)))
- (datetime.datetime(2001, 1, 1, 0, 0), datetime.datetime(2002, 1, 1, 0, 0))
- ('DURING', (datetime.datetime(2000, 1, 1, 0, 0), datetime.datetime(2003, 1, 1, 0, 0)))
- ('STARTS', (datetime.datetime(2001, 1, 1, 0, 0), datetime.datetime(2004, 1, 1, 0, 0)))
- ('PRECEDES', (datetime.datetime(2002, 1, 1, 0, 0), datetime.datetime(2005, 1, 1, 0, 0)))
- (datetime.datetime(2002, 1, 1, 0, 0), datetime.datetime(2003, 1, 1, 0, 0))
- ('PRECEDES', (datetime.datetime(2003, 1, 1, 0, 0), datetime.datetime(2006, 1, 1, 0, 0)))
- ('FINISHES', (datetime.datetime(2000, 1, 1, 0, 0), datetime.datetime(2003, 1, 1, 0, 0)))
- ('DURING', (datetime.datetime(2000, 1, 1, 0, 0), datetime.datetime(2003, 1, 1, 0, 0)))
- ('STARTS', (datetime.datetime(2002, 1, 1, 0, 0), datetime.datetime(2005, 1, 1, 0, 0)))
- (datetime.datetime(2003, 1, 1, 0, 0), datetime.datetime(2004, 1, 1, 0, 0))
- ('FOLLOWS', (datetime.datetime(2000, 1, 1, 0, 0), datetime.datetime(2003, 1, 1, 0, 0)))
- ('DURING', (datetime.datetime(2001, 1, 1, 0, 0), datetime.datetime(2004, 1, 1, 0, 0)))
- ('FINISHES', (datetime.datetime(2001, 1, 1, 0, 0), datetime.datetime(2004, 1, 1, 0, 0)))
- ('STARTS', (datetime.datetime(2003, 1, 1, 0, 0), datetime.datetime(2006, 1, 1, 0, 0)))
- >>> mapsA = []
- >>> mapsB = []
- >>> for i in range(4):
- ... idA = "a%i@B"%(i)
- ... mapA = tgis.RasterDataset(idA)
- ... idB = "b%i@B"%(i)
- ... mapB = tgis.RasterDataset(idB)
- ... start = datetime.datetime(2000 + i, 1, 1)
- ... end = datetime.datetime(2000 + i + 2, 1, 1)
- ... check = mapA.set_absolute_time(start, end)
- ... start = datetime.datetime(2000 + i, 1, 1)
- ... end = datetime.datetime(2000 + i + 3, 1, 1)
- ... check = mapB.set_absolute_time(start, end)
- ... mapsA.append(mapA)
- ... mapsB.append(mapB)
- >>> # Build the topology between the two map lists
- >>> tb = SpatioTemporalTopologyBuilder()
- >>> tb.build(mapsA, mapsB, None)
- >>> # Check relations of mapsA
- >>> for map in mapsA:
- ... print(map.get_temporal_extent_as_tuple())
- ... m = map.get_temporal_relations()
- ... for key in m.keys():
- ... if key not in ["NEXT", "PREV"]:
- ... print((key, m[key][0].get_temporal_extent_as_tuple()))
- (datetime.datetime(2000, 1, 1, 0, 0), datetime.datetime(2002, 1, 1, 0, 0))
- ('OVERLAPS', (datetime.datetime(2001, 1, 1, 0, 0), datetime.datetime(2004, 1, 1, 0, 0)))
- ('DURING', (datetime.datetime(2000, 1, 1, 0, 0), datetime.datetime(2003, 1, 1, 0, 0)))
- ('STARTS', (datetime.datetime(2000, 1, 1, 0, 0), datetime.datetime(2003, 1, 1, 0, 0)))
- ('PRECEDES', (datetime.datetime(2002, 1, 1, 0, 0), datetime.datetime(2005, 1, 1, 0, 0)))
- (datetime.datetime(2001, 1, 1, 0, 0), datetime.datetime(2003, 1, 1, 0, 0))
- ('OVERLAPS', (datetime.datetime(2002, 1, 1, 0, 0), datetime.datetime(2005, 1, 1, 0, 0)))
- ('PRECEDES', (datetime.datetime(2003, 1, 1, 0, 0), datetime.datetime(2006, 1, 1, 0, 0)))
- ('FINISHES', (datetime.datetime(2000, 1, 1, 0, 0), datetime.datetime(2003, 1, 1, 0, 0)))
- ('DURING', (datetime.datetime(2000, 1, 1, 0, 0), datetime.datetime(2003, 1, 1, 0, 0)))
- ('STARTS', (datetime.datetime(2001, 1, 1, 0, 0), datetime.datetime(2004, 1, 1, 0, 0)))
- (datetime.datetime(2002, 1, 1, 0, 0), datetime.datetime(2004, 1, 1, 0, 0))
- ('OVERLAPS', (datetime.datetime(2003, 1, 1, 0, 0), datetime.datetime(2006, 1, 1, 0, 0)))
- ('OVERLAPPED', (datetime.datetime(2000, 1, 1, 0, 0), datetime.datetime(2003, 1, 1, 0, 0)))
- ('FINISHES', (datetime.datetime(2001, 1, 1, 0, 0), datetime.datetime(2004, 1, 1, 0, 0)))
- ('DURING', (datetime.datetime(2001, 1, 1, 0, 0), datetime.datetime(2004, 1, 1, 0, 0)))
- ('STARTS', (datetime.datetime(2002, 1, 1, 0, 0), datetime.datetime(2005, 1, 1, 0, 0)))
- (datetime.datetime(2003, 1, 1, 0, 0), datetime.datetime(2005, 1, 1, 0, 0))
- ('OVERLAPPED', (datetime.datetime(2001, 1, 1, 0, 0), datetime.datetime(2004, 1, 1, 0, 0)))
- ('DURING', (datetime.datetime(2002, 1, 1, 0, 0), datetime.datetime(2005, 1, 1, 0, 0)))
- ('FINISHES', (datetime.datetime(2002, 1, 1, 0, 0), datetime.datetime(2005, 1, 1, 0, 0)))
- ('STARTS', (datetime.datetime(2003, 1, 1, 0, 0), datetime.datetime(2006, 1, 1, 0, 0)))
- ('FOLLOWS', (datetime.datetime(2000, 1, 1, 0, 0), datetime.datetime(2003, 1, 1, 0, 0)))
- >>> mapsA = []
- >>> mapsB = []
- >>> for i in range(4):
- ... idA = "a%i@B"%(i)
- ... mapA = tgis.RasterDataset(idA)
- ... idB = "b%i@B"%(i)
- ... mapB = tgis.RasterDataset(idB)
- ... start = datetime.datetime(2000, 1, 1, 0, 0, i)
- ... end = datetime.datetime(2000, 1, 1, 0, 0, i + 2)
- ... check = mapA.set_absolute_time(start, end)
- ... start = datetime.datetime(2000, 1, 1, 0, 0, i + 1)
- ... end = datetime.datetime(2000, 1, 1, 0, 0, i + 3)
- ... check = mapB.set_absolute_time(start, end)
- ... mapsA.append(mapA)
- ... mapsB.append(mapB)
- >>> # Build the topology between the two map lists
- >>> tb = SpatioTemporalTopologyBuilder()
- >>> tb.build(mapsA, mapsB, None)
- >>> # Check relations of mapsA
- >>> for map in mapsA:
- ... print(map.get_temporal_extent_as_tuple())
- ... m = map.get_temporal_relations()
- ... for key in m.keys():
- ... if key not in ["NEXT", "PREV"]:
- ... print((key, m[key][0].get_temporal_extent_as_tuple()))
- (datetime.datetime(2000, 1, 1, 0, 0), datetime.datetime(2000, 1, 1, 0, 0, 2))
- ('OVERLAPS', (datetime.datetime(2000, 1, 1, 0, 0, 1), datetime.datetime(2000, 1, 1, 0, 0, 3)))
- ('PRECEDES', (datetime.datetime(2000, 1, 1, 0, 0, 2), datetime.datetime(2000, 1, 1, 0, 0, 4)))
- (datetime.datetime(2000, 1, 1, 0, 0, 1), datetime.datetime(2000, 1, 1, 0, 0, 3))
- ('OVERLAPS', (datetime.datetime(2000, 1, 1, 0, 0, 2), datetime.datetime(2000, 1, 1, 0, 0, 4)))
- ('PRECEDES', (datetime.datetime(2000, 1, 1, 0, 0, 3), datetime.datetime(2000, 1, 1, 0, 0, 5)))
- ('EQUAL', (datetime.datetime(2000, 1, 1, 0, 0, 1), datetime.datetime(2000, 1, 1, 0, 0, 3)))
- (datetime.datetime(2000, 1, 1, 0, 0, 2), datetime.datetime(2000, 1, 1, 0, 0, 4))
- ('OVERLAPS', (datetime.datetime(2000, 1, 1, 0, 0, 3), datetime.datetime(2000, 1, 1, 0, 0, 5)))
- ('OVERLAPPED', (datetime.datetime(2000, 1, 1, 0, 0, 1), datetime.datetime(2000, 1, 1, 0, 0, 3)))
- ('PRECEDES', (datetime.datetime(2000, 1, 1, 0, 0, 4), datetime.datetime(2000, 1, 1, 0, 0, 6)))
- ('EQUAL', (datetime.datetime(2000, 1, 1, 0, 0, 2), datetime.datetime(2000, 1, 1, 0, 0, 4)))
- (datetime.datetime(2000, 1, 1, 0, 0, 3), datetime.datetime(2000, 1, 1, 0, 0, 5))
- ('OVERLAPS', (datetime.datetime(2000, 1, 1, 0, 0, 4), datetime.datetime(2000, 1, 1, 0, 0, 6)))
- ('FOLLOWS', (datetime.datetime(2000, 1, 1, 0, 0, 1), datetime.datetime(2000, 1, 1, 0, 0, 3)))
- ('OVERLAPPED', (datetime.datetime(2000, 1, 1, 0, 0, 2), datetime.datetime(2000, 1, 1, 0, 0, 4)))
- ('EQUAL', (datetime.datetime(2000, 1, 1, 0, 0, 3), datetime.datetime(2000, 1, 1, 0, 0, 5)))
- >>> mapsA = []
- >>> for i in range(4):
- ... idA = "a%i@B"%(i)
- ... mapA = tgis.RasterDataset(idA)
- ... start = datetime.datetime(2000, 1, 1, 0, 0, i)
- ... end = datetime.datetime(2000, 1, 1, 0, 0, i + 2)
- ... check = mapA.set_absolute_time(start, end)
- ... mapsA.append(mapA)
- >>> tb = SpatioTemporalTopologyBuilder()
- >>> tb.build(mapsA)
- >>> # Check relations of mapsA
- >>> for map in mapsA:
- ... print(map.get_temporal_extent_as_tuple())
- ... m = map.get_temporal_relations()
- ... for key in m.keys():
- ... if key not in ["NEXT", "PREV"]:
- ... print((key, m[key][0].get_temporal_extent_as_tuple()))
- (datetime.datetime(2000, 1, 1, 0, 0), datetime.datetime(2000, 1, 1, 0, 0, 2))
- ('OVERLAPS', (datetime.datetime(2000, 1, 1, 0, 0, 1), datetime.datetime(2000, 1, 1, 0, 0, 3)))
- ('PRECEDES', (datetime.datetime(2000, 1, 1, 0, 0, 2), datetime.datetime(2000, 1, 1, 0, 0, 4)))
- (datetime.datetime(2000, 1, 1, 0, 0, 1), datetime.datetime(2000, 1, 1, 0, 0, 3))
- ('OVERLAPS', (datetime.datetime(2000, 1, 1, 0, 0, 2), datetime.datetime(2000, 1, 1, 0, 0, 4)))
- ('OVERLAPPED', (datetime.datetime(2000, 1, 1, 0, 0), datetime.datetime(2000, 1, 1, 0, 0, 2)))
- ('PRECEDES', (datetime.datetime(2000, 1, 1, 0, 0, 3), datetime.datetime(2000, 1, 1, 0, 0, 5)))
- (datetime.datetime(2000, 1, 1, 0, 0, 2), datetime.datetime(2000, 1, 1, 0, 0, 4))
- ('OVERLAPS', (datetime.datetime(2000, 1, 1, 0, 0, 3), datetime.datetime(2000, 1, 1, 0, 0, 5)))
- ('FOLLOWS', (datetime.datetime(2000, 1, 1, 0, 0), datetime.datetime(2000, 1, 1, 0, 0, 2)))
- ('OVERLAPPED', (datetime.datetime(2000, 1, 1, 0, 0, 1), datetime.datetime(2000, 1, 1, 0, 0, 3)))
- (datetime.datetime(2000, 1, 1, 0, 0, 3), datetime.datetime(2000, 1, 1, 0, 0, 5))
- ('FOLLOWS', (datetime.datetime(2000, 1, 1, 0, 0, 1), datetime.datetime(2000, 1, 1, 0, 0, 3)))
- ('OVERLAPPED', (datetime.datetime(2000, 1, 1, 0, 0, 2), datetime.datetime(2000, 1, 1, 0, 0, 4)))
- """
- def __init__(self):
- self._reset()
- # 0001-01-01 00:00:00
- self._timeref = datetime(1, 1, 1)
- def _reset(self):
- self._store = {}
- self._first = None
- self._iteratable = False
- def _set_first(self, first):
- self._first = first
- self._insert(first)
- def _detect_first(self):
- if len(self) > 0:
- prev_ = self._store.values()[0]
- while prev_ is not None:
- self._first = prev_
- prev_ = prev_.prev()
- def _insert(self, t):
- self._store[t.get_id()] = t
- def get_first(self):
- """Return the first map with the earliest start time
- :return: The map with the earliest start time
- """
- return self._first
- def _build_internal_iteratable(self, maps, spatial):
- """Build an iteratable temporal topology structure for all maps in
- the list and store the maps internally
- Basically the "next" and "prev" relations will be set in the
- temporal topology structure of each map
- The maps will be added to the object, so they can be
- accessed using the iterator of this class
- :param maps: A sorted (by start_time)list of abstract_dataset
- objects with initiated temporal extent
- """
- self._build_iteratable(maps, spatial)
- for _map in maps:
- self._insert(_map)
- # Detect the first map
- self._detect_first()
- def _build_iteratable(self, maps, spatial):
- """Build an iteratable temporal topology structure for
- all maps in the list
- Basically the "next" and "prev" relations will be set in
- the temporal topology structure of each map.
- :param maps: A sorted (by start_time)list of abstract_dataset
- objects with initiated temporal extent
- """
- # for i in xrange(len(maps)):
- # offset = i + 1
- # for j in xrange(offset, len(maps)):
- # # Get the temporal relationship
- # relation = maps[j].temporal_relation(maps[i])
- #
- # # Build the next reference
- # if relation != "equal" and relation != "started":
- # maps[i].set_next(maps[j])
- # break
- # First we need to order the map list chronologically
- sorted_maps = sorted(
- maps, key=AbstractDatasetComparisonKeyStartTime)
- for i in range(len(sorted_maps) - 1):
- sorted_maps[i].set_next(sorted_maps[i + 1])
- for map_ in sorted_maps:
- next_ = map_.next()
- if next_:
- next_.set_prev(map_)
- map_.set_temporal_topology_build_true()
- if spatial is not None:
- map_.set_spatial_topology_build_true()
- def _map_to_rect(self, tree, map_, spatial=None):
- """Use the spatio-temporal extent of a map to create and
- return a RTree rectangle
- :param spatial: This indicates if the spatial topology is created
- as well: spatial can be None (no spatial topology),
- "2D" using west, east, south, north or "3D" using
- west, east, south, north, bottom, top
- """
- rect = rtree.RTreeAllocRect(tree)
- start, end = map_.get_temporal_extent_as_tuple()
- if not end:
- end = start
- if map_.is_time_absolute():
- start = time_delta_to_relative_time_seconds(start - self._timeref)
- end = time_delta_to_relative_time_seconds(end - self._timeref)
- if spatial is None:
- rtree.RTreeSetRect1D(rect, tree, float(start), float(end))
- elif spatial == "2D":
- north, south, east, west, top, bottom = map_.get_spatial_extent_as_tuple()
- rtree.RTreeSetRect3D(rect, tree, west, east, south, north,
- float(start), float(end))
- elif spatial == "3D":
- north, south, east, west, top, bottom = map_.get_spatial_extent_as_tuple()
- rtree.RTreeSetRect4D(rect, tree, west, east, south, north,
- bottom, top, float(start), float(end))
- return rect
- def _build_rtree(self, maps, spatial=None):
- """Build and return the 1-4 dimensional R*-Tree
- :param spatial: This indicates if the spatial topology is created
- as well: spatial can be None (no spatial topology),
- "2D" using west, east, south, north or "3D" using
- west, east, south, north, bottom, top
- """
- dim = 1
- if spatial == "2D":
- dim = 3
- if spatial == "3D":
- dim = 4
- tree = rtree.RTreeCreateTree(-1, 0, dim)
- for i in range(len(maps)):
- rect = self._map_to_rect(tree, maps[i], spatial)
- rtree.RTreeInsertRect(rect, i + 1, tree)
- return tree
- def build(self, mapsA, mapsB=None, spatial=None):
- """Build the spatio-temporal topology structure between
- one or two unordered lists of abstract dataset objects
- This method builds the temporal or spatio-temporal topology from
- mapsA to mapsB and vice verse. The spatio-temporal topology
- structure of each map will be reset and rebuild for mapsA and
- mapsB.
- After building the temporal or spatio-temporal topology the modified
- map objects of mapsA can be accessed
- in the same way as a dictionary using there id.
- The implemented iterator assures
- the chronological iteration over the mapsA.
- :param mapsA: A list of abstract_dataset
- objects with initiated spatio-temporal extent
- :param mapsB: An optional list of abstract_dataset
- objects with initiated spatio-temporal extent
- :param spatial: This indicates if the spatial topology is created
- as well: spatial can be None (no spatial topology),
- "2D" using west, east, south, north or "3D" using
- west, east, south, north, bottom, top
- """
- identical = False
- if mapsA == mapsB:
- identical = True
- if mapsB is None:
- mapsB = mapsA
- identical = True
- for map_ in mapsA:
- map_.reset_topology()
- if not identical:
- for map_ in mapsB:
- map_.reset_topology()
- tree = self. _build_rtree(mapsA, spatial)
- list_ = gis.G_new_ilist()
- for j in range(len(mapsB)):
- rect = self._map_to_rect(tree, mapsB[j], spatial)
- vector.RTreeSearch2(tree, rect, list_)
- rtree.RTreeFreeRect(rect)
- for k in range(list_.contents.n_values):
- i = list_.contents.value[k] - 1
- # Get the temporal relationship
- relation = mapsB[j].temporal_relation(mapsA[i])
- A = mapsA[i]
- B = mapsB[j]
- set_temoral_relationship(A, B, relation)
- if spatial is not None:
- relation = mapsB[j].spatial_relation(mapsA[i])
- set_spatial_relationship(A, B, relation)
- self._build_internal_iteratable(mapsA, spatial)
- if not identical and mapsB is not None:
- self._build_iteratable(mapsB, spatial)
- gis.G_free_ilist(list_)
- rtree.RTreeDestroyTree(tree)
- def __iter__(self):
- start_ = self._first
- while start_ is not None:
- yield start_
- start_ = start_.next()
- def __getitem__(self, index):
- return self._store[index.get_id()]
- def __len__(self):
- return len(self._store)
- def __contains__(self, _map):
- return _map in self._store.values()
- ###############################################################################
- def set_temoral_relationship(A, B, relation):
- if relation == "equal" or relation == "equals":
- if A != B:
- if not B.get_equal() or \
- (B.get_equal() and \
- A not in B.get_equal()):
- B.append_equal(A)
- if not A.get_equal() or \
- (A.get_equal() and \
- B not in A.get_equal()):
- A.append_equal(B)
- elif relation == "follows":
- if not B.get_follows() or \
- (B.get_follows() and \
- A not in B.get_follows()):
- B.append_follows(A)
- if not A.get_precedes() or \
- (A.get_precedes() and
- B not in A.get_precedes()):
- A.append_precedes(B)
- elif relation == "precedes":
- if not B.get_precedes() or \
- (B.get_precedes() and \
- A not in B.get_precedes()):
- B.append_precedes(A)
- if not A.get_follows() or \
- (A.get_follows() and \
- B not in A.get_follows()):
- A.append_follows(B)
- elif relation == "during" or relation == "starts" or \
- relation == "finishes":
- if not B.get_during() or \
- (B.get_during() and \
- A not in B.get_during()):
- B.append_during(A)
- if not A.get_contains() or \
- (A.get_contains() and \
- B not in A.get_contains()):
- A.append_contains(B)
- if relation == "starts":
- if not B.get_starts() or \
- (B.get_starts() and \
- A not in B.get_starts()):
- B.append_starts(A)
- if not A.get_started() or \
- (A.get_started() and \
- B not in A.get_started()):
- A.append_started(B)
- if relation == "finishes":
- if not B.get_finishes() or \
- (B.get_finishes() and \
- A not in B.get_finishes()):
- B.append_finishes(A)
- if not A.get_finished() or \
- (A.get_finished() and \
- B not in A.get_finished()):
- A.append_finished(B)
- elif relation == "contains" or relation == "started" or \
- relation == "finished":
- if not B.get_contains() or \
- (B.get_contains() and \
- A not in B.get_contains()):
- B.append_contains(A)
- if not A.get_during() or \
- (A.get_during() and \
- B not in A.get_during()):
- A.append_during(B)
- if relation == "started":
- if not B.get_started() or \
- (B.get_started() and \
- A not in B.get_started()):
- B.append_started(A)
- if not A.get_starts() or \
- (A.get_starts() and \
- B not in A.get_starts()):
- A.append_starts(B)
- if relation == "finished":
- if not B.get_finished() or \
- (B.get_finished() and \
- A not in B.get_finished()):
- B.append_finished(A)
- if not A.get_finishes() or \
- (A.get_finishes() and \
- B not in A.get_finishes()):
- A.append_finishes(B)
- elif relation == "overlaps":
- if not B.get_overlaps() or \
- (B.get_overlaps() and \
- A not in B.get_overlaps()):
- B.append_overlaps(A)
- if not A.get_overlapped() or \
- (A.get_overlapped() and \
- B not in A.get_overlapped()):
- A.append_overlapped(B)
- elif relation == "overlapped":
- if not B.get_overlapped() or \
- (B.get_overlapped() and \
- A not in B.get_overlapped()):
- B.append_overlapped(A)
- if not A.get_overlaps() or \
- (A.get_overlaps() and \
- B not in A.get_overlaps()):
- A.append_overlaps(B)
- ###############################################################################
- def set_spatial_relationship(A, B, relation):
- if relation == "equivalent":
- if A != B:
- if not B.get_equivalent() or \
- (B.get_equivalent() and \
- A not in B.get_equivalent()):
- B.append_equivalent(A)
- if not A.get_equivalent() or \
- (A.get_equivalent() and \
- B not in A.get_equivalent()):
- A.append_equivalent(B)
- elif relation == "overlap":
- if not B.get_overlap() or \
- (B.get_overlap() and \
- A not in B.get_overlap()):
- B.append_overlap(A)
- if not A.get_overlap() or \
- (A.get_overlap() and
- B not in A.get_overlap()):
- A.append_overlap(B)
- elif relation == "meet":
- if not B.get_meet() or \
- (B.get_meet() and \
- A not in B.get_meet()):
- B.append_meet(A)
- if not A.get_meet() or \
- (A.get_meet() and
- B not in A.get_meet()):
- A.append_meet(B)
- elif relation == "contain":
- if not B.get_contain() or \
- (B.get_contain() and \
- A not in B.get_contain()):
- B.append_contain(A)
- if not A.get_in() or \
- (A.get_in() and \
- B not in A.get_in()):
- A.append_in(B)
- elif relation == "in":
- if not B.get_in() or \
- (B.get_in() and \
- A not in B.get_in()):
- B.append_in(A)
- if not A.get_contain() or \
- (A.get_contain() and \
- B not in A.get_contain()):
- A.append_contain(B)
- elif relation == "cover":
- if not B.get_cover() or \
- (B.get_cover() and \
- A not in B.get_cover()):
- B.append_cover(A)
- if not A.get_covered() or \
- (A.get_covered() and \
- B not in A.get_covered()):
- A.append_covered(B)
- elif relation == "covered":
- if not B.get_covered() or \
- (B.get_covered() and \
- A not in B.get_covered()):
- B.append_covered(A)
- if not A.get_cover() or \
- (A.get_cover() and \
- B not in A.get_cover()):
- A.append_cover(B)
- ###############################################################################
- def print_temporal_topology_relationships(maps1, maps2=None, dbif=None):
- """Print the temporal relationships of the
- map lists maps1 and maps2 to stdout.
- :param maps1: A list of abstract_dataset
- objects with initiated temporal extent
- :param maps2: An optional list of abstract_dataset
- objects with initiated temporal extent
- :param dbif: The database interface to be used
- """
- tb = SpatioTemporalTopologyBuilder()
- tb.build(maps1, maps2)
- dbif, connected = init_dbif(dbif)
- for _map in tb:
- _map.select(dbif)
- _map.print_info()
- if connected:
- dbif.close()
- return
- ###############################################################################
- def print_spatio_temporal_topology_relationships(maps1, maps2=None,
- spatial="2D", dbif=None):
- """Print the temporal relationships of the
- map lists maps1 and maps2 to stdout.
- :param maps1: A list of abstract_dataset
- objects with initiated temporal extent
- :param maps2: An optional list of abstract_dataset
- objects with initiated temporal extent
- :param spatial: The dimension of the spatial extent to be used: "2D"
- using west, east, south, north or "3D" using west,
- east, south, north, bottom, top
- :param dbif: The database interface to be used
- """
- tb = SpatioTemporalTopologyBuilder()
- tb.build(maps1, maps2, spatial)
- dbif, connected = init_dbif(dbif)
- for _map in tb:
- _map.select(dbif)
- _map.print_info()
- if connected:
- dbif.close()
- return
- ###############################################################################
- def count_temporal_topology_relationships(maps1, maps2=None, dbif=None):
- """Count the temporal relations of a single list of maps or between two
- lists of maps
- :param maps1: A list of abstract_dataset
- objects with initiated temporal extent
- :param maps2: A list of abstract_dataset
- objects with initiated temporal extent
- :param dbif: The database interface to be used
- :return: A dictionary with counted temporal relationships
- """
- tb = SpatioTemporalTopologyBuilder()
- tb.build(maps1, maps2)
- dbif, connected = init_dbif(dbif)
- relations = None
- for _map in tb:
- if relations is not None:
- r = _map.get_number_of_relations()
- for k in r.keys():
- relations[k] += r[k]
- else:
- relations = _map.get_number_of_relations()
- if connected:
- dbif.close()
- return relations
- ###############################################################################
- def create_temporal_relation_sql_where_statement(start, end, use_start=True,
- use_during=False,
- use_overlap=False,
- use_contain=False,
- use_equal=False,
- use_follows=False,
- use_precedes=False):
- """Create a SQL WHERE statement for temporal relation selection of maps in
- space time datasets
- :param start: The start time
- :param end: The end time
- :param use_start: Select maps of which the start time is located in
- the selection granule ::
- map : s
- granule: s-----------------e
- map : s--------------------e
- granule: s-----------------e
- map : s--------e
- granule: s-----------------e
- :param use_during: Select maps which are temporal during the selection
- granule ::
- map : s-----------e
- granule: s-----------------e
- :param use_overlap: Select maps which temporal overlap the selection
- granule ::
- map : s-----------e
- granule: s-----------------e
- map : s-----------e
- granule: s----------e
- :param use_contain: Select maps which temporally contain the selection
- granule ::
- map : s-----------------e
- granule: s-----------e
- :param use_equal: Select maps which temporally equal to the selection
- granule ::
- map : s-----------e
- granule: s-----------e
- :param use_follows: Select maps which temporally follow the selection
- granule ::
- map : s-----------e
- granule: s-----------e
- :param use_precedes: Select maps which temporally precedes the
- selection granule ::
- map : s-----------e
- granule: s-----------e
- Usage:
- .. code-block:: python
- >>> # Relative time
- >>> start = 1
- >>> end = 2
- >>> create_temporal_relation_sql_where_statement(start, end,
- ... use_start=False)
- >>> create_temporal_relation_sql_where_statement(start, end)
- '((start_time >= 1 and start_time < 2) )'
- >>> create_temporal_relation_sql_where_statement(start, end,
- ... use_start=True)
- '((start_time >= 1 and start_time < 2) )'
- >>> create_temporal_relation_sql_where_statement(start, end,
- ... use_start=False, use_during=True)
- '(((start_time > 1 and end_time < 2) OR (start_time >= 1 and end_time < 2) OR (start_time > 1 and end_time <= 2)))'
- >>> create_temporal_relation_sql_where_statement(start, end,
- ... use_start=False, use_overlap=True)
- '(((start_time < 1 and end_time > 1 and end_time < 2) OR (start_time < 2 and start_time > 1 and end_time > 2)))'
- >>> create_temporal_relation_sql_where_statement(start, end,
- ... use_start=False, use_contain=True)
- '(((start_time < 1 and end_time > 2) OR (start_time <= 1 and end_time > 2) OR (start_time < 1 and end_time >= 2)))'
- >>> create_temporal_relation_sql_where_statement(start, end,
- ... use_start=False, use_equal=True)
- '((start_time = 1 and end_time = 2))'
- >>> create_temporal_relation_sql_where_statement(start, end,
- ... use_start=False, use_follows=True)
- '((start_time = 2))'
- >>> create_temporal_relation_sql_where_statement(start, end,
- ... use_start=False, use_precedes=True)
- '((end_time = 1))'
- >>> create_temporal_relation_sql_where_statement(start, end,
- ... use_start=True, use_during=True, use_overlap=True, use_contain=True,
- ... use_equal=True, use_follows=True, use_precedes=True)
- '((start_time >= 1 and start_time < 2) OR ((start_time > 1 and end_time < 2) OR (start_time >= 1 and end_time < 2) OR (start_time > 1 and end_time <= 2)) OR ((start_time < 1 and end_time > 1 and end_time < 2) OR (start_time < 2 and start_time > 1 and end_time > 2)) OR ((start_time < 1 and end_time > 2) OR (start_time <= 1 and end_time > 2) OR (start_time < 1 and end_time >= 2)) OR (start_time = 1 and end_time = 2) OR (start_time = 2) OR (end_time = 1))'
- >>> # Absolute time
- >>> start = datetime(2001, 1, 1, 12, 30)
- >>> end = datetime(2001, 3, 31, 14, 30)
- >>> create_temporal_relation_sql_where_statement(start, end,
- ... use_start=False)
- >>> create_temporal_relation_sql_where_statement(start, end)
- "((start_time >= '2001-01-01 12:30:00' and start_time < '2001-03-31 14:30:00') )"
- >>> create_temporal_relation_sql_where_statement(start, end,
- ... use_start=True)
- "((start_time >= '2001-01-01 12:30:00' and start_time < '2001-03-31 14:30:00') )"
- >>> create_temporal_relation_sql_where_statement(start, end,
- ... use_start=False, use_during=True)
- "(((start_time > '2001-01-01 12:30:00' and end_time < '2001-03-31 14:30:00') OR (start_time >= '2001-01-01 12:30:00' and end_time < '2001-03-31 14:30:00') OR (start_time > '2001-01-01 12:30:00' and end_time <= '2001-03-31 14:30:00')))"
- >>> create_temporal_relation_sql_where_statement(start, end,
- ... use_start=False, use_overlap=True)
- "(((start_time < '2001-01-01 12:30:00' and end_time > '2001-01-01 12:30:00' and end_time < '2001-03-31 14:30:00') OR (start_time < '2001-03-31 14:30:00' and start_time > '2001-01-01 12:30:00' and end_time > '2001-03-31 14:30:00')))"
- >>> create_temporal_relation_sql_where_statement(start, end,
- ... use_start=False, use_contain=True)
- "(((start_time < '2001-01-01 12:30:00' and end_time > '2001-03-31 14:30:00') OR (start_time <= '2001-01-01 12:30:00' and end_time > '2001-03-31 14:30:00') OR (start_time < '2001-01-01 12:30:00' and end_time >= '2001-03-31 14:30:00')))"
- >>> create_temporal_relation_sql_where_statement(start, end,
- ... use_start=False, use_equal=True)
- "((start_time = '2001-01-01 12:30:00' and end_time = '2001-03-31 14:30:00'))"
- >>> create_temporal_relation_sql_where_statement(start, end,
- ... use_start=False, use_follows=True)
- "((start_time = '2001-03-31 14:30:00'))"
- >>> create_temporal_relation_sql_where_statement(start, end,
- ... use_start=False, use_precedes=True)
- "((end_time = '2001-01-01 12:30:00'))"
- >>> create_temporal_relation_sql_where_statement(start, end,
- ... use_start=True, use_during=True, use_overlap=True, use_contain=True,
- ... use_equal=True, use_follows=True, use_precedes=True)
- "((start_time >= '2001-01-01 12:30:00' and start_time < '2001-03-31 14:30:00') OR ((start_time > '2001-01-01 12:30:00' and end_time < '2001-03-31 14:30:00') OR (start_time >= '2001-01-01 12:30:00' and end_time < '2001-03-31 14:30:00') OR (start_time > '2001-01-01 12:30:00' and end_time <= '2001-03-31 14:30:00')) OR ((start_time < '2001-01-01 12:30:00' and end_time > '2001-01-01 12:30:00' and end_time < '2001-03-31 14:30:00') OR (start_time < '2001-03-31 14:30:00' and start_time > '2001-01-01 12:30:00' and end_time > '2001-03-31 14:30:00')) OR ((start_time < '2001-01-01 12:30:00' and end_time > '2001-03-31 14:30:00') OR (start_time <= '2001-01-01 12:30:00' and end_time > '2001-03-31 14:30:00') OR (start_time < '2001-01-01 12:30:00' and end_time >= '2001-03-31 14:30:00')) OR (start_time = '2001-01-01 12:30:00' and end_time = '2001-03-31 14:30:00') OR (start_time = '2001-03-31 14:30:00') OR (end_time = '2001-01-01 12:30:00'))"
- """
- where = "("
- if use_start:
- if isinstance(start, datetime):
- where += "(start_time >= '%s' and start_time < '%s') " % (start,
- end)
- else:
- where += "(start_time >= %i and start_time < %i) " % (start, end)
- if use_during:
- if use_start:
- where += " OR "
- if isinstance(start, datetime):
- where += "((start_time > '%s' and end_time < '%s') OR " % (start,
- end)
- where += "(start_time >= '%s' and end_time < '%s') OR " % (start,
- end)
- where += "(start_time > '%s' and end_time <= '%s'))" % (start, end)
- else:
- where += "((start_time > %i and end_time < %i) OR " % (start, end)
- where += "(start_time >= %i and end_time < %i) OR " % (start, end)
- where += "(start_time > %i and end_time <= %i))" % (start, end)
- if use_overlap:
- if use_start or use_during:
- where += " OR "
- if isinstance(start, datetime):
- where += "((start_time < '%s' and end_time > '%s' and end_time <" \
- " '%s') OR " % (start, start, end)
- where += "(start_time < '%s' and start_time > '%s' and end_time " \
- "> '%s'))" % (end, start, end)
- else:
- where += "((start_time < %i and end_time > %i and end_time < %i)" \
- " OR " % (start, start, end)
- where += "(start_time < %i and start_time > %i and end_time > " \
- "%i))" % (end, start, end)
- if use_contain:
- if use_start or use_during or use_overlap:
- where += " OR "
- if isinstance(start, datetime):
- where += "((start_time < '%s' and end_time > '%s') OR " % (start,
- end)
- where += "(start_time <= '%s' and end_time > '%s') OR " % (start,
- end)
- where += "(start_time < '%s' and end_time >= '%s'))" % (start, end)
- else:
- where += "((start_time < %i and end_time > %i) OR " % (start, end)
- where += "(start_time <= %i and end_time > %i) OR " % (start, end)
- where += "(start_time < %i and end_time >= %i))" % (start, end)
- if use_equal:
- if use_start or use_during or use_overlap or use_contain:
- where += " OR "
- if isinstance(start, datetime):
- where += "(start_time = '%s' and end_time = '%s')" % (start, end)
- else:
- where += "(start_time = %i and end_time = %i)" % (start, end)
- if use_follows:
- if use_start or use_during or use_overlap or use_contain or use_equal:
- where += " OR "
- if isinstance(start, datetime):
- where += "(start_time = '%s')" % (end)
- else:
- where += "(start_time = %i)" % (end)
- if use_precedes:
- if use_start or use_during or use_overlap or use_contain or use_equal \
- or use_follows:
- where += " OR "
- if isinstance(start, datetime):
- where += "(end_time = '%s')" % (start)
- else:
- where += "(end_time = %i)" % (start)
- where += ")"
- # Catch empty where statement
- if where == "()":
- where = None
- return where
- ###############################################################################
- if __name__ == "__main__":
- import doctest
- doctest.testmod()
|