Ejemplo n.º 1
0
    def test_360_to_366(self):
        source = xr.DataArray(np.arange(360), coords=[np.arange(1, 361), ], dims='dayofyear')
        time = pd.date_range('2000-01-01', '2001-12-31', freq='D')
        target = xr.DataArray(np.arange(len(time)), coords=[time, ], dims='time')

        out = adjust_doy_calendar(source, target)

        assert out.sel(dayofyear=1) == source.sel(dayofyear=1)
        assert out.sel(dayofyear=366) == source.sel(dayofyear=360)
Ejemplo n.º 2
0
    def test_360_to_366(self):
        source = xr.DataArray(np.arange(360),
                              coords=[np.arange(1, 361)],
                              dims="dayofyear")
        time = pd.date_range("2000-01-01", "2001-12-31", freq="D")
        target = xr.DataArray(np.arange(len(time)), coords=[time], dims="time")

        out = adjust_doy_calendar(source, target)

        assert out.sel(dayofyear=1) == source.sel(dayofyear=1)
        assert out.sel(dayofyear=366) == source.sel(dayofyear=360)
Ejemplo n.º 3
0
def warm_spell_duration_index(tasmax, tx90, window=6, freq="YS"):
    r"""Warm spell duration index

    Number of days with at least six consecutive days where the daily maximum temperature is above the 90th
    percentile. The 90th percentile should be computed for a 5-day window centred on each calendar day in the
    1961-1990 period.

    Parameters
    ----------
    tasmax : xarray.DataArray
      Maximum daily temperature [℃] or [K]
    tx90 : float
      90th percentile of daily maximum temperature [℃] or [K]
    window : int
      Minimum number of days with temperature below threshold to qualify as a warm spell.
    freq : str, optional
      Resampling frequency

    Returns
    -------
    xarray.DataArray
      Count of days with at least six consecutive days where the daily maximum temperature is above the 90th
      percentile [days].

    References
    ----------
    From the Expert Team on Climate Change Detection, Monitoring and Indices (ETCCDMI).
    Used in Alexander, L. V., et al. (2006), Global observed changes in daily climate extremes of temperature and
    precipitation, J. Geophys. Res., 111, D05109, doi: 10.1029/2005JD006290.

    """
    if "dayofyear" not in tx90.coords.keys():
        raise AttributeError("tx90 should have dayofyear coordinates.")

    # The day of year value of the tasmax series.
    doy = tasmax.indexes["time"].dayofyear

    # adjustment of tx90 to tasmax doy range
    tx90 = utils.adjust_doy_calendar(tx90, tasmax)

    # Create an array with the shape and coords of tasmax, but with values set to tx90 according to the doy index.
    thresh = xr.full_like(tasmax, np.nan)
    thresh.data = tx90.sel(dayofyear=doy)

    above = tasmax > thresh

    return above.resample(time=freq).apply(rl.windowed_run_count,
                                           window=window,
                                           dim="time")
Ejemplo n.º 4
0
def days_over_precip_thresh(pr, per, thresh="1 mm/day", freq="YS"):
    r"""Number of wet days with daily precipitation over a given percentile.

    Number of days over period where the precipitation is above a threshold defining wet days and above a given
    percentile for that day.

    Parameters
    ----------
    pr : xarray.DataArray
      Mean daily precipitation flux [Kg m-2 s-1] or [mm/day]
    per : xarray.DataArray
      Daily percentile of wet day precipitation flux [Kg m-2 s-1] or [mm/day]
    thresh : str
       Precipitation value over which a day is considered wet [Kg m-2 s-1] or [mm/day].
    freq : str, optional
      Resampling frequency

    Returns
    -------
    xarray.DataArray
      Count of days with daily precipitation above the given percentile [days]

    Notes
    -----
    The percentile should be computed for a 5 day window centered on each calendar day for a reference period.

    Example
    -------
    >>> p75 = percentile_doy(historical_pr, per=0.75)
    >>> r75p = days_over_precip_thresh(pr, p75)
    """
    if "dayofyear" not in per.coords.keys():
        raise AttributeError("percentile should have dayofyear coordinates.")

    per = utils.convert_units_to(per, pr)
    thresh = utils.convert_units_to(thresh, pr)

    per = utils.adjust_doy_calendar(per, pr)
    mper = np.maximum(per, thresh)

    # create array of percentile with pr shape and coords
    tp = xr.full_like(pr, np.nan)
    doy = tp.time.dt.dayofyear.values
    tp.data = mper.sel(dayofyear=doy)

    # compute the days where precip is both over the wet day threshold and the percentile threshold.
    over = pr > tp

    return over.resample(time=freq).sum(dim="time")
Ejemplo n.º 5
0
def fraction_over_precip_thresh(pr, per, thresh="1 mm/day", freq="YS"):
    r"""Fraction of precipitation due to wet days with daily precipitation over a given percentile.

    Percentage of the total precipitation over period occurring in days where the precipitation is above a threshold
    defining wet days and above a given percentile for that day.

    Parameters
    ----------
    pr : xarray.DataArray
      Mean daily precipitation flux [Kg m-2 s-1] or [mm/day]
    per : xarray.DataArray
      Daily percentile of wet day precipitation flux [Kg m-2 s-1] or [mm/day]
    thresh : str
       Precipitation value over which a day is considered wet [Kg m-2 s-1] or [mm/day].
    freq : str, optional
      Resampling frequency

    Returns
    -------
    xarray.DataArray
      Fraction of precipitation over threshold during wet days days.

    Notes
    -----
    The percentile should be computed for a 5 day window centered on each calendar day for a reference period.
    """
    if "dayofyear" not in per.coords.keys():
        raise AttributeError("percentile should have dayofyear coordinates.")

    per = utils.convert_units_to(per, pr)
    thresh = utils.convert_units_to(thresh, pr)

    per = utils.adjust_doy_calendar(per, pr)
    mper = np.maximum(per, thresh)

    # create array of percentile with pr shape and coords
    tp = xr.full_like(pr, np.nan)
    doy = tp.time.dt.dayofyear.values
    tp.data = mper.sel(dayofyear=doy)

    # Total precip during wet days over period
    total = pr.where(pr > thresh).resample(time=freq).sum(dim="time")

    # compute the days where precip is both over the wet day threshold and the percentile threshold.
    over = pr.where(pr > tp).resample(time=freq).sum(dim="time")

    return over / total
