pychemstation 0.10.5__tar.gz → 0.10.6__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.10.5 → pychemstation-0.10.6}/.gitignore +1 -1
- {pychemstation-0.10.5 → pychemstation-0.10.6}/PKG-INFO +1 -1
- pychemstation-0.10.6/pychemstation/analysis/__init__.py +11 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/pychemstation/control/controllers/__init__.py +2 -2
- pychemstation-0.10.6/pychemstation/control/controllers/abc_tables/device.py +15 -0
- pychemstation-0.10.5/pychemstation/control/controllers/tables/table.py → pychemstation-0.10.6/pychemstation/control/controllers/abc_tables/run.py +24 -195
- pychemstation-0.10.6/pychemstation/control/controllers/abc_tables/table.py +221 -0
- pychemstation-0.10.6/pychemstation/control/controllers/comm.py +150 -0
- {pychemstation-0.10.5/pychemstation/control/controllers/tables → pychemstation-0.10.6/pychemstation/control/controllers/data_aq}/method.py +2 -2
- {pychemstation-0.10.5/pychemstation/control/controllers/tables → pychemstation-0.10.6/pychemstation/control/controllers/data_aq}/sequence.py +72 -53
- pychemstation-0.10.6/pychemstation/control/controllers/devices/__init__.py +3 -0
- pychemstation-0.10.6/pychemstation/control/controllers/devices/injector.py +106 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/pychemstation/control/hplc.py +5 -1
- {pychemstation-0.10.5 → pychemstation-0.10.6}/pychemstation/utils/injector_types.py +22 -2
- pychemstation-0.10.5/pychemstation/control/controllers/comm.py → pychemstation-0.10.6/pychemstation/utils/mocking/abc_comm.py +18 -104
- pychemstation-0.10.6/pychemstation/utils/mocking/mock_comm.py +5 -0
- pychemstation-0.10.6/pychemstation/utils/mocking/mock_hplc.py +2 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/pychemstation/utils/sequence_types.py +19 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/pychemstation/utils/table_types.py +6 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/pychemstation/utils/tray_types.py +36 -1
- {pychemstation-0.10.5 → pychemstation-0.10.6}/pyproject.toml +1 -1
- pychemstation-0.10.6/tests/__init__.py +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/out.txt +3986 -0
- pychemstation-0.10.6/tests/test_injector.py +39 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/test_integration.py +7 -7
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/test_method.py +75 -11
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/test_offline.py +3 -4
- pychemstation-0.10.6/tests/test_online.py +79 -0
- pychemstation-0.10.6/tests/test_sequence.py +217 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/uv.lock +1 -1
- pychemstation-0.10.5/pychemstation/analysis/__init__.py +0 -4
- pychemstation-0.10.5/pychemstation/control/controllers/devices/device.py +0 -74
- pychemstation-0.10.5/pychemstation/control/controllers/devices/injector.py +0 -73
- pychemstation-0.10.5/tests/test_online.py +0 -303
- pychemstation-0.10.5/tests/test_sequence.py +0 -91
- {pychemstation-0.10.5 → pychemstation-0.10.6}/.gitlab-ci.yml +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/.pre-commit-config.yaml +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/CHANGELOG.md +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/CONTRIBUTING.md +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/LICENSE +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/README.md +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/doc/index.html +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/doc/pychemstation/analysis/base_spectrum.html +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/doc/pychemstation/analysis/spec_utils.html +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/doc/pychemstation/analysis/utils.html +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/doc/pychemstation/analysis.html +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/doc/pychemstation/control/chromatogram.html +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/doc/pychemstation/control/hplc.html +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/doc/pychemstation/control.html +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/doc/pychemstation/generated.html +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/doc/pychemstation/utils/chemstation.html +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/doc/pychemstation/utils/constants.html +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/doc/pychemstation/utils/hplc_param_types.html +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/doc/pychemstation/utils.html +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/doc/pychemstation.html +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/doc/search.js +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/out.txt +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/pychemstation/__init__.py +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/pychemstation/analysis/base_spectrum.py +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/pychemstation/analysis/chromatogram.py +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/pychemstation/analysis/process_report.py +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/pychemstation/control/README.md +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/pychemstation/control/__init__.py +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/pychemstation/control/controllers/README.md +0 -0
- {pychemstation-0.10.5/pychemstation/control/controllers/devices → pychemstation-0.10.6/pychemstation/control/controllers/abc_tables}/__init__.py +0 -0
- {pychemstation-0.10.5/pychemstation/control/controllers/tables → pychemstation-0.10.6/pychemstation/control/controllers/data_aq}/__init__.py +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/pychemstation/generated/__init__.py +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/pychemstation/generated/dad_method.py +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/pychemstation/generated/pump_method.py +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/pychemstation/utils/__init__.py +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/pychemstation/utils/macro.py +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/pychemstation/utils/method_types.py +0 -0
- {pychemstation-0.10.5/tests → pychemstation-0.10.6/pychemstation/utils/mocking}/__init__.py +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/pychemstation/utils/num_utils.py +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/pychemstation/utils/parsing.py +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/pychemstation/utils/pump_types.py +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/pychemstation/utils/spec_utils.py +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/pychemstation.egg-info/PKG-INFO +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/pychemstation.egg-info/SOURCES.txt +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/pychemstation.egg-info/dependency_links.txt +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/pychemstation.egg-info/requires.txt +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/pychemstation.egg-info/top_level.txt +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/0_2025-03-15 19-14-35.D/0_2025-03-15 19-14-35.PDF +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/0_2025-03-15 19-14-35.D/ACQRES.REG +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/0_2025-03-15 19-14-35.D/CSlbk.ini +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/0_2025-03-15 19-14-35.D/DA.M/DAMETHOD.REG +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/0_2025-03-15 19-14-35.D/DA.M/INFO.MTH +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/0_2025-03-15 19-14-35.D/DA.M/RECALIB.MTH +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/0_2025-03-15 19-14-35.D/DA.M/rpthead.txt +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/0_2025-03-15 19-14-35.D/DAD1.UV +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/0_2025-03-15 19-14-35.D/DAD1A.ch +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/0_2025-03-15 19-14-35.D/DAD1A.npz +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/0_2025-03-15 19-14-35.D/DAD1B.ch +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/0_2025-03-15 19-14-35.D/DAD1B.npz +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/0_2025-03-15 19-14-35.D/DAD1C.ch +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/0_2025-03-15 19-14-35.D/DAD1C.npz +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/0_2025-03-15 19-14-35.D/DAD1D.ch +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/0_2025-03-15 19-14-35.D/DAD1D.npz +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/0_2025-03-15 19-14-35.D/DAD1E.ch +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/0_2025-03-15 19-14-35.D/DAD1E.npz +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/0_2025-03-15 19-14-35.D/DiagResults.REG +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/0_2025-03-15 19-14-35.D/PMP1.AnalyticalResults.drvml +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/0_2025-03-15 19-14-35.D/REPORT01.CSV +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/0_2025-03-15 19-14-35.D/REPORT02.CSV +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/0_2025-03-15 19-14-35.D/REPORT03.CSV +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/0_2025-03-15 19-14-35.D/REPORT04.CSV +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/0_2025-03-15 19-14-35.D/REPORT05.CSV +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/0_2025-03-15 19-14-35.D/RUN.LOG +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/0_2025-03-15 19-14-35.D/Report.TXT +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/0_2025-03-15 19-14-35.D/Report00.CSV +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/0_2025-03-15 19-14-35.D/Report01.xls +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/0_2025-03-15 19-14-35.D/SAMPLE.XML +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/0_2025-03-15 19-14-35.D/SAMPLE.XML.bak +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/0_2025-03-15 19-14-35.D/WLS1.Sampler.scml +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/0_2025-03-15 19-14-35.D/acq.macaml +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/0_2025-03-15 19-14-35.D/acq.txt +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/0_2025-03-15 19-14-35.D/acq_MethHist.txt +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/0_2025-03-15 19-14-35.D/acq_damethod.reg +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/0_2025-03-15 19-14-35.D/da.macaml +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/0_2025-03-15 19-14-35.D/lcdiag.reg +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/0_2025-03-15 19-14-35.D/sample.acaml +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/0_2025-03-15 19-14-35.D/single.B +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/10 IS 2025-02-10 23-41-33_10_2025-02-11 02-21-44.D/ACQRES.REG +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/10 IS 2025-02-10 23-41-33_10_2025-02-11 02-21-44.D/AUTOMATICALLY_GENERATED_REPORT01.CSV +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/10 IS 2025-02-10 23-41-33_10_2025-02-11 02-21-44.D/AUTOMATICALLY_GENERATED_REPORT02.CSV +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/10 IS 2025-02-10 23-41-33_10_2025-02-11 02-21-44.D/AUTOMATICALLY_GENERATED_REPORT03.CSV +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/10 IS 2025-02-10 23-41-33_10_2025-02-11 02-21-44.D/AUTOMATICALLY_GENERATED_REPORT04.CSV +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/10 IS 2025-02-10 23-41-33_10_2025-02-11 02-21-44.D/AUTOMATICALLY_GENERATED_REPORT05.CSV +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/10 IS 2025-02-10 23-41-33_10_2025-02-11 02-21-44.D/Automatically_Generated_Report.TXT +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/10 IS 2025-02-10 23-41-33_10_2025-02-11 02-21-44.D/Automatically_Generated_Report00.CSV +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/10 IS 2025-02-10 23-41-33_10_2025-02-11 02-21-44.D/CSlbk.ini +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/10 IS 2025-02-10 23-41-33_10_2025-02-11 02-21-44.D/DA.M/DAMETHOD.REG +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/10 IS 2025-02-10 23-41-33_10_2025-02-11 02-21-44.D/DA.M/INFO.MTH +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/10 IS 2025-02-10 23-41-33_10_2025-02-11 02-21-44.D/DA.M/RECALIB.MTH +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/10 IS 2025-02-10 23-41-33_10_2025-02-11 02-21-44.D/DA.M/rpthead.txt +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/10 IS 2025-02-10 23-41-33_10_2025-02-11 02-21-44.D/DAD1.UV +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/10 IS 2025-02-10 23-41-33_10_2025-02-11 02-21-44.D/DAD1A.ch +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/10 IS 2025-02-10 23-41-33_10_2025-02-11 02-21-44.D/DAD1A.npz +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/10 IS 2025-02-10 23-41-33_10_2025-02-11 02-21-44.D/DAD1B.ch +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/10 IS 2025-02-10 23-41-33_10_2025-02-11 02-21-44.D/DAD1B.npz +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/10 IS 2025-02-10 23-41-33_10_2025-02-11 02-21-44.D/DAD1C.ch +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/10 IS 2025-02-10 23-41-33_10_2025-02-11 02-21-44.D/DAD1C.npz +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/10 IS 2025-02-10 23-41-33_10_2025-02-11 02-21-44.D/DAD1D.ch +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/10 IS 2025-02-10 23-41-33_10_2025-02-11 02-21-44.D/DAD1D.npz +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/10 IS 2025-02-10 23-41-33_10_2025-02-11 02-21-44.D/DAD1E.ch +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/10 IS 2025-02-10 23-41-33_10_2025-02-11 02-21-44.D/DAD1E.npz +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/10 IS 2025-02-10 23-41-33_10_2025-02-11 02-21-44.D/DAD1F.ch +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/10 IS 2025-02-10 23-41-33_10_2025-02-11 02-21-44.D/DAD1F.npz +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/10 IS 2025-02-10 23-41-33_10_2025-02-11 02-21-44.D/DAD1G.ch +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/10 IS 2025-02-10 23-41-33_10_2025-02-11 02-21-44.D/DAD1G.npz +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/10 IS 2025-02-10 23-41-33_10_2025-02-11 02-21-44.D/DAD1H.ch +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/10 IS 2025-02-10 23-41-33_10_2025-02-11 02-21-44.D/DAD1H.npz +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/10 IS 2025-02-10 23-41-33_10_2025-02-11 02-21-44.D/DiagResults.REG +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/10 IS 2025-02-10 23-41-33_10_2025-02-11 02-21-44.D/Limsinf.xml +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/10 IS 2025-02-10 23-41-33_10_2025-02-11 02-21-44.D/PMP1.AnalyticalResults.drvml +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/10 IS 2025-02-10 23-41-33_10_2025-02-11 02-21-44.D/RUN.LOG +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/10 IS 2025-02-10 23-41-33_10_2025-02-11 02-21-44.D/SAMPLE.XML +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/10 IS 2025-02-10 23-41-33_10_2025-02-11 02-21-44.D/SAMPLE.XML.bak +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/10 IS 2025-02-10 23-41-33_10_2025-02-11 02-21-44.D/WLS1.Sampler.scml +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/10 IS 2025-02-10 23-41-33_10_2025-02-11 02-21-44.D/acq.macaml +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/10 IS 2025-02-10 23-41-33_10_2025-02-11 02-21-44.D/acq.txt +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/10 IS 2025-02-10 23-41-33_10_2025-02-11 02-21-44.D/acq_MethHist.txt +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/10 IS 2025-02-10 23-41-33_10_2025-02-11 02-21-44.D/acq_damethod.reg +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/10 IS 2025-02-10 23-41-33_10_2025-02-11 02-21-44.D/da.macaml +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/10 IS 2025-02-10 23-41-33_10_2025-02-11 02-21-44.D/lcdiag.reg +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/10 IS 2025-02-10 23-41-33_10_2025-02-11 02-21-44.D/sample.acaml +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/10 IS 2025-02-10 23-41-33_10_2025-02-11 02-21-44.D/single.B +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/constants.py +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/hplc_talk.mac +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/hplc_testing 2025-03-27 17-13-47/CSlbk.ini +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/hplc_testing 2025-03-27 17-13-47/GENERAL-POROSHELL-OPT.M/ACQ.MS +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/hplc_testing 2025-03-27 17-13-47/GENERAL-POROSHELL-OPT.M/Agilent1200erDadDriver1.RapidControl.ConfigXML.xml +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/hplc_testing 2025-03-27 17-13-47/GENERAL-POROSHELL-OPT.M/Agilent1200erDadDriver1.RapidControl.MethodMetaData.xml +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/hplc_testing 2025-03-27 17-13-47/GENERAL-POROSHELL-OPT.M/Agilent1200erDadDriver1.RapidControl.MethodXML.xml +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/hplc_testing 2025-03-27 17-13-47/GENERAL-POROSHELL-OPT.M/AgilentColumnCompDriver1.RapidControl.ConfigXML.xml +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/hplc_testing 2025-03-27 17-13-47/GENERAL-POROSHELL-OPT.M/AgilentColumnCompDriver1.RapidControl.MethodMetaData.xml +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/hplc_testing 2025-03-27 17-13-47/GENERAL-POROSHELL-OPT.M/AgilentColumnCompDriver1.RapidControl.MethodXML.xml +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/hplc_testing 2025-03-27 17-13-47/GENERAL-POROSHELL-OPT.M/AgilentPumpDriver1.RapidControl.ConfigXML.xml +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/hplc_testing 2025-03-27 17-13-47/GENERAL-POROSHELL-OPT.M/AgilentPumpDriver1.RapidControl.MethodMetaData.xml +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/hplc_testing 2025-03-27 17-13-47/GENERAL-POROSHELL-OPT.M/AgilentPumpDriver1.RapidControl.MethodXML.xml +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/hplc_testing 2025-03-27 17-13-47/GENERAL-POROSHELL-OPT.M/AgilentSamplerDriver1.RapidControl.ConfigXML.xml +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/hplc_testing 2025-03-27 17-13-47/GENERAL-POROSHELL-OPT.M/AgilentSamplerDriver1.RapidControl.MethodMetaData.xml +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/hplc_testing 2025-03-27 17-13-47/GENERAL-POROSHELL-OPT.M/AgilentSamplerDriver1.RapidControl.MethodXML.xml +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/hplc_testing 2025-03-27 17-13-47/GENERAL-POROSHELL-OPT.M/AgilentSamplerDriver1.RapidControl.PretreatXML.xml +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/hplc_testing 2025-03-27 17-13-47/GENERAL-POROSHELL-OPT.M/DAMETHOD.REG +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/hplc_testing 2025-03-27 17-13-47/GENERAL-POROSHELL-OPT.M/FIA.REG +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/hplc_testing 2025-03-27 17-13-47/GENERAL-POROSHELL-OPT.M/INFO.MTH +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/hplc_testing 2025-03-27 17-13-47/GENERAL-POROSHELL-OPT.M/INJECTOR.MTH +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/hplc_testing 2025-03-27 17-13-47/GENERAL-POROSHELL-OPT.M/MassHunterIntegration.ini +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/hplc_testing 2025-03-27 17-13-47/GENERAL-POROSHELL-OPT.M/RECALIB.MTH +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/hplc_testing 2025-03-27 17-13-47/GENERAL-POROSHELL-OPT.M/RapidControl.InstrumentConfig.xml +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/hplc_testing 2025-03-27 17-13-47/GENERAL-POROSHELL-OPT.M/rpthead.txt +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/hplc_testing 2025-03-27 17-13-47/GENERAL-POROSHELL-OPT.M/smpl_pur.mth +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/hplc_testing 2025-03-27 17-13-47/Methods.Reg +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/hplc_testing 2025-03-27 17-13-47/hplc_testing.B +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/hplc_testing 2025-03-27 17-13-47/hplc_testing.LOG +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/hplc_testing 2025-03-27 17-13-47/hplc_testing.S +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/hplc_testing 2025-03-27 17-13-47/hplc_testing.Start +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/hplc_testing 2025-03-27 17-13-47/run seq with new method.D/ACQRES.REG +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/hplc_testing 2025-03-27 17-13-47/run seq with new method.D/CSlbk.ini +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/hplc_testing 2025-03-27 17-13-47/run seq with new method.D/DA.M/DAMETHOD.REG +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/hplc_testing 2025-03-27 17-13-47/run seq with new method.D/DA.M/INFO.MTH +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/hplc_testing 2025-03-27 17-13-47/run seq with new method.D/DA.M/RECALIB.MTH +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/hplc_testing 2025-03-27 17-13-47/run seq with new method.D/DA.M/rpthead.txt +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/hplc_testing 2025-03-27 17-13-47/run seq with new method.D/DAD1.UV +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/hplc_testing 2025-03-27 17-13-47/run seq with new method.D/DAD1A.ch +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/hplc_testing 2025-03-27 17-13-47/run seq with new method.D/DAD1A.npz +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/hplc_testing 2025-03-27 17-13-47/run seq with new method.D/DAD1B.ch +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/hplc_testing 2025-03-27 17-13-47/run seq with new method.D/DAD1B.npz +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/hplc_testing 2025-03-27 17-13-47/run seq with new method.D/DAD1C.ch +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/hplc_testing 2025-03-27 17-13-47/run seq with new method.D/DAD1C.npz +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/hplc_testing 2025-03-27 17-13-47/run seq with new method.D/DAD1D.ch +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/hplc_testing 2025-03-27 17-13-47/run seq with new method.D/DAD1D.npz +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/hplc_testing 2025-03-27 17-13-47/run seq with new method.D/DAD1E.ch +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/hplc_testing 2025-03-27 17-13-47/run seq with new method.D/DAD1E.npz +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/hplc_testing 2025-03-27 17-13-47/run seq with new method.D/DiagResults.REG +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/hplc_testing 2025-03-27 17-13-47/run seq with new method.D/Limsinf.xml +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/hplc_testing 2025-03-27 17-13-47/run seq with new method.D/PMP1.AnalyticalResults.drvml +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/hplc_testing 2025-03-27 17-13-47/run seq with new method.D/REPORT01.CSV +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/hplc_testing 2025-03-27 17-13-47/run seq with new method.D/REPORT02.CSV +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/hplc_testing 2025-03-27 17-13-47/run seq with new method.D/REPORT03.CSV +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/hplc_testing 2025-03-27 17-13-47/run seq with new method.D/REPORT04.CSV +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/hplc_testing 2025-03-27 17-13-47/run seq with new method.D/REPORT05.CSV +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/hplc_testing 2025-03-27 17-13-47/run seq with new method.D/RUN.LOG +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/hplc_testing 2025-03-27 17-13-47/run seq with new method.D/Report.TXT +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/hplc_testing 2025-03-27 17-13-47/run seq with new method.D/Report00.CSV +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/hplc_testing 2025-03-27 17-13-47/run seq with new method.D/Report01.xls +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/hplc_testing 2025-03-27 17-13-47/run seq with new method.D/SAMPLE.XML +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/hplc_testing 2025-03-27 17-13-47/run seq with new method.D/SAMPLE.XML.bak +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/hplc_testing 2025-03-27 17-13-47/run seq with new method.D/WLS1.Sampler.scml +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/hplc_testing 2025-03-27 17-13-47/run seq with new method.D/acq.macaml +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/hplc_testing 2025-03-27 17-13-47/run seq with new method.D/acq.txt +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/hplc_testing 2025-03-27 17-13-47/run seq with new method.D/acq_MethHist.txt +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/hplc_testing 2025-03-27 17-13-47/run seq with new method.D/acq_damethod.reg +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/hplc_testing 2025-03-27 17-13-47/run seq with new method.D/da.macaml +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/hplc_testing 2025-03-27 17-13-47/run seq with new method.D/hplc_testing 2025-03-27 17-13-47_run seq with new method.PDF +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/hplc_testing 2025-03-27 17-13-47/run seq with new method.D/lcdiag.reg +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/hplc_testing 2025-03-27 17-13-47/run seq with new method.D/sequence.acam_ +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/tests/hplc_testing 2025-03-27 17-13-47/sequence.acaml +0 -0
- {pychemstation-0.10.5 → pychemstation-0.10.6}/update-lib.sh +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: pychemstation
|
3
|
-
Version: 0.10.
|
3
|
+
Version: 0.10.6
|
4
4
|
Summary: Library to interact with Chemstation software, primarily used in Hein lab
|
5
5
|
Project-URL: Documentation, https://pychemstation-e5a086.gitlab.io/pychemstation.html
|
6
6
|
Project-URL: Repository, https://gitlab.com/heingroup/device-api/pychemstation
|
@@ -0,0 +1,11 @@
|
|
1
|
+
from .process_report import CSVProcessor
|
2
|
+
from .process_report import TXTProcessor
|
3
|
+
from .chromatogram import AgilentChannelChromatogramData
|
4
|
+
from .chromatogram import AgilentHPLCChromatogram
|
5
|
+
|
6
|
+
__all__ = [
|
7
|
+
"CSVProcessor",
|
8
|
+
"TXTProcessor",
|
9
|
+
"AgilentChannelChromatogramData",
|
10
|
+
"AgilentHPLCChromatogram",
|
11
|
+
]
|
@@ -0,0 +1,15 @@
|
|
1
|
+
from __future__ import annotations
|
2
|
+
|
3
|
+
from abc import ABC
|
4
|
+
|
5
|
+
from ....control.controllers import CommunicationController
|
6
|
+
from ....utils.table_types import Table
|
7
|
+
from .table import ABCTableController
|
8
|
+
|
9
|
+
|
10
|
+
class DeviceController(ABCTableController, ABC):
|
11
|
+
def __init__(
|
12
|
+
self, controller: CommunicationController, table: Table, offline: bool
|
13
|
+
):
|
14
|
+
super().__init__(controller=controller, table=table)
|
15
|
+
self.offline = offline
|
@@ -17,6 +17,7 @@ import polling
|
|
17
17
|
import rainbow as rb
|
18
18
|
from result import Err, Result, Ok
|
19
19
|
|
20
|
+
from .table import ABCTableController
|
20
21
|
from ....analysis.process_report import (
|
21
22
|
AgilentReport,
|
22
23
|
CSVProcessor,
|
@@ -28,15 +29,15 @@ from pychemstation.analysis.chromatogram import (
|
|
28
29
|
AgilentChannelChromatogramData,
|
29
30
|
AgilentHPLCChromatogram,
|
30
31
|
)
|
31
|
-
from ....utils.macro import
|
32
|
+
from ....utils.macro import HPLCRunningStatus
|
32
33
|
from ....utils.method_types import MethodDetails
|
33
34
|
from ....utils.sequence_types import SequenceTable
|
34
|
-
from ....utils.table_types import
|
35
|
+
from ....utils.table_types import Table, T
|
35
36
|
|
36
37
|
TableType = Union[MethodDetails, SequenceTable]
|
37
38
|
|
38
39
|
|
39
|
-
class
|
40
|
+
class RunController(ABCTableController, abc.ABC):
|
40
41
|
def __init__(
|
41
42
|
self,
|
42
43
|
controller: Optional[CommunicationController],
|
@@ -45,8 +46,10 @@ class TableController(abc.ABC):
|
|
45
46
|
table: Table,
|
46
47
|
offline: bool = False,
|
47
48
|
):
|
48
|
-
|
49
|
-
|
49
|
+
super().__init__(controller=controller, table=table)
|
50
|
+
warnings.warn(
|
51
|
+
"This abstract class is not meant to be initialized. Use MethodController or SequenceController."
|
52
|
+
)
|
50
53
|
self.table_state: Optional[TableType] = None
|
51
54
|
self.curr_run_starting_time: Optional[float] = None
|
52
55
|
self.timeout: Optional[float] = None
|
@@ -76,179 +79,27 @@ class TableController(abc.ABC):
|
|
76
79
|
self.uv: Dict[int, AgilentHPLCChromatogram] = {}
|
77
80
|
self.data_files: List = []
|
78
81
|
|
79
|
-
def receive(self) -> Result[Response, str]:
|
80
|
-
if self.controller:
|
81
|
-
for _ in range(10):
|
82
|
-
try:
|
83
|
-
return self.controller.receive()
|
84
|
-
except IndexError:
|
85
|
-
continue
|
86
|
-
return Err("Could not parse response")
|
87
|
-
else:
|
88
|
-
raise ValueError("Controller is offline!")
|
89
|
-
|
90
|
-
def send(self, cmd: Union[Command, str]):
|
91
|
-
if not self.controller:
|
92
|
-
raise RuntimeError(
|
93
|
-
"Communication controller must be initialized before sending command. It is currently in offline mode."
|
94
|
-
)
|
95
|
-
self.controller.send(cmd)
|
96
|
-
|
97
|
-
def sleepy_send(self, cmd: Union[Command, str]):
|
98
|
-
if self.controller:
|
99
|
-
self.controller.sleepy_send(cmd)
|
100
|
-
else:
|
101
|
-
raise ValueError("Controller is offline")
|
102
|
-
|
103
|
-
def sleep(self, seconds: int):
|
104
|
-
"""
|
105
|
-
Tells the HPLC to wait for a specified number of seconds.
|
106
|
-
|
107
|
-
:param seconds: number of seconds to wait
|
108
|
-
"""
|
109
|
-
self.send(Command.SLEEP_CMD.value.format(seconds=seconds))
|
110
|
-
|
111
|
-
def get_num(self, row: int, col_name: RegisterFlag) -> Union[int, float]:
|
112
|
-
if self.controller:
|
113
|
-
return self.controller.get_num_val(
|
114
|
-
TableOperation.GET_ROW_VAL.value.format(
|
115
|
-
register=self.table_locator.register,
|
116
|
-
table_name=self.table_locator.name,
|
117
|
-
row=row,
|
118
|
-
col_name=col_name.value,
|
119
|
-
)
|
120
|
-
)
|
121
|
-
else:
|
122
|
-
raise ValueError("Controller is offline")
|
123
|
-
|
124
|
-
def get_text(self, row: int, col_name: RegisterFlag) -> str:
|
125
|
-
if self.controller:
|
126
|
-
return self.controller.get_text_val(
|
127
|
-
TableOperation.GET_ROW_TEXT.value.format(
|
128
|
-
register=self.table_locator.register,
|
129
|
-
table_name=self.table_locator.name,
|
130
|
-
row=row,
|
131
|
-
col_name=col_name.value,
|
132
|
-
)
|
133
|
-
)
|
134
|
-
else:
|
135
|
-
raise ValueError("Controller is offline")
|
136
|
-
|
137
|
-
def add_new_col_num(self, col_name: RegisterFlag, val: Union[int, float]):
|
138
|
-
self.sleepy_send(
|
139
|
-
TableOperation.NEW_COL_VAL.value.format(
|
140
|
-
register=self.table_locator.register,
|
141
|
-
table_name=self.table_locator.name,
|
142
|
-
col_name=col_name,
|
143
|
-
val=val,
|
144
|
-
)
|
145
|
-
)
|
146
|
-
|
147
|
-
def add_new_col_text(self, col_name: RegisterFlag, val: str):
|
148
|
-
self.sleepy_send(
|
149
|
-
TableOperation.NEW_COL_TEXT.value.format(
|
150
|
-
register=self.table_locator.register,
|
151
|
-
table_name=self.table_locator.name,
|
152
|
-
col_name=col_name,
|
153
|
-
val=val,
|
154
|
-
)
|
155
|
-
)
|
156
|
-
|
157
|
-
def _edit_row_num(
|
158
|
-
self, col_name: RegisterFlag, val: Union[int, float], row: Optional[int] = None
|
159
|
-
):
|
160
|
-
self.sleepy_send(
|
161
|
-
TableOperation.EDIT_ROW_VAL.value.format(
|
162
|
-
register=self.table_locator.register,
|
163
|
-
table_name=self.table_locator.name,
|
164
|
-
row=row if row is not None else "Rows",
|
165
|
-
col_name=col_name,
|
166
|
-
val=val,
|
167
|
-
)
|
168
|
-
)
|
169
|
-
|
170
|
-
def _edit_row_text(
|
171
|
-
self, col_name: RegisterFlag, val: str, row: Optional[int] = None
|
172
|
-
):
|
173
|
-
self.sleepy_send(
|
174
|
-
TableOperation.EDIT_ROW_TEXT.value.format(
|
175
|
-
register=self.table_locator.register,
|
176
|
-
table_name=self.table_locator.name,
|
177
|
-
row=row if row is not None else "Rows",
|
178
|
-
col_name=col_name,
|
179
|
-
val=val,
|
180
|
-
)
|
181
|
-
)
|
182
|
-
|
183
82
|
@abc.abstractmethod
|
184
|
-
def
|
83
|
+
def fuzzy_match_most_recent_folder(self, most_recent_folder: T) -> Result[T, str]:
|
185
84
|
pass
|
186
85
|
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
row=row,
|
193
|
-
)
|
194
|
-
)
|
195
|
-
|
196
|
-
def add_row(self):
|
197
|
-
"""
|
198
|
-
Adds a row to the provided table for currently loaded method or sequence.
|
199
|
-
"""
|
200
|
-
self.sleepy_send(
|
201
|
-
TableOperation.NEW_ROW.value.format(
|
202
|
-
register=self.table_locator.register, table_name=self.table_locator.name
|
203
|
-
)
|
204
|
-
)
|
205
|
-
|
206
|
-
def delete_table(self):
|
207
|
-
"""
|
208
|
-
Deletes the table for the current loaded method or sequence.
|
209
|
-
"""
|
210
|
-
self.sleepy_send(
|
211
|
-
TableOperation.DELETE_TABLE.value.format(
|
212
|
-
register=self.table_locator.register, table_name=self.table_locator.name
|
213
|
-
)
|
214
|
-
)
|
215
|
-
|
216
|
-
def new_table(self):
|
217
|
-
"""
|
218
|
-
Creates the table for the currently loaded method or sequence.
|
219
|
-
"""
|
220
|
-
self.send(
|
221
|
-
TableOperation.CREATE_TABLE.value.format(
|
222
|
-
register=self.table_locator.register, table_name=self.table_locator.name
|
223
|
-
)
|
224
|
-
)
|
86
|
+
@abc.abstractmethod
|
87
|
+
def get_data(
|
88
|
+
self, custom_path: Optional[str] = None
|
89
|
+
) -> Union[List[AgilentChannelChromatogramData], AgilentChannelChromatogramData]:
|
90
|
+
pass
|
225
91
|
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
col_name=RegisterFlag.NUM_ROWS,
|
232
|
-
)
|
233
|
-
)
|
234
|
-
self.send(
|
235
|
-
Command.GET_ROWS_CMD.value.format(
|
236
|
-
register=self.table_locator.register,
|
237
|
-
table_name=self.table_locator.name,
|
238
|
-
col_name=RegisterFlag.NUM_ROWS,
|
239
|
-
)
|
240
|
-
)
|
241
|
-
if self.controller:
|
242
|
-
res = self.controller.receive()
|
243
|
-
else:
|
244
|
-
raise ValueError("Controller is offline")
|
92
|
+
@abc.abstractmethod
|
93
|
+
def get_data_uv(
|
94
|
+
self, custom_path: str | None = None
|
95
|
+
) -> Dict[int, AgilentHPLCChromatogram]:
|
96
|
+
pass
|
245
97
|
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
return Err("No rows could be read.")
|
98
|
+
@abc.abstractmethod
|
99
|
+
def get_report(
|
100
|
+
self, custom_path: str, report_type: ReportType = ReportType.TXT
|
101
|
+
) -> List[AgilentReport]:
|
102
|
+
pass
|
252
103
|
|
253
104
|
def check_hplc_is_running(self) -> bool:
|
254
105
|
if self.controller:
|
@@ -334,28 +185,6 @@ class TableController(abc.ABC):
|
|
334
185
|
return self.data_files[-1]
|
335
186
|
return Err("Run did not complete as expected")
|
336
187
|
|
337
|
-
@abc.abstractmethod
|
338
|
-
def fuzzy_match_most_recent_folder(self, most_recent_folder: T) -> Result[T, str]:
|
339
|
-
pass
|
340
|
-
|
341
|
-
@abc.abstractmethod
|
342
|
-
def get_data(
|
343
|
-
self, custom_path: Optional[str] = None
|
344
|
-
) -> Union[List[AgilentChannelChromatogramData], AgilentChannelChromatogramData]:
|
345
|
-
pass
|
346
|
-
|
347
|
-
@abc.abstractmethod
|
348
|
-
def get_data_uv(
|
349
|
-
self, custom_path: str | None = None
|
350
|
-
) -> Dict[int, AgilentHPLCChromatogram]:
|
351
|
-
pass
|
352
|
-
|
353
|
-
@abc.abstractmethod
|
354
|
-
def get_report(
|
355
|
-
self, custom_path: str, report_type: ReportType = ReportType.TXT
|
356
|
-
) -> List[AgilentReport]:
|
357
|
-
pass
|
358
|
-
|
359
188
|
def get_uv_spectrum(self, path: str):
|
360
189
|
data_uv = rb.agilent.chemstation.parse_file(os.path.join(path, "DAD1.UV"))
|
361
190
|
times = data_uv.xlabels
|
@@ -0,0 +1,221 @@
|
|
1
|
+
"""
|
2
|
+
Abstract module containing shared logic for Method and Sequence tables.
|
3
|
+
|
4
|
+
Authors: Lucy Hao
|
5
|
+
"""
|
6
|
+
|
7
|
+
from __future__ import annotations
|
8
|
+
|
9
|
+
import abc
|
10
|
+
import warnings
|
11
|
+
from typing import Optional, Union
|
12
|
+
|
13
|
+
from result import Err, Result
|
14
|
+
|
15
|
+
from ....control.controllers.comm import CommunicationController
|
16
|
+
from ....utils.macro import Command, Response
|
17
|
+
from ....utils.method_types import MethodDetails
|
18
|
+
from ....utils.sequence_types import SequenceTable
|
19
|
+
from ....utils.table_types import RegisterFlag, Table, TableOperation
|
20
|
+
|
21
|
+
TableType = Union[MethodDetails, SequenceTable]
|
22
|
+
|
23
|
+
|
24
|
+
class ABCTableController(abc.ABC):
|
25
|
+
def __init__(
|
26
|
+
self,
|
27
|
+
controller: Optional[CommunicationController],
|
28
|
+
table: Table,
|
29
|
+
):
|
30
|
+
warnings.warn(
|
31
|
+
"This abstract class is not meant to be initialized. Use MethodController or SequenceController."
|
32
|
+
)
|
33
|
+
self.controller = controller
|
34
|
+
self.table_locator = table
|
35
|
+
self.table_state: Optional[TableType] = None
|
36
|
+
|
37
|
+
def receive(self) -> Result[Response, str]:
|
38
|
+
if self.controller:
|
39
|
+
for _ in range(10):
|
40
|
+
try:
|
41
|
+
return self.controller.receive()
|
42
|
+
except IndexError:
|
43
|
+
continue
|
44
|
+
return Err("Could not parse response")
|
45
|
+
else:
|
46
|
+
raise ValueError("Controller is offline!")
|
47
|
+
|
48
|
+
def send(self, cmd: Union[Command, str]):
|
49
|
+
if not self.controller:
|
50
|
+
raise RuntimeError(
|
51
|
+
"Communication controller must be initialized before sending command. It is currently in offline mode."
|
52
|
+
)
|
53
|
+
self.controller.send(cmd)
|
54
|
+
|
55
|
+
def sleepy_send(self, cmd: Union[Command, str]):
|
56
|
+
if self.controller:
|
57
|
+
self.controller.sleepy_send(cmd)
|
58
|
+
else:
|
59
|
+
raise ValueError("Controller is offline")
|
60
|
+
|
61
|
+
def sleep(self, seconds: int):
|
62
|
+
"""
|
63
|
+
Tells the HPLC to wait for a specified number of seconds.
|
64
|
+
|
65
|
+
:param seconds: number of seconds to wait
|
66
|
+
"""
|
67
|
+
self.send(Command.SLEEP_CMD.value.format(seconds=seconds))
|
68
|
+
|
69
|
+
def get_num(self, row: int, col_name: RegisterFlag) -> Union[int, float]:
|
70
|
+
if self.controller:
|
71
|
+
return self.controller.get_num_val(
|
72
|
+
TableOperation.GET_ROW_VAL.value.format(
|
73
|
+
register=self.table_locator.register,
|
74
|
+
table_name=self.table_locator.name,
|
75
|
+
row=row,
|
76
|
+
col_name=col_name.value,
|
77
|
+
)
|
78
|
+
)
|
79
|
+
else:
|
80
|
+
raise ValueError("Controller is offline")
|
81
|
+
|
82
|
+
def get_text(self, row: int, col_name: RegisterFlag) -> str:
|
83
|
+
if self.controller:
|
84
|
+
return self.controller.get_text_val(
|
85
|
+
TableOperation.GET_ROW_TEXT.value.format(
|
86
|
+
register=self.table_locator.register,
|
87
|
+
table_name=self.table_locator.name,
|
88
|
+
row=row,
|
89
|
+
col_name=col_name.value,
|
90
|
+
)
|
91
|
+
)
|
92
|
+
else:
|
93
|
+
raise ValueError("Controller is offline")
|
94
|
+
|
95
|
+
def add_new_col_num(self, col_name: RegisterFlag, val: Union[int, float]):
|
96
|
+
self.sleepy_send(
|
97
|
+
TableOperation.NEW_COL_VAL.value.format(
|
98
|
+
register=self.table_locator.register,
|
99
|
+
table_name=self.table_locator.name,
|
100
|
+
col_name=col_name,
|
101
|
+
val=val,
|
102
|
+
)
|
103
|
+
)
|
104
|
+
|
105
|
+
def add_new_col_text(self, col_name: RegisterFlag, val: str):
|
106
|
+
self.sleepy_send(
|
107
|
+
TableOperation.NEW_COL_TEXT.value.format(
|
108
|
+
register=self.table_locator.register,
|
109
|
+
table_name=self.table_locator.name,
|
110
|
+
col_name=col_name,
|
111
|
+
val=val,
|
112
|
+
)
|
113
|
+
)
|
114
|
+
|
115
|
+
def _edit_row_num(
|
116
|
+
self, col_name: RegisterFlag, val: Union[int, float], row: Optional[int] = None
|
117
|
+
):
|
118
|
+
if row:
|
119
|
+
num_rows = self.get_num_rows()
|
120
|
+
if num_rows.is_ok():
|
121
|
+
if num_rows.value.num_response < row:
|
122
|
+
raise ValueError("Not enough rows to edit!")
|
123
|
+
|
124
|
+
self.sleepy_send(
|
125
|
+
TableOperation.EDIT_ROW_VAL.value.format(
|
126
|
+
register=self.table_locator.register,
|
127
|
+
table_name=self.table_locator.name,
|
128
|
+
row=row if row is not None else "Rows",
|
129
|
+
col_name=col_name,
|
130
|
+
val=val,
|
131
|
+
)
|
132
|
+
)
|
133
|
+
|
134
|
+
def _edit_row_text(
|
135
|
+
self, col_name: RegisterFlag, val: str, row: Optional[int] = None
|
136
|
+
):
|
137
|
+
if row:
|
138
|
+
num_rows = self.get_num_rows()
|
139
|
+
if num_rows.is_ok():
|
140
|
+
if num_rows.value.num_response < row:
|
141
|
+
raise ValueError("Not enough rows to edit!")
|
142
|
+
|
143
|
+
self.sleepy_send(
|
144
|
+
TableOperation.EDIT_ROW_TEXT.value.format(
|
145
|
+
register=self.table_locator.register,
|
146
|
+
table_name=self.table_locator.name,
|
147
|
+
row=row if row is not None else "Rows",
|
148
|
+
col_name=col_name,
|
149
|
+
val=val,
|
150
|
+
)
|
151
|
+
)
|
152
|
+
|
153
|
+
@abc.abstractmethod
|
154
|
+
def get_row(self, row: int):
|
155
|
+
pass
|
156
|
+
|
157
|
+
def delete_row(self, row: int):
|
158
|
+
self.sleepy_send(
|
159
|
+
TableOperation.DELETE_ROW.value.format(
|
160
|
+
register=self.table_locator.register,
|
161
|
+
table_name=self.table_locator.name,
|
162
|
+
row=row,
|
163
|
+
)
|
164
|
+
)
|
165
|
+
|
166
|
+
def add_row(self):
|
167
|
+
"""
|
168
|
+
Adds a row to the provided table for currently loaded method or sequence.
|
169
|
+
"""
|
170
|
+
self.sleepy_send(
|
171
|
+
TableOperation.NEW_ROW.value.format(
|
172
|
+
register=self.table_locator.register, table_name=self.table_locator.name
|
173
|
+
)
|
174
|
+
)
|
175
|
+
|
176
|
+
def delete_table(self):
|
177
|
+
"""
|
178
|
+
Deletes the table for the current loaded method or sequence.
|
179
|
+
"""
|
180
|
+
self.sleepy_send(
|
181
|
+
TableOperation.DELETE_TABLE.value.format(
|
182
|
+
register=self.table_locator.register, table_name=self.table_locator.name
|
183
|
+
)
|
184
|
+
)
|
185
|
+
|
186
|
+
def new_table(self):
|
187
|
+
"""
|
188
|
+
Creates the table for the currently loaded method or sequence.
|
189
|
+
"""
|
190
|
+
self.send(
|
191
|
+
TableOperation.CREATE_TABLE.value.format(
|
192
|
+
register=self.table_locator.register, table_name=self.table_locator.name
|
193
|
+
)
|
194
|
+
)
|
195
|
+
|
196
|
+
def get_num_rows(self) -> Result[Response, str]:
|
197
|
+
self.send(
|
198
|
+
TableOperation.GET_NUM_ROWS.value.format(
|
199
|
+
register=self.table_locator.register,
|
200
|
+
table_name=self.table_locator.name,
|
201
|
+
col_name=RegisterFlag.NUM_ROWS,
|
202
|
+
)
|
203
|
+
)
|
204
|
+
self.send(
|
205
|
+
Command.GET_ROWS_CMD.value.format(
|
206
|
+
register=self.table_locator.register,
|
207
|
+
table_name=self.table_locator.name,
|
208
|
+
col_name=RegisterFlag.NUM_ROWS,
|
209
|
+
)
|
210
|
+
)
|
211
|
+
if self.controller:
|
212
|
+
res = self.controller.receive()
|
213
|
+
else:
|
214
|
+
raise ValueError("Controller is offline")
|
215
|
+
|
216
|
+
if res.is_ok():
|
217
|
+
self.send("Sleep 0.1")
|
218
|
+
self.send("Print Rows")
|
219
|
+
return res
|
220
|
+
else:
|
221
|
+
return Err("No rows could be read.")
|
@@ -0,0 +1,150 @@
|
|
1
|
+
"""
|
2
|
+
Module to provide API for the communication with Agilent HPLC systems.
|
3
|
+
|
4
|
+
HPLCController sends commands to Chemstation software via a command file.
|
5
|
+
Answers are received via reply file. On the Chemstation side, a custom
|
6
|
+
Macro monitors the command file, executes commands and writes to the reply file.
|
7
|
+
Each command is given a number (cmd_no) to keep track of which commands have
|
8
|
+
been processed.
|
9
|
+
|
10
|
+
Authors: Alexander Hammer, Hessam Mehr, Lucy Hao
|
11
|
+
"""
|
12
|
+
|
13
|
+
import time
|
14
|
+
from typing import Optional, Union
|
15
|
+
|
16
|
+
from result import Err, Ok, Result
|
17
|
+
|
18
|
+
from ...utils.macro import (
|
19
|
+
str_to_status,
|
20
|
+
HPLCErrorStatus,
|
21
|
+
Command,
|
22
|
+
Status,
|
23
|
+
)
|
24
|
+
from ...utils.mocking.abc_comm import ABCCommunicationController
|
25
|
+
|
26
|
+
|
27
|
+
class CommunicationController(ABCCommunicationController):
|
28
|
+
"""
|
29
|
+
Class that communicates with Agilent using Macros
|
30
|
+
"""
|
31
|
+
|
32
|
+
def __init__(
|
33
|
+
self,
|
34
|
+
comm_dir: str,
|
35
|
+
cmd_file: str = "cmd",
|
36
|
+
reply_file: str = "reply",
|
37
|
+
offline: bool = False,
|
38
|
+
debug: bool = False,
|
39
|
+
):
|
40
|
+
"""
|
41
|
+
:param comm_dir:
|
42
|
+
:param cmd_file: Name of command file
|
43
|
+
:param reply_file: Name of reply file
|
44
|
+
:param debug: whether to save log of sent commands
|
45
|
+
"""
|
46
|
+
super().__init__(comm_dir, cmd_file, reply_file, offline, debug)
|
47
|
+
|
48
|
+
def get_num_val(self, cmd: str) -> Union[int, float]:
|
49
|
+
tries = 10
|
50
|
+
for _ in range(tries):
|
51
|
+
self.send(Command.GET_NUM_VAL_CMD.value.format(cmd=cmd))
|
52
|
+
res = self.receive()
|
53
|
+
if res.is_ok():
|
54
|
+
return res.ok_value.num_response
|
55
|
+
raise RuntimeError("Failed to get number.")
|
56
|
+
|
57
|
+
def get_text_val(self, cmd: str) -> str:
|
58
|
+
tries = 10
|
59
|
+
for _ in range(tries):
|
60
|
+
self.send(Command.GET_TEXT_VAL_CMD.value.format(cmd=cmd))
|
61
|
+
res = self.receive()
|
62
|
+
if res.is_ok():
|
63
|
+
return res.ok_value.string_response
|
64
|
+
raise RuntimeError("Failed to get string")
|
65
|
+
|
66
|
+
def get_status(self) -> Status:
|
67
|
+
"""Get device status(es).
|
68
|
+
|
69
|
+
:return: list of ChemStation's current status
|
70
|
+
"""
|
71
|
+
self.send(Command.GET_STATUS_CMD)
|
72
|
+
time.sleep(1)
|
73
|
+
|
74
|
+
try:
|
75
|
+
res = self.receive()
|
76
|
+
if res.is_err():
|
77
|
+
return HPLCErrorStatus.NORESPONSE
|
78
|
+
if res.is_ok():
|
79
|
+
parsed_response = self.receive().value.string_response
|
80
|
+
self._most_recent_hplc_status = str_to_status(parsed_response)
|
81
|
+
return self._most_recent_hplc_status
|
82
|
+
else:
|
83
|
+
raise RuntimeError("Failed to get status")
|
84
|
+
except IOError:
|
85
|
+
return HPLCErrorStatus.NORESPONSE
|
86
|
+
except IndexError:
|
87
|
+
return HPLCErrorStatus.MALFORMED
|
88
|
+
|
89
|
+
def _send(self, cmd: str, cmd_no: int, num_attempts=5) -> None:
|
90
|
+
"""Low-level execution primitive. Sends a command string to HPLC.
|
91
|
+
|
92
|
+
:param cmd: string to be sent to HPLC
|
93
|
+
:param cmd_no: Command number
|
94
|
+
:param num_attempts: Number of attempts to send the command before raising exception.
|
95
|
+
:raises IOError: Could not write to command file.
|
96
|
+
"""
|
97
|
+
err = None
|
98
|
+
for _ in range(num_attempts):
|
99
|
+
time.sleep(1)
|
100
|
+
try:
|
101
|
+
with open(self.cmd_file, "w", encoding="utf8") as cmd_file:
|
102
|
+
cmd_file.write(f"{cmd_no} {cmd}")
|
103
|
+
except IOError as e:
|
104
|
+
err = e
|
105
|
+
continue
|
106
|
+
else:
|
107
|
+
return
|
108
|
+
else:
|
109
|
+
raise IOError(f"Failed to send command #{cmd_no}: {cmd}.") from err
|
110
|
+
|
111
|
+
def _receive(self, cmd_no: int, num_attempts=100) -> Result[str, str]:
|
112
|
+
"""Low-level execution primitive. Recives a response from HPLC.
|
113
|
+
|
114
|
+
:param cmd_no: Command number
|
115
|
+
:param num_attempts: Number of retries to open reply file
|
116
|
+
:raises IOError: Could not read reply file.
|
117
|
+
:return: Potential ChemStation response
|
118
|
+
"""
|
119
|
+
err: Optional[Union[OSError, IndexError, ValueError]] = None
|
120
|
+
err_msg = ""
|
121
|
+
for _ in range(num_attempts):
|
122
|
+
time.sleep(1)
|
123
|
+
|
124
|
+
try:
|
125
|
+
with open(self.reply_file, "r", encoding="utf_16") as reply_file:
|
126
|
+
response = reply_file.read()
|
127
|
+
except OSError as e:
|
128
|
+
err = e
|
129
|
+
continue
|
130
|
+
|
131
|
+
try:
|
132
|
+
first_line = response.splitlines()[0]
|
133
|
+
try:
|
134
|
+
response_no = int(first_line.split()[0])
|
135
|
+
except ValueError as e:
|
136
|
+
err = e
|
137
|
+
err_msg = f"Caused by {first_line}"
|
138
|
+
except IndexError as e:
|
139
|
+
err = e
|
140
|
+
continue
|
141
|
+
|
142
|
+
# check that response corresponds to sent command
|
143
|
+
if response_no == cmd_no:
|
144
|
+
return Ok(response)
|
145
|
+
else:
|
146
|
+
continue
|
147
|
+
else:
|
148
|
+
return Err(
|
149
|
+
f"Failed to receive reply to command #{cmd_no} due to {err} caused by {err_msg}."
|
150
|
+
)
|