ms-mint 0.2.4__tar.gz → 0.3.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.
- {ms-mint-0.2.4/ms_mint.egg-info → ms-mint-0.3.0}/PKG-INFO +17 -10
- {ms-mint-0.2.4 → ms-mint-0.3.0}/README.md +16 -9
- ms-mint-0.2.4/ms_mint/chromatogram.py → ms-mint-0.3.0/ms_mint/Chromatogram.py +34 -28
- {ms-mint-0.2.4 → ms-mint-0.3.0}/ms_mint/Mint.py +80 -24
- ms-mint-0.2.4/ms_mint/plotting.py → ms-mint-0.3.0/ms_mint/MintPlotter.py +5 -4
- ms-mint-0.3.0/ms_mint/TargetOptimizer.py +158 -0
- {ms-mint-0.2.4 → ms-mint-0.3.0}/ms_mint/_version.py +3 -3
- {ms-mint-0.2.4 → ms-mint-0.3.0}/ms_mint/filters.py +10 -3
- {ms-mint-0.2.4 → ms-mint-0.3.0}/ms_mint/io.py +2 -7
- {ms-mint-0.2.4 → ms-mint-0.3.0}/ms_mint/matplotlib_tools.py +1 -1
- {ms-mint-0.2.4 → ms-mint-0.3.0}/ms_mint/pca.py +85 -23
- {ms-mint-0.2.4 → ms-mint-0.3.0}/ms_mint/plotly_tools.py +9 -5
- {ms-mint-0.2.4 → ms-mint-0.3.0}/ms_mint/processing.py +34 -3
- {ms-mint-0.2.4 → ms-mint-0.3.0}/ms_mint/standards.py +3 -2
- {ms-mint-0.2.4 → ms-mint-0.3.0}/ms_mint/targets.py +6 -144
- {ms-mint-0.2.4 → ms-mint-0.3.0}/ms_mint/tools.py +26 -4
- {ms-mint-0.2.4 → ms-mint-0.3.0/ms_mint.egg-info}/PKG-INFO +17 -10
- {ms-mint-0.2.4 → ms-mint-0.3.0}/ms_mint.egg-info/SOURCES.txt +3 -2
- {ms-mint-0.2.4 → ms-mint-0.3.0}/LICENSE +0 -0
- {ms-mint-0.2.4 → ms-mint-0.3.0}/MANIFEST.in +0 -0
- {ms-mint-0.2.4 → ms-mint-0.3.0}/ms_mint/__init__.py +0 -0
- {ms-mint-0.2.4 → ms-mint-0.3.0}/ms_mint/filelock.py +0 -0
- {ms-mint-0.2.4 → ms-mint-0.3.0}/ms_mint/notebook.py +0 -0
- {ms-mint-0.2.4 → ms-mint-0.3.0}/ms_mint.egg-info/dependency_links.txt +0 -0
- {ms-mint-0.2.4 → ms-mint-0.3.0}/ms_mint.egg-info/requires.txt +0 -0
- {ms-mint-0.2.4 → ms-mint-0.3.0}/ms_mint.egg-info/top_level.txt +0 -0
- {ms-mint-0.2.4 → ms-mint-0.3.0}/scripts/ms-mint-convert.py +0 -0
- {ms-mint-0.2.4 → ms-mint-0.3.0}/setup.cfg +0 -0
- {ms-mint-0.2.4 → ms-mint-0.3.0}/setup.py +0 -0
- {ms-mint-0.2.4 → ms-mint-0.3.0}/versioneer.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: ms-mint
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: Metabolomics Integrator (Mint)
|
|
5
5
|
Home-page: https://github.com/LewisResearchGroup/ms-mint
|
|
6
6
|
Author: Soren Wacker
|
|
@@ -16,19 +16,28 @@ License-File: LICENSE
|
|
|
16
16
|

|
|
17
17
|
[](https://github.com/lewisresearchgroup/ms-mint/actions/workflows/codeql-analysis.yml)
|
|
18
18
|
|
|
19
|
-
# Wecome to ms-mint
|
|
19
|
+
# Wecome to ms-mint
|
|
20
20
|
|
|
21
21
|
## A Python library for targeted metabolomics
|
|
22
22
|
The `ms-mint` library is a tool designed to assist with targeted metabolomics studies, which involves the systematic analysis of small chemical compounds called metabolites that are present in biological samples. These metabolites can provide valuable information about the state of an organism, including indicators of disease or other physiological changes. In order to perform a targeted metabolomics study, researchers typically use liquid chromatography-mass spectrometry (LCMS) to identify and quantify specific metabolites of interest.
|
|
23
23
|
|
|
24
24
|
The `ms-mint` library includes a range of functions for processing LCMS data from targeted metabolomics experiments, and it is particularly well-suited for handling large amounts of data (10,000+ files). To use `ms-mint`, you provide it with a target list of the specific metabolites you want to analyze, as well as the names of the mass spectrometry files containing the data. ms-mint then extracts peak intensities and other relevant information from the data, allowing you to gain insights into the concentrations and profiles of the metabolites in your samples. This information can be used to identify biomarkers, which are indicators of disease or other physiological changes that can be used in the development of diagnostic tests or other medical applications.
|
|
25
25
|
|
|
26
|
+
## Installation
|
|
27
|
+
|
|
28
|
+
pip install ms-mint
|
|
29
|
+
|
|
30
|
+
|
|
26
31
|
## Documentation
|
|
27
32
|
The code documentation can be accessed [here](https://lewisresearchgroup.github.io/ms-mint/readme.html).
|
|
28
33
|
|
|
29
34
|
## ms-mint application with graphical user iterface (GUI)
|
|
30
35
|
MINT has been split into the Python library and the app. This repository contains the Python library. For the app follow [this link](https://github.com/LewisResearchGroup/ms-mint-app).
|
|
31
36
|
|
|
37
|
+
## Publications that used ms-mint
|
|
38
|
+
1. Brown K, Thomson CA, Wacker S, Drikic M, Groves R, Fan V, et al. [Microbiota alters the metabolome in an age- and sex- dependent manner in mice.](https://pubmed.ncbi.nlm.nih.gov/36906623/) Nat Commun. 2023;14: 1348.
|
|
39
|
+
|
|
40
|
+
---
|
|
32
41
|
## Contributions
|
|
33
42
|
All contributions, bug reports, code reviews, bug fixes, documentation improvements, enhancements, and ideas are welcome.
|
|
34
43
|
Before you modify the code please reach out to us using the [issues](https://github.com/LewisResearchGroup/ms-mint/issues) page.
|
|
@@ -36,8 +45,6 @@ Before you modify the code please reach out to us using the [issues](https://git
|
|
|
36
45
|
## Code standards
|
|
37
46
|
The project follows PEP8 standard and uses Black and Flake8 to ensure a consistent code format throughout the project.
|
|
38
47
|
|
|
39
|
-
---
|
|
40
|
-
|
|
41
48
|
## Usage
|
|
42
49
|
|
|
43
50
|
To use the main class of the ms-mint library, you can import it into your code with the following command:
|
|
@@ -129,7 +136,7 @@ If you only have retention time (Rt) values for your targets, or if the Rt value
|
|
|
129
136
|
|
|
130
137
|
To use the `mint.opt.rt_min_max()` function, you will need to provide it with a list of retention times for your targets and the names of the mass spectrometry files containing your data. The function will then search through the data to find the optimal `rt_min` and `rt_max` values, which you can use to refine your analysis. You can then use these optimized values in conjunction with the other functions and methods of the `Mint` class to process and analyze your data.
|
|
131
138
|
|
|
132
|
-

|
|
139
|
+

|
|
133
140
|
|
|
134
141
|
Now, we can run the peak optimization with:
|
|
135
142
|
|
|
@@ -146,7 +153,7 @@ If you do not provide a list of peak_labels to the `mint.opt.rt_min_max()` funct
|
|
|
146
153
|
|
|
147
154
|
After running the optimization, it is a good idea to perform a manual fine-tuning of the `rt_min` and `rt_max` values, especially for complicated peaks (peaks with multiple components, noisy peaks, etc.). You can use the `mint.plot.peak_shapes()` function to visualize the peak shapes and identify any areas that may require further attention.
|
|
148
155
|
|
|
149
|
-

|
|
156
|
+

|
|
150
157
|
|
|
151
158
|
The black lines indicates the average intensity across all files used for the optimization. The orange dotted lines show the shape of the gaussian function used to weight the mean intensities for peak selection. The orange horizontal lines indicate the peak width and the blue `x`s show the identified peak maxima. The green shaded areas show the Rt ranges which were selected by the algorithm.
|
|
152
159
|
|
|
@@ -155,7 +162,7 @@ Then we apply the changes and plot the new peak shapes:
|
|
|
155
162
|
mint.run()
|
|
156
163
|
mint.plot.peak_shapes(col_wrap=3)
|
|
157
164
|
|
|
158
|
-

|
|
165
|
+

|
|
159
166
|
|
|
160
167
|
As you can see, the shapes of Xanthine, Succinate, Citrulline look much better.
|
|
161
168
|
|
|
@@ -165,7 +172,7 @@ The `Mint` class has a few convenient methods to visualize and explore the proce
|
|
|
165
172
|
|
|
166
173
|
## Plot peak shapes
|
|
167
174
|
|
|
168
|
-

|
|
175
|
+

|
|
169
176
|
|
|
170
177
|
mint.plot.peak_shapes(col_wrap = 3)
|
|
171
178
|
|
|
@@ -200,7 +207,7 @@ Before clustering the data can be transformed and scaled. By default `log2p1(x)
|
|
|
200
207
|
cmap=None # Name of a matplotlib color map
|
|
201
208
|
)
|
|
202
209
|
|
|
203
|
-

|
|
210
|
+

|
|
204
211
|
|
|
205
212
|
## Principal Components Analysis
|
|
206
213
|
|
|
@@ -214,7 +221,7 @@ After running the PCA the results can be plotted with:
|
|
|
214
221
|
|
|
215
222
|
mint.pca.plot.pairplot(n_components=5, interactive=False)
|
|
216
223
|
|
|
217
|
-

|
|
224
|
+

|
|
218
225
|
|
|
219
226
|
## FAQ
|
|
220
227
|
### What is a target list
|
|
@@ -2,19 +2,28 @@
|
|
|
2
2
|

|
|
3
3
|
[](https://github.com/lewisresearchgroup/ms-mint/actions/workflows/codeql-analysis.yml)
|
|
4
4
|
|
|
5
|
-
# Wecome to ms-mint
|
|
5
|
+
# Wecome to ms-mint
|
|
6
6
|
|
|
7
7
|
## A Python library for targeted metabolomics
|
|
8
8
|
The `ms-mint` library is a tool designed to assist with targeted metabolomics studies, which involves the systematic analysis of small chemical compounds called metabolites that are present in biological samples. These metabolites can provide valuable information about the state of an organism, including indicators of disease or other physiological changes. In order to perform a targeted metabolomics study, researchers typically use liquid chromatography-mass spectrometry (LCMS) to identify and quantify specific metabolites of interest.
|
|
9
9
|
|
|
10
10
|
The `ms-mint` library includes a range of functions for processing LCMS data from targeted metabolomics experiments, and it is particularly well-suited for handling large amounts of data (10,000+ files). To use `ms-mint`, you provide it with a target list of the specific metabolites you want to analyze, as well as the names of the mass spectrometry files containing the data. ms-mint then extracts peak intensities and other relevant information from the data, allowing you to gain insights into the concentrations and profiles of the metabolites in your samples. This information can be used to identify biomarkers, which are indicators of disease or other physiological changes that can be used in the development of diagnostic tests or other medical applications.
|
|
11
11
|
|
|
12
|
+
## Installation
|
|
13
|
+
|
|
14
|
+
pip install ms-mint
|
|
15
|
+
|
|
16
|
+
|
|
12
17
|
## Documentation
|
|
13
18
|
The code documentation can be accessed [here](https://lewisresearchgroup.github.io/ms-mint/readme.html).
|
|
14
19
|
|
|
15
20
|
## ms-mint application with graphical user iterface (GUI)
|
|
16
21
|
MINT has been split into the Python library and the app. This repository contains the Python library. For the app follow [this link](https://github.com/LewisResearchGroup/ms-mint-app).
|
|
17
22
|
|
|
23
|
+
## Publications that used ms-mint
|
|
24
|
+
1. Brown K, Thomson CA, Wacker S, Drikic M, Groves R, Fan V, et al. [Microbiota alters the metabolome in an age- and sex- dependent manner in mice.](https://pubmed.ncbi.nlm.nih.gov/36906623/) Nat Commun. 2023;14: 1348.
|
|
25
|
+
|
|
26
|
+
---
|
|
18
27
|
## Contributions
|
|
19
28
|
All contributions, bug reports, code reviews, bug fixes, documentation improvements, enhancements, and ideas are welcome.
|
|
20
29
|
Before you modify the code please reach out to us using the [issues](https://github.com/LewisResearchGroup/ms-mint/issues) page.
|
|
@@ -22,8 +31,6 @@ Before you modify the code please reach out to us using the [issues](https://git
|
|
|
22
31
|
## Code standards
|
|
23
32
|
The project follows PEP8 standard and uses Black and Flake8 to ensure a consistent code format throughout the project.
|
|
24
33
|
|
|
25
|
-
---
|
|
26
|
-
|
|
27
34
|
## Usage
|
|
28
35
|
|
|
29
36
|
To use the main class of the ms-mint library, you can import it into your code with the following command:
|
|
@@ -115,7 +122,7 @@ If you only have retention time (Rt) values for your targets, or if the Rt value
|
|
|
115
122
|
|
|
116
123
|
To use the `mint.opt.rt_min_max()` function, you will need to provide it with a list of retention times for your targets and the names of the mass spectrometry files containing your data. The function will then search through the data to find the optimal `rt_min` and `rt_max` values, which you can use to refine your analysis. You can then use these optimized values in conjunction with the other functions and methods of the `Mint` class to process and analyze your data.
|
|
117
124
|
|
|
118
|
-

|
|
125
|
+

|
|
119
126
|
|
|
120
127
|
Now, we can run the peak optimization with:
|
|
121
128
|
|
|
@@ -132,7 +139,7 @@ If you do not provide a list of peak_labels to the `mint.opt.rt_min_max()` funct
|
|
|
132
139
|
|
|
133
140
|
After running the optimization, it is a good idea to perform a manual fine-tuning of the `rt_min` and `rt_max` values, especially for complicated peaks (peaks with multiple components, noisy peaks, etc.). You can use the `mint.plot.peak_shapes()` function to visualize the peak shapes and identify any areas that may require further attention.
|
|
134
141
|
|
|
135
|
-

|
|
142
|
+

|
|
136
143
|
|
|
137
144
|
The black lines indicates the average intensity across all files used for the optimization. The orange dotted lines show the shape of the gaussian function used to weight the mean intensities for peak selection. The orange horizontal lines indicate the peak width and the blue `x`s show the identified peak maxima. The green shaded areas show the Rt ranges which were selected by the algorithm.
|
|
138
145
|
|
|
@@ -141,7 +148,7 @@ Then we apply the changes and plot the new peak shapes:
|
|
|
141
148
|
mint.run()
|
|
142
149
|
mint.plot.peak_shapes(col_wrap=3)
|
|
143
150
|
|
|
144
|
-

|
|
151
|
+

|
|
145
152
|
|
|
146
153
|
As you can see, the shapes of Xanthine, Succinate, Citrulline look much better.
|
|
147
154
|
|
|
@@ -151,7 +158,7 @@ The `Mint` class has a few convenient methods to visualize and explore the proce
|
|
|
151
158
|
|
|
152
159
|
## Plot peak shapes
|
|
153
160
|
|
|
154
|
-

|
|
161
|
+

|
|
155
162
|
|
|
156
163
|
mint.plot.peak_shapes(col_wrap = 3)
|
|
157
164
|
|
|
@@ -186,7 +193,7 @@ Before clustering the data can be transformed and scaled. By default `log2p1(x)
|
|
|
186
193
|
cmap=None # Name of a matplotlib color map
|
|
187
194
|
)
|
|
188
195
|
|
|
189
|
-

|
|
196
|
+

|
|
190
197
|
|
|
191
198
|
## Principal Components Analysis
|
|
192
199
|
|
|
@@ -200,7 +207,7 @@ After running the PCA the results can be plotted with:
|
|
|
200
207
|
|
|
201
208
|
mint.pca.plot.pairplot(n_components=5, interactive=False)
|
|
202
209
|
|
|
203
|
-

|
|
210
|
+

|
|
204
211
|
|
|
205
212
|
## FAQ
|
|
206
213
|
### What is a target list
|
|
@@ -6,31 +6,48 @@ from matplotlib import pyplot as plt
|
|
|
6
6
|
|
|
7
7
|
from .tools import find_peaks_in_timeseries, gaussian, mz_mean_width_to_min_max
|
|
8
8
|
from .io import ms_file_to_df
|
|
9
|
-
from .filters import Resampler, Smoother, GaussFilter
|
|
9
|
+
from .filters import Filter, Resampler, Smoother, GaussFilter
|
|
10
10
|
from .matplotlib_tools import plot_peaks
|
|
11
|
+
from .processing import get_chromatogram_from_ms_file
|
|
12
|
+
|
|
13
|
+
from typing import Optional, Union, List, Any
|
|
11
14
|
|
|
12
15
|
|
|
13
16
|
class Chromatogram:
|
|
14
17
|
def __init__(
|
|
15
|
-
self,
|
|
18
|
+
self,
|
|
19
|
+
scan_times: Optional[Union[List[float], np.ndarray]] = None,
|
|
20
|
+
intensities: Optional[Union[List[float], np.ndarray]] = None,
|
|
21
|
+
filters: Optional[List[Filter]] = None,
|
|
22
|
+
expected_rt: Optional[float] = None
|
|
16
23
|
):
|
|
17
|
-
|
|
18
|
-
|
|
24
|
+
"""
|
|
25
|
+
Initialize a Chromatogram object.
|
|
26
|
+
|
|
27
|
+
:param scan_times: Array-like object containing the scan times.
|
|
28
|
+
:param intensities: Array-like object containing the intensities.
|
|
29
|
+
:param filters: List of filters to be applied.
|
|
30
|
+
:param expected_rt: Expected retention time.
|
|
31
|
+
"""
|
|
32
|
+
# Initialize empty arrays for scan_times and intensities
|
|
33
|
+
# Initialize scan_times and intensities as empty lists or arrays
|
|
34
|
+
self.t = np.array([]) if scan_times is None or 0 in scan_times else np.array([0])
|
|
35
|
+
self.x = np.array([]) if intensities is None or 0 in scan_times else np.array([0])
|
|
36
|
+
|
|
37
|
+
# Update scan_times and intensities if provided
|
|
19
38
|
if scan_times is not None:
|
|
20
39
|
self.t = np.append(self.t, scan_times)
|
|
21
40
|
if intensities is not None:
|
|
22
41
|
self.x = np.append(self.x, intensities)
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
self.
|
|
29
|
-
self.selected_peak_ndxs = None
|
|
30
|
-
if expected_rt is None and scan_times is not None:
|
|
31
|
-
expected_rt = max(scan_times) // 2
|
|
42
|
+
|
|
43
|
+
# Initialize other attributes
|
|
44
|
+
self.noise_level: Optional[float] = None
|
|
45
|
+
self.filters: List[Any] = filters or [Resampler(), GaussFilter(), Smoother()]
|
|
46
|
+
self.peaks: Optional[pd.DataFrame] = None
|
|
47
|
+
self.selected_peak_ndxs: Optional[List[int]] = None
|
|
32
48
|
self.expected_rt = expected_rt
|
|
33
|
-
self.weights = None
|
|
49
|
+
self.weights: Optional[Union[List[float], np.ndarray]] = None
|
|
50
|
+
|
|
34
51
|
|
|
35
52
|
def from_file(self, fn, mz_mean, mz_width=10, expected_rt=None):
|
|
36
53
|
chrom = get_chromatogram_from_ms_file(fn, mz_mean=mz_mean, mz_width=mz_width)
|
|
@@ -47,14 +64,15 @@ class Chromatogram:
|
|
|
47
64
|
for filt in self.filters:
|
|
48
65
|
self.t, self.x = filt.transform(self.t, self.x)
|
|
49
66
|
|
|
50
|
-
def find_peaks(self, prominence=None, rel_height=0.9):
|
|
67
|
+
def find_peaks(self, prominence=None, rel_height=0.9, **kwargs):
|
|
51
68
|
self.estimate_noise_level()
|
|
52
69
|
if prominence is None:
|
|
53
|
-
prominence = self.noise_level *
|
|
70
|
+
prominence = self.noise_level * 5
|
|
54
71
|
self.peaks = find_peaks_in_timeseries(
|
|
55
72
|
self.data.intensity,
|
|
56
73
|
prominence=prominence,
|
|
57
74
|
rel_height=rel_height,
|
|
75
|
+
**kwargs
|
|
58
76
|
)
|
|
59
77
|
|
|
60
78
|
def optimise_peak_times_with_diff(self, rolling_window=20, plot=False):
|
|
@@ -153,15 +171,3 @@ class Chromatogram:
|
|
|
153
171
|
)
|
|
154
172
|
return fig
|
|
155
173
|
|
|
156
|
-
|
|
157
|
-
def get_chromatogram_from_ms_file(ms_file, mz_mean, mz_width=10):
|
|
158
|
-
df = ms_file_to_df(ms_file)
|
|
159
|
-
chrom = extract_chromatogram_from_ms1(df, mz_mean, mz_width=mz_width)
|
|
160
|
-
return chrom
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
def extract_chromatogram_from_ms1(ms1, mz_mean, mz_width=10):
|
|
164
|
-
mz_min, mz_max = mz_mean_width_to_min_max(mz_mean, mz_width)
|
|
165
|
-
chrom = ms1[(ms1["mz"] >= mz_min) & (ms1["mz"] <= mz_max)].copy()
|
|
166
|
-
chrom = chrom.groupby("scan_time", as_index=False).sum(numeric_only=True)
|
|
167
|
-
return chrom.set_index("scan_time")["intensity"]
|
|
@@ -11,20 +11,21 @@ from multiprocessing import Pool, Manager, cpu_count
|
|
|
11
11
|
from glob import glob
|
|
12
12
|
|
|
13
13
|
from .standards import MINT_RESULTS_COLUMNS, TARGETS_COLUMNS, DEPRECATED_LABELS
|
|
14
|
-
from .processing import process_ms1_files_in_parallel
|
|
14
|
+
from .processing import process_ms1_files_in_parallel, extract_chromatogram_from_ms1
|
|
15
15
|
from .io import export_to_excel, ms_file_to_df
|
|
16
|
-
from .
|
|
16
|
+
from .TargetOptimizer import TargetOptimizer
|
|
17
|
+
from .targets import read_targets, check_targets, standardize_targets
|
|
17
18
|
from .tools import (
|
|
18
19
|
is_ms_file,
|
|
19
20
|
get_ms_files_from_results,
|
|
20
21
|
get_targets_from_results,
|
|
21
22
|
scale_dataframe,
|
|
23
|
+
init_metadata,
|
|
24
|
+
fn_to_label
|
|
22
25
|
)
|
|
23
26
|
from .pca import PrincipalComponentsAnalyser
|
|
24
|
-
from .
|
|
25
|
-
|
|
26
|
-
# from .filter import Resampler
|
|
27
|
-
from .chromatogram import Chromatogram, extract_chromatogram_from_ms1
|
|
27
|
+
from .MintPlotter import MintPlotter
|
|
28
|
+
from .Chromatogram import Chromatogram
|
|
28
29
|
|
|
29
30
|
import ms_mint
|
|
30
31
|
|
|
@@ -33,6 +34,7 @@ from tqdm import tqdm
|
|
|
33
34
|
from typing import Callable
|
|
34
35
|
from functools import lru_cache
|
|
35
36
|
|
|
37
|
+
METADATA_DEFAUT_FN = 'metadata.parquet'
|
|
36
38
|
|
|
37
39
|
class Mint(object):
|
|
38
40
|
"""
|
|
@@ -44,6 +46,8 @@ class Mint(object):
|
|
|
44
46
|
:param progress_callback: A callback for a progress bar.
|
|
45
47
|
:type progress_callback: Callable[]
|
|
46
48
|
|
|
49
|
+
:parm wdir: Working directory
|
|
50
|
+
:type wdir: str
|
|
47
51
|
"""
|
|
48
52
|
|
|
49
53
|
def __init__(
|
|
@@ -51,18 +55,21 @@ class Mint(object):
|
|
|
51
55
|
verbose: bool = False,
|
|
52
56
|
progress_callback: Callable = None,
|
|
53
57
|
time_unit: str = "s",
|
|
58
|
+
wdir: str = None
|
|
54
59
|
):
|
|
55
60
|
self.verbose = verbose
|
|
56
61
|
self._version = ms_mint.__version__
|
|
62
|
+
print("Mint version:", self.version, "\n")
|
|
57
63
|
self.progress_callback = progress_callback
|
|
58
64
|
self.reset()
|
|
59
|
-
if self.verbose:
|
|
60
|
-
print("Mint Version:", self.version, "\n")
|
|
61
65
|
self.plot = MintPlotter(mint=self)
|
|
62
66
|
self.opt = TargetOptimizer(mint=self)
|
|
63
67
|
self.pca = PrincipalComponentsAnalyser(self)
|
|
64
68
|
self.tqdm = tqdm
|
|
65
|
-
|
|
69
|
+
|
|
70
|
+
# Setup working directory as pathlib.Path
|
|
71
|
+
self.wdir = os.getcwd() if wdir is None else wdir
|
|
72
|
+
self.wdir = P(self.wdir)
|
|
66
73
|
|
|
67
74
|
@property
|
|
68
75
|
def version(self):
|
|
@@ -90,6 +97,7 @@ class Mint(object):
|
|
|
90
97
|
self.runtime = None
|
|
91
98
|
self._status = "waiting"
|
|
92
99
|
self._messages = []
|
|
100
|
+
self.meta = init_metadata()
|
|
93
101
|
return self
|
|
94
102
|
|
|
95
103
|
def clear_targets(self):
|
|
@@ -200,7 +208,6 @@ class Mint(object):
|
|
|
200
208
|
def _run_parallel(
|
|
201
209
|
self, nthreads=1, mode="standard", maxtasksperchild=None, fn=None
|
|
202
210
|
):
|
|
203
|
-
print(f"maxtasksperchild: {maxtasksperchild}")
|
|
204
211
|
pool = Pool(processes=nthreads, maxtasksperchild=maxtasksperchild)
|
|
205
212
|
m = Manager()
|
|
206
213
|
q = m.Queue()
|
|
@@ -274,6 +281,7 @@ class Mint(object):
|
|
|
274
281
|
self._files = list_of_files
|
|
275
282
|
if self.verbose:
|
|
276
283
|
print("Set files to:\n" + "\n".join(self.ms_files) + "\n")
|
|
284
|
+
self.meta = self.meta.reindex([fn_to_label(fn) for fn in list_of_files])
|
|
277
285
|
|
|
278
286
|
@property
|
|
279
287
|
def n_files(self):
|
|
@@ -373,7 +381,7 @@ class Mint(object):
|
|
|
373
381
|
def results(self, df):
|
|
374
382
|
self._results = df
|
|
375
383
|
|
|
376
|
-
def crosstab(self,
|
|
384
|
+
def crosstab(self, values: str = "peak_max", index: str = None, column: str = None, aggfunc: str = 'mean', apply: Callable = None, scaler: Callable = None):
|
|
377
385
|
"""
|
|
378
386
|
Create condensed representation of the results.
|
|
379
387
|
More specifically, a cross-table with filenames as index and target labels.
|
|
@@ -384,12 +392,23 @@ class Mint(object):
|
|
|
384
392
|
|
|
385
393
|
cells of the returned table.
|
|
386
394
|
"""
|
|
395
|
+
|
|
396
|
+
df_meta = pd.merge(self.meta, self.results, left_index=True, right_on='ms_file_label')
|
|
397
|
+
|
|
398
|
+
if index is None:
|
|
399
|
+
index = 'ms_file_label'
|
|
400
|
+
if column is None:
|
|
401
|
+
column = 'peak_label'
|
|
402
|
+
if values is None:
|
|
403
|
+
values = 'peak_area_top3'
|
|
404
|
+
|
|
387
405
|
df = pd.crosstab(
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
aggfunc=
|
|
406
|
+
df_meta[index],
|
|
407
|
+
df_meta[column],
|
|
408
|
+
df_meta[values],
|
|
409
|
+
aggfunc=aggfunc,
|
|
392
410
|
).astype(np.float64)
|
|
411
|
+
|
|
393
412
|
if apply:
|
|
394
413
|
df = df.apply(apply)
|
|
395
414
|
if scaler:
|
|
@@ -462,6 +481,11 @@ class Mint(object):
|
|
|
462
481
|
results = pd.read_parquet(fn)
|
|
463
482
|
else:
|
|
464
483
|
results = pd.read_csv(fn)
|
|
484
|
+
|
|
485
|
+
# Add file labels if not present already
|
|
486
|
+
if 'ms_file_label' not in results.columns:
|
|
487
|
+
results['ms_file_label'] = [fn_to_label(fn) for fn in results.ms_file]
|
|
488
|
+
|
|
465
489
|
self.results = results.rename(columns=DEPRECATED_LABELS)
|
|
466
490
|
self.digest_results()
|
|
467
491
|
return self
|
|
@@ -470,35 +494,47 @@ class Mint(object):
|
|
|
470
494
|
self.ms_files = get_ms_files_from_results(self.results)
|
|
471
495
|
self.targets = get_targets_from_results(self.results)
|
|
472
496
|
|
|
473
|
-
|
|
474
|
-
def get_chromatograms(self, fns=None,
|
|
497
|
+
|
|
498
|
+
def get_chromatograms(self, fns=None, peak_labels=None, filters=None, **kwargs):
|
|
475
499
|
if fns is None:
|
|
476
500
|
fns = self.ms_files
|
|
501
|
+
if peak_labels is None:
|
|
502
|
+
peak_labels = self.peak_labels
|
|
503
|
+
return self._get_chromatograms(fns=tuple(fns), peak_labels=tuple(peak_labels),
|
|
504
|
+
filters=tuple(filters) if filters is not None else None, **kwargs)
|
|
505
|
+
|
|
506
|
+
@lru_cache(1)
|
|
507
|
+
def _get_chromatograms(self, fns=None, peak_labels=None, filters=None, **kwargs):
|
|
477
508
|
|
|
478
509
|
if isinstance(fns, tuple):
|
|
479
|
-
fns = list(fns)
|
|
510
|
+
fns = list(fns)
|
|
480
511
|
|
|
481
512
|
if not isinstance(fns, list):
|
|
482
513
|
fns = [fns]
|
|
483
514
|
|
|
484
|
-
|
|
485
|
-
|
|
515
|
+
labels = [fn_to_label(fn) for fn in fns]
|
|
516
|
+
|
|
517
|
+
# Need to get the actual file names with get_chromatogramsath
|
|
518
|
+
# in case only ms_file_labels are provided
|
|
519
|
+
fns = [fn for fn in self.ms_files if fn_to_label(fn) in labels]
|
|
486
520
|
|
|
487
521
|
data = []
|
|
488
522
|
|
|
489
|
-
for fn in self.tqdm(fns):
|
|
523
|
+
for fn in self.tqdm(fns, desc="Loading chromatograms"):
|
|
490
524
|
df = ms_file_to_df(fn)
|
|
491
|
-
for label in
|
|
525
|
+
for label in peak_labels:
|
|
492
526
|
mz_mean, mz_width, rt_min, rt_max = self.get_target_params(label)
|
|
493
527
|
chrom_raw = extract_chromatogram_from_ms1(
|
|
494
528
|
df, mz_mean=mz_mean, mz_width=mz_width
|
|
495
529
|
).to_frame()
|
|
496
530
|
if len(chrom_raw) == 0:
|
|
497
531
|
continue
|
|
498
|
-
chrom = Chromatogram(chrom_raw.index, chrom_raw.values)
|
|
499
|
-
|
|
532
|
+
chrom = Chromatogram(chrom_raw.index, chrom_raw.values, filters=filters, **kwargs)
|
|
533
|
+
if filters is not None:
|
|
534
|
+
chrom.apply_filters()
|
|
500
535
|
chrom_data = chrom.data
|
|
501
536
|
chrom_data["ms_file"] = fn
|
|
537
|
+
chrom_data["ms_file_label"] = fn_to_label(fn)
|
|
502
538
|
chrom_data["peak_label"] = label
|
|
503
539
|
chrom_data["rt_min"] = rt_min
|
|
504
540
|
chrom_data["rt_max"] = rt_max
|
|
@@ -508,3 +544,23 @@ class Mint(object):
|
|
|
508
544
|
|
|
509
545
|
data["ms_file"] = data["ms_file"].apply(lambda x: P(x).with_suffix("").name)
|
|
510
546
|
return data
|
|
547
|
+
|
|
548
|
+
def load_metadata(self, fn=None):
|
|
549
|
+
if fn is None:
|
|
550
|
+
fn = self.wdir/METADATA_DEFAUT_FN
|
|
551
|
+
if str(fn).endswith('.csv'):
|
|
552
|
+
self.meta = pd.read_csv(fn, index_col=0)
|
|
553
|
+
elif str(fn).endswith('.parquet'):
|
|
554
|
+
self.meta = pd.read_parquet(fn)
|
|
555
|
+
if 'ms_file_label' in self.meta.columns:
|
|
556
|
+
self.meta = self.meta.set_index('ms_file_label')
|
|
557
|
+
return self
|
|
558
|
+
|
|
559
|
+
def save_metadata(self, fn=None):
|
|
560
|
+
if fn is None:
|
|
561
|
+
fn = self.wdir/METADATA_DEFAUT_FN
|
|
562
|
+
if str(fn).endswith('.csv'):
|
|
563
|
+
self.meta.to_csv(fn, na_filter=False)
|
|
564
|
+
elif str(fn).endswith('.parquet'):
|
|
565
|
+
self.meta.to_parquet(fn)
|
|
566
|
+
return self
|
|
@@ -147,6 +147,7 @@ class MintPlotter:
|
|
|
147
147
|
else:
|
|
148
148
|
self.mint.clustered = data.iloc[ndx_y, ndx_x]
|
|
149
149
|
return fig
|
|
150
|
+
|
|
150
151
|
|
|
151
152
|
def peak_shapes(self, fns=None, peak_labels=None, interactive=False, **kwargs):
|
|
152
153
|
"""Plot peak shapes.
|
|
@@ -263,7 +264,7 @@ class MintPlotter:
|
|
|
263
264
|
plt.title(f'{P(fn).with_suffix("").name}\n{peak_label}')
|
|
264
265
|
return fig
|
|
265
266
|
|
|
266
|
-
def chromatogram(self, fns=None, peak_labels=None, interactive=False, **kwargs):
|
|
267
|
+
def chromatogram(self, fns=None, peak_labels=None, interactive=False, filters=None, **kwargs):
|
|
267
268
|
"""Plot the chromatogram extracted from one or more files.
|
|
268
269
|
|
|
269
270
|
:param fns: File names to extract chromatogram from.
|
|
@@ -294,7 +295,7 @@ class MintPlotter:
|
|
|
294
295
|
if peak_labels is not None:
|
|
295
296
|
peak_labels = tuple(peak_labels)
|
|
296
297
|
|
|
297
|
-
data = self.mint.get_chromatograms(fns=fns, peak_labels=peak_labels)
|
|
298
|
+
data = self.mint.get_chromatograms(fns=fns, peak_labels=peak_labels, filters=filters)
|
|
298
299
|
|
|
299
300
|
if not interactive:
|
|
300
301
|
params = dict(
|
|
@@ -305,7 +306,7 @@ class MintPlotter:
|
|
|
305
306
|
col_order=peak_labels,
|
|
306
307
|
height=1.5,
|
|
307
308
|
aspect=5,
|
|
308
|
-
hue="
|
|
309
|
+
hue="ms_file_label",
|
|
309
310
|
facet_kws=dict(sharey=False),
|
|
310
311
|
marker=".",
|
|
311
312
|
linewidth=0,
|
|
@@ -331,7 +332,7 @@ class MintPlotter:
|
|
|
331
332
|
x="scan_time",
|
|
332
333
|
y="intensity",
|
|
333
334
|
facet_col="peak_label",
|
|
334
|
-
color="
|
|
335
|
+
color="ms_file_label",
|
|
335
336
|
height=700,
|
|
336
337
|
facet_col_wrap=1,
|
|
337
338
|
)
|