pychemstation 0.5.3.dev1__tar.gz → 0.5.5__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.
Files changed (41) hide show
  1. {pychemstation-0.5.3.dev1 → pychemstation-0.5.5}/PKG-INFO +12 -9
  2. {pychemstation-0.5.3.dev1 → pychemstation-0.5.5}/README.md +10 -8
  3. {pychemstation-0.5.3.dev1 → pychemstation-0.5.5}/pychemstation/control/__init__.py +0 -1
  4. {pychemstation-0.5.3.dev1/pychemstation/control/table → pychemstation-0.5.5/pychemstation/control/controllers}/__init__.py +1 -0
  5. {pychemstation-0.5.3.dev1/pychemstation/control → pychemstation-0.5.5/pychemstation/control/controllers}/comm.py +11 -7
  6. {pychemstation-0.5.3.dev1/pychemstation/control/table → pychemstation-0.5.5/pychemstation/control/controllers}/method.py +6 -6
  7. {pychemstation-0.5.3.dev1/pychemstation/control/table → pychemstation-0.5.5/pychemstation/control/controllers}/sequence.py +44 -50
  8. {pychemstation-0.5.3.dev1/pychemstation/control/table → pychemstation-0.5.5/pychemstation/control/controllers}/table_controller.py +36 -12
  9. {pychemstation-0.5.3.dev1 → pychemstation-0.5.5}/pychemstation/control/hplc.py +10 -11
  10. {pychemstation-0.5.3.dev1 → pychemstation-0.5.5}/pychemstation/utils/chromatogram.py +7 -26
  11. {pychemstation-0.5.3.dev1 → pychemstation-0.5.5}/pychemstation/utils/table_types.py +1 -0
  12. {pychemstation-0.5.3.dev1 → pychemstation-0.5.5}/pychemstation.egg-info/PKG-INFO +12 -9
  13. {pychemstation-0.5.3.dev1 → pychemstation-0.5.5}/pychemstation.egg-info/SOURCES.txt +5 -5
  14. {pychemstation-0.5.3.dev1 → pychemstation-0.5.5}/pychemstation.egg-info/requires.txt +1 -0
  15. {pychemstation-0.5.3.dev1 → pychemstation-0.5.5}/setup.py +6 -5
  16. {pychemstation-0.5.3.dev1 → pychemstation-0.5.5}/tests/constants.py +4 -4
  17. pychemstation-0.5.5/tests/test_comb.py +143 -0
  18. {pychemstation-0.5.3.dev1 → pychemstation-0.5.5}/tests/test_sequence.py +48 -0
  19. pychemstation-0.5.3.dev1/tests/test_comb.py +0 -129
  20. {pychemstation-0.5.3.dev1 → pychemstation-0.5.5}/LICENSE +0 -0
  21. {pychemstation-0.5.3.dev1 → pychemstation-0.5.5}/pychemstation/__init__.py +0 -0
  22. {pychemstation-0.5.3.dev1 → pychemstation-0.5.5}/pychemstation/analysis/__init__.py +0 -0
  23. {pychemstation-0.5.3.dev1 → pychemstation-0.5.5}/pychemstation/analysis/base_spectrum.py +0 -0
  24. {pychemstation-0.5.3.dev1 → pychemstation-0.5.5}/pychemstation/analysis/spec_utils.py +0 -0
  25. {pychemstation-0.5.3.dev1 → pychemstation-0.5.5}/pychemstation/analysis/utils.py +0 -0
  26. {pychemstation-0.5.3.dev1 → pychemstation-0.5.5}/pychemstation/generated/__init__.py +0 -0
  27. {pychemstation-0.5.3.dev1 → pychemstation-0.5.5}/pychemstation/generated/dad_method.py +0 -0
  28. {pychemstation-0.5.3.dev1 → pychemstation-0.5.5}/pychemstation/generated/pump_method.py +0 -0
  29. {pychemstation-0.5.3.dev1 → pychemstation-0.5.5}/pychemstation/utils/__init__.py +0 -0
  30. {pychemstation-0.5.3.dev1 → pychemstation-0.5.5}/pychemstation/utils/macro.py +0 -0
  31. {pychemstation-0.5.3.dev1 → pychemstation-0.5.5}/pychemstation/utils/method_types.py +0 -0
  32. {pychemstation-0.5.3.dev1 → pychemstation-0.5.5}/pychemstation/utils/parsing.py +0 -0
  33. {pychemstation-0.5.3.dev1 → pychemstation-0.5.5}/pychemstation/utils/sequence_types.py +0 -0
  34. {pychemstation-0.5.3.dev1 → pychemstation-0.5.5}/pychemstation/utils/tray_types.py +0 -0
  35. {pychemstation-0.5.3.dev1 → pychemstation-0.5.5}/pychemstation.egg-info/dependency_links.txt +0 -0
  36. {pychemstation-0.5.3.dev1 → pychemstation-0.5.5}/pychemstation.egg-info/top_level.txt +0 -0
  37. {pychemstation-0.5.3.dev1 → pychemstation-0.5.5}/pyproject.toml +0 -0
  38. {pychemstation-0.5.3.dev1 → pychemstation-0.5.5}/setup.cfg +0 -0
  39. {pychemstation-0.5.3.dev1 → pychemstation-0.5.5}/tests/__init__.py +0 -0
  40. {pychemstation-0.5.3.dev1 → pychemstation-0.5.5}/tests/test_comm.py +0 -0
  41. {pychemstation-0.5.3.dev1 → pychemstation-0.5.5}/tests/test_method.py +0 -0
@@ -1,8 +1,8 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pychemstation
3
- Version: 0.5.3.dev1
3
+ Version: 0.5.5
4
4
  Summary: Library to interact with Chemstation software, primarily used in Hein lab
5
- Home-page: https://gitlab.com/heingroup/pychemstation
5
+ Home-page: https://gitlab.com/heingroup/device-api/pychemstation
6
6
  Author: Lucy Hao
7
7
  Author-email: lhao03@student.ubc.ca
8
8
  Classifier: Programming Language :: Python :: 3
@@ -12,6 +12,7 @@ Description-Content-Type: text/markdown
12
12
  License-File: LICENSE
13
13
  Requires-Dist: polling
14
14
  Requires-Dist: seabreeze
15
+ Requires-Dist: xsdata
15
16
 
16
17
  # Agilent HPLC Macro Control
17
18
 
@@ -40,7 +41,7 @@ pip install pychemstation
40
41
  where you will put your
41
42
  MACRO file(s).
