Skip to content

SPEI: Passing rv_continuous distributions #2326

@rubhae

Description

@rubhae

Setup Information

  • Xclim version: 0.53.2
  • Python version: 3.12.7
  • Operating System: Ubuntu 24.04

Description

I tried to calculate SPEI with a GenEV distribution as suggested in Stagge et al. 2015.

The documentation of xclim.indices.standardized_precipitation_evapotranspiration_index claims that rv_continuous can be used for the distribution:

dist ({‘gamma’, ‘fisk’} or rv_continuous function) – Name of the univariate distribution, or a callable rv_continuous (see scipy.stats).

However, this does not work, as only the below shown manually written set of distributions can be used.
In xclim.indices.stats.standardized_index_fit_params, the following check makes it impossible to use any other distribution:

dist_and_methods = {"gamma": ["ML", "APP", "PWM"], "fisk": ["ML", "APP"]}
dist = xclim.indices.stats.get_dist(dist)
if dist.name not in dist_and_methods:
    raise NotImplementedError(f"The distribution `{dist.name}` is not supported.")
if method not in dist_and_methods[dist.name]:
    raise NotImplementedError(
        f"The method `{method}` is not supported for distribution `{dist.name}`."

Steps To Reproduce

If I try to run:

spei_gev = xclim.indices.standardized_precipitation_evapotranspiration_index(
    wb,
    freq="MS",
    window=1,
    dist=scipy.stats.genextreme,
    method="ML",
)

I get the error message:

NotImplementedError: <scipy.stats._continuous_distns.genextreme_gen object at 0x77859811b2f0> distribution is not yet implemented.

Additional context

I was able to use scipy.stats.genextreme as a distribution by bypassing the if statement above by only checking against the dictionary dist_and_methods if "dist" is a string:

dist_and_methods = {"gamma": ["ML", "APP", "PWM"], "fisk": ["ML", "APP"]}
if isinstance(dist, str):
    dist = xclim.indices.stats.get_dist(dist)
    if dist.name not in dist_and_methods:
        raise NotImplementedError(f"The distribution `{dist.name}` is not supported.")
    if method not in dist_and_methods[dist.name]:
        raise NotImplementedError(
            f"The method `{method}` is not supported for distribution `{dist.name}`."

The same method is used in standardized_precipitation_evapotranspiration_index().

Contribution

  • I would be willing/able to open a Pull Request to address this bug.

Code of Conduct

  • I agree to follow this project's Code of Conduct

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions