pychemstation 0.6.1__tar.gz → 0.6.3__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 (54) hide show
  1. {pychemstation-0.6.1 → pychemstation-0.6.3}/PKG-INFO +1 -1
  2. {pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation/analysis/process_report.py +47 -12
  3. {pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation/control/controllers/tables/method.py +1 -1
  4. {pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation/control/controllers/tables/table.py +1 -1
  5. {pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation/utils/macro.py +1 -0
  6. {pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation/utils/tray_types.py +13 -9
  7. {pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation.egg-info/PKG-INFO +1 -1
  8. {pychemstation-0.6.1 → pychemstation-0.6.3}/setup.py +1 -1
  9. {pychemstation-0.6.1 → pychemstation-0.6.3}/tests/test_inj.py +10 -4
  10. pychemstation-0.6.3/tests/test_proc_rep.py +52 -0
  11. pychemstation-0.6.1/tests/test_proc_rep.py +0 -27
  12. {pychemstation-0.6.1 → pychemstation-0.6.3}/LICENSE +0 -0
  13. {pychemstation-0.6.1 → pychemstation-0.6.3}/README.md +0 -0
  14. {pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation/__init__.py +0 -0
  15. {pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation/analysis/__init__.py +0 -0
  16. {pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation/analysis/base_spectrum.py +0 -0
  17. {pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation/analysis/spec_utils.py +0 -0
  18. {pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation/analysis/utils.py +0 -0
  19. {pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation/control/__init__.py +0 -0
  20. {pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation/control/controllers/__init__.py +0 -0
  21. {pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation/control/controllers/comm.py +0 -0
  22. {pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation/control/controllers/devices/__init__.py +0 -0
  23. {pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation/control/controllers/devices/column.py +0 -0
  24. {pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation/control/controllers/devices/dad.py +0 -0
  25. {pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation/control/controllers/devices/device.py +0 -0
  26. {pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation/control/controllers/devices/injector.py +0 -0
  27. {pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation/control/controllers/devices/pump.py +0 -0
  28. {pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation/control/controllers/tables/__init__.py +0 -0
  29. {pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation/control/controllers/tables/ms.py +0 -0
  30. {pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation/control/controllers/tables/sequence.py +0 -0
  31. {pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation/control/hplc.py +0 -0
  32. {pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation/generated/__init__.py +0 -0
  33. {pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation/generated/dad_method.py +0 -0
  34. {pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation/generated/pump_method.py +0 -0
  35. {pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation/utils/__init__.py +0 -0
  36. {pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation/utils/chromatogram.py +0 -0
  37. {pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation/utils/injector_types.py +0 -0
  38. {pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation/utils/method_types.py +0 -0
  39. {pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation/utils/parsing.py +0 -0
  40. {pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation/utils/pump_types.py +0 -0
  41. {pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation/utils/sequence_types.py +0 -0
  42. {pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation/utils/table_types.py +0 -0
  43. {pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation.egg-info/SOURCES.txt +0 -0
  44. {pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation.egg-info/dependency_links.txt +0 -0
  45. {pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation.egg-info/requires.txt +0 -0
  46. {pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation.egg-info/top_level.txt +0 -0
  47. {pychemstation-0.6.1 → pychemstation-0.6.3}/pyproject.toml +0 -0
  48. {pychemstation-0.6.1 → pychemstation-0.6.3}/setup.cfg +0 -0
  49. {pychemstation-0.6.1 → pychemstation-0.6.3}/tests/__init__.py +0 -0
  50. {pychemstation-0.6.1 → pychemstation-0.6.3}/tests/constants.py +0 -0
  51. {pychemstation-0.6.1 → pychemstation-0.6.3}/tests/test_comb.py +0 -0
  52. {pychemstation-0.6.1 → pychemstation-0.6.3}/tests/test_comm.py +0 -0
  53. {pychemstation-0.6.1 → pychemstation-0.6.3}/tests/test_method.py +0 -0
  54. {pychemstation-0.6.1 → pychemstation-0.6.3}/tests/test_sequence.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pychemstation
3
- Version: 0.6.1
3
+ Version: 0.6.3
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
@@ -1,18 +1,15 @@
1
- """
2
- pip install pandas
3
- pip install aghplctools==4.8.6
4
- """
5
-
6
1
  import os
7
2
  import re
8
3
  from dataclasses import dataclass
9
- from typing import List, AnyStr
4
+ from typing import List, AnyStr, Dict
10
5
 
11
6
  import pandas as pd
12
7
  from aghplctools.ingestion.text import _no_peaks_re, _area_report_re, _header_block_re, _signal_info_re, \
13
8
  _signal_table_re, chunk_string
14
9
  from result import Result, Err, Ok
15
10
 
11
+ from pychemstation.utils.tray_types import FiftyFourVialPlate, int_to_ffvp, Tray
12
+
16
13
 
17
14
  @dataclass
18
15
  class AgilentPeak:
@@ -25,6 +22,13 @@ class AgilentPeak:
25
22
  height_percent: float
26
23
 
27
24
 
25
+ @dataclass
26
+ class AgilentReport:
27
+ vial_location: Tray
28
+ signals: Dict[AnyStr, List[AgilentPeak]]
29
+ solvents: Dict[AnyStr, AnyStr]
30
+
31
+
28
32
  _column_re_dictionary = { # regex matches for column and unit combinations
29
33
  'Peak': { # peak index
30
34
  '#': '[ ]+(?P<Peak>[\d]+)', # number
@@ -51,7 +55,7 @@ _column_re_dictionary = { # regex matches for column and unit combinations
51
55
  }
52
56
 
53
57
 
54
- def build_peak_regex(signal_table: str):
58
+ def build_peak_regex(signal_table: str) -> re.Pattern[AnyStr]:
55
59
  """
56
60
  Builds a peak regex from a signal table
57
61
 
@@ -211,9 +215,40 @@ def process_folder(folder_path, target_wavelengths=None, min_retention_time=0, m
211
215
  return results_df
212
216
 
213
217
 
214
- def process_csv_report(folder_path: str, num: int) -> Result[List[AgilentPeak], AnyStr]:
215
- potential_report = os.path.join(folder_path, f'REPORT0{num}.CSV')
216
- if os.path.exists(potential_report):
217
- df = pd.read_csv(potential_report, encoding="utf-16", header=None)
218
- return Ok(df.apply(lambda row: AgilentPeak(*row), axis=1))
218
+ def process_csv_report(folder_path: str) -> Result[AgilentReport, AnyStr]:
219
+ labels = os.path.join(folder_path, f'REPORT00.CSV')
220
+ if os.path.exists(labels):
221
+ df_labels: Dict[int, Dict[int: AnyStr]] = pd.read_csv(labels, encoding="utf-16", header=None).to_dict()
222
+ vial_location = []
223
+ signals = {}
224
+ solvents = {}
225
+ for pos, val in df_labels[0].items():
226
+ if val == "Location":
227
+ vial_location = df_labels[1][pos]
228
+ elif "Solvent" in val:
229
+ if val not in solvents.keys():
230
+ solvents[val] = df_labels[2][pos]
231
+ elif val == "Number of Signals":
232
+ num_signals = int(df_labels[1][pos])
233
+ for s in range(1, num_signals + 1):
234
+ peaks = process_peaks(os.path.join(folder_path, f'REPORT0{s}.CSV'))
235
+ if peaks.is_ok():
236
+ wavelength = df_labels[1][pos + s].partition(",4 Ref=off")[0][-3:]
237
+ signals[wavelength] = peaks.ok_value
238
+ break
239
+
240
+ return Ok(AgilentReport(
241
+ signals=signals,
242
+ vial_location=int_to_ffvp(vial_location),
243
+ solvents=solvents
244
+ ))
245
+
219
246
  return Err("No report found")
247
+
248
+
249
+ def process_peaks(folder_path: str) -> Result[List[AgilentPeak], AnyStr]:
250
+ try:
251
+ df = pd.read_csv(folder_path, encoding="utf-16", header=None)
252
+ return Ok(df.apply(lambda row: AgilentPeak(*row), axis=1))
253
+ except Exception:
254
+ return Err("Trouble reading report")
@@ -132,7 +132,7 @@ class MethodController(TableController):
132
132
  :raise IndexError: Response did not have expected format. Try again.
133
133
  :raise AssertionError: The desired method is not selected. Try again.
134
134
  """
135
- self.send(Command.SWITCH_METHOD_CMD.value.format(method_dir=self.src,
135
+ self.send(Command.SWITCH_METHOD_CMD_SPECIFIC.value.format(method_dir=self.src,
136
136
  method_name=method_name))
137
137
 
138
138
  time.sleep(2)
@@ -305,5 +305,5 @@ class TableController(abc.ABC):
305
305
  try:
306
306
  spec.load_spectrum(data_path=data_path, channel=channel)
307
307
  except FileNotFoundError:
308
- self.spectra[channel] = None
308
+ self.spectra[channel] = AgilentHPLCChromatogram(self.data_dir)
309
309
  print(f"No data at channel: {channel}")
@@ -38,6 +38,7 @@ class Command(Enum):
38
38
  GET_METHOD_CMD = "response$ = _MethFile$"
39
39
  GET_ROWS_CMD = 'response_num = TabHdrVal({register}, "{table_name}", "{col_name}")'
40
40
  SWITCH_METHOD_CMD = 'LoadMethod _MethPath$, _MethFile$'
41
+ SWITCH_METHOD_CMD_SPECIFIC = 'LoadMethod "{method_dir}", "{method_name}.M"'
41
42
  START_METHOD_CMD = "StartMethod"
42
43
  RUN_METHOD_CMD = 'RunMethod "{data_dir}",, "{experiment_name}_{timestamp}"'
43
44
  STOP_METHOD_CMD = "StopMethod"
@@ -18,16 +18,16 @@ class Num(Enum):
18
18
 
19
19
 
20
20
  class Plate(Enum):
21
- ONE = "1"
22
- TWO = "2"
21
+ ONE = 0
22
+ TWO = 4000
23
23
 
24
24
 
25
25
  class Letter(Enum):
26
- A = 8191
27
- B = 8255
28
- C = 8319
29
- D = 8383
30
- F = 8447
26
+ A = 4191
27
+ B = 4255
28
+ C = 4319
29
+ D = 4383
30
+ F = 4447
31
31
 
32
32
 
33
33
  @dataclass
@@ -37,7 +37,11 @@ class FiftyFourVialPlate:
37
37
  num: Num
38
38
 
39
39
  def value(self) -> int:
40
- return self.letter.value + self.num.value
40
+ return self.plate.value + self.letter.value + self.num.value
41
+
42
+
43
+ def int_to_ffvp(num: int) -> FiftyFourVialPlate:
44
+ return num
41
45
 
42
46
 
43
47
  class TenVialColumn(Enum):
@@ -53,4 +57,4 @@ class TenVialColumn(Enum):
53
57
  TEN = 10
54
58
 
55
59
 
56
- Tray = Union[FiftyFourVialPlate, TenVialColumn]
60
+ Tray = Union[FiftyFourVialPlate, TenVialColumn]
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pychemstation
3
- Version: 0.6.1
3
+ Version: 0.6.3
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
@@ -5,7 +5,7 @@ with open("README.md", "r") as fh:
5
5
 
6
6
  setuptools.setup(
7
7
  name="pychemstation",
8
- version="0.6.1",
8
+ version="0.6.3",
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",
@@ -2,22 +2,27 @@ import os
2
2
  import unittest
3
3
 
4
4
  from pychemstation.control import HPLCController
5
+ from pychemstation.utils.tray_types import FiftyFourVialPlate, Letter, Plate, Num
5
6
  from tests.constants import *
6
7
 
8
+ offline = True
9
+
7
10
 
8
11
  class TestInj(unittest.TestCase):
9
12
  def setUp(self):
10
13
  path_constants = room(254)
11
14
  for path in path_constants:
12
- if not os.path.exists(path):
15
+ if not offline and not os.path.exists(path):
13
16
  self.fail(
14
17
  f"{path} does not exist on your system. If you would like to run tests, please change this path.")
15
18
 
16
- self.hplc_controller = HPLCController(comm_dir=path_constants[0],
19
+ self.hplc_controller = HPLCController(offline=offline,
20
+ comm_dir=path_constants[0],
17
21
  method_dir=path_constants[1],
18
22
  data_dir=path_constants[2],
19
23
  sequence_dir=path_constants[3])
20
- # self.hplc_controller.switch_method(DEFAULT_METHOD)
24
+ if not offline:
25
+ self.hplc_controller.switch_method(DEFAULT_METHOD)
21
26
 
22
27
  def test_load_inj(self):
23
28
  try:
@@ -26,7 +31,8 @@ class TestInj(unittest.TestCase):
26
31
  except Exception as e:
27
32
  self.fail(f"Should have not failed, {e}")
28
33
 
29
-
34
+ def test_plate_number(self):
35
+ self.assertEqual(4096, FiftyFourVialPlate(plate=Plate.ONE, letter=Letter.A, num=Num.FOUR).value())
30
36
 
31
37
 
32
38
  if __name__ == '__main__':
@@ -0,0 +1,52 @@
1
+ import unittest
2
+
3
+ from result import Result
4
+
5
+ from pychemstation.analysis.process_report import process_csv_report
6
+
7
+
8
+ class TestReport(unittest.TestCase):
9
+
10
+ def test_build_peak_regex(self):
11
+ try:
12
+ # TODO
13
+ print('yes')
14
+ except Exception as e:
15
+ self.fail(f"Should have not failed, {e}")
16
+
17
+ def test_parse_area_report(self):
18
+ try:
19
+ # TODO
20
+ print('yes')
21
+ except Exception as e:
22
+ self.fail(f"Should have not failed, {e}")
23
+
24
+ def test_process_export_report(self):
25
+ try:
26
+ import pandas as pd
27
+
28
+ file_path = "/Users/lucyhao/Codes/pychemstation/tests/0_2025-03-15 19-14-35.D/Report00.CSV"
29
+ df = pd.read_csv(file_path, encoding="utf-16")
30
+
31
+ # Print the first column
32
+ print(df)
33
+ except Exception as e:
34
+ self.fail(f"Should have not failed, {e}")
35
+
36
+ def test_process_folder(self):
37
+ try:
38
+ # TODO
39
+ print('yes')
40
+ except Exception as e:
41
+ self.fail(f"Should have not failed, {e}")
42
+
43
+ def test_report_csv(self):
44
+ try:
45
+ report: Result = process_csv_report(folder_path="0_2025-03-15 19-14-35.D")
46
+ print(report)
47
+ except Exception as e:
48
+ self.fail(f"Should have not failed: {e}")
49
+
50
+
51
+ if __name__ == '__main__':
52
+ unittest.main()
@@ -1,27 +0,0 @@
1
- import unittest
2
-
3
- from result import Result
4
-
5
- from pychemstation.analysis.process_report import process_csv_report
6
-
7
-
8
- class TestReport(unittest.TestCase):
9
-
10
- def test_process_reporttxt(self):
11
- try:
12
- # TODO
13
- print('yes')
14
- except Exception as e:
15
- self.fail(f"Should have not failed, {e}")
16
-
17
- def test_report_csv(self):
18
- try:
19
- possible_peaks: Result = process_csv_report(folder_path="0_2025-03-15 19-14-35.D", num=1)
20
- self.assertTrue(len(possible_peaks.ok_value) == 16)
21
- print('yes')
22
- except Exception as e:
23
- self.fail(f"Should have not failed: {e}")
24
-
25
-
26
- if __name__ == '__main__':
27
- unittest.main()
File without changes
File without changes
File without changes