def get_seconds(dt1: numpy.datetime64, dt2: numpy.datetime64, precision: str='us') -> float: """ The number of seconds between two numpy.datetime64 elements. Parameters ---------- dt1 : numpy.datetime64 dt2 : numpy.datetime64 precision : str one of 's', 'ms', 'us', or 'ns'. Returns ------- float the number of seconds between dt2 and dt1 (i.e. dt1 - dt2). """ if precision == 's': scale = 1 elif precision == 'ms': scale = 1e-3 elif precision == 'us': scale = 1e-6 elif precision == 'ns': scale = 1e-9 else: raise ValueError('unrecognized precision {}'.format(precision)) dtype = 'datetime64[{}]'.format(precision) tdt1 = dt1.astype(dtype) tdt2 = dt2.astype(dtype) return float((tdt1.astype('int64') - tdt2.astype('int64'))*scale)
def load_dataset(self, first_date: np.datetime64, last_date: np.datetime64) -> xr.Dataset: """Load SSH from NATL60 model. Args: first_date (np.datetime64): first date to load last_date (np.datetime64): last date to load Returns: xr.Dataset: SSH dataset """ first_date = self._shift_date(first_date.astype("datetime64[ns]"), -1, self.time_delta) last_date = self._shift_date(last_date.astype("datetime64[ns]"), 1, self.time_delta) LOGGER.debug("Loading dataset from %s to %s", first_date, last_date) if first_date < self.dataset.time[ 0] or last_date > self.dataset.time[-1]: raise IndexError( f"period [{first_date}, {last_date}] is out of range: " f"[{self.dataset.time[0]}, {self.dataset.time[-1]}]") # Mask for selecting data covering the time period provided. mask = (self.dataset.time.data >= first_date) & (self.dataset.time.data <= last_date) return self.dataset.isel(time=np.argwhere(mask).squeeze())
def select_netcdf_files(self, first_date: np.datetime64, last_date: np.datetime64) -> np.ndarray: """Selects the netcdf files that cover the time period. Args: first_date (numpy.datetime64): first date of the time period last_date (numpy.datetime64): last date of the time period Returns: numpy.ndarray: Array containing the paths to the netcdf files that cover the time period. """ first_date = self._shift_date(first_date.astype("datetime64[ns]"), -1, self.time_delta) last_date = self._shift_date(last_date.astype("datetime64[ns]"), 1, self.time_delta) if first_date < self.time_series["date"][ 0] or last_date > self.time_series["date"][-1]: raise IndexError( f"period [{first_date}, {last_date}] is out of range: " f"[{self.time_series['date'][0]}, " f"{self.time_series['date'][-1]}]") selected = np.logical_and(self.time_series["date"] >= first_date, self.time_series["date"] < last_date) return selected
def _compute_interpolation_weight( d: np.datetime64, d0: np.datetime64, d1: np.datetime64 ) -> float: # pylint: disable=invalid-name d_as_uint = d.astype(np.uint64) d0_as_uint = d0.astype(np.uint64) d1_as_uint = d1.astype(np.uint64) return float(d_as_uint - d0_as_uint) / float(d1_as_uint - d0_as_uint)
def file_path(first_date: np.datetime64, last_date: np.datetime64, cycle_number: int, pass_number: int, parameters: settings.Parameters, nadir: bool = False) -> Optional[str]: """Get the absolute path of the file to be created. Args: first_date (numpy.datetime64): Date of the first simulated measurement. last_date (numpy.datetime64): Date of the last simulated measurement. cycle_number (int): Cycle number of the file to be created. pass_number (int): Pass number of the file to be created. parameters (settings.Parameters): Simulation parameters. nadir (bool, optional): True if the product to be created contains the nadir measurements, false if it is a product containing the swath measurements. Returns: str, optional: The path to the file to be created or None if the file already exists """ first_datetime: datetime.datetime = first_date.astype( datetime.datetime) # type: ignore last_datetime: datetime.datetime = last_date.astype( datetime.datetime) # type: ignore product_type = "nadir" if nadir else "karin" dirname = os.path.join(parameters.working_directory, product_type, first_datetime.strftime("%Y")) os.makedirs(dirname, exist_ok=True) if nadir: filename = (f"SWOT_GPR_2PTP{cycle_number:03d}_{pass_number:03d}_" f"{first_datetime:%Y%m%d}_{first_datetime:%H%M%S}_" f"{last_datetime:%Y%m%d}_{last_datetime:%H%M%S}.nc") else: product_type = "".join( [item.capitalize() for item in parameters.product_type.split("_")]) filename = (f"SWOT_L2_LR_SSH_{product_type}_" f"{cycle_number:03d}_{pass_number:03d}_" f"{first_datetime:%Y%m%dT%H%M%S}_" f"{last_datetime:%Y%m%dT%H%M%S}_" "DG10_01.nc") result = os.path.join(dirname, filename) # If the product has already been produced, the generation of this # half orbit is disabled. if os.path.exists(result): LOGGER.debug("%s already generated: %d/%d", "nadir" if nadir else "swath", cycle_number, pass_number) return None return result
def getHistoricDates(self, t: np.datetime64): diff = t.astype('datetime64[s]') - self.newestTimestamp.astype( 'datetime64[s]') if diff >= np.timedelta64(0, 's'): days = self.indays(diff) days = days % self.diffdays t = self.oldestTimestamp + np.timedelta64(days + 1, 'D') return t
def flat_fill(periods: int, start_date: np.datetime64, value: float, dtype=np.float32): price_strip = np.repeat(value, periods).astype(dtype) start_date = start_date.astype("datetime64[M]") end_date = start_date + np.timedelta64(periods, "M") date_strip = np.arange(start_date, end_date).astype("datetime64[D]") pricing = np.array([date_strip, price_strip]) return pricing
def create_time_points(start_time: np.datetime64, period_length: np.timedelta64, points_num: int): end_time_output = start_time + (points_num - 1) * period_length return np.linspace( start_time.astype("datetime64[s]").astype(float), end_time_output.astype("datetime64[s]").astype(float), points_num, dtype="datetime64[s]", )
def minute(datetime64: np.datetime64) -> np.generic: """Get minute from NumPy datetime64 value/array. :param datetime64: Value/array to get minute(s) from. :return: Minute or array of minutes from `datetime64`. """ return datetime64.astype("datetime64[m]").astype(int) % 60
def hour(datetime64: np.datetime64) -> np.generic: """Get hour from NumPy datetime64 value/array. :param datetime64: Value/array to get hour(s) from. :return: Hour or array of hours from `datetime64`. """ return datetime64.astype("datetime64[h]").astype(int) % 24
def microsecond(datetime64: np.datetime64) -> np.generic: """Get microsecond from NumPy datetime64 value/array. :param datetime64: Value/array to get microsecond(s) from. :return: Microsecond or array of microseconds from `datetime64`. """ return datetime64.astype("datetime64[us]").astype(int) % 1000000
def year(datetime64: np.datetime64) -> np.generic: """Get year from NumPy datetime64 value/array. :param datetime64: Value/array to get year number(s) from. :return: Year or array of years from `datetime64`. """ # based on: https://stackoverflow.com/a/26895491 return datetime64.astype("datetime64[Y]").astype(int) + 1970
def month(datetime64: np.datetime64) -> np.generic: """Get month from NumPy datetime64 value/array. :param datetime64: Value/array to get month number(s) from. :return: Month or array of months from `datetime64`. """ # based on: https://stackoverflow.com/a/26895491 return datetime64.astype("datetime64[M]").astype(int) % 12 + 1
def day(datetime64: np.datetime64) -> np.generic: """Get day of month from NumPy datetime64 value/array. :param datetime64: Value/array to get day(s) of month from. :return: Day of month or array of days of month from `datetime64`. """ # based on: https://stackoverflow.com/a/26895491 return (datetime64.astype("datetime64[D]") - datetime64.astype("datetime64[M]")).astype(int) + 1
def ymdhmsus( datetime64: np.datetime64, ) -> Tuple[np.generic, np.generic, np.generic, np.generic, np.generic, np.generic, np.generic]: """Get time components from NumPy datetime64 value/array. :param datetime64: Value/array to get time components from. :return: A tuple with the following: * Year or array of years from `datetime64`. * Month or array of months from `datetime64`. * Day of month or array of days of month from `datetime64`. * Hour or array of hours from `datetime64`. * Minute or array of minutes from `datetime64`. * Second or array of seconds from `datetime64`. * Microsecond or array of microseconds from `datetime64`. """ # based on: https://stackoverflow.com/a/26895491 year = datetime64.astype("datetime64[Y]").astype(int) + 1970 month_ = datetime64.astype("datetime64[M]") month = month_.astype(int) % 12 + 1 day = (datetime64.astype("datetime64[D]") - month_).astype(int) + 1 hour = datetime64.astype("datetime64[h]").astype(int) % 24 minute = datetime64.astype("datetime64[m]").astype(int) % 60 second = datetime64.astype("datetime64[s]").astype(int) % 60 microsecond = datetime64.astype("datetime64[us]").astype(int) % 1000000 return year, month, day, hour, minute, second, microsecond
def file_path(first_date: np.datetime64, last_date: np.datetime64, cycle_number: int, pass_number: int, parameters: settings.Parameters, nadir: bool = False) -> str: """Get the absolute path of the file to be created. Args: first_date (numpy.datetime64): Date of the first simulated measurement. last_date (numpy.datetime64): Date of the last simulated measurement. cycle_number (int): Cycle number of the file to be created. pass_number (int): Pass number of the file to be created. parameters (settings.Parameters): Simulation parameters. nadir (bool, optional): True if the product to be created contains the nadir measurements, false if it is a product containing the swath measurements. Returns: str: The path to the file to be created. """ first_date = first_date.astype(datetime.datetime) last_date = last_date.astype(datetime.datetime) product_type = "nadir" if nadir else "karin" dirname = os.path.join(parameters.working_directory, product_type, first_date.strftime("%Y")) os.makedirs(dirname, exist_ok=True) if nadir: filename = (f"SWOT_GPN_2P1P{cycle_number:03d}_{pass_number:03d}_" f"{first_date:%Y%m%d}_{first_date:%H%M%S}_" f"{last_date:%Y%m%d}_{last_date:%H%M%S}.nc") else: product_type = "".join( [item.capitalize() for item in parameters.product_type.split("_")]) filename = (f"SWOT_L2_LR_SSH_{product_type}_" f"{cycle_number:03d}_{pass_number:03d}_" f"{first_date:%Y%m%dT%H%M%S}_{last_date:%Y%m%dT%H%M%S}_" "DG10_01.nc") return os.path.join(dirname, filename)
def create_time_points( # TODO: replace by simpler function start_time: np.datetime64, period_length: np.timedelta64, points_num: int, timeseries_type: Union[ParameterType, str], ) -> np.ndarray: """ Create time points for an equi-distant time series. Parameters ---------- start_time First time point of the timeseries period_length Period length points_num Length of timeseries timeseries_type Timeseries type Returns ------- :class:`np.ndarray` of :class:`np.datetime64` Array of the timeseries time points """ timeseries_type = ParameterType.from_timeseries_type(timeseries_type) points_num_output = ( (points_num + 1) # +1 for averages as we need to give the full last interval if timeseries_type == ParameterType.AVERAGE_TIMESERIES else points_num) end_time_output = start_time + (points_num_output - 1) * period_length return np.linspace( start_time.astype("datetime64[s]").astype(float), end_time_output.astype("datetime64[s]").astype(float), points_num_output, dtype="datetime64[s]", )
def _get_datetime(time: np.datetime64) -> date: return datetime.strptime(time.astype(str)[:10], "%Y-%m-%d").date()
def offset_from_center(v: numpy.datetime64): return p.datetime + timedelta(microseconds=v.astype(float) * 1_000_000.0)
def _grid_date(self, date: np.datetime64, shift: int): """Calculates the grid date immediately before or after the date provided""" if date.astype("int64") % self.dt.astype("int64") != 0: return date + self.dt * shift return date
def datetime64_to_date(dt64: np.datetime64) -> datetime.date: """Convert a np.datetime64('D') to a datetime.date""" return dt64.astype(datetime.date)
def _iso_date(date: np.datetime64) -> str: """Return the time formatted according to ISO.""" epoch = date.astype("datetime64[us]").astype( "int64") * 1e-6 # type: ignore return datetime.datetime.utcfromtimestamp(epoch).strftime( "%Y-%m-%dT%H:%M:%S.%fZ")
def represent_numpy_datetime(self, data: numpy.datetime64): return represent_datetime(self, data.astype("M8[ms]").tolist())
def date_to_str(d: np.datetime64) -> str: """Convert from np.datetime64 to str without hyphens""" return d.astype(str).replace("-", "")
def _iso_date(date: np.datetime64) -> str: """Return the time formatted according to ISO.""" epoch = date.astype("datetime64[us]").astype( "int64") * 1e-6 # type: ignore return datetime.datetime.utcfromtimestamp(epoch).isoformat() + "Z"
def _floor_to_dt(value: np.datetime64) -> np.datetime64: """Floor a datetime64 to the nearest dt.""" integral = int(value.astype("<M8[h]").astype("int64") / 3) # type: ignore return np.datetime64(integral * 3, "h")
def _truncate_day_to_monday(datetime_day: np.datetime64) -> np.datetime64: # A bit hackish, utilizes the fact that datetime64 is relative to epoch # 1970-01-01 which is a Thursday return datetime_day.astype("datetime64[W]").astype("datetime64[D]") + 4