oct-to-tiff 0.6.0__tar.gz → 0.6.1__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.
@@ -1,14 +1,12 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: oct-to-tiff
3
- Version: 0.6.0
3
+ Version: 0.6.1
4
4
  Summary: A command line tool for converting optical coherence tomography angiography (OCTA) data.
5
+ Keywords: angiography,cli,oct,octa
6
+ Author: Cameron Lloyd
5
7
  Author-email: Cameron Lloyd <lloyd@med.unideb.hu>
6
- Maintainer-email: Cameron Lloyd <lloyd@med.unideb.hu>
7
8
  License-Expression: BSD-3-Clause
8
- Project-URL: Homepage, https://github.com/camlloyd/oct-to-tiff
9
- Project-URL: Bug Tracker, https://github.com/camlloyd/oct-to-tiff/issues
10
- Project-URL: Changelog, https://github.com/camlloyd/oct-to-tiff/blob/main/CHANGELOG.md
11
- Keywords: angiography,cli,oct,octa
9
+ License-File: LICENSE.txt
12
10
  Classifier: Development Status :: 3 - Alpha
13
11
  Classifier: Intended Audience :: Science/Research
14
12
  Classifier: Natural Language :: English
@@ -18,18 +16,21 @@ Classifier: Programming Language :: Python :: 3.11
18
16
  Classifier: Programming Language :: Python :: 3.12
19
17
  Classifier: Programming Language :: Python :: 3.13
20
18
  Classifier: Programming Language :: Python :: 3.14
21
- Requires-Python: >=3.11
22
- Description-Content-Type: text/markdown
23
- License-File: LICENSE.txt
24
19
  Requires-Dist: defusedxml
25
20
  Requires-Dist: numpy
26
21
  Requires-Dist: roifile
27
22
  Requires-Dist: tifffile
23
+ Requires-Dist: mypy ; extra == 'dev'
24
+ Requires-Dist: ruff ; extra == 'dev'
25
+ Requires-Dist: types-defusedxml ; extra == 'dev'
26
+ Maintainer: Cameron Lloyd
27
+ Maintainer-email: Cameron Lloyd <lloyd@med.unideb.hu>
28
+ Requires-Python: >=3.11
29
+ Project-URL: Homepage, https://github.com/camlloyd/oct-to-tiff
30
+ Project-URL: Bug Tracker, https://github.com/camlloyd/oct-to-tiff/issues
31
+ Project-URL: Changelog, https://github.com/camlloyd/oct-to-tiff/blob/main/CHANGELOG.md
28
32
  Provides-Extra: dev
29
- Requires-Dist: mypy; extra == "dev"
30
- Requires-Dist: ruff; extra == "dev"
31
- Requires-Dist: types-defusedxml; extra == "dev"
32
- Dynamic: license-file
33
+ Description-Content-Type: text/markdown
33
34
 
34
35
  # oct-to-tiff
35
36
 
@@ -46,9 +47,9 @@ via pip:
46
47
 
47
48
  pip install oct-to-tiff
48
49
 
49
- via mamba:
50
+ via conda:
50
51
 
51
- mamba install -c conda-forge oct-to-tiff
52
+ conda install conda-forge::oct-to-tiff
52
53
 
53
54
  ## Getting started
54
55
  oct-to-tiff /path/to/image.OCT
