thyra 1.27.2__tar.gz → 2.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. {thyra-1.27.2 → thyra-2.0.0}/PKG-INFO +7 -8
  2. {thyra-1.27.2 → thyra-2.0.0}/README.md +1 -1
  3. {thyra-1.27.2 → thyra-2.0.0}/pyproject.toml +26 -24
  4. {thyra-1.27.2 → thyra-2.0.0}/thyra/__init__.py +1 -1
  5. {thyra-1.27.2 → thyra-2.0.0}/thyra/converters/spatialdata/base_spatialdata_converter.py +0 -64
  6. {thyra-1.27.2 → thyra-2.0.0}/thyra/metadata/extractors/waters_extractor.py +5 -2
  7. {thyra-1.27.2 → thyra-2.0.0}/thyra/tools/make_example_data.py +5 -1
  8. {thyra-1.27.2 → thyra-2.0.0}/LICENSE +0 -0
  9. {thyra-1.27.2 → thyra-2.0.0}/thyra/__main__.py +0 -0
  10. {thyra-1.27.2 → thyra-2.0.0}/thyra/alignment/__init__.py +0 -0
  11. {thyra-1.27.2 → thyra-2.0.0}/thyra/alignment/affine.py +0 -0
  12. {thyra-1.27.2 → thyra-2.0.0}/thyra/alignment/teaching_points.py +0 -0
  13. {thyra-1.27.2 → thyra-2.0.0}/thyra/config.py +0 -0
  14. {thyra-1.27.2 → thyra-2.0.0}/thyra/convert.py +0 -0
  15. {thyra-1.27.2 → thyra-2.0.0}/thyra/converters/__init__.py +0 -0
  16. {thyra-1.27.2 → thyra-2.0.0}/thyra/converters/spatialdata/__init__.py +0 -0
  17. {thyra-1.27.2 → thyra-2.0.0}/thyra/converters/spatialdata/_chunking.py +0 -0
  18. {thyra-1.27.2 → thyra-2.0.0}/thyra/converters/spatialdata/converter.py +0 -0
  19. {thyra-1.27.2 → thyra-2.0.0}/thyra/converters/spatialdata/spatialdata_2d_converter.py +0 -0
  20. {thyra-1.27.2 → thyra-2.0.0}/thyra/converters/spatialdata/spatialdata_3d_converter.py +0 -0
  21. {thyra-1.27.2 → thyra-2.0.0}/thyra/converters/spatialdata/streaming_converter.py +0 -0
  22. {thyra-1.27.2 → thyra-2.0.0}/thyra/core/__init__.py +0 -0
  23. {thyra-1.27.2 → thyra-2.0.0}/thyra/core/base_converter.py +0 -0
  24. {thyra-1.27.2 → thyra-2.0.0}/thyra/core/base_extractor.py +0 -0
  25. {thyra-1.27.2 → thyra-2.0.0}/thyra/core/base_reader.py +0 -0
  26. {thyra-1.27.2 → thyra-2.0.0}/thyra/core/registry.py +0 -0
  27. {thyra-1.27.2 → thyra-2.0.0}/thyra/metadata/__init__.py +0 -0
  28. {thyra-1.27.2 → thyra-2.0.0}/thyra/metadata/extractors/__init__.py +0 -0
  29. {thyra-1.27.2 → thyra-2.0.0}/thyra/metadata/extractors/bruker_extractor.py +0 -0
  30. {thyra-1.27.2 → thyra-2.0.0}/thyra/metadata/extractors/imzml_extractor.py +0 -0
  31. {thyra-1.27.2 → thyra-2.0.0}/thyra/metadata/ontology/__init__.py +0 -0
  32. {thyra-1.27.2 → thyra-2.0.0}/thyra/metadata/ontology/_ims.py +0 -0
  33. {thyra-1.27.2 → thyra-2.0.0}/thyra/metadata/ontology/_ms.py +0 -0
  34. {thyra-1.27.2 → thyra-2.0.0}/thyra/metadata/ontology/_uo.py +0 -0
  35. {thyra-1.27.2 → thyra-2.0.0}/thyra/metadata/ontology/cache.py +0 -0
  36. {thyra-1.27.2 → thyra-2.0.0}/thyra/metadata/types.py +0 -0
  37. {thyra-1.27.2 → thyra-2.0.0}/thyra/metadata/validator.py +0 -0
  38. {thyra-1.27.2 → thyra-2.0.0}/thyra/preview.py +0 -0
  39. {thyra-1.27.2 → thyra-2.0.0}/thyra/readers/__init__.py +0 -0
  40. {thyra-1.27.2 → thyra-2.0.0}/thyra/readers/bruker/__init__.py +0 -0
  41. {thyra-1.27.2 → thyra-2.0.0}/thyra/readers/bruker/base_bruker_reader.py +0 -0
  42. {thyra-1.27.2 → thyra-2.0.0}/thyra/readers/bruker/folder_structure.py +0 -0
  43. {thyra-1.27.2 → thyra-2.0.0}/thyra/readers/bruker/mis_parser.py +0 -0
  44. {thyra-1.27.2 → thyra-2.0.0}/thyra/readers/bruker/rapiflex/__init__.py +0 -0
  45. {thyra-1.27.2 → thyra-2.0.0}/thyra/readers/bruker/rapiflex/rapiflex_reader.py +0 -0
  46. {thyra-1.27.2 → thyra-2.0.0}/thyra/readers/bruker/timstof/__init__.py +0 -0
  47. {thyra-1.27.2 → thyra-2.0.0}/thyra/readers/bruker/timstof/sdk/__init__.py +0 -0
  48. {thyra-1.27.2 → thyra-2.0.0}/thyra/readers/bruker/timstof/sdk/dll/LICENCE-BRUKER.txt +0 -0
  49. {thyra-1.27.2 → thyra-2.0.0}/thyra/readers/bruker/timstof/sdk/dll/README.md +0 -0
  50. {thyra-1.27.2 → thyra-2.0.0}/thyra/readers/bruker/timstof/sdk/dll/timsdata.dll +0 -0
  51. {thyra-1.27.2 → thyra-2.0.0}/thyra/readers/bruker/timstof/sdk/dll/timsdata.so +0 -0
  52. {thyra-1.27.2 → thyra-2.0.0}/thyra/readers/bruker/timstof/sdk/dll_manager.py +0 -0
  53. {thyra-1.27.2 → thyra-2.0.0}/thyra/readers/bruker/timstof/sdk/platform_detector.py +0 -0
  54. {thyra-1.27.2 → thyra-2.0.0}/thyra/readers/bruker/timstof/sdk/sdk_functions.py +0 -0
  55. {thyra-1.27.2 → thyra-2.0.0}/thyra/readers/bruker/timstof/timstof_reader.py +0 -0
  56. {thyra-1.27.2 → thyra-2.0.0}/thyra/readers/bruker/timstof/utils/__init__.py +0 -0
  57. {thyra-1.27.2 → thyra-2.0.0}/thyra/readers/bruker/timstof/utils/batch_processor.py +0 -0
  58. {thyra-1.27.2 → thyra-2.0.0}/thyra/readers/bruker/timstof/utils/coordinate_cache.py +0 -0
  59. {thyra-1.27.2 → thyra-2.0.0}/thyra/readers/bruker/timstof/utils/mass_axis_builder.py +0 -0
  60. {thyra-1.27.2 → thyra-2.0.0}/thyra/readers/bruker/timstof/utils/memory_manager.py +0 -0
  61. {thyra-1.27.2 → thyra-2.0.0}/thyra/readers/imzml/__init__.py +0 -0
  62. {thyra-1.27.2 → thyra-2.0.0}/thyra/readers/imzml/imzml_reader.py +0 -0
  63. {thyra-1.27.2 → thyra-2.0.0}/thyra/readers/waters/__init__.py +0 -0
  64. {thyra-1.27.2 → thyra-2.0.0}/thyra/readers/waters/imaging_grid.py +0 -0
  65. {thyra-1.27.2 → thyra-2.0.0}/thyra/readers/waters/lib/MLReader.dll +0 -0
  66. {thyra-1.27.2 → thyra-2.0.0}/thyra/readers/waters/lib/MassLynxRaw.dll +0 -0
  67. {thyra-1.27.2 → thyra-2.0.0}/thyra/readers/waters/lib/libMLReader.so +0 -0
  68. {thyra-1.27.2 → thyra-2.0.0}/thyra/readers/waters/lib/libMassLynxRaw.so +0 -0
  69. {thyra-1.27.2 → thyra-2.0.0}/thyra/readers/waters/masslynx_lib.py +0 -0
  70. {thyra-1.27.2 → thyra-2.0.0}/thyra/readers/waters/waters_reader.py +0 -0
  71. {thyra-1.27.2 → thyra-2.0.0}/thyra/resampling/__init__.py +0 -0
  72. {thyra-1.27.2 → thyra-2.0.0}/thyra/resampling/common_axis.py +0 -0
  73. {thyra-1.27.2 → thyra-2.0.0}/thyra/resampling/constants.py +0 -0
  74. {thyra-1.27.2 → thyra-2.0.0}/thyra/resampling/data_characteristics.py +0 -0
  75. {thyra-1.27.2 → thyra-2.0.0}/thyra/resampling/decision_tree.py +0 -0
  76. {thyra-1.27.2 → thyra-2.0.0}/thyra/resampling/instrument_detectors.py +0 -0
  77. {thyra-1.27.2 → thyra-2.0.0}/thyra/resampling/mass_axis/__init__.py +0 -0
  78. {thyra-1.27.2 → thyra-2.0.0}/thyra/resampling/mass_axis/base_generator.py +0 -0
  79. {thyra-1.27.2 → thyra-2.0.0}/thyra/resampling/mass_axis/fticr_generator.py +0 -0
  80. {thyra-1.27.2 → thyra-2.0.0}/thyra/resampling/mass_axis/linear_generator.py +0 -0
  81. {thyra-1.27.2 → thyra-2.0.0}/thyra/resampling/mass_axis/linear_tof_generator.py +0 -0
  82. {thyra-1.27.2 → thyra-2.0.0}/thyra/resampling/mass_axis/orbitrap_generator.py +0 -0
  83. {thyra-1.27.2 → thyra-2.0.0}/thyra/resampling/mass_axis/reflector_tof_generator.py +0 -0
  84. {thyra-1.27.2 → thyra-2.0.0}/thyra/resampling/strategies/__init__.py +0 -0
  85. {thyra-1.27.2 → thyra-2.0.0}/thyra/resampling/strategies/base.py +0 -0
  86. {thyra-1.27.2 → thyra-2.0.0}/thyra/resampling/strategies/nearest_neighbor.py +0 -0
  87. {thyra-1.27.2 → thyra-2.0.0}/thyra/resampling/strategies/tic_preserving.py +0 -0
  88. {thyra-1.27.2 → thyra-2.0.0}/thyra/resampling/types.py +0 -0
  89. {thyra-1.27.2 → thyra-2.0.0}/thyra/tools/__init__.py +0 -0
  90. {thyra-1.27.2 → thyra-2.0.0}/thyra/tools/check_ontology.py +0 -0
  91. {thyra-1.27.2 → thyra-2.0.0}/thyra/utils/__init__.py +0 -0
  92. {thyra-1.27.2 → thyra-2.0.0}/thyra/utils/bruker_exceptions.py +0 -0
  93. {thyra-1.27.2 → thyra-2.0.0}/thyra/utils/logging_config.py +0 -0
  94. {thyra-1.27.2 → thyra-2.0.0}/thyra/utils/windows_paths.py +0 -0
  95. {thyra-1.27.2 → thyra-2.0.0}/thyra/utils/zarr_atomic_write.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: thyra
