Пример #1
0
def prcptot(pr: xarray.DataArray, input_freq: str = None, freq: str = "YS"):
    r"""ANUCLIM Accumulated total precipitation.

    Parameters
    ----------
    pr : xarray.DataArray
      Total precipitation flux [mm d-1], [mm week-1], [mm month-1] or similar.
    input_freq : str
      Input data time frequency - One of 'daily', 'weekly' or 'monthly'.
    freq : str
      Resampling frequency; Defaults to "YS".

    Returns
    -------
    xarray.DataArray
       Total precipitation [mm].

    Notes
    -----
    According to the ANUCLIM user-guide https://fennerschool.anu.edu.au/files/anuclim61.pdf (ch. 6), input
    values should be at a weekly (or monthly) frequency.  However, the xclim.indices implementation here will calculate
    the result with input data with daily frequency as well.
    """
    if input_freq == "monthly":
        pr = pint_multiply(pr, 1 * units.month, "mm")
    elif input_freq == "weekly":
        pr = pint_multiply(pr, 1 * units.week, "mm")
    elif input_freq == "daily":
        pr = pint_multiply(pr, 1 * units.day, "mm")
    else:
        raise NotImplementedError(
            f'Unknown input time frequency "{input_freq}" : input_freq parameter must be '
            f'one of "daily", "weekly" or "monthly"')
    return pr.resample(time=freq).sum(dim="time", keep_attrs=True)
Пример #2
0
def precip_accumulation(
    pr: xarray.DataArray,
    tas: xarray.DataArray = None,
    phase: Optional[str] = None,
    freq: str = "YS",
) -> xarray.DataArray:
    r"""Accumulated total (liquid and/or solid) precipitation.

    Resample the original daily mean precipitation flux and accumulate over each period.
    If the daily mean temperature is provided, the phase keyword can be used to only sum precipitation of a certain phase.
    When the mean temperature is over 0 degC, precipitatio is assumed to be liquid rain and snow otherwise.

    Parameters
    ----------
    pr : xarray.DataArray
      Mean daily precipitation flux [Kg m-2 s-1] or [mm].
    tas : xarray.DataArray, optional
      Mean daily temperature [℃] or [K]
    phase : str, optional,
      Which phase to consider, "liquid" or "solid", if None (default), both are considered.
    freq : str
      Resampling frequency as defined in
      http://pandas.pydata.org/pandas-docs/stable/timeseries.html#resampling. Defaults to "YS"

    Returns
    -------
    xarray.DataArray
      The total daily precipitation at the given time frequency for the given phase.

    Notes
    -----
    Let :math:`PR_i` be the mean daily precipitation of day :math:`i`, then for a period :math:`j` starting at
    day :math:`a` and finishing on day :math:`b`:

    .. math::

       PR_{ij} = \sum_{i=a}^{b} PR_i

    If `phase` is "liquid", only times where the daily mean temperature :math:`T_i` is above or equal to 0 °C are considered, inversely for "solid".

    Examples
    --------
    The following would compute for each grid cell of file `pr_day.nc` the total
    precipitation at the seasonal frequency, ie DJF, MAM, JJA, SON, DJF, etc.:

    >>> import xarray as xr
    >>> pr_day = xr.open_dataset('pr_day.nc').pr
    >>> prcp_tot_seasonal = precip_accumulation(pr_day, freq="QS-DEC")
    """

    if phase in ["liquid", "solid"]:
        frz = convert_units_to("0 degC", tas)

        if phase == "liquid":
            pr = pr.where(tas >= frz, 0)
        elif phase == "solid":
            pr = pr.where(tas < frz, 0)

    out = pr.resample(time=freq).sum(dim="time", keep_attrs=True)
    return pint_multiply(out, 1 * units.day, "mm")
