space_time_datasets_tools.py 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901
  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. tgis.register_maps_in_space_time_dataset(type, name, maps)
  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. from space_time_datasets import *
  17. ###############################################################################
  18. def register_maps_in_space_time_dataset(type, name, maps=None, layer=None, file=None, start=None, \
  19. end=None, unit=None, increment=None, dbif = None, \
  20. interval=False, fs="|"):
  21. """Use this method to register maps in space time datasets. This function is generic and
  22. Additionally a start time string and an increment string can be specified
  23. to assign a time interval automatically to the maps.
  24. It takes care of the correct update of the space time datasets from all
  25. registered maps.
  26. @param type: The type of the maps raster, raster3d or vector
  27. @param name: The name of the space time dataset
  28. @param maps: A comma separated list of map names
  29. @param layer: A comma separated list of layer id's or the file identifier in case the layer is provided in the input file
  30. @param file: Input file one map with optional layer, start and end time, one per line
  31. @param start: The start date and time of the first raster map (format absolute: "yyyy-mm-dd HH:MM:SS" or "yyyy-mm-dd", format relative is integer 5)
  32. @param end: The end date and time of the first raster map (format absolute: "yyyy-mm-dd HH:MM:SS" or "yyyy-mm-dd", format relative is integer 5)
  33. @param unit: The unit of the relative time: years, months, days, hours, minutes, seconds
  34. @param increment: Time increment between maps for time stamp creation (format absolute: NNN seconds, minutes, hours, days, weeks, months, years; format relative: 1.0)
  35. @param dbif: The database interface to be used
  36. @param interval: If True, time intervals are created in case the start time and an increment is provided
  37. @param fs: Field separator used in input file
  38. """
  39. start_time_in_file = False
  40. end_time_in_file = False
  41. if maps and file:
  42. core.fatal(_("%s= and %s= are mutually exclusive") % ("input","file"))
  43. if end and increment:
  44. core.fatal(_("%s= and %s= are mutually exclusive") % ("end","increment"))
  45. if end and not start:
  46. core.fatal(_("Please specify %s= and %s=") % ("start_time","end_time"))
  47. if not maps and not file:
  48. core.fatal(_("Please specify %s= or %s=") % ("input","file"))
  49. layer_in_file = False
  50. if layer and layer == "file":
  51. layer_in_file = True
  52. if start and start == "file":
  53. start_time_in_file = True
  54. if end and end == "file":
  55. end_time_in_file = True
  56. # We may need the mapset
  57. mapset = core.gisenv()["MAPSET"]
  58. # Check if the dataset name contains the mapset as well
  59. if name.find("@") < 0:
  60. id = name + "@" + mapset
  61. else:
  62. id = name
  63. sp = dataset_factory(type, id)
  64. connect = False
  65. if dbif == None:
  66. dbif = sql_database_interface()
  67. dbif.connect()
  68. connect = True
  69. # Read content from temporal database
  70. sp.select(dbif)
  71. if sp.is_in_db(dbif) == False:
  72. dbif.close()
  73. core.fatal(_("Space time %s dataset <%s> no found") % (sp.get_new_map_instance(None).get_type(), name))
  74. dummy = sp.get_new_map_instance(None)
  75. maplist = []
  76. layerlist = []
  77. # Map names as comma separated string
  78. if maps:
  79. if maps.find(",") < 0:
  80. maplist = [maps,]
  81. else:
  82. maplist = maps.split(",")
  83. # Layer as comma separated string
  84. if layer:
  85. if layer.find(",") < 0:
  86. layerlist = (layer,)
  87. else:
  88. layerlist = layer.split(",")
  89. if len(maplist) != len(layerlist):
  90. core.fatal(_("Number of %s= and %s= must be equal") % ("maps","layer"))
  91. # Build the maplist again with the ids
  92. for count in range(len(maplist)):
  93. row = {}
  94. if layer:
  95. mapid = dummy.build_id(maplist[count], mapset, layerlist[count])
  96. else:
  97. mapid = dummy.build_id(maplist[count], mapset, None)
  98. row["id"] = mapid
  99. maplist[count] = row
  100. # Read the map list from file
  101. if file:
  102. fd = open(file, "r")
  103. line = True
  104. while True:
  105. line = fd.readline()
  106. if not line:
  107. break
  108. line_list = line.split(fs)
  109. mapname = line_list[0].strip()
  110. row = {}
  111. if layer_in_file:
  112. row["layer"] = line_list[1].strip()
  113. if start_time_in_file and end_time_in_file:
  114. row["start"] = line_list[2].strip()
  115. row["end"] = line_list[3].strip()
  116. if start_time_in_file and not end_time_in_file:
  117. row["start"] = line_list[2].strip()
  118. row["id"] = dummy.build_id(mapname, mapset, row["layer"])
  119. else:
  120. if start_time_in_file and end_time_in_file:
  121. row["start"] = line_list[1].strip()
  122. row["end"] = line_list[2].strip()
  123. if start_time_in_file and not end_time_in_file:
  124. row["start"] = line_list[1].strip()
  125. row["id"] = dummy.build_id(mapname, mapset)
  126. maplist.append(row)
  127. num_maps = len(maplist)
  128. for count in range(len(maplist)):
  129. core.percent(count, num_maps, 1)
  130. # Get a new instance of the space time dataset map type
  131. map = sp.get_new_map_instance(maplist[count]["id"])
  132. # Use the time data from file
  133. if start_time_in_file:
  134. start = maplist[count]["start"]
  135. if end_time_in_file:
  136. end = maplist[count]["end"]
  137. # Put the map into the database
  138. if map.is_in_db(dbif) == False:
  139. # Break in case no valid time is provided
  140. if start == "" or start == None:
  141. dbif.close()
  142. if map.get_layer():
  143. core.fatal(_("Unable to register %s map <%s> with layer %s. The map has no valid time and the start time is not set.") % \
  144. (map.get_type(), map.get_map_id(), map.get_layer() ))
  145. else:
  146. core.fatal(_("Unable to register %s map <%s>. The map has no valid time and the start time is not set.") % \
  147. (map.get_type(), map.get_map_id() ))
  148. # Load the data from the grass file database
  149. map.load()
  150. if sp.get_temporal_type() == "absolute":
  151. map.set_time_to_absolute()
  152. else:
  153. map.set_time_to_relative()
  154. # Put it into the temporal database
  155. map.insert(dbif)
  156. else:
  157. map.select(dbif)
  158. if map.get_temporal_type() != sp.get_temporal_type():
  159. dbif.close()
  160. if map.get_layer():
  161. core.fatal(_("Unable to register %s map <%s> with layer. The temporal types are different.") % \
  162. (map.get_type(), map.get_map_id(), map.get_layer()))
  163. core.fatal(_("Unable to register %s map <%s>. The temporal types are different.") % \
  164. (map.get_type(), map.get_map_id()))
  165. # In case the time is in the input file we ignore the increment counter
  166. if start_time_in_file:
  167. count = 1
  168. # Set the valid time
  169. if start:
  170. assign_valid_time_to_map(ttype=sp.get_temporal_type(), map=map, start=start, end=end, unit=unit, increment=increment, mult=count, dbif=dbif, interval=interval)
  171. # Finally Register map in the space time dataset
  172. sp.register_map(map, dbif)
  173. # Update the space time tables
  174. sp.update_from_registered_maps(dbif)
  175. if connect == True:
  176. dbif.close()
  177. core.percent(num_maps, num_maps, 1)
  178. ###############################################################################
  179. def unregister_maps_from_space_time_datasets(type, name, maps, layer=None, file=None, dbif=None):
  180. """Unregister maps from a single space time dataset or, in case no dataset name is provided,
  181. unregister from all datasets within the maps are registered.
  182. @param type: The type of the maps raster, vector or raster3d
  183. @param name: Name of an existing space time raster dataset. If no name is provided the raster map(s) are unregistered from all space time datasets in which they are registered.
  184. @param maps: A comma separated list of map names
  185. @param layer: A comma separated list of layer id's or the file identifier in case the layer is provided in the input file
  186. @param file: Input file one map with optional layer, start and end time, one per line
  187. @param dbif: The database interface to be used
  188. """
  189. if maps and file:
  190. core.fatal(_("%s= and %s= are mutually exclusive") % ("input","file"))
  191. mapset = core.gisenv()["MAPSET"]
  192. if dbif == None:
  193. dbif = sql_database_interface()
  194. dbif.connect()
  195. connect = True
  196. layer_in_file = False
  197. if layer and layer == "file":
  198. layer_in_file = True
  199. # In case a space time dataset is specified
  200. if name:
  201. # Check if the dataset name contains the mapset as well
  202. if name.find("@") < 0:
  203. id = name + "@" + mapset
  204. else:
  205. id = name
  206. if type == "rast":
  207. sp = dataset_factory("strds", id)
  208. if type == "rast3d":
  209. sp = dataset_factory("str3ds", id)
  210. if type == "vect":
  211. sp = dataset_factory("stvds", id)
  212. if sp.is_in_db(dbif) == False:
  213. dbif.close()
  214. core.fatal("Space time " + sp.get_new_map_instance(None).get_type() + " dataset <" + name + "> not found")
  215. maplist = []
  216. layerlist = []
  217. dummy = raster_dataset(None)
  218. # Map names as comma separated string
  219. if maps != None:
  220. if maps.find(",") == -1:
  221. maplist = [maps,]
  222. else:
  223. maplist = maps.split(",")
  224. if layer:
  225. if layer.find(",") < 0:
  226. layerlist = (layer,)
  227. else:
  228. layerlist = layer.split(",")
  229. if len(maplist) != len(layerlist):
  230. core.fatal(_("Number of %s= and %s= must be equal") % ("maps","layer"))
  231. # Build the maplist
  232. for count in range(len(maplist)):
  233. mapname = maplist[count]
  234. if layer:
  235. mylayer = layerlist[count]
  236. mapid = dummy.build_id(mapname, mapset, mylayer)
  237. else:
  238. mapid = dummy.build_id(mapname, mapset)
  239. maplist[count] = mapid
  240. # Read the map list from file
  241. if file:
  242. fd = open(file, "r")
  243. line = True
  244. while True:
  245. line = fd.readline()
  246. if not line:
  247. break
  248. line_list = line.split(fs)
  249. mapname = line_list[0].strip()
  250. if layer_in_file:
  251. mylayer = line_list[1].strip()
  252. mapid = dummy.build_id(mapname, mapset, mylayer)
  253. else:
  254. mapid = dummy.build_id(mapname, mapset)
  255. maplist.append(mapid)
  256. num_maps = len(maplist)
  257. count = 0
  258. for mapid in maplist:
  259. core.percent(count, num_maps, 1)
  260. print mapid
  261. map = dataset_factory(type, mapid)
  262. # Unregister map if in database
  263. if map.is_in_db(dbif) == True:
  264. if name:
  265. sp.select(dbif)
  266. sp.unregister_map(map, dbif)
  267. else:
  268. map.select(dbif)
  269. map.unregister(dbif)
  270. count += 1
  271. if name:
  272. sp.update_from_registered_maps(dbif)
  273. if connect == True:
  274. dbif.close()
  275. core.percent(num_maps, num_maps, 1)
  276. ###############################################################################
  277. def assign_valid_time_to_maps(type, maps, layer, ttype, start, end=None, unit=None, file=file, increment=None, dbif = None, interval=False, fs="|"):
  278. """Use this method to assign valid time (absolute or relative) to raster,
  279. raster3d and vector datasets.
  280. It takes care of the correct update of the space time datasets from all
  281. registered maps.
  282. Valid end time and increment are mutual exclusive.
  283. @param type: The type of the maps raster, raster3d or vector
  284. @param maps: A comma separated list of map names
  285. @param layer: A comma separated list of layer id's or the file identifier in case the layer is provided in the input file
  286. @param start: The start date and time of the first raster map (format absolute: "yyyy-mm-dd HH:MM:SS" or "yyyy-mm-dd", format relative is integer 5)
  287. @param end: The end date and time of the first raster map (format absolute: "yyyy-mm-dd HH:MM:SS" or "yyyy-mm-dd", format relative is integer 5)
  288. @param unit: The unit of the relative time: years, months, days, hours, minutes, seconds
  289. @param increment: Time increment between maps for time stamp creation (format absolute: NNN seconds, minutes, hours, days, weeks, months, years; format relative: 1.0)
  290. @param file: Input file one map with optional start and end time, one per line
  291. @param dbif: The database interface to be used
  292. @param interval: If True, time intervals are created in case the start time and an increment is provided
  293. @param fs: Field separator used in input file
  294. """
  295. start_time_in_file = False
  296. end_time_in_file = False
  297. if end and increment:
  298. if dbif:
  299. dbif.close()
  300. core.fatal(_("Valid end time and increment are mutual exclusive"))
  301. # List of space time datasets to be updated
  302. splist = {}
  303. if maps and file:
  304. core.fatal(_("%s= and %s= are mutually exclusive") % ("input","file"))
  305. if end and increment:
  306. core.fatal(_("%s= and %s= are mutually exclusive") % ("end","increment"))
  307. if end and not start:
  308. core.fatal(_("Please specify %s= and %s=") % ("start_time","end_time"))
  309. if not maps and not file:
  310. core.fatal(_("Please specify %s= or %s=") % ("input","file"))
  311. layer_in_file = False
  312. if layer and layer == "file":
  313. layer_in_file = True
  314. if start and start == "file":
  315. start_time_in_file = True
  316. if end and end == "file":
  317. end_time_in_file = True
  318. # We may need the mapset
  319. mapset = core.gisenv()["MAPSET"]
  320. connect = False
  321. if dbif == None:
  322. dbif = sql_database_interface()
  323. dbif.connect()
  324. connect = True
  325. maplist = []
  326. layerlist = []
  327. dummy = raster_dataset(None)
  328. # Map names as comma separated string
  329. if maps:
  330. if maps.find(",") < 0:
  331. maplist = [maps,]
  332. else:
  333. maplist = maps.split(",")
  334. # Layer as comma separated string
  335. if layer:
  336. if layer.find(",") < 0:
  337. layerlist = (layer,)
  338. else:
  339. layerlist = layer.split(",")
  340. if len(maplist) != len(layerlist):
  341. core.fatal(_("Number of %s= and %s= must be equal") % ("maps","layer"))
  342. # Build the maplist again with the ids
  343. for count in range(len(maplist)):
  344. row = {}
  345. if layer:
  346. mapid = dummy.build_id(maplist[count], mapset, layerlist[count])
  347. else:
  348. mapid = dummy.build_id(maplist[count], mapset, None)
  349. row["id"] = mapid
  350. maplist[count] = row
  351. # Read the map list from file
  352. if file:
  353. fd = open(file, "r")
  354. line = True
  355. while True:
  356. line = fd.readline()
  357. if not line:
  358. break
  359. line_list = line.split(fs)
  360. mapname = line_list[0].strip()
  361. row = {}
  362. if layer_in_file:
  363. row["layer"] = line_list[1].strip()
  364. if start_time_in_file and end_time_in_file:
  365. row["start"] = line_list[2].strip()
  366. row["end"] = line_list[3].strip()
  367. if start_time_in_file and not end_time_in_file:
  368. row["start"] = line_list[2].strip()
  369. row["id"] = dummy.build_id(mapname, mapset, row["layer"])
  370. else:
  371. if start_time_in_file and end_time_in_file:
  372. row["start"] = line_list[1].strip()
  373. row["end"] = line_list[2].strip()
  374. if start_time_in_file and not end_time_in_file:
  375. row["start"] = line_list[1].strip()
  376. row["id"] = dummy.build_id(mapname, mapset)
  377. maplist.append(row)
  378. num_maps = len(maplist)
  379. for count in range(len(maplist)):
  380. core.percent(count, num_maps, 1)
  381. # Get a new instance of the space time dataset map type
  382. map = map = dataset_factory(type, maplist[count]["id"])
  383. # Use the time data from file
  384. if start_time_in_file:
  385. start = maplist[count]["start"]
  386. if end_time_in_file:
  387. end = maplist[count]["end"]
  388. if map.is_in_db(dbif) == False:
  389. # Load the data from the grass file database
  390. map.load()
  391. if ttype == "absolute":
  392. map.set_time_to_absolute()
  393. else:
  394. map.set_time_to_relative()
  395. # Put it into the temporal database
  396. map.insert(dbif)
  397. else:
  398. map.select(dbif)
  399. sprows = map.get_registered_datasets(dbif)
  400. # Make an entry in the dataset list, using a dict make sure that
  401. # each dataset is listed only once
  402. if sprows != None:
  403. for dataset in sprows:
  404. splist[dataset["id"]] = True
  405. # In case the time is in the input file we ignore the increment counter
  406. if start_time_in_file:
  407. count = 1
  408. # Set the valid time
  409. assign_valid_time_to_map(ttype=ttype, map=map, start=start, end=end, unit=unit, increment=increment, mult=count, dbif=dbif, interval=interval)
  410. count += 1
  411. # Update all the space time datasets in which registered maps are changed there valid time
  412. for name in splist.keys():
  413. sp = map.get_new_stds_instance(name)
  414. sp.select(dbif)
  415. sp.update_from_registered_maps(dbif)
  416. if connect == True:
  417. dbif.close()
  418. core.percent(num_maps, num_maps, 1)
  419. ###############################################################################
  420. def assign_valid_time_to_map(ttype, map, start, end, unit, increment=None, mult=1, dbif = None, interval=False):
  421. """Assign the valid time to a map dataset
  422. @param ttype: The temporal type which should be assigned and which the time format is of
  423. @param map: A map dataset object derived from abstract_map_dataset
  424. @param start: The start date and time of the first raster map (format absolute: "yyyy-mm-dd HH:MM:SS" or "yyyy-mm-dd", format relative is integer 5)
  425. @param end: The end date and time of the first raster map (format absolute: "yyyy-mm-dd HH:MM:SS" or "yyyy-mm-dd", format relative is integer 5)
  426. @param unit: The unit of the relative time: years, months, days, hours, minutes, seconds
  427. @param increment: Time increment between maps for time stamp creation (format absolute: NNN seconds, minutes, hours, days, weeks, months, years; format relative is integer 1)
  428. @param multi: A multiplier for the increment
  429. @param dbif: The database interface to use for sql queries
  430. @param interval: If True, time intervals are created in case the start time and an increment is provided
  431. """
  432. connect = False
  433. if dbif == None:
  434. dbif = sql_database_interface()
  435. dbif.connect()
  436. connect = True
  437. if ttype == "absolute":
  438. start_time = string_to_datetime(start)
  439. if start_time == None:
  440. dbif.close()
  441. core.fatal(_("Unable to convert string \"%s\"into a datetime object")%(start))
  442. end_time = None
  443. if end:
  444. end_time = string_to_datetime(end)
  445. if end_time == None:
  446. dbif.close()
  447. core.fatal(_("Unable to convert string \"%s\"into a datetime object")%(end))
  448. # Add the increment
  449. if increment:
  450. start_time = increment_datetime_by_string(start_time, increment, mult)
  451. if interval:
  452. end_time = increment_datetime_by_string(start_time, increment, 1)
  453. if map.get_layer():
  454. core.verbose(_("Set absolute valid time for map <%s> with layer %s to %s - %s") % (map.get_map_id(), map.get_layer(), str(start_time), str(end_time)))
  455. else:
  456. core.verbose(_("Set absolute valid time for map <%s> to %s - %s") % (map.get_map_id(), str(start_time), str(end_time)))
  457. map.update_absolute_time(start_time, end_time, None, dbif)
  458. else:
  459. start_time = int(start)
  460. end_time = None
  461. if end:
  462. end_time = int(end)
  463. if increment:
  464. start_time = start_time + mult * int(increment)
  465. if interval:
  466. end_time = start_time + int(increment)
  467. if map.get_layer():
  468. core.verbose(_("Set relative valid time for map <%s> with layer %s to %i - %s with unit %s") % (map.get_map_id(), map.get_layer(), start_time, str(end_time), unit))
  469. else:
  470. core.verbose(_("Set relative valid time for map <%s> to %i - %s with unit %s") % (map.get_map_id(), start_time, str(end_time), unit))
  471. map.update_relative_time(start_time, end_time, unit, dbif)
  472. if connect == True:
  473. dbif.close()
  474. ###############################################################################
  475. def dataset_factory(type, id):
  476. """A factory functions to create space time or map datasets
  477. @param type: the dataset type: rast, rast3d, vect, strds, str3ds, stvds
  478. @param id: The id of the dataset ("name@mapset")
  479. """
  480. if type == "strds":
  481. sp = space_time_raster_dataset(id)
  482. elif type == "str3ds":
  483. sp = space_time_raster3d_dataset(id)
  484. elif type == "stvds":
  485. sp = space_time_vector_dataset(id)
  486. elif type == "rast":
  487. sp = raster_dataset(id)
  488. elif type == "rast3d":
  489. sp = raster3d_dataset(id)
  490. elif type == "vect":
  491. sp = vector_dataset(id)
  492. else:
  493. core.error(_("Unknown dataset type: %s") % type)
  494. return None
  495. return sp
  496. ###############################################################################
  497. def list_maps_of_stds(type, input, columns, order, where, separator, method, header):
  498. """ List the maps of a space time dataset using diffetent methods
  499. @param type: The type of the maps raster, raster3d or vector
  500. @param input: Name of a space time raster dataset
  501. @param columns: A comma separated list of columns to be printed to stdout
  502. @param order: A comma separated list of columns to order the space time dataset by category
  503. @param where: A where statement for selected listing without "WHERE" e.g: start_time < "2001-01-01" and end_time > "2001-01-01"
  504. @param separator: The field separator character between the columns
  505. @param method: String identifier to select a method out of cols,comma,delta or deltagaps
  506. * "cols": Print preselected columns specified by columns
  507. * "comma": Print the map ids (name@mapset) as comma separated string
  508. * "delta": Print the map ids (name@mapset) with start time, end time, relative length of intervals and the relative distance to the begin
  509. * "deltagaps": Same as "delta" with additional listing of gaps. Gaps can be simply identified as the id is "None"
  510. * "gran": List map using the granularity of the space time dataset, columns are identical to deltagaps
  511. @param header: Set True to print column names
  512. """
  513. mapset = core.gisenv()["MAPSET"]
  514. if input.find("@") >= 0:
  515. id = input
  516. else:
  517. id = input + "@" + mapset
  518. sp = dataset_factory(type, id)
  519. if sp.is_in_db() == False:
  520. core.fatal(_("Dataset <%s> not found in temporal database") % (id))
  521. sp.select()
  522. if separator == None or separator == "":
  523. separator = "\t"
  524. # This method expects a list of objects for gap detection
  525. if method == "delta" or method == "deltagaps" or method == "gran":
  526. if type == "stvds":
  527. columns = "id,name,layer,mapset,start_time,end_time"
  528. else:
  529. columns = "id,name,mapset,start_time,end_time"
  530. if method == "deltagaps":
  531. maps = sp.get_registered_maps_as_objects_with_gaps(where, None)
  532. elif method == "delta":
  533. maps = sp.get_registered_maps_as_objects(where, "start_time", None)
  534. elif method == "gran":
  535. maps = sp.get_registered_maps_as_objects_by_granularity(None)
  536. if header:
  537. string = ""
  538. string += "%s%s" % ("id", separator)
  539. string += "%s%s" % ("name", separator)
  540. if type == "stvds":
  541. string += "%s%s" % ("layer", separator)
  542. string += "%s%s" % ("mapset", separator)
  543. string += "%s%s" % ("start_time", separator)
  544. string += "%s%s" % ("end_time", separator)
  545. string += "%s%s" % ("interval_length", separator)
  546. string += "%s" % ("distance_from_begin")
  547. print string
  548. if maps and len(maps) > 0:
  549. if isinstance(maps[0], list):
  550. first_time, dummy = maps[0][0].get_valid_time()
  551. else:
  552. first_time, dummy = maps[0].get_valid_time()
  553. for mymap in maps:
  554. if isinstance(mymap, list):
  555. map = mymap[0]
  556. else:
  557. map = mymap
  558. start, end = map.get_valid_time()
  559. if end:
  560. delta = end -start
  561. else:
  562. delta = None
  563. delta_first = start - first_time
  564. if map.is_time_absolute():
  565. if end:
  566. delta = time_delta_to_relative_time(delta)
  567. delta_first = time_delta_to_relative_time(delta_first)
  568. string = ""
  569. string += "%s%s" % (map.get_id(), separator)
  570. string += "%s%s" % (map.get_name(), separator)
  571. if type == "stvds":
  572. string += "%s%s" % (map.get_layer(), separator)
  573. string += "%s%s" % (map.get_mapset(), separator)
  574. string += "%s%s" % (start, separator)
  575. string += "%s%s" % (end, separator)
  576. string += "%s%s" % (delta, separator)
  577. string += "%s" % (delta_first)
  578. print string
  579. else:
  580. # In comma separated mode only map ids are needed
  581. if method == "comma":
  582. columns = "id"
  583. rows = sp.get_registered_maps(columns, where, order, None)
  584. if rows:
  585. if method == "comma":
  586. string = ""
  587. count = 0
  588. for row in rows:
  589. if count == 0:
  590. string += row["id"]
  591. else:
  592. string += ",%s" % row["id"]
  593. count += 1
  594. print string
  595. elif method == "cols":
  596. # Print the column names if requested
  597. if header:
  598. output = ""
  599. count = 0
  600. collist = columns.split(",")
  601. for key in collist:
  602. if count > 0:
  603. output += separator + str(key)
  604. else:
  605. output += str(key)
  606. count += 1
  607. print output
  608. for row in rows:
  609. output = ""
  610. count = 0
  611. for col in row:
  612. if count > 0:
  613. output += separator + str(col)
  614. else:
  615. output += str(col)
  616. count += 1
  617. print output
  618. ###############################################################################
  619. def sample_stds_by_stds_topology(intype, sampletype, input, sampler, header, separator, method):
  620. """ Sample the input space time dataset with a sample space time dataset and print the result to stdout
  621. In case multiple maps are located in the current granule, the map names are separated by comma.
  622. In case a layer is present, the names map ids are extended in this form: name:layer@mapset
  623. Attention: Do not use the comma as separator
  624. @param intype: Type of the input space time dataset (strds, stvds or str3ds)
  625. @param samtype: Type of the sample space time dataset (strds, stvds or str3ds)
  626. @param input: Name of a space time dataset
  627. @param sampler: Name of a space time dataset used for temporal sampling
  628. @param header: Set True to print column names
  629. @param separator: The field separator character between the columns
  630. @param method: The method to be used for sampling (start,during,contain,overlap,equal)
  631. """
  632. mapset = core.gisenv()["MAPSET"]
  633. if input.find("@") >= 0:
  634. id = input
  635. else:
  636. id = input + "@" + mapset
  637. sp = dataset_factory(intype, id)
  638. if sampler.find("@") >= 0:
  639. sid = sampler
  640. else:
  641. sid = sampler + "@" + mapset
  642. ssp = dataset_factory(sampletype, sid)
  643. dbif = sql_database_interface()
  644. dbif.connect()
  645. if sp.is_in_db(dbif) == False:
  646. core.fatal(_("Dataset <%s> not found in temporal database") % (id))
  647. if ssp.is_in_db(dbif) == False:
  648. core.fatal(_("Dataset <%s> not found in temporal database") % (sid))
  649. sp.select(dbif)
  650. ssp.select(dbif)
  651. if separator == None or separator == "" or separator.find(",") >= 0:
  652. separator = " | "
  653. mapmatrix = sp.sample_by_dataset_topology(ssp, method, dbif)
  654. if mapmatrix and len(mapmatrix) > 0:
  655. if header:
  656. string = ""
  657. string += "%s%s" % ("sample_id", separator)
  658. string += "%s%s" % ("ids", separator)
  659. string += "%s%s" % ("start_time", separator)
  660. string += "%s%s" % ("end_time", separator)
  661. string += "%s%s" % ("interval_length", separator)
  662. string += "%s" % ("distance_from_begin")
  663. print string
  664. first_time, dummy = mapmatrix[0]["granule"].get_valid_time()
  665. for entry in mapmatrix:
  666. mapnames = ""
  667. count = 0
  668. for sample in entry["samples"]:
  669. if count == 0:
  670. mapnames += str(sample.get_id())
  671. else:
  672. mapnames += ",%s" % str(sample.get_id())
  673. count += 1
  674. map = entry["granule"]
  675. start, end = map.get_valid_time()
  676. if end:
  677. delta = end - start
  678. else:
  679. delta = None
  680. delta_first = start - first_time
  681. if map.is_time_absolute():
  682. if end:
  683. delta = time_delta_to_relative_time(delta)
  684. delta_first = time_delta_to_relative_time(delta_first)
  685. string = ""
  686. string += "%s%s" % (map.get_id(), separator)
  687. string += "%s%s" % (mapnames, separator)
  688. string += "%s%s" % (start, separator)
  689. string += "%s%s" % (end, separator)
  690. string += "%s%s" % (delta, separator)
  691. string += "%s" % (delta_first)
  692. print string
  693. dbif.close()