3
- Version: 1.27.2
3
+ Version: 2.0.0
4
4
  Summary: A modern Python library for converting Mass Spectrometry Imaging (MSI) data into SpatialData/Zarr format - your portal to spatial omics
5
5
  License: MIT
6
6
  License-File: LICENSE
@@ -9,14 +9,13 @@ Author: Theodoros Visvikis
9
9
  Author-email: t.visvikis@maastrichtuniversity.nl
10
10
  Maintainer: Theodoros Visvikis
11
11
  Maintainer-email: t.visvikis@maastrichtuniversity.nl
12
- Requires-Python: >=3.11,<3.14
12
+ Requires-Python: >=3.12,<3.14
13
13
  Classifier: Development Status :: 4 - Beta
14
14
  Classifier: Environment :: Console
15
15
  Classifier: Intended Audience :: Science/Research
16
16
  Classifier: License :: OSI Approved :: MIT License
17
17
  Classifier: Operating System :: OS Independent
18
18
  Classifier: Programming Language :: Python :: 3
19
- Classifier: Programming Language :: Python :: 3.11
20
19
  Classifier: Programming Language :: Python :: 3.12
21
20
  Classifier: Programming Language :: Python :: 3.13
22
21
  Classifier: Topic :: File Formats
@@ -26,19 +25,19 @@ Classifier: Topic :: Scientific/Engineering :: Medical Science Apps.
26
25
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
27
26
  Classifier: Typing :: Typed
