Skip to content

Commit

Permalink
Create _streamflow_flow_indices.py (#1832)
Browse files Browse the repository at this point in the history
streamflow_flow_indice is a submodule in the xclim indices module to
calculate streamflow signatures, representing individual watershed
characteristics of large river/lake basins.

<!--Please ensure the PR fulfills the following requirements! -->
<!-- If this is your first PR, make sure to add your details to the
AUTHORS.rst! -->
### Pull Request Checklist:
- [x] This PR addresses an already opened issue (for bug fixes /
features)
    - This PR fixes #xyz
- [x] Tests for the changes have been added (for bug fixes / features)
- [ ] (If applicable) Documentation has been added / updated (for bug
fixes / features)
- [x] CHANGELOG.rst has been updated (with summary of main changes)
- [ ] Link to issue (:issue:`number`) and pull request (:pull:`number`)
has been added

### What kind of change does this PR introduce?

* ...This PR introduces three hydrological signatures in xclim indices
module. The functions included are to calculate the high and low flow
variables of a data series of watersheds and generate a characteristic
value of the catchment from the calculated hydrological signatures.

### Does this PR introduce a breaking change?
This can develop unique watershed attributes.
### Other information:
  • Loading branch information
huard authored Oct 8, 2024
2 parents dd37e5a + 6118234 commit cfdc49d
Show file tree
Hide file tree
Showing 8 changed files with 281 additions and 15 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -122,3 +122,6 @@ docs/variables.json

# dask
dask-worker-space

# Apple
.DS_Store
1 change: 1 addition & 0 deletions AUTHORS.rst
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,5 @@ Contributors
* Javier Diez-Sierra <[email protected]> `@JavierDiezSierra <https://github.com/JavierDiezSierra>`_
* Hui-Min Wang `@Hem-W <https://github.com/Hem-W>`_
* Adrien Lamarche `@LamAdr <https://github.com/LamAdr>`_
* Faisal Mahmood <[email protected]> <[email protected]> `@faimahsho <https://github.com/faimahsho>`_
* Sebastian Lehner <[email protected]> `@seblehner <https://github.com/seblehner>`_
34 changes: 33 additions & 1 deletion docs/references.bib
Original file line number Diff line number Diff line change
Expand Up @@ -2153,7 +2153,39 @@ @article{droogers2002
type = {Article}
}

@Article{robin_2019,
@article{addor2018,
author = {Addor, Nans and Nearing, Grey and Prieto, Cristina and Newman, A. and Le Vine, Nataliya and Clark, Martyn},
year = {2018},
month = {11},
pages = {},
title = {A Ranking of Hydrological Signatures Based on Their Predictability in Space},
journal = {Water Resources Research},
doi = {10.1029/2018WR022606}
}

@article{Clausen2000,
author = {Clausen, B and Biggs, Barry},
year = {2000},
month = {11},
pages = {184-197},
title = {Flow variables for ecological studies in temperate streams: Groupings based on covariance},
volume = {237},
journal = {Journal of Hydrology},
doi = {10.1016/S0022-1694(00)00306-1}
}

@article{Olden2003,
author = {Olden, Julian and Poff, N.},
year = {2003},
month = {03},
pages = {101 - 121},
title = {Redundancy and the Choice of Hydrologic Indices for Characterizing Stream Flow Regimes},
volume = {19},
journal = {River Research and Applications},
doi = {10.1002/rra.700}
}

@article{robin_2019,
author = {Robin, Y. and Vrac, M. and Naveau, P. and Yiou, P.},
title = {Multivariate stochastic bias corrections with optimal transport},
journal = {Hydrology and Earth System Sciences},
Expand Down
30 changes: 30 additions & 0 deletions tests/test_hydrology.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,3 +70,33 @@ def test_simple(self, snw_series, pr_series):
out = xci.melt_and_precip_max(snw, pr)
np.testing.assert_array_equal(out, 2)
assert out.units == "kg m-2"


class TestFlowindex:
def test_simple(self, q_series):
a = np.ones(365 * 2) * 10
a[10:50] = 50
q = q_series(a)
out = xci.flow_index(q, 0.95)
np.testing.assert_array_equal(out, 5)


class TestHighflowfrequency:
def test_simple(self, q_series):
a = np.zeros(365 * 2)
a[50:60] = 10
a[200:210] = 20
q = q_series(a)
out = xci.high_flow_frequency(q, 9, freq="YS")
np.testing.assert_array_equal(out, [20, 0])


class TestLowflowfrequency:
def test_simple(self, q_series):
a = np.ones(365 * 2) * 10
a[50:60] = 1
a[200:210] = 1
q = q_series(a)
out = xci.low_flow_frequency(q, 0.2, freq="YS")

np.testing.assert_array_equal(out, [20, 0])
31 changes: 31 additions & 0 deletions tests/test_land.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,3 +66,34 @@ def test_snw_storm_days(snw_series):
snw = snw_series(a)
out = land.snw_storm_days(snw, thresh="0.5 kg m-2")
np.testing.assert_array_equal(out, [9, np.nan])


def test_flow_index(q_series):
a = np.ones(365 * 2) * 10
a[10:50] = 50
q = q_series(a)

out = land.flow_index(q, p=0.95)
np.testing.assert_array_equal(out, 5)


def test_high_flow_frequency(q_series):
a = np.zeros(366 * 2) * 10
a[50:60] = 10
a[200:210] = 20
q = q_series(a)
out = land.high_flow_frequency(
q,
threshold_factor=9,
freq="YS",
)
np.testing.assert_array_equal(out, [20, 0, np.nan])


def test_low_flow_frequency(q_series):
a = np.ones(366 * 2) * 10
a[50:60] = 1
a[200:210] = 1
q = q_series(a)
out = land.low_flow_frequency(q, threshold_factor=0.2, freq="YS")
np.testing.assert_array_equal(out, [20, 0, np.nan])
18 changes: 18 additions & 0 deletions xclim/data/fr.json
Original file line number Diff line number Diff line change
Expand Up @@ -1392,6 +1392,24 @@
"title": "Rayonnement de grandes longueurs d'onde ascendant",
"abstract": "Calcul du rayonnement de grandes longueurs d'onde ascendant à partir du rayonnement de grandes longueurs d'onde net et descendant."
},
"FLOW_INDEX": {
"long_name": "Indice de débit",
"description": "Le {p}e percentile du débit normalisé par le débit médian.",
"title": "Indice de débit",
"abstract": "Indice de débit, calculé comme le rapport entre un percentile donné du débit et la médiane."
},
"HIGH_FLOW_FREQUENCY": {
"long_name": "Fréquence des débits élevés",
"description": "Nombre de jours où le débit est {threshold_factor} fois supérieur à la médiane.",
"title": "Fréquence des débits élevés",
"abstract": "Fréquence des débits élevés, calculée comme le nombre de jours où le débit est supérieur à un multiple de la médiane."
},
"LOW_FLOW_FREQUENCY": {
"long_name": "Fréquence des débits faibles",
"description": "Nombre de jours où le débit est inférieur à une fraction ({threshold_factor}) de la moyenne.",
"title": "Fréquence des débits faibles",
"abstract": "Fréquence des débits faibles, calculée comme le nombre de jours où le débit est inférieur à une fraction de la moyenne."
},
"CP": {
"title": "Portions de froid (Chill Portions) selon le modèle Dynamique.",
"abstract": "Les portions de froid (chill portions) sont une mesure du potentiel de débourrement de différentes récoltes basée sur le modèle Dynamique.",
Expand Down
51 changes: 49 additions & 2 deletions xclim/indicators/land/_streamflow.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,27 @@
from __future__ import annotations

from xclim.core.cfchecks import check_valid
from xclim.core.indicator import ResamplingIndicator
from xclim.core.indicator import (
ReducingIndicator,
ResamplingIndicator,
)
from xclim.core.units import declare_units
from xclim.indices import base_flow_index, generic, rb_flashiness_index
from xclim.indices import (
base_flow_index,
flow_index,
generic,
high_flow_frequency,
low_flow_frequency,
rb_flashiness_index,
)

__all__ = [
"base_flow_index",
"doy_qmax",
"doy_qmin",
"flow_index",
"high_flow_frequency",
"low_flow_frequency",
"rb_flashiness_index",
]

Expand Down Expand Up @@ -74,3 +87,37 @@ def cfcheck(q):
compute=declare_units(da="[discharge]")(generic.select_resample_op),
parameters={"op": generic.doymin, "out_units": None},
)

flow_index = ReducingIndicator(
realm="land",
context="hydro",
title="Flow index",
identifier="flow_index",
var_name="q_flow_index",
long_name="Flow index",
description="{p}th percentile normalized by the median flow.",
units="1",
compute=flow_index,
)


high_flow_frequency = Streamflow(
title="High flow frequency",
identifier="high_flow_frequency",
var_name="q_high_flow_frequency",
long_name="High flow frequency",
description="{freq} frequency of flows greater than {threshold_factor} times the median flow.",
units="days",
compute=high_flow_frequency,
)


low_flow_frequency = Streamflow(
title="Low flow frequency",
identifier="low_flow_frequency",
var_name="q_low_flow_frequency",
long_name="Low flow frequency",
description="{freq} frequency of flows smaller than a fraction ({threshold_factor}) of the mean flow.",
units="days",
compute=low_flow_frequency,
)
Loading

0 comments on commit cfdc49d

Please sign in to comment.