pychemstation 0.10.10__py3-none-any.whl → 0.10.12__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.
@@ -54,7 +54,7 @@ class CommunicationController(ABCCommunicationController):
54
54
  raise RuntimeError("Failed to get number.")
55
55
 
56
56
  def get_text_val(self, cmd: str) -> str:
57
- tries = 10
57
+ tries = 5
58
58
  for _ in range(tries):
59
59
  self.send(Command.GET_TEXT_VAL_CMD.value.format(cmd=cmd))
60
60
  res = self.receive()
@@ -5,12 +5,16 @@ import time
5
5
  import warnings
6
6
  from typing import Dict, List, Optional, Union, Tuple
7
7
 
8
- from result import Err, Ok, Result
8
+ from result import Err, Result, Ok
9
9
 
10
- from pychemstation.analysis.chromatogram import (
10
+ from ..devices.column import ColumnController
11
+ from ..devices.dad import DADController
12
+ from ..devices.pump import PumpController
13
+ from ..devices.sample_info import SampleInfo
14
+ from ....analysis.chromatogram import (
11
15
  TIME_FORMAT,
12
- AgilentChannelChromatogramData,
13
16
  AgilentHPLCChromatogram,
17
+ AgilentChannelChromatogramData,
14
18
  )
15
19
 
16
20
  from ....analysis.process_report import AgilentReport, ReportType
@@ -20,12 +24,13 @@ from ....utils.macro import Command
20
24
  from ....utils.method_types import (
21
25
  HPLCMethodParams,
22
26
  MethodDetails,
27
+ TimeTableEntry,
23
28
  Param,
24
29
  PType,
25
- TimeTableEntry,
26
30
  )
27
- from ....utils.table_types import RegisterFlag, T, Table, TableOperation
31
+ from ....utils.table_types import RegisterFlag, T, Table
28
32
  from ..devices.injector import InjectorController
33
+ from ....utils.tray_types import Tray
29
34
 
30
35
 
31
36
  class MethodController(RunController):
@@ -38,9 +43,17 @@ class MethodController(RunController):
38
43
  data_dirs: Optional[List[str]],
39
44
  table: Table,
40
45
  offline: bool,
41
- injector_controller: InjectorController,
46
+ injector: InjectorController,
47
+ pump: PumpController,
48
+ dad: DADController,
49
+ column: ColumnController,
50
+ sample_info: SampleInfo,
42
51
  ):
43
- self.injector_controller = injector_controller
52
+ self.injector = injector
53
+ self.pump = pump
54
+ self.dad = dad
55
+ self.column = column
56
+ self.sample_info = sample_info
44
57
  self.data_files: List[str] = []
45
58
  super().__init__(
46
59
  controller=controller,
@@ -50,6 +63,9 @@ class MethodController(RunController):
50
63
  offline=offline,
51
64
  )
52
65
 
66
+ def get_sample_location(self) -> Tray:
67
+ return self.sample_info.get_location()
68
+
53
69
  def get_current_method_name(self) -> str:
54
70
  self.sleepy_send(Command.GET_METHOD_CMD)
55
71
  res = self.receive()
@@ -60,18 +76,8 @@ class MethodController(RunController):
60
76
  def get_method_params(self) -> HPLCMethodParams:
61
77
  if self.controller:
62
78
  return HPLCMethodParams(
63
- organic_modifier=self.controller.get_num_val(
64
- cmd=TableOperation.GET_OBJ_HDR_VAL.value.format(
65
- register=self.table_locator.register,
66
- register_flag=RegisterFlag.SOLVENT_B_COMPOSITION,
67
- )
68
- ),
69
- flow=self.controller.get_num_val(
70
- cmd=TableOperation.GET_OBJ_HDR_VAL.value.format(
71
- register=self.table_locator.register,
72
- register_flag=RegisterFlag.FLOW,
73
- )
74
- ),
79
+ organic_modifier=self.get_om(),
80
+ flow=self.get_flow(),
75
81
  )
76
82
  raise ValueError("Communication controller is offline!")
77
83
 
@@ -114,23 +120,20 @@ class MethodController(RunController):
114
120
  return entries
115
121
 
116
122
  def load(self) -> MethodDetails:
117
- rows = self.get_num_rows()
118
- if rows.is_ok():
119
- method_name = self.get_method_name()
120
- timetable_rows = self.get_timetable(int(rows.ok_value.num_response))
121
- params = self.get_method_params()
122
- stop_time = self.get_stop_time()
123
- post_time = self.get_post_time()
124
- self.table_state = MethodDetails(
125
- name=method_name,
126
- timetable=timetable_rows,
127
- stop_time=stop_time,
128
- post_time=post_time,
129
- params=params,
130
- )
131
- return self.table_state
132
- else:
133
- raise RuntimeError(rows.err_value)
123
+ rows = self.get_row_count_safely()
124
+ method_name = self.get_method_name()
125
+ timetable_rows = self.get_timetable(rows)
126
+ params = self.get_method_params()
127
+ stop_time = self.get_stop_time()
128
+ post_time = self.get_post_time()
129
+ self.table_state = MethodDetails(
130
+ name=method_name,
131
+ timetable=timetable_rows,
132
+ stop_time=stop_time,
133
+ post_time=post_time,
134
+ params=params,
135
+ )
136
+ return self.table_state
134
137
 
135
138
  def get_method_name(self):
136
139
  self.send(Command.GET_METHOD_CMD)
@@ -138,26 +141,6 @@ class MethodController(RunController):
138
141
  method_name = res.ok_value.string_response
139
142
  return method_name
140
143
 
141
- def get_post_time(self) -> Union[int, float]:
142
- if self.controller:
143
- return self.controller.get_num_val(
144
- cmd=TableOperation.GET_OBJ_HDR_VAL.value.format(
145
- register=self.table_locator.register,
146
- register_flag=RegisterFlag.POST_TIME,
147
- )
148
- )
149
- raise ValueError("Communication controller is not online!")
150
-
151
- def get_stop_time(self) -> Union[int, float]:
152
- if self.controller:
153
- return self.controller.get_num_val(
154
- cmd=TableOperation.GET_OBJ_HDR_VAL.value.format(
155
- register=self.table_locator.register,
156
- register_flag=RegisterFlag.MAX_TIME,
157
- )
158
- )
159
- raise ValueError("Communication controller is not online!")
160
-
161
144
  def get_total_runtime(self) -> Union[int, float]:
162
145
  """Returns total method runtime in minutes."""
163
146
  return self.get_post_time() + self.get_stop_time()
@@ -217,20 +200,14 @@ class MethodController(RunController):
217
200
  self.edit_method_timetable(updated_method.timetable)
218
201
 
219
202
  if save:
220
- self.send(
221
- Command.SAVE_METHOD_CMD.value.format(
222
- commit_msg=f"saved method at {str(time.time())}"
223
- )
224
- )
203
+ self.save_method()
225
204
 
226
- def edit_initial_om(self, new_om: Union[int, float]):
227
- self._validate_organic_modifier(new_om)
228
- initial_organic_modifier: Param = Param(
229
- val=new_om,
230
- chemstation_key=RegisterFlag.SOLVENT_B_COMPOSITION,
231
- ptype=PType.NUM,
205
+ def save_method(self):
206
+ self.send(
207
+ Command.SAVE_METHOD_CMD.value.format(
208
+ commit_msg=f"saved method at {str(time.time())}"
209
+ )
232
210
  )
233
- self._update_param(initial_organic_modifier)
234
211
 
235
212
  def _validate_organic_modifier(self, new_om):
236
213
  if not (isinstance(new_om, int) or isinstance(new_om, float)):
@@ -240,13 +217,6 @@ class MethodController(RunController):
240
217
  if new_om > 100:
241
218
  raise ValueError("Organic modifer must be less than 100.")
242
219
 
243
- def edit_flow(self, new_flow: Union[int, float]):
244
- self._validate_flow(new_flow)
245
- flow: Param = Param(
246
- val=new_flow, chemstation_key=RegisterFlag.FLOW, ptype=PType.NUM
247
- )
248
- self._update_param(flow)
249
-
250
220
  def _validate_flow(self, new_flow):
251
221
  if not (isinstance(new_flow, int) or isinstance(new_flow, float)):
252
222
  raise ValueError("Flow must be int or float")
@@ -255,38 +225,12 @@ class MethodController(RunController):
255
225
  if new_flow >= 5.0:
256
226
  raise ValueError("Flow must be less than 5.0")
257
227
 
258
- def edit_stop_time(self, new_stop_time: Union[int, float]):
259
- self.validate_stop_time(new_stop_time)
260
- stop_time: Param = Param(
261
- val=new_stop_time,
262
- chemstation_key=RegisterFlag.MAX_TIME,
263
- ptype=PType.NUM,
264
- )
265
- self._update_param(
266
- Param(
267
- val="Set", chemstation_key=RegisterFlag.STOPTIME_MODE, ptype=PType.STR
268
- )
269
- )
270
- self._update_param(stop_time)
271
-
272
228
  def validate_stop_time(self, new_stop_time):
273
229
  if not (isinstance(new_stop_time, int) or isinstance(new_stop_time, float)):
274
230
  raise ValueError("Stop time must be int or float")
275
231
  if new_stop_time < 0:
276
232
  raise ValueError("Stop time must be positive")
277
233
 
278
- def edit_post_time(self, new_post_time: Union[int, float]):
279
- self.validate_post_time(new_post_time)
280
- post_time: Param = Param(
281
- val=new_post_time,
282
- chemstation_key=RegisterFlag.POST_TIME,
283
- ptype=PType.NUM,
284
- )
285
- self._update_param(
286
- Param(val="Set", chemstation_key=RegisterFlag.POSTIME_MODE, ptype=PType.STR)
287
- )
288
- self._update_param(post_time)
289
-
290
234
  def validate_post_time(self, new_post_time):
291
235
  if not (isinstance(new_post_time, int) or isinstance(new_post_time, float)):
292
236
  raise ValueError("Post time must be int or float")
@@ -301,59 +245,14 @@ class MethodController(RunController):
301
245
  new_post_time: Union[int, float] | None,
302
246
  ):
303
247
  self.delete_table()
304
- self.edit_initial_om(new_initial_om)
248
+ self._validate_flow(new_flow)
249
+ self.validate_post_time(new_post_time)
250
+ self._validate_organic_modifier(new_initial_om)
251
+ self.validate_stop_time(new_stop_time)
305
252
  self.edit_flow(new_flow)
306
- if new_stop_time:
307
- self.edit_stop_time(new_stop_time)
308
- else:
309
- self._update_param(
310
- Param(
311
- val="Off",
312
- chemstation_key=RegisterFlag.STOPTIME_MODE,
313
- ptype=PType.STR,
314
- )
315
- )
316
- if new_post_time:
317
- self.edit_post_time(new_post_time)
318
- else:
319
- self._update_param(
320
- Param(
321
- val="Off",
322
- chemstation_key=RegisterFlag.POSTIME_MODE,
323
- ptype=PType.STR,
324
- )
325
- )
326
-
327
- def _update_param(self, method_param: Param):
328
- """Change a method parameter, changes what is visibly seen in Chemstation GUI.
329
- (changes the first row in the timetable)
330
-
331
- :param method_param: a parameter to update for currently loaded method.
332
- """
333
- register = self.table_locator.register
334
- setting_command = (
335
- TableOperation.UPDATE_OBJ_HDR_VAL
336
- if method_param.ptype == PType.NUM
337
- else TableOperation.UPDATE_OBJ_HDR_TEXT
338
- )
339
- if isinstance(method_param.chemstation_key, list):
340
- for register_flag in method_param.chemstation_key:
341
- self.sleepy_send(
342
- setting_command.value.format(
343
- register=register,
344
- register_flag=register_flag,
345
- val=method_param.val,
346
- )
347
- )
348
- else:
349
- self.sleepy_send(
350
- setting_command.value.format(
351
- register=register,
352
- register_flag=method_param.chemstation_key,
353
- val=method_param.val,
354
- )
355
- )
356
- self.download()
253
+ self.edit_initial_om(new_initial_om)
254
+ self.edit_stop_time(new_stop_time)
255
+ self.edit_post_time(new_post_time)
357
256
 
358
257
  def download(self):
359
258
  self.sleepy_send("DownloadRCMethod PMP1")
@@ -443,62 +342,6 @@ class MethodController(RunController):
443
342
  self.download()
444
343
  return time_added, flow_added, om_added, function_added
445
344
 
