space_time_datasets.py 53 KB

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