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.
Files changed (30) hide show
  1. {ms-mint-0.2.4/ms_mint.egg-info → ms-mint-0.3.0}/PKG-INFO +17 -10
  2. {ms-mint-0.2.4 → ms-mint-0.3.0}/README.md +16 -9
  3. ms-mint-0.2.4/ms_mint/chromatogram.py → ms-mint-0.3.0/ms_mint/Chromatogram.py +34 -28
  4. {ms-mint-0.2.4 → ms-mint-0.3.0}/ms_mint/Mint.py +80 -24
  5. ms-mint-0.2.4/ms_mint/plotting.py → ms-mint-0.3.0/ms_mint/MintPlotter.py +5 -4
  6. ms-mint-0.3.0/ms_mint/TargetOptimizer.py +158 -0
  7. {ms-mint-0.2.4 → ms-mint-0.3.0}/ms_mint/_version.py +3 -3
  8. {ms-mint-0.2.4 → ms-mint-0.3.0}/ms_mint/filters.py +10 -3
  9. {ms-mint-0.2.4 → ms-mint-0.3.0}/ms_mint/io.py +2 -7
  10. {ms-mint-0.2.4 → ms-mint-0.3.0}/ms_mint/matplotlib_tools.py +1 -1
  11. {ms-mint-0.2.4 → ms-mint-0.3.0}/ms_mint/pca.py +85 -23
  12. {ms-mint-0.2.4 → ms-mint-0.3.0}/ms_mint/plotly_tools.py +9 -5
  13. {ms-mint-0.2.4 → ms-mint-0.3.0}/ms_mint/processing.py +34 -3
  14. {ms-mint-0.2.4 → ms-mint-0.3.0}/ms_mint/standards.py +3 -2
  15. {ms-mint-0.2.4 → ms-mint-0.3.0}/ms_mint/targets.py +6 -144
  16. {ms-mint-0.2.4 → ms-mint-0.3.0}/ms_mint/tools.py +26 -4
  17. {ms-mint-0.2.4 → ms-mint-0.3.0/ms_mint.egg-info}/PKG-INFO +17 -10
  18. {ms-mint-0.2.4 → ms-mint-0.3.0}/ms_mint.egg-info/SOURCES.txt +3 -2
  19. {ms-mint-0.2.4 → ms-mint-0.3.0}/LICENSE +0 -0
  20. {ms-mint-0.2.4 → ms-mint-0.3.0}/MANIFEST.in +0 -0
  21. {ms-mint-0.2.4 → ms-mint-0.3.0}/ms_mint/__init__.py +0 -0
  22. {ms-mint-0.2.4 → ms-mint-0.3.0}/ms_mint/filelock.py +0 -0
  23. {ms-mint-0.2.4 → ms-mint-0.3.0}/ms_mint/notebook.py +0 -0
  24. {ms-mint-0.2.4 → ms-mint-0.3.0}/ms_mint.egg-info/dependency_links.txt +0 -0
  25. {ms-mint-0.2.4 → ms-mint-0.3.0}/ms_mint.egg-info/requires.txt +0 -0
  26. {ms-mint-0.2.4 → ms-mint-0.3.0}/ms_mint.egg-info/top_level.txt +0 -0
  27. {ms-mint-0.2.4 → ms-mint-0.3.0}/scripts/ms-mint-convert.py +0 -0
  28. {ms-mint-0.2.4 → ms-mint-0.3.0}/setup.cfg +0 -0
  29. {ms-mint-0.2.4 → ms-mint-0.3.0}/setup.py +0 -0
  30. {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.2.4
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
  ![](https://github.com/LewisResearchGroup/ms-mint/blob/develop/images/coverage.svg)
17
17
  [![CodeQL](https://github.com/lewisresearchgroup/ms-mint/actions/workflows/codeql-analysis.yml/badge.svg)](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
- ![](notebooks/peak-shapes-before-opt.png)
139
+ ![](https://raw.githubusercontent.com/LewisResearchGroup/ms-mint/develop/notebooks/peak-shapes-before-opt.png)
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
- ![](notebooks/optimize-rt_min_max.png)
156
+ ![](https://raw.githubusercontent.com/LewisResearchGroup/ms-mint/develop/notebooks/optimize-rt_min_max.png)
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
- ![](notebooks/peak-shapes-after-opt.png)
165
+ ![](https://raw.githubusercontent.com/LewisResearchGroup/ms-mint/develop/notebooks/peak-shapes-after-opt.png)
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
- ![](notebooks/peak-shapes-after-opt.png)
175
+ ![](https://raw.githubusercontent.com/LewisResearchGroup/ms-mint/develop/notebooks/peak-shapes-after-opt.png)
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
- ![](notebooks/hierarchical_clustering.png)
210
+ ![](https://raw.githubusercontent.com/LewisResearchGroup/ms-mint/develop/notebooks/hierarchical_clustering.png)
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
- ![](notebooks/pca-pairplot.png)
224
+ ![](https://raw.githubusercontent.com/LewisResearchGroup/ms-mint/develop/notebooks/pca-pairplot.png)
218
225
 
219
226
  ## FAQ
220
227
  ### What is a target list
@@ -2,19 +2,28 @@
2
2
  ![](https://github.com/LewisResearchGroup/ms-mint/blob/develop/images/coverage.svg)
3
3
  [![CodeQL](https://github.com/lewisresearchgroup/ms-mint/actions/workflows/codeql-analysis.yml/badge.svg)](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
- ![](notebooks/peak-shapes-before-opt.png)
125
+ ![](https://raw.githubusercontent.com/LewisResearchGroup/ms-mint/develop/notebooks/peak-shapes-before-opt.png)
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
- ![](notebooks/optimize-rt_min_max.png)
142
+ ![](https://raw.githubusercontent.com/LewisResearchGroup/ms-mint/develop/notebooks/optimize-rt_min_max.png)
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
- ![](notebooks/peak-shapes-after-opt.png)
151
+ ![](https://raw.githubusercontent.com/LewisResearchGroup/ms-mint/develop/notebooks/peak-shapes-after-opt.png)
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
- ![](notebooks/peak-shapes-after-opt.png)
161
+ ![](https://raw.githubusercontent.com/LewisResearchGroup/ms-mint/develop/notebooks/peak-shapes-after-opt.png)
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
- ![](notebooks/hierarchical_clustering.png)
196
+ ![](https://raw.githubusercontent.com/LewisResearchGroup/ms-mint/develop/notebooks/hierarchical_clustering.png)
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
- ![](notebooks/pca-pairplot.png)
210
+ ![](https://raw.githubusercontent.com/LewisResearchGroup/ms-mint/develop/notebooks/pca-pairplot.png)
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, scan_times=None, intensities=None, filters=None, expected_rt=None
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
- self.t = np.array([0])
18
- self.x = np.array([0])
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
- self.noise_level = None
24
- if filters is None:
25
- self.filters = [Resampler(), GaussFilter(), Smoother()]
26
- else:
27
- self.filters = filters
28
- self.peaks = None
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 * 3
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 .targets import read_targets, check_targets, standardize_targets, TargetOptimizer
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 .plotting import MintPlotter
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
- self.meta = None
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, col_name="peak_max", apply=None, scaler=None):
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
- self.results.ms_file,
389
- self.results.peak_label,
390
- self.results[col_name],
391
- aggfunc=sum,
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
- @lru_cache(1)
474
- def get_chromatograms(self, fns=None, peak_label=None, **kwargs):
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
- if peak_label is None:
485
- peak_label = self.peak_labels
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 peak_label:
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
- chrom.apply_filter()
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="ms_file",
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="ms_file",
335
+ color="ms_file_label",
335
336
  height=700,
336
337
  facet_col_wrap=1,
337
338
  )