├── .amlignore ├── .amlignore.amltmp ├── .github └── workflows │ ├── send-to-pypi.yml │ ├── test-release.yml │ └── tox-tests.yml ├── .gitignore ├── .ipynb_aml_checkpoints └── EWR_tool-checkpoint2022-4-30-0-31-47Z.ipynb ├── CITATION.cff ├── EWR_tool_requirements.txt ├── LICENSE ├── README.md ├── example_parallel_run.py ├── license.amltmp ├── py_ewr ├── .amlignore ├── .amlignore.amltmp ├── __init__.py ├── data_inputs.py ├── evaluate_EWRs.py ├── gauge_data │ └── bom_gauge_data.csv ├── io.py ├── model_metadata │ ├── .amlignore │ ├── .amlignore.amltmp │ ├── SiteID_MDBA.csv │ ├── SiteID_NSW.csv │ ├── iqqm_stations.csv │ └── siteid_mdba.csv.amltmp ├── observed_handling.py ├── parameter_metadata │ ├── ewr2obj.csv │ ├── ewr_calc_config.json │ ├── obj2target.csv │ ├── obj2yrtarget.csv │ └── parameter_sheet.csv ├── scenario_handling.py └── summarise_results.py ├── pyproject.toml ├── readme.md.amltmp ├── requirements-dev.txt ├── requirements-notebook-env.txt ├── requirements.txt ├── setup.py ├── setup.py.amltmp ├── tests ├── conftest.py ├── test_data_inputs.py ├── test_evaluate_ewr_rest.py ├── test_evaluate_ewrs.py ├── test_observed_handling.py ├── test_scenario_handling.py └── test_summarise_results.py ├── tox.ini └── unit_testing_files ├── Low_flow_EWRs_Bidgee_410007.csv ├── MDBA_bigmod_test_file.csv ├── MDBA_bigmod_test_file_buggy_ID.csv ├── MDBA_bigmod_test_file_flow_result.csv ├── MDBA_bigmod_test_file_header_result.csv ├── MURRAY_MDBA_update_nest.csv ├── NSW_10000yr_test_file.csv ├── NSW_source_res_test_file.csv ├── NSW_source_res_test_file_flow_result.csv ├── NSW_source_res_test_file_header_result.csv ├── detailed_results_observed.csv ├── detailed_results_test.csv ├── ex_tasker.nc ├── gauge_results_after_process.pickle ├── gauge_results_before_process.pickle ├── input_for_summarise_data.csv ├── mock_gg_pull.json ├── multi_gauge_input.csv ├── multi_gauge_input_label.csv ├── murray_IQQM_df_wp.csv ├── observed_flows_test_input.csv ├── observed_flows_test_input_QC.csv ├── observed_flows_test_output.csv ├── observed_flows_test_output_QC.csv ├── parameter_sheet.csv ├── qld_parameter_sheet.csv ├── sa_parameter_sheet.csv ├── test_EWR_table_bad_output.csv ├── test_EWR_table_good_output.csv ├── test_EWR_table_input.csv ├── test_climate_cats.nc ├── vic_parameter_sheet.csv └── werp_ncdf.nc /.amlignore: -------------------------------------------------------------------------------- 1 | ## This file was auto generated by the Azure Machine Learning Studio. Please do not remove. 2 | ## Read more about the .amlignore file here: https://docs.microsoft.com/azure/machine-learning/how-to-save-write-experiment-files#storage-limits-of-experiment-snapshots 3 | 4 | .ipynb_aml_checkpoints/ 5 | *.amltmp 6 | *.amltemp -------------------------------------------------------------------------------- /.amlignore.amltmp: -------------------------------------------------------------------------------- 1 | ## This file was auto generated by the Azure Machine Learning Studio. Please do not remove. 2 | ## Read more about the .amlignore file here: https://docs.microsoft.com/azure/machine-learning/how-to-save-write-experiment-files#storage-limits-of-experiment-snapshots 3 | 4 | .ipynb_aml_checkpoints/ 5 | *.amltmp 6 | *.amltemp -------------------------------------------------------------------------------- /.github/workflows/send-to-pypi.yml: -------------------------------------------------------------------------------- 1 | name: send 🐍 📦 to PyPI 2 | 3 | on: 4 | workflow_call: 5 | inputs: 6 | username: 7 | required: true 8 | type: string 9 | secrets: 10 | test_token: 11 | required: true 12 | token: 13 | required: true 14 | 15 | jobs: 16 | 17 | build-n-publish: 18 | name: Build and publish Python 🐍 distributions 📦 to PyPI and TestPyPI 19 | runs-on: ubuntu-latest 20 | steps: 21 | - uses: actions/checkout@master 22 | - name: Set up Python 3.10 23 | uses: actions/setup-python@v2 24 | with: 25 | python-version: "3.10" 26 | - name: Install pypa/build 27 | run: >- 28 | python -m 29 | pip install 30 | build 31 | --user 32 | - name: Build a binary wheel and a source tarball 33 | run: >- 34 | python -m 35 | build 36 | --sdist 37 | --wheel 38 | --outdir dist/ 39 | . 40 | - name: Publish distribution 📦 to Test PyPI 41 | uses: pypa/gh-action-pypi-publish@release/v1 42 | with: 43 | user: ${{ inputs.username }} 44 | password: ${{ secrets.test_token }} 45 | repository_url: https://test.pypi.org/legacy/ 46 | skip_existing: true 47 | - name: Publish distribution 📦 to PyPI 48 | if: startsWith(github.ref, 'refs/tags') 49 | uses: pypa/gh-action-pypi-publish@release/v1 50 | with: 51 | password: ${{ secrets.token }} 52 | -------------------------------------------------------------------------------- /.github/workflows/test-release.yml: -------------------------------------------------------------------------------- 1 | name: test-release 2 | 3 | on: [push] 4 | 5 | jobs: 6 | tox-tests: 7 | uses: ./.github/workflows/tox-tests.yml 8 | 9 | code-quality-release-pypi: 10 | needs: tox-tests 11 | uses: ./.github/workflows/send-to-pypi.yml 12 | with: 13 | username: __token__ 14 | secrets: 15 | test_token: ${{ secrets.TEST_PYPI_API_TOKEN }} 16 | token: ${{ secrets.PYPI_API_TOKEN }} -------------------------------------------------------------------------------- /.github/workflows/tox-tests.yml: -------------------------------------------------------------------------------- 1 | name: Tox 2 | 3 | on: 4 | - workflow_call 5 | 6 | jobs: 7 | test: 8 | runs-on: ${{ matrix.os }} 9 | strategy: 10 | matrix: 11 | os: [ubuntu-latest] 12 | python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"] 13 | 14 | steps: 15 | - uses: actions/checkout@v2 16 | - name: Set up Python ${{ matrix.python-version }} 17 | uses: actions/setup-python@v2 18 | with: 19 | python-version: ${{ matrix.python-version }} 20 | - name: Install dependencies 21 | run: | 22 | python -m pip install --upgrade pip 23 | pip install tox tox-gh-actions 24 | - name: Test with tox 25 | run: tox 26 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | pip-wheel-metadata/ 24 | share/python-wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | .idea/ 30 | 31 | # PyInstaller 32 | # Usually these files are written by a python script from a template 33 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 34 | *.manifest 35 | *.spec 36 | 37 | # Installer logs 38 | pip-log.txt 39 | pip-delete-this-directory.txt 40 | 41 | # Unit test / coverage reports 42 | htmlcov/ 43 | .tox/ 44 | .nox/ 45 | .coverage 46 | .coverage.* 47 | .cache 48 | nosetests.xml 49 | coverage.xml 50 | *.cover 51 | *.py,cover 52 | .hypothesis/ 53 | .pytest_cache/ 54 | 55 | # Translations 56 | *.mo 57 | *.pot 58 | 59 | # Django stuff: 60 | *.log 61 | local_settings.py 62 | db.sqlite3 63 | db.sqlite3-journal 64 | 65 | # Flask stuff: 66 | instance/ 67 | .webassets-cache 68 | 69 | # Scrapy stuff: 70 | .scrapy 71 | 72 | # Sphinx documentation 73 | docs/_build/ 74 | 75 | # PyBuilder 76 | target/ 77 | 78 | # Jupyter Notebook 79 | .ipynb_checkpoints 80 | 81 | # IPython 82 | profile_default/ 83 | ipython_config.py 84 | 85 | # pyenv 86 | .python-version 87 | 88 | # pipenv 89 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 90 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 91 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 92 | # install all needed dependencies. 93 | #Pipfile.lock 94 | 95 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 96 | __pypackages__/ 97 | 98 | # Celery stuff 99 | celerybeat-schedule 100 | celerybeat.pid 101 | 102 | # SageMath parsed files 103 | *.sage.py 104 | 105 | # Environments 106 | .env 107 | .venv 108 | env/ 109 | venv/ 110 | ENV/ 111 | env.bak/ 112 | venv.bak/ 113 | 114 | # Spyder project settings 115 | .spyderproject 116 | .spyproject 117 | 118 | # Rope project settings 119 | .ropeproject 120 | 121 | # mkdocs documentation 122 | /site 123 | 124 | # mypy 125 | .mypy_cache/ 126 | .dmypy.json 127 | dmypy.json 128 | 129 | # Pyre type checker 130 | .pyre/ 131 | 132 | agile*.py 133 | /agile 134 | 135 | # Distribution / packaging 136 | .Python 137 | build/ 138 | develop-eggs/ 139 | dist/ 140 | downloads/ 141 | eggs/ 142 | .eggs/ 143 | lib/ 144 | lib64/ 145 | parts/ 146 | sdist/ 147 | var/ 148 | wheels/ 149 | pip-wheel-metadata/ 150 | share/python-wheels/ 151 | *.egg-info/ 152 | .installed.cfg 153 | *.egg 154 | MANIFEST 155 | 156 | # Other 157 | sandbox.py 158 | test.py 159 | Source/ 160 | Example_EWR_tool_run.ipynb 161 | Scenario1all_events.csv 162 | Scenario1all_interevents.csv 163 | Scenario1all_results.csv 164 | Scenario1all_successful_Events.csv 165 | Scenario1all_successful_interEvents.csv 166 | Scenario1yearly_ewr_results.csv 167 | py_ewr/model_metadata/SiteID_NSW_test.csv 168 | py_ewr/parameter_metadata/parameter_sheet_test.csv 169 | run_local_script/ 170 | run_local_script.zip 171 | standard_flow_handler.py 172 | NSW_BUG_v1.py 173 | NSW_bug.py 174 | NSW_bug/ -------------------------------------------------------------------------------- /CITATION.cff: -------------------------------------------------------------------------------- 1 | cff-version: 2.3.7 2 | message: "If you use this software, please cite it as below." 3 | authors: 4 | - Murray-Darling Basin Authority 5 | 6 | title: "EWR_tool" 7 | version: 2.3.7 8 | doi: 10.5281/zenodo.7435847 9 | date-released: 2025-02-07 10 | -------------------------------------------------------------------------------- /EWR_tool_requirements.txt: -------------------------------------------------------------------------------- 1 | # This file may be used to create an environment using: 2 | # $ conda create --name --file 3 | # platform: linux-64 4 | _libgcc_mutex=0.1=main 5 | argon2-cffi=20.1.0=py36h27cfd23_1 6 | async_generator=1.10=py36h28b3542_0 7 | attrs=20.3.0=pyhd3eb1b0_0 8 | backcall=0.2.0=pyhd3eb1b0_0 9 | blas=1.0=mkl 10 | bleach=3.3.0=pyhd3eb1b0_0 11 | brotlipy=0.7.0=py36h27cfd23_1003 12 | ca-certificates=2021.7.5=h06a4308_1 13 | certifi=2021.5.30=py36h06a4308_0 14 | cffi=1.14.5=py36h261ae71_0 15 | chardet=4.0.0=py36h06a4308_1003 16 | cryptography=3.4.7=py36hd23ed53_0 17 | decorator=5.0.6=pyhd3eb1b0_0 18 | defusedxml=0.7.1=pyhd3eb1b0_0 19 | entrypoints=0.3=py36_0 20 | idna=2.10=pyhd3eb1b0_0 21 | importlib-metadata=3.10.0=py36h06a4308_0 22 | importlib_metadata=3.10.0=hd3eb1b0_0 23 | intel-openmp=2021.2.0=h06a4308_610 24 | ipykernel=5.3.4=py36h5ca1d4c_0 25 | ipython=7.16.1=py36h5ca1d4c_0 26 | ipython_genutils=0.2.0=pyhd3eb1b0_1 27 | ipywidgets=7.6.3=pyhd3eb1b0_1 28 | jedi=0.17.0=py36_0 29 | jinja2=2.11.3=pyhd3eb1b0_0 30 | jsonschema=3.2.0=py_2 31 | jupyter_client=6.1.12=pyhd3eb1b0_0 32 | jupyter_core=4.7.1=py36h06a4308_0 33 | jupyterlab_pygments=0.1.2=py_0 34 | jupyterlab_widgets=1.0.0=pyhd3eb1b0_1 35 | ld_impl_linux-64=2.33.1=h53a641e_7 36 | libffi=3.3=he6710b0_2 37 | libgcc-ng=9.1.0=hdf63c60_0 38 | libsodium=1.0.18=h7b6447c_0 39 | libstdcxx-ng=9.1.0=hdf63c60_0 40 | markupsafe=1.1.1=py36h7b6447c_0 41 | mdba-gauge-getter=0.1=pypi_0 42 | mistune=0.8.4=py36h7b6447c_0 43 | mkl=2020.2=256 44 | mkl-service=2.3.0=py36he8ac12f_0 45 | mkl_fft=1.3.0=py36h54f3939_0 46 | mkl_random=1.1.1=py36h0573a6f_0 47 | nbclient=0.5.3=pyhd3eb1b0_0 48 | nbconvert=6.0.7=py36_0 49 | nbformat=5.1.3=pyhd3eb1b0_0 50 | ncurses=6.2=he6710b0_1 51 | nest-asyncio=1.5.1=pyhd3eb1b0_0 52 | notebook=6.3.0=py36h06a4308_0 53 | numpy=1.19.2=py36h54aff64_0 54 | numpy-base=1.19.2=py36hfa32c7d_0 55 | openssl=1.1.1l=h7f8727e_0 56 | packaging=20.9=pyhd3eb1b0_0 57 | pandas=1.1.3=py36he6710b0_0 58 | pandoc=2.12=h06a4308_0 59 | pandocfilters=1.4.3=py36h06a4308_1 60 | parso=0.8.2=pyhd3eb1b0_0 61 | pexpect=4.8.0=pyhd3eb1b0_3 62 | pickleshare=0.7.5=pyhd3eb1b0_1003 63 | pip=21.0.1=py36h06a4308_0 64 | prometheus_client=0.10.1=pyhd3eb1b0_0 65 | prompt-toolkit=3.0.17=pyh06a4308_0 66 | ptyprocess=0.7.0=pyhd3eb1b0_2 67 | pycparser=2.20=py_2 68 | pygments=2.8.1=pyhd3eb1b0_0 69 | pyopenssl=20.0.1=pyhd3eb1b0_1 70 | pyparsing=2.4.7=pyhd3eb1b0_0 71 | pyrsistent=0.17.3=py36h7b6447c_0 72 | pysocks=1.7.1=py36h06a4308_0 73 | python=3.6.13=hdb3f193_0 74 | python-dateutil=2.8.1=pyhd3eb1b0_0 75 | pytz=2021.1=pyhd3eb1b0_0 76 | pyzmq=20.0.0=py36h2531618_1 77 | readline=8.1=h27cfd23_0 78 | requests=2.25.1=pyhd3eb1b0_0 79 | send2trash=1.5.0=pyhd3eb1b0_1 80 | setuptools=52.0.0=py36h06a4308_0 81 | six=1.15.0=py36h06a4308_0 82 | sqlite=3.35.4=hdfb4753_0 83 | terminado=0.9.4=py36h06a4308_0 84 | testpath=0.4.4=pyhd3eb1b0_0 85 | tk=8.6.10=hbc83047_0 86 | tornado=6.1=py36h27cfd23_0 87 | tqdm=4.59.0=pyhd3eb1b0_1 88 | traitlets=4.3.3=py36_0 89 | typing_extensions=3.7.4.3=pyha847dfd_0 90 | urllib3=1.26.4=pyhd3eb1b0_0 91 | wcwidth=0.2.5=py_0 92 | webencodings=0.5.1=py36_1 93 | wheel=0.36.2=pyhd3eb1b0_0 94 | widgetsnbextension=3.5.1=py36_0 95 | xlsxwriter=3.0.1=pyhd3eb1b0_0 96 | xz=5.2.5=h7b6447c_0 97 | zeromq=4.3.4=h2531618_0 98 | zipp=3.4.1=pyhd3eb1b0_0 99 | zlib=1.2.11=h7b6447c_3 100 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Creative Commons Legal Code 2 | 3 | CC0 1.0 Universal 4 | 5 | CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE 6 | LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN 7 | ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS 8 | INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES 9 | REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS 10 | PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM 11 | THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED 12 | HEREUNDER. 13 | 14 | Statement of Purpose 15 | 16 | The laws of most jurisdictions throughout the world automatically confer 17 | exclusive Copyright and Related Rights (defined below) upon the creator 18 | and subsequent owner(s) (each and all, an "owner") of an original work of 19 | authorship and/or a database (each, a "Work"). 20 | 21 | Certain owners wish to permanently relinquish those rights to a Work for 22 | the purpose of contributing to a commons of creative, cultural and 23 | scientific works ("Commons") that the public can reliably and without fear 24 | of later claims of infringement build upon, modify, incorporate in other 25 | works, reuse and redistribute as freely as possible in any form whatsoever 26 | and for any purposes, including without limitation commercial purposes. 27 | These owners may contribute to the Commons to promote the ideal of a free 28 | culture and the further production of creative, cultural and scientific 29 | works, or to gain reputation or greater distribution for their Work in 30 | part through the use and efforts of others. 31 | 32 | For these and/or other purposes and motivations, and without any 33 | expectation of additional consideration or compensation, the person 34 | associating CC0 with a Work (the "Affirmer"), to the extent that he or she 35 | is an owner of Copyright and Related Rights in the Work, voluntarily 36 | elects to apply CC0 to the Work and publicly distribute the Work under its 37 | terms, with knowledge of his or her Copyright and Related Rights in the 38 | Work and the meaning and intended legal effect of CC0 on those rights. 39 | 40 | 1. Copyright and Related Rights. A Work made available under CC0 may be 41 | protected by copyright and related or neighboring rights ("Copyright and 42 | Related Rights"). Copyright and Related Rights include, but are not 43 | limited to, the following: 44 | 45 | i. the right to reproduce, adapt, distribute, perform, display, 46 | communicate, and translate a Work; 47 | ii. moral rights retained by the original author(s) and/or performer(s); 48 | iii. publicity and privacy rights pertaining to a person's image or 49 | likeness depicted in a Work; 50 | iv. rights protecting against unfair competition in regards to a Work, 51 | subject to the limitations in paragraph 4(a), below; 52 | v. rights protecting the extraction, dissemination, use and reuse of data 53 | in a Work; 54 | vi. database rights (such as those arising under Directive 96/9/EC of the 55 | European Parliament and of the Council of 11 March 1996 on the legal 56 | protection of databases, and under any national implementation 57 | thereof, including any amended or successor version of such 58 | directive); and 59 | vii. other similar, equivalent or corresponding rights throughout the 60 | world based on applicable law or treaty, and any national 61 | implementations thereof. 62 | 63 | 2. Waiver. To the greatest extent permitted by, but not in contravention 64 | of, applicable law, Affirmer hereby overtly, fully, permanently, 65 | irrevocably and unconditionally waives, abandons, and surrenders all of 66 | Affirmer's Copyright and Related Rights and associated claims and causes 67 | of action, whether now known or unknown (including existing as well as 68 | future claims and causes of action), in the Work (i) in all territories 69 | worldwide, (ii) for the maximum duration provided by applicable law or 70 | treaty (including future time extensions), (iii) in any current or future 71 | medium and for any number of copies, and (iv) for any purpose whatsoever, 72 | including without limitation commercial, advertising or promotional 73 | purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each 74 | member of the public at large and to the detriment of Affirmer's heirs and 75 | successors, fully intending that such Waiver shall not be subject to 76 | revocation, rescission, cancellation, termination, or any other legal or 77 | equitable action to disrupt the quiet enjoyment of the Work by the public 78 | as contemplated by Affirmer's express Statement of Purpose. 79 | 80 | 3. Public License Fallback. Should any part of the Waiver for any reason 81 | be judged legally invalid or ineffective under applicable law, then the 82 | Waiver shall be preserved to the maximum extent permitted taking into 83 | account Affirmer's express Statement of Purpose. In addition, to the 84 | extent the Waiver is so judged Affirmer hereby grants to each affected 85 | person a royalty-free, non transferable, non sublicensable, non exclusive, 86 | irrevocable and unconditional license to exercise Affirmer's Copyright and 87 | Related Rights in the Work (i) in all territories worldwide, (ii) for the 88 | maximum duration provided by applicable law or treaty (including future 89 | time extensions), (iii) in any current or future medium and for any number 90 | of copies, and (iv) for any purpose whatsoever, including without 91 | limitation commercial, advertising or promotional purposes (the 92 | "License"). The License shall be deemed effective as of the date CC0 was 93 | applied by Affirmer to the Work. Should any part of the License for any 94 | reason be judged legally invalid or ineffective under applicable law, such 95 | partial invalidity or ineffectiveness shall not invalidate the remainder 96 | of the License, and in such case Affirmer hereby affirms that he or she 97 | will not (i) exercise any of his or her remaining Copyright and Related 98 | Rights in the Work or (ii) assert any associated claims and causes of 99 | action with respect to the Work, in either case contrary to Affirmer's 100 | express Statement of Purpose. 101 | 102 | 4. Limitations and Disclaimers. 103 | 104 | a. No trademark or patent rights held by Affirmer are waived, abandoned, 105 | surrendered, licensed or otherwise affected by this document. 106 | b. Affirmer offers the Work as-is and makes no representations or 107 | warranties of any kind concerning the Work, express, implied, 108 | statutory or otherwise, including without limitation warranties of 109 | title, merchantability, fitness for a particular purpose, non 110 | infringement, or the absence of latent or other defects, accuracy, or 111 | the present or absence of errors, whether or not discoverable, all to 112 | the greatest extent permissible under applicable law. 113 | c. Affirmer disclaims responsibility for clearing rights of other persons 114 | that may apply to the Work or any use thereof, including without 115 | limitation any person's Copyright and Related Rights in the Work. 116 | Further, Affirmer disclaims responsibility for obtaining any necessary 117 | consents, permissions or other rights required for any use of the 118 | Work. 119 | d. Affirmer understands and acknowledges that Creative Commons is not a 120 | party to this document and has no duty or obligation with respect to 121 | this CC0 or use of the Work. 122 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![CI](https://github.com/MDBAuth/EWR_tool/actions/workflows/test-release.yml/badge.svg)]() 2 | [![PyPI - Python Version](https://img.shields.io/pypi/pyversions/py-ewr)](https://pypi.org/project/py-ewr/) 3 | [![PyPI](https://img.shields.io/pypi/v/py-ewr)](https://pypi.org/project/py-ewr/) 4 | [![DOI](https://zenodo.org/badge/342122359.svg)](https://zenodo.org/badge/latestdoi/342122359) 5 | 6 | ### **EWR tool version 2.3.7 README** 7 | 8 | ### **Notes on recent version updates** 9 | - Including metadata report (this is still being ironed out and tested) 10 | - CLLMM_c and CLLMM_d ewrs are now able to be calculated without all barrage level gauges being present in the model file. 11 | - Including draft objective mapping files in the package (see below sub heading **Objective mapping** for more information). Objective mapping has been therefore pulled out of the parameter sheet 12 | - Including an example parallel processing script for running the EWR tool 13 | - Adding handling for cases where there are single MDBA bigmod site IDs mapping to multiple different gauges 14 | - Fix SDL resource unit mapping in the parameter sheet 15 | - Adding lat and lon to the parameter sheet 16 | - ten thousand year handling - this has been brought back online. 17 | - Remove TQDM loading bars 18 | - Adding new model format handling - 'IQQM - netcdf' 19 | - Standard time-series handling added - each column needs a gauge, followed by and underscore, followed by either flow or level (e.g. 409025_flow). This handling also has missing date filling - so any missing dates will be filled with NaN values in all columns. 20 | - bug fixes: spells of length equal to the minimum required spell length were getting filtered out of the successful events table and successful interevents table, fixed misclassification of some gauges to flow, level, and lake level categories 21 | - New EWRs: New Qld EWRs - SF_FD and BF_FD used to look into the FD EWRs in closer detail. 22 | - Adding state and Surface Water SDL (SWSDL) to py-ewr output tables 23 | 24 | ### **Installation** 25 | 26 | Note - requires Python 3.9 to 3.13 (inclusive) 27 | 28 | Step 1. 29 | Upgrade pip 30 | ```bash 31 | python -m pip install –-upgrade pip 32 | ``` 33 | 34 | Step 2. 35 | ```bash 36 | pip install py-ewr 37 | ``` 38 | 39 | ### Option 1: Running the observed mode of the tool 40 | The EWR tool will use a second program called gauge getter to first download the river data at the locations and dates selected and then run this through the EWR tool 41 | 42 | ```python 43 | 44 | from datetime import datetime 45 | 46 | #USER INPUT REQUIRED>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 47 | 48 | dates = {'start_date': datetime(YYYY, 7, 1), 49 | 'end_date': datetime(YYYY, 6, 30)} 50 | 51 | gauges = ['Gauge1', 'Gauge2'] 52 | 53 | # END USER INPUT<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 54 | 55 | ``` 56 | 57 | ```python 58 | 59 | from py_ewr.observed_handling import ObservedHandler 60 | 61 | # Running the EWR tool: 62 | ewr_oh = ObservedHandler(gauges=gauges, dates=dates) 63 | 64 | # Generating tables: 65 | # Table 1: Summarised EWR results for the entire timeseries 66 | ewr_results = ewr_oh.get_ewr_results() 67 | 68 | # Table 2: Summarised EWR results, aggregated to water years: 69 | yearly_ewr_results = ewr_oh.get_yearly_ewr_results() 70 | 71 | # Table 3: All events details regardless of duration 72 | all_events = ewr_oh.get_all_events() 73 | 74 | # Table 4: Inverse of Table 3 showing the interevent periods 75 | all_interEvents = ewr_oh.get_all_interEvents() 76 | 77 | # Table 5: All events details that also meet the duration requirement: 78 | all_successfulEvents = ewr_oh.get_all_successful_events() 79 | 80 | # Table 6: Inverse of Table 5 showing the interevent periods: 81 | all_successful_interEvents = ewr_oh.get_all_successful_interEvents() 82 | 83 | ``` 84 | 85 | ### Option 2: Running model scenarios through the EWR tool 86 | 87 | 1. Tell the tool where the model files are (can either be local or in a remote location) 88 | 2. Tell the tool what format the model files are in. The current model format options are: 89 | - 'Bigmod - MDBA' 90 | Bigmod formatted outputs 91 | - 'Source - NSW (res.csv)' 92 | Source res.csv formatted outputs 93 | - 'Standard time-series' 94 | The first column header should be *Date* with the date values in the YYYY-MM-DD format. 95 | The next columns should have the *gauge* followed by *_* followed by either *flow* or *level* 96 | E.g. 97 | | Date | 409025_flow | 409025_level | 414203_flow | 98 | | --- | --- | --- | --- | 99 | | 1895-07-01 | 8505 | 5.25 | 8500 | 100 | | 1895-07-02 | 8510 | 5.26 | 8505 | 101 | 102 | - 'ten thousand year' 103 | This has the same formatting requirements as the 'Standard time-series'. This can handle ten thousand years worth of hydrology data. 104 | The first column header should be *Date* with the date values in the YYYY-MM-DD format. 105 | The next columns should have the *gauge* followed by *_* followed by either *flow* or *level* 106 | E.g. 107 | | Date | 409025_flow | 409025_level | 414203_flow | 108 | | --- | --- | --- | --- | 109 | | 105-07-01 | 8505 | 5.25 | 8500 | 110 | | 105-07-02 | 8510 | 5.26 | 8505 | 111 | 112 | 113 | ```python 114 | #USER INPUT REQUIRED>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 115 | 116 | # Minimum 1 scenario and 1 related file required 117 | scenarios = {'Scenario1': ['file/location/1', 'file/location/2', 'file/location/3'], 118 | 'Scenario2': ['file/location/1', 'file/location/2', 'file/location/3']} 119 | 120 | model_format = 'Bigmod - MDBA' 121 | 122 | # END USER INPUT<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 123 | 124 | ``` 125 | 126 | ``` python 127 | from py_ewr.scenario_handling import ScenarioHandler 128 | import pandas as pd 129 | 130 | ewr_results_dict = {} 131 | yearly_results_dict = {} 132 | all_events_dict = {} 133 | all_interEvents_dict = {} 134 | all_successful_Events_dict = {} 135 | all_successful_interEvents_dict = {} 136 | 137 | for scenario_name, scenario_list in scenarios.items(): 138 | ewr_results = pd.DataFrame() 139 | yearly_ewr_results = pd.DataFrame() 140 | all_events = pd.DataFrame() 141 | all_interEvents = pd.DataFrame() 142 | all_successful_Events = pd.DataFrame() 143 | all_successful_interEvents = pd.DataFrame() 144 | for file in scenarios[scenario_name]: 145 | 146 | # Running the EWR tool: 147 | ewr_sh = ScenarioHandler(scenario_file = file, 148 | model_format = model_format) 149 | 150 | # Return each table and stitch the different files of the same scenario together: 151 | # Table 1: Summarised EWR results for the entire timeseries 152 | temp_ewr_results = ewr_sh.get_ewr_results() 153 | ewr_results = pd.concat([ewr_results, temp_ewr_results], axis = 0) 154 | # Table 2: Summarised EWR results, aggregated to water years: 155 | temp_yearly_ewr_results = ewr_sh.get_yearly_ewr_results() 156 | yearly_ewr_results = pd.concat([yearly_ewr_results, temp_yearly_ewr_results], axis = 0) 157 | # Table 3: All events details regardless of duration 158 | temp_all_events = ewr_sh.get_all_events() 159 | all_events = pd.concat([all_events, temp_all_events], axis = 0) 160 | # Table 4: Inverse of Table 3 showing the interevent periods 161 | temp_all_interEvents = ewr_sh.get_all_interEvents() 162 | all_interEvents = pd.concat([all_interEvents, temp_all_interEvents], axis = 0) 163 | # Table 5: All events details that also meet the duration requirement: 164 | temp_all_successfulEvents = ewr_sh.get_all_successful_events() 165 | all_successful_Events = pd.concat([all_successful_Events, temp_all_successfulEvents], axis = 0) 166 | # Table 6: Inverse of Table 5 showing the interevent periods: 167 | temp_all_successful_interEvents = ewr_sh.get_all_successful_interEvents() 168 | all_successful_interEvents = pd.concat([all_successful_interEvents, temp_all_successful_interEvents], axis = 0) 169 | 170 | 171 | # Optional code to output results to csv files: 172 | ewr_results.to_csv(scenario_name + 'all_results.csv') 173 | yearly_ewr_results.to_csv(scenario_name + 'yearly_ewr_results.csv') 174 | all_events.to_csv(scenario_name + 'all_events.csv') 175 | all_interEvents.to_csv(scenario_name + 'all_interevents.csv') 176 | all_successful_Events.to_csv(scenario_name + 'all_successful_Events.csv') 177 | all_successful_interEvents.to_csv(scenario_name + 'all_successful_interEvents.csv') 178 | 179 | # Save the final tables to the dictionaries: 180 | ewr_results_dict[scenario_name] = ewr_results 181 | yearly_results_dict[scenario_name] = yearly_ewr_results 182 | all_events_dict[scenario_name] = all_events_dict 183 | all_interEvents_dict[scenario_name] = all_interEvents 184 | all_successful_Events_dict[scenario_name] = all_successful_Events 185 | all_successful_interEvents_dict[scenario_name] = all_successful_interEvents 186 | 187 | 188 | ``` 189 | 190 | 191 | ### **Purpose** 192 | This tool has two purposes: 193 | 1. Operational: Tracking EWR success at gauges of interest in real time - option 1 above. 194 | 2. Planning: Comparing EWR success between scenarios (i.e. model runs) - option 2 above. 195 | 196 | **Support** 197 | For issues relating to the script, a tutorial, or feedback please contact Lara Palmer at lara.palmer@mdba.gov.au, Martin Job at martin.job@mdba.gov.au, or Joel Bailey at joel.bailey@mdba.gov.au 198 | 199 | 200 | **Disclaimer** 201 | Every effort has been taken to ensure the EWR database represents the original EWRs from state Long Term Water Plans (LTWPs) and Environmental Water Management Plans (EWMPs) as best as possible, and that the code within this tool has been developed to interpret and analyse these EWRs in an accurate way. However, there may still be unresolved bugs in the EWR parameter sheet and/or EWR tool. Please report any bugs to the issues tab under the GitHub project so we can investigate further. 202 | 203 | 204 | **Notes on development of the dataset of EWRs** 205 | The MDBA has worked with Basin state representatives to ensure scientific integrity of EWRs has been maintained when translating from raw EWRs in the Basin state LTWPs and EWMPs to the machine readable format found in the parameter sheet within this tool. 206 | 207 | **Compatibility** 208 | 209 | NSW: 210 | - All Queensland catchments 211 | - All New South Wales catchments 212 | - All South Australian catchments 213 | - All EWRs from river based Environmental Water Management Plans (EWMPs) in Victoria* 214 | 215 | *Currently the wetland EWMPS and mixed wetland-river EWMPs in Victoria contain EWRs that cannot be evaluated by an automated EWR tool so the EWRs from these plans have been left out for now. The MDBA will work with our Victorian colleagues to ensure any updated EWRs in these plans are integrated into the tool where possible. 216 | 217 | **Input data** 218 | 219 | - Gauge data from the relevant Basin state websites and the Bureau of Meteorology website 220 | - Scenario data input by the user 221 | - Model metadata for location association between gauge ID's and model nodes 222 | - EWR parameter sheet 223 | 224 | **Running the tool** 225 | 226 | Consult the user manual for instructions on how to run the tool. Please email the above email addresses for a copy of the user manual. 227 | 228 | **Objective mapping** 229 | Objective mapping csv files are now included in the EWR tool package. Currently this objective mapping is in an early draft format. The objective mapping will be finalised after consultation with relevant state representatives. The files are intended to be used together to link EWRs to the detailed objectives, theme level targets and specific goals. The three sheets are located in the py_ewr/parameter_metadata folder: 230 | - ewr2obj.csv: For each planning unit, gauge, ewr combination there are either one or many env_obj codes. These env_obj codes come under one of five different theme level targets (Native Fish, Native vegetation, Waterbirds, Other species or Ecosystem functions) 231 | - obj2target.csv: env_obj's are unique to their planning unit in the LTWP (noting there are often a lot of similarities between env_obj's in the same states). The plain english wording of the env objectives is also contained in this csv. The LTWP, planning unit and env_obj rows are repeated for each specific goal related to that LTWP, planning unit and env_obj. 232 | - obj2yrtarget.csv: The environmental objectives are related to 5, 10 and 20 year targets 233 | -------------------------------------------------------------------------------- /example_parallel_run.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import multiprocessing as mp 3 | import os 4 | 5 | from py_ewr.scenario_handling import ScenarioHandler 6 | 7 | #####--------------------- DEFINE EWR TOOL RUN FUCTION -------------------------##### 8 | 9 | def run_EWR_tool( 10 | scenario_name, 11 | scenario_files, 12 | model_format 13 | ): 14 | 15 | ewr_results = pd.DataFrame() 16 | yearly_ewr_results = pd.DataFrame() 17 | all_events = pd.DataFrame() 18 | all_interEvents = pd.DataFrame() 19 | all_successful_Events = pd.DataFrame() 20 | all_successful_interEvents = pd.DataFrame() 21 | 22 | for file in scenario_files: 23 | # Running the EWR tool: 24 | ewr_sh = ScenarioHandler(scenario_file=file, model_format=model_format) 25 | 26 | # Return each table and stitch the different files of the same scenario together: 27 | # Table 1: Summarised EWR results for the entire timeseries 28 | temp_ewr_results = ewr_sh.get_ewr_results() 29 | ewr_results = pd.concat([ewr_results, temp_ewr_results], axis=0) 30 | # Table 2: Summarised EWR results, aggregated to water years: 31 | temp_yearly_ewr_results = ewr_sh.get_yearly_ewr_results() 32 | yearly_ewr_results = pd.concat( 33 | [yearly_ewr_results, temp_yearly_ewr_results], axis=0 34 | ) 35 | # Table 3: All events details regardless of duration 36 | temp_all_events = ewr_sh.get_all_events() 37 | all_events = pd.concat([all_events, temp_all_events], axis=0) 38 | # Table 4: Inverse of Table 3 showing the interevent periods 39 | temp_all_interEvents = ewr_sh.get_all_interEvents() 40 | all_interEvents = pd.concat([all_interEvents, temp_all_interEvents], axis=0) 41 | # Table 5: All events details that also meet the duration requirement: 42 | temp_all_successfulEvents = ewr_sh.get_all_successful_events() 43 | all_successful_Events = pd.concat( 44 | [all_successful_Events, temp_all_successfulEvents], axis=0 45 | ) 46 | # Table 6: Inverse of Table 5 showing the interevent periods: 47 | temp_all_successful_interEvents = ewr_sh.get_all_successful_interEvents() 48 | all_successful_interEvents = pd.concat( 49 | [all_successful_interEvents, temp_all_successful_interEvents], axis=0 50 | ) 51 | 52 | ewr_results.to_csv(scenario_name + "_all_results.csv") 53 | yearly_ewr_results.to_csv(scenario_name + "_yearly_ewr_results.csv") 54 | all_events.to_csv(scenario_name + "_all_events.csv") 55 | all_interEvents.to_csv(scenario_name + "_all_interevents.csv") 56 | all_successful_Events.to_csv(scenario_name + "_all_successful_Events.csv") 57 | all_successful_interEvents.to_csv(scenario_name + "_all_successful_interEvents.csv") 58 | 59 | 60 | #####----------------------- RUN EWR_TOOL IN PARALLEL --------------------------##### 61 | 62 | # get the number of cores 63 | num_processes = os.cpu_count() 64 | 65 | if __name__ == "__main__": 66 | 67 | # OPTIONAL USER INPUT>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 68 | # define number of cores here manually: 69 | # default is all available cores (num_processes) replace with intger eg. processes = 4 70 | 71 | pool = mp.Pool(processes = num_processes) 72 | 73 | # END OPTIONAL USER INPUT<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 74 | 75 | # USER INPUT REQUIRED>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> 76 | 77 | # Minimum 1 scenario and 1 related file required 78 | scenarios = { 79 | "Scenario1": ["file/location/1", "file/location/2", "file/location/3"], 80 | "Scenario2": ["file/location/1", "file/location/2", "file/location/3"], 81 | } 82 | 83 | # model format 84 | model_format = "Bigmod - MDBA" 85 | 86 | # END USER INPUT<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<< 87 | 88 | # argument list for the run_EWR tool function 89 | args_list = [ 90 | (scenario_name, scenario_files, model_format) 91 | for scenario_name, scenario_files in scenarios.items() 92 | ] 93 | 94 | pool.starmap(run_EWR_tool, args_list) 95 | pool.close() 96 | pool.join() 97 | 98 | 99 | 100 | -------------------------------------------------------------------------------- /license.amltmp: -------------------------------------------------------------------------------- 1 | Creative Commons Legal Code 2 | 3 | CC0 1.0 Universal 4 | 5 | CREATIVE COMMONS CORPORATION IS NOT A LAW FIRM AND DOES NOT PROVIDE 6 | LEGAL SERVICES. DISTRIBUTION OF THIS DOCUMENT DOES NOT CREATE AN 7 | ATTORNEY-CLIENT RELATIONSHIP. CREATIVE COMMONS PROVIDES THIS 8 | INFORMATION ON AN "AS-IS" BASIS. CREATIVE COMMONS MAKES NO WARRANTIES 9 | REGARDING THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS 10 | PROVIDED HEREUNDER, AND DISCLAIMS LIABILITY FOR DAMAGES RESULTING FROM 11 | THE USE OF THIS DOCUMENT OR THE INFORMATION OR WORKS PROVIDED 12 | HEREUNDER. 13 | 14 | Statement of Purpose 15 | 16 | The laws of most jurisdictions throughout the world automatically confer 17 | exclusive Copyright and Related Rights (defined below) upon the creator 18 | and subsequent owner(s) (each and all, an "owner") of an original work of 19 | authorship and/or a database (each, a "Work"). 20 | 21 | Certain owners wish to permanently relinquish those rights to a Work for 22 | the purpose of contributing to a commons of creative, cultural and 23 | scientific works ("Commons") that the public can reliably and without fear 24 | of later claims of infringement build upon, modify, incorporate in other 25 | works, reuse and redistribute as freely as possible in any form whatsoever 26 | and for any purposes, including without limitation commercial purposes. 27 | These owners may contribute to the Commons to promote the ideal of a free 28 | culture and the further production of creative, cultural and scientific 29 | works, or to gain reputation or greater distribution for their Work in 30 | part through the use and efforts of others. 31 | 32 | For these and/or other purposes and motivations, and without any 33 | expectation of additional consideration or compensation, the person 34 | associating CC0 with a Work (the "Affirmer"), to the extent that he or she 35 | is an owner of Copyright and Related Rights in the Work, voluntarily 36 | elects to apply CC0 to the Work and publicly distribute the Work under its 37 | terms, with knowledge of his or her Copyright and Related Rights in the 38 | Work and the meaning and intended legal effect of CC0 on those rights. 39 | 40 | 1. Copyright and Related Rights. A Work made available under CC0 may be 41 | protected by copyright and related or neighboring rights ("Copyright and 42 | Related Rights"). Copyright and Related Rights include, but are not 43 | limited to, the following: 44 | 45 | i. the right to reproduce, adapt, distribute, perform, display, 46 | communicate, and translate a Work; 47 | ii. moral rights retained by the original author(s) and/or performer(s); 48 | iii. publicity and privacy rights pertaining to a person's image or 49 | likeness depicted in a Work; 50 | iv. rights protecting against unfair competition in regards to a Work, 51 | subject to the limitations in paragraph 4(a), below; 52 | v. rights protecting the extraction, dissemination, use and reuse of data 53 | in a Work; 54 | vi. database rights (such as those arising under Directive 96/9/EC of the 55 | European Parliament and of the Council of 11 March 1996 on the legal 56 | protection of databases, and under any national implementation 57 | thereof, including any amended or successor version of such 58 | directive); and 59 | vii. other similar, equivalent or corresponding rights throughout the 60 | world based on applicable law or treaty, and any national 61 | implementations thereof. 62 | 63 | 2. Waiver. To the greatest extent permitted by, but not in contravention 64 | of, applicable law, Affirmer hereby overtly, fully, permanently, 65 | irrevocably and unconditionally waives, abandons, and surrenders all of 66 | Affirmer's Copyright and Related Rights and associated claims and causes 67 | of action, whether now known or unknown (including existing as well as 68 | future claims and causes of action), in the Work (i) in all territories 69 | worldwide, (ii) for the maximum duration provided by applicable law or 70 | treaty (including future time extensions), (iii) in any current or future 71 | medium and for any number of copies, and (iv) for any purpose whatsoever, 72 | including without limitation commercial, advertising or promotional 73 | purposes (the "Waiver"). Affirmer makes the Waiver for the benefit of each 74 | member of the public at large and to the detriment of Affirmer's heirs and 75 | successors, fully intending that such Waiver shall not be subject to 76 | revocation, rescission, cancellation, termination, or any other legal or 77 | equitable action to disrupt the quiet enjoyment of the Work by the public 78 | as contemplated by Affirmer's express Statement of Purpose. 79 | 80 | 3. Public License Fallback. Should any part of the Waiver for any reason 81 | be judged legally invalid or ineffective under applicable law, then the 82 | Waiver shall be preserved to the maximum extent permitted taking into 83 | account Affirmer's express Statement of Purpose. In addition, to the 84 | extent the Waiver is so judged Affirmer hereby grants to each affected 85 | person a royalty-free, non transferable, non sublicensable, non exclusive, 86 | irrevocable and unconditional license to exercise Affirmer's Copyright and 87 | Related Rights in the Work (i) in all territories worldwide, (ii) for the 88 | maximum duration provided by applicable law or treaty (including future 89 | time extensions), (iii) in any current or future medium and for any number 90 | of copies, and (iv) for any purpose whatsoever, including without 91 | limitation commercial, advertising or promotional purposes (the 92 | "License"). The License shall be deemed effective as of the date CC0 was 93 | applied by Affirmer to the Work. Should any part of the License for any 94 | reason be judged legally invalid or ineffective under applicable law, such 95 | partial invalidity or ineffectiveness shall not invalidate the remainder 96 | of the License, and in such case Affirmer hereby affirms that he or she 97 | will not (i) exercise any of his or her remaining Copyright and Related 98 | Rights in the Work or (ii) assert any associated claims and causes of 99 | action with respect to the Work, in either case contrary to Affirmer's 100 | express Statement of Purpose. 101 | 102 | 4. Limitations and Disclaimers. 103 | 104 | a. No trademark or patent rights held by Affirmer are waived, abandoned, 105 | surrendered, licensed or otherwise affected by this document. 106 | b. Affirmer offers the Work as-is and makes no representations or 107 | warranties of any kind concerning the Work, express, implied, 108 | statutory or otherwise, including without limitation warranties of 109 | title, merchantability, fitness for a particular purpose, non 110 | infringement, or the absence of latent or other defects, accuracy, or 111 | the present or absence of errors, whether or not discoverable, all to 112 | the greatest extent permissible under applicable law. 113 | c. Affirmer disclaims responsibility for clearing rights of other persons 114 | that may apply to the Work or any use thereof, including without 115 | limitation any person's Copyright and Related Rights in the Work. 116 | Further, Affirmer disclaims responsibility for obtaining any necessary 117 | consents, permissions or other rights required for any use of the 118 | Work. 119 | d. Affirmer understands and acknowledges that Creative Commons is not a 120 | party to this document and has no duty or obligation with respect to 121 | this CC0 or use of the Work. 122 | -------------------------------------------------------------------------------- /py_ewr/.amlignore: -------------------------------------------------------------------------------- 1 | ## This file was auto generated by the Azure Machine Learning Studio. Please do not remove. 2 | ## Read more about the .amlignore file here: https://docs.microsoft.com/azure/machine-learning/how-to-save-write-experiment-files#storage-limits-of-experiment-snapshots 3 | 4 | .ipynb_aml_checkpoints/ 5 | *.amltmp 6 | *.amltemp -------------------------------------------------------------------------------- /py_ewr/.amlignore.amltmp: -------------------------------------------------------------------------------- 1 | ## This file was auto generated by the Azure Machine Learning Studio. Please do not remove. 2 | ## Read more about the .amlignore file here: https://docs.microsoft.com/azure/machine-learning/how-to-save-write-experiment-files#storage-limits-of-experiment-snapshots 3 | 4 | .ipynb_aml_checkpoints/ 5 | *.amltmp 6 | *.amltemp -------------------------------------------------------------------------------- /py_ewr/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MDBAuth/EWR_tool/467885c638d1c8f86cbb822af56f3fac38801828/py_ewr/__init__.py -------------------------------------------------------------------------------- /py_ewr/io.py: -------------------------------------------------------------------------------- 1 | import xarray as xr 2 | from pandas import DataFrame as Dataframe 3 | 4 | 5 | def read_netcdf_as_dataframe(netcdf_path: str) -> Dataframe: 6 | dataset = xr.open_dataset(netcdf_path, engine='netcdf4') 7 | df = dataset.to_dataframe() 8 | dataset.close() 9 | 10 | return df 11 | 12 | 13 | def save_dataframe_as_netcdf(df, output_path: str) -> None: 14 | # Convert DataFrame to Xarray Dataset 15 | ds = xr.Dataset.from_dataframe(df) 16 | 17 | # Modify variable names to ensure they are valid for NetCDF 18 | for var_name in ds.variables: 19 | new_var_name = var_name.replace(" ", "_") # Replace spaces with underscores 20 | new_var_name = ''.join(c for c in new_var_name if c.isalnum() or c == "_") # Remove non-alphanumeric characters 21 | ds = ds.rename({var_name: new_var_name}) 22 | 23 | # Save the modified Xarray Dataset as a NetCDF file 24 | ds.to_netcdf(output_path) -------------------------------------------------------------------------------- /py_ewr/model_metadata/.amlignore: -------------------------------------------------------------------------------- 1 | ## This file was auto generated by the Azure Machine Learning Studio. Please do not remove. 2 | ## Read more about the .amlignore file here: https://docs.microsoft.com/azure/machine-learning/how-to-save-write-experiment-files#storage-limits-of-experiment-snapshots 3 | 4 | .ipynb_aml_checkpoints/ 5 | *.amltmp 6 | *.amltemp -------------------------------------------------------------------------------- /py_ewr/model_metadata/.amlignore.amltmp: -------------------------------------------------------------------------------- 1 | ## This file was auto generated by the Azure Machine Learning Studio. Please do not remove. 2 | ## Read more about the .amlignore file here: https://docs.microsoft.com/azure/machine-learning/how-to-save-write-experiment-files#storage-limits-of-experiment-snapshots 3 | 4 | .ipynb_aml_checkpoints/ 5 | *.amltmp 6 | *.amltemp -------------------------------------------------------------------------------- /py_ewr/model_metadata/SiteID_NSW.csv: -------------------------------------------------------------------------------- 1 | SITEID,Name,Description,AWRC,StateID 2 | Gauge: 410001 Murrumbidgee River at Wagga Wagga: Downstream Flow,Wagga gauge,,410001,2 3 | Gauge: 410005 Murrumbidgee River at Narrandera: Downstream Flow,Narrandera gauge,,410005,2 4 | Gauge: 410006 Tumut River at Tumut: Downstream Flow,Tumut River (from Blowering Dam to junction with Murrumbidgee) (as measured at Tumut town gauge),,410006,2 5 | Gauge: 410008 Murrumbidgee River at DS Burrinjuck Dam: Downstream Flow,Tumut Junction as measured at downstream Burrinjuck gauge ,,410008,2 6 | Gauge: 410021 Murrumbidgee River at Darlington Point: Downstream Flow,Darlington Point gauge,,410021,2 7 | Gauge: 410040 Murrumbidgee River at DS Maude Weir: Downstream Flow,downstream Maude Weir - Maude gauge,,410040,2 8 | Gauge: 410093 Old Man Creek at Kywong_Topreeds: Downstream Flow,Old Man Creek at Kywong,,410093,2 9 | Gauge: 410130 Murrumbidgee River at DS Balranald Weir: Downstream Flow,Murrumbidgee River @ Balranald Weir,,410130,2 10 | Gauge: 410007 Yanco Creek at Offtake: Downstream Flow,Yanco Creek at Offtake,,410007,2 11 | Gauge: 410014 Colombo Creek at Morundah: Downstream Flow,Colombo Creek at Morundah,,410014,2 12 | Gauge: 410015 Yanco Creek at Morundah: Downstream Flow,Yanco Creek at Morundah,,410015,2 13 | Gauge: 410016 Billabong Creek at Jerilderie: Downstream Flow,Billabong Creek at Jerilderie ,,410016,2 14 | Gauge: 410134 Billabong Creek at Darlot: Downstream Flow,Billabong Creek at Darlot,,410134,4 15 | Environmental Flow: Eflow Nimmie-Caira: Downstream Flow,"Gayini/ Nimmie-Caira, combined Eulimbah and Nimmie Creek regulators",,"Eulimbah, Nimmie Creek",2 16 | Environmental Flow: Eflow Yanga: Downstream Flow,Yanga (South Redbank),,Pumped from Yanga Lake,2 17 | Environmental Flow: Eflow Glen Dee: Downstream Flow,North Redbank,,Glen Dee,2 18 | Environmental Flow: Eflow Pattos Pipe: Downstream Flow,North Redbank,,Pattos Pipe,2 19 | Environmental Flow: Eflow Bills Pipe: Downstream Flow,North Redbank,,Bills Pipe,2 20 | Environmental Flow: LF3 Pump direct from river: Downstream Flow,"North Redbank, pumped direct from river",,Pump direct from river,2 21 | Environmental Flow: Eflow Glen Dee: Downstream Flow,"Western Lakes, Glenn Dee",,Glen Dee,2 22 | Environmental Flow: Eflow Yanga: Downstream Flow,Yanga (South Redbank) 1AS,,1AS,2 23 | 5>Edward River @ DS Stevens Weir (409023)>Downstream Flow,DS Stevens Weir,,409023,2 24 | Gauge: River Murray @ DS Yarrawonga (409025): Downstream Flow,Yarrawonga,,409025,2 25 | Gauge: 410006 Tumut River at Tumut: Downstream Flow,Tumut,,410006,2 26 | Gauge: 410008 Murrumbidgee River at DS Burrinjuck Dam: Downstream Flow,DS Burrinjuck,,410008,2 27 | Gauge: 410001 Murrumbidgee River at Wagga Wagga: Downstream Flow,Wagga Wagga,,410001,2 28 | Gauge: 410005 Murrumbidgee River at Narrandera: Downstream Flow,Narrandera,,410005,2 29 | Gauge: 410021 Murrumbidgee River at Darlington Point: Downstream Flow,Darlington Point,,410021,2 30 | Gauge: 410040 Murrumbidgee River at DS Maude Weir: Downstream Flow,DS Maude Weir,,410040,2 31 | Gauge: 410130 Murrumbidgee River at DS Balranald Weir: Downstream Flow,DS Balranald,,410130,2 32 | Gauge: 410093 Old Man Creek at Kywong_Topreeds: Downstream Flow,Kywong,,410093,2 33 | Gauge: 410007 Yanco Creek at Offtake: Downstream Flow,Yanco Creek,,410007,2 34 | Gauge: 410014 Colombo Creek at Morundah: Downstream Flow,Colombo at Morundah,,410014,2 35 | Gauge: 410016 Billabong Creek at Jerilderie: Downstream Flow,Jerilderie,,410016,2 36 | Gauge: 410015 Yanco Creek at Morundah: Downstream Flow,Yanco at Morundah,,410015,2 37 | Gauge: 410134 Billabong Creek at Darlot: Downstream Flow,Darlot,,410134,2 38 | Gauge: Darling River @ Burtundy (425007): Downstream Flow,Darling River @ Burtundy,,425007, 39 | Gauge: Darling River @ Pooncarie (425005): Downstream Flow,Darling River @ Pooncarie,,425005, 40 | Gauge: Darling River @ Weir 32 (425012): Downstream Flow,Darling River @ Weir 32,,425012, 41 | Gauge: Edward River @ Deniliquin (409003): Downstream Flow,Edward River @ Deniliquin,,409003, 42 | Gauge: Edward River @ DS Stevens Weir (409023): Downstream Flow,Edward River @ DS Stevens Weir,,409023, 43 | Gauge: Edward River @ Liewah (409035): Downstream Flow,Edward River @ Liewah,,409035, 44 | Gauge: Edward River @ Moulamein (409014): Downstream Flow,Edward River @ Moulamein,,409014, 45 | Gauge: Edward River @ Toonalook (409047): Downstream Flow,Edward River @ Toonalook,,409047, 46 | Gauge: Niemur River @ Barham-Wakool Rd (409048): Downstream Flow,Niemur River @ Barham-Wakool Rd,,409048, 47 | Gauge: Niemur River @ Mallan School (409086): Downstream Flow,Niemur River @ Mallan School,,409086, 48 | Gauge: River Murray @ Barmah (409215): Downstream Flow,River Murray @ Barmah,,409215, 49 | Gauge: River Murray @ Colignan (414207): Downstream Flow,River Murray @ Colignan,,414207, 50 | Gauge: River Murray @ Corowa (409002): Downstream Flow,River Murray @ Corowa,,409002, 51 | Gauge: River Murray @ Doctors Point (409017): Downstream Flow,River Murray @ Doctors Point,,409017, 52 | Gauge: River Murray @ DS Euston (414203): Downstream Flow,River Murray @ DS Euston,,414203, 53 | Gauge: River Murray @ DS Torrumbarry (409207): Downstream Flow,River Murray @ DS Torrumbarry,,409207, 54 | Gauge: River Murray @ DS Yarrawonga (409025): Downstream Flow,River Murray @ DS Yarrawonga,,409025, 55 | Gauge: River Murray @ Lock 11 (414202): Downstream Flow,River Murray @ Lock 11,,414202, 56 | Gauge: River Murray @ Lock 7 US (426508): Downstream Flow,River Murray @ Lock 7 US,,426508, 57 | Gauge: River Murray @ Lock 8 US (426506): Downstream Flow,River Murray @ Lock 8 US,,426506, 58 | Gauge: River Murray @ Lock 9 US(426501): Downstream Flow,River Murray @ Lock 9 US,,426501, 59 | Gauge: River Murray @ Swan Hill (409204): Downstream Flow,River Murray @ Swan Hill,,409204, 60 | Gauge: River Murray @ Tocumwal (409202): Downstream Flow,River Murray @ Tocumwal,,409202, 61 | Gauge: River Murray @ Wakool Junction (414200): Downstream Flow,River Murray @ Wakool Junction,,414200, 62 | Gauge: River Murray @ Wentworth (425010): Downstream Flow,River Murray @ Wentworth,,425010, 63 | Gauge: Wakool River @ Barham Rd (409045): Downstream Flow,Wakool River @ Barham Rd,,409045, 64 | Gauge: Wakool River @ Gee Gee Bridge (409062): Downstream Flow,Wakool River @ Gee Gee Bridge,,409062, 65 | Gauge: Wakool River @ Stoney Crossing (409013): Downstream Flow,Wakool River @ Stoney Crossing,,409013, 66 | Gauge: Wakool River @ Wakool-Deniliquin Road (409072): Downstream Flow,Wakool River @ Wakool-Deniliquin Road,,409072, 67 | Inflow: Billabong Creek @ Darlot (410134): Downstream Flow,Billabong Creek @ Darlot,,410134, 68 | Inflow: Campaspe River @ Rochester (406202): Downstream Flow,Campaspe River @ Rochester,,406202, 69 | Inflow: Goulburn River @ McCoys Bridge (405232): Downstream Flow,Goulburn River @ McCoys Bridge,,405232, 70 | Inflow: Murrumbidgee River @ Balranald (410130): Downstream Flow,Murrumbidgee River @ Balranald,,410130, 71 | Inflow: Ovens River @ Peechelba (403241A): Downstream Flow,Ovens River @ Peechelba,,403241A, 72 | -------------------------------------------------------------------------------- /py_ewr/model_metadata/iqqm_stations.csv: -------------------------------------------------------------------------------- 1 | IQQM,gauge 2 | 229,421023 3 | 42,421001 4 | 464,421011 5 | 240,421019 6 | 266,421146 7 | 951,421090 8 | 487,421022 9 | 130,421012 10 | 171,421004 11 | 12 | -------------------------------------------------------------------------------- /py_ewr/observed_handling.py: -------------------------------------------------------------------------------- 1 | from datetime import timedelta, date, datetime 2 | from typing import Dict, List 3 | import logging 4 | 5 | import pandas as pd 6 | import numpy as np 7 | 8 | from . import data_inputs, evaluate_EWRs, summarise_results, scenario_handling 9 | from mdba_gauge_getter import gauge_getter as gg 10 | 11 | log = logging.getLogger(__name__) 12 | log.addHandler(logging.NullHandler()) 13 | 14 | 15 | def categorise_gauges(gauges: list, ewr_table_path:str = None) -> tuple: 16 | '''Separate gauges into level, flow, or both 17 | 18 | Args: 19 | gauges (list): List of user defined gauges 20 | 21 | Results: 22 | tuple[list, list]: A list of flow gauges; A list of water level gauges 23 | 24 | ''' 25 | lake_level_gauges = [] 26 | level_gauges = [] 27 | flow_gauges = [] 28 | 29 | EWR_TABLE, _ = data_inputs.get_EWR_table(ewr_table_path) 30 | 31 | # if ewr_table_path: 32 | level_gauges_to_add = EWR_TABLE[EWR_TABLE['GaugeType']=='L']['Gauge'].to_list() 33 | # only add gauges if in the incoming list 34 | for gauge in level_gauges_to_add: 35 | if gauge in gauges: 36 | level_gauges.append(gauge) 37 | lake_level_gauges_to_add = EWR_TABLE[EWR_TABLE['GaugeType']=='LL']['Gauge'].to_list() 38 | for gauge in lake_level_gauges_to_add: 39 | if gauge in gauges: 40 | lake_level_gauges.append(gauge) 41 | flow_gauges_to_add = EWR_TABLE[EWR_TABLE['GaugeType']=='F']['Gauge'].to_list() 42 | for gauge in flow_gauges_to_add: 43 | if gauge in gauges: 44 | flow_gauges.append(gauge) 45 | 46 | weirpool_gauges_to_add = [ i for i in EWR_TABLE['WeirpoolGauge'].to_list() if type(i) == str] 47 | weirpool_gauges_to_add = [i for i in weirpool_gauges_to_add if i ] 48 | if weirpool_gauges_to_add: 49 | for gauge in weirpool_gauges_to_add: 50 | if gauge in gauges: 51 | level_gauges.append(gauge) 52 | # lake_level_gauges.append(gauge) 53 | 54 | # hard code gauges in data_input module 55 | sa_barrage_gauges = data_inputs.get_barrage_level_gauges() 56 | sa_barrage_gauges = [value for key in sa_barrage_gauges for value in sa_barrage_gauges[key]] 57 | _level_gauges, weirpool_gauges = data_inputs.get_level_gauges() 58 | multi_gauges = data_inputs.get_multi_gauges('gauges') 59 | 60 | # Loop through once to get the special gauges: 61 | for gauge in gauges: 62 | if gauge in multi_gauges.keys(): 63 | flow_gauges.append(gauge) 64 | flow_gauges.append(multi_gauges[gauge]) 65 | if gauge in weirpool_gauges.keys(): # need level and flow gauges 66 | flow_gauges.append(gauge) 67 | level_gauges.append(weirpool_gauges[gauge]) 68 | 69 | # add hard coded gauges only if it int he incoming list 70 | if any(gauge in gauges for gauge in sa_barrage_gauges): 71 | lake_level_gauges += sa_barrage_gauges 72 | level_gauges += sa_barrage_gauges 73 | 74 | unique_flow_gauges = list(set(flow_gauges)) 75 | unique_level_gauges = list(set(level_gauges)) 76 | unique_lake_level_gauges = list(set(lake_level_gauges)) 77 | 78 | return unique_flow_gauges, unique_level_gauges, unique_lake_level_gauges 79 | 80 | def remove_data_with_bad_QC(input_dataframe: pd.DataFrame, qc_codes: list) -> pd.DataFrame: 81 | '''Takes in a dataframe of flow and a list of bad qc codes, removes the poor quality data from 82 | the timeseries, returns this dataframe 83 | 84 | Args: 85 | input_dataframe (pd.DataFrame): flow/water level dataframe 86 | qc_codes (list): list of quality codes to filter out 87 | Results: 88 | pd.DataFrame: flow/water level dataframe with "None" assigned to the poor quality data days 89 | 90 | ''' 91 | for qc in qc_codes: 92 | input_dataframe.loc[input_dataframe.QUALITYCODE == qc, 'VALUE'] = None 93 | 94 | return input_dataframe 95 | 96 | def one_gauge_per_column(input_dataframe: pd.DataFrame, gauge_iter: str) -> pd.DataFrame: 97 | '''Takes in a dataframe and the name of a gauge, extracts this one location to a new dataframe, 98 | cleans this and returns the dataframe with only the selected gauge data 99 | 100 | Args: 101 | input_dataframe (pd.DataFrame): Raw dataframe returned from water portal API 102 | gauge_iter (str): unique gauge ID 103 | Returns: 104 | pd.DataFrame: A dataframe daily flow/water level data matching the gauge_iter 105 | 106 | ''' 107 | 108 | is_in = input_dataframe['SITEID']== gauge_iter 109 | single_df = input_dataframe[is_in] 110 | single_df = single_df.drop(['DATASOURCEID','SITEID','SUBJECTID','QUALITYCODE','DATETIME'], 111 | axis = 1) 112 | single_df = single_df.set_index('Date') 113 | single_df = single_df.rename(columns={'VALUE': str(gauge_iter)}) 114 | 115 | return single_df 116 | 117 | def observed_cleaner(input_df: pd.DataFrame, dates: dict) -> pd.DataFrame: 118 | '''Takes in raw dataframe consolidated from state websites, removes poor quality data. 119 | returns a dataframe with a date index and one flow column per gauge location. 120 | 121 | Args: 122 | input_df (pd.DataFrame): Raw dataframe returned from water portal API 123 | dates (dict): Dictionary with the start and end dates from user request 124 | Results: 125 | pd.DataFrame: Daily flow/water level, gauges as the column ID's 126 | 127 | ''' 128 | 129 | start_date = datetime(dates['start_date'].year, dates['start_date'].month, dates['start_date'].day) 130 | end_date = datetime(dates['end_date'].year, dates['end_date'].month, dates['end_date'].day) 131 | 132 | df_index = pd.date_range(start=start_date,end=end_date - timedelta(days=1))#.to_period() 133 | gauge_data_df = pd.DataFrame() 134 | gauge_data_df['Date'] = df_index 135 | gauge_data_df = gauge_data_df.set_index('Date') 136 | 137 | input_df["VALUE"] = pd.to_numeric(input_df["VALUE"])#, downcast="float") 138 | 139 | 140 | input_df['Date'] = pd.to_datetime(input_df['DATETIME'], format = '%Y-%m-%d') 141 | # input_df['Date'] = input_df['Date'].apply(lambda x: x.to_period(freq='D')) 142 | 143 | # Check with states for more codes: 144 | bad_data_codes = data_inputs.get_bad_QA_codes() 145 | input_df = remove_data_with_bad_QC(input_df, bad_data_codes) 146 | 147 | site_list = set(input_df['SITEID']) 148 | 149 | for gauge in site_list: 150 | # Seperate out to one gauge per column and add this to the gauge_data_df made above: 151 | single_gauge_df = one_gauge_per_column(input_df, gauge) 152 | gauge_data_df = pd.merge(gauge_data_df, single_gauge_df, left_index=True, right_index=True, how="outer") 153 | 154 | # Drop the non unique values: 155 | gauge_data_df = gauge_data_df[~gauge_data_df.index.duplicated(keep='first')] 156 | return gauge_data_df 157 | 158 | 159 | class ObservedHandler: 160 | 161 | def __init__(self, gauges:List, dates:Dict, parameter_sheet:str = None, calc_config_path:str = None): 162 | self.gauges = gauges 163 | self.dates = dates 164 | self.yearly_events = None 165 | self.pu_ewr_statistics = None 166 | self.summary_results = None 167 | self.parameter_sheet = parameter_sheet 168 | self.calc_config_path = calc_config_path 169 | self.flow_data = None 170 | self.level_data = None 171 | 172 | def process_gauges(self): 173 | '''ingests a list of gauges and user defined parameters 174 | pulls gauge data using relevant states API, calculates and analyses EWRs 175 | returns dictionary of raw data results and result summary 176 | ''' 177 | 178 | # Classify gauges: 179 | flow_gauges, level_gauges, lake_level_gauges = categorise_gauges(self.gauges, self.parameter_sheet) 180 | # print('flow gauges') 181 | # print(flow_gauges) 182 | # print('level gauges') 183 | # print(level_gauges) 184 | # print('lake level gauges') 185 | # print(lake_level_gauges) 186 | # Call state API for flow and level gauge data, then combine to single dataframe 187 | log.info(f'Including gauges: flow gauges: { ", ".join(flow_gauges)} level gauges: { ", ".join(level_gauges)} lake level gauges: { ", ".join(lake_level_gauges)}') 188 | 189 | flows = gg.gauge_pull(flow_gauges, start_time_user = self.dates['start_date'], end_time_user = self.dates['end_date'], var = 'F') 190 | levels = gg.gauge_pull(level_gauges, start_time_user = self.dates['start_date'], end_time_user = self.dates['end_date'], var = 'L') 191 | lake_levels = gg.gauge_pull(lake_level_gauges, start_time_user=self.dates['start_date'], end_time_user=self.dates['end_date'], var='LL') 192 | 193 | # Clean observed data: 194 | df_F = observed_cleaner(flows, self.dates) 195 | df_L = observed_cleaner(levels, self.dates) 196 | df_S = observed_cleaner(lake_levels, self.dates) 197 | # Append stage values to level df 198 | df_L = pd.concat([df_L, df_S], axis=1) 199 | # Calculate EWRs 200 | detailed_results = {} 201 | gauge_results = {} 202 | gauge_events = {} 203 | detailed_events = {} 204 | all_locations = set(df_F.columns.to_list() + df_L.columns.to_list()) 205 | EWR_table, bad_EWRs = data_inputs.get_EWR_table(self.parameter_sheet) 206 | calc_config = data_inputs.get_ewr_calc_config(self.calc_config_path) 207 | for gauge in all_locations: 208 | gauge_results[gauge], gauge_events[gauge] = evaluate_EWRs.calc_sorter(df_F, df_L, gauge, EWR_table, calc_config) 209 | 210 | detailed_results['observed'] = gauge_results 211 | 212 | detailed_events['observed'] = gauge_events 213 | 214 | self.pu_ewr_statistics = detailed_results 215 | self.yearly_events = detailed_events 216 | 217 | self.flow_data = df_F 218 | self.level_data = df_L 219 | 220 | 221 | def get_all_events(self)-> pd.DataFrame: 222 | 223 | if not self.yearly_events: 224 | self.process_gauges() 225 | 226 | events_to_process = summarise_results.get_events_to_process(self.yearly_events) 227 | all_events = summarise_results.process_all_events_results(events_to_process) 228 | 229 | all_events = summarise_results.join_ewr_parameters(cols_to_add=['Multigauge', 'State', 'SWSDLName'], 230 | left_table=all_events, 231 | left_on=['gauge','pu','ewr'], 232 | selected_columns= ['scenario', 'gauge', 'pu', 'State', 'SWSDLName', 'ewr', 'waterYear', 'startDate', 'endDate', 233 | 'eventDuration', 'eventLength', 234 | 'Multigauge'], 235 | parameter_sheet_path=self.parameter_sheet) 236 | 237 | all_events = summarise_results.filter_duplicate_start_dates(all_events) 238 | 239 | return all_events 240 | 241 | def get_all_interEvents(self)-> pd.DataFrame: 242 | 243 | if not self.yearly_events: 244 | self.process_gauges() 245 | 246 | events_to_process = summarise_results.get_events_to_process(self.yearly_events) 247 | all_events_temp = summarise_results.process_all_events_results(events_to_process) 248 | 249 | all_events_temp = summarise_results.join_ewr_parameters(cols_to_add=['Multigauge', 'State', 'SWSDLName'], 250 | left_table=all_events_temp, 251 | left_on=['gauge','pu','ewr'], 252 | selected_columns= ['scenario', 'gauge', 'pu', 'State', 'SWSDLName', 'ewr', 'waterYear', 'startDate', 'endDate', 253 | 'eventDuration', 'eventLength', 254 | 'Multigauge'], 255 | parameter_sheet_path=self.parameter_sheet) 256 | 257 | all_events_temp = summarise_results.filter_duplicate_start_dates(all_events_temp) 258 | 259 | # Get start and end date of the timeseries. 260 | date0 = self.flow_data.index[0] 261 | date1 = self.flow_data.index[-1] 262 | start_date = date(date0.year, date0.month, date0.day) 263 | end_date = date(date1.year, date1.month, date1.day) 264 | 265 | all_interEvents = summarise_results.events_to_interevents(start_date, end_date, all_events_temp) 266 | 267 | return all_interEvents 268 | 269 | def get_all_successful_events(self)-> pd.DataFrame: 270 | 271 | if not self.yearly_events: 272 | self.process_gauges() 273 | 274 | events_to_process = summarise_results.get_events_to_process(self.yearly_events) 275 | all_events_temp1 = summarise_results.process_all_events_results(events_to_process) 276 | 277 | all_events_temp1 = summarise_results.join_ewr_parameters(cols_to_add=['Multigauge', 'State', 'SWSDLName'], 278 | left_table=all_events_temp1, 279 | left_on=['gauge','pu','ewr'], 280 | selected_columns= ['scenario', 'gauge', 'pu', 'State', 'SWSDLName', 'ewr', 'waterYear', 'startDate', 'endDate', 281 | 'eventDuration', 'eventLength', 282 | 'Multigauge'], 283 | parameter_sheet_path=self.parameter_sheet) 284 | 285 | all_events_temp1 = summarise_results.filter_duplicate_start_dates(all_events_temp1) 286 | 287 | all_successfulEvents = summarise_results.filter_successful_events(all_events_temp1, self.parameter_sheet) 288 | 289 | return all_successfulEvents 290 | 291 | def get_all_successful_interEvents(self)-> pd.DataFrame: 292 | 293 | if not self.yearly_events: 294 | self.process_gauges() 295 | 296 | events_to_process = summarise_results.get_events_to_process(self.yearly_events) 297 | all_events_temp2 = summarise_results.process_all_events_results(events_to_process) 298 | 299 | all_events_temp2 = summarise_results.join_ewr_parameters(cols_to_add=['Multigauge', 'State', 'SWSDLName'], 300 | left_table=all_events_temp2, 301 | left_on=['gauge','pu','ewr'], 302 | selected_columns= ['scenario', 'gauge', 'pu', 'State', 'SWSDLName', 'ewr', 'waterYear', 'startDate', 'endDate', 303 | 'eventDuration', 'eventLength', 304 | 'Multigauge'], 305 | parameter_sheet_path=self.parameter_sheet) 306 | 307 | all_events_temp2 = summarise_results.filter_duplicate_start_dates(all_events_temp2) 308 | 309 | # Part 1 - Get only the successful events: 310 | all_successfulEvents = summarise_results.filter_successful_events(all_events_temp2, self.parameter_sheet) 311 | 312 | # Part 2 - Now we have a dataframe of only successful events, pull down the interevent periods 313 | # Get start and end date of the timeseries. 314 | date0 = self.flow_data.index[0] 315 | date1 = self.flow_data.index[-1] 316 | 317 | start_date = date(date0.year, date0.month, date0.day) 318 | end_date = date(date1.year, date1.month, date1.day) 319 | 320 | all_successful_interEvents = summarise_results.events_to_interevents(start_date, end_date, all_successfulEvents) 321 | 322 | return all_successful_interEvents 323 | 324 | def get_yearly_ewr_results(self)-> pd.DataFrame: 325 | 326 | if not self.pu_ewr_statistics: 327 | self.process_gauges() 328 | 329 | to_process = summarise_results.pu_dfs_to_process(self.pu_ewr_statistics) 330 | yearly_ewr_results = summarise_results.process_df_results(to_process) 331 | 332 | yearly_ewr_results = summarise_results.join_ewr_parameters(cols_to_add=['Multigauge', 'State', 'SWSDLName'], 333 | left_table=yearly_ewr_results, 334 | left_on=['gauge','pu','ewrCode'], 335 | selected_columns= ['Year', 'eventYears', 'numAchieved', 'numEvents', 'numEventsAll', 336 | 'eventLength', 'eventLengthAchieved', 'totalEventDays', 'totalEventDaysAchieved', 337 | 'maxEventDays', 'maxRollingEvents', 'maxRollingAchievement', 338 | 'missingDays', 'totalPossibleDays', 'ewrCode', 339 | 'scenario', 'gauge', 'pu', 'State', 'SWSDLName', 'Multigauge'], 340 | parameter_sheet_path=self.parameter_sheet) 341 | 342 | # Setting up the dictionary of yearly rolling maximum interevent periods: 343 | events_to_process = summarise_results.get_events_to_process(self.yearly_events) 344 | all_events_temp = summarise_results.process_all_events_results(events_to_process) 345 | 346 | all_events_temp = summarise_results.join_ewr_parameters(cols_to_add=['Multigauge', 'State', 'SWSDLName'], 347 | left_table=all_events_temp, 348 | left_on=['gauge', 'pu', 'ewr'], 349 | selected_columns=['scenario', 'gauge', 'pu', 'State', 'SWSDLName', 'ewr', 350 | 'waterYear', 'startDate', 'endDate', 351 | 'eventDuration', 'eventLength', 352 | 'Multigauge'], 353 | parameter_sheet_path=self.parameter_sheet) 354 | 355 | all_events_temp = summarise_results.filter_duplicate_start_dates(all_events_temp) 356 | 357 | # Filter out the unsuccessful events: 358 | all_successfulEvents = summarise_results.filter_successful_events(all_events_temp, self.parameter_sheet) 359 | 360 | # Get start and end date of the timeseries. 361 | date0 = self.flow_data.index[0] 362 | date1 = self.flow_data.index[-1] 363 | start_date = date(date0.year, date0.month, date0.day) 364 | end_date = date(date1.year, date1.month, date1.day) 365 | df = summarise_results.events_to_interevents(start_date, end_date, all_successfulEvents) 366 | rolling_max_interevents_dict = summarise_results.get_rolling_max_interEvents(df, self.dates['start_date'], self.dates['end_date'], 367 | yearly_ewr_results, self.parameter_sheet) 368 | 369 | # Add the rolling max interevents to the yearly dataframe: 370 | yearly_ewr_results = summarise_results.add_interevent_to_yearly_results(yearly_ewr_results, 371 | rolling_max_interevents_dict) 372 | 373 | yearly_ewr_results = summarise_results.add_interevent_check_to_yearly_results(yearly_ewr_results, self.parameter_sheet) 374 | 375 | return yearly_ewr_results 376 | 377 | def get_ewr_results(self) -> pd.DataFrame: 378 | 379 | if not self.pu_ewr_statistics: 380 | self.process_gauges() 381 | 382 | return summarise_results.summarise(self.pu_ewr_statistics , self.yearly_events) -------------------------------------------------------------------------------- /py_ewr/parameter_metadata/ewr_calc_config.json: -------------------------------------------------------------------------------- 1 | { 2 | "flow_handle": [ 3 | "IC1_S-single-F", 4 | "IC1_PS-single-F", 5 | "IC2_S-single-F", 6 | "IC2_PS-single-F", 7 | "IC3_S-single-F", 8 | "IC3_PS-single-F", 9 | "IC4_S-single-F", 10 | "IC4_PS-single-F", 11 | "FP1_S-single-F", 12 | "FP1_PS-single-F", 13 | "FP2_S-single-F", 14 | "FP2_PS-single-F", 15 | "FP3_S-single-F", 16 | "FP3_PS-single-F", 17 | "FP4_S-single-F", 18 | "FP4_PS-single-F", 19 | "FP5_S-single-F", 20 | "FP5_PS-single-F", 21 | "SF1_S-single-F", 22 | "SF1_P-single-F", 23 | "SF2-single-F", 24 | "LF1_S-single-F", 25 | "LF1_P-single-F", 26 | "LF2-single-F", 27 | "BK1-single-F", 28 | "OB1-single-F", 29 | "OB1_a-single-F", 30 | "OB2-single-F", 31 | "OB3-single-F", 32 | "BK2_P-single-F", 33 | "BK2_S-single-F", 34 | "OB2_P-single-F", 35 | "OB2_S-single-F", 36 | "OB3_P-single-F", 37 | "OB3_S-single-F", 38 | "AC1_P-single-F", 39 | "AC1_S-single-F", 40 | "AC2-single-F", 41 | "OB4_P-single-F", 42 | "OB4_S-single-F", 43 | "AC1-single-F", 44 | "OB5-single-F", 45 | "LF3_P-single-F", 46 | "LF3_S-single-F", 47 | "OB4-single-F", 48 | "DSF-single-F", 49 | "OB-WS3_S-single-F", 50 | "OB-WS3_P-single-F", 51 | "SF1-single-F", 52 | "LF1-single-F", 53 | "OB-WS3-single-F", 54 | "OB-WM-single-F", 55 | "OB-WL-single-F", 56 | "OB-WS2-single-F", 57 | "SF3-single-F", 58 | "OB-WS4-single-F", 59 | "OB-WM_S-single-F", 60 | "OB-WL_S-single-F", 61 | "OB-WM_P-single-F", 62 | "OB-WL_P-single-F", 63 | "SF3_S-single-F", 64 | "SF3_P-single-F", 65 | "OB-WS2_S-single-F", 66 | "OB-WS2_P-single-F", 67 | "OB-WS4_S-single-F", 68 | "OB-WS4_P-single-F", 69 | "BK1_S-single-F", 70 | "BK1_P-single-F", 71 | "OB-WL1_P-single-F", 72 | "OB1_S-single-F", 73 | "OB1_P-single-F", 74 | "OB-WL1_S-single-F", 75 | "OB-WL3_P-single-F", 76 | "OB-WL3_S-single-F", 77 | "OB-WL4-single-F", 78 | "LF3-single-F", 79 | "OB2a_S-single-F", 80 | "OB2b_S-single-F", 81 | "OB2a_P-single-F", 82 | "OB2b_P-single-F", 83 | "OB3a_P-single-F", 84 | "OB3a_S-single-F", 85 | "OB3b_P-single-F", 86 | "OB3b_S-single-F", 87 | "OB5_S-single-F", 88 | "OB5_P-single-F", 89 | "OB6_S-single-F", 90 | "OB6_P-single-F", 91 | "OB7_P-single-F", 92 | "OB7_S-single-F", 93 | "OB8_P-single-F", 94 | "OB8_S-single-F", 95 | "OB9-single-F", 96 | "OB10-single-F", 97 | "LF4_S-single-F", 98 | "LF4_P-single-F", 99 | "LF2_S-single-F", 100 | "LF2_P-single-F", 101 | "BK1b_P-single-F", 102 | "BK1a_P-single-F", 103 | "ALT-CTF-single-F", 104 | "SF-WP-single-F", 105 | "LF2-WP-single-F", 106 | "BK2-single-F", 107 | "BK1_ds-single-F", 108 | "BK2_ds-single-F", 109 | "BK1_us-single-F", 110 | "BK2_us-single-F", 111 | "OB2-WHA_P-single-F", 112 | "OB2-WHA_S-single-F", 113 | "SF1_a_P-single-F", 114 | "SF1_a_S-single-F", 115 | "SF1_b_P-single-F", 116 | "SF1_b_S-single-F", 117 | "LF5_P-single-F", 118 | "LF5_S-single-F", 119 | "OB-S2-single-F", 120 | "W-LF4_S-single-F", 121 | "W-LF4_P-single-F", 122 | "W-LF6_S-single-F", 123 | "W-LF6_P-single-F", 124 | "W-LF7-single-F", 125 | "W-LF8-single-F", 126 | "OB-S2_S-single-F", 127 | "OB-S2_P-single-F", 128 | "DSF1-single-F", 129 | "W-LF5-single-F", 130 | "OB-L1_S-single-F", 131 | "OB-L1_P-single-F", 132 | "OB-S1-single-F", 133 | "OB-L1-single-F", 134 | "OB-L2_P-single-F", 135 | "OB-L2_S-single-F", 136 | "W-LF7_a-single-F", 137 | "OB-S2_a-single-F", 138 | "OB-L1_a-single-F", 139 | "OB-L2_P_a-single-F", 140 | "OB-L2_S_a-single-F", 141 | "W-LF7_b-single-F", 142 | "OB-S2_b-single-F", 143 | "OB-L1_b-single-F", 144 | "OB-L2_P_b-single-F", 145 | "OB-L2_S_b-single-F", 146 | "SF2_S-single-F", 147 | "SF2_P-single-F", 148 | "DR-VLF-single-F", 149 | "F1-single-F", 150 | "F2a_P-single-F", 151 | "F2b_P-single-F", 152 | "F2a_S-single-F", 153 | "F2b_S-single-F", 154 | "BK2a_P-single-F", 155 | "BK2b_P-single-F", 156 | "BK2a_S-single-F", 157 | "BK2b_S-single-F", 158 | "OB1a_P-single-F", 159 | "OB1b_P-single-F", 160 | "OB1a_S-single-F", 161 | "OB1b_S-single-F", 162 | "BK3a-single-F", 163 | "BK3b-single-F", 164 | "F1a-single-F", 165 | "F1b-single-F", 166 | "F1c-single-F", 167 | "F1d-single-F", 168 | "F2a-single-F", 169 | "F2b-single-F", 170 | "F2c-single-F", 171 | "F2d-single-F", 172 | "F3a-single-F", 173 | "F3b-single-F", 174 | "OB1a-single-F", 175 | "OB1b-single-F", 176 | "OB2a-single-F", 177 | "OB2b-single-F", 178 | "F1_a_P-single-F", 179 | "F1_a_S-single-F", 180 | "F1_b-single-F", 181 | "F2_a_P_pd-single-F", 182 | "F2_a_P_sd-single-F", 183 | "F2_a_S_pd-single-F", 184 | "F2_a_S_sd-single-F", 185 | "F2_b_pd-single-F", 186 | "F2_b_sd-single-F", 187 | "F3_P_pd-single-F", 188 | "F3_P_sd-single-F", 189 | "F3_S_pd-single-F", 190 | "F3_S_sd-single-F", 191 | "F4_P_pd-single-F", 192 | "F4_P_sd-single-F", 193 | "F4_S_pd-single-F", 194 | "F4_S_sd-single-F", 195 | "F5_P_pd-single-F", 196 | "F5_P_sd-single-F", 197 | "F5_S_pd-single-F", 198 | "F5_S_sd-single-F", 199 | "LF1_P_pd-single-F", 200 | "LF1_P_sd-single-F", 201 | "LF1_S_pd-single-F", 202 | "LF1_S_sd-single-F", 203 | "BK1_pd-single-F", 204 | "BK1_sd-single-F", 205 | "F1_a-single-F", 206 | "F2_a_pd-single-F", 207 | "F2_a_sd-single-F", 208 | "LF1_pd-single-F", 209 | "LF1_sd-single-F", 210 | "F1_a_SP-single-F", 211 | "F1_b_P-single-F", 212 | "F1_b_SP-single-F", 213 | "F2_a_PS_pd-single-F", 214 | "F2_a_PS_sd-single-F", 215 | "F2_b_P_pd-single-F", 216 | "F2_b_P_sd-single-F", 217 | "F2_b_SP_pd-single-F", 218 | "F2_b_SP_sd-single-F", 219 | "F2_b_S_pd-single-F", 220 | "F2_b_S_sd-single-F", 221 | "F3_pd-single-F", 222 | "F3_sd-single-F", 223 | "F4_pd-single-F", 224 | "F4_sd-single-F", 225 | "F5_pd-single-F", 226 | "F5_sd-single-F", 227 | "F1_P_pd-single-F", 228 | "F1_P_sd-single-F", 229 | "F1_S_pd-single-F", 230 | "F1_S_sd-single-F", 231 | "F2_P_pd-single-F", 232 | "F2_P_sd-single-F", 233 | "F2_S_pd-single-F", 234 | "F2_S_sd-single-F", 235 | "LF2_P_pd-single-F", 236 | "LF2_P_sd-single-F", 237 | "LF2_S_pd-single-F", 238 | "LF2_S_sd-single-F", 239 | "F2_a_P-single-F", 240 | "F2_a_S-single-F", 241 | "F2_b-single-F", 242 | "F1_b_S-single-F", 243 | "F2_P-single-F", 244 | "F2_S-single-F", 245 | "F1_pd-single-F", 246 | "F1_sd-single-F", 247 | "F2_pd-single-F", 248 | "F2_sd-single-F", 249 | "BKPP_pd-single-F", 250 | "BKPP_sd-single-F", 251 | "SF1a-single-F", 252 | "SF1b-single-F", 253 | "SF1_S-single-nan", 254 | "F1_c_P-single-F", 255 | "F1_c_S-single-F", 256 | "F2_c_P_pd-single-F", 257 | "F2_c_P_sd-single-F", 258 | "F2_c_S_pd-single-F", 259 | "F2_c_S_sd-single-F", 260 | "SF1_P_pd-single-F", 261 | "SF1_P_sd-single-F", 262 | "SF1_S_pd-single-F", 263 | "SF1_S_sd-single-F", 264 | "SF2_P_pd-single-F", 265 | "SF2_P_sd-single-F", 266 | "SF2_S_pd-single-F", 267 | "SF2_S_sd-single-F", 268 | "BK1_P_pd-single-F", 269 | "BK1_S_sd-single-F", 270 | "F1_c-single-F", 271 | "F2_a-single-F", 272 | "F2_c-single-F", 273 | "F3_a-single-F", 274 | "F3_b-single-F", 275 | "F3_c-single-F", 276 | "F4_a-single-F", 277 | "F4_b-single-F", 278 | "F4_c-single-F", 279 | "F5_a-single-F", 280 | "F5_b-single-F", 281 | "F6_a-single-F", 282 | "F6_b-single-F", 283 | "F6_c-single-F", 284 | "BK1_a_P-single-F", 285 | "BK1_b_P-single-F", 286 | "BK1_a_S-single-F", 287 | "BK1_b_S-single-F", 288 | "F5_c-single-F", 289 | "BK1_a-single-F", 290 | "BK1_b-single-F", 291 | "LF1a-single-F", 292 | "LF1b-single-F", 293 | "F3_S-single-F", 294 | "F3_P-single-F", 295 | "BF1_a_PS-single-F", 296 | "F1_a_PS-single-F", 297 | "F1_c_PS-single-F", 298 | "F1_c_PS-single-F", 299 | "F2_c_SP_pd-single-F", 300 | "F2_c_SP_sd-single-F", 301 | "F3_a_pd-single-F", 302 | "F3_a_sd-single-F", 303 | "F4_a_pd-single-F", 304 | "F4_a_sd-single-F", 305 | "SF1_a_P_pd-single-F", 306 | "SF1_a_P_sd-single-F", 307 | "SF1_a_S_pd-single-F", 308 | "SF1_a_S_sd-single-F", 309 | "SF2_a_P_pd-single-F", 310 | "SF2_a_P_sd-single-F", 311 | "SF2_a_S_pd-single-F", 312 | "SF2_a_S_sd-single-F", 313 | "F2_c_pd-single-F", 314 | "F2_c_sd-single-F", 315 | "F3_a_P_pd-single-F", 316 | "F3_a_P_sd-single-F", 317 | "F3_a_S_pd-single-F", 318 | "F3_a_S_sd-single-F", 319 | "F4_a_P_pd-single-F", 320 | "F4_a_P_sd-single-F", 321 | "F4_a_S_pd-single-F", 322 | "F4_a_S_sd-single-F", 323 | "F2_c_pd-single-F", 324 | "F2_c_sd-single-F", 325 | "F3_a_P_pd-single-F", 326 | "F3_a_P_sd-single-F", 327 | "F3_a_S_pd-single-F", 328 | "F3_a_S_sd-single-F", 329 | "F4_a_P_pd-single-F", 330 | "F4_a_P_sd-single-F", 331 | "F4_a_S_pd-single-F", 332 | "F4_a_S_sd-single-F", 333 | "BK3_pd-single-F", 334 | "BK3_sd-single-F", 335 | "F2_c_P-single-F", 336 | "F2_c_S-single-F", 337 | "OB1_P_pd-single-F", 338 | "OB1_P_sd-single-F", 339 | "OB1_S_pd-single-F", 340 | "OB1_S_sd-single-F", 341 | "BK2_P_pd-single-F", 342 | "BK2_P_sd-single-F", 343 | "BK2_S_pd-single-F", 344 | "BK2_S_sd-single-F", 345 | "F2_c_P-single-F", 346 | "F2_c_S-single-F", 347 | "OB1_P_pd-single-F", 348 | "OB1_P_sd-single-F", 349 | "OB1_S_pd-single-F", 350 | "OB1_S_sd-single-F", 351 | "F1_P-single-F", 352 | "F1_S-single-F", 353 | "LF1_a_P-single-F", 354 | "LF1_a_S-single-F", 355 | "LF1_a-single-F", 356 | "SF1_a_P_pd-single-F", 357 | "SF1_a_P_sd-single-F", 358 | "SF1_a_S_pd-single-F", 359 | "SF1_a_S_sd-single-F", 360 | "SF2_a_P_pd-single-F", 361 | "SF2_a_P_sd-single-F", 362 | "SF2_a_S_pd-single-F", 363 | "SF2_a_S_sd-single-F", 364 | "F2_c_pd-single-F", 365 | "F2_c_sd-single-F", 366 | "F3_a_P_pd-single-F", 367 | "F3_a_P_sd-single-F", 368 | "F3_a_S_pd-single-F", 369 | "F3_a_S_sd-single-F", 370 | "F4_a_P_pd-single-F", 371 | "F4_a_P_sd-single-F", 372 | "F4_a_S_pd-single-F", 373 | "F4_a_S_sd-single-F", 374 | "BK2_P_pd-single-F", 375 | "BK2_P_sd-single-F", 376 | "BK2_S_pd-single-F", 377 | "BK2_S_sd-single-F", 378 | "F2_c_P-single-F", 379 | "F2_c_S-single-F", 380 | "OB1_P_pd-single-F", 381 | "OB1_P_sd-single-F", 382 | "OB1_S_pd-single-F", 383 | "OB1_S_sd-single-F", 384 | "F3_S-single-F", 385 | "F3_P-single-F", 386 | "F3_d-single-F", 387 | "F1_c_pd-single-F", 388 | "F1_c_sd-single-F", 389 | "F1_d_pd-single-F", 390 | "F1_d_sd-single-F", 391 | "F3_d-single-F", 392 | "F1_a_pd-single-F", 393 | "F1_a_sd-single-F", 394 | "F1_b_pd-single-F", 395 | "F1_b_sd-single-F", 396 | "F1_c_pd-single-F", 397 | "F1_c_sd-single-F", 398 | "F1_d_pd-single-F", 399 | "F1_d_sd-single-F", 400 | "F2_d-single-F", 401 | "F1_a_pd-single-F", 402 | "F1_a_sd-single-F", 403 | "F1_b_pd-single-F", 404 | "F1_b_sd-single-F", 405 | "F1_c_pd-single-F", 406 | "F1_c_sd-single-F", 407 | "F1_d_pd-single-F", 408 | "F1_d_sd-single-F", 409 | "F2_d-single-F", 410 | "F2-single-F", 411 | "F3-single-F", 412 | "F1_a_pd-single-F", 413 | "F1_a_sd-single-F", 414 | "F1_b_pd-single-F", 415 | "F1_b_sd-single-F", 416 | "F1_d_pd-single-F", 417 | "F1_d_sd-single-F", 418 | "F2_d-single-F", 419 | "BK1_S_pd-single-F", 420 | "BK1_P_sd-single-F" 421 | ], 422 | "flow_handle_sa": [ 423 | "IC1_P-single-F", 424 | "IC2_P-single-F", 425 | "IC3_P-single-F", 426 | "IC4_P-single-F", 427 | "FP1_P-single-F", 428 | "FP2_P-single-F", 429 | "FP3_P-single-F", 430 | "FP4_P-single-F", 431 | "FP5_P-single-F" 432 | ], 433 | "barrage_flow_handle": [ 434 | "CLLMM1a_P-single-F", 435 | "CLLMM1a_S-single-F", 436 | "CLLMM1b-single-F", 437 | "CLLMM2a_P-single-F", 438 | "CLLMM2a_S-single-F", 439 | "CLLMM2b-single-F", 440 | "CLLMM3a_P-single-F", 441 | "CLLMM3a_S-single-F", 442 | "CLLMM4a_P-single-F", 443 | "CLLMM4a_S-single-F" 444 | ], 445 | "barrage_level_handle": [ 446 | "CLLMM1d_P-single-L", 447 | "CLLMM1d_S-single-L", 448 | "CLLMM2c-single-L", 449 | "CLLMM2d_P-single-L", 450 | "CLLMM2d_S-single-L", 451 | "CLLMM3c-single-L", 452 | "CLLMM3d_P-single-L", 453 | "CLLMM3d_S-single-L", 454 | "CLLMM4c-single-L", 455 | "CLLMM1c_P-single-L", 456 | "CLLMM1c_S-single-L" 457 | ], 458 | "ctf_handle": [ 459 | "CF_a-single-F", 460 | "CF_b-single-F", 461 | "CF_c-single-F", 462 | "CF1_a-single-F", 463 | "CF1_c-single-F", 464 | "CF1_b-single-F", 465 | "CF-single-F", 466 | "CF1-single-F", 467 | "CF1_hot-single-F", 468 | "CF1_cool-single-F", 469 | "CF1_d-single-F", 470 | "CF1_c_P_pd-single-F", 471 | "CF1_c_S_pd-single-F", 472 | "CF1_c_S_sd-single-F", 473 | "CF1_c_P_sd-single-F" 474 | ], 475 | "lowflow_handle": [ 476 | "VF_a-single-F", 477 | "VF_b-single-F", 478 | "BF1_a-single-F", 479 | "BF1_b-single-F", 480 | "BF2_a-single-F", 481 | "BF2_b-single-F", 482 | "VF1_a-single-F", 483 | "VF1_b-single-F", 484 | "VF-single-F", 485 | "BF3-single-F", 486 | "BF1-single-F", 487 | "BF2-single-F", 488 | "BF3_P-single-F", 489 | "BF3_S-single-F", 490 | "BF1a-single-F", 491 | "BF1b-single-F", 492 | "BF2a-single-F", 493 | "BF2b-single-F", 494 | "BF2c-single-F", 495 | "BF1_a_P-single-F", 496 | "BF1_a_S-single-F", 497 | "BF2_a_P-single-F", 498 | "BF2_a_S-single-F", 499 | "BF1_a_SP-single-F", 500 | "BF2_a_PS-single-F", 501 | "BF2_b_P-single-F", 502 | "BF2_b_S-single-F", 503 | "BF2_P-single-F", 504 | "BF2_S-single-F", 505 | "BF1_b_P-single-F", 506 | "BF1_b_S-single-F", 507 | "BF3_a-single-F", 508 | "BF3_a_S-single-F", 509 | "BF3_a_P-single-F", 510 | "BF3_b-single-F", 511 | "BF3_c-single-F", 512 | "BF1_P-single-F", 513 | "BF1_S-single-F", 514 | "BF1_PS-single-F", 515 | "BF1_c-single-F", 516 | "BF2_c-single-F", 517 | "BF2_PS-single-F", 518 | "BF1_c_P-single-F", 519 | "BF1_c_S-single-F", 520 | "BF2_c_P-single-F", 521 | "BF2_c_S-single-F", 522 | "BF4-single-F", 523 | "BF5-single-F", 524 | "BF-FD1-single-F", 525 | "BF-FD2-single-F", 526 | "BF1_1-single-F", 527 | "BF1_2-single-F", 528 | "BF1_3-single-F", 529 | "BF1_4-single-F", 530 | "BF1_5-single-F", 531 | "BF1_6-single-F", 532 | "BF1_7-single-F", 533 | "BF1_8-single-F", 534 | "BF1_9-single-F", 535 | "BF1_10-single-F", 536 | "BF1_11-single-F", 537 | "BF1_12-single-F" 538 | ], 539 | "ctf_handle_multi": [ 540 | "CF-multigauge-F" 541 | ], 542 | "lowflow_handle_multi": [ 543 | "VF-multigauge-F", 544 | "BF1_a-multigauge-F", 545 | "BF1_b-multigauge-F", 546 | "BF2_a-multigauge-F", 547 | "BF2_b-multigauge-F", 548 | "BF3-multigauge-F" 549 | ], 550 | "flow_handle_multi": [ 551 | "DSF-multigauge-F", 552 | "SF1_S-multigauge-F", 553 | "SF1_P-multigauge-F", 554 | "SF2-multigauge-F", 555 | "LF1-multigauge-F", 556 | "LF2-multigauge-F", 557 | "OB-WS2-multigauge-F", 558 | "OB-WS3-multigauge-F", 559 | "OB-WS4-multigauge-F", 560 | "OB-WM-multigauge-F", 561 | "OB-WL-multigauge-F", 562 | "OB-L2_P-multigauge-F", 563 | "OB-L2_S-multigauge-F" 564 | ], 565 | "cumulative_handle_multi": [ 566 | "OB-WS1_P-multigauge-V", 567 | "OB-WS1_S-multigauge-V", 568 | "OB-WS4_P-multigauge-V", 569 | "OB-WS4_S-multigauge-V", 570 | "OB-WM_P-multigauge-V", 571 | "OB-WM_S-multigauge-V", 572 | "OB-WL_P-multigauge-V", 573 | "OB-WL_S-multigauge-V", 574 | "OB-S2-multigauge-V", 575 | "OB-L1-multigauge-V", 576 | "WL1-multigauge-V", 577 | "WL2-multigauge-V", 578 | "WL3-multigauge-V", 579 | "WL4-multigauge-V" 580 | ], 581 | "cumulative_handle": [ 582 | "OB-WM_P-single-V", 583 | "OB-WM_S-single-V", 584 | "LF6-single-V", 585 | "OB1_S-single-V", 586 | "OB1_P-single-V", 587 | "OB2_S-single-V", 588 | "OB2_P-single-V", 589 | "OB3_S-single-V", 590 | "OB3_P-single-V", 591 | "WL1-single-V", 592 | "WL2_S-single-V", 593 | "WL2_P-single-V", 594 | "WL3-single-V", 595 | "WL4_S-single-V", 596 | "WL4_P-single-V", 597 | "LF6_P-single-V", 598 | "LF6_S-single-V", 599 | "OB5-single-V", 600 | "W-LF4_P-single-V", 601 | "W-LF4_S-single-V", 602 | "W-LF7-single-V", 603 | "OB-S2-single-V", 604 | "OB-L1-single-V", 605 | "OB-L2_P-single-V", 606 | "OB-L2_S-single-V", 607 | "WL2-single-V", 608 | "WL4-single-V", 609 | "BF1_1-single-V", 610 | "BF1_2-single-V", 611 | "BF1_3-single-V", 612 | "BF1_4-single-V", 613 | "BF1_5-single-V", 614 | "BF1_6-single-V", 615 | "BF1_7-single-V", 616 | "BF1_8-single-V", 617 | "BF1_9-single-V", 618 | "BF1_10-single-V", 619 | "BF1_11-single-V", 620 | "BF1_12-single-V" 621 | ], 622 | "level_handle": [ 623 | "WL3_S-single-L", 624 | "WL3_P-single-L", 625 | "LLLF-single-L", 626 | "MLLF-single-L", 627 | "HLLF-single-L", 628 | "VHLL-single-L" 629 | ], 630 | "nest_handle": [ 631 | "NestS1-single-F", 632 | "NestS1_tcmc-single-F", 633 | "NestS1_mc-single-F", 634 | "NestS1a-single-F", 635 | "NestS1b-single-F" 636 | ], 637 | "weirpool_handle": [ 638 | "WP1-single-F", 639 | "WP2-single-F", 640 | "WP3-single-F", 641 | "WP4-single-F" 642 | ], 643 | "flow_handle_anytime": [ 644 | "dANA-single-F", 645 | "DR_S-single-F", 646 | "FR2-single-F", 647 | "NE-single-F", 648 | "PP-single-F", 649 | "rANA-single-F", 650 | "DR1-single-F", 651 | "DR2-single-F", 652 | "FR1-single-F", 653 | "LDF-single-F", 654 | "WFT-single-F", 655 | "SF-FD1-single-F", 656 | "SF-FD2-single-F" 657 | ], 658 | "flow_handle_check_ctf": [ 659 | "FD1-single-F", 660 | "FD2-single-F", 661 | "FrC-single-F" 662 | ], 663 | "cumulative_handle_bbr": [ 664 | "BBR1_a-single-V", 665 | "BBR1_b-single-V" 666 | ], 667 | "cumulative_handle_qld": [ 668 | "BBR2-single-V" 669 | ], 670 | "water_stability_handle": [ 671 | "FrW1-single-F", 672 | "FrW2-single-F", 673 | "FrW3-single-F", 674 | "FrW4-single-F" 675 | ], 676 | "water_stability_level_handle": [ 677 | "FrL1-single-F", 678 | "FrL2-single-F" 679 | ], 680 | "rise_and_fall_handle": [ 681 | "RRF-single-F", 682 | "RFF-single-F", 683 | "RRL_su-single-L", 684 | "RFL_su-single-L", 685 | "RRL_au-single-L", 686 | "RFL_au-single-L", 687 | "RRL_wi-single-L", 688 | "RFL_wi-single-L", 689 | "RRL_sp-single-L", 690 | "RFL_sp-single-L" 691 | ] 692 | } 693 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [build-system] 2 | requires = ["setuptools>=42"] 3 | build-backend = "setuptools.build_meta" -------------------------------------------------------------------------------- /readme.md.amltmp: -------------------------------------------------------------------------------- 1 | [![CI](https://github.com/MDBAuth/EWR_tool/actions/workflows/tox-test.yml/badge.svg)]() 2 | 3 | 4 | ### **EWR tool beta 0.0.8 README** 5 | 6 | **Installation** 7 | 8 | Step 1. 9 | Upgrade pip 10 | python -m pip install –upgrade pip 11 | 12 | Step 2. 13 | pip install py-ewr 14 | 15 | 16 | **Purpose** 17 | This tool has two purposes: 18 | 1. Operational: Tracking EWR success at gauges of interest in real time. 19 | 2. Planning: Comparing EWR success between scenarios (i.e. model runs) 20 | 21 | **Support** 22 | For issues relating to the script, a tutorial, or feedback please contact Martin Job at martin.job@mdba.gov.au or Joel Bailey at joel.bailey@mdba.gov.au 23 | 24 | **Notes on development of the tool** 25 | This is the version 0.0.6 of the EWR tool. Testing is still being undertaken. 26 | 27 | **Disclaimer** 28 | Every effort has been taken to ensure the EWR database represents the original EWRs from state long term water plans as best as possible, and that the code within this tool has been developed to interpret and analyse these EWRs in an accurate way. However, there may still be unresolved bugs in the database and/or EWR tool. Please report any bugs to the issues tab under this GitHub project so we can investigate further. 29 | 30 | 31 | **Notes on development of the database** 32 | The Environmental Assets & Functions Database (EAFD) migration to a machine readable format is underway. This migration may impact on the intricacies of the original EWRs. The MDBA has started working with NSW to ensure the translation from EWRs as they are written in the long term water plans to how they are interpreted by this tool is done in a scientifically robust manner. 33 | 34 | **Compatability** 35 | The tool can currently evaluate most to all of EWRs in the following catchments. Evaluation of EWRs is largely dependent on the migration of the Environmental Assets & Functions Database (EAFD) database into a machine readable format. 36 | 37 | NSW: 38 | - All NSW catchments 39 | 40 | Work is currently underway to migrate the EWRs in the remaining Basin catchments. 41 | 42 | **Input data** 43 | - EWR information: This tool accesses the EWRs in the Environmental Assets & Functions Database (EAFD) 44 | - Climate data from the AWRA-L model 45 | - Gauge data from the relevant state websites 46 | - Scenario data input by the user 47 | - Model metadata for location association between gauge ID's and model nodes 48 | 49 | **Running the tool** 50 | Consult the user manual for instructions on how to run the tool. Please email the above email addresses for a copy of the user manual. 51 | 52 | **Climate sequence** 53 | NSW Long Term Watering Plans (LTWP) define climate using the Resource Availability Scenarios (RAS). However, until this process can be completed the climate categories defined using outputs from the AWRA-L model will be used. 54 | -------------------------------------------------------------------------------- /requirements-dev.txt: -------------------------------------------------------------------------------- 1 | -r requirements.txt 2 | pytest 3 | pytest-cov 4 | tox 5 | notebook -------------------------------------------------------------------------------- /requirements-notebook-env.txt: -------------------------------------------------------------------------------- 1 | argon2-cffi==21.3.0 2 | argon2-cffi-bindings==21.2.0 3 | asttokens==2.0.5 4 | attrs==21.4.0 5 | backcall==0.2.0 6 | beautifulsoup4==4.11.1 7 | bleach==5.0.0 8 | certifi==2021.10.8 9 | cffi==1.15.0 10 | chardet==4.0.0 11 | charset-normalizer==2.0.12 12 | coverage==6.3.3 13 | debugpy==1.6.0 14 | decorator==5.1.1 15 | defusedxml==0.7.1 16 | entrypoints==0.4 17 | executing==0.8.3 18 | fastjsonschema==2.15.3 19 | idna==2.10 20 | importlib-resources==5.7.1 21 | iniconfig==1.1.1 22 | ipykernel==6.13.0 23 | ipython==8.8.0 24 | ipython-genutils==0.2.0 25 | ipywidgets==7.7.0 26 | jedi==0.18.1 27 | Jinja2==3.1.2 28 | jsonschema==4.5.1 29 | jupyter-client==7.3.1 30 | jupyter-core==4.10.0 31 | jupyterlab-pygments==0.2.2 32 | jupyterlab-widgets==1.1.0 33 | MarkupSafe==2.1.1 34 | matplotlib-inline==0.1.3 35 | mdba-gauge-getter==0.4.4 36 | mistune==0.8.4 37 | nbclient==0.6.3 38 | nbconvert==6.5.0 39 | nbformat==5.4.0 40 | nest-asyncio==1.5.5 41 | notebook==6.4.11 42 | numpy==1.22.3 43 | openpyxl==3.0.9 44 | packaging==21.3 45 | pandas==1.4.2 46 | pandocfilters==1.5.0 47 | parso==0.8.3 48 | pexpect==4.8.0 49 | pickleshare==0.7.5 50 | pluggy==1.0.0 51 | prometheus-client==0.14.1 52 | prompt-toolkit==3.0.29 53 | psutil==5.9.0 54 | ptyprocess==0.7.0 55 | pure-eval==0.2.2 56 | py==1.11.0 57 | pycparser==2.21 58 | Pygments==2.12.0 59 | pyparsing==3.0.9 60 | pyrsistent==0.18.1 61 | pytest==7.1.2 62 | pytest-cov==3.0.0 63 | python-dateutil==2.8.2 64 | pytz==2022.1 65 | pyzmq==22.3.0 66 | requests==2.25.1 67 | Send2Trash==1.8.0 68 | six==1.16.0 69 | soupsieve==2.3.2.post1 70 | stack-data==0.2.0 71 | terminado==0.13.3 72 | tinycss2==1.1.1 73 | tomli==2.0.1 74 | tornado==6.1 75 | tqdm==4.64.0 76 | traitlets==5.2.0 77 | urllib3==1.26.9 78 | wcwidth==0.2.5 79 | webencodings==0.5.1 80 | widgetsnbextension==3.6.0 81 | XlsxWriter==3.0.3 82 | zipp==3.8.0 83 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | ipython 2 | ipywidgets 3 | mdba-gauge-getter 4 | numpy 5 | pandas 6 | requests 7 | tqdm 8 | traitlets 9 | xarray 10 | netCDF4 -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | from setuptools import find_packages, setup 2 | 3 | 4 | with open("README.md", "r", encoding="utf-8") as fh: 5 | long_description = fh.read() 6 | 7 | setup( 8 | name="py_ewr", 9 | version="2.3.7", 10 | author="Martin Job", 11 | author_email="Martin.Job@mdba.gov.au", 12 | description="Environmental Water Requirement calculator", 13 | long_description=long_description, 14 | long_description_content_type="text/markdown", 15 | url="https://github.com/MDBAuth/EWR_tool", 16 | project_urls={ 17 | "Bug Tracker": "https://github.com/MDBAuth/EWR_tool/issues", 18 | }, 19 | classifiers=[ 20 | "Programming Language :: Python :: 3", 21 | "License :: OSI Approved :: GNU General Public License (GPL)", 22 | "Operating System :: OS Independent", 23 | 'Development Status :: 4 - Beta', 24 | 'Programming Language :: Python', 25 | 'Programming Language :: Python :: 3', 26 | 'Programming Language :: Python :: 3.9', 27 | 'Programming Language :: Python :: 3.10', 28 | 'Programming Language :: Python :: 3.11', 29 | 'Programming Language :: Python :: 3.12', 30 | 'Programming Language :: Python :: 3.13', 31 | 'Framework :: Pytest', 32 | ], 33 | packages=find_packages(exclude=["tests"]), 34 | install_requires=[ 35 | "pandas>2",#==2.0.3", 36 | "requests>2",#==2.25.1", 37 | "mdba-gauge-getter==0.5.1", 38 | "cachetools>5",#==5.2.0", 39 | "xarray",#==2023.09.0", 40 | "h5py",#==3.12.1", 41 | "netCDF4",#==1.6.4", 42 | "numpy<2" 43 | ], 44 | package_data={'': ["model_metadata/*.csv", "parameter_metadata/*.csv","parameter_metadata/*.json"]}, 45 | ) 46 | -------------------------------------------------------------------------------- /setup.py.amltmp: -------------------------------------------------------------------------------- 1 | from setuptools import find_packages, setup 2 | 3 | 4 | with open("README.md", "r", encoding="utf-8") as fh: 5 | long_description = fh.read() 6 | 7 | setup( 8 | name="py_ewr", 9 | version="1.0.6", 10 | author="Martin Job", 11 | author_email="Martin.Job@mdba.gov.au", 12 | description="Environmental Water Requirement calculator", 13 | long_description=long_description, 14 | long_description_content_type="text/markdown", 15 | url="https://github.com/MDBAuth/EWR_tool", 16 | project_urls={ 17 | "Bug Tracker": "https://github.com/MDBAuth/EWR_tool/issues", 18 | }, 19 | classifiers=[ 20 | "Programming Language :: Python :: 3", 21 | "License :: OSI Approved :: GNU General Public License (GPL)", 22 | "Operating System :: OS Independent", 23 | 'Development Status :: 4 - Beta', 24 | 'Programming Language :: Python', 25 | 'Programming Language :: Python :: 3', 26 | 'Programming Language :: Python :: 3.8', 27 | 'Programming Language :: Python :: 3.9', 28 | 'Programming Language :: Python :: 3.10', 29 | 'Framework :: Pytest', 30 | ], 31 | packages=find_packages(exclude=["tests"]), 32 | install_requires=[ 33 | "ipython==8.8.0", 34 | "ipywidgets==7.7.0", 35 | "pandas==1.4.2", 36 | "requests==2.25.1", 37 | "tqdm==4.64.0", 38 | "mdba-gauge-getter==0.4.4", 39 | "cachetools==5.2.0", 40 | ], 41 | package_data={'': ['climate_data/*.csv', "model_metadata/*.csv", "parameter_metadata/*.csv"]}, 42 | ) 43 | -------------------------------------------------------------------------------- /tests/conftest.py: -------------------------------------------------------------------------------- 1 | from datetime import date, timedelta, datetime 2 | import re 3 | import json 4 | 5 | import pandas as pd 6 | import pytest 7 | import pickle 8 | from unittest.mock import patch 9 | import mdba_gauge_getter 10 | 11 | from py_ewr import observed_handling, scenario_handling, data_inputs 12 | 13 | @pytest.fixture(scope="function") 14 | def pu_df(): 15 | df_data = {'CF1_a_eventYears': {2016: 0, 2017: 0}, 16 | 'CF1_a_numAchieved': {2016: 0, 2017: 0}, 17 | 'CF1_a_numEvents': {2016: 0, 2017: 0}, 18 | 'CF1_a_numEventsAll': {2016: 0, 2017: 0}, 19 | 'CF1_a_eventLength': {2016: 0.0, 2017: 0.0}, 20 | 'CF1_a_eventLengthAchieved': {2016: 0.0, 2017: 0.0}, 21 | 'CF1_a_totalEventDays': {2016: 0, 2017: 0}, 22 | 'CF1_a_totalEventDaysAchieved': {2016: 0, 2017: 0}, 23 | 'CF1_a_rollingMaxInterEventAchieved': {2016: [], 2017: []}, 24 | 'CF1_a_missingDays': {2016: 0, 2017: 0}, 25 | 'CF1_a_totalPossibleDays': {2016: 365, 2017: 365}} 26 | return pd.DataFrame.from_dict(df_data) 27 | 28 | 29 | @pytest.fixture(scope="function") 30 | def detailed_results(pu_df): 31 | return {"observed": {"419001": {"Keepit to Boggabri": pu_df}, 32 | "419002": {"Keepit to Boggabri": pu_df}}} 33 | 34 | 35 | @pytest.fixture(scope="function") 36 | def item_to_process(pu_df): 37 | return { "scenario" : 'observed', 38 | "gauge" : '419001', 39 | "pu" : 'Keepit to Boggabri', 40 | "pu_df" : pu_df } 41 | 42 | @pytest.fixture(scope="function") 43 | def items_to_process(pu_df): 44 | 45 | return [ { "scenario" : 'observed', 46 | "gauge" : '419001', 47 | "pu" : 'Keepit to Boggabri', 48 | "pu_df" : pu_df }, 49 | { "scenario" : 'observed', 50 | "gauge" : '419002', 51 | "pu" : 'Keepit to Boggabri', 52 | "pu_df" : pu_df } 53 | ] 54 | 55 | @pytest.fixture(scope="function") 56 | def gauge_events(): 57 | return {'observed': {'419001': {'Keepit to Boggabri': {'CF1_a': ({2010: [], 58 | 2011: [], 59 | 2012: [], 60 | 2013: [], 61 | 2014: [[0.0, 0.0, 0.0, 0.0, 0.0, 0.0]]},)} 62 | }, 63 | '419002': {'Keepit to Boggabri': {'CF1_a': ({2010: [], 64 | 2011: [], 65 | 2012: [], 66 | 2013: [], 67 | 2014: [[0.0, 0.0, 0.0, 0.0, 0.0, 0.0]]},)} 68 | } 69 | }, 70 | } 71 | 72 | @pytest.fixture(scope="function") 73 | def yearly_events(): 74 | return {2010: [], 75 | 2011: [], 76 | 2012: [], 77 | 2013: [], 78 | 2014: [[0.0, 0.0, 0.0, 0.0, 0.0, 0.0]]} 79 | 80 | @pytest.fixture(scope="function") 81 | def event_item_to_process(): 82 | return { "scenario" : 'observed', 83 | "gauge" : '419001', 84 | "pu" : 'Keepit to Boggabri', 85 | "ewr": 'CF1_a', 86 | "ewr_events" : { 2010: [], 87 | 2011: [], 88 | 2012: [], 89 | 2013: [], 90 | 2014: [[(date(2020, 11, 30), 0.0), 91 | (date(2020, 12, 1), 0.0), 92 | (date(2020, 12, 2), 0.0), 93 | (date(2020, 12, 3), 0.0), 94 | (date(2020, 12, 4), 0.0), 95 | (date(2020, 12, 5), 0.0),]]} 96 | } 97 | 98 | @pytest.fixture(scope="function") 99 | def event_items_to_process(): 100 | return [{ "scenario" : 'observed', 101 | "gauge" : '419001', 102 | "pu" : 'Keepit to Boggabri', 103 | "ewr": 'CF1_a', 104 | "ewr_events" : { 2010: [], 105 | 2011: [], 106 | 2012: [], 107 | 2013: [], 108 | 2014: [[(date(2020, 11, 30), 0.0), 109 | (date(2020, 12, 1), 0.0), 110 | (date(2020, 12, 2), 0.0), 111 | (date(2020, 12, 3), 0.0), 112 | (date(2020, 12, 4), 0.0), 113 | (date(2020, 12, 5), 0.0),]]} 114 | }, 115 | { "scenario" : 'observed', 116 | "gauge" : '419002', 117 | "pu" : 'Keepit to Boggabri', 118 | "ewr": 'CF1_a', 119 | "ewr_events" : { 2010: [], 120 | 2011: [], 121 | 2012: [], 122 | 2013: [], 123 | 2014: [[(date(2020, 11, 30), 0.0), 124 | (date(2020, 12, 1), 0.0), 125 | (date(2020, 12, 2), 0.0), 126 | (date(2020, 12, 3), 0.0), 127 | (date(2020, 12, 4), 0.0), 128 | (date(2020, 12, 5), 0.0),]]} 129 | } 130 | ] 131 | 132 | @pytest.fixture(scope="function") 133 | def stamp_index(): 134 | return pd.date_range(start= datetime.strptime('2012-07-01', '%Y-%m-%d'), end = datetime.strptime('2016-06-30', '%Y-%m-%d')) 135 | 136 | @pytest.fixture(scope="function") 137 | def date_index():#supersedes period_index 138 | return pd.date_range(start= datetime.strptime('2012-07-01', '%Y-%m-%d'), end = datetime.strptime('2016-06-30', '%Y-%m-%d'))#.to_period() 139 | 140 | @pytest.fixture(scope="function") 141 | def stamp_date(stamp_index): 142 | return stamp_index[0] 143 | 144 | @pytest.fixture(scope="function") 145 | def datetime_date(date_index):#supersedes period_date 146 | return date_index[0] 147 | 148 | 149 | @pytest.fixture(scope="module") 150 | def observed_handler_expected_detail(): 151 | # Load and format expected results 152 | expected_detailed_results = pd.read_csv('unit_testing_files/detailed_results_observed.csv', index_col = 0) 153 | expected_detailed_results.index = expected_detailed_results.index.astype('int64') 154 | cols = expected_detailed_results.columns[expected_detailed_results.columns.str.contains('eventLength')] 155 | expected_detailed_results[cols] = expected_detailed_results[cols].astype('float64') 156 | for i_col, col in enumerate(expected_detailed_results): 157 | if 'daysBetweenEvents' in col: 158 | for i, val in enumerate(expected_detailed_results[col]): 159 | new = expected_detailed_results[col].iloc[i] 160 | if new == '[]': 161 | new_list = [] 162 | else: 163 | new = re.sub(r'\[', '', new) 164 | new = re.sub(r'\]', '', new) 165 | new = new.split(',') 166 | new_list = [] 167 | for days in new: 168 | new_days = days.strip() 169 | new_days = int(new_days) 170 | new_list.append(new_days) 171 | 172 | expected_detailed_results.iat[i, i_col] = new_list 173 | 174 | return expected_detailed_results 175 | 176 | @pytest.fixture(scope="module") 177 | def scenario_handler_expected_detail(): 178 | # Expected output params 179 | expected_detailed_results = pd.read_csv('unit_testing_files/detailed_results_test.csv', index_col=0) 180 | expected_detailed_results.index = expected_detailed_results.index.astype('int64') 181 | expected_detailed_results.index.astype('object') 182 | cols = expected_detailed_results.columns[expected_detailed_results.columns.str.contains('eventLength')] 183 | expected_detailed_results[cols] = expected_detailed_results[cols].astype('float64') 184 | for i_col, col in enumerate(expected_detailed_results): 185 | if 'daysBetweenEvents' in col: 186 | for i, val in enumerate(expected_detailed_results[col]): 187 | new = expected_detailed_results[col].iloc[i] 188 | if new == '[]': 189 | new_list = [] 190 | else: 191 | new = re.sub(r'\[', '', new) 192 | new = re.sub(r'\]', '', new) 193 | new = new.split(',') 194 | new_list = [] 195 | for days in new: 196 | new_days = days.strip() 197 | new_days = int(new_days) 198 | new_list.append(new_days) 199 | 200 | expected_detailed_results.iat[i, i_col] = new_list 201 | 202 | return expected_detailed_results 203 | 204 | def gg_pull_mock(*args, **kwargs): 205 | 206 | with open('unit_testing_files/mock_gg_pull.json', 'r') as f: 207 | data = json.load(f) 208 | 209 | gg_response = pd.DataFrame(data) 210 | 211 | return gg_response 212 | 213 | @pytest.fixture(scope="module") 214 | def scenario_handler_instance(): 215 | # Testing the MDBA bigmod format: 216 | # Input params 217 | scenario = 'unit_testing_files/Low_flow_EWRs_Bidgee_410007.csv' 218 | model_format = 'Bigmod - MDBA' 219 | 220 | # Pass to the class 221 | 222 | ewr_sh = scenario_handling.ScenarioHandler(scenario, model_format) 223 | 224 | ewr_sh.process_scenarios() 225 | 226 | return ewr_sh 227 | 228 | @pytest.fixture(scope="function") 229 | def parameter_sheet(): 230 | EWR_table, _ = data_inputs.get_EWR_table("unit_testing_files/parameter_sheet.csv") 231 | return EWR_table 232 | 233 | 234 | @pytest.fixture(scope="function") 235 | def wp_df_F_df_L(): 236 | 237 | murray_IQQM_df_wp = pd.read_csv("unit_testing_files/murray_IQQM_df_wp.csv", index_col = 'Date') 238 | df_F, df_L = scenario_handling.cleaner_standard_timeseries(murray_IQQM_df_wp) 239 | 240 | return df_F, df_L 241 | 242 | @pytest.fixture(scope="function") 243 | def sa_parameter_sheet(): 244 | EWR_table, _ = data_inputs.get_EWR_table("unit_testing_files/sa_parameter_sheet.csv") 245 | return EWR_table 246 | 247 | @pytest.fixture(scope="function") 248 | def wp_EWR_table(parameter_sheet): 249 | 250 | wp_flow_level_gauges = ['414203', '414209', '425010', 'A4260501' ] 251 | 252 | 253 | return parameter_sheet[(parameter_sheet["Gauge"].isin(wp_flow_level_gauges))&(parameter_sheet["Code"].isin(["WP3","WP4","LF2-WP","SF-WP"]))] 254 | 255 | 256 | @pytest.fixture(scope="function") 257 | def PU_df_wp(): 258 | df_data = { 259 | 'WP3_eventYears': {1896: 1, 1897: 0, 1898: 1, 1895: 0}, 260 | 'WP3_numAchieved': {1896: 1, 1897: 1, 1898: 1, 1895: 1}, 261 | 'WP3_numEvents': {1896: 1, 1897: 1, 1898: 1, 1895: 1}, 262 | 'WP3_numEventsAll': {1896: 1, 1897: 1, 1898: 1, 1895: 1}, 263 | 264 | 'WP4_eventYears': {1896: 0, 1897: 1, 1898: 0, 1895: 1}, 265 | 'WP4_numAchieved': {1896: 1, 1897: 1, 1898: 1, 1895: 1}, 266 | 'WP4_numEvents': {1896: 1, 1897: 1, 1898: 1, 1895: 1}, 267 | 'WP4_numEventsAll': {1896: 1, 1897: 1, 1898: 1, 1895: 1}, 268 | 269 | 'SF-WP_eventYears': {1896: 1, 1897: 1, 1898: 0, 1895: 0}, 270 | 'SF-WP_numAchieved': {1896: 1, 1897: 1, 1898: 1, 1895: 1}, 271 | 'SF-WP_numEvents': {1896: 1, 1897: 1, 1898: 1, 1895: 1}, 272 | 'SF-WP_numEventsAll': {1896: 1, 1897: 1, 1898: 1, 1895: 1}, 273 | 274 | 'LF2-WP_eventYears': {1896: 0, 1897: 0, 1898: 1, 1895: 1}, 275 | 'LF2-WP_numAchieved': {1896: 1, 1897: 1, 1898: 1, 1895: 1}, 276 | 'LF2-WP_numEvents': {1896: 1, 1897: 1, 1898: 1, 1895: 1}, 277 | 'LF2-WP_numEventsAll': {1896: 1, 1897: 1, 1898: 1, 1895: 1} 278 | } 279 | 280 | return pd.DataFrame(df_data) 281 | 282 | @pytest.fixture(scope="function") 283 | def interEvent_item_to_process(): 284 | return {'scenario': ['example_scenario']*9, 285 | 'gauge': ['409025']*6+['410007']*3, 286 | 'pu': ['Murray River - Yarrawonga to Barmah']*6+['Upper Yanco Creek']*3, 287 | 'State': ['NSW']*9, 288 | 'SWSDLName': ['New South Wales Murray']*6+['Murrumbidgee']*3, 289 | 'ewr': ['VF']*3+['LF2']*3+['SF2']*3, 290 | 'waterYear': ['1901', '1901', '1904']*3, 291 | 'startDate': [date(1901, 8, 1), date(1901, 12, 1), date(1904, 1, 31), date(1901, 8, 5), date(1901, 12, 1), date(1904, 1, 31), date(1901, 8, 10), date(1901, 12, 6), date(1904, 1, 31)], 292 | 'endDate': [date(1901, 8, 31), date(1901, 12, 15), date(1904, 3, 31), date(1901, 8, 25), date(1901, 12, 10), date(1904, 2, 15), date(1901, 8, 15), date(1901, 12, 8), date(1904, 2, 5)], 293 | 'eventDuration': [31, 15, 61, 21, 10, 16, 6, 3, 6], 294 | 'eventLength': [31, 15, 61, 21, 10, 16, 6, 3, 6], 295 | 'Multigauge': ['']*9} 296 | 297 | @pytest.fixture(scope="function") 298 | def successfulEvent_item_to_process(): 299 | return {'scenario': ['example_scenario']*9, 300 | 'gauge': ['409025']*6+['410007']*3, 301 | 'pu': ['Murray River - Yarrawonga to Barmah']*6+['Upper Yanco Creek']*3, 302 | 'ewr': ['VF']*3+['LF2']*3+['SF2']*3, 303 | 'waterYear': ['1901', '1901', '1904']*3, 304 | 'startDate': [date(1901, 8, 1), date(1901, 12, 1), date(1904, 1, 31), date(1901, 8, 5), date(1901, 12, 1), date(1904, 1, 31), date(1901, 8, 10), date(1901, 12, 6), date(1904, 1, 31)], 305 | 'endDate': [date(1901, 8, 31), date(1901, 12, 2), date(1904, 3, 31), date(1901, 8, 25), date(1901, 12, 9), date(1904, 2, 15), date(1901, 8, 15), date(1901, 12, 8), date(1904, 3, 5)], 306 | 'eventDuration': [31, 2, 61, 21, 9, 16, 6, 3, 34], 307 | 'eventLength': [31, 2, 61, 21, 9, 16, 6, 3, 34], 308 | 'Multigauge': ['']*9} 309 | 310 | @pytest.fixture(scope="function") 311 | def duplicate_event_item_to_process(): 312 | return {'scenario': ['example_scenario']*9, 313 | 'gauge': ['409025']*6+['410007']*3, 314 | 'pu': ['Murray River - Yarrawonga to Barmah']*6+['Upper Yanco Creek']*3, 315 | 'ewr': ['VF']*3+['LF2']*3+['SF2']*3, 316 | 'waterYear': ['1901', '1901', '1904']*3, 317 | 'startDate': [date(1901, 8, 1), date(1901, 8, 1), date(1904, 1, 31), date(1901, 8, 5), date(1901, 12, 1), date(1904, 1, 31), date(1901, 8, 10), date(1901, 12, 6), date(1901, 12, 6)], 318 | 'endDate': [date(1901, 8, 31), date(1901, 12, 2), date(1904, 3, 31), date(1901, 8, 25), date(1901, 12, 9), date(1904, 2, 15), date(1901, 8, 15), date(1901, 12, 8), date(1904, 3, 5)], 319 | 'eventDuration': [31, 124, 61, 21, 9, 16, 6, 3, 821], 320 | 'eventLength': [31, 124, 61, 21, 9, 16, 6, 3, 821], 321 | 'Multigauge': ['']*9} 322 | 323 | @pytest.fixture(scope="function") 324 | def ewr_calc_config(): 325 | ewr_calc_config = data_inputs.get_ewr_calc_config() 326 | return ewr_calc_config 327 | 328 | @pytest.fixture(scope="function") 329 | def gauge_results(): 330 | return {"scenario": 331 | {"A4261002":{"pu":"DataFrame"}, 332 | "A4260527":{"pu":"DataFrame"}, 333 | "A4260633":{"pu":"DataFrame"}, 334 | "A4260634":{"pu":"DataFrame"}, 335 | "A4260635":{"pu":"DataFrame"}, 336 | "A4260637":{"pu":"DataFrame"} 337 | } 338 | } 339 | 340 | @pytest.fixture(scope="function") 341 | def gauge_results_before_process(): 342 | with open(f"unit_testing_files/gauge_results_before_process.pickle", "rb") as fp: 343 | gauge_results = pickle.load(fp) 344 | return gauge_results 345 | 346 | 347 | @pytest.fixture(scope="function") 348 | def qld_parameter_sheet(): 349 | EWR_table, _ = data_inputs.get_EWR_table("unit_testing_files/qld_parameter_sheet.csv") 350 | return EWR_table 351 | 352 | 353 | @pytest.fixture(scope="function") 354 | def vic_parameter_sheet(): 355 | EWR_table, _ = data_inputs.get_EWR_table("unit_testing_files/vic_parameter_sheet.csv") 356 | return EWR_table 357 | 358 | def gg_pull_mock(*args, **kwargs): 359 | 360 | with open('unit_testing_files/mock_gg_pull.json', 'r') as f: 361 | data = json.load(f) 362 | 363 | gg_response = pd.DataFrame(data) 364 | 365 | return gg_response 366 | 367 | @pytest.fixture(scope="module") 368 | def observed_handler_instance(): 369 | # Set up input parameters and pass to test function 370 | gauges = ['419039'] 371 | dates = {'start_date': date(2020, 7, 1), 'end_date': date(2021, 6, 30)} 372 | 373 | with patch("mdba_gauge_getter.gauge_getter.gauge_pull", side_effect=gg_pull_mock): 374 | ewr_oh = observed_handling.ObservedHandler(gauges, dates, parameter_sheet='unit_testing_files/parameter_sheet.csv') 375 | ewr_oh.process_gauges() 376 | yield ewr_oh -------------------------------------------------------------------------------- /tests/test_data_inputs.py: -------------------------------------------------------------------------------- 1 | from pathlib import Path 2 | import io 3 | 4 | import pandas as pd 5 | from pandas._testing import assert_frame_equal 6 | import numpy as np 7 | import requests 8 | from datetime import datetime 9 | import os 10 | 11 | from py_ewr import data_inputs 12 | import pytest 13 | 14 | BASE_PATH = Path(__file__).resolve().parents[1] 15 | 16 | def test_get_multi_gauges(): 17 | ''' 18 | 1. Test for returning planning units and gauges where there are multi gauge EWR requirements 19 | 2. Test for returning the unique gauge to gauge dictionaries where there are multi gauge EWR requirements 20 | ''' 21 | # Test 1 22 | expected_multi_gauges = {'PU_0000130': {'421090': '421088', '421088': '421090'}, 23 | 'PU_0000131': {'421090': '421088', '421088': '421090'}, 24 | 'PU_0000132': {'421090': '421088', '421088': '421090'}, 25 | 'PU_0000133': {'421090': '421088', '421088': '421090'}, 26 | 'PU_0000251': {'423001': '423002'}, 27 | 'PU_0000280': {'1AS': '1ES'} 28 | } 29 | multi_gauges = data_inputs.get_multi_gauges('all') 30 | assert expected_multi_gauges == multi_gauges 31 | #-------------------------------------------------------- 32 | # Test 2 33 | expected_multi_gauges = {'421090': '421088', '421088': '421090', '423001': '423002', '1AS': '1ES'} 34 | multi_gauges = data_inputs.get_multi_gauges('gauges') 35 | assert expected_multi_gauges == multi_gauges 36 | 37 | def test_get_EWR_table(): 38 | ''' 39 | - 1. Test for equal entries (no lost EWRs) 40 | - 2. Test to ensure no bad EWRs make it through using a subset of EWRs 41 | ''' 42 | # Test 1 43 | proxies={} # Populate with your proxy settings 44 | my_url = os.path.join(BASE_PATH, "py_ewr/parameter_metadata/parameter_sheet.csv") 45 | df = pd.read_csv(my_url, 46 | usecols=['PlanningUnitID', 'PlanningUnitName', 'LTWPShortName', 'CompliancePoint/Node', 'Gauge', 'Code', 'StartMonth', 47 | 'EndMonth', 'TargetFrequency', 'TargetFrequencyMin', 'TargetFrequencyMax', 'EventsPerYear', 'Duration', 'MinSpell', 48 | 'FlowThresholdMin', 'FlowThresholdMax', 'MaxInter-event', 'WithinEventGapTolerance', 'WeirpoolGauge', 'FlowLevelVolume', 49 | 'LevelThresholdMin', 'LevelThresholdMax', 'VolumeThreshold', 'DrawdownRate', 'AccumulationPeriod', 50 | 'Multigauge', 'MaxSpell', 'TriggerDay', 'TriggerMonth', 'DrawDownRateWeek'], 51 | dtype='str', encoding='cp1252' 52 | ) 53 | 54 | # Get the cleaned dataset: 55 | EWR_table, bad_EWRs = data_inputs.get_EWR_table() 56 | 57 | total_len = len(EWR_table)+len(bad_EWRs) 58 | assert len(df), total_len 59 | 60 | def test_get_ewr_calc_config(): 61 | ''' 62 | 1. Test for correct return of EWR calculation config 63 | assert it returns a dictionary 64 | ''' 65 | 66 | ewr_calc_config = data_inputs.get_ewr_calc_config() 67 | 68 | assert isinstance(ewr_calc_config, dict) 69 | assert "flow_handle" in ewr_calc_config.keys() 70 | 71 | 72 | def test_get_barrage_flow_gauges(): 73 | result = data_inputs.get_barrage_flow_gauges() 74 | assert isinstance(result, dict) 75 | # there is only one key in the dictionary 76 | assert len(result) == 1 77 | ## all key main gauge belong to the list of gauges 78 | for k, v in result.items(): 79 | assert isinstance(v, list) 80 | assert k in v 81 | 82 | 83 | def test_get_barrage_level_gauges(): 84 | result = data_inputs.get_barrage_level_gauges() 85 | assert isinstance(result, dict) 86 | # there is only one key in the dictionary 87 | ## all key main gauge belong to the list of gauges 88 | for k, v in result.items(): 89 | assert isinstance(v, list) 90 | assert k in v 91 | 92 | 93 | def test_get_cllmm_gauges(): 94 | result = data_inputs.get_cllmm_gauges() 95 | assert isinstance(result, list) 96 | for item in result: 97 | assert isinstance(item, str) 98 | 99 | @pytest.mark.parametrize('expected_results', 100 | [ 101 | ( 102 | ['A4260527', 'A4260633', 'A4260634', 'A4260635', 'A4260637', 'A4261002'] 103 | ) 104 | ]) 105 | def test_get_scenario_gauges(gauge_results, expected_results): 106 | result = data_inputs.get_scenario_gauges(gauge_results) 107 | assert sorted(result) == expected_results 108 | 109 | def test_get_iqqm_codes(): 110 | result = data_inputs.get_iqqm_codes() 111 | stations = { 112 | '229': '421023', 113 | '42': '421001', 114 | '464': '421011', 115 | '240': '421019', 116 | '266': '421146', 117 | '951': '421090', 118 | '487': '421022', 119 | '130': '421012', 120 | '171': '421004', 121 | } 122 | assert stations == result 123 | 124 | def test_get_causal_ewr(): 125 | 126 | causal_ewr = data_inputs.get_causal_ewr() 127 | assert isinstance(causal_ewr, dict) 128 | 129 | assert len(causal_ewr) > 0 130 | 131 | expected_keys = {"ewr2obj", "obj2target", "obj2yrtarget"} 132 | assert set(causal_ewr.keys()) == expected_keys 133 | 134 | for value in causal_ewr.values(): 135 | assert isinstance(value, pd.DataFrame) -------------------------------------------------------------------------------- /tests/test_observed_handling.py: -------------------------------------------------------------------------------- 1 | from pathlib import Path 2 | import copy 3 | from datetime import date 4 | import re 5 | 6 | import pandas as pd 7 | from pandas._testing import assert_frame_equal 8 | import pytest 9 | 10 | from py_ewr import observed_handling, data_inputs 11 | 12 | BASE_PATH = Path(__file__).resolve().parents[1] 13 | 14 | def test_observed_cleaner(): 15 | ''' 16 | 1. Run sample data through and compare the expected output sample data 17 | ''' 18 | # Test 1 19 | # Load sample input data and pass to function 20 | input_df = pd.read_csv( 'unit_testing_files/observed_flows_test_input.csv') 21 | dates = {'start_date': date(2014, 1, 1), 'end_date': date(2020, 1, 1)} 22 | result = observed_handling.observed_cleaner(input_df, dates) 23 | # Load sample output data and test 24 | output_df = 'unit_testing_files/observed_flows_test_output.csv' 25 | expected_result = pd.read_csv(output_df, index_col = 'Date') 26 | expected_result.index = pd.to_datetime(expected_result.index, format='%Y-%m-%d') 27 | expected_result.index = expected_result.index#.to_period() 28 | expected_result.columns = ['419039'] 29 | assert_frame_equal(result, expected_result) 30 | 31 | def test_one_gauge_per_column(): 32 | ''' 33 | 1. Run sample data through and compare to the expected output sample data 34 | ''' 35 | # Test 1 36 | # load and format expected output data 37 | output_df = 'unit_testing_files/observed_flows_test_output.csv' 38 | expected_result = pd.read_csv(output_df, index_col = 'Date') 39 | expected_result.index = pd.to_datetime(expected_result.index, format='%Y-%m-%d') 40 | expected_result.columns = ['419039'] 41 | # Load input data and pass to function 42 | input_dataframe = pd.read_csv('unit_testing_files/observed_flows_test_input.csv') 43 | gauge_iter = 419039 44 | input_dataframe['Date'] = expected_result.index 45 | result = observed_handling.one_gauge_per_column(input_dataframe, gauge_iter) 46 | # assert equal test 47 | assert_frame_equal(result, expected_result) 48 | 49 | 50 | def test_remove_data_with_bad_QC(): 51 | ''' 52 | 1. Run sample data through and compare to the expected output sample data to ensure bad data is removed 53 | ''' 54 | # Test 1 55 | # Load sample input data: 56 | input_dataframe = pd.read_csv('unit_testing_files/observed_flows_test_input_QC.csv', index_col = 'Date') 57 | gauge_iter = 419039 58 | qc_codes = data_inputs.get_bad_QA_codes() 59 | # Load output sample data 60 | expected_df = pd.read_csv('unit_testing_files/observed_flows_test_output_QC.csv', index_col = 'Date') 61 | 62 | # Throw to the function 63 | df = observed_handling.remove_data_with_bad_QC(input_dataframe, qc_codes) 64 | 65 | # Test for equality 66 | assert_frame_equal(df, expected_df) 67 | 68 | 69 | def test_categorise_gauges(): 70 | ''' 71 | 1. gauges in all categories 72 | 2. gauges outside cats 73 | ''' 74 | gauges = ['422015', '422030', '416001', '421088', '414203', 'A4260527', 'A4260633', '425020', 'A4261002', 'A4261002'] 75 | 76 | flow = ['422015', '422030', '421088', '414203', '416001', 'A4261002'] 77 | level = ['422015', '422030', '414209', 'A4260527', 'A4260633'] 78 | lake_level = ['A4260527', 'A4260633','425020'] 79 | 80 | expected_flow = ['422015', '422030', '421088', '421090', '414203', '416001', 'A4261002'] 81 | expected_level = ['422015', '422030', '414209', 'A4260527','A4261133', 'A4260524', 'A4260574', 'A4260575', 'A4260633','A4261209', 'A4261165'] 82 | expected_lake_level = ['425020', 'A4260527','A4261133', 'A4260524', 'A4260574', 'A4260575', 'A4260633','A4261209', 'A4261165'] 83 | 84 | all_gauges = level + flow + lake_level 85 | 86 | f, l, ll = observed_handling.categorise_gauges(all_gauges) 87 | 88 | # expected_level = copy.deepcopy(level) 89 | # expected_flow = copy.deepcopy(flow) 90 | # expected_lake_level = copy.deepcopy(lake_level) 91 | 92 | assert set(f) == set(expected_flow) 93 | assert set(l) == set(expected_level) 94 | assert set(ll) == set(expected_lake_level) 95 | 96 | 97 | def test_observed_handler_class(observed_handler_expected_detail, observed_handler_instance): 98 | 99 | observed_handler_instance.process_gauges() 100 | 101 | detailed = observed_handler_instance.pu_ewr_statistics 102 | 103 | detailed['observed']['419039']['Boggabri to Wee Waa'].index = detailed['observed']['419039']['Boggabri to Wee Waa'].index.astype('int64') 104 | 105 | assert_frame_equal(detailed['observed']['419039']['Boggabri to Wee Waa'], observed_handler_expected_detail) 106 | 107 | def test_get_all_events(observed_handler_instance): 108 | 109 | all_events = observed_handler_instance.get_all_events() 110 | assert type(all_events) == pd.DataFrame 111 | assert all_events.shape == (76, 12) 112 | assert all_events.columns.to_list() == ['scenario', 'gauge', 'pu', 'State', 'SWSDLName', 'ewr', 'waterYear', 'startDate', 'endDate', 113 | 'eventDuration', 'eventLength', 'Multigauge'] 114 | 115 | def test_get_yearly_ewr_results(observed_handler_instance): 116 | 117 | yearly_results = observed_handler_instance.get_yearly_ewr_results() 118 | assert type(yearly_results) == pd.DataFrame 119 | assert yearly_results.shape == (24, 23) 120 | assert yearly_results.columns.to_list() == ['Year', 'eventYears', 'numAchieved', 'numEvents', 'numEventsAll', 121 | 'eventLength', 'eventLengthAchieved', 122 | 'totalEventDays', 'totalEventDaysAchieved','maxEventDays', 'maxRollingEvents', 'maxRollingAchievement','missingDays', 123 | 'totalPossibleDays', 'ewrCode', 'scenario', 'gauge', 'pu', 'State', 'SWSDLName', 'Multigauge', 'rollingMaxInterEvent', 'rollingMaxInterEventAchieved'] 124 | 125 | def test_get_ewr_results(observed_handler_instance): 126 | 127 | ewr_results = observed_handler_instance.get_ewr_results() 128 | assert type(ewr_results) == pd.DataFrame 129 | assert ewr_results.shape == (24, 21) 130 | assert ewr_results.columns.to_list() == ['Scenario', 'Gauge', 'PlanningUnit', 'State', 'SWSDLName', 'EwrCode', 'Multigauge','EventYears', 131 | 'Frequency', 'TargetFrequency', 'AchievementCount', 132 | 'AchievementPerYear', 'EventCount', 'EventCountAll', 'EventsPerYear', 'EventsPerYearAll', 133 | 'AverageEventLength', 'ThresholdDays', 134 | 'MaxInterEventYears', 'NoDataDays', 'TotalDays'] 135 | -------------------------------------------------------------------------------- /tests/test_summarise_results.py: -------------------------------------------------------------------------------- 1 | from datetime import date 2 | import pandas as pd 3 | from pandas._testing import assert_frame_equal 4 | import pytest 5 | 6 | 7 | from py_ewr import data_inputs, summarise_results 8 | 9 | 10 | def test_get_frequency(): 11 | ''' 12 | Series input to get_frequency function will only be made up of combination of 1's or 0's. 13 | 1. Test to see if function is returning frequency of 1 occurrence out of all years. 14 | 2. Test to see if function handles no occurrence of 1's 15 | ''' 16 | # Test 1 17 | input_series = pd.Series(index=[1895, 1896, 1897, 1898, 1899], data=[0,1,1,1,0]) 18 | f = summarise_results.get_frequency(input_series) 19 | expected_f = 60 20 | assert f == expected_f 21 | # ---------------------------- 22 | # Test 2 23 | input_series = pd.Series(index=[1895, 1896, 1897, 1898, 1899], data=[0,0,0,0,0]) 24 | f = summarise_results.get_frequency(input_series) 25 | expected_f = 0 26 | assert f == expected_f 27 | 28 | @pytest.mark.parametrize("ewr,cols,expected", 29 | [("CF1", ["CF1_foo","CF1_bar","CF2_foo","CF2_bar"],["CF1_foo","CF1_bar"]), 30 | ("CF3", ["CF1_foo","CF1_bar","CF2_foo","CF2_bar"],[])], 31 | ) 32 | def test_get_ewr_columns(ewr, cols, expected): 33 | result = summarise_results.get_ewr_columns(ewr, cols) 34 | assert result == expected 35 | 36 | @pytest.mark.parametrize("cols,expected", 37 | [(["CF1_foo","CF1_bar","CF2_foo","CF2_bar"],["foo","bar","foo","bar"]), 38 | ], 39 | ) 40 | def test_get_columns_attributes(cols, expected): 41 | result = summarise_results.get_columns_attributes(cols) 42 | 43 | assert result == expected 44 | 45 | 46 | def test_get_ewrs(pu_df): 47 | result = summarise_results.get_ewrs(pu_df) 48 | assert result == ["CF1_a"] 49 | 50 | 51 | def test_pu_dfs_to_process(detailed_results, pu_df): 52 | result = summarise_results.pu_dfs_to_process(detailed_results) 53 | assert result == [{ "scenario" : 'observed', 54 | "gauge" : '419001', 55 | "pu" : 'Keepit to Boggabri', 56 | "pu_df" : pu_df }, 57 | { "scenario" : 'observed', 58 | "gauge" : '419002', 59 | "pu" : 'Keepit to Boggabri', 60 | "pu_df" : pu_df }] 61 | 62 | def test_process_df(item_to_process): 63 | result = summarise_results.process_df(**item_to_process) 64 | columns = result.columns.to_list() 65 | assert columns == ['Year', 'eventYears', 'numAchieved', 'numEvents', 'numEventsAll','eventLength', 'eventLengthAchieved', 66 | 'totalEventDays', 'totalEventDaysAchieved', "rollingMaxInterEventAchieved", 'missingDays', 67 | 'totalPossibleDays', 'ewrCode', 'scenario', 'gauge', 'pu'] 68 | assert result.shape == (2, 16) 69 | 70 | def test_process_df_results(items_to_process): 71 | result = summarise_results.process_df_results(items_to_process) 72 | columns = result.columns.to_list() 73 | assert columns == ['Year', 'eventYears', 'numAchieved', 'numEvents', 'numEventsAll','eventLength', 'eventLengthAchieved', 74 | 'totalEventDays', 'totalEventDaysAchieved', "rollingMaxInterEventAchieved", 'missingDays', 75 | 'totalPossibleDays', 'ewrCode', 'scenario', 'gauge', 'pu'] 76 | assert result.shape == (4, 16) 77 | 78 | def test_get_events_to_process(gauge_events): 79 | result = summarise_results.get_events_to_process(gauge_events) 80 | assert result == [ { "scenario" : 'observed', 81 | "gauge" : '419001', 82 | "pu" : 'Keepit to Boggabri', 83 | "ewr": 'CF1_a', 84 | "ewr_events" : {2010: [], 85 | 2011: [], 86 | 2012: [], 87 | 2013: [], 88 | 2014: [[0.0, 0.0, 0.0, 0.0, 0.0, 0.0]]} 89 | }, 90 | {"scenario" : 'observed', 91 | "gauge" : '419002', 92 | "pu" : 'Keepit to Boggabri', 93 | "ewr": 'CF1_a', 94 | "ewr_events" : {2010: [], 95 | 2011: [], 96 | 2012: [], 97 | 2013: [], 98 | 2014: [[0.0, 0.0, 0.0, 0.0, 0.0, 0.0]]}} 99 | ] 100 | 101 | def test_count_events(yearly_events): 102 | result = summarise_results.count_events(yearly_events) 103 | assert result == 1 104 | 105 | def test_sum_events(yearly_events): 106 | result = summarise_results.sum_events(yearly_events) 107 | assert result == 6 108 | 109 | def test_process_yearly_events(event_item_to_process): 110 | result = summarise_results.process_yearly_events(**event_item_to_process) 111 | assert type(result) == pd.DataFrame 112 | assert result.to_dict() == {'scenario': {0: 'observed'}, 113 | 'gauge': {0: '419001'}, 114 | 'pu': {0: 'Keepit to Boggabri'}, 115 | 'ewrCode': {0: 'CF1_a'}, 116 | 'totalEvents': {0: 1}, 117 | 'totalEventDays': {0: 6}, 118 | 'averageEventLength': {0: 6.0}} 119 | 120 | def test_process_ewr_events_stats(event_items_to_process): 121 | result = summarise_results.process_ewr_events_stats(event_items_to_process) 122 | assert type(result) == pd.DataFrame 123 | assert result.shape == (2, 7) 124 | assert result.to_dict() == {'scenario': {0: 'observed', 1: 'observed'}, 125 | 'gauge': {0: '419001', 1: '419002'}, 126 | 'pu': {0: 'Keepit to Boggabri', 1: 'Keepit to Boggabri'}, 127 | 'ewrCode': {0: 'CF1_a', 1: 'CF1_a'}, 128 | 'totalEvents': {0: 1, 1: 1}, 129 | 'totalEventDays': {0: 6, 1: 6}, 130 | 'averageEventLength': {0: 6.0, 1: 6.0}} 131 | 132 | def test_summarise(detailed_results, gauge_events): 133 | result = summarise_results.summarise(input_dict=detailed_results, events=gauge_events) 134 | assert type(result) == pd.DataFrame 135 | 136 | 137 | def test_process_all_yearly_events(event_item_to_process): 138 | result = summarise_results.process_all_yearly_events(**event_item_to_process) 139 | assert result.to_dict() == {'scenario': {0: 'observed'}, 140 | 'gauge': {0: '419001'}, 141 | 'pu': {0: 'Keepit to Boggabri'}, 142 | 'ewr': {0: 'CF1_a'}, 143 | 'waterYear': {0: 2014}, 144 | 'startDate': {0: date(2020, 11, 30)}, 145 | 'endDate': {0: date(2020, 12, 5)}, 146 | 'eventDuration': {0: 6}, 147 | 'eventLength': {0: 6}} 148 | 149 | def test_process_all_events_results(event_items_to_process): 150 | result = summarise_results.process_all_events_results(event_items_to_process) 151 | assert result.to_dict() == {'scenario': {0: 'observed', 1: 'observed'}, 152 | 'gauge': {0: '419001', 1: '419002'}, 153 | 'pu': {0: 'Keepit to Boggabri', 1: 'Keepit to Boggabri'}, 154 | 'ewr': {0: 'CF1_a', 1: 'CF1_a'}, 155 | 'waterYear': {0: 2014, 1: 2014}, 156 | 'startDate': {0: date(2020, 11, 30), 1: date(2020, 11, 30)}, 157 | 'endDate': {0: date(2020, 12, 5), 1: date(2020, 12, 5)}, 158 | 'eventDuration': {0: 6, 1: 6}, 159 | 'eventLength': {0: 6, 1: 6}} 160 | 161 | 162 | def test_events_to_interevents(interEvent_item_to_process): 163 | 164 | all_events_df = pd.DataFrame(data = interEvent_item_to_process) 165 | start_date = date(1901,7,1) 166 | end_date = date(1905,6,30) 167 | all_interevents_df = summarise_results.events_to_interevents(start_date, end_date, all_events_df) 168 | 169 | expected_data = {'scenario': ['example_scenario']*12, 170 | 'gauge': ['409025']*8+['410007']*4, 171 | 'pu': ['Murray River - Yarrawonga to Barmah']*8+['Upper Yanco Creek']*4, 172 | 'State': ['NSW']*12, 173 | 'SWSDLName': ['New South Wales Murray']*8+['Murrumbidgee']*4, 174 | 'ewr': ['VF']*4+['LF2']*4+['SF2']*4, 175 | 'startDate': [date(1901,7,1), date(1901, 9, 1), date(1901, 12, 16), date(1904, 4, 1), date(1901,7,1), date(1901, 8, 26), date(1901, 12, 11), date(1904, 2, 16), date(1901, 7, 1), date(1901, 8, 16), date(1901, 12, 9), date(1904, 2, 6)], 176 | 'endDate': [date(1901, 7, 31), date(1901, 11, 30), date(1904, 1, 30), date(1905,6,30), date(1901, 8, 4), date(1901, 11, 30), date(1904, 1, 30), date(1905,6,30), date(1901, 8, 9), date(1901, 12, 5), date(1904, 1, 30), date(1905,6,30)], 177 | 'interEventLength': [31, 91, 776, 456, 35, 97, 781, 501, 40, 112, 783, 511] 178 | } 179 | expected_all_interevents_df = pd.DataFrame(data = expected_data) 180 | 181 | assert all_interevents_df.to_dict() == expected_all_interevents_df.to_dict() 182 | 183 | def test_filter_successful_events(successfulEvent_item_to_process): 184 | all_events_df = pd.DataFrame(data = successfulEvent_item_to_process) 185 | all_interevents_df = summarise_results.filter_successful_events(all_events_df) 186 | 187 | expected_data = {'scenario': ['example_scenario']*6, 188 | 'gauge': ['409025']*5+['410007']*1, 189 | 'pu': ['Murray River - Yarrawonga to Barmah']*5+['Upper Yanco Creek']*1, 190 | 'ewr': ['VF']*3+['LF2']*2+['SF2']*1, 191 | 'waterYear': ['1901', '1901', '1904', '1901', '1904', '1904'], 192 | 'startDate': [date(1901, 8, 1), date(1901, 12, 1), date(1904, 1, 31), date(1901, 8, 5), date(1904, 1, 31), date(1904, 1, 31)], 193 | 'endDate': [date(1901, 8, 31), date(1901, 12, 2), date(1904, 3, 31), date(1901, 8, 25), date(1904, 2, 15), date(1904, 3, 5)], 194 | 'eventDuration': [31, 2, 61, 21, 16, 34], 195 | 'eventLength': [31, 2, 61, 21, 16, 34], 196 | 'Multigauge': ['']*6} 197 | expected_all_interevents_df = pd.DataFrame(data = expected_data) 198 | 199 | assert all_interevents_df.to_dict() == expected_all_interevents_df.to_dict() 200 | 201 | def test_filter_duplicate_start_dates(duplicate_event_item_to_process): 202 | all_events_df = pd.DataFrame(data = duplicate_event_item_to_process) 203 | df = summarise_results.filter_duplicate_start_dates(all_events_df) 204 | 205 | expected_data = {'scenario': ['example_scenario']*7, 206 | 'gauge': ['409025']*5+['410007']*2, 207 | 'pu': ['Murray River - Yarrawonga to Barmah']*5+['Upper Yanco Creek']*2, 208 | 'ewr': ['VF']*2+['LF2']*3+['SF2']*2, 209 | 'waterYear': ['1901', '1904', '1901', '1901', '1904','1901', '1904'], 210 | 'startDate': [date(1901, 8, 1), date(1904, 1, 31), date(1901, 8, 5), date(1901, 12, 1), date(1904, 1, 31), date(1901, 8, 10), date(1901, 12, 6)], 211 | 'endDate': [date(1901, 12, 2), date(1904, 3, 31), date(1901, 8, 25), date(1901, 12, 9), date(1904, 2, 15), date(1901, 8, 15), date(1904, 3, 5)], 212 | 'eventDuration': [124, 61, 21, 9, 16, 6, 821], 213 | 'eventLength': [124, 61, 21, 9, 16, 6, 821], 214 | 'Multigauge': ['']*7} 215 | 216 | expected_df = pd.DataFrame(data=expected_data) 217 | 218 | assert df.reset_index(drop=True).to_dict() == expected_df.reset_index(drop=True).to_dict() 219 | 220 | 221 | @pytest.mark.parametrize("events_date_range, start_date, end_date, expected_result",[ 222 | ( 223 | [ 224 | ( date(2000,12,14), date(2007,1,2) ), 225 | ( date(2004,3,19), date(2009,12,25)), 226 | ( date(2013,4,23), date(2020,1,24) ) 227 | ], 228 | date(2000,1,1), 229 | date(2023,12,31), 230 | 231 | [(date(2000, 1, 1), date(2000, 12, 13)), 232 | (date(2009, 12, 26), date(2013, 4, 22)), 233 | (date(2020, 1, 25), date(2023, 12, 31))] 234 | ), 235 | ( 236 | [ 237 | ( date(2000,12,14), date(2007,1,2) ), 238 | ( date(2004,3,19), date(2009,12,25)), 239 | ( date(2013,4,23), date(2020,1,24) ) 240 | ], 241 | date(2000,12,14), 242 | date(2023,12,31), 243 | 244 | [ 245 | (date(2009, 12, 26), date(2013, 4, 22)), 246 | (date(2020, 1, 25), date(2023, 12, 31))] 247 | ), 248 | ( 249 | [ 250 | ( date(2000,12,14), date(2007,1,2) ), 251 | ( date(2004,3,19), date(2009,12,25)), 252 | ( date(2013,4,23), date(2020,1,24) ) 253 | ], 254 | date(2000,12,14), 255 | date(2020,1,24), 256 | 257 | [ 258 | (date(2009, 12, 26), date(2013, 4, 22)) 259 | ] 260 | ), 261 | ( 262 | [ 263 | ( date(2000,12,14), date(2007,1,2) ), 264 | ( date(2004,3,19), date(2009,12,25)) 265 | ], 266 | date(2000,12,14), 267 | date(2009,12,25), 268 | 269 | [ 270 | 271 | ] 272 | ), 273 | 274 | ]) 275 | def test_get_inter_events_date_ranges(events_date_range, start_date, end_date, expected_result): 276 | result = summarise_results.get_inter_events_date_ranges(events_date_range, start_date, end_date) 277 | assert result == expected_result 278 | 279 | -------------------------------------------------------------------------------- /tox.ini: -------------------------------------------------------------------------------- 1 | [tox] 2 | envlist = python3.9, python3.10, python3.11, python3.12, python3.13 3 | 4 | [gh-actions] 5 | python = 6 | 3.9: python3.9 7 | 3.10: python3.10 8 | 3.11: python3.11 9 | 3.12: python3.12 10 | 3.13: python3.13 11 | 12 | [testenv] 13 | deps = pytest 14 | commands = 15 | pytest 16 | -------------------------------------------------------------------------------- /unit_testing_files/MDBA_bigmod_test_file_header_result.csv: -------------------------------------------------------------------------------- 1 | Field,Precision,Infill,LastMonth,Site,Measurand,Quality,Name,Description,Units 2 | EOC,,,,,,,,, 3 | 2,,,,,,,,, 4 | 1,0,0,0,'SACHRES',287,'9','','SA Critical Human Needs Reserve (GL)',GL 5 | 2,0,0,0,'JINGELL',1,'8','','JINGELL -401201 Flow (ML/d)',ML.day^-1 6 | -------------------------------------------------------------------------------- /unit_testing_files/NSW_source_res_test_file_header_result.csv: -------------------------------------------------------------------------------- 1 | Field,Units,RunName,ScenarioName,ScenarioInputSetName,Name,Site,ElementName,WaterFeatureType,ElementType,Structure,Custom 2 | EOC,,,,,,,,,,, 3 | 514,,,,,,,,,,, 4 | 1,m,Latest Run,Yanco Acceleration,No_Change,049050_SILO_FAO56.csv,Data Sources,Data Sources,Data Sources,Miscellaneous,Data Sources@Climate Data@FAO56_res_csv@049050_SILO_FAO56.csv,0a6ba333-3066-4678-bc30-9ba8b52e2c46 5 | 2,m,Latest Run,Yanco Acceleration,No_Change,049050_SILO_Mwet.csv,Data Sources,Data Sources,Data Sources,Miscellaneous,Data Sources@Climate Data@Mwet_res_csv@049050_SILO_Mwet.csv,0a6ba333-3066-4678-bc30-9ba8b52e2c46 6 | -------------------------------------------------------------------------------- /unit_testing_files/detailed_results_observed.csv: -------------------------------------------------------------------------------- 1 | ,CF1_a_eventYears,CF1_a_numAchieved,CF1_a_numEvents,CF1_a_numEventsAll,CF1_a_maxInterEventDays,CF1_a_maxInterEventDaysAchieved,CF1_a_eventLength,CF1_a_eventLengthAchieved,CF1_a_totalEventDays,CF1_a_totalEventDaysAchieved,CF1_a_maxEventDays,CF1_a_maxRollingEvents,CF1_a_maxRollingAchievement,CF1_a_missingDays,CF1_a_totalPossibleDays,CF1_c_eventYears,CF1_c_numAchieved,CF1_c_numEvents,CF1_c_numEventsAll,CF1_c_maxInterEventDays,CF1_c_maxInterEventDaysAchieved,CF1_c_eventLength,CF1_c_eventLengthAchieved,CF1_c_totalEventDays,CF1_c_totalEventDaysAchieved,CF1_c_maxEventDays,CF1_c_maxRollingEvents,CF1_c_maxRollingAchievement,CF1_c_missingDays,CF1_c_totalPossibleDays,CF1_b_eventYears,CF1_b_numAchieved,CF1_b_numEvents,CF1_b_numEventsAll,CF1_b_maxInterEventDays,CF1_b_maxInterEventDaysAchieved,CF1_b_eventLength,CF1_b_eventLengthAchieved,CF1_b_totalEventDays,CF1_b_totalEventDaysAchieved,CF1_b_maxEventDays,CF1_b_maxRollingEvents,CF1_b_maxRollingAchievement,CF1_b_missingDays,CF1_b_totalPossibleDays,VF1_a_eventYears,VF1_a_numAchieved,VF1_a_numEvents,VF1_a_numEventsAll,VF1_a_maxInterEventDays,VF1_a_maxInterEventDaysAchieved,VF1_a_eventLength,VF1_a_eventLengthAchieved,VF1_a_totalEventDays,VF1_a_totalEventDaysAchieved,VF1_a_maxEventDays,VF1_a_maxRollingEvents,VF1_a_maxRollingAchievement,VF1_a_missingDays,VF1_a_totalPossibleDays,VF1_b_eventYears,VF1_b_numAchieved,VF1_b_numEvents,VF1_b_numEventsAll,VF1_b_maxInterEventDays,VF1_b_maxInterEventDaysAchieved,VF1_b_eventLength,VF1_b_eventLengthAchieved,VF1_b_totalEventDays,VF1_b_totalEventDaysAchieved,VF1_b_maxEventDays,VF1_b_maxRollingEvents,VF1_b_maxRollingAchievement,VF1_b_missingDays,VF1_b_totalPossibleDays,BF1_a_eventYears,BF1_a_numAchieved,BF1_a_numEvents,BF1_a_numEventsAll,BF1_a_maxInterEventDays,BF1_a_maxInterEventDaysAchieved,BF1_a_eventLength,BF1_a_eventLengthAchieved,BF1_a_totalEventDays,BF1_a_totalEventDaysAchieved,BF1_a_maxEventDays,BF1_a_maxRollingEvents,BF1_a_maxRollingAchievement,BF1_a_missingDays,BF1_a_totalPossibleDays,BF1_b_eventYears,BF1_b_numAchieved,BF1_b_numEvents,BF1_b_numEventsAll,BF1_b_maxInterEventDays,BF1_b_maxInterEventDaysAchieved,BF1_b_eventLength,BF1_b_eventLengthAchieved,BF1_b_totalEventDays,BF1_b_totalEventDaysAchieved,BF1_b_maxEventDays,BF1_b_maxRollingEvents,BF1_b_maxRollingAchievement,BF1_b_missingDays,BF1_b_totalPossibleDays,BF2_a_eventYears,BF2_a_numAchieved,BF2_a_numEvents,BF2_a_numEventsAll,BF2_a_maxInterEventDays,BF2_a_maxInterEventDaysAchieved,BF2_a_eventLength,BF2_a_eventLengthAchieved,BF2_a_totalEventDays,BF2_a_totalEventDaysAchieved,BF2_a_maxEventDays,BF2_a_maxRollingEvents,BF2_a_maxRollingAchievement,BF2_a_missingDays,BF2_a_totalPossibleDays,BF2_b_eventYears,BF2_b_numAchieved,BF2_b_numEvents,BF2_b_numEventsAll,BF2_b_maxInterEventDays,BF2_b_maxInterEventDaysAchieved,BF2_b_eventLength,BF2_b_eventLengthAchieved,BF2_b_totalEventDays,BF2_b_totalEventDaysAchieved,BF2_b_maxEventDays,BF2_b_maxRollingEvents,BF2_b_maxRollingAchievement,BF2_b_missingDays,BF2_b_totalPossibleDays,SF1_P_eventYears,SF1_P_numAchieved,SF1_P_numEvents,SF1_P_numEventsAll,SF1_P_maxInterEventDays,SF1_P_maxInterEventDaysAchieved,SF1_P_eventLength,SF1_P_eventLengthAchieved,SF1_P_totalEventDays,SF1_P_totalEventDaysAchieved,SF1_P_maxEventDays,SF1_P_maxRollingEvents,SF1_P_maxRollingAchievement,SF1_P_missingDays,SF1_P_totalPossibleDays,SF1_S_eventYears,SF1_S_numAchieved,SF1_S_numEvents,SF1_S_numEventsAll,SF1_S_maxInterEventDays,SF1_S_maxInterEventDaysAchieved,SF1_S_eventLength,SF1_S_eventLengthAchieved,SF1_S_totalEventDays,SF1_S_totalEventDaysAchieved,SF1_S_maxEventDays,SF1_S_maxRollingEvents,SF1_S_maxRollingAchievement,SF1_S_missingDays,SF1_S_totalPossibleDays,SF2_eventYears,SF2_numAchieved,SF2_numEvents,SF2_numEventsAll,SF2_maxInterEventDays,SF2_maxInterEventDaysAchieved,SF2_eventLength,SF2_eventLengthAchieved,SF2_totalEventDays,SF2_totalEventDaysAchieved,SF2_maxEventDays,SF2_maxRollingEvents,SF2_maxRollingAchievement,SF2_missingDays,SF2_totalPossibleDays,LF1_P_eventYears,LF1_P_numAchieved,LF1_P_numEvents,LF1_P_numEventsAll,LF1_P_maxInterEventDays,LF1_P_maxInterEventDaysAchieved,LF1_P_eventLength,LF1_P_eventLengthAchieved,LF1_P_totalEventDays,LF1_P_totalEventDaysAchieved,LF1_P_maxEventDays,LF1_P_maxRollingEvents,LF1_P_maxRollingAchievement,LF1_P_missingDays,LF1_P_totalPossibleDays,LF1_S_eventYears,LF1_S_numAchieved,LF1_S_numEvents,LF1_S_numEventsAll,LF1_S_maxInterEventDays,LF1_S_maxInterEventDaysAchieved,LF1_S_eventLength,LF1_S_eventLengthAchieved,LF1_S_totalEventDays,LF1_S_totalEventDaysAchieved,LF1_S_maxEventDays,LF1_S_maxRollingEvents,LF1_S_maxRollingAchievement,LF1_S_missingDays,LF1_S_totalPossibleDays,LF2_eventYears,LF2_numAchieved,LF2_numEvents,LF2_numEventsAll,LF2_maxInterEventDays,LF2_maxInterEventDaysAchieved,LF2_eventLength,LF2_eventLengthAchieved,LF2_totalEventDays,LF2_totalEventDaysAchieved,LF2_maxEventDays,LF2_maxRollingEvents,LF2_maxRollingAchievement,LF2_missingDays,LF2_totalPossibleDays,BK1_eventYears,BK1_numAchieved,BK1_numEvents,BK1_numEventsAll,BK1_maxInterEventDays,BK1_maxInterEventDaysAchieved,BK1_eventLength,BK1_eventLengthAchieved,BK1_totalEventDays,BK1_totalEventDaysAchieved,BK1_maxEventDays,BK1_maxRollingEvents,BK1_maxRollingAchievement,BK1_missingDays,BK1_totalPossibleDays,BK2_P_eventYears,BK2_P_numAchieved,BK2_P_numEvents,BK2_P_numEventsAll,BK2_P_maxInterEventDays,BK2_P_maxInterEventDaysAchieved,BK2_P_eventLength,BK2_P_eventLengthAchieved,BK2_P_totalEventDays,BK2_P_totalEventDaysAchieved,BK2_P_maxEventDays,BK2_P_maxRollingEvents,BK2_P_maxRollingAchievement,BK2_P_missingDays,BK2_P_totalPossibleDays,BK2_S_eventYears,BK2_S_numAchieved,BK2_S_numEvents,BK2_S_numEventsAll,BK2_S_maxInterEventDays,BK2_S_maxInterEventDaysAchieved,BK2_S_eventLength,BK2_S_eventLengthAchieved,BK2_S_totalEventDays,BK2_S_totalEventDaysAchieved,BK2_S_maxEventDays,BK2_S_maxRollingEvents,BK2_S_maxRollingAchievement,BK2_S_missingDays,BK2_S_totalPossibleDays,OB1_eventYears,OB1_numAchieved,OB1_numEvents,OB1_numEventsAll,OB1_maxInterEventDays,OB1_maxInterEventDaysAchieved,OB1_eventLength,OB1_eventLengthAchieved,OB1_totalEventDays,OB1_totalEventDaysAchieved,OB1_maxEventDays,OB1_maxRollingEvents,OB1_maxRollingAchievement,OB1_missingDays,OB1_totalPossibleDays,OB2_eventYears,OB2_numAchieved,OB2_numEvents,OB2_numEventsAll,OB2_maxInterEventDays,OB2_maxInterEventDaysAchieved,OB2_eventLength,OB2_eventLengthAchieved,OB2_totalEventDays,OB2_totalEventDaysAchieved,OB2_maxEventDays,OB2_maxRollingEvents,OB2_maxRollingAchievement,OB2_missingDays,OB2_totalPossibleDays,OB3_P_eventYears,OB3_P_numAchieved,OB3_P_numEvents,OB3_P_numEventsAll,OB3_P_maxInterEventDays,OB3_P_maxInterEventDaysAchieved,OB3_P_eventLength,OB3_P_eventLengthAchieved,OB3_P_totalEventDays,OB3_P_totalEventDaysAchieved,OB3_P_maxEventDays,OB3_P_maxRollingEvents,OB3_P_maxRollingAchievement,OB3_P_missingDays,OB3_P_totalPossibleDays,OB3_S_eventYears,OB3_S_numAchieved,OB3_S_numEvents,OB3_S_numEventsAll,OB3_S_maxInterEventDays,OB3_S_maxInterEventDaysAchieved,OB3_S_eventLength,OB3_S_eventLengthAchieved,OB3_S_totalEventDays,OB3_S_totalEventDaysAchieved,OB3_S_maxEventDays,OB3_S_maxRollingEvents,OB3_S_maxRollingAchievement,OB3_S_missingDays,OB3_S_totalPossibleDays,OB4_P_eventYears,OB4_P_numAchieved,OB4_P_numEvents,OB4_P_numEventsAll,OB4_P_maxInterEventDays,OB4_P_maxInterEventDaysAchieved,OB4_P_eventLength,OB4_P_eventLengthAchieved,OB4_P_totalEventDays,OB4_P_totalEventDaysAchieved,OB4_P_maxEventDays,OB4_P_maxRollingEvents,OB4_P_maxRollingAchievement,OB4_P_missingDays,OB4_P_totalPossibleDays,OB4_S_eventYears,OB4_S_numAchieved,OB4_S_numEvents,OB4_S_numEventsAll,OB4_S_maxInterEventDays,OB4_S_maxInterEventDaysAchieved,OB4_S_eventLength,OB4_S_eventLengthAchieved,OB4_S_totalEventDays,OB4_S_totalEventDaysAchieved,OB4_S_maxEventDays,OB4_S_maxRollingEvents,OB4_S_maxRollingAchievement,OB4_S_missingDays,OB4_S_totalPossibleDays 2 | 2020,1,1,1,1,0,1,22.0,22.0,22,22,22,22,1,0,365,1,1,1,1,0,1,22.0,22.0,22,22,22,22,1,0,365,0,0,0,1,0,1,22.0,0.0,22,0,22,22,0,0,365,0,0,0,5,0,1,54.8,54.8,274,274,191,191,0,0,365,1,1,1,5,0,1,54.8,54.8,274,274,191,191,1,0,365,0,0,0,9,0,1,24.77777777777778,24.77777777777778,223,223,71,71,0,0,365,1,2,2,9,0,1,24.77777777777778,24.77777777777778,223,223,71,71,0,0,365,0,0,0,5,0,1,20.8,20.8,104,104,71,71,0,0,365,1,1,1,5,0,1,20.8,20.8,104,104,71,71,1,0,365,1,3,3,7,0,1,12.714285714285714,27.666666666666668,89,83,29,29,1,0,365,1,5,5,11,0,1,11.909090909090908,23.2,131,116,29,29,1,0,365,1,3,3,9,0,1,9.11111111111111,21.666666666666668,82,65,29,29,1,0,365,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,365,1,2,2,4,0,1,3.5,5.5,14,11,6,6,1,0,365,1,1,1,2,0,1,3.5,6.0,7,6,6,6,1,0,365,1,1,1,1,0,1,2.0,2.0,2,2,2,2,1,0,365,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,365,0,0,0,1,0,1,2.0,0.0,2,0,2,2,0,0,365,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,365,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,365,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,365,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,365,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,365,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,365 3 | -------------------------------------------------------------------------------- /unit_testing_files/detailed_results_test.csv: -------------------------------------------------------------------------------- 1 | ,CF1_eventYears,CF1_numAchieved,CF1_numEvents,CF1_numEventsAll,CF1_maxInterEventDays,CF1_maxInterEventDaysAchieved,CF1_eventLength,CF1_eventLengthAchieved,CF1_totalEventDays,CF1_totalEventDaysAchieved,CF1_maxEventDays,CF1_maxRollingEvents,CF1_maxRollingAchievement,CF1_missingDays,CF1_totalPossibleDays,VF1_a_eventYears,VF1_a_numAchieved,VF1_a_numEvents,VF1_a_numEventsAll,VF1_a_maxInterEventDays,VF1_a_maxInterEventDaysAchieved,VF1_a_eventLength,VF1_a_eventLengthAchieved,VF1_a_totalEventDays,VF1_a_totalEventDaysAchieved,VF1_a_maxEventDays,VF1_a_maxRollingEvents,VF1_a_maxRollingAchievement,VF1_a_missingDays,VF1_a_totalPossibleDays,VF1_b_eventYears,VF1_b_numAchieved,VF1_b_numEvents,VF1_b_numEventsAll,VF1_b_maxInterEventDays,VF1_b_maxInterEventDaysAchieved,VF1_b_eventLength,VF1_b_eventLengthAchieved,VF1_b_totalEventDays,VF1_b_totalEventDaysAchieved,VF1_b_maxEventDays,VF1_b_maxRollingEvents,VF1_b_maxRollingAchievement,VF1_b_missingDays,VF1_b_totalPossibleDays,BF1_a_eventYears,BF1_a_numAchieved,BF1_a_numEvents,BF1_a_numEventsAll,BF1_a_maxInterEventDays,BF1_a_maxInterEventDaysAchieved,BF1_a_eventLength,BF1_a_eventLengthAchieved,BF1_a_totalEventDays,BF1_a_totalEventDaysAchieved,BF1_a_maxEventDays,BF1_a_maxRollingEvents,BF1_a_maxRollingAchievement,BF1_a_missingDays,BF1_a_totalPossibleDays,BF1_b_eventYears,BF1_b_numAchieved,BF1_b_numEvents,BF1_b_numEventsAll,BF1_b_maxInterEventDays,BF1_b_maxInterEventDaysAchieved,BF1_b_eventLength,BF1_b_eventLengthAchieved,BF1_b_totalEventDays,BF1_b_totalEventDaysAchieved,BF1_b_maxEventDays,BF1_b_maxRollingEvents,BF1_b_maxRollingAchievement,BF1_b_missingDays,BF1_b_totalPossibleDays,NestS1_tcmc_eventYears,NestS1_tcmc_numAchieved,NestS1_tcmc_numEvents,NestS1_tcmc_numEventsAll,NestS1_tcmc_maxInterEventDays,NestS1_tcmc_maxInterEventDaysAchieved,NestS1_tcmc_eventLength,NestS1_tcmc_eventLengthAchieved,NestS1_tcmc_totalEventDays,NestS1_tcmc_totalEventDaysAchieved,NestS1_tcmc_maxEventDays,NestS1_tcmc_maxRollingEvents,NestS1_tcmc_maxRollingAchievement,NestS1_tcmc_missingDays,NestS1_tcmc_totalPossibleDays,NestS1_mc_eventYears,NestS1_mc_numAchieved,NestS1_mc_numEvents,NestS1_mc_numEventsAll,NestS1_mc_maxInterEventDays,NestS1_mc_maxInterEventDaysAchieved,NestS1_mc_eventLength,NestS1_mc_eventLengthAchieved,NestS1_mc_totalEventDays,NestS1_mc_totalEventDaysAchieved,NestS1_mc_maxEventDays,NestS1_mc_maxRollingEvents,NestS1_mc_maxRollingAchievement,NestS1_mc_missingDays,NestS1_mc_totalPossibleDays,SF1_S_eventYears,SF1_S_numAchieved,SF1_S_numEvents,SF1_S_numEventsAll,SF1_S_maxInterEventDays,SF1_S_maxInterEventDaysAchieved,SF1_S_eventLength,SF1_S_eventLengthAchieved,SF1_S_totalEventDays,SF1_S_totalEventDaysAchieved,SF1_S_maxEventDays,SF1_S_maxRollingEvents,SF1_S_maxRollingAchievement,SF1_S_missingDays,SF1_S_totalPossibleDays,SF1_P_eventYears,SF1_P_numAchieved,SF1_P_numEvents,SF1_P_numEventsAll,SF1_P_maxInterEventDays,SF1_P_maxInterEventDaysAchieved,SF1_P_eventLength,SF1_P_eventLengthAchieved,SF1_P_totalEventDays,SF1_P_totalEventDaysAchieved,SF1_P_maxEventDays,SF1_P_maxRollingEvents,SF1_P_maxRollingAchievement,SF1_P_missingDays,SF1_P_totalPossibleDays,SF2_eventYears,SF2_numAchieved,SF2_numEvents,SF2_numEventsAll,SF2_maxInterEventDays,SF2_maxInterEventDaysAchieved,SF2_eventLength,SF2_eventLengthAchieved,SF2_totalEventDays,SF2_totalEventDaysAchieved,SF2_maxEventDays,SF2_maxRollingEvents,SF2_maxRollingAchievement,SF2_missingDays,SF2_totalPossibleDays,LF1_P_eventYears,LF1_P_numAchieved,LF1_P_numEvents,LF1_P_numEventsAll,LF1_P_maxInterEventDays,LF1_P_maxInterEventDaysAchieved,LF1_P_eventLength,LF1_P_eventLengthAchieved,LF1_P_totalEventDays,LF1_P_totalEventDaysAchieved,LF1_P_maxEventDays,LF1_P_maxRollingEvents,LF1_P_maxRollingAchievement,LF1_P_missingDays,LF1_P_totalPossibleDays,LF1_S_eventYears,LF1_S_numAchieved,LF1_S_numEvents,LF1_S_numEventsAll,LF1_S_maxInterEventDays,LF1_S_maxInterEventDaysAchieved,LF1_S_eventLength,LF1_S_eventLengthAchieved,LF1_S_totalEventDays,LF1_S_totalEventDaysAchieved,LF1_S_maxEventDays,LF1_S_maxRollingEvents,LF1_S_maxRollingAchievement,LF1_S_missingDays,LF1_S_totalPossibleDays,LF2_eventYears,LF2_numAchieved,LF2_numEvents,LF2_numEventsAll,LF2_maxInterEventDays,LF2_maxInterEventDaysAchieved,LF2_eventLength,LF2_eventLengthAchieved,LF2_totalEventDays,LF2_totalEventDaysAchieved,LF2_maxEventDays,LF2_maxRollingEvents,LF2_maxRollingAchievement,LF2_missingDays,LF2_totalPossibleDays,W-LF6_S_eventYears,W-LF6_S_numAchieved,W-LF6_S_numEvents,W-LF6_S_numEventsAll,W-LF6_S_maxInterEventDays,W-LF6_S_maxInterEventDaysAchieved,W-LF6_S_eventLength,W-LF6_S_eventLengthAchieved,W-LF6_S_totalEventDays,W-LF6_S_totalEventDaysAchieved,W-LF6_S_maxEventDays,W-LF6_S_maxRollingEvents,W-LF6_S_maxRollingAchievement,W-LF6_S_missingDays,W-LF6_S_totalPossibleDays,W-LF6_P_eventYears,W-LF6_P_numAchieved,W-LF6_P_numEvents,W-LF6_P_numEventsAll,W-LF6_P_maxInterEventDays,W-LF6_P_maxInterEventDaysAchieved,W-LF6_P_eventLength,W-LF6_P_eventLengthAchieved,W-LF6_P_totalEventDays,W-LF6_P_totalEventDaysAchieved,W-LF6_P_maxEventDays,W-LF6_P_maxRollingEvents,W-LF6_P_maxRollingAchievement,W-LF6_P_missingDays,W-LF6_P_totalPossibleDays,W-LF7_eventYears,W-LF7_numAchieved,W-LF7_numEvents,W-LF7_numEventsAll,W-LF7_maxInterEventDays,W-LF7_maxInterEventDaysAchieved,W-LF7_eventLength,W-LF7_eventLengthAchieved,W-LF7_totalEventDays,W-LF7_totalEventDaysAchieved,W-LF7_maxEventDays,W-LF7_maxRollingEvents,W-LF7_maxRollingAchievement,W-LF7_missingDays,W-LF7_totalPossibleDays,W-LF8_eventYears,W-LF8_numAchieved,W-LF8_numEvents,W-LF8_numEventsAll,W-LF8_maxInterEventDays,W-LF8_maxInterEventDaysAchieved,W-LF8_eventLength,W-LF8_eventLengthAchieved,W-LF8_totalEventDays,W-LF8_totalEventDaysAchieved,W-LF8_maxEventDays,W-LF8_maxRollingEvents,W-LF8_maxRollingAchievement,W-LF8_missingDays,W-LF8_totalPossibleDays,OB-S2_S_eventYears,OB-S2_S_numAchieved,OB-S2_S_numEvents,OB-S2_S_numEventsAll,OB-S2_S_maxInterEventDays,OB-S2_S_maxInterEventDaysAchieved,OB-S2_S_eventLength,OB-S2_S_eventLengthAchieved,OB-S2_S_totalEventDays,OB-S2_S_totalEventDaysAchieved,OB-S2_S_maxEventDays,OB-S2_S_maxRollingEvents,OB-S2_S_maxRollingAchievement,OB-S2_S_missingDays,OB-S2_S_totalPossibleDays,OB-S2_P_eventYears,OB-S2_P_numAchieved,OB-S2_P_numEvents,OB-S2_P_numEventsAll,OB-S2_P_maxInterEventDays,OB-S2_P_maxInterEventDaysAchieved,OB-S2_P_eventLength,OB-S2_P_eventLengthAchieved,OB-S2_P_totalEventDays,OB-S2_P_totalEventDaysAchieved,OB-S2_P_maxEventDays,OB-S2_P_maxRollingEvents,OB-S2_P_maxRollingAchievement,OB-S2_P_missingDays,OB-S2_P_totalPossibleDays,OB-L1_S_eventYears,OB-L1_S_numAchieved,OB-L1_S_numEvents,OB-L1_S_numEventsAll,OB-L1_S_maxInterEventDays,OB-L1_S_maxInterEventDaysAchieved,OB-L1_S_eventLength,OB-L1_S_eventLengthAchieved,OB-L1_S_totalEventDays,OB-L1_S_totalEventDaysAchieved,OB-L1_S_maxEventDays,OB-L1_S_maxRollingEvents,OB-L1_S_maxRollingAchievement,OB-L1_S_missingDays,OB-L1_S_totalPossibleDays,OB-L1_P_eventYears,OB-L1_P_numAchieved,OB-L1_P_numEvents,OB-L1_P_numEventsAll,OB-L1_P_maxInterEventDays,OB-L1_P_maxInterEventDaysAchieved,OB-L1_P_eventLength,OB-L1_P_eventLengthAchieved,OB-L1_P_totalEventDays,OB-L1_P_totalEventDaysAchieved,OB-L1_P_maxEventDays,OB-L1_P_maxRollingEvents,OB-L1_P_maxRollingAchievement,OB-L1_P_missingDays,OB-L1_P_totalPossibleDays 2 | 1895,0,0,0,0,0,1,0.0,0.0,0,0,0,0,1,0,366,1,1,1,1,0,1,366.0,366.0,366,366,366,366,1,0,366,1,1,1,1,0,1,366.0,366.0,366,366,366,366,1,0,366,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,366,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,366,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,366,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,366,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,366,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,366,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,366,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,366,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,366,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,366,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,366,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,366,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,366,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,366,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,366,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,366,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,366,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,366 3 | 1896,1,1,1,1,0,1,5.0,5.0,5,5,5,5,1,0,365,0,0,0,1,0,1,360.0,360.0,360,360,360,360,0,0,365,1,1,1,1,0,1,360.0,360.0,360,360,360,360,1,0,365,1,1,1,1,0,1,360.0,360.0,360,360,360,360,1,0,365,1,1,1,1,0,1,360.0,360.0,360,360,360,360,1,0,365,1,1,1,1,0,1,62.0,62.0,62,62,62,62,1,0,365,1,1,1,1,0,1,46.0,46.0,46,46,46,46,1,0,365,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,365,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,365,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,365,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,365,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,365,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,365,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,365,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,365,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,365,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,365,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,365,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,365,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,365,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,365 4 | 1897,1,1,1,1,0,1,4.0,4.0,4,4,4,4,1,0,365,0,0,0,2,0,1,180.5,180.5,361,361,225,225,0,0,365,1,1,1,2,0,1,180.5,180.5,361,361,225,225,0,0,365,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,365,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,365,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,365,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,365,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,365,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,365,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,365,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,365,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,365,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,365,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,365,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,365,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,365,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,365,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,365,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,365,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,365,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,365 5 | 1898,1,1,1,1,0,1,5.0,5.0,5,5,5,5,1,0,365,0,0,0,2,0,1,180.0,180.0,360,360,248,248,0,0,365,1,1,1,2,0,1,180.0,180.0,360,360,248,248,0,0,365,1,1,1,2,0,1,180.0,180.0,360,360,248,248,0,0,365,1,1,1,2,0,1,180.0,180.0,360,360,248,248,1,0,365,0,0,0,1,0,1,36.0,0.0,36,0,36,36,0,0,365,0,0,0,1,0,1,20.0,0.0,20,0,20,20,0,0,365,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,365,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,365,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,365,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,365,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,365,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,365,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,365,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,365,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,365,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,365,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,365,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,365,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,365,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,365 6 | 1899,0,0,0,0,0,1,0.0,0.0,0,0,0,365,1,0,365,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,365,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,365,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,365,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,365,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,365,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,365,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,365,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,365,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,365,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,365,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,365,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,365,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,365,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,365,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,365,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,365,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,365,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,365,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,365,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,365 7 | 1900,1,1,1,1,0,1,549.0,549.0,549,549,549,549,1,0,184,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,184,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,184,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,184,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,184,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,184,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,184,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,184,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,184,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,184,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,184,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,184,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,184,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,184,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,184,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,184,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,184,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,184,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,184,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,184,0,0,0,0,0,1,0.0,0.0,0,0,0,0,0,0,184 8 | -------------------------------------------------------------------------------- /unit_testing_files/ex_tasker.nc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MDBAuth/EWR_tool/467885c638d1c8f86cbb822af56f3fac38801828/unit_testing_files/ex_tasker.nc -------------------------------------------------------------------------------- /unit_testing_files/gauge_results_after_process.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MDBAuth/EWR_tool/467885c638d1c8f86cbb822af56f3fac38801828/unit_testing_files/gauge_results_after_process.pickle -------------------------------------------------------------------------------- /unit_testing_files/gauge_results_before_process.pickle: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MDBAuth/EWR_tool/467885c638d1c8f86cbb822af56f3fac38801828/unit_testing_files/gauge_results_before_process.pickle -------------------------------------------------------------------------------- /unit_testing_files/input_for_summarise_data.csv: -------------------------------------------------------------------------------- 1 | ,VF1_eventYears,VF1_numAchieved,VF1_numEvents,VF1_eventLength,VF1_totalEventDays,VF1_daysBetweenEvents,VF1_missingDays,VF1_totalPossibleDays 2 | 1895,1,1,1,366,366,[],0,366 3 | 1896,0,0,0,112.3333333,337,[],0,365 4 | 1897,0,0,0,177,354,[],0,365 5 | 1898,1,1,1,365,365,[],0,365 6 | 1899,1,1,1,365,365,[],0,365 7 | 1900,0,0,0,87.25,349,[],0,365 8 | -------------------------------------------------------------------------------- /unit_testing_files/mock_gg_pull.json: -------------------------------------------------------------------------------- 1 | {"DATASOURCEID": ["NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW", "NSW"], "SITEID": ["419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039", "419039"], "SUBJECTID": ["WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER", "WATER"], "DATETIME": ["2020-07-01", "2020-07-02", "2020-07-03", "2020-07-04", "2020-07-05", "2020-07-06", "2020-07-07", "2020-07-08", "2020-07-09", "2020-07-10", "2020-07-11", "2020-07-12", "2020-07-13", "2020-07-14", "2020-07-15", "2020-07-16", "2020-07-17", "2020-07-18", "2020-07-19", "2020-07-20", "2020-07-21", "2020-07-22", "2020-07-23", "2020-07-24", "2020-07-25", "2020-07-26", "2020-07-27", "2020-07-28", "2020-07-29", "2020-07-30", "2020-07-31", "2020-08-01", "2020-08-02", "2020-08-03", "2020-08-04", "2020-08-05", "2020-08-06", "2020-08-07", "2020-08-08", "2020-08-09", "2020-08-10", "2020-08-11", "2020-08-12", "2020-08-13", "2020-08-14", "2020-08-15", "2020-08-16", "2020-08-17", "2020-08-18", "2020-08-19", "2020-08-20", "2020-08-21", "2020-08-22", "2020-08-23", "2020-08-24", "2020-08-25", "2020-08-26", "2020-08-27", "2020-08-28", "2020-08-29", "2020-08-30", "2020-08-31", "2020-09-01", "2020-09-02", "2020-09-03", "2020-09-04", "2020-09-05", "2020-09-06", "2020-09-07", "2020-09-08", "2020-09-09", "2020-09-10", "2020-09-11", "2020-09-12", "2020-09-13", "2020-09-14", "2020-09-15", "2020-09-16", "2020-09-17", "2020-09-18", "2020-09-19", "2020-09-20", "2020-09-21", "2020-09-22", "2020-09-23", "2020-09-24", "2020-09-25", "2020-09-26", "2020-09-27", "2020-09-28", "2020-09-29", "2020-09-30", "2020-10-01", "2020-10-02", "2020-10-03", "2020-10-04", "2020-10-05", "2020-10-06", "2020-10-07", "2020-10-08", "2020-10-09", "2020-10-10", "2020-10-11", "2020-10-12", "2020-10-13", "2020-10-14", "2020-10-15", "2020-10-16", "2020-10-17", "2020-10-18", "2020-10-19", "2020-10-20", "2020-10-21", "2020-10-22", "2020-10-23", "2020-10-24", "2020-10-25", "2020-10-26", "2020-10-27", "2020-10-28", "2020-10-29", "2020-10-30", "2020-10-31", "2020-11-01", "2020-11-02", "2020-11-03", "2020-11-04", "2020-11-05", "2020-11-06", "2020-11-07", "2020-11-08", "2020-11-09", "2020-11-10", "2020-11-11", "2020-11-12", "2020-11-13", "2020-11-14", "2020-11-15", "2020-11-16", "2020-11-17", "2020-11-18", "2020-11-19", "2020-11-20", "2020-11-21", "2020-11-22", "2020-11-23", "2020-11-24", "2020-11-25", "2020-11-26", "2020-11-27", "2020-11-28", "2020-11-29", "2020-11-30", "2020-12-01", "2020-12-02", "2020-12-03", "2020-12-04", "2020-12-05", "2020-12-06", "2020-12-07", "2020-12-08", "2020-12-09", "2020-12-10", "2020-12-11", "2020-12-12", "2020-12-13", "2020-12-14", "2020-12-15", "2020-12-16", "2020-12-17", "2020-12-18", "2020-12-19", "2020-12-20", "2020-12-21", "2020-12-22", "2020-12-23", "2020-12-24", "2020-12-25", "2020-12-26", "2020-12-27", "2020-12-28", "2020-12-29", "2020-12-30", "2020-12-31", "2021-01-01", "2021-01-02", "2021-01-03", "2021-01-04", "2021-01-05", "2021-01-06", "2021-01-07", "2021-01-08", "2021-01-09", "2021-01-10", "2021-01-11", "2021-01-12", "2021-01-13", "2021-01-14", "2021-01-15", "2021-01-16", "2021-01-17", "2021-01-18", "2021-01-19", "2021-01-20", "2021-01-21", "2021-01-22", "2021-01-23", "2021-01-24", "2021-01-25", "2021-01-26", "2021-01-27", "2021-01-28", "2021-01-29", "2021-01-30", "2021-01-31", "2021-02-01", "2021-02-02", "2021-02-03", "2021-02-04", "2021-02-05", "2021-02-06", "2021-02-07", "2021-02-08", "2021-02-09", "2021-02-10", "2021-02-11", "2021-02-12", "2021-02-13", "2021-02-14", "2021-02-15", "2021-02-16", "2021-02-17", "2021-02-18", "2021-02-19", "2021-02-20", "2021-02-21", "2021-02-22", "2021-02-23", "2021-02-24", "2021-02-25", "2021-02-26", "2021-02-27", "2021-02-28", "2021-03-01", "2021-03-02", "2021-03-03", "2021-03-04", "2021-03-05", "2021-03-06", "2021-03-07", "2021-03-08", "2021-03-09", "2021-03-10", "2021-03-11", "2021-03-12", "2021-03-13", "2021-03-14", "2021-03-15", "2021-03-16", "2021-03-17", "2021-03-18", "2021-03-19", "2021-03-20", "2021-03-21", "2021-03-22", "2021-03-23", "2021-03-24", "2021-03-25", "2021-03-26", "2021-03-27", "2021-03-28", "2021-03-29", "2021-03-30", "2021-03-31", "2021-04-01", "2021-04-02", "2021-04-03", "2021-04-04", "2021-04-05", "2021-04-06", "2021-04-07", "2021-04-08", "2021-04-09", "2021-04-10", "2021-04-11", "2021-04-12", "2021-04-13", "2021-04-14", "2021-04-15", "2021-04-16", "2021-04-17", "2021-04-18", "2021-04-19", "2021-04-20", "2021-04-21", "2021-04-22", "2021-04-23", "2021-04-24", "2021-04-25", "2021-04-26", "2021-04-27", "2021-04-28", "2021-04-29", "2021-04-30", "2021-05-01", "2021-05-02", "2021-05-03", "2021-05-04", "2021-05-05", "2021-05-06", "2021-05-07", "2021-05-08", "2021-05-09", "2021-05-10", "2021-05-11", "2021-05-12", "2021-05-13", "2021-05-14", "2021-05-15", "2021-05-16", "2021-05-17", "2021-05-18", "2021-05-19", "2021-05-20", "2021-05-21", "2021-05-22", "2021-05-23", "2021-05-24", "2021-05-25", "2021-05-26", "2021-05-27", "2021-05-28", "2021-05-29", "2021-05-30", "2021-05-31", "2021-06-01", "2021-06-02", "2021-06-03", "2021-06-04", "2021-06-05", "2021-06-06", "2021-06-07", "2021-06-08", "2021-06-09", "2021-06-10", "2021-06-11", "2021-06-12", "2021-06-13", "2021-06-14", "2021-06-15", "2021-06-16", "2021-06-17", "2021-06-18", "2021-06-19", "2021-06-20", "2021-06-21", "2021-06-22", "2021-06-23", "2021-06-24", "2021-06-25", "2021-06-26", "2021-06-27", "2021-06-28", "2021-06-29", "2021-06-30"], "VALUE": ["4.251", "4.201", "4.295", "3.723", "3.886", "4.068", "4.187", "4.357", "4.218", "4.356", "5.205", "4.354", "4.603", "4.520", "3.685", "3.436", "3.208", "3.056", "3.255", "3.005", "2.840", "2.735", "2.803", "2.848", "3.211", "4.440", "4.296", "3.940", "209.732", "595.109", "2172.341", "2724.694", "2190.760", "2086.197", "1200.048", "861.082", "737.538", "748.498", "728.422", "713.486", "677.273", "540.049", "440.343", "407.663", "412.484", "909.056", "918.720", "924.733", "786.684", "614.609", "610.154", "574.799", "512.836", "489.717", "536.738", "485.044", "486.024", "350.064", "323.075", "311.551", "252.634", "190.799", "182.906", "176.697", "148.172", "110.207", "107.797", "104.677", "103.093", "100.794", "104.128", "350.923", "343.966", "65.001", "60.193", "47.064", "22.389", "17.537", "14.091", "12.072", "11.089", "11.591", "11.281", "11.011", "10.386", "10.184", "10.459", "9.684", "16.402", "16.998", "7.519", "7.927", "7.286", "6.678", "6.430", "6.303", "6.107", "5.957", "5.733", "5.413", "5.075", "4.994", "4.739", "4.411", "4.407", "4.559", "4.752", "4.870", "4.493", "4.954", "4.856", "4.435", "4.270", "4.780", "4.495", "6.689", "8.651", "7.356", "5.721", "93.503", "513.431", "494.954", "223.210", "20.497", "12.248", "327.763", "575.920", "619.544", "544.719", "477.637", "502.248", "480.587", "465.125", "452.432", "485.819", "497.749", "391.010", "145.844", "20.887", "17.485", "6.005", "5.886", "7.513", "9.244", "15.741", "4.840", "1.939", "1.312", "0.958", "0.682", "0.324", "0.045", "0.000", "0.000", "0.000", "0.000", "0.000", "0.000", "0.000", "0.000", "0.000", "0.000", "0.000", "0.000", "0.000", "0.000", "0.000", "0.000", "0.000", "0.000", "0.000", "0.000", "0.000", "0.000", "1327.019", "3077.595", "4049.790", "9468.761", "4684.797", "1527.886", "1725.031", "1381.610", "1007.406", "1096.996", "1848.443", "4317.152", "3028.163", "1940.835", "1500.632", "1141.012", "1190.757", "1746.110", "2535.200", "2371.178", "1689.780", "1321.224", "1321.633", "1079.542", "715.675", "429.638", "406.925", "392.262", "403.636", "390.350", "346.312", "329.827", "314.728", "303.949", "294.463", "279.893", "539.445", "675.434", "563.872", "508.651", "604.298", "604.365", "702.036", "584.610", "776.212", "768.445", "683.371", "713.177", "917.321", "1033.594", "818.199", "670.471", "678.628", "683.415", "680.304", "675.013", "640.591", "853.353", "1002.180", "781.993", "673.982", "673.867", "540.238", "620.756", "572.615", "404.063", "415.386", "451.403", "445.198", "374.565", "286.074", "192.449", "118.561", "75.442", "20.865", "15.625", "42.394", "163.219", "151.754", "91.718", "25.881", "22.532", "24.834", "133.076", "634.494", "1397.590", "3946.404", "2736.969", "1797.656", "1403.140", "836.262", "1851.085", "12709.188", "6745.059", "12417.812", "18866.158", "19293.440", "10104.901", "3813.879", "2906.205", "1940.698", "1434.857", "1319.621", "906.110", "885.604", "869.612", "826.104", "797.663", "672.843", "583.840", "558.213", "539.710", "512.560", "490.590", "475.821", "478.467", "481.989", "461.725", "437.328", "378.173", "343.368", "186.139", "28.456", "69.471", "265.620", "400.991", "515.533", "351.376", "373.544", "366.025", "301.352", "260.079", "246.557", "368.311", "193.968", "255.520", "203.940", "202.059", "203.015", "199.844", "239.684", "331.089", "215.631", "291.318", "255.110", "243.836", "291.848", "227.403", "202.984", "229.077", "210.444", "202.815", "225.313", "295.757", "340.256", "375.256", "408.682", "434.857", "453.451", "407.932", "402.881", "425.967", "408.913", "399.858", "446.207", "473.049", "497.033", "456.142", "338.686", "358.099", "414.914", "1751.602", "2357.176", "6454.285", "17323.325", "17115.910", "10905.696", "6127.459", "3913.220", "2808.485", "2188.341", "1904.545", "1680.784", "1629.775", "1610.596", "1458.686", "1410.763", "1520.734", "6567.546", "7009.936", "4891.022"], "QUALITYCODE": [130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130, 130]} -------------------------------------------------------------------------------- /unit_testing_files/qld_parameter_sheet.csv: -------------------------------------------------------------------------------- 1 | PlanningUnitID,PlanningUnitName,LTWPShortName,CompliancePoint/Node,Gauge,Code,StartMonth,EndMonth,TargetFrequency,TargetFrequencyMin,TargetFrequencyMax,EventsPerYear,Duration,MinSpell,FlowThresholdMin,FlowThresholdMax,MaxInter-event,WithinEventGapTolerance,WeirpoolGauge,FlowLevelVolume,LevelThresholdMin,LevelThresholdMax,VolumeThreshold,DrawdownRate,MaxLevelRise,AccumulationPeriod,Multigauge,MaxSpell,TriggerDay,TriggerMonth,DrawDownRateWeek,AnnualFlowSum,AnnualBarrageFlow,ThreeYearsBarrageFlow,HighReleaseWindowStart,HighReleaseWindowEnd,LowReleaseWindowStart,LowReleaseWindowEnd,PeakLevelWindowStart,PeakLevelWindowEnd,LowLevelWindowStart,LowLevelWindowEnd,NonFlowSpell,EggsDaysSpell,LarvaeDaysSpell,MinLevelRise,RateOfRiseMax1,RateOfRiseMax2,RateOfFallMin,RateOfRiseThreshold1,RateOfRiseThreshold2,RateOfRiseRiverLevel,RateOfFallRiverLevel,CtfThreshold,GaugeType,State,SWSDLName 2 | PU_0000999,Border Rivers and Moonie Long-term watering plan,Border Rivers,Goondiwindi,416201A,dANA,7,6,,,,1,1,1,5000,10000,2,,,F,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,QLD,Queensland Border Rivers 3 | PU_0000999,Border Rivers and Moonie Long-term watering plan,Border Rivers,Kanowna,416048,DR_S,7,6,,,,1,1,1,4400,,3,,,F,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,QLD,Queensland Border Rivers 4 | PU_0000999,Border Rivers and Moonie Long-term watering plan,Border Rivers,Roseneath,416011,DR_VLF,7,6,,,,1,1,1,1,,1,,,F,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,QLD,Queensland Border Rivers 5 | PU_0000999,Border Rivers and Moonie Long-term watering plan,Border Rivers,Kanowna,416048,DR_VLF,7,6,,,,1,1,1,1,,1,,,F,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,QLD,Queensland Border Rivers 6 | PU_0000999,Border Rivers and Moonie Long-term watering plan,Border Rivers,Roseneath,416011,FD1,7,6,,,,1,8,8,5500,,,,,F,,,,,,,,,,,,,,,,,,,,,,,365,,,,,,,,,,,,,QLD,Queensland Border Rivers 7 | PU_0000999,Border Rivers and Moonie Long-term watering plan,Border Rivers,Kanowna,416048,FD1,7,6,,,,1,8,8,1700,,,,,F,,,,,,,,,,,,,,,,,,,,,,,365,,,,,,,,,,,,,QLD,Queensland Border Rivers 8 | PU_0000999,Border Rivers and Moonie Long-term watering plan,Border Rivers,Roseneath,416011,FR2,10,4,,,,1,8,8,5500,,4,,,F,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,QLD,Queensland Border Rivers 9 | PU_0000999,Border Rivers and Moonie Long-term watering plan,Border Rivers,Kanowna,416048,FR2,10,4,,,,1,8,8,1700,,4,,,F,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,QLD,Queensland Border Rivers 10 | PU_0000999,Border Rivers and Moonie Long-term watering plan,Border Rivers,Goondiwindi,416201A,NE,7,6,,,,1,1,1,5000,10000,4,,,F,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,QLD,Queensland Border Rivers 11 | PU_0000999,Border Rivers and Moonie Long-term watering plan,Border Rivers,Goondiwindi,416201A,PP,7,6,,,,1,1,1,5000,10000,4,,,F,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,QLD,Queensland Border Rivers 12 | PU_0000999,Border Rivers and Moonie Long-term watering plan,Border Rivers,Goondiwindi,416201A,rANA,10,2,,,,2,1,1,5000,10000,2,,,F,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,QLD,Queensland Border Rivers 13 | PU_0000991,Condamine and Balonne Long-term watering plan,Condamine,Wilby Wilby,422016,BBR1_a,7,6,25,,,1,90,90,100,1000000,,,422034,V,,1.08,154000,,,90,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,QLD,Condamine-Balonne 14 | PU_0000991,Condamine and Balonne Long-term watering plan,Condamine,Wilby Wilby,422016,BBR1_b,7,6,25,,,1,10,10,100,1000000,,,422034,V,,1.08,20000,,,10,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,QLD,Condamine-Balonne 15 | PU_0000991,Condamine and Balonne Long-term watering plan,Condamine,Wilby Wilby,422016,BBR2,7,6,76,,,1,1,1,0,1000000,,,,V,,,25000,,,60,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,QLD,Condamine-Balonne 16 | PU_0000992,Warrego Paroo Bulloo and Nebine Long-term watering plan,Condamine,Nebine Creek at Roseleigh Crossing,422502A,DR1,7,6,100,,,1,1,1,2,,1,,,F,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,QLD,Nebine 17 | PU_0000992,Warrego Paroo Bulloo and Nebine Long-term watering plan,Condamine,Nebine Creek at Roseleigh Crossing,422502A,DR2,7,6,,,,1,1,1,2540,,,,,F,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,QLD,Nebine 18 | PU_0000992,Warrego Paroo Bulloo and Nebine Long-term watering plan,Condamine,Nebine Creek at Roseleigh Crossing,422502A,FD1,7,6,,,,1,8,8,8,,,,,F,,,,,,,,,,,,,,,,,,,,,,,548,,,,,,,,,,,,,QLD,Nebine 19 | PU_0000991,Condamine and Balonne Long-term watering plan,Condamine,Brenda GS (Node A),422015,FD1,7,6,,,,1,1,1,20,,,,,F,,,,,,,,,,,,,,,,,,,,,,,365,,,,,,,,,,,,,QLD,Condamine-Balonne 20 | PU_0000991,Condamine and Balonne Long-term watering plan,Condamine,Woolerbilla-Hebel GS (Node B),422211A,FD1,7,6,,,,1,1,1,20,,,,,F,,,,,,,,,,,,,,,,,,,,,,,365,,,,,,,,,,,,,QLD,Condamine-Balonne 21 | PU_0000991,Condamine and Balonne Long-term watering plan,Condamine,Hebel-Bollon Road GS (Node C),422207A,FD1,7,6,,,,1,1,1,20,,,,,F,,,,,,,,,,,,,,,,,,,,,,,365,,,,,,,,,,,,,QLD,Condamine-Balonne 22 | PU_0000991,Condamine and Balonne Long-term watering plan,Condamine,Hebel GS (Node D),422209A,FD1,7,6,,,,1,1,1,20,,,,,F,,,,,,,,,,,,,,,,,,,,,,,365,,,,,,,,,,,,,QLD,Condamine-Balonne 23 | PU_0000991,Condamine and Balonne Long-term watering plan,Condamine,Narran @ Angledool 2 GS,422030,FD1,7,6,,,,1,1,1,20,,,,,F,,,,,,,,,,,,,,,,,,,,,,,365,,,,,,,,,,,,,QLD,Condamine-Balonne 24 | PU_0000991,Condamine and Balonne Long-term watering plan,Condamine,Brenda GS (Node A),422015,FD2,7,6,,,,1,8,8,1500,,,,,F,,,,,,,,,,,,,,,,,,,,,,,548,,,,,,,,,,,,,QLD,Condamine-Balonne 25 | PU_0000991,Condamine and Balonne Long-term watering plan,Condamine,Woolerbilla-Hebel GS (Node B),422211A,FD2,7,6,,,,1,8,8,690,,,,,F,,,,,,,,,,,,,,,,,,,,,,,548,,,,,,,,,,,,,QLD,Condamine-Balonne 26 | PU_0000991,Condamine and Balonne Long-term watering plan,Condamine,Hebel-Bollon Road GS (Node C),422207A,FD2,7,6,,,,1,8,8,320,,,,,F,,,,,,,,,,,,,,,,,,,,,,,548,,,,,,,,,,,,,QLD,Condamine-Balonne 27 | PU_0000991,Condamine and Balonne Long-term watering plan,Condamine,Hebel GS (Node D),422209A,FD2,7,6,,,,1,8,8,1000,,,,,F,,,,,,,,,,,,,,,,,,,,,,,548,,,,,,,,,,,,,QLD,Condamine-Balonne 28 | PU_0000991,Condamine and Balonne Long-term watering plan,Condamine,Narran @ Angledool 2 GS,422030,FD2,7,6,,,,1,8,8,2100,,,,,F,,,,,,,,,,,,,,,,,,,,,,,548,,,,,,,,,,,,,QLD,Condamine-Balonne 29 | PU_0000992,Warrego Paroo Bulloo and Nebine Long-term watering plan,Condamine,Nebine Creek at Roseleigh Crossing,422502A,FrC,10,4,,,,1,8,8,8,,,,,F,,,,,,,,,,,,,,,,,,,,,,,548,,,,,,,,,,,,,QLD,Nebine 30 | PU_0000991,Condamine and Balonne Long-term watering plan,Condamine,Brenda GS (Node A),422015,FR2,10,4,,,,1,8,8,1500,,4,,,F,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,QLD,Condamine-Balonne 31 | PU_0000991,Condamine and Balonne Long-term watering plan,Condamine,Woolerbilla-Hebel GS (Node B),422211A,FR1,10,4,,,,1,8,8,690,,4,,,F,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,QLD,Condamine-Balonne 32 | PU_0000991,Condamine and Balonne Long-term watering plan,Condamine,Hebel-Bollon Road GS (Node C),422207A,FR1,10,4,,,,1,8,8,320,,4,,,F,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,QLD,Condamine-Balonne 33 | PU_0000991,Condamine and Balonne Long-term watering plan,Condamine,Hebel GS (Node D),422209A,FR1,10,4,,,,1,8,8,1000,,4,,,F,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,QLD,Condamine-Balonne 34 | PU_0000991,Condamine and Balonne Long-term watering plan,Condamine,Narran @ Angledool 2 GS,422030,FR1,10,4,,,,1,8,8,2100,,4,,,F,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,QLD,Condamine-Balonne 35 | PU_0000992,Warrego Paroo Bulloo and Nebine Long-term watering plan,Condamine,Nebine Creek at Roseleigh Crossing,422502A,LDF,7,6,25,,,1,1,1,2540,,,,,F,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,QLD,Nebine 36 | PU_0000992,Warrego Paroo Bulloo and Nebine Long-term watering plan,Condamine,Nebine Creek at Roseleigh Crossing,422502A,WFT,7,6,25,,,1,1,1,5271,,,,,F,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,QLD,Nebine 37 | PU_0000992,Warrego Paroo Bulloo and Nebine Long-term watering plan,Paroo,Paroo River at Caiwarro,424201A,DR1,7,6,100,,,1,1,1,2,,1,,,F,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,QLD,Paroo 38 | PU_0000992,Warrego Paroo Bulloo and Nebine Long-term watering plan,Paroo,Paroo River at Caiwarro,424201A,DR2,7,6,,,,1,1,1,36652,,,,,F,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,QLD,Paroo 39 | PU_0000992,Warrego Paroo Bulloo and Nebine Long-term watering plan,Paroo,Paroo River at Caiwarro,424201A,FD1,7,6,,,,1,8,8,3412,,,,,F,,,,,,,,,,,,,,,,,,,,,,,548,,,,,,,,,,,,,QLD,Paroo 40 | PU_0000992,Warrego Paroo Bulloo and Nebine Long-term watering plan,Paroo,Paroo River at Caiwarro,424201A,FrC,10,4,,,,1,8,8,3412,,,,,F,,,,,,,,,,,,,,,,,,,,,,,548,,,,,,,,,,,,,QLD,Paroo 41 | PU_0000992,Warrego Paroo Bulloo and Nebine Long-term watering plan,Paroo,Paroo River at Caiwarro,424201A,LDF,7,6,25,,,1,1,1,36652,,,,,F,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,QLD,Paroo 42 | PU_0000992,Warrego Paroo Bulloo and Nebine Long-term watering plan,Paroo,Paroo River at Caiwarro,424201A,WFT,7,6,25,,,1,1,1,81776,,,,,F,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,QLD,Paroo 43 | PU_0000992,Warrego Paroo Bulloo and Nebine Long-term watering plan,Warrego,Cuttaburra Creek at Turra,423005,DR1,7,6,100,,,1,1,1,2,,1,,,F,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,QLD,Warrego 44 | PU_0000992,Warrego Paroo Bulloo and Nebine Long-term watering plan,Warrego,Warrego River at Barringun #2,423004,DR1,7,6,100,,,1,1,1,2,,1,,,F,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,QLD,Warrego 45 | PU_0000992,Warrego Paroo Bulloo and Nebine Long-term watering plan,Warrego,Cuttaburra Creek at Turra,423005,DR2,7,6,,,,1,1,1,11511,,,,,F,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,QLD,Warrego 46 | PU_0000992,Warrego Paroo Bulloo and Nebine Long-term watering plan,Warrego,Warrego River at Barringun #2,423004,DR2,7,6,,,,1,1,1,6048,,,,,F,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,QLD,Warrego 47 | PU_0000992,Warrego Paroo Bulloo and Nebine Long-term watering plan,Warrego,Cuttaburra Creek at Turra,423005,FD1,7,6,,,,1,8,8,60,,,,,F,,,,,,,,,,,,,,,,,,,,,,,548,,,,,,,,,,,,,QLD,Warrego 48 | PU_0000992,Warrego Paroo Bulloo and Nebine Long-term watering plan,Warrego,Warrego River at Barringun #2,423004,FD1,7,6,,,,1,8,8,636,,,,,F,,,,,,,,,,,,,,,,,,,,,,,548,,,,,,,,,,,,,QLD,Warrego 49 | PU_0000992,Warrego Paroo Bulloo and Nebine Long-term watering plan,Warrego,Cuttaburra Creek at Turra,423005,FrC,10,4,,,,1,8,8,60,,,,,F,,,,,,,,,,,,,,,,,,,,,,,548,,,,,,,,,,,,,QLD,Warrego 50 | PU_0000992,Warrego Paroo Bulloo and Nebine Long-term watering plan,Warrego,Warrego River at Barringun #2,423004,FrC,10,4,,,,1,8,8,636,,,,,F,,,,,,,,,,,,,,,,,,,,,,,548,,,,,,,,,,,,,QLD,Warrego 51 | PU_0000992,Warrego Paroo Bulloo and Nebine Long-term watering plan,Warrego,Cuttaburra Creek at Turra,423005,LDF,7,6,25,,,1,1,1,11511,,,,,F,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,QLD,Warrego 52 | PU_0000992,Warrego Paroo Bulloo and Nebine Long-term watering plan,Warrego,Warrego River at Barringun #2,423004,LDF,7,6,25,,,1,1,1,6048,,,,,F,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,QLD,Warrego 53 | PU_0000992,Warrego Paroo Bulloo and Nebine Long-term watering plan,Warrego,Cuttaburra Creek at Turra,423005,WFT,7,6,25,,,1,1,1,27735,,,,,F,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,QLD,Warrego 54 | PU_0000992,Warrego Paroo Bulloo and Nebine Long-term watering plan,Warrego,Warrego River at Barringun #2,423004,WFT,7,6,25,,,1,1,1,13715,,,,,F,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,QLD,Warrego 55 | PU_0000991,Condamine and Balonne Long-term watering plan,,Brenda GS (Node A),422015,DR1,7,6,100,,,1,1,1,1,,1,,,F,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,QLD,Condamine-Balonne 56 | PU_0000991,Condamine and Balonne Long-term watering plan,,Woolerbilla-Hebel GS (Node B),422211A,DR1,7,6,100,,,1,1,1,1,,1,,,F,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,QLD,Condamine-Balonne 57 | PU_0000991,Condamine and Balonne Long-term watering plan,,Hebel-Bollon Road GS (Node C),422207A,DR1,7,6,100,,,1,1,1,1,,1,,,F,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,QLD,Condamine-Balonne 58 | PU_0000991,Condamine and Balonne Long-term watering plan,,Hebel GS (Node D),422209A,DR1,7,6,100,,,1,1,1,1,,1,,,F,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,QLD,Condamine-Balonne 59 | PU_0000991,Condamine and Balonne Long-term watering plan,,Narran @ Angledool 2 GS,422030,DR1,7,6,100,,,1,1,1,1,,1,,,F,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,QLD,Condamine-Balonne 60 | PU_0000999,Border Rivers and Moonie Long-term watering plan,Border Rivers,Roseneath,416011,FrW1,10,12,,,,1,27,27,70,120,3,,416011,F,,,,0.05,0.05,,,,,,,,,,,,,,,,,,,7,20,,,,,,,,,,,QLD,Queensland Border Rivers 61 | PU_0000999,Border Rivers and Moonie Long-term watering plan,Border Rivers,Roseneath,416011,FrW2,8,12,,,,1,9,9,70,120,3,,416011,F,,,,0.05,0.05,,,,,,,,,,,,,,,,,,,3,6,,,,,,,,,,,QLD,Queensland Border Rivers 62 | PU_0000999,Border Rivers and Moonie Long-term watering plan,Border Rivers,Roseneath,416011,FrW3,12,2,,,,2,10,10,70,120,2,,416011,F,,,,0.05,0.05,,,,,,,,,,,,,,,,,,,9,1,,,,,,,,,,,QLD,Queensland Border Rivers 63 | PU_0000999,Border Rivers and Moonie Long-term watering plan,Border Rivers,Roseneath,416011,FrW4,12,2,,,,1,7,7,70,120,3,,416011,F,,,,0.05,0.05,,,,,,,,,,,,,,,,,,,7,0,,,,,,,,,,,QLD,Queensland Border Rivers 64 | PU_0000999,Border Rivers and Moonie Long-term watering plan,Border Rivers,Kanowna,416048,FrW1,10,12,,,,1,27,27,0,360,3,,416048,F,,,,0.05,0.05,,,,,,,,,,,,,,,,,,,7,20,,,,,,,,,,,QLD,Queensland Border Rivers 65 | PU_0000999,Border Rivers and Moonie Long-term watering plan,Border Rivers,Kanowna,416048,FrW2,8,12,,,,1,9,9,0,360,3,,416048,F,,,,0.05,0.05,,,,,,,,,,,,,,,,,,,3,6,,,,,,,,,,,QLD,Queensland Border Rivers 66 | PU_0000999,Border Rivers and Moonie Long-term watering plan,Border Rivers,Kanowna,416048,FrW3,12,2,,,,2,10,10,0,360,2,,416048,F,,,,0.05,0.05,,,,,,,,,,,,,,,,,,,9,1,,,,,,,,,,,QLD,Queensland Border Rivers 67 | PU_0000999,Border Rivers and Moonie Long-term watering plan,Border Rivers,Kanowna,416048,FrW4,12,2,,,,1,7,7,0,360,3,,416048,F,,,,0.05,0.05,,,,,,,,,,,,,,,,,,,7,0,,,,,,,,,,,QLD,Queensland Border Rivers 68 | PU_0000991,Condamine and Balonne Long-term watering plan,Condamine,Brenda GS (Node A),422015,FrL1,12,2,,,,2,10,10,2,,,,422015,L,0,1.63,,0.05,0.05,,,,,,,,,,,,,,,,,,,9,1,,,,,,,,,,,QLD,Condamine-Balonne 69 | PU_0000991,Condamine and Balonne Long-term watering plan,Condamine,Brenda GS (Node A),422015,FrL2,8,12,,,,1,9,9,3,,,,422015,L,0,1.63,,0.05,0.05,,,,,,,,,,,,,,,,,,,3,6,,,,,,,,,,,QLD,Condamine-Balonne 70 | PU_0000991,Condamine and Balonne Long-term watering plan,Condamine,Narran @ Angledool 2 GS,422030,FrL1,12,2,,,,2,10,10,2,,,,422030,L,0,1.8,,0.05,0.05,,,,,,,,,,,,,,,,,,,9,1,,,,,,,,,,,QLD,Condamine-Balonne 71 | PU_0000991,Condamine and Balonne Long-term watering plan,Condamine,Narran @ Angledool 2 GS,422030,FrL2,8,12,,,,1,9,9,3,,,,422030,L,0,1.8,,0.05,0.05,,,,,,,,,,,,,,,,,,,3,6,,,,,,,,,,,QLD,Condamine-Balonne 72 | -------------------------------------------------------------------------------- /unit_testing_files/sa_parameter_sheet.csv: -------------------------------------------------------------------------------- 1 | PlanningUnitID,PlanningUnitName,LTWPShortName,CompliancePoint/Node,Gauge,Code,StartMonth,EndMonth,TargetFrequency,TargetFrequencyMin,TargetFrequencyMax,EventsPerYear,Duration,MinSpell,FlowThresholdMin,FlowThresholdMax,MaxInter-event,WithinEventGapTolerance,WeirpoolGauge,FlowLevelVolume,LevelThresholdMin,LevelThresholdMax,VolumeThreshold,DrawdownRate,MaxLevelRise,AccumulationPeriod,Multigauge,MaxSpell,TriggerDay,TriggerMonth,DrawDownRateWeek,AnnualFlowSum,AnnualBarrageFlow,ThreeYearsBarrageFlow,HighReleaseWindowStart,HighReleaseWindowEnd,LowReleaseWindowStart,LowReleaseWindowEnd,PeakLevelWindowStart,PeakLevelWindowEnd,LowLevelWindowStart,LowLevelWindowEnd,EggsDaysSpell,NonFlowSpell,LarvaeDaysSpell,MinLevelRise,RateOfRiseMax1,RateOfRiseMax2,RateOfFallMin,RateOfRiseThreshold1,RateOfRiseThreshold2,RateOfRiseRiverLevel,RateOfFallRiverLevel,CtfThreshold,GaugeType,State,SWSDLName 2 | PU_0000027,SA River Murray Channel,South Australia River Murray,Flow at South Australia border,A4261001,IC1_S,9,3,95,,,1,40,40,10000,1000000,2,3,,F,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,SA,South Australian Murray 3 | PU_0000027,SA River Murray Channel,South Australia River Murray,Flow at South Australia border,A4261001,IC1_P,9,3,95,,,1,60,60,10000,1000000,2,,,L,,,,232,465,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,SA,South Australian Murray 4 | PU_0000027,SA River Murray Channel,South Australia River Murray,Flow at South Australia border,A4261001,IC1_PS,9,3,95,,,1,60,60,10000,1000000,2,,,F,,,,232,465,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,SA,South Australian Murray 5 | PU_0000027,SA River Murray Channel,South Australia River Murray,Flow at South Australia border,A4261001,IC2_S,10,3,75,,,1,40,40,20000,1000000,2,3,,F,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,SA,South Australian Murray 6 | PU_0000027,SA River Murray Channel,South Australia River Murray,Flow at South Australia border,A4261001,IC2_P,10,12,75,,,1,60,60,20000,1000000,2,,,L,,,,232,465,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,SA,South Australian Murray 7 | PU_0000027,SA River Murray Channel,South Australia River Murray,Flow at South Australia border,A4261001,IC2_PS,10,12,75,,,1,60,60,20000,1000000,2,,,F,,,,232,465,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,SA,South Australian Murray 8 | PU_0000027,SA River Murray Channel,South Australia River Murray,Flow at South Australia border,A4261001,IC3_S,10,3,55,,,1,40,40,30000,1000000,2,3,,F,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,SA,South Australian Murray 9 | PU_0000027,SA River Murray Channel,South Australia River Murray,Flow at South Australia border,A4261001,IC3_P,10,12,65,,,1,60,60,30000,1000000,2,,,L,,,,232,465,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,SA,South Australian Murray 10 | PU_0000027,SA River Murray Channel,South Australia River Murray,Flow at South Australia border,A4261001,IC3_PS,10,12,65,,,1,60,60,30000,1000000,2,,,F,,,,232,465,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,SA,South Australian Murray 11 | PU_0000027,SA River Murray Channel,South Australia River Murray,Flow at South Australia border,A4261001,IC4_S,10,3,59,,,1,40,40,40000,1000000,2,3,,F,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,SA,South Australian Murray 12 | PU_0000027,SA River Murray Channel,South Australia River Murray,Flow at South Australia border,A4261001,IC4_P,10,12,45,,,1,60,60,40000,1000000,2,,,L,,,,232,465,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,SA,South Australian Murray 13 | PU_0000027,SA River Murray Channel,South Australia River Murray,Flow at South Australia border,A4261001,IC4_PS,10,12,45,,,1,60,60,40000,1000000,2,,,F,,,,232,465,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,SA,South Australian Murray 14 | PU_0000028,SA River Murray Floodplain,South Australia River Murray,Flow at South Australia border,A4261001,FP1_S,7,6,63,,,1,25,25,50000,1000000,4,6,,F,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,SA,South Australian Murray 15 | PU_0000028,SA River Murray Floodplain,South Australia River Murray,Flow at South Australia border,A4261001,FP1_P,9,12,60,,,1,40,40,50000,1000000,4,,,L,,,,232,465,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,SA,South Australian Murray 16 | PU_0000028,SA River Murray Floodplain,South Australia River Murray,Flow at South Australia border,A4261001,FP1_PS,9,12,60,,,1,40,40,50000,1000000,4,,,F,,,,232,465,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,SA,South Australian Murray 17 | PU_0000028,SA River Murray Floodplain,South Australia River Murray,Flow at South Australia border,A4261001,FP2_S,7,6,50,,,1,12,12,60000,1000000,5,6,,F,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,SA,South Australian Murray 18 | PU_0000028,SA River Murray Floodplain,South Australia River Murray,Flow at South Australia border,A4261001,FP2_P,9,12,45,,,1,20,20,60000,1000000,5,,,L,,,,232,465,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,SA,South Australian Murray 19 | PU_0000028,SA River Murray Floodplain,South Australia River Murray,Flow at South Australia border,A4261001,FP2_PS,9,12,45,,,1,20,20,60000,1000000,5,,,F,,,,232,465,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,SA,South Australian Murray 20 | PU_0000028,SA River Murray Floodplain,South Australia River Murray,Flow at South Australia border,A4261001,FP3_S,7,6,38,,,1,20,20,70000,1000000,5,6,,F,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,SA,South Australian Murray 21 | PU_0000028,SA River Murray Floodplain,South Australia River Murray,Flow at South Australia border,A4261001,FP3_P,9,12,35,,,1,30,30,70000,1000000,5,,,L,,,,232,465,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,SA,South Australian Murray 22 | PU_0000028,SA River Murray Floodplain,South Australia River Murray,Flow at South Australia border,A4261001,FP3_PS,9,12,35,,,1,30,30,70000,1000000,5,,,F,,,,232,465,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,SA,South Australian Murray 23 | PU_0000028,SA River Murray Floodplain,South Australia River Murray,Flow at South Australia border,A4261001,FP4_S,7,6,28,,,1,20,20,80000,1000000,5,6,,F,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,SA,South Australian Murray 24 | PU_0000028,SA River Murray Floodplain,South Australia River Murray,Flow at South Australia border,A4261001,FP4_P,9,12,25,,,1,30,30,80000,1000000,5,,,L,,,,232,465,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,SA,South Australian Murray 25 | PU_0000028,SA River Murray Floodplain,South Australia River Murray,Flow at South Australia border,A4261001,FP4_PS,9,12,25,,,1,30,30,80000,1000000,5,,,F,,,,232,465,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,SA,South Australian Murray 26 | PU_0000028,SA River Murray Floodplain,South Australia River Murray,Flow at South Australia border,A4261001,FP5_S,7,6,13,,,1,20,20,80000,1000000,8.5,6,,F,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,SA,South Australian Murray 27 | PU_0000028,SA River Murray Floodplain,South Australia River Murray,Flow at South Australia border,A4261001,FP5_P,9,12,13,,,1,30,30,80000,1000000,8.5,,,L,,,,232,465,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,SA,South Australian Murray 28 | PU_0000028,SA River Murray Floodplain,South Australia River Murray,Flow at South Australia border,A4261001,FP5_PS,9,12,13,,,1,30,30,80000,1000000,8.5,,,F,,,,232,465,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,SA,South Australian Murray 29 | PU_0000029,"Coorong, Lower Lakes and Murray Mouth",South Australia River Murray,Barrages near the Murray Mouth,A4261002,CLLMM1a_P,9,12,100,,,1,1,1,0,0,0,,,F,,,0,,,,,,,,,,2000000,,9,12,1,8,,,,,,,,,,,,,,,,,,, 30 | PU_0000029,"Coorong, Lower Lakes and Murray Mouth",South Australia River Murray,Barrages near the Murray Mouth,A4261002,CLLMM1a_S,9,12,100,,,1,1,1,0,0,0,,,F,,,0,,,,,,,,,,2000000,,,,,,,,,,,,,,,,,,,,,,,, 31 | PU_0000029,"Coorong, Lower Lakes and Murray Mouth",South Australia River Murray,Barrages near the Murray Mouth,A4261002,CLLMM1b,9,12,100,,,1,1,1,0,0,0,,,F,,,0,,,,,,,,,,650000,6000000,9,12,1,9,,,,,,,,,,,,,,,,,,, 32 | PU_0000029,"Coorong, Lower Lakes and Murray Mouth",South Australia River Murray,Barrages near the Murray Mouth,A4260633,CLLMM1d_P,9,12,100,,,1,90,1,0,0,0,,,L,0,0.1,0,,,,,,,,,,,,,,,,9,12,3,5,,,,,,,,,,,,,,, 33 | PU_0000029,"Coorong, Lower Lakes and Murray Mouth",South Australia River Murray,Barrages near the Murray Mouth,A4260633,CLLMM1d_S,9,12,100,,,1,90,1,0,0,0,,,L,0,1000,0,,,,,,,,,,,,,,,,9,12,3,5,,,,,,,,,,,,,,, 34 | PU_0000029,"Coorong, Lower Lakes and Murray Mouth",South Australia River Murray,Barrages near the Murray Mouth,A4261002,CLLMM2a_P,9,1,50,,,1,1,1,0,0,3,,,F,,,0,,,,,,,,,,4000000,,10,12,1,9,,,,,,,,,,,,,,,,,,, 35 | PU_0000029,"Coorong, Lower Lakes and Murray Mouth",South Australia River Murray,Barrages near the Murray Mouth,A4261002,CLLMM2a_S,9,1,50,,,1,1,1,0,0,3,,,F,,,0,,,,,,,,,,4000000,,,,,,,,,,,,,,,,,,,,,,,, 36 | PU_0000029,"Coorong, Lower Lakes and Murray Mouth",South Australia River Murray,Barrages near the Murray Mouth,A4261002,CLLMM2b,9,1,50,,,1,1,1,0,0,3,,,F,,,0,,,,,,,,,,3150000,12000000,10,12,1,9,,,,,,,,,,,,,,,,,,, 37 | PU_0000029,"Coorong, Lower Lakes and Murray Mouth",South Australia River Murray,Barrages near the Murray Mouth,A4260527,CLLMM2c,9,1,50,,,1,1,1,0,0,3,,,L,0.5,0.83,0,,,,,,,,,,,,,,,,12,2,3,5,,,,,,,,,,,,,,, 38 | PU_0000029,"Coorong, Lower Lakes and Murray Mouth",South Australia River Murray,Barrages near the Murray Mouth,A4260633,CLLMM2d_P,9,1,50,,,1,150,1,0,0,3,,,L,0.2,0.45,0,,,,,,,,,,,,,,,,12,2,3,5,,,,,,,,,,,,,,, 39 | PU_0000029,"Coorong, Lower Lakes and Murray Mouth",South Australia River Murray,Barrages near the Murray Mouth,A4260633,CLLMM2d_S,9,1,50,,,1,150,1,0,0,3,,,L,0.2,1000,0,,,,,,,,,,,,,,,,12,2,3,5,,,,,,,,,,,,,,, 40 | PU_0000029,"Coorong, Lower Lakes and Murray Mouth",South Australia River Murray,Barrages near the Murray Mouth,A4261002,CLLMM3a_P,9,2,33,,,1,1,1,0,0,5,,,F,,,0,,,,,,,,,,6000000,,10,12,1,9,,,,,,,,,,,,,,,,,,, 41 | PU_0000029,"Coorong, Lower Lakes and Murray Mouth",South Australia River Murray,Barrages near the Murray Mouth,A4261002,CLLMM3a_S,9,2,33,,,1,1,1,0,0,5,,,F,,,0,,,,,,,,,,6000000,,,,,,,,,,,,,,,,,,,,,,,, 42 | PU_0000029,"Coorong, Lower Lakes and Murray Mouth",South Australia River Murray,Barrages near the Murray Mouth,A4260527,CLLMM3c,9,2,33,,,1,1,1,0,0,5,,,L,0.6,0.83,0,,,,,,,,,,,,,,,,12,2,3,5,,,,,,,,,,,,,,, 43 | PU_0000029,"Coorong, Lower Lakes and Murray Mouth",South Australia River Murray,Barrages near the Murray Mouth,A4260633,CLLMM3d_P,9,2,33,,,1,180,1,0,0,5,,,L,0.2,0.45,0,,,,,,,,,,,,,,,,12,2,3,5,,,,,,,,,,,,,,, 44 | PU_0000029,"Coorong, Lower Lakes and Murray Mouth",South Australia River Murray,Barrages near the Murray Mouth,A4260633,CLLMM3d_S,9,2,33,,,1,180,1,0,0,5,,,L,0.2,1000,0,,,,,,,,,,,,,,,,12,2,3,5,,,,,,,,,,,,,,, 45 | PU_0000029,"Coorong, Lower Lakes and Murray Mouth",South Australia River Murray,Barrages near the Murray Mouth,A4261002,CLLMM4a_P,9,2,14,,,1,1,1,0,0,17,,,F,,,0,,,,,,,,,,10000000,,10,12,1,9,,,,,,,,,,,,,,,,,,, 46 | PU_0000029,"Coorong, Lower Lakes and Murray Mouth",South Australia River Murray,Barrages near the Murray Mouth,A4261002,CLLMM4a_S,9,2,14,,,1,1,1,0,0,17,,,F,,,0,,,,,,,,,,10000000,,,,,,,,,,,,,,,,,,,,,,,, 47 | PU_0000029,"Coorong, Lower Lakes and Murray Mouth",South Australia River Murray,Barrages near the Murray Mouth,A4260527,CLLMM4c,9,2,14,,,1,1,1,0,0,17,,,L,0.6,0.9,0,,,,,,,,,,,,,,,,12,2,3,5,,,,,,,,,,,,,,, 48 | PU_0000029,"Coorong, Lower Lakes and Murray Mouth",South Australia River Murray,Barrages near the Murray Mouth,A4260527,CLLMM1c_P,9,12,100,,,1,1,1,0,0,0,,,L,0.5,0.75,0,,,,,,,,,,,,,,,,9,12,3,5,,,,,,,,,,,,,,, 49 | PU_0000029,"Coorong, Lower Lakes and Murray Mouth",South Australia River Murray,Barrages near the Murray Mouth,A4260527,CLLMM1c_S,8,12,100,,,1,1,1,0,0,0,,,L,0.4,0.5,0,,,,,,,,,,,,,,,,9,12,3,5,,,,,,,,,,,,,,, 50 | -------------------------------------------------------------------------------- /unit_testing_files/test_EWR_table_bad_output.csv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MDBAuth/EWR_tool/467885c638d1c8f86cbb822af56f3fac38801828/unit_testing_files/test_EWR_table_bad_output.csv -------------------------------------------------------------------------------- /unit_testing_files/test_EWR_table_good_output.csv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MDBAuth/EWR_tool/467885c638d1c8f86cbb822af56f3fac38801828/unit_testing_files/test_EWR_table_good_output.csv -------------------------------------------------------------------------------- /unit_testing_files/test_EWR_table_input.csv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MDBAuth/EWR_tool/467885c638d1c8f86cbb822af56f3fac38801828/unit_testing_files/test_EWR_table_input.csv -------------------------------------------------------------------------------- /unit_testing_files/test_climate_cats.nc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MDBAuth/EWR_tool/467885c638d1c8f86cbb822af56f3fac38801828/unit_testing_files/test_climate_cats.nc -------------------------------------------------------------------------------- /unit_testing_files/vic_parameter_sheet.csv: -------------------------------------------------------------------------------- 1 | PlanningUnitID,PlanningUnitName,LTWPShortName,CompliancePoint/Node,Gauge,Code,StartMonth,EndMonth,TargetFrequency,TargetFrequencyMin,TargetFrequencyMax,EventsPerYear,Duration,MinSpell,FlowThresholdMin,FlowThresholdMax,MaxInter-event,WithinEventGapTolerance,WeirpoolGauge,FlowLevelVolume,LevelThresholdMin,LevelThresholdMax,VolumeThreshold,DrawdownRate,MaxLevelRise,AccumulationPeriod,Multigauge,MaxSpell,TriggerDay,TriggerMonth,DrawDownRateWeek,AnnualFlowSum,AnnualBarrageFlow,ThreeYearsBarrageFlow,HighReleaseWindowStart,HighReleaseWindowEnd,LowReleaseWindowStart,LowReleaseWindowEnd,PeakLevelWindowStart,PeakLevelWindowEnd,LowLevelWindowStart,LowLevelWindowEnd,NonFlowSpell,EggsDaysSpell,LarvaeDaysSpell,MinLevelRise,RateOfRiseMax1,RateOfRiseMax2,RateOfFallMin,RateOfRiseThreshold1,RateOfRiseThreshold2,RateOfRiseRiverLevel,RateOfFallRiverLevel,CtfThreshold,GaugeType,State,SWSDLName 2 | PU_0000189,Reach 1: Lake Eildon to Yea River,Goulburn River 2015,Goulburn River @ Lake Eildon,405203,RRF,7,6,,,,1,1,1,1,,,,,F,,,,,,,,,,,,,,,,,,,,,,,,,,,2,2.7,,1000,5000,,,,,VIC,Goulburn 3 | PU_0000189,Reach 1: Lake Eildon to Yea River,Goulburn River 2015,Goulburn River @ Lake Eildon,405203,RFF,7,6,,,,1,1,1,1,,,,,F,,,,,,,,,,,,,,,,,,,,,,,,,,,,,0.8,,,,,,,VIC,Goulburn 4 | PU_0000192,Reach 4: Nagambie (downstream of Goulburn Weir) to Loch Garry,Goulburn River 2017,Goulburn River @ Murchison,405200,RRL_su,12,2,,,,1,1,1,1,,,,,L,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,0.38,,,,VIC,Goulburn 5 | PU_0000192,Reach 4: Nagambie (downstream of Goulburn Weir) to Loch Garry,Goulburn River 2017,Goulburn River @ Murchison,405200,RFL_su,12,2,,,,1,1,1,1,,,,,L,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,0.15,,,VIC,Goulburn 6 | PU_0000192,Reach 4: Nagambie (downstream of Goulburn Weir) to Loch Garry,Goulburn River 2017,Goulburn River @ Murchison,405200,RRL_au,3,5,,,,1,1,1,1,,,,,L,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,0.38,,,,VIC,Goulburn 7 | PU_0000192,Reach 4: Nagambie (downstream of Goulburn Weir) to Loch Garry,Goulburn River 2017,Goulburn River @ Murchison,405200,RFL_au,3,5,,,,1,1,1,1,,,,,L,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,0.15,,,VIC,Goulburn 8 | PU_0000192,Reach 4: Nagambie (downstream of Goulburn Weir) to Loch Garry,Goulburn River 2017,Goulburn River @ Murchison,405200,RRL_wi,6,8,,,,1,1,1,1,,,,,L,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,1.2,,,,VIC,Goulburn 9 | PU_0000192,Reach 4: Nagambie (downstream of Goulburn Weir) to Loch Garry,Goulburn River 2017,Goulburn River @ Murchison,405200,RFL_wi,6,8,,,,1,1,1,1,,,,,L,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,0.78,,,VIC,Goulburn 10 | PU_0000192,Reach 4: Nagambie (downstream of Goulburn Weir) to Loch Garry,Goulburn River 2017,Goulburn River @ Murchison,405200,RRL_sp,9,11,,,,1,1,1,1,,,,,L,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,0.8,,,,VIC,Goulburn 11 | PU_0000192,Reach 4: Nagambie (downstream of Goulburn Weir) to Loch Garry,Goulburn River 2017,Goulburn River @ Murchison,405200,RFL_sp,9,11,,,,1,1,1,1,,,,,L,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,0.72,,,VIC,Goulburn 12 | PU_0000190,Reach 2: Yea River to Sunday Creek (Seymour),Goulburn River 2017,Goulburn River @ Trawool,405201,F3,9,11,100,,,1,7,7,,,,,,L,0,,,,,,,,,,,,,,,,,,,,,,,,,0.5,,,,,,,,,,VIC,Goulburn 13 | PU_0000191,Reach 3: Sunday Creek (Seymour) to Goulburn Weir,Goulburn River 2017,Goulburn River @ Seymour,405202,F3,9,11,100,,,1,7,7,,,,,,L,0,,,,,,,,,,,,,,,,,,,,,,,,,0.5,,,,,,,,,,VIC,Goulburn 14 | -------------------------------------------------------------------------------- /unit_testing_files/werp_ncdf.nc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/MDBAuth/EWR_tool/467885c638d1c8f86cbb822af56f3fac38801828/unit_testing_files/werp_ncdf.nc --------------------------------------------------------------------------------