28
27
  Requires-Dist: Shapely (>=2.0.0)
29
- Requires-Dist: anndata (>=0.11.0,<0.13)
30
- Requires-Dist: dask (>=2025.12.0,<2026.2)
28
+ Requires-Dist: anndata (>=0.13.2,<0.14)
29
+ Requires-Dist: dask (>=2026.3.0,<2026.8)
31
30
  Requires-Dist: defusedxml (>=0.7.1)
32
31
  Requires-Dist: geopandas (>=0.9.0)
33
32
  Requires-Dist: imagecodecs (>=2024.1.1)
34
33
  Requires-Dist: lxml (>=4.6.0)
35
34
  Requires-Dist: numpy (>=2.0.0,<3)
36
- Requires-Dist: ome-zarr (>=0.14.0,<0.16)
35
+ Requires-Dist: ome-zarr (>=0.16.0,<0.19)
37
36
  Requires-Dist: pandas (>=2.0.0,<4)
38
37
  Requires-Dist: psutil (>=5.0.0)
39
38
  Requires-Dist: pyimzML (>=1.4.0)
40
39
  Requires-Dist: scipy (>=1.7.0)
41
- Requires-Dist: spatialdata (>=0.7.3,<0.8)
40
+ Requires-Dist: spatialdata (>=0.8.0,<0.9)
42
41
  Requires-Dist: tqdm (>=4.50.0)
