space_time_datasets.py 51 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367
  1. """
  2. Map layer and space time dataset classes
  3. (C) 2012-2013 by the GRASS Development Team
  4. This program is free software under the GNU General Public
  5. License (>=v2). Read the file COPYING that comes with GRASS
  6. for details.
  7. :authors: Soeren Gebbert
  8. """
  9. # i18N
  10. import gettext
  11. import getpass
  12. from datetime import datetime
  13. from .core import get_current_mapset
  14. from .abstract_map_dataset import AbstractMapDataset
  15. from .abstract_space_time_dataset import AbstractSpaceTimeDataset
  16. from .base import Raster3DBase, RasterBase, VectorBase, STR3DSBase, STVDSBase, STRDSBase,\
  17. VectorSTDSRegister, Raster3DSTDSRegister, RasterSTDSRegister
  18. from .metadata import Raster3DMetadata, RasterMetadata, VectorMetadata, STRDSMetadata,\
  19. STR3DSMetadata, STVDSMetadata
  20. from .spatial_extent import RasterSpatialExtent, Raster3DSpatialExtent, VectorSpatialExtent,\
  21. STRDSSpatialExtent, STR3DSSpatialExtent, STVDSSpatialExtent
  22. from .temporal_extent import RasterAbsoluteTime, RasterRelativeTime, Raster3DAbsoluteTime, \
  23. Raster3DRelativeTime, VectorAbsoluteTime, VectorRelativeTime, STRDSAbsoluteTime,\
  24. STRDSRelativeTime, STR3DSAbsoluteTime, STR3DSRelativeTime, STVDSAbsoluteTime, STVDSRelativeTime
  25. import grass.script.array as garray
  26. from .core import init
  27. from datetime import datetime
  28. ###############################################################################
  29. class RasterDataset(AbstractMapDataset):
  30. """Raster dataset class
  31. This class provides functions to select, update, insert or delete raster
  32. map information and valid time stamps into the SQL temporal database.
  33. Usage:
  34. .. code-block:: python
  35. >>> import grass.script as grass
  36. >>> init()
  37. >>> grass.use_temp_region()
  38. >>> grass.run_command("g.region", n=80.0, s=0.0, e=120.0, w=0.0,
  39. ... t=1.0, b=0.0, res=10.0)
  40. 0
  41. >>> grass.run_command("r.mapcalc", overwrite=True, quiet=True,
  42. ... expression="strds_map_test_case = 1")
  43. 0
  44. >>> grass.run_command("r.timestamp", map="strds_map_test_case",
  45. ... date="15 jan 1999", quiet=True)
  46. 0
  47. >>> mapset = get_current_mapset()
  48. >>> name = "strds_map_test_case"
  49. >>> identifier = "%s@%s" % (name, mapset)
  50. >>> rmap = RasterDataset(identifier)
  51. >>> rmap.map_exists()
  52. True
  53. >>> rmap.read_timestamp_from_grass()
  54. True
  55. >>> rmap.get_temporal_extent_as_tuple()
  56. (datetime.datetime(1999, 1, 15, 0, 0), None)
  57. >>> rmap.load()
  58. True
  59. >>> rmap.spatial_extent.print_info()
  60. +-------------------- Spatial extent ----------------------------------------+
  61. | North:...................... 80.0
  62. | South:...................... 0.0
  63. | East:.. .................... 120.0
  64. | West:....................... 0.0
  65. | Top:........................ 0.0
  66. | Bottom:..................... 0.0
  67. >>> rmap.absolute_time.print_info()
  68. +-------------------- Absolute time -----------------------------------------+
  69. | Start time:................. 1999-01-15 00:00:00
  70. | End time:................... None
  71. >>> rmap.metadata.print_info()
  72. +-------------------- Metadata information ----------------------------------+
  73. | Datatype:................... CELL
  74. | Number of columns:.......... 8
  75. | Number of rows:............. 12
  76. | Number of cells:............ 96
  77. | North-South resolution:..... 10.0
  78. | East-west resolution:....... 10.0
  79. | Minimum value:.............. 1.0
  80. | Maximum value:.............. 1.0
  81. >>> grass.run_command("r.timestamp", map="strds_map_test_case",
  82. ... date="2 years", quiet=True)
  83. 0
  84. >>> rmap.read_timestamp_from_grass()
  85. True
  86. >>> rmap.get_temporal_extent_as_tuple()
  87. (2, None)
  88. >>> rmap.get_relative_time_unit()
  89. 'years'
  90. >>> rmap.is_in_db()
  91. False
  92. >>> rmap.is_stds()
  93. False
  94. >>> newmap = rmap.get_new_instance("new@PERMANENT")
  95. >>> isinstance(newmap, RasterDataset)
  96. True
  97. >>> newstrds = rmap.get_new_stds_instance("new@PERMANENT")
  98. >>> isinstance(newstrds, SpaceTimeRasterDataset)
  99. True
  100. >>> rmap.get_type()
  101. 'raster'
  102. >>> rmap.set_absolute_time(start_time=datetime(2001,1,1),
  103. ... end_time=datetime(2012,1,1))
  104. True
  105. >>> rmap.get_absolute_time()
  106. (datetime.datetime(2001, 1, 1, 0, 0), datetime.datetime(2012, 1, 1, 0, 0))
  107. >>> rmap.get_temporal_extent_as_tuple()
  108. (datetime.datetime(2001, 1, 1, 0, 0), datetime.datetime(2012, 1, 1, 0, 0))
  109. >>> rmap.get_name()
  110. u'strds_map_test_case'
  111. >>> rmap.get_mapset() == mapset
  112. True
  113. >>> rmap.get_temporal_type()
  114. 'absolute'
  115. >>> rmap.get_spatial_extent_as_tuple()
  116. (80.0, 0.0, 120.0, 0.0, 0.0, 0.0)
  117. >>> rmap.is_time_absolute()
  118. True
  119. >>> rmap.is_time_relative()
  120. False
  121. >>> grass.run_command("g.remove", flags="f", type="raster", name=name, quiet=True)
  122. 0
  123. >>> grass.del_temp_region()
  124. """
  125. def __init__(self, ident):
  126. AbstractMapDataset.__init__(self)
  127. self.reset(ident)
  128. def is_stds(self):
  129. """Return True if this class is a space time dataset
  130. :return: True if this class is a space time dataset, False otherwise
  131. """
  132. return False
  133. def get_type(self):
  134. return 'raster'
  135. def get_new_instance(self, ident):
  136. """Return a new instance with the type of this class"""
  137. return RasterDataset(ident)
  138. def get_new_stds_instance(self, ident):
  139. """Return a new space time dataset instance in which maps
  140. are stored with the type of this class"""
  141. return SpaceTimeRasterDataset(ident)
  142. def spatial_overlapping(self, dataset):
  143. """Return True if the spatial extents 2d overlap"""
  144. return self.spatial_extent.overlapping_2d(dataset.spatial_extent)
  145. def spatial_relation(self, dataset):
  146. """Return the two dimensional spatial relation"""
  147. return self.spatial_extent.spatial_relation_2d(dataset.spatial_extent)
  148. def spatial_intersection(self, dataset):
  149. """Return the two dimensional intersection as spatial_extent
  150. object or None in case no intersection was found.
  151. :param dataset: The abstract dataset to intersect with
  152. :return: The intersection spatial extent or None
  153. """
  154. return self.spatial_extent.intersect_2d(dataset.spatial_extent)
  155. def spatial_union(self, dataset):
  156. """Return the two dimensional union as spatial_extent
  157. object or None in case the extents does not overlap or meet.
  158. :param dataset :The abstract dataset to create a union with
  159. :return: The union spatial extent or None
  160. """
  161. return self.spatial_extent.union_2d(dataset.spatial_extent)
  162. def spatial_disjoint_union(self, dataset):
  163. """Return the two dimensional union as spatial_extent object.
  164. :param dataset: The abstract dataset to create a union with
  165. :return: The union spatial extent
  166. """
  167. return self.spatial_extent.disjoint_union_2d(dataset.spatial_extent)
  168. def get_np_array(self):
  169. """Return this raster map as memmap numpy style array to access the raster
  170. values in numpy style without loading the whole map in the RAM.
  171. In case this raster map does exists in the grass spatial database,
  172. the map will be exported using r.out.bin to a temporary location
  173. and assigned to the memmap object that is returned by this function.
  174. In case the raster map does not exist, an empty temporary
  175. binary file will be created and assigned to the memap object.
  176. You need to call the write function to write the memmap
  177. array back into grass.
  178. """
  179. a = garray.array()
  180. if self.map_exists():
  181. a.read(self.get_map_id())
  182. return a
  183. def reset(self, ident):
  184. """Reset the internal structure and set the identifier"""
  185. self.base = RasterBase(ident=ident)
  186. self.absolute_time = RasterAbsoluteTime(ident=ident)
  187. self.relative_time = RasterRelativeTime(ident=ident)
  188. self.spatial_extent = RasterSpatialExtent(ident=ident)
  189. self.metadata = RasterMetadata(ident=ident)
  190. self.stds_register = RasterSTDSRegister(ident=ident)
  191. def has_grass_timestamp(self):
  192. """Check if a grass file based time stamp exists for this map.
  193. :return: True if success, False on error
  194. """
  195. return self.ciface.has_raster_timestamp(self.get_name(),
  196. self.get_mapset())
  197. def read_timestamp_from_grass(self):
  198. """Read the timestamp of this map from the map metadata
  199. in the grass file system based spatial database and
  200. set the internal time stamp that should be insert/updated
  201. in the temporal database.
  202. :return: True if success, False on error
  203. """
  204. if not self.has_grass_timestamp():
  205. return False
  206. check, dates = self.ciface.read_raster_timestamp(self.get_name(),
  207. self.get_mapset(),)
  208. if check < 1:
  209. self.msgr.error(_("Unable to read timestamp file "
  210. "for raster map <%s>" % (self.get_map_id())))
  211. return False
  212. if len(dates) == 2:
  213. self.set_absolute_time(dates[0], dates[1])
  214. else:
  215. self.set_relative_time(dates[0], dates[1], dates[2])
  216. return True
  217. def write_timestamp_to_grass(self):
  218. """Write the timestamp of this map into the map metadata in
  219. the grass file system based spatial database.
  220. Internally the libgis API functions are used for writing
  221. :return: True if success, False on error
  222. """
  223. check = self.ciface.write_raster_timestamp(self.get_name(),
  224. self.get_mapset(),
  225. self._convert_timestamp())
  226. if check == -1:
  227. self.msgr.error(_("Unable to create timestamp file "
  228. "for raster map <%s>" % (self.get_map_id())))
  229. return False
  230. if check == -2:
  231. self.msgr.error(_("Invalid datetime in timestamp for raster map "
  232. "<%s>" % (self.get_map_id())))
  233. return False
  234. if check == -3:
  235. self.msgr.error(_("Internal error"))
  236. return False
  237. return True
  238. def remove_timestamp_from_grass(self):
  239. """Remove the timestamp from the grass file system based
  240. spatial database
  241. Internally the libgis API functions are used for removal
  242. :return: True if success, False on error
  243. """
  244. check = self.ciface.remove_raster_timestamp(self.get_name(),
  245. self.get_mapset())
  246. if check == -1:
  247. self.msgr.error(_("Unable to remove timestamp for raster map <%s>"
  248. % (self.get_name())))
  249. return False
  250. return True
  251. def map_exists(self):
  252. """Return True in case the map exists in the grass spatial database
  253. :return: True if map exists, False otherwise
  254. """
  255. return self.ciface.raster_map_exists(self.get_name(),
  256. self.get_mapset())
  257. def load(self):
  258. """Load all info from an existing raster map into the internal structure
  259. This method checks first if the map exists, in case it exists
  260. the metadata of the map is put into this object and True is returned
  261. :return: True is the map exists and the metadata was filled
  262. successfully and getting the data was successful,
  263. False otherwise
  264. """
  265. if self.map_exists() is not True:
  266. return False
  267. # Fill base information
  268. self.base.set_creator(str(getpass.getuser()))
  269. kvp = self.ciface.read_raster_info(self.get_name(),
  270. self.get_mapset())
  271. if kvp:
  272. # Fill spatial extent
  273. self.set_spatial_extent_from_values(north=kvp["north"],
  274. south=kvp["south"],
  275. east=kvp["east"],
  276. west=kvp["west"])
  277. # Fill metadata
  278. self.metadata.set_nsres(kvp["nsres"])
  279. self.metadata.set_ewres(kvp["ewres"])
  280. self.metadata.set_datatype(kvp["datatype"])
  281. self.metadata.set_min(kvp["min"])
  282. self.metadata.set_max(kvp["max"])
  283. rows = int(kvp["rows"])
  284. cols = int(kvp["cols"])
  285. ncells = cols * rows
  286. self.metadata.set_cols(cols)
  287. self.metadata.set_rows(rows)
  288. self.metadata.set_number_of_cells(ncells)
  289. return True
  290. return False
  291. ###############################################################################
  292. class Raster3DDataset(AbstractMapDataset):
  293. """Raster3d dataset class
  294. This class provides functions to select, update, insert or delete raster3d
  295. map information and valid time stamps into the SQL temporal database.
  296. Usage:
  297. .. code-block:: python
  298. >>> import grass.script as grass
  299. >>> init()
  300. >>> grass.use_temp_region()
  301. >>> grass.run_command("g.region", n=80.0, s=0.0, e=120.0, w=0.0,
  302. ... t=100.0, b=0.0, res=10.0, res3=10.0)
  303. 0
  304. >>> grass.run_command("r3.mapcalc", overwrite=True, quiet=True,
  305. ... expression="str3ds_map_test_case = 1")
  306. 0
  307. >>> grass.run_command("r3.timestamp", map="str3ds_map_test_case",
  308. ... date="15 jan 1999", quiet=True)
  309. 0
  310. >>> mapset = get_current_mapset()
  311. >>> name = "str3ds_map_test_case"
  312. >>> identifier = "%s@%s" % (name, mapset)
  313. >>> r3map = Raster3DDataset(identifier)
  314. >>> r3map.map_exists()
  315. True
  316. >>> r3map.read_timestamp_from_grass()
  317. True
  318. >>> r3map.get_temporal_extent_as_tuple()
  319. (datetime.datetime(1999, 1, 15, 0, 0), None)
  320. >>> r3map.load()
  321. True
  322. >>> r3map.spatial_extent.print_info()
  323. +-------------------- Spatial extent ----------------------------------------+
  324. | North:...................... 80.0
  325. | South:...................... 0.0
  326. | East:.. .................... 120.0
  327. | West:....................... 0.0
  328. | Top:........................ 100.0
  329. | Bottom:..................... 0.0
  330. >>> r3map.absolute_time.print_info()
  331. +-------------------- Absolute time -----------------------------------------+
  332. | Start time:................. 1999-01-15 00:00:00
  333. | End time:................... None
  334. >>> r3map.metadata.print_info()
  335. +-------------------- Metadata information ----------------------------------+
  336. | Datatype:................... DCELL
  337. | Number of columns:.......... 8
  338. | Number of rows:............. 12
  339. | Number of cells:............ 960
  340. | North-South resolution:..... 10.0
  341. | East-west resolution:....... 10.0
  342. | Minimum value:.............. 1.0
  343. | Maximum value:.............. 1.0
  344. | Number of depths:........... 10
  345. | Top-Bottom resolution:...... 10.0
  346. >>> grass.run_command("r3.timestamp", map="str3ds_map_test_case",
  347. ... date="2 years", quiet=True)
  348. 0
  349. >>> r3map.read_timestamp_from_grass()
  350. True
  351. >>> r3map.get_temporal_extent_as_tuple()
  352. (2, None)
  353. >>> r3map.get_relative_time_unit()
  354. 'years'
  355. >>> r3map.is_in_db()
  356. False
  357. >>> r3map.is_stds()
  358. False
  359. >>> newmap = r3map.get_new_instance("new@PERMANENT")
  360. >>> isinstance(newmap, Raster3DDataset)
  361. True
  362. >>> newstr3ds = r3map.get_new_stds_instance("new@PERMANENT")
  363. >>> isinstance(newstr3ds, SpaceTimeRaster3DDataset)
  364. True
  365. >>> r3map.get_type()
  366. 'raster3d'
  367. >>> r3map.set_absolute_time(start_time=datetime(2001,1,1),
  368. ... end_time=datetime(2012,1,1))
  369. True
  370. >>> r3map.get_absolute_time()
  371. (datetime.datetime(2001, 1, 1, 0, 0), datetime.datetime(2012, 1, 1, 0, 0))
  372. >>> r3map.get_temporal_extent_as_tuple()
  373. (datetime.datetime(2001, 1, 1, 0, 0), datetime.datetime(2012, 1, 1, 0, 0))
  374. >>> r3map.get_name()
  375. u'str3ds_map_test_case'
  376. >>> r3map.get_mapset() == mapset
  377. True
  378. >>> r3map.get_temporal_type()
  379. 'absolute'
  380. >>> r3map.get_spatial_extent_as_tuple()
  381. (80.0, 0.0, 120.0, 0.0, 100.0, 0.0)
  382. >>> r3map.is_time_absolute()
  383. True
  384. >>> r3map.is_time_relative()
  385. False
  386. >>> grass.run_command("g.remove", flags="f", type="raster_3d", name=name, quiet=True)
  387. 0
  388. >>> grass.del_temp_region()
  389. """
  390. def __init__(self, ident):
  391. AbstractMapDataset.__init__(self)
  392. self.reset(ident)
  393. def is_stds(self):
  394. """Return True if this class is a space time dataset
  395. :return: True if this class is a space time dataset, False otherwise
  396. """
  397. return False
  398. def get_type(self):
  399. return "raster3d"
  400. def get_new_instance(self, ident):
  401. """Return a new instance with the type of this class"""
  402. return Raster3DDataset(ident)
  403. def get_new_stds_instance(self, ident):
  404. """Return a new space time dataset instance in which maps
  405. are stored with the type of this class"""
  406. return SpaceTimeRaster3DDataset(ident)
  407. def spatial_overlapping(self, dataset):
  408. """Return True if the spatial extents overlap"""
  409. if self.get_type() == dataset.get_type() or dataset.get_type() == "str3ds":
  410. return self.spatial_extent.overlapping(dataset.spatial_extent)
  411. else:
  412. return self.spatial_extent.overlapping_2d(dataset.spatial_extent)
  413. def spatial_relation(self, dataset):
  414. """Return the two or three dimensional spatial relation"""
  415. if self.get_type() == dataset.get_type() or dataset.get_type() == "str3ds":
  416. return self.spatial_extent.spatial_relation(dataset.spatial_extent)
  417. else:
  418. return self.spatial_extent.spatial_relation_2d(dataset.spatial_extent)
  419. def spatial_intersection(self, dataset):
  420. """Return the three or two dimensional intersection as spatial_extent
  421. object or None in case no intersection was found.
  422. :param dataset: The abstract dataset to intersect with
  423. :return: The intersection spatial extent or None
  424. """
  425. if self.get_type() == dataset.get_type() or dataset.get_type() == "str3ds":
  426. return self.spatial_extent.intersect(dataset.spatial_extent)
  427. else:
  428. return self.spatial_extent.intersect_2d(dataset.spatial_extent)
  429. def spatial_union(self, dataset):
  430. """Return the three or two dimensional union as spatial_extent
  431. object or None in case the extents does not overlap or meet.
  432. :param dataset: The abstract dataset to create a union with
  433. :return: The union spatial extent or None
  434. """
  435. if self.get_type() == dataset.get_type() or dataset.get_type() == "str3ds":
  436. return self.spatial_extent.union(dataset.spatial_extent)
  437. else:
  438. return self.spatial_extent.union_2d(dataset.spatial_extent)
  439. def spatial_disjoint_union(self, dataset):
  440. """Return the three or two dimensional union as spatial_extent object.
  441. :param dataset: The abstract dataset to create a union with
  442. :return: The union spatial extent
  443. """
  444. if self.get_type() == dataset.get_type() or dataset.get_type() == "str3ds":
  445. return self.spatial_extent.disjoint_union(dataset.spatial_extent)
  446. else:
  447. return self.spatial_extent.disjoint_union_2d(dataset.spatial_extent)
  448. def get_np_array(self):
  449. """Return this 3D raster map as memmap numpy style array to access the
  450. 3D raster values in numpy style without loading the whole map in
  451. the RAM.
  452. In case this 3D raster map does exists in the grass spatial database,
  453. the map will be exported using r3.out.bin to a temporary location
  454. and assigned to the memmap object that is returned by this function.
  455. In case the 3D raster map does not exist, an empty temporary
  456. binary file will be created and assigned to the memap object.
  457. You need to call the write function to write the memmap
  458. array back into grass.
  459. """
  460. a = garray.array3d()
  461. if self.map_exists():
  462. a.read(self.get_map_id())
  463. return a
  464. def reset(self, ident):
  465. """Reset the internal structure and set the identifier"""
  466. self.base = Raster3DBase(ident=ident)
  467. self.absolute_time = Raster3DAbsoluteTime(ident=ident)
  468. self.relative_time = Raster3DRelativeTime(ident=ident)
  469. self.spatial_extent = Raster3DSpatialExtent(ident=ident)
  470. self.metadata = Raster3DMetadata(ident=ident)
  471. self.stds_register = Raster3DSTDSRegister(ident=ident)
  472. def has_grass_timestamp(self):
  473. """Check if a grass file bsased time stamp exists for this map.
  474. :return: True if success, False on error
  475. """
  476. return self.ciface.has_raster3d_timestamp(self.get_name(),
  477. self.get_mapset())
  478. def read_timestamp_from_grass(self):
  479. """Read the timestamp of this map from the map metadata
  480. in the grass file system based spatial database and
  481. set the internal time stamp that should be insert/updated
  482. in the temporal database.
  483. :return: True if success, False on error
  484. """
  485. if not self.has_grass_timestamp():
  486. return False
  487. check, dates = self.ciface.read_raster3d_timestamp(self.get_name(),
  488. self.get_mapset(),)
  489. if check < 1:
  490. self.msgr.error(_("Unable to read timestamp file "
  491. "for 3D raster map <%s>" % (self.get_map_id())))
  492. return False
  493. if len(dates) == 2:
  494. self.set_absolute_time(dates[0], dates[1])
  495. else:
  496. self.set_relative_time(dates[0], dates[1], dates[2])
  497. return True
  498. def write_timestamp_to_grass(self):
  499. """Write the timestamp of this map into the map metadata
  500. in the grass file system based spatial database.
  501. Internally the libgis API functions are used for writing
  502. :return: True if success, False on error
  503. """
  504. check = self.ciface.write_raster3d_timestamp(self.get_name(),
  505. self.get_mapset(),
  506. self._convert_timestamp())
  507. if check == -1:
  508. self.msgr.error(_("Unable to create timestamp file "
  509. "for 3D raster map <%s>" % (self.get_map_id())))
  510. return False
  511. if check == -2:
  512. self.msgr.error(_("Invalid datetime in timestamp for 3D raster "
  513. "map <%s>" % (self.get_map_id())))
  514. return False
  515. if check == -3:
  516. self.msgr.error(_("Internal error"))
  517. return False
  518. return True
  519. def remove_timestamp_from_grass(self):
  520. """Remove the timestamp from the grass file system based spatial database
  521. :return: True if success, False on error
  522. """
  523. check = self.ciface.remove_raster3d_timestamp(self.get_name(),
  524. self.get_mapset())
  525. if check == -1:
  526. self.msgr.error(_("Unable to remove timestamp for raster map "
  527. "<%s>" % (self.get_name())))
  528. return False
  529. return True
  530. def map_exists(self):
  531. """Return True in case the map exists in the grass spatial database
  532. :return: True if map exists, False otherwise
  533. """
  534. return self.ciface.raster3d_map_exists(self.get_name(),
  535. self.get_mapset())
  536. def load(self):
  537. """Load all info from an existing 3d raster map into the internal structure
  538. This method checks first if the map exists, in case it exists
  539. the metadata of the map is put into this object and True is returned
  540. :return: True is the map exists and the metadata was filled
  541. successfully and getting the data was successful,
  542. False otherwise
  543. """
  544. if self.map_exists() is not True:
  545. return False
  546. # Fill base information
  547. self.base.set_creator(str(getpass.getuser()))
  548. # Fill spatial extent
  549. kvp = self.ciface.read_raster3d_info(self.get_name(),
  550. self.get_mapset())
  551. if kvp:
  552. self.set_spatial_extent_from_values(north=kvp["north"],
  553. south=kvp["south"],
  554. east=kvp["east"],
  555. west=kvp["west"],
  556. top=kvp["top"],
  557. bottom=kvp["bottom"])
  558. # Fill metadata
  559. self.metadata.set_nsres(kvp["nsres"])
  560. self.metadata.set_ewres(kvp["ewres"])
  561. self.metadata.set_tbres(kvp["tbres"])
  562. self.metadata.set_datatype(kvp["datatype"])
  563. self.metadata.set_min(kvp["min"])
  564. self.metadata.set_max(kvp["max"])
  565. rows = int(kvp["rows"])
  566. cols = int(kvp["cols"])
  567. depths = int(kvp["depths"])
  568. ncells = cols * rows * depths
  569. self.metadata.set_cols(cols)
  570. self.metadata.set_rows(rows)
  571. self.metadata.set_depths(depths)
  572. self.metadata.set_number_of_cells(ncells)
  573. return True
  574. return False
  575. ###############################################################################
  576. class VectorDataset(AbstractMapDataset):
  577. """Vector dataset class
  578. This class provides functions to select, update, insert or delete vector
  579. map information and valid time stamps into the SQL temporal database.
  580. Usage:
  581. .. code-block:: python
  582. >>> import grass.script as grass
  583. >>> init()
  584. >>> grass.use_temp_region()
  585. >>> grass.run_command("g.region", n=80.0, s=0.0, e=120.0, w=0.0,
  586. ... t=1.0, b=0.0, res=10.0)
  587. 0
  588. >>> grass.run_command("v.random", overwrite=True, output="stvds_map_test_case",
  589. ... n=100, zmin=0, zmax=100, flags="z", column="elevation", quiet=True)
  590. 0
  591. >>> grass.run_command("v.timestamp", map="stvds_map_test_case",
  592. ... date="15 jan 1999", quiet=True)
  593. 0
  594. >>> mapset = get_current_mapset()
  595. >>> name = "stvds_map_test_case"
  596. >>> identifier = "%s@%s" % (name, mapset)
  597. >>> vmap = VectorDataset(identifier)
  598. >>> vmap.map_exists()
  599. True
  600. >>> vmap.read_timestamp_from_grass()
  601. True
  602. >>> vmap.get_temporal_extent_as_tuple()
  603. (datetime.datetime(1999, 1, 15, 0, 0), None)
  604. >>> vmap.load()
  605. True
  606. >>> vmap.absolute_time.print_info()
  607. +-------------------- Absolute time -----------------------------------------+
  608. | Start time:................. 1999-01-15 00:00:00
  609. | End time:................... None
  610. >>> vmap.metadata.print_info()
  611. +-------------------- Metadata information ----------------------------------+
  612. | Is map 3d .................. True
  613. | Number of points ........... 100
  614. | Number of lines ............ 0
  615. | Number of boundaries ....... 0
  616. | Number of centroids ........ 0
  617. | Number of faces ............ 0
  618. | Number of kernels .......... 0
  619. | Number of primitives ....... 100
  620. | Number of nodes ............ 0
  621. | Number of areas ............ 0
  622. | Number of islands .......... 0
  623. | Number of holes ............ 0
  624. | Number of volumes .......... 0
  625. >>> grass.run_command("v.timestamp", map="stvds_map_test_case",
  626. ... date="2 years", quiet=True)
  627. 0
  628. >>> vmap.read_timestamp_from_grass()
  629. True
  630. >>> vmap.get_temporal_extent_as_tuple()
  631. (2, None)
  632. >>> vmap.get_relative_time_unit()
  633. 'years'
  634. >>> vmap.is_in_db()
  635. False
  636. >>> vmap.is_stds()
  637. False
  638. >>> newmap = vmap.get_new_instance("new@PERMANENT")
  639. >>> isinstance(newmap, VectorDataset)
  640. True
  641. >>> newstvds = vmap.get_new_stds_instance("new@PERMANENT")
  642. >>> isinstance(newstvds, SpaceTimeVectorDataset)
  643. True
  644. >>> vmap.get_type()
  645. 'vector'
  646. >>> vmap.set_absolute_time(start_time=datetime(2001,1,1),
  647. ... end_time=datetime(2012,1,1))
  648. True
  649. >>> vmap.get_absolute_time()
  650. (datetime.datetime(2001, 1, 1, 0, 0), datetime.datetime(2012, 1, 1, 0, 0))
  651. >>> vmap.get_temporal_extent_as_tuple()
  652. (datetime.datetime(2001, 1, 1, 0, 0), datetime.datetime(2012, 1, 1, 0, 0))
  653. >>> vmap.get_name()
  654. u'stvds_map_test_case'
  655. >>> vmap.get_mapset() == mapset
  656. True
  657. >>> vmap.get_temporal_type()
  658. 'absolute'
  659. >>> vmap.is_time_absolute()
  660. True
  661. >>> vmap.is_time_relative()
  662. False
  663. >>> grass.run_command("g.remove", flags="f", type="vector", name=name, quiet=True)
  664. 0
  665. >>> grass.del_temp_region()
  666. """
  667. def __init__(self, ident):
  668. AbstractMapDataset.__init__(self)
  669. self.reset(ident)
  670. def is_stds(self):
  671. """Return True if this class is a space time dataset
  672. :return: True if this class is a space time dataset, False otherwise
  673. """
  674. return False
  675. def get_type(self):
  676. return "vector"
  677. def get_new_instance(self, ident):
  678. """Return a new instance with the type of this class"""
  679. return VectorDataset(ident)
  680. def get_new_stds_instance(self, ident):
  681. """Return a new space time dataset instance in which maps
  682. are stored with the type of this class"""
  683. return SpaceTimeVectorDataset(ident)
  684. def get_layer(self):
  685. """Return the layer"""
  686. return self.base.get_layer()
  687. def spatial_overlapping(self, dataset):
  688. """Return True if the spatial extents 2d overlap"""
  689. return self.spatial_extent.overlapping_2d(dataset.spatial_extent)
  690. def spatial_relation(self, dataset):
  691. """Return the two dimensional spatial relation"""
  692. return self.spatial_extent.spatial_relation_2d(dataset.spatial_extent)
  693. def spatial_intersection(self, dataset):
  694. """Return the two dimensional intersection as spatial_extent
  695. object or None in case no intersection was found.
  696. :param dataset: The abstract dataset to intersect with
  697. :return: The intersection spatial extent or None
  698. """
  699. return self.spatial_extent.intersect_2d(dataset.spatial_extent)
  700. def spatial_union(self, dataset):
  701. """Return the two dimensional union as spatial_extent
  702. object or None in case the extents does not overlap or meet.
  703. :param dataset: The abstract dataset to create a union with
  704. :return: The union spatial extent or None
  705. """
  706. return self.spatial_extent.union_2d(dataset.spatial_extent)
  707. def spatial_disjoint_union(self, dataset):
  708. """Return the two dimensional union as spatial_extent object.
  709. :param dataset: The abstract dataset to create a union with
  710. :return: The union spatial extent
  711. """
  712. return self.spatial_extent.disjoint_union_2d(dataset.spatial_extent)
  713. def reset(self, ident):
  714. """Reset the internal structure and set the identifier"""
  715. self.base = VectorBase(ident=ident)
  716. self.absolute_time = VectorAbsoluteTime(ident=ident)
  717. self.relative_time = VectorRelativeTime(ident=ident)
  718. self.spatial_extent = VectorSpatialExtent(ident=ident)
  719. self.metadata = VectorMetadata(ident=ident)
  720. self.stds_register = VectorSTDSRegister(ident=ident)
  721. def has_grass_timestamp(self):
  722. """Check if a grass file bsased time stamp exists for this map.
  723. """
  724. return self.ciface.has_vector_timestamp(self.get_name(),
  725. self.get_mapset(),
  726. self.get_layer())
  727. def read_timestamp_from_grass(self):
  728. """Read the timestamp of this map from the map metadata
  729. in the grass file system based spatial database and
  730. set the internal time stamp that should be insert/updated
  731. in the temporal database.
  732. """
  733. if not self.has_grass_timestamp():
  734. return False
  735. check, dates = self.ciface.read_vector_timestamp(self.get_name(),
  736. self.get_mapset(),)
  737. if check < 1:
  738. self.msgr.error(_("Unable to read timestamp file "
  739. "for vector map <%s>" % (self.get_map_id())))
  740. return False
  741. if len(dates) == 2:
  742. self.set_absolute_time(dates[0], dates[1])
  743. else:
  744. self.set_relative_time(dates[0], dates[1], dates[2])
  745. return True
  746. def write_timestamp_to_grass(self):
  747. """Write the timestamp of this map into the map metadata in
  748. the grass file system based spatial database.
  749. Internally the libgis API functions are used for writing
  750. """
  751. check = self.ciface.write_vector_timestamp(self.get_name(),
  752. self.get_mapset(),
  753. self._convert_timestamp(),
  754. self.get_layer())
  755. if check == -1:
  756. self.msgr.error(_("Unable to create timestamp file "
  757. "for vector map <%s>" % (self.get_map_id())))
  758. return False
  759. if check == -2:
  760. self.msgr.error(_("Invalid datetime in timestamp for vector "
  761. "map <%s>" % (self.get_map_id())))
  762. return False
  763. return True
  764. def remove_timestamp_from_grass(self):
  765. """Remove the timestamp from the grass file system based spatial
  766. database
  767. Internally the libgis API functions are used for removal
  768. """
  769. check = self.ciface.remove_vector_timestamp(self.get_name(),
  770. self.get_mapset())
  771. if check == -1:
  772. self.msgr.error(_("Unable to remove timestamp for vector "
  773. "map <%s>" % (self.get_name())))
  774. return False
  775. return True
  776. def map_exists(self):
  777. """Return True in case the map exists in the grass spatial database
  778. :return: True if map exists, False otherwise
  779. """
  780. return self.ciface.vector_map_exists(self.get_name(),
  781. self.get_mapset())
  782. def load(self):
  783. """Load all info from an existing vector map into the internal structure
  784. This method checks first if the map exists, in case it exists
  785. the metadata of the map is put into this object and True is returned
  786. :return: True is the map exists and the metadata was filled
  787. successfully and getting the data was successful,
  788. False otherwise
  789. """
  790. if self.map_exists() is not True:
  791. return False
  792. # Fill base information
  793. self.base.set_creator(str(getpass.getuser()))
  794. # Get the data from an existing vector map
  795. kvp = self.ciface.read_vector_info(self.get_name(),
  796. self.get_mapset())
  797. if kvp:
  798. # Fill spatial extent
  799. self.set_spatial_extent_from_values(north=kvp["north"],
  800. south=kvp["south"],
  801. east=kvp["east"],
  802. west=kvp["west"],
  803. top=kvp["top"],
  804. bottom=kvp["bottom"])
  805. # Fill metadata
  806. self.metadata.set_3d_info(kvp["map3d"])
  807. self.metadata.set_number_of_points(kvp["points"])
  808. self.metadata.set_number_of_lines(kvp["lines"])
  809. self.metadata.set_number_of_boundaries(kvp["boundaries"])
  810. self.metadata.set_number_of_centroids(kvp["centroids"])
  811. self.metadata.set_number_of_faces(kvp["faces"])
  812. self.metadata.set_number_of_kernels(kvp["kernels"])
  813. self.metadata.set_number_of_primitives(kvp["primitives"])
  814. self.metadata.set_number_of_nodes(kvp["nodes"])
  815. self.metadata.set_number_of_areas(kvp["areas"])
  816. self.metadata.set_number_of_islands(kvp["islands"])
  817. self.metadata.set_number_of_holes(kvp["holes"])
  818. self.metadata.set_number_of_volumes(kvp["volumes"])
  819. return True
  820. return False
  821. ###############################################################################
  822. class SpaceTimeRasterDataset(AbstractSpaceTimeDataset):
  823. """Space time raster dataset class
  824. .. code-block:: python
  825. >>> import grass.temporal as tgis
  826. >>> tgis.init()
  827. >>> strds = tgis.SpaceTimeRasterDataset("old@PERMANENT")
  828. >>> strds.is_in_db()
  829. False
  830. >>> strds.is_stds()
  831. True
  832. >>> strds.get_type()
  833. 'strds'
  834. >>> newstrds = strds.get_new_instance("newstrds@PERMANENT")
  835. >>> isinstance(newstrds, SpaceTimeRasterDataset)
  836. True
  837. >>> newmap = strds.get_new_map_instance("newmap@PERMANENT")
  838. >>> isinstance(newmap, RasterDataset)
  839. True
  840. >>> strds.reset("new@PERMANENT")
  841. >>> strds.is_in_db()
  842. False
  843. >>> strds.get_id()
  844. 'new@PERMANENT'
  845. >>> strds.reset(None)
  846. >>> strds.is_in_db()
  847. False
  848. >>> strds.get_id()
  849. ...
  850. """
  851. def __init__(self, ident):
  852. AbstractSpaceTimeDataset.__init__(self, ident)
  853. def is_stds(self):
  854. """Return True if this class is a space time dataset
  855. :return: True if this class is a space time dataset, False otherwise
  856. """
  857. return True
  858. def get_type(self):
  859. return "strds"
  860. def get_new_instance(self, ident):
  861. """Return a new instance with the type of this class"""
  862. return SpaceTimeRasterDataset(ident)
  863. def get_new_map_instance(self, ident):
  864. """Return a new instance of a map dataset which is associated "
  865. "with the type of this class"""
  866. return RasterDataset(ident)
  867. def get_map_register(self):
  868. """Return the name of the map register table"""
  869. return self.metadata.get_raster_register()
  870. def set_map_register(self, name):
  871. """Set the name of the map register table"""
  872. self.metadata.set_raster_register(name)
  873. def spatial_overlapping(self, dataset):
  874. """Return True if the spatial extents 2d overlap"""
  875. return self.spatial_extent.overlapping_2d(dataset.spatial_extent)
  876. def spatial_relation(self, dataset):
  877. """Return the two dimensional spatial relation"""
  878. return self.spatial_extent.spatial_relation_2d(dataset.spatial_extent)
  879. def spatial_intersection(self, dataset):
  880. """Return the two dimensional intersection as spatial_extent
  881. object or None in case no intersection was found.
  882. :param dataset: The abstract dataset to intersect with
  883. :return: The intersection spatial extent or None
  884. """
  885. return self.spatial_extent.intersect_2d(dataset.spatial_extent)
  886. def spatial_union(self, dataset):
  887. """Return the two dimensional union as spatial_extent
  888. object or None in case the extents does not overlap or meet.
  889. :param dataset: The abstract dataset to create a union with
  890. :return: The union spatial extent or None
  891. """
  892. return self.spatial_extent.union_2d(dataset.spatial_extent)
  893. def spatial_disjoint_union(self, dataset):
  894. """Return the two dimensional union as spatial_extent object.
  895. :param dataset: The abstract dataset to create a union with
  896. :return: The union spatial extent
  897. """
  898. return self.spatial_extent.disjoint_union_2d(dataset.spatial_extent)
  899. def reset(self, ident):
  900. """Reset the internal structure and set the identifier"""
  901. self.base = STRDSBase(ident=ident)
  902. self.base.set_creator(str(getpass.getuser()))
  903. self.absolute_time = STRDSAbsoluteTime(ident=ident)
  904. self.relative_time = STRDSRelativeTime(ident=ident)
  905. self.spatial_extent = STRDSSpatialExtent(ident=ident)
  906. self.metadata = STRDSMetadata(ident=ident)
  907. ###############################################################################
  908. class SpaceTimeRaster3DDataset(AbstractSpaceTimeDataset):
  909. """Space time raster3d dataset class
  910. .. code-block:: python
  911. >>> import grass.temporal as tgis
  912. >>> tgis.init()
  913. >>> str3ds = tgis.SpaceTimeRaster3DDataset("old@PERMANENT")
  914. >>> str3ds.is_in_db()
  915. False
  916. >>> str3ds.is_stds()
  917. True
  918. >>> str3ds.get_type()
  919. 'str3ds'
  920. >>> newstrds = str3ds.get_new_instance("newstrds@PERMANENT")
  921. >>> isinstance(newstrds, SpaceTimeRaster3DDataset)
  922. True
  923. >>> newmap = str3ds.get_new_map_instance("newmap@PERMANENT")
  924. >>> isinstance(newmap, Raster3DDataset)
  925. True
  926. >>> str3ds.reset("new@PERMANENT")
  927. >>> str3ds.is_in_db()
  928. False
  929. >>> str3ds.get_id()
  930. 'new@PERMANENT'
  931. >>> str3ds.reset(None)
  932. >>> str3ds.is_in_db()
  933. False
  934. >>> str3ds.get_id()
  935. ...
  936. """
  937. def __init__(self, ident):
  938. AbstractSpaceTimeDataset.__init__(self, ident)
  939. def is_stds(self):
  940. """Return True if this class is a space time dataset
  941. :return: True if this class is a space time dataset, False otherwise
  942. """
  943. return True
  944. def get_type(self):
  945. return "str3ds"
  946. def get_new_instance(self, ident):
  947. """Return a new instance with the type of this class"""
  948. return SpaceTimeRaster3DDataset(ident)
  949. def get_new_map_instance(self, ident):
  950. """Return a new instance of a map dataset which is associated
  951. with the type of this class"""
  952. return Raster3DDataset(ident)
  953. def get_map_register(self):
  954. """Return the name of the map register table"""
  955. return self.metadata.get_raster3d_register()
  956. def set_map_register(self, name):
  957. """Set the name of the map register table"""
  958. self.metadata.set_raster3d_register(name)
  959. def spatial_overlapping(self, dataset):
  960. """Return True if the spatial extents overlap"""
  961. if self.get_type() == dataset.get_type() or dataset.get_type() == "str3ds":
  962. return self.spatial_extent.overlapping(dataset.spatial_extent)
  963. else:
  964. return self.spatial_extent.overlapping_2d(dataset.spatial_extent)
  965. def spatial_relation(self, dataset):
  966. """Return the two or three dimensional spatial relation"""
  967. if self.get_type() == dataset.get_type() or \
  968. dataset.get_type() == "str3ds":
  969. return self.spatial_extent.spatial_relation(dataset.spatial_extent)
  970. else:
  971. return self.spatial_extent.spatial_relation_2d(dataset.spatial_extent)
  972. def spatial_intersection(self, dataset):
  973. """Return the three or two dimensional intersection as spatial_extent
  974. object or None in case no intersection was found.
  975. :param dataset: The abstract dataset to intersect with
  976. :return: The intersection spatial extent or None
  977. """
  978. if self.get_type() == dataset.get_type() or dataset.get_type() == "raster3d":
  979. return self.spatial_extent.intersect(dataset.spatial_extent)
  980. else:
  981. return self.spatial_extent.intersect_2d(dataset.spatial_extent)
  982. def spatial_union(self, dataset):
  983. """Return the three or two dimensional union as spatial_extent
  984. object or None in case the extents does not overlap or meet.
  985. :param dataset: The abstract dataset to create a union with
  986. :return: The union spatial extent or None
  987. """
  988. if self.get_type() == dataset.get_type() or dataset.get_type() == "raster3d":
  989. return self.spatial_extent.union(dataset.spatial_extent)
  990. else:
  991. return self.spatial_extent.union_2d(dataset.spatial_extent)
  992. def spatial_disjoint_union(self, dataset):
  993. """Return the three or two dimensional union as spatial_extent object.
  994. :param dataset: The abstract dataset to create a union with
  995. :return: The union spatial extent
  996. """
  997. if self.get_type() == dataset.get_type() or dataset.get_type() == "raster3d":
  998. return self.spatial_extent.disjoint_union(dataset.spatial_extent)
  999. else:
  1000. return self.spatial_extent.disjoint_union_2d(dataset.spatial_extent)
  1001. def reset(self, ident):
  1002. """Reset the internal structure and set the identifier"""
  1003. self.base = STR3DSBase(ident=ident)
  1004. self.base.set_creator(str(getpass.getuser()))
  1005. self.absolute_time = STR3DSAbsoluteTime(ident=ident)
  1006. self.relative_time = STR3DSRelativeTime(ident=ident)
  1007. self.spatial_extent = STR3DSSpatialExtent(ident=ident)
  1008. self.metadata = STR3DSMetadata(ident=ident)
  1009. ###############################################################################
  1010. class SpaceTimeVectorDataset(AbstractSpaceTimeDataset):
  1011. """Space time vector dataset class
  1012. .. code-block:: python
  1013. >>> import grass.temporal as tgis
  1014. >>> tgis.init()
  1015. >>> stvds = tgis.SpaceTimeVectorDataset("old@PERMANENT")
  1016. >>> stvds.is_in_db()
  1017. False
  1018. >>> stvds.is_stds()
  1019. True
  1020. >>> stvds.get_type()
  1021. 'stvds'
  1022. >>> newstvds = stvds.get_new_instance("newstvds@PERMANENT")
  1023. >>> isinstance(newstvds, SpaceTimeVectorDataset)
  1024. True
  1025. >>> newmap = stvds.get_new_map_instance("newmap@PERMANENT")
  1026. >>> isinstance(newmap, VectorDataset)
  1027. True
  1028. >>> stvds.reset("new@PERMANENT")
  1029. >>> stvds.is_in_db()
  1030. False
  1031. >>> stvds.get_id()
  1032. 'new@PERMANENT'
  1033. >>> stvds.reset(None)
  1034. >>> stvds.is_in_db()
  1035. False
  1036. >>> stvds.get_id()
  1037. ...
  1038. """
  1039. def __init__(self, ident):
  1040. AbstractSpaceTimeDataset.__init__(self, ident)
  1041. def is_stds(self):
  1042. """Return True if this class is a space time dataset
  1043. :return: True if this class is a space time dataset, False otherwise
  1044. """
  1045. return True
  1046. def get_type(self):
  1047. return "stvds"
  1048. def get_new_instance(self, ident):
  1049. """Return a new instance with the type of this class"""
  1050. return SpaceTimeVectorDataset(ident)
  1051. def get_new_map_instance(self, ident):
  1052. """Return a new instance of a map dataset which is associated
  1053. with the type of this class"""
  1054. return VectorDataset(ident)
  1055. def get_map_register(self):
  1056. """Return the name of the map register table"""
  1057. return self.metadata.get_vector_register()
  1058. def set_map_register(self, name):
  1059. """Set the name of the map register table"""
  1060. self.metadata.set_vector_register(name)
  1061. def spatial_overlapping(self, dataset):
  1062. """Return True if the spatial extents 2d overlap"""
  1063. return self.spatial_extent.overlapping_2d(dataset.spatial_extent)
  1064. def spatial_relation(self, dataset):
  1065. """Return the two dimensional spatial relation"""
  1066. return self.spatial_extent.spatial_relation_2d(dataset.spatial_extent)
  1067. def spatial_intersection(self, dataset):
  1068. """Return the two dimensional intersection as spatial_extent
  1069. object or None in case no intersection was found.
  1070. :param dataset: The abstract dataset to intersect with
  1071. :return: The intersection spatial extent or None
  1072. """
  1073. return self.spatial_extent.intersect_2d(dataset.spatial_extent)
  1074. def spatial_union(self, dataset):
  1075. """Return the two dimensional union as spatial_extent
  1076. object or None in case the extents does not overlap or meet.
  1077. :param dataset: The abstract dataset to create a union with
  1078. :return: The union spatial extent or None
  1079. """
  1080. return self.spatial_extent.union_2d(dataset.spatial_extent)
  1081. def spatial_disjoint_union(self, dataset):
  1082. """Return the two dimensional union as spatial_extent object.
  1083. :param dataset: The abstract dataset to create a union with
  1084. :return: The union spatial extent
  1085. """
  1086. return self.spatial_extent.disjoint_union_2d(dataset.spatial_extent)
  1087. def reset(self, ident):
  1088. """Reset the internal structure and set the identifier"""
  1089. self.base = STVDSBase(ident=ident)
  1090. self.base.set_creator(str(getpass.getuser()))
  1091. self.absolute_time = STVDSAbsoluteTime(ident=ident)
  1092. self.relative_time = STVDSRelativeTime(ident=ident)
  1093. self.spatial_extent = STVDSSpatialExtent(ident=ident)
  1094. self.metadata = STVDSMetadata(ident=ident)
  1095. ###############################################################################
  1096. if __name__ == "__main__":
  1097. import doctest
  1098. doctest.testmod()