446
- # if first_row:
447
- # time_added = False
448
- # flow_row_method: Callable = (
449
- # self.add_new_col_text
450
- # if row.flow and not row.organic_modifer
451
- # else self._edit_row_text
452
- # )
453
- # if row.organic_modifer:
454
- # self.add_row()
455
- # self.add_new_col_text(
456
- # col_name=RegisterFlag.FUNCTION,
457
- # val=RegisterFlag.SOLVENT_COMPOSITION.value,
458
- # )
459
- # if not time_added:
460
- # time_added = True
461
- # self.add_new_col_num(col_name=RegisterFlag.TIME, val=row.start_time)
462
- # self.add_new_col_num(
463
- # col_name=RegisterFlag.TIMETABLE_SOLVENT_B_COMPOSITION,
464
- # val=row.organic_modifer,
465
- # )
466
- # if row.flow:
467
- # self.add_row()
468
- # self.get_num_rows()
469
- # flow_row_method(
470
- # col_name=RegisterFlag.FUNCTION, val=RegisterFlag.FLOW.value
471
- # )
472
- # if not time_added:
473
- # time_added = True
474
- # self.add_new_col_num(col_name=RegisterFlag.TIME, val=row.start_time)
475
- # self.add_new_col_num(col_name=RegisterFlag.TIMETABLE_FLOW, val=row.flow)
476
- # self._edit_row_num(col_name=RegisterFlag.TIMETABLE_FLOW, val=row.flow)
477
- # self.download()
478
- # else:
479
- # if row.organic_modifer:
480
- # self.add_row()
481
- # self.get_num_rows()
482
- # self._edit_row_text(
483
- # col_name=RegisterFlag.FUNCTION,
484
- # val=RegisterFlag.SOLVENT_COMPOSITION.value,
485
- # )
486
- # self._edit_row_num(col_name=RegisterFlag.TIME, val=row.start_time)
487
- # self._edit_row_num(
488
- # col_name=RegisterFlag.TIMETABLE_SOLVENT_B_COMPOSITION,
489
- # val=row.organic_modifer,
490
- # )
491
- # self.download()
492
- # if row.flow:
493
- # self.add_row()
494
- # self.get_num_rows()
495
- # self._edit_row_text(
496
- # col_name=RegisterFlag.FUNCTION, val=RegisterFlag.FLOW.value
497
- # )
498
- # self._edit_row_num(col_name=RegisterFlag.TIMETABLE_FLOW, val=row.flow)
499
- # self._edit_row_num(col_name=RegisterFlag.TIME, val=row.start_time)
500
- # self.download()
501
-
502
345
  def edit_method_timetable(self, timetable_rows: List[TimeTableEntry]):
503
346
  self.get_num_rows()
504
347
  self.delete_table()
@@ -508,8 +351,8 @@ class MethodController(RunController):
508
351
  res = self.get_num_rows()
509
352
 
510
353
  self.new_table()
511
- num_rows = self.get_num_rows()
512
- if num_rows.ok_value.num_response != 0:
354
+ num_rows = self.get_row_count_safely()
355
+ if num_rows != 0:
513
356
  raise ValueError("Should be zero rows!")
514
357
 
515
358
  time_added = False
