list_stds.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  1. """
  2. Functions to create space time dataset lists
  3. Usage:
  4. .. code-block:: python
  5. import grass.temporal as tgis
  6. tgis.register_maps_in_space_time_dataset(type, name, maps)
  7. (C) 2012-2016 by the GRASS Development Team
  8. This program is free software under the GNU General Public
  9. License (>=v2). Read the file COPYING that comes with GRASS GIS
  10. for details.
  11. :authors: Soeren Gebbert
  12. """
  13. from __future__ import print_function
  14. from .core import get_tgis_message_interface, get_available_temporal_mapsets, init_dbif
  15. from .datetime_math import time_delta_to_relative_time
  16. from .factory import dataset_factory
  17. from .open_stds import open_old_stds
  18. import grass.script as gscript
  19. ###############################################################################
  20. def get_dataset_list(
  21. type, temporal_type, columns=None, where=None, order=None, dbif=None
  22. ):
  23. """Return a list of time stamped maps or space time datasets of a specific
  24. temporal type that are registered in the temporal database
  25. This method returns a dictionary, the keys are the available mapsets,
  26. the values are the rows from the SQL database query.
  27. :param type: The type of the datasets (strds, str3ds, stvds, raster,
  28. raster_3d, vector)
  29. :param temporal_type: The temporal type of the datasets (absolute,
  30. relative)
  31. :param columns: A comma separated list of columns that will be selected
  32. :param where: A where statement for selected listing without "WHERE"
  33. :param order: A comma separated list of columns to order the
  34. datasets by category
  35. :param dbif: The database interface to be used
  36. :return: A dictionary with the rows of the SQL query for each
  37. available mapset
  38. .. code-block:: python
  39. >>> import grass.temporal as tgis
  40. >>> tgis.core.init()
  41. >>> name = "list_stds_test"
  42. >>> sp = tgis.open_stds.open_new_stds(name=name, type="strds",
  43. ... temporaltype="absolute", title="title", descr="descr",
  44. ... semantic="mean", dbif=None, overwrite=True)
  45. >>> mapset = tgis.get_current_mapset()
  46. >>> stds_list = tgis.list_stds.get_dataset_list("strds", "absolute", columns="name")
  47. >>> rows = stds_list[mapset]
  48. >>> for row in rows:
  49. ... if row["name"] == name:
  50. ... print(True)
  51. True
  52. >>> stds_list = tgis.list_stds.get_dataset_list("strds", "absolute", columns="name,mapset", where="mapset = '%s'"%(mapset))
  53. >>> rows = stds_list[mapset]
  54. >>> for row in rows:
  55. ... if row["name"] == name and row["mapset"] == mapset:
  56. ... print(True)
  57. True
  58. >>> check = sp.delete()
  59. """
  60. id = None
  61. sp = dataset_factory(type, id)
  62. dbif, connection_state_changed = init_dbif(dbif)
  63. mapsets = get_available_temporal_mapsets()
  64. result = {}
  65. for mapset in mapsets.keys():
  66. if temporal_type == "absolute":
  67. table = sp.get_type() + "_view_abs_time"
  68. else:
  69. table = sp.get_type() + "_view_rel_time"
  70. if columns and columns.find("all") == -1:
  71. sql = "SELECT " + str(columns) + " FROM " + table
  72. else:
  73. sql = "SELECT * FROM " + table
  74. if where:
  75. sql += " WHERE " + where
  76. sql += " AND mapset = '%s'" % (mapset)
  77. else:
  78. sql += " WHERE mapset = '%s'" % (mapset)
  79. if order:
  80. sql += " ORDER BY " + order
  81. dbif.execute(sql, mapset=mapset)
  82. rows = dbif.fetchall(mapset=mapset)
  83. if rows:
  84. result[mapset] = rows
  85. if connection_state_changed:
  86. dbif.close()
  87. return result
  88. ###############################################################################
  89. def list_maps_of_stds(
  90. type,
  91. input,
  92. columns,
  93. order,
  94. where,
  95. separator,
  96. method,
  97. no_header=False,
  98. gran=None,
  99. dbif=None,
  100. outpath=None,
  101. ):
  102. """List the maps of a space time dataset using different methods
  103. :param type: The type of the maps raster, raster3d or vector
  104. :param input: Name of a space time raster dataset
  105. :param columns: A comma separated list of columns to be printed to stdout
  106. :param order: A comma separated list of columns to order the
  107. maps by category
  108. :param where: A where statement for selected listing without "WHERE"
  109. e.g: start_time < "2001-01-01" and end_time > "2001-01-01"
  110. :param separator: The field separator character between the columns
  111. :param method: String identifier to select a method out of cols,
  112. comma,delta or deltagaps
  113. :param dbif: The database interface to be used
  114. - "cols" Print preselected columns specified by columns
  115. - "comma" Print the map ids ("name@mapset") as comma separated string
  116. - "delta" Print the map ids ("name@mapset") with start time,
  117. end time, relative length of intervals and the relative
  118. distance to the begin
  119. - "deltagaps" Same as "delta" with additional listing of gaps.
  120. Gaps can be easily identified as the id is "None"
  121. - "gran" List map using the granularity of the space time dataset,
  122. columns are identical to deltagaps
  123. :param no_header: Suppress the printing of column names
  124. :param gran: The user defined granule to be used if method=gran is
  125. set, in case gran=None the granule of the space time
  126. dataset is used
  127. :param outpath: The path to file where to save output
  128. """
  129. dbif, connection_state_changed = init_dbif(dbif)
  130. msgr = get_tgis_message_interface()
  131. sp = open_old_stds(input, type, dbif)
  132. if separator is None or separator == "":
  133. separator = "\t"
  134. if outpath:
  135. outfile = open(outpath, "w")
  136. # This method expects a list of objects for gap detection
  137. if method == "delta" or method == "deltagaps" or method == "gran":
  138. if type == "stvds":
  139. columns = "id,name,layer,mapset,start_time,end_time"
  140. else:
  141. columns = "id,name,mapset,start_time,end_time"
  142. if method == "deltagaps":
  143. maps = sp.get_registered_maps_as_objects_with_gaps(where=where, dbif=dbif)
  144. elif method == "delta":
  145. maps = sp.get_registered_maps_as_objects(
  146. where=where, order="start_time", dbif=dbif
  147. )
  148. elif method == "gran":
  149. if gran is not None and gran != "":
  150. maps = sp.get_registered_maps_as_objects_by_granularity(
  151. gran=gran, dbif=dbif
  152. )
  153. else:
  154. maps = sp.get_registered_maps_as_objects_by_granularity(dbif=dbif)
  155. if no_header is False:
  156. string = ""
  157. string += "%s%s" % ("id", separator)
  158. string += "%s%s" % ("name", separator)
  159. if type == "stvds":
  160. string += "%s%s" % ("layer", separator)
  161. string += "%s%s" % ("mapset", separator)
  162. string += "%s%s" % ("start_time", separator)
  163. string += "%s%s" % ("end_time", separator)
  164. string += "%s%s" % ("interval_length", separator)
  165. string += "%s" % ("distance_from_begin")
  166. if outpath:
  167. outfile.write("{st}\n".format(st=string))
  168. else:
  169. print(string)
  170. if maps and len(maps) > 0:
  171. if isinstance(maps[0], list):
  172. if len(maps[0]) > 0:
  173. first_time, dummy = maps[0][0].get_temporal_extent_as_tuple()
  174. else:
  175. msgr.warning(_("Empty map list"))
  176. return
  177. else:
  178. first_time, dummy = maps[0].get_temporal_extent_as_tuple()
  179. for mymap in maps:
  180. if isinstance(mymap, list):
  181. if len(mymap) > 0:
  182. map = mymap[0]
  183. else:
  184. msgr.fatal(_("Empty entry in map list, this should not happen"))
  185. else:
  186. map = mymap
  187. start, end = map.get_temporal_extent_as_tuple()
  188. if end:
  189. delta = end - start
  190. else:
  191. delta = None
  192. delta_first = start - first_time
  193. if map.is_time_absolute():
  194. if end:
  195. delta = time_delta_to_relative_time(delta)
  196. delta_first = time_delta_to_relative_time(delta_first)
  197. string = ""
  198. string += "%s%s" % (map.get_id(), separator)
  199. string += "%s%s" % (map.get_name(), separator)
  200. if type == "stvds":
  201. string += "%s%s" % (map.get_layer(), separator)
  202. string += "%s%s" % (map.get_mapset(), separator)
  203. string += "%s%s" % (start, separator)
  204. string += "%s%s" % (end, separator)
  205. string += "%s%s" % (delta, separator)
  206. string += "%s" % (delta_first)
  207. if outpath:
  208. outfile.write("{st}\n".format(st=string))
  209. else:
  210. print(string)
  211. else:
  212. # In comma separated mode only map ids are needed
  213. if method == "comma":
  214. if columns not in ["id", "name"]:
  215. columns = "id"
  216. rows = sp.get_registered_maps(columns, where, order, dbif)
  217. if not rows:
  218. dbif.close()
  219. err = "Space time %(sp)s dataset <%(i)s> is empty"
  220. if where:
  221. err += " or where condition is wrong"
  222. gscript.fatal(
  223. _(err)
  224. % {"sp": sp.get_new_map_instance(None).get_type(), "i": sp.get_id()}
  225. )
  226. if rows:
  227. if method == "comma":
  228. string = ""
  229. count = 0
  230. for row in rows:
  231. if count == 0:
  232. string += row[columns]
  233. else:
  234. string += ",%s" % row[columns]
  235. count += 1
  236. if outpath:
  237. outfile.write("{st}\n".format(st=string))
  238. else:
  239. print(string)
  240. elif method == "cols":
  241. # Print the column names if requested
  242. if no_header is False:
  243. output = ""
  244. count = 0
  245. collist = columns.split(",")
  246. for key in collist:
  247. if count > 0:
  248. output += separator + str(key)
  249. else:
  250. output += str(key)
  251. count += 1
  252. if outpath:
  253. outfile.write("{st}\n".format(st=output))
  254. else:
  255. print(output)
  256. for row in rows:
  257. output = ""
  258. count = 0
  259. for col in row:
  260. if count > 0:
  261. output += separator + str(col)
  262. else:
  263. output += str(col)
  264. count += 1
  265. if outpath:
  266. outfile.write("{st}\n".format(st=output))
  267. else:
  268. print(output)
  269. if outpath:
  270. outfile.close()
  271. if connection_state_changed:
  272. dbif.close()
  273. ###############################################################################
  274. if __name__ == "__main__":
  275. import doctest
  276. doctest.testmod()