dapper 1.6.0__tar.gz → 1.7.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {dapper-1.6.0 → dapper-1.7.1}/PKG-INFO +49 -25
- {dapper-1.6.0 → dapper-1.7.1}/README.md +57 -57
- dapper-1.7.1/dapper/README.md +17 -0
- {dapper-1.6.0 → dapper-1.7.1}/dapper/__init__.py +2 -2
- {dapper-1.6.0 → dapper-1.7.1}/dapper/da_methods/README.md +2 -4
- {dapper-1.6.0 → dapper-1.7.1}/dapper/da_methods/__init__.py +23 -15
- {dapper-1.6.0 → dapper-1.7.1}/dapper/da_methods/baseline.py +49 -40
- {dapper-1.6.0 → dapper-1.7.1}/dapper/da_methods/ensemble.py +331 -282
- dapper-1.7.1/dapper/da_methods/extended.py +113 -0
- {dapper-1.6.0 → dapper-1.7.1}/dapper/da_methods/other.py +59 -49
- {dapper-1.6.0 → dapper-1.7.1}/dapper/da_methods/particle.py +167 -161
- {dapper-1.6.0 → dapper-1.7.1}/dapper/da_methods/variational.py +127 -113
- {dapper-1.6.0 → dapper-1.7.1}/dapper/dpr_config.py +18 -14
- {dapper-1.6.0 → dapper-1.7.1}/dapper/dpr_config.yaml +0 -5
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/DoublePendulum/__init__.py +24 -16
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/DoublePendulum/demo.py +19 -9
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/DoublePendulum/settings101.py +6 -7
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/Id/__init__.py +3 -2
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/Ikeda/__init__.py +15 -16
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/Ikeda/demo.py +8 -8
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/Ikeda/some_settings_01.py +8 -8
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/KS/__init__.py +53 -46
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/KS/bocquet2019.py +10 -9
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/KS/compare_schemes.py +14 -15
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/KS/demo.py +14 -14
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/LA/__init__.py +22 -21
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/LA/demo.py +1 -0
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/LA/evensen2009.py +11 -11
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/LA/raanes2015.py +20 -17
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/LA/small.py +8 -8
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/Lorenz05/__init__.py +35 -27
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/Lorenz05/demo.py +1 -1
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/Lorenz05/settings01.py +6 -6
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/Lorenz63/__init__.py +4 -5
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/Lorenz63/anderson2010rhf.py +7 -7
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/Lorenz63/bocquet2012.py +1 -1
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/Lorenz63/demo.py +6 -6
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/Lorenz63/extras.py +9 -11
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/Lorenz63/mandel2016.py +10 -7
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/Lorenz63/ramgraber2022.py +6 -6
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/Lorenz63/sakov2012.py +7 -7
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/Lorenz63/wiljes2017.py +2 -2
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/Lorenz84/__init__.py +7 -8
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/Lorenz84/demo.py +8 -9
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/Lorenz84/harder.py +1 -1
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/Lorenz84/pajonk2012.py +8 -8
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/Lorenz96/__init__.py +2 -2
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/Lorenz96/anderson2009.py +15 -10
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/Lorenz96/bocquet2010.py +5 -5
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/Lorenz96/bocquet2010_m40.py +4 -3
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/Lorenz96/bocquet2015loc.py +2 -2
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/Lorenz96/demo.py +1 -1
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/Lorenz96/extras.py +16 -13
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/Lorenz96/frei2013bridging.py +10 -10
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/Lorenz96/hoteit2015.py +1 -1
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/Lorenz96/miyoshi2011.py +14 -11
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/Lorenz96/pinheiro2019.py +8 -7
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/Lorenz96/raanes2016.py +1 -1
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/Lorenz96/sakov2008.py +13 -13
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/Lorenz96/spantini2019.py +8 -8
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/Lorenz96/spectral_obs.py +10 -11
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/Lorenz96/todter2015.py +6 -6
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/Lorenz96/todter2015_G.py +1 -1
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/Lorenz96s/__init__.py +29 -22
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/Lorenz96s/grudzien2020.py +4 -4
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/LorenzUV/__init__.py +28 -24
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/LorenzUV/demo.py +6 -6
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/LorenzUV/illust_LorenzUV.py +59 -45
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/LorenzUV/illust_parameterizations.py +47 -37
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/LorenzUV/lorenz96.py +12 -12
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/LorenzUV/wilks05.py +15 -15
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/LotkaVolterra/__init__.py +15 -11
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/LotkaVolterra/demo.py +2 -2
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/LotkaVolterra/settings101.py +7 -8
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/QG/__init__.py +63 -41
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/QG/counillon2009.py +4 -4
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/QG/demo.py +12 -10
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/QG/f90/README.md +4 -4
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/QG/illust_obs.py +9 -9
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/QG/sakov2008.py +13 -13
- dapper-1.7.1/dapper/mods/README.md +91 -0
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/VL20/__init__.py +29 -24
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/VL20/demo.py +5 -4
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/__init__.py +100 -69
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/explore_props.py +90 -80
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/integration.py +14 -8
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/utils.py +47 -35
- {dapper-1.6.0 → dapper-1.7.1}/dapper/stats.py +283 -142
- dapper-1.7.1/dapper/stats_etc.md +84 -0
- {dapper-1.6.0 → dapper-1.7.1}/dapper/tools/chronos.py +81 -61
- {dapper-1.6.0 → dapper-1.7.1}/dapper/tools/colors.py +28 -21
- {dapper-1.6.0 → dapper-1.7.1}/dapper/tools/datafiles.py +20 -14
- {dapper-1.6.0 → dapper-1.7.1}/dapper/tools/linalg.py +7 -7
- {dapper-1.6.0 → dapper-1.7.1}/dapper/tools/liveplotting.py +392 -350
- {dapper-1.6.0 → dapper-1.7.1}/dapper/tools/localization.py +60 -52
- {dapper-1.6.0 → dapper-1.7.1}/dapper/tools/matrices.py +80 -78
- {dapper-1.6.0 → dapper-1.7.1}/dapper/tools/multiproc.py +18 -9
- {dapper-1.6.0 → dapper-1.7.1}/dapper/tools/progressbar.py +22 -13
- {dapper-1.6.0 → dapper-1.7.1}/dapper/tools/randvars.py +40 -38
- {dapper-1.6.0 → dapper-1.7.1}/dapper/tools/remote/README.md +61 -48
- {dapper-1.6.0 → dapper-1.7.1}/dapper/tools/remote/autoscaler.py +131 -91
- {dapper-1.6.0 → dapper-1.7.1}/dapper/tools/remote/uplink.py +71 -50
- {dapper-1.6.0 → dapper-1.7.1}/dapper/tools/rounding.py +15 -10
- {dapper-1.6.0 → dapper-1.7.1}/dapper/tools/seeding.py +6 -4
- {dapper-1.6.0 → dapper-1.7.1}/dapper/tools/series.py +61 -47
- {dapper-1.6.0 → dapper-1.7.1}/dapper/tools/viz.py +195 -171
- {dapper-1.6.0 → dapper-1.7.1}/dapper/xp_launch.py +100 -71
- {dapper-1.6.0 → dapper-1.7.1}/dapper/xp_process.py +181 -111
- {dapper-1.6.0 → dapper-1.7.1}/dapper.egg-info/PKG-INFO +49 -25
- {dapper-1.6.0 → dapper-1.7.1}/dapper.egg-info/SOURCES.txt +1 -2
- dapper-1.7.1/dapper.egg-info/requires.txt +79 -0
- {dapper-1.6.0 → dapper-1.7.1}/dapper.egg-info/top_level.txt +0 -1
- dapper-1.7.1/pyproject.toml +133 -0
- dapper-1.7.1/setup.py +152 -0
- {dapper-1.6.0 → dapper-1.7.1}/tests/test_HMMs.py +3 -3
- {dapper-1.6.0 → dapper-1.7.1}/tests/test_TLMs.py +16 -3
- {dapper-1.6.0 → dapper-1.7.1}/tests/test_data.py +20 -20
- {dapper-1.6.0 → dapper-1.7.1}/tests/test_example_2.py +2 -2
- {dapper-1.6.0 → dapper-1.7.1}/tests/test_iEnKS.py +53 -49
- dapper-1.7.1/tests/test_localization.py +64 -0
- {dapper-1.6.0 → dapper-1.7.1}/tests/test_matrices.py +1 -1
- {dapper-1.6.0 → dapper-1.7.1}/tests/test_plotting.py +14 -15
- {dapper-1.6.0 → dapper-1.7.1}/tests/test_round2.py +52 -57
- dapper-1.6.0/dapper/README.md +0 -43
- dapper-1.6.0/dapper/da_methods/extended.py +0 -114
- dapper-1.6.0/dapper/mods/README.md +0 -110
- dapper-1.6.0/dapper.egg-info/requires.txt +0 -66
- dapper-1.6.0/examples/basic_1.py +0 -104
- dapper-1.6.0/examples/basic_2.py +0 -79
- dapper-1.6.0/pyproject.toml +0 -143
- dapper-1.6.0/setup.py +0 -129
- dapper-1.6.0/tests/test_localization.py +0 -56
- {dapper-1.6.0 → dapper-1.7.1}/LICENCE.txt +0 -0
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/QG/f90/Makefile +0 -0
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/QG/f90/__init__.py +0 -0
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/QG/f90/calc.f90 +0 -0
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/QG/f90/data.f90 +0 -0
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/QG/f90/helmholtz.f90 +0 -0
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/QG/f90/interface.f90 +0 -0
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/QG/f90/nfw.f90 +0 -0
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/QG/f90/parameters.f90 +0 -0
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/QG/f90/prms_cou09_ens.txt +0 -0
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/QG/f90/prms_cou09_truth.txt +0 -0
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/QG/f90/prms_counillon2009_ens.txt +0 -0
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/QG/f90/prms_counillon2009_truth.txt +0 -0
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/QG/f90/prms_sak08.txt +0 -0
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/QG/f90/prms_sakov2008.txt +0 -0
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/QG/f90/prms_sample_generation.txt +0 -0
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/QG/f90/prms_test_model.txt +0 -0
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/QG/f90/qg.f90 +0 -0
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/QG/f90/qgflux.f90 +0 -0
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/QG/f90/qgstep.f90 +0 -0
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/QG/f90/utils.f90 +0 -0
- {dapper-1.6.0 → dapper-1.7.1}/dapper/mods/QG/governing_eqn.png +0 -0
- {dapper-1.6.0 → dapper-1.7.1}/dapper/tools/__init__.py +0 -0
- {dapper-1.6.0 → dapper-1.7.1}/dapper/tools/remote/__init__.py +0 -0
- {dapper-1.6.0 → dapper-1.7.1}/dapper.egg-info/dependency_links.txt +0 -0
- {dapper-1.6.0 → dapper-1.7.1}/setup.cfg +0 -0
- {dapper-1.6.0 → dapper-1.7.1}/tests/__init__.py +0 -0
- {dapper-1.6.0 → dapper-1.7.1}/tests/test_demos.py +0 -0
- {dapper-1.6.0 → dapper-1.7.1}/tests/test_operator.py +0 -0
- {dapper-1.6.0 → dapper-1.7.1}/tests/test_printing.py +0 -0
- {dapper-1.6.0 → dapper-1.7.1}/tests/test_randvars.py +0 -0
- {dapper-1.6.0 → dapper-1.7.1}/tests/test_rng.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: dapper
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.7.1
|
|
4
4
|
Summary: DAPPER benchmarks the performance of data assimilation (DA) methods.
|
|
5
5
|
Author: Patrick N. Raanes
|
|
6
6
|
Author-email: patrick.n.raanes@gmail.com
|
|
@@ -17,21 +17,22 @@ Classifier: Operating System :: OS Independent
|
|
|
17
17
|
Requires-Python: >=3.9
|
|
18
18
|
Description-Content-Type: text/markdown
|
|
19
19
|
License-File: LICENCE.txt
|
|
20
|
-
Requires-Dist: scipy>=1.
|
|
21
|
-
Requires-Dist:
|
|
20
|
+
Requires-Dist: scipy>=1.14
|
|
21
|
+
Requires-Dist: numpy~=2.0
|
|
22
|
+
Requires-Dist: matplotlib>=3.10
|
|
23
|
+
Requires-Dist: pyyaml>=6.0.2
|
|
24
|
+
Requires-Dist: ipython>=7.34
|
|
22
25
|
Requires-Dist: ipdb
|
|
23
|
-
Requires-Dist:
|
|
24
|
-
Requires-Dist:
|
|
25
|
-
Requires-Dist:
|
|
26
|
-
Requires-Dist:
|
|
27
|
-
Requires-Dist: tqdm~=4.31
|
|
28
|
-
Requires-Dist: pyyaml
|
|
26
|
+
Requires-Dist: jupyter
|
|
27
|
+
Requires-Dist: notebook<7
|
|
28
|
+
Requires-Dist: mpl-tools==0.4.1
|
|
29
|
+
Requires-Dist: tqdm~=4.67
|
|
29
30
|
Requires-Dist: colorama~=0.4.1
|
|
30
31
|
Requires-Dist: tabulate~=0.8.3
|
|
31
|
-
Requires-Dist:
|
|
32
|
-
Requires-Dist:
|
|
32
|
+
Requires-Dist: pathos~=0.3
|
|
33
|
+
Requires-Dist: dill==0.3.8
|
|
34
|
+
Requires-Dist: patlib==0.3.7
|
|
33
35
|
Requires-Dist: struct-tools==0.2.5
|
|
34
|
-
Requires-Dist: multiprocessing-on-dill==3.5.0a4
|
|
35
36
|
Requires-Dist: threadpoolctl<4.0.0,>=3.0.0
|
|
36
37
|
Provides-Extra: qt
|
|
37
38
|
Requires-Dist: PyQt5; extra == "qt"
|
|
@@ -39,7 +40,6 @@ Requires-Dist: qtpy; extra == "qt"
|
|
|
39
40
|
Provides-Extra: debug
|
|
40
41
|
Requires-Dist: line_profiler; extra == "debug"
|
|
41
42
|
Requires-Dist: pre-commit; extra == "debug"
|
|
42
|
-
Requires-Dist: pdbpp>=0.10.3; extra == "debug"
|
|
43
43
|
Provides-Extra: test
|
|
44
44
|
Requires-Dist: tox; extra == "test"
|
|
45
45
|
Requires-Dist: coverage>=5.1; extra == "test"
|
|
@@ -51,17 +51,23 @@ Requires-Dist: pytest-clarity; extra == "test"
|
|
|
51
51
|
Requires-Dist: pytest-xdist; extra == "test"
|
|
52
52
|
Requires-Dist: pytest-timeout; extra == "test"
|
|
53
53
|
Provides-Extra: lint
|
|
54
|
-
Requires-Dist:
|
|
55
|
-
|
|
56
|
-
Requires-Dist:
|
|
54
|
+
Requires-Dist: ruff; extra == "lint"
|
|
55
|
+
Provides-Extra: doc
|
|
56
|
+
Requires-Dist: mkdocs-material; extra == "doc"
|
|
57
|
+
Requires-Dist: mkdocstrings; extra == "doc"
|
|
58
|
+
Requires-Dist: mkdocstrings-python; extra == "doc"
|
|
59
|
+
Requires-Dist: mkdocs-gen-files; extra == "doc"
|
|
60
|
+
Requires-Dist: mkdocs-literate-nav; extra == "doc"
|
|
61
|
+
Requires-Dist: mkdocs-section-index; extra == "doc"
|
|
62
|
+
Requires-Dist: mkdocs-glightbox; extra == "doc"
|
|
63
|
+
Requires-Dist: mkdocs-jupyter; extra == "doc"
|
|
64
|
+
Requires-Dist: pybtex; extra == "doc"
|
|
57
65
|
Provides-Extra: build
|
|
58
66
|
Requires-Dist: twine; extra == "build"
|
|
59
|
-
Requires-Dist:
|
|
60
|
-
Requires-Dist: jupytext; extra == "build"
|
|
67
|
+
Requires-Dist: jupytext<=1.15; extra == "build"
|
|
61
68
|
Provides-Extra: dev
|
|
62
69
|
Requires-Dist: line_profiler; extra == "dev"
|
|
63
70
|
Requires-Dist: pre-commit; extra == "dev"
|
|
64
|
-
Requires-Dist: pdbpp>=0.10.3; extra == "dev"
|
|
65
71
|
Requires-Dist: tox; extra == "dev"
|
|
66
72
|
Requires-Dist: coverage>=5.1; extra == "dev"
|
|
67
73
|
Requires-Dist: pytest; extra == "dev"
|
|
@@ -71,12 +77,30 @@ Requires-Dist: pytest-benchmark; extra == "dev"
|
|
|
71
77
|
Requires-Dist: pytest-clarity; extra == "dev"
|
|
72
78
|
Requires-Dist: pytest-xdist; extra == "dev"
|
|
73
79
|
Requires-Dist: pytest-timeout; extra == "dev"
|
|
74
|
-
Requires-Dist:
|
|
75
|
-
Requires-Dist: flakeheaven; extra == "dev"
|
|
76
|
-
Requires-Dist: autopep8; extra == "dev"
|
|
80
|
+
Requires-Dist: ruff; extra == "dev"
|
|
77
81
|
Requires-Dist: twine; extra == "dev"
|
|
78
|
-
Requires-Dist:
|
|
79
|
-
Requires-Dist:
|
|
82
|
+
Requires-Dist: jupytext<=1.15; extra == "dev"
|
|
83
|
+
Requires-Dist: mkdocs-material; extra == "dev"
|
|
84
|
+
Requires-Dist: mkdocstrings; extra == "dev"
|
|
85
|
+
Requires-Dist: mkdocstrings-python; extra == "dev"
|
|
86
|
+
Requires-Dist: mkdocs-gen-files; extra == "dev"
|
|
87
|
+
Requires-Dist: mkdocs-literate-nav; extra == "dev"
|
|
88
|
+
Requires-Dist: mkdocs-section-index; extra == "dev"
|
|
89
|
+
Requires-Dist: mkdocs-glightbox; extra == "dev"
|
|
90
|
+
Requires-Dist: mkdocs-jupyter; extra == "dev"
|
|
91
|
+
Requires-Dist: pybtex; extra == "dev"
|
|
92
|
+
Dynamic: author
|
|
93
|
+
Dynamic: author-email
|
|
94
|
+
Dynamic: classifier
|
|
95
|
+
Dynamic: description
|
|
96
|
+
Dynamic: description-content-type
|
|
97
|
+
Dynamic: keywords
|
|
98
|
+
Dynamic: license-file
|
|
99
|
+
Dynamic: project-url
|
|
100
|
+
Dynamic: provides-extra
|
|
101
|
+
Dynamic: requires-dist
|
|
102
|
+
Dynamic: requires-python
|
|
103
|
+
Dynamic: summary
|
|
80
104
|
|
|
81
105
|
It is usually best to install from source (github),
|
|
82
106
|
so that you the code is readily available to play with.
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
!
|
|
9
9
|
-->
|
|
10
10
|
|
|
11
|
-
<img src="/docs/
|
|
11
|
+
<img src="https://github.com/nansencenter/DAPPER/raw/master/docs/images/logos/logo_wtxt.png" align="left" width="250"/>
|
|
12
12
|
|
|
13
13
|
DAPPER is a set of templates for **benchmarking** the performance of **data assimilation** (DA) methods.
|
|
14
14
|
The numerical experiments provide support and guidance for new developments in DA.
|
|
@@ -26,21 +26,19 @@ and then estimate that truth given the models and noisy observations.
|
|
|
26
26
|
|
|
27
27
|
## Getting started
|
|
28
28
|
|
|
29
|
-
[
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
The [documentation](https://nansencenter.github.io/DAPPER)
|
|
36
|
-
includes general guidelines and the API,
|
|
37
|
-
but
|
|
38
|
-
If
|
|
39
|
-
*The experiments used (inspiration from) DAPPER [ref], version 1.6.0*,
|
|
40
|
-
where [ref] points to [.
|
|
43
|
-
|
|
29
|
+
- Read & run [examples](examples)/`basic_1.py` and `basic_2.py`,
|
|
30
|
+
or their corresponding notebooks [](http://colab.research.google.com/github/nansencenter/DAPPER)
|
|
31
|
+
(requires Google login).
|
|
32
|
+
- This [screencast](https://www.youtube.com/watch?v=YtalK0Zkzvg&t=6475s)
|
|
33
|
+
provides an overview to DAPPER.
|
|
34
|
+
- [Install](#installation).
|
|
35
|
+
- The [documentation](https://nansencenter.github.io/DAPPER)
|
|
36
|
+
includes general guidelines and the API reference,
|
|
37
|
+
but most users must expect to read the code as well.
|
|
38
|
+
- If used towards a publication, please cite as
|
|
39
|
+
*The experiments used (inspiration from) DAPPER [ref], version 1.6.0*,
|
|
40
|
+
or similar, where [ref] points to [](https://doi.org/10.21105/joss.05150).
|
|
41
|
+
- Also see the interactive [tutorials on DA theory](https://github.com/nansencenter/DA-tutorials) with Python.
|
|
44
42
|
|
|
45
43
|
## Highlights
|
|
46
44
|
|
|
@@ -50,26 +48,30 @@ through a variety of typical [test cases](#test-cases-models) and statistics. It
|
|
|
50
48
|
(b) facilitates comparative studies, thus promoting the
|
|
51
49
|
(a) reliability and
|
|
52
50
|
(b) relevance of the results.
|
|
53
|
-
For example,
|
|
54
|
-
making use of built-in tools for experiment and result management,
|
|
51
|
+
For example, the figure below is generated by `docs/examples/basic_3.py`,
|
|
55
52
|
reproduces figure 5.7 of [these lecture notes](http://cerea.enpc.fr/HomePages/bocquet/teaching/assim-mb-en.pdf).
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
53
|
+
DAPPER is
|
|
54
|
+
(c) open source, written in Python, and
|
|
55
|
+
(d) focuses on readability;
|
|
56
|
+
this promotes the
|
|
57
|
+
(c) reproduction and
|
|
58
|
+
(d) dissemination of the underlying science,
|
|
61
59
|
and makes it easy to adapt and extend.
|
|
62
60
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
61
|
+

|
|
62
|
+
|
|
63
|
+
DAPPER demonstrates how to parallelise ensemble forecasts (e.g., the QG model),
|
|
64
|
+
local analyses (e.g., the LETKF), and independent experiments (e.g., `docs/examples/basic_3.py`).
|
|
65
|
+
It includes a battery of diagnostics and statistics,
|
|
66
|
+
which all get averaged over subdomains (e.g., "ocean" and "land") and then in time.
|
|
67
67
|
Confidence intervals are computed, including correction for auto-correlations,
|
|
68
68
|
and used for uncertainty quantification, and significant digits printing.
|
|
69
69
|
Several diagnostics are included in the on-line "liveplotting" illustrated below,
|
|
70
70
|
which may be paused for further interactive inspection.
|
|
71
|
+
In summary, DAPPER is well suited for teaching and fundamental DA research.
|
|
72
|
+
Also see its [drawbacks](#similar-projects).
|
|
71
73
|
|
|
72
|
-

|
|
73
75
|
|
|
74
76
|
<!-- Non-highlighted features:
|
|
75
77
|
- Time sequences use via `tools.chronos.Chronology` and `tools.chronos.Ticker`.
|
|
@@ -79,12 +81,9 @@ which may be paused for further interactive inspection.
|
|
|
79
81
|
provides input flexibility/overloading,
|
|
80
82
|
lazy eval that facilitates the use of non-diagonal
|
|
81
83
|
covariance matrices (whether sparse or full).
|
|
84
|
+
- built-in tools for experiment and result management,
|
|
82
85
|
-->
|
|
83
86
|
|
|
84
|
-
In summary, DAPPER is well suited for teaching and fundamental DA research.
|
|
85
|
-
Also see its [drawbacks](#similar-projects).
|
|
86
|
-
|
|
87
|
-
|
|
88
87
|
## Installation
|
|
89
88
|
|
|
90
89
|
Successfully tested on Linux/Mac/Windows.
|
|
@@ -98,12 +97,12 @@ open the [Anaconda terminal](https://docs.conda.io/projects/conda/en/latest/user
|
|
|
98
97
|
and run the following commands:
|
|
99
98
|
|
|
100
99
|
```sh
|
|
101
|
-
conda create --yes --name dapper-env python=3.
|
|
100
|
+
conda create --yes --name dapper-env python=3.12
|
|
102
101
|
conda activate dapper-env
|
|
103
102
|
python --version
|
|
104
103
|
```
|
|
105
104
|
|
|
106
|
-
Ensure the printed version is
|
|
105
|
+
Ensure the printed version is as desired.
|
|
107
106
|
*Keep using the same terminal for the commands below.*
|
|
108
107
|
|
|
109
108
|
### Install
|
|
@@ -114,19 +113,17 @@ Ensure the printed version is 3.9 or more.
|
|
|
114
113
|
|
|
115
114
|
- Download and unzip (or `git clone`) DAPPER.
|
|
116
115
|
- Move the resulting folder wherever you like,
|
|
117
|
-
and `cd` into it
|
|
118
|
-
|
|
119
|
-
- `pip install -e '.[dev]'`
|
|
120
|
-
You can omit `[dev]` if you don't need to do serious development.
|
|
116
|
+
and `cd` into it *(ensure you're in the folder with a `setup.py` file)*.
|
|
117
|
+
- `pip install -e '.'`
|
|
121
118
|
|
|
122
119
|
#### *Or*: Install as library
|
|
123
120
|
|
|
124
121
|
*Do you just want to run a script that requires DAPPER?* Then
|
|
125
122
|
|
|
126
|
-
- If the script comes with a `requirements.txt` file, then do
|
|
123
|
+
- If the script comes with a `requirements.txt` file that lists DAPPER, then do
|
|
127
124
|
`pip install -r path/to/requirements.txt`.
|
|
128
125
|
- If not, hopefully you know the version of DAPPER needed. Run
|
|
129
|
-
`pip install dapper==1.
|
|
126
|
+
`pip install dapper==1.6.0` to get version `1.6.0` (as an example).
|
|
130
127
|
|
|
131
128
|
#### *Finally*: Test the installation
|
|
132
129
|
|
|
@@ -134,7 +131,7 @@ You should now be able to do run your script with
|
|
|
134
131
|
`python path/to/script.py`.
|
|
135
132
|
For example, if you are in the DAPPER dir,
|
|
136
133
|
|
|
137
|
-
python examples/basic_1.py
|
|
134
|
+
python docs/examples/basic_1.py
|
|
138
135
|
|
|
139
136
|
**PS**: If you closed the terminal (or shut down your computer),
|
|
140
137
|
you'll first need to run `conda activate dapper-env`
|
|
@@ -146,16 +143,16 @@ you'll first need to run `conda activate dapper-env`
|
|
|
146
143
|
<!-- markdownlint-disable line-length -->
|
|
147
144
|
Method | Literature reproduced
|
|
148
145
|
------------------------------------------------------ | ------------------------
|
|
149
|
-
EnKF <sup>1</sup> | [Sakov08](https://nansencenter.github.io/DAPPER/
|
|
150
|
-
EnKF-N | [Bocquet12](https://nansencenter.github.io/DAPPER/
|
|
151
|
-
EnKS, EnRTS | [Raanes2016](https://nansencenter.github.io/DAPPER/
|
|
152
|
-
iEnKS / iEnKF / EnRML / ES-MDA <sup>2</sup> | [Sakov12](https://nansencenter.github.io/DAPPER/
|
|
153
|
-
LETKF, local & serial EAKF | [Bocquet11](https://nansencenter.github.io/DAPPER/
|
|
154
|
-
Sqrt. model noise methods | [Raanes2014](https://nansencenter.github.io/DAPPER/
|
|
155
|
-
Particle filter (bootstrap) <sup>3</sup> | [Bocquet10](https://nansencenter.github.io/DAPPER/
|
|
156
|
-
Optimal/implicit Particle filter <sup>3</sup> | [Bocquet10](https://nansencenter.github.io/DAPPER/
|
|
157
|
-
NETF | [Tödter15](https://nansencenter.github.io/DAPPER/
|
|
158
|
-
Rank histogram filter (RHF) | [Anderson10](https://nansencenter.github.io/DAPPER/
|
|
146
|
+
EnKF <sup>1</sup> | [Sakov08](https://nansencenter.github.io/DAPPER/references/#sakov2008b), [Hoteit15](https://nansencenter.github.io/DAPPER/references/#hoteit2015a), [Grudzien2020](https://nansencenter.github.io/DAPPER/references/#grudzien2020a)
|
|
147
|
+
EnKF-N | [Bocquet12](https://nansencenter.github.io/DAPPER/references/#bocquet2012a), [Bocquet15](https://nansencenter.github.io/DAPPER/references/#bocquet2015)
|
|
148
|
+
EnKS, EnRTS | [Raanes2016](https://nansencenter.github.io/DAPPER/references/#raanes2016thesis)
|
|
149
|
+
iEnKS / iEnKF / EnRML / ES-MDA <sup>2</sup> | [Sakov12](https://nansencenter.github.io/DAPPER/references/#sakov2012a), [Bocquet12](https://nansencenter.github.io/DAPPER/references/#Bocquet12), [Bocquet14](https://nansencenter.github.io/DAPPER/references/#bocquet2014)
|
|
150
|
+
LETKF, local & serial EAKF | [Bocquet11](https://nansencenter.github.io/DAPPER/references/#bocquet2011)
|
|
151
|
+
Sqrt. model noise methods | [Raanes2014](https://nansencenter.github.io/DAPPER/references/#raanes2014)
|
|
152
|
+
Particle filter (bootstrap) <sup>3</sup> | [Bocquet10](https://nansencenter.github.io/DAPPER/references/#bocquet2010a)
|
|
153
|
+
Optimal/implicit Particle filter <sup>3</sup> | [Bocquet10](https://nansencenter.github.io/DAPPER/references/#bocquet2010a)
|
|
154
|
+
NETF | [Tödter15](https://nansencenter.github.io/DAPPER/references/#todter2015a), [Wiljes16](https://nansencenter.github.io/DAPPER/references/#wiljes2016)
|
|
155
|
+
Rank histogram filter (RHF) | [Anderson10](https://nansencenter.github.io/DAPPER/references/#anderson2010)
|
|
159
156
|
4D-Var |
|
|
160
157
|
3D-Var |
|
|
161
158
|
Extended KF |
|
|
@@ -174,7 +171,7 @@ The particle filter is tuned with "effective-N monitoring",
|
|
|
174
171
|
"regularization/jittering" strength, and more.
|
|
175
172
|
|
|
176
173
|
For a list of ready-made experiments with suitable,
|
|
177
|
-
tuned settings for a given method (e.g
|
|
174
|
+
tuned settings for a given method (e.g., the `iEnKS`), use:
|
|
178
175
|
|
|
179
176
|
```sh
|
|
180
177
|
grep -r "xp.*iEnKS" dapper/mods
|
|
@@ -183,6 +180,9 @@ grep -r "xp.*iEnKS" dapper/mods
|
|
|
183
180
|
|
|
184
181
|
## Test cases (models)
|
|
185
182
|
|
|
183
|
+
Simple models facilitate the reliability, reproducibility,
|
|
184
|
+
and interpretability of experiment results.
|
|
185
|
+
|
|
186
186
|
Model | Lin | TLM** | PDE? | Phys.dim. | State len | Lyap≥0 | Implementer
|
|
187
187
|
----------- | --- | ----- | ---- | --------- | --------- | ------ | ----------
|
|
188
188
|
Id | Yes | Yes | No | N/A | * | 0 | Raanes
|
|
@@ -351,11 +351,11 @@ and the Center for Western Weather and Water Extremes (CW3E).
|
|
|
351
351
|
|
|
352
352
|
<!-- markdownlint-capture -->
|
|
353
353
|
<!-- markdownlint-disable line-length -->
|
|
354
|
-

|
|
355
|
+

|
|
356
|
+
<img src="https://github.com/nansencenter/DAPPER/raw/master/docs/images/logos/UoR-logo.png?raw=true" height="120" />
|
|
357
|
+
<img src="https://github.com/nansencenter/DAPPER/raw/master/docs/images/logos/nceologo1000.png?raw=true" height="100">
|
|
358
|
+
<img src="https://github.com/nansencenter/DAPPER/raw/master/docs/images/logos/CW3E-Logo-Horizontal-FullColor.png?raw=true" width="400">
|
|
359
359
|
<!-- markdownlint-restore -->
|
|
360
360
|
|
|
361
361
|
## Publications
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
## Adding your own model/method
|
|
2
|
+
|
|
3
|
+
If you wish to illustrate and run benchmarks with
|
|
4
|
+
your own **model** or **method**, then
|
|
5
|
+
|
|
6
|
+
- If it is a complex one, you may be better off using DAPPER
|
|
7
|
+
merely as *inspiration* (but you can still
|
|
8
|
+
[cite it](../#getting-started))
|
|
9
|
+
rather than trying to squeeze everything into its templates.
|
|
10
|
+
- If it is relatively simple, however, you may well want to use DAPPER.
|
|
11
|
+
In that case, read this:
|
|
12
|
+
- [`mods`](mods)
|
|
13
|
+
- [`da_methods`](da_methods)
|
|
14
|
+
|
|
15
|
+
Since the generality of DAPPER is
|
|
16
|
+
[limited](../#similar-projects)
|
|
17
|
+
it is quite likely you will also need to make changes to the DAPPER code itself.
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
"""Root package of **DAPPER**
|
|
2
2
|
(Data Assimilation with Python: a Package for Experimental Research)
|
|
3
3
|
|
|
4
|
-
|
|
4
|
+
--8<-- "dapper/README.md"
|
|
5
5
|
"""
|
|
6
6
|
|
|
7
|
-
__version__ = "1.
|
|
7
|
+
__version__ = "1.7.1"
|
|
8
8
|
|
|
9
9
|
# A parsimonious list of imports used in the examples
|
|
10
10
|
from .dpr_config import rc
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
Also see
|
|
2
|
-
[DA Methods](https://github.com/nansencenter/DAPPER#DA-Methods)
|
|
3
|
-
in the main README
|
|
1
|
+
Also see [this section on DA Methods](../../#da-methods)
|
|
4
2
|
for an overview of the methods included with DAPPER.
|
|
5
3
|
|
|
6
4
|
## Defining your own method
|
|
@@ -8,7 +6,7 @@ for an overview of the methods included with DAPPER.
|
|
|
8
6
|
Follow the example of one of the methods within one of the
|
|
9
7
|
sub-directories/packages.
|
|
10
8
|
The simplest example is perhaps
|
|
11
|
-
`
|
|
9
|
+
[`da_methods.ensemble.EnKF`][].
|
|
12
10
|
|
|
13
11
|
## General advice for programming/debugging scientific experiments
|
|
14
12
|
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
"""Contains the data assimilation methods included with DAPPER.
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
--8<-- "dapper/da_methods/README.md"
|
|
4
4
|
"""
|
|
5
|
+
|
|
5
6
|
from pathlib import Path
|
|
6
7
|
|
|
7
8
|
|
|
@@ -15,7 +16,7 @@ def da_method(*default_dataclasses):
|
|
|
15
16
|
The decorated classes are defined like a `dataclass`,
|
|
16
17
|
but are decorated by `@da_method()` instead of `@dataclass`.
|
|
17
18
|
|
|
18
|
-
|
|
19
|
+
!!! note
|
|
19
20
|
The classes must define a method called `assimilate`.
|
|
20
21
|
This method gets slightly enhanced by this wrapper which provides:
|
|
21
22
|
|
|
@@ -24,7 +25,8 @@ def da_method(*default_dataclasses):
|
|
|
24
25
|
- Duration timing
|
|
25
26
|
- Progressbar naming magic.
|
|
26
27
|
|
|
27
|
-
|
|
28
|
+
Examples
|
|
29
|
+
--------
|
|
28
30
|
>>> @da_method()
|
|
29
31
|
... class Sleeper():
|
|
30
32
|
... "Do nothing."
|
|
@@ -42,7 +44,6 @@ def da_method(*default_dataclasses):
|
|
|
42
44
|
which enables defining default parameters which can be inherited,
|
|
43
45
|
similar to subclassing.
|
|
44
46
|
|
|
45
|
-
Example:
|
|
46
47
|
>>> class ens_defaults:
|
|
47
48
|
... infl : float = 1.0
|
|
48
49
|
... rot : bool = False
|
|
@@ -55,13 +56,13 @@ def da_method(*default_dataclasses):
|
|
|
55
56
|
... def assimilate(self, HMM, xx, yy):
|
|
56
57
|
... ...
|
|
57
58
|
|
|
58
|
-
|
|
59
|
+
!!! note
|
|
59
60
|
Apart from what's listed in the above `Note`, there is nothing special to the
|
|
60
61
|
resulting `xp`. That is, just like any Python object, it can serve as a data
|
|
61
62
|
container, and you can write any number of attributes to it (at creation-time,
|
|
62
63
|
or later). For example, you can set attributes that are not used by the
|
|
63
64
|
`assimilate` method, but are instead used to customize other aspects of the
|
|
64
|
-
experiments (see `
|
|
65
|
+
experiments (see [`xp_launch.run_experiment`][]).
|
|
65
66
|
"""
|
|
66
67
|
import dataclasses
|
|
67
68
|
import functools
|
|
@@ -82,7 +83,7 @@ def da_method(*default_dataclasses):
|
|
|
82
83
|
def set_field(name, type_, val):
|
|
83
84
|
"""Set the inherited (i.e. default, i.e. has value) field."""
|
|
84
85
|
# Ensure annotations
|
|
85
|
-
cls.__annotations__ = getattr(cls,
|
|
86
|
+
cls.__annotations__ = getattr(cls, "__annotations__", {})
|
|
86
87
|
# Set annotation
|
|
87
88
|
cls.__annotations__[name] = type_
|
|
88
89
|
# Set value
|
|
@@ -102,7 +103,7 @@ def da_method(*default_dataclasses):
|
|
|
102
103
|
# Define the new assimilate method (has bells and whistles)
|
|
103
104
|
def assimilate(self, HMM, xx, yy, desc=None, fail_gently=False, **stat_kwargs):
|
|
104
105
|
# Progressbar name
|
|
105
|
-
pb_name_hook = self.da_method if desc is None else desc
|
|
106
|
+
pb_name_hook = self.da_method if desc is None else desc # noqa
|
|
106
107
|
|
|
107
108
|
# Init stats
|
|
108
109
|
self.stats = dapper.stats.Stats(self, HMM, xx, yy, **stat_kwargs)
|
|
@@ -120,7 +121,7 @@ def da_method(*default_dataclasses):
|
|
|
120
121
|
# Don't use _print_cropped_traceback here -- It would
|
|
121
122
|
# crop out errors in the DAPPER infrastructure itself.
|
|
122
123
|
raise
|
|
123
|
-
self.stat("duration", time.time()-time0)
|
|
124
|
+
self.stat("duration", time.time() - time0)
|
|
124
125
|
|
|
125
126
|
# Overwrite the assimilate method with the new one
|
|
126
127
|
try:
|
|
@@ -128,12 +129,14 @@ def da_method(*default_dataclasses):
|
|
|
128
129
|
except AttributeError as error:
|
|
129
130
|
raise AttributeError(
|
|
130
131
|
"Classes decorated by da_method()"
|
|
131
|
-
" must define a method called 'assimilate'."
|
|
132
|
+
" must define a method called 'assimilate'."
|
|
133
|
+
) from error
|
|
132
134
|
cls.assimilate = functools.wraps(_assimilate)(assimilate)
|
|
133
135
|
|
|
134
136
|
# Shortcut for register_stat
|
|
135
137
|
def stat(self, name, value):
|
|
136
138
|
dapper.stats.register_stat(self.stats, name, value)
|
|
139
|
+
|
|
137
140
|
cls.stat = stat
|
|
138
141
|
|
|
139
142
|
# Make self.__class__.__name__ an attrib.
|
|
@@ -141,6 +144,7 @@ def da_method(*default_dataclasses):
|
|
|
141
144
|
cls.da_method = cls.__name__
|
|
142
145
|
|
|
143
146
|
return cls
|
|
147
|
+
|
|
144
148
|
return dataclass_with_defaults
|
|
145
149
|
|
|
146
150
|
|
|
@@ -155,15 +159,17 @@ def _print_cropped_traceback(ERR):
|
|
|
155
159
|
msg = "Traceback (most recent call last):\n"
|
|
156
160
|
try:
|
|
157
161
|
# If in IPython, use its coloring functionality
|
|
158
|
-
__IPYTHON__ # type: ignore
|
|
162
|
+
__IPYTHON__ # type: ignore # noqa: B018
|
|
159
163
|
except (NameError, ImportError):
|
|
160
164
|
msg += "".join(traceback.format_tb(ERR.__traceback__))
|
|
161
165
|
else:
|
|
162
166
|
from IPython.core.debugger import Pdb
|
|
167
|
+
|
|
163
168
|
pdb_instance = Pdb()
|
|
164
169
|
pdb_instance.curframe = inspect.currentframe()
|
|
165
170
|
|
|
166
171
|
import dapper.da_methods
|
|
172
|
+
|
|
167
173
|
keep = False
|
|
168
174
|
for frame in traceback.walk_tb(ERR.__traceback__):
|
|
169
175
|
if keep:
|
|
@@ -175,10 +181,12 @@ def _print_cropped_traceback(ERR):
|
|
|
175
181
|
return msg
|
|
176
182
|
|
|
177
183
|
msg = crop_traceback(ERR) + "\nError message: " + str(ERR)
|
|
178
|
-
msg += (
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
184
|
+
msg += (
|
|
185
|
+
"\n\nResuming execution."
|
|
186
|
+
"\nIf instead you wish to raise the exceptions as usual,"
|
|
187
|
+
"\nwhich will halt the execution (and enable post-mortem debug),"
|
|
188
|
+
"\nthen use `fail_gently=False`"
|
|
189
|
+
)
|
|
182
190
|
print(msg, file=sys.stderr)
|
|
183
191
|
|
|
184
192
|
|