space_time_datasets_tools.py 33 KB

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