def time(self, val): if viscid.is_datetime_like(val): val = viscid.as_timedelta(self.basetime - viscid.as_datetime64(val)) val = val.total_seconds() elif viscid.is_timedelta_like(val, conservative=True): val = viscid.as_timedelta(val).total_seconds() elif val is not None: self.set_info('time', float(val))
def convert_timelike(value): if value in (None, ''): return None elif viscid.is_datetime_like(value, conservative=True): return viscid.as_datetime64(value) elif viscid.is_timedelta_like(value, conservative=True): return viscid.as_timedelta64(value) else: return value
def as_floating_t(self, t, none_passthrough=False): t_as_s = None try: t = vutil.str_to_value(t) if viscid.is_timedelta_like(t, conservative=True): t_as_s = viscid.as_timedelta(t).total_seconds() elif viscid.is_datetime_like(t, conservative=True): delta_t = viscid.as_datetime64(t) - self.basetime t_as_s = viscid.as_timedelta(delta_t).total_seconds() elif not isinstance(t, (int, np.integer, type(None))): t_as_s = float(t) except AttributeError: if t is None: if none_passthrough: pass else: t = 0.0 else: t_as_s = float(t) return t_as_s
def extract_index(arr, start=None, stop=None, step=None, endpoint=True, tol=100): """Get integer indices for slice parts If start, stop, or step are strings, they are either cast to integers or used for a float lookup if they have a trailing 'f'. An example float lookup is:: >>> [0.1, 0.2, 0.3, 0.4, 0.5, 0.6]['0.2f:0.6f:2'] [0.2, 0.4, 0.6] The rules for float lookup endpoints are: - The slice will never include an element whose value in arr is < start (or > if the slice is backward) - The slice will never include an element whose value in arr is > stop (or < if the slice is backward) - !! The slice WILL INCLUDE stop if you don't change endpoint. This is different from normal slicing, but it's more natural when specifying a slice as a float. To this end, an epsilon tolerance can be given to determine what's close enough. - TODO: implement floating point steps, this is tricky since arr need not be uniformly spaced, so step is ambiguous in this case Args: arr (ndarray): filled with floats to do the lookup start (None, int, str): like slice().start stop (None, int, str): like slice().stop step (None, int): like slice().step endpoint (bool): iff True then include stop in the slice. Set to False to get python slicing symantics when it comes to excluding stop, but fair warning, python symantics feel awkward here. Consider the case [0.1, 0.2, 0.3][:0.25]. If you think this should include 0.2, then leave keep endpoint=True. tol (int): number of machine epsilons to consider "close enough" Returns: start, stop, step after floating point vals have been converted to integers """ float_err_msg = ("Slicing by floats is no longer supported. If you " "want to slice by location, suffix the value with " "'f', as in 'x = 0f'.") arr = np.asarray(arr) try: epsilon = tol * np.finfo(arr.dtype).eps except ValueError: # array is probably of type numpy.int* epsilon = 0.01 _step = 1 if step is None else int(step) epsilon_step = epsilon if _step > 0 else -epsilon start = convert_timelike(start) stop = convert_timelike(stop) start = convert_deprecated_floats(start, "start") stop = convert_deprecated_floats(stop, "stop") # print("?!? |{0}| |{1}|".format(start, stop)) startstop = [start, stop] eps_sign = [1, -1] # if start or stop is not an int, try to make it one for i in range(2): byval = None s = startstop[i] _epsilon_step = epsilon_step if viscid.is_datetime_like(s, conservative=True): byval = s.astype(arr.dtype) _epsilon_step = 0 elif viscid.is_timedelta_like(s, conservative=True): byval = s.astype(arr.dtype) _epsilon_step = 0 else: try: s = s.strip() if len(s) == 0: startstop[i] = None elif s[-1] == 'f': byval = float(s[:-1]) except AttributeError: pass if byval is not None: if _epsilon_step: diff = arr - byval + (eps_sign[i] * _epsilon_step) else: diff = arr - byval zero = np.array([0]).astype(diff.dtype)[0] # FIXME: there is far too much decision making here if i == 0: # start if _step > 0: diff = np.ma.masked_less(diff, zero) else: diff = np.ma.masked_greater(diff, zero) if np.ma.count(diff) == 0: # start value is past the wrong end of the array if _step > 0: startstop[i] = len(arr) else: # start = -len(arr) - 1 # having a value < -len(arr) won't play # nice with make_fwd_slice, but in this # case, the slice will have no data, so... return 0, 0, step else: startstop[i] = int(np.argmin(np.abs(diff))) else: # stop if _step > 0: diff = np.ma.masked_greater(diff, zero) if np.ma.count(diff) == 0: # stop value is past the wong end of the array startstop[i] = 0 else: startstop[i] = int(np.argmin(np.abs(diff))) if endpoint: startstop[i] += 1 else: diff = np.ma.masked_less(diff, zero) if np.ma.count(diff) == 0: # stop value is past the wrong end of the array startstop[i] = len(arr) else: startstop[i] = int(np.argmin(np.abs(diff))) if endpoint: if startstop[i] > 0: startstop[i] -= 1 else: # 0 - 1 == -1 which would wrap to the end of # of the array... instead, just make it None startstop[i] = None start, stop = startstop # turn start, stop, step into indices sss = [start, stop, step] for i, s in enumerate(sss): if s is None: pass elif isinstance(s, string_types): sss[i] = int(s) else: sss[i] = s.__index__() return sss