ci-deconvolve 0.1.0__py3-none-any.whl

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.
@@ -0,0 +1,3 @@
1
+ """Focused command-line package for CI-RL deconvolution."""
2
+
3
+ __version__ = "0.1.0"
ci_deconvolve/cli.py ADDED
@@ -0,0 +1,292 @@
1
+ from __future__ import annotations
2
+
3
+ import argparse
4
+ import logging
5
+ import shutil
6
+ import sys
7
+ import time
8
+ from pathlib import Path
9
+ from typing import Iterable
10
+
11
+ LOGGER = logging.getLogger("ci_deconvolve")
12
+
13
+ OME_TIFF_SUFFIXES = (".ome.tif", ".ome.tiff")
14
+ ZARR_SUFFIXES = (".zarr", ".ome.zarr")
15
+
16
+
17
+ def _require_torch() -> None:
18
+ try:
19
+ import torch # noqa: F401
20
+ except Exception as exc:
21
+ raise RuntimeError(
22
+ "PyTorch is required but is not installed or cannot be imported. "
23
+ "Install a CPU or CUDA PyTorch build first, then rerun ci_deconvolve. "
24
+ "See https://pytorch.org/get-started/locally/ for the current install command."
25
+ ) from exc
26
+
27
+
28
+ def _is_ome_tiff(path: Path) -> bool:
29
+ name = path.name.lower()
30
+ return path.is_file() and any(name.endswith(suffix) for suffix in OME_TIFF_SUFFIXES)
31
+
32
+
33
+ def _is_ome_zarr(path: Path) -> bool:
34
+ name = path.name.lower()
35
+ return path.is_dir() and any(name.endswith(suffix) for suffix in ZARR_SUFFIXES)
36
+
37
+
38
+ def _discover_inputs(path: Path) -> list[Path]:
39
+ if _is_ome_tiff(path) or _is_ome_zarr(path):
40
+ return [path]
41
+ if path.is_dir():
42
+ inputs = [
43
+ child
44
+ for child in sorted(path.iterdir(), key=lambda p: p.name.lower())
45
+ if _is_ome_tiff(child) or _is_ome_zarr(child)
46
+ ]
47
+ if inputs:
48
+ return inputs
49
+ raise ValueError(f"No OME-TIFF files or OME-Zarr folders found in {path}")
50
+ raise ValueError(
51
+ f"Unsupported input {path}. Expected .ome.tif/.ome.tiff, .zarr/.ome.zarr, "
52
+ "or a folder containing those inputs."
53
+ )
54
+
55
+
56
+ def _stem(path: Path) -> str:
57
+ name = path.name
58
+ lower = name.lower()
59
+ for suffix in (".ome.tiff", ".ome.tif", ".ome.zarr", ".zarr"):
60
+ if lower.endswith(suffix):
61
+ return name[: -len(suffix)]
62
+ return path.stem
63
+
64
+
65
+ def _parse_int_list(raw: str) -> list[int]:
66
+ values = []
67
+ for item in str(raw or "").replace(";", ",").split(","):
68
+ item = item.strip()
69
+ if not item:
70
+ continue
71
+ try:
72
+ values.append(max(1, int(float(item))))
73
+ except ValueError as exc:
74
+ raise argparse.ArgumentTypeError(f"Invalid iteration count: {item!r}") from exc
75
+ if not values:
76
+ raise argparse.ArgumentTypeError("At least one iteration count is required")
77
+ return values
78
+
79
+
80
+ def _parse_float_list(raw: str | None) -> list[float] | None:
81
+ if raw is None:
82
+ return None
83
+ values = []
84
+ for item in str(raw).replace(";", ",").split(","):
85
+ item = item.strip()
86
+ if not item:
87
+ continue
88
+ values.append(float(item))
89
+ return values or None
90
+
91
+
92
+ def _parse_float_or_auto(raw: str):
93
+ text = str(raw).strip().lower()
94
+ if text == "auto":
95
+ return "auto"
96
+ if text in {"none", "0", "0.0"}:
97
+ return 0.0
98
+ return float(text)
99
+
100
+
101
+ def _build_parser() -> argparse.ArgumentParser:
102
+ parser = argparse.ArgumentParser(
103
+ prog="ci_deconvolve",
104
+ description="Run CI-RL deconvolution on OME-TIFF and OME-Zarr inputs.",
105
+ )
106
+ parser.add_argument("input_path", nargs="?", help="Input file/folder. Alias for --input.")
107
+ parser.add_argument("--input", dest="input_option", help="OME-TIFF, OME-Zarr, or folder.")
108
+ parser.add_argument("--output", required=True, help="Output folder.")
109
+ parser.add_argument(
110
+ "--output-format",
111
+ choices=("ome-tiff", "ome-zarr"),
112
+ default="ome-tiff",
113
+ help="Output format. Default: ome-tiff.",
114
+ )
115
+ parser.add_argument("--iterations", type=_parse_int_list, default=[40])
116
+ parser.add_argument("--device", choices=("auto", "cpu", "cuda"), default="auto")
117
+ parser.add_argument("--background", default="auto")
118
+ parser.add_argument("--offset", default="auto")
119
+ parser.add_argument("--damping", default="none")
120
+ parser.add_argument("--prefilter-sigma", type=float, default=0.0)
121
+ parser.add_argument(
122
+ "--start",
123
+ choices=(
124
+ "auto",
125
+ "flat",
126
+ "percentile_flat",
127
+ "observed",
128
+ "observed_bgsub",
129
+ "lowpass",
130
+ "lowpass_bgsub",
131
+ "hybrid",
132
+ ),
133
+ default="auto",
134
+ )
135
+ parser.add_argument("--convergence", choices=("auto", "fixed", "none"), default="auto")
136
+ parser.add_argument("--rel-threshold", type=float, default=0.005)
137
+ parser.add_argument("--check-every", type=int, default=5)
138
+ parser.add_argument("--na", type=float, default=1.4)
139
+ parser.add_argument("--refractive-index", type=float, default=1.515)
140
+ parser.add_argument("--sample-ri", type=float, default=1.47)
141
+ parser.add_argument("--microscope-type", choices=("widefield", "confocal"), default="confocal")
142
+ parser.add_argument("--emission-wl", default="520")
143
+ parser.add_argument("--excitation-wl", default="488")
144
+ parser.add_argument("--pinhole-airy", default="1.0")
145
+ parser.add_argument("--pixel-size-xy", type=float, default=0.065, help="Micrometers.")
146
+ parser.add_argument("--pixel-size-z", type=float, default=0.2, help="Micrometers.")
147
+ parser.add_argument(
148
+ "--overrule-metadata",
149
+ action="store_true",
150
+ help="Use CLI metadata values even when image metadata is present.",
151
+ )
152
+ parser.add_argument(
153
+ "--two-d-mode",
154
+ choices=("auto", "legacy_2d"),
155
+ default="auto",
156
+ )
157
+ parser.add_argument(
158
+ "--two-d-wf-aggressiveness",
159
+ choices=("conservative", "balanced", "strong"),
160
+ default="balanced",
161
+ )
162
+ parser.add_argument("--two-d-wf-bg-radius-um", type=float, default=0.5)
163
+ parser.add_argument("--two-d-wf-bg-scale", type=float, default=1.0)
164
+ parser.add_argument("-v", "--verbose", action="store_true")
165
+ return parser
166
+
167
+
168
+ def _normalise_convergence(value: str) -> str:
169
+ return "fixed" if value == "none" else value
170
+
171
+
172
+ def _output_path(input_path: Path, output_dir: Path, output_format: str) -> Path:
173
+ if output_format == "ome-zarr":
174
+ return output_dir / f"{_stem(input_path)}_decon.ome.zarr"
175
+ return output_dir / f"{_stem(input_path)}_decon.ome.tiff"
176
+
177
+
178
+ def _run_one(input_path: Path, output_dir: Path, args: argparse.Namespace) -> Path:
179
+ from core.deconvolve import deconvolve_image, save_result
180
+ from core.ome_zarr_io import is_hcs_plate, save_result_ome_zarr
181
+
182
+ if _is_ome_zarr(input_path) and is_hcs_plate(input_path):
183
+ if args.output_format == "ome-tiff":
184
+ raise ValueError("HCS plate OME-Zarr input cannot be written as one OME-TIFF output.")
185
+ raise ValueError("HCS plate OME-Zarr output is not supported by the focused CLI yet.")
186
+
187
+ device = None if args.device == "auto" else args.device
188
+ result = deconvolve_image(
189
+ input_path,
190
+ method="ci_rl",
191
+ niter=args.iterations,
192
+ na=args.na,
193
+ refractive_index=args.refractive_index,
194
+ sample_refractive_index=args.sample_ri,
195
+ microscope_type=args.microscope_type,
196
+ emission_wavelengths=_parse_float_list(args.emission_wl),
197
+ excitation_wavelengths=_parse_float_list(args.excitation_wl),
198
+ pinhole_airy_units=_parse_float_list(args.pinhole_airy),
199
+ overrule_metadata=bool(args.overrule_metadata),
200
+ pixel_size_xy=args.pixel_size_xy,
201
+ pixel_size_z=args.pixel_size_z,
202
+ background=_parse_float_or_auto(args.background),
203
+ damping=_parse_float_or_auto(args.damping),
204
+ offset=_parse_float_or_auto(args.offset),
205
+ prefilter_sigma=max(0.0, float(args.prefilter_sigma)),
206
+ start=args.start,
207
+ convergence=_normalise_convergence(args.convergence),
208
+ rel_threshold=max(1e-8, float(args.rel_threshold)),
209
+ check_every=max(1, int(args.check_every)),
210
+ two_d_mode=args.two_d_mode,
211
+ two_d_wf_aggressiveness=args.two_d_wf_aggressiveness,
212
+ two_d_wf_bg_radius_um=max(0.1, float(args.two_d_wf_bg_radius_um)),
213
+ two_d_wf_bg_scale=max(0.1, float(args.two_d_wf_bg_scale)),
214
+ device=device,
215
+ )
216
+
217
+ out_path = _output_path(input_path, output_dir, args.output_format)
218
+ if args.output_format == "ome-zarr":
219
+ return save_result_ome_zarr(result, out_path)
220
+
221
+ tmp_dir = output_dir / ".ci_deconvolve_tmp"
222
+ tmp_dir.mkdir(parents=True, exist_ok=True)
223
+ tmp_path = tmp_dir / out_path.name
224
+ try:
225
+ save_result(result, tmp_path)
226
+ if out_path.exists():
227
+ out_path.unlink()
228
+ shutil.move(str(tmp_path), str(out_path))
229
+ finally:
230
+ shutil.rmtree(tmp_dir, ignore_errors=True)
231
+ return out_path
232
+
233
+
234
+ def run(argv: Iterable[str] | None = None) -> int:
235
+ parser = _build_parser()
236
+ args = parser.parse_args(list(argv) if argv is not None else None)
237
+ logging.basicConfig(
238
+ level=logging.INFO if args.verbose else logging.WARNING,
239
+ format="%(asctime)s [%(levelname)s] %(name)s: %(message)s",
240
+ )
241
+
242
+ input_value = args.input_option or args.input_path
243
+ if not input_value:
244
+ parser.error("an input path is required via --input or positional input_path")
245
+ input_path = Path(input_value)
246
+ output_dir = Path(args.output)
247
+
248
+ _require_torch()
249
+ inputs = _discover_inputs(input_path)
250
+ output_dir.mkdir(parents=True, exist_ok=True)
251
+
252
+ print("ci_deconvolve")
253
+ print(f" method : ci_rl")
254
+ print(f" input count : {len(inputs)}")
255
+ print(f" output : {output_dir}")
256
+ print(f" output format: {args.output_format}")
257
+ print(f" iterations : {', '.join(str(v) for v in args.iterations)}")
258
+
259
+ failures: list[tuple[Path, Exception]] = []
260
+ for index, item in enumerate(inputs, start=1):
261
+ print(f"\n[{index}/{len(inputs)}] {item}")
262
+ start = time.time()
263
+ try:
264
+ out_path = _run_one(item, output_dir, args)
265
+ print(f" saved: {out_path}")
266
+ print(f" time : {time.time() - start:.1f}s")
267
+ except Exception as exc:
268
+ failures.append((item, exc))
269
+ print(f" ERROR: {exc}", file=sys.stderr)
270
+
271
+ if failures:
272
+ print(f"\nFailed inputs: {len(failures)}", file=sys.stderr)
273
+ for item, exc in failures:
274
+ print(f" {item}: {exc}", file=sys.stderr)
275
+ return 1
276
+ print("\nci_deconvolve complete.")
277
+ return 0
278
+
279
+
280
+ def main(argv: Iterable[str] | None = None) -> int:
281
+ try:
282
+ return run(argv)
283
+ except KeyboardInterrupt:
284
+ print("Interrupted.", file=sys.stderr)
285
+ return 130
286
+ except Exception as exc:
287
+ print(f"ci_deconvolve failed: {exc}", file=sys.stderr)
288
+ return 1
289
+
290
+
291
+ if __name__ == "__main__":
292
+ raise SystemExit(main())
@@ -0,0 +1,232 @@
1
+ Metadata-Version: 2.4
2
+ Name: ci-deconvolve
3
+ Version: 0.1.0
4
+ Summary: Focused command-line CI-RL deconvolution for OME-TIFF and OME-Zarr images.
5
+ Author: NL-BioImaging contributors
6
+ License-Expression: MIT
7
+ Keywords: microscopy,deconvolution,ome-tiff,ome-zarr,richardson-lucy
8
+ Classifier: Development Status :: 3 - Alpha
9
+ Classifier: Intended Audience :: Science/Research
10
+ Classifier: Programming Language :: Python :: 3
11
+ Classifier: Programming Language :: Python :: 3.12
12
+ Classifier: Topic :: Scientific/Engineering :: Image Processing
13
+ Requires-Python: >=3.12
14
+ Description-Content-Type: text/markdown
15
+ Requires-Dist: numpy<3,>=1.26
16
+ Requires-Dist: Pillow>=10.0
17
+ Requires-Dist: tifffile>=2024.1.30
18
+ Requires-Dist: imagecodecs>=2024.1.1
19
+ Requires-Dist: bioio==3.2.0
20
+ Requires-Dist: bioio-ome-tiff==1.4.0
21
+ Requires-Dist: ome-zarr<0.19,>=0.18
22
+ Requires-Dist: numcodecs>=0.14
23
+ Provides-Extra: dev
24
+ Requires-Dist: pytest; extra == "dev"
25
+ Requires-Dist: build; extra == "dev"
26
+ Requires-Dist: twine; extra == "dev"
27
+
28
+ # ci-deconvolve
29
+
30
+ Focused command-line CI-RL deconvolution for OME-TIFF and OME-Zarr images.
31
+
32
+ This package installs the `ci_deconvolve` command. On Windows, `pip` also
33
+ creates a `ci_deconvolve.exe` console launcher in the active environment.
34
+
35
+ ## Prerequisite: PyTorch
36
+
37
+ PyTorch is required but is not bundled in this package. Install the CPU or CUDA
38
+ build that matches your system before running `ci_deconvolve`.
39
+
40
+ Examples:
41
+
42
+ ```bash
43
+ pip install torch
44
+ ```
45
+
46
+ or install a CUDA build using the command from:
47
+
48
+ ```text
49
+ https://pytorch.org/get-started/locally/
50
+ ```
51
+
52
+ ## Install
53
+
54
+ From this folder during development:
55
+
56
+ ```bash
57
+ pip install -e .
58
+ ```
59
+
60
+ From PyPI after publishing:
61
+
62
+ ```bash
63
+ pip install ci-deconvolve
64
+ ```
65
+
66
+ The package depends on `ome-zarr` for OME-Zarr reading and writing. `zarr` is
67
+ installed transitively by `ome-zarr`; it is not declared as a direct dependency.
68
+
69
+ ## Usage
70
+
71
+ Run one OME-TIFF file:
72
+
73
+ ```bash
74
+ ci_deconvolve --input image.ome.tiff --output out
75
+ ```
76
+
77
+ Run one OME-Zarr image:
78
+
79
+ ```bash
80
+ ci_deconvolve --input image.ome.zarr --output out --output-format ome-zarr
81
+ ```
82
+
83
+ Run every supported immediate child in a folder:
84
+
85
+ ```bash
86
+ ci_deconvolve --input in_folder --output out_folder --iterations 40
87
+ ```
88
+
89
+ Only these inputs are accepted:
90
+
91
+ - `.ome.tif`
92
+ - `.ome.tiff`
93
+ - `.zarr` / `.ome.zarr` directories
94
+
95
+ The CLI always runs `ci_rl`. It intentionally has no `--method` option.
96
+
97
+ ## Examples
98
+
99
+ ```bash
100
+ ci_deconvolve --input image.ome.tiff --output out ^
101
+ --iterations 40 ^
102
+ --device auto ^
103
+ --output-format ome-tiff ^
104
+ --emission-wl 520 ^
105
+ --excitation-wl 488 ^
106
+ --pixel-size-xy 0.065 ^
107
+ --pixel-size-z 0.2
108
+ ```
109
+
110
+ Use `--overrule-metadata` when CLI metadata values should replace image
111
+ metadata. Without it, CLI metadata values are used as fallbacks.
112
+
113
+ Per-channel values can be comma-separated. If there are more channels than
114
+ values, the last value is reused for the remaining channels.
115
+
116
+ ```bash
117
+ ci_deconvolve --input image.ome.tiff --output out ^
118
+ --iterations 40,60,80 ^
119
+ --emission-wl 520,610 ^
120
+ --excitation-wl 488,561 ^
121
+ --pinhole-airy 1.0,1.2
122
+ ```
123
+
124
+ ## Parameters
125
+
126
+ ### Required Paths
127
+
128
+ | Option | Default | Description |
129
+ | --- | --- | --- |
130
+ | `input_path` | none | Optional positional input path. Use this or `--input`. |
131
+ | `--input PATH` | none | Input OME-TIFF file, OME-Zarr folder, or folder containing supported inputs. |
132
+ | `--output DIR` | required | Output folder. Created if it does not exist. |
133
+
134
+ Supported inputs are immediate files/folders only:
135
+
136
+ - `.ome.tif`
137
+ - `.ome.tiff`
138
+ - `.zarr` / `.ome.zarr` directories
139
+
140
+ HCS plate OME-Zarr inputs are detected and rejected clearly; this focused CLI
141
+ does not process plate fields.
142
+
143
+ ### Output And Compute
144
+
145
+ | Option | Default | Description |
146
+ | --- | --- | --- |
147
+ | `--output-format ome-tiff\|ome-zarr` | `ome-tiff` | Writes `<stem>_decon.ome.tiff` or `<stem>_decon.ome.zarr`. |
148
+ | `--iterations N[,N...]` | `40` | CI-RL iteration count. A comma- or semicolon-separated list applies per channel, with the last value reused for extra channels. |
149
+ | `--device auto\|cpu\|cuda` | `auto` | Compute device. `auto` lets PyTorch choose CUDA when available, otherwise CPU. |
150
+ | `-v`, `--verbose` | off | Enable INFO logging from the CLI and core deconvolution code. |
151
+
152
+ ### CI-RL Solver
153
+
154
+ | Option | Default | Description |
155
+ | --- | --- | --- |
156
+ | `--background VALUE\|auto` | `auto` | Background level used by the solver. `auto` estimates it from the image. Numeric values are accepted. |
157
+ | `--offset VALUE\|auto\|none` | `auto` | Positive offset added before iteration and removed afterwards. Use `none`, `0`, or `0.0` to disable. |
158
+ | `--damping VALUE\|auto\|none` | `none` | Noise-gated damping strength. Use `auto` for automatic damping, numeric values for manual damping, or `none`/`0` to disable. |
159
+ | `--prefilter-sigma VALUE` | `0.0` | Optional Anscombe/low-pass prefilter sigma. `0.0` disables prefiltering. |
160
+ | `--start MODE` | `auto` | Initial estimate mode. Choices: `auto`, `flat`, `percentile_flat`, `observed`, `observed_bgsub`, `lowpass`, `lowpass_bgsub`, `hybrid`. |
161
+ | `--convergence auto\|fixed\|none` | `auto` | `auto` enables early stopping based on convergence. `fixed` and `none` both run the requested iteration count. |
162
+ | `--rel-threshold VALUE` | `0.005` | Relative convergence threshold used when `--convergence auto`. Values are clamped to at least `1e-8`. |
163
+ | `--check-every N` | `5` | Check convergence every N iterations. Values below 1 are clamped to 1. |
164
+
165
+ ### Metadata And PSF
166
+
167
+ These values are used to generate the point spread function. By default, image
168
+ metadata wins and CLI values fill in missing metadata. With
169
+ `--overrule-metadata`, CLI values replace image metadata.
170
+
171
+ | Option | Default | Description |
172
+ | --- | --- | --- |
173
+ | `--na VALUE` | `1.4` | Numerical aperture. |
174
+ | `--refractive-index VALUE` | `1.515` | Immersion medium refractive index, typically oil. |
175
+ | `--sample-ri VALUE` | `1.47` | Sample medium refractive index. |
176
+ | `--microscope-type widefield\|confocal` | `confocal` | Microscope model used for PSF generation. |
177
+ | `--emission-wl VALUE[,VALUE...]` | `520` | Emission wavelength(s), in nm. Per-channel list supported. |
178
+ | `--excitation-wl VALUE[,VALUE...]` | `488` | Excitation wavelength(s), in nm. Per-channel list supported. |
179
+ | `--pinhole-airy VALUE[,VALUE...]` | `1.0` | Confocal pinhole diameter in Airy units. Per-channel list supported. |
180
+ | `--pixel-size-xy VALUE` | `0.065` | Lateral pixel size in micrometers. Applied to X and Y. |
181
+ | `--pixel-size-z VALUE` | `0.2` | Axial pixel size in micrometers. |
182
+ | `--overrule-metadata` | off | Replace image metadata with CLI metadata values instead of only using CLI values as fallbacks. |
183
+
184
+ List syntax:
185
+
186
+ ```bash
187
+ --emission-wl 520,610
188
+ --excitation-wl 488;561
189
+ --iterations 30,40,50
190
+ ```
191
+
192
+ Commas and semicolons are both accepted.
193
+
194
+ ### 2D Widefield Options
195
+
196
+ These only affect 2D widefield data when `--microscope-type widefield` and
197
+ `--two-d-mode auto` are used.
198
+
199
+ | Option | Default | Description |
200
+ | --- | --- | --- |
201
+ | `--two-d-mode auto\|legacy_2d` | `auto` | `auto` enables the enhanced 2D widefield path. `legacy_2d` uses the historical pure-2D PSF behavior. |
202
+ | `--two-d-wf-aggressiveness conservative\|balanced\|strong` | `balanced` | Strength preset for the enhanced 2D widefield model. |
203
+ | `--two-d-wf-bg-radius-um VALUE` | `0.5` | Background-estimation radius in micrometers. Values below `0.1` are clamped to `0.1`. |
204
+ | `--two-d-wf-bg-scale VALUE` | `1.0` | Multiplier for the estimated 2D widefield background. Values below `0.1` are clamped to `0.1`. |
205
+
206
+ ## Metadata Override Behavior
207
+
208
+ Without `--overrule-metadata`:
209
+
210
+ - Existing OME metadata is preserved.
211
+ - CLI metadata values are used only when a value is missing or invalid.
212
+ - This is the recommended mode for well-annotated OME-TIFF or OME-Zarr data.
213
+
214
+ With `--overrule-metadata`:
215
+
216
+ - CLI metadata values replace image metadata.
217
+ - Use this when source metadata is known to be wrong, incomplete, or converted
218
+ with incorrect physical pixel sizes or wavelengths.
219
+
220
+ Example:
221
+
222
+ ```bash
223
+ ci_deconvolve --input image.ome.tiff --output out ^
224
+ --overrule-metadata ^
225
+ --microscope-type widefield ^
226
+ --na 1.40 ^
227
+ --refractive-index 1.515 ^
228
+ --sample-ri 1.47 ^
229
+ --pixel-size-xy 0.065 ^
230
+ --pixel-size-z 0.200 ^
231
+ --emission-wl 520,610
232
+ ```
@@ -0,0 +1,12 @@
1
+ ci_deconvolve/__init__.py,sha256=6KvpHMilH5eQK56n8a7npW11k1soiTXAUIsPaG-RAs4,83
2
+ ci_deconvolve/cli.py,sha256=b1jS5DoYKKLe419xAG1RTZrzFlEKbSe9IsW-y2mQlow,10536
3
+ core/__init__.py,sha256=-yMZ_O1WisEVjusjWyUbj3Q8o4q2C8EU8cdsvgAq-L8,460
4
+ core/_meta_helpers.py,sha256=2VndQriokjD_BVsy1MyE__DPbuOr96iL5GDHTc5PZmY,11223
5
+ core/deconvolve.py,sha256=2mgDsc3XlBu-WLYgfa2bs298tEtR8BUYpczQrCw8Zro,62327
6
+ core/deconvolve_ci.py,sha256=sX1M0aONkB_Zaf1WbUygnaTMdyfFHQwzYVfw5PsAYws,80379
7
+ core/ome_zarr_io.py,sha256=0zmHwJYKGdkgRkr_0KN9xK1f4dKFHO_GVHvsCoSyp8w,8968
8
+ ci_deconvolve-0.1.0.dist-info/METADATA,sha256=V3l4XRg-637uAggxqSVsiFxg3BQ6cZP1Gv3wwKyBvrM,8455
9
+ ci_deconvolve-0.1.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
10
+ ci_deconvolve-0.1.0.dist-info/entry_points.txt,sha256=CUy5vVJU6ZzAmnfjI-qduljcgZCMpdsMrA-Zi3g85qo,57
11
+ ci_deconvolve-0.1.0.dist-info/top_level.txt,sha256=76r0e8VMIoGrdcRgh-lsaWbI8bvBgRn64LkZgd70hIg,19
12
+ ci_deconvolve-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (82.0.1)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ ci_deconvolve = ci_deconvolve.cli:main
@@ -0,0 +1,2 @@
1
+ ci_deconvolve
2
+ core
core/__init__.py ADDED
@@ -0,0 +1,23 @@
1
+ """Focused core package for the ci_deconvolve CLI."""
2
+
3
+ from .deconvolve import (
4
+ deconvolve,
5
+ deconvolve_image,
6
+ generate_psf,
7
+ load_image,
8
+ save_mip_png,
9
+ save_result,
10
+ _DEFAULT_PINHOLE_AIRY_UNITS,
11
+ _apply_pinhole_airy_units,
12
+ )
13
+
14
+ __all__ = [
15
+ "deconvolve",
16
+ "deconvolve_image",
17
+ "generate_psf",
18
+ "load_image",
19
+ "save_mip_png",
20
+ "save_result",
21
+ "_DEFAULT_PINHOLE_AIRY_UNITS",
22
+ "_apply_pinhole_airy_units",
23
+ ]