msdt 1.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.
Potentially problematic release.
This version of msdt might be problematic. Click here for more details.
- msdt-1.0.0/MANIFEST.in +2 -0
- msdt-1.0.0/PKG-INFO +116 -0
- msdt-1.0.0/README.md +97 -0
- msdt-1.0.0/msdt/__init__.py +112 -0
- msdt-1.0.0/msdt/_models/sediment_model.py +1191 -0
- msdt-1.0.0/msdt/_models/soil_model.py +1119 -0
- msdt-1.0.0/msdt/_models/water_ph7_model.py +1166 -0
- msdt-1.0.0/msdt/_models/water_ph9_model.py +738 -0
- msdt-1.0.0/msdt/engine.py +220 -0
- msdt-1.0.0/msdt/thresholds.json +42 -0
- msdt-1.0.0/msdt.egg-info/PKG-INFO +116 -0
- msdt-1.0.0/msdt.egg-info/SOURCES.txt +15 -0
- msdt-1.0.0/msdt.egg-info/dependency_links.txt +1 -0
- msdt-1.0.0/msdt.egg-info/requires.txt +3 -0
- msdt-1.0.0/msdt.egg-info/top_level.txt +1 -0
- msdt-1.0.0/pyproject.toml +34 -0
- msdt-1.0.0/setup.cfg +4 -0
msdt-1.0.0/MANIFEST.in
ADDED
msdt-1.0.0/PKG-INFO
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: msdt
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Multi-medium DT50 persistence prediction: DreaMS 1024-d embedding -> logDT50 interval, p(P)/p(vP) and P/vP decision across soil/sediment/water_ph7/water_ph9
|
|
5
|
+
Author: DT50 project
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://pypi.org/project/msdt/
|
|
8
|
+
Keywords: DT50,half-life,DreaMS,mass-spectrometry,persistence,uncertainty
|
|
9
|
+
Classifier: Programming Language :: Python :: 3
|
|
10
|
+
Classifier: Operating System :: Microsoft :: Windows
|
|
11
|
+
Classifier: Operating System :: POSIX :: Linux
|
|
12
|
+
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
|
|
13
|
+
Classifier: Topic :: Scientific/Engineering :: Chemistry
|
|
14
|
+
Requires-Python: >=3.10
|
|
15
|
+
Description-Content-Type: text/markdown
|
|
16
|
+
Requires-Dist: numpy>=1.24
|
|
17
|
+
Requires-Dist: scipy>=1.13
|
|
18
|
+
Requires-Dist: torch>=2.0
|
|
19
|
+
|
|
20
|
+
# msdt — Multi-medium DT50 Persistence Predictor
|
|
21
|
+
|
|
22
|
+
Predict chemical biotransformation persistence from a DreaMS mass-spectrometry
|
|
23
|
+
embedding (1024-d) with four pre-trained heteroscedastic neural networks:
|
|
24
|
+
|
|
25
|
+
| medium | NLL (val) | R² | model |
|
|
26
|
+
|---|---|---|---|
|
|
27
|
+
| soil | -0.619 | 0.777 | two-stage, STAGE2 pure-NLL |
|
|
28
|
+
| sediment | -0.560 | 0.358 | bagging 0.8, 20-member ensemble |
|
|
29
|
+
| water_ph7 | 0.636 | 0.103 | 10-member ensemble, VAR_SCALE 1.16 |
|
|
30
|
+
| water_ph9 | -0.396 | 0.545 | single, β-NLL (β=0.70) |
|
|
31
|
+
|
|
32
|
+
For each medium and scenario (`prec` = precision-oriented 0.7, `rec` =
|
|
33
|
+
recall-oriented 0.7) it returns the predictive interval, persistence
|
|
34
|
+
probabilities `p(P)` (≥120 d) / `p(vP)` (≥180 d), and the P/vP decision made
|
|
35
|
+
with the corresponding best threshold (from 5-fold CV on the training set).
|
|
36
|
+
|
|
37
|
+
## Installation
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
pip install msdt
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
> Note: `torch` is declared as a dependency; pip installs the PyPI build
|
|
44
|
+
> (CPU on Windows). For GPU inference, install the CUDA build first, e.g.
|
|
45
|
+
> `pip install torch --index-url https://download.pytorch.org/whl/cu126`.
|
|
46
|
+
|
|
47
|
+
### Model weights (required)
|
|
48
|
+
|
|
49
|
+
Weights (~210 MB zip) are **not** bundled in the wheel. Download
|
|
50
|
+
`msdt_models_v1.zip`, extract it, and point `MSDT_MODELS_DIR` at the extracted
|
|
51
|
+
`models` directory:
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
set MSDT_MODELS_DIR=D:\path\to\extracted\models # Windows
|
|
55
|
+
export MSDT_MODELS_DIR=/path/to/extracted/models # Linux
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Layout expected:
|
|
59
|
+
|
|
60
|
+
```
|
|
61
|
+
models/
|
|
62
|
+
soil/model_final.pth
|
|
63
|
+
sediment/model_final.pth
|
|
64
|
+
water_ph7/model_final.pth
|
|
65
|
+
water_ph9/model_final.pth
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Usage
|
|
69
|
+
|
|
70
|
+
```python
|
|
71
|
+
import msdt
|
|
72
|
+
|
|
73
|
+
# Single compound
|
|
74
|
+
r = msdt.predict(medium="soil", scenario="prec", dreams=dreams_1024d)
|
|
75
|
+
print(r["interval_days"], r["p_P"], r["p_vP"], r["is_P"], r["is_vP"])
|
|
76
|
+
|
|
77
|
+
# Batch (N, 1024)
|
|
78
|
+
b = msdt.predict_batch(medium="water_ph7", scenario="rec", dreams=dreams_Nx1024)
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
Parameters:
|
|
82
|
+
|
|
83
|
+
| parameter | values |
|
|
84
|
+
|---|---|
|
|
85
|
+
| `medium` | `"soil"` `"sediment"` `"water_ph7"` `"water_ph9"` |
|
|
86
|
+
| `scenario` | `"prec"` (precision ≥ 0.7, max recall) / `"rec"` (recall ≥ 0.7, max precision) |
|
|
87
|
+
| `dreams` | `(1024,)` or `(N, 1024)` float — raw DreaMS embedding, standardised internally |
|
|
88
|
+
|
|
89
|
+
## Output
|
|
90
|
+
|
|
91
|
+
Single (`predict`) returns a dict; batch (`predict_batch`) returns the same
|
|
92
|
+
keys as arrays of length N (`interval_*` as `(N, 2)`):
|
|
93
|
+
|
|
94
|
+
| field | meaning |
|
|
95
|
+
|---|---|
|
|
96
|
+
| `mu_log10` / `sigma_latent_log10` | predictive mean / deployable σ (log10 days) |
|
|
97
|
+
| `interval_log10` / `interval_days` | 95% interval μ ± 1.96·σ_latent, log10 and days |
|
|
98
|
+
| `p_P` / `p_vP` | P(logDT50 ≥ 120 d) / P(logDT50 ≥ 180 d) |
|
|
99
|
+
| `threshold_P` / `threshold_vP` | best threshold for the chosen scenario |
|
|
100
|
+
| `is_P` / `is_vP` | `p ≥ threshold` → `True` (classified as P / vP) |
|
|
101
|
+
|
|
102
|
+
## Thresholds (5-fold CV, training set)
|
|
103
|
+
|
|
104
|
+
| medium | P·prec | P·rec | vP·prec | vP·rec |
|
|
105
|
+
|---|---|---|---|---|
|
|
106
|
+
| soil | 0.118 | 0.132 | 0.020 | 0.006 |
|
|
107
|
+
| sediment | 0.237 | 0.048 | 0.055 | 0.014 |
|
|
108
|
+
| water_ph7 | 0.285 | 0.591 | 0.281 | 0.534 |
|
|
109
|
+
| water_ph9 | 0.429 | 0.381 | 0.414 | 0.321 |
|
|
110
|
+
|
|
111
|
+
## References
|
|
112
|
+
|
|
113
|
+
- Salz et al., *Environ. Sci. Technol.* 2026 — DT50 with known label noise α
|
|
114
|
+
- Seitzer et al., ICLR 2022 — β-NLL
|
|
115
|
+
- Lakshminarayanan et al., NeurIPS 2017 — deep ensembles
|
|
116
|
+
- Cator et al., 2022 — bootstrapped deep ensembles
|
msdt-1.0.0/README.md
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
# msdt — Multi-medium DT50 Persistence Predictor
|
|
2
|
+
|
|
3
|
+
Predict chemical biotransformation persistence from a DreaMS mass-spectrometry
|
|
4
|
+
embedding (1024-d) with four pre-trained heteroscedastic neural networks:
|
|
5
|
+
|
|
6
|
+
| medium | NLL (val) | R² | model |
|
|
7
|
+
|---|---|---|---|
|
|
8
|
+
| soil | -0.619 | 0.777 | two-stage, STAGE2 pure-NLL |
|
|
9
|
+
| sediment | -0.560 | 0.358 | bagging 0.8, 20-member ensemble |
|
|
10
|
+
| water_ph7 | 0.636 | 0.103 | 10-member ensemble, VAR_SCALE 1.16 |
|
|
11
|
+
| water_ph9 | -0.396 | 0.545 | single, β-NLL (β=0.70) |
|
|
12
|
+
|
|
13
|
+
For each medium and scenario (`prec` = precision-oriented 0.7, `rec` =
|
|
14
|
+
recall-oriented 0.7) it returns the predictive interval, persistence
|
|
15
|
+
probabilities `p(P)` (≥120 d) / `p(vP)` (≥180 d), and the P/vP decision made
|
|
16
|
+
with the corresponding best threshold (from 5-fold CV on the training set).
|
|
17
|
+
|
|
18
|
+
## Installation
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
pip install msdt
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
> Note: `torch` is declared as a dependency; pip installs the PyPI build
|
|
25
|
+
> (CPU on Windows). For GPU inference, install the CUDA build first, e.g.
|
|
26
|
+
> `pip install torch --index-url https://download.pytorch.org/whl/cu126`.
|
|
27
|
+
|
|
28
|
+
### Model weights (required)
|
|
29
|
+
|
|
30
|
+
Weights (~210 MB zip) are **not** bundled in the wheel. Download
|
|
31
|
+
`msdt_models_v1.zip`, extract it, and point `MSDT_MODELS_DIR` at the extracted
|
|
32
|
+
`models` directory:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
set MSDT_MODELS_DIR=D:\path\to\extracted\models # Windows
|
|
36
|
+
export MSDT_MODELS_DIR=/path/to/extracted/models # Linux
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Layout expected:
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
models/
|
|
43
|
+
soil/model_final.pth
|
|
44
|
+
sediment/model_final.pth
|
|
45
|
+
water_ph7/model_final.pth
|
|
46
|
+
water_ph9/model_final.pth
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Usage
|
|
50
|
+
|
|
51
|
+
```python
|
|
52
|
+
import msdt
|
|
53
|
+
|
|
54
|
+
# Single compound
|
|
55
|
+
r = msdt.predict(medium="soil", scenario="prec", dreams=dreams_1024d)
|
|
56
|
+
print(r["interval_days"], r["p_P"], r["p_vP"], r["is_P"], r["is_vP"])
|
|
57
|
+
|
|
58
|
+
# Batch (N, 1024)
|
|
59
|
+
b = msdt.predict_batch(medium="water_ph7", scenario="rec", dreams=dreams_Nx1024)
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
Parameters:
|
|
63
|
+
|
|
64
|
+
| parameter | values |
|
|
65
|
+
|---|---|
|
|
66
|
+
| `medium` | `"soil"` `"sediment"` `"water_ph7"` `"water_ph9"` |
|
|
67
|
+
| `scenario` | `"prec"` (precision ≥ 0.7, max recall) / `"rec"` (recall ≥ 0.7, max precision) |
|
|
68
|
+
| `dreams` | `(1024,)` or `(N, 1024)` float — raw DreaMS embedding, standardised internally |
|
|
69
|
+
|
|
70
|
+
## Output
|
|
71
|
+
|
|
72
|
+
Single (`predict`) returns a dict; batch (`predict_batch`) returns the same
|
|
73
|
+
keys as arrays of length N (`interval_*` as `(N, 2)`):
|
|
74
|
+
|
|
75
|
+
| field | meaning |
|
|
76
|
+
|---|---|
|
|
77
|
+
| `mu_log10` / `sigma_latent_log10` | predictive mean / deployable σ (log10 days) |
|
|
78
|
+
| `interval_log10` / `interval_days` | 95% interval μ ± 1.96·σ_latent, log10 and days |
|
|
79
|
+
| `p_P` / `p_vP` | P(logDT50 ≥ 120 d) / P(logDT50 ≥ 180 d) |
|
|
80
|
+
| `threshold_P` / `threshold_vP` | best threshold for the chosen scenario |
|
|
81
|
+
| `is_P` / `is_vP` | `p ≥ threshold` → `True` (classified as P / vP) |
|
|
82
|
+
|
|
83
|
+
## Thresholds (5-fold CV, training set)
|
|
84
|
+
|
|
85
|
+
| medium | P·prec | P·rec | vP·prec | vP·rec |
|
|
86
|
+
|---|---|---|---|---|
|
|
87
|
+
| soil | 0.118 | 0.132 | 0.020 | 0.006 |
|
|
88
|
+
| sediment | 0.237 | 0.048 | 0.055 | 0.014 |
|
|
89
|
+
| water_ph7 | 0.285 | 0.591 | 0.281 | 0.534 |
|
|
90
|
+
| water_ph9 | 0.429 | 0.381 | 0.414 | 0.321 |
|
|
91
|
+
|
|
92
|
+
## References
|
|
93
|
+
|
|
94
|
+
- Salz et al., *Environ. Sci. Technol.* 2026 — DT50 with known label noise α
|
|
95
|
+
- Seitzer et al., ICLR 2022 — β-NLL
|
|
96
|
+
- Lakshminarayanan et al., NeurIPS 2017 — deep ensembles
|
|
97
|
+
- Cator et al., 2022 — bootstrapped deep ensembles
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
"""msdt - multi-medium DT50 persistence prediction library.
|
|
2
|
+
|
|
3
|
+
Combines the four medium-optimal heteroscedastic models
|
|
4
|
+
(soil / sediment / water_ph7 / water_ph9). Given a DreaMS mass-spectrometry
|
|
5
|
+
embedding (1024-d) it returns:
|
|
6
|
+
- predictive interval (mu +/- 1.96*sigma_latent, log10-days and days)
|
|
7
|
+
- persistence probabilities p(P) / p(vP) (120 d / 180 d thresholds)
|
|
8
|
+
- P / vP decisions made with the best threshold of the chosen scenario
|
|
9
|
+
(``prec`` = precision-oriented 0.7, ``rec`` = recall-oriented 0.7)
|
|
10
|
+
|
|
11
|
+
Usage:
|
|
12
|
+
import msdt
|
|
13
|
+
out = msdt.predict("soil", "prec", dreams_1024d, models_dir="D:/models")
|
|
14
|
+
outs = msdt.predict_batch("water_ph7", "rec", dreams_Nx1024, models_dir="D:/models")
|
|
15
|
+
"""
|
|
16
|
+
from __future__ import annotations
|
|
17
|
+
|
|
18
|
+
from typing import Any, Dict, List, Optional, Union
|
|
19
|
+
|
|
20
|
+
import numpy as np
|
|
21
|
+
|
|
22
|
+
from .engine import (
|
|
23
|
+
MEDIUM_CFG,
|
|
24
|
+
MEDIUMS,
|
|
25
|
+
SCENARIOS,
|
|
26
|
+
get_engine,
|
|
27
|
+
validate_scenario,
|
|
28
|
+
_validate_vector,
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
__all__ = ["predict", "predict_batch", "MEDIUMS", "SCENARIOS"]
|
|
32
|
+
__version__ = "1.0.0"
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def _single_result(medium: str, scenario: str, r: Dict[str, Any]) -> Dict[str, Any]:
|
|
36
|
+
return {
|
|
37
|
+
"medium": medium,
|
|
38
|
+
"scenario": scenario,
|
|
39
|
+
"mu_log10": float(r["mu_log10"][0]),
|
|
40
|
+
"sigma_latent_log10": float(r["sigma_latent_log10"][0]),
|
|
41
|
+
"interval_log10": [float(r["interval_log10"][0, 0]), float(r["interval_log10"][0, 1])],
|
|
42
|
+
"interval_days": [float(r["interval_days"][0, 0]), float(r["interval_days"][0, 1])],
|
|
43
|
+
"p_P": float(r["p_P"][0]),
|
|
44
|
+
"p_vP": float(r["p_vP"][0]),
|
|
45
|
+
"threshold_P": float(r["threshold_P"]),
|
|
46
|
+
"threshold_vP": float(r["threshold_vP"]),
|
|
47
|
+
"is_P": bool(r["is_P"][0]),
|
|
48
|
+
"is_vP": bool(r["is_vP"][0]),
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def predict(
|
|
53
|
+
medium: str,
|
|
54
|
+
scenario: str,
|
|
55
|
+
dreams: Union[np.ndarray, List[float]],
|
|
56
|
+
models_dir: Optional[str] = None,
|
|
57
|
+
) -> Dict[str, Any]:
|
|
58
|
+
"""Predict for a single compound.
|
|
59
|
+
|
|
60
|
+
Args:
|
|
61
|
+
medium: "soil" | "sediment" | "water_ph7" | "water_ph9"
|
|
62
|
+
scenario: "prec" (precision >= 0.7, max recall) | "rec" (recall >= 0.7, max precision)
|
|
63
|
+
dreams: DreaMS embedding, shape (1024,)
|
|
64
|
+
models_dir: optional directory containing {medium}/model_final.pth;
|
|
65
|
+
overrides MSDT_MODELS_DIR
|
|
66
|
+
|
|
67
|
+
Returns:
|
|
68
|
+
dict with predictive interval, p(P)/p(vP), thresholds and P/vP decisions
|
|
69
|
+
"""
|
|
70
|
+
medium = str(medium).lower().strip()
|
|
71
|
+
scenario = validate_scenario(scenario)
|
|
72
|
+
x = _validate_vector(dreams, batch=False)
|
|
73
|
+
r = get_engine(medium, models_dir).run(x, scenario)
|
|
74
|
+
return _single_result(medium, scenario, r)
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def predict_batch(
|
|
78
|
+
medium: str,
|
|
79
|
+
scenario: str,
|
|
80
|
+
dreams: Union[np.ndarray, List[List[float]]],
|
|
81
|
+
models_dir: Optional[str] = None,
|
|
82
|
+
) -> Dict[str, Any]:
|
|
83
|
+
"""Predict for a batch of compounds.
|
|
84
|
+
|
|
85
|
+
Args:
|
|
86
|
+
medium: "soil" | "sediment" | "water_ph7" | "water_ph9"
|
|
87
|
+
scenario: "prec" | "rec"
|
|
88
|
+
dreams: DreaMS embedding matrix, shape (N, 1024)
|
|
89
|
+
models_dir: optional directory containing {medium}/model_final.pth
|
|
90
|
+
|
|
91
|
+
Returns:
|
|
92
|
+
dict; scalar fields become arrays of length N (interval_* are (N, 2))
|
|
93
|
+
"""
|
|
94
|
+
medium = str(medium).lower().strip()
|
|
95
|
+
scenario = validate_scenario(scenario)
|
|
96
|
+
x = _validate_vector(dreams, batch=True)
|
|
97
|
+
r = get_engine(medium, models_dir).run(x, scenario)
|
|
98
|
+
return {
|
|
99
|
+
"medium": medium,
|
|
100
|
+
"scenario": scenario,
|
|
101
|
+
"n": int(len(x)),
|
|
102
|
+
"mu_log10": r["mu_log10"],
|
|
103
|
+
"sigma_latent_log10": r["sigma_latent_log10"],
|
|
104
|
+
"interval_log10": r["interval_log10"],
|
|
105
|
+
"interval_days": r["interval_days"],
|
|
106
|
+
"p_P": r["p_P"],
|
|
107
|
+
"p_vP": r["p_vP"],
|
|
108
|
+
"threshold_P": float(r["threshold_P"]),
|
|
109
|
+
"threshold_vP": float(r["threshold_vP"]),
|
|
110
|
+
"is_P": r["is_P"],
|
|
111
|
+
"is_vP": r["is_vP"],
|
|
112
|
+
}
|