@@ -644,3 +487,77 @@ class MethodController(RunController):
644
487
  Row {i + 1} ({timetable[i].start_time}) has a smaller or equal starttime than row {i} ({start_time})"""
645
488
  )
646
489
  self._validate_row(row)
490
+
491
+ def get_om(self):
492
+ return self._read_num_param(RegisterFlag.SOLVENT_B_COMPOSITION)
493
+
494
+ def get_flow(self):
495
+ return self._read_num_param(RegisterFlag.FLOW)
496
+
497
+ def get_post_time(self) -> Union[int, float]:
498
+ return self._read_num_param(RegisterFlag.POST_TIME)
499
+
500
+ def get_stop_time(self) -> Union[int, float]:
501
+ return self._read_num_param(RegisterFlag.MAX_TIME)
502
+
503
+ def edit_post_time(self, new_post_time: Optional[int | float]):
504
+ if new_post_time:
505
+ post_time: Param = Param(
506
+ val=new_post_time,
507
+ chemstation_key=RegisterFlag.POST_TIME,
508
+ ptype=PType.NUM,
509
+ )
510
+ self._update_param(
511
+ Param(
512
+ val="Set",
513
+ chemstation_key=RegisterFlag.POSTIME_MODE,
514
+ ptype=PType.STR,
515
+ )
516
+ )
517
+ self._update_param(post_time)
518
+ else:
519
+ self._update_param(
520
+ Param(
521
+ val="Off",
522
+ chemstation_key=RegisterFlag.POSTIME_MODE,
523
+ ptype=PType.STR,
524
+ )
525
+ )
526
+
527
+ def edit_stop_time(self, new_stop_time: Optional[int | float]):
528
+ if new_stop_time:
529
+ stop_time: Param = Param(
530
+ val=new_stop_time,
531
+ chemstation_key=RegisterFlag.MAX_TIME,
532
+ ptype=PType.NUM,
533
+ )
534
+ self._update_param(
535
+ Param(
536
+ val="Set",
537
+ chemstation_key=RegisterFlag.STOPTIME_MODE,
538
+ ptype=PType.STR,
539
+ )
540
+ )
541
+ self._update_param(stop_time)
542
+ else:
543
+ self._update_param(
544
+ Param(
545
+ val="Off",
546
+ chemstation_key=RegisterFlag.STOPTIME_MODE,
547
+ ptype=PType.STR,
548
+ )
549
+ )
550
+
551
+ def edit_flow(self, new_flow: Union[int, float]):
552
+ flow: Param = Param(
553
+ val=new_flow, chemstation_key=RegisterFlag.FLOW, ptype=PType.NUM
554
+ )
555
+ self._update_param(flow)
556
+
557
+ def edit_initial_om(self, new_om: Union[int, float]):
558
+ initial_organic_modifier: Param = Param(
559
+ val=new_om,
560
+ chemstation_key=RegisterFlag.SOLVENT_B_COMPOSITION,
561
+ ptype=PType.NUM,
562
+ )
563
+ self._update_param(initial_organic_modifier)
@@ -55,19 +55,20 @@ class SequenceController(RunController):
55
55
  )
56
56
 
57
57
  def load(self) -> SequenceTable:
58
- rows = self.get_num_rows()
58
+ rows = self.get_row_count_safely()
59
59
  self.send(Command.GET_SEQUENCE_CMD)
60
60
  seq_name = self.receive()
61
61
 
62
- if rows.is_ok() and seq_name.is_ok():
62
+ if seq_name.is_ok():
63
63
  self.table_state: SequenceTable = SequenceTable(
64
64
  name=seq_name.ok_value.string_response.partition(".S")[0],
65
- rows=[
66
- self.get_row(r + 1) for r in range(int(rows.ok_value.num_response))
67
- ],
65
+ rows=[self.get_row(r + 1) for r in range(int(rows))],
68
66
  )
69
67
  return self.table_state
70
- raise RuntimeError(rows.err_value)
68
+ else:
69
+ raise RuntimeError(
70
+ f"couldn't read rows or sequence name: {seq_name.err_value}"
71
+ )
71
72
 
72
73
  def try_int(self, val: Any) -> Optional[int]:
73
74
  try:
@@ -88,18 +89,17 @@ class SequenceController(RunController):
88
89
  raise ValueError("Expected vial location, is empty.")
89
90
 
90
91
  def get_row(self, row: int) -> SequenceEntry:
91
- sample_name = self.get_text(row, RegisterFlag.NAME)
92
- vial_location = self.try_int(self.get_num(row, RegisterFlag.VIAL_LOCATION))
93
- data_file = self.get_text(row, RegisterFlag.DATA_FILE)
94
- method = self.get_text(row, RegisterFlag.METHOD)
95
- num_inj = self.try_int(self.get_num(row, RegisterFlag.NUM_INJ))
96
- inj_vol = self.try_float(self.get_text(row, RegisterFlag.INJ_VOL))
97
- inj_source = InjectionSource(self.get_text(row, RegisterFlag.INJ_SOR))
98
- sample_type = SampleType(self.get_num(row, RegisterFlag.SAMPLE_TYPE))
99
- vial_enum = self.try_vial_location(vial_location)
92
+ sample_name = self.get_sample_name(row)
93
+ vial_location = self.get_vial_location(row)
94
+ data_file = self.get_data_file(row)
95
+ method = self.get_method(row)
96
+ num_inj = self.get_num_inj(row)
97
+ inj_vol = self.get_inj_vol(row)
98
+ inj_source = self.get_inj_source(row)
99
+ sample_type = self.get_sample_type(row)
100
100
  return SequenceEntry(
101
101
  sample_name=sample_name,
102
- vial_location=vial_enum,
102
+ vial_location=vial_location,
103
103
  method=None if len(method) == 0 else method,
104
104
  num_inj=num_inj,
105
105
  inj_vol=inj_vol,
@@ -108,6 +108,32 @@ class SequenceController(RunController):
108
108
  data_file=data_file,
109
109
  )
110
110
 
111
+ def get_sample_type(self, row):
112
+ return SampleType(self.get_num(row, RegisterFlag.SAMPLE_TYPE))
113
+
114
+ def get_inj_source(self, row):
115
+ return InjectionSource(self.get_text(row, RegisterFlag.INJ_SOR))
116
+
117
+ def get_inj_vol(self, row):
118
+ return self.try_float(self.get_text(row, RegisterFlag.INJ_VOL))
119
+
120
+ def get_num_inj(self, row):
121
+ return self.try_int(self.get_num(row, RegisterFlag.NUM_INJ))
122
+
123
+ def get_method(self, row):
124
+ return self.get_text(row, RegisterFlag.METHOD)
125
+
126
+ def get_data_file(self, row):
127
+ return self.get_text(row, RegisterFlag.DATA_FILE)
128
+
129
+ def get_vial_location(self, row) -> Tray:
130
+ return self.try_vial_location(
131
+ self.try_int(self.get_num(row, RegisterFlag.VIAL_LOCATION))
132
+ )
133
+
134
+ def get_sample_name(self, row):
135
+ return self.get_text(row, RegisterFlag.NAME)
136
+
111
137
  def switch(self, seq_name: str):
112
138
  """