Ejemplo n.º 6
0
def tx10p(tasmax, t10, freq="YS"):
    r"""Number of days with daily maximum temperature below the 10th percentile.

    Number of days with daily maximum temperature below the 10th percentile.

    Parameters
    ----------
    tasmax : xarray.DataArray
      Maximum daily temperature [℃] or [K]
    t10 : xarray.DataArray
      10th percentile of daily maximum temperature [℃] or [K]
    freq : str, optional
      Resampling frequency

    Returns
    -------
    xarray.DataArray
      Count of days with daily maximum temperature below the 10th percentile [days]

    Notes
    -----
    The 10th percentile should be computed for a 5 day window centered on each calendar day for a reference period.

    Example
    -------
    >>> t10 = percentile_doy(historical_tas, per=0.1)
    >>> cold_days = tg10p(tas, t10)
    """
    if "dayofyear" not in t10.coords.keys():
        raise AttributeError("t10 should have dayofyear coordinates.")

    t10 = utils.convert_units_to(t10, tasmax)

    # adjustment of t10 to tas doy range
    t10 = utils.adjust_doy_calendar(t10, tasmax)

    # create array of percentile with tas shape and coords
    thresh = xr.full_like(tasmax, np.nan)
    doy = thresh.time.dt.dayofyear.values
    thresh.data = t10.sel(dayofyear=doy)

    # compute the cold days
    below = tasmax < thresh

    return below.resample(time=freq).sum(dim="time")
Ejemplo n.º 7
0
def tg90p(tas, t90, freq='YS'):
    r"""Number of days with daily mean temperature over the 90th percentile.

    Number of days with daily mean temperature over the 90th percentile.

    Parameters
    ----------
    tas : xarray.DataArray
      Mean daily temperature [℃] or [K]
    t90 : xarray.DataArray
      90th percentile of daily mean temperature [℃] or [K]
    freq : str, optional
      Resampling frequency

    Returns
    -------
    xarray.DataArray
      Count of days with daily mean temperature below the 10th percentile [days]

    Notes
    -----
    The 90th percentile should be computed for a 5 day window centered on each calendar day for a reference period.

    Example
    -------
    >>> t90 = percentile_doy(historical_tas, per=0.9)
    >>> hot_days = tg90p(tas, t90)
    """
    if 'dayofyear' not in t90.coords.keys():
        raise AttributeError("t10 should have dayofyear coordinates.")

    t90 = utils.convert_units_to(t90, tas)

    # adjustment of t90 to tas doy range
    t90 = utils.adjust_doy_calendar(t90, tas)

    # create array of percentile with tas shape and coords
    thresh = xr.full_like(tas, np.nan)
    doy = thresh.time.dt.dayofyear.values
    thresh.data = t90.sel(dayofyear=doy)

    # compute the cold days
    over = (tas > thresh)

    return over.resample(time=freq).sum(dim='time')
Ejemplo n.º 8
0
def cold_spell_duration_index(tasmin, tn10, window=6, freq="YS"):
    r"""Cold spell duration index

    Number of days with at least six consecutive days where the daily minimum temperature is below the 10th
    percentile.

    Parameters
    ----------
    tasmin : xarray.DataArray
      Minimum daily temperature.
    tn10 : float
      10th percentile of daily minimum temperature.
    window : int
      Minimum number of days with temperature below threshold to qualify as a cold spell. Default: 6.
    freq : str, optional
      Resampling frequency

    Returns
    -------
    xarray.DataArray
      Count of days with at least six consecutive days where the daily minimum temperature is below the 10th
      percentile [days].

    Notes
    -----
    Let :math:`TN_i` be the minimum daily temperature for the day of the year :math:`i` and :math:`TN10_i` the 10th
    percentile of the minimum daily temperature over the 1961-1990 period for day of the year :math:`i`, the cold spell
    duration index over period :math:`\phi` is defined as:

    .. math::

       \sum_{i \in \phi} \prod_{j=i}^{i+6} \left[ TN_j < TN10_j \right]

    where :math:`[P]` is 1 if :math:`P` is true, and 0 if false.

    References
    ----------
    From the Expert Team on Climate Change Detection, Monitoring and Indices (ETCCDMI).

    Example
    -------
    >>> tn10 = percentile_doy(historical_tasmin, per=.1)
    >>> cold_spell_duration_index(reference_tasmin, tn10)
    """
    if "dayofyear" not in tn10.coords.keys():
        raise AttributeError("tn10 should have dayofyear coordinates.")

    # The day of year value of the tasmin series.
    doy = tasmin.indexes["time"].dayofyear

    tn10 = utils.convert_units_to(tn10, tasmin)
    # If calendar of `tn10` is different from `tasmin`, interpolate.
    tn10 = utils.adjust_doy_calendar(tn10, tasmin)

    # Create an array with the shape and coords of tasmin, but with values set to tx90 according to the doy index.
    thresh = xr.full_like(tasmin, np.nan)
    thresh.data = tn10.sel(dayofyear=doy)

    below = tasmin < thresh

    return below.resample(time=freq).apply(rl.windowed_run_count,
                                           window=window,
                                           dim="time")