Пример #3
0
def prcptot_wetdry_period(
    pr: xarray.DataArray, *, op: str, src_timestep: str, freq: str = "YS"
) -> xarray.DataArray:
    r"""ANUCLIM precipitation of the wettest/driest day, week, or month, depending on the time step.

    Parameters
    ----------
    pr : xarray.DataArray
      Total precipitation flux [mm d-1], [mm week-1], [mm month-1] or similar.
    op : str
      Operation to perform :  'wettest' calculate wettest period ; 'driest' calculate driest period.
    src_timestep : {'D', 'W', 'M'}
      Input data time frequency - One of daily, weekly or monthly.
    freq : str
      Resampling frequency; Defaults to "YS".

    Returns
    -------
    xarray.DataArray
       Total precipitation [mm] of the wettest / driest period.

    Notes
    -----
    According to the ANUCLIM user-guide https://fennerschool.anu.edu.au/files/anuclim61.pdf (ch. 6), input
    values should be at a weekly (or monthly) frequency.  However, the xclim.indices implementation here will calculate
    the result with input data with daily frequency as well. As such weekly or monthly input values, if desired,
    should be calculated prior to calling the function.
    """
    if src_timestep == "M":
        pr = pint_multiply(pr, 1 * units.month, "mm")
    elif src_timestep == "W":
        pr = pint_multiply(pr, 1 * units.week, "mm")
    elif src_timestep == "D":
        pr = pint_multiply(pr, 1 * units.day, "mm")
    else:
        raise NotImplementedError(
            f'Unknown input time frequency "{src_timestep}" : src_timestep parameter must be '
            f'one of "D", "W" or "M"'
        )

    if op == "wettest":
        return pr.resample(time=freq).max(dim="time", keep_attrs=True)
    if op == "driest":
        return pr.resample(time=freq).min(dim="time", keep_attrs=True)
    raise NotImplementedError(
        f'Unknown operation "{op}" ; op parameter but be one of "wettest" or "driest"'
    )
Пример #4
0
def daily_pr_intensity(pr: xarray.DataArray,
                       thresh: str = "1 mm/day",
                       freq: str = "YS"):
    r"""Average daily precipitation intensity.

    Return the average precipitation over wet days.

    Parameters
    ----------
    pr : xarray.DataArray
      Daily precipitation [mm/d or kg/m²/s]
    thresh : str
      precipitation value over which a day is considered wet. Default : '1 mm/day'
    freq : str
      Resampling frequency defining the periods defined in
      http://pandas.pydata.org/pandas-docs/stable/timeseries.html#resampling; Defaults to "YS".

    Returns
    -------
    xarray.DataArray
      The average precipitation over wet days for each period

    Notes
    -----
    Let :math:`\mathbf{p} = p_0, p_1, \ldots, p_n` be the daily precipitation and :math:`thresh` be the precipitation
    threshold defining wet days. Then the daily precipitation intensity is defined as

    .. math::

       \frac{\sum_{i=0}^n p_i [p_i \leq thresh]}{\sum_{i=0}^n [p_i \leq thresh]}

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

    Examples
    --------
    The following would compute for each grid cell of file `pr.day.nc` the average
    precipitation fallen over days with precipitation >= 5 mm at seasonal
    frequency, ie DJF, MAM, JJA, SON, DJF, etc.:

    >>> from xclim.indices import daily_pr_intensity
    >>> pr = xr.open_dataset(path_to_pr_file).pr
    >>> daily_int = daily_pr_intensity(pr, thresh='5 mm/day', freq="QS-DEC")
    """
    t = convert_units_to(thresh, pr, "hydro")

    # put pr=0 for non wet-days
    pr_wd = xarray.where(pr >= t, pr, 0)
    pr_wd.attrs["units"] = pr.units

    # sum over wanted period
    s = pr_wd.resample(time=freq).sum(dim="time", keep_attrs=True)
    sd = pint_multiply(s, 1 * units.day, "mm")

    # get number of wetdays over period
    wd = wetdays(pr, thresh=thresh, freq=freq)
    return sd / wd
Пример #5
0
def _to_quarter(
    freq: str,
    pr: Optional[xarray.DataArray] = None,
    tas: Optional[xarray.DataArray] = None,
) -> xarray.DataArray:
    """Convert daily, weekly or monthly time series to quarterly time series according to ANUCLIM specifications."""
    if freq.upper().startswith("D"):
        if tas is not None:
            tas = tg_mean(tas, freq="7D")

        if pr is not None:
            pr = precip_accumulation(pr, freq="7D")
            pr.attrs["units"] = "mm/week"

        freq = "W"

    if freq.upper().startswith("W"):
        window = 13
        u = units.week

    elif freq.upper().startswith("M"):
        window = 3
        u = units.month

    else:
        raise NotImplementedError(
            f'Unknown input time frequency "{freq}": must be one of "D", "W" or "M".'
        )

    if tas is not None:
        tas = ensure_chunk_size(tas, time=np.ceil(window / 2))
    if pr is not None:
        pr = ensure_chunk_size(pr, time=np.ceil(window / 2))

    with xarray.set_options(keep_attrs=True):
        if pr is not None:
            pr = pint_multiply(pr, 1 * u, "mm")
            out = pr.rolling(time=window, center=False).sum()
            out.attrs = pr.attrs
            out.attrs["units"] = "mm"

        if tas is not None:
            out = tas.rolling(time=window, center=False).mean(skipna=False)
            out.attrs = tas.attrs

    out = ensure_chunk_size(out, time=-1)
    return out
