"""!@package grass.temporal @brief GRASS Python scripting module (temporal GIS functions) Temporal GIS related functions to be used in temporal GIS Python library package. Usage: @code import grass.temporal as tgis tgis.compute_relative_time_granularity(maps) ... @endcode (C) 2008-2011 by the GRASS Development Team This program is free software under the GNU General Public License (>=v2). Read the file COPYING that comes with GRASS for details. @author Soeren Gebbert """ from abstract_dataset import * from datetime_math import * ############################################################################### def compute_relative_time_granularity(maps): """!Compute the relative time granularity Attention: The computation of the granularity is only correct in case of not overlapping intervals. Hence a correct temporal topology is required for computation. @param maps: a ordered by start_time list of map objects """ # The interval time must be scaled to days resolution granularity = None delta = [] # First we compute the timedelta of the intervals for map in maps: start, end = map.get_valid_time() if start and end: t = abs(end - start) delta.append(int(t)) # Compute the timedelta of the gaps for i in range(len(maps)): if i < len(maps) - 1: relation = maps[i + 1].temporal_relation(maps[i]) if relation == "after": start1, end1 = maps[i].get_valid_time() start2, end2 = maps[i + 1].get_valid_time() # Gaps are between intervals, intervals and # points, points and points if end1 and start2: t = abs(end1 - start2) delta.append(int(t)) if not end1 and start2: t = abs(start1 - start2) delta.append(int(t)) delta.sort() ulist = list(set(delta)) if len(ulist) > 1: # Find greatest common divisor granularity = gcd_list(ulist) elif len(ulist) == 1: granularity = ulist[0] else: granularity = 0 return granularity ############################################################################### def compute_absolute_time_granularity(maps): """!Compute the absolute time granularity Attention: The computation of the granularity is only correct in case of not overlapping intervals. Hence a correct temporal topology is required for computation. @param maps: a ordered by start_time list of map objects """ has_seconds = False has_minutes = False has_hours = False has_days = False has_months = False has_years = False use_seconds = False use_minutes = False use_hours = False use_days = False use_months = False use_years = False delta = [] datetime_delta = [] # First we compute the timedelta of the intervals for map in maps: start, end = map.get_valid_time() if start and end: delta.append(end - start) datetime_delta.append(compute_datetime_delta(start, end)) # Compute the timedelta of the gaps for i in range(len(maps)): if i < len(maps) - 1: relation = maps[i + 1].temporal_relation(maps[i]) if relation == "after": start1, end1 = maps[i].get_valid_time() start2, end2 = maps[i + 1].get_valid_time() # Gaps are between intervals, intervals and # points, points and points if end1 and start2: delta.append(end1 - start2) datetime_delta.append(compute_datetime_delta(end1, start2)) if not end1 and start2: delta.append(start2 - start1) datetime_delta.append(compute_datetime_delta( start1, start2)) # Check what changed dlist = [] for d in datetime_delta: if "second" in d and d["second"] > 0: has_seconds = True if "minute" in d and d["minute"] > 0: has_minutes = True if "hour" in d and d["hour"] > 0: has_hours = True if "day" in d and d["day"] > 0: has_days = True if "month" in d and d["month"] > 0: has_months = True if "year" in d and d["year"] > 0: has_years = True # Create a list with a single time unit only if has_seconds: for d in datetime_delta: if "second" in d: dlist.append(d["second"]) elif "minute" in d: dlist.append(d["minute"] * 60) elif "hour" in d: dlist.append(d["hour"] * 3600) elif "day" in d: dlist.append(d["day"] * 24 * 3600) else: dlist.append(d["max_days"] * 24 * 3600) use_seconds = True elif has_minutes: for d in datetime_delta: if "minute" in d: dlist.append(d["minute"]) elif "hour" in d: dlist.append(d["hour"] * 60) elif "day" in d: dlist.append(d["day"] * 24 * 60) else: dlist.append(d["max_days"] * 24 * 60) use_minutes = True elif has_hours: for d in datetime_delta: if "hour" in d: dlist.append(d["hour"]) elif "day" in d: dlist.append(d["day"] * 24) else: dlist.append(d["max_days"] * 24) use_hours = True elif has_days: for d in datetime_delta: if "day" in d: dlist.append(d["day"]) else: dlist.append(d["max_days"]) use_days = True elif has_months: for d in datetime_delta: if "month" in d: dlist.append(d["month"]) elif "year" in d: dlist.append(d["year"] * 12) use_months = True elif has_years: for d in datetime_delta: if "year" in d: dlist.append(d["year"]) use_years = True dlist.sort() ulist = list(set(dlist)) if len(ulist) == 0: return None if len(ulist) > 1: # Find greatest common divisor granularity = gcd_list(ulist) else: granularity = ulist[0] if use_seconds: return "%i seconds" % granularity elif use_minutes: return "%i minutes" % granularity elif use_hours: return "%i hours" % granularity elif use_days: return "%i days" % granularity elif use_months: return "%i months" % granularity elif use_years: return "%i years" % granularity return None ############################################################################### # http://akiscode.com/articles/gcd_of_a_list.shtml # Copyright (c) 2010 Stephen Akiki # MIT License (Means you can do whatever you want with this) # See http://www.opensource.org/licenses/mit-license.php # Error Codes: # None def gcd(a, b): """!The Euclidean Algorithm """ a = abs(a) b = abs(b) while a: a, b = b % a, a return b ############################################################################### def gcd_list(list): """!Finds the GCD of numbers in a list. Input: List of numbers you want to find the GCD of E.g. [8, 24, 12] Returns: GCD of all numbers """ return reduce(gcd, list)