pychemstation 0.5.1__py3-none-any.whl → 0.5.3.dev1__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/analysis/base_spectrum.py +509 -509
- pychemstation/analysis/spec_utils.py +304 -304
- pychemstation/control/comm.py +51 -24
- pychemstation/control/hplc.py +45 -19
- pychemstation/control/table/method.py +77 -61
- pychemstation/control/table/sequence.py +114 -67
- pychemstation/control/table/table_controller.py +72 -35
- pychemstation/utils/macro.py +11 -1
- pychemstation/utils/method_types.py +1 -2
- pychemstation/utils/sequence_types.py +14 -8
- pychemstation/utils/table_types.py +7 -4
- pychemstation/utils/tray_types.py +14 -0
- {pychemstation-0.5.1.dist-info → pychemstation-0.5.3.dev1.dist-info}/METADATA +1 -1
- pychemstation-0.5.3.dev1.dist-info/RECORD +34 -0
- tests/constants.py +58 -5
- tests/test_comb.py +129 -0
- tests/test_comm.py +21 -9
- tests/test_method.py +26 -29
- tests/test_sequence.py +51 -75
- .DS_Store +0 -0
- pychemstation/control/chromatogram.py +0 -128
- pychemstation/control/method.py +0 -232
- pychemstation/control/sequence.py +0 -140
- pychemstation/control/table_controller.py +0 -75
- pychemstation/utils/chemstation.py +0 -290
- pychemstation/utils/constants.py +0 -15
- pychemstation/utils/hplc_param_types.py +0 -185
- pychemstation-0.5.1.dist-info/RECORD +0 -40
- {pychemstation-0.5.1.dist-info → pychemstation-0.5.3.dev1.dist-info}/LICENSE +0 -0
- {pychemstation-0.5.1.dist-info → pychemstation-0.5.3.dev1.dist-info}/WHEEL +0 -0
- {pychemstation-0.5.1.dist-info → pychemstation-0.5.3.dev1.dist-info}/top_level.txt +0 -0
@@ -8,10 +8,10 @@ import time
|
|
8
8
|
from .table_controller import TableController
|
9
9
|
from ...control import CommunicationController
|
10
10
|
from ...utils.chromatogram import SEQUENCE_TIME_FORMAT, AgilentHPLCChromatogram
|
11
|
-
from ...utils.constants import SEQUENCE_TABLE
|
12
11
|
from ...utils.macro import Command
|
13
|
-
from ...utils.sequence_types import SequenceTable, SequenceEntry, SequenceDataFiles
|
14
|
-
from ...utils.table_types import TableOperation, RegisterFlag
|
12
|
+
from ...utils.sequence_types import SequenceTable, SequenceEntry, SequenceDataFiles, InjectionSource, SampleType
|
13
|
+
from ...utils.table_types import TableOperation, RegisterFlag, Table
|
14
|
+
from ...utils.tray_types import TenColumn
|
15
15
|
|
16
16
|
|
17
17
|
class SequenceController(TableController):
|
@@ -19,8 +19,36 @@ class SequenceController(TableController):
|
|
19
19
|
Class containing sequence related logic
|
20
20
|
"""
|
21
21
|
|
22
|
-
def __init__(self, controller: CommunicationController, src: str, data_dir: str):
|
23
|
-
|
22
|
+
def __init__(self, controller: CommunicationController, src: str, data_dir: str, table: Table, method_dir: str):
|
23
|
+
self.method_dir = method_dir
|
24
|
+
super().__init__(controller, src, data_dir, table)
|
25
|
+
|
26
|
+
def load(self) -> SequenceTable:
|
27
|
+
rows = self.get_num_rows()
|
28
|
+
self.send(Command.GET_SEQUENCE_CMD)
|
29
|
+
seq_name = self.receive()
|
30
|
+
|
31
|
+
if rows.is_ok() and seq_name.is_ok():
|
32
|
+
return SequenceTable(
|
33
|
+
name=seq_name.ok_value.num_response,
|
34
|
+
rows=[self.get_row(r + 1) for r in range(int(rows.ok_value.num_response))])
|
35
|
+
raise RuntimeError(rows.err_value)
|
36
|
+
|
37
|
+
def get_row(self, row: int) -> SequenceEntry:
|
38
|
+
sample_name = self.get_text(row, RegisterFlag.NAME)
|
39
|
+
vial_location = int(self.get_num(row, RegisterFlag.VIAL_LOCATION))
|
40
|
+
method = self.get_text(row, RegisterFlag.METHOD)
|
41
|
+
num_inj = int(self.get_num(row, RegisterFlag.NUM_INJ))
|
42
|
+
inj_vol = int(self.get_text(row, RegisterFlag.INJ_VOL))
|
43
|
+
inj_source = InjectionSource(self.get_text(row, RegisterFlag.INJ_SOR))
|
44
|
+
sample_type = SampleType(self.get_num(row, RegisterFlag.SAMPLE_TYPE))
|
45
|
+
return SequenceEntry(sample_name=sample_name,
|
46
|
+
vial_location=vial_location,
|
47
|
+
method=None if len(method) == 0 else method,
|
48
|
+
num_inj=num_inj,
|
49
|
+
inj_vol=inj_vol,
|
50
|
+
inj_source=inj_source,
|
51
|
+
sample_type=sample_type, )
|
24
52
|
|
25
53
|
def switch(self, seq_name: str):
|
26
54
|
"""
|
@@ -34,13 +62,7 @@ class SequenceController(TableController):
|
|
34
62
|
time.sleep(2)
|
35
63
|
self.send(Command.GET_SEQUENCE_CMD)
|
36
64
|
time.sleep(2)
|
37
|
-
|
38
|
-
for _ in range(10):
|
39
|
-
try:
|
40
|
-
parsed_response = self.receive().splitlines()[1].split()[1:][0]
|
41
|
-
break
|
42
|
-
except IndexError:
|
43
|
-
continue
|
65
|
+
parsed_response = self.receive().value.string_response
|
44
66
|
|
45
67
|
assert parsed_response == f"{seq_name}.S", "Switching sequence failed."
|
46
68
|
|
@@ -53,85 +75,108 @@ class SequenceController(TableController):
|
|
53
75
|
"""
|
54
76
|
self.send("Local Rows")
|
55
77
|
self.sleep(1)
|
56
|
-
self.delete_table(
|
78
|
+
self.delete_table()
|
57
79
|
self.sleep(1)
|
58
|
-
self.new_table(
|
80
|
+
self.new_table()
|
59
81
|
self.sleep(1)
|
60
|
-
self.
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
82
|
+
self.get_num_rows()
|
83
|
+
|
84
|
+
if True:
|
85
|
+
for _ in sequence_table.rows:
|
86
|
+
self.add_row()
|
87
|
+
self.sleep(1)
|
88
|
+
self.send(Command.SAVE_SEQUENCE_CMD)
|
89
|
+
self.get_num_rows()
|
65
90
|
self.send(Command.SAVE_SEQUENCE_CMD)
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
91
|
+
for i, row in enumerate(sequence_table.rows):
|
92
|
+
self.edit_row(row=row, row_num=i + 1)
|
93
|
+
self.sleep(1)
|
94
|
+
self.send(Command.SAVE_SEQUENCE_CMD)
|
95
|
+
else:
|
96
|
+
for i, row in enumerate(sequence_table.rows):
|
97
|
+
self.add_row()
|
98
|
+
self.sleep(0.1)
|
99
|
+
self.edit_row(row=row, row_num=i + 1)
|
100
|
+
self.sleep(0.1)
|
101
|
+
rows = self.get_num_rows()
|
102
|
+
self.send(Command.SAVE_SEQUENCE_CMD)
|
103
|
+
self.send(Command.SWITCH_SEQUENCE_CMD)
|
75
104
|
|
76
105
|
def edit_row(self, row: SequenceEntry, row_num: int):
|
77
106
|
"""
|
78
|
-
Edits a row in the sequence table.
|
107
|
+
Edits a row in the sequence table. If a row does NOT exist, a new one will be created.
|
79
108
|
|
80
109
|
:param row: sequence row entry with updated information
|
81
|
-
:param row_num: the row to edit, based on
|
110
|
+
:param row_num: the row to edit, based on 1-based indexing
|
82
111
|
"""
|
112
|
+
num_rows = self.get_num_rows()
|
113
|
+
if num_rows.is_ok():
|
114
|
+
while num_rows.ok_value.num_response < row_num:
|
115
|
+
self.add_row()
|
116
|
+
self.send(Command.SAVE_SEQUENCE_CMD)
|
117
|
+
num_rows = self.get_num_rows()
|
118
|
+
|
119
|
+
table_register = self.table.register
|
120
|
+
table_name = self.table.name
|
121
|
+
|
83
122
|
if row.vial_location:
|
84
|
-
self.sleepy_send(TableOperation.EDIT_ROW_VAL.value.format(register=
|
85
|
-
table_name=
|
123
|
+
self.sleepy_send(TableOperation.EDIT_ROW_VAL.value.format(register=table_register,
|
124
|
+
table_name=table_name,
|
86
125
|
row=row_num,
|
87
126
|
col_name=RegisterFlag.VIAL_LOCATION,
|
88
|
-
val=row.vial_location))
|
127
|
+
val=row.vial_location.value))
|
89
128
|
if row.method:
|
90
|
-
|
91
|
-
|
129
|
+
possible_path = os.path.join(self.method_dir, row.method)
|
130
|
+
method = row.method
|
131
|
+
if os.path.exists(possible_path):
|
132
|
+
method = os.path.join(self.method_dir, row.method)
|
133
|
+
self.sleepy_send(TableOperation.EDIT_ROW_TEXT.value.format(register=table_register,
|
134
|
+
table_name=table_name,
|
92
135
|
row=row_num,
|
93
136
|
col_name=RegisterFlag.METHOD,
|
94
|
-
val=
|
137
|
+
val=method))
|
95
138
|
|
96
139
|
if row.num_inj:
|
97
|
-
self.sleepy_send(TableOperation.EDIT_ROW_VAL.value.format(register=
|
98
|
-
table_name=
|
140
|
+
self.sleepy_send(TableOperation.EDIT_ROW_VAL.value.format(register=table_register,
|
141
|
+
table_name=table_name,
|
99
142
|
row=row_num,
|
100
143
|
col_name=RegisterFlag.NUM_INJ,
|
101
144
|
val=row.num_inj))
|
102
145
|
|
103
146
|
if row.inj_vol:
|
104
|
-
self.sleepy_send(TableOperation.EDIT_ROW_TEXT.value.format(register=
|
105
|
-
table_name=
|
147
|
+
self.sleepy_send(TableOperation.EDIT_ROW_TEXT.value.format(register=table_register,
|
148
|
+
table_name=table_name,
|
106
149
|
row=row_num,
|
107
150
|
col_name=RegisterFlag.INJ_VOL,
|
108
151
|
val=row.inj_vol))
|
109
152
|
|
110
153
|
if row.inj_source:
|
111
|
-
self.sleepy_send(TableOperation.EDIT_ROW_TEXT.value.format(register=
|
112
|
-
table_name=
|
154
|
+
self.sleepy_send(TableOperation.EDIT_ROW_TEXT.value.format(register=table_register,
|
155
|
+
table_name=table_name,
|
113
156
|
row=row_num,
|
114
157
|
col_name=RegisterFlag.INJ_SOR,
|
115
158
|
val=row.inj_source.value))
|
116
159
|
|
117
160
|
if row.sample_name:
|
118
|
-
self.sleepy_send(TableOperation.EDIT_ROW_TEXT.value.format(register=
|
119
|
-
table_name=
|
161
|
+
self.sleepy_send(TableOperation.EDIT_ROW_TEXT.value.format(register=table_register,
|
162
|
+
table_name=table_name,
|
120
163
|
row=row_num,
|
121
164
|
col_name=RegisterFlag.NAME,
|
122
165
|
val=row.sample_name))
|
123
|
-
self.sleepy_send(TableOperation.EDIT_ROW_TEXT.value.format(register=
|
124
|
-
table_name=
|
166
|
+
self.sleepy_send(TableOperation.EDIT_ROW_TEXT.value.format(register=table_register,
|
167
|
+
table_name=table_name,
|
125
168
|
row=row_num,
|
126
169
|
col_name=RegisterFlag.DATA_FILE,
|
127
170
|
val=row.sample_name))
|
128
171
|
if row.sample_type:
|
129
|
-
self.sleepy_send(TableOperation.EDIT_ROW_VAL.value.format(register=
|
130
|
-
table_name=
|
172
|
+
self.sleepy_send(TableOperation.EDIT_ROW_VAL.value.format(register=table_register,
|
173
|
+
table_name=table_name,
|
131
174
|
row=row_num,
|
132
175
|
col_name=RegisterFlag.SAMPLE_TYPE,
|
133
176
|
val=row.sample_type.value))
|
134
177
|
|
178
|
+
self.send(Command.SAVE_SEQUENCE_CMD)
|
179
|
+
|
135
180
|
def run(self, sequence_table: SequenceTable):
|
136
181
|
"""
|
137
182
|
Starts the currently loaded sequence, storing data
|
@@ -142,29 +187,31 @@ class SequenceController(TableController):
|
|
142
187
|
"""
|
143
188
|
timestamp = time.strftime(SEQUENCE_TIME_FORMAT)
|
144
189
|
self.send(Command.RUN_SEQUENCE_CMD.value)
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
190
|
+
|
191
|
+
if self.check_hplc_is_running():
|
192
|
+
folder_name = f"{sequence_table.name} {timestamp}"
|
193
|
+
self.data_files.append(SequenceDataFiles(dir=folder_name,
|
194
|
+
sequence_name=sequence_table.name, ))
|
195
|
+
|
196
|
+
run_completed = self.check_hplc_done_running()
|
197
|
+
|
198
|
+
if run_completed.is_ok():
|
199
|
+
self.data_files[-1].dir = run_completed.value
|
200
|
+
else:
|
201
|
+
raise RuntimeError("Run error has occured.")
|
154
202
|
|
155
203
|
def retrieve_recent_data_files(self):
|
156
204
|
sequence_data_files: SequenceDataFiles = self.data_files[-1]
|
157
205
|
return os.path.join(sequence_data_files.dir, sequence_data_files.child_dirs[-1])
|
158
206
|
|
159
|
-
def get_data(self) ->
|
160
|
-
data_ready = self.data_ready()
|
207
|
+
def get_data(self) -> list[dict[str, AgilentHPLCChromatogram]]:
|
161
208
|
sequence_data_files: SequenceDataFiles = self.data_files[-1]
|
209
|
+
subdirs = [x[0] for x in os.walk(self.data_dir)]
|
210
|
+
potential_folders = sorted(list(filter(lambda d: sequence_data_files.dir in d, subdirs)))
|
211
|
+
self.data_files[-1].child_dirs = potential_folders
|
162
212
|
spectra: list[dict[str, AgilentHPLCChromatogram]] = []
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
return data_ready, spectra
|
169
|
-
else:
|
170
|
-
return False, None
|
213
|
+
for row in sequence_data_files.child_dirs:
|
214
|
+
data_path = os.path.join(sequence_data_files.dir, row)
|
215
|
+
self.get_spectrum(data_path)
|
216
|
+
spectra.append(deepcopy(self.spectra))
|
217
|
+
return spectra
|
@@ -9,10 +9,11 @@ import os
|
|
9
9
|
from typing import Union, Optional
|
10
10
|
|
11
11
|
import polling
|
12
|
+
from result import Result, Ok, Err
|
12
13
|
|
13
14
|
from ...control import CommunicationController
|
14
15
|
from ...utils.chromatogram import AgilentHPLCChromatogram
|
15
|
-
from ...utils.macro import Command
|
16
|
+
from ...utils.macro import Command, HPLCRunningStatus, Response
|
16
17
|
from ...utils.method_types import MethodTimetable
|
17
18
|
from ...utils.sequence_types import SequenceDataFiles
|
18
19
|
from ...utils.table_types import Table, TableOperation, RegisterFlag
|
@@ -20,8 +21,10 @@ from ...utils.table_types import Table, TableOperation, RegisterFlag
|
|
20
21
|
|
21
22
|
class TableController(abc.ABC):
|
22
23
|
|
23
|
-
def __init__(self, controller: CommunicationController, src: str, data_dir: str):
|
24
|
+
def __init__(self, controller: CommunicationController, src: str, data_dir: str, table: Table):
|
24
25
|
self.controller = controller
|
26
|
+
self.table = table
|
27
|
+
|
25
28
|
if os.path.isdir(src):
|
26
29
|
self.src: str = src
|
27
30
|
else:
|
@@ -32,7 +35,7 @@ class TableController(abc.ABC):
|
|
32
35
|
else:
|
33
36
|
raise FileNotFoundError(f"dir: {data_dir} not found.")
|
34
37
|
|
35
|
-
self.spectra = {
|
38
|
+
self.spectra: dict[str, AgilentHPLCChromatogram] = {
|
36
39
|
"A": AgilentHPLCChromatogram(self.data_dir),
|
37
40
|
"B": AgilentHPLCChromatogram(self.data_dir),
|
38
41
|
"C": AgilentHPLCChromatogram(self.data_dir),
|
@@ -41,8 +44,13 @@ class TableController(abc.ABC):
|
|
41
44
|
|
42
45
|
self.data_files: Union[list[SequenceDataFiles], list[str]] = []
|
43
46
|
|
44
|
-
def receive(self):
|
45
|
-
|
47
|
+
def receive(self) -> Result[Response, str]:
|
48
|
+
for _ in range(10):
|
49
|
+
try:
|
50
|
+
return self.controller.receive()
|
51
|
+
except IndexError:
|
52
|
+
continue
|
53
|
+
return Err("Could not parse response")
|
46
54
|
|
47
55
|
def send(self, cmd: Union[Command, str]):
|
48
56
|
self.controller.send(cmd)
|
@@ -58,7 +66,23 @@ class TableController(abc.ABC):
|
|
58
66
|
"""
|
59
67
|
self.send(Command.SLEEP_CMD.value.format(seconds=seconds))
|
60
68
|
|
61
|
-
def
|
69
|
+
def get_num(self, row: int, col_name: RegisterFlag) -> float:
|
70
|
+
return self.controller.get_num_val(TableOperation.GET_ROW_VAL.value.format(register=self.table.register,
|
71
|
+
table_name=self.table.name,
|
72
|
+
row=row,
|
73
|
+
col_name=col_name.value))
|
74
|
+
|
75
|
+
def get_text(self, row: int, col_name: RegisterFlag) -> str:
|
76
|
+
return self.controller.get_text_val(TableOperation.GET_ROW_TEXT.value.format(register=self.table.register,
|
77
|
+
table_name=self.table.name,
|
78
|
+
row=row,
|
79
|
+
col_name=col_name.value))
|
80
|
+
|
81
|
+
@abc.abstractmethod
|
82
|
+
def get_row(self, row: int):
|
83
|
+
pass
|
84
|
+
|
85
|
+
def add_row(self):
|
62
86
|
"""
|
63
87
|
Adds a row to the provided table for currently loaded method or sequence.
|
64
88
|
Import either the SEQUENCE_TABLE or METHOD_TIMETABLE from hein_analytical_control.constants.
|
@@ -66,10 +90,10 @@ class TableController(abc.ABC):
|
|
66
90
|
|
67
91
|
:param table: the table to add a new row to
|
68
92
|
"""
|
69
|
-
self.sleepy_send(TableOperation.NEW_ROW.value.format(register=table.register,
|
70
|
-
table_name=table.name))
|
93
|
+
self.sleepy_send(TableOperation.NEW_ROW.value.format(register=self.table.register,
|
94
|
+
table_name=self.table.name))
|
71
95
|
|
72
|
-
def delete_table(self
|
96
|
+
def delete_table(self):
|
73
97
|
"""
|
74
98
|
Deletes the table for the current loaded method or sequence.
|
75
99
|
Import either the SEQUENCE_TABLE or METHOD_TIMETABLE from hein_analytical_control.constants.
|
@@ -77,46 +101,62 @@ class TableController(abc.ABC):
|
|
77
101
|
|
78
102
|
:param table: the table to delete
|
79
103
|
"""
|
80
|
-
self.sleepy_send(TableOperation.DELETE_TABLE.value.format(register=table.register,
|
81
|
-
table_name=table.name))
|
104
|
+
self.sleepy_send(TableOperation.DELETE_TABLE.value.format(register=self.table.register,
|
105
|
+
table_name=self.table.name))
|
82
106
|
|
83
|
-
def new_table(self
|
107
|
+
def new_table(self):
|
84
108
|
"""
|
85
109
|
Creates the table for the currently loaded method or sequence. Import either the SEQUENCE_TABLE or
|
86
110
|
METHOD_TIMETABLE from hein_analytical_control.constants. You can also provide your own table.
|
87
111
|
|
88
112
|
:param table: the table to create
|
89
113
|
"""
|
90
|
-
self.send(TableOperation.CREATE_TABLE.value.format(register=table.register,
|
91
|
-
table_name=table.name))
|
92
|
-
|
93
|
-
def
|
94
|
-
self.send(TableOperation.
|
95
|
-
|
96
|
-
|
97
|
-
|
114
|
+
self.send(TableOperation.CREATE_TABLE.value.format(register=self.table.register,
|
115
|
+
table_name=self.table.name))
|
116
|
+
|
117
|
+
def get_num_rows(self) -> Result[int, str]:
|
118
|
+
self.send(TableOperation.GET_NUM_ROWS.value.format(register=self.table.register,
|
119
|
+
table_name=self.table.name,
|
120
|
+
col_name=RegisterFlag.NUM_ROWS))
|
121
|
+
self.send(Command.GET_ROWS_CMD.value.format(register=self.table.register,
|
122
|
+
table_name=self.table.name,
|
123
|
+
col_name=RegisterFlag.NUM_ROWS))
|
98
124
|
res = self.controller.receive()
|
99
|
-
self.send("Sleep 1")
|
100
|
-
self.send('Print Rows')
|
101
|
-
return res
|
102
125
|
|
103
|
-
|
126
|
+
if res.is_ok():
|
127
|
+
self.send("Sleep 1")
|
128
|
+
self.send('Print Rows')
|
129
|
+
return res
|
130
|
+
else:
|
131
|
+
return Err("No rows could be read.")
|
132
|
+
|
133
|
+
def check_hplc_is_running(self) -> bool:
|
134
|
+
started_running = polling.poll(
|
135
|
+
lambda: isinstance(self.controller.get_status(), HPLCRunningStatus),
|
136
|
+
step=30,
|
137
|
+
max_tries=10)
|
138
|
+
return started_running
|
139
|
+
|
140
|
+
def check_hplc_done_running(self, method: Optional[MethodTimetable] = None) -> Result[str, str]:
|
104
141
|
"""
|
105
|
-
Checks if ChemStation has finished
|
142
|
+
Checks if ChemStation has finished running and can read data back
|
106
143
|
|
107
144
|
:param method: if you are running a method and want to read back data, the timeout period will be adjusted to be longer than the method's runtime
|
108
145
|
:return: Return True if data can be read back, else False.
|
109
146
|
"""
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
lambda: self.controller.check_data(self.retrieve_recent_data_files()),
|
147
|
+
timeout = 10 * 60 if method is None else (method.first_row.maximum_run_time + 2) * 60
|
148
|
+
most_recent_folder = self.retrieve_recent_data_files()
|
149
|
+
finished_run = polling.poll(
|
150
|
+
lambda: self.controller.check_if_running(most_recent_folder),
|
115
151
|
timeout=timeout,
|
116
152
|
step=30
|
117
153
|
)
|
118
|
-
|
119
|
-
|
154
|
+
if finished_run:
|
155
|
+
subdirs = [x[0] for x in os.walk(self.data_dir)]
|
156
|
+
potential_folders = sorted(list(filter(lambda d: most_recent_folder in d, subdirs)))
|
157
|
+
return Ok(potential_folders[0])
|
158
|
+
else:
|
159
|
+
return Err("Run did not complete as expected")
|
120
160
|
|
121
161
|
@abc.abstractmethod
|
122
162
|
def retrieve_recent_data_files(self):
|
@@ -132,6 +172,3 @@ class TableController(abc.ABC):
|
|
132
172
|
"""
|
133
173
|
for channel, spec in self.spectra.items():
|
134
174
|
spec.load_spectrum(data_path=data_file, channel=channel)
|
135
|
-
|
136
|
-
def data_ready(self) -> bool:
|
137
|
-
return self.check_hplc_ready_with_data()
|
pychemstation/utils/macro.py
CHANGED
@@ -1,5 +1,12 @@
|
|
1
1
|
from enum import Enum
|
2
2
|
from typing import Union
|
3
|
+
from dataclasses import dataclass
|
4
|
+
|
5
|
+
|
6
|
+
@dataclass
|
7
|
+
class Response:
|
8
|
+
string_response: str
|
9
|
+
num_response: Union[int, float]
|
3
10
|
|
4
11
|
|
5
12
|
# Commands sent to the Chemstation Macro
|
@@ -8,6 +15,8 @@ class Command(Enum):
|
|
8
15
|
def __str__(self):
|
9
16
|
return '%s' % self.value
|
10
17
|
|
18
|
+
GET_NUM_VAL_CMD = "response_num = {cmd}"
|
19
|
+
GET_TEXT_VAL_CMD = "response$ = {cmd}"
|
11
20
|
RESET_COUNTER_CMD = "last_cmd_no = 0"
|
12
21
|
GET_STATUS_CMD = "response$ = AcqStatus$"
|
13
22
|
SLEEP_CMD = "Sleep {seconds}"
|
@@ -19,6 +28,7 @@ class Command(Enum):
|
|
19
28
|
PUMP_ON_CMD = "PumpAll ON"
|
20
29
|
PUMP_OFF_CMD = "PumpAll OFF"
|
21
30
|
GET_METHOD_CMD = "response$ = _MethFile$"
|
31
|
+
GET_ROWS_CMD = 'response_num = TabHdrVal({register}, "{table_name}", "{col_name}")'
|
22
32
|
SWITCH_METHOD_CMD = 'LoadMethod "{method_dir}", "{method_name}.M"'
|
23
33
|
START_METHOD_CMD = "StartMethod"
|
24
34
|
RUN_METHOD_CMD = 'RunMethod "{data_dir}",, "{experiment_name}_{timestamp}"'
|
@@ -26,7 +36,7 @@ class Command(Enum):
|
|
26
36
|
UPDATE_METHOD_CMD = 'UpdateMethod'
|
27
37
|
SWITCH_SEQUENCE_CMD = 'LoadSequence _SeqPath$, _SeqFile$'
|
28
38
|
SAVE_SEQUENCE_CMD = 'SaveSequence _SeqPath$, _SeqFile$'
|
29
|
-
SAVE_METHOD_CMD = 'SaveMethod _MethPath$, _MethFile$, {commit_msg}'
|
39
|
+
SAVE_METHOD_CMD = 'SaveMethod _MethPath$, _MethFile$, "{commit_msg}"'
|
30
40
|
GET_SEQUENCE_CMD = 'response$ = _SeqFile$'
|
31
41
|
RUN_SEQUENCE_CMD = 'RunSequence'
|
32
42
|
|
@@ -22,7 +22,6 @@ class Param:
|
|
22
22
|
class HPLCMethodParams:
|
23
23
|
organic_modifier: int
|
24
24
|
flow: float
|
25
|
-
temperature: float
|
26
25
|
maximum_run_time: int
|
27
26
|
|
28
27
|
|
@@ -30,7 +29,7 @@ class HPLCMethodParams:
|
|
30
29
|
class TimeTableEntry:
|
31
30
|
start_time: float
|
32
31
|
organic_modifer: float
|
33
|
-
flow: float
|
32
|
+
flow: Optional[float] = None
|
34
33
|
|
35
34
|
|
36
35
|
@dataclass
|
@@ -1,19 +1,17 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
1
3
|
from dataclasses import dataclass
|
2
4
|
from enum import Enum
|
3
|
-
from typing import Optional
|
4
|
-
|
5
|
+
from typing import Optional, Union
|
5
6
|
|
6
|
-
|
7
|
-
class TrayLocation:
|
8
|
-
row: str
|
9
|
-
col: int
|
7
|
+
from pychemstation.utils.tray_types import TenColumn
|
10
8
|
|
11
9
|
|
12
10
|
@dataclass
|
13
11
|
class SequenceDataFiles:
|
14
12
|
sequence_name: str
|
15
13
|
dir: str
|
16
|
-
child_dirs: list[str]
|
14
|
+
child_dirs: Optional[list[str]] = None
|
17
15
|
|
18
16
|
|
19
17
|
class SampleType(Enum):
|
@@ -22,6 +20,10 @@ class SampleType(Enum):
|
|
22
20
|
CALIBRATION = 3
|
23
21
|
CONTROL = 4
|
24
22
|
|
23
|
+
@classmethod
|
24
|
+
def _missing_(cls, value):
|
25
|
+
return cls.SAMPLE
|
26
|
+
|
25
27
|
|
26
28
|
class InjectionSource(Enum):
|
27
29
|
AS_METHOD = "As Method"
|
@@ -29,11 +31,15 @@ class InjectionSource(Enum):
|
|
29
31
|
MSD = "MSD"
|
30
32
|
HIP_ALS = "HipAls"
|
31
33
|
|
34
|
+
@classmethod
|
35
|
+
def _missing_(cls, value):
|
36
|
+
return cls.HIP_ALS
|
37
|
+
|
32
38
|
|
33
39
|
@dataclass
|
34
40
|
class SequenceEntry:
|
35
41
|
sample_name: str
|
36
|
-
vial_location: int
|
42
|
+
vial_location: Union[TenColumn, int]
|
37
43
|
method: Optional[str] = None
|
38
44
|
num_inj: Optional[int] = 1
|
39
45
|
inj_vol: Optional[int] = 2
|
@@ -11,10 +11,11 @@ class TableOperation(Enum):
|
|
11
11
|
NEW_ROW = 'InsTabRow {register}, "{table_name}"'
|
12
12
|
EDIT_ROW_VAL = 'SetTabVal "{register}", "{table_name}", {row}, "{col_name}", {val}'
|
13
13
|
EDIT_ROW_TEXT = 'SetTabText "{register}", "{table_name}", {row}, "{col_name}", "{val}"'
|
14
|
-
GET_ROW_VAL = 'TabVal
|
15
|
-
GET_ROW_TEXT = 'TabText
|
16
|
-
|
17
|
-
|
14
|
+
GET_ROW_VAL = 'TabVal("{register}", "{table_name}", {row}, "{col_name}")'
|
15
|
+
GET_ROW_TEXT = 'TabText$("{register}", "{table_name}", {row}, "{col_name}")'
|
16
|
+
GET_NUM_ROWS = 'Rows = TabHdrVal({register}, "{table_name}", "{col_name}")'
|
17
|
+
GET_OBJ_HDR_VAL = 'ObjHdrVal("{register}", "{register_flag}")'
|
18
|
+
GET_OBJ_HDR_TEXT = 'ObjHdrText$("{register}", "{register_flag}")'
|
18
19
|
UPDATE_OBJ_HDR_VAL = 'SetObjHdrVal {register}, {register_flag}, {val}'
|
19
20
|
UPDATE_OBJ_HDR_TEXT = 'SetObjHdrText {register}, {register_flag}, {val}'
|
20
21
|
NEW_COL_TEXT = 'NewColText {register}, "{table_name}", "{col_name}", "{val}"'
|
@@ -39,6 +40,8 @@ class RegisterFlag(Enum):
|
|
39
40
|
COLUMN_OVEN_TEMP2 = "TemperatureControl2_Temperature"
|
40
41
|
STOPTIME_MODE = "StopTime_Mode"
|
41
42
|
POSTIME_MODE = "PostTime_Mode"
|
43
|
+
TIME = "Time"
|
44
|
+
TIMETABLE_SOLVENT_B_COMPOSITION = "SolventCompositionPumpChannel2_Percentage"
|
42
45
|
|
43
46
|
# for Method Timetable
|
44
47
|
SOLVENT_COMPOSITION = "SolventComposition"
|
@@ -0,0 +1,34 @@
|
|
1
|
+
pychemstation/__init__.py,sha256=SpTl-Tg1B1HTyjNOE-8ue-N2wGnXN_2zl7RFUSxlkiM,33
|
2
|
+
pychemstation/analysis/__init__.py,sha256=EWoU47iyn9xGS-b44zK9eq50bSjOV4AC5dvt420YMI4,44
|
3
|
+
pychemstation/analysis/base_spectrum.py,sha256=FBvwzLtF9mdqW7f8ETY9G4cpfJ-SzbiSkZq9EtXcSXo,17045
|
4
|
+
pychemstation/analysis/spec_utils.py,sha256=8NZMV0dtfxZLARjWzM5ks0tgEYQv_SKUiZzba2IoKgw,10505
|
5
|
+
pychemstation/analysis/utils.py,sha256=ISupAOb_yqA4_DZRK9v18UL-XjUQccAicIJKb1VMnGg,2055
|
6
|
+
pychemstation/control/__init__.py,sha256=aH9cPf-ljrVeVhN0K3cyEcAavmPXCjhhOnpLNf8qLqE,106
|
7
|
+
pychemstation/control/comm.py,sha256=19RaKugJ7TbBfW-OM8fHxf90cfXCiDnNnZWPAOiWpGQ,7266
|
8
|
+
pychemstation/control/hplc.py,sha256=r1N8kf5o1kAoY1taALvLJoIxNEbuOYsjwZ8eljrMZRM,6763
|
9
|
+
pychemstation/control/table/__init__.py,sha256=RgMN4uIWHdNUHpGRBWdzmzAbk7XEKl6Y-qtqWCxzSZU,124
|
10
|
+
pychemstation/control/table/method.py,sha256=THVoGomSXff_CTU3eAYme0BYwkPzab5UgZKsiZ29QSk,12196
|
11
|
+
pychemstation/control/table/sequence.py,sha256=iTpk1oiGByut7MSFDHKpTlKUCYzXENOB6EMSKaWJWVY,10651
|
12
|
+
pychemstation/control/table/table_controller.py,sha256=eq9P213Jslr1gJnjZEuvyQ4TpgrxdIXFXHwtQbJkrg0,7131
|
13
|
+
pychemstation/generated/__init__.py,sha256=GAoZFAYbPVEJDkcOw3e1rgOqd7TCW0HyKNPM8OMehMg,1005
|
14
|
+
pychemstation/generated/dad_method.py,sha256=0W8Z5WDtF5jpIcudMqb7XrkTnR2EGg_QOCsHRFQ0rmM,8402
|
15
|
+
pychemstation/generated/pump_method.py,sha256=sUhE2Oo00nzVcoONtq3EMWsN4wLSryXbG8f3EeViWKg,12174
|
16
|
+
pychemstation/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
17
|
+
pychemstation/utils/chromatogram.py,sha256=35nvEh6prVsWO6lMHYgGuidUOFHv954_7MNf0Az3Fz4,3759
|
18
|
+
pychemstation/utils/macro.py,sha256=BAIcE_dppNffwrSqGq8gh0ccE9YAJfQFQZHXJgA1WtA,2586
|
19
|
+
pychemstation/utils/method_types.py,sha256=YngbyHg96JSFnvhm5Zd7wJvLTQPPQsLbvbyz3HlGLYY,862
|
20
|
+
pychemstation/utils/parsing.py,sha256=bnFIsZZwFy9NKzVUf517yN-ogzQbm0hp_aho3KUD6Is,9317
|
21
|
+
pychemstation/utils/sequence_types.py,sha256=3VqiUHsfFEdynAxfR-z8JIWBCo7PdnGwTvsk7sm7Ij8,1055
|
22
|
+
pychemstation/utils/table_types.py,sha256=HAxAsqmyWsCqGwhg4LadGlX6ubacsd8tjXXz-6DL2nI,2287
|
23
|
+
pychemstation/utils/tray_types.py,sha256=UUDED-IAf-8FmPVZezuWSiIQE_HgiZQMV2sTqu4oZw8,177
|
24
|
+
tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
25
|
+
tests/constants.py,sha256=CqahQtWK0NSGIpoCOY_uoN4BwR6TFtaX9wPAkPkG9BE,2074
|
26
|
+
tests/test_comb.py,sha256=IrCqsGEBdrAqoGBQuKiJiaGRW9Ym9UNlVjPA9gc2UrA,5431
|
27
|
+
tests/test_comm.py,sha256=1ZZd0UrIBOKe91wzA-XI-gSRgXmId9mLWYSMeche82Y,2973
|
28
|
+
tests/test_method.py,sha256=uCPpZVYKPz1CNWwhmBo_8TH0ku2V0ZpDZJj3f8iINB4,2440
|
29
|
+
tests/test_sequence.py,sha256=w_WQj97hlaZtcW1Zibzlrq0p179c-4-otM-ik_1EXME,2937
|
30
|
+
pychemstation-0.5.3.dev1.dist-info/LICENSE,sha256=9bdF75gIf1MecZ7oymqWgJREVz7McXPG-mjqrTmzzD8,18658
|
31
|
+
pychemstation-0.5.3.dev1.dist-info/METADATA,sha256=YIbggvShXX-YxNtMFlMXfJIIB0LanjwtYBLz7O5Ttdw,3964
|
32
|
+
pychemstation-0.5.3.dev1.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
|
33
|
+
pychemstation-0.5.3.dev1.dist-info/top_level.txt,sha256=zXfKu_4nYWwPHo3OsuhshMNC3SPkcoTGCyODjURaghY,20
|
34
|
+
pychemstation-0.5.3.dev1.dist-info/RECORD,,
|