space_time_datasets.py 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930
  1. """!@package grass.temporal
  2. @brief GRASS Python scripting module (temporal GIS functions)
  3. Temporal GIS related functions to be used in Python scripts.
  4. Usage:
  5. @code
  6. import grass.temporal as tgis
  7. strds = tgis.space_time_raster_dataset("soils_1950_2010")
  8. ...
  9. @endcode
  10. (C) 2008-2011 by the GRASS Development Team
  11. This program is free software under the GNU General Public
  12. License (>=v2). Read the file COPYING that comes with GRASS
  13. for details.
  14. @author Soeren Gebbert
  15. """
  16. import getpass
  17. from ctypes import *
  18. import grass.lib.gis as libgis
  19. import grass.lib.raster as libraster
  20. import grass.lib.vector as libvector
  21. import grass.lib.raster3d as libraster3d
  22. import grass.script.array as garray
  23. from datetime_math import *
  24. from abstract_map_dataset import *
  25. from abstract_space_time_dataset import *
  26. ###############################################################################
  27. class raster_dataset(AbstractMapDataset):
  28. """!Raster dataset class
  29. This class provides functions to select, update, insert or delete raster
  30. map information and valid time stamps into the SQL temporal database.
  31. """
  32. def __init__(self, ident):
  33. AbstractMapDataset.__init__(self)
  34. self.reset(ident)
  35. def get_type(self):
  36. return "raster"
  37. def get_new_instance(self, ident):
  38. """!Return a new instance with the type of this class"""
  39. return raster_dataset(ident)
  40. def get_new_stds_instance(self, ident):
  41. """!Return a new space time dataset instance in which maps are stored with the type of this class"""
  42. return space_time_raster_dataset(ident)
  43. def get_stds_register(self):
  44. """!Return the space time dataset register table name in which stds are listed in which this map is registered"""
  45. return self.metadata.get_strds_register()
  46. def set_stds_register(self, name):
  47. """!Set the space time dataset register table name in which stds are listed in which this map is registered"""
  48. self.metadata.set_strds_register(name)
  49. def spatial_overlapping(self, dataset):
  50. """!Return True if the spatial extents 2d overlap"""
  51. return self.spatial_extent.overlapping_2d(dataset.spatial_extent)
  52. def spatial_relation(self, dataset):
  53. """Return the two dimensional spatial relation"""
  54. return self.spatial_extent.spatial_relation_2d(dataset.spatial_extent)
  55. def get_np_array(self):
  56. """Return this raster map as memmap numpy style array to access the raster
  57. values in numpy style without loading the whole map in the RAM.
  58. In case this raster map does exists in the grass spatial database, the map
  59. will be exported using r.out.bin to a temporary location and assigned to the
  60. memmap object that is returned by this function.
  61. In case the raster map does not exists, an empty temporary binary file will be created
  62. and assigned to the memap object.
  63. You need to call the write function to write the memmap array back into grass.
  64. """
  65. a = garray.array()
  66. if self.map_exists():
  67. a.read(self.get_map_id())
  68. return a
  69. def reset(self, ident):
  70. """!Reset the internal structure and set the identifier"""
  71. self.base = RasterBase(ident=ident)
  72. self.absolute_time = RasterAbslouteTime(ident=ident)
  73. self.relative_time = RasterRelativeTime(ident=ident)
  74. self.spatial_extent = RasterSpatialExtent(ident=ident)
  75. self.metadata = RasterMetadata(ident=ident)
  76. def has_grass_timestamp(self):
  77. """!Check if a grass file bsased time stamp exists for this map.
  78. """
  79. if G_has_raster_timestamp(self.get_name(), self.get_mapset()):
  80. return True
  81. else:
  82. return False
  83. def write_timestamp_to_grass(self):
  84. """!Write the timestamp of this map into the map metadata in the grass file system based spatial
  85. database.
  86. Internally the libgis API functions are used for writing
  87. """
  88. ts = libgis.TimeStamp()
  89. libgis.G_scan_timestamp(byref(ts), self._convert_timestamp())
  90. check = libgis.G_write_raster_timestamp(self.get_name(), byref(ts))
  91. if check == -1:
  92. core.error(_("Unable to create timestamp file for raster map <%s>"%(self.get_map_id())))
  93. if check == -2:
  94. core.error(_("Invalid datetime in timestamp for raster map <%s>"%(self.get_map_id())))
  95. def remove_timestamp_from_grass(self):
  96. """!Remove the timestamp from the grass file system based spatial database
  97. Internally the libgis API functions are used for removal
  98. """
  99. check = libgis.G_remove_raster_timestamp(self.get_name())
  100. if check == -1:
  101. core.error(_("Unable to remove timestamp for raster map <%s>"%(self.get_name())))
  102. def map_exists(self):
  103. """!Return True in case the map exists in the grass spatial database
  104. @return True if map exists, False otherwise
  105. """
  106. mapset = libgis.G_find_raster(self.get_name(), self.get_mapset())
  107. if not mapset:
  108. return False
  109. return True
  110. def read_info(self):
  111. """!Read the raster map info from the file system and store the content
  112. into a dictionary
  113. This method uses the ctypes interface to the gis and raster libraries
  114. to read the map metadata information
  115. """
  116. kvp = {}
  117. name = self.get_name()
  118. mapset = self.get_mapset()
  119. if not self.map_exists():
  120. core.fatal(_("Raster map <%s> not found" % name))
  121. # Read the region information
  122. region = libgis.Cell_head()
  123. libraster.Rast_get_cellhd(name, mapset, byref(region))
  124. kvp["north"] = region.north
  125. kvp["south"] = region.south
  126. kvp["east"] = region.east
  127. kvp["west"] = region.west
  128. kvp["nsres"] = region.ns_res
  129. kvp["ewres"] = region.ew_res
  130. kvp["rows"] = region.cols
  131. kvp["cols"] = region.rows
  132. maptype = libraster.Rast_map_type(name, mapset)
  133. if maptype == libraster.DCELL_TYPE:
  134. kvp["datatype"] = "DCELL"
  135. elif maptype == libraster.FCELL_TYPE:
  136. kvp["datatype"] = "FCELL"
  137. elif maptype == libraster.CELL_TYPE:
  138. kvp["datatype"] = "CELL"
  139. # Read range
  140. if libraster.Rast_map_is_fp(name, mapset):
  141. range = libraster.FPRange()
  142. libraster.Rast_init_fp_range (byref(range))
  143. ret = libraster.Rast_read_fp_range(name, mapset, byref(range))
  144. if ret < 0:
  145. core.fatal(_("Unable to read range file"))
  146. if ret == 2:
  147. kvp["min"] = None
  148. kvp["max"] = None
  149. else:
  150. min = libgis.DCELL()
  151. max = libgis.DCELL()
  152. libraster.Rast_get_fp_range_min_max(byref(range), byref(min), byref(max))
  153. kvp["min"] = min.value
  154. kvp["max"] = max.value
  155. else:
  156. range = libraster.Range()
  157. libraster.Rast_init_range (byref(range))
  158. ret = libraster.Rast_read_range(name, mapset, byref(range))
  159. if ret < 0:
  160. core.fatal(_("Unable to read range file"))
  161. if ret == 2:
  162. kvp["min"] = None
  163. kvp["max"] = None
  164. else:
  165. min = libgis.CELL()
  166. max = libgis.CELL()
  167. libraster.Rast_get_range_min_max(byref(range), byref(min), byref(max))
  168. kvp["min"] = min.value
  169. kvp["max"] = max.value
  170. return kvp
  171. def load(self):
  172. """!Load all info from an existing raster map into the internal structure"""
  173. # Fill base information
  174. self.base.set_creator(str(getpass.getuser()))
  175. # Get the data from an existing raster map
  176. kvp = self.read_info()
  177. # Fill spatial extent
  178. self.set_spatial_extent(north=kvp["north"], south=kvp["south"], \
  179. east=kvp["east"], west=kvp["west"])
  180. # Fill metadata
  181. self.metadata.set_nsres(kvp["nsres"])
  182. self.metadata.set_ewres(kvp["ewres"])
  183. self.metadata.set_datatype(kvp["datatype"])
  184. self.metadata.set_min(kvp["min"])
  185. self.metadata.set_max(kvp["max"])
  186. rows = kvp["rows"]
  187. cols = kvp["cols"]
  188. ncells = cols * rows
  189. self.metadata.set_cols(cols)
  190. self.metadata.set_rows(rows)
  191. self.metadata.set_number_of_cells(ncells)
  192. ###############################################################################
  193. class raster3d_dataset(AbstractMapDataset):
  194. """!Raster3d dataset class
  195. This class provides functions to select, update, insert or delete raster3d
  196. map information and valid time stamps into the SQL temporal database.
  197. """
  198. def __init__(self, ident):
  199. AbstractMapDataset.__init__(self)
  200. self.reset(ident)
  201. def get_type(self):
  202. return "raster3d"
  203. def get_new_instance(self, ident):
  204. """!Return a new instance with the type of this class"""
  205. return raster3d_dataset(ident)
  206. def get_new_stds_instance(self, ident):
  207. """!Return a new space time dataset instance in which maps are stored with the type of this class"""
  208. return space_time_raster3d_dataset(ident)
  209. def get_stds_register(self):
  210. """!Return the space time dataset register table name in which stds are listed in which this map is registered"""
  211. return self.metadata.get_str3ds_register()
  212. def set_stds_register(self, name):
  213. """!Set the space time dataset register table name in which stds are listed in which this map is registered"""
  214. self.metadata.set_str3ds_register(name)
  215. def spatial_overlapping(self, dataset):
  216. """!Return True if the spatial extents overlap"""
  217. if self.get_type() == dataset.get_type() or dataset.get_type() == "str3ds":
  218. return self.spatial_extent.overlapping(dataset.spatial_extent)
  219. else:
  220. return self.spatial_extent.overlapping_2d(dataset.spatial_extent)
  221. def spatial_relation(self, dataset):
  222. """!Return the two or three dimensional spatial relation"""
  223. if self.get_type() == dataset.get_type() or dataset.get_type() == "str3ds":
  224. return self.spatial_extent.spatial_relation(dataset.spatial_extent)
  225. else:
  226. return self.spatial_extent.spatial_relation_2d(dataset.spatial_extent)
  227. def reset(self, ident):
  228. """!Reset the internal structure and set the identifier"""
  229. self.base = Raster3DBase(ident=ident)
  230. self.absolute_time = Raster3DAbslouteTime(ident=ident)
  231. self.relative_time = Raster3DRelativeTime(ident=ident)
  232. self.spatial_extent = Raster3DSpatialExtent(ident=ident)
  233. self.metadata = Raster3DMetadata(ident=ident)
  234. def has_grass_timestamp(self):
  235. """!Check if a grass file bsased time stamp exists for this map.
  236. """
  237. if G_has_raster3d_timestamp(self.get_name(), self.get_mapset()):
  238. return True
  239. else:
  240. return False
  241. def write_timestamp_to_grass(self):
  242. """!Write the timestamp of this map into the map metadata in the grass file system based spatial
  243. database.
  244. Internally the libgis API functions are used for writing
  245. """
  246. ts = libgis.TimeStamp()
  247. libgis.G_scan_timestamp(byref(ts), self._convert_timestamp())
  248. check = libgis.G_write_raster3d_timestamp(self.get_name(), byref(ts))
  249. if check == -1:
  250. core.error(_("Unable to create timestamp file for raster3d map <%s>"%(self.get_map_id())))
  251. if check == -2:
  252. core.error(_("Invalid datetime in timestamp for raster3d map <%s>"%(self.get_map_id())))
  253. def remove_timestamp_from_grass(self):
  254. """!Remove the timestamp from the grass file system based spatial database
  255. Internally the libgis API functions are used for removal
  256. """
  257. check = libgis.G_remove_raster3d_timestamp(self.get_name())
  258. if check == -1:
  259. core.error(_("Unable to remove timestamp for raster3d map <%s>"%(self.get_name())))
  260. def map_exists(self):
  261. """!Return True in case the map exists in the grass spatial database
  262. @return True if map exists, False otherwise
  263. """
  264. mapset = libgis.G_find_raster3d(self.get_name(), self.get_mapset())
  265. if not mapset:
  266. return False
  267. return True
  268. def read_info(self):
  269. """!Read the raster3d map info from the file system and store the content
  270. into a dictionary
  271. This method uses the ctypes interface to the gis and raster3d libraries
  272. to read the map metadata information
  273. """
  274. kvp = {}
  275. name = self.get_name()
  276. mapset = self.get_mapset()
  277. if not self.map_exists():
  278. core.fatal(_("Raster3d map <%s> not found" % name))
  279. # Read the region information
  280. region = libraster3d.RASTER3D_Region()
  281. libraster3d.Rast3d_read_region_map(name, mapset, byref(region))
  282. kvp["north"] = region.north
  283. kvp["south"] = region.south
  284. kvp["east"] = region.east
  285. kvp["west"] = region.west
  286. kvp["nsres"] = region.ns_res
  287. kvp["ewres"] = region.ew_res
  288. kvp["tbres"] = region.tb_res
  289. kvp["rows"] = region.cols
  290. kvp["cols"] = region.rows
  291. kvp["depths"] = region.depths
  292. kvp["top"] = region.top
  293. kvp["bottom"] = region.bottom
  294. # We need to open the map, this function returns a void pointer
  295. # but we may need the correct type which is RASTER3D_Map, hence the casting
  296. g3map = cast(libraster3d.Rast3d_open_cell_old(name, mapset, \
  297. libraster3d.RASTER3D_DEFAULT_WINDOW, libraster3d.RASTER3D_TILE_SAME_AS_FILE, \
  298. libraster3d.RASTER3D_NO_CACHE), POINTER(libraster3d.RASTER3D_Map))
  299. if not g3map:
  300. core.fatal(_("Unable to open 3D raster map <%s>"%(name)));
  301. maptype = libraster3d.Rast3d_file_type_map(g3map)
  302. if maptype == libraster.DCELL_TYPE:
  303. kvp["datatype"] = "DCELL"
  304. elif maptype == libraster.FCELL_TYPE:
  305. kvp["datatype"] = "FCELL"
  306. # Read range
  307. min = libgis.DCELL()
  308. max = libgis.DCELL()
  309. ret = libraster3d.Rast3d_range_load(g3map)
  310. if not ret:
  311. core.fatal(_("Unable to load range of 3D raster map <%s>"%(name)));
  312. libraster3d.Rast3d_range_min_max(g3map, byref(min), byref(max))
  313. if min.value != min.value:
  314. kvp["min"] = None
  315. else:
  316. kvp["min"] = float(min.value)
  317. if max.value != max.value:
  318. kvp["max"] = None
  319. else:
  320. kvp["max"] = float(max.value)
  321. if not libraster3d.Rast3d_close(g3map):
  322. G_fatal_error(_("Unable to close 3D raster map <%s>"%(name)))
  323. return kvp
  324. def load(self):
  325. """!Load all info from an existing raster3d map into the internal structure"""
  326. # Fill base information
  327. self.base.set_creator(str(getpass.getuser()))
  328. # Fill spatial extent
  329. # Get the data from an existing raster map
  330. kvp = self.read_info()
  331. self.set_spatial_extent(north=kvp["north"], south=kvp["south"], \
  332. east=kvp["east"], west=kvp["west"],\
  333. top=kvp["top"], bottom=kvp["bottom"])
  334. # Fill metadata
  335. self.metadata.set_nsres(kvp["nsres"])
  336. self.metadata.set_ewres(kvp["ewres"])
  337. self.metadata.set_tbres(kvp["tbres"])
  338. self.metadata.set_datatype(kvp["datatype"])
  339. self.metadata.set_min(kvp["min"])
  340. self.metadata.set_max(kvp["max"])
  341. rows = kvp["rows"]
  342. cols = kvp["cols"]
  343. depths = kvp["depths"]
  344. ncells = cols * rows
  345. ncells = cols * rows * depths
  346. self.metadata.set_cols(cols)
  347. self.metadata.set_rows(rows)
  348. self.metadata.set_depths(depths)
  349. self.metadata.set_number_of_cells(ncells)
  350. ###############################################################################
  351. class vector_dataset(AbstractMapDataset):
  352. """!Vector dataset class
  353. This class provides functions to select, update, insert or delete vector
  354. map information and valid time stamps into the SQL temporal database.
  355. """
  356. def __init__(self, ident):
  357. AbstractMapDataset.__init__(self)
  358. self.reset(ident)
  359. def get_type(self):
  360. return "vector"
  361. def get_new_instance(self, ident):
  362. """!Return a new instance with the type of this class"""
  363. return vector_dataset(ident)
  364. def get_new_stds_instance(self, ident):
  365. """!Return a new space time dataset instance in which maps are stored with the type of this class"""
  366. return space_time_vector_dataset(ident)
  367. def get_stds_register(self):
  368. """!Return the space time dataset register table name in which stds are listed in which this map is registered"""
  369. return self.metadata.get_stvds_register()
  370. def set_stds_register(self, name):
  371. """!Set the space time dataset register table name in which stds are listed in which this map is registered"""
  372. self.metadata.set_stvds_register(name)
  373. def get_layer(self):
  374. """!Return the layer"""
  375. return self.base.get_layer()
  376. def spatial_overlapping(self, dataset):
  377. """!Return True if the spatial extents 2d overlap"""
  378. return self.spatial_extent.overlapping_2d(dataset.spatial_extent)
  379. def spatial_relation(self, dataset):
  380. """!Return the two dimensional spatial relation"""
  381. return self.spatial_extent.spatial_relation_2d(dataset.spatial_extent)
  382. def reset(self, ident):
  383. """!Reset the internal structure and set the identifier"""
  384. self.base = VectorBase(ident=ident)
  385. self.absolute_time = VectorAbslouteTime(ident=ident)
  386. self.relative_time = VectorRelativeTime(ident=ident)
  387. self.spatial_extent = VectorSpatialExtent(ident=ident)
  388. self.metadata = VectorMetadata(ident=ident)
  389. def has_grass_timestamp(self):
  390. """!Check if a grass file bsased time stamp exists for this map.
  391. """
  392. if G_has_raster_timestamp(self.get_name(), self.get_layer(), self.get_mapset()):
  393. return True
  394. else:
  395. return False
  396. def write_timestamp_to_grass(self):
  397. """!Write the timestamp of this map into the map metadata in the grass file system based spatial
  398. database.
  399. Internally the libgis API functions are used for writing
  400. """
  401. ts = libgis.TimeStamp()
  402. libgis.G_scan_timestamp(byref(ts), self._convert_timestamp())
  403. check = libgis.G_write_vector_timestamp(self.get_name(), self.get_layer(), byref(ts))
  404. if check == -1:
  405. core.error(_("Unable to create timestamp file for vector map <%s>"%(self.get_map_id())))
  406. if check == -2:
  407. core.error(_("Invalid datetime in timestamp for vector map <%s>"%(self.get_map_id())))
  408. def remove_timestamp_from_grass(self):
  409. """!Remove the timestamp from the grass file system based spatial database
  410. Internally the libgis API functions are used for removal
  411. """
  412. check = libgis.G_remove_vector_timestamp(self.get_name(), self.get_layer())
  413. if check == -1:
  414. core.error(_("Unable to remove timestamp for vector map <%s>"%(self.get_name())))
  415. def map_exists(self):
  416. """!Return True in case the map exists in the grass spatial database
  417. @return True if map exists, False otherwise
  418. """
  419. mapset = libgis.G_find_vector(self.get_name(), self.get_mapset())
  420. if not mapset:
  421. return False
  422. return True
  423. def read_info(self):
  424. """!Read the vector map info from the file system and store the content
  425. into a dictionary
  426. This method uses the ctypes interface to the vector libraries
  427. to read the map metadata information
  428. """
  429. kvp = {}
  430. name = self.get_name()
  431. mapset = self.get_mapset()
  432. if not self.map_exists():
  433. core.fatal(_("Vector map <%s> not found" % name))
  434. # The vector map structure
  435. Map = libvector.Map_info()
  436. # We open the maps always in topology mode first
  437. libvector.Vect_set_open_level(2)
  438. with_topo = True
  439. # Code lend from v.info main.c
  440. if libvector.Vect_open_old_head2(byref(Map), name, mapset, "1") < 2:
  441. # force level 1, open fully
  442. # NOTE: number of points, lines, boundaries, centroids, faces, kernels is still available
  443. libvector.Vect_set_open_level(1) # no topology
  444. with_topo = False
  445. core.message(_("Open map without topology support"))
  446. if libvector.Vect_open_old2(byref(Map), name, mapset, "1") < 1:
  447. core.fatal(_("Unable to open vector map <%s>"%(libvector.Vect_get_full_name(byref(Map)))))
  448. # Read the extent information
  449. bbox = libvector.bound_box()
  450. libvector.Vect_get_map_box(byref(Map), byref(bbox));
  451. kvp["north"] = bbox.N
  452. kvp["south"] = bbox.S
  453. kvp["east"] = bbox.E
  454. kvp["west"] = bbox.W
  455. kvp["top"] = bbox.T
  456. kvp["bottom"] = bbox.B
  457. kvp["is_3d"] = bool(libvector.Vect_is_3d(byref(Map)))
  458. # Read number of features
  459. if with_topo:
  460. kvp["points"] = libvector.Vect_get_num_primitives(byref(Map), libvector.GV_POINT)
  461. kvp["lines"] = libvector.Vect_get_num_primitives(byref(Map), libvector.GV_LINE)
  462. kvp["boundaries"] = libvector.Vect_get_num_primitives(byref(Map), libvector.GV_BOUNDARY)
  463. kvp["centroids"] = libvector.Vect_get_num_primitives(byref(Map), libvector.GV_CENTROID)
  464. kvp["faces"] = libvector.Vect_get_num_primitives(byref(Map), libvector.GV_FACE)
  465. kvp["kernels"] = libvector.Vect_get_num_primitives(byref(Map), libvector.GV_KERNEL)
  466. # Summarize the primitives
  467. kvp["primitives"] = kvp["points"] + kvp["lines"] + kvp["boundaries"] + kvp["centroids"]
  468. if kvp["is_3d"]:
  469. kvp["primitives"] += kvp["faces"] + kvp["kernels"]
  470. # Read topology information
  471. kvp["nodes"] = libvector.Vect_get_num_nodes(byref(Map))
  472. kvp["areas"] = libvector.Vect_get_num_areas(byref(Map))
  473. kvp["islands"] = libvector.Vect_get_num_islands(byref(Map))
  474. kvp["holes"] = libvector.Vect_get_num_holes(byref(Map))
  475. kvp["volumes"] = libvector.Vect_get_num_primitives(byref(Map), libvector.GV_VOLUME)
  476. else:
  477. kvp["points"] = None
  478. kvp["lines"] = None
  479. kvp["boundaries"] = None
  480. kvp["centroids"] = None
  481. kvp["faces"] = None
  482. kvp["kernels"] = None
  483. kvp["primitives"] = None
  484. kvp["nodes"] = None
  485. kvp["areas"] = None
  486. kvp["islands"] = None
  487. kvp["holes"] = None
  488. kvp["volumes"] = None
  489. libvector.Vect_close(byref(Map))
  490. return kvp
  491. def load(self):
  492. """!Load all info from an existing vector map into the internal structure"""
  493. # Fill base information
  494. self.base.set_creator(str(getpass.getuser()))
  495. # Get the data from an existing raster map
  496. kvp = self.read_info()
  497. # Fill spatial extent
  498. self.set_spatial_extent(north=kvp["north"], south=kvp["south"], \
  499. east=kvp["east"], west=kvp["west"],\
  500. top=kvp["top"], bottom=kvp["bottom"])
  501. # Fill metadata
  502. self.metadata.set_3d_info(kvp["is_3d"])
  503. self.metadata.set_points(kvp["points"])
  504. self.metadata.set_lines(kvp["lines"])
  505. self.metadata.set_boundaries(kvp["boundaries"])
  506. self.metadata.set_centroids(kvp["centroids"])
  507. self.metadata.set_faces(kvp["faces"])
  508. self.metadata.set_kernels(kvp["kernels"])
  509. self.metadata.set_primitives(kvp["primitives"])
  510. self.metadata.set_nodes(kvp["nodes"])
  511. self.metadata.set_areas(kvp["areas"])
  512. self.metadata.set_islands(kvp["islands"])
  513. self.metadata.set_holes(kvp["holes"])
  514. self.metadata.set_volumes(kvp["volumes"])
  515. ###############################################################################
  516. class space_time_raster_dataset(AbstractSpaceTimeDataset):
  517. """!Space time raster dataset class
  518. """
  519. def __init__(self, ident):
  520. AbstractSpaceTimeDataset.__init__(self, ident)
  521. def get_type(self):
  522. return "strds"
  523. def get_new_instance(self, ident):
  524. """!Return a new instance with the type of this class"""
  525. return space_time_raster_dataset(ident)
  526. def get_new_map_instance(self, ident):
  527. """!Return a new instance of a map dataset which is associated with the type of this class"""
  528. return raster_dataset(ident)
  529. def get_map_register(self):
  530. """!Return the name of the map register table"""
  531. return self.metadata.get_raster_register()
  532. def set_map_register(self, name):
  533. """!Set the name of the map register table"""
  534. self.metadata.set_raster_register(name)
  535. def spatial_overlapping(self, dataset):
  536. """!Return True if the spatial extents 2d overlap"""
  537. return self.spatial_extent.overlapping_2d(dataset.spatial_extent)
  538. def spatial_relation(self, dataset):
  539. """!Return the two dimensional spatial relation"""
  540. return self.spatial_extent.spatial_relation_2d(dataset.spatial_extent)
  541. def reset(self, ident):
  542. """!Reset the internal structure and set the identifier"""
  543. self.base = STRDSBase(ident=ident)
  544. self.base.set_creator(str(getpass.getuser()))
  545. self.absolute_time = STRDSAbslouteTime(ident=ident)
  546. self.relative_time = STRDSRelativeTime(ident=ident)
  547. self.spatial_extent = STRDSSpatialExtent(ident=ident)
  548. self.metadata = STRDSMetadata(ident=ident)
  549. ###############################################################################
  550. class space_time_raster3d_dataset(AbstractSpaceTimeDataset):
  551. """!Space time raster3d dataset class
  552. """
  553. def __init__(self, ident):
  554. AbstractSpaceTimeDataset.__init__(self, ident)
  555. def get_type(self):
  556. return "str3ds"
  557. def get_new_instance(self, ident):
  558. """!Return a new instance with the type of this class"""
  559. return space_time_raster3d_dataset(ident)
  560. def get_new_map_instance(self, ident):
  561. """!Return a new instance of a map dataset which is associated with the type of this class"""
  562. return raster3d_dataset(ident)
  563. def get_map_register(self):
  564. """!Return the name of the map register table"""
  565. return self.metadata.get_raster3d_register()
  566. def set_map_register(self, name):
  567. """!Set the name of the map register table"""
  568. self.metadata.set_raster3d_register(name)
  569. def spatial_overlapping(self, dataset):
  570. """!Return True if the spatial extents overlap"""
  571. if self.get_type() == dataset.get_type() or dataset.get_type() == "str3ds":
  572. return self.spatial_extent.overlapping(dataset.spatial_extent)
  573. else:
  574. return self.spatial_extent.overlapping_2d(dataset.spatial_extent)
  575. def spatial_relation(self, dataset):
  576. """!Return the two or three dimensional spatial relation"""
  577. if self.get_type() == dataset.get_type() or dataset.get_type() == "str3ds":
  578. return self.spatial_extent.spatial_relation(dataset.spatial_extent)
  579. else:
  580. return self.spatial_extent.spatial_relation_2d(dataset.spatial_extent)
  581. def reset(self, ident):
  582. """!Reset the internal structure and set the identifier"""
  583. self.base = STR3DSBase(ident=ident)
  584. self.base.set_creator(str(getpass.getuser()))
  585. self.absolute_time = STR3DSAbslouteTime(ident=ident)
  586. self.relative_time = STR3DSRelativeTime(ident=ident)
  587. self.spatial_extent = STR3DSSpatialExtent(ident=ident)
  588. self.metadata = STR3DSMetadata(ident=ident)
  589. ###############################################################################
  590. class space_time_vector_dataset(AbstractSpaceTimeDataset):
  591. """!Space time vector dataset class
  592. """
  593. def __init__(self, ident):
  594. AbstractSpaceTimeDataset.__init__(self, ident)
  595. def get_type(self):
  596. return "stvds"
  597. def get_new_instance(self, ident):
  598. """!Return a new instance with the type of this class"""
  599. return space_time_vector_dataset(ident)
  600. def get_new_map_instance(self, ident):
  601. """!Return a new instance of a map dataset which is associated with the type of this class"""
  602. return vector_dataset(ident)
  603. def get_map_register(self):
  604. """!Return the name of the map register table"""
  605. return self.metadata.get_vector_register()
  606. def set_map_register(self, name):
  607. """!Set the name of the map register table"""
  608. self.metadata.set_vector_register(name)
  609. def spatial_overlapping(self, dataset):
  610. """!Return True if the spatial extents 2d overlap"""
  611. return self.spatial_extent.overlapping_2d(dataset.spatial_extent)
  612. def spatial_relation(self, dataset):
  613. """!Return the two dimensional spatial relation"""
  614. return self.spatial_extent.spatial_relation_2d(dataset.spatial_extent)
  615. def reset(self, ident):
  616. """!Reset the internal structure and set the identifier"""
  617. self.base = STVDSBase(ident=ident)
  618. self.base.set_creator(str(getpass.getuser()))
  619. self.absolute_time = STVDSAbslouteTime(ident=ident)
  620. self.relative_time = STVDSRelativeTime(ident=ident)
  621. self.spatial_extent = STVDSSpatialExtent(ident=ident)
  622. self.metadata = STVDSMetadata(ident=ident)
  623. ###############################################################################
  624. class AbstractDatasetComparisonKeyStartTime(object):
  625. """!This comparison key can be used to sort lists of abstract datasets by start time
  626. Example:
  627. # Return all maps in a space time raster dataset as map objects
  628. map_list = strds.get_registered_maps_as_objects()
  629. # Sort the maps in the list by start time
  630. sorted_map_list = sorted(
  631. map_list, key=AbstractDatasetComparisonKeyStartTime)
  632. """
  633. def __init__(self, obj, *args):
  634. self.obj = obj
  635. def __lt__(self, other):
  636. startA, endA = self.obj.get_valid_time()
  637. startB, endB = other.obj.get_valid_time()
  638. return startA < startB
  639. def __gt__(self, other):
  640. startA, endA = self.obj.get_valid_time()
  641. startB, endB = other.obj.get_valid_time()
  642. return startA > startB
  643. def __eq__(self, other):
  644. startA, endA = self.obj.get_valid_time()
  645. startB, endB = other.obj.get_valid_time()
  646. return startA == startB
  647. def __le__(self, other):
  648. startA, endA = self.obj.get_valid_time()
  649. startB, endB = other.obj.get_valid_time()
  650. return startA <= startB
  651. def __ge__(self, other):
  652. startA, endA = self.obj.get_valid_time()
  653. startB, endB = other.obj.get_valid_time()
  654. return startA >= startB
  655. def __ne__(self, other):
  656. startA, endA = self.obj.get_valid_time()
  657. startB, endB = other.obj.get_valid_time()
  658. return startA != startB
  659. ###############################################################################
  660. class AbstractDatasetComparisonKeyEndTime(object):
  661. """!This comparison key can be used to sort lists of abstract datasets by end time
  662. Example:
  663. # Return all maps in a space time raster dataset as map objects
  664. map_list = strds.get_registered_maps_as_objects()
  665. # Sort the maps in the list by end time
  666. sorted_map_list = sorted(
  667. map_list, key=AbstractDatasetComparisonKeyEndTime)
  668. """
  669. def __init__(self, obj, *args):
  670. self.obj = obj
  671. def __lt__(self, other):
  672. startA, endA = self.obj.get_valid_time()
  673. startB, endB = other.obj.get_valid_time()
  674. return endA < endB
  675. def __gt__(self, other):
  676. startA, endA = self.obj.get_valid_time()
  677. startB, endB = other.obj.get_valid_time()
  678. return endA > endB
  679. def __eq__(self, other):
  680. startA, endA = self.obj.get_valid_time()
  681. startB, endB = other.obj.get_valid_time()
  682. return endA == endB
  683. def __le__(self, other):
  684. startA, endA = self.obj.get_valid_time()
  685. startB, endB = other.obj.get_valid_time()
  686. return endA <= endB
  687. def __ge__(self, other):
  688. startA, endA = self.obj.get_valid_time()
  689. startB, endB = other.obj.get_valid_time()
  690. return endA >= endB
  691. def __ne__(self, other):
  692. startA, endA = self.obj.get_valid_time()
  693. startB, endB = other.obj.get_valid_time()
  694. return endA != endB