temporal_granularity.py 7.6 KB

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