ms-mint 0.2.2__tar.gz → 0.2.4__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 (29) hide show
  1. {ms-mint-0.2.2/ms_mint.egg-info → ms-mint-0.2.4}/PKG-INFO +11 -16
  2. {ms-mint-0.2.2 → ms-mint-0.2.4}/README.md +10 -15
  3. {ms-mint-0.2.2 → ms-mint-0.2.4}/ms_mint/Mint.py +62 -78
  4. {ms-mint-0.2.2 → ms-mint-0.2.4}/ms_mint/_version.py +3 -3
  5. {ms-mint-0.2.2 → ms-mint-0.2.4}/ms_mint/chromatogram.py +8 -9
  6. {ms-mint-0.2.2 → ms-mint-0.2.4}/ms_mint/filelock.py +1 -10
  7. ms-mint-0.2.2/ms_mint/filter.py → ms-mint-0.2.4/ms_mint/filters.py +3 -1
  8. {ms-mint-0.2.2 → ms-mint-0.2.4}/ms_mint/io.py +117 -137
  9. {ms-mint-0.2.2 → ms-mint-0.2.4}/ms_mint/matplotlib_tools.py +3 -4
  10. {ms-mint-0.2.2 → ms-mint-0.2.4}/ms_mint/notebook.py +2 -3
  11. {ms-mint-0.2.2 → ms-mint-0.2.4}/ms_mint/pca.py +1 -1
  12. {ms-mint-0.2.2 → ms-mint-0.2.4}/ms_mint/plotly_tools.py +2 -3
  13. {ms-mint-0.2.2 → ms-mint-0.2.4}/ms_mint/plotting.py +4 -4
  14. {ms-mint-0.2.2 → ms-mint-0.2.4}/ms_mint/processing.py +3 -5
  15. {ms-mint-0.2.2 → ms-mint-0.2.4}/ms_mint/targets.py +8 -24
  16. {ms-mint-0.2.2 → ms-mint-0.2.4/ms_mint.egg-info}/PKG-INFO +11 -16
  17. {ms-mint-0.2.2 → ms-mint-0.2.4}/ms_mint.egg-info/SOURCES.txt +3 -2
  18. {ms-mint-0.2.2 → ms-mint-0.2.4}/ms_mint.egg-info/requires.txt +2 -0
  19. ms-mint-0.2.4/scripts/ms-mint-convert.py +43 -0
  20. {ms-mint-0.2.2 → ms-mint-0.2.4}/setup.cfg +2 -0
  21. {ms-mint-0.2.2 → ms-mint-0.2.4}/setup.py +7 -0
  22. {ms-mint-0.2.2 → ms-mint-0.2.4}/LICENSE +0 -0
  23. {ms-mint-0.2.2 → ms-mint-0.2.4}/MANIFEST.in +0 -0
  24. {ms-mint-0.2.2 → ms-mint-0.2.4}/ms_mint/__init__.py +0 -0
  25. {ms-mint-0.2.2 → ms-mint-0.2.4}/ms_mint/standards.py +0 -0
  26. {ms-mint-0.2.2 → ms-mint-0.2.4}/ms_mint/tools.py +0 -0
  27. {ms-mint-0.2.2 → ms-mint-0.2.4}/ms_mint.egg-info/dependency_links.txt +0 -0
  28. {ms-mint-0.2.2 → ms-mint-0.2.4}/ms_mint.egg-info/top_level.txt +0 -0
  29. {ms-mint-0.2.2 → ms-mint-0.2.4}/versioneer.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: ms-mint
3
- Version: 0.2.2
3
+ Version: 0.2.4
4
4
  Summary: Metabolomics Integrator (Mint)
5
5
  Home-page: https://github.com/LewisResearchGroup/ms-mint
6
6
  Author: Soren Wacker
@@ -26,7 +26,7 @@ The `ms-mint` library includes a range of functions for processing LCMS data fro
26
26
  ## Documentation