113
139
  Switch to the specified sequence. The sequence name does not need the '.S' extension.
@@ -136,23 +162,21 @@ class SequenceController(RunController):
136
162
  :param sequence_table:
137
163
  """
138
164
  self.table_state = sequence_table
139
- rows = self.get_num_rows()
140
- if rows.is_ok():
141
- existing_row_num = rows.ok_value.num_response
142
- wanted_row_num = len(sequence_table.rows)
143
- for i in range(int(existing_row_num)):
144
- self.delete_row(int(existing_row_num - i))
145
- self.send(Command.SAVE_SEQUENCE_CMD)
146
- for i in range(int(wanted_row_num)):
147
- self.add_row()
148
- self.save()
149
- self.send(Command.SWITCH_SEQUENCE_CMD)
150
-
151
- for i, row in enumerate(sequence_table.rows):
152
- self._edit_row(row=row, row_num=i + 1)
153
- self.sleep(1)
154
- self.save()
155
- self.send(Command.SWITCH_SEQUENCE_CMD)
165
+ rows = self.get_row_count_safely()
166
+ existing_row_num = rows
167
+ wanted_row_num = len(sequence_table.rows)
168
+ for i in range(int(existing_row_num)):
169
+ self.delete_row(int(existing_row_num - i))
170
+ self.send(Command.SAVE_SEQUENCE_CMD)
171
+ for i in range(int(wanted_row_num)):
172
+ self.add_row()
173
+ self.download()
174
+ self.send(Command.SWITCH_SEQUENCE_CMD)
175
+ for i, row in enumerate(sequence_table.rows):
176
+ self._edit_row(row=row, row_num=i + 1)
177
+ self.sleep(1)
178
+ self.download()
179
+ self.send(Command.SWITCH_SEQUENCE_CMD)
156
180
 
157
181
  def _edit_row(self, row: SequenceEntry, row_num: int):
158
182
  """
@@ -161,12 +185,11 @@ class SequenceController(RunController):
161
185
  :param row: sequence row entry with updated information
162
186
  :param row_num: the row to edit, based on 1-based indexing
