openghg_inversions 0.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 (76) hide show
  1. openghg_inversions-0.6.0/LICENSE +21 -0
  2. openghg_inversions-0.6.0/PKG-INFO +377 -0
  3. openghg_inversions-0.6.0/README.md +326 -0
  4. openghg_inversions-0.6.0/docs/conf.py +82 -0
  5. openghg_inversions-0.6.0/openghg_inversions/__init__.py +0 -0
  6. openghg_inversions-0.6.0/openghg_inversions/array_ops.py +161 -0
  7. openghg_inversions-0.6.0/openghg_inversions/basis/__init__.py +11 -0
  8. openghg_inversions-0.6.0/openghg_inversions/basis/_functions.py +398 -0
  9. openghg_inversions-0.6.0/openghg_inversions/basis/_helpers.py +160 -0
  10. openghg_inversions-0.6.0/openghg_inversions/basis/_wrapper.py +190 -0
  11. openghg_inversions-0.6.0/openghg_inversions/basis/algorithms/__init__.py +5 -0
  12. openghg_inversions-0.6.0/openghg_inversions/basis/algorithms/_quadtree.py +161 -0
  13. openghg_inversions-0.6.0/openghg_inversions/basis/algorithms/_weighted.py +235 -0
  14. openghg_inversions-0.6.0/openghg_inversions/basis/algorithms/country-EUROPE-UKMO-landsea-2023.nc +0 -0
  15. openghg_inversions-0.6.0/openghg_inversions/basis/algorithms/country-land-sea_EASTASIA.nc +0 -0
  16. openghg_inversions-0.6.0/openghg_inversions/basis/outer_region_definition_EASTASIA.nc +0 -0
  17. openghg_inversions-0.6.0/openghg_inversions/basis/outer_region_definition_EUROPE.nc +0 -0
  18. openghg_inversions-0.6.0/openghg_inversions/config/__init__.py +0 -0
  19. openghg_inversions-0.6.0/openghg_inversions/config/config.py +764 -0
  20. openghg_inversions-0.6.0/openghg_inversions/config/paths.py +59 -0
  21. openghg_inversions-0.6.0/openghg_inversions/config/version.py +43 -0
  22. openghg_inversions-0.6.0/openghg_inversions/convert.py +64 -0
  23. openghg_inversions-0.6.0/openghg_inversions/filters.py +433 -0
  24. openghg_inversions-0.6.0/openghg_inversions/hbmcmc/__init__.py +0 -0
  25. openghg_inversions-0.6.0/openghg_inversions/hbmcmc/components.py +34 -0
  26. openghg_inversions-0.6.0/openghg_inversions/hbmcmc/config/openghg_hbmcmc_input_satellite_template.ini +205 -0
  27. openghg_inversions-0.6.0/openghg_inversions/hbmcmc/config/openghg_hbmcmc_input_template.ini +224 -0
  28. openghg_inversions-0.6.0/openghg_inversions/hbmcmc/config/openghg_hbmcmc_input_template_example.ini +199 -0
  29. openghg_inversions-0.6.0/openghg_inversions/hbmcmc/hbmcmc.py +866 -0
  30. openghg_inversions-0.6.0/openghg_inversions/hbmcmc/hbmcmc_output.py +142 -0
  31. openghg_inversions-0.6.0/openghg_inversions/hbmcmc/hbmcmc_post_process.py +1552 -0
  32. openghg_inversions-0.6.0/openghg_inversions/hbmcmc/inversion_pymc.py +975 -0
  33. openghg_inversions-0.6.0/openghg_inversions/hbmcmc/inversionsetup.py +139 -0
  34. openghg_inversions-0.6.0/openghg_inversions/hbmcmc/post_process_inputs.py +202 -0
  35. openghg_inversions-0.6.0/openghg_inversions/hbmcmc/run_hbmcmc.py +233 -0
  36. openghg_inversions-0.6.0/openghg_inversions/inversion_data/__init__.py +4 -0
  37. openghg_inversions-0.6.0/openghg_inversions/inversion_data/get_data.py +413 -0
  38. openghg_inversions-0.6.0/openghg_inversions/inversion_data/getters.py +474 -0
  39. openghg_inversions-0.6.0/openghg_inversions/inversion_data/scenario.py +45 -0
  40. openghg_inversions-0.6.0/openghg_inversions/inversion_data/serialise.py +375 -0
  41. openghg_inversions-0.6.0/openghg_inversions/model_error.py +131 -0
  42. openghg_inversions-0.6.0/openghg_inversions/postprocessing/PARIS_Lagrangian_inversion_concentration_EUROPE_v03.cdl +99 -0
  43. openghg_inversions-0.6.0/openghg_inversions/postprocessing/PARIS_Lagrangian_inversion_flux_EUROPE.cdl +180 -0
  44. openghg_inversions-0.6.0/openghg_inversions/postprocessing/__init__.py +1 -0
  45. openghg_inversions-0.6.0/openghg_inversions/postprocessing/_country_codes.py +363 -0
  46. openghg_inversions-0.6.0/openghg_inversions/postprocessing/countries.py +427 -0
  47. openghg_inversions-0.6.0/openghg_inversions/postprocessing/diagnostics.py +165 -0
  48. openghg_inversions-0.6.0/openghg_inversions/postprocessing/inversion_output.py +769 -0
  49. openghg_inversions-0.6.0/openghg_inversions/postprocessing/iso3166.json +1 -0
  50. openghg_inversions-0.6.0/openghg_inversions/postprocessing/make_outputs.py +318 -0
  51. openghg_inversions-0.6.0/openghg_inversions/postprocessing/make_paris_outputs.py +438 -0
  52. openghg_inversions-0.6.0/openghg_inversions/postprocessing/stats.py +209 -0
  53. openghg_inversions-0.6.0/openghg_inversions/postprocessing/utils.py +140 -0
  54. openghg_inversions-0.6.0/openghg_inversions/utils.py +235 -0
  55. openghg_inversions-0.6.0/openghg_inversions.egg-info/PKG-INFO +377 -0
  56. openghg_inversions-0.6.0/openghg_inversions.egg-info/SOURCES.txt +75 -0
  57. openghg_inversions-0.6.0/openghg_inversions.egg-info/dependency_links.txt +1 -0
  58. openghg_inversions-0.6.0/openghg_inversions.egg-info/requires.txt +13 -0
  59. openghg_inversions-0.6.0/openghg_inversions.egg-info/top_level.txt +4 -0
  60. openghg_inversions-0.6.0/pyproject.toml +61 -0
  61. openghg_inversions-0.6.0/setup.cfg +14 -0
  62. openghg_inversions-0.6.0/setup.py +3 -0
  63. openghg_inversions-0.6.0/tests/conftest.py +346 -0
  64. openghg_inversions-0.6.0/tests/helpers.py +42 -0
  65. openghg_inversions-0.6.0/tests/postprocessing/test_countries.py +80 -0
  66. openghg_inversions-0.6.0/tests/postprocessing/test_country_codes.py +113 -0
  67. openghg_inversions-0.6.0/tests/postprocessing/test_diagnostics.py +18 -0
  68. openghg_inversions-0.6.0/tests/test_array_ops.py +9 -0
  69. openghg_inversions-0.6.0/tests/test_basis_functions.py +174 -0
  70. openghg_inversions-0.6.0/tests/test_conftest.py +37 -0
  71. openghg_inversions-0.6.0/tests/test_filters.py +78 -0
  72. openghg_inversions-0.6.0/tests/test_full_inversion.py +198 -0
  73. openghg_inversions-0.6.0/tests/test_get_data.py +264 -0
  74. openghg_inversions-0.6.0/tests/test_inversion_setup.py +19 -0
  75. openghg_inversions-0.6.0/tests/test_postprocessing.py +135 -0
  76. openghg_inversions-0.6.0/tests/test_utils.py +25 -0
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2022 OpenGHG
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,377 @@
1
+ Metadata-Version: 2.4
2
+ Name: openghg_inversions
3
+ Version: 0.6.0
4
+ Summary: OpenGHG Inversions
5
+ Author-email: Eric Saboya <eric.saboya@bristol.ac.uk>
6
+ Maintainer-email: Brendan Murphy <brendan.murphy@bristol.ac.uk>
7
+ License: MIT License
8
+
9
+ Copyright (c) 2022 OpenGHG
10
+
11
+ Permission is hereby granted, free of charge, to any person obtaining a copy
12
+ of this software and associated documentation files (the "Software"), to deal
13
+ in the Software without restriction, including without limitation the rights
14
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15
+ copies of the Software, and to permit persons to whom the Software is
16
+ furnished to do so, subject to the following conditions:
17
+
18
+ The above copyright notice and this permission notice shall be included in all
19
+ copies or substantial portions of the Software.
20
+
21
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27
+ SOFTWARE.
28
+
29
+ Project-URL: Home, https://github.com/openghg/openghg_inversions
30
+ Project-URL: Bug Tracker, https://github.com/openghg/openghg_inversions/issues
31
+ Classifier: Programming Language :: Python :: 3
32
+ Classifier: License :: OSI Approved :: MIT License
33
+ Classifier: Operating System :: OS Independent
34
+ Requires-Python: >=3.10
35
+ Description-Content-Type: text/markdown
36
+ License-File: LICENSE
37
+ Requires-Dist: numpy>=2.0
38
+ Requires-Dist: numba>=0.59
39
+ Requires-Dist: pymc
40
+ Requires-Dist: numpyro[cpu]
41
+ Requires-Dist: xarray>=2025.06.0
42
+ Requires-Dist: pandas
43
+ Requires-Dist: matplotlib
44
+ Requires-Dist: scipy
45
+ Requires-Dist: numpy
46
+ Requires-Dist: openghg
47
+ Requires-Dist: sparse
48
+ Requires-Dist: flox
49
+ Requires-Dist: opt_einsum
50
+ Dynamic: license-file
51
+
52
+ <img src="https://github.com/openghg/logo/raw/main/OpenGHG_Logo_Landscape.png" width="100">
53
+
54
+ # OpenGHG Inversions
55
+
56
+ OpenGHG Inversions is a Python package that is being developed as part of the [OpenGHG project](https://openghg.org) with the aim of merging the data-processing and simulation modelling capabilities of OpenGHG with the atmospheric Bayesian inverse models developed by the Atmospheric Chemistry Research Group (ACRG) at the University of Bristol, UK.
57
+
58
+ Currently, OpenGHG Inversions includes the following regional inversion models:
59
+ - Hierarchical Bayesian Markov Chain Monte Carlo (HBMCMC) model (as described in Ganesan et al., 2014, _ACP_)
60
+
61
+ [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.10650595.svg)](https://doi.org/10.5281/zenodo.10650595)
62
+
63
+ ## Installation
64
+
65
+ ### Using pip (recommended for most users)
66
+
67
+ ```bash
68
+ pip install openghg-inversions
69
+ ```
70
+
71
+ ### Using uv (faster alternative)
72
+
73
+ ```bash
74
+ uv pip install openghg-inversions
75
+ ```
76
+
77
+ Or with uv's project management:
78
+
79
+ ```bash
80
+ # Add to your project
81
+ uv add openghg-inversions
82
+
83
+ # Or install in a virtual environment
84
+ uv venv
85
+ uv pip install openghg-inversions
86
+ ```
87
+
88
+ ### Development Installation
89
+
90
+ If you want to contribute or modify the package:
91
+
92
+ **With uv (recommended):**
93
+ ```bash
94
+ git clone https://github.com/openghg/openghg_inversions.git
95
+ cd openghg_inversions
96
+ uv sync --dev
97
+ ```
98
+
99
+ **With pip:**
100
+ ```bash
101
+ git clone https://github.com/openghg/openghg_inversions.git
102
+ cd openghg_inversions
103
+ pip install -e ".[dev]"
104
+ ```
105
+
106
+ ## Installation and Setup
107
+ As OpenGHG Inversions is dependent on OpenGHG, please ensure that when running locally you are using Python 3.10 or later on Linux or MacOS. Please see the [OpenGHG project](https://github.com/openghg/openghg/) for further installation instructions of OpenGHG and setting up an object store.
108
+
109
+ ### Setup a virtual environment
110
+
111
+ Check that you have Python 3.10 or greater:
112
+ ```bash
113
+ python --version
114
+ ```
115
+ (Note for Bristol ACRG group: If you are on Blue Pebble, the default anaconda module `lang/python/anaconda` is Python 3.9. Use `module avail` to list other options; `lang/python/miniconda/3.10.10.cuda-12` or `lang/python/miniconda/3.12.2.inc-perl-5.30.0` will work.)
116
+
117
+ Make a virtual environment
118
+ ```bash
119
+ python -m venv openghg_inv
120
+ ```
121
+
122
+ Next activate the environment
123
+ ```bash
124
+ source openghg_inv/bin/activate
125
+ ```
126
+
127
+ ### Installation using `pip`
128
+
129
+ First you'll need to clone the repository
130
+
131
+ ```bash
132
+ git clone https://github.com/openghg/openghg_inversions.git
133
+ ```
134
+
135
+ Next make sure `pip` and related install tools are up to date and then install OpenGHG Inversions using the editable install flag (`-e`)
136
+
137
+ ```bash
138
+ pip install --upgrade pip setuptools wheel
139
+ pip install -e openghg_inversions
140
+ ```
141
+
142
+ Optionally, install the developer requirements (there is more information about this in the "Contributing" section below):
143
+ ``` bash
144
+ pip install -r requirements-dev.txt
145
+ ```
146
+
147
+ ### Verify that PyMC is using fast linear algebra libraries
148
+ At this point, run
149
+
150
+ ``` bash
151
+ python -c "import pymc"
152
+ ```
153
+ This should run without printing any messages.
154
+ If you receive a message about `pymc` or `pytensor` using the `numpy` C-API, then your inversions might run slowly because the fast linear algebra libraries used by `numpy` haven't been found.
155
+
156
+ Solutions to this are:
157
+ 1. try `python -m pip install numpy` after upgrading `pip, setuptools, wheel`
158
+ 2. create a `conda` env, install `numpy` using `conda`, then use `pip` to upgrade `pip, setuptools, wheel` and install `openghg_inversions`
159
+
160
+
161
+ ## Using OpenGHG Inversions
162
+
163
+ ### Getting Started
164
+
165
+ For an overview of OpenGHG inversions, see this [primer](docs/getting_started.md).
166
+
167
+ ### Passing parameters to the inversion
168
+
169
+ Keyword arguments are propagated as follows:
170
+ 1. any key-value pair in an `ini` file or passed via the `--kwargs` flag is passed to the MCMC function as a keyword argument. (Currently, `fixedbasisMCMC` is the only available MCMC function)
171
+ 2. any keyword argument not recognised by the MCMC function (i.e. `fixedbasisMCMC`) is passed to the function `inferpymc` in `hbmcmc.inversion_pymc`, which is the function that creates and samples from the RHIME model.
172
+
173
+ Thus you can pass arguments to either `fixedbasisMCMC` or `inferpymc`, but all of these arguments will be specified in the `ini` file (or command line).
174
+
175
+ Let's look at these two steps in detail.
176
+
177
+ #### Ways of passing arguments to the inversion
178
+
179
+ ##### Passing options in an `ini` file
180
+
181
+ Extra options can be added to an `ini` file in almost any location.
182
+ The [template ini file](openghg_inversions/hbmcmc/config/openghg_hbmcmc_input_template_example.ini) puts
183
+ these option under the heading `MCMC.OPTIONS`:
184
+
185
+ ``` ini
186
+ [MCMC.OPTIONS]
187
+ averaging_error = True
188
+ fix_basis_outer_regions = True
189
+ use_bc = True
190
+ nuts_sampler = "numpyro"
191
+ save_trace = False
192
+ calculate_min_error = "percentile"
193
+ pollution_events_from_obs = True
194
+ reparameterise_log_normal = True
195
+ sampler_kwargs = {"target_accept": 0.99}
196
+ ```
197
+
198
+ These will be passed to the MCMC function (e.g. `fixedbasisMCMC`) as keyword arguments.
199
+ Any argument in `fixedbasisMCMC` can be specified in an `ini` file this way.
200
+
201
+ ##### Passing options at the command line
202
+
203
+ When running inversions using the script `run_hbmcmc.py`, you must specify the start and end date of
204
+ the inversion period, and you pass an `ini` file using the flag `-c`.
205
+
206
+ In addition, you can pass the output path using the flag `--output-path`; this is useful if your SLURM script
207
+ uses different output locations for different array jobs.
208
+
209
+ You can also pass arbitrary keyword arguments to `run_hbmcmc.py` using the `--kwargs` flag.
210
+ For instance:
211
+
212
+ ``` bash
213
+ python run_hbmcmc.py "2019-01-01" "2019-02-01" -c "example.ini" --kwargs '{"averaging_error": true, "min_error": 20.0, "nuts_sampler": "numpyro"}'
214
+ ```
215
+ It is crucial that you enclose the dictionary in single quotes, otherwise the command line will split the dictionary on white space.
216
+
217
+ Again, this can be used to change the arguments passed to an inversion on the fly (say, in a SLURM script).
218
+
219
+ The format of the dictionary inside single quotes must be JSON, because the value of `kwargs` is parsed using `json.loads`.
220
+ Python translates JSON according to [this table](https://docs.python.org/3/library/json.html#encoders-and-decoders).
221
+ In particular, `"true"` in JSON translate to `True` in Python (but `"True"` will be translated as a string).
222
+
223
+ The parsing in our `ini` files is more flexible; in particular, values that are Python statements will be translated to Python, so you don't need to worry about translation.
224
+
225
+ #### What parameters can you set?
226
+
227
+ The following sections detail some parameters that enable/specify optional behaviour in the inversion.
228
+
229
+ ##### Parameters for `fixedbasisMCMC`
230
+
231
+ This is not a comprehensive list (see the docstring for `fixedbasisMCMC` in the [hbmcmc module](openghg_inversions/hbmcmc/hbmcmc.py) for more arguments).
232
+
233
+
234
+ Arguments affecting the data using in the inversion:
235
+ - `sites`: a list of the sites to use in the inversion. Other information applied on a site-to-site basis that is presented in lists must be in the same order as used in the `sites` list.
236
+ - `inlet`: a list of inlets for each site. If only one inlet is available for a given site and species, then `None` may be used as the value for that site. If there are a range of inlet heights at a single site, and these should correspond to a single footprint release height, then you may use, for instance, `slice(140, 160)` to combine inlet heights between 140 and 160 meters into a single timeseries of observations.
237
+ -`instrument`, `fp_height`, `obs_data_level`, and `met_model` must either be lists of the same length as `sites`, or a single value may be supplied and will be converted to a list of the correct length.
238
+
239
+
240
+ Arguments affecting the inverse model:
241
+ - `averaging_error`: if `True`, the error from resampling to the given `averaging_period` will be added to the observation's error.
242
+ - `use_bc`: defaults to `True`. If `False`, no boundary conditions will be used in the inversion. This implicitly assumes that contributions from the boundary have been subtracted from the observations.
243
+ - `fix_basis_outer_regions`:
244
+ - Default value is `False`
245
+ - If `True`, the "outer regions" of the (`EUROPE`) domain use basis regions specified by a file provided by the Met Office (from their "InTem" model), and the "inner region", which includes the UK, is fit using our basis algorithms.
246
+ - This option is only available for the `EUROPE` domain currently.
247
+ - `calculate_min_error`: calculate min_error (see below) on the fly using the "residual error method" or a method based on percentiles of observations. Available arguments:
248
+ - `residual`: use "residual error method"
249
+ - `percentile`: use method based on percentiles
250
+ - `None`: in this case, you should pass in a value directly using (for instance) `min_error = 12.3`
251
+ - `min_error_options`: additional parameters to pass to the function that compute min error. This should be a dictionary, and the available options depend on the function used. (The functions to compute min. model error are in `model_error.py`).
252
+ - If `calculate_min_error = "residual"`, then, for instance, you could use `min_error_options = {"robust": False, "by_site": True}`. (By default, `robust` is `False`, this is just to show the possibilities.)
253
+ - `filters`: filters to apply to data (after it is resampled and aligned)
254
+ - `filters = None` will skip filtering
255
+ - if `filters` is a list of filters (or a string containing a single filter name), those filters will be applied to all sites.
256
+ - if `filters` is a dictionary with site codes as keys and lists of filters as values, then each site will have filters applied individually according to this dictionary. All sites must supplied; to skip a site, pass `None` instead of a list (or omit that site from the dictionary). For instance: `filters = {"MHD": ["pblh_inlet_diff", "pblh_min"], "JFJ": None}`.
257
+ - the list of available filters can be found in the `filtering` function in the [utils module](openghg_inversions/utils.py).
258
+ - Further parameters affecting the model are in the next subsection: they are passed to `inferpymc`.
259
+ - `xprior` and `bcprior`: these should be a dictionary containing `"pdf": <distribution>` and the arguments that should be passed to the PyMC distribution with that name. `<distribution>`
260
+
261
+ Arguments affecting the output of the inversion:
262
+ - `save_trace`:
263
+ - The default value is `False`.
264
+ - If `True`, the arviz `InferenceData` output from sampling will be saved to the output path of the inversion, with a file name of the form `f"{outputname}{start_data}_trace.nc`. To load this trace into arviz, you need to use `InferenceData.from_netcdf`.
265
+ - Alternatively, you can pass a path (including filename), and that path will be used.
266
+
267
+
268
+ ##### Parameters for `inferpymc`
269
+
270
+ As mentioned above, any keyword argument passed to `fixedbasisMCMC` (either by an `ini` file or from `--kwargs` on the command line) that is not recognised by `fixedbasisMCMC` is passed on to `inferpymc`.
271
+
272
+ These parameters include:
273
+ - `min_error`: a non-negative float value specifying a lower bound for the model-measurement mismatch error (i.e. the error on (y - y_mod)).
274
+ - `nuts_sampler`: a string, which defaults to `"pymc"`. The other option is `"numpyro"`, which will the [JAX](https://jax.readthedocs.io/en/latest/index.html) accelerated sampler from [Numpyro](https://num.pyro.ai/en/stable/index.html); this tends to be significantly faster than the NUTS sampler built into PyMC.
275
+ - `pollution_events_from_obs`: Determines whether the model error is calculated as a fraction of:
276
+ - the measured enhancement above the modelled baseline (if `True`)
277
+ - the prior modelled enhancement (if `False`)
278
+ - `no_model_error`: if `True`, only use obs error in likelihood (omitting min. model error and model error from scaling pollution events).
279
+ - `reparameterise_log_normal`: if `True`, then log normal priors will be sampled by transforming samples from standard normal random variable to samples from the appropriate log normal distribution.
280
+
281
+
282
+ ### The output from inversions
283
+
284
+ The results of an inversions are returned as an xarray `Dataset`.
285
+
286
+ The dimension `nmeasure` consists of the time for each observation stacked into a single 1D array.
287
+
288
+ TODO: complete this part
289
+
290
+ - `Yerror`: obs. error used in the inversion; if `add_averaging` is True, this will contain the combined "repeatability" and "variability"; otherwise, it will just contain "repeatability", if it is available, or "variability"
291
+ - `Yerror_repeatablity`: obs. repeatability. If repeatability isn't available for some sites, then this is filled with zeros.
292
+ - `Yerror_variability`: obs. variability.
293
+
294
+
295
+
296
+ ## Contributing
297
+
298
+ ### Code quality tools
299
+
300
+ To contribute to `openghg_inversions`, you should also install the developer packages:
301
+ ```bash
302
+ pip install -r requirements-dev.txt
303
+ ```
304
+ This will install the packages `flake8, pytest, black`.
305
+
306
+ We use `black` to format our code. To check if your code needs reformatting, run:
307
+ ``` bash
308
+ black --check openghg_inversions
309
+ ```
310
+ in your `openghg_inversions` repository (with your virtual env activated).
311
+ If you replace the flag `--check` with `--diff`, you can see what will be changed.
312
+
313
+ To make these changes, run
314
+ ``` bash
315
+ black openghg_inversions
316
+ ```
317
+
318
+ We also recommend using `flake8` to check for code style issues, which you can run with:
319
+ ``` bash
320
+ flake8 openghg_inversions
321
+ ```
322
+
323
+ You can run the tests using:
324
+ ``` bash
325
+ pytest
326
+ ```
327
+ in the `openghg_inversions` repository. (Make sure your virtual env is activated.)
328
+
329
+ ### Using `tox` to check code
330
+
331
+ Alternatively, use `tox` to run tests and check the code format.
332
+ `tox` creates isolated environments to run the tests, which means it can test against different
333
+ versions of OpenGHG.
334
+ It does this automatically, so you don't need to manage pip or conda virtual environments to do this.
335
+
336
+ To install `tox` globally in a "safe" way, use:
337
+
338
+ ```bash
339
+ python -m pip install pipx-in-pipx --user
340
+ pipx install tox
341
+ ```
342
+ or, within a virtual environment, do `pip install tox`.
343
+
344
+ Calling `tox -p` will run tests against OpenGHG devel and the last two releases of OpenGHG, and run black, flake8, and mypy.
345
+
346
+ To specify individual jobs, you can use, e.g.:
347
+
348
+ ```bash
349
+ tox -e openghgDev
350
+ ```
351
+
352
+ to run the tests against the devel branch.
353
+
354
+ Use `tox -l` to list all options.
355
+
356
+ To pass arguments to pytest, mypy, black, etc, you can use, e.g.
357
+
358
+ ```bash
359
+ tox -- "openghg_inversions/hbmcmc"
360
+ ```
361
+
362
+ which will pass the positional argument "openghg_inversions/hbmcmc" to the commands invoked by tox.
363
+
364
+ ### Using branches
365
+
366
+ To contribute new code, make a branch off of the `devel` branch.
367
+ When your code is ready to be added, push it to github (`origin`).
368
+ You can then open a "pull request" on github and request a code review.
369
+ It's helpful to write a description of the changes made in your PR, as well as linking to any relevant issues.
370
+
371
+ Your code must past the tests and be reviewed before it can be merged.
372
+ After this, you can merge your branch and close it (it can always be recovered later if necessary).
373
+
374
+ ## References
375
+ Ganesan et al. (2014),_ACP_;
376
+
377
+ Western et al. (2021), _Enviro. Sci. Tech Lett._