pychemstation 0.8.3__py3-none-any.whl → 0.10.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. pychemstation/analysis/__init__.py +4 -0
  2. pychemstation/analysis/base_spectrum.py +9 -9
  3. pychemstation/analysis/process_report.py +13 -7
  4. pychemstation/analysis/utils.py +1 -3
  5. pychemstation/control/__init__.py +4 -0
  6. pychemstation/control/comm.py +206 -0
  7. pychemstation/control/controllers/__init__.py +6 -0
  8. pychemstation/control/controllers/comm.py +12 -5
  9. pychemstation/control/controllers/devices/column.py +12 -0
  10. pychemstation/control/controllers/devices/dad.py +0 -0
  11. pychemstation/control/controllers/devices/device.py +10 -7
  12. pychemstation/control/controllers/devices/injector.py +18 -84
  13. pychemstation/control/controllers/devices/pump.py +43 -0
  14. pychemstation/control/controllers/method.py +338 -0
  15. pychemstation/control/controllers/sequence.py +190 -0
  16. pychemstation/control/controllers/table_controller.py +266 -0
  17. pychemstation/control/controllers/tables/method.py +35 -13
  18. pychemstation/control/controllers/tables/sequence.py +46 -37
  19. pychemstation/control/controllers/tables/table.py +46 -30
  20. pychemstation/control/hplc.py +27 -11
  21. pychemstation/control/table/__init__.py +3 -0
  22. pychemstation/control/table/method.py +274 -0
  23. pychemstation/control/table/sequence.py +210 -0
  24. pychemstation/control/table/table_controller.py +201 -0
  25. pychemstation/generated/dad_method.py +1 -1
  26. pychemstation/generated/pump_method.py +1 -1
  27. pychemstation/utils/chromatogram.py +2 -5
  28. pychemstation/utils/injector_types.py +1 -1
  29. pychemstation/utils/macro.py +3 -3
  30. pychemstation/utils/method_types.py +2 -2
  31. pychemstation/utils/num_utils.py +65 -0
  32. pychemstation/utils/parsing.py +1 -0
  33. pychemstation/utils/sequence_types.py +3 -3
  34. pychemstation/utils/spec_utils.py +304 -0
  35. {pychemstation-0.8.3.dist-info → pychemstation-0.10.0.dist-info}/METADATA +19 -8
  36. pychemstation-0.10.0.dist-info/RECORD +62 -0
  37. {pychemstation-0.8.3.dist-info → pychemstation-0.10.0.dist-info}/WHEEL +2 -1
  38. pychemstation-0.10.0.dist-info/top_level.txt +2 -0
  39. tests/__init__.py +0 -0
  40. tests/constants.py +134 -0
  41. tests/test_comb.py +136 -0
  42. tests/test_comm.py +65 -0
  43. tests/test_inj.py +39 -0
  44. tests/test_method.py +99 -0
  45. tests/test_nightly.py +80 -0
  46. tests/test_offline_stable.py +69 -0
  47. tests/test_online_stable.py +275 -0
  48. tests/test_proc_rep.py +52 -0
  49. tests/test_runs_stable.py +225 -0
  50. tests/test_sequence.py +125 -0
  51. tests/test_stable.py +276 -0
  52. pychemstation/control/README.md +0 -124
  53. pychemstation/control/controllers/README.md +0 -1
  54. pychemstation-0.8.3.dist-info/RECORD +0 -37
  55. {pychemstation-0.8.3.dist-info → pychemstation-0.10.0.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,304 @@
1
+ """
2
+ Module contains various utility function for spectral data processing and
3
+ analysis.
4
+ """
5
+
6
+ import numpy as np
7
+ import scipy
8
+
9
+ from ..utils.num_utils import find_nearest_value_index
10
+
11
+
12
+ def create_binary_peak_map(data):
13
+ """Return binary map of the peaks within data points.
14
+
15
+ True values are assigned to potential peak points, False - to baseline.
16
+
17
+ Args:
18
+ data (:obj:np.array): 1D array with data points.
19
+
20
+ Returns:
21
+ :obj:np.array, dtype=bool: Mapping of data points, where True is
22
+ potential peak region point, False - baseline.
23
+ """
24
+ # copying array
25
+ data_c = np.copy(data)
26
+
27
+ # placeholder for the peak mapping
28
+ peak_map = np.full_like(data_c, False, dtype=bool)
29
+
30
+ for _ in range(100500): # shouldn't take more iterations
31
+
32
+ # looking for peaks
33
+ peaks_found = np.logical_or(
34
+ data_c > np.mean(data_c) + np.std(data_c) * 3,
35
+ data_c < np.mean(data_c) - np.std(data_c) * 3,
36
+ )
37
+
38
+ # merging with peak mapping
39
+ np.logical_or(peak_map, peaks_found, out=peak_map)
40
+
41
+ # if no peaks found - break
42
+ if not peaks_found.any():
43
+ break
44
+
45
+ # setting values to 0 and iterating again
46
+ data_c[peaks_found] = 0
47
+
48
+ return peak_map
49
+
50
+
51
+ def combine_map_to_regions(mapping):
52
+ """Combine True values into their indexes arrays.
53
+
54
+ Args:
55
+ mapping (:obj:np.array): Boolean mapping array to extract the indexes
56
+ from.
57
+
58
+ Returns:
59
+ :obj:np.array: 2D array with left and right borders of regions, where
60
+ mapping is True.
61
+
62
+ Example:
63
+ >>> combine_map_to_regions(np.array([True, True, False, True, False]))
64
+ array([[0, 1],
65
+ [3, 3]])
66
+ """
67
+
68
+ # No peaks identified, i.e. mapping is all False
69
+ if not mapping.any():
70
+ return np.array([], dtype="int64")
71
+
72
+ # region borders
73
+ region_borders = np.diff(mapping)
74
+
75
+ # corresponding indexes
76
+ border_indexes = np.argwhere(region_borders)
77
+
78
+ lefts = border_indexes[::2] + 1 # because diff was used to get the index
79
+
80
+ # edge case, where first peak doesn't have left border
81
+ if mapping[border_indexes][0]:
82
+ # just preppend 0 as first left border
83
+ # mind the vstack, as np.argwhere produces a vector array
84
+ lefts = np.vstack((0, lefts))
85
+
86
+ rights = border_indexes[1::2]
87
+
88
+ # another edge case, where last peak doesn't have a right border
89
+ if mapping[-1]: # True if last point identified as potential peak
90
+ # just append -1 as last peak right border
91
+ rights = np.vstack((rights, -1))
92
+
93
+ # columns as borders, rows as regions, i.e.
94
+ # :output:[0] -> first peak region
95
+ return np.hstack((lefts, rights))
96
+
97
+
98
+ def filter_regions(x_data, peaks_regions):
99
+ """Filter peak regions.
100
+
101
+ Peak regions are filtered to remove potential false positives (e.g. noise
102
+ spikes).
103
+
104
+ Args:
105
+ x_data (:obj:np.array): X data points, needed to pick up the data
106
+ resolution and map the region indexes to the corresponding data
107
+ points.
108
+ y_data (:obj:np.array): Y data points, needed to validate if the peaks
109
+ are actually present in the region and remove invalid regions.
110
+ peaks_regions (:obj:np.array): 2D Nx2 array with peak regions indexes
111
+ (rows) as left and right borders (columns).
112
+
113
+ Returns:
114
+ :obj:np.array: 2D Mx2 array with filtered peak regions indexes(rows) as
115
+ left and right borders (columns).
116
+ """
117
+
118
+ # filter peaks where region is smaller than spectrum resolution
119
+ # like single spikes, e.g. noise
120
+ # compute the regions first
121
+ x_data_regions = np.copy(x_data[peaks_regions])
122
+
123
+ # get arguments where absolute difference is greater than data resolution
124
+ resolution = np.absolute(np.mean(np.diff(x_data)))
125
+
126
+ # (N, 1) array!
127
+ valid_regions_map = np.absolute(np.diff(x_data_regions)) > resolution
128
+
129
+ # get their indexes, mind the flattening of all arrays!
130
+ valid_regions_indexes = np.argwhere(valid_regions_map.flatten()).flatten()
131
+
132
+ # filtering!
133
+ peaks_regions = peaks_regions[valid_regions_indexes]
134
+
135
+ return peaks_regions
136
+
137
+
138
+ def filter_noisy_regions(y_data, peaks_regions):
139
+ """Remove noisy regions from given regions array.
140
+
141
+ Peak regions are filtered to remove false positive noise regions, e.g.
142
+ incorrectly assigned due to curvy baseline. Filtering is performed by
143
+ computing average peak points/data points ratio.
144
+
145
+ Args:
146
+ y_data (:obj:np.array): Y data points, needed to validate if the peaks
147
+ are actually present in the region and remove invalid regions.
148
+ peaks_regions (:obj:np.array): 2D Nx2 array with peak regions indexes
149
+ (rows) as left and right borders (columns).
150
+
151
+ Returns:
152
+ :obj:np.array: 2D Mx2 array with filtered peak regions indexes(rows) as
153
+ left and right borders (columns).
154
+ """
155
+
156
+ # compute the actual regions data points
157
+ y_data_regions = []
158
+ for region in peaks_regions:
159
+ y_data_regions.append(y_data[region[0]: region[-1]])
160
+
161
+ # compute noise data regions, i.e. in between peak regions
162
+ noise_data_regions = []
163
+ for row, _ in enumerate(peaks_regions):
164
+ try:
165
+ noise_data_regions.append(
166
+ y_data[peaks_regions[row][1]: peaks_regions[row + 1][0]]
167
+ )
168
+ except IndexError:
169
+ # exception for the last row -> discard
170
+ pass
171
+
172
+ # compute average peaks/data points ratio for noisy regions
173
+ noise_peaks_ratio = []
174
+ for region in noise_data_regions:
175
+ # protection from empty regions
176
+ if region.size != 0:
177
+ # minimum height is pretty low to ensure enough noise is picked
178
+ peaks, _ = scipy.signal.find_peaks(region, height=region.max() * 0.2)
179
+ noise_peaks_ratio.append(peaks.size / region.size)
180
+
181
+ # compute average with weights equal to the region length
182
+ noise_peaks_ratio = np.average(
183
+ noise_peaks_ratio, weights=[region.size for region in noise_data_regions]
184
+ )
185
+
186
+ # filtering!
187
+ valid_regions_indexes = []
188
+ for row, region in enumerate(y_data_regions):
189
+ peaks, _ = scipy.signal.find_peaks(region, height=region.max() * 0.2)
190
+ if peaks.size != 0 and peaks.size / region.size < noise_peaks_ratio:
191
+ valid_regions_indexes.append(row)
192
+
193
+ # protecting from complete cleaning
194
+ if not valid_regions_indexes:
195
+ return peaks_regions
196
+
197
+ peaks_regions = peaks_regions[np.array(valid_regions_indexes)]
198
+
199
+ return peaks_regions
200
+
201
+
202
+ def merge_regions(x_data, peaks_regions, d_merge, recursively=True):
203
+ """Merge peak regions if distance between is less than delta.
204
+
205
+ Args:
206
+ x_data (:obj:np.array): X data points.
207
+ peaks_regions (:obj:np.array): 2D Nx2 array with peak regions indexes
208
+ (rows) as left and right borders (columns).
209
+ d_merge (float): Minimum distance in X data points to merge two or more
210
+ regions together.
211
+ recursively (bool, optional): If True - will repeat the procedure until
212
+ all regions with distance < than d_merge will merge.
213
+
214
+ Returns:
215
+ :obj:np.array: 2D Mx2 array with peak regions indexes (rows) as left and
216
+ right borders (columns), merged according to predefined minimal
217
+ distance.
218
+
219
+ Example:
220
+ >>> regions = np.array([
221
+ [1, 10],
222
+ [11, 20],
223
+ [25, 45],
224
+ [50, 75],
225
+ [100, 120],
226
+ [122, 134]
227
+ ])
228
+ >>> data = np.ones_like(regions) # ones as example
229
+ >>> merge_regions(data, regions, 1)
230
+ array([[ 1, 20],
231
+ [ 25, 45],
232
+ [ 50, 75],
233
+ [100, 120],
234
+ [122, 134]])
235
+ >>> merge_regions(data, regions, 20, True)
236
+ array([[ 1, 75],
237
+ [100, 134]])
238
+ """
239
+ # the code is pretty ugly but works
240
+ merged_regions = []
241
+
242
+ # converting to list to drop the data of the fly
243
+ regions = peaks_regions.tolist()
244
+
245
+ for i, _ in enumerate(regions):
246
+ try:
247
+ # check left border of i regions with right of i+1
248
+ if abs(x_data[regions[i][-1]] - x_data[regions[i + 1][0]]) <= d_merge:
249
+ # if lower append merge the regions
250
+ merged_regions.append([regions[i][0], regions[i + 1][-1]])
251
+ # drop the merged one
252
+ regions.pop(i + 1)
253
+ else:
254
+ # if nothing to merge, just append the current region
255
+ merged_regions.append(regions[i])
256
+ except IndexError:
257
+ # last row
258
+ merged_regions.append(regions[i])
259
+
260
+ merged_regions = np.array(merged_regions)
261
+
262
+ if not recursively:
263
+ return merged_regions
264
+
265
+ # if recursively, check for the difference
266
+ if (merged_regions == regions).all():
267
+ # done
268
+ return merged_regions
269
+
270
+ return merge_regions(x_data, merged_regions, d_merge, recursively=True)
271
+
272
+
273
+ def expand_regions(x_data, peaks_regions, d_expand):
274
+ """Expand the peak regions by the desired value.
275
+
276
+ Args:
277
+ x_data (:obj:np.array): X data points.
278
+ peaks_regions (:obj:np.array): 2D Nx2 array with peak regions indexes
279
+ (rows) as left and right borders (columns).
280
+ d_expand (float): Value to expand borders to (in X data scale).
281
+
282
+ Returns:
283
+ :obj:np.array: 2D Nx2 array with expanded peak regions indexes (rows) as
284
+ left and right borders (columns).
285
+ """
286
+
287
+ data_regions = np.copy(x_data[peaks_regions])
288
+
289
+ # determine scale orientation, i.e. decreasing (e.g. ppm on NMR spectrum)
290
+ # or increasing (e.g. wavelength on UV spectrum)
291
+ if (data_regions[:, 0] - data_regions[:, 1]).mean() > 0:
292
+ # ppm-like scale
293
+ data_regions[:, 0] += d_expand
294
+ data_regions[:, -1] -= d_expand
295
+ else:
296
+ # wavelength-like scale
297
+ data_regions[:, 0] -= d_expand
298
+ data_regions[:, -1] += d_expand
299
+
300
+ # converting new values to new indexes
301
+ for index_, value in np.ndenumerate(data_regions):
302
+ data_regions[index_] = find_nearest_value_index(x_data, value)[1]
303
+
304
+ return data_regions.astype(int)
@@ -1,10 +1,13 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pychemstation
3
- Version: 0.8.3
4
- Summary: Library to interact with Chemstation software, primarily used in Hein lab.
3
+ Version: 0.10.0
4
+ Summary: Library to interact with Chemstation software, primarily used in Hein lagit branch -mb
5
+ Home-page: https://gitlab.com/heingroup/device-api/pychemstation
6
+ Author: Lucy Hao
5
7
  Author-email: lucyhao <hao.lucyy@gmail.com>
8
+ Requires-Python: >=3.10
9
+ Description-Content-Type: text/markdown
6
10
  License-File: LICENSE
7
- Requires-Python: >=3.8
8
11
  Requires-Dist: aghplctools>=4.8.8
9
12
  Requires-Dist: coverage>=7.6.1
10
13
  Requires-Dist: matplotlib>=3.7.5
@@ -19,7 +22,9 @@ Requires-Dist: seabreeze>=2.9.2
19
22
  Requires-Dist: setuptools>=75.3.2
20
23
  Requires-Dist: twine>=6.1.0
21
24
  Requires-Dist: xsdata>=24.9
22
- Description-Content-Type: text/markdown
25
+ Dynamic: author
26
+ Dynamic: home-page
27
+ Dynamic: license-file
23
28
 
24
29
  # Agilent HPLC Macro Control
25
30
 
@@ -27,8 +32,12 @@ Description-Content-Type: text/markdown
27
32
 
28
33
  [![PyPI Latest Release](https://img.shields.io/pypi/v/pychemstation.svg)](https://pypi.org/project/pychemstation/)
29
34
 
35
+ > **_NOTE:_** If you are running Python **3.8**, use versions 0.**8**.x. If you are running Python **>=3.10**, use
36
+ > version 0.**10**.x. You are welcome to use newer pychemstation versions with older Python versions, but functionality
37
+ > is not guaranteed!
38
+
30
39
  Unofficial Python package to control Agilent Chemstation; we are not affiliated with Agilent.
31
- Check out the [docs](https://hein-analytical-control-5e6e85.gitlab.io/) for usage instructions. This project is under
40
+ Check out the [docs](https://pychemstation-e5a086.gitlab.io/pychemstation.html) for usage instructions. This project is under
32
41
  active development, and breaking changes may occur at any moment.
33
42
 
34
43
  ## Getting started
@@ -110,6 +119,8 @@ Lucy Hao, Maria Politi
110
119
 
111
120
  - Adapted from [**AnalyticalLabware**](https://github.com/croningp/analyticallabware), created by members in the Cronin
112
121
  Group. Copyright © Cronin Group, used under the [CC-BY-4.0](https://creativecommons.org/licenses/by/4.0/) license.
113
- - Adapted from the [MACROS](https://github.com/Bourne-Group/HPLCMethodOptimisationGUI)
114
- used in [**Operator-free HPLC automated method development guided by Bayesian optimization**](https://pubs.rsc.org/en/content/articlelanding/2024/dd/d4dd00062e),
115
- created by members in the Bourne Group. Copyright © Bourne Group, used under the [MIT](https://opensource.org/license/mit) license.
122
+ - Adapted from the [MACROS](https://github.com/Bourne-Group/HPLCMethodOptimisationGUI) used in [**Operator-free HPLC
123
+ automated method development guided by Bayesian optimization
124
+ **](https://pubs.rsc.org/en/content/articlelanding/2024/dd/d4dd00062e),
125
+ created by members in the Bourne Group. Copyright © Bourne Group, used under
126
+ the [MIT](https://opensource.org/license/mit) license.
@@ -0,0 +1,62 @@
1
+ pychemstation/__init__.py,sha256=SpTl-Tg1B1HTyjNOE-8ue-N2wGnXN_2zl7RFUSxlkiM,33
2
+ pychemstation/analysis/__init__.py,sha256=Vi31PZ7fgIvyuIhkgCNvEYeV_jtUCa8FCrAGbpks7zc,83
3
+ pychemstation/analysis/base_spectrum.py,sha256=9WkOLk2qTAYTF1ALNUenVPoosOtBiLRvy2ni8zlGU5w,16540
4
+ pychemstation/analysis/process_report.py,sha256=ZOgcRUMGXdGMrMFcdzsSwdOk6OBp-PpcA83vSvnmVSg,11871
5
+ pychemstation/analysis/spec_utils.py,sha256=UOo9hJR3evJfmaohEEsyb7aq6X996ofuUfu-GKjiDi8,10201
6
+ pychemstation/analysis/utils.py,sha256=ISupAOb_yqA4_DZRK9v18UL-XjUQccAicIJKb1VMnGg,2055
7
+ pychemstation/control/__init__.py,sha256=Js79QczKZxDNZrzG1-4yl_whCoP2aw-yDAQJungiiic,100
8
+ pychemstation/control/comm.py,sha256=u44g1hTluQ0yUG93Un-QAshScoDpgYRrZfFTgweP5tY,7386
9
+ pychemstation/control/hplc.py,sha256=f7NHcCWtc_ApasjU5VMQtEvWQxoIboi_-RU9dkjORrs,13215
10
+ pychemstation/control/controllers/__init__.py,sha256=r7UU0u5zuJHO_KTqt-4Gy65BMlyXtxrdskiOhtO9Yw4,260
11
+ pychemstation/control/controllers/comm.py,sha256=AN3A3ThvIsOKWY7Kmb_tnE5pRUqI7O2ID8M54z_w-uE,7831
12
+ pychemstation/control/controllers/method.py,sha256=XUclB7lQ_SIkquR58MBmmi9drHIPEq9AR8VprTLenvI,15503
13
+ pychemstation/control/controllers/sequence.py,sha256=kYNxxck2I-q9mZDEZwG8bJ_99FfLmunS13EAHOS65wU,8288
14
+ pychemstation/control/controllers/table_controller.py,sha256=70ovnIjLKkJborS1ztk445Mv42TtUM9jUniaQmZuyWQ,11031
15
+ pychemstation/control/controllers/devices/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
+ pychemstation/control/controllers/devices/column.py,sha256=SCpCnVFZFUM9LM51MbWkVcBRayN3WFxy7lz9gs2PYeY,348
17
+ pychemstation/control/controllers/devices/dad.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
18
+ pychemstation/control/controllers/devices/device.py,sha256=JNBKVRka1I3LA1lElIeUO0j93BTK5IJufTPNq95OhNE,1473
19
+ pychemstation/control/controllers/devices/injector.py,sha256=s40jFd0B_wJn4ID6SgAk_F8WhnGbbflpiti4uwIhaSs,1950
20
+ pychemstation/control/controllers/devices/pump.py,sha256=DJQh4lNXEraeC1CWrsKmsITOjuYlRI3tih_XRB3F1hg,1404
21
+ pychemstation/control/controllers/tables/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
22
+ pychemstation/control/controllers/tables/method.py,sha256=LHoNRSTsSrrktghqNnU5KTRXDczcuGgqdqKEs_3sUXI,18609
23
+ pychemstation/control/controllers/tables/ms.py,sha256=JFD-tOhu8uRyKdl-E3-neRssii8MNqVRIlsrnFhNY_M,682
24
+ pychemstation/control/controllers/tables/sequence.py,sha256=DwX0wi5GhHmk8wnl89X2MKvqTSojLycV4IEvNjdVdWg,13400
25
+ pychemstation/control/controllers/tables/table.py,sha256=zMzsQgkLxM3LVe9w-OM8WjLZxTo9zrmBTNH182gAyh8,12750
26
+ pychemstation/control/table/__init__.py,sha256=RgMN4uIWHdNUHpGRBWdzmzAbk7XEKl6Y-qtqWCxzSZU,124
27
+ pychemstation/control/table/method.py,sha256=THVoGomSXff_CTU3eAYme0BYwkPzab5UgZKsiZ29QSk,12196
28
+ pychemstation/control/table/sequence.py,sha256=Eri52AnbE3BGthfrRSvYKYciquUzvHKo0lYUTySYYE8,10542
29
+ pychemstation/control/table/table_controller.py,sha256=HVNYUXqtyFTAvb67fa3RO5RHgmBTFMsYRHKpiXdYcfs,8313
30
+ pychemstation/generated/__init__.py,sha256=GAoZFAYbPVEJDkcOw3e1rgOqd7TCW0HyKNPM8OMehMg,1005
31
+ pychemstation/generated/dad_method.py,sha256=xTUiSCvkXcxBUhjVm1YZKu-tHs16k23pF-0xYrQSwWA,8408
32
+ pychemstation/generated/pump_method.py,sha256=797RsSDI2-QPf_BX8isZQx0O3aRx84EGIXJXhXw3IS0,12180
33
+ pychemstation/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
34
+ pychemstation/utils/chromatogram.py,sha256=2Los_ix_wAi4yxG_9neGRnNYPre9_uC1mrne3Ygit5c,3242
35
+ pychemstation/utils/injector_types.py,sha256=PXwJK1uXs8hlQ6dWIEbAGfk2BpQJQmN3SlUbL4ntZz0,822
36
+ pychemstation/utils/macro.py,sha256=Lh8aGcwo9sC2Sfc19Wgms5d3VgBLV3VXdvspqNHYE18,2931
37
+ pychemstation/utils/method_types.py,sha256=ZOFMJ7wpqWBRJNIvOux-7Ou4nJVSuyWRHrd37wMnPa0,1638
38
+ pychemstation/utils/num_utils.py,sha256=rgpTJTrpsiBANbtsfys9xj0sqlTe__3J0OSeoygaQTM,2081
39
+ pychemstation/utils/parsing.py,sha256=iFdnie-v0u5JI4cctJye_yhWQxHgy72_PWZ7w57Ltvg,9318
40
+ pychemstation/utils/pump_types.py,sha256=HWQHxscGn19NTrfYBwQRCO2VcYfwyko7YfBO5uDhEm4,93
41
+ pychemstation/utils/sequence_types.py,sha256=WyJWL18Q86TgoUpYH2_CevoTZuhcui0EnyHYdrp3Nmo,1070
42
+ pychemstation/utils/spec_utils.py,sha256=MQZPDwCYZRfkEhNJQUt74huPexXBlJ3W4o7_230JWcE,10210
43
+ pychemstation/utils/table_types.py,sha256=7txqW_oNpkh4venSkGEtreVe6UV9dzNB1DTrIeTkQHA,3217
44
+ pychemstation/utils/tray_types.py,sha256=eOO-muUjadyvCM8JnYAZVyxJeyYBlENP1zXiFskAFbs,5049
45
+ pychemstation-0.10.0.dist-info/licenses/LICENSE,sha256=9bdF75gIf1MecZ7oymqWgJREVz7McXPG-mjqrTmzzD8,18658
46
+ tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
47
+ tests/constants.py,sha256=4XZkV9pw3PLYy6R-18Pbf5ry2iNmAM-jqXA2MuKKkh4,5422
48
+ tests/test_comb.py,sha256=TS-CbtiPbntL4u6E1gSZ6xquNp6cQxIFdJqUr2ak7PA,5515
49
+ tests/test_comm.py,sha256=iwl-Ey-xoytXmlNrjG84pDm82Ry_QUX6wY4gmVh4NDc,2516
50
+ tests/test_inj.py,sha256=UakPA1Sd1GAbFvFepEredWcWPoW7PMLKotfqVZ1i4hE,1434
51
+ tests/test_method.py,sha256=KB7yAtVb4gZftnYzh-VfPb9LGVZOHUIW6OljEYRtbhA,4570
52
+ tests/test_nightly.py,sha256=WpLZfs-n9oPrwz-64gWJB5oxJGYz_ab4sLZ4E-xFBpY,2654
53
+ tests/test_offline_stable.py,sha256=nUyX-LGiQYMjJ1fvjByFBAUS6eMqaqlq6ufoHb8Ai0E,2911
54
+ tests/test_online_stable.py,sha256=f--r8QqGJtx3kDQi1j0pM5v1IOT4SC7B636otZRYfhE,11325
55
+ tests/test_proc_rep.py,sha256=sxRiTBybVm6lyAqmgrri-T2EfZgs27oSgbYXSsN9CwU,1380
56
+ tests/test_runs_stable.py,sha256=hmsI0ZjJRsjSdiRPqXPqEoIxS2sqZIyybNpQpacRs9Q,10235
57
+ tests/test_sequence.py,sha256=vs5-dqkItRds_tPM2-N6MNJ37FB0nLRFaDzBV8d42i8,4880
58
+ tests/test_stable.py,sha256=UFb9rUBnOk7JabcweNIYZLWpBHWGbqKAtsTNfxDhEFg,12208
59
+ pychemstation-0.10.0.dist-info/METADATA,sha256=8jxjr4cJvOZcxFtKJKwkrriG_prk1tmal1_xPD8ruVM,4998
60
+ pychemstation-0.10.0.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
61
+ pychemstation-0.10.0.dist-info/top_level.txt,sha256=zXfKu_4nYWwPHo3OsuhshMNC3SPkcoTGCyODjURaghY,20
62
+ pychemstation-0.10.0.dist-info/RECORD,,
@@ -1,4 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: hatchling 1.27.0
2
+ Generator: setuptools (78.1.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ pychemstation
2
+ tests
tests/__init__.py ADDED
File without changes
tests/constants.py ADDED
@@ -0,0 +1,134 @@
1
+ import os
2
+ import random
3
+ import shutil
4
+
5
+ from pychemstation.control import HPLCController
6
+ from pychemstation.utils.macro import Command
7
+ from pychemstation.utils.method_types import (
8
+ HPLCMethodParams,
9
+ MethodDetails,
10
+ TimeTableEntry,
11
+ )
12
+ from pychemstation.utils.sequence_types import SampleType, SequenceEntry
13
+ from pychemstation.utils.tray_types import FiftyFourVialPlate, TenVialColumn
14
+
15
+ VIAL_PLATES = [
16
+ FiftyFourVialPlate.from_str('P1-A7'),
17
+ FiftyFourVialPlate.from_str('P1-B4'),
18
+ FiftyFourVialPlate.from_str('P1-C2'),
19
+ FiftyFourVialPlate.from_str('P1-D8'),
20
+ FiftyFourVialPlate.from_str('P1-E3'),
21
+ FiftyFourVialPlate.from_str('P1-F5'),
22
+ # plate 2
23
+ FiftyFourVialPlate.from_str('P2-A7'),
24
+ FiftyFourVialPlate.from_str('P2-B2'),
25
+ FiftyFourVialPlate.from_str('P2-C1'),
26
+ FiftyFourVialPlate.from_str('P2-D8'),
27
+ FiftyFourVialPlate.from_str('P2-E3'),
28
+ FiftyFourVialPlate.from_str('P2-F6'),
29
+ ]
30
+
31
+ DEFAULT_METHOD = "GENERAL-POROSHELL-OPT"
32
+ DEFAULT_SEQUENCE = "hplc_testing"
33
+
34
+ # CONSTANTS: paths only work in Hein group HPLC machine in room 242
35
+ DEFAULT_COMMAND_PATH = "C:\\Users\\User\\Desktop\\Lucy\\hplc-method-optimization\\tests\\"
36
+ DEFAULT_METHOD_DIR = "C:\\ChemStation\\1\\Methods\\"
37
+ DATA_DIR = "C:\\Users\\Public\\Documents\\ChemStation\\2\\Data\\LC-BO\\"
38
+ SEQUENCE_DIR = "C:\\USERS\\PUBLIC\\DOCUMENTS\\CHEMSTATION\\3\\Sequence"
39
+ SEQUENCE_DATA_DIR_2 = "C:\\Users\\Public\\Documents\\ChemStation\\2\\Data"
40
+ SEQUENCE_DATA_DIR = "C:\\Users\\Public\\Documents\\ChemStation\\3\\Data\\"
41
+
42
+ HEIN_LAB_CONSTANTS_242 = [DEFAULT_COMMAND_PATH,
43
+ DEFAULT_METHOD_DIR,
44
+ DATA_DIR,
45
+ SEQUENCE_DIR,
46
+ SEQUENCE_DATA_DIR_2,
47
+ SEQUENCE_DATA_DIR]
48
+
49
+ # these CONSTANTS work in rm 254
50
+ DEFAULT_COMMAND_PATH_254 = "D:\\\git_repositories\\\hplc_comm\\"
51
+ DEFAULT_METHOD_DIR_254 = "D:\\Chemstation\\1\\Methods\\"
52
+ DATA_DIR_254 = "D:\\Chemstation\\1\\Data\\LC BO\\"
53
+ SEQUENCE_DIR_254 = "C:\\1\\Sequence\\"
54
+ SEQUENCE_DATA_DIR_254 = "D:\\Chemstation\\1\\Data\\"
55
+
56
+ HEIN_LAB_CONSTANTS_254 = [DEFAULT_COMMAND_PATH_254,
57
+ DEFAULT_METHOD_DIR_254,
58
+ DATA_DIR_254,
59
+ SEQUENCE_DIR_254,
60
+ SEQUENCE_DATA_DIR_254]
61
+
62
+
63
+ def room(num: int):
64
+ if num == 242:
65
+ return HEIN_LAB_CONSTANTS_242
66
+ elif num == 254:
67
+ return HEIN_LAB_CONSTANTS_254
68
+
69
+
70
+ def gen_rand_method():
71
+ org_modifier = int(random.random() * 10)
72
+ max_run_time = int(random.random() * 10)
73
+ post_run_time = int(random.random() * 10)
74
+ flow = float(random.random() * 10) / 10
75
+ flow_1 = float(random.random() * 10) / 10
76
+ flow_2 = float(random.random() * 10) / 10
77
+ return MethodDetails(name=DEFAULT_METHOD,
78
+ timetable=[TimeTableEntry(start_time=0.10,
79
+ organic_modifer=org_modifier,
80
+ flow=flow_1),
81
+ TimeTableEntry(start_time=1,
82
+ organic_modifer=100 - int(random.random() * 10),
83
+ flow=flow_2)],
84
+ stop_time=max_run_time,
85
+ post_time=post_run_time,
86
+ params=HPLCMethodParams(organic_modifier=org_modifier, flow=flow))
87
+
88
+
89
+ seq_entry = SequenceEntry(
90
+ vial_location=TenVialColumn.ONE,
91
+ method=DEFAULT_METHOD,
92
+ num_inj=int(random.random() * 10),
93
+ inj_vol=int(random.random() * 10),
94
+ sample_name="Test",
95
+ sample_type=SampleType(int(random.random() * 3)),
96
+ )
97
+
98
+
99
+ def set_up_utils(num: int, offline: bool = False, runs: bool = False) -> HPLCController:
100
+ path_constants = room(num)
101
+ if not offline:
102
+ for path in path_constants:
103
+ if not os.path.exists(path):
104
+ raise FileNotFoundError(
105
+ f"{path} does not exist on your system. If you would like to run tests, please change this path.")
106
+
107
+ controller = HPLCController(offline=offline,
108
+ comm_dir=path_constants[0],
109
+ method_dir=path_constants[1],
110
+ data_dirs=[path_constants[2], path_constants[4], path_constants[5]],
111
+ sequence_dir=path_constants[3],
112
+ debug=True)
113
+ if not offline:
114
+ controller.send(Command.SAVE_METHOD_CMD.value.format(commit_msg="method saved by pychemstation"))
115
+ controller.send(Command.SAVE_SEQUENCE_CMD)
116
+ if runs:
117
+ controller.instrument_on()
118
+ controller.preprun()
119
+ return controller
120
+
121
+
122
+
123
+ def clean_up(hplc_controller: HPLCController):
124
+ if hasattr(hplc_controller.method_controller, "data_dirs") and hasattr(hplc_controller.sequence_controller, "data_dirs"):
125
+ files = hplc_controller.method_controller.data_files + [d.dir for d in hplc_controller.sequence_controller.data_files]
126
+ data_dirs = hplc_controller.method_controller.data_dirs
127
+ for folder in files:
128
+ if os.path.isdir(folder):
129
+ shutil.rmtree(folder)
130
+ else:
131
+ for data_dir in data_dirs:
132
+ possible_path = os.path.join(data_dir, folder)
133
+ if os.path.isdir(possible_path):
134
+ shutil.rmtree(possible_path)