42
43
  3. Download the [
43
- `hplc_talk.mac`](https://github.com/croningp/analyticallabware/blob/master/AnalyticalLabware/devices/Agilent/hplctalk.mac).
44
+ `hplc_talk.mac`](https://gitlab.com/heingroup/device-api/pychemstation/-/blob/main/tests/hplc_talk.mac).
44
45
  - On line 69, change the path name up to `\cmd` and `\reply`. For instance, you should have:
45
46
  `MonitorFile "[my path]\cmd", "[my path]\reply"`
46
47
  - and then add this file to the folder from the previous step.
@@ -77,13 +78,12 @@ hplc_controller = HPLCController(data_dir=DATA_DIR,
77
78
  hplc_controller.preprun()
78
79
  hplc_controller.switch_method(method_name=DEFAULT_METHOD)
79
80
  hplc_controller.run_method(experiment_name="Run 10")
80
- data_status_valid, chrom = hplc_controller.get_last_run_method_data()
81
+ chrom = hplc_controller.get_last_run_method_data()
81
82
 
82
- if data_status_valid:
83
- # afterwards, save, analyze or plot the data!
84
- values = {"x": chrom.x, "y": chrom.y}
85
- chromatogram_data = pd.DataFrame.from_dict(values)
86
- chromatogram_data.to_csv("Run 10.csv", index=False)
83
+ # afterwards, save, analyze or plot the data!
84
+ values = {"x": chrom.A.x, "y": chrom.A.y}
85
+ chromatogram_data = pd.DataFrame.from_dict(values)
86
+ chromatogram_data.to_csv("Run 10.csv", index=False)
87
87
  ```
88
88
 
89
89
  ## Adding your own MACROs
@@ -102,3 +102,6 @@ Lucy Hao
102
102
 
103
103
  - Adapted from [**AnalyticalLabware**](https://github.com/croningp/analyticallabware), created by members in the Cronin
104
104
  Group. Copyright © Cronin Group, used under the [CC-BY-4.0](https://creativecommons.org/licenses/by/4.0/) license.
105
+ - Adapted from the [MACROS](https://github.com/Bourne-Group/HPLCMethodOptimisationGUI)
106
+ used in [**Operator-free HPLC automated method development guided by Bayesian optimization**](https://pubs.rsc.org/en/content/articlelanding/2024/dd/d4dd00062e),
107
+ created by members in the Bourne Group. Copyright © Bourne Group, used under the [MIT](https://opensource.org/license/mit) license.
@@ -25,7 +25,7 @@ pip install pychemstation
25
25
  where you will put your
26
26
  MACRO file(s).
27
27
  3. Download the [
28
- `hplc_talk.mac`](https://github.com/croningp/analyticallabware/blob/master/AnalyticalLabware/devices/Agilent/hplctalk.mac).
28
+ `hplc_talk.mac`](https://gitlab.com/heingroup/device-api/pychemstation/-/blob/main/tests/hplc_talk.mac).
29
29
  - On line 69, change the path name up to `\cmd` and `\reply`. For instance, you should have:
30
30
  `MonitorFile "[my path]\cmd", "[my path]\reply"`
31
31
  - and then add this file to the folder from the previous step.
@@ -62,13 +62,12 @@ hplc_controller = HPLCController(data_dir=DATA_DIR,
62
62
  hplc_controller.preprun()
63
63
  hplc_controller.switch_method(method_name=DEFAULT_METHOD)
64
64
  hplc_controller.run_method(experiment_name="Run 10")
65
- data_status_valid, chrom = hplc_controller.get_last_run_method_data()
65
+ chrom = hplc_controller.get_last_run_method_data()
66
66
 
67
- if data_status_valid:
68
- # afterwards, save, analyze or plot the data!
69
- values = {"x": chrom.x, "y": chrom.y}
70
- chromatogram_data = pd.DataFrame.from_dict(values)
71
- chromatogram_data.to_csv("Run 10.csv", index=False)
67
+ # afterwards, save, analyze or plot the data!
68
+ values = {"x": chrom.A.x, "y": chrom.A.y}
69
+ chromatogram_data = pd.DataFrame.from_dict(values)
70
+ chromatogram_data.to_csv("Run 10.csv", index=False)
72
71
  ```
73
72
 
74
73
  ## Adding your own MACROs
@@ -86,4 +85,7 @@ our [GitLab](https://gitlab.com/heingroup/device-api/pychemstation)!
86
85
  Lucy Hao
87
86
 
88
87
  - Adapted from [**AnalyticalLabware**](https://github.com/croningp/analyticallabware), created by members in the Cronin
89
- Group. Copyright © Cronin Group, used under the [CC-BY-4.0](https://creativecommons.org/licenses/by/4.0/) license.
88
+ Group. Copyright © Cronin Group, used under the [CC-BY-4.0](https://creativecommons.org/licenses/by/4.0/) license.
89
+ - Adapted from the [MACROS](https://github.com/Bourne-Group/HPLCMethodOptimisationGUI)
90
+ used in [**Operator-free HPLC automated method development guided by Bayesian optimization**](https://pubs.rsc.org/en/content/articlelanding/2024/dd/d4dd00062e),
91
+ created by members in the Bourne Group. Copyright © Bourne Group, used under the [MIT](https://opensource.org/license/mit) license.
@@ -1,5 +1,4 @@
1
1
  """
2
2
  .. include:: README.md
3
3
  """
4
- from .comm import CommunicationController
5
4
  from .hplc import HPLCController
@@ -1,3 +1,4 @@
1
1
  from .method import MethodController
2
2
  from .sequence import SequenceController
3
3
  from .table_controller import TableController
4
+ from .comm import CommunicationController
@@ -14,8 +14,8 @@ import os
14
14
  import time
15
15
 
16
16
  from result import Result, Ok, Err
17
- from ..utils.macro import *
18
- from ..utils.method_types import *
17
+
18
+ from ...utils.macro import *
19
19
 
20
20
 
21
21
  class CommunicationController:
@@ -86,17 +86,18 @@ class CommunicationController:
86
86
 
87
87
  def set_status(self):
88
88
  """Updates current status of HPLC machine"""
89
- self._most_recent_hplc_status = self.get_status()[0]
89
+ self._most_recent_hplc_status = self.get_status()
90
90
 
91
- def check_if_running(self, data_path: str) -> bool:
91
+ def check_if_running(self) -> bool:
92
92
  """Checks if HPLC machine is in an available state, meaning a state that data is not being written.
93
93
 
94
94
  :return: whether the HPLC machine is in a safe state to retrieve data back."""
95
95
  self.set_status()
96
- file_exists = os.path.exists(data_path)
97
96
  hplc_avail = isinstance(self._most_recent_hplc_status, HPLCAvailStatus)
98
- done_writing_data = hplc_avail and file_exists
99
- return done_writing_data
97
+ time.sleep(30)
98
+ self.set_status()
99
+ hplc_actually_avail = isinstance(self._most_recent_hplc_status, HPLCAvailStatus)
100
+ return hplc_avail and hplc_actually_avail
100
101
 
101
102
  def _send(self, cmd: str, cmd_no: int, num_attempts=5) -> None:
102
103
  """Low-level execution primitive. Sends a command string to HPLC.
@@ -170,6 +171,9 @@ class CommunicationController:
170
171
  cmd_to_send: str = cmd.value if isinstance(cmd, Command) else cmd
171
172
  self.cmd_no += 1
172
173
  self._send(cmd_to_send, self.cmd_no)
174
+ f = open("out.txt", "a")
175
+ f.write(cmd_to_send + "\n")
176
+ f.close()
173
177
 
174
178
  def receive(self) -> Result[Response, str]:
175
179
  """Returns messages received in reply file.
@@ -1,13 +1,13 @@
1
1
  import os
2
2
  import time
3
- from typing import Optional, Any
3
+ from typing import Optional
4
4
 
5
5
  from xsdata.formats.dataclass.parsers import XmlParser
6
6
 
7
- from .. import CommunicationController
8
- from ...control.table.table_controller import TableController
7
+ from ...control.controllers.table_controller import TableController
8
+ from ...control.controllers.comm import CommunicationController
9
9
  from ...generated import PumpMethod, DadMethod, SolventElement
10
- from ...utils.chromatogram import TIME_FORMAT, AgilentHPLCChromatogram
10
+ from ...utils.chromatogram import TIME_FORMAT, AgilentChannelChromatogramData
11
11
  from ...utils.macro import Command
12
12
  from ...utils.method_types import PType, TimeTableEntry, Param, MethodTimetable, HPLCMethodParams
13
13
  from ...utils.table_types import RegisterFlag, TableOperation, Table
@@ -269,6 +269,6 @@ class MethodController(TableController):
269
269
  def retrieve_recent_data_files(self) -> str:
270
270
  return self.data_files[-1]
271
271
 
272
- def get_data(self) -> dict[str, AgilentHPLCChromatogram]:
272
+ def get_data(self) -> AgilentChannelChromatogramData:
273
273
  self.get_spectrum(self.data_files[-1])
274
- return self.spectra
274
+ return AgilentChannelChromatogramData(**self.spectra)
@@ -1,17 +1,12 @@
1
- from typing import Any
2
-
3
- from copy import deepcopy
4
-
5
1
  import os
6
2
  import time
7
3
 
8
- from .table_controller import TableController
9
- from ...control import CommunicationController
10
- from ...utils.chromatogram import SEQUENCE_TIME_FORMAT, AgilentHPLCChromatogram
4
+ from ...control.controllers.table_controller import TableController
5
+ from ...control.controllers.comm import CommunicationController
6
+ from ...utils.chromatogram import SEQUENCE_TIME_FORMAT, AgilentChannelChromatogramData
11
7
  from ...utils.macro import Command
12
8
  from ...utils.sequence_types import SequenceTable, SequenceEntry, SequenceDataFiles, InjectionSource, SampleType
13
9
  from ...utils.table_types import TableOperation, RegisterFlag, Table
14
- from ...utils.tray_types import TenColumn
15
10
 
16
11
 
17
12
  class SequenceController(TableController):
@@ -30,7 +25,7 @@ class SequenceController(TableController):
30
25
 
31
26
  if rows.is_ok() and seq_name.is_ok():
32
27
  return SequenceTable(
33
- name=seq_name.ok_value.num_response,
28
+ name=seq_name.ok_value.string_response.partition(".S")[0],
34
29
  rows=[self.get_row(r + 1) for r in range(int(rows.ok_value.num_response))])
35
30
  raise RuntimeError(rows.err_value)
36
31
 
@@ -73,34 +68,25 @@ class SequenceController(TableController):
73
68
 
74
69
  :param sequence_table:
75
70
  """
76
- self.send("Local Rows")
77
- self.sleep(1)
78
- self.delete_table()
79
- self.sleep(1)
80
- self.new_table()
81
- self.sleep(1)
82
- self.get_num_rows()
83
-
84
- if True:
85
- for _ in sequence_table.rows:
86
- self.add_row()
87
- self.sleep(1)
71
+
72
+ rows = self.get_num_rows()
73
+ if rows.is_ok():
74
+ existing_row_num = rows.value.num_response
75
+ wanted_row_num = len(sequence_table.rows)
76
+ while existing_row_num != wanted_row_num:
77
+ if wanted_row_num > existing_row_num:
78
+ self.add_row()
79
+ elif wanted_row_num < existing_row_num:
80
+ self.delete_row(int(existing_row_num))
88
81
  self.send(Command.SAVE_SEQUENCE_CMD)
89
- self.get_num_rows()
90
- self.send(Command.SAVE_SEQUENCE_CMD)
82
+ existing_row_num = self.get_num_rows().ok_value.num_response
83
+ self.send(Command.SWITCH_SEQUENCE_CMD)
84
+
91
85
  for i, row in enumerate(sequence_table.rows):
92
86
  self.edit_row(row=row, row_num=i + 1)
93
87
  self.sleep(1)
94
88
  self.send(Command.SAVE_SEQUENCE_CMD)
95
- else:
96
- for i, row in enumerate(sequence_table.rows):
97
- self.add_row()
98
- self.sleep(0.1)
99
- self.edit_row(row=row, row_num=i + 1)
100
- self.sleep(0.1)
101
- rows = self.get_num_rows()
102
- self.send(Command.SAVE_SEQUENCE_CMD)
103
- self.send(Command.SWITCH_SEQUENCE_CMD)
89
+ self.send(Command.SWITCH_SEQUENCE_CMD)
104
90
 
105
91
  def edit_row(self, row: SequenceEntry, row_num: int):
106
92
  """
@@ -120,13 +106,16 @@ class SequenceController(TableController):
120
106
  table_name = self.table.name
121
107
 
122
108
  if row.vial_location:
109
+ loc = row.vial_location
110
+ if isinstance(row.vial_location, InjectionSource):
111
+ loc = row.vial_location.value
123
112
  self.sleepy_send(TableOperation.EDIT_ROW_VAL.value.format(register=table_register,
124
113
  table_name=table_name,
125
114
  row=row_num,
126
115
  col_name=RegisterFlag.VIAL_LOCATION,
127
- val=row.vial_location.value))
116
+ val=loc))
128
117
  if row.method:
129
- possible_path = os.path.join(self.method_dir, row.method)
118
+ possible_path = os.path.join(self.method_dir, row.method) + ".M\\"
130
119
  method = row.method
131
120
  if os.path.exists(possible_path):
132
121
  method = os.path.join(self.method_dir, row.method)
@@ -177,23 +166,22 @@ class SequenceController(TableController):
177
166
 
178
167
  self.send(Command.SAVE_SEQUENCE_CMD)
179
168
 
180
- def run(self, sequence_table: SequenceTable):
169
+ def run(self):
181
170
  """
182
171
  Starts the currently loaded sequence, storing data
183
172
  under the <data_dir>/<sequence table name> folder.
184
173
  Device must be ready.
185
-
186
- :param sequence_table:
187
174
  """
188
175
  timestamp = time.strftime(SEQUENCE_TIME_FORMAT)
176
+ seq_table = self.load()
189
177
  self.send(Command.RUN_SEQUENCE_CMD.value)
190
178
 
191
179
  if self.check_hplc_is_running():
192
- folder_name = f"{sequence_table.name} {timestamp}"
180
+ folder_name = f"{seq_table.name} {timestamp}"
193
181
  self.data_files.append(SequenceDataFiles(dir=folder_name,
194
- sequence_name=sequence_table.name, ))
182
+ sequence_name=seq_table.name))
195
183
 
196
- run_completed = self.check_hplc_done_running()
184
+ run_completed = self.check_hplc_done_running(sequence=seq_table)
197
185
 
198
186
  if run_completed.is_ok():
199
187
  self.data_files[-1].dir = run_completed.value
@@ -202,16 +190,22 @@ class SequenceController(TableController):
202
190
 
203
191
  def retrieve_recent_data_files(self):
204
192
  sequence_data_files: SequenceDataFiles = self.data_files[-1]
205
- return os.path.join(sequence_data_files.dir, sequence_data_files.child_dirs[-1])
193
+ return sequence_data_files.dir
206
194
 
207
- def get_data(self) -> list[dict[str, AgilentHPLCChromatogram]]:
208
- sequence_data_files: SequenceDataFiles = self.data_files[-1]
195
+ def get_data(self) -> list[AgilentChannelChromatogramData]:
196
+ parent_dir = self.data_files[-1].dir
209
197
  subdirs = [x[0] for x in os.walk(self.data_dir)]
210
- potential_folders = sorted(list(filter(lambda d: sequence_data_files.dir in d, subdirs)))
211
- self.data_files[-1].child_dirs = potential_folders
212
- spectra: list[dict[str, AgilentHPLCChromatogram]] = []
213
- for row in sequence_data_files.child_dirs:
214
- data_path = os.path.join(sequence_data_files.dir, row)
215
- self.get_spectrum(data_path)
216
- spectra.append(deepcopy(self.spectra))
198
+ potential_folders = sorted(list(filter(lambda d: parent_dir in d, subdirs)))
199
+ self.data_files[-1].child_dirs = [f for f in potential_folders if
200
+ parent_dir in f and ".M" not in f and ".D" in f]
201
+
202
+ spectra: list[AgilentChannelChromatogramData] = []
203
+ for row in self.data_files[-1].child_dirs:
204
+ self.get_spectrum(row)
205
+ spectra.append(
206
+ AgilentChannelChromatogramData(
207
+ A=self.spectra["A"],
208
+ B=self.spectra["B"],
209
+ C=self.spectra["C"],
210
+ D=self.spectra["D"]))
217
211
  return spectra
@@ -6,16 +6,17 @@ Authors: Lucy Hao
6
6
 
7
7
  import abc
8
8
  import os
9
+ import time
9
10
  from typing import Union, Optional
10
11
 
11
12
  import polling
12
13
  from result import Result, Ok, Err
13
14
 
14
- from ...control import CommunicationController
15
- from ...utils.chromatogram import AgilentHPLCChromatogram
15
+ from ...control.controllers.comm import CommunicationController
16
+ from ...utils.chromatogram import AgilentHPLCChromatogram, AgilentChannelChromatogramData
16
17
  from ...utils.macro import Command, HPLCRunningStatus, Response
17
18
  from ...utils.method_types import MethodTimetable
18
- from ...utils.sequence_types import SequenceDataFiles
19
+ from ...utils.sequence_types import SequenceDataFiles, SequenceTable
19
20
  from ...utils.table_types import Table, TableOperation, RegisterFlag
20
21
 
21
22
 
@@ -82,6 +83,11 @@ class TableController(abc.ABC):
82
83
  def get_row(self, row: int):
83
84
  pass
84
85
 
86
+ def delete_row(self, row: int):
87
+ self.sleepy_send(TableOperation.DELETE_ROW.value.format(register=self.table.register,
88
+ table_name=self.table.name,
89
+ row=row))
90
+
85
91
  def add_row(self):
86
92
  """
87
93
  Adds a row to the provided table for currently loaded method or sequence.
@@ -124,7 +130,7 @@ class TableController(abc.ABC):
124
130
  res = self.controller.receive()
125
131
 
126
132
  if res.is_ok():
127
- self.send("Sleep 1")
133
+ self.send("Sleep 0.1")
128
134
  self.send('Print Rows')
129
135
  return res
130
136
  else:
@@ -137,24 +143,42 @@ class TableController(abc.ABC):
137
143
  max_tries=10)
138
144
  return started_running
139
145
 
140
- def check_hplc_done_running(self, method: Optional[MethodTimetable] = None) -> Result[str, str]:
146
+ def check_hplc_done_running(self,
147
+ method: Optional[MethodTimetable] = None,
148
+ sequence: Optional[SequenceTable] = None) -> Result[str, str]:
141
149
  """
142
150
  Checks if ChemStation has finished running and can read data back
143
151
 
144
152
  :param method: if you are running a method and want to read back data, the timeout period will be adjusted to be longer than the method's runtime
145
153
  :return: Return True if data can be read back, else False.
146
154
  """
147
- timeout = 10 * 60 if method is None else (method.first_row.maximum_run_time + 2) * 60
155
+ timeout = 10 * 60
156
+ if method:
157
+ timeout = ((method.first_row.maximum_run_time + 2) * 60)
158
+ if sequence:
159
+ timeout *= len(sequence.rows)
160
+
148
161
  most_recent_folder = self.retrieve_recent_data_files()
149
162
  finished_run = polling.poll(
150
- lambda: self.controller.check_if_running(most_recent_folder),
163
+ lambda: self.controller.check_if_running(),
151
164
  timeout=timeout,
152
- step=30
165
+ step=60
153
166
  )
167
+
154
168
  if finished_run:
155
- subdirs = [x[0] for x in os.walk(self.data_dir)]
156
- potential_folders = sorted(list(filter(lambda d: most_recent_folder in d, subdirs)))
157
- return Ok(potential_folders[0])
169
+ if os.path.exists(most_recent_folder):
170
+ return Ok(most_recent_folder)
171
+ else:
172
+ subdirs = [x[0] for x in os.walk(self.data_dir)]
173
+ potential_folders = sorted(list(filter(lambda d: most_recent_folder in d, subdirs)))
174
+ parent_dirs = []
175
+ for folder in potential_folders:
176
+ path = os.path.normpath(folder)
177
+ split_folder = path.split(os.sep)
178
+ if most_recent_folder in split_folder[-1]:
179
+ parent_dirs.append(folder)
180
+ parent_dir = sorted(parent_dirs, reverse=True)[0]
181
+ return Ok(parent_dir)
158
182
  else:
159
183
  return Err("Run did not complete as expected")
160
184
 
@@ -163,7 +187,7 @@ class TableController(abc.ABC):
163
187
  pass
164
188
 
165
189
  @abc.abstractmethod
166
- def get_data(self) -> tuple[bool,]:
190
+ def get_data(self) -> Union[list[AgilentChannelChromatogramData], AgilentChannelChromatogramData]:
167
191
  pass
168
192
 
169
193
  def get_spectrum(self, data_file: str):
@@ -6,9 +6,8 @@ Authors: Lucy Hao
6
6
 
7
7
  from typing import Union, Optional
8
8
 
9
- from ..control import CommunicationController
10
- from ..control.table import MethodController, SequenceController
11
- from ..utils.chromatogram import AgilentHPLCChromatogram
9
+ from ..control.controllers import MethodController, SequenceController, CommunicationController
10
+ from ..utils.chromatogram import AgilentHPLCChromatogram, AgilentChannelChromatogramData
12
11
  from ..utils.macro import Command, HPLCRunningStatus, HPLCAvailStatus, HPLCErrorStatus, Response
13
12
  from ..utils.method_types import MethodTimetable
14
13
  from ..utils.sequence_types import SequenceTable, SequenceEntry
@@ -65,8 +64,8 @@ class HPLCController:
65
64
  only 'General-Poroshell' is needed.
66
65
 
67
66
  :param method_name: any available method in Chemstation method directory
68
- :raise IndexError: Response did not have expected format. Try again.
69
- :raise AssertionError: The desired method is not selected. Try again.
67
+ :raises IndexError: Response did not have expected format. Try again.
68
+ :raises AssertionError: The desired method is not selected. Try again.
70
69
  """
71
70
  self.method_controller.switch(method_name)
72
71
 
@@ -91,15 +90,15 @@ class HPLCController:
91
90
  """
92
91
  self.method_controller.run(experiment_name)
93
92
 
94
- def run_sequence(self, sequence_table: SequenceTable):
93
+ def run_sequence(self):
95
94
  """
96
95
  Starts the currently loaded sequence, storing data
97
96
  under the <data_dir>/<sequence table name> folder.
98
97
  Device must be ready.
99
98
 
100
- :param sequence_table:
99
+ :param sequence_name:
101
100
  """
102
- self.sequence_controller.run(sequence_table)
101
+ self.sequence_controller.run()
103
102
 
104
103
  def edit_method(self, updated_method: MethodTimetable, save: bool = False):
105
104
  """Updated the currently loaded method in ChemStation with provided values.
@@ -114,7 +113,7 @@ class HPLCController:
114
113
  Updates the currently loaded sequence table with the provided table. This method will delete the existing sequence table and remake it.
115
114
  If you would only like to edit a single row of a sequence table, use `edit_sequence_row` instead.
116
115
 
117
- :param sequence_table:
116
+ :param updated_sequence:
118
117
  """
119
118
  self.sequence_controller.edit(updated_sequence)
120
119
 
@@ -127,13 +126,13 @@ class HPLCController:
127
126
  """
128
127
  self.sequence_controller.edit_row(row, num)
129
128
 
130
- def get_last_run_method_data(self) -> dict[str, AgilentHPLCChromatogram]:
129
+ def get_last_run_method_data(self) -> AgilentChannelChromatogramData:
131
130
  """
132
131
  Returns the last run method data.
133
132
  """
134
133
  return self.method_controller.get_data()
135
134
 
136
- def get_last_run_sequence_data(self) -> list[dict[str, AgilentHPLCChromatogram]]:
135
+ def get_last_run_sequence_data(self) -> list[AgilentChannelChromatogramData]:
137
136
  """
138
137
  Returns data for all rows in the last run sequence data.
139
138
  """
@@ -1,17 +1,14 @@
1
1
  """Module for HPLC chromatogram data loading and manipulating"""
2
2
 
3
3
  import os
4
- import logging
5
4
  import time
5
+ from dataclasses import dataclass
6
6
 
7
7
  import numpy as np
8
8
 
9
9
  from .parsing import CHFile
10
10
  from ..analysis import AbstractSpectrum
11
11
 
12
- # Chemstation data path
13
- DATA_DIR = r"C:\Chem32\1\Data"
14
-
15
12
  # standard filenames for spectral data
16
13
  CHANNELS = {"A": "01", "B": "02", "C": "03", "D": "04"}
17
14
 
@@ -105,26 +102,10 @@ class AgilentHPLCChromatogram(AbstractSpectrum):
105
102
  np.savez_compressed(npz_file, times=data.times, values=data.values)
106
103
  return np.array(data.times), np.array(data.values)
107
104
 
108
- def extract_peakarea(self, experiment_dir: str):
109
- """
110
- Reads processed data from Chemstation report files.
111
105
 
112
- Args:
113
- experiment_dir: .D directory with the report files
114
- """
115
- # filename = os.path.join(experiment_dir, f"REPORT{CHANNELS[channel]}.csv")
116
- # TODO parse file properly
117
- # data = np.genfromtxt(filename, delimiter=',')
118
- # return data
119
- pass
120
-
121
- def default_processing(self):
122
- """
123
- Processes the chromatogram in place.
124
- """
125
- # trim first 5 min and last 3 min of run
126
- self.trim(5, 25)
127
- # parameters found to work best for chromatogram data
128
- self.correct_baseline(lmbd=1e5, p=0.0001, n_iter=10)
129
- # get all peaks in processed chromatogram
130
- self.find_peaks()
106
+ @dataclass
107
+ class AgilentChannelChromatogramData:
108
+ A: AgilentHPLCChromatogram
109
+ B: AgilentHPLCChromatogram
110
+ C: AgilentHPLCChromatogram
111
+ D: AgilentHPLCChromatogram
@@ -9,6 +9,7 @@ class TableOperation(Enum):
9
9
  DELETE_TABLE = 'DelTab {register}, "{table_name}"'
10
10
  CREATE_TABLE = 'NewTab {register}, "{table_name}"'
11
11
  NEW_ROW = 'InsTabRow {register}, "{table_name}"'
12
+ DELETE_ROW = 'DelTabRow {register}, "{table_name}", {row}'
12
13
  EDIT_ROW_VAL = 'SetTabVal "{register}", "{table_name}", {row}, "{col_name}", {val}'
13
14
  EDIT_ROW_TEXT = 'SetTabText "{register}", "{table_name}", {row}, "{col_name}", "{val}"'
14
15
  GET_ROW_VAL = 'TabVal("{register}", "{table_name}", {row}, "{col_name}")'
@@ -1,8 +1,8 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pychemstation
3
- Version: 0.5.3.dev1
3
+ Version: 0.5.5
4
4
  Summary: Library to interact with Chemstation software, primarily used in Hein lab
5
- Home-page: https://gitlab.com/heingroup/pychemstation
5
+ Home-page: https://gitlab.com/heingroup/device-api/pychemstation
6
6
  Author: Lucy Hao
7
7
  Author-email: lhao03@student.ubc.ca
8
8
  Classifier: Programming Language :: Python :: 3
@@ -12,6 +12,7 @@ Description-Content-Type: text/markdown
12
12
  License-File: LICENSE
13
13
  Requires-Dist: polling
14
14
  Requires-Dist: seabreeze
15
+ Requires-Dist: xsdata
15
16
 
16
17
  # Agilent HPLC Macro Control
17
18
 
@@ -40,7 +41,7 @@ pip install pychemstation
40
41
  where you will put your
41
42
  MACRO file(s).
42
43
  3. Download the [
43
- `hplc_talk.mac`](https://github.com/croningp/analyticallabware/blob/master/AnalyticalLabware/devices/Agilent/hplctalk.mac).
44
+ `hplc_talk.mac`](https://gitlab.com/heingroup/device-api/pychemstation/-/blob/main/tests/hplc_talk.mac).
44
45
  - On line 69, change the path name up to `\cmd` and `\reply`. For instance, you should have:
45
46
  `MonitorFile "[my path]\cmd", "[my path]\reply"`
46
47
  - and then add this file to the folder from the previous step.
@@ -77,13 +78,12 @@ hplc_controller = HPLCController(data_dir=DATA_DIR,
77
78
  hplc_controller.preprun()
78
79
  hplc_controller.switch_method(method_name=DEFAULT_METHOD)
79
80
  hplc_controller.run_method(experiment_name="Run 10")
80
- data_status_valid, chrom = hplc_controller.get_last_run_method_data()
81
+ chrom = hplc_controller.get_last_run_method_data()
81
82
 
82
- if data_status_valid:
83
- # afterwards, save, analyze or plot the data!
84
- values = {"x": chrom.x, "y": chrom.y}
85
- chromatogram_data = pd.DataFrame.from_dict(values)
86
- chromatogram_data.to_csv("Run 10.csv", index=False)
83
+ # afterwards, save, analyze or plot the data!
84
+ values = {"x": chrom.A.x, "y": chrom.A.y}
85
+ chromatogram_data = pd.DataFrame.from_dict(values)
86
+ chromatogram_data.to_csv("Run 10.csv", index=False)
87
87
  ```
88
88
 
89
89
  ## Adding your own MACROs
@@ -102,3 +102,6 @@ Lucy Hao
102
102
 
103
103
  - Adapted from [**AnalyticalLabware**](https://github.com/croningp/analyticallabware), created by members in the Cronin
104
104
  Group. Copyright © Cronin Group, used under the [CC-BY-4.0](https://creativecommons.org/licenses/by/4.0/) license.
105
+ - Adapted from the [MACROS](https://github.com/Bourne-Group/HPLCMethodOptimisationGUI)
106
+ used in [**Operator-free HPLC automated method development guided by Bayesian optimization**](https://pubs.rsc.org/en/content/articlelanding/2024/dd/d4dd00062e),
107
+ created by members in the Bourne Group. Copyright © Bourne Group, used under the [MIT](https://opensource.org/license/mit) license.
@@ -13,12 +13,12 @@ pychemstation/analysis/base_spectrum.py
13
13
  pychemstation/analysis/spec_utils.py
14
14
  pychemstation/analysis/utils.py
15
15
  pychemstation/control/__init__.py
16
- pychemstation/control/comm.py
17
16
  pychemstation/control/hplc.py
18
- pychemstation/control/table/__init__.py
19
- pychemstation/control/table/method.py
20
- pychemstation/control/table/sequence.py
21
- pychemstation/control/table/table_controller.py
17
+ pychemstation/control/controllers/__init__.py
18
+ pychemstation/control/controllers/comm.py
19
+ pychemstation/control/controllers/method.py
20
+ pychemstation/control/controllers/sequence.py
21
+ pychemstation/control/controllers/table_controller.py
22
22
  pychemstation/generated/__init__.py
23
23
  pychemstation/generated/dad_method.py
24
24
  pychemstation/generated/pump_method.py
@@ -5,21 +5,22 @@ with open("README.md", "r") as fh:
5
5
 
6
6
  setuptools.setup(
7
7
  name="pychemstation",
8
- version="0.5.3.dev1",
8
+ version="0.5.5",
9
9
  author="Lucy Hao",
10
10
  author_email="lhao03@student.ubc.ca",
11
11
  description="Library to interact with Chemstation software, primarily used in Hein lab",
12
12
  long_description=long_description,
13
13
  long_description_content_type="text/markdown",
14
- url="https://gitlab.com/heingroup/pychemstation",
14
+ url="https://gitlab.com/heingroup/device-api/pychemstation",
15
15
  packages=setuptools.find_packages(),
16
16
  install_requires=[
17
- 'polling',
18
- 'seabreeze'
17
+ 'polling',
18
+ 'seabreeze',
19
+ 'xsdata'
19
20
  ],
20
21
  classifiers=[
21
22
  "Programming Language :: Python :: 3",
22
23
  "License :: OSI Approved :: MIT License",
23
24
  "Operating System :: OS Independent",
24
25
  ],
25
- )
26
+ )
@@ -4,7 +4,7 @@ from pychemstation.utils.method_types import *
4
4
  from pychemstation.utils.sequence_types import *
5
5
 
6
6
  DEFAULT_METHOD = "GENERAL-POROSHELL-OPT"
7
- DEFAULT_SEQUENCE = "hplc_testing"
7
+ DEFAULT_SEQUENCE = "LLETest"
8
8
 
9
9
  # CONSTANTS: paths only work in Hein group HPLC machine in room 242
10
10
  DEFAULT_COMMAND_PATH = "C:\\Users\\User\\Desktop\\Lucy\\"
@@ -20,8 +20,8 @@ HEIN_LAB_CONSTANTS = [DEFAULT_COMMAND_PATH,
20
20
  # these CONSTANTS work in rm 254
21
21
  DEFAULT_COMMAND_PATH_254 = "D:\\\git_repositories\\\hplc_comm\\"
22
22
  DEFAULT_METHOD_DIR_254 = "D:\\Chemstation\\1\\Methods\\"
23
- DATA_DIR_254 = "D:\\Chemstation\\1\\Data"
24
- SEQUENCE_DIR_254 = "C:\\1\\Sequence"
23
+ DATA_DIR_254 = "D:\\Chemstation\\1\\Data\\2024-12\\"
24
+ SEQUENCE_DIR_254 = "C:\\1\\Sequence\\"
25
25
 
26
26
  HEIN_LAB_CONSTANTS_254 = [DEFAULT_COMMAND_PATH_254,
27
27
  DEFAULT_METHOD_DIR_254,
@@ -42,7 +42,7 @@ def gen_rand_method():
42
42
  return MethodTimetable(
43
43
  first_row=HPLCMethodParams(
44
44
  organic_modifier=org_modifier,
45
- flow=random.random(),
45
+ flow=round(random.random(), 2),
46
46
  maximum_run_time=max_run_time),
47
47
  subsequent_rows=[
48
48
  TimeTableEntry(
@@ -0,0 +1,143 @@
1
+ import os
2
+
3
+ import unittest
4
+
5
+ from pychemstation.control import HPLCController
6
+ from tests.constants import *
7
+
8
+ run_too = True
9
+
10
+
11
+ class TestCombinations(unittest.TestCase):
12
+ def setUp(self):
13
+ path_constants = room(254)
14
+ for path in path_constants:
15
+ if not os.path.exists(path):
16
+ self.fail(
17
+ f"{path} does not exist on your system. If you would like to run tests, please change this path.")
18
+
19
+ self.hplc_controller = HPLCController(comm_dir=path_constants[0],
20
+ method_dir=path_constants[1],
21
+ data_dir=path_constants[2],
22
+ sequence_dir=path_constants[3])
23
+
24
+ def test_run_method_after_update(self):
25
+ try:
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=2),
32
+ subsequent_rows=[
33
+ TimeTableEntry(
34
+ start_time=0.10,
35
+ organic_modifer=5,
36
+ flow=0.34),
37
+ TimeTableEntry(
38
+ start_time=1,
39
+ organic_modifer=98,
40
+ flow=0.55)])
41
+ self.hplc_controller.edit_method(rand_method, save=True)
42
+ if run_too:
43
+ self.hplc_controller.run_method(experiment_name="changed_method")
44
+ except Exception as e:
45
+ self.fail(f"Should have not failed: {e}")
46
+
47
+ def test_run_after_table_edit(self):
48
+ try:
49
+ self.hplc_controller.switch_sequence(sequence_name=DEFAULT_SEQUENCE)
50
+ seq_table = self.hplc_controller.load_sequence()
51
+ seq_table.rows.append(SequenceEntry(
52
+ vial_location=TenColumn.ONE,
53
+ method=DEFAULT_METHOD,
54
+ num_inj=3,
55
+ inj_vol=4,
56
+ sample_name="Sampel1",
57
+ sample_type=SampleType.SAMPLE,
58
+ ))
59
+ seq_table.rows[0] = SequenceEntry(
60
+ vial_location=TenColumn.ONE,
61
+ method=DEFAULT_METHOD,
62
+ num_inj=3,
63
+ inj_vol=4,
64
+ sample_name="Sampel2",
65
+ sample_type=SampleType.SAMPLE)
66
+ self.hplc_controller.edit_sequence(seq_table)
67
+ if run_too:
68
+ self.hplc_controller.run_sequence()
69
+ chrom = self.hplc_controller.get_last_run_sequence_data()
70
+ self.assertTrue(len(chrom) == 2)
71
+ except Exception as e:
72
+ self.fail("Failed")
73
+
74
+ def test_run_after_existing_row_edit(self):
75
+ try:
76
+ self.hplc_controller.switch_sequence(sequence_name=DEFAULT_SEQUENCE)
77
+ seq_table = self.hplc_controller.load_sequence()
78
+ self.hplc_controller.edit_sequence_row(seq_entry, 1)
79
+ if run_too:
80
+ self.hplc_controller.run_sequence()
81
+ chrom = self.hplc_controller.get_last_run_sequence_data()
82
+ self.assertTrue(len(chrom) == 2)
83
+ except Exception:
84
+ self.fail("Failed")
85
+
86
+ def test_update_method_update_seq_table_run(self):
87
+ try:
88
+ self.hplc_controller.method_controller.switch(DEFAULT_METHOD)
89
+ rand_method = MethodTimetable(
90
+ first_row=HPLCMethodParams(
91
+ organic_modifier=5,
92
+ flow=0.65,
93
+ maximum_run_time=2),
94
+ subsequent_rows=[
95
+ TimeTableEntry(
96
+ start_time=0.50,
97
+ organic_modifer=99,
98
+ flow=0.34)])
99
+ self.hplc_controller.edit_method(rand_method, save=True)
100
+
101
+ self.hplc_controller.switch_sequence(sequence_name=DEFAULT_SEQUENCE)
102
+ seq_table = SequenceTable(
103
+ 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
+ )
125
+
126
+ self.hplc_controller.edit_sequence(seq_table)
127
+ if run_too:
128
+ self.hplc_controller.preprun()
129
+ self.hplc_controller.run_sequence()
130
+ chrom = self.hplc_controller.get_last_run_sequence_data()
131
+ self.assertTrue(len(chrom) == 2)
132
+ except Exception:
133
+ self.fail("Failed")
134
+
135
+ def test_run_sequence(self):
136
+ try:
137
+ self.hplc_controller.switch_sequence(sequence_name=DEFAULT_SEQUENCE)
138
+ self.hplc_controller.preprun()
139
+ self.hplc_controller.run_sequence()
140
+ chrom = self.hplc_controller.get_last_run_sequence_data()
141
+ self.assertTrue(len(chrom) == 2)
142
+ except Exception:
143
+ self.fail("Failed")
@@ -63,6 +63,54 @@ class TestSequence(unittest.TestCase):
63
63
  sample_name="Sampel2",
64
64
  sample_type=SampleType.SAMPLE,
65
65
  inj_source=InjectionSource.HIP_ALS
66
+ ),
67
+ SequenceEntry(
68
+ vial_location=TenColumn.TEN,
69
+ method=DEFAULT_METHOD,
70
+ num_inj=3,
71
+ inj_vol=4,
72
+ sample_name="Sampel2",
73
+ sample_type=SampleType.SAMPLE,
74
+ inj_source=InjectionSource.HIP_ALS
75
+ ),
76
+ SequenceEntry(
77
+ vial_location=TenColumn.THREE,
78
+ method=DEFAULT_METHOD,
79
+ num_inj=3,
80
+ inj_vol=4,
81
+ sample_name="Sampel2",
82
+ sample_type=SampleType.SAMPLE,
83
+ inj_source=InjectionSource.HIP_ALS
84
+ )
85
+ ]
86
+ )
87
+ self.hplc_controller.edit_sequence(seq_table)
88
+ except Exception:
89
+ self.fail("Should have not occured")
90
+
91
+ def test_edit_entire_table_less_rows(self):
92
+ self.hplc_controller.switch_sequence(sequence_name=DEFAULT_SEQUENCE)
93
+ try:
94
+ seq_table = SequenceTable(
95
+ name=DEFAULT_SEQUENCE,
96
+ rows=[
97
+ SequenceEntry(
98
+ vial_location=TenColumn.TEN,
99
+ method=DEFAULT_METHOD,
100
+ num_inj=3,
101
+ inj_vol=4,
102
+ sample_name="Sampel2",
103
+ sample_type=SampleType.SAMPLE,
104
+ inj_source=InjectionSource.HIP_ALS
105
+ ),
106
+ SequenceEntry(
107
+ vial_location=TenColumn.THREE,
108
+ method=DEFAULT_METHOD,
109
+ num_inj=3,
110
+ inj_vol=4,
111
+ sample_name="Sampel2",
112
+ sample_type=SampleType.SAMPLE,
113
+ inj_source=InjectionSource.HIP_ALS
66
114
  )
67
115
  ]
68
116
  )
@@ -1,129 +0,0 @@
1
- import os
2
-
3
- import unittest
4
-
5
- from pychemstation.control import HPLCController
6
- from tests.constants import *
7
-
8
- run_too = False
9
-
10
-
11
-
12
-
13
- class TestCombinations(unittest.TestCase):
14
- def setUp(self):
15
- path_constants = room(254)
16
- for path in path_constants:
17
- if not os.path.exists(path):
18
- self.fail(
19
- f"{path} does not exist on your system. If you would like to run tests, please change this path.")
20
-
21
- self.hplc_controller = HPLCController(comm_dir=path_constants[0],
22
- method_dir=path_constants[1],
23
- data_dir=path_constants[2],
24
- sequence_dir=path_constants[3])
25
-
26
- def test_run_method_after_update(self):
27
- self.hplc_controller.method_controller.switch(DEFAULT_METHOD)
28
-
29
- try:
30
- rand_method = gen_rand_method()
31
- self.hplc_controller.edit_method(rand_method)
32
- if run_too:
33
- self.hplc_controller.run_method(experiment_name="changed_method")
34
- except Exception as e:
35
- self.fail(f"Should have not failed: {e}")
36
-
37
- def test_run_after_table_edit(self):
38
- try:
39
- self.hplc_controller.switch_sequence(sequence_name=DEFAULT_SEQUENCE)
40
- seq_table = self.hplc_controller.load_sequence()
41
- seq_table.rows[0].vial_location = TenColumn.FIVE
42
- seq_table.rows[1].vial_location = TenColumn.ONE
43
- seq_table.rows[0].inj_source = InjectionSource.HIP_ALS
44
- seq_table.rows[1].inj_source = InjectionSource.MANUAL
45
- self.hplc_controller.edit_sequence(seq_table)
46
- if run_too:
47
- self.hplc_controller.run_sequence(seq_table)
48
- chrom = self.hplc_controller.get_last_run_sequence_data()
49
- self.assertTrue(len(chrom) == 2)
50
- except Exception as e:
51
- self.fail("Failed")
52
-
53
- def test_run_after_existing_row_edit(self):
54
- try:
55
- self.hplc_controller.switch_sequence(sequence_name=DEFAULT_SEQUENCE)
56
- seq_table = self.hplc_controller.load_sequence()
57
- self.hplc_controller.edit_sequence_row(seq_entry, 1)
58
- if run_too:
59
- self.hplc_controller.run_sequence(seq_table)
60
- chrom = self.hplc_controller.get_last_run_sequence_data()
61
- self.assertTrue(len(chrom) == 2)
62
- except Exception:
63
- self.fail("Failed")
64
-
65
- def test_update_method_update_seq_table_run(self):
66
- try:
67
- self.hplc_controller.method_controller.switch(DEFAULT_METHOD)
68
- rand_method = gen_rand_method()
69
- self.hplc_controller.edit_method(rand_method, save=True)
70
-
71
- self.hplc_controller.switch_sequence(sequence_name=DEFAULT_SEQUENCE)
72
- seq_table = self.hplc_controller.load_sequence()
73
- seq_table.rows[0].vial_location = TenColumn.ONE
74
- seq_table.rows[0].inj_source = InjectionSource.HIP_ALS
75
- seq_table.rows[1].vial_location = TenColumn.TWO
76
- seq_table.rows[1].inj_source = InjectionSource.HIP_ALS
77
- self.hplc_controller.edit_sequence(seq_table)
78
-
79
- if run_too:
80
- self.hplc_controller.run_sequence(seq_table)
81
- chrom = self.hplc_controller.get_last_run_sequence_data()
82
- self.assertTrue(len(chrom) == 2)
83
- except Exception:
84
- self.fail("Failed")
85
-
86
- def test_update_table_then_row(self):
87
- try:
88
- self.hplc_controller.method_controller.switch(DEFAULT_METHOD)
89
- self.hplc_controller.switch_sequence(sequence_name=DEFAULT_SEQUENCE)
90
- rand_method = gen_rand_method()
91
- self.hplc_controller.edit_method(rand_method, save=True)
92
-
93
- seq_table = self.hplc_controller.load_sequence()
94
- seq_table.rows[0].vial_location = TenColumn.ONE
95
- seq_table.rows[0].inj_source = InjectionSource.HIP_ALS
96
- seq_table.rows[0].method = DEFAULT_METHOD
97
- seq_table.rows[1].vial_location = TenColumn.TWO
98
- seq_table.rows[1].inj_source = InjectionSource.HIP_ALS
99
- seq_table.rows[1].method = DEFAULT_METHOD
100
-
101
- self.hplc_controller.edit_sequence(seq_table)
102
- self.hplc_controller.edit_sequence_row(
103
- SequenceEntry(
104
- vial_location=TenColumn.ONE,
105
- method=DEFAULT_METHOD,
106
- num_inj=3,
107
- inj_vol=4,
108
- sample_name="Blank",
109
- sample_type=SampleType.BLANK,
110
- )
111
- )
112
- if run_too:
113
- self.hplc_controller.run_sequence(seq_table)
114
- chrom = self.hplc_controller.get_last_run_sequence_data()
115
- self.assertTrue(len(chrom) == 2)
116
- except Exception:
117
- self.fail("Failed")
118
-
119
- def test_run_after_new_row_edit(self):
120
- try:
121
- self.hplc_controller.switch_sequence(sequence_name=DEFAULT_SEQUENCE)
122
- seq_table = self.hplc_controller.load_sequence()
123
- self.hplc_controller.edit_sequence_row(seq_entry, 3)
124
- if run_too:
125
- self.hplc_controller.run_sequence(seq_table)
126
- chrom = self.hplc_controller.get_last_run_sequence_data()
127
- self.assertTrue(len(chrom) == 2)
128
- except Exception:
129
- self.fail("Failed")