dapper 1.5.0__tar.gz → 1.6.0__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.
Files changed (159) hide show
  1. dapper-1.6.0/PKG-INFO +83 -0
  2. {dapper-1.5.0 → dapper-1.6.0}/README.md +25 -12
  3. {dapper-1.5.0 → dapper-1.6.0}/dapper/README.md +4 -4
  4. {dapper-1.5.0 → dapper-1.6.0}/dapper/__init__.py +2 -2
  5. {dapper-1.5.0 → dapper-1.6.0}/dapper/da_methods/README.md +2 -1
  6. {dapper-1.5.0 → dapper-1.6.0}/dapper/da_methods/baseline.py +6 -6
  7. {dapper-1.5.0 → dapper-1.6.0}/dapper/da_methods/ensemble.py +24 -21
  8. {dapper-1.5.0 → dapper-1.6.0}/dapper/da_methods/extended.py +8 -8
  9. {dapper-1.5.0 → dapper-1.6.0}/dapper/da_methods/other.py +9 -10
  10. {dapper-1.5.0 → dapper-1.6.0}/dapper/da_methods/particle.py +38 -32
  11. {dapper-1.5.0 → dapper-1.6.0}/dapper/da_methods/variational.py +23 -20
  12. {dapper-1.5.0 → dapper-1.6.0}/dapper/dpr_config.py +2 -4
  13. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/LA/__init__.py +5 -3
  14. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/Lorenz63/bocquet2012.py +1 -1
  15. dapper-1.6.0/dapper/mods/Lorenz63/ramgraber2022.py +37 -0
  16. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/Lorenz96/anderson2009.py +3 -3
  17. dapper-1.6.0/dapper/mods/Lorenz96/spantini2019.py +41 -0
  18. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/Lorenz96/spectral_obs.py +1 -1
  19. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/Lorenz96/todter2015_G.py +1 -1
  20. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/Lorenz96s/__init__.py +2 -1
  21. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/QG/__init__.py +2 -2
  22. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/QG/demo.py +0 -0
  23. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/QG/f90/README.md +36 -32
  24. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/QG/sakov2008.py +35 -28
  25. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/__init__.py +70 -33
  26. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/integration.py +2 -1
  27. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/utils.py +2 -2
  28. {dapper-1.5.0 → dapper-1.6.0}/dapper/stats.py +2 -5
  29. {dapper-1.5.0 → dapper-1.6.0}/dapper/tools/datafiles.py +1 -1
  30. {dapper-1.5.0 → dapper-1.6.0}/dapper/tools/liveplotting.py +72 -58
  31. {dapper-1.5.0 → dapper-1.6.0}/dapper/tools/localization.py +6 -16
  32. {dapper-1.5.0 → dapper-1.6.0}/dapper/tools/matrices.py +11 -2
  33. {dapper-1.5.0 → dapper-1.6.0}/dapper/tools/progressbar.py +7 -7
  34. {dapper-1.5.0 → dapper-1.6.0}/dapper/tools/randvars.py +14 -14
  35. {dapper-1.5.0 → dapper-1.6.0}/dapper/tools/remote/README.md +1 -1
  36. dapper-1.6.0/dapper/tools/seeding.py +29 -0
  37. dapper-1.6.0/dapper.egg-info/PKG-INFO +83 -0
  38. {dapper-1.5.0 → dapper-1.6.0}/dapper.egg-info/SOURCES.txt +3 -0
  39. {dapper-1.5.0 → dapper-1.6.0}/dapper.egg-info/requires.txt +1 -1
  40. {dapper-1.5.0 → dapper-1.6.0}/examples/basic_1.py +5 -7
  41. {dapper-1.5.0 → dapper-1.6.0}/examples/basic_2.py +2 -2
  42. {dapper-1.5.0 → dapper-1.6.0}/setup.py +1 -1
  43. {dapper-1.5.0 → dapper-1.6.0}/tests/test_HMMs.py +20 -21
  44. {dapper-1.5.0 → dapper-1.6.0}/tests/test_example_2.py +42 -37
  45. dapper-1.6.0/tests/test_rng.py +22 -0
  46. dapper-1.5.0/PKG-INFO +0 -29
  47. dapper-1.5.0/dapper/tools/seeding.py +0 -68
  48. dapper-1.5.0/dapper.egg-info/PKG-INFO +0 -29
  49. {dapper-1.5.0 → dapper-1.6.0}/LICENCE.txt +0 -0
  50. {dapper-1.5.0 → dapper-1.6.0}/dapper/da_methods/__init__.py +0 -0
  51. {dapper-1.5.0 → dapper-1.6.0}/dapper/dpr_config.yaml +0 -0
  52. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/DoublePendulum/__init__.py +0 -0
  53. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/DoublePendulum/demo.py +0 -0
  54. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/DoublePendulum/settings101.py +0 -0
  55. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/Id/__init__.py +0 -0
  56. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/Ikeda/__init__.py +0 -0
  57. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/Ikeda/demo.py +0 -0
  58. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/Ikeda/some_settings_01.py +0 -0
  59. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/KS/__init__.py +0 -0
  60. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/KS/bocquet2019.py +0 -0
  61. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/KS/compare_schemes.py +0 -0
  62. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/KS/demo.py +0 -0
  63. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/LA/demo.py +0 -0
  64. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/LA/evensen2009.py +0 -0
  65. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/LA/raanes2015.py +0 -0
  66. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/LA/small.py +0 -0
  67. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/Lorenz05/__init__.py +0 -0
  68. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/Lorenz05/demo.py +0 -0
  69. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/Lorenz05/settings01.py +0 -0
  70. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/Lorenz63/__init__.py +0 -0
  71. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/Lorenz63/anderson2010rhf.py +0 -0
  72. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/Lorenz63/demo.py +0 -0
  73. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/Lorenz63/extras.py +0 -0
  74. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/Lorenz63/mandel2016.py +0 -0
  75. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/Lorenz63/sakov2012.py +0 -0
  76. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/Lorenz63/wiljes2017.py +0 -0
  77. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/Lorenz84/__init__.py +0 -0
  78. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/Lorenz84/demo.py +0 -0
  79. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/Lorenz84/harder.py +0 -0
  80. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/Lorenz84/pajonk2012.py +0 -0
  81. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/Lorenz96/__init__.py +0 -0
  82. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/Lorenz96/bocquet2010.py +0 -0
  83. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/Lorenz96/bocquet2010_m40.py +0 -0
  84. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/Lorenz96/bocquet2015loc.py +0 -0
  85. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/Lorenz96/demo.py +0 -0
  86. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/Lorenz96/extras.py +0 -0
  87. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/Lorenz96/frei2013bridging.py +0 -0
  88. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/Lorenz96/hoteit2015.py +0 -0
  89. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/Lorenz96/miyoshi2011.py +0 -0
  90. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/Lorenz96/pinheiro2019.py +0 -0
  91. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/Lorenz96/raanes2016.py +0 -0
  92. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/Lorenz96/sakov2008.py +0 -0
  93. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/Lorenz96/todter2015.py +0 -0
  94. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/Lorenz96s/grudzien2020.py +0 -0
  95. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/LorenzUV/__init__.py +0 -0
  96. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/LorenzUV/demo.py +0 -0
  97. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/LorenzUV/illust_LorenzUV.py +0 -0
  98. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/LorenzUV/illust_parameterizations.py +0 -0
  99. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/LorenzUV/lorenz96.py +0 -0
  100. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/LorenzUV/wilks05.py +0 -0
  101. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/LotkaVolterra/__init__.py +0 -0
  102. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/LotkaVolterra/demo.py +0 -0
  103. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/LotkaVolterra/settings101.py +0 -0
  104. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/QG/counillon2009.py +0 -0
  105. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/QG/f90/Makefile +0 -0
  106. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/QG/f90/__init__.py +0 -0
  107. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/QG/f90/calc.f90 +0 -0
  108. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/QG/f90/data.f90 +0 -0
  109. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/QG/f90/helmholtz.f90 +0 -0
  110. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/QG/f90/interface.f90 +0 -0
  111. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/QG/f90/nfw.f90 +0 -0
  112. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/QG/f90/parameters.f90 +0 -0
  113. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/QG/f90/prms_cou09_ens.txt +0 -0
  114. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/QG/f90/prms_cou09_truth.txt +0 -0
  115. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/QG/f90/prms_counillon2009_ens.txt +0 -0
  116. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/QG/f90/prms_counillon2009_truth.txt +0 -0
  117. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/QG/f90/prms_sak08.txt +0 -0
  118. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/QG/f90/prms_sakov2008.txt +0 -0
  119. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/QG/f90/prms_sample_generation.txt +0 -0
  120. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/QG/f90/prms_test_model.txt +0 -0
  121. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/QG/f90/qg.f90 +0 -0
  122. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/QG/f90/qgflux.f90 +0 -0
  123. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/QG/f90/qgstep.f90 +0 -0
  124. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/QG/f90/utils.f90 +0 -0
  125. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/QG/governing_eqn.png +0 -0
  126. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/QG/illust_obs.py +0 -0
  127. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/README.md +0 -0
  128. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/VL20/__init__.py +0 -0
  129. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/VL20/demo.py +0 -0
  130. {dapper-1.5.0 → dapper-1.6.0}/dapper/mods/explore_props.py +0 -0
  131. {dapper-1.5.0 → dapper-1.6.0}/dapper/tools/__init__.py +0 -0
  132. {dapper-1.5.0 → dapper-1.6.0}/dapper/tools/chronos.py +0 -0
  133. {dapper-1.5.0 → dapper-1.6.0}/dapper/tools/colors.py +0 -0
  134. {dapper-1.5.0 → dapper-1.6.0}/dapper/tools/linalg.py +0 -0
  135. {dapper-1.5.0 → dapper-1.6.0}/dapper/tools/multiproc.py +0 -0
  136. {dapper-1.5.0 → dapper-1.6.0}/dapper/tools/remote/__init__.py +0 -0
  137. {dapper-1.5.0 → dapper-1.6.0}/dapper/tools/remote/autoscaler.py +0 -0
  138. {dapper-1.5.0 → dapper-1.6.0}/dapper/tools/remote/uplink.py +0 -0
  139. {dapper-1.5.0 → dapper-1.6.0}/dapper/tools/rounding.py +0 -0
  140. {dapper-1.5.0 → dapper-1.6.0}/dapper/tools/series.py +0 -0
  141. {dapper-1.5.0 → dapper-1.6.0}/dapper/tools/viz.py +0 -0
  142. {dapper-1.5.0 → dapper-1.6.0}/dapper/xp_launch.py +0 -0
  143. {dapper-1.5.0 → dapper-1.6.0}/dapper/xp_process.py +0 -0
  144. {dapper-1.5.0 → dapper-1.6.0}/dapper.egg-info/dependency_links.txt +0 -0
  145. {dapper-1.5.0 → dapper-1.6.0}/dapper.egg-info/top_level.txt +0 -0
  146. {dapper-1.5.0 → dapper-1.6.0}/pyproject.toml +0 -0
  147. {dapper-1.5.0 → dapper-1.6.0}/setup.cfg +0 -0
  148. {dapper-1.5.0 → dapper-1.6.0}/tests/__init__.py +0 -0
  149. {dapper-1.5.0 → dapper-1.6.0}/tests/test_TLMs.py +0 -0
  150. {dapper-1.5.0 → dapper-1.6.0}/tests/test_data.py +0 -0
  151. {dapper-1.5.0 → dapper-1.6.0}/tests/test_demos.py +0 -0
  152. {dapper-1.5.0 → dapper-1.6.0}/tests/test_iEnKS.py +0 -0
  153. {dapper-1.5.0 → dapper-1.6.0}/tests/test_localization.py +0 -0
  154. {dapper-1.5.0 → dapper-1.6.0}/tests/test_matrices.py +0 -0
  155. {dapper-1.5.0 → dapper-1.6.0}/tests/test_operator.py +0 -0
  156. {dapper-1.5.0 → dapper-1.6.0}/tests/test_plotting.py +0 -0
  157. {dapper-1.5.0 → dapper-1.6.0}/tests/test_printing.py +0 -0
  158. {dapper-1.5.0 → dapper-1.6.0}/tests/test_randvars.py +0 -0
  159. {dapper-1.5.0 → dapper-1.6.0}/tests/test_round2.py +0 -0
