openproteo 1.0.2__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.
@@ -0,0 +1,71 @@
1
+ Metadata-Version: 2.4
2
+ Name: openproteo
3
+ Version: 1.0.2
4
+ Summary: Open proteomics: one install for the OpenProteo vendor reader stack (Thermo, Bruker, Waters)
5
+ Author-email: Nathan Riley <git@nathanriley.com>
6
+ License: Apache-2.0
7
+ Project-URL: Homepage, https://github.com/Sigilweaver/OpenProteo
8
+ Project-URL: Documentation, https://github.com/Sigilweaver/OpenProteo
9
+ Project-URL: Source, https://github.com/Sigilweaver/OpenProteo
10
+ Project-URL: Issues, https://github.com/Sigilweaver/OpenProteo/issues
11
+ Keywords: mass-spectrometry,proteomics,raw,thermo,bruker,waters,tdf,mzml
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: License :: OSI Approved :: Apache Software License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Rust
16
+ Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
17
+ Requires-Python: >=3.9
18
+ Description-Content-Type: text/markdown
19
+ Requires-Dist: openproteo-io
20
+ Provides-Extra: thermo
21
+ Requires-Dist: opentfraw; extra == "thermo"
22
+ Provides-Extra: bruker
23
+ Requires-Dist: opentimstdf; extra == "bruker"
24
+ Provides-Extra: waters
25
+ Requires-Dist: openwraw; extra == "waters"
26
+ Provides-Extra: all
27
+ Requires-Dist: opentfraw; extra == "all"
28
+ Requires-Dist: opentimstdf; extra == "all"
29
+ Requires-Dist: openwraw; extra == "all"
30
+
31
+ # openproteo
32
+
33
+ `openproteo` is a thin Python metapackage that bundles the OpenProteo vendor reader stack:
34
+
35
+ | Vendor | Format | Underlying package |
36
+ |--------|----------------|--------------------|
37
+ | Thermo | `.raw` file | `opentfraw` |
38
+ | Bruker | `.d/` bundle | `opentimstdf` |
39
+ | Waters | `.raw/` dir | `openwraw` |
40
+
41
+ ## Install
42
+
43
+ Install just what you need:
44
+
45
+ ```bash
46
+ pip install openproteo[thermo]
47
+ pip install openproteo[bruker]
48
+ pip install openproteo[waters]
49
+ ```
50
+
51
+ Or install every supported vendor reader:
52
+
53
+ ```bash
54
+ pip install openproteo[all]
55
+ ```
56
+
57
+ ## Usage
58
+
59
+ ```python
60
+ import openproteo
61
+
62
+ kind = openproteo.detect("/data/sample.raw") # "thermo" | "bruker" | "waters" | None
63
+ run = openproteo.open_run("/data/sample.raw") # vendor-specific reader object
64
+ ```
65
+
66
+ `open_run` raises `ImportError` if the matching vendor extra is not installed and
67
+ `ValueError` if the format cannot be detected.
68
+
69
+ ## License
70
+
71
+ Apache-2.0. See [`LICENSE`](../LICENSE).
@@ -0,0 +1,41 @@
1
+ # openproteo
2
+
3
+ `openproteo` is a thin Python metapackage that bundles the OpenProteo vendor reader stack:
4
+
5
+ | Vendor | Format | Underlying package |
6
+ |--------|----------------|--------------------|
7
+ | Thermo | `.raw` file | `opentfraw` |
8
+ | Bruker | `.d/` bundle | `opentimstdf` |
9
+ | Waters | `.raw/` dir | `openwraw` |
10
+
11
+ ## Install
12
+
13
+ Install just what you need:
14
+
15
+ ```bash
16
+ pip install openproteo[thermo]
17
+ pip install openproteo[bruker]
18
+ pip install openproteo[waters]
19
+ ```
20
+
21
+ Or install every supported vendor reader:
22
+
23
+ ```bash
24
+ pip install openproteo[all]
25
+ ```
26
+
27
+ ## Usage
28
+
29
+ ```python
30
+ import openproteo
31
+
32
+ kind = openproteo.detect("/data/sample.raw") # "thermo" | "bruker" | "waters" | None
33
+ run = openproteo.open_run("/data/sample.raw") # vendor-specific reader object
34
+ ```
35
+
36
+ `open_run` raises `ImportError` if the matching vendor extra is not installed and
37
+ `ValueError` if the format cannot be detected.
38
+
39
+ ## License
40
+
41
+ Apache-2.0. See [`LICENSE`](../LICENSE).
@@ -0,0 +1,114 @@
1
+ """OpenProteo: open proteomics vendor reader stack.
2
+
3
+ This metapackage is the single pip install surface for the stack. The
4
+ base install always brings ``openproteo_io`` (the Rust-backed reader
5
+ that converts vendor inputs to mzML / Arrow); the per-vendor extras
6
+ layer on direct Python bindings for each native vendor package:
7
+
8
+ * ``opentfraw`` - Thermo `.raw` files
9
+ * ``opentimstdf`` - Bruker timsTOF `.d/` bundles
10
+ * ``openwraw`` - Waters MassLynx `.raw/` directories
11
+
12
+ Install the umbrella::
13
+
14
+ pip install openproteo # openproteo_io only
15
+ pip install openproteo[thermo] # + opentfraw
16
+ pip install openproteo[bruker] # + opentimstdf
17
+ pip install openproteo[waters] # + openwraw
18
+ pip install openproteo[all] # + all vendor extensions
19
+
20
+ Top-level helpers fall into two layers:
21
+
22
+ * ``detect_format``, ``to_mzml``, ``iter_spectra`` are re-exports from
23
+ ``openproteo_io`` - the vendor-agnostic reader.
24
+ * ``detect``, ``open_run`` use only structural checks and dispatch to
25
+ the vendor extension that matches the input path (requires the
26
+ corresponding extra).
27
+ """
28
+
29
+ from __future__ import annotations
30
+
31
+ import os
32
+ from importlib.metadata import PackageNotFoundError, version as _pkg_version
33
+ from pathlib import Path
34
+ from typing import Optional
35
+
36
+ try:
37
+ __version__ = _pkg_version("openproteo")
38
+ except PackageNotFoundError: # pragma: no cover - source checkout fallback
39
+ __version__ = "0.0.0+unknown"
40
+
41
+ # Re-export the openproteo_io reader surface so callers can write
42
+ # ``from openproteo import to_mzml, iter_spectra, detect_format``.
43
+ try:
44
+ from openproteo_io import ( # type: ignore[import-not-found]
45
+ Spectrum,
46
+ iter_spectra,
47
+ to_mzml,
48
+ )
49
+ from openproteo_io import detect as detect_format # type: ignore[import-not-found]
50
+ except ImportError: # pragma: no cover - openproteo_io is a hard dep
51
+ Spectrum = None # type: ignore[assignment]
52
+ detect_format = None # type: ignore[assignment]
53
+ iter_spectra = None # type: ignore[assignment]
54
+ to_mzml = None # type: ignore[assignment]
55
+
56
+ __all__ = [
57
+ "__version__",
58
+ "VENDORS",
59
+ "Spectrum",
60
+ "detect",
61
+ "detect_format",
62
+ "iter_spectra",
63
+ "open_run",
64
+ "to_mzml",
65
+ ]
66
+
67
+ VENDORS = ("thermo", "bruker", "waters")
68
+
69
+
70
+ def detect(path: str | os.PathLike[str]) -> Optional[str]:
71
+ """Return ``"thermo"``, ``"bruker"``, ``"waters"`` or ``None`` for *path*.
72
+
73
+ The check is purely structural (extension + sentinel files); no vendor
74
+ reader needs to be importable.
75
+ """
76
+ p = Path(path)
77
+ if not p.exists():
78
+ return None
79
+ if p.is_file() and p.suffix.lower() == ".raw":
80
+ return "thermo"
81
+ if p.is_dir():
82
+ suffix = p.suffix.lower()
83
+ if suffix == ".d" and (p / "analysis.tdf").is_file():
84
+ return "bruker"
85
+ if suffix == ".raw" and any(
86
+ (p / name).exists()
87
+ for name in ("_FUNCTNS.INF", "_extern.inf", "_HEADER.TXT")
88
+ ):
89
+ return "waters"
90
+ return None
91
+
92
+
93
+ def open_run(path: str | os.PathLike[str]):
94
+ """Detect *path*, import the matching vendor package, and open the run.
95
+
96
+ Raises ``ImportError`` if the matching vendor extra is not installed and
97
+ ``ValueError`` if the format cannot be detected.
98
+ """
99
+ kind = detect(path)
100
+ if kind is None:
101
+ raise ValueError(f"no supported vendor format detected at {path}")
102
+ if kind == "thermo":
103
+ import opentfraw # type: ignore[import-not-found]
104
+
105
+ return opentfraw.RawFile(str(path))
106
+ if kind == "bruker":
107
+ import opentimstdf # type: ignore[import-not-found]
108
+
109
+ return opentimstdf.Reader(str(path))
110
+ if kind == "waters":
111
+ import openwraw # type: ignore[import-not-found]
112
+
113
+ return openwraw.RawReader(str(path))
114
+ raise ValueError(f"unhandled vendor kind: {kind}")
@@ -0,0 +1,71 @@
1
+ Metadata-Version: 2.4
2
+ Name: openproteo
3
+ Version: 1.0.2
4
+ Summary: Open proteomics: one install for the OpenProteo vendor reader stack (Thermo, Bruker, Waters)
5
+ Author-email: Nathan Riley <git@nathanriley.com>
6
+ License: Apache-2.0
7
+ Project-URL: Homepage, https://github.com/Sigilweaver/OpenProteo
8
+ Project-URL: Documentation, https://github.com/Sigilweaver/OpenProteo
9
+ Project-URL: Source, https://github.com/Sigilweaver/OpenProteo
10
+ Project-URL: Issues, https://github.com/Sigilweaver/OpenProteo/issues
11
+ Keywords: mass-spectrometry,proteomics,raw,thermo,bruker,waters,tdf,mzml
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: License :: OSI Approved :: Apache Software License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Rust
16
+ Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
17
+ Requires-Python: >=3.9
18
+ Description-Content-Type: text/markdown
19
+ Requires-Dist: openproteo-io
20
+ Provides-Extra: thermo
21
+ Requires-Dist: opentfraw; extra == "thermo"
22
+ Provides-Extra: bruker
23
+ Requires-Dist: opentimstdf; extra == "bruker"
24
+ Provides-Extra: waters
25
+ Requires-Dist: openwraw; extra == "waters"
26
+ Provides-Extra: all
27
+ Requires-Dist: opentfraw; extra == "all"
28
+ Requires-Dist: opentimstdf; extra == "all"
29
+ Requires-Dist: openwraw; extra == "all"
30
+
31
+ # openproteo
32
+
33
+ `openproteo` is a thin Python metapackage that bundles the OpenProteo vendor reader stack:
34
+
35
+ | Vendor | Format | Underlying package |
36
+ |--------|----------------|--------------------|
37
+ | Thermo | `.raw` file | `opentfraw` |
38
+ | Bruker | `.d/` bundle | `opentimstdf` |
39
+ | Waters | `.raw/` dir | `openwraw` |
40
+
41
+ ## Install
42
+
43
+ Install just what you need:
44
+
45
+ ```bash
46
+ pip install openproteo[thermo]
47
+ pip install openproteo[bruker]
48
+ pip install openproteo[waters]
49
+ ```
50
+
51
+ Or install every supported vendor reader:
52
+
53
+ ```bash
54
+ pip install openproteo[all]
55
+ ```
56
+
57
+ ## Usage
58
+
59
+ ```python
60
+ import openproteo
61
+
62
+ kind = openproteo.detect("/data/sample.raw") # "thermo" | "bruker" | "waters" | None
63
+ run = openproteo.open_run("/data/sample.raw") # vendor-specific reader object
64
+ ```
65
+
66
+ `open_run` raises `ImportError` if the matching vendor extra is not installed and
67
+ `ValueError` if the format cannot be detected.
68
+
69
+ ## License
70
+
71
+ Apache-2.0. See [`LICENSE`](../LICENSE).
@@ -0,0 +1,10 @@
1
+ README.md
2
+ pyproject.toml
3
+ ./openproteo/__init__.py
4
+ openproteo/__init__.py
5
+ openproteo.egg-info/PKG-INFO
6
+ openproteo.egg-info/SOURCES.txt
7
+ openproteo.egg-info/dependency_links.txt
8
+ openproteo.egg-info/requires.txt
9
+ openproteo.egg-info/top_level.txt
10
+ tests/test_metapackage.py
@@ -0,0 +1,15 @@
1
+ openproteo-io
2
+
3
+ [all]
4
+ opentfraw
5
+ opentimstdf
6
+ openwraw
7
+
8
+ [bruker]
9
+ opentimstdf
10
+
11
+ [thermo]
12
+ opentfraw
13
+
14
+ [waters]
15
+ openwraw
@@ -0,0 +1 @@
1
+ openproteo
@@ -0,0 +1,49 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "openproteo"
7
+ version = "1.0.2"
8
+ description = "Open proteomics: one install for the OpenProteo vendor reader stack (Thermo, Bruker, Waters)"
9
+ readme = "README.md"
10
+ license = { text = "Apache-2.0" }
11
+ authors = [{ name = "Nathan Riley", email = "git@nathanriley.com" }]
12
+ requires-python = ">=3.9"
13
+ keywords = [
14
+ "mass-spectrometry",
15
+ "proteomics",
16
+ "raw",
17
+ "thermo",
18
+ "bruker",
19
+ "waters",
20
+ "tdf",
21
+ "mzml",
22
+ ]
23
+ classifiers = [
24
+ "Development Status :: 4 - Beta",
25
+ "License :: OSI Approved :: Apache Software License",
26
+ "Programming Language :: Python :: 3",
27
+ "Programming Language :: Rust",
28
+ "Topic :: Scientific/Engineering :: Bio-Informatics",
29
+ ]
30
+ dependencies = ["openproteo-io"]
31
+
32
+ [project.optional-dependencies]
33
+ # The base install always brings openproteo-io (the vendor-agnostic Rust
34
+ # reader). Each extra layers on a per-vendor native binding; the `all`
35
+ # extra installs every supported vendor.
36
+ thermo = ["opentfraw"]
37
+ bruker = ["opentimstdf"]
38
+ waters = ["openwraw"]
39
+ all = ["opentfraw", "opentimstdf", "openwraw"]
40
+
41
+ [project.urls]
42
+ Homepage = "https://github.com/Sigilweaver/OpenProteo"
43
+ Documentation = "https://github.com/Sigilweaver/OpenProteo"
44
+ Source = "https://github.com/Sigilweaver/OpenProteo"
45
+ Issues = "https://github.com/Sigilweaver/OpenProteo/issues"
46
+
47
+ [tool.setuptools]
48
+ packages = ["openproteo"]
49
+ package-dir = { "" = "." }
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,155 @@
1
+ """Smoke tests for the `openproteo` metapackage.
2
+
3
+ These tests do not require any vendor corpus. They exercise:
4
+
5
+ * metadata (`__version__`, `__all__`),
6
+ * structural `detect()` against synthesized directories/files,
7
+ * `open_run()` error paths,
8
+ * presence of the `openproteo_io` re-exports (when installed).
9
+ """
10
+
11
+ from __future__ import annotations
12
+
13
+ from pathlib import Path
14
+
15
+ import openproteo
16
+ import pytest
17
+
18
+
19
+ def test_version_string():
20
+ assert isinstance(openproteo.__version__, str)
21
+ assert openproteo.__version__.count(".") >= 1
22
+
23
+
24
+ def test_vendors_tuple():
25
+ assert openproteo.VENDORS == ("thermo", "bruker", "waters")
26
+
27
+
28
+ def test_detect_thermo_file(tmp_path: Path):
29
+ f = tmp_path / "sample.raw"
30
+ f.write_bytes(b"")
31
+ assert openproteo.detect(f) == "thermo"
32
+
33
+
34
+ def test_detect_bruker_d(tmp_path: Path):
35
+ d = tmp_path / "sample.d"
36
+ d.mkdir()
37
+ (d / "analysis.tdf").write_bytes(b"")
38
+ assert openproteo.detect(d) == "bruker"
39
+
40
+
41
+ def test_detect_waters_raw(tmp_path: Path):
42
+ d = tmp_path / "sample.raw"
43
+ d.mkdir()
44
+ (d / "_HEADER.TXT").write_bytes(b"")
45
+ assert openproteo.detect(d) == "waters"
46
+
47
+
48
+ def test_detect_unknown_returns_none(tmp_path: Path):
49
+ p = tmp_path / "something.txt"
50
+ p.write_bytes(b"hello")
51
+ assert openproteo.detect(p) is None
52
+
53
+
54
+ def test_detect_missing_path_returns_none(tmp_path: Path):
55
+ assert openproteo.detect(tmp_path / "does-not-exist") is None
56
+
57
+
58
+ def test_open_run_unknown_raises(tmp_path: Path):
59
+ p = tmp_path / "nope.txt"
60
+ p.write_bytes(b"")
61
+ with pytest.raises(ValueError):
62
+ openproteo.open_run(p)
63
+
64
+
65
+ def test_openproteo_io_reexports_present():
66
+ # The base install pulls openproteo_io; the re-exports should be
67
+ # importable callables. If openproteo_io is genuinely missing the
68
+ # module falls back to None and we skip.
69
+ if openproteo.to_mzml is None:
70
+ pytest.skip("openproteo_io not importable in this environment")
71
+ assert callable(openproteo.to_mzml)
72
+ assert callable(openproteo.iter_spectra)
73
+ assert callable(openproteo.detect_format)
74
+
75
+
76
+ def test_version_matches_installed_metadata():
77
+ """Catch ``__version__`` drift from ``pyproject.toml`` early."""
78
+ from importlib.metadata import PackageNotFoundError, version
79
+
80
+ try:
81
+ installed = version("openproteo")
82
+ except PackageNotFoundError:
83
+ pytest.skip("openproteo not installed (running from source)")
84
+ assert openproteo.__version__ == installed
85
+
86
+
87
+ def test_open_run_thermo_dispatch(monkeypatch, tmp_path: Path):
88
+ """``open_run`` on a thermo file imports opentfraw and calls ``RawFile``."""
89
+ import sys
90
+ import types
91
+
92
+ f = tmp_path / "sample.raw"
93
+ f.write_bytes(b"")
94
+ calls: list[str] = []
95
+
96
+ fake = types.ModuleType("opentfraw")
97
+ fake.RawFile = lambda p: calls.append(("thermo", p)) or "thermo-handle" # type: ignore[attr-defined]
98
+ monkeypatch.setitem(sys.modules, "opentfraw", fake)
99
+
100
+ assert openproteo.open_run(f) == "thermo-handle"
101
+ assert calls == [("thermo", str(f))]
102
+
103
+
104
+ def test_open_run_bruker_dispatch(monkeypatch, tmp_path: Path):
105
+ import sys
106
+ import types
107
+
108
+ d = tmp_path / "sample.d"
109
+ d.mkdir()
110
+ (d / "analysis.tdf").write_bytes(b"")
111
+ calls: list[str] = []
112
+
113
+ fake = types.ModuleType("opentimstdf")
114
+ fake.Reader = lambda p: calls.append(("bruker", p)) or "bruker-handle" # type: ignore[attr-defined]
115
+ monkeypatch.setitem(sys.modules, "opentimstdf", fake)
116
+
117
+ assert openproteo.open_run(d) == "bruker-handle"
118
+ assert calls == [("bruker", str(d))]
119
+
120
+
121
+ def test_open_run_waters_dispatch(monkeypatch, tmp_path: Path):
122
+ import sys
123
+ import types
124
+
125
+ d = tmp_path / "sample.raw"
126
+ d.mkdir()
127
+ (d / "_HEADER.TXT").write_bytes(b"")
128
+ calls: list[str] = []
129
+
130
+ fake = types.ModuleType("openwraw")
131
+ fake.RawReader = lambda p: calls.append(("waters", p)) or "waters-handle" # type: ignore[attr-defined]
132
+ monkeypatch.setitem(sys.modules, "openwraw", fake)
133
+
134
+ assert openproteo.open_run(d) == "waters-handle"
135
+ assert calls == [("waters", str(d))]
136
+
137
+
138
+ def test_vendors_is_immutable_tuple():
139
+ assert isinstance(openproteo.VENDORS, tuple)
140
+ with pytest.raises((TypeError, AttributeError)):
141
+ openproteo.VENDORS[0] = "nope" # type: ignore[index]
142
+
143
+
144
+ def test_public_api_surface():
145
+ expected = {
146
+ "__version__",
147
+ "VENDORS",
148
+ "Spectrum",
149
+ "detect",
150
+ "detect_format",
151
+ "iter_spectra",
152
+ "open_run",
153
+ "to_mzml",
154
+ }
155
+ assert set(openproteo.__all__) == expected