space_time_datasets_tools.py 26 KB

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