pychemstation 0.5.9__py3-none-any.whl → 0.5.11__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.
@@ -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, MethodTimetable, HPLCMethodParams
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=None)
58
-
59
- def load(self) -> MethodTimetable:
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 = [self.get_row(r + 1) for r in range(int(rows.ok_value.num_response))]
66
- self.table_state = MethodTimetable(
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
- first_row=self.get_method_params(),
69
- subsequent_rows=timetable_rows)
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) -> MethodTimetable:
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 = MethodTimetable(
137
- first_row=HPLCMethodParams(
138
- organic_modifier=organic_modifier.percentage,
139
- flow=method.flow,
140
- maximum_run_time=method.stop_time.stop_time_value),
141
- subsequent_rows=[
142
- TimeTableEntry(
143
- start_time=tte.time,
144
- organic_modifer=tte.percent_b,
145
- flow=method.flow
146
- ) for tte in method.timetable.timetable_entry
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: MethodTimetable, save: bool):
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.first_row.organic_modifier,
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.first_row.maximum_run_time,
184
+ max_time: Param = Param(val=updated_method.stop_time,
166
185
  chemstation_key=RegisterFlag.MAX_TIME,
167
186
  ptype=PType.NUM)
168
- flow: Param = Param(val=updated_method.first_row.flow,
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.delete_table()
174
- self._update_param(initial_organic_modifier)
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 _update_method_timetable(self, timetable_rows: list[TimeTableEntry]):
194
- self.sleepy_send('Local Rows')
195
- self.get_num_rows()
196
-
197
- self.sleepy_send('DelTab RCPMP1Method[1], "Timetable"')
198
- res = self.get_num_rows()
199
- while not res.is_err():
200
- self.sleepy_send('DelTab RCPMP1Method[1], "Timetable"')
201
- res = self.get_num_rows()
202
-
203
- self.sleepy_send('NewTab RCPMP1Method[1], "Timetable"')
204
- self.get_num_rows()
205
-
206
- for i, row in enumerate(timetable_rows):
207
- if i == 0:
208
- self.send('Sleep 1')
209
- self.sleepy_send('InsTabRow RCPMP1Method[1], "Timetable"')
210
- self.send('Sleep 1')
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,15 +1,14 @@
1
- from typing import Optional
2
-
3
-
4
1
  import os
5
2
  import time
3
+ from typing import Optional
6
4
 
7
- from ...control.controllers.table_controller import TableController
8
5
  from ...control.controllers.comm import CommunicationController
6
+ from ...control.controllers.table_controller import TableController
9
7
  from ...utils.chromatogram import SEQUENCE_TIME_FORMAT, AgilentChannelChromatogramData
10
8
  from ...utils.macro import Command
11
9
  from ...utils.sequence_types import SequenceTable, SequenceEntry, SequenceDataFiles, InjectionSource, SampleType
12
- from ...utils.table_types import TableOperation, RegisterFlag, Table
10
+ from ...utils.table_types import RegisterFlag, Table
11
+ from ...utils.tray_types import TenVialColumn
13
12
 
14
13
 
15
14
  class SequenceController(TableController):
@@ -47,7 +46,7 @@ class SequenceController(TableController):
47
46
  num_inj=num_inj,
48
47
  inj_vol=inj_vol,
49
48
  inj_source=inj_source,
50
- sample_type=sample_type, )
49
+ sample_type=sample_type)
51
50
 
52
51
  def check(self) -> str:
53
52
  time.sleep(2)
@@ -116,67 +115,34 @@ class SequenceController(TableController):
116
115
  self.send(Command.SAVE_SEQUENCE_CMD)
117
116
  num_rows = self.get_num_rows()
118
117
 
119
- table_register = self.table.register
120
- table_name = self.table.name
121
-
122
118
  if row.vial_location:
123
119
  loc = row.vial_location
124
- if isinstance(row.vial_location, InjectionSource):
120
+ if isinstance(row.vial_location, TenVialColumn):
125
121
  loc = row.vial_location.value
126
- self.sleepy_send(TableOperation.EDIT_ROW_VAL.value.format(register=table_register,
127
- table_name=table_name,
128
- row=row_num,
129
- col_name=RegisterFlag.VIAL_LOCATION,
130
- val=loc))
122
+ self.edit_row_num(row=row_num, col_name=RegisterFlag.VIAL_LOCATION, val=loc)
123
+
131
124
  if row.method:
132
125
  possible_path = os.path.join(self.method_dir, row.method) + ".M\\"
133
126
  method = row.method
134
127
  if os.path.exists(possible_path):
135
128
  method = os.path.join(self.method_dir, row.method)
136
- self.sleepy_send(TableOperation.EDIT_ROW_TEXT.value.format(register=table_register,
137
- table_name=table_name,
138
- row=row_num,
139
- col_name=RegisterFlag.METHOD,
140
- val=method))
129
+ self.edit_row_text(row=row_num, col_name=RegisterFlag.METHOD, val=method)
141
130
 
142
131
  if row.num_inj:
143
- self.sleepy_send(TableOperation.EDIT_ROW_VAL.value.format(register=table_register,
144
- table_name=table_name,
145
- row=row_num,
146
- col_name=RegisterFlag.NUM_INJ,
147
- val=row.num_inj))
132
+ self.edit_row_num(row=row_num, col_name=RegisterFlag.NUM_INJ, val=row.num_inj)
148
133
 
149
134
  if row.inj_vol:
150
- self.sleepy_send(TableOperation.EDIT_ROW_TEXT.value.format(register=table_register,
151
- table_name=table_name,
152
- row=row_num,
153
- col_name=RegisterFlag.INJ_VOL,
154
- val=row.inj_vol))
135
+ self.edit_row_text(row=row_num, col_name=RegisterFlag.INJ_VOL, val=row.inj_vol)
155
136
 
