temporal_granularity.py 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255
  1. """!@package grass.temporal
  2. @brief GRASS Python scripting module (temporal GIS functions)
  3. Temporal GIS related functions to be used in temporal GIS Python library package.
  4. Usage:
  5. @code
  6. import grass.temporal as tgis
  7. tgis.compute_relative_time_granularity(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 abstract_dataset import *
  17. from datetime_math import *
  18. ###############################################################################
  19. def compute_relative_time_granularity(maps):
  20. """!Compute the relative time granularity
  21. Attention: The computation of the granularity
  22. is only correct in case of not overlapping intervals.
  23. Hence a correct temporal topology is required for computation.
  24. @param maps: a ordered by start_time list of map objects
  25. """
  26. # The interval time must be scaled to days resolution
  27. granularity = None
  28. delta = []
  29. # First we compute the timedelta of the intervals
  30. for map in maps:
  31. start, end = map.get_valid_time()
  32. if start and end:
  33. t = abs(end - start)
  34. delta.append(int(t))
  35. # Compute the timedelta of the gaps
  36. for i in range(len(maps)):
  37. if i < len(maps) - 1:
  38. relation = maps[i + 1].temporal_relation(maps[i])
  39. if relation == "after":
  40. start1, end1 = maps[i].get_valid_time()
  41. start2, end2 = maps[i + 1].get_valid_time()
  42. # Gaps are between intervals, intervals and
  43. # points, points and points
  44. if end1 and start2:
  45. t = abs(end1 - start2)
  46. delta.append(int(t))
  47. if not end1 and start2:
  48. t = abs(start1 - start2)
  49. delta.append(int(t))
  50. delta.sort()
  51. ulist = list(set(delta))
  52. if len(ulist) > 1:
  53. # Find greatest common divisor
  54. granularity = gcd_list(ulist)
  55. elif len(ulist) == 1:
  56. granularity = ulist[0]
  57. else:
  58. granularity = 0
  59. return granularity
  60. ###############################################################################
  61. def compute_absolute_time_granularity(maps):
  62. """!Compute the absolute time granularity
  63. Attention: The computation of the granularity
  64. is only correct in case of not overlapping intervals.
  65. Hence a correct temporal topology is required for computation.
  66. @param maps: a ordered by start_time list of map objects
  67. """
  68. has_seconds = False
  69. has_minutes = False
  70. has_hours = False
  71. has_days = False
  72. has_months = False
  73. has_years = False
  74. use_seconds = False
  75. use_minutes = False
  76. use_hours = False
  77. use_days = False
  78. use_months = False
  79. use_years = False
  80. delta = []
  81. datetime_delta = []
  82. # First we compute the timedelta of the intervals
  83. for map in maps:
  84. start, end = map.get_valid_time()
  85. if start and end:
  86. delta.append(end - start)
  87. datetime_delta.append(compute_datetime_delta(start, end))
  88. # Compute the timedelta of the gaps
  89. for i in range(len(maps)):
  90. if i < len(maps) - 1:
  91. relation = maps[i + 1].temporal_relation(maps[i])
  92. if relation == "after":
  93. start1, end1 = maps[i].get_valid_time()
  94. start2, end2 = maps[i + 1].get_valid_time()
  95. # Gaps are between intervals, intervals and
  96. # points, points and points
  97. if end1 and start2:
  98. delta.append(end1 - start2)
  99. datetime_delta.append(compute_datetime_delta(end1, start2))
  100. if not end1 and start2:
  101. delta.append(start2 - start1)
  102. datetime_delta.append(compute_datetime_delta(
  103. start1, start2))
  104. # Check what changed
  105. dlist = []
  106. for d in datetime_delta:
  107. if "second" in d and d["second"] > 0:
  108. has_seconds = True
  109. if "minute" in d and d["minute"] > 0:
  110. has_minutes = True
  111. if "hour" in d and d["hour"] > 0:
  112. has_hours = True
  113. if "day" in d and d["day"] > 0:
  114. has_days = True
  115. if "month" in d and d["month"] > 0:
  116. has_months = True
  117. if "year" in d and d["year"] > 0:
  118. has_years = True
  119. # Create a list with a single time unit only
  120. if has_seconds:
  121. for d in datetime_delta:
  122. if "second" in d:
  123. dlist.append(d["second"])
  124. elif "minute" in d:
  125. dlist.append(d["minute"] * 60)
  126. elif "hour" in d:
  127. dlist.append(d["hour"] * 3600)
  128. elif "day" in d:
  129. dlist.append(d["day"] * 24 * 3600)
  130. else:
  131. dlist.append(d["max_days"] * 24 * 3600)
  132. use_seconds = True
  133. elif has_minutes:
  134. for d in datetime_delta:
  135. if "minute" in d:
  136. dlist.append(d["minute"])
  137. elif "hour" in d:
  138. dlist.append(d["hour"] * 60)
  139. elif "day" in d:
  140. dlist.append(d["day"] * 24 * 60)
  141. else:
  142. dlist.append(d["max_days"] * 24 * 60)
  143. use_minutes = True
  144. elif has_hours:
  145. for d in datetime_delta:
  146. if "hour" in d:
  147. dlist.append(d["hour"])
  148. elif "day" in d:
  149. dlist.append(d["day"] * 24)
  150. else:
  151. dlist.append(d["max_days"] * 24)
  152. use_hours = True
  153. elif has_days:
  154. for d in datetime_delta:
  155. if "day" in d:
  156. dlist.append(d["day"])
  157. else:
  158. dlist.append(d["max_days"])
  159. use_days = True
  160. elif has_months:
  161. for d in datetime_delta:
  162. if "month" in d:
  163. dlist.append(d["month"])
  164. elif "year" in d:
  165. dlist.append(d["year"] * 12)
  166. use_months = True
  167. elif has_years:
  168. for d in datetime_delta:
  169. if "year" in d:
  170. dlist.append(d["year"])
  171. use_years = True
  172. dlist.sort()
  173. ulist = list(set(dlist))
  174. if len(ulist) == 0:
  175. return None
  176. if len(ulist) > 1:
  177. # Find greatest common divisor
  178. granularity = gcd_list(ulist)
  179. else:
  180. granularity = ulist[0]
  181. if use_seconds:
  182. return "%i seconds" % granularity
  183. elif use_minutes:
  184. return "%i minutes" % granularity
  185. elif use_hours:
  186. return "%i hours" % granularity
  187. elif use_days:
  188. return "%i days" % granularity
  189. elif use_months:
  190. return "%i months" % granularity
  191. elif use_years:
  192. return "%i years" % granularity
  193. return None
  194. ###############################################################################
  195. # http://akiscode.com/articles/gcd_of_a_list.shtml
  196. # Copyright (c) 2010 Stephen Akiki
  197. # MIT License (Means you can do whatever you want with this)
  198. # See http://www.opensource.org/licenses/mit-license.php
  199. # Error Codes:
  200. # None
  201. def gcd(a, b):
  202. """!The Euclidean Algorithm """
  203. a = abs(a)
  204. b = abs(b)
  205. while a:
  206. a, b = b % a, a
  207. return b
  208. ###############################################################################
  209. def gcd_list(list):
  210. """!Finds the GCD of numbers in a list.
  211. Input: List of numbers you want to find the GCD of
  212. E.g. [8, 24, 12]
  213. Returns: GCD of all numbers
  214. """
  215. return reduce(gcd, list)