def get_grid_points(user_axis, crs_axis): """ Computes the number of grid points corresponding to the axis. :param UserAxis user_axis: the axis as given by the user :param CrsAxis crs_axis: the corresponding crs axis :return: int gridPoints """ # if no interval on the axis (slice), then 1 single grid point if user_axis.interval.high is None: return 1 if isinstance(user_axis, RegularUserAxis): # number of geo-intervals over resolution if user_axis.type != UserAxisType.DATE: # number_of_grid_points = (geo_max - geo_min) / resolution grid_points = abs( (decimal.Decimal(str(user_axis.interval.high)) - decimal.Decimal(str(user_axis.interval.low))) / decimal.Decimal(str(user_axis.resolution))) # The resolution in ingredient file can have big factor to the calculation, so must take care if abs( decimal.Decimal(str(grid_points), ROUND_UP) - grid_points) > HighPixelAjuster.THRESHOLD: log.warning( "The computed number of grid points is not an integer for axis " + user_axis.name + ". This usually indicates that the resolution is not correct." ) grid_points = HighPixelAjuster.adjust_high(grid_points) # Negative axis (e.g: latitude) min <--- max if user_axis.resolution < 0: return int(math.floor(grid_points)) else: # Positive axis (e.g: longitude) min ---> max return int(math.ceil(grid_points)) else: time_difference = user_axis.interval.high - user_axis.interval.low # AS time always point to future (min --> max) if crs_axis.is_time_day_axis(): # days ((seconds / 86400) / resolution) grid_points = abs( (decimal.Decimal(str(time_difference)) / decimal.Decimal(DateTimeUtil.DAY_IN_SECONDS)) / decimal.Decimal(str(user_axis.resolution))) grid_points = HighPixelAjuster.adjust_high(grid_points) return int(math.ceil(grid_points)) else: # seconds (seconds / resolution) grid_points = abs( (decimal.Decimal(str(time_difference)) / decimal.Decimal(str(user_axis.resolution)))) grid_points = HighPixelAjuster.adjust_high(grid_points) return int(math.ceil(grid_points)) else: # number of direct positions (i.e: irregular axis with coefficients [0, 1, 3, 5, 8, 15]) return len(user_axis.directPositions)
def get_origin(user_axis, crs_axis): """ Computes the origin for the user_axis by shifting the limit with half resolution. :param UserAxis user_axis: the axis as given by the user. :return: float origin """ # if axis is datetime then just return the low if user_axis.type == UserAxisType.DATE: return PointPixelAdjuster.get_origin_for_time_axis( user_axis, crs_axis) if isinstance(user_axis, RegularUserAxis): if user_axis.resolution > 0 or user_axis.interval.high is None: # axis goes from low to high, so origin is lowest, with half a pixel shift # min (min + 0.5*resolution) --> max return decimal.Decimal(str(user_axis.interval.low))\ + decimal.Decimal(0.5) * decimal.Decimal(str(user_axis.resolution)) else: # axis goes from high to low, so origin is highest, with half pixel shift (resolution is negative) # min <---- (max + 0.5*resolution) max return decimal.Decimal(str(user_axis.interval.high))\ + decimal.Decimal(0.5) * decimal.Decimal(str(user_axis.resolution)) else: # irregular axis, the same but without shift # normally, irregular axis points from min ---> max, so origin is min (e.g: time ansidate, unixtime) if user_axis.resolution > 0 or user_axis.interval.high is None: return user_axis.interval.low else: return user_axis.interval.high
def adjust_axis_bounds_to_continuous_space(user_axis, crs_axis): """ Moves pixels inside the user_axis from the middle of the interval to the bounds of the interval. :param UserAxis user_axis: the axis given by the user :param crs_axis is the axis from SECORE (e.g: 4326, Ansidate, UnixTime) :return: None """ if user_axis.type == UserAxisType.DATE: PointPixelAdjuster.adjust_axis_bounds_for_time_axis(user_axis, crs_axis) else: # if low < high, adjust it if user_axis.interval.high is not None and user_axis.interval.low > user_axis.interval.high: user_axis.interval.low, user_axis.interval.high = user_axis.interval.high, user_axis.interval.low if isinstance(user_axis, RegularUserAxis): user_axis.interval.low = decimal.Decimal(str(user_axis.interval.low)) \ - decimal.Decimal(str(0.5)) * abs(decimal.Decimal(str(user_axis.resolution))) if user_axis.interval.high: user_axis.interval.high = decimal.Decimal(str(user_axis.interval.high)) \ + decimal.Decimal(str(0.5)) * abs(decimal.Decimal(str(user_axis.resolution)))
def adjust_axis_bounds_for_time_axis(user_axis, crs_axis): # convert to timestamp and change the axis type user_axis.interval.low = arrow.get( user_axis.interval.low).float_timestamp if user_axis.interval.high: user_axis.interval.high = arrow.get( user_axis.interval.high).float_timestamp # if low < high, adjust it if user_axis.interval.high is not None and user_axis.interval.low > user_axis.interval.high: user_axis.interval.low, user_axis.interval.high = user_axis.interval.high, user_axis.interval.low # The formula for all regular axes is when "pixelIsPoint": # min = min - 0.5 * resolution # max = max + 0.5 * resolution if isinstance(user_axis, RegularUserAxis): # if axis is time axis if crs_axis.is_time_day_axis(): user_axis.interval.low = decimal.Decimal(str(user_axis.interval.low)) \ - decimal.Decimal(0.5) * decimal.Decimal(str(abs(user_axis.resolution))) * DateTimeUtil.DAY_IN_SECONDS if user_axis.interval.high: user_axis.interval.high = decimal.Decimal(str(user_axis.interval.high)) \ + decimal.Decimal(0.5) * decimal.Decimal(str(abs(user_axis.resolution))) * DateTimeUtil.DAY_IN_SECONDS else: # if axis is normal axis (lat, lon, index1d,...) user_axis.interval.low = decimal.Decimal(str(user_axis.interval.low)) \ - decimal.Decimal(0.5) * decimal.Decimal(str(abs(user_axis.resolution))) if user_axis.interval.high: user_axis.interval.high = decimal.Decimal(str(user_axis.interval.high)) \ + decimal.Decimal(0.5) * decimal.Decimal(str(abs(user_axis.resolution)))
def get_origin_for_time_axis(user_axis, crs_axis): user_axis.interval.low = arrow.get( user_axis.interval.low).float_timestamp if user_axis.interval.high: user_axis.interval.high = arrow.get( user_axis.interval.high).float_timestamp if isinstance(user_axis, RegularUserAxis): # ansidate, need to calculate with day in seconds if crs_axis.is_time_day_axis: if user_axis.resolution > 0 or user_axis.interval.high is None: # axis goes from low to high, so origin is lowest, with half a pixel shift return decimal.Decimal(str(user_axis.interval.low))\ + decimal.Decimal(0.5) * decimal.Decimal(str(user_axis.resolution)) * DateTimeUtil.DAY_IN_SECONDS else: # axis goes from high to low, so origin is highest, with half pixel shift (resolution is negative) return decimal.Decimal(str(user_axis.interval.high))\ + decimal.Decimal(0.5) * decimal.Decimal(str(user_axis.resolution)) * DateTimeUtil.DAY_IN_SECONDS else: # unix time, already in seconds if user_axis.resolution > 0 or user_axis.interval.high is None: # axis goes from low to high, so origin is lowest, with half a pixel shift return decimal.Decimal(str(user_axis.interval.low))\ + decimal.Decimal(0.5) * decimal.Decimal(str(user_axis.resolution)) else: # axis goes from high to low, so origin is highest, with half pixel shift (resolution is negative) return decimal.Decimal(str(user_axis.interval.high))\ + decimal.Decimal(0.5) * decimal.Decimal(str(user_axis.resolution)) else: # irregular axis, the same but without shift if user_axis.resolution > 0 or user_axis.interval.high is None: return user_axis.interval.low else: return user_axis.interval.high