156
137
  if row.inj_source:
157
- self.sleepy_send(TableOperation.EDIT_ROW_TEXT.value.format(register=table_register,
158
- table_name=table_name,
159
- row=row_num,
160
- col_name=RegisterFlag.INJ_SOR,
161
- val=row.inj_source.value))
138
+ self.edit_row_text(row=row_num, col_name=RegisterFlag.INJ_SOR, val=row.inj_source.value)
162
139
 
163
140
  if row.sample_name:
164
- self.sleepy_send(TableOperation.EDIT_ROW_TEXT.value.format(register=table_register,
165
- table_name=table_name,
166
- row=row_num,
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))
141
+ self.edit_row_text(row=row_num, col_name=RegisterFlag.NAME, val=row.sample_name)
142
+ self.edit_row_text(row=row_num, col_name=RegisterFlag.DATA_FILE, val=row.sample_name)
143
+
174
144
  if row.sample_type:
175
- self.sleepy_send(TableOperation.EDIT_ROW_VAL.value.format(register=table_register,
176
- table_name=table_name,
177
- row=row_num,
178
- col_name=RegisterFlag.SAMPLE_TYPE,
179
- val=row.sample_type.value))
145
+ self.edit_row_num(row=row_num, col_name=RegisterFlag.SAMPLE_TYPE, val=row.sample_type.value)
180
146
 
181
147
  self.send(Command.SAVE_SEQUENCE_CMD)
182
148
 
@@ -210,7 +176,7 @@ class SequenceController(TableController):
210
176
  sequence_data_files: SequenceDataFiles = self.data_files[-1]
211
177
  return sequence_data_files.dir
212
178
 
213
- def get_data(self, custom_path:Optional[str] = None ) -> list[AgilentChannelChromatogramData]:
179
+ def get_data(self, custom_path: Optional[str] = None) -> list[AgilentChannelChromatogramData]:
214
180
  parent_dir = self.data_files[-1].dir if not custom_path else custom_path
215
181
  subdirs = [x[0] for x in os.walk(self.data_dir)]
216
182
  potential_folders = sorted(list(filter(lambda d: parent_dir in d, subdirs)))
@@ -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 MethodTimetable
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 : Optional[TableType] = None
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[MethodTimetable] = None,
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
- spec.load_spectrum(data_path=data_file, channel=channel)
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}")
@@ -9,7 +9,7 @@ from typing import Union, Optional
9
9
  from ..control.controllers import MethodController, SequenceController, CommunicationController
10
10
  from ..utils.chromatogram import AgilentChannelChromatogramData
11
11
  from ..utils.macro import Command, HPLCRunningStatus, HPLCAvailStatus, HPLCErrorStatus, Response
12
- from ..utils.method_types import MethodTimetable
12
+ from ..utils.method_types import MethodDetails
13
13
  from ..utils.sequence_types import SequenceTable, SequenceEntry
14
14
  from ..utils.table_types import Table
15
15
 
@@ -26,6 +26,11 @@ class HPLCController:
26
26
  name="SeqTable1"
27
27
  )
28
28
 