163
187
  """
164
- num_rows = self.get_num_rows()
165
- if num_rows.is_ok():
166
- while num_rows.ok_value.num_response < row_num:
167
- self.add_row()
168
- self.save()
169
- num_rows = self.get_num_rows()
188
+ num_rows = self.get_row_count_safely()
189
+ while num_rows < row_num:
190
+ self.add_row()
191
+ self.download()
192
+ num_rows = self.get_row_count_safely()
170
193
  if row.vial_location:
171
194
  self.edit_vial_location(row.vial_location, row_num, save=False)
172
195
  if row.method:
@@ -183,7 +206,7 @@ class SequenceController(RunController):
183
206
  self.edit_data_file(row.data_file, row_num, save=False)
184
207
  if row.sample_type:
185
208
  self.edit_sample_type(row.sample_type, row_num, save=False)
186
- self.save()
209
+ self.download()
187
210
 
188
211
  def edit_sample_type(
189
212
  self, sample_type: SampleType, row_num: int, save: bool = True
@@ -196,17 +219,17 @@ class SequenceController(RunController):
196
219
  val=sample_type.value,
197
220
  )
198
221
  if save:
199
- self.save()
222
+ self.download()
200
223
 
201
224
  def edit_data_file(self, data_file: str, row_num: int, save: bool = True):
202
225
  self._edit_row_text(row=row_num, col_name=RegisterFlag.DATA_FILE, val=data_file)
203
226
  if save:
204
- self.save()
227
+ self.download()
205
228
 
206
229
  def edit_sample_name(self, sample_name: str, row_num: int, save: bool = True):
207
230
  self._edit_row_text(row=row_num, col_name=RegisterFlag.NAME, val=sample_name)
208
231
  if save:
209
- self.save()
232
+ self.download()
210
233
 
211
234
  def edit_injection_source(
212
235
  self, inj_source: InjectionSource, row_num: int, save: bool = True
@@ -217,7 +240,7 @@ class SequenceController(RunController):
217
240
  row=row_num, col_name=RegisterFlag.INJ_SOR, val=inj_source.value
218
241
  )
219
242
  if save:
220
- self.save()
243
+ self.download()
221
244
 
222
245
  def edit_injection_volume(
223
246
  self, inj_vol: Union[int, float], row_num: int, save: bool = True
@@ -226,12 +249,12 @@ class SequenceController(RunController):
226
249
  row=row_num, col_name=RegisterFlag.INJ_VOL, val=str(inj_vol)
227
250
  )
228
251
  if save:
229
- self.save()
252
+ self.download()
230
253
 
231
254
  def edit_num_injections(self, num_inj: int, row_num: int, save: bool = True):
232
255
  self._edit_row_num(row=row_num, col_name=RegisterFlag.NUM_INJ, val=num_inj)
233
256
  if save:
234
- self.save()
257
+ self.download()
235
258
 
236
259
  def edit_method_name(
237
260
  self, method: str, row_num: int, save: bool = True, override_check: bool = False
@@ -246,7 +269,7 @@ class SequenceController(RunController):
246
269
  )
247
270
  self._edit_row_text(row=row_num, col_name=RegisterFlag.METHOD, val=method)
248
271
  if save:
249
- self.save()
272
+ self.download()
250
273
 
251
274
  def edit_vial_location(self, loc: Tray, row_num: int, save: bool = True):
252
275
  loc_num = -1
@@ -268,11 +291,11 @@ class SequenceController(RunController):
268
291
  elif isinstance(loc, VialBar) or isinstance(loc, FiftyFourVialPlate):
269
292
  self.add_row()
270
293
  previous_contents.vial_location = loc
271
- num_rows = self.get_num_rows().ok_value.num_response
294
+ num_rows = self.get_row_count_safely()
272
295
  self._edit_row(previous_contents, num_rows)
273
296
  self.move_row(int(num_rows), row_num)
274
297
  self.delete_row(row_num + 1)
275
- self.save()
298
+ self.download()
276
299
  else:
277
300
  raise ValueError(
278
301
  "`loc` should be of type `VialBar`, `FiftyFourVialPlate`"
@@ -290,9 +313,9 @@ class SequenceController(RunController):
290
313
  row=row_num, col_name=RegisterFlag.VIAL_LOCATION, val=loc_num
291
314
  )
292
315
  if save:
293
- self.save()
316
+ self.download()
294
317
 
295
- def save(self):
318
+ def download(self):
296
319
  self.send(Command.SAVE_SEQUENCE_CMD)
297
320
 
298
321
  def run(self, stall_while_running: bool = True):