chromparser 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,183 @@
1
+ """Read chromatography raw files into one data model; write HDF5 and ANDI.
2
+
3
+ Supported: Chromeleon 7 (`.cmbx`, raw signal files, text exports), Thermo MS
4
+ `.raw` (embedded in `.cmbx`), Agilent (`.ch`, `.D`, `.dx`), Shimadzu
5
+ GCMSsolution (`.qgd`, `.gcd`) and ANDI netCDF (`.cdf`, MS and chromatography;
6
+ also written by `write_andi`). See the README for the scope of each reader.
7
+ """
8
+
9
+ from __future__ import annotations
10
+
11
+ import inspect
12
+ from importlib.metadata import PackageNotFoundError, version
13
+ from pathlib import Path
14
+ from typing import Any
15
+
16
+ from .errors import (
17
+ ChromparserError,
18
+ ChromparserWarning,
19
+ CorruptFile,
20
+ UnsupportedFormat,
21
+ UnsupportedVariant,
22
+ )
23
+ from .hdf5 import read_hdf5, write_hdf5
24
+ from .model import SATURATED, Injection, MSData, Signal
25
+ from .sniff import HDF5, sniff
26
+ from .vendors import FORMATS
27
+ from .vendors.andi import write_andi
28
+ from .vendors.chromeleon import extract_ms_raw
29
+
30
+ try:
31
+ __version__ = version("chromparser")
32
+ except PackageNotFoundError: # pragma: no cover
33
+ __version__ = "0+unknown"
34
+
35
+ #: Options that some readers take; `read` passes each reader those it accepts.
36
+ READ_OPTIONS = ("ms", "signal_unit", "dayfirst", "channel", "name")
37
+
38
+
39
+ def _reader(fmt: str):
40
+ if fmt == HDF5:
41
+ return read_hdf5
42
+ return next(f.read for f in FORMATS if f.id == fmt)
43
+
44
+
45
+ def read(path: str | Path, **options: Any) -> list[Injection]:
46
+ """Read any supported file; the format is detected from the content.
47
+
48
+ Parameters
49
+ ----------
50
+ path : str or Path
51
+ File or Agilent `.D` folder; also chromparser/cmbx-reader HDF5 files.
52
+ **options
53
+ Reader options (`READ_OPTIONS`): ``ms`` (read MS data of `.cmbx`),
54
+ ``signal_unit`` (Chromeleon raw signal files), ``dayfirst``
55
+ (Chromeleon text exports), ``channel`` (Agilent `.ch`), ``name``
56
+ (Thermo raw). Options a reader does not take are ignored.
57
+
58
+ Returns
59
+ -------
60
+ list of Injection
61
+ ``metadata["source_file"]`` is set to the file name.
62
+
63
+ Raises
64
+ ------
65
+ TypeError
66
+ For an unknown option.
67
+ UnsupportedFormat, UnsupportedVariant, CorruptFile
68
+ See `chromparser.errors`.
69
+ """
70
+ unknown = set(options) - set(READ_OPTIONS)
71
+ if unknown:
72
+ raise TypeError(f"Unknown read option(s): {', '.join(sorted(unknown))}")
73
+ path = Path(path)
74
+ reader = _reader(sniff(path))
75
+ accepted = inspect.signature(reader).parameters
76
+ injections = reader(path, **{k: v for k, v in options.items() if k in accepted})
77
+ for injection in injections:
78
+ injection.metadata.setdefault("source_file", path.name)
79
+ return injections
80
+
81
+
82
+ def read_one(path: str | Path, **options: Any) -> Injection:
83
+ """Read a file that holds exactly one injection.
84
+
85
+ Parameters
86
+ ----------
87
+ path : str or Path
88
+ See `read`.
89
+ **options
90
+ See `read`.
91
+
92
+ Returns
93
+ -------
94
+ Injection
95
+ The injection.
96
+
97
+ Raises
98
+ ------
99
+ ValueError
100
+ If the file holds no or several injections.
101
+ """
102
+ injections = read(path, **options)
103
+ if len(injections) != 1:
104
+ raise ValueError(
105
+ f"{Path(path).name} holds {len(injections)} injections; use read()."
106
+ )
107
+ return injections[0]
108
+
109
+
110
+ def convert(
111
+ source: str | Path,
112
+ destination: str | Path | None = None,
113
+ *,
114
+ overwrite: bool = False,
115
+ compression: bool = True,
116
+ **options: Any,
117
+ ) -> Path:
118
+ """Convert a file to HDF5 (layout v3).
119
+
120
+ Parameters
121
+ ----------
122
+ source : str or Path
123
+ Any file `read` accepts, including HDF5 files of older layouts.
124
+ destination : str or Path, optional
125
+ Output file. Defaults to `source` with suffix `.h5` (for a `.h5`
126
+ source: ``<name>.v3.h5``).
127
+ overwrite : bool
128
+ Replace an existing output file.
129
+ compression : bool
130
+ Compress datasets.
131
+ **options
132
+ Reader options, see `read`.
133
+
134
+ Returns
135
+ -------
136
+ Path
137
+ The written file.
138
+ """
139
+ source = Path(source)
140
+ fmt = sniff(source)
141
+ if destination is None:
142
+ suffix = ".v3.h5" if fmt == HDF5 else ".h5"
143
+ destination = source.with_name(source.name.removesuffix(source.suffix) + suffix)
144
+ injections = read(source, **options)
145
+ if fmt == HDF5:
146
+ import h5py
147
+
148
+ from .hdf5 import _value
149
+
150
+ with h5py.File(source, "r") as hdf:
151
+ fmt = _value(hdf.attrs.get("source_format", HDF5))
152
+ return write_hdf5(
153
+ injections,
154
+ destination,
155
+ overwrite=overwrite,
156
+ compression=compression,
157
+ source=source,
158
+ source_format=fmt,
159
+ )
160
+
161
+
162
+ __all__ = [
163
+ "FORMATS",
164
+ "READ_OPTIONS",
165
+ "SATURATED",
166
+ "ChromparserError",
167
+ "ChromparserWarning",
168
+ "CorruptFile",
169
+ "Injection",
170
+ "MSData",
171
+ "Signal",
172
+ "UnsupportedFormat",
173
+ "UnsupportedVariant",
174
+ "__version__",
175
+ "convert",
176
+ "extract_ms_raw",
177
+ "read",
178
+ "read_hdf5",
179
+ "read_one",
180
+ "sniff",
181
+ "write_andi",
182
+ "write_hdf5",
183
+ ]
@@ -0,0 +1,7 @@
1
+ """Run the command line interface: ``python -m chromparser``."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from .cli import main
6
+
7
+ raise SystemExit(main())