29
+ INJECTOR_TABLE = Table(
30
+ register="_LeoAlsMethod",
31
+ name="ProgTable"
32
+ )
33
+
29
34
  def __init__(self,
30
35
  comm_dir: str,
31
36
  data_dir: str,
@@ -51,17 +56,20 @@ class HPLCController:
51
56
 
52
57
  def send(self, cmd: Union[Command, str]):
53
58
  if not self.comm:
54
- raise RuntimeError("Communication controller must be initialized before sending command. It is currently in offline mode.")
59
+ raise RuntimeError(
60
+ "Communication controller must be initialized before sending command. It is currently in offline mode.")
55
61
  self.comm.send(cmd)
56
62
 
57
63
  def receive(self) -> Response:
58
64
  if not self.comm:
59
- raise RuntimeError("Communication controller must be initialized before sending command. It is currently in offline mode.")
65
+ raise RuntimeError(
66
+ "Communication controller must be initialized before sending command. It is currently in offline mode.")
60
67
  return self.comm.receive().value
61
68
 
62
69
  def status(self) -> Union[HPLCRunningStatus | HPLCAvailStatus | HPLCErrorStatus]:
63
70
  if not self.comm:
64
- raise RuntimeError("Communication controller must be initialized before sending command. It is currently in offline mode.")
71
+ raise RuntimeError(
72
+ "Communication controller must be initialized before sending command. It is currently in offline mode.")
65
73
  return self.comm.get_status()
66
74
 
67
75
  def switch_method(self, method_name: str):
@@ -74,8 +82,6 @@ class HPLCController:
74
82
  :raises IndexError: Response did not have expected format. Try again.
75
83
  :raises AssertionError: The desired method is not selected. Try again.
76
84
  """
77
- if not self.comm:
78
- raise RuntimeError("Communication controller must be initialized before sending command. It is currently in offline mode.")
79
85
  self.method_controller.switch(method_name)
80
86
 
81
87
  def switch_sequence(self, sequence_name: str):
@@ -85,8 +91,6 @@ class HPLCController:
85
91
 
86
92
  :param sequence_name: The name of the sequence file
87
93
  """
88
- if not self.comm:
89
- raise RuntimeError("Communication controller must be initialized before sending command. It is currently in offline mode.")
90
94
  self.sequence_controller.switch(sequence_name)
91
95
 
92
96
  def run_method(self, experiment_name: str, stall_while_running: bool = True):
@@ -100,8 +104,6 @@ class HPLCController:
100
104
  :param experiment_name: Name of the experiment
101
105
  :param stall_while_running: whether this method should return or stall while HPLC runs.
102
106
  """
103
- if not self.comm:
104
- raise RuntimeError("Communication controller must be initialized before sending command. It is currently in offline mode.")
105
107
  self.method_controller.run(experiment_name, stall_while_running)
106
108
 
107
109
  def run_sequence(self, stall_while_running: bool = True):
@@ -112,29 +114,23 @@ class HPLCController:
112
114
 
113
115
  :param stall_while_running: whether this method should return or stall while HPLC runs.
114
116
  """
115
- if not self.comm:
116
- raise RuntimeError("Communication controller must be initialized before sending command. It is currently in offline mode.")
117
117
  self.sequence_controller.run(stall_while_running=stall_while_running)
118
118
 
119
- def edit_method(self, updated_method: MethodTimetable, save: bool = False):
119
+ def edit_method(self, updated_method: MethodDetails, save: bool = False):
120
120
  """Updated the currently loaded method in ChemStation with provided values.
121
121
 
122
122
  :param updated_method: the method with updated values, to be sent to Chemstation to modify the currently loaded method.
123
- :param save:
123
+ :param save: whether this method should be to disk, or just modified.
124
124
  """
125
- if not self.comm:
126
- raise RuntimeError("Communication controller must be initialized before sending command. It is currently in offline mode.")
127
125
  self.method_controller.edit(updated_method, save)
128
126
 
129
127
  def edit_sequence(self, updated_sequence: SequenceTable):
130
128
  """
131
- Updates the currently loaded sequence table with the provided table. This method will delete the existing sequence table and remake it.
129
+ Updates the currently loaded sequence table with the provided table.
132
130
  If you would only like to edit a single row of a sequence table, use `edit_sequence_row` instead.
133
131
 
134
- :param updated_sequence:
132
+ :param updated_sequence: The sequence table to be written to the currently loaded sequence table.
135
133
  """
136
- if not self.comm:
137
- raise RuntimeError("Communication controller must be initialized before sending command. It is currently in offline mode.")
138
134
  self.sequence_controller.edit(updated_sequence)
139
135
 
140
136
  def edit_sequence_row(self, row: SequenceEntry, num: int):
@@ -142,21 +138,23 @@ class HPLCController:
142
138
  Edits a row in the sequence table. Assumes the row already exists.
143
139
 
144
140
  :param row: sequence row entry with updated information
145
- :param row_num: the row to edit, based on -1-based indexing
141
+ :param num: the row to edit, based on 1-based indexing
146
142
  """
147
- if not self.comm:
148
- raise RuntimeError("Communication controller must be initialized before sending command. It is currently in offline mode.")
149
143
  self.sequence_controller.edit_row(row, num)
150
144
 
151
145
  def get_last_run_method_data(self, data: Optional[str] = None) -> AgilentChannelChromatogramData:
152
146
  """
153
147
  Returns the last run method data.
148
+
149
+ :param data: If you want to just load method data but from a file path. This file path must be the complete file path.
154
150
  """
155
151
  return self.method_controller.get_data(custom_path=data)
156
152
 
157
153
  def get_last_run_sequence_data(self, data: Optional[str] = None) -> list[AgilentChannelChromatogramData]:
158
154
  """
159
155
  Returns data for all rows in the last run sequence data.
156
+
157
+ :param data: If you want to just load sequence data but from a file path. This file path must be the complete file path.
160
158
  """
161
159
  return self.sequence_controller.get_data(custom_path=data)
162
160
 
@@ -164,66 +162,54 @@ class HPLCController:
164
162
  """
165
163
  Returns the name of the currently loaded sequence.
166
164
  """
167
- if not self.comm:
168
- raise RuntimeError("Communication controller must be initialized before sending command. It is currently in offline mode.")
169
165
  return self.sequence_controller.check()
170
166
 
171
167
  def check_loaded_method(self) -> str:
172
168
  """
173
169
  Returns the name of the currently loaded method.
174
170
  """
175
- if not self.comm:
176
- raise RuntimeError("Communication controller must be initialized before sending command. It is currently in offline mode.")
177
171
  return self.method_controller.check()
178
172
 
179
- def load_method(self) -> MethodTimetable:
173
+ def load_method(self) -> MethodDetails:
180
174
  """
181
175
  Returns all details of the currently loaded method, including its timetable.
182
176
  """
183
- if not self.comm:
184
- raise RuntimeError("Communication controller must be initialized before sending command. It is currently in offline mode.")
185
177
  return self.method_controller.load()
186
178
 
187
179
  def load_sequence(self) -> SequenceTable:
188
180
  """
189
181
  Returns the currently loaded sequence.
190
182
  """
191
- if not self.comm:
192
- raise RuntimeError("Communication controller must be initialized before sending command. It is currently in offline mode.")
193
183
  return self.sequence_controller.load()
194
184
 
195
185
  def standby(self):
196
186
  """Switches all modules in standby mode. All lamps and pumps are switched off."""
197
- if not self.comm:
198
- raise RuntimeError("Communication controller must be initialized before sending command. It is currently in offline mode.")
199
187
  self.send(Command.STANDBY_CMD)
200
188
 
201
189
  def preprun(self):
202
190
  """ Prepares all modules for run. All lamps and pumps are switched on."""
203
- if not self.comm:
204
- raise RuntimeError("Communication controller must be initialized before sending command. It is currently in offline mode.")
205
191
  self.send(Command.PREPRUN_CMD)
206
192
 
207
193
  def lamp_on(self):
208
194
  """Turns the UV lamp on."""
209
- if not self.comm:
210
- raise RuntimeError("Communication controller must be initialized before sending command. It is currently in offline mode.")
211
195
  self.send(Command.LAMP_ON_CMD)
212
196
 
213
197
  def lamp_off(self):
214
198
  """Turns the UV lamp off."""
215
- if not self.comm:
216
- raise RuntimeError("Communication controller must be initialized before sending command. It is currently in offline mode.")
217
199
  self.send(Command.LAMP_OFF_CMD)
218
200
 
219
201
  def pump_on(self):
220
202
  """Turns on the pump on."""
221
- if not self.comm:
222
- raise RuntimeError("Communication controller must be initialized before sending command. It is currently in offline mode.")
223
203
  self.send(Command.PUMP_ON_CMD)
224
204
 
225
205
  def pump_off(self):
226
206
  """Turns the pump off."""
227
- if not self.comm:
228
- raise RuntimeError("Communication controller must be initialized before sending command. It is currently in offline mode.")
229
207
  self.send(Command.PUMP_OFF_CMD)
208
+
209
+ def instrument_off(self):
210
+ """Shuts the entire instrument off, including pumps, lamps, thermostat."""
211
+ self.send(Command.INSTRUMENT_OFF)
212
+
213
+ def instrument_on(self):
214
+ """Turns the entire instrument on, including pumps, lamps, thermostat."""
215
+ self.send(Command.INSTRUMENT_ON)
@@ -23,10 +23,16 @@ class Command(Enum):
23
23
  STANDBY_CMD = "Standby"
24
24
  STOP_MACRO_CMD = "Stop"
25
25
  PREPRUN_CMD = "PrepRun"
26
+
27
+ # Instrument Control
26
28
  LAMP_ON_CMD = "LampAll ON"
27
29
  LAMP_OFF_CMD = "LampAll OFF"
28
30
  PUMP_ON_CMD = "PumpAll ON"
29
31
  PUMP_OFF_CMD = "PumpAll OFF"
32
+ INSTRUMENT_OFF = 'macro "SHUTDOWN.MAC" ,go'
33
+ INSTRUMENT_ON = 'LIDoOperation "TURN_ON"'
34
+
35
+
30
36
  GET_METHOD_CMD = "response$ = _MethFile$"
31
37
  GET_ROWS_CMD = 'response_num = TabHdrVal({register}, "{table_name}", "{col_name}")'
32
38
  SWITCH_METHOD_CMD = 'LoadMethod "{method_dir}", "{method_name}.M"'
@@ -3,8 +3,7 @@ from enum import Enum
3
3
  from typing import Union, Any, Optional
4
4
 
5
5
  from .table_types import RegisterFlag
6
- from ..generated import Signal, SolventElement
7
-
6
+ from ..generated import Signal
8
7
 
9
8
 
10
9
  class PType(Enum):
@@ -23,7 +22,7 @@ class Param:
23
22
  class HPLCMethodParams:
24
23
  organic_modifier: int
25
24
  flow: float
26
- maximum_run_time: int
25
+ pressure: Optional[float] = None #TODO: find this
27
26
 
28
27
 
29
28
  @dataclass
@@ -34,10 +33,20 @@ class TimeTableEntry:
34
33
 
35
34
 
36
35
  @dataclass
37
- class MethodTimetable:
36
+ class MethodDetails:
37
+ """An Agilent Chemstation method, TODO is to add MS parameters
38
+
39
+ :attribute name: the name of the method, should be the same as the Chemstation method name.
40
+ :attribute timetable: list of entries in the method timetable
41
+ :attribute stop_time: the time the method stops running after the last timetable entry.
42
+ :attribute post_time: the amount of time after the stoptime that the pumps keep running,
43
+ based on settings in the first row of the timetable.
44
+ :attribute params: the organic modifier (pump B) and flow rate displayed for the method (the time 0 settings)
45
+ :attribute dad_wavelengthes:
46
+ """
38
47
  name: str
39
- first_row: HPLCMethodParams
40
- subsequent_rows: list[TimeTableEntry]
48
+ params: HPLCMethodParams
49
+ timetable: list[TimeTableEntry]
50
+ stop_time: Optional[int] = None
51
+ post_time: Optional[int] = None
41
52
  dad_wavelengthes: Optional[list[Signal]] = None
42
- organic_modifier: Optional[SolventElement] = None
43
- modifier_a: Optional[SolventElement] = None
@@ -4,7 +4,7 @@ from dataclasses import dataclass
4
4
  from enum import Enum
5
5
  from typing import Optional, Union
6
6
 
7
- from pychemstation.utils.tray_types import TenColumn
7
+ from pychemstation.utils.tray_types import TenVialColumn
8
8
 
9
9
 
10
10
  @dataclass
@@ -39,7 +39,7 @@ class InjectionSource(Enum):
39
39
  @dataclass
40
40
  class SequenceEntry:
41
41
  sample_name: str
42
- vial_location: Union[TenColumn, int]
42
+ vial_location: Union[TenVialColumn, int]
43
43
  method: Optional[str] = None
44
44
  num_inj: Optional[int] = 1
45
45
  inj_vol: Optional[int] = 2
@@ -37,17 +37,20 @@ class RegisterFlag(Enum):
37
37
  SOLVENT_D_COMPOSITION = "PumpChannel4_CompositionPercentage"
38
38
  FLOW = "Flow"
39
39
  MAX_TIME = "StopTime_Time"
40
+ POST_TIME = "PostTime_Time" #TODO: check
40
41
  COLUMN_OVEN_TEMP1 = "TemperatureControl_Temperature"
41
42
  COLUMN_OVEN_TEMP2 = "TemperatureControl2_Temperature"
42
43
  STOPTIME_MODE = "StopTime_Mode"
43
44
  POSTIME_MODE = "PostTime_Mode"
44
45
  TIME = "Time"
45
46
  TIMETABLE_SOLVENT_B_COMPOSITION = "SolventCompositionPumpChannel2_Percentage"
47
+ TIMETABLE_FLOW = "FlowFlow"
46
48
 
47
49
  # for Method Timetable
48
50
  SOLVENT_COMPOSITION = "SolventComposition"
49
51
  PRESSURE = "Pressure"
50
52
  EXTERNAL_CONTACT = "ExternalContact"
53
+ FUNCTION = "Function"
51
54
 
52
55
 
53
56
  # for Sequence
@@ -1,7 +1,43 @@
1
+ from dataclasses import dataclass
1
2
  from enum import Enum
2
3
 
3
4
 
4
- class TenColumn(Enum):
5
+ class Num(Enum):
6
+ ONE = 1
7
+ TWO = 2
8
+ THREE = 3
9
+ FOUR = 4
10
+ FIVE = 5
11
+ SIX = 6
12
+ SEVEN = 7
13
+ EIGHT = 8
14
+ NINE = 9
15
+
16
+
17
+ class Plate(Enum):
18
+ ONE = "1"
19
+ TWO = "2"
20
+
21
+
22
+ class Letter(Enum):
23
+ A = 8191
24
+ B = 8255
25
+ C = 8319
26
+ D = 8383
27
+ F = 8447
28
+
29
+
30
+ @dataclass
31
+ class FiftyFourVialPlate:
32
+ plate: Plate
33
+ letter: Letter
34
+ num: Num
35
+
36
+ def value(self) -> int:
37
+ return self.letter.value + self.num.value
38
+
39
+
40
+ class TenVialColumn(Enum):
5
41
  ONE = 1
6
42
  TWO = 2
7
43
  THREE = 3
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pychemstation
3
- Version: 0.5.9
3
+ Version: 0.5.11
4
4
  Summary: Library to interact with Chemstation software, primarily used in Hein lab
5
5
  Home-page: https://gitlab.com/heingroup/device-api/pychemstation
6
6
  Author: Lucy Hao
@@ -13,6 +13,7 @@ License-File: LICENSE
13
13
  Requires-Dist: polling
14
14
  Requires-Dist: seabreeze
15
15
  Requires-Dist: xsdata
16
+ Requires-Dist: result
16
17
 
17
18
  # Agilent HPLC Macro Control
18
19
 
@@ -5,12 +5,12 @@ pychemstation/analysis/spec_utils.py,sha256=UOo9hJR3evJfmaohEEsyb7aq6X996ofuUfu-
5
5
  pychemstation/analysis/utils.py,sha256=ISupAOb_yqA4_DZRK9v18UL-XjUQccAicIJKb1VMnGg,2055
6
6
  pychemstation/control/__init__.py,sha256=4xTy8X-mkn_PPZKr7w9rnj1wZhtmTesbQptPhpYmKXs,64
7
7
  pychemstation/control/comm.py,sha256=u44g1hTluQ0yUG93Un-QAshScoDpgYRrZfFTgweP5tY,7386
8
- pychemstation/control/hplc.py,sha256=mIq7iN-BkWLSCNGCQPWc19Wjx82_mA_0X5Cy8TJoaUQ,10751
8
+ pychemstation/control/hplc.py,sha256=5xC5q-hrAn5hKdz-ZwT_Dlas9LWLV27jZvhCKj7Lzg4,8761
9
9
  pychemstation/control/controllers/__init__.py,sha256=di3ytLIK-35XC_THw4IjNaOtCUTe7GuEOFb-obmREw4,166
10
10
  pychemstation/control/controllers/comm.py,sha256=IU4I_Q42VNCNUlVi93MxCmw2EBY9hiBDkU9FxubKg3c,7441
11
- pychemstation/control/controllers/method.py,sha256=rB-7o7ibOhh1ZzkmhJ1YdOz3vbs-CGxjjQKd0-rWlWs,14230
12
- pychemstation/control/controllers/sequence.py,sha256=ME9F5nWt-GqL5Qonhe8uNRU0K9oRwGPkPpb_YgqbziI,11318
13
- pychemstation/control/controllers/table_controller.py,sha256=ecMbFWRv5fk7onCWO_NAE8liAYcGrPipFeusuJKQslA,9113
11
+ pychemstation/control/controllers/method.py,sha256=XUclB7lQ_SIkquR58MBmmi9drHIPEq9AR8VprTLenvI,15503
12
+ pychemstation/control/controllers/sequence.py,sha256=kYNxxck2I-q9mZDEZwG8bJ_99FfLmunS13EAHOS65wU,8288
13
+ pychemstation/control/controllers/table_controller.py,sha256=ItuNJ3aQqx73rviGVXs7vYaZKA9icPFreOUuUZupqB4,11029
14
14
  pychemstation/control/table/__init__.py,sha256=RgMN4uIWHdNUHpGRBWdzmzAbk7XEKl6Y-qtqWCxzSZU,124
15
15
  pychemstation/control/table/method.py,sha256=THVoGomSXff_CTU3eAYme0BYwkPzab5UgZKsiZ29QSk,12196
16
16
  pychemstation/control/table/sequence.py,sha256=Eri52AnbE3BGthfrRSvYKYciquUzvHKo0lYUTySYYE8,10542
@@ -20,20 +20,20 @@ pychemstation/generated/dad_method.py,sha256=0W8Z5WDtF5jpIcudMqb7XrkTnR2EGg_QOCs
20
20
  pychemstation/generated/pump_method.py,sha256=sUhE2Oo00nzVcoONtq3EMWsN4wLSryXbG8f3EeViWKg,12174
21
21
  pychemstation/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
22
22
  pychemstation/utils/chromatogram.py,sha256=-q3_hL9GTyi4C95os7IwAiOrkTM4EXIiigm-nW9pFmM,3221
23
- pychemstation/utils/macro.py,sha256=9rSdup9HucmVfT9ZnhwMUpH3vjxDsILXnBCGXQGVdYU,2656
24
- pychemstation/utils/method_types.py,sha256=Hyd_Kxf-ygKW7LlOtEhGG-uujwFPE1w-orqyxcDz17E,877
23
+ pychemstation/utils/macro.py,sha256=a6M6iK6c56Z75Opr2a-gsLKvMMpShu05DwcBYn5aTUs,2778
24
+ pychemstation/utils/method_types.py,sha256=SRpr61Ca57NzfYoDiaooeI5tw1ESgVj_2-MctGyuN60,1478
25
25
  pychemstation/utils/parsing.py,sha256=bnFIsZZwFy9NKzVUf517yN-ogzQbm0hp_aho3KUD6Is,9317
26
- pychemstation/utils/sequence_types.py,sha256=3VqiUHsfFEdynAxfR-z8JIWBCo7PdnGwTvsk7sm7Ij8,1055
27
- pychemstation/utils/table_types.py,sha256=H67-7I96X8Zkm2HygHYttYwG_XuNDmV2AKZW10yZbiA,2418
28
- pychemstation/utils/tray_types.py,sha256=UUDED-IAf-8FmPVZezuWSiIQE_HgiZQMV2sTqu4oZw8,177
26
+ pychemstation/utils/sequence_types.py,sha256=OhbmBUS7XQOKHC8YLjgbEVdpjriEc1bORkwB5ZV43oA,1063
27
+ pychemstation/utils/table_types.py,sha256=HVE_tuM2TUED843iXvZqtONt8Eeolm6B5eciq60ZjR8,2521
28
+ pychemstation/utils/tray_types.py,sha256=NzeH1IYI-k6u-2QrZshhx-lNlvOmGoOElbZ0fspT-38,654
29
29
  tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
30
- tests/constants.py,sha256=ngjbR4FXfEFkgwsGB7Al4_6m9iUaV8EO7PCTraJ7TOk,2121
31
- tests/test_comb.py,sha256=Ef5PD_uEVszCMmpurbzlweSAXzGH6o1rblFqYhGC9r0,5680
32
- tests/test_comm.py,sha256=1ZZd0UrIBOKe91wzA-XI-gSRgXmId9mLWYSMeche82Y,2973
33
- tests/test_method.py,sha256=uCPpZVYKPz1CNWwhmBo_8TH0ku2V0ZpDZJj3f8iINB4,2440
34
- tests/test_sequence.py,sha256=yIQGhUTehtHz6D1ai5W6AlP0zes2icF0VdQ0IGJ2CbQ,4901
35
- pychemstation-0.5.9.dist-info/LICENSE,sha256=9bdF75gIf1MecZ7oymqWgJREVz7McXPG-mjqrTmzzD8,18658
36
- pychemstation-0.5.9.dist-info/METADATA,sha256=mExMVySyRewB-QkP_1ah4qv0Hi_ZgKxTuVfLek_DJ1s,4307
37
- pychemstation-0.5.9.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
38
- pychemstation-0.5.9.dist-info/top_level.txt,sha256=zXfKu_4nYWwPHo3OsuhshMNC3SPkcoTGCyODjURaghY,20
39
- pychemstation-0.5.9.dist-info/RECORD,,
30
+ tests/constants.py,sha256=iU6knsNpQGnBfGcC8VAj5SrCDcHD3jBZLhQdF6UUwY4,2452
31
+ tests/test_comb.py,sha256=EDE1Ve0A_EK4qro9imZsrD0xXrQN8hAowiOWPFtw3dM,5515
32
+ tests/test_comm.py,sha256=EYOpVXzEMQLGhhKYDPO-KaLcJdPSMPTD9Y4jSI0yVQY,2516
33
+ tests/test_method.py,sha256=r1Q1irqiVzs31QuTYLX3u_A0FpX8rIAQ1L4WOk9tLbk,2473
34
+ tests/test_sequence.py,sha256=Nz2iqp1cJgw6kcQvnwSkfBmhxpOH62PoEu6o_5rO-PY,4929
35
+ pychemstation-0.5.11.dist-info/LICENSE,sha256=9bdF75gIf1MecZ7oymqWgJREVz7McXPG-mjqrTmzzD8,18658
36
+ pychemstation-0.5.11.dist-info/METADATA,sha256=K1Hd9ry_rHoZ67yHBIjwuxwI8ooUp4ntAlDLZiI8rsA,4330
37
+ pychemstation-0.5.11.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
38
+ pychemstation-0.5.11.dist-info/top_level.txt,sha256=zXfKu_4nYWwPHo3OsuhshMNC3SPkcoTGCyODjURaghY,20
39
+ pychemstation-0.5.11.dist-info/RECORD,,
tests/constants.py CHANGED
@@ -39,25 +39,24 @@ def room(num: int):
39
39
  def gen_rand_method():
40
40
  org_modifier = int(random.random() * 10)
41
41
  max_run_time = int(random.random() * 10)
42
- return MethodTimetable(
43
- name=DEFAULT_METHOD,
44
- first_row=HPLCMethodParams(
45
- organic_modifier=org_modifier,
46
- flow=round(random.random(), 2),
47
- maximum_run_time=max_run_time),
48
- subsequent_rows=[
49
- TimeTableEntry(
50
- start_time=0.10,
51
- organic_modifer=org_modifier,
52
- flow=0.34),
53
- TimeTableEntry(
54
- start_time=1,
55
- organic_modifer=100 - int(random.random() * 10),
56
- flow=0.55)])
42
+ post_run_time = int(random.random() * 10)
43
+ flow = float(random.random() * 10) / 10
44
+ flow_1 = float(random.random() * 10) / 10
45
+ flow_2 = float(random.random() * 10) / 10
46
+ return MethodDetails(name=DEFAULT_METHOD,
47
+ timetable=[TimeTableEntry(start_time=0.10,
48
+ organic_modifer=org_modifier,
49
+ flow=flow_1),
50
+ TimeTableEntry(start_time=1,
51
+ organic_modifer=100 - int(random.random() * 10),
52
+ flow=flow_2)],
53
+ stop_time=max_run_time,
54
+ post_time=post_run_time,
55
+ params=HPLCMethodParams(organic_modifier=org_modifier, flow=flow))
57
56
 
58
57
 
59
58
  seq_entry = SequenceEntry(
60
- vial_location=TenColumn.ONE,
59
+ vial_location=TenVialColumn.ONE,
61
60
  method=DEFAULT_METHOD,
62
61
  num_inj=int(random.random() * 10),
63
62
  inj_vol=int(random.random() * 10),
tests/test_comb.py CHANGED
@@ -24,17 +24,15 @@ class TestCombinations(unittest.TestCase):
24
24
  def test_run_method_after_update(self):
25
25
  try:
26
26
  self.hplc_controller.method_controller.switch(DEFAULT_METHOD)
27
- rand_method = MethodTimetable(
28
- first_row=HPLCMethodParams(
29
- organic_modifier=5,
30
- flow=0.65,
31
- maximum_run_time=4),
32
- subsequent_rows=[
33
- TimeTableEntry(
34
- start_time=3.5,
35
- organic_modifer=100,
36
- flow=0.65)],
37
- name=DEFAULT_METHOD)
27
+ rand_method = MethodDetails(
28
+ params=HPLCMethodParams(organic_modifier=5,
29
+ flow=0.65),
30
+ timetable=[TimeTableEntry(start_time=3.5,
31
+ organic_modifer=100,
32
+ flow=0.65)],
33
+ name=DEFAULT_METHOD,
34
+ stop_time=10,
35
+ post_time=9)
38
36
  self.hplc_controller.edit_method(rand_method, save=True)
39
37
  if run_too:
40
38
  self.hplc_controller.run_method(experiment_name="changed_method")
@@ -48,7 +46,7 @@ class TestCombinations(unittest.TestCase):
48
46
  self.hplc_controller.switch_sequence(sequence_name=DEFAULT_SEQUENCE)
49
47
  seq_table = self.hplc_controller.load_sequence()
50
48
  seq_table.rows.append(SequenceEntry(
51
- vial_location=TenColumn.ONE,
49
+ vial_location=TenVialColumn.ONE,
52
50
  method=DEFAULT_METHOD,
53
51
  num_inj=3,
54
52
  inj_vol=4,
@@ -56,7 +54,7 @@ class TestCombinations(unittest.TestCase):
56
54
  sample_type=SampleType.SAMPLE,
57
55
  ))
58
56
  seq_table.rows[0] = SequenceEntry(
59
- vial_location=TenColumn.ONE,
57
+ vial_location=TenVialColumn.ONE,
60
58
  method=DEFAULT_METHOD,
61
59
  num_inj=3,
62
60
  inj_vol=4,
@@ -85,43 +83,38 @@ class TestCombinations(unittest.TestCase):
85
83
  def test_update_method_update_seq_table_run(self):
86
84
  try:
87
85
  self.hplc_controller.method_controller.switch(DEFAULT_METHOD)
88
- rand_method = MethodTimetable(
89
- first_row=HPLCMethodParams(
86
+ rand_method = MethodDetails(
87
+ name=DEFAULT_METHOD,
88
+ params=HPLCMethodParams(
90
89
  organic_modifier=5,
91
- flow=0.65,
92
- maximum_run_time=2),
93
- subsequent_rows=[
94
- TimeTableEntry(
95
- start_time=0.50,
96
- organic_modifer=99,
97
- flow=0.34)],
98
- name=DEFAULT_METHOD)
90
+ flow=0.65),
91
+ timetable=[TimeTableEntry(
92
+ start_time=0.50,
93
+ organic_modifer=99,
94
+ flow=0.34)],
95
+ stop_time=10,
96
+ post_time=5)
99
97
  self.hplc_controller.edit_method(rand_method, save=True)
100
98
 
101
99
  self.hplc_controller.switch_sequence(sequence_name=DEFAULT_SEQUENCE)
102
100
  seq_table = SequenceTable(
103
101
  name=DEFAULT_SEQUENCE,
104
- rows=[
105
- SequenceEntry(
106
- vial_location=8320,
107
- sample_name="WM-01-001_Cr-Org",
108
- method=DEFAULT_METHOD,
109
- inj_source=InjectionSource.HIP_ALS,
110
- inj_vol=2,
111
- num_inj=1,
112
- sample_type=SampleType.SAMPLE
113
- ),
114
- SequenceEntry(
115
- vial_location=8448,
116
- sample_name="WM-01-001_Cr-Aq",
117
- method=DEFAULT_METHOD,
118
- inj_source=InjectionSource.HIP_ALS,
119
- inj_vol=2,
120
- num_inj=1,
121
- sample_type=SampleType.SAMPLE
122
- ),
123
- ]
124
- )
102
+ rows=[SequenceEntry(
103
+ vial_location=8320,
104
+ sample_name="WM-01-001_Cr-Org",
105
+ method=DEFAULT_METHOD,
106
+ inj_source=InjectionSource.HIP_ALS,
107
+ inj_vol=2,
108
+ num_inj=1,
109
+ sample_type=SampleType.SAMPLE
110
+ ), SequenceEntry(
111
+ vial_location=8448,
112
+ sample_name="WM-01-001_Cr-Aq",
113
+ method=DEFAULT_METHOD,
114
+ inj_source=InjectionSource.HIP_ALS,
115
+ inj_vol=2,
116
+ num_inj=1,
117
+ sample_type=SampleType.SAMPLE)])
125
118
 
126
119
  self.hplc_controller.edit_sequence(seq_table)
127
120
  if run_too:
tests/test_comm.py CHANGED
@@ -42,7 +42,7 @@ class TestComm(unittest.TestCase):
42
42
  self.hplc_controller.send("TestNum = 0")
43
43
  self.hplc_controller.send("Print TestNum")
44
44
  self.hplc_controller.send("response_num = TestNum")
45
- self.hplc_controller.send("Print num_response")
45
+ self.hplc_controller.send("Print response_num")
46
46
  except Exception as e:
47
47
  self.fail(f"Should not throw error: {e}")
48
48
 
@@ -63,16 +63,3 @@ class TestComm(unittest.TestCase):
63
63
  except Exception as e:
64
64
  self.fail(f"Should not throw error: {e}")
65
65
 
66
- def test_pump_lamp(self):
67
- pump_lamp = [
68
- ("response", self.hplc_controller.lamp_on),
69
- ("response", self.hplc_controller.lamp_off),
70
- ("response", self.hplc_controller.pump_on),
71
- ("response", self.hplc_controller.pump_off),
72
- ]
73
-
74
- for operation in pump_lamp:
75
- try:
76
- operation[1]()
77
- except Exception as e:
78
- self.fail(f"Failed due to: {e}")
tests/test_method.py CHANGED
@@ -40,12 +40,12 @@ class TestMethod(unittest.TestCase):
40
40
  try:
41
41
  self.hplc_controller.edit_method(new_method)
42
42
  loaded_method = self.hplc_controller.load_method()
43
- self.assertEqual(new_method.first_row.organic_modifier,
44
- loaded_method.first_row.organic_modifier)
45
- self.assertEqual(new_method.subsequent_rows,
46
- loaded_method.subsequent_rows)
47
- self.assertEqual(new_method.first_row.flow,
48
- loaded_method.first_row.flow)
43
+ self.assertEqual(new_method.params.organic_modifier,
44
+ loaded_method.params.organic_modifier)
45
+ self.assertEqual(new_method.timetable[0].organic_modifer,
46
+ loaded_method.timetable[0].organic_modifer)
47
+ self.assertEqual(round(new_method.params.flow, 2),
48
+ round(loaded_method.params.flow, 2))
49
49
  except Exception as e:
50
50
  self.fail(f"Should have not failed: {e}")
51
51
 
@@ -58,4 +58,4 @@ class TestMethod(unittest.TestCase):
58
58
 
59
59
 
60
60
  if __name__ == '__main__':
61
- unittest.main()
61
+ unittest.main()
tests/test_sequence.py CHANGED
@@ -29,7 +29,7 @@ class TestSequence(unittest.TestCase):
29
29
  self.hplc_controller.switch_sequence(sequence_name=DEFAULT_SEQUENCE)
30
30
  try:
31
31
  self.hplc_controller.edit_sequence_row(SequenceEntry(
32
- vial_location=TenColumn.TEN,
32
+ vial_location=TenVialColumn.TEN,
33
33
  method=DEFAULT_METHOD,
34
34
  num_inj=3,
35
35
  inj_vol=4,
@@ -47,7 +47,7 @@ class TestSequence(unittest.TestCase):
47
47
  name=DEFAULT_SEQUENCE,
48
48
  rows=[
49
49
  SequenceEntry(
50
- vial_location=TenColumn.ONE,
50
+ vial_location=TenVialColumn.ONE,
51
51
  method=DEFAULT_METHOD,
52
52
  num_inj=3,
53
53
  inj_vol=4,
@@ -56,7 +56,7 @@ class TestSequence(unittest.TestCase):
56
56
  inj_source=InjectionSource.HIP_ALS
57
57
  ),
58
58
  SequenceEntry(
59
- vial_location=TenColumn.TWO,
59
+ vial_location=TenVialColumn.TWO,
60
60
  method=DEFAULT_METHOD,
61
61
  num_inj=3,
62
62
  inj_vol=4,
@@ -65,7 +65,7 @@ class TestSequence(unittest.TestCase):
65
65
  inj_source=InjectionSource.HIP_ALS
66
66
  ),
67
67
  SequenceEntry(
68
- vial_location=TenColumn.TEN,
68
+ vial_location=TenVialColumn.TEN,
69
69
  method=DEFAULT_METHOD,
70
70
  num_inj=3,
71
71
  inj_vol=4,
@@ -74,7 +74,7 @@ class TestSequence(unittest.TestCase):
74
74
  inj_source=InjectionSource.HIP_ALS
75
75
  ),
76
76
  SequenceEntry(
77
- vial_location=TenColumn.THREE,
77
+ vial_location=TenVialColumn.THREE,
78
78
  method=DEFAULT_METHOD,
79
79
  num_inj=3,
80
80
  inj_vol=4,
@@ -95,7 +95,7 @@ class TestSequence(unittest.TestCase):
95
95
  name=DEFAULT_SEQUENCE,
96
96
  rows=[
97
97
  SequenceEntry(
98
- vial_location=TenColumn.TEN,
98
+ vial_location=TenVialColumn.TEN,
99
99
  method=DEFAULT_METHOD,
100
100
  num_inj=3,
101
101
  inj_vol=4,
@@ -104,7 +104,7 @@ class TestSequence(unittest.TestCase):
104
104
  inj_source=InjectionSource.HIP_ALS
105
105
  ),
106
106
  SequenceEntry(
107
- vial_location=TenColumn.THREE,
107
+ vial_location=TenVialColumn.THREE,
108
108
  method=DEFAULT_METHOD,
109
109
  num_inj=3,
110
110
  inj_vol=4,