Пример #6
0
def max_n_day_precipitation_amount(pr: xarray.DataArray,
                                   window: int = 1,
                                   freq: str = "YS"):
    r"""Highest precipitation amount cumulated over a n-day moving window.

    Calculate the n-day rolling sum of the original daily total precipitation series
    and determine the maximum value over each period.

    Parameters
    ----------
    pr : xarray.DataArray
      Daily precipitation values [Kg m-2 s-1] or [mm]
    window : int
      Window size in days.
    freq : str
      Resampling frequency; Defaults to "YS" (yearly).

    Returns
    -------
    xarray.DataArray
      The highest cumulated n-day precipitation value at the given time frequency.

    Examples
    --------
    >>> from xclim.indices import max_n_day_precipitation_amount

    # The following would compute for each grid cell the highest 5-day total precipitation
    #at an annual frequency:
    >>> pr = xr.open_dataset(path_to_pr_file).pr
    >>> out = max_n_day_precipitation_amount(pr, window=5, freq="YS")
    """
    # Rolling sum of the values
    arr = pr.rolling(time=window).sum(skipna=False)
    out = arr.resample(time=freq).max(dim="time", keep_attrs=True)

    out.attrs["units"] = pr.units
    # Adjust values and units to make sure they are daily
    return pint_multiply(out, 1 * units.day, "mm")
Пример #7
0
 def test_pint_multiply(self, pr_series):
     a = pr_series([1, 2, 3])
     out = pint_multiply(a, 1 * units.days)
     assert out[0] == 1 * 60 * 60 * 24
     assert out.units == "kg m-2"
Пример #8
0
def precip_accumulation(
    pr: xarray.DataArray,
    tas: xarray.DataArray = None,
    phase: Optional[str] = None,
    thresh: str = "0 degC",
    freq: str = "YS",
) -> xarray.DataArray:
    r"""Accumulated total (liquid and/or solid) precipitation.

    Resample the original daily mean precipitation flux and accumulate over each period.
    If a daily temperature is provided, the `phase` keyword can be used to sum precipitation of a given phase only.
    When the temperature is under the provided threshold, precipitation is assumed to be snow, and liquid rain otherwise.
    This indice is agnostic to the type of daily temperature (tas, tasmax or tasmin) given.

    Parameters
    ----------
    pr : xarray.DataArray
      Mean daily precipitation flux [Kg m-2 s-1] or [mm].
    tas : xarray.DataArray, optional
      Mean, maximum or minimum daily temperature.
    phase : str, optional,
      Which phase to consider, "liquid" or "solid", if None (default), both are considered.
    thresh : str,
      Threshold of `tas` over which the precipication is assumed to be liquid rain.
    freq : str
      Resampling frequency as defined in
      http://pandas.pydata.org/pandas-docs/stable/timeseries.html#resampling. Defaults to "YS"

    Returns
    -------
    xarray.DataArray
      The total daily precipitation at the given time frequency for the given phase.

    Notes
    -----
    Let :math:`PR_i` be the mean daily precipitation of day :math:`i`, then for a period :math:`j` starting at
    day :math:`a` and finishing on day :math:`b`:

    .. math::

       PR_{ij} = \sum_{i=a}^{b} PR_i

    If tas and phase are given, the corresponding phase precipitation is estimated before computing the accumulation,
    using one of `snowfall_approximation` or `rain_approximation` with the `binary` method.

    Examples
    --------
    The following would compute, for each grid cell of a dataset, the total
    precipitation at the seasonal frequency, ie DJF, MAM, JJA, SON, DJF, etc.:

    >>> from xclim.indices import precip_accumulation
    >>> pr_day = xr.open_dataset(path_to_pr_file).pr
    >>> prcp_tot_seasonal = precip_accumulation(pr_day, freq="QS-DEC")
    """
    if phase == "liquid":
        pr = rain_approximation(pr, tas=tas, thresh=thresh, method="binary")
    elif phase == "solid":
        pr = snowfall_approximation(pr,
                                    tas=tas,
                                    thresh=thresh,
                                    method="binary")

    out = pr.resample(time=freq).sum(dim="time", keep_attrs=True)
    return pint_multiply(out, 1 * units.day, "mm")