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.
- {pychemstation-0.6.1 → pychemstation-0.6.3}/PKG-INFO +1 -1
- {pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation/analysis/process_report.py +47 -12
- {pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation/control/controllers/tables/method.py +1 -1
- {pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation/control/controllers/tables/table.py +1 -1
- {pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation/utils/macro.py +1 -0
- {pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation/utils/tray_types.py +13 -9
- {pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation.egg-info/PKG-INFO +1 -1
- {pychemstation-0.6.1 → pychemstation-0.6.3}/setup.py +1 -1
- {pychemstation-0.6.1 → pychemstation-0.6.3}/tests/test_inj.py +10 -4
- pychemstation-0.6.3/tests/test_proc_rep.py +52 -0
- pychemstation-0.6.1/tests/test_proc_rep.py +0 -27
- {pychemstation-0.6.1 → pychemstation-0.6.3}/LICENSE +0 -0
- {pychemstation-0.6.1 → pychemstation-0.6.3}/README.md +0 -0
- {pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation/__init__.py +0 -0
- {pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation/analysis/__init__.py +0 -0
- {pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation/analysis/base_spectrum.py +0 -0
- {pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation/analysis/spec_utils.py +0 -0
- {pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation/analysis/utils.py +0 -0
- {pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation/control/__init__.py +0 -0
- {pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation/control/controllers/__init__.py +0 -0
- {pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation/control/controllers/comm.py +0 -0
- {pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation/control/controllers/devices/__init__.py +0 -0
- {pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation/control/controllers/devices/column.py +0 -0
- {pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation/control/controllers/devices/dad.py +0 -0
- {pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation/control/controllers/devices/device.py +0 -0
- {pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation/control/controllers/devices/injector.py +0 -0
- {pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation/control/controllers/devices/pump.py +0 -0
- {pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation/control/controllers/tables/__init__.py +0 -0
- {pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation/control/controllers/tables/ms.py +0 -0
- {pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation/control/controllers/tables/sequence.py +0 -0
- {pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation/control/hplc.py +0 -0
- {pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation/generated/__init__.py +0 -0
- {pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation/generated/dad_method.py +0 -0
- {pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation/generated/pump_method.py +0 -0
- {pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation/utils/__init__.py +0 -0
- {pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation/utils/chromatogram.py +0 -0
- {pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation/utils/injector_types.py +0 -0
- {pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation/utils/method_types.py +0 -0
- {pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation/utils/parsing.py +0 -0
- {pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation/utils/pump_types.py +0 -0
- {pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation/utils/sequence_types.py +0 -0
- {pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation/utils/table_types.py +0 -0
- {pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation.egg-info/SOURCES.txt +0 -0
- {pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation.egg-info/dependency_links.txt +0 -0
- {pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation.egg-info/requires.txt +0 -0
- {pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation.egg-info/top_level.txt +0 -0
- {pychemstation-0.6.1 → pychemstation-0.6.3}/pyproject.toml +0 -0
- {pychemstation-0.6.1 → pychemstation-0.6.3}/setup.cfg +0 -0
- {pychemstation-0.6.1 → pychemstation-0.6.3}/tests/__init__.py +0 -0
- {pychemstation-0.6.1 → pychemstation-0.6.3}/tests/constants.py +0 -0
- {pychemstation-0.6.1 → pychemstation-0.6.3}/tests/test_comb.py +0 -0
- {pychemstation-0.6.1 → pychemstation-0.6.3}/tests/test_comm.py +0 -0
- {pychemstation-0.6.1 → pychemstation-0.6.3}/tests/test_method.py +0 -0
- {pychemstation-0.6.1 → pychemstation-0.6.3}/tests/test_sequence.py +0 -0
@@ -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
|
215
|
-
|
216
|
-
if os.path.exists(
|
217
|
-
|
218
|
-
|
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")
|
{pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation/control/controllers/tables/method.py
RENAMED
@@ -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.
|
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)
|
{pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation/control/controllers/tables/table.py
RENAMED
@@ -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] =
|
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 =
|
22
|
-
TWO =
|
21
|
+
ONE = 0
|
22
|
+
TWO = 4000
|
23
23
|
|
24
24
|
|
25
25
|
class Letter(Enum):
|
26
|
-
A =
|
27
|
-
B =
|
28
|
-
C =
|
29
|
-
D =
|
30
|
-
F =
|
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]
|
@@ -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.
|
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(
|
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
|
-
|
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
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation/control/controllers/devices/__init__.py
RENAMED
File without changes
|
{pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation/control/controllers/devices/column.py
RENAMED
File without changes
|
{pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation/control/controllers/devices/dad.py
RENAMED
File without changes
|
{pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation/control/controllers/devices/device.py
RENAMED
File without changes
|
{pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation/control/controllers/devices/injector.py
RENAMED
File without changes
|
{pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation/control/controllers/devices/pump.py
RENAMED
File without changes
|
{pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation/control/controllers/tables/__init__.py
RENAMED
File without changes
|
File without changes
|
{pychemstation-0.6.1 → pychemstation-0.6.3}/pychemstation/control/controllers/tables/sequence.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|