pychemstation 0.5.2__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 +12 -8
- pychemstation/utils/table_types.py +7 -4
- pychemstation/utils/tray_types.py +14 -0
- {pychemstation-0.5.2.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.2.dist-info/RECORD +0 -40
- {pychemstation-0.5.2.dist-info → pychemstation-0.5.3.dev1.dist-info}/LICENSE +0 -0
- {pychemstation-0.5.2.dist-info → pychemstation-0.5.3.dev1.dist-info}/WHEEL +0 -0
- {pychemstation-0.5.2.dist-info → pychemstation-0.5.3.dev1.dist-info}/top_level.txt +0 -0
pychemstation/control/comm.py
CHANGED
@@ -13,7 +13,7 @@ Authors: Alexander Hammer, Hessam Mehr, Lucy Hao
|
|
13
13
|
import os
|
14
14
|
import time
|
15
15
|
|
16
|
-
from
|
16
|
+
from result import Result, Ok, Err
|
17
17
|
from ..utils.macro import *
|
18
18
|
from ..utils.method_types import *
|
19
19
|
|
@@ -23,6 +23,9 @@ class CommunicationController:
|
|
23
23
|
Class that communicates with Agilent using Macros
|
24
24
|
"""
|
25
25
|
|
26
|
+
# maximum command number
|
27
|
+
MAX_CMD_NO = 255
|
28
|
+
|
26
29
|
def __init__(
|
27
30
|
self,
|
28
31
|
comm_dir: str,
|
@@ -48,7 +51,23 @@ class CommunicationController:
|
|
48
51
|
|
49
52
|
self.reset_cmd_counter()
|
50
53
|
|
51
|
-
def
|
54
|
+
def get_num_val(self, cmd: str) -> Union[int, float, Err]:
|
55
|
+
self.send(Command.GET_NUM_VAL_CMD.value.format(cmd=cmd))
|
56
|
+
res = self.receive()
|
57
|
+
if res.is_ok():
|
58
|
+
return res.ok_value.num_response
|
59
|
+
else:
|
60
|
+
raise RuntimeError("Failed to get number.")
|
61
|
+
|
62
|
+
def get_text_val(self, cmd: str) -> str:
|
63
|
+
self.send(Command.GET_TEXT_VAL_CMD.value.format(cmd=cmd))
|
64
|
+
res = self.receive()
|
65
|
+
if res.is_ok():
|
66
|
+
return res.ok_value.string_response
|
67
|
+
else:
|
68
|
+
raise RuntimeError("Failed to get string")
|
69
|
+
|
70
|
+
def get_status(self) -> Union[HPLCRunningStatus, HPLCAvailStatus, HPLCErrorStatus]:
|
52
71
|
"""Get device status(es).
|
53
72
|
|
54
73
|
:return: list of ChemStation's current status
|
@@ -57,33 +76,28 @@ class CommunicationController:
|
|
57
76
|
time.sleep(1)
|
58
77
|
|
59
78
|
try:
|
60
|
-
parsed_response = self.receive().
|
61
|
-
|
62
|
-
self._most_recent_hplc_status
|
63
|
-
return recieved_status
|
79
|
+
parsed_response = self.receive().value.string_response
|
80
|
+
self._most_recent_hplc_status = str_to_status(parsed_response)
|
81
|
+
return self._most_recent_hplc_status
|
64
82
|
except IOError:
|
65
|
-
return
|
83
|
+
return HPLCErrorStatus.NORESPONSE
|
66
84
|
except IndexError:
|
67
|
-
return
|
85
|
+
return HPLCErrorStatus.MALFORMED
|
68
86
|
|
69
87
|
def set_status(self):
|
70
88
|
"""Updates current status of HPLC machine"""
|
71
89
|
self._most_recent_hplc_status = self.get_status()[0]
|
72
90
|
|
73
|
-
def
|
91
|
+
def check_if_running(self, data_path: str) -> bool:
|
74
92
|
"""Checks if HPLC machine is in an available state, meaning a state that data is not being written.
|
75
93
|
|
76
94
|
:return: whether the HPLC machine is in a safe state to retrieve data back."""
|
77
|
-
old_status = self._most_recent_hplc_status
|
78
95
|
self.set_status()
|
79
96
|
file_exists = os.path.exists(data_path)
|
80
|
-
|
81
|
-
|
97
|
+
hplc_avail = isinstance(self._most_recent_hplc_status, HPLCAvailStatus)
|
98
|
+
done_writing_data = hplc_avail and file_exists
|
82
99
|
return done_writing_data
|
83
100
|
|
84
|
-
def check_data(self, data_path: str) -> bool:
|
85
|
-
return self._check_data_status(data_path)
|
86
|
-
|
87
101
|
def _send(self, cmd: str, cmd_no: int, num_attempts=5) -> None:
|
88
102
|
"""Low-level execution primitive. Sends a command string to HPLC.
|
89
103
|
|
@@ -106,13 +120,13 @@ class CommunicationController:
|
|
106
120
|
else:
|
107
121
|
raise IOError(f"Failed to send command #{cmd_no}: {cmd}.") from err
|
108
122
|
|
109
|
-
def _receive(self, cmd_no: int, num_attempts=100) -> str:
|
123
|
+
def _receive(self, cmd_no: int, num_attempts=100) -> Result[str, str]:
|
110
124
|
"""Low-level execution primitive. Recives a response from HPLC.
|
111
125
|
|
112
126
|
:param cmd_no: Command number
|
113
127
|
:param num_attempts: Number of retries to open reply file
|
114
128
|
:raises IOError: Could not read reply file.
|
115
|
-
:return: ChemStation response
|
129
|
+
:return: Potential ChemStation response
|
116
130
|
"""
|
117
131
|
err = None
|
118
132
|
for _ in range(num_attempts):
|
@@ -134,11 +148,11 @@ class CommunicationController:
|
|
134
148
|
|
135
149
|
# check that response corresponds to sent command
|
136
150
|
if response_no == cmd_no:
|
137
|
-
return response
|
151
|
+
return Ok(response)
|
138
152
|
else:
|
139
153
|
continue
|
140
154
|
else:
|
141
|
-
|
155
|
+
return Err(f"Failed to receive reply to command #{cmd_no} due to {err}.")
|
142
156
|
|
143
157
|
def sleepy_send(self, cmd: Union[Command, str]):
|
144
158
|
self.send("Sleep 0.1")
|
@@ -150,24 +164,37 @@ class CommunicationController:
|
|
150
164
|
|
151
165
|
:param cmd: Command to be sent to HPLC
|
152
166
|
"""
|
153
|
-
if self.cmd_no == MAX_CMD_NO:
|
167
|
+
if self.cmd_no == self.MAX_CMD_NO:
|
154
168
|
self.reset_cmd_counter()
|
155
169
|
|
156
170
|
cmd_to_send: str = cmd.value if isinstance(cmd, Command) else cmd
|
157
171
|
self.cmd_no += 1
|
158
172
|
self._send(cmd_to_send, self.cmd_no)
|
159
173
|
|
160
|
-
def receive(self) -> str:
|
174
|
+
def receive(self) -> Result[Response, str]:
|
161
175
|
"""Returns messages received in reply file.
|
162
176
|
|
163
177
|
:return: ChemStation response
|
164
178
|
"""
|
165
|
-
|
179
|
+
num_response_prefix = "Numerical Responses:"
|
180
|
+
str_response_prefix = "String Responses:"
|
181
|
+
possible_response = self._receive(self.cmd_no)
|
182
|
+
if Ok(possible_response):
|
183
|
+
lines = possible_response.value.splitlines()
|
184
|
+
for line in lines:
|
185
|
+
if str_response_prefix in line and num_response_prefix in line:
|
186
|
+
string_responses_dirty, _, numerical_responses = line.partition(num_response_prefix)
|
187
|
+
_, _, string_responses = string_responses_dirty.partition(str_response_prefix)
|
188
|
+
return Ok(Response(string_response=string_responses.strip(),
|
189
|
+
num_response=float(numerical_responses.strip())))
|
190
|
+
return Err(f"Could not retrieve HPLC response")
|
191
|
+
else:
|
192
|
+
return Err(f"Could not establish response to HPLC: {possible_response}")
|
166
193
|
|
167
194
|
def reset_cmd_counter(self):
|
168
195
|
"""Resets the command counter."""
|
169
|
-
self._send(Command.RESET_COUNTER_CMD.value, cmd_no=MAX_CMD_NO + 1)
|
170
|
-
self._receive(cmd_no=MAX_CMD_NO + 1)
|
196
|
+
self._send(Command.RESET_COUNTER_CMD.value, cmd_no=self.MAX_CMD_NO + 1)
|
197
|
+
self._receive(cmd_no=self.MAX_CMD_NO + 1)
|
171
198
|
self.cmd_no = 0
|
172
199
|
|
173
200
|
def stop_macro(self):
|
pychemstation/control/hplc.py
CHANGED
@@ -9,12 +9,24 @@ from typing import Union, Optional
|
|
9
9
|
from ..control import CommunicationController
|
10
10
|
from ..control.table import MethodController, SequenceController
|
11
11
|
from ..utils.chromatogram import AgilentHPLCChromatogram
|
12
|
-
from ..utils.macro import Command, HPLCRunningStatus, HPLCAvailStatus, HPLCErrorStatus
|
12
|
+
from ..utils.macro import Command, HPLCRunningStatus, HPLCAvailStatus, HPLCErrorStatus, Response
|
13
13
|
from ..utils.method_types import MethodTimetable
|
14
14
|
from ..utils.sequence_types import SequenceTable, SequenceEntry
|
15
|
+
from ..utils.table_types import Table
|
15
16
|
|
16
17
|
|
17
18
|
class HPLCController:
|
19
|
+
# tables
|
20
|
+
METHOD_TIMETABLE = Table(
|
21
|
+
register="RCPMP1Method[1]",
|
22
|
+
name="Timetable"
|
23
|
+
)
|
24
|
+
|
25
|
+
SEQUENCE_TABLE = Table(
|
26
|
+
register="_sequence[1]",
|
27
|
+
name="SeqTable1"
|
28
|
+
)
|
29
|
+
|
18
30
|
def __init__(self,
|
19
31
|
comm_dir: str,
|
20
32
|
data_dir: str,
|
@@ -27,16 +39,23 @@ class HPLCController:
|
|
27
39
|
:raises FileNotFoundError: If either `data_dir`, `method_dir` or `comm_dir` is not a valid directory.
|
28
40
|
"""
|
29
41
|
self.comm = CommunicationController(comm_dir=comm_dir)
|
30
|
-
self.method_controller = MethodController(controller=self.comm,
|
31
|
-
|
42
|
+
self.method_controller = MethodController(controller=self.comm,
|
43
|
+
src=method_dir,
|
44
|
+
data_dir=data_dir,
|
45
|
+
table=self.METHOD_TIMETABLE)
|
46
|
+
self.sequence_controller = SequenceController(controller=self.comm,
|
47
|
+
src=sequence_dir,
|
48
|
+
data_dir=data_dir,
|
49
|
+
table=self.SEQUENCE_TABLE,
|
50
|
+
method_dir=method_dir)
|
32
51
|
|
33
52
|
def send(self, cmd: Union[Command, str]):
|
34
53
|
self.comm.send(cmd)
|
35
54
|
|
36
|
-
def receive(self) ->
|
37
|
-
return self.comm.receive()
|
55
|
+
def receive(self) -> Response:
|
56
|
+
return self.comm.receive().value
|
38
57
|
|
39
|
-
def status(self) ->
|
58
|
+
def status(self) -> Union[HPLCRunningStatus | HPLCAvailStatus | HPLCErrorStatus]:
|
40
59
|
return self.comm.get_status()
|
41
60
|
|
42
61
|
def switch_method(self, method_name: str):
|
@@ -56,7 +75,7 @@ class HPLCController:
|
|
56
75
|
Allows the user to switch between pre-programmed sequences. The sequence name does not need the '.S' extension.
|
57
76
|
For example. for the method named 'mySeq.S', only 'mySeq' is needed.
|
58
77
|
|
59
|
-
:param
|
78
|
+
:param sequence_name: The name of the sequence file
|
60
79
|
"""
|
61
80
|
self.sequence_controller.switch(sequence_name)
|
62
81
|
|
@@ -82,12 +101,13 @@ class HPLCController:
|
|
82
101
|
"""
|
83
102
|
self.sequence_controller.run(sequence_table)
|
84
103
|
|
85
|
-
def edit_method(self, updated_method: MethodTimetable):
|
104
|
+
def edit_method(self, updated_method: MethodTimetable, save: bool = False):
|
86
105
|
"""Updated the currently loaded method in ChemStation with provided values.
|
87
106
|
|
88
107
|
:param updated_method: the method with updated values, to be sent to Chemstation to modify the currently loaded method.
|
108
|
+
:param save:
|
89
109
|
"""
|
90
|
-
self.method_controller.edit(updated_method)
|
110
|
+
self.method_controller.edit(updated_method, save)
|
91
111
|
|
92
112
|
def edit_sequence(self, updated_sequence: SequenceTable):
|
93
113
|
"""
|
@@ -107,23 +127,29 @@ class HPLCController:
|
|
107
127
|
"""
|
108
128
|
self.sequence_controller.edit_row(row, num)
|
109
129
|
|
110
|
-
def get_last_run_method_data(self) ->
|
130
|
+
def get_last_run_method_data(self) -> dict[str, AgilentHPLCChromatogram]:
|
111
131
|
"""
|
112
132
|
Returns the last run method data.
|
113
133
|
"""
|
114
|
-
|
115
|
-
if data_valid:
|
116
|
-
return data
|
117
|
-
return None
|
134
|
+
return self.method_controller.get_data()
|
118
135
|
|
119
|
-
def get_last_run_sequence_data(self) ->
|
136
|
+
def get_last_run_sequence_data(self) -> list[dict[str, AgilentHPLCChromatogram]]:
|
120
137
|
"""
|
121
138
|
Returns data for all rows in the last run sequence data.
|
122
139
|
"""
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
140
|
+
return self.sequence_controller.get_data()
|
141
|
+
|
142
|
+
def load_method(self) -> MethodTimetable:
|
143
|
+
"""
|
144
|
+
Returns the currently loaded method, including its timetable.
|
145
|
+
"""
|
146
|
+
return self.method_controller.load()
|
147
|
+
|
148
|
+
def load_sequence(self) -> SequenceTable:
|
149
|
+
"""
|
150
|
+
Returns the currently loaded sequence.
|
151
|
+
"""
|
152
|
+
return self.sequence_controller.load()
|
127
153
|
|
128
154
|
def standby(self):
|
129
155
|
"""Switches all modules in standby mode. All lamps and pumps are switched off."""
|
@@ -7,11 +7,10 @@ from xsdata.formats.dataclass.parsers import XmlParser
|
|
7
7
|
from .. import CommunicationController
|
8
8
|
from ...control.table.table_controller import TableController
|
9
9
|
from ...generated import PumpMethod, DadMethod, SolventElement
|
10
|
-
from ...utils.chromatogram import TIME_FORMAT
|
11
|
-
from ...utils.constants import METHOD_TIMETABLE
|
10
|
+
from ...utils.chromatogram import TIME_FORMAT, AgilentHPLCChromatogram
|
12
11
|
from ...utils.macro import Command
|
13
12
|
from ...utils.method_types import PType, TimeTableEntry, Param, MethodTimetable, HPLCMethodParams
|
14
|
-
from ...utils.table_types import RegisterFlag, TableOperation
|
13
|
+
from ...utils.table_types import RegisterFlag, TableOperation, Table
|
15
14
|
|
16
15
|
|
17
16
|
class MethodController(TableController):
|
@@ -19,10 +18,46 @@ class MethodController(TableController):
|
|
19
18
|
Class containing method related logic
|
20
19
|
"""
|
21
20
|
|
22
|
-
def __init__(self, controller: CommunicationController, src: str, data_dir: str):
|
23
|
-
super().__init__(controller, src, data_dir)
|
21
|
+
def __init__(self, controller: CommunicationController, src: str, data_dir: str, table: Table):
|
22
|
+
super().__init__(controller, src, data_dir, table)
|
24
23
|
|
25
|
-
def
|
24
|
+
def get_method_params(self) -> HPLCMethodParams:
|
25
|
+
return HPLCMethodParams(organic_modifier=self.controller.get_num_val(
|
26
|
+
cmd=TableOperation.GET_OBJ_HDR_VAL.value.format(
|
27
|
+
register=self.table.register,
|
28
|
+
register_flag=RegisterFlag.SOLVENT_B_COMPOSITION
|
29
|
+
)
|
30
|
+
),
|
31
|
+
flow=self.controller.get_num_val(
|
32
|
+
cmd=TableOperation.GET_OBJ_HDR_VAL.value.format(
|
33
|
+
register=self.table.register,
|
34
|
+
register_flag=RegisterFlag.FLOW
|
35
|
+
)
|
36
|
+
),
|
37
|
+
maximum_run_time=self.controller.get_num_val(
|
38
|
+
cmd=TableOperation.GET_OBJ_HDR_VAL.value.format(
|
39
|
+
register=self.table.register,
|
40
|
+
register_flag=RegisterFlag.MAX_TIME
|
41
|
+
)
|
42
|
+
),
|
43
|
+
)
|
44
|
+
|
45
|
+
def get_row(self, row: int) -> TimeTableEntry:
|
46
|
+
return TimeTableEntry(start_time=self.get_num(row, RegisterFlag.TIME),
|
47
|
+
organic_modifer=self.get_num(row, RegisterFlag.TIMETABLE_SOLVENT_B_COMPOSITION),
|
48
|
+
flow=None)
|
49
|
+
|
50
|
+
def load(self) -> MethodTimetable:
|
51
|
+
rows = self.get_num_rows()
|
52
|
+
if rows.is_ok():
|
53
|
+
timetable_rows = [self.get_row(r + 1) for r in range(int(rows.ok_value.num_response))]
|
54
|
+
return MethodTimetable(
|
55
|
+
first_row=self.get_method_params(),
|
56
|
+
subsequent_rows=timetable_rows)
|
57
|
+
else:
|
58
|
+
raise RuntimeError(rows.err_value)
|
59
|
+
|
60
|
+
def current_method(self, method_name: str):
|
26
61
|
"""
|
27
62
|
Checks if a given method is already loaded into Chemstation. Method name does not need the ".M" extension.
|
28
63
|
|
@@ -30,7 +65,7 @@ class MethodController(TableController):
|
|
30
65
|
:return: True if method is already loaded
|
31
66
|
"""
|
32
67
|
self.send(Command.GET_METHOD_CMD)
|
33
|
-
parsed_response = self.receive()
|
68
|
+
parsed_response = self.receive()
|
34
69
|
return method_name in parsed_response
|
35
70
|
|
36
71
|
def switch(self, method_name: str):
|
@@ -49,18 +84,12 @@ class MethodController(TableController):
|
|
49
84
|
time.sleep(2)
|
50
85
|
self.send(Command.GET_METHOD_CMD)
|
51
86
|
time.sleep(2)
|
87
|
+
res = self.receive()
|
88
|
+
if res.is_ok():
|
89
|
+
parsed_response = res.ok_value.string_response
|
90
|
+
assert parsed_response == f"{method_name}.M", "Switching Methods failed."
|
52
91
|
|
53
|
-
|
54
|
-
for _ in range(10):
|
55
|
-
try:
|
56
|
-
parsed_response = self.receive().splitlines()[1].split()[1:][0]
|
57
|
-
break
|
58
|
-
except IndexError:
|
59
|
-
continue
|
60
|
-
|
61
|
-
assert parsed_response == f"{method_name}.M", "Switching Methods failed."
|
62
|
-
|
63
|
-
def load(self, method_name: str):
|
92
|
+
def load_from_disk(self, method_name: str) -> MethodTimetable:
|
64
93
|
"""
|
65
94
|
Retrieve method details of an existing method. Don't need to append ".M" to the end. This assumes the
|
66
95
|
organic modifier is in Channel B and that Channel A contains the aq layer. Additionally, assumes
|
@@ -91,25 +120,10 @@ class MethodController(TableController):
|
|
91
120
|
|
92
121
|
return MethodTimetable(
|
93
122
|
first_row=HPLCMethodParams(
|
94
|
-
organic_modifier=
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
chemstation_key=RegisterFlag.FLOW,
|
99
|
-
ptype=PType.NUM),
|
100
|
-
maximum_run_time=Param(val=method.stop_time,
|
101
|
-
chemstation_key=RegisterFlag.MAX_TIME,
|
102
|
-
ptype=PType.NUM),
|
103
|
-
temperature=Param(val=None,
|
104
|
-
chemstation_key=[RegisterFlag.COLUMN_OVEN_TEMP1,
|
105
|
-
RegisterFlag.COLUMN_OVEN_TEMP2],
|
106
|
-
ptype=PType.NUM),
|
107
|
-
inj_vol=Param(val=None,
|
108
|
-
chemstation_key=None,
|
109
|
-
ptype=PType.NUM),
|
110
|
-
equ_time=Param(val=None,
|
111
|
-
chemstation_key=None,
|
112
|
-
ptype=PType.NUM)),
|
123
|
+
organic_modifier=organic_modifier.percentage,
|
124
|
+
flow=method.flow,
|
125
|
+
maximum_run_time=method.stop_time,
|
126
|
+
temperature=-1),
|
113
127
|
subsequent_rows=[
|
114
128
|
TimeTableEntry(
|
115
129
|
start_time=tte.time,
|
@@ -124,7 +138,7 @@ class MethodController(TableController):
|
|
124
138
|
else:
|
125
139
|
raise FileNotFoundError
|
126
140
|
|
127
|
-
def edit(self, updated_method: MethodTimetable):
|
141
|
+
def edit(self, updated_method: MethodTimetable, save: bool):
|
128
142
|
"""Updated the currently loaded method in ChemStation with provided values.
|
129
143
|
|
130
144
|
:param updated_method: the method with updated values, to be sent to Chemstation to modify the currently loaded method.
|
@@ -138,13 +152,9 @@ class MethodController(TableController):
|
|
138
152
|
flow: Param = Param(val=updated_method.first_row.flow,
|
139
153
|
chemstation_key=RegisterFlag.FLOW,
|
140
154
|
ptype=PType.NUM)
|
141
|
-
temperature: Param = Param(val=updated_method.first_row.temperature,
|
142
|
-
chemstation_key=[RegisterFlag.COLUMN_OVEN_TEMP1,
|
143
|
-
RegisterFlag.COLUMN_OVEN_TEMP2],
|
144
|
-
ptype=PType.NUM)
|
145
155
|
|
146
156
|
# Method settings required for all runs
|
147
|
-
self.delete_table(
|
157
|
+
self.delete_table()
|
148
158
|
self._update_param(initial_organic_modifier)
|
149
159
|
self._update_param(flow)
|
150
160
|
self._update_param(Param(val="Set",
|
@@ -159,18 +169,23 @@ class MethodController(TableController):
|
|
159
169
|
|
160
170
|
self._update_method_timetable(updated_method.subsequent_rows)
|
161
171
|
|
172
|
+
if save:
|
173
|
+
self.send(Command.SAVE_METHOD_CMD.value.format(
|
174
|
+
commit_msg=f"saved method at {str(time.time())}"
|
175
|
+
))
|
176
|
+
|
162
177
|
def _update_method_timetable(self, timetable_rows: list[TimeTableEntry]):
|
163
178
|
self.sleepy_send('Local Rows')
|
164
|
-
self.
|
179
|
+
self.get_num_rows()
|
165
180
|
|
166
181
|
self.sleepy_send('DelTab RCPMP1Method[1], "Timetable"')
|
167
|
-
res = self.
|
168
|
-
while
|
182
|
+
res = self.get_num_rows()
|
183
|
+
while not res.is_err():
|
169
184
|
self.sleepy_send('DelTab RCPMP1Method[1], "Timetable"')
|
170
|
-
res = self.
|
185
|
+
res = self.get_num_rows()
|
171
186
|
|
172
187
|
self.sleepy_send('NewTab RCPMP1Method[1], "Timetable"')
|
173
|
-
self.
|
188
|
+
self.get_num_rows()
|
174
189
|
|
175
190
|
for i, row in enumerate(timetable_rows):
|
176
191
|
if i == 0:
|
@@ -188,7 +203,7 @@ class MethodController(TableController):
|
|
188
203
|
self.send('Sleep 1')
|
189
204
|
else:
|
190
205
|
self.sleepy_send('InsTabRow RCPMP1Method[1], "Timetable"')
|
191
|
-
self.
|
206
|
+
self.get_num_rows()
|
192
207
|
|
193
208
|
self.sleepy_send(
|
194
209
|
f'SetTabText RCPMP1Method[1], "Timetable", Rows, "Function", "SolventComposition"')
|
@@ -200,7 +215,7 @@ class MethodController(TableController):
|
|
200
215
|
self.send("Sleep 1")
|
201
216
|
self.sleepy_send("DownloadRCMethod PMP1")
|
202
217
|
self.send("Sleep 1")
|
203
|
-
self.
|
218
|
+
self.get_num_rows()
|
204
219
|
|
205
220
|
def _update_param(self, method_param: Param):
|
206
221
|
"""Change a method parameter, changes what is visibly seen in Chemstation GUI.
|
@@ -208,7 +223,7 @@ class MethodController(TableController):
|
|
208
223
|
|
209
224
|
:param method_param: a parameter to update for currently loaded method.
|
210
225
|
"""
|
211
|
-
register =
|
226
|
+
register = self.table.register
|
212
227
|
setting_command = TableOperation.UPDATE_OBJ_HDR_VAL if method_param.ptype == PType.NUM else TableOperation.UPDATE_OBJ_HDR_TEXT
|
213
228
|
if isinstance(method_param.chemstation_key, list):
|
214
229
|
for register_flag in method_param.chemstation_key:
|
@@ -238,21 +253,22 @@ class MethodController(TableController):
|
|
238
253
|
:param experiment_name: Name of the experiment
|
239
254
|
"""
|
240
255
|
timestamp = time.strftime(TIME_FORMAT)
|
241
|
-
|
242
256
|
self.send(Command.RUN_METHOD_CMD.value.format(data_dir=self.data_dir,
|
243
257
|
experiment_name=experiment_name,
|
244
258
|
timestamp=timestamp))
|
245
259
|
|
246
|
-
|
247
|
-
|
260
|
+
if self.check_hplc_is_running():
|
261
|
+
folder_name = f"{experiment_name}_{timestamp}.D"
|
262
|
+
self.data_files.append(os.path.join(self.data_dir, folder_name))
|
263
|
+
|
264
|
+
run_completed = self.check_hplc_done_running()
|
265
|
+
|
266
|
+
if not run_completed.is_ok():
|
267
|
+
raise RuntimeError("Run did not complete as expected")
|
248
268
|
|
249
269
|
def retrieve_recent_data_files(self) -> str:
|
250
270
|
return self.data_files[-1]
|
251
271
|
|
252
|
-
def get_data(self) ->
|
253
|
-
|
254
|
-
|
255
|
-
self.get_spectrum(self.data_files[-1])
|
256
|
-
return data_ready, self.spectra
|
257
|
-
else:
|
258
|
-
return False, None
|
272
|
+
def get_data(self) -> dict[str, AgilentHPLCChromatogram]:
|
273
|
+
self.get_spectrum(self.data_files[-1])
|
274
|
+
return self.spectra
|