@@ -186,4 +187,4 @@ This project uses [Ruff](https://github.com/astral-sh/ruff) for linting and form
186
187
 
187
188
  ## Requirements
188
189
 
189
- Requires Python 3.11 or higher.
190
+ Requires Python 3.11 or higher.
@@ -13,9 +13,9 @@ via pip:
13
13
 
14
14
  pip install oct-to-tiff
15
15
 
16
- via mamba:
16
+ via conda:
17
17
 
18
- mamba install -c conda-forge oct-to-tiff
18
+ conda install conda-forge::oct-to-tiff
19
19
 
20
20
  ## Getting started
21
21
  oct-to-tiff /path/to/image.OCT
@@ -1,10 +1,10 @@
1
1
  [build-system]
2
- requires = ["setuptools >= 77.0.3"]
3
- build-backend = "setuptools.build_meta"
2
+ requires = ["uv_build>=0.9.26,<0.10.0"]
3
+ build-backend = "uv_build"
4
4
 
5
5
  [project]
6
6
  name = "oct-to-tiff"
7
- version = "0.6.0"
7
+ version = "0.6.1"
8
8
  dependencies = [
9
9
  "defusedxml",
10
10
  "numpy",
@@ -46,8 +46,9 @@ Changelog = "https://github.com/camlloyd/oct-to-tiff/blob/main/CHANGELOG.md"
46
46
  [project.scripts]
47
47
  oct-to-tiff = "oct_to_tiff.cli:main"
48
48
 
49
- [tool.setuptools.packages.find]
50
- where = ["src"]
49
+ [tool.semantic_release]
50
+ allow_zero_version = "true"
51
+ version_toml = ["pyproject.toml:project.version"]
51
52
 
52
53
  [tool.ruff.lint]
53
54
  select = [
@@ -52,12 +52,47 @@ def reshape_volume(
52
52
  return volume
53
53
 
54
54
 
55
+ def volume_metadata(
56
+ pixel_size_x: float | None,
57
+ pixel_size_y: float | None,
58
+ pixel_size_z: float | None,
59
+ ) -> dict[str, Any]:
60
+ """Build a dictionary of metadata.
61
+
62
+ Parameters
63
+ ----------
64
+ pixel_size_x : float | None
65
+ The pixel (voxel) width in mm.
66
+ pixel_size_y : float | None
67
+ The pixel (voxel) height in mm.
68
+ pixel_size_z : float | None
69
+ The pixel (voxel) depth in mm.
70
+
71
+ Returns
72
+ -------
73
+ metadata : dict[str, Any]
74
+ A dictionary of metadata.
75
+
76
+ """
77
+ metadata: dict[str, Any] = {"axes": "ZYX"}
78
+ if pixel_size_x is not None:
79
+ metadata["PhysicalSizeX"] = pixel_size_x
80
+ metadata["PhysicalSizeXUnit"] = "mm"
81
+ if pixel_size_y is not None:
82
+ metadata["PhysicalSizeY"] = pixel_size_y
83
+ metadata["PhysicalSizeYUnit"] = "mm"
84
+ if pixel_size_z is not None:
85
+ metadata["PhysicalSizeZ"] = pixel_size_z
86
+ metadata["PhysicalSizeZUnit"] = "mm"
87
+ return metadata
88
+
89
+
55
90
  def write_volume(
56
91
  output_path: Path,
57
92
  volume: npt.NDArray[Any],
58
- pixel_size_x: float,
59
- pixel_size_y: float,
60
- pixel_size_z: float,
93
+ pixel_size_x: float | None,
94
+ pixel_size_y: float | None,
95
+ pixel_size_z: float | None,
61
96
  ) -> None:
62
97
  """Write a 3-dimensional array to the output path as an OME-TIFF file, including voxel size in the metadata.
63
98
 
@@ -79,15 +114,7 @@ def write_volume(
79
114
  output_path,
80
115
  volume,
81
116
  photometric="minisblack",
82
- metadata={
83
- "axes": "ZYX",
84
- "PhysicalSizeX": pixel_size_x,
85
- "PhysicalSizeXUnit": "mm",
86
- "PhysicalSizeY": pixel_size_y,
87
- "PhysicalSizeYUnit": "mm",
88
- "PhysicalSizeZ": pixel_size_z,
89
- "PhysicalSizeZUnit": "mm",
90
- },
117
+ metadata=volume_metadata(pixel_size_x, pixel_size_y, pixel_size_z),
91
118
  )
92
119
 
93
120
 
@@ -245,7 +272,7 @@ def main() -> None:
245
272
  xy_scan_length = int(len(volume) ** 0.5)
246
273
  pixel_size_x = args.size / oct_window_height
247
274
  pixel_size_y = args.size / xy_scan_length
248
- pixel_size_z = 1
275
+ pixel_size_z = None
249
276
  elif args.seg_curve:
250
277
  volume = np.frombuffer(f.read(), dtype=np.single)
251
278
  if len(volume) == 1280000 or len(volume) == 1120000:
@@ -256,9 +283,9 @@ def main() -> None:
256
283
  oct_window_height = 304
257
284
  total_data_groups = 1
258
285
  xy_scan_length = len(volume) // (frames_per_data_group * oct_window_height)
259
- pixel_size_x = 1
260
- pixel_size_y = 1
261
- pixel_size_z = 1
286
+ pixel_size_x = None
287
+ pixel_size_y = None
288
+ pixel_size_z = None
262
289
  elif "3D Cornea" in file_name:
263
290
  volume = np.frombuffer(f.read(), dtype=np.single)
264
291
  frames_per_data_group = 106
@@ -338,7 +365,7 @@ def main() -> None:
338
365
  xy_scan_length = 1020
339
366
  pixel_size_x = 0.002941
340
367
  pixel_size_y = 0.003071
341
- pixel_size_z = 1
368
+ pixel_size_z = None
342
369
  elif "Cornea Cross Line" in file_name:
343
370
  volume = np.frombuffer(f.read(), dtype=np.single)
344
371
  frames_per_data_group = 2
@@ -347,7 +374,7 @@ def main() -> None:
347
374
  xy_scan_length = 941
348
375
  pixel_size_x = 0.008502
349
376
  pixel_size_y = 0.003071
350
- pixel_size_z = 1
377
+ pixel_size_z = None
351
378
  elif "Cornea Line" in file_name:
352
379
  volume = np.frombuffer(f.read(), dtype=np.single)
353
380
  frames_per_data_group = 1
@@ -356,7 +383,7 @@ def main() -> None:
356
383
  xy_scan_length = 1020
357
384
  pixel_size_x = 0.007843
358
385
  pixel_size_y = 0.003071
359
- pixel_size_z = 1
386
+ pixel_size_z = None
360
387
  elif "Cross Line" in file_name:
361
388
  volume = np.frombuffer(f.read(), dtype=np.single)
362
389
  frames_per_data_group = 2
@@ -365,7 +392,7 @@ def main() -> None:
365
392
  xy_scan_length = 1020
366
393
  pixel_size_x = 0.009804
367
394
  pixel_size_y = 0.003071
368
- pixel_size_z = 1
395
+ pixel_size_z = None
369
396
  elif "Enhanced HD Line" in file_name:
370
397
  volume = np.frombuffer(f.read(), dtype=np.single)
371
398
  frames_per_data_group = 1
@@ -374,7 +401,7 @@ def main() -> None:
374
401
  xy_scan_length = 998
375
402
  pixel_size_x = 0.012024
376
403
  pixel_size_y = 0.003071
377
- pixel_size_z = 1
404
+ pixel_size_z = None
378
405
  elif "GCC" in file_name:
379
406
  volume = np.frombuffer(f.read(), dtype=np.single)
380
407
  frames_per_data_group = 16
@@ -383,7 +410,7 @@ def main() -> None:
383
410
  xy_scan_length = 933
384
411
  pixel_size_x = 0.007503
385
412
  pixel_size_y = 0.003071
386
- pixel_size_z = 1
413
+ pixel_size_z = None
387
414
  elif "Grid" in file_name:
388
415
  volume = np.frombuffer(f.read(), dtype=np.single)
389
416
  frames_per_data_group = 10
@@ -392,7 +419,7 @@ def main() -> None:
392
419
  xy_scan_length = 1020
393
420
  pixel_size_x = 0.005882
394
421
  pixel_size_y = 0.003071
395
- pixel_size_z = 1
422
+ pixel_size_z = None
396
423
  elif "HD Angio Disc" in file_name:
397
424
  volume = np.frombuffer(f.read(), dtype=np.single)
398
425
  frames_per_data_group = 400
@@ -446,7 +473,7 @@ def main() -> None:
446
473
  xy_scan_length = 1024
447
474
  pixel_size_x = 0.009766
448
475
  pixel_size_y = 0.003071
449
- pixel_size_z = 1
476
+ pixel_size_z = None
450
477
  elif "Line" in file_name:
451
478
  volume = np.frombuffer(f.read(), dtype=np.single)
452
479
  frames_per_data_group = 1
@@ -455,7 +482,7 @@ def main() -> None:
455
482
  xy_scan_length = 1020
456
483
  pixel_size_x = 0.008824
457
484
  pixel_size_y = 0.003071
458
- pixel_size_z = 1
485
+ pixel_size_z = None
459
486
  elif "ONH" in file_name:
460
487
  volume = np.frombuffer(f.read(), dtype=np.single, count=2223360)
461
488
  frames_per_data_group = 3
@@ -464,7 +491,7 @@ def main() -> None:
464
491
  xy_scan_length = 965
465
492
  pixel_size_x = 0.015952
466
493
  pixel_size_y = 0.003071
467
- pixel_size_z = 1
494
+ pixel_size_z = None
468
495
  elif "PachymetryWide" in file_name:
469
496
  volume = np.frombuffer(f.read(), dtype=np.single)
470
497
  frames_per_data_group = 16
@@ -473,7 +500,7 @@ def main() -> None:
473
500
  xy_scan_length = 1536
474
501
  pixel_size_x = 0.005859
475
502
  pixel_size_y = 0.003071
476
- pixel_size_z = 1
503
+ pixel_size_z = None
477
504
  elif "Raster" in file_name:
478
505
  volume = np.frombuffer(f.read(), dtype=np.single)
479
506
  frames_per_data_group = 21
@@ -482,7 +509,7 @@ def main() -> None:
482
509
  xy_scan_length = 1020
483
510
  pixel_size_x = 0.011765
484
511
  pixel_size_y = 0.003071
485
- pixel_size_z = 1
512
+ pixel_size_z = None
486
513
  elif "Retina Map" in file_name:
487
514
  volume = np.frombuffer(f.read(), dtype=np.single, count=6680960)
488
515
  frames_per_data_group = 13
@@ -491,7 +518,7 @@ def main() -> None:
491
518
  xy_scan_length = 803
492
519
  pixel_size_x = 0.007472
493
520
  pixel_size_y = 0.003071
494
- pixel_size_z = 1
521
+ pixel_size_z = None
495
522
 
496
523
  volume = reshape_volume(
497
524
  volume,
@@ -1,189 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: oct-to-tiff
3
- Version: 0.6.0
4
- Summary: A command line tool for converting optical coherence tomography angiography (OCTA) data.
5
- Author-email: Cameron Lloyd <lloyd@med.unideb.hu>
6
- Maintainer-email: Cameron Lloyd <lloyd@med.unideb.hu>
7
- License-Expression: BSD-3-Clause
8
- Project-URL: Homepage, https://github.com/camlloyd/oct-to-tiff
9
- Project-URL: Bug Tracker, https://github.com/camlloyd/oct-to-tiff/issues
10
- Project-URL: Changelog, https://github.com/camlloyd/oct-to-tiff/blob/main/CHANGELOG.md
11
- Keywords: angiography,cli,oct,octa
12
- Classifier: Development Status :: 3 - Alpha
13
- Classifier: Intended Audience :: Science/Research
14
- Classifier: Natural Language :: English
15
- Classifier: Operating System :: OS Independent
16
- Classifier: Programming Language :: Python :: 3
17
- Classifier: Programming Language :: Python :: 3.11
18
- Classifier: Programming Language :: Python :: 3.12
19
- Classifier: Programming Language :: Python :: 3.13
20
- Classifier: Programming Language :: Python :: 3.14
21
- Requires-Python: >=3.11
22
- Description-Content-Type: text/markdown
23
- License-File: LICENSE.txt
24
- Requires-Dist: defusedxml
25
- Requires-Dist: numpy
26
- Requires-Dist: roifile
27
- Requires-Dist: tifffile
28
- Provides-Extra: dev
29
- Requires-Dist: mypy; extra == "dev"
30
- Requires-Dist: ruff; extra == "dev"
31
- Requires-Dist: types-defusedxml; extra == "dev"
32
- Dynamic: license-file
33
-
34
- # oct-to-tiff
35
-
36
- [![DOI](https://zenodo.org/badge/382486199.svg)](https://zenodo.org/badge/latestdoi/382486199)
37
- [![PyPI - Version](https://img.shields.io/pypi/v/oct-to-tiff)](https://pypi.org/project/oct-to-tiff)
38
- [![PyPI - License](https://img.shields.io/pypi/l/oct-to-tiff)](https://github.com/camlloyd/oct-to-tiff/blob/main/LICENSE.txt)
39
- [![PyPI Downloads](https://static.pepy.tech/badge/oct-to-tiff)](https://pepy.tech/projects/oct-to-tiff)
40
-
41
-
42
- A command line tool for converting optical coherence tomography angiography (OCTA) data.
43
-
44
- ## Installation
45
- via pip:
46
-
47
- pip install oct-to-tiff
48
-
49
- via mamba:
50
-
51
- mamba install -c conda-forge oct-to-tiff
52
-
53
- ## Getting started
54
- oct-to-tiff /path/to/image.OCT
55
-
56
- will read an OCT volume and write to a single OME-TIFF file, including voxel size in the metadata.
57
-
58
- By default, the output file will be written with the same name as the input file and to the same directory:
59
-
60
-
61
- tree /path/to/images
62
- ├── image.OCT
63
- └── image.ome.tif
64
-
65
- To specify a custom output directory, see [Optional arguments](#optional-arguments) below.
66
-
67
- ## Batch processing
68
- ``` bash
69
- for file in *.OCT; do oct-to-tiff "${file}"; done
70
- ```
71
- will convert all OCT volumes in the current directory to OME-TIFF files, including voxel size in the metadata.
72
-
73
- ## Supported scan patterns
74
-
75
- This tool has been developed by reverse engineering data from the Optovue RTVue XR Avanti System.
76
-
77
- Due to limited test data, only the following scan patterns are currently supported:
78
-
79
- ### Structural OCT
80
- - 3D Cornea
81
- - 3D Disc
82
- - 3D Retina
83
- - 3D Widefield
84
- - 3D Widefield MCT
85
- - Angle
86
- - Cornea Cross Line
87
- - Cornea Line
88
- - Cross Line
89
- - Enhanced HD Line
90
- - GCC
91
- - Grid
92
- - Line
93
- - ONH (Partial)
94
- - Pachymetry Wide
95
- - Radial Lines
96
- - Raster
97
- - Retina Map (Partial)
98
-
99
- ### OCT Angiography
100
- - Angio Disc
101
- - Angio Retina
102
- - HD Angio Disc
103
- - HD Angio Retina
104
-
105
-
106
- ## Optional arguments
107
-
108
- To view these options at any time, run `oct-to-tiff --help`.
109
-
110
- #### `--output OUTPUT`
111
- **Description**: specify a custom output directory.
112
-
113
- If the path to the output directory does not exist, a new directory (and parent directories) will be created.
114
-
115
- **Usage**:
116
-
117
- oct-to-tiff /path/to/image.OCT --output /path/to/output/directory
118
-
119
- #### `--overwrite`
120
- **Description**: overwrite output file if it exists.
121
-
122
- **Usage**:
123
-
124
- oct-to-tiff /path/to/image.OCT --overwrite
125
-
126
- #### `--size SIZE`
127
- **Description**: scan size in mm.
128
-
129
- Sets the correct voxel size for scan patterns with adjustable length.
130
-
131
- **Usage**:
132
-
133
- oct-to-tiff /path/to/image.OCT --size 4.5
134
-
135
- #### `--log-level LEVEL`
136
- **Description**: sets the logging level (default: `WARNING`)
137
-
138
- **Usage**:
139
-
140
- oct-to-tiff /path/to/image.OCT --log-level INFO
141
-
142
- #### `--version`
143
- **Description**: show program's version number and exit.
144
-
145
- **Usage**:
146
-
147
- oct-to-tiff --version
148
-
149
- #### The following options are mutually exclusive:
150
-
151
- #### `--angio`
152
- **Description**: convert extracted OCTA data.
153
-
154
- Requires `--size SIZE`.
155
-
156
- **Usage**:
157
-
158
- oct-to-tiff /path/to/data --angio --size 4.5
159
-
160
- #### `--en-face`
161
- **Description**: convert extracted en face data.
162
-
163
- Requires `--size SIZE`.
164
-
165
- **Usage**:
166
-
167
- oct-to-tiff /path/to/data --en-face --size 4.5
168
-
169
- #### `--seg-curve`
170
- **Description**: convert extracted segmentation data.
171
-
172
- **Usage**:
173
-
174
- oct-to-tiff /path/to/data --seg-curve
175
-
176
- #### `--boundaries`
177
- **Description**: extract segmentation lines.
178
-
179
- **Usage**:
180
-
181
- oct-to-tiff /path/to/curve.xml --boundaries
182
-
183
- ## Contributing
184
-
185
- This project uses [Ruff](https://github.com/astral-sh/ruff) for linting and formatting.
186
-
187
- ## Requirements
188
-
189
- Requires Python 3.11 or higher.
@@ -1,4 +0,0 @@
1
- [egg_info]
2
- tag_build =
3
- tag_date = 0
4
-
@@ -1,11 +0,0 @@
1
- LICENSE.txt
2
- README.md
3
- pyproject.toml
4
- src/oct_to_tiff/__init__.py
5
- src/oct_to_tiff/cli.py
6
- src/oct_to_tiff.egg-info/PKG-INFO
7
- src/oct_to_tiff.egg-info/SOURCES.txt
8
- src/oct_to_tiff.egg-info/dependency_links.txt
9
- src/oct_to_tiff.egg-info/entry_points.txt
10
- src/oct_to_tiff.egg-info/requires.txt
11
- src/oct_to_tiff.egg-info/top_level.txt
@@ -1,2 +0,0 @@
1
- [console_scripts]
2
- oct-to-tiff = oct_to_tiff.cli:main
@@ -1,9 +0,0 @@
1
- defusedxml
2
- numpy
3
- roifile
4
- tifffile
5
-
6
- [dev]
7
- mypy
8
- ruff
9
- types-defusedxml
@@ -1 +0,0 @@
1
- oct_to_tiff
File without changes