43
42
  Requires-Dist: zarr (>=3.0.0,<3.2)
44
43
  Project-URL: Bug Tracker, https://github.com/M4i-Imaging-Mass-Spectrometry/thyra/issues
@@ -56,7 +55,7 @@ Description-Content-Type: text/markdown
56
55
 
57
56
  [![Tests](https://img.shields.io/github/actions/workflow/status/M4i-Imaging-Mass-Spectrometry/thyra/tests.yml?branch=main&logo=github)](https://github.com/M4i-Imaging-Mass-Spectrometry/thyra/actions/workflows/tests.yml)
58
57
  [![PyPI](https://img.shields.io/pypi/v/thyra?logo=pypi&logoColor=white)](https://pypi.org/project/thyra/)
59
- [![Python 3.11+](https://img.shields.io/badge/python-3.11+-blue.svg)](https://www.python.org/downloads/)
58
+ [![Python 3.12+](https://img.shields.io/badge/python-3.12+-blue.svg)](https://www.python.org/downloads/)
60
59
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
61
60
  [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
62
61
  [![Docs](https://img.shields.io/badge/docs-mkdocs-blue)](https://M4i-Imaging-Mass-Spectrometry.github.io/thyra)
@@ -4,7 +4,7 @@
4
4
 
5
5
  [![Tests](https://img.shields.io/github/actions/workflow/status/M4i-Imaging-Mass-Spectrometry/thyra/tests.yml?branch=main&logo=github)](https://github.com/M4i-Imaging-Mass-Spectrometry/thyra/actions/workflows/tests.yml)
6
6
  [![PyPI](https://img.shields.io/pypi/v/thyra?logo=pypi&logoColor=white)](https://pypi.org/project/thyra/)
7
- [![Python 3.11+](https://img.shields.io/badge/python-3.11+-blue.svg)](https://www.python.org/downloads/)
7
+ [![Python 3.12+](https://img.shields.io/badge/python-3.12+-blue.svg)](https://www.python.org/downloads/)
8
8
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
9
9
  [![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
10
10
  [![Docs](https://img.shields.io/badge/docs-mkdocs-blue)](https://M4i-Imaging-Mass-Spectrometry.github.io/thyra)
@@ -4,7 +4,7 @@ build-backend = "poetry.core.masonry.api"
4
4
 
5
5
  [tool.poetry]
6
6
  name = "thyra"
7
- version = "1.27.2"
7
+ version = "2.0.0"
8
8
  description = "A modern Python library for converting Mass Spectrometry Imaging (MSI) data into SpatialData/Zarr format - your portal to spatial omics"
9
9
  authors = ["Theodoros Visvikis <t.visvikis@maastrichtuniversity.nl>"]
10
10
  maintainers = ["Theodoros Visvikis <t.visvikis@maastrichtuniversity.nl>"]
@@ -34,7 +34,6 @@ classifiers = [
34
34
  "License :: OSI Approved :: MIT License",
35
35
  "Operating System :: OS Independent",
36
36
  "Programming Language :: Python :: 3",
37
- "Programming Language :: Python :: 3.11",
38
37
  "Programming Language :: Python :: 3.12",
39
38
  "Programming Language :: Python :: 3.13",
40
39
  "Topic :: Scientific/Engineering :: Bio-Informatics",
@@ -54,48 +53,51 @@ packages = [{include = "thyra"}]
54
53
  "Contributing" = "https://github.com/M4i-Imaging-Mass-Spectrometry/thyra/blob/main/CONTRIBUTING.md"
55
54
 
56
55
  [tool.poetry.dependencies]
57
- python = ">=3.11, <3.14"
56
+ python = ">=3.12, <3.14"
58
57
 
59
58
  # The spatialdata / ome-zarr / zarr / dask cluster is tightly coupled and
60
59
  # all four release frequently with breaking cross-version interactions.
61
60
  # Floors alone are NOT enough for `pip install thyra`: without upper
62
- # bounds pip resolves a mismatched set (e.g. spatialdata 0.7.0 pulled in
63
- # alongside ome-zarr 0.18.0 + dask 2026.7.0), which fails to save/read
64
- # back a SpatialData object. The upper bounds below pin this cluster to
61
+ # bounds pip resolves a mismatched set (a stale spatialdata alongside a
62
+ # much newer ome-zarr and dask), which fails to save/read back a
63
+ # SpatialData object. The upper bounds below pin this cluster to
65
64
  # the tested, lockfile-consistent set so a plain pip install lands on a
66
65
  # working combination. The clean-venv CI job in .github/workflows/tests.yml
67
66
  # exercises exactly this pip-resolved path so these bounds stay honest.
68
67
  # Bump the ceilings deliberately after re-testing against newer releases.
69
- dask = ">=2025.12.0, <2026.2" # tested 2026.1.1 (spatialdata 0.7.3 needs <2026.1.2)
68
+ dask = ">=2026.3.0, <2026.8" # tested 2026.7.1 (spatialdata 0.8.0 needs >=2026.3.0)
70
69
  defusedxml = ">=0.7.1" # Secure XML parsing for the Bruker Rapiflex reader
71
70
  geopandas = ">=0.9.0"
72
71
  lxml = ">=4.6.0"
73
72
  numpy = ">=2.0.0, <3"
74
73
  # pandas 3.0 makes `future.infer_string` the default, which gives the table
75
- # indices and string columns a dtype the pinned anndata cannot serialize.
76
- # `BaseSpatialDataConverter._coerce_table_strings_to_object` handles that, so
77
- # the ceiling is NOT `<3`: capping there would strand users whose other
78
- # packages want pandas 3, for a defect we already fix. `<4` records the newest
79
- # major actually exercised -- the unit suite passes on 2.3.2 (the lockfile)
80
- # and on 3.0.5 with this dependency set.
74
+ # indices and string columns pandas' `str` dtype. anndata >= 0.13 serializes
75
+ # that natively (anndata #2133); older anndata could not, which is why this
76
+ # project carried a write-time coercion until the anndata floor moved. The
77
+ # ceiling is NOT `<3`: capping there would strand users whose other packages
78
+ # want pandas 3. `<4` records the newest major actually exercised -- the unit
79
+ # suite passes on 2.3.2 (the lockfile) and on 3.0.5 with this set.
81
80
  pandas = ">=2.0.0, <4" # tested 2.3.2 and 3.0.5
82
81
  pyimzML = ">=1.4.0"
83
82
  scipy = ">=1.7.0"
84
83
  Shapely = ">=2.0.0"
85
- spatialdata = ">=0.7.3, <0.8" # tested 0.7.3
84
+ spatialdata = ">=0.8.0, <0.9" # tested 0.8.0
86
85
  # Floor pulls the fix for the zarr_format/Group.create_array() bug that
87
- # bit ome_zarr 0.12.x with newer dask; the ceiling keeps pip off the
88
- # 0.16+ releases that the resolver otherwise pairs with a stale spatialdata.
89
- ome-zarr = ">=0.14.0, <0.16" # tested 0.15.0
86
+ # bit ome_zarr 0.12.x with newer dask, and spatialdata 0.8 requires >= 0.16.
87
+ ome-zarr = ">=0.16.0, <0.19" # tested 0.18.0
90
88
  tqdm = ">=4.50.0"
91
89
  zarr = ">=3.0.0, <3.2" # tested 3.1.3
92
90
  imagecodecs = ">=2024.1.1" # For reading compressed TIFF optical images
93
- # Moving this ceiling is the removal trigger for the pandas 3 string-dtype
94
- # coercion in base_spatialdata_converter.py: anndata 0.12.19 carries its own
95
- # `pandas<3` cap, so bumping to a release with pandas 3 support (#2221,
96
- # milestone 0.14.0) both opens the pandas 3 door and makes that coercion dead
97
- # code. Delete it in the same change.
98
- anndata = ">=0.11.0, <0.13" # tested 0.12.2
91
+ # Floor is 0.13.2, not 0.13.0. anndata 0.13.0 imports
92
+ # `typing_extensions.sentinel` (needs typing-extensions >= 4.16) but declares
93
+ # no floor for it, so a resolver prefers 0.13.0, pairs it with an older
94
+ # typing-extensions, and produces an environment that installs cleanly and
95
+ # then dies at import. 0.13.2 declares the floor correctly.
96
+ #
97
+ # 0.13 is also the release that made the pandas 3 string-dtype coercion in
98
+ # base_spatialdata_converter.py unnecessary (anndata #2221, fixed by #2133);
99
+ # that coercion was deleted when this floor moved. See issue #117.
100
+ anndata = ">=0.13.2, <0.14" # tested 0.13.2
99
101
  psutil = ">=5.0.0"
100
102
 
101
103
  [tool.poetry.group.test.dependencies]
@@ -188,7 +190,7 @@ exclude_dirs = ["tests", "docs"]
188
190
  skips = ["B101", "B601", "B603", "B607"] # Allow assert statements, shell usage, and subprocess calls with controlled input
189
191
 
190
192
  [tool.mypy]
191
- python_version = "3.11"
193
+ python_version = "3.12"
192
194
  warn_return_any = true
193
195
  warn_unused_configs = true
194
196
  disallow_untyped_defs = false # Set to true once types are added
@@ -36,7 +36,7 @@ warnings.filterwarnings(
36
36
  category=FutureWarning,
37
37
  )
38
38
 
39
- __version__ = "1.27.2"
39
+ __version__ = "2.0.0"
40
40
 
41
41
  # Import key components - avoid wildcard imports
42
42
  try:
@@ -1829,58 +1829,6 @@ class BaseSpatialDataConverter(BaseMSIConverter, ABC):
1829
1829
 
1830
1830
  return f"{self.dataset_id}_optical_{suffix}"
1831
1831
 
1832
- # --- pandas 3 string dtypes: removal trigger ---------------------------
1833
- # anndata #2221 ("Pandas 3.0 compatibility") is open and milestoned
1834
- # 0.14.0: the plan is to warn in 0.13 and flip the defaults in 0.14.
1835
- # anndata #2377 is this exact IORegistryError, closed as a duplicate of
1836
- # it, and spatialdata-io #364 is the same failure in spatialdata's own
1837
- # Xenium writer, so this is an ecosystem gap and not a Thyra bug.
1838
- # anndata's documented escape hatches do not help on the pinned 0.12.2:
1839
- # `ad.settings.allow_write_nullable_strings = True` and
1840
- # `pd.set_option("mode.string_storage", "python")` both still raise.
1841
- #
1842
- # Delete `_coerce_table_strings_to_object` and its call in `_save_output`
1843
- # once the anndata ceiling in pyproject.toml moves to a release with
1844
- # pandas 3 support (>= 0.14). Until then this is the only thing keeping
1845
- # non-PCS conversions writable, so it is not dead code yet:
1846
- # tests/unit/converters/test_pandas3_string_dtypes.py
1847
- # ::test_anndata_can_write_arrow_backed_strings XPASSes when it becomes so.
1848
- @staticmethod
1849
- def _coerce_table_strings_to_object(df: pd.DataFrame) -> None:
1850
- """Coerce pandas string-extension dtypes in ``df`` to NumPy ``object``.
1851
-
1852
- Under pandas >= 3.0 (or with ``future.infer_string`` enabled) string
1853
- columns and string indices carry ``pandas.StringDtype``, backed by
1854
- ``ArrowStringArray`` on pandas 3 and by
1855
- ``ArrowStringArrayNumpySemantics`` on pandas 2. anndata's IO registry
1856
- matches exact types and has no writer for either, so writing such a
1857
- table raises ``IORegistryError: No method registered for writing
1858
- <ArrowStringArray...> into zarr.core.group.Group``. Converting these to
1859
- ``object`` dtype restores writeability without changing any values, and
1860
- is a no-op on pandas < 3.0 where the same columns are already
1861
- ``object``.
1862
-
1863
- Operates on an AnnData ``obs``/``var`` table in place. Categorical
1864
- columns whose categories are string-backed (e.g. the ``region`` column)
1865
- have their categories coerced to ``object`` while preserving codes.
1866
-
1867
- Args:
1868
- df: An AnnData ``obs`` or ``var`` table to sanitize in place.
1869
- """
1870
- if isinstance(df.index.dtype, pd.StringDtype):
1871
- df.index = df.index.astype(object)
1872
-
1873
- for column in df.columns:
1874
- dtype = df[column].dtype
1875
- if isinstance(dtype, pd.StringDtype):
1876
- df[column] = df[column].astype(object)
1877
- elif isinstance(dtype, pd.CategoricalDtype) and isinstance(
1878
- dtype.categories.dtype, pd.StringDtype
1879
- ):
1880
- df[column] = df[column].cat.rename_categories(
1881
- dtype.categories.astype(object)
1882
- )
1883
-
1884
1832
  def _save_output(self, data_structures: Dict[str, Any]) -> bool:
1885
1833
  """Save the data to SpatialData format.
1886
1834
 
@@ -1894,18 +1842,6 @@ class BaseSpatialDataConverter(BaseMSIConverter, ABC):
1894
1842
  raise ImportError("SpatialData dependencies not available")
1895
1843
 
1896
1844
  try:
1897
- # Coerce pandas string-extension dtypes (ArrowStringArray under
1898
- # pandas >= 3.0 / future.infer_string) back to ``object`` so
1899
- # anndata's Zarr writer can serialize the table indices and string
1900
- # columns. No-op on pandas < 3.0 (already ``object``).
1901
- for table in data_structures["tables"].values():
1902
- obs = getattr(table, "obs", None)
1903
- if isinstance(obs, pd.DataFrame):
1904
- self._coerce_table_strings_to_object(obs)
1905
- var = getattr(table, "var", None)
1906
- if isinstance(var, pd.DataFrame):
1907
- self._coerce_table_strings_to_object(var)
1908
-
1909
1845
  # Create SpatialData object with images included
1910
1846
  sdata = SpatialData(
1911
1847
  tables=data_structures["tables"],
@@ -7,7 +7,7 @@ files using the MassLynx native library and pre-built imaging grid.
7
7
 
8
8
  import logging
9
9
  from pathlib import Path
10
- from typing import Any, Dict, List, Optional, Tuple
10
+ from typing import TYPE_CHECKING, Any, Dict, List, Optional, Tuple
11
11
 
12
12
  import numpy as np
13
13
  from numpy.typing import NDArray
@@ -16,6 +16,9 @@ from tqdm import tqdm
16
16
  from ...core.base_extractor import MetadataExtractor
17
17
  from ..types import ComprehensiveMetadata, EssentialMetadata
18
18
 
19
+ if TYPE_CHECKING:
20
+ from ...readers.waters.masslynx_lib import MassLynxLib
21
+
19
22
  logger = logging.getLogger(__name__)
20
23
 
21
24
 
@@ -29,7 +32,7 @@ class WatersMetadataExtractor(MetadataExtractor):
29
32
 
30
33
  def __init__(
31
34
  self,
32
- ml, # MassLynxLib instance
35
+ ml: "MassLynxLib",
33
36
  handle, # opaque file handle
34
37
  data_path: Path,
35
38
  imaging_grid, # ImagingGrid instance
@@ -56,7 +56,11 @@ def _ellipse_mask(
56
56
  ) -> np.ndarray:
57
57
  """Boolean mask of an axis-aligned ellipse on a (y, x) grid."""
58
58
  n_y, n_x = shape
59
- yy, xx = np.mgrid[0:n_y, 0:n_x]
59
+ # np.mgrid is typed as Any, which propagates through the arithmetic below
60
+ # and makes the returned mask untyped. Broadcasting two typed 1-D ranges
61
+ # produces the same grid while keeping the return type checkable.
62
+ yy = np.arange(n_y, dtype=np.float64).reshape(n_y, 1)
63
+ xx = np.arange(n_x, dtype=np.float64).reshape(1, n_x)
60
64
  cy, cx = centre
61
65
  ry, rx = radii
62
66
  return ((yy - cy) / ry) ** 2 + ((xx - cx) / rx) ** 2 <= 1.0
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes