def normalize_labels(da: DataArray): # ...infer what axis the "time" axis actually is da = da.rename({"time": "E"}) # ...reshape flattened axes ... # ...replace the "time" axis' coords with more meaningful thing da = da.assign_coords({"E": range(da.shape[0])}) return da
def stream_elas(da: DataArray, prcp: DataArray, coord: str = 'date') -> float: # rename precip coordinate name (to avoid problems with 'index' or 'date') prcp = prcp.rename({list(prcp.coords.keys())[0]: coord}) # slice prcp to the same time window as the discharge prcp = prcp.sel({coord: slice(da.coords[coord][0], da.coords[coord][-1])}) # determine the date of the first October 1st in the data period first_date = da.coords[coord][0].values.astype('datetime64[s]').astype( datetime) last_date = da.coords[coord][-1].values.astype('datetime64[s]').astype( datetime) if first_date > datetime.strptime(f'{first_date.year}-10-01', '%Y-%m-%d'): start_date = datetime.strptime(f'{first_date.year + 1}-10-01', '%Y-%m-%d') else: start_date = datetime.strptime(f'{first_date.year}-10-01', '%Y-%m-%d') end_date = start_date + relativedelta(years=1) - relativedelta(days=1) # mask only valid time steps (only discharge has missing values) idx = (da >= 0) & (~da.isnull()) da = da[idx] prcp = prcp[idx] # calculate long-term means q_mean_total = da.mean() p_mean_total = prcp.mean() values = [] while end_date < last_date: q = da.sel({coord: slice(start_date, end_date)}) p = prcp.sel({coord: slice(start_date, end_date)}) val = (q.mean() - q_mean_total) / (p.mean() - p_mean_total) * ( p_mean_total / q_mean_total) values.append(val) start_date += relativedelta(years=1) end_date += relativedelta(years=1) return np.median([float(v) for v in values])
def runoff_ratio(da: DataArray, prcp: DataArray, datetime_coord: str = None) -> float: """Calculate runoff ratio. Runoff ratio (ratio of mean discharge to mean precipitation) [#]_ (Eq. 2). Parameters ---------- da : DataArray Array of flow values. prcp : DataArray Array of precipitation values. datetime_coord : str, optional Datetime coordinate in the passed DataArray. Tried to infer automatically if not specified. Returns ------- float Runoff ratio. References ---------- .. [#] Sawicz, K., Wagener, T., Sivapalan, M., Troch, P. A., and Carrillo, G.: Catchment classification: empirical analysis of hydrologic similarity based on catchment function in the eastern USA. Hydrology and Earth System Sciences, 2011, 15, 2895--2911, doi:10.5194/hess-15-2895-2011 """ if datetime_coord is None: datetime_coord = utils.infer_datetime_coord(da) # rename precip coordinate name (to avoid problems with 'index' or 'date') prcp = prcp.rename({list(prcp.coords.keys())[0]: datetime_coord}) # slice prcp to the same time window as the discharge prcp = prcp.sel({ datetime_coord: slice(da.coords[datetime_coord][0], da.coords[datetime_coord][-1]) }) # calculate runoff ratio value = da.mean() / prcp.mean() return float(value)
def stream_elas(da: DataArray, prcp: DataArray, datetime_coord: str = None) -> float: """Calculate stream elasticity. Streamflow precipitation elasticity (sensitivity of streamflow to changes in precipitation at the annual time scale) [#]_. Parameters ---------- da : DataArray Array of flow values. prcp : DataArray Array of precipitation values. datetime_coord : str, optional Datetime coordinate in the passed DataArray. Tried to infer automatically if not specified. Returns ------- float Stream elasticity. References ---------- .. [#] Sankarasubramanian, A., Vogel, R. M., and Limbrunner, J. F.: Climate elasticity of streamflow in the United States. Water Resources Research, 2001, 37, 1771--1781, doi:10.1029/2000WR900330 """ if datetime_coord is None: datetime_coord = utils.infer_datetime_coord(da) # rename precip coordinate name (to avoid problems with 'index' or 'date') prcp = prcp.rename({list(prcp.coords.keys())[0]: datetime_coord}) # slice prcp to the same time window as the discharge prcp = prcp.sel({ datetime_coord: slice(da.coords[datetime_coord][0], da.coords[datetime_coord][-1]) }) # determine the date of the first October 1st in the data period first_date = da.coords[datetime_coord][0].values.astype( 'datetime64[s]').astype(datetime) last_date = da.coords[datetime_coord][-1].values.astype( 'datetime64[s]').astype(datetime) if first_date > datetime.strptime(f'{first_date.year}-10-01', '%Y-%m-%d'): start_date = datetime.strptime(f'{first_date.year + 1}-10-01', '%Y-%m-%d') else: start_date = datetime.strptime(f'{first_date.year}-10-01', '%Y-%m-%d') end_date = start_date + relativedelta(years=1) - relativedelta(seconds=1) # mask only valid time steps (only discharge has missing values) idx = (da >= 0) & (~da.isnull()) da = da[idx] prcp = prcp[idx] # calculate long-term means q_mean_total = da.mean() p_mean_total = prcp.mean() values = [] while end_date < last_date: q = da.sel({datetime_coord: slice(start_date, end_date)}) p = prcp.sel({datetime_coord: slice(start_date, end_date)}) val = (q.mean() - q_mean_total) / (p.mean() - p_mean_total) * ( p_mean_total / q_mean_total) values.append(val) start_date += relativedelta(years=1) end_date += relativedelta(years=1) return np.median([float(v) for v in values])