MaldiBatchKit 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,344 @@
1
+ Metadata-Version: 2.4
2
+ Name: MaldiBatchKit
3
+ Version: 0.1.0
4
+ Summary: Batch-effect correction methods for MALDI-TOF spectra in clinical AMR prediction workflows
5
+ Author-email: Ettore Rocchi <ettore.rocchi3@unibo.it>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/EttoreRocchi/MaldiBatchKit
8
+ Project-URL: Documentation, https://maldibatchkit.readthedocs.io/
9
+ Project-URL: Source, https://github.com/EttoreRocchi/MaldiBatchKit
10
+ Project-URL: Issues, https://github.com/EttoreRocchi/MaldiBatchKit/issues
11
+ Keywords: MALDI,MALDI-TOF,mass-spectrometry,batch-effect,ComBat,harmonization,AMR,antimicrobial-resistance,machine-learning
12
+ Classifier: Development Status :: 3 - Alpha
13
+ Classifier: Programming Language :: Python :: 3
14
+ Classifier: Programming Language :: Python :: 3.10
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
18
+ Classifier: Intended Audience :: Science/Research
19
+ Classifier: Topic :: Scientific/Engineering :: Bio-Informatics
20
+ Classifier: Topic :: Scientific/Engineering :: Chemistry
21
+ Classifier: Operating System :: OS Independent
22
+ Requires-Python: >=3.10
23
+ Description-Content-Type: text/markdown
24
+ License-File: LICENSE
25
+ Requires-Dist: numpy>=1.21.0
26
+ Requires-Dist: pandas>=1.3.0
27
+ Requires-Dist: scipy>=1.13.0
28
+ Requires-Dist: scikit-learn>=1.6.0
29
+ Requires-Dist: matplotlib>=3.4.0
30
+ Requires-Dist: combatlearn>=2.0.0
31
+ Requires-Dist: harmonypy<2,>=0.2.0
32
+ Requires-Dist: maldiamrkit>=0.12.0
33
+ Requires-Dist: typer>=0.9.0
34
+ Provides-Extra: dev
35
+ Requires-Dist: pytest>=7.0.0; extra == "dev"
36
+ Requires-Dist: pytest-cov>=4.0.0; extra == "dev"
37
+ Requires-Dist: ruff>=0.1.0; extra == "dev"
38
+ Requires-Dist: pre-commit>=3.0.0; extra == "dev"
39
+ Requires-Dist: hypothesis>=6.0.0; extra == "dev"
40
+ Provides-Extra: docs
41
+ Requires-Dist: sphinx>=7.0.0; extra == "docs"
42
+ Requires-Dist: pydata-sphinx-theme>=0.15.0; extra == "docs"
43
+ Requires-Dist: sphinx-autodoc-typehints>=2.0.0; extra == "docs"
44
+ Requires-Dist: sphinx-design>=0.6.0; extra == "docs"
45
+ Requires-Dist: sphinx-click>=5.0.0; extra == "docs"
46
+ Requires-Dist: nbsphinx>=0.9.0; extra == "docs"
47
+ Requires-Dist: ipykernel>=6.0.0; extra == "docs"
48
+ Requires-Dist: ipywidgets>=8.0.0; extra == "docs"
49
+ Provides-Extra: viz
50
+ Requires-Dist: umap-learn>=0.5.3; extra == "viz"
51
+ Requires-Dist: seaborn>=0.11.0; extra == "viz"
52
+ Dynamic: license-file
53
+
54
+ # MaldiBatchKit
55
+
56
+ [![CI](https://github.com/EttoreRocchi/MaldiBatchKit/actions/workflows/ci.yml/badge.svg)](https://github.com/EttoreRocchi/MaldiBatchKit/actions/workflows/ci.yml)
57
+ [![Coverage](https://codecov.io/github/EttoreRocchi/MaldiBatchKit/branch/main/graph/badge.svg)](https://codecov.io/github/EttoreRocchi/MaldiBatchKit)
58
+ [![Docs](https://readthedocs.org/projects/maldibatchkit/badge/?version=latest)](https://maldibatchkit.readthedocs.io/en/latest/)
59
+ [![Python](https://img.shields.io/badge/python-3.10--3.13-blue)](https://pypi.org/project/maldibatchkit/)
60
+ [![License](https://img.shields.io/github/license/EttoreRocchi/MaldiBatchKit)](https://github.com/EttoreRocchi/MaldiBatchKit/blob/main/LICENSE)
61
+
62
+ <p align="center">
63
+ <img src="docs/maldibatchkit_logo.png" alt="MaldiBatchKit" width="320"/>
64
+ </p>
65
+
66
+ <p align="center">
67
+ <strong>Batch-effect correction methods for MALDI-TOF spectra in clinical AMR prediction workflows</strong>
68
+ </p>
69
+
70
+ <p align="center">
71
+ <a href="#installation">Installation</a> •
72
+ <a href="#features">Features</a> •
73
+ <a href="#quick-start">Quick Start</a> •
74
+ <a href="#algorithms">Algorithms</a> •
75
+ <a href="#diagnostics">Diagnostics</a> •
76
+ <a href="#citation">Citation</a>
77
+ </p>
78
+
79
+ MaldiBatchKit is part of the **MaldiSuite** ecosystem and complements
80
+ [MaldiAMRKit](https://github.com/EttoreRocchi/MaldiAMRKit): where
81
+ MaldiAMRKit handles preprocessing, alignment and AMR-aware evaluation,
82
+ MaldiBatchKit focuses on the *harmonization* step, removing the
83
+ inter-batch / inter-site shifts that plague multi-centre MALDI-TOF
84
+ studies.
85
+
86
+ ## Installation
87
+
88
+ ```bash
89
+ pip install maldibatchkit
90
+ ```
91
+
92
+ Optional extras:
93
+
94
+ ```bash
95
+ pip install maldibatchkit[viz] # UMAP plots, seaborn
96
+ pip install maldibatchkit[dev] # testing + linting
97
+ pip install maldibatchkit[docs] # sphinx
98
+ ```
99
+
100
+ `maldiamrkit` is a core dependency - installing MaldiBatchKit pulls
101
+ it in automatically. `BatchAwareWarping` reuses
102
+ `maldiamrkit.alignment.Warping` under the hood, and the
103
+ `MaldiSetAdapter` bridges to `maldiamrkit.MaldiSet` for end-to-end
104
+ AMR workflows.
105
+
106
+ ## Features
107
+
108
+ - **Unified sklearn API** (`BaseEstimator` + `TransformerMixin`) for
109
+ every correction method. `batch` and covariates are passed at
110
+ construction time and aligned to `X.index` at `fit` / `transform`,
111
+ so the same object works inside `Pipeline` / cross-validation
112
+ without data leakage.
113
+ - **ComBat variants** (Johnson 2007, Fortin 2018, Chen 2022 CovBat)
114
+ re-exported from [combatlearn](https://github.com/EttoreRocchi/combatlearn).
115
+ - **Limma `removeBatchEffect`** (Ritchie et al. 2015).
116
+ - **Harmony** (Korsunsky et al. 2019) via [harmonypy](https://github.com/slowkow/harmonypy), with a **mandatory, frozen PCA preprocessing stage** so it behaves sensibly on high-dimensional MALDI-TOF intensity matrices (tune with the `n_components=` argument).
117
+ - **Simple baselines**: median centering, z-score per batch,
118
+ reference scaling.
119
+ - **MALDI-specific corrections**:
120
+ - `BatchAwareWarping` - per-batch m/z warping sharing a global
121
+ reference (wraps `maldiamrkit.alignment.Warping`).
122
+ - `QualityWeightedComBat` - weighted empirical-Bayes ComBat
123
+ variant where low-SNR spectra contribute less to the shrinkage
124
+ prior.
125
+ - `SpeciesAwareComBat` - convenience preset for ComBat-Fortin with
126
+ `species` as the protected biological covariate.
127
+ - **Diagnostics**: kBET, LISI, silhouette-by-batch, per-batch peak
128
+ drift, per-batch TIC coefficient of variation, per-batch spectrum
129
+ count, plus a combined `diagnostic_report` DataFrame summary.
130
+ - **Visualization**: UMAP before/after, per-batch peak-shape overlays,
131
+ before/after bar charts.
132
+ - **Integration adapter**: `MaldiSetAdapter` turns a
133
+ `maldiamrkit.MaldiSet` into a corrected `MaldiSet` in one call.
134
+ - **CLI**: `maldibatchkit correct ...` and `maldibatchkit diagnose ...`.
135
+
136
+ ## Quick start
137
+
138
+ ```python
139
+ from maldibatchkit import ComBat, QualityWeightedComBat, SpeciesAwareComBat
140
+ from maldibatchkit.diagnostics import diagnostic_report
141
+
142
+ # X: (n_samples, n_bins) DataFrame; batch & species indexed by X.index
143
+ corrector = SpeciesAwareComBat(batch=batch, species=species)
144
+ X_corrected = corrector.fit_transform(X)
145
+
146
+ report = diagnostic_report(X, X_corrected, batch)
147
+ print(report)
148
+ ```
149
+
150
+ Train/test without leakage:
151
+
152
+ ```python
153
+ from sklearn.model_selection import train_test_split
154
+
155
+ X_train, X_test, y_train, y_test = train_test_split(X, y, stratify=batch)
156
+
157
+ corrector = ComBat(batch=batch, method="fortin", discrete_covariates=species)
158
+ corrector.fit(X_train) # learns on train only
159
+ X_train_c = corrector.transform(X_train)
160
+ X_test_c = corrector.transform(X_test) # same parameters applied to test
161
+ ```
162
+
163
+ `batch` is indexed by the same sample IDs that X uses, so the
164
+ corrector picks the right subset on each call.
165
+
166
+ ### MaldiSet integration
167
+
168
+ ```python
169
+ from maldiamrkit import MaldiSet
170
+ from maldibatchkit.integrations import MaldiSetAdapter
171
+ from maldibatchkit import SpeciesAwareComBat
172
+
173
+ ds = MaldiSet.from_directory(...)
174
+ adapter = MaldiSetAdapter(
175
+ batch_column="Batch",
176
+ species_column="Species",
177
+ quality_column="SNR",
178
+ )
179
+ corrected_ds = adapter.correct(ds, SpeciesAwareComBat)
180
+ corrected_ds.X # harmonised feature matrix
181
+ corrected_ds.y # AMR labels, unchanged
182
+ ```
183
+
184
+ ### CLI
185
+
186
+ The CLI is organised as `maldibatchkit correct <method>` +
187
+ `maldibatchkit diagnose`. Every method has its own subcommand with
188
+ only the flags it actually uses:
189
+
190
+ ```bash
191
+ # Vanilla Johnson ComBat
192
+ maldibatchkit correct combat \
193
+ -i X.csv --batch-csv batch.csv -o X_corrected.csv
194
+
195
+ # Fortin ComBat with a species covariate
196
+ maldibatchkit correct combat-fortin \
197
+ -i X.csv --batch-csv batch.csv \
198
+ --discrete-covariates-csv species.csv \
199
+ -o X_corrected.csv
200
+
201
+ # Species-aware preset (shortcut for the above)
202
+ maldibatchkit correct species-combat \
203
+ -i X.csv --batch-csv batch.csv --species-csv species.csv \
204
+ -o X_corrected.csv
205
+
206
+ # Quality-weighted ComBat
207
+ maldibatchkit correct quality-combat \
208
+ -i X.csv --batch-csv batch.csv --quality-csv snr.csv \
209
+ -o X_corrected.csv
210
+
211
+ # Diagnostic report
212
+ maldibatchkit diagnose \
213
+ -i X.csv --corrected X_corrected.csv \
214
+ --batch-csv batch.csv --mz-csv mz.csv -o report.csv
215
+ ```
216
+
217
+ NPZ inputs bundle X, index, columns, and batch labels in one file, so
218
+ the same commands work without sidecar CSVs:
219
+
220
+ ```bash
221
+ maldibatchkit correct combat-fortin \
222
+ -i maldiset.npz \
223
+ --discrete-covariates-csv species.csv \
224
+ -o corrected.npz
225
+ ```
226
+
227
+ Run `maldibatchkit correct <method> --help` for the full flag list of
228
+ any corrector. `combat-fortin` / `combat-chen` refuse to run without
229
+ covariates (they would silently reduce to Johnson ComBat);
230
+ `species-combat` / `quality-combat` require their dedicated
231
+ `--species-csv` / `--quality-csv` inputs.
232
+
233
+ ## Algorithms
234
+
235
+ | Method | Class | Protects covariates? | Train/test safe? |
236
+ |--------------------------------|---------------------------|----------------------|------------------|
237
+ | ComBat (Johnson, Fortin, Chen) | `ComBat` | Fortin / Chen | yes |
238
+ | Limma | `Limma` | via `design=` | yes |
239
+ | Harmony | `Harmony` | via `covariates=` | yes |
240
+ | Median centering | `MedianCentering` | no | yes |
241
+ | Z-score per batch | `ZScorePerBatch` | no | yes |
242
+ | Reference scaling | `ReferenceScaling` | no | yes |
243
+ | Batch-aware warping | `BatchAwareWarping` | no | yes |
244
+ | Quality-weighted ComBat | `QualityWeightedComBat` | no | yes |
245
+ | Species-aware ComBat | `SpeciesAwareComBat` | species | yes |
246
+
247
+ See the `QualityWeightedComBat` docstring for the mathematical
248
+ formulation of the weighted empirical-Bayes update.
249
+
250
+ ## Extending MaldiBatchKit
251
+
252
+ Every corrector in this package inherits from `BaseBatchCorrector`,
253
+ which is re-exported at the top level. Subclass it, implement
254
+ `_fit_impl` and `_transform_impl`, and you get a scikit-learn compatible,
255
+ train/test-safe corrector for free - the base class handles index
256
+ alignment between `X` and the stored `batch` labels, NaN / finite
257
+ checks, DataFrame-vs-ndarray round-tripping, and the `feature_names_in_`
258
+ / `n_features_in_` / `get_feature_names_out` sklearn bookkeeping.
259
+
260
+ Minimal custom corrector:
261
+
262
+ ```python
263
+ import pandas as pd
264
+ from maldibatchkit import BaseBatchCorrector
265
+
266
+ class MeanCentering(BaseBatchCorrector):
267
+ """Subtract per-batch means from each feature."""
268
+
269
+ def _fit_impl(self, X_df, batch):
270
+ # Store whatever you learn as ``..._`` attributes so
271
+ # ``sklearn.utils.validation.check_is_fitted`` picks them up.
272
+ self.batch_means_ = X_df.groupby(batch).mean()
273
+ self.grand_mean_ = X_df.mean(axis=0)
274
+
275
+ def _transform_impl(self, X_df, batch):
276
+ out = X_df.copy().astype(float)
277
+ known = set(self.batch_means_.index)
278
+ for lvl in pd.unique(batch):
279
+ mask = batch == lvl
280
+ offset = (
281
+ self.batch_means_.loc[lvl].to_numpy()
282
+ if lvl in known
283
+ else self.grand_mean_.to_numpy() # unseen-batch fallback
284
+ )
285
+ out.loc[mask] = out.loc[mask].to_numpy() - offset
286
+ return out
287
+ ```
288
+
289
+ Drop it straight into a pipeline:
290
+
291
+ ```python
292
+ from sklearn.pipeline import Pipeline
293
+ from sklearn.preprocessing import StandardScaler
294
+ from sklearn.ensemble import RandomForestClassifier
295
+
296
+ pipe = Pipeline([
297
+ ("mean", MeanCentering(batch=batch)),
298
+ ("scaler", StandardScaler()),
299
+ ("clf", RandomForestClassifier()),
300
+ ])
301
+ pipe.fit(X_train, y_train)
302
+ pipe.score(X_test, y_test) # no leakage: transform, never refit
303
+ ```
304
+
305
+ Conventions (see `CONTRIBUTING.md`):
306
+
307
+ - NumPy-style docstring on every public class.
308
+ - Fitted attributes end in `_` (`self.batch_means_`, not `self.means`).
309
+ - `transform` must be idempotent - no side effects outside `fit`.
310
+ - Raise a clear `ImportError` (not a bare `ModuleNotFoundError`) when
311
+ an optional dependency is missing; see `Harmony._require_harmonypy`
312
+ for the reference pattern.
313
+
314
+ Look at `maldibatchkit/corrections/baselines.py` for the simplest
315
+ end-to-end references (`MedianCentering`, `ZScorePerBatch`,
316
+ `ReferenceScaling`), or at `quality_weighted.py` for a corrector with
317
+ an iterative fit.
318
+
319
+ ## Diagnostics
320
+
321
+ ```python
322
+ from maldibatchkit.diagnostics import (
323
+ silhouette_batch, kbet, lisi,
324
+ peak_position_drift, tic_cov_per_batch, per_batch_spectrum_count,
325
+ diagnostic_report,
326
+ )
327
+ ```
328
+
329
+ All metrics take the same `(X, batch)` signature. `diagnostic_report`
330
+ composes them into a tidy DataFrame suitable for
331
+ `plot_diagnostic_summary`.
332
+
333
+ ## Citation
334
+
335
+ If you use MaldiBatchKit in academic work please cite:
336
+
337
+ > _Citation will be available soon._
338
+
339
+ along with the upstream references for whichever methods you apply
340
+ (Johnson 2007, Fortin 2018, Chen 2022, Ritchie 2015, Korsunsky 2019).
341
+
342
+ ## License
343
+
344
+ MIT. See [LICENSE](LICENSE).
@@ -0,0 +1,29 @@
1
+ maldibatchkit/__init__.py,sha256=VtoblR3GyM9S8MR178abapwNDA4gcanBTh3KotUDZy0,1861
2
+ maldibatchkit/_base.py,sha256=qvGN15g3PDvdNvXQ6_lzId_mjJN2wh0wvbIaTBmEq-I,6598
3
+ maldibatchkit/_cli_io.py,sha256=4AQR7hv6t5Cufvt0lLpNVN-gxMDZ7utqHQVvPtXhvtM,7452
4
+ maldibatchkit/_utils.py,sha256=IZ82HLXXp7St8HE9__qOYeH4bf30PkQge51zcNe4cH8,4705
5
+ maldibatchkit/cli.py,sha256=WtlMh_tF9qo-VksU5OMjDMHc3JhbLb7VoxE3MGOgc60,16194
6
+ maldibatchkit/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
+ maldibatchkit/corrections/__init__.py,sha256=vQ24MNXMIL41Ia86Pnq_j32IL1vDh2qSJ01voe1ZvKY,536
8
+ maldibatchkit/corrections/baselines.py,sha256=7YuzWn8H59iRv_ZQ4Euc1SaCrqo8X0oRPBPf2IRzFEU,8352
9
+ maldibatchkit/corrections/combat.py,sha256=r_P6TqU4GVoJZ7MKwsLLyx3Sc0Kt3NaN4v7PM7ExeK8,2968
10
+ maldibatchkit/corrections/harmony.py,sha256=dIPmZP-Pl72CNYLuG5cVcRXhmv5goj-2lmO2VDUrtXo,19150
11
+ maldibatchkit/corrections/limma.py,sha256=3kFI0xUky1XJtjf00T9j3yaWW4ML-8DvMuygw1EVhhQ,5636
12
+ maldibatchkit/corrections/maldi.py,sha256=0GZpaJceeyxZ1owxJ9p6diIc9XEgfyzZicPZm7S79Yg,5781
13
+ maldibatchkit/corrections/quality_weighted.py,sha256=6GTzGVY-H6nFEUT5_6bTfQliDSIH-V8CuXFyaaXzh5w,12459
14
+ maldibatchkit/diagnostics/__init__.py,sha256=QTtlmwMoQkzVj9xMNZfTREhgRTy5LcI62JD5bCQF-jw,1112
15
+ maldibatchkit/diagnostics/generic.py,sha256=JchApPkelttp1o4iGzVBJKAO91p2SstJteqg-gFrv6U,10814
16
+ maldibatchkit/diagnostics/maldi.py,sha256=ap3aqkGjAxQ7C84EEi6rV2TnFrtWobzF2aTwaXAmY70,5105
17
+ maldibatchkit/diagnostics/report.py,sha256=AoGxkG2nrz1u3Fy52cN1Kt7ZpIKecv8gYUDufzaWXVI,4764
18
+ maldibatchkit/integrations/__init__.py,sha256=4QYmeyQS8YiGmLd_3GZG-qiT3pz4O5KgjTgrkk4IqhM,208
19
+ maldibatchkit/integrations/maldiset.py,sha256=9lVHRbPhiPnWOwlNgwMIA5k5fdg8WzxIkElGjsTFv4Y,6830
20
+ maldibatchkit/viz/__init__.py,sha256=sUQGivvmQ9te1-F8t2xtKcZZ1vS87EvdgviZLrvvUSY,264
21
+ maldibatchkit/viz/peaks.py,sha256=bJ9LFepw-WKsPwAB1Afbxu1H1vK-O4VDfvU9DPYZDdg,2513
22
+ maldibatchkit/viz/summary.py,sha256=c6n1Al_ARV1XgWGPB37cLO3LGWe6FWM51cfiQg8h9j4,5139
23
+ maldibatchkit/viz/umap.py,sha256=sJ_ZHoFwtMeUkh5svwrcudoPhNlzvfTU3QTr5JEn01k,4031
24
+ maldibatchkit-0.1.0.dist-info/licenses/LICENSE,sha256=Lol2WnehwxpVVFc-xCZ88vvfdx8D3oEFXQR_zzKOvzQ,1070
25
+ maldibatchkit-0.1.0.dist-info/METADATA,sha256=CyWB3o-QvHMEJan2cTPdQjBfvQQ6nW0J0_HwV_jmwA4,13493
26
+ maldibatchkit-0.1.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
27
+ maldibatchkit-0.1.0.dist-info/entry_points.txt,sha256=4757O2qnRE-4jbc5koxzVsVfaev8C4fF2D3FrFd4PMM,56
28
+ maldibatchkit-0.1.0.dist-info/top_level.txt,sha256=AwIkysYFxU2uOIvZFq7ehuAfdFNgoQWDC5pVfwWoCPs,14
29
+ maldibatchkit-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
+ maldibatchkit = maldibatchkit.cli:app
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Ettore Rocchi
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1 @@
1
+ maldibatchkit