fimx 0.1.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.
- fimx-0.1.0/LICENSE +21 -0
- fimx-0.1.0/PKG-INFO +203 -0
- fimx-0.1.0/README.md +174 -0
- fimx-0.1.0/pyproject.toml +71 -0
- fimx-0.1.0/pyproject.toml.orig +59 -0
- fimx-0.1.0/src/fimx/__init__.py +22 -0
- fimx-0.1.0/src/fimx/cli.py +97 -0
- fimx-0.1.0/src/fimx/combination.py +67 -0
- fimx-0.1.0/src/fimx/construction.py +100 -0
- fimx-0.1.0/src/fimx/datasets.py +72 -0
- fimx-0.1.0/src/fimx/inversion.py +78 -0
- fimx-0.1.0/src/fimx/io.py +24 -0
- fimx-0.1.0/src/fimx/parameters.py +204 -0
- fimx-0.1.0/src/fimx/plotting/__init__.py +88 -0
- fimx-0.1.0/src/fimx/plotting/base.py +98 -0
- fimx-0.1.0/src/fimx/plotting/getdist.py +68 -0
- fimx-0.1.0/src/fimx/py.typed +0 -0
fimx-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Bernardo Porto Veronese
|
|
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.
|
fimx-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: fimx
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Dense Fisher matrix functions on labeled xarray arrays
|
|
5
|
+
Keywords: fisher-matrix,forecasting,cosmology,xarray
|
|
6
|
+
Author: binado
|
|
7
|
+
Author-email: binado <bernardopveronese@gmail.com>
|
|
8
|
+
License-Expression: MIT
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Classifier: Development Status :: 3 - Alpha
|
|
11
|
+
Classifier: Intended Audience :: Science/Research
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Topic :: Scientific/Engineering
|
|
14
|
+
Classifier: Typing :: Typed
|
|
15
|
+
Requires-Dist: numpy
|
|
16
|
+
Requires-Dist: xarray
|
|
17
|
+
Requires-Dist: xarray-einstats>=0.10.0
|
|
18
|
+
Requires-Dist: h5netcdf[h5py] ; extra == 'io'
|
|
19
|
+
Requires-Dist: getdist ; extra == 'plotting'
|
|
20
|
+
Requires-Dist: matplotlib ; extra == 'plotting'
|
|
21
|
+
Requires-Python: >=3.12
|
|
22
|
+
Project-URL: Homepage, https://github.com/binado/fimx
|
|
23
|
+
Project-URL: Repository, https://github.com/binado/fimx
|
|
24
|
+
Project-URL: Issues, https://github.com/binado/fimx/issues
|
|
25
|
+
Project-URL: Changelog, https://github.com/binado/fimx/blob/main/CHANGELOG.md
|
|
26
|
+
Provides-Extra: io
|
|
27
|
+
Provides-Extra: plotting
|
|
28
|
+
Description-Content-Type: text/markdown
|
|
29
|
+
|
|
30
|
+
# fimx
|
|
31
|
+
|
|
32
|
+
`fimx` provides functions for dense Fisher information matrices stored
|
|
33
|
+
as ordinary `xarray.DataArray` objects. NumPy handles the computation; xarray
|
|
34
|
+
handles labels, metadata containers, and persistence.
|
|
35
|
+
|
|
36
|
+
```sh
|
|
37
|
+
uv add fimx
|
|
38
|
+
# Optional NetCDF backend:
|
|
39
|
+
uv add 'fimx[io]'
|
|
40
|
+
# Optional Gaussian plotting backend:
|
|
41
|
+
uv add 'fimx[plotting]'
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Quickstart
|
|
45
|
+
|
|
46
|
+
```python
|
|
47
|
+
from fimx import combine, errors, fix, gaussian_prior, inv, marginalize, matrix
|
|
48
|
+
|
|
49
|
+
F = matrix([[4, 1], [1, 2]], ["a", "b"])
|
|
50
|
+
fixed = fix(F, "b") # [[4.0]]: b is held fixed
|
|
51
|
+
reduced = marginalize(F, "b") # [[3.5]]: uncertainty in b is integrated out
|
|
52
|
+
C = inv(F) # covariance, with the same row/col labels
|
|
53
|
+
sigma = errors(F) # sqrt(diag(C)), dimension "parameter"
|
|
54
|
+
|
|
55
|
+
prior = gaussian_prior({"a": 0.5}) # standard deviation 0.5 -> information 4
|
|
56
|
+
posterior = combine(F, prior)
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
| Function | Behavior |
|
|
60
|
+
| --- | --- |
|
|
61
|
+
| `matrix(values, parameters)` | Construct and validate a canonical matrix. |
|
|
62
|
+
| `expand(F, parameters)` | Embed in a larger or reordered parameter set, filling with zeros. |
|
|
63
|
+
| `fix(F, parameters)` | Remove names through a principal submatrix. |
|
|
64
|
+
| `marginalize(F, parameters)` | Remove names through the Schur complement. |
|
|
65
|
+
| `inv(F)` | Return the inverse using Cholesky. |
|
|
66
|
+
| `errors(F)` | Return marginalized standard deviations. |
|
|
67
|
+
| `transform(F, jacobian)` | Change variables using `J.T @ F @ J`. |
|
|
68
|
+
| `combine(*matrices)` | Sum independent information over the parameter union. |
|
|
69
|
+
| `gaussian_prior(sigmas)` | Construct diagonal information `1 / sigma**2`. |
|
|
70
|
+
|
|
71
|
+
## Array contract
|
|
72
|
+
|
|
73
|
+
- Matrices have dimensions exactly `("row", "col")`, a nonempty square shape,
|
|
74
|
+
and explicit, identical, ordered coordinates of unique string names.
|
|
75
|
+
Batches, inferred dimensions, and coordinate repair are unsupported.
|
|
76
|
+
- Values must be real, finite, and symmetric. They are converted to float64.
|
|
77
|
+
- Positive semidefiniteness is not checked, so singular matrices can be built,
|
|
78
|
+
fixed, transformed, or combined. `inv` and `errors` require positive
|
|
79
|
+
definite input; `marginalize` only requires the removed block to be.
|
|
80
|
+
- Functions return fresh DataArrays and never mutate their inputs. Attributes,
|
|
81
|
+
names, and auxiliary coordinates are not preserved.
|
|
82
|
+
- Arrays built directly with xarray work if they meet the contract.
|
|
83
|
+
|
|
84
|
+
Behavior worth knowing:
|
|
85
|
+
|
|
86
|
+
- `fix` and `marginalize` accept one name or a sequence and keep the remaining
|
|
87
|
+
order. Unknown names raise `KeyError`; duplicates or removing every
|
|
88
|
+
parameter raise `ValueError`.
|
|
89
|
+
- `expand` embeds a matrix in a larger or reordered set of names, filling new
|
|
90
|
+
entries with zeros. The target must contain every existing name. Matrices
|
|
91
|
+
expanded to the same names add with plain `+`, whereas `+` on mismatched
|
|
92
|
+
names silently keeps only the overlap.
|
|
93
|
+
- `combine` keeps the first matrix's order and appends new parameters as they
|
|
94
|
+
appear. Missing entries contribute zero.
|
|
95
|
+
- `gaussian_prior` takes **standard deviations**, not information values.
|
|
96
|
+
- Failures are explicit: `ValueError` for malformed or non-finite data,
|
|
97
|
+
`TypeError` for non-DataArray inputs, and `numpy.linalg.LinAlgError` for
|
|
98
|
+
singular or indefinite matrices. There is no pseudoinverse or regularization.
|
|
99
|
+
|
|
100
|
+
### Changes of variables
|
|
101
|
+
|
|
102
|
+
The Jacobian has dimensions `("old", "new")` and orientation
|
|
103
|
+
**`J[i, j] = d theta_i / d phi_j`**, where theta are the old parameters and phi
|
|
104
|
+
the new ones. Every old parameter must appear exactly once (rows are reordered
|
|
105
|
+
to match `F`), and the order of the new parameters sets the output order.
|
|
106
|
+
Rectangular Jacobians are supported.
|
|
107
|
+
|
|
108
|
+
```python
|
|
109
|
+
import xarray as xr
|
|
110
|
+
from fimx import transform
|
|
111
|
+
|
|
112
|
+
# theta_a = 2 * phi_x, theta_b = phi_x
|
|
113
|
+
# Rows deliberately appear in reverse order to F.
|
|
114
|
+
J = xr.DataArray(
|
|
115
|
+
[[1.0], [2.0]],
|
|
116
|
+
dims=("old", "new"),
|
|
117
|
+
coords={"old": ["b", "a"], "new": ["x"]},
|
|
118
|
+
)
|
|
119
|
+
G = transform(F, J) # [[22.0]]
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## Plotting
|
|
123
|
+
|
|
124
|
+
Plotting needs the `plotting` extra (GetDist and Matplotlib, loaded lazily).
|
|
125
|
+
|
|
126
|
+
### Forecast Datasets
|
|
127
|
+
|
|
128
|
+
Keep fiducials separate from the Fisher matrix and bundle them with
|
|
129
|
+
`dataset()`. In the mapping of extra variables, 1D arrays use `row` and 2D
|
|
130
|
+
arrays use `(row, col)`; plain arrays follow matrix order and indexed axes are
|
|
131
|
+
aligned by label. Strings, units, and nonfinite metadata are allowed. The names
|
|
132
|
+
`fisher`, `row`, and `col` are reserved.
|
|
133
|
+
|
|
134
|
+
### Corner plots
|
|
135
|
+
|
|
136
|
+
```python
|
|
137
|
+
from fimx import dataset, plot
|
|
138
|
+
|
|
139
|
+
fiducials = xr.DataArray([1.0, 2.0], dims="row", coords={"row": ["a", "b"]})
|
|
140
|
+
survey_a = dataset(F, {"fiducials": fiducials, "units": ["km", "s"]})
|
|
141
|
+
survey_b = dataset(2 * F, {"fiducials": fiducials})
|
|
142
|
+
|
|
143
|
+
fig = plot({"Survey A": survey_a, "Survey B": survey_b})
|
|
144
|
+
fig.savefig("constraints.pdf")
|
|
145
|
+
|
|
146
|
+
# Explicit order and GetDist customization:
|
|
147
|
+
fig = plot(
|
|
148
|
+
{"Survey A": survey_a, "Survey B": survey_b},
|
|
149
|
+
parameters=["b", "a"],
|
|
150
|
+
backend="getdist",
|
|
151
|
+
filled=False,
|
|
152
|
+
backend_kwargs={"contour_colors": ["C0", "C1"]},
|
|
153
|
+
)
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
- `plot()` takes a nonempty mapping of labels to Datasets with `fisher` and
|
|
157
|
+
finite, real `fiducials`. Each forecast is centered on its own fiducials;
|
|
158
|
+
mapping order sets the overlay order and keys become legend labels.
|
|
159
|
+
- By default, the plot uses the parameters shared by all forecasts, in the
|
|
160
|
+
first forecast's order. An explicit `parameters` list must be unique and
|
|
161
|
+
present in every forecast.
|
|
162
|
+
- Each full Fisher matrix is inverted before selecting parameters, so omitted
|
|
163
|
+
parameters are marginalized and every complete matrix (nuisance blocks
|
|
164
|
+
included) must be positive definite.
|
|
165
|
+
- The GetDist backend draws analytic Gaussians, with no sampling, and returns
|
|
166
|
+
a Matplotlib `Figure` without showing or saving it. Filled contours are the
|
|
167
|
+
default. `backend_kwargs` is forwarded to `triangle_plot`, except `roots`,
|
|
168
|
+
`params`, `legend_labels`, and `filled`, which `plot()` controls.
|
|
169
|
+
- Additional backends implement `fimx.plotting.base.PlotBackend`.
|
|
170
|
+
|
|
171
|
+
### Command line
|
|
172
|
+
|
|
173
|
+
With both extras installed, `fimx-plot` draws a corner plot from NetCDF
|
|
174
|
+
Datasets that contain `fisher` and `fiducials`:
|
|
175
|
+
|
|
176
|
+
```sh
|
|
177
|
+
uv add 'fimx[io,plotting]'
|
|
178
|
+
fimx-plot --file survey-a.nc --file survey-b.nc \
|
|
179
|
+
--figure-file constraints.png --figure-dpi 200 \
|
|
180
|
+
--parameters a b --no-filled --backend getdist \
|
|
181
|
+
--backend-kwargs '{"contour_colors": ["C0", "C1"]}'
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
Each file stem becomes a legend label, so stems must be unique. The output
|
|
185
|
+
defaults to `plot.png` at 150 dpi. `--parameters` selects and orders
|
|
186
|
+
parameters, `--no-filled` draws line contours, `--backend` picks a backend, and
|
|
187
|
+
`--backend-kwargs` takes a JSON object. `fimx.io.load_dataset(path)` loads the
|
|
188
|
+
same files from Python.
|
|
189
|
+
|
|
190
|
+
## Storage
|
|
191
|
+
|
|
192
|
+
There is no `fimx` file format; use xarray. The `io` extra supplies `h5netcdf`.
|
|
193
|
+
|
|
194
|
+
```python
|
|
195
|
+
F.to_netcdf("fisher.nc", engine="h5netcdf")
|
|
196
|
+
restored = xr.load_dataarray("fisher.nc", engine="h5netcdf")
|
|
197
|
+
C_restored = inv(restored)
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
## More
|
|
201
|
+
|
|
202
|
+
See [CHANGELOG.md](CHANGELOG.md) for release notes. `fimx` is released under
|
|
203
|
+
the MIT license; see [LICENSE](LICENSE).
|
fimx-0.1.0/README.md
ADDED
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
# fimx
|
|
2
|
+
|
|
3
|
+
`fimx` provides functions for dense Fisher information matrices stored
|
|
4
|
+
as ordinary `xarray.DataArray` objects. NumPy handles the computation; xarray
|
|
5
|
+
handles labels, metadata containers, and persistence.
|
|
6
|
+
|
|
7
|
+
```sh
|
|
8
|
+
uv add fimx
|
|
9
|
+
# Optional NetCDF backend:
|
|
10
|
+
uv add 'fimx[io]'
|
|
11
|
+
# Optional Gaussian plotting backend:
|
|
12
|
+
uv add 'fimx[plotting]'
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
## Quickstart
|
|
16
|
+
|
|
17
|
+
```python
|
|
18
|
+
from fimx import combine, errors, fix, gaussian_prior, inv, marginalize, matrix
|
|
19
|
+
|
|
20
|
+
F = matrix([[4, 1], [1, 2]], ["a", "b"])
|
|
21
|
+
fixed = fix(F, "b") # [[4.0]]: b is held fixed
|
|
22
|
+
reduced = marginalize(F, "b") # [[3.5]]: uncertainty in b is integrated out
|
|
23
|
+
C = inv(F) # covariance, with the same row/col labels
|
|
24
|
+
sigma = errors(F) # sqrt(diag(C)), dimension "parameter"
|
|
25
|
+
|
|
26
|
+
prior = gaussian_prior({"a": 0.5}) # standard deviation 0.5 -> information 4
|
|
27
|
+
posterior = combine(F, prior)
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
| Function | Behavior |
|
|
31
|
+
| --- | --- |
|
|
32
|
+
| `matrix(values, parameters)` | Construct and validate a canonical matrix. |
|
|
33
|
+
| `expand(F, parameters)` | Embed in a larger or reordered parameter set, filling with zeros. |
|
|
34
|
+
| `fix(F, parameters)` | Remove names through a principal submatrix. |
|
|
35
|
+
| `marginalize(F, parameters)` | Remove names through the Schur complement. |
|
|
36
|
+
| `inv(F)` | Return the inverse using Cholesky. |
|
|
37
|
+
| `errors(F)` | Return marginalized standard deviations. |
|
|
38
|
+
| `transform(F, jacobian)` | Change variables using `J.T @ F @ J`. |
|
|
39
|
+
| `combine(*matrices)` | Sum independent information over the parameter union. |
|
|
40
|
+
| `gaussian_prior(sigmas)` | Construct diagonal information `1 / sigma**2`. |
|
|
41
|
+
|
|
42
|
+
## Array contract
|
|
43
|
+
|
|
44
|
+
- Matrices have dimensions exactly `("row", "col")`, a nonempty square shape,
|
|
45
|
+
and explicit, identical, ordered coordinates of unique string names.
|
|
46
|
+
Batches, inferred dimensions, and coordinate repair are unsupported.
|
|
47
|
+
- Values must be real, finite, and symmetric. They are converted to float64.
|
|
48
|
+
- Positive semidefiniteness is not checked, so singular matrices can be built,
|
|
49
|
+
fixed, transformed, or combined. `inv` and `errors` require positive
|
|
50
|
+
definite input; `marginalize` only requires the removed block to be.
|
|
51
|
+
- Functions return fresh DataArrays and never mutate their inputs. Attributes,
|
|
52
|
+
names, and auxiliary coordinates are not preserved.
|
|
53
|
+
- Arrays built directly with xarray work if they meet the contract.
|
|
54
|
+
|
|
55
|
+
Behavior worth knowing:
|
|
56
|
+
|
|
57
|
+
- `fix` and `marginalize` accept one name or a sequence and keep the remaining
|
|
58
|
+
order. Unknown names raise `KeyError`; duplicates or removing every
|
|
59
|
+
parameter raise `ValueError`.
|
|
60
|
+
- `expand` embeds a matrix in a larger or reordered set of names, filling new
|
|
61
|
+
entries with zeros. The target must contain every existing name. Matrices
|
|
62
|
+
expanded to the same names add with plain `+`, whereas `+` on mismatched
|
|
63
|
+
names silently keeps only the overlap.
|
|
64
|
+
- `combine` keeps the first matrix's order and appends new parameters as they
|
|
65
|
+
appear. Missing entries contribute zero.
|
|
66
|
+
- `gaussian_prior` takes **standard deviations**, not information values.
|
|
67
|
+
- Failures are explicit: `ValueError` for malformed or non-finite data,
|
|
68
|
+
`TypeError` for non-DataArray inputs, and `numpy.linalg.LinAlgError` for
|
|
69
|
+
singular or indefinite matrices. There is no pseudoinverse or regularization.
|
|
70
|
+
|
|
71
|
+
### Changes of variables
|
|
72
|
+
|
|
73
|
+
The Jacobian has dimensions `("old", "new")` and orientation
|
|
74
|
+
**`J[i, j] = d theta_i / d phi_j`**, where theta are the old parameters and phi
|
|
75
|
+
the new ones. Every old parameter must appear exactly once (rows are reordered
|
|
76
|
+
to match `F`), and the order of the new parameters sets the output order.
|
|
77
|
+
Rectangular Jacobians are supported.
|
|
78
|
+
|
|
79
|
+
```python
|
|
80
|
+
import xarray as xr
|
|
81
|
+
from fimx import transform
|
|
82
|
+
|
|
83
|
+
# theta_a = 2 * phi_x, theta_b = phi_x
|
|
84
|
+
# Rows deliberately appear in reverse order to F.
|
|
85
|
+
J = xr.DataArray(
|
|
86
|
+
[[1.0], [2.0]],
|
|
87
|
+
dims=("old", "new"),
|
|
88
|
+
coords={"old": ["b", "a"], "new": ["x"]},
|
|
89
|
+
)
|
|
90
|
+
G = transform(F, J) # [[22.0]]
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
## Plotting
|
|
94
|
+
|
|
95
|
+
Plotting needs the `plotting` extra (GetDist and Matplotlib, loaded lazily).
|
|
96
|
+
|
|
97
|
+
### Forecast Datasets
|
|
98
|
+
|
|
99
|
+
Keep fiducials separate from the Fisher matrix and bundle them with
|
|
100
|
+
`dataset()`. In the mapping of extra variables, 1D arrays use `row` and 2D
|
|
101
|
+
arrays use `(row, col)`; plain arrays follow matrix order and indexed axes are
|
|
102
|
+
aligned by label. Strings, units, and nonfinite metadata are allowed. The names
|
|
103
|
+
`fisher`, `row`, and `col` are reserved.
|
|
104
|
+
|
|
105
|
+
### Corner plots
|
|
106
|
+
|
|
107
|
+
```python
|
|
108
|
+
from fimx import dataset, plot
|
|
109
|
+
|
|
110
|
+
fiducials = xr.DataArray([1.0, 2.0], dims="row", coords={"row": ["a", "b"]})
|
|
111
|
+
survey_a = dataset(F, {"fiducials": fiducials, "units": ["km", "s"]})
|
|
112
|
+
survey_b = dataset(2 * F, {"fiducials": fiducials})
|
|
113
|
+
|
|
114
|
+
fig = plot({"Survey A": survey_a, "Survey B": survey_b})
|
|
115
|
+
fig.savefig("constraints.pdf")
|
|
116
|
+
|
|
117
|
+
# Explicit order and GetDist customization:
|
|
118
|
+
fig = plot(
|
|
119
|
+
{"Survey A": survey_a, "Survey B": survey_b},
|
|
120
|
+
parameters=["b", "a"],
|
|
121
|
+
backend="getdist",
|
|
122
|
+
filled=False,
|
|
123
|
+
backend_kwargs={"contour_colors": ["C0", "C1"]},
|
|
124
|
+
)
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
- `plot()` takes a nonempty mapping of labels to Datasets with `fisher` and
|
|
128
|
+
finite, real `fiducials`. Each forecast is centered on its own fiducials;
|
|
129
|
+
mapping order sets the overlay order and keys become legend labels.
|
|
130
|
+
- By default, the plot uses the parameters shared by all forecasts, in the
|
|
131
|
+
first forecast's order. An explicit `parameters` list must be unique and
|
|
132
|
+
present in every forecast.
|
|
133
|
+
- Each full Fisher matrix is inverted before selecting parameters, so omitted
|
|
134
|
+
parameters are marginalized and every complete matrix (nuisance blocks
|
|
135
|
+
included) must be positive definite.
|
|
136
|
+
- The GetDist backend draws analytic Gaussians, with no sampling, and returns
|
|
137
|
+
a Matplotlib `Figure` without showing or saving it. Filled contours are the
|
|
138
|
+
default. `backend_kwargs` is forwarded to `triangle_plot`, except `roots`,
|
|
139
|
+
`params`, `legend_labels`, and `filled`, which `plot()` controls.
|
|
140
|
+
- Additional backends implement `fimx.plotting.base.PlotBackend`.
|
|
141
|
+
|
|
142
|
+
### Command line
|
|
143
|
+
|
|
144
|
+
With both extras installed, `fimx-plot` draws a corner plot from NetCDF
|
|
145
|
+
Datasets that contain `fisher` and `fiducials`:
|
|
146
|
+
|
|
147
|
+
```sh
|
|
148
|
+
uv add 'fimx[io,plotting]'
|
|
149
|
+
fimx-plot --file survey-a.nc --file survey-b.nc \
|
|
150
|
+
--figure-file constraints.png --figure-dpi 200 \
|
|
151
|
+
--parameters a b --no-filled --backend getdist \
|
|
152
|
+
--backend-kwargs '{"contour_colors": ["C0", "C1"]}'
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Each file stem becomes a legend label, so stems must be unique. The output
|
|
156
|
+
defaults to `plot.png` at 150 dpi. `--parameters` selects and orders
|
|
157
|
+
parameters, `--no-filled` draws line contours, `--backend` picks a backend, and
|
|
158
|
+
`--backend-kwargs` takes a JSON object. `fimx.io.load_dataset(path)` loads the
|
|
159
|
+
same files from Python.
|
|
160
|
+
|
|
161
|
+
## Storage
|
|
162
|
+
|
|
163
|
+
There is no `fimx` file format; use xarray. The `io` extra supplies `h5netcdf`.
|
|
164
|
+
|
|
165
|
+
```python
|
|
166
|
+
F.to_netcdf("fisher.nc", engine="h5netcdf")
|
|
167
|
+
restored = xr.load_dataarray("fisher.nc", engine="h5netcdf")
|
|
168
|
+
C_restored = inv(restored)
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
## More
|
|
172
|
+
|
|
173
|
+
See [CHANGELOG.md](CHANGELOG.md) for release notes. `fimx` is released under
|
|
174
|
+
the MIT license; see [LICENSE](LICENSE).
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "fimx"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "Dense Fisher matrix functions on labeled xarray arrays"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
license = "MIT"
|
|
7
|
+
license-files = ["LICENSE*"]
|
|
8
|
+
keywords = [
|
|
9
|
+
"fisher-matrix",
|
|
10
|
+
"forecasting",
|
|
11
|
+
"cosmology",
|
|
12
|
+
"xarray",
|
|
13
|
+
]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Development Status :: 3 - Alpha",
|
|
16
|
+
"Intended Audience :: Science/Research",
|
|
17
|
+
"Programming Language :: Python :: 3",
|
|
18
|
+
"Topic :: Scientific/Engineering",
|
|
19
|
+
"Typing :: Typed",
|
|
20
|
+
]
|
|
21
|
+
requires-python = ">=3.12"
|
|
22
|
+
dependencies = [
|
|
23
|
+
"numpy",
|
|
24
|
+
"xarray",
|
|
25
|
+
"xarray-einstats>=0.10.0",
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
[[project.authors]]
|
|
29
|
+
name = "binado"
|
|
30
|
+
email = "bernardopveronese@gmail.com"
|
|
31
|
+
|
|
32
|
+
[project.optional-dependencies]
|
|
33
|
+
io = ["h5netcdf[h5py]"]
|
|
34
|
+
plotting = [
|
|
35
|
+
"getdist",
|
|
36
|
+
"matplotlib",
|
|
37
|
+
]
|
|
38
|
+
|
|
39
|
+
[project.urls]
|
|
40
|
+
Homepage = "https://github.com/binado/fimx"
|
|
41
|
+
Repository = "https://github.com/binado/fimx"
|
|
42
|
+
Issues = "https://github.com/binado/fimx/issues"
|
|
43
|
+
Changelog = "https://github.com/binado/fimx/blob/main/CHANGELOG.md"
|
|
44
|
+
|
|
45
|
+
[project.scripts]
|
|
46
|
+
fimx-plot = "fimx.cli:main"
|
|
47
|
+
|
|
48
|
+
[build-system]
|
|
49
|
+
requires = ["uv_build>=0.12.7,<0.13.0"]
|
|
50
|
+
build-backend = "uv_build"
|
|
51
|
+
|
|
52
|
+
[dependency-groups]
|
|
53
|
+
dev = [
|
|
54
|
+
"getdist>=1.7.7",
|
|
55
|
+
"h5netcdf[h5py]",
|
|
56
|
+
"ipykernel>=7.1.0",
|
|
57
|
+
"matplotlib>=3.10.8",
|
|
58
|
+
"prek>=0.5.3",
|
|
59
|
+
"pytest>=9.0.2",
|
|
60
|
+
"ruff>=0.16.0",
|
|
61
|
+
"ty>=0.0.83",
|
|
62
|
+
]
|
|
63
|
+
|
|
64
|
+
[tool.ruff]
|
|
65
|
+
extend-exclude = ["examples"]
|
|
66
|
+
|
|
67
|
+
[tool.ty.src]
|
|
68
|
+
include = [
|
|
69
|
+
"src",
|
|
70
|
+
"tests",
|
|
71
|
+
]
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "fimx"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "Dense Fisher matrix functions on labeled xarray arrays"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
license = "MIT"
|
|
7
|
+
license-files = ["LICENSE*"]
|
|
8
|
+
authors = [
|
|
9
|
+
{ name = "binado", email = "bernardopveronese@gmail.com" }
|
|
10
|
+
]
|
|
11
|
+
keywords = ["fisher-matrix", "forecasting", "cosmology", "xarray"]
|
|
12
|
+
classifiers = [
|
|
13
|
+
"Development Status :: 3 - Alpha",
|
|
14
|
+
"Intended Audience :: Science/Research",
|
|
15
|
+
"Programming Language :: Python :: 3",
|
|
16
|
+
"Topic :: Scientific/Engineering",
|
|
17
|
+
"Typing :: Typed",
|
|
18
|
+
]
|
|
19
|
+
requires-python = ">=3.12"
|
|
20
|
+
dependencies = [
|
|
21
|
+
"numpy",
|
|
22
|
+
"xarray",
|
|
23
|
+
"xarray-einstats>=0.10.0",
|
|
24
|
+
]
|
|
25
|
+
|
|
26
|
+
[project.optional-dependencies]
|
|
27
|
+
io = ["h5netcdf[h5py]"]
|
|
28
|
+
plotting = ["getdist", "matplotlib"]
|
|
29
|
+
|
|
30
|
+
[project.urls]
|
|
31
|
+
Homepage = "https://github.com/binado/fimx"
|
|
32
|
+
Repository = "https://github.com/binado/fimx"
|
|
33
|
+
Issues = "https://github.com/binado/fimx/issues"
|
|
34
|
+
Changelog = "https://github.com/binado/fimx/blob/main/CHANGELOG.md"
|
|
35
|
+
|
|
36
|
+
[project.scripts]
|
|
37
|
+
fimx-plot = "fimx.cli:main"
|
|
38
|
+
|
|
39
|
+
[build-system]
|
|
40
|
+
requires = ["uv_build>=0.12.7,<0.13.0"]
|
|
41
|
+
build-backend = "uv_build"
|
|
42
|
+
|
|
43
|
+
[dependency-groups]
|
|
44
|
+
dev = [
|
|
45
|
+
"getdist>=1.7.7",
|
|
46
|
+
"h5netcdf[h5py]",
|
|
47
|
+
"ipykernel>=7.1.0",
|
|
48
|
+
"matplotlib>=3.10.8",
|
|
49
|
+
"prek>=0.5.3",
|
|
50
|
+
"pytest>=9.0.2",
|
|
51
|
+
"ruff>=0.16.0",
|
|
52
|
+
"ty>=0.0.83",
|
|
53
|
+
]
|
|
54
|
+
|
|
55
|
+
[tool.ruff]
|
|
56
|
+
extend-exclude = ["examples"]
|
|
57
|
+
|
|
58
|
+
[tool.ty.src]
|
|
59
|
+
include = ["src", "tests"]
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"""Functions for Fisher information on labeled xarray matrices."""
|
|
2
|
+
|
|
3
|
+
from .combination import combine, gaussian_prior
|
|
4
|
+
from .construction import matrix
|
|
5
|
+
from .datasets import dataset
|
|
6
|
+
from .inversion import errors, inv
|
|
7
|
+
from .parameters import expand, fix, marginalize, transform
|
|
8
|
+
from .plotting import plot
|
|
9
|
+
|
|
10
|
+
__all__ = [
|
|
11
|
+
"combine",
|
|
12
|
+
"dataset",
|
|
13
|
+
"errors",
|
|
14
|
+
"expand",
|
|
15
|
+
"fix",
|
|
16
|
+
"gaussian_prior",
|
|
17
|
+
"inv",
|
|
18
|
+
"marginalize",
|
|
19
|
+
"matrix",
|
|
20
|
+
"plot",
|
|
21
|
+
"transform",
|
|
22
|
+
]
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
"""Command-line interface for plotting Fisher forecasts."""
|
|
2
|
+
|
|
3
|
+
from argparse import ArgumentParser, BooleanOptionalAction
|
|
4
|
+
from collections.abc import Sequence
|
|
5
|
+
from json import loads
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
|
|
8
|
+
from .io import load_dataset
|
|
9
|
+
from .plotting import plot
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def _parser() -> ArgumentParser:
|
|
13
|
+
"""Build the command-line argument parser."""
|
|
14
|
+
parser = ArgumentParser(
|
|
15
|
+
description="Overlay Fisher forecast Datasets in a corner plot."
|
|
16
|
+
)
|
|
17
|
+
parser.add_argument(
|
|
18
|
+
"--file",
|
|
19
|
+
dest="files",
|
|
20
|
+
action="append",
|
|
21
|
+
required=True,
|
|
22
|
+
type=Path,
|
|
23
|
+
metavar="PATH",
|
|
24
|
+
help="NetCDF Dataset to plot; repeat to overlay multiple forecasts.",
|
|
25
|
+
)
|
|
26
|
+
parser.add_argument(
|
|
27
|
+
"--figure-file",
|
|
28
|
+
type=Path,
|
|
29
|
+
default=Path("plot.png"),
|
|
30
|
+
metavar="PATH",
|
|
31
|
+
help="Output figure path (default: plot.png).",
|
|
32
|
+
)
|
|
33
|
+
parser.add_argument(
|
|
34
|
+
"--figure-dpi",
|
|
35
|
+
type=int,
|
|
36
|
+
default=150,
|
|
37
|
+
metavar="DPI",
|
|
38
|
+
help="Output resolution in dots per inch (default: 150).",
|
|
39
|
+
)
|
|
40
|
+
parser.add_argument(
|
|
41
|
+
"--parameters",
|
|
42
|
+
nargs="+",
|
|
43
|
+
metavar="NAME",
|
|
44
|
+
help="Parameters to include in the plot, in the requested order.",
|
|
45
|
+
)
|
|
46
|
+
parser.add_argument(
|
|
47
|
+
"--filled",
|
|
48
|
+
action=BooleanOptionalAction,
|
|
49
|
+
default=True,
|
|
50
|
+
help="Fill two-dimensional contours (default; use --no-filled for lines).",
|
|
51
|
+
)
|
|
52
|
+
parser.add_argument(
|
|
53
|
+
"--backend",
|
|
54
|
+
default="getdist",
|
|
55
|
+
metavar="NAME",
|
|
56
|
+
help="Plotting backend (default: getdist).",
|
|
57
|
+
)
|
|
58
|
+
parser.add_argument(
|
|
59
|
+
"--backend-kwargs",
|
|
60
|
+
type=loads,
|
|
61
|
+
metavar="JSON",
|
|
62
|
+
help="JSON object of backend-specific plotting options.",
|
|
63
|
+
)
|
|
64
|
+
return parser
|
|
65
|
+
|
|
66
|
+
|
|
67
|
+
def main(argv: Sequence[str] | None = None) -> None:
|
|
68
|
+
"""Load Fisher forecast files, plot them, and save the figure.
|
|
69
|
+
|
|
70
|
+
Parameters
|
|
71
|
+
----------
|
|
72
|
+
argv : sequence of str, optional
|
|
73
|
+
Arguments to parse. Defaults to the process command line.
|
|
74
|
+
"""
|
|
75
|
+
parser = _parser()
|
|
76
|
+
args = parser.parse_args(argv)
|
|
77
|
+
datasets = {}
|
|
78
|
+
for path in args.files:
|
|
79
|
+
label = path.stem
|
|
80
|
+
if label in datasets:
|
|
81
|
+
parser.error(
|
|
82
|
+
f"Input filenames must have unique stems; duplicate {label!r}."
|
|
83
|
+
)
|
|
84
|
+
datasets[label] = load_dataset(path)
|
|
85
|
+
|
|
86
|
+
figure = plot(
|
|
87
|
+
datasets,
|
|
88
|
+
parameters=args.parameters,
|
|
89
|
+
filled=args.filled,
|
|
90
|
+
backend=args.backend,
|
|
91
|
+
backend_kwargs=args.backend_kwargs,
|
|
92
|
+
)
|
|
93
|
+
figure.savefig(args.figure_file, dpi=args.figure_dpi)
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
if __name__ == "__main__":
|
|
97
|
+
main()
|