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 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()