pychemstation 0.5.9__tar.gz → 0.5.10__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {pychemstation-0.5.9 → pychemstation-0.5.10}/PKG-INFO +1 -1
- {pychemstation-0.5.9 → pychemstation-0.5.10}/pychemstation/control/controllers/method.py +130 -107
- {pychemstation-0.5.9 → pychemstation-0.5.10}/pychemstation/control/controllers/sequence.py +15 -48
- {pychemstation-0.5.9 → pychemstation-0.5.10}/pychemstation/control/controllers/table_controller.py +56 -6
- {pychemstation-0.5.9 → pychemstation-0.5.10}/pychemstation/control/hplc.py +30 -44
- {pychemstation-0.5.9 → pychemstation-0.5.10}/pychemstation/utils/macro.py +6 -0
- pychemstation-0.5.10/pychemstation/utils/method_types.py +52 -0
- {pychemstation-0.5.9 → pychemstation-0.5.10}/pychemstation/utils/sequence_types.py +2 -2
- {pychemstation-0.5.9 → pychemstation-0.5.10}/pychemstation/utils/table_types.py +3 -0
- pychemstation-0.5.10/pychemstation/utils/tray_types.py +50 -0
- {pychemstation-0.5.9 → pychemstation-0.5.10}/pychemstation.egg-info/PKG-INFO +1 -1
- {pychemstation-0.5.9 → pychemstation-0.5.10}/setup.py +1 -1
- {pychemstation-0.5.9 → pychemstation-0.5.10}/tests/constants.py +15 -16
- {pychemstation-0.5.9 → pychemstation-0.5.10}/tests/test_comb.py +37 -44
- {pychemstation-0.5.9 → pychemstation-0.5.10}/tests/test_comm.py +1 -14
- {pychemstation-0.5.9 → pychemstation-0.5.10}/tests/test_method.py +7 -7
- {pychemstation-0.5.9 → pychemstation-0.5.10}/tests/test_sequence.py +7 -7
- pychemstation-0.5.9/pychemstation/utils/method_types.py +0 -43
- pychemstation-0.5.9/pychemstation/utils/tray_types.py +0 -14
- {pychemstation-0.5.9 → pychemstation-0.5.10}/LICENSE +0 -0
- {pychemstation-0.5.9 → pychemstation-0.5.10}/README.md +0 -0
- {pychemstation-0.5.9 → pychemstation-0.5.10}/pychemstation/__init__.py +0 -0
- {pychemstation-0.5.9 → pychemstation-0.5.10}/pychemstation/analysis/__init__.py +0 -0
- {pychemstation-0.5.9 → pychemstation-0.5.10}/pychemstation/analysis/base_spectrum.py +0 -0
- {pychemstation-0.5.9 → pychemstation-0.5.10}/pychemstation/analysis/spec_utils.py +0 -0
- {pychemstation-0.5.9 → pychemstation-0.5.10}/pychemstation/analysis/utils.py +0 -0
- {pychemstation-0.5.9 → pychemstation-0.5.10}/pychemstation/control/__init__.py +0 -0
- {pychemstation-0.5.9 → pychemstation-0.5.10}/pychemstation/control/controllers/__init__.py +0 -0
- {pychemstation-0.5.9 → pychemstation-0.5.10}/pychemstation/control/controllers/comm.py +0 -0
- {pychemstation-0.5.9 → pychemstation-0.5.10}/pychemstation/generated/__init__.py +0 -0
- {pychemstation-0.5.9 → pychemstation-0.5.10}/pychemstation/generated/dad_method.py +0 -0
- {pychemstation-0.5.9 → pychemstation-0.5.10}/pychemstation/generated/pump_method.py +0 -0
- {pychemstation-0.5.9 → pychemstation-0.5.10}/pychemstation/utils/__init__.py +0 -0
- {pychemstation-0.5.9 → pychemstation-0.5.10}/pychemstation/utils/chromatogram.py +0 -0
- {pychemstation-0.5.9 → pychemstation-0.5.10}/pychemstation/utils/parsing.py +0 -0
- {pychemstation-0.5.9 → pychemstation-0.5.10}/pychemstation.egg-info/SOURCES.txt +0 -0
- {pychemstation-0.5.9 → pychemstation-0.5.10}/pychemstation.egg-info/dependency_links.txt +0 -0
- {pychemstation-0.5.9 → pychemstation-0.5.10}/pychemstation.egg-info/requires.txt +0 -0
- {pychemstation-0.5.9 → pychemstation-0.5.10}/pychemstation.egg-info/top_level.txt +0 -0
- {pychemstation-0.5.9 → pychemstation-0.5.10}/pyproject.toml +0 -0
- {pychemstation-0.5.9 → pychemstation-0.5.10}/setup.cfg +0 -0
- {pychemstation-0.5.9 → pychemstation-0.5.10}/tests/__init__.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
import os
|
2
2
|
import time
|
3
|
-
from typing import Optional
|
3
|
+
from typing import Optional, Union
|
4
4
|
|
5
5
|
from xsdata.formats.dataclass.parsers import XmlParser
|
6
6
|
|
@@ -9,7 +9,7 @@ from ...control.controllers.comm import CommunicationController
|
|
9
9
|
from ...generated import PumpMethod, DadMethod, SolventElement
|
10
10
|
from ...utils.chromatogram import TIME_FORMAT, AgilentChannelChromatogramData
|
11
11
|
from ...utils.macro import Command
|
12
|
-
from ...utils.method_types import PType, TimeTableEntry, Param,
|
12
|
+
from ...utils.method_types import PType, TimeTableEntry, Param, MethodDetails, HPLCMethodParams
|
13
13
|
from ...utils.table_types import RegisterFlag, TableOperation, Table
|
14
14
|
|
15
15
|
|
@@ -43,30 +43,53 @@ class MethodController(TableController):
|
|
43
43
|
register_flag=RegisterFlag.FLOW
|
44
44
|
)
|
45
45
|
),
|
46
|
-
maximum_run_time=self.controller.get_num_val(
|
47
|
-
cmd=TableOperation.GET_OBJ_HDR_VAL.value.format(
|
48
|
-
register=self.table.register,
|
49
|
-
register_flag=RegisterFlag.MAX_TIME
|
50
|
-
)
|
51
|
-
),
|
52
46
|
)
|
53
47
|
|
54
48
|
def get_row(self, row: int) -> TimeTableEntry:
|
55
49
|
return TimeTableEntry(start_time=self.get_num(row, RegisterFlag.TIME),
|
56
50
|
organic_modifer=self.get_num(row, RegisterFlag.TIMETABLE_SOLVENT_B_COMPOSITION),
|
57
|
-
flow=
|
58
|
-
|
59
|
-
def
|
51
|
+
flow=self.get_num(row, RegisterFlag.TIMETABLE_FLOW))
|
52
|
+
|
53
|
+
def get_timetable(self, rows: int):
|
54
|
+
uncoalesced_timetable_rows = [self.get_row(r + 1) for r in range(rows)]
|
55
|
+
timetable_rows = {}
|
56
|
+
for row in uncoalesced_timetable_rows:
|
57
|
+
time_key = str(row.start_time)
|
58
|
+
if time_key not in timetable_rows.keys():
|
59
|
+
timetable_rows[time_key] = TimeTableEntry(start_time=row.start_time,
|
60
|
+
flow=row.flow,
|
61
|
+
organic_modifer=row.organic_modifer)
|
62
|
+
else:
|
63
|
+
if row.flow:
|
64
|
+
timetable_rows[time_key].flow = row.flow
|
65
|
+
if row.organic_modifer:
|
66
|
+
timetable_rows[time_key].organic_modifer = row.organic_modifer
|
67
|
+
entries = list(timetable_rows.values())
|
68
|
+
entries.sort(key=lambda e: e.start_time)
|
69
|
+
return entries
|
70
|
+
|
71
|
+
def load(self) -> MethodDetails:
|
60
72
|
rows = self.get_num_rows()
|
61
73
|
if rows.is_ok():
|
62
74
|
self.send(Command.GET_METHOD_CMD)
|
63
75
|
res = self.receive()
|
64
76
|
method_name = res.ok_value.string_response
|
65
|
-
timetable_rows =
|
66
|
-
|
77
|
+
timetable_rows = self.get_timetable(int(rows.ok_value.num_response))
|
78
|
+
params = self.get_method_params()
|
79
|
+
stop_time = self.controller.get_num_val(
|
80
|
+
cmd=TableOperation.GET_OBJ_HDR_VAL.value.format(
|
81
|
+
register=self.table.register,
|
82
|
+
register_flag=RegisterFlag.MAX_TIME))
|
83
|
+
post_time = self.controller.get_num_val(
|
84
|
+
cmd=TableOperation.GET_OBJ_HDR_VAL.value.format(
|
85
|
+
register=self.table.register,
|
86
|
+
register_flag=RegisterFlag.POST_TIME))
|
87
|
+
self.table_state = MethodDetails(
|
67
88
|
name=method_name,
|
68
|
-
|
69
|
-
|
89
|
+
timetable=timetable_rows,
|
90
|
+
stop_time=stop_time,
|
91
|
+
post_time=post_time,
|
92
|
+
params=params)
|
70
93
|
return self.table_state
|
71
94
|
else:
|
72
95
|
raise RuntimeError(rows.err_value)
|
@@ -104,7 +127,7 @@ class MethodController(TableController):
|
|
104
127
|
assert parsed_response == f"{method_name}.M", "Switching Methods failed."
|
105
128
|
self.table_state = None
|
106
129
|
|
107
|
-
def load_from_disk(self, method_name: str) ->
|
130
|
+
def load_from_disk(self, method_name: str) -> MethodDetails:
|
108
131
|
"""
|
109
132
|
Retrieve method details of an existing method. Don't need to append ".M" to the end. This assumes the
|
110
133
|
organic modifier is in Channel B and that Channel A contains the aq layer. Additionally, assumes
|
@@ -133,120 +156,69 @@ class MethodController(TableController):
|
|
133
156
|
elif solvent.channel == "Channel_B":
|
134
157
|
organic_modifier = solvent
|
135
158
|
|
136
|
-
self.table_state =
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
],
|
148
|
-
dad_wavelengthes=dad.signals.signal,
|
149
|
-
organic_modifier=organic_modifier,
|
150
|
-
modifier_a=aq_modifier
|
151
|
-
)
|
159
|
+
self.table_state = MethodDetails(
|
160
|
+
name=method_name,
|
161
|
+
params=HPLCMethodParams(organic_modifier=organic_modifier.percentage,
|
162
|
+
flow=method.flow),
|
163
|
+
stop_time=method.stop_time.stop_time_value,
|
164
|
+
post_time=method.post_time.post_time_value,
|
165
|
+
timetable=[TimeTableEntry(start_time=tte.time,
|
166
|
+
organic_modifer=tte.percent_b,
|
167
|
+
flow=method.flow
|
168
|
+
) for tte in method.timetable.timetable_entry],
|
169
|
+
dad_wavelengthes=dad.signals.signal)
|
152
170
|
return self.table_state
|
153
171
|
else:
|
154
172
|
raise FileNotFoundError
|
155
173
|
|
156
|
-
def edit(self, updated_method:
|
174
|
+
def edit(self, updated_method: MethodDetails, save: bool):
|
157
175
|
"""Updated the currently loaded method in ChemStation with provided values.
|
158
176
|
|
159
177
|
:param updated_method: the method with updated values, to be sent to Chemstation to modify the currently loaded method.
|
178
|
+
:param save: if false only modifies the method, otherwise saves to disk
|
160
179
|
"""
|
161
180
|
self.table_state = updated_method
|
162
|
-
initial_organic_modifier: Param = Param(val=updated_method.
|
181
|
+
initial_organic_modifier: Param = Param(val=updated_method.params.organic_modifier,
|
163
182
|
chemstation_key=RegisterFlag.SOLVENT_B_COMPOSITION,
|
164
183
|
ptype=PType.NUM)
|
165
|
-
max_time: Param = Param(val=updated_method.
|
184
|
+
max_time: Param = Param(val=updated_method.stop_time,
|
166
185
|
chemstation_key=RegisterFlag.MAX_TIME,
|
167
186
|
ptype=PType.NUM)
|
168
|
-
|
187
|
+
post_time: Param = Param(val=updated_method.post_time,
|
188
|
+
chemstation_key=RegisterFlag.POST_TIME,
|
189
|
+
ptype=PType.NUM) # TODO check postime works
|
190
|
+
flow: Param = Param(val=updated_method.params.flow,
|
169
191
|
chemstation_key=RegisterFlag.FLOW,
|
170
192
|
ptype=PType.NUM)
|
171
193
|
|
172
194
|
# Method settings required for all runs
|
173
|
-
self.
|
174
|
-
self.
|
175
|
-
self._update_param(flow)
|
176
|
-
self._update_param(Param(val="Set",
|
177
|
-
chemstation_key=RegisterFlag.STOPTIME_MODE,
|
178
|
-
ptype=PType.STR))
|
179
|
-
self._update_param(max_time)
|
180
|
-
self._update_param(Param(val="Off",
|
181
|
-
chemstation_key=RegisterFlag.POSTIME_MODE,
|
182
|
-
ptype=PType.STR))
|
183
|
-
|
184
|
-
self.send("DownloadRCMethod PMP1")
|
185
|
-
|
186
|
-
self._update_method_timetable(updated_method.subsequent_rows)
|
195
|
+
self.update_method_params(flow, initial_organic_modifier, max_time, post_time)
|
196
|
+
self._update_method_timetable(updated_method.timetable)
|
187
197
|
|
188
198
|
if save:
|
189
199
|
self.send(Command.SAVE_METHOD_CMD.value.format(
|
190
200
|
commit_msg=f"saved method at {str(time.time())}"
|
191
201
|
))
|
192
202
|
|
193
|
-
def
|
194
|
-
self.
|
195
|
-
self.
|
196
|
-
|
197
|
-
self.
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
self.sleepy_send('NewColText RCPMP1Method[1], "Timetable", "Function", "SolventComposition"')
|
213
|
-
self.sleepy_send(f'NewColVal RCPMP1Method[1], "Timetable", "Time", {row.start_time}')
|
214
|
-
self.sleepy_send(
|
215
|
-
f'NewColVal RCPMP1Method[1], "Timetable", "SolventCompositionPumpChannel2_Percentage", {row.organic_modifer}')
|
216
|
-
|
217
|
-
self.sleepy_send('InsTabRow RCPMP1Method[1], "Timetable"')
|
218
|
-
self.sleepy_send('SetTabText RCPMP1Method[1], "Timetable", 2, "Function", "Flow"')
|
219
|
-
self.sleepy_send(f'NewColVal RCPMP1Method[1], "Timetable", "FlowFlow", {row.flow}')
|
220
|
-
self.sleepy_send(f'SetTabVal RCPMP1Method[1], "Timetable", 2, "FlowFlow", {row.flow})')
|
221
|
-
|
222
|
-
self.send('Sleep 1')
|
223
|
-
self.sleepy_send("DownloadRCMethod PMP1")
|
224
|
-
self.send('Sleep 1')
|
225
|
-
else:
|
226
|
-
self.sleepy_send('InsTabRow RCPMP1Method[1], "Timetable"')
|
227
|
-
self.get_num_rows()
|
228
|
-
|
229
|
-
self.sleepy_send(
|
230
|
-
f'SetTabText RCPMP1Method[1], "Timetable", Rows, "Function", "SolventComposition"')
|
231
|
-
self.sleepy_send(
|
232
|
-
f'SetTabVal RCPMP1Method[1], "Timetable", Rows, "Time", {row.start_time}')
|
233
|
-
self.sleepy_send(
|
234
|
-
f'SetTabVal RCPMP1Method[1], "Timetable", Rows, "SolventCompositionPumpChannel2_Percentage", {row.organic_modifer}')
|
235
|
-
|
236
|
-
self.send("Sleep 1")
|
237
|
-
self.sleepy_send("DownloadRCMethod PMP1")
|
238
|
-
self.send("Sleep 1")
|
239
|
-
|
240
|
-
self.sleepy_send('InsTabRow RCPMP1Method[1], "Timetable"')
|
241
|
-
self.get_num_rows()
|
242
|
-
|
243
|
-
self.sleepy_send('SetTabText RCPMP1Method[1], "Timetable", Rows , "Function", "Flow"')
|
244
|
-
self.sleepy_send(f'SetTabVal RCPMP1Method[1], "Timetable", Rows , "FlowFlow", {row.flow}')
|
245
|
-
self.sleepy_send(f'SetTabVal RCPMP1Method[1], "Timetable", Rows , "Time", {row.start_time}')
|
246
|
-
|
247
|
-
self.send("Sleep 1")
|
248
|
-
self.sleepy_send("DownloadRCMethod PMP1")
|
249
|
-
self.send("Sleep 1")
|
203
|
+
def update_method_params(self, flow, initial_organic_modifier, max_time, post_time):
|
204
|
+
self.delete_table()
|
205
|
+
self._update_param(initial_organic_modifier)
|
206
|
+
self._update_param(flow)
|
207
|
+
if self.table_state.stop_time:
|
208
|
+
self._update_param(Param(val="Set",
|
209
|
+
chemstation_key=RegisterFlag.STOPTIME_MODE,
|
210
|
+
ptype=PType.STR))
|
211
|
+
self._update_param(max_time)
|
212
|
+
else:
|
213
|
+
self._update_param(Param(val="Off",
|
214
|
+
chemstation_key=RegisterFlag.STOPTIME_MODE,
|
215
|
+
ptype=PType.STR))
|
216
|
+
if self.table_state.post_time:
|
217
|
+
self._update_param(Param(val="Set",
|
218
|
+
chemstation_key=RegisterFlag.POSTIME_MODE,
|
219
|
+
ptype=PType.STR))
|
220
|
+
self._update_param(post_time)
|
221
|
+
self.download()
|
250
222
|
|
251
223
|
def _update_param(self, method_param: Param):
|
252
224
|
"""Change a method parameter, changes what is visibly seen in Chemstation GUI.
|
@@ -267,6 +239,57 @@ class MethodController(TableController):
|
|
267
239
|
val=method_param.val))
|
268
240
|
time.sleep(2)
|
269
241
|
|
242
|
+
def download(self):
|
243
|
+
self.send('Sleep 1')
|
244
|
+
self.sleepy_send("DownloadRCMethod PMP1")
|
245
|
+
self.send('Sleep 1')
|
246
|
+
|
247
|
+
def edit_row(self, row: TimeTableEntry, first_row: bool = False):
|
248
|
+
if first_row:
|
249
|
+
self.add_row()
|
250
|
+
self.add_new_col_text(col_name=RegisterFlag.FUNCTION,
|
251
|
+
val=RegisterFlag.SOLVENT_COMPOSITION.value)
|
252
|
+
self.add_new_col_num(col_name=RegisterFlag.TIME, val=row.start_time)
|
253
|
+
self.add_new_col_num(col_name=RegisterFlag.TIMETABLE_SOLVENT_B_COMPOSITION,
|
254
|
+
val=row.organic_modifer)
|
255
|
+
self.add_row()
|
256
|
+
self.get_num_rows()
|
257
|
+
self.edit_row_text(col_name=RegisterFlag.FUNCTION, val=RegisterFlag.FLOW.value)
|
258
|
+
self.add_new_col_num(col_name=RegisterFlag.TIMETABLE_FLOW, val=row.flow)
|
259
|
+
self.edit_row_num(col_name=RegisterFlag.TIMETABLE_FLOW, val=row.flow)
|
260
|
+
self.download()
|
261
|
+
else:
|
262
|
+
self.add_row()
|
263
|
+
self.get_num_rows()
|
264
|
+
self.edit_row_text(col_name=RegisterFlag.FUNCTION,
|
265
|
+
val=RegisterFlag.SOLVENT_COMPOSITION.value)
|
266
|
+
self.edit_row_num(col_name=RegisterFlag.TIME, val=row.start_time)
|
267
|
+
self.edit_row_num(col_name=RegisterFlag.TIMETABLE_SOLVENT_B_COMPOSITION,
|
268
|
+
val=row.organic_modifer)
|
269
|
+
self.download()
|
270
|
+
|
271
|
+
self.add_row()
|
272
|
+
self.get_num_rows()
|
273
|
+
self.edit_row_text(col_name=RegisterFlag.FUNCTION, val=RegisterFlag.FLOW.value)
|
274
|
+
self.edit_row_num(col_name=RegisterFlag.TIMETABLE_FLOW, val=row.flow)
|
275
|
+
self.edit_row_num(col_name=RegisterFlag.TIME, val=row.start_time)
|
276
|
+
self.download()
|
277
|
+
|
278
|
+
def _update_method_timetable(self, timetable_rows: list[TimeTableEntry]):
|
279
|
+
self.get_num_rows()
|
280
|
+
|
281
|
+
self.delete_table()
|
282
|
+
res = self.get_num_rows()
|
283
|
+
while not res.is_err():
|
284
|
+
self.delete_table()
|
285
|
+
res = self.get_num_rows()
|
286
|
+
|
287
|
+
self.new_table()
|
288
|
+
self.get_num_rows()
|
289
|
+
|
290
|
+
for i, row in enumerate(timetable_rows):
|
291
|
+
self.edit_row(row=row, first_row=i == 0)
|
292
|
+
|
270
293
|
def stop(self):
|
271
294
|
"""
|
272
295
|
Stops the method run. A dialog window will pop up and manual intervention may be required.\
|
@@ -1,5 +1,4 @@
|
|
1
|
-
from typing import
|
2
|
-
|
1
|
+
from typing import Optional
|
3
2
|
|
4
3
|
import os
|
5
4
|
import time
|
@@ -10,6 +9,7 @@ from ...utils.chromatogram import SEQUENCE_TIME_FORMAT, AgilentChannelChromatogr
|
|
10
9
|
from ...utils.macro import Command
|
11
10
|
from ...utils.sequence_types import SequenceTable, SequenceEntry, SequenceDataFiles, InjectionSource, SampleType
|
12
11
|
from ...utils.table_types import TableOperation, RegisterFlag, Table
|
12
|
+
from ...utils.tray_types import TenColumn
|
13
13
|
|
14
14
|
|
15
15
|
class SequenceController(TableController):
|
@@ -47,7 +47,7 @@ class SequenceController(TableController):
|
|
47
47
|
num_inj=num_inj,
|
48
48
|
inj_vol=inj_vol,
|
49
49
|
inj_source=inj_source,
|
50
|
-
sample_type=sample_type
|
50
|
+
sample_type=sample_type)
|
51
51
|
|
52
52
|
def check(self) -> str:
|
53
53
|
time.sleep(2)
|
@@ -116,67 +116,34 @@ class SequenceController(TableController):
|
|
116
116
|
self.send(Command.SAVE_SEQUENCE_CMD)
|
117
117
|
num_rows = self.get_num_rows()
|
118
118
|
|
119
|
-
table_register = self.table.register
|
120
|
-
table_name = self.table.name
|
121
|
-
|
122
119
|
if row.vial_location:
|
123
120
|
loc = row.vial_location
|
124
|
-
if isinstance(row.vial_location,
|
121
|
+
if isinstance(row.vial_location, TenColumn):
|
125
122
|
loc = row.vial_location.value
|
126
|
-
self.
|
127
|
-
|
128
|
-
row=row_num,
|
129
|
-
col_name=RegisterFlag.VIAL_LOCATION,
|
130
|
-
val=loc))
|
123
|
+
self.edit_row_num(row=row_num, col_name=RegisterFlag.VIAL_LOCATION, val=loc)
|
124
|
+
|
131
125
|
if row.method:
|
132
126
|
possible_path = os.path.join(self.method_dir, row.method) + ".M\\"
|
133
127
|
method = row.method
|
134
128
|
if os.path.exists(possible_path):
|
135
129
|
method = os.path.join(self.method_dir, row.method)
|
136
|
-
self.
|
137
|
-
table_name=table_name,
|
138
|
-
row=row_num,
|
139
|
-
col_name=RegisterFlag.METHOD,
|
140
|
-
val=method))
|
130
|
+
self.edit_row_text(row=row_num, col_name=RegisterFlag.METHOD, val=method)
|
141
131
|
|
142
132
|
if row.num_inj:
|
143
|
-
self.
|
144
|
-
table_name=table_name,
|
145
|
-
row=row_num,
|
146
|
-
col_name=RegisterFlag.NUM_INJ,
|
147
|
-
val=row.num_inj))
|
133
|
+
self.edit_row_num(row=row_num, col_name=RegisterFlag.NUM_INJ, val=row.num_inj)
|
148
134
|
|
149
135
|
if row.inj_vol:
|
150
|
-
self.
|
151
|
-
table_name=table_name,
|
152
|
-
row=row_num,
|
153
|
-
col_name=RegisterFlag.INJ_VOL,
|
154
|
-
val=row.inj_vol))
|
136
|
+
self.edit_row_text(row=row_num, col_name=RegisterFlag.INJ_VOL, val=row.inj_vol)
|
155
137
|
|
156
138
|
if row.inj_source:
|
157
|
-
self.
|
158
|
-
table_name=table_name,
|
159
|
-
row=row_num,
|
160
|
-
col_name=RegisterFlag.INJ_SOR,
|
161
|
-
val=row.inj_source.value))
|
139
|
+
self.edit_row_text(row=row_num, col_name=RegisterFlag.INJ_SOR, val=row.inj_source.value)
|
162
140
|
|
163
141
|
if row.sample_name:
|
164
|
-
self.
|
165
|
-
|
166
|
-
|
167
|
-
col_name=RegisterFlag.NAME,
|
168
|
-
val=row.sample_name))
|
169
|
-
self.sleepy_send(TableOperation.EDIT_ROW_TEXT.value.format(register=table_register,
|
170
|
-
table_name=table_name,
|
171
|
-
row=row_num,
|
172
|
-
col_name=RegisterFlag.DATA_FILE,
|
173
|
-
val=row.sample_name))
|
142
|
+
self.edit_row_text(row=row_num, col_name=RegisterFlag.NAME, val=row.sample_name)
|
143
|
+
self.edit_row_text(row=row_num, col_name=RegisterFlag.DATA_FILE, val=row.sample_name)
|
144
|
+
|
174
145
|
if row.sample_type:
|
175
|
-
self.
|
176
|
-
table_name=table_name,
|
177
|
-
row=row_num,
|
178
|
-
col_name=RegisterFlag.SAMPLE_TYPE,
|
179
|
-
val=row.sample_type.value))
|
146
|
+
self.edit_row_num(row=row_num, col_name=RegisterFlag.SAMPLE_TYPE, val=row.sample_type.value)
|
180
147
|
|
181
148
|
self.send(Command.SAVE_SEQUENCE_CMD)
|
182
149
|
|
@@ -210,7 +177,7 @@ class SequenceController(TableController):
|
|
210
177
|
sequence_data_files: SequenceDataFiles = self.data_files[-1]
|
211
178
|
return sequence_data_files.dir
|
212
179
|
|
213
|
-
def get_data(self, custom_path:Optional[str] = None
|
180
|
+
def get_data(self, custom_path: Optional[str] = None) -> list[AgilentChannelChromatogramData]:
|
214
181
|
parent_dir = self.data_files[-1].dir if not custom_path else custom_path
|
215
182
|
subdirs = [x[0] for x in os.walk(self.data_dir)]
|
216
183
|
potential_folders = sorted(list(filter(lambda d: parent_dir in d, subdirs)))
|
{pychemstation-0.5.9 → pychemstation-0.5.10}/pychemstation/control/controllers/table_controller.py
RENAMED
@@ -14,19 +14,19 @@ from result import Result, Ok, Err
|
|
14
14
|
from ...control.controllers.comm import CommunicationController
|
15
15
|
from ...utils.chromatogram import AgilentHPLCChromatogram, AgilentChannelChromatogramData
|
16
16
|
from ...utils.macro import Command, HPLCRunningStatus, Response
|
17
|
-
from ...utils.method_types import
|
17
|
+
from ...utils.method_types import MethodDetails
|
18
18
|
from ...utils.sequence_types import SequenceDataFiles, SequenceTable
|
19
19
|
from ...utils.table_types import Table, TableOperation, RegisterFlag
|
20
20
|
|
21
|
+
TableType = Union[MethodDetails, SequenceTable]
|
21
22
|
|
22
|
-
TableType = Union[MethodTimetable, SequenceTable]
|
23
23
|
|
24
24
|
class TableController(abc.ABC):
|
25
25
|
|
26
26
|
def __init__(self, controller: CommunicationController, src: str, data_dir: str, table: Table):
|
27
27
|
self.controller = controller
|
28
28
|
self.table = table
|
29
|
-
self.table_state
|
29
|
+
self.table_state: Optional[TableType] = None
|
30
30
|
|
31
31
|
if os.path.isdir(src):
|
32
32
|
self.src: str = src
|
@@ -38,7 +38,7 @@ class TableController(abc.ABC):
|
|
38
38
|
else:
|
39
39
|
raise FileNotFoundError(f"dir: {data_dir} not found.")
|
40
40
|
|
41
|
-
self.spectra: dict[str, AgilentHPLCChromatogram] = {
|
41
|
+
self.spectra: dict[str, Optional[AgilentHPLCChromatogram]] = {
|
42
42
|
"A": AgilentHPLCChromatogram(self.data_dir),
|
43
43
|
"B": AgilentHPLCChromatogram(self.data_dir),
|
44
44
|
"C": AgilentHPLCChromatogram(self.data_dir),
|
@@ -51,6 +51,9 @@ class TableController(abc.ABC):
|
|
51
51
|
|
52
52
|
self.data_files: Union[list[SequenceDataFiles], list[str]] = []
|
53
53
|
|
54
|
+
# Initialize row counter for table operations
|
55
|
+
self.send('Local Rows')
|
56
|
+
|
54
57
|
def receive(self) -> Result[Response, str]:
|
55
58
|
for _ in range(10):
|
56
59
|
try:
|
@@ -60,6 +63,9 @@ class TableController(abc.ABC):
|
|
60
63
|
return Err("Could not parse response")
|
61
64
|
|
62
65
|
def send(self, cmd: Union[Command, str]):
|
66
|
+
if not self.controller:
|
67
|
+
raise RuntimeError(
|
68
|
+
"Communication controller must be initialized before sending command. It is currently in offline mode.")
|
63
69
|
self.controller.send(cmd)
|
64
70
|
|
65
71
|
def sleepy_send(self, cmd: Union[Command, str]):
|
@@ -85,6 +91,46 @@ class TableController(abc.ABC):
|
|
85
91
|
row=row,
|
86
92
|
col_name=col_name.value))
|
87
93
|
|
94
|
+
def add_new_col_num(self,
|
95
|
+
col_name: RegisterFlag,
|
96
|
+
val: Union[int, float]):
|
97
|
+
self.sleepy_send(TableOperation.NEW_COL_VAL.value.format(
|
98
|
+
register=self.table.register,
|
99
|
+
table_name=self.table.name,
|
100
|
+
col_name=col_name,
|
101
|
+
val=val))
|
102
|
+
|
103
|
+
def add_new_col_text(self,
|
104
|
+
col_name: RegisterFlag,
|
105
|
+
val: str):
|
106
|
+
self.sleepy_send(TableOperation.NEW_COL_TEXT.value.format(
|
107
|
+
register=self.table.register,
|
108
|
+
table_name=self.table.name,
|
109
|
+
col_name=col_name,
|
110
|
+
val=val))
|
111
|
+
|
112
|
+
def edit_row_num(self,
|
113
|
+
col_name: RegisterFlag,
|
114
|
+
val: Union[int, float],
|
115
|
+
row: Optional[int] = None):
|
116
|
+
self.sleepy_send(TableOperation.EDIT_ROW_VAL.value.format(
|
117
|
+
register=self.table.register,
|
118
|
+
table_name=self.table.name,
|
119
|
+
row=row if row is not None else 'Rows',
|
120
|
+
col_name=col_name,
|
121
|
+
val=val))
|
122
|
+
|
123
|
+
def edit_row_text(self,
|
124
|
+
col_name: RegisterFlag,
|
125
|
+
val: str,
|
126
|
+
row: Optional[int] = None):
|
127
|
+
self.sleepy_send(TableOperation.EDIT_ROW_TEXT.value.format(
|
128
|
+
register=self.table.register,
|
129
|
+
table_name=self.table.name,
|
130
|
+
row=row if row is not None else 'Rows',
|
131
|
+
col_name=col_name,
|
132
|
+
val=val))
|
133
|
+
|
88
134
|
@abc.abstractmethod
|
89
135
|
def get_row(self, row: int):
|
90
136
|
pass
|
@@ -150,7 +196,7 @@ class TableController(abc.ABC):
|
|
150
196
|
return started_running
|
151
197
|
|
152
198
|
def check_hplc_done_running(self,
|
153
|
-
method: Optional[
|
199
|
+
method: Optional[MethodDetails] = None,
|
154
200
|
sequence: Optional[SequenceTable] = None) -> Result[str, str]:
|
155
201
|
"""
|
156
202
|
Checks if ChemStation has finished running and can read data back
|
@@ -213,4 +259,8 @@ class TableController(abc.ABC):
|
|
213
259
|
Load chromatogram for any channel in spectra dictionary.
|
214
260
|
"""
|
215
261
|
for channel, spec in self.spectra.items():
|
216
|
-
|
262
|
+
try:
|
263
|
+
spec.load_spectrum(data_path=data_file, channel=channel)
|
264
|
+
except FileNotFoundError:
|
265
|
+
self.spectra[channel] = None
|
266
|
+
print(f"No data at channel: {channel}")
|