pychemstation 0.10.2__py3-none-any.whl → 0.10.4__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.
- pychemstation/__init__.py +1 -1
- pychemstation/analysis/__init__.py +3 -4
- pychemstation/analysis/base_spectrum.py +7 -7
- pychemstation/{utils → analysis}/chromatogram.py +4 -4
- pychemstation/analysis/process_report.py +106 -70
- pychemstation/control/README.md +21 -53
- pychemstation/control/__init__.py +3 -2
- pychemstation/control/controllers/__init__.py +1 -5
- pychemstation/control/controllers/comm.py +20 -11
- pychemstation/control/controllers/devices/device.py +22 -12
- pychemstation/control/controllers/devices/injector.py +24 -14
- pychemstation/control/controllers/tables/method.py +233 -100
- pychemstation/control/controllers/tables/ms.py +7 -4
- pychemstation/control/controllers/tables/sequence.py +134 -54
- pychemstation/control/controllers/tables/table.py +152 -92
- pychemstation/control/hplc.py +96 -78
- pychemstation/generated/__init__.py +0 -2
- pychemstation/generated/pump_method.py +15 -19
- pychemstation/utils/macro.py +10 -9
- pychemstation/utils/method_types.py +1 -0
- pychemstation/utils/num_utils.py +2 -2
- pychemstation/utils/parsing.py +0 -11
- pychemstation/utils/sequence_types.py +2 -3
- pychemstation/utils/spec_utils.py +2 -3
- pychemstation/utils/table_types.py +10 -9
- pychemstation/utils/tray_types.py +48 -38
- {pychemstation-0.10.2.dist-info → pychemstation-0.10.4.dist-info}/METADATA +46 -20
- pychemstation-0.10.4.dist-info/RECORD +37 -0
- pychemstation-0.10.2.dist-info/RECORD +0 -37
- {pychemstation-0.10.2.dist-info → pychemstation-0.10.4.dist-info}/WHEEL +0 -0
- {pychemstation-0.10.2.dist-info → pychemstation-0.10.4.dist-info}/licenses/LICENSE +0 -0
pychemstation/control/hplc.py
CHANGED
@@ -3,57 +3,48 @@ Module to provide API for higher-level HPLC actions.
|
|
3
3
|
|
4
4
|
Authors: Lucy Hao
|
5
5
|
"""
|
6
|
+
|
6
7
|
from __future__ import annotations
|
7
8
|
|
8
9
|
from typing import Dict, List, Optional, Tuple, Union
|
9
10
|
|
10
|
-
from pychemstation.
|
11
|
+
from pychemstation.analysis.chromatogram import (
|
11
12
|
AgilentHPLCChromatogram,
|
12
13
|
)
|
13
|
-
|
14
|
+
|
14
15
|
from ..analysis.process_report import AgilentReport, ReportType
|
15
16
|
from ..control.controllers import (
|
16
17
|
CommunicationController,
|
17
18
|
MethodController,
|
18
19
|
SequenceController,
|
19
20
|
)
|
20
|
-
from
|
21
|
-
from ..utils.injector_types import InjectorTable
|
21
|
+
from pychemstation.analysis.chromatogram import AgilentChannelChromatogramData
|
22
22
|
from ..utils.macro import Command, Response, Status
|
23
23
|
from ..utils.method_types import MethodDetails
|
24
24
|
from ..utils.sequence_types import SequenceTable
|
25
25
|
from ..utils.table_types import Table
|
26
|
+
from .controllers.devices.injector import InjectorController
|
26
27
|
|
27
28
|
|
28
29
|
class HPLCController:
|
29
30
|
# tables
|
30
|
-
METHOD_TIMETABLE = Table(
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
name="SprayChamber"
|
48
|
-
)
|
49
|
-
|
50
|
-
def __init__(self,
|
51
|
-
comm_dir: str,
|
52
|
-
method_dir: str,
|
53
|
-
sequence_dir: str,
|
54
|
-
data_dirs: List[str],
|
55
|
-
offline: bool = False,
|
56
|
-
debug: bool = False,):
|
31
|
+
METHOD_TIMETABLE = Table(register="RCPMP1Method[1]", name="Timetable")
|
32
|
+
|
33
|
+
SEQUENCE_TABLE = Table(register="_sequence[1]", name="SeqTable1")
|
34
|
+
|
35
|
+
INJECTOR_TABLE = Table(register="RCWLS1Pretreatment[1]", name="InstructionTable")
|
36
|
+
|
37
|
+
MSD_TABLE = Table(register="MSACQINFO[1]", name="SprayChamber")
|
38
|
+
|
39
|
+
def __init__(
|
40
|
+
self,
|
41
|
+
comm_dir: str,
|
42
|
+
method_dir: str,
|
43
|
+
sequence_dir: str,
|
44
|
+
data_dirs: List[str],
|
45
|
+
offline: bool = False,
|
46
|
+
debug: bool = False,
|
47
|
+
):
|
57
48
|
"""Initialize HPLC controller. The `hplc_talk.mac` macro file must be loaded in the Chemstation software.
|
58
49
|
`comm_dir` must match the file path in the macro file. All file paths are normal strings, with the left slash
|
59
50
|
double escaped: "C:\\my_folder\\"
|
@@ -65,21 +56,29 @@ class HPLCController:
|
|
65
56
|
:param sequence_dir: Name of directory where sequence files are stored.
|
66
57
|
:raises FileNotFoundError: If either `data_dir`, `method_dir`, `sequence_dir`, `sequence_data_dir`or `comm_dir` is not a valid directory.
|
67
58
|
"""
|
68
|
-
self.comm =
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
59
|
+
self.comm = (
|
60
|
+
CommunicationController(comm_dir=comm_dir, debug=debug)
|
61
|
+
if not offline
|
62
|
+
else None
|
63
|
+
)
|
64
|
+
self.method_controller = MethodController(
|
65
|
+
controller=self.comm,
|
66
|
+
src=method_dir,
|
67
|
+
data_dirs=data_dirs,
|
68
|
+
table=self.METHOD_TIMETABLE,
|
69
|
+
offline=offline,
|
70
|
+
injector_controller=InjectorController(
|
71
|
+
controller=self.comm, table=self.INJECTOR_TABLE, offline=offline
|
72
|
+
),
|
73
|
+
)
|
74
|
+
self.sequence_controller = SequenceController(
|
75
|
+
controller=self.comm,
|
76
|
+
src=sequence_dir,
|
77
|
+
data_dirs=data_dirs,
|
78
|
+
table=self.SEQUENCE_TABLE,
|
79
|
+
method_controller=self.method_controller,
|
80
|
+
offline=offline,
|
81
|
+
)
|
83
82
|
|
84
83
|
def send(self, cmd: Union[Command, str]):
|
85
84
|
"""
|
@@ -89,29 +88,32 @@ class HPLCController:
|
|
89
88
|
"""
|
90
89
|
if not self.comm:
|
91
90
|
raise RuntimeError(
|
92
|
-
"Communication controller must be initialized before sending command. It is currently in offline mode."
|
91
|
+
"Communication controller must be initialized before sending command. It is currently in offline mode."
|
92
|
+
)
|
93
93
|
self.comm.send(cmd)
|
94
94
|
|
95
95
|
def receive(self) -> Response:
|
96
96
|
"""
|
97
97
|
Get the most recent response from Chemstation.
|
98
98
|
|
99
|
-
:
|
99
|
+
:return: most recent response from a macro that returned a response.
|
100
100
|
"""
|
101
101
|
if not self.comm:
|
102
102
|
raise RuntimeError(
|
103
|
-
"Communication controller must be initialized before sending command. It is currently in offline mode."
|
103
|
+
"Communication controller must be initialized before sending command. It is currently in offline mode."
|
104
|
+
)
|
104
105
|
return self.comm.receive().value
|
105
106
|
|
106
107
|
def status(self) -> Status:
|
107
108
|
"""
|
108
109
|
Get the current status of the HPLC machine.
|
109
110
|
|
110
|
-
:
|
111
|
+
:return: current status of the HPLC machine; Status types can be found in `pychemstation.utils.macro`
|
111
112
|
"""
|
112
113
|
if not self.comm:
|
113
114
|
raise RuntimeError(
|
114
|
-
"Communication controller must be initialized before sending command. It is currently in offline mode."
|
115
|
+
"Communication controller must be initialized before sending command. It is currently in offline mode."
|
116
|
+
)
|
115
117
|
return self.comm.get_status()
|
116
118
|
|
117
119
|
def switch_method(self, method_name: str):
|
@@ -135,7 +137,12 @@ class HPLCController:
|
|
135
137
|
"""
|
136
138
|
self.sequence_controller.switch(sequence_name)
|
137
139
|
|
138
|
-
def run_method(
|
140
|
+
def run_method(
|
141
|
+
self,
|
142
|
+
experiment_name: str,
|
143
|
+
add_timestamp: bool = True,
|
144
|
+
stall_while_running: bool = True,
|
145
|
+
):
|
139
146
|
"""
|
140
147
|
This is the preferred method to trigger a run.
|
141
148
|
Starts the currently selected method, storing data
|
@@ -146,9 +153,11 @@ class HPLCController:
|
|
146
153
|
:param stall_while_running: whether to return or stall while HPLC runs.
|
147
154
|
:param add_timestamp: whether to append a timestamp in '%Y-%m-%d-%H-%M' format to end of experiment name.
|
148
155
|
"""
|
149
|
-
self.method_controller.run(
|
150
|
-
|
151
|
-
|
156
|
+
self.method_controller.run(
|
157
|
+
experiment_name=experiment_name,
|
158
|
+
stall_while_running=stall_while_running,
|
159
|
+
add_timestamp=add_timestamp,
|
160
|
+
)
|
152
161
|
|
153
162
|
def stop_method(self):
|
154
163
|
"""Stops the current running method, manual intervention may be needed."""
|
@@ -168,7 +177,7 @@ class HPLCController:
|
|
168
177
|
"""
|
169
178
|
Check if the currently running method (if any) is done.
|
170
179
|
|
171
|
-
:returns
|
180
|
+
:returns the percent of the method run completed, and whether the run is complete.
|
172
181
|
"""
|
173
182
|
return self.method_controller.check_hplc_run_finished()
|
174
183
|
|
@@ -176,7 +185,7 @@ class HPLCController:
|
|
176
185
|
"""
|
177
186
|
Check if the currently running sequence (if any) is done.
|
178
187
|
|
179
|
-
:
|
188
|
+
:return: the percent of the sequence run completed, and whether the run is complete.
|
180
189
|
"""
|
181
190
|
return self.sequence_controller.check_hplc_run_finished()
|
182
191
|
|
@@ -197,19 +206,25 @@ class HPLCController:
|
|
197
206
|
"""
|
198
207
|
self.sequence_controller.edit(updated_sequence)
|
199
208
|
|
200
|
-
def get_last_run_method_report(
|
201
|
-
|
202
|
-
|
209
|
+
def get_last_run_method_report(
|
210
|
+
self,
|
211
|
+
custom_path: Optional[str] = None,
|
212
|
+
report_type: ReportType = ReportType.CSV,
|
213
|
+
) -> AgilentReport:
|
203
214
|
"""
|
204
215
|
Return data contained in the REPORT files. Use `aghplctools` if you want more report processing utility.
|
216
|
+
|
205
217
|
:param custom_path: path to sequence folder
|
206
218
|
:param report_type: read either the TXT or CSV version
|
207
|
-
:
|
219
|
+
:return: report data for method
|
208
220
|
"""
|
209
|
-
return self.method_controller.get_report(
|
221
|
+
return self.method_controller.get_report(
|
222
|
+
custom_path=custom_path, report_type=report_type
|
223
|
+
)[0]
|
210
224
|
|
211
|
-
def get_last_run_method_data(
|
212
|
-
|
225
|
+
def get_last_run_method_data(
|
226
|
+
self, read_uv: bool = False, custom_path: Optional[str] = None
|
227
|
+
) -> Dict[str, AgilentHPLCChromatogram] | AgilentChannelChromatogramData:
|
213
228
|
"""
|
214
229
|
Returns the last run method data.
|
215
230
|
|
@@ -221,20 +236,27 @@ class HPLCController:
|
|
221
236
|
else:
|
222
237
|
return self.method_controller.get_data(custom_path=custom_path)
|
223
238
|
|
224
|
-
def get_last_run_sequence_reports(
|
225
|
-
|
226
|
-
|
239
|
+
def get_last_run_sequence_reports(
|
240
|
+
self,
|
241
|
+
custom_path: Optional[str] = None,
|
242
|
+
report_type: ReportType = ReportType.CSV,
|
243
|
+
) -> List[AgilentReport]:
|
227
244
|
"""
|
228
245
|
Return data contained in the REPORT files. Use `aghplctools` if you want more report processing utility.
|
246
|
+
|
229
247
|
:param custom_path: path to sequence folder
|
230
248
|
:param report_type: read either the TXT or CSV version
|
231
|
-
:
|
249
|
+
:return: list of reports for each row
|
232
250
|
"""
|
233
|
-
return self.sequence_controller.get_report(
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
251
|
+
return self.sequence_controller.get_report(
|
252
|
+
custom_path=custom_path, report_type=report_type
|
253
|
+
)
|
254
|
+
|
255
|
+
def get_last_run_sequence_data(
|
256
|
+
self, read_uv: bool = False, custom_path: Optional[str] = None
|
257
|
+
) -> (
|
258
|
+
List[Dict[int, AgilentHPLCChromatogram]] | List[AgilentChannelChromatogramData]
|
259
|
+
):
|
238
260
|
"""
|
239
261
|
Returns data for all rows in the last run sequence data.
|
240
262
|
|
@@ -254,10 +276,6 @@ class HPLCController:
|
|
254
276
|
"""Returns the name of the currently loaded method."""
|
255
277
|
return self.method_controller.check()
|
256
278
|
|
257
|
-
def load_injector_program(self) -> InjectorTable:
|
258
|
-
"""Returns all details of the injector program for the currently loaded method."""
|
259
|
-
return self.method_controller.injector_controller.load()
|
260
|
-
|
261
279
|
def load_method(self) -> MethodDetails:
|
262
280
|
"""Returns details of the currently loaded method, such as its starting modifier conditions and timetable."""
|
263
281
|
return self.method_controller.load()
|
@@ -271,7 +289,7 @@ class HPLCController:
|
|
271
289
|
self.send(Command.STANDBY_CMD)
|
272
290
|
|
273
291
|
def preprun(self):
|
274
|
-
"""
|
292
|
+
"""Prepares all modules for run. All lamps and pumps are switched on."""
|
275
293
|
self.send(Command.PREPRUN_CMD)
|
276
294
|
|
277
295
|
def lamp_on(self):
|
@@ -313,25 +313,21 @@ class SolventElement:
|
|
313
313
|
"required": True,
|
314
314
|
},
|
315
315
|
)
|
316
|
-
channel1_extended_solvent_type: Optional[Channel1ExtendedSolventType] = (
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
"type": "Element",
|
332
|
-
"required": True,
|
333
|
-
},
|
334
|
-
)
|
316
|
+
channel1_extended_solvent_type: Optional[Channel1ExtendedSolventType] = field(
|
317
|
+
default=None,
|
318
|
+
metadata={
|
319
|
+
"name": "Channel1ExtendedSolventType",
|
320
|
+
"type": "Element",
|
321
|
+
"required": True,
|
322
|
+
},
|
323
|
+
)
|
324
|
+
channel2_extended_solvent_type: Optional[Channel2ExtendedSolventType] = field(
|
325
|
+
default=None,
|
326
|
+
metadata={
|
327
|
+
"name": "Channel2ExtendedSolventType",
|
328
|
+
"type": "Element",
|
329
|
+
"required": True,
|
330
|
+
},
|
335
331
|
)
|
336
332
|
|
337
333
|
|
pychemstation/utils/macro.py
CHANGED
@@ -15,7 +15,7 @@ class Response:
|
|
15
15
|
# See https://www.agilent.com/cs/library/usermanuals/Public/MACROS.PDF
|
16
16
|
class Command(Enum):
|
17
17
|
def __str__(self):
|
18
|
-
return
|
18
|
+
return "%s" % self.value
|
19
19
|
|
20
20
|
GET_NUM_VAL_CMD = "response_num = {cmd}"
|
21
21
|
GET_TEXT_VAL_CMD = "response$ = {cmd}"
|
@@ -37,17 +37,17 @@ class Command(Enum):
|
|
37
37
|
# Method and Sequence Related
|
38
38
|
GET_METHOD_CMD = "response$ = _MethFile$"
|
39
39
|
GET_ROWS_CMD = 'response_num = TabHdrVal({register}, "{table_name}", "{col_name}")'
|
40
|
-
SWITCH_METHOD_CMD =
|
40
|
+
SWITCH_METHOD_CMD = "LoadMethod _MethPath$, _MethFile$"
|
41
41
|
SWITCH_METHOD_CMD_SPECIFIC = 'LoadMethod "{method_dir}", "{method_name}.M"'
|
42
42
|
START_METHOD_CMD = "StartMethod"
|
43
43
|
RUN_METHOD_CMD = 'RunMethod "{data_dir}",, "{experiment_name}"'
|
44
44
|
STOP_METHOD_CMD = "StopMethod"
|
45
|
-
UPDATE_METHOD_CMD =
|
46
|
-
SWITCH_SEQUENCE_CMD =
|
47
|
-
SAVE_SEQUENCE_CMD =
|
45
|
+
UPDATE_METHOD_CMD = "UpdateMethod"
|
46
|
+
SWITCH_SEQUENCE_CMD = "LoadSequence _SeqPath$, _SeqFile$"
|
47
|
+
SAVE_SEQUENCE_CMD = "SaveSequence _SeqPath$, _SeqFile$"
|
48
48
|
SAVE_METHOD_CMD = 'SaveMethod _MethPath$, _MethFile$, "{commit_msg}"'
|
49
|
-
GET_SEQUENCE_CMD =
|
50
|
-
RUN_SEQUENCE_CMD =
|
49
|
+
GET_SEQUENCE_CMD = "response$ = _SeqFile$"
|
50
|
+
RUN_SEQUENCE_CMD = "RunSequence"
|
51
51
|
|
52
52
|
|
53
53
|
class HPLCRunningStatus(Enum):
|
@@ -76,7 +76,6 @@ class HPLCAvailStatus(Enum):
|
|
76
76
|
|
77
77
|
|
78
78
|
class HPLCErrorStatus(Enum):
|
79
|
-
|
80
79
|
@classmethod
|
81
80
|
def has_member_key(cls, key):
|
82
81
|
return key in cls.__members__
|
@@ -87,7 +86,9 @@ class HPLCErrorStatus(Enum):
|
|
87
86
|
MALFORMED = "MALFORMED"
|
88
87
|
|
89
88
|
|
90
|
-
def str_to_status(
|
89
|
+
def str_to_status(
|
90
|
+
status: str,
|
91
|
+
) -> Type[HPLCRunningStatus[Any] | HPLCErrorStatus[Any] | HPLCAvailStatus[Any]]:
|
91
92
|
if HPLCErrorStatus.has_member_key(status):
|
92
93
|
return HPLCErrorStatus[status]
|
93
94
|
if HPLCRunningStatus.has_member_key(status):
|
pychemstation/utils/num_utils.py
CHANGED
@@ -11,7 +11,7 @@ def find_nearest_value_index(array, value) -> Tuple[float, int]:
|
|
11
11
|
:param value: Target value.
|
12
12
|
:type value: float
|
13
13
|
|
14
|
-
:
|
14
|
+
:return: Nearest value in array and its index.
|
15
15
|
"""
|
16
16
|
|
17
17
|
index_ = np.argmin(np.abs(array - value))
|
@@ -34,7 +34,7 @@ def interpolate_to_index(array, ids, precision: int = 100) -> np.array:
|
|
34
34
|
:type ids: np.array[float]
|
35
35
|
:param precision: Desired presion.
|
36
36
|
|
37
|
-
:
|
37
|
+
:return: New array with interpolated values according to provided indexes "ids".
|
38
38
|
|
39
39
|
Example:
|
40
40
|
>>> interpolate_to_index(np.array([1.5]), np.array([1,2,3], 100))
|
pychemstation/utils/parsing.py
CHANGED
@@ -27,7 +27,6 @@ UINT32 = ENDIAN + "I"
|
|
27
27
|
|
28
28
|
|
29
29
|
def fread(fid, nelements, dtype):
|
30
|
-
|
31
30
|
"""Equivalent to Matlab fread function"""
|
32
31
|
|
33
32
|
if dtype is str:
|
@@ -42,7 +41,6 @@ def fread(fid, nelements, dtype):
|
|
42
41
|
|
43
42
|
|
44
43
|
def parse_utf16_string(file_, encoding="UTF16"):
|
45
|
-
|
46
44
|
"""Parse a pascal type UTF16 encoded string from a binary file object"""
|
47
45
|
|
48
46
|
# First read the expected number of CHARACTERS
|
@@ -53,7 +51,6 @@ def parse_utf16_string(file_, encoding="UTF16"):
|
|
53
51
|
|
54
52
|
|
55
53
|
class cached_property(object):
|
56
|
-
|
57
54
|
"""A property that is only computed once per instance and then replaces
|
58
55
|
itself with an ordinary attribute. Deleting the attribute resets the
|
59
56
|
property.
|
@@ -73,7 +70,6 @@ class cached_property(object):
|
|
73
70
|
|
74
71
|
|
75
72
|
class CHFile(object):
|
76
|
-
|
77
73
|
"""Class that implementats the Agilent .ch file format version
|
78
74
|
130. Warning: Not all aspects of the file header is understood,
|
79
75
|
so there may and probably is information that is not parsed. See
|
@@ -122,7 +118,6 @@ class CHFile(object):
|
|
122
118
|
supported_versions = {130}
|
123
119
|
|
124
120
|
def __init__(self, filepath):
|
125
|
-
|
126
121
|
self.filepath = filepath
|
127
122
|
self.metadata = {}
|
128
123
|
with open(self.filepath, "rb") as file_:
|
@@ -130,7 +125,6 @@ class CHFile(object):
|
|
130
125
|
self.values = self._parse_data(file_)
|
131
126
|
|
132
127
|
def _parse_header(self, file_):
|
133
|
-
|
134
128
|
"""Parse the header"""
|
135
129
|
|
136
130
|
# Parse and check version
|
@@ -154,7 +148,6 @@ class CHFile(object):
|
|
154
148
|
]
|
155
149
|
|
156
150
|
def _parse_header_status(self):
|
157
|
-
|
158
151
|
"""Print known and unknown parts of the header"""
|
159
152
|
|
160
153
|
file_ = open(self.filepath, "rb")
|
@@ -234,7 +227,6 @@ class CHFile(object):
|
|
234
227
|
file_.close()
|
235
228
|
|
236
229
|
def _parse_data(self, file_):
|
237
|
-
|
238
230
|
"""Parse the data. Decompress the delta-encoded data, and scale them
|
239
231
|
with y-scaling"""
|
240
232
|
|
@@ -252,7 +244,6 @@ class CHFile(object):
|
|
252
244
|
buff = [0, 0, 0, 0]
|
253
245
|
|
254
246
|
while file_.tell() < stop:
|
255
|
-
|
256
247
|
buff[0] = fread(file_, 1, INT16)[0][0]
|
257
248
|
buff[1] = buff[3]
|
258
249
|
|
@@ -260,7 +251,6 @@ class CHFile(object):
|
|
260
251
|
break
|
261
252
|
|
262
253
|
for i in range(buff[0] & 4095):
|
263
|
-
|
264
254
|
buff[2] = fread(file_, 1, INT16)[0][0]
|
265
255
|
|
266
256
|
if buff[2] != -32768:
|
@@ -279,7 +269,6 @@ class CHFile(object):
|
|
279
269
|
|
280
270
|
@cached_property
|
281
271
|
def times(self):
|
282
|
-
|
283
272
|
"""The time values (x-value) for the data set in minutes"""
|
284
273
|
|
285
274
|
return np.linspace(
|
@@ -1,9 +1,8 @@
|
|
1
1
|
from __future__ import annotations
|
2
2
|
|
3
|
-
from dataclasses import dataclass
|
4
3
|
from enum import Enum
|
5
4
|
from typing import Optional, List
|
6
|
-
|
5
|
+
from dataclasses import dataclass, field
|
7
6
|
from pychemstation.utils.tray_types import Tray
|
8
7
|
|
9
8
|
|
@@ -11,7 +10,7 @@ from pychemstation.utils.tray_types import Tray
|
|
11
10
|
class SequenceDataFiles:
|
12
11
|
sequence_name: str
|
13
12
|
dir: str
|
14
|
-
child_dirs:
|
13
|
+
child_dirs: List[str] = field(default_factory=list)
|
15
14
|
|
16
15
|
|
17
16
|
class SampleType(Enum):
|
@@ -28,7 +28,6 @@ def create_binary_peak_map(data):
|
|
28
28
|
peak_map = np.full_like(data_c, False, dtype=bool)
|
29
29
|
|
30
30
|
for _ in range(100500): # shouldn't take more iterations
|
31
|
-
|
32
31
|
# looking for peaks
|
33
32
|
peaks_found = np.logical_or(
|
34
33
|
data_c > np.mean(data_c) + np.std(data_c) * 3,
|
@@ -156,14 +155,14 @@ def filter_noisy_regions(y_data, peaks_regions):
|
|
156
155
|
# compute the actual regions data points
|
157
156
|
y_data_regions = []
|
158
157
|
for region in peaks_regions:
|
159
|
-
y_data_regions.append(y_data[region[0]: region[-1]])
|
158
|
+
y_data_regions.append(y_data[region[0] : region[-1]])
|
160
159
|
|
161
160
|
# compute noise data regions, i.e. in between peak regions
|
162
161
|
noise_data_regions = []
|
163
162
|
for row, _ in enumerate(peaks_regions):
|
164
163
|
try:
|
165
164
|
noise_data_regions.append(
|
166
|
-
y_data[peaks_regions[row][1]: peaks_regions[row + 1][0]]
|
165
|
+
y_data[peaks_regions[row][1] : peaks_regions[row + 1][0]]
|
167
166
|
)
|
168
167
|
except IndexError:
|
169
168
|
# exception for the last row -> discard
|
@@ -7,28 +7,30 @@ from typing import TypeVar
|
|
7
7
|
|
8
8
|
class TableOperation(Enum):
|
9
9
|
def __str__(self):
|
10
|
-
return
|
10
|
+
return "%s" % self.value
|
11
11
|
|
12
12
|
DELETE_TABLE = 'DelTab {register}, "{table_name}"'
|
13
13
|
CREATE_TABLE = 'NewTab {register}, "{table_name}"'
|
14
14
|
NEW_ROW = 'InsTabRow {register}, "{table_name}"'
|
15
15
|
DELETE_ROW = 'DelTabRow {register}, "{table_name}", {row}'
|
16
16
|
EDIT_ROW_VAL = 'SetTabVal "{register}", "{table_name}", {row}, "{col_name}", {val}'
|
17
|
-
EDIT_ROW_TEXT =
|
17
|
+
EDIT_ROW_TEXT = (
|
18
|
+
'SetTabText "{register}", "{table_name}", {row}, "{col_name}", "{val}"'
|
19
|
+
)
|
18
20
|
GET_ROW_VAL = 'TabVal("{register}", "{table_name}", {row}, "{col_name}")'
|
19
21
|
GET_ROW_TEXT = 'TabText$("{register}", "{table_name}", {row}, "{col_name}")'
|
20
22
|
GET_NUM_ROWS = 'Rows = TabHdrVal({register}, "{table_name}", "{col_name}")'
|
21
23
|
GET_OBJ_HDR_VAL = 'ObjHdrVal("{register}", "{register_flag}")'
|
22
24
|
GET_OBJ_HDR_TEXT = 'ObjHdrText$("{register}", "{register_flag}")'
|
23
|
-
UPDATE_OBJ_HDR_VAL =
|
24
|
-
UPDATE_OBJ_HDR_TEXT =
|
25
|
+
UPDATE_OBJ_HDR_VAL = "SetObjHdrVal {register}, {register_flag}, {val}"
|
26
|
+
UPDATE_OBJ_HDR_TEXT = "SetObjHdrText {register}, {register_flag}, {val}"
|
25
27
|
NEW_COL_TEXT = 'NewColText {register}, "{table_name}", "{col_name}", "{val}"'
|
26
28
|
NEW_COL_VAL = 'NewColVal {register}, "{table_name}", "{col_name}", {val}'
|
27
29
|
|
28
30
|
|
29
31
|
class RegisterFlag(Enum):
|
30
32
|
def __str__(self):
|
31
|
-
return
|
33
|
+
return "%s" % self.value
|
32
34
|
|
33
35
|
# for table
|
34
36
|
NUM_ROWS = "NumberOfRows"
|
@@ -40,7 +42,7 @@ class RegisterFlag(Enum):
|
|
40
42
|
SOLVENT_D_COMPOSITION = "PumpChannel4_CompositionPercentage"
|
41
43
|
FLOW = "Flow"
|
42
44
|
MAX_TIME = "StopTime_Time"
|
43
|
-
POST_TIME = "PostTime_Time"
|
45
|
+
POST_TIME = "PostTime_Time" # TODO: check
|
44
46
|
COLUMN_OVEN_TEMP1 = "TemperatureControl_Temperature"
|
45
47
|
COLUMN_OVEN_TEMP2 = "TemperatureControl2_Temperature"
|
46
48
|
STOPTIME_MODE = "StopTime_Mode"
|
@@ -55,7 +57,6 @@ class RegisterFlag(Enum):
|
|
55
57
|
EXTERNAL_CONTACT = "ExternalContact"
|
56
58
|
FUNCTION = "Function"
|
57
59
|
|
58
|
-
|
59
60
|
# for Sequence
|
60
61
|
VIAL_LOCATION = "Vial"
|
61
62
|
NAME = "SampleName"
|
@@ -86,10 +87,10 @@ class RegisterFlag(Enum):
|
|
86
87
|
REMOTE_DUR = "RemoteDuration"
|
87
88
|
|
88
89
|
|
89
|
-
|
90
90
|
@dataclass
|
91
91
|
class Table:
|
92
92
|
register: str
|
93
93
|
name: str
|
94
94
|
|
95
|
-
|
95
|
+
|
96
|
+
T = TypeVar("T")
|