dapper-1.6.0/PKG-INFO ADDED
@@ -0,0 +1,83 @@
1
+ Metadata-Version: 2.1
2
+ Name: dapper
3
+ Version: 1.6.0
4
+ Summary: DAPPER benchmarks the performance of data assimilation (DA) methods.
5
+ Author: Patrick N. Raanes
6
+ Author-email: patrick.n.raanes@gmail.com
7
+ Project-URL: Documentation, https://nansencenter.github.io/DAPPER/
8
+ Project-URL: Source, https://github.com/nansencenter/DAPPER
9
+ Project-URL: Tracker, https://github.com/nansencenter/DAPPER/issues
10
+ Keywords: data-assimilation enkf kalman-filtering state-estimation particle-filter kalman bayesian-methods bayesian-filter chaos
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Intended Audience :: Science/Research
13
+ Classifier: Topic :: Scientific/Engineering :: Mathematics
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Operating System :: OS Independent
17
+ Requires-Python: >=3.9
18
+ Description-Content-Type: text/markdown
19
+ License-File: LICENCE.txt
20
+ Requires-Dist: scipy>=1.10
21
+ Requires-Dist: jupyter
22
+ Requires-Dist: ipdb
23
+ Requires-Dist: ipython>=5.1
24
+ Requires-Dist: tornado~=6.3.2
25
+ Requires-Dist: matplotlib~=3.7
26
+ Requires-Dist: mpl-tools==0.2.50
27
+ Requires-Dist: tqdm~=4.31
28
+ Requires-Dist: pyyaml
29
+ Requires-Dist: colorama~=0.4.1
30
+ Requires-Dist: tabulate~=0.8.3
31
+ Requires-Dist: dill==0.3.2
32
+ Requires-Dist: patlib==0.3.5
33
+ Requires-Dist: struct-tools==0.2.5
34
+ Requires-Dist: multiprocessing-on-dill==3.5.0a4
35
+ Requires-Dist: threadpoolctl<4.0.0,>=3.0.0
36
+ Provides-Extra: qt
37
+ Requires-Dist: PyQt5; extra == "qt"
38
+ Requires-Dist: qtpy; extra == "qt"
39
+ Provides-Extra: debug
40
+ Requires-Dist: line_profiler; extra == "debug"
41
+ Requires-Dist: pre-commit; extra == "debug"
42
+ Requires-Dist: pdbpp>=0.10.3; extra == "debug"
43
+ Provides-Extra: test
44
+ Requires-Dist: tox; extra == "test"
45
+ Requires-Dist: coverage>=5.1; extra == "test"
46
+ Requires-Dist: pytest; extra == "test"
47
+ Requires-Dist: pytest-cov; extra == "test"
48
+ Requires-Dist: pytest-sugar; extra == "test"
49
+ Requires-Dist: pytest-benchmark; extra == "test"
50
+ Requires-Dist: pytest-clarity; extra == "test"
51
+ Requires-Dist: pytest-xdist; extra == "test"
52
+ Requires-Dist: pytest-timeout; extra == "test"
53
+ Provides-Extra: lint
54
+ Requires-Dist: flake8<5; extra == "lint"
55
+ Requires-Dist: flakeheaven; extra == "lint"
56
+ Requires-Dist: autopep8; extra == "lint"
57
+ Provides-Extra: build
58
+ Requires-Dist: twine; extra == "build"
59
+ Requires-Dist: pdoc; extra == "build"
60
+ Requires-Dist: jupytext; extra == "build"
61
+ Provides-Extra: dev
62
+ Requires-Dist: line_profiler; extra == "dev"
63
+ Requires-Dist: pre-commit; extra == "dev"
64
+ Requires-Dist: pdbpp>=0.10.3; extra == "dev"
65
+ Requires-Dist: tox; extra == "dev"
66
+ Requires-Dist: coverage>=5.1; extra == "dev"
67
+ Requires-Dist: pytest; extra == "dev"
68
+ Requires-Dist: pytest-cov; extra == "dev"
69
+ Requires-Dist: pytest-sugar; extra == "dev"
70
+ Requires-Dist: pytest-benchmark; extra == "dev"
71
+ Requires-Dist: pytest-clarity; extra == "dev"
72
+ Requires-Dist: pytest-xdist; extra == "dev"
73
+ Requires-Dist: pytest-timeout; extra == "dev"
74
+ Requires-Dist: flake8<5; extra == "dev"
75
+ Requires-Dist: flakeheaven; extra == "dev"
76
+ Requires-Dist: autopep8; extra == "dev"
77
+ Requires-Dist: twine; extra == "dev"
78
+ Requires-Dist: pdoc; extra == "dev"
79
+ Requires-Dist: jupytext; extra == "dev"
80
+
81
+ It is usually best to install from source (github),
82
+ so that you the code is readily available to play with.
83
+ See full README on [github](https://github.com/nansencenter/DAPPER).
@@ -10,10 +10,8 @@
10
10
 
11
11
  <img src="/docs/imgs/logo_wtxt.png" align="left" width="250"/>
12
12
 
13
- DAPPER is a set of templates for **benchmarking** the performance of
14
- **data assimilation** (DA) methods.
15
- The tests provide experimental support and guidance for
16
- new developments in DA.
13
+ DAPPER is a set of templates for **benchmarking** the performance of **data assimilation** (DA) methods.
14
+ The numerical experiments provide support and guidance for new developments in DA.
17
15
  The typical set-up is a **synthetic (twin) experiment**, where you
18
16
  specify a dynamic model and an observational model,
19
17
  and use these to generate a synthetic truth (multivariate time series),
@@ -38,8 +36,8 @@ The [documentation](https://nansencenter.github.io/DAPPER)
38
36
  includes general guidelines and the API,
39
37
  but for any serious use you will want to read and adapt the code yourself.
40
38
  If you use it in a publication, please cite, e.g.,
41
- *The experiments used (inspiration from) DAPPER [ref], version 1.2.1*,
42
- where [ref] points to [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.2029296.svg)](https://doi.org/10.5281/zenodo.2029296).
39
+ *The experiments used (inspiration from) DAPPER [ref], version 1.6.0*,
40
+ where [ref] points to [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.10710355.svg)](https://doi.org/10.5281/zenodo.10710355).
43
41
  Lastly, for an introduction to DA theory also using Python,
44
42
  see these [tutorials](https://github.com/nansencenter/DA-tutorials).
45
43
 
@@ -128,7 +126,7 @@ Ensure the printed version is 3.9 or more.
128
126
  - If the script comes with a `requirements.txt` file, then do
129
127
  `pip install -r path/to/requirements.txt`.
130
128
  - If not, hopefully you know the version of DAPPER needed. Run
131
- `pip install dapper==1.0.0` to get version `1.2.3` (as an example).
129
+ `pip install dapper==1.5.1` to get version `1.5.1` (as an example).
132
130
 
133
131
  #### *Finally*: Test the installation
134
132
 
@@ -233,9 +231,7 @@ DAPPER is aimed at research and teaching (see discussion up top).
233
231
  Example of limitations:
234
232
 
235
233
  - It is not suited for very big models (>60k unknowns).
236
- - Time-dependent error covariances and changes in lengths of state/obs
237
- (although the `Dyn` and `Obs` models may otherwise be time-dependent).
238
- - Non-uniform time sequences not fully supported.
234
+ - Non-uniform time sequences.
239
235
 
240
236
  The scope of DAPPER is restricted because
241
237
 
@@ -321,7 +317,24 @@ in the development of DAPPER.
321
317
  [26]: https://github.com/CliMA/EnsembleKalmanProcesses.jl
322
318
 
323
319
 
324
- ## Contributors
320
+ ## Contributing
321
+
322
+ ### Issues and Pull requests
323
+
324
+ Do not hesitate to open an issue, whether to report a problem or ask a question.
325
+ It may take some time for us to get back to you,
326
+ since DAPPER is primarily a volunteer effort.
327
+ Please start by perusing the [documentation](https://nansencenter.github.io/DAPPER/dapper.html)
328
+ and searching the issue tracker for similar items.
329
+
330
+ Pull requests are very welcome.
331
+ Examples: adding a new DA method, dynamical models,
332
+ experimental configuration reproducing literature results,
333
+ or improving the features and capabilities of DAPPER.
334
+ Please keep in mind the intentional [limitations](https://github.com/nansencenter/DAPPER#similar-projects)
335
+ and read the [developers guidelines](https://nansencenter.github.io/DAPPER/dev_guide).
336
+
337
+ ### Contributors
325
338
 
326
339
  Patrick N. Raanes,
327
340
  Yumeng Chen,
@@ -345,7 +358,7 @@ and the Center for Western Weather and Water Extremes (CW3E).
345
358
  <img src="./docs/imgs/CW3E-Logo-Horizontal-FullColor.png?raw=true" width="400">
346
359
  <!-- markdownlint-restore -->
347
360
 
348
- ## Publication list
361
+ ## Publications
349
362
 
350
363
  - [Combining data assimilation and machine learning to emulate a dynamical model from sparse and noisy observations: A case study with the Lorenz 96 model](https://doi.org/10.1016/j.jocs.2020.101171)
351
364
  - [Adaptive covariance inflation in the ensemble Kalman filter by Gaussian scale mixtures](https://doi.org/10.1002/qj.3386)
@@ -5,11 +5,11 @@ the docs for the various modules.
5
5
 
6
6
  ## Installation
7
7
 
8
- See [README/Installation](https://github.com/nansencenter/DAPPER#Installation)
8
+ See [README/Installation](https://github.com/nansencenter/DAPPER#installation)
9
9
 
10
10
  ## Usage
11
11
 
12
- See [README/Getting-started](https://github.com/nansencenter/DAPPER#Getting-started)
12
+ See [README/Getting-started](https://github.com/nansencenter/DAPPER#getting-started)
13
13
 
14
14
  ##### Examples
15
15
 
@@ -26,8 +26,8 @@ your own **model** or **method**, then
26
26
  rather than trying to squeeze everything into its templates.
27
27
  - If it is relatively simple, however, you may well want to use DAPPER.
28
28
  In that case, read this:
29
- - `mods`
30
- - `da_methods`
29
+ - `dapper.mods`
30
+ - `dapper.da_methods`
31
31
 
32
32
  Since the generality of DAPPER is
33
33
  [limited](https://github.com/nansencenter/DAPPER#similar-projects)
@@ -4,12 +4,12 @@
4
4
  .. include:: ./README.md
5
5
  """
6
6
 
7
- __version__ = "1.5.0"
7
+ __version__ = "1.6.0"
8
8
 
9
9
  # A parsimonious list of imports used in the examples
10
10
  from .dpr_config import rc
11
11
  from .tools.datafiles import find_latest_run, load_xps
12
12
  from .tools.rounding import round2sigfig
13
- from .tools.seeding import set_seed
13
+ from .tools.seeding import rng, set_seed
14
14
  from .xp_launch import combinator, seed_and_simulate, xpList
15
15
  from .xp_process import xpSpace
@@ -1,5 +1,6 @@
1
- See the README section on
1
+ Also see the section on
2
2
  [DA Methods](https://github.com/nansencenter/DAPPER#DA-Methods)
3
+ in the main README
3
4
  for an overview of the methods included with DAPPER.
4
5
 
5
6
  ## Defining your own method
@@ -68,9 +68,9 @@ class OptInterp:
68
68
  self.stats.assess(k, ko, 'f', mu=muC, Cov=PC)
69
69
 
70
70
  # Analysis
71
- H = HMM.Obs.linear(muC, t)
72
- KG = mrdiv(PC@H.T, H@PC@H.T + HMM.Obs.noise.C.full)
73
- mu = muC + KG@(yy[ko] - HMM.Obs(muC, t))
71
+ H = HMM.Obs(ko).linear(muC)
72
+ KG = mrdiv(PC@H.T, H@PC@H.T + HMM.Obs(ko).noise.C.full)
73
+ mu = muC + KG@(yy[ko] - HMM.Obs(ko)(muC))
74
74
 
75
75
  P = (Id - KG@H) @ PC
76
76
  SM = fit_sigmoid(P.trace()/PC.trace(), L, k)
@@ -123,9 +123,9 @@ class Var3D:
123
123
  self.stats.assess(k, ko, 'f', mu=mu, Cov=P)
124
124
 
125
125
  # Analysis
126
- H = HMM.Obs.linear(mu, t)
127
- KG = mrdiv(B@H.T, H@B@H.T + HMM.Obs.noise.C.full)
128
- mu = mu + KG@(yy[ko] - HMM.Obs(mu, t))
126
+ H = HMM.Obs(ko).linear(mu)
127
+ KG = mrdiv(B@H.T, H@B@H.T + HMM.Obs(ko).noise.C.full)
128
+ mu = mu + KG@(yy[ko] - HMM.Obs(ko)(mu))
129
129
 
130
130
  # Re-calibrate fit_sigmoid with new W0 = Pa/B
131
131
  P = (Id - KG@H) @ B
@@ -1,7 +1,6 @@
1
1
  """The EnKF and other ensemble-based methods."""
2
2
 
3
3
  import numpy as np
4
- import numpy.random as rnd
5
4
  import scipy.linalg as sla
6
5
  from numpy import diag, eye, sqrt, zeros
7
6
 
@@ -11,6 +10,7 @@ from dapper.tools.linalg import mldiv, mrdiv, pad0, svd0, svdi, tinv, tsvd
11
10
  from dapper.tools.matrices import funm_psd, genOG_1
12
11
  from dapper.tools.progressbar import progbar
13
12
  from dapper.tools.randvars import GaussRV
13
+ from dapper.tools.seeding import rng
14
14
 
15
15
  from . import da_method
16
16
 
@@ -47,7 +47,7 @@ class EnKF:
47
47
  # Analysis update
48
48
  if ko is not None:
49
49
  self.stats.assess(k, ko, 'f', E=E)
50
- E = EnKF_analysis(E, HMM.Obs(E, t), HMM.Obs.noise, yy[ko],
50
+ E = EnKF_analysis(E, HMM.Obs(ko)(E), HMM.Obs(ko).noise, yy[ko],
51
51
  self.upd_a, self.stats, ko)
52
52
  E = post_process(E, self.infl, self.rot)
53
53
 
@@ -161,10 +161,10 @@ def EnKF_analysis(E, Eo, hnoise, y, upd_a, stats=None, ko=None):
161
161
  v = v - mult[0]*Yj # noqa
162
162
  v /= sqrt(v@v)
163
163
  Zj = v*sqrt(N1) # Standardized perturbation along v
164
- Zj *= np.sign(rnd.rand()-0.5) # Random sign
164
+ Zj *= np.sign(rng.standard_normal() - 0.5) # Random sign
165
165
  else:
166
166
  # The usual stochastic perturbations.
167
- Zj = mean0(rnd.randn(N)) # Un-coloured noise
167
+ Zj = mean0(rng.standard_normal(N)) # Un-coloured noise
168
168
  if 'Var1' in upd_a:
169
169
  Zj *= sqrt(N/(Zj@Zj))
170
170
 
@@ -319,7 +319,7 @@ def add_noise(E, dt, noise, method):
319
319
  E, _, Qa12 = sqrt_core()
320
320
  if N <= Nx:
321
321
  Z = Q12 - A.T@Qa12
322
- E += sqrt(dt)*(Z@rnd.randn(Z.shape[1], N)).T
322
+ E += sqrt(dt)*(Z@rng.standard_normal((Z.shape[1], N))).T
323
323
 
324
324
  elif method == 'Sqrt-Dep':
325
325
  E, T, Qa12 = sqrt_core()
@@ -334,7 +334,7 @@ def add_noise(E, dt, noise, method):
334
334
  Z = Q12 - Q_hat12
335
335
  D_hat = A.T@(T-eye(N))
336
336
  Xi_hat = Q_hat12_inv @ D_hat
337
- Xi_til = (eye(rQ) - Q_hat12_proj)@rnd.randn(rQ, N)
337
+ Xi_til = (eye(rQ) - Q_hat12_proj)@rng.standard_normal((rQ, N))
338
338
  D_til = Z@(Xi_hat + sqrt(dt)*Xi_til)
339
339
  E += D_til.T
340
340
 
@@ -382,7 +382,7 @@ class EnKS:
382
382
  if ko is not None:
383
383
  self.stats.assess(k, ko, 'f', E=E[k])
384
384
 
385
- Eo = HMM.Obs(E[k], t)
385
+ Eo = HMM.Obs(ko)(E[k])
386
386
  y = yy[ko]
387
387
 
388
388
  # Inds within Lag
@@ -391,7 +391,7 @@ class EnKS:
391
391
  EE = E[kk]
392
392
 
393
393
  EE = self.reshape_to(EE)
394
- EE = EnKF_analysis(EE, Eo, HMM.Obs.noise, y,
394
+ EE = EnKF_analysis(EE, Eo, HMM.Obs(ko).noise, y,
395
395
  self.upd_a, self.stats, ko)
396
396
  E[kk] = self.reshape_fr(EE, HMM.Dyn.M)
397
397
  E[k] = post_process(E[k], self.infl, self.rot)
@@ -427,9 +427,9 @@ class EnRTS:
427
427
 
428
428
  if ko is not None:
429
429
  self.stats.assess(k, ko, 'f', E=E[k])
430
- Eo = HMM.Obs(E[k], t)
430
+ Eo = HMM.Obs(ko)(E[k])
431
431
  y = yy[ko]
432
- E[k] = EnKF_analysis(E[k], Eo, HMM.Obs.noise, y,
432
+ E[k] = EnKF_analysis(E[k], Eo, HMM.Obs(ko).noise, y,
433
433
  self.upd_a, self.stats, ko)
434
434
  E[k] = post_process(E[k], self.infl, self.rot)
435
435
  self.stats.assess(k, ko, 'a', E=E[k])
@@ -468,7 +468,7 @@ def serial_inds(upd_a, y, cvR, A):
468
468
  dC = np.sum(A*A, 0)/(N-1)
469
469
  inds = np.argsort(dC)
470
470
  else: # Default: random ordering
471
- inds = rnd.permutation(len(y))
471
+ inds = rng.permutation(len(y))
472
472
  return inds
473
473
 
474
474
 
@@ -492,8 +492,6 @@ class SL_EAKF:
492
492
 
493
493
  def assimilate(self, HMM, xx, yy):
494
494
  N1 = self.N-1
495
- R = HMM.Obs.noise
496
- Rm12 = HMM.Obs.noise.C.sym_sqrt_inv
497
495
 
498
496
  E = HMM.X0.sample(self.N)
499
497
  self.stats.assess(0, E=E)
@@ -504,14 +502,17 @@ class SL_EAKF:
504
502
 
505
503
  if ko is not None:
506
504
  self.stats.assess(k, ko, 'f', E=E)
505
+ Obs = HMM.Obs(ko)
506
+ R = Obs.noise
507
507
  y = yy[ko]
508
508
  inds = serial_inds(self.ordr, y, R, center(E)[0])
509
+ Rm12 = Obs.noise.C.sym_sqrt_inv
509
510
 
510
- state_taperer = HMM.Obs.localizer(self.loc_rad, 'y2x', t, self.taper)
511
+ state_taperer = Obs.localizer(self.loc_rad, 'y2x', self.taper)
511
512
  for j in inds:
512
513
  # Prep:
513
514
  # ------------------------------------------------------
514
- Eo = HMM.Obs(E, t)
515
+ Eo = Obs(E)
515
516
  xo = np.mean(Eo, 0)
516
517
  Y = Eo - xo
517
518
  mu = np.mean(E, 0)
@@ -632,8 +633,9 @@ class LETKF:
632
633
 
633
634
  if ko is not None:
634
635
  self.stats.assess(k, ko, 'f', E=E)
635
- batch, taper = HMM.Obs.localizer(self.loc_rad, 'x2y', t, self.taper)
636
- E, stats = local_analyses(E, HMM.Obs(E, t), HMM.Obs.noise.C, yy[ko],
636
+ Obs = HMM.Obs(ko)
637
+ batch, taper = Obs.localizer(self.loc_rad, 'x2y', self.taper)
638
+ E, stats = local_analyses(E, Obs(E), Obs.noise.C, yy[ko],
637
639
  batch, taper, pool.map, self.xN, self.g)
638
640
  self.stats.write(stats, k, ko, "a")
639
641
  E = post_process(E, self.infl, self.rot)
@@ -851,7 +853,7 @@ class EnKF_N:
851
853
  g: int = 0
852
854
 
853
855
  def assimilate(self, HMM, xx, yy):
854
- R, N, N1 = HMM.Obs.noise.C, self.N, self.N-1
856
+ N, N1 = self.N, self.N-1
855
857
 
856
858
  # Init
857
859
  E = HMM.X0.sample(N)
@@ -866,7 +868,7 @@ class EnKF_N:
866
868
  # Analysis
867
869
  if ko is not None:
868
870
  self.stats.assess(k, ko, 'f', E=E)
869
- Eo = HMM.Obs(E, t)
871
+ Eo = HMM.Obs(ko)(E)
870
872
  y = yy[ko]
871
873
 
872
874
  mu = np.mean(E, 0)
@@ -876,6 +878,7 @@ class EnKF_N:
876
878
  Y = Eo-xo
877
879
  dy = y - xo
878
880
 
881
+ R = HMM.Obs(ko).noise.C
879
882
  V, s, UT = svd0(Y @ R.sym_sqrt_inv.T)
880
883
  du = UT @ (dy @ R.sym_sqrt_inv.T)
881
884
  def dgn_N(l1): return pad0((l1*s)**2, N) + N1
@@ -887,7 +890,7 @@ class EnKF_N:
887
890
 
888
891
  if self.dual:
889
892
  # Make dual cost function (in terms of l1)
890
- def pad_rk(arr): return pad0(arr, min(N, HMM.Obs.M))
893
+ def pad_rk(arr): return pad0(arr, min(N, len(y)))
891
894
  def dgn_rk(l1): return pad_rk((l1*s)**2) + N1
892
895
 
893
896
  def J(l1):
@@ -962,6 +965,6 @@ class EnKF_N:
962
965
  E = post_process(E, self.infl, self.rot)
963
966
 
964
967
  self.stats.infl[ko] = l1
965
- self.stats.trHK[ko] = (((l1*s)**2 + N1)**(-1.0)*s**2).sum()/HMM.Ny
968
+ self.stats.trHK[ko] = (((l1*s)**2 + N1)**(-1.0)*s**2).sum()/len(y)
966
969
 
967
970
  self.stats.assess(k, ko, E=E)
@@ -25,7 +25,6 @@ class ExtKF:
25
25
  infl: float = 1.0
26
26
 
27
27
  def assimilate(self, HMM, xx, yy):
28
- R = HMM.Obs.noise.C.full
29
28
  Q = 0 if HMM.Dyn.noise.C == 0 else HMM.Dyn.noise.C.full
30
29
 
31
30
  mu = HMM.X0.mu
@@ -44,10 +43,11 @@ class ExtKF:
44
43
 
45
44
  if ko is not None:
46
45
  self.stats.assess(k, ko, 'f', mu=mu, Cov=P)
47
- H = HMM.Obs.linear(mu, t)
48
- KG = mrdiv(P @ H.T, H@P@H.T + R)
46
+ Obs = HMM.Obs(ko)
47
+ H = Obs.linear(mu)
48
+ KG = mrdiv(P @ H.T, H@P@H.T + Obs.noise.C.full)
49
49
  y = yy[ko]
50
- mu = mu + KG@(y - HMM.Obs(mu, t))
50
+ mu = mu + KG@(y - Obs(mu))
51
51
  KH = KG@H
52
52
  P = (np.eye(HMM.Dyn.M) - KH) @ P
53
53
 
@@ -67,7 +67,6 @@ class ExtRTS:
67
67
  def assimilate(self, HMM, xx, yy):
68
68
  Nx = HMM.Dyn.M
69
69
 
70
- R = HMM.Obs.noise.C.full
71
70
  Q = 0 if HMM.Dyn.noise.C == 0 else HMM.Dyn.noise.C.full
72
71
 
73
72
  mu = np.zeros((HMM.tseq.K+1, Nx))
@@ -96,10 +95,11 @@ class ExtRTS:
96
95
 
97
96
  if ko is not None:
98
97
  self.stats.assess(k, ko, 'f', mu=mu[k], Cov=P[k])
99
- H = HMM.Obs.linear(mu[k], t)
100
- KG = mrdiv(P[k] @ H.T, H@P[k]@H.T + R)
98
+ Obs = HMM.Obs(ko)
99
+ H = Obs.linear(mu[k])
100
+ KG = mrdiv(P[k] @ H.T, H@P[k]@H.T + Obs.noise.C.full)
101
101
  y = yy[ko]
102
- mu[k] = mu[k] + KG@(y - HMM.Obs(mu[k], t))
102
+ mu[k] = mu[k] + KG@(y - Obs(mu[k]))
103
103
  KH = KG@H
104
104
  P[k] = (np.eye(Nx) - KH) @ P[k]
105
105
  self.stats.assess(k, ko, 'a', mu=mu[k], Cov=P[k])
@@ -31,9 +31,6 @@ class RHF:
31
31
  step = 1/N
32
32
  cdf_grid = np.linspace(step/2, 1-step/2, N)
33
33
 
34
- R = Obs.noise
35
- Rm12 = Obs.noise.C.sym_sqrt_inv
36
-
37
34
  E = X0.sample(N)
38
35
  stats.assess(0, E=E)
39
36
 
@@ -43,11 +40,13 @@ class RHF:
43
40
 
44
41
  if ko is not None:
45
42
  stats.assess(k, ko, 'f', E=E)
43
+ Obs = HMM.Obs(ko)
44
+ Rm12 = Obs.noise.C.sym_sqrt_inv
46
45
  y = yy[ko]
47
- inds = serial_inds(self.ordr, y, R, center(E)[0])
46
+ inds = serial_inds(self.ordr, y, Obs.noise.C, center(E)[0])
48
47
 
49
48
  for _, j in enumerate(inds):
50
- Eo = Obs(E, t)
49
+ Eo = Obs(E)
51
50
  xo = np.mean(Eo, 0)
52
51
  Y = Eo - xo
53
52
  mu = np.mean(E, 0)
@@ -92,8 +91,7 @@ class LNETF:
92
91
  Rs: float = 1.0
93
92
 
94
93
  def assimilate(self, HMM, xx, yy):
95
- Dyn, Obs, tseq, X0, stats = HMM.Dyn, HMM.Obs, HMM.tseq, HMM.X0, self.stats
96
- Rm12 = Obs.noise.C.sym_sqrt_inv
94
+ Dyn, tseq, X0, stats = HMM.Dyn, HMM.tseq, HMM.X0, self.stats
97
95
 
98
96
  E = X0.sample(self.N)
99
97
  stats.assess(0, E=E)
@@ -107,10 +105,11 @@ class LNETF:
107
105
  mu = np.mean(E, 0)
108
106
  A = E - mu
109
107
 
110
- Eo = Obs(E, t)
108
+ Obs = HMM.Obs(ko)
109
+ Eo = Obs(E)
111
110
  xo = np.mean(Eo, 0)
112
- YR = (Eo-xo) @ Rm12.T
113
- yR = (yy[ko] - xo) @ Rm12.T
111
+ YR = (Eo-xo) @ Obs.noise.C.sym_sqrt_inv.T
112
+ yR = (yy[ko] - xo) @ Obs.noise.C.sym_sqrt_inv.T
114
113
 
115
114
  state_batches, obs_taperer = Obs.localizer(
116
115
  self.loc_rad, 'x2y', t, self.taper)