27
27
  The code documentation can be accessed [here](https://lewisresearchgroup.github.io/ms-mint/readme.html).
28
28
 
29
- ## News
29
+ ## ms-mint application with graphical user iterface (GUI)
30
30
  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
31
 
32
32
  ## Contributions
@@ -38,7 +38,7 @@ The project follows PEP8 standard and uses Black and Flake8 to ensure a consiste
38
38
 
39
39
  ---
40
40
 
41
- # Usage
41
+ ## Usage
42
42
 
43
43
  To use the main class of the ms-mint library, you can import it into your code with the following command:
44
44
 
@@ -159,7 +159,6 @@ Then we apply the changes and plot the new peak shapes:
159
159
 
160
160
  As you can see, the shapes of Xanthine, Succinate, Citrulline look much better.
161
161
 
162
-
163
162
  ## Plotting and data exploration
164
163
 
165
164
  The `Mint` class has a few convenient methods to visualize and explore the processed data. The results can be viewed directly in JupyterLab or stored to files using `matplotlib` and `seaborn` syntax. The figures are matplotlib objects and can be easily customised.
@@ -172,7 +171,6 @@ The `Mint` class has a few convenient methods to visualize and explore the proce
172
171
 
173
172
  The method uses seaborn [sns.relplot()](https://seaborn.pydata.org/generated/seaborn.relplot.html) function and keyword arguments are passed on.
174
173
 
175
-
176
174
  ## Hierarchical clustering
177
175
  Mint ca be used to cluster the extracted data. An agglomerative hierarchical clustering is a bottom-up clustering technique where each data point starts as its own cluster and then are merged with other clusters in a hierarchical manner based on their proximity or similarity until a single cluster is formed or a specified stopping criteria is met. The proximity is usually determined by a distance metric, such as Euclidean distance, and the similarity is usually determined by a linkage function, such as ward linkage or complete linkage. The result is a tree-like representation called a dendrogram, which can be used to determine the number of clusters and the cluster assignments of the data points.
178
176
 
@@ -202,7 +200,6 @@ Before clustering the data can be transformed and scaled. By default `log2p1(x)
202
200
  cmap=None # Name of a matplotlib color map
203
201
  )
204
202
 
205
-
206
203
  ![](notebooks/hierarchical_clustering.png)
207
204
 
208
205
  ## Principal Components Analysis
@@ -219,8 +216,8 @@ After running the PCA the results can be plotted with:
219
216
 
220
217
  ![](notebooks/pca-pairplot.png)
221
218
 
222
- # FAQ
223
- ## What is a target list
219
+ ## FAQ
220
+ ### What is a target list
224
221
  A target list is a pandas dataframe with specific columns.
225
222
 
226
223
  - **peak_label**: string, Label of the peak (must be unique).
@@ -235,11 +232,11 @@ A target list is a pandas dataframe with specific columns.
235
232
 
236
233
  The target list can be stored as csv or Excel file.
237
234
 
238
- ## What input files can be used
235
+ ### What input files can be used
239
236
  `ms_mint` can be used with `mzXML`, `mzML`, `mzMLb` and experimental formats in `.feather` and `.parquet` format.
240
237
 
241
- ## Which properties does ms-mint extract
242
- ### Parameters from target list
238
+ ### Which properties does ms-mint extract
239
+ #### Parameters from target list
243
240
  - **ms_file**: Filename of MS-file
244
241
  - **peak_label**: From target list
245
242
  - **mz_mean**: From target list
@@ -253,7 +250,7 @@ The target list can be stored as csv or Excel file.
253
250
 
254
251
  ---
255
252
 
256
- ### Results columns
253
+ #### Results columns
257
254
  - **peak_area**: The sum of all intensities in the extraction window
258
255
  - **peak_area_top3**: The average of the 3 largest intensities in the extraction window
259
256
  - **peak_n_datapoints**: Number of datapoints
@@ -274,9 +271,7 @@ The target list can be stored as csv or Excel file.
274
271
  - **ms_file_size**: Size of the MS-file in MB
275
272
  ---
276
273
 
274
+ ## Release Notes
277
275
 
278
- # Release Notes
279
-
280
- ## 0.2.0 Milestones
276
+ ### 0.2.0 Milestones
281
277
  - peak_area_top3 comparable to El-Maven PeakAreaTop values
282
-
@@ -12,7 +12,7 @@ The `ms-mint` library includes a range of functions for processing LCMS data fro
12
12
  ## Documentation
13
13
  The code documentation can be accessed [here](https://lewisresearchgroup.github.io/ms-mint/readme.html).
14
14
 
15
- ## News
15
+ ## ms-mint application with graphical user iterface (GUI)
16
16
  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
17
 
18
18
  ## Contributions
@@ -24,7 +24,7 @@ The project follows PEP8 standard and uses Black and Flake8 to ensure a consiste
24
24
 
25
25
  ---
26
26
 
27
- # Usage
27
+ ## Usage
28
28
 
29
29
  To use the main class of the ms-mint library, you can import it into your code with the following command:
30
30
 
@@ -145,7 +145,6 @@ Then we apply the changes and plot the new peak shapes:
145
145
 
146
146
  As you can see, the shapes of Xanthine, Succinate, Citrulline look much better.
147
147
 
148
-
149
148
  ## Plotting and data exploration
150
149
 
151
150
  The `Mint` class has a few convenient methods to visualize and explore the processed data. The results can be viewed directly in JupyterLab or stored to files using `matplotlib` and `seaborn` syntax. The figures are matplotlib objects and can be easily customised.
@@ -158,7 +157,6 @@ The `Mint` class has a few convenient methods to visualize and explore the proce
158
157
 
159
158
  The method uses seaborn [sns.relplot()](https://seaborn.pydata.org/generated/seaborn.relplot.html) function and keyword arguments are passed on.
160
159
 
161
-
162
160
  ## Hierarchical clustering
163
161
  Mint ca be used to cluster the extracted data. An agglomerative hierarchical clustering is a bottom-up clustering technique where each data point starts as its own cluster and then are merged with other clusters in a hierarchical manner based on their proximity or similarity until a single cluster is formed or a specified stopping criteria is met. The proximity is usually determined by a distance metric, such as Euclidean distance, and the similarity is usually determined by a linkage function, such as ward linkage or complete linkage. The result is a tree-like representation called a dendrogram, which can be used to determine the number of clusters and the cluster assignments of the data points.
164
162
 
@@ -188,7 +186,6 @@ Before clustering the data can be transformed and scaled. By default `log2p1(x)
188
186
  cmap=None # Name of a matplotlib color map
189
187
  )
190
188
 
191
-
192
189
  ![](notebooks/hierarchical_clustering.png)
193
190
 
194
191
  ## Principal Components Analysis
@@ -205,8 +202,8 @@ After running the PCA the results can be plotted with:
205
202
 
206
203
  ![](notebooks/pca-pairplot.png)
207
204
 
208
- # FAQ
209
- ## What is a target list
205
+ ## FAQ
206
+ ### What is a target list
210
207
  A target list is a pandas dataframe with specific columns.
211
208
 
212
209
  - **peak_label**: string, Label of the peak (must be unique).
@@ -221,11 +218,11 @@ A target list is a pandas dataframe with specific columns.
221
218
 
222
219
  The target list can be stored as csv or Excel file.
223
220
 
224
- ## What input files can be used
221
+ ### What input files can be used
225
222
  `ms_mint` can be used with `mzXML`, `mzML`, `mzMLb` and experimental formats in `.feather` and `.parquet` format.
226
223
 
227
- ## Which properties does ms-mint extract
228
- ### Parameters from target list
224
+ ### Which properties does ms-mint extract
225
+ #### Parameters from target list
229
226
  - **ms_file**: Filename of MS-file
230
227
  - **peak_label**: From target list
231
228
  - **mz_mean**: From target list
@@ -239,7 +236,7 @@ The target list can be stored as csv or Excel file.
239
236
 
240
237
  ---
241
238
 
242
- ### Results columns
239
+ #### Results columns
243
240
  - **peak_area**: The sum of all intensities in the extraction window
244
241
  - **peak_area_top3**: The average of the 3 largest intensities in the extraction window
245
242
  - **peak_n_datapoints**: Number of datapoints
@@ -260,9 +257,7 @@ The target list can be stored as csv or Excel file.
260
257
  - **ms_file_size**: Size of the MS-file in MB
261
258
  ---
262
259
 
260
+ ## Release Notes
263
261
 
264
- # Release Notes
265
-
266
- ## 0.2.0 Milestones
262
+ ### 0.2.0 Milestones
267
263
  - peak_area_top3 comparable to El-Maven PeakAreaTop values
268
-
@@ -22,7 +22,8 @@ from .tools import (
22
22
  )
23
23
  from .pca import PrincipalComponentsAnalyser
24
24
  from .plotting import MintPlotter
25
- #from .filter import Resampler
25
+
26
+ # from .filter import Resampler
26
27
  from .chromatogram import Chromatogram, extract_chromatogram_from_ms1
27
28
 
28
29
  import ms_mint
@@ -45,11 +46,15 @@ class Mint(object):
45
46
 
46
47
  """
47
48
 
48
- def __init__(self, verbose: bool = False, progress_callback=None, time_unit="s"):
49
-
50
- self._verbose = verbose
49
+ def __init__(
50
+ self,
51
+ verbose: bool = False,
52
+ progress_callback: Callable = None,
53
+ time_unit: str = "s",
54
+ ):
55
+ self.verbose = verbose
51
56
  self._version = ms_mint.__version__
52
- self._progress_callback = progress_callback
57
+ self.progress_callback = progress_callback
53
58
  self.reset()
54
59
  if self.verbose:
55
60
  print("Mint Version:", self.version, "\n")
@@ -59,24 +64,6 @@ class Mint(object):
59
64
  self.tqdm = tqdm
60
65
  self.meta = None
61
66
 
62
- @property
63
- def verbose(self):
64
- """
65
- Get/set verbosity.
66
-
67
- :getter: Get current verbosity.
68
- :return: True or False
69
- :rtype: bool
70
- :setter: Sets verbosity.
71
- :param value: True or False
72
- :type value: bool
73
- """
74
- return self._verbose
75
-
76
- @verbose.setter
77
- def verbose(self, value: bool):
78
- self._verbose = value
79
-
80
67
  @property
81
68
  def version(self):
82
69
  """
@@ -133,11 +120,11 @@ class Mint(object):
133
120
  * 1: Run without multiprocessing on one CPU
134
121
  * >1: Run with multiprocessing enabled using nthreads threads.
135
122
  :param mode: Compute mode ('standard' or 'express'), defaults to 'standard'
123
+ :type mode: str
136
124
  * 'standard': calculates peak shaped projected to RT dimension
137
125
  * 'express': omits calculation of other features, only peak_areas
138
126
  :param fn: Output filename to not keep results in memory.
139
127
  :type fn: str
140
- :type mode: str
141
128
  :param kwargs: Arguments passed to the procesing function.
142
129
  """
143
130
  self._status = "running"
@@ -146,39 +133,57 @@ class Mint(object):
146
133
  return None
147
134
 
148
135
  targets = self.targets.reset_index()
136
+ self._set_rt_min_max(targets, rt_margin)
149
137
 
150
- if "rt" in targets.columns:
151
- ndx = (targets.rt_min.isna()) & (~targets.rt.isna())
152
- targets.loc[ndx, "rt_min"] = targets.loc[ndx, "rt"] - rt_margin
153
- ndx = (targets.rt_max.isna()) & (~targets.rt.isna())
154
- targets.loc[ndx, "rt_max"] = targets.loc[ndx, "rt"] + rt_margin
155
- del ndx
156
-
157
- if nthreads is None:
158
- nthreads = min(cpu_count(), self.n_files)
138
+ nthreads = self._determine_nthreads(nthreads)
159
139
 
160
140
  if self.verbose:
161
141
  print(f"Run MINT with {nthreads} processes:")
162
142
 
163
143
  start = time.time()
164
144
  if nthreads > 1:
165
- self.__run_parallel__(nthreads=nthreads, mode=mode, fn=fn, **kwargs)
145
+ self._run_parallel(nthreads=nthreads, mode=mode, fn=fn, **kwargs)
166
146
  else:
167
- results = []
168
- for i, filename in enumerate(self.ms_files):
169
- args = {
170
- "filename": filename,
171
- "targets": targets,
172
- "q": None,
173
- "mode": mode,
174
- "output_fn": None,
175
- }
176
- results.append(process_ms1_files_in_parallel(args))
177
- self.progress = int(100 * (i / self.n_files))
178
- self.results = pd.concat(results).reset_index(drop=True)
147
+ self._run_sequential(mode=mode, fn=fn, targets=targets)
179
148
 
180
149
  self.progress = 100
150
+ self._report_runtime(start)
151
+
152
+ self._status = "done"
153
+ assert self.progress == 100
154
+ return self
181
155
 
156
+ def _set_rt_min_max(self, targets, rt_margin):
157
+ if "rt" in targets.columns:
158
+ update_rt_min = (targets.rt_min.isna()) & (~targets.rt.isna())
159
+ targets.loc[update_rt_min, "rt_min"] = (
160
+ targets.loc[update_rt_min, "rt"] - rt_margin
161
+ )
162
+ update_rt_max = (targets.rt_max.isna()) & (~targets.rt.isna())
163
+ targets.loc[update_rt_max, "rt_max"] = (
164
+ targets.loc[update_rt_max, "rt"] + rt_margin
165
+ )
166
+
167
+ def _determine_nthreads(self, nthreads):
168
+ if nthreads is None:
169
+ nthreads = min(cpu_count(), self.n_files)
170
+ return nthreads
171
+
172
+ def _run_sequential(self, mode, fn, targets):
173
+ results = []
174
+ for i, filename in enumerate(self.ms_files):
175
+ args = {
176
+ "filename": filename,
177
+ "targets": targets,
178
+ "q": None,
179
+ "mode": mode,
180
+ "output_fn": None,
181
+ }
182
+ results.append(process_ms1_files_in_parallel(args))
183
+ self.progress = int(100 * (i / self.n_files))
184
+ self.results = pd.concat(results).reset_index(drop=True)
185
+
186
+ def _report_runtime(self, start):
182
187
  end = time.time()
183
188
  self.runtime = end - start
184
189
  self.runtime_per_file = self.runtime / self.n_files
@@ -192,11 +197,7 @@ class Mint(object):
192
197
  )
193
198
  print("Results:", self.results)
194
199
 
195
- self._status = "done"
196
- assert self.progress == 100
197
- return self
198
-
199
- def __run_parallel__(
200
+ def _run_parallel(
200
201
  self, nthreads=1, mode="standard", maxtasksperchild=None, fn=None
201
202
  ):
202
203
  print(f"maxtasksperchild: {maxtasksperchild}")
@@ -221,17 +222,7 @@ class Mint(object):
221
222
  )
222
223
 
223
224
  results = pool.map_async(process_ms1_files_in_parallel, args)
224
-
225
- # monitor progress
226
- while True:
227
- if results.ready():
228
- break
229
- else:
230
- size = q.qsize()
231
- self.progress = 100 * size / self.n_files
232
- time.sleep(1)
233
-
234
- self.progress = 100
225
+ self._monitor_progress(results, q)
235
226
 
236
227
  pool.close()
237
228
  pool.join()
@@ -240,6 +231,13 @@ class Mint(object):
240
231
  results = results.get()
241
232
  self.results = pd.concat(results).reset_index(drop=True)
242
233
 
234
+ def _monitor_progress(self, results, q):
235
+ while not results.ready():
236
+ size = q.qsize()
237
+ self.progress = 100 * size / self.n_files
238
+ time.sleep(1)
239
+ self.progress = 100
240
+
243
241
  @property
244
242
  def status(self):
245
243
  """
@@ -398,20 +396,6 @@ class Mint(object):
398
396
  df = scale_dataframe(df, scaler=scaler)
399
397
  return df
400
398
 
401
- @property
402
- def progress_callback(self):
403
- """
404
- Assigns a callback function to update a progress bar.
405
-
406
- :getter: Returns the current callback function.
407
- :setter: Sets the callback function.
408
- """
409
- return self._progress_callback
410
-
411
- @progress_callback.setter
412
- def progress_callback(self, func: Callable = None):
413
- self._progress_callback = func
414
-
415
399
  @property
416
400
  def progress(self):
417
401
  """
@@ -501,7 +485,7 @@ class Mint(object):
501
485
  peak_label = self.peak_labels
502
486
 
503
487
  data = []
504
-
488
+
505
489
  for fn in self.tqdm(fns):
506
490
  df = ms_file_to_df(fn)
507
491
  for label in peak_label:
@@ -517,7 +501,7 @@ class Mint(object):
517
501
  chrom_data["ms_file"] = fn
518
502
  chrom_data["peak_label"] = label
519
503
  chrom_data["rt_min"] = rt_min
520
- chrom_data["rt_max"] = rt_min
504
+ chrom_data["rt_max"] = rt_max
521
505
  data.append(chrom_data)
522
506
 
523
507
  data = pd.concat(data).reset_index()
@@ -8,11 +8,11 @@ import json
8
8
 
9
9
  version_json = '''
10
10
  {
11
- "date": "2023-03-09T14:53:52-0700",
11
+ "date": "2023-05-09T10:35:26-0600",
12
12
  "dirty": false,
13
13
  "error": null,
14
- "full-revisionid": "7107a0d99427edc8f89ec5853dcef4dddff9c839",
15
- "version": "v0.2.2"
14
+ "full-revisionid": "509e8d0641ce628f2c4e4fdf65a850d805427c99",
15
+ "version": "v0.2.4"
16
16
  }
17
17
  ''' # END VERSION_JSON
18
18
 
@@ -6,13 +6,13 @@ 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 .filter import Resampler, Smoother, GaussFilter
9
+ from .filters import Resampler, Smoother, GaussFilter
10
10
  from .matplotlib_tools import plot_peaks
11
11
 
12
12
 
13
13
  class Chromatogram:
14
14
  def __init__(
15
- self, scan_times=None, intensities=None, filter=None, expected_rt=None
15
+ self, scan_times=None, intensities=None, filters=None, expected_rt=None
16
16
  ):
17
17
  self.t = np.array([0])
18
18
  self.x = np.array([0])
@@ -21,10 +21,10 @@ class Chromatogram:
21
21
  if intensities is not None:
22
22
  self.x = np.append(self.x, intensities)
23
23
  self.noise_level = None
24
- if filter is None:
25
- self.filter = [Resampler(), GaussFilter(), Smoother()]
24
+ if filters is None:
25
+ self.filters = [Resampler(), GaussFilter(), Smoother()]
26
26
  else:
27
- self.filter = filter
27
+ self.filters = filters
28
28
  self.peaks = None
29
29
  self.selected_peak_ndxs = None
30
30
  if expected_rt is None and scan_times is not None:
@@ -43,8 +43,8 @@ class Chromatogram:
43
43
  data = pd.Series(index=self.t, data=self.x)
44
44
  self.noise_level = data.rolling(window, center=True).std().median()
45
45
 
46
- def apply_filter(self):
47
- for filt in self.filter:
46
+ def apply_filters(self):
47
+ for filt in self.filters:
48
48
  self.t, self.x = filt.transform(self.t, self.x)
49
49
 
50
50
  def find_peaks(self, prominence=None, rel_height=0.9):
@@ -80,7 +80,6 @@ class Chromatogram:
80
80
  plt.show()
81
81
 
82
82
  for ndx, row in peaks.iterrows():
83
-
84
83
  new_rt_min = row.rt_min
85
84
  new_rt_max = row.rt_max
86
85
 
@@ -130,7 +129,7 @@ class Chromatogram:
130
129
 
131
130
  @property
132
131
  def selected_peaks(self):
133
- self.peaks.loc[self.selected_peak_ndxs]
132
+ return self.peaks.loc[self.selected_peak_ndxs]
134
133
 
135
134
  @property
136
135
  def data(self):
@@ -50,15 +50,6 @@ try:
50
50
  except ImportError:
51
51
  fcntl = None
52
52
 
53
-
54
- # Backward compatibility
55
- # ------------------------------------------------
56
- try:
57
- TimeoutError
58
- except NameError:
59
- TimeoutError = OSError
60
-
61
-
62
53
  # Data
63
54
  # ------------------------------------------------
64
55
  __all__ = [
@@ -105,6 +96,7 @@ class Timeout(TimeoutError):
105
96
  # Classes
106
97
  # ------------------------------------------------
107
98
 
99
+
108
100
  # This is a helper class which is returned by :meth:`BaseFileLock.acquire`
109
101
  # and wraps the lock to make sure __enter__ is not called twice when entering
110
102
  # the with statement.
@@ -310,7 +302,6 @@ class BaseFileLock(object):
310
302
  every case.
311
303
  """
312
304
  with self._thread_lock:
313
-
314
305
  if self.is_locked:
315
306
  self._lock_counter -= 1
316
307
 
@@ -49,7 +49,7 @@ class Smoother:
49
49
  averages.
50
50
  """
51
51
 
52
- def __init__(self, windows=[30, 20]):
52
+ def __init__(self, windows=None):
53
53
  """
54
54
  Filter for time series that smoothes the
55
55
  x values by running one or more rolling
@@ -58,6 +58,8 @@ class Smoother:
58
58
  :param windows: Window sizes of rolling averages applied to time series, defaults to [30, 20]
59
59
  :type windows: : List[int], optional
60
60
  """
61
+ if windows is None:
62
+ windows = [30, 20]
61
63
  self.windows = windows
62
64
  self.name = "smoother"
63
65