├── doc ├── .gitignore ├── source │ ├── .gitignore │ ├── _static │ │ ├── overview.png │ │ ├── theme_overrides.css │ │ └── laser_control_client.py │ ├── common │ │ ├── socket_clients.rst │ │ ├── text_plot.rst │ │ └── database_saver.rst │ ├── README │ ├── apps │ │ └── bakeout.rst │ ├── howtos │ │ └── bakeoutbox.rst │ ├── auxiliary.rst │ ├── apps.rst │ ├── howtos.rst │ ├── drivers-autogen-only │ │ ├── fug.rst │ │ ├── scpi.rst │ │ ├── NGC2D.rst │ │ ├── tenma.rst │ │ ├── ccs811.rst │ │ ├── epimax.rst │ │ ├── innova.rst │ │ ├── lascar.rst │ │ ├── xgs600.rst │ │ ├── ADS1115.rst │ │ ├── crowcon.rst │ │ ├── htc5500.rst │ │ ├── vogtlin.rst │ │ ├── cpx400dp.rst │ │ ├── luxaflex.rst │ │ ├── mks_937b.rst │ │ ├── omegabus.rst │ │ ├── tsl45315.rst │ │ ├── hamamatsu.rst │ │ ├── mks_pi_pc.rst │ │ ├── omega_cni.rst │ │ ├── srs_sr630.rst │ │ ├── bronkhorst.rst │ │ ├── dataq_comm.rst │ │ ├── ti_ads1115.rst │ │ ├── wpi_al1000.rst │ │ ├── asair_aht20.rst │ │ ├── edwards_agc.rst │ │ ├── galaxy_3500.rst │ │ ├── isotech_ips.rst │ │ ├── nxp_pcf8593.rst │ │ ├── omega_D6400.rst │ │ ├── omron_d6fph.rst │ │ ├── powerwalker.rst │ │ ├── specs_iqe11.rst │ │ ├── bosch_bme280.rst │ │ ├── dataq_DI2008.rst │ │ ├── dataq_binary.rst │ │ ├── edwards_nxds.rst │ │ ├── keithley_smu.rst │ │ ├── mks_g_series.rst │ │ ├── omega_cn7800.rst │ │ ├── stahl_hv_400.rst │ │ ├── weather_info.rst │ │ ├── chemitec_s411.rst │ │ ├── keithley_2700.rst │ │ ├── specs_XRC1000.rst │ │ ├── teltonika_rut.rst │ │ ├── agilent_34410A.rst │ │ ├── agilent_34972A.rst │ │ ├── deltaco_TB_298.rst │ │ ├── honeywell_6000.rst │ │ ├── inficon_sqm160.rst │ │ ├── mks_925_pirani.rst │ │ ├── vaisala_dmt143.rst │ │ ├── pfeiffer_qmg420.rst │ │ ├── pfeiffer_qmg422.rst │ │ ├── sensirion_sps30.rst │ │ ├── polyscience_4100.rst │ │ ├── brooks_s_protocol.rst │ │ ├── rosemount_nga2000.rst │ │ ├── vivo_technologies.rst │ │ ├── seeed_studio_relay.rst │ │ ├── freescale_mma7660fc.rst │ │ ├── kjlc_pressure_gauge.rst │ │ ├── pfeiffer_turbo_pump.rst │ │ ├── sparkfun_quad_relay.rst │ │ ├── tdk_lambda_z_series.rst │ │ ├── xp_power_hpa_series.rst │ │ ├── analogdevices_ad5667.rst │ │ ├── intellemetrics_il800.rst │ │ ├── ocs_3l_oxygen_sensor.rst │ │ ├── powerwalker_ethernet.rst │ │ ├── xp_power_1500_series.rst │ │ ├── microchip_tech_mcp3428.rst │ │ ├── microchip_tech_mcp9808.rst │ │ ├── stmicroelectronics_ais328dq.rst │ │ └── stmicroelectronics_l3g4200d.rst │ ├── file-parsers.rst │ ├── drivers.rst │ ├── common.rst │ ├── drivers_autogen_only.rst │ ├── index.rst │ ├── drivers │ │ ├── four_d_systems.rst │ │ └── pfeiffer.rst │ └── settings.rst └── NOTES ├── PyExpLabSys ├── apps │ ├── __init__.py │ ├── qms │ │ ├── __init__.py │ │ ├── .gitignore │ │ └── NOTES │ ├── stepped_program_runner │ │ └── __init__.py │ ├── keithley_2450_probe_station │ │ ├── execute_iteration.lua │ │ ├── prepare_tsp_triggers.lua │ │ └── ps_dmm_reader.py │ ├── bakeoutweb │ │ ├── runbakeoutweb.bash │ │ ├── static │ │ │ └── frontpage.css │ │ └── templates │ │ │ └── frontpage.html │ ├── tof │ │ └── helper_scripts │ │ │ └── lm_test.py │ ├── socket_supervisor.py │ └── transparency_measurement.py ├── auxiliary │ ├── __init__.py │ ├── tc_calculator.py │ ├── pid.py │ └── rtd_calculator.py ├── common │ ├── __init__.py │ ├── massspec │ │ ├── qt.py │ │ └── test.py │ ├── decorators.py │ ├── chiller_reader.py │ └── supported_versions.py ├── drivers │ ├── __init__.py │ ├── sparkfun_quad_relay.py │ ├── ti_ads1115.py │ ├── microchip_tech_mcp9808.py │ ├── intellemetrics_il800.py │ ├── seeed_studio_relay.py │ ├── inficon_sqc310.py │ ├── kjlc_pressure_gauge.py │ ├── freescale_mma7660fc.py │ ├── tsl45315.py │ ├── honeywell_6000.py │ ├── isotech_ips.py │ ├── omega_cn7800.py │ ├── keithley_2700.py │ ├── NI_USB_TC01.py │ ├── NGC2D.py │ ├── omron_d6fph.py │ ├── nxp_pcf8593.py │ ├── mks_925_pirani.py │ ├── lascar.py │ ├── stmicroelectronics_l3g4200d.py │ ├── stmicroelectronics_ais328dq.py │ ├── asair_aht20.py │ ├── htc5500.py │ └── edwards_agc.py ├── file_parsers │ ├── __init__.py │ └── omicron.py ├── thirdparty │ ├── __init__.py │ ├── olefile.txt │ └── cached_property.py ├── defaults.yaml └── __init__.py ├── tests ├── .gitignore ├── functional_test │ └── fileparsers │ │ └── test_chemstation │ │ ├── TCD3C.ch │ │ ├── 05102016_CAL_CH4_5CM3 │ │ └── 001F0101.D │ │ │ ├── Report.TXT │ │ │ ├── REPORT01.CSV │ │ │ ├── REPORT02.CSV │ │ │ └── Report00.CSV │ │ ├── def_GC 2015-01-13 11-16-24 │ │ └── NV-F0101.D │ │ │ ├── FID1A.ch │ │ │ ├── FID2B.ch │ │ │ ├── TCD3C.ch │ │ │ ├── Report.TXT │ │ │ ├── REPORT01.CSV │ │ │ ├── REPORT02.CSV │ │ │ ├── REPORT03.CSV │ │ │ └── Report00.CSV │ │ ├── ch_metadata.json │ │ ├── sequence_metadata.json │ │ ├── chemstation_data.json │ │ └── generate.py ├── README.md └── tmp │ └── sockets │ └── test_live_socket.py ├── .flake8 ├── archive ├── rasppi75_pH_regulation │ ├── .gitignore │ ├── PURPOSE │ ├── test_pump.py │ ├── omega_test.py │ ├── values_and_commands.txt │ └── pid_opt_test.py ├── rasppi68 │ └── settings.py ├── multimeter │ └── demo │ │ └── plots │ │ ├── qtseigner_qwt │ │ ├── README │ │ └── simple_plot.ui │ │ └── simple_qwt │ │ └── plottest.py ├── cinfkiosk │ ├── INSTALL │ ├── test2.py │ ├── double_axis.py │ ├── test_pyqwt.py │ ├── test_websocket.py │ └── test_pyqtgraph.py ├── nh3_setup │ ├── rasppi14 │ │ ├── start_screen.sh │ │ └── socket_server.py │ └── rasppi09 │ │ ├── socket_server.py │ │ └── xgs600.py ├── pentax_picture.py ├── canon_eos.py ├── nidaq.py ├── ParallelPortBinaryOut.py └── byg │ └── BYG-F0139 │ └── mymaster.py ├── requirements-dev.txt ├── pyproject.toml ├── release.bash ├── .vim ├── ftdetect │ └── channel.vim └── syntax │ └── channel.vim ├── MANIFEST.in ├── bootstrap ├── PyExpLabSys.reg ├── filetypes.common ├── filetypes.python ├── .emacs-simple ├── user_settings.yaml ├── linux_basic_config.bash ├── .emacs ├── README.bootstrap_windows └── bootstrap_windows.bat ├── requirements.txt ├── bin ├── socket_tester ├── pycheckers └── purpose ├── requirements-doc.txt ├── .gitignore ├── makefile ├── setup.cfg └── .readthedocs.yaml /doc/.gitignore: -------------------------------------------------------------------------------- 1 | build/* -------------------------------------------------------------------------------- /PyExpLabSys/apps/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /tests/.gitignore: -------------------------------------------------------------------------------- 1 | testdata -------------------------------------------------------------------------------- /PyExpLabSys/apps/qms/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /PyExpLabSys/auxiliary/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /PyExpLabSys/common/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /PyExpLabSys/drivers/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /doc/source/.gitignore: -------------------------------------------------------------------------------- 1 | py3_stat.inc -------------------------------------------------------------------------------- /PyExpLabSys/file_parsers/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /PyExpLabSys/thirdparty/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.flake8: -------------------------------------------------------------------------------- 1 | [flake8] 2 | max-line-length = 85 -------------------------------------------------------------------------------- /PyExpLabSys/apps/qms/.gitignore: -------------------------------------------------------------------------------- 1 | qms.txt 2 | -------------------------------------------------------------------------------- /archive/rasppi75_pH_regulation/.gitignore: -------------------------------------------------------------------------------- 1 | archive -------------------------------------------------------------------------------- /PyExpLabSys/apps/stepped_program_runner/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /requirements-dev.txt: -------------------------------------------------------------------------------- 1 | invoke 2 | pylint 3 | pytest 4 | -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.black] 2 | skip-string-normalization = true 3 | -------------------------------------------------------------------------------- /release.bash: -------------------------------------------------------------------------------- 1 | rm -rf build 2 | python setup.py sdist bdist_wheel 3 | -------------------------------------------------------------------------------- /.vim/ftdetect/channel.vim: -------------------------------------------------------------------------------- 1 | au BufRead,BufNewFile *.txt set filetype=channel 2 | -------------------------------------------------------------------------------- /archive/rasppi68/settings.py: -------------------------------------------------------------------------------- 1 | setup = 'TOF display server' 2 | ports = [5900] 3 | -------------------------------------------------------------------------------- /doc/NOTES: -------------------------------------------------------------------------------- 1 | You can force Sphinx to build all files by doing 2 | make html OPTS=-a -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include LICENSE README.rst requirements.txt 2 | recursive-include PyExpLabSys *.py 3 | -------------------------------------------------------------------------------- /bootstrap/PyExpLabSys.reg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CINF/PyExpLabSys/HEAD/bootstrap/PyExpLabSys.reg -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | six 2 | numpy 3 | smbus 4 | pyyaml 5 | pymysql 6 | pyserial 7 | requests 8 | minimalmodbus 9 | -------------------------------------------------------------------------------- /doc/source/_static/overview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CINF/PyExpLabSys/HEAD/doc/source/_static/overview.png -------------------------------------------------------------------------------- /bin/socket_tester: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python2 2 | 3 | from PyExpLabSys.apps import socket_tester 4 | 5 | socket_tester.main() 6 | -------------------------------------------------------------------------------- /bootstrap/filetypes.common: -------------------------------------------------------------------------------- 1 | [build-menu] 2 | FT_01_LB=Check 3 | FT_01_CM=pycheckers %f 4 | FT_01_WD= 5 | error_regex=([^:]+):([0-9]+):([0-9:]+)? .* 6 | -------------------------------------------------------------------------------- /bootstrap/filetypes.python: -------------------------------------------------------------------------------- 1 | [build-menu] 2 | FT_01_LB=Check 3 | FT_01_CM=pycheckers %f 4 | FT_01_WD= 5 | error_regex=([^:]+):([0-9]+):([0-9:]+)? .* 6 | -------------------------------------------------------------------------------- /doc/source/common/socket_clients.rst: -------------------------------------------------------------------------------- 1 | .. _common-doc-socket-client: 2 | 3 | ************************ 4 | The socket_client module 5 | ************************ 6 | -------------------------------------------------------------------------------- /archive/rasppi75_pH_regulation/PURPOSE: -------------------------------------------------------------------------------- 1 | This Raspberry Pi is responsible for controlling pH in the NiGa synthesis setup located in the east wards fumehood in 312. 2 | -------------------------------------------------------------------------------- /tests/functional_test/fileparsers/test_chemstation/TCD3C.ch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CINF/PyExpLabSys/HEAD/tests/functional_test/fileparsers/test_chemstation/TCD3C.ch -------------------------------------------------------------------------------- /bin/pycheckers: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | #echo "====== pyflakes ======" 4 | #pyflakes $1 5 | #echo "====== pylint ======" 6 | pylint --reports=n --output-format=parseable $1 7 | -------------------------------------------------------------------------------- /doc/source/README: -------------------------------------------------------------------------------- 1 | To generate the docs go back to the "PyExpLabSys/doc" level and execute: 2 | 3 | make html 4 | 5 | Generating the docs require Sphinx and the Napoleon Sphinx extension. -------------------------------------------------------------------------------- /archive/multimeter/demo/plots/qtseigner_qwt/README: -------------------------------------------------------------------------------- 1 | The simple_plot.ui file from QtDesigner is translated into simple_plot.py with the command: 2 | 3 | pyuic4 simple_plot.ui > simple_plot.py 4 | -------------------------------------------------------------------------------- /tests/functional_test/fileparsers/test_chemstation/05102016_CAL_CH4_5CM3/001F0101.D/Report.TXT: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CINF/PyExpLabSys/HEAD/tests/functional_test/fileparsers/test_chemstation/05102016_CAL_CH4_5CM3/001F0101.D/Report.TXT -------------------------------------------------------------------------------- /requirements-doc.txt: -------------------------------------------------------------------------------- 1 | chainmap 2 | crc16 3 | pyyaml 4 | sphinx 5 | pyserial 6 | evdev 7 | minimalmodbus==0.6 8 | smbus-cffi 9 | unicodecsv 10 | sphinx-rtd-theme 11 | pymysql 12 | pyodbc 13 | numpy 14 | pyusb 15 | wiringpi 16 | paramiko 17 | -------------------------------------------------------------------------------- /tests/functional_test/fileparsers/test_chemstation/05102016_CAL_CH4_5CM3/001F0101.D/REPORT01.CSV: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CINF/PyExpLabSys/HEAD/tests/functional_test/fileparsers/test_chemstation/05102016_CAL_CH4_5CM3/001F0101.D/REPORT01.CSV -------------------------------------------------------------------------------- /tests/functional_test/fileparsers/test_chemstation/05102016_CAL_CH4_5CM3/001F0101.D/REPORT02.CSV: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CINF/PyExpLabSys/HEAD/tests/functional_test/fileparsers/test_chemstation/05102016_CAL_CH4_5CM3/001F0101.D/REPORT02.CSV -------------------------------------------------------------------------------- /tests/functional_test/fileparsers/test_chemstation/05102016_CAL_CH4_5CM3/001F0101.D/Report00.CSV: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CINF/PyExpLabSys/HEAD/tests/functional_test/fileparsers/test_chemstation/05102016_CAL_CH4_5CM3/001F0101.D/Report00.CSV -------------------------------------------------------------------------------- /tests/functional_test/fileparsers/test_chemstation/def_GC 2015-01-13 11-16-24/NV-F0101.D/FID1A.ch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CINF/PyExpLabSys/HEAD/tests/functional_test/fileparsers/test_chemstation/def_GC 2015-01-13 11-16-24/NV-F0101.D/FID1A.ch -------------------------------------------------------------------------------- /tests/functional_test/fileparsers/test_chemstation/def_GC 2015-01-13 11-16-24/NV-F0101.D/FID2B.ch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CINF/PyExpLabSys/HEAD/tests/functional_test/fileparsers/test_chemstation/def_GC 2015-01-13 11-16-24/NV-F0101.D/FID2B.ch -------------------------------------------------------------------------------- /tests/functional_test/fileparsers/test_chemstation/def_GC 2015-01-13 11-16-24/NV-F0101.D/TCD3C.ch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CINF/PyExpLabSys/HEAD/tests/functional_test/fileparsers/test_chemstation/def_GC 2015-01-13 11-16-24/NV-F0101.D/TCD3C.ch -------------------------------------------------------------------------------- /doc/source/apps/bakeout.rst: -------------------------------------------------------------------------------- 1 | .. _app_bakeout: 2 | 3 | *************** 4 | The Bakeout App 5 | *************** 6 | 7 | .. contents:: 8 | 9 | This app ... FIXME 10 | 11 | A Section 12 | ========= 13 | 14 | A subsection 15 | ------------ 16 | -------------------------------------------------------------------------------- /tests/functional_test/fileparsers/test_chemstation/def_GC 2015-01-13 11-16-24/NV-F0101.D/Report.TXT: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CINF/PyExpLabSys/HEAD/tests/functional_test/fileparsers/test_chemstation/def_GC 2015-01-13 11-16-24/NV-F0101.D/Report.TXT -------------------------------------------------------------------------------- /tests/functional_test/fileparsers/test_chemstation/def_GC 2015-01-13 11-16-24/NV-F0101.D/REPORT01.CSV: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CINF/PyExpLabSys/HEAD/tests/functional_test/fileparsers/test_chemstation/def_GC 2015-01-13 11-16-24/NV-F0101.D/REPORT01.CSV -------------------------------------------------------------------------------- /tests/functional_test/fileparsers/test_chemstation/def_GC 2015-01-13 11-16-24/NV-F0101.D/REPORT02.CSV: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CINF/PyExpLabSys/HEAD/tests/functional_test/fileparsers/test_chemstation/def_GC 2015-01-13 11-16-24/NV-F0101.D/REPORT02.CSV -------------------------------------------------------------------------------- /tests/functional_test/fileparsers/test_chemstation/def_GC 2015-01-13 11-16-24/NV-F0101.D/REPORT03.CSV: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CINF/PyExpLabSys/HEAD/tests/functional_test/fileparsers/test_chemstation/def_GC 2015-01-13 11-16-24/NV-F0101.D/REPORT03.CSV -------------------------------------------------------------------------------- /tests/functional_test/fileparsers/test_chemstation/def_GC 2015-01-13 11-16-24/NV-F0101.D/Report00.CSV: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/CINF/PyExpLabSys/HEAD/tests/functional_test/fileparsers/test_chemstation/def_GC 2015-01-13 11-16-24/NV-F0101.D/Report00.CSV -------------------------------------------------------------------------------- /archive/cinfkiosk/INSTALL: -------------------------------------------------------------------------------- 1 | APT 2 | numpy 3 | libssl-dev 4 | libffi-dev 5 | python3-pyqt4 6 | libmysqlclient-dev 7 | 8 | PIP 9 | service_identity 10 | pyqtgraph 11 | pyopenssl 12 | cryptography 13 | autobahn 14 | twisted 15 | mysqlclient 16 | 17 | 18 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | *.p 3 | *.pyc 4 | *flymake* 5 | \#*\# 6 | machines/rasppi25/credentials.py 7 | machines/rasppi25/thetaprobe_pressure_logger.log* 8 | machines/towermain/temperature_log* 9 | *credentials.py 10 | *error_log.txt 11 | *logger.txt 12 | .cache 13 | .venv 14 | -------------------------------------------------------------------------------- /archive/nh3_setup/rasppi14/start_screen.sh: -------------------------------------------------------------------------------- 1 | NAME="autostart" 2 | 3 | cd /home/pi/PyExpLabSys/rasppi14 4 | screen -dmS "$NAME" 5 | screen -S "$NAME" -X screen 6 | screen -S "$NAME" -p 0 -X stuff "python socket_server.py $(printf \\r)" 7 | screen -S "$NAME" -p 1 -X stuff "python data_logger.py $(printf \\r)" -------------------------------------------------------------------------------- /archive/pentax_picture.py: -------------------------------------------------------------------------------- 1 | import os 2 | from subprocess import call 3 | 4 | def AcquireImage(filename): 5 | call(["pktriggercord-cli", "--model=k-r","--output_file=pentax"]) 6 | os.rename("pentax-0000.jpg",filename) 7 | 8 | if __name__ == "__main__": 9 | AcquireImage("test.jpg") 10 | -------------------------------------------------------------------------------- /doc/source/howtos/bakeoutbox.rst: -------------------------------------------------------------------------------- 1 | .. _howtos_bakeout_box: 2 | 3 | ********************* 4 | The Bakeout Box HOWTO 5 | ********************* 6 | 7 | .. contents:: 8 | 9 | This HOWTO explains how to setup and configure a new bakeout box ... FIXME 10 | 11 | A Section 12 | ========= 13 | 14 | A subsection 15 | ------------ 16 | -------------------------------------------------------------------------------- /bootstrap/.emacs-simple: -------------------------------------------------------------------------------- 1 | ;; .emacs 2 | 3 | ;; enable visual feedback on selections 4 | (setq transient-mark-mode t) 5 | (setq column-number-mode t) 6 | 7 | ;; default to better frame titles 8 | (setq frame-title-format 9 | (concat "%b - emacs@" (system-name))) 10 | 11 | ;; default to unified diffs 12 | (setq diff-switches "-u") 13 | -------------------------------------------------------------------------------- /doc/source/auxiliary.rst: -------------------------------------------------------------------------------- 1 | ***************************** 2 | Auxiliary Software Components 3 | ***************************** 4 | 5 | .. The common components subpage has its own table of contents for everything 6 | .. that is below this level, which is contained in the files below. 7 | .. toctree:: 8 | :maxdepth: 4 9 | 10 | auxiliary/communications_collecting_pyserial -------------------------------------------------------------------------------- /doc/source/common/text_plot.rst: -------------------------------------------------------------------------------- 1 | .. _common-text-plot: 2 | 3 | ******************** 4 | The text plot module 5 | ******************** 6 | 7 | Autogenerated API documentation for text_plot 8 | ============================================= 9 | 10 | .. automodule:: PyExpLabSys.common.text_plot 11 | :members: 12 | :member-order: bysource 13 | :show-inheritance: 14 | -------------------------------------------------------------------------------- /doc/source/apps.rst: -------------------------------------------------------------------------------- 1 | 2 | .. _apps: 3 | 4 | **** 5 | Apps 6 | **** 7 | 8 | This section documents the various apps in PyExpLabSys. 9 | 10 | .. The howtos components subpage has its own table of contents if necessary for everything 11 | .. that is below this level, which is contained in the files below. 12 | .. toctree:: 13 | :maxdepth: 1 14 | :glob: 15 | 16 | apps/* 17 | -------------------------------------------------------------------------------- /doc/source/common/database_saver.rst: -------------------------------------------------------------------------------- 1 | .. _common-doc-database_saver: 2 | 3 | ************************* 4 | The database_saver module 5 | ************************* 6 | 7 | Autogenerated API documentation for database_saver 8 | ================================================== 9 | 10 | .. automodule:: PyExpLabSys.common.database_saver 11 | :members: 12 | :member-order: bysource 13 | :show-inheritance: 14 | -------------------------------------------------------------------------------- /doc/source/_static/theme_overrides.css: -------------------------------------------------------------------------------- 1 | /* override table width restrictions */ 2 | @media screen and (min-width: 767px) { 3 | 4 | .wy-table-responsive table td { 5 | /* !important prevents the common CSS stylesheets from overriding 6 | this as on RTD they are loaded after this stylesheet */ 7 | white-space: normal !important; 8 | } 9 | 10 | .wy-table-responsive { 11 | overflow: visible !important; 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /makefile: -------------------------------------------------------------------------------- 1 | test2: 2 | python2 -m pytest 3 | 4 | test3: 5 | python3 -m pytest 6 | 7 | docs: 8 | $(MAKE) -C doc html 9 | @echo "\033[95m\n\nBuild successful! View the docs at docs/_build/html/index.html.\n\033[0m" 10 | 11 | clean: 12 | find . -name '*.py[co]' -delete 13 | 14 | find . -name '*~' -delete 15 | find . -name '__pycache__' -delete 16 | rm -rf soco.egg-info 17 | rm -rf dist 18 | $(MAKE) -C doc clean 19 | 20 | .PHONY: docs test clean 21 | -------------------------------------------------------------------------------- /PyExpLabSys/thirdparty/olefile.txt: -------------------------------------------------------------------------------- 1 | olefile.py is a (short lived) fork from this project. 2 | 3 | http://www.decalage.info/python/olefileio 4 | 5 | PyExpLabSys needed more changes to the core library, than it was 6 | realistic to have upstreamed quickly, hence the fork. It is the goal 7 | to upstream the changes in time. All credits for the olefile project 8 | goes the original developers as described in the start of the 9 | olefile.py file and on the project homepage. 10 | -------------------------------------------------------------------------------- /PyExpLabSys/apps/keithley_2450_probe_station/execute_iteration.lua: -------------------------------------------------------------------------------- 1 | -- Lua script for taking a single reading on both nodes 2 | node[2].trigger.model.initiate() 3 | trigger.model.initiate() 4 | waitcomplete() 5 | n = node[1].defbuffer1.endindex 6 | m = node[2].defbuffer1.endindex 7 | printbuffer(n, n, node[1].defbuffer1, node[1].defbuffer1.units, node[1].defbuffer1.sourcevalues) 8 | printbuffer(m, m, node[2].defbuffer1, node[2].defbuffer1.units, node[2].defbuffer1.sourcevalues) 9 | print("end " .. n .. " " .. m) 10 | -------------------------------------------------------------------------------- /PyExpLabSys/defaults.yaml: -------------------------------------------------------------------------------- 1 | # PyExpLabSys settings defaults 2 | 3 | # Common 4 | common_sql_reader_user: null 5 | common_sql_reader_password: null 6 | # The host can be hostname or IP-address 7 | common_liveserver_host: null 8 | common_liveserver_port: null 9 | 10 | # PyExpLabSys.common.utilities settings 11 | util_log_warning_email: null 12 | util_log_error_email: null 13 | util_log_mail_host: null 14 | util_log_max_emails_per_period: 5 15 | util_log_email_throttle_time: 86400 # 1 day 16 | util_log_backlog_limit: 250 17 | -------------------------------------------------------------------------------- /doc/source/howtos.rst: -------------------------------------------------------------------------------- 1 | 2 | .. _howtos: 3 | 4 | ******** 5 | How To's 6 | ******** 7 | 8 | This section contain howtos for different procedures associated with elements of 9 | PyExpLabSys. This could e.g. be the installation and configuration of a requirement. 10 | 11 | 12 | .. The howtos components subpage has its own table of contents if necessary for everything 13 | .. that is below this level, which is contained in the files below. 14 | .. toctree:: 15 | :maxdepth: 1 16 | :glob: 17 | 18 | howtos/* 19 | -------------------------------------------------------------------------------- /archive/cinfkiosk/test2.py: -------------------------------------------------------------------------------- 1 | from qwt.qt.QtGui import QApplication 2 | from qwt import QwtPlot, QwtPlotCurve 3 | import numpy as np 4 | 5 | app = QApplication([]) 6 | 7 | x = np.linspace(-10, 10, 500) 8 | y1, y2 = np.cos(x), np.sin(x) 9 | 10 | my_plot = QwtPlot("Two curves") 11 | curve1, curve2 = QwtPlotCurve("Curve 1"), QwtPlotCurve("Curve 2") 12 | curve1.setData(x, y1) 13 | curve2.setData(x, y2) 14 | curve1.attach(my_plot) 15 | curve2.attach(my_plot) 16 | my_plot.resize(600, 300) 17 | my_plot.replot() 18 | my_plot.show() 19 | 20 | app.exec_() 21 | -------------------------------------------------------------------------------- /setup.cfg: -------------------------------------------------------------------------------- 1 | [tool.pytest] 2 | # By default, run with verbose on and show detail for skipped and xfail tests. 3 | # The confcutdir argument tells pytest to load conftest.py starting from 4 | # the unittest directory 5 | addopts = -rsxX -v 6 | # We need py.test >=2.5 (for yield_fixtures) 7 | minversion = 2.5 8 | # Don't look in these directories for tests 9 | norecursedirs=venv* .git .hg build doc *.egg-info equipment_test tmp machines archive file_parsers 10 | 11 | [bdist_wheel] 12 | universal = 1 13 | 14 | [metadata] 15 | license_file = LICENSE 16 | -------------------------------------------------------------------------------- /doc/source/drivers-autogen-only/fug.rst: -------------------------------------------------------------------------------- 1 | .. 2 | This file has been autogenerated 3 | 4 | If you wish to add more content e.g. usage examples please also move the file from the 5 | drivers-autogen-only folder to the drivers folder. 6 | 7 | .. _drivers-doc-fug: 8 | 9 | ************** 10 | The fug module 11 | ************** 12 | 13 | Autogenerated API documentation for fug 14 | ======================================= 15 | 16 | .. automodule:: PyExpLabSys.drivers.fug 17 | :members: 18 | :member-order: bysource 19 | :show-inheritance: 20 | 21 | -------------------------------------------------------------------------------- /doc/source/drivers-autogen-only/scpi.rst: -------------------------------------------------------------------------------- 1 | .. 2 | This file has been autogenerated 3 | 4 | If you wish to add more content e.g. usage examples please also move the file from the 5 | drivers-autogen-only folder to the drivers folder. 6 | 7 | .. _drivers-doc-scpi: 8 | 9 | *************** 10 | The scpi module 11 | *************** 12 | 13 | Autogenerated API documentation for scpi 14 | ======================================== 15 | 16 | .. automodule:: PyExpLabSys.drivers.scpi 17 | :members: 18 | :member-order: bysource 19 | :show-inheritance: 20 | 21 | -------------------------------------------------------------------------------- /bootstrap/user_settings.yaml: -------------------------------------------------------------------------------- 1 | # PyExpLabSys settings defaults 2 | 3 | # Common 4 | sql_server_host: 'sql_server_hostname.example.com' 5 | sql_database: 'data' 6 | 7 | common_sql_reader_user: 'reader' 8 | common_sql_reader_password: 'reader' 9 | # The host can be hostname or IP-address 10 | common_liveserver_host: 'wsserver.example.com' 11 | common_liveserver_port: 9767 12 | 13 | # PyExpLabSys.common.utilities settings 14 | util_log_warning_email: 'server_admin@example.com' 15 | util_log_error_email: 'server_admin@example.com' 16 | util_log_mail_host: 'smtp.example.com' 17 | -------------------------------------------------------------------------------- /doc/source/drivers-autogen-only/NGC2D.rst: -------------------------------------------------------------------------------- 1 | .. 2 | This file has been autogenerated 3 | 4 | If you wish to add more content e.g. usage examples please also move the file from the 5 | drivers-autogen-only folder to the drivers folder. 6 | 7 | .. _drivers-doc-NGC2D: 8 | 9 | **************** 10 | The NGC2D module 11 | **************** 12 | 13 | Autogenerated API documentation for NGC2D 14 | ========================================= 15 | 16 | .. automodule:: PyExpLabSys.drivers.NGC2D 17 | :members: 18 | :member-order: bysource 19 | :show-inheritance: 20 | 21 | -------------------------------------------------------------------------------- /doc/source/drivers-autogen-only/tenma.rst: -------------------------------------------------------------------------------- 1 | .. 2 | This file has been autogenerated 3 | 4 | If you wish to add more content e.g. usage examples please also move the file from the 5 | drivers-autogen-only folder to the drivers folder. 6 | 7 | .. _drivers-doc-tenma: 8 | 9 | **************** 10 | The tenma module 11 | **************** 12 | 13 | Autogenerated API documentation for tenma 14 | ========================================= 15 | 16 | .. automodule:: PyExpLabSys.drivers.tenma 17 | :members: 18 | :member-order: bysource 19 | :show-inheritance: 20 | 21 | -------------------------------------------------------------------------------- /doc/source/drivers-autogen-only/ccs811.rst: -------------------------------------------------------------------------------- 1 | .. 2 | This file has been autogenerated 3 | 4 | If you wish to add more content e.g. usage examples please also move the file from the 5 | drivers-autogen-only folder to the drivers folder. 6 | 7 | .. _drivers-doc-ccs811: 8 | 9 | ***************** 10 | The ccs811 module 11 | ***************** 12 | 13 | Autogenerated API documentation for ccs811 14 | ========================================== 15 | 16 | .. automodule:: PyExpLabSys.drivers.ccs811 17 | :members: 18 | :member-order: bysource 19 | :show-inheritance: 20 | 21 | -------------------------------------------------------------------------------- /doc/source/drivers-autogen-only/epimax.rst: -------------------------------------------------------------------------------- 1 | .. 2 | This file has been autogenerated 3 | 4 | If you wish to add more content e.g. usage examples please also move the file from the 5 | drivers-autogen-only folder to the drivers folder. 6 | 7 | .. _drivers-doc-epimax: 8 | 9 | ***************** 10 | The epimax module 11 | ***************** 12 | 13 | Autogenerated API documentation for epimax 14 | ========================================== 15 | 16 | .. automodule:: PyExpLabSys.drivers.epimax 17 | :members: 18 | :member-order: bysource 19 | :show-inheritance: 20 | 21 | -------------------------------------------------------------------------------- /doc/source/drivers-autogen-only/innova.rst: -------------------------------------------------------------------------------- 1 | .. 2 | This file has been autogenerated 3 | 4 | If you wish to add more content e.g. usage examples please also move the file from the 5 | drivers-autogen-only folder to the drivers folder. 6 | 7 | .. _drivers-doc-innova: 8 | 9 | ***************** 10 | The innova module 11 | ***************** 12 | 13 | Autogenerated API documentation for innova 14 | ========================================== 15 | 16 | .. automodule:: PyExpLabSys.drivers.innova 17 | :members: 18 | :member-order: bysource 19 | :show-inheritance: 20 | 21 | -------------------------------------------------------------------------------- /doc/source/drivers-autogen-only/lascar.rst: -------------------------------------------------------------------------------- 1 | .. 2 | This file has been autogenerated 3 | 4 | If you wish to add more content e.g. usage examples please also move the file from the 5 | drivers-autogen-only folder to the drivers folder. 6 | 7 | .. _drivers-doc-lascar: 8 | 9 | ***************** 10 | The lascar module 11 | ***************** 12 | 13 | Autogenerated API documentation for lascar 14 | ========================================== 15 | 16 | .. automodule:: PyExpLabSys.drivers.lascar 17 | :members: 18 | :member-order: bysource 19 | :show-inheritance: 20 | 21 | -------------------------------------------------------------------------------- /doc/source/drivers-autogen-only/xgs600.rst: -------------------------------------------------------------------------------- 1 | .. 2 | This file has been autogenerated 3 | 4 | If you wish to add more content e.g. usage examples please also move the file from the 5 | drivers-autogen-only folder to the drivers folder. 6 | 7 | .. _drivers-doc-xgs600: 8 | 9 | ***************** 10 | The xgs600 module 11 | ***************** 12 | 13 | Autogenerated API documentation for xgs600 14 | ========================================== 15 | 16 | .. automodule:: PyExpLabSys.drivers.xgs600 17 | :members: 18 | :member-order: bysource 19 | :show-inheritance: 20 | 21 | -------------------------------------------------------------------------------- /doc/source/drivers-autogen-only/ADS1115.rst: -------------------------------------------------------------------------------- 1 | .. 2 | This file has been autogenerated 3 | 4 | If you wish to add more content e.g. usage examples please also move the file from the 5 | drivers-autogen-only folder to the drivers folder. 6 | 7 | .. _drivers-doc-ADS1115: 8 | 9 | ****************** 10 | The ADS1115 module 11 | ****************** 12 | 13 | Autogenerated API documentation for ADS1115 14 | =========================================== 15 | 16 | .. automodule:: PyExpLabSys.drivers.ADS1115 17 | :members: 18 | :member-order: bysource 19 | :show-inheritance: 20 | 21 | -------------------------------------------------------------------------------- /doc/source/drivers-autogen-only/crowcon.rst: -------------------------------------------------------------------------------- 1 | .. 2 | This file has been autogenerated 3 | 4 | If you wish to add more content e.g. usage examples please also move the file from the 5 | drivers-autogen-only folder to the drivers folder. 6 | 7 | .. _drivers-doc-crowcon: 8 | 9 | ****************** 10 | The crowcon module 11 | ****************** 12 | 13 | Autogenerated API documentation for crowcon 14 | =========================================== 15 | 16 | .. automodule:: PyExpLabSys.drivers.crowcon 17 | :members: 18 | :member-order: bysource 19 | :show-inheritance: 20 | 21 | -------------------------------------------------------------------------------- /doc/source/drivers-autogen-only/htc5500.rst: -------------------------------------------------------------------------------- 1 | .. 2 | This file has been autogenerated 3 | 4 | If you wish to add more content e.g. usage examples please also move the file from the 5 | drivers-autogen-only folder to the drivers folder. 6 | 7 | .. _drivers-doc-htc5500: 8 | 9 | ****************** 10 | The htc5500 module 11 | ****************** 12 | 13 | Autogenerated API documentation for htc5500 14 | =========================================== 15 | 16 | .. automodule:: PyExpLabSys.drivers.htc5500 17 | :members: 18 | :member-order: bysource 19 | :show-inheritance: 20 | 21 | -------------------------------------------------------------------------------- /doc/source/drivers-autogen-only/vogtlin.rst: -------------------------------------------------------------------------------- 1 | .. 2 | This file has been autogenerated 3 | 4 | If you wish to add more content e.g. usage examples please also move the file from the 5 | drivers-autogen-only folder to the drivers folder. 6 | 7 | .. _drivers-doc-vogtlin: 8 | 9 | ****************** 10 | The vogtlin module 11 | ****************** 12 | 13 | Autogenerated API documentation for vogtlin 14 | =========================================== 15 | 16 | .. automodule:: PyExpLabSys.drivers.vogtlin 17 | :members: 18 | :member-order: bysource 19 | :show-inheritance: 20 | 21 | -------------------------------------------------------------------------------- /doc/source/drivers-autogen-only/cpx400dp.rst: -------------------------------------------------------------------------------- 1 | .. 2 | This file has been autogenerated 3 | 4 | If you wish to add more content e.g. usage examples please also move the file from the 5 | drivers-autogen-only folder to the drivers folder. 6 | 7 | .. _drivers-doc-cpx400dp: 8 | 9 | ******************* 10 | The cpx400dp module 11 | ******************* 12 | 13 | Autogenerated API documentation for cpx400dp 14 | ============================================ 15 | 16 | .. automodule:: PyExpLabSys.drivers.cpx400dp 17 | :members: 18 | :member-order: bysource 19 | :show-inheritance: 20 | 21 | -------------------------------------------------------------------------------- /doc/source/drivers-autogen-only/luxaflex.rst: -------------------------------------------------------------------------------- 1 | .. 2 | This file has been autogenerated 3 | 4 | If you wish to add more content e.g. usage examples please also move the file from the 5 | drivers-autogen-only folder to the drivers folder. 6 | 7 | .. _drivers-doc-luxaflex: 8 | 9 | ******************* 10 | The luxaflex module 11 | ******************* 12 | 13 | Autogenerated API documentation for luxaflex 14 | ============================================ 15 | 16 | .. automodule:: PyExpLabSys.drivers.luxaflex 17 | :members: 18 | :member-order: bysource 19 | :show-inheritance: 20 | 21 | -------------------------------------------------------------------------------- /doc/source/drivers-autogen-only/mks_937b.rst: -------------------------------------------------------------------------------- 1 | .. 2 | This file has been autogenerated 3 | 4 | If you wish to add more content e.g. usage examples please also move the file from the 5 | drivers-autogen-only folder to the drivers folder. 6 | 7 | .. _drivers-doc-mks_937b: 8 | 9 | ******************* 10 | The mks_937b module 11 | ******************* 12 | 13 | Autogenerated API documentation for mks_937b 14 | ============================================ 15 | 16 | .. automodule:: PyExpLabSys.drivers.mks_937b 17 | :members: 18 | :member-order: bysource 19 | :show-inheritance: 20 | 21 | -------------------------------------------------------------------------------- /doc/source/drivers-autogen-only/omegabus.rst: -------------------------------------------------------------------------------- 1 | .. 2 | This file has been autogenerated 3 | 4 | If you wish to add more content e.g. usage examples please also move the file from the 5 | drivers-autogen-only folder to the drivers folder. 6 | 7 | .. _drivers-doc-omegabus: 8 | 9 | ******************* 10 | The omegabus module 11 | ******************* 12 | 13 | Autogenerated API documentation for omegabus 14 | ============================================ 15 | 16 | .. automodule:: PyExpLabSys.drivers.omegabus 17 | :members: 18 | :member-order: bysource 19 | :show-inheritance: 20 | 21 | -------------------------------------------------------------------------------- /doc/source/drivers-autogen-only/tsl45315.rst: -------------------------------------------------------------------------------- 1 | .. 2 | This file has been autogenerated 3 | 4 | If you wish to add more content e.g. usage examples please also move the file from the 5 | drivers-autogen-only folder to the drivers folder. 6 | 7 | .. _drivers-doc-tsl45315: 8 | 9 | ******************* 10 | The tsl45315 module 11 | ******************* 12 | 13 | Autogenerated API documentation for tsl45315 14 | ============================================ 15 | 16 | .. automodule:: PyExpLabSys.drivers.tsl45315 17 | :members: 18 | :member-order: bysource 19 | :show-inheritance: 20 | 21 | -------------------------------------------------------------------------------- /doc/source/drivers-autogen-only/hamamatsu.rst: -------------------------------------------------------------------------------- 1 | .. 2 | This file has been autogenerated 3 | 4 | If you wish to add more content e.g. usage examples please also move the file from the 5 | drivers-autogen-only folder to the drivers folder. 6 | 7 | .. _drivers-doc-hamamatsu: 8 | 9 | ******************** 10 | The hamamatsu module 11 | ******************** 12 | 13 | Autogenerated API documentation for hamamatsu 14 | ============================================= 15 | 16 | .. automodule:: PyExpLabSys.drivers.hamamatsu 17 | :members: 18 | :member-order: bysource 19 | :show-inheritance: 20 | 21 | -------------------------------------------------------------------------------- /doc/source/drivers-autogen-only/mks_pi_pc.rst: -------------------------------------------------------------------------------- 1 | .. 2 | This file has been autogenerated 3 | 4 | If you wish to add more content e.g. usage examples please also move the file from the 5 | drivers-autogen-only folder to the drivers folder. 6 | 7 | .. _drivers-doc-mks_pi_pc: 8 | 9 | ******************** 10 | The mks_pi_pc module 11 | ******************** 12 | 13 | Autogenerated API documentation for mks_pi_pc 14 | ============================================= 15 | 16 | .. automodule:: PyExpLabSys.drivers.mks_pi_pc 17 | :members: 18 | :member-order: bysource 19 | :show-inheritance: 20 | 21 | -------------------------------------------------------------------------------- /doc/source/drivers-autogen-only/omega_cni.rst: -------------------------------------------------------------------------------- 1 | .. 2 | This file has been autogenerated 3 | 4 | If you wish to add more content e.g. usage examples please also move the file from the 5 | drivers-autogen-only folder to the drivers folder. 6 | 7 | .. _drivers-doc-omega_cni: 8 | 9 | ******************** 10 | The omega_cni module 11 | ******************** 12 | 13 | Autogenerated API documentation for omega_cni 14 | ============================================= 15 | 16 | .. automodule:: PyExpLabSys.drivers.omega_cni 17 | :members: 18 | :member-order: bysource 19 | :show-inheritance: 20 | 21 | -------------------------------------------------------------------------------- /doc/source/drivers-autogen-only/srs_sr630.rst: -------------------------------------------------------------------------------- 1 | .. 2 | This file has been autogenerated 3 | 4 | If you wish to add more content e.g. usage examples please also move the file from the 5 | drivers-autogen-only folder to the drivers folder. 6 | 7 | .. _drivers-doc-srs_sr630: 8 | 9 | ******************** 10 | The srs_sr630 module 11 | ******************** 12 | 13 | Autogenerated API documentation for srs_sr630 14 | ============================================= 15 | 16 | .. automodule:: PyExpLabSys.drivers.srs_sr630 17 | :members: 18 | :member-order: bysource 19 | :show-inheritance: 20 | 21 | -------------------------------------------------------------------------------- /doc/source/drivers-autogen-only/bronkhorst.rst: -------------------------------------------------------------------------------- 1 | .. 2 | This file has been autogenerated 3 | 4 | If you wish to add more content e.g. usage examples please also move the file from the 5 | drivers-autogen-only folder to the drivers folder. 6 | 7 | .. _drivers-doc-bronkhorst: 8 | 9 | ********************* 10 | The bronkhorst module 11 | ********************* 12 | 13 | Autogenerated API documentation for bronkhorst 14 | ============================================== 15 | 16 | .. automodule:: PyExpLabSys.drivers.bronkhorst 17 | :members: 18 | :member-order: bysource 19 | :show-inheritance: 20 | 21 | -------------------------------------------------------------------------------- /doc/source/drivers-autogen-only/dataq_comm.rst: -------------------------------------------------------------------------------- 1 | .. 2 | This file has been autogenerated 3 | 4 | If you wish to add more content e.g. usage examples please also move the file from the 5 | drivers-autogen-only folder to the drivers folder. 6 | 7 | .. _drivers-doc-dataq_comm: 8 | 9 | ********************* 10 | The dataq_comm module 11 | ********************* 12 | 13 | Autogenerated API documentation for dataq_comm 14 | ============================================== 15 | 16 | .. automodule:: PyExpLabSys.drivers.dataq_comm 17 | :members: 18 | :member-order: bysource 19 | :show-inheritance: 20 | 21 | -------------------------------------------------------------------------------- /doc/source/drivers-autogen-only/ti_ads1115.rst: -------------------------------------------------------------------------------- 1 | .. 2 | This file has been autogenerated 3 | 4 | If you wish to add more content e.g. usage examples please also move the file from the 5 | drivers-autogen-only folder to the drivers folder. 6 | 7 | .. _drivers-doc-ti_ads1115: 8 | 9 | ********************* 10 | The ti_ads1115 module 11 | ********************* 12 | 13 | Autogenerated API documentation for ti_ads1115 14 | ============================================== 15 | 16 | .. automodule:: PyExpLabSys.drivers.ti_ads1115 17 | :members: 18 | :member-order: bysource 19 | :show-inheritance: 20 | 21 | -------------------------------------------------------------------------------- /doc/source/drivers-autogen-only/wpi_al1000.rst: -------------------------------------------------------------------------------- 1 | .. 2 | This file has been autogenerated 3 | 4 | If you wish to add more content e.g. usage examples please also move the file from the 5 | drivers-autogen-only folder to the drivers folder. 6 | 7 | .. _drivers-doc-wpi_al1000: 8 | 9 | ********************* 10 | The wpi_al1000 module 11 | ********************* 12 | 13 | Autogenerated API documentation for wpi_al1000 14 | ============================================== 15 | 16 | .. automodule:: PyExpLabSys.drivers.wpi_al1000 17 | :members: 18 | :member-order: bysource 19 | :show-inheritance: 20 | 21 | -------------------------------------------------------------------------------- /PyExpLabSys/auxiliary/tc_calculator.py: -------------------------------------------------------------------------------- 1 | def TC_Calculator(V, No=1, tctype='K'): 2 | if tctype == 'K': 3 | coef = [] 4 | coef.append(0.0) 5 | coef.append(0.0 * 1.0) 6 | coef.append(2.5928 * 10) 7 | coef.append(-7.602961 * 10 ** -1) 8 | coef.append(4.637791 * 10 ** -2) 9 | coef.append(-2.165394 * 10 ** -2) 10 | coef.append(6.048144 * 10 ** -5) 11 | coef.append(-7.293422 * 10 ** -7) 12 | else: 13 | return None 14 | 15 | V = V / No 16 | T = 0.0 17 | for i, c in enumerate(coef): 18 | T += c * V ** i 19 | return T 20 | -------------------------------------------------------------------------------- /doc/source/drivers-autogen-only/asair_aht20.rst: -------------------------------------------------------------------------------- 1 | .. 2 | This file has been autogenerated 3 | 4 | If you wish to add more content e.g. usage examples please also move the file from the 5 | drivers-autogen-only folder to the drivers folder. 6 | 7 | .. _drivers-doc-asair_aht20: 8 | 9 | ********************** 10 | The asair_aht20 module 11 | ********************** 12 | 13 | Autogenerated API documentation for asair_aht20 14 | =============================================== 15 | 16 | .. automodule:: PyExpLabSys.drivers.asair_aht20 17 | :members: 18 | :member-order: bysource 19 | :show-inheritance: 20 | 21 | -------------------------------------------------------------------------------- /doc/source/drivers-autogen-only/edwards_agc.rst: -------------------------------------------------------------------------------- 1 | .. 2 | This file has been autogenerated 3 | 4 | If you wish to add more content e.g. usage examples please also move the file from the 5 | drivers-autogen-only folder to the drivers folder. 6 | 7 | .. _drivers-doc-edwards_agc: 8 | 9 | ********************** 10 | The edwards_agc module 11 | ********************** 12 | 13 | Autogenerated API documentation for edwards_agc 14 | =============================================== 15 | 16 | .. automodule:: PyExpLabSys.drivers.edwards_agc 17 | :members: 18 | :member-order: bysource 19 | :show-inheritance: 20 | 21 | -------------------------------------------------------------------------------- /doc/source/drivers-autogen-only/galaxy_3500.rst: -------------------------------------------------------------------------------- 1 | .. 2 | This file has been autogenerated 3 | 4 | If you wish to add more content e.g. usage examples please also move the file from the 5 | drivers-autogen-only folder to the drivers folder. 6 | 7 | .. _drivers-doc-galaxy_3500: 8 | 9 | ********************** 10 | The galaxy_3500 module 11 | ********************** 12 | 13 | Autogenerated API documentation for galaxy_3500 14 | =============================================== 15 | 16 | .. automodule:: PyExpLabSys.drivers.galaxy_3500 17 | :members: 18 | :member-order: bysource 19 | :show-inheritance: 20 | 21 | -------------------------------------------------------------------------------- /doc/source/drivers-autogen-only/isotech_ips.rst: -------------------------------------------------------------------------------- 1 | .. 2 | This file has been autogenerated 3 | 4 | If you wish to add more content e.g. usage examples please also move the file from the 5 | drivers-autogen-only folder to the drivers folder. 6 | 7 | .. _drivers-doc-isotech_ips: 8 | 9 | ********************** 10 | The isotech_ips module 11 | ********************** 12 | 13 | Autogenerated API documentation for isotech_ips 14 | =============================================== 15 | 16 | .. automodule:: PyExpLabSys.drivers.isotech_ips 17 | :members: 18 | :member-order: bysource 19 | :show-inheritance: 20 | 21 | -------------------------------------------------------------------------------- /doc/source/drivers-autogen-only/nxp_pcf8593.rst: -------------------------------------------------------------------------------- 1 | .. 2 | This file has been autogenerated 3 | 4 | If you wish to add more content e.g. usage examples please also move the file from the 5 | drivers-autogen-only folder to the drivers folder. 6 | 7 | .. _drivers-doc-nxp_pcf8593: 8 | 9 | ********************** 10 | The nxp_pcf8593 module 11 | ********************** 12 | 13 | Autogenerated API documentation for nxp_pcf8593 14 | =============================================== 15 | 16 | .. automodule:: PyExpLabSys.drivers.nxp_pcf8593 17 | :members: 18 | :member-order: bysource 19 | :show-inheritance: 20 | 21 | -------------------------------------------------------------------------------- /doc/source/drivers-autogen-only/omega_D6400.rst: -------------------------------------------------------------------------------- 1 | .. 2 | This file has been autogenerated 3 | 4 | If you wish to add more content e.g. usage examples please also move the file from the 5 | drivers-autogen-only folder to the drivers folder. 6 | 7 | .. _drivers-doc-omega_D6400: 8 | 9 | ********************** 10 | The omega_D6400 module 11 | ********************** 12 | 13 | Autogenerated API documentation for omega_D6400 14 | =============================================== 15 | 16 | .. automodule:: PyExpLabSys.drivers.omega_D6400 17 | :members: 18 | :member-order: bysource 19 | :show-inheritance: 20 | 21 | -------------------------------------------------------------------------------- /doc/source/drivers-autogen-only/omron_d6fph.rst: -------------------------------------------------------------------------------- 1 | .. 2 | This file has been autogenerated 3 | 4 | If you wish to add more content e.g. usage examples please also move the file from the 5 | drivers-autogen-only folder to the drivers folder. 6 | 7 | .. _drivers-doc-omron_d6fph: 8 | 9 | ********************** 10 | The omron_d6fph module 11 | ********************** 12 | 13 | Autogenerated API documentation for omron_d6fph 14 | =============================================== 15 | 16 | .. automodule:: PyExpLabSys.drivers.omron_d6fph 17 | :members: 18 | :member-order: bysource 19 | :show-inheritance: 20 | 21 | -------------------------------------------------------------------------------- /doc/source/drivers-autogen-only/powerwalker.rst: -------------------------------------------------------------------------------- 1 | .. 2 | This file has been autogenerated 3 | 4 | If you wish to add more content e.g. usage examples please also move the file from the 5 | drivers-autogen-only folder to the drivers folder. 6 | 7 | .. _drivers-doc-powerwalker: 8 | 9 | ********************** 10 | The powerwalker module 11 | ********************** 12 | 13 | Autogenerated API documentation for powerwalker 14 | =============================================== 15 | 16 | .. automodule:: PyExpLabSys.drivers.powerwalker 17 | :members: 18 | :member-order: bysource 19 | :show-inheritance: 20 | 21 | -------------------------------------------------------------------------------- /doc/source/drivers-autogen-only/specs_iqe11.rst: -------------------------------------------------------------------------------- 1 | .. 2 | This file has been autogenerated 3 | 4 | If you wish to add more content e.g. usage examples please also move the file from the 5 | drivers-autogen-only folder to the drivers folder. 6 | 7 | .. _drivers-doc-specs_iqe11: 8 | 9 | ********************** 10 | The specs_iqe11 module 11 | ********************** 12 | 13 | Autogenerated API documentation for specs_iqe11 14 | =============================================== 15 | 16 | .. automodule:: PyExpLabSys.drivers.specs_iqe11 17 | :members: 18 | :member-order: bysource 19 | :show-inheritance: 20 | 21 | -------------------------------------------------------------------------------- /tests/functional_test/fileparsers/test_chemstation/ch_metadata.json: -------------------------------------------------------------------------------- 1 | {"version_string": "179", "software revision": "Rev. C.01.06 [61] C", "description": "GC DATA FILE", "instrument": "GC", "software name": "Asterix ChemStation", "start_time": 0.0033333165486653647, "software version": "B.02.03.1", "units": "25 \u00b5V", "sample": "CO2 meth", "date": "21-Jan-15, 08:36:56", "magic_number_version": 179, "sequence_line_or_injection": 38, "end_time": 7.5, "operator": "SYSTEM", "yscaling": 0.00013020833333333333, "detector": "TCD3C, Aux Signal", "datetime": 1421825816.0, "method": "Sine15.M", "injection_or_sequence_line": 38, "inlet": "GCI"} -------------------------------------------------------------------------------- /doc/source/drivers-autogen-only/bosch_bme280.rst: -------------------------------------------------------------------------------- 1 | .. 2 | This file has been autogenerated 3 | 4 | If you wish to add more content e.g. usage examples please also move the file from the 5 | drivers-autogen-only folder to the drivers folder. 6 | 7 | .. _drivers-doc-bosch_bme280: 8 | 9 | *********************** 10 | The bosch_bme280 module 11 | *********************** 12 | 13 | Autogenerated API documentation for bosch_bme280 14 | ================================================ 15 | 16 | .. automodule:: PyExpLabSys.drivers.bosch_bme280 17 | :members: 18 | :member-order: bysource 19 | :show-inheritance: 20 | 21 | -------------------------------------------------------------------------------- /doc/source/drivers-autogen-only/dataq_DI2008.rst: -------------------------------------------------------------------------------- 1 | .. 2 | This file has been autogenerated 3 | 4 | If you wish to add more content e.g. usage examples please also move the file from the 5 | drivers-autogen-only folder to the drivers folder. 6 | 7 | .. _drivers-doc-dataq_DI2008: 8 | 9 | *********************** 10 | The dataq_DI2008 module 11 | *********************** 12 | 13 | Autogenerated API documentation for dataq_DI2008 14 | ================================================ 15 | 16 | .. automodule:: PyExpLabSys.drivers.dataq_DI2008 17 | :members: 18 | :member-order: bysource 19 | :show-inheritance: 20 | 21 | -------------------------------------------------------------------------------- /doc/source/drivers-autogen-only/dataq_binary.rst: -------------------------------------------------------------------------------- 1 | .. 2 | This file has been autogenerated 3 | 4 | If you wish to add more content e.g. usage examples please also move the file from the 5 | drivers-autogen-only folder to the drivers folder. 6 | 7 | .. _drivers-doc-dataq_binary: 8 | 9 | *********************** 10 | The dataq_binary module 11 | *********************** 12 | 13 | Autogenerated API documentation for dataq_binary 14 | ================================================ 15 | 16 | .. automodule:: PyExpLabSys.drivers.dataq_binary 17 | :members: 18 | :member-order: bysource 19 | :show-inheritance: 20 | 21 | -------------------------------------------------------------------------------- /doc/source/drivers-autogen-only/edwards_nxds.rst: -------------------------------------------------------------------------------- 1 | .. 2 | This file has been autogenerated 3 | 4 | If you wish to add more content e.g. usage examples please also move the file from the 5 | drivers-autogen-only folder to the drivers folder. 6 | 7 | .. _drivers-doc-edwards_nxds: 8 | 9 | *********************** 10 | The edwards_nxds module 11 | *********************** 12 | 13 | Autogenerated API documentation for edwards_nxds 14 | ================================================ 15 | 16 | .. automodule:: PyExpLabSys.drivers.edwards_nxds 17 | :members: 18 | :member-order: bysource 19 | :show-inheritance: 20 | 21 | -------------------------------------------------------------------------------- /doc/source/drivers-autogen-only/keithley_smu.rst: -------------------------------------------------------------------------------- 1 | .. 2 | This file has been autogenerated 3 | 4 | If you wish to add more content e.g. usage examples please also move the file from the 5 | drivers-autogen-only folder to the drivers folder. 6 | 7 | .. _drivers-doc-keithley_smu: 8 | 9 | *********************** 10 | The keithley_smu module 11 | *********************** 12 | 13 | Autogenerated API documentation for keithley_smu 14 | ================================================ 15 | 16 | .. automodule:: PyExpLabSys.drivers.keithley_smu 17 | :members: 18 | :member-order: bysource 19 | :show-inheritance: 20 | 21 | -------------------------------------------------------------------------------- /doc/source/drivers-autogen-only/mks_g_series.rst: -------------------------------------------------------------------------------- 1 | .. 2 | This file has been autogenerated 3 | 4 | If you wish to add more content e.g. usage examples please also move the file from the 5 | drivers-autogen-only folder to the drivers folder. 6 | 7 | .. _drivers-doc-mks_g_series: 8 | 9 | *********************** 10 | The mks_g_series module 11 | *********************** 12 | 13 | Autogenerated API documentation for mks_g_series 14 | ================================================ 15 | 16 | .. automodule:: PyExpLabSys.drivers.mks_g_series 17 | :members: 18 | :member-order: bysource 19 | :show-inheritance: 20 | 21 | -------------------------------------------------------------------------------- /doc/source/drivers-autogen-only/omega_cn7800.rst: -------------------------------------------------------------------------------- 1 | .. 2 | This file has been autogenerated 3 | 4 | If you wish to add more content e.g. usage examples please also move the file from the 5 | drivers-autogen-only folder to the drivers folder. 6 | 7 | .. _drivers-doc-omega_cn7800: 8 | 9 | *********************** 10 | The omega_cn7800 module 11 | *********************** 12 | 13 | Autogenerated API documentation for omega_cn7800 14 | ================================================ 15 | 16 | .. automodule:: PyExpLabSys.drivers.omega_cn7800 17 | :members: 18 | :member-order: bysource 19 | :show-inheritance: 20 | 21 | -------------------------------------------------------------------------------- /doc/source/drivers-autogen-only/stahl_hv_400.rst: -------------------------------------------------------------------------------- 1 | .. 2 | This file has been autogenerated 3 | 4 | If you wish to add more content e.g. usage examples please also move the file from the 5 | drivers-autogen-only folder to the drivers folder. 6 | 7 | .. _drivers-doc-stahl_hv_400: 8 | 9 | *********************** 10 | The stahl_hv_400 module 11 | *********************** 12 | 13 | Autogenerated API documentation for stahl_hv_400 14 | ================================================ 15 | 16 | .. automodule:: PyExpLabSys.drivers.stahl_hv_400 17 | :members: 18 | :member-order: bysource 19 | :show-inheritance: 20 | 21 | -------------------------------------------------------------------------------- /doc/source/drivers-autogen-only/weather_info.rst: -------------------------------------------------------------------------------- 1 | .. 2 | This file has been autogenerated 3 | 4 | If you wish to add more content e.g. usage examples please also move the file from the 5 | drivers-autogen-only folder to the drivers folder. 6 | 7 | .. _drivers-doc-weather_info: 8 | 9 | *********************** 10 | The weather_info module 11 | *********************** 12 | 13 | Autogenerated API documentation for weather_info 14 | ================================================ 15 | 16 | .. automodule:: PyExpLabSys.drivers.weather_info 17 | :members: 18 | :member-order: bysource 19 | :show-inheritance: 20 | 21 | -------------------------------------------------------------------------------- /doc/source/drivers-autogen-only/chemitec_s411.rst: -------------------------------------------------------------------------------- 1 | .. 2 | This file has been autogenerated 3 | 4 | If you wish to add more content e.g. usage examples please also move the file from the 5 | drivers-autogen-only folder to the drivers folder. 6 | 7 | .. _drivers-doc-chemitec_s411: 8 | 9 | ************************ 10 | The chemitec_s411 module 11 | ************************ 12 | 13 | Autogenerated API documentation for chemitec_s411 14 | ================================================= 15 | 16 | .. automodule:: PyExpLabSys.drivers.chemitec_s411 17 | :members: 18 | :member-order: bysource 19 | :show-inheritance: 20 | 21 | -------------------------------------------------------------------------------- /doc/source/drivers-autogen-only/keithley_2700.rst: -------------------------------------------------------------------------------- 1 | .. 2 | This file has been autogenerated 3 | 4 | If you wish to add more content e.g. usage examples please also move the file from the 5 | drivers-autogen-only folder to the drivers folder. 6 | 7 | .. _drivers-doc-keithley_2700: 8 | 9 | ************************ 10 | The keithley_2700 module 11 | ************************ 12 | 13 | Autogenerated API documentation for keithley_2700 14 | ================================================= 15 | 16 | .. automodule:: PyExpLabSys.drivers.keithley_2700 17 | :members: 18 | :member-order: bysource 19 | :show-inheritance: 20 | 21 | -------------------------------------------------------------------------------- /doc/source/drivers-autogen-only/specs_XRC1000.rst: -------------------------------------------------------------------------------- 1 | .. 2 | This file has been autogenerated 3 | 4 | If you wish to add more content e.g. usage examples please also move the file from the 5 | drivers-autogen-only folder to the drivers folder. 6 | 7 | .. _drivers-doc-specs_XRC1000: 8 | 9 | ************************ 10 | The specs_XRC1000 module 11 | ************************ 12 | 13 | Autogenerated API documentation for specs_XRC1000 14 | ================================================= 15 | 16 | .. automodule:: PyExpLabSys.drivers.specs_XRC1000 17 | :members: 18 | :member-order: bysource 19 | :show-inheritance: 20 | 21 | -------------------------------------------------------------------------------- /doc/source/drivers-autogen-only/teltonika_rut.rst: -------------------------------------------------------------------------------- 1 | .. 2 | This file has been autogenerated 3 | 4 | If you wish to add more content e.g. usage examples please also move the file from the 5 | drivers-autogen-only folder to the drivers folder. 6 | 7 | .. _drivers-doc-teltonika_rut: 8 | 9 | ************************ 10 | The teltonika_rut module 11 | ************************ 12 | 13 | Autogenerated API documentation for teltonika_rut 14 | ================================================= 15 | 16 | .. automodule:: PyExpLabSys.drivers.teltonika_rut 17 | :members: 18 | :member-order: bysource 19 | :show-inheritance: 20 | 21 | -------------------------------------------------------------------------------- /doc/source/file-parsers.rst: -------------------------------------------------------------------------------- 1 | 2 | .. _file-parsers: 3 | 4 | ************ 5 | File parsers 6 | ************ 7 | 8 | File parsers. 9 | 10 | .. contents:: Table of Contents 11 | :depth: 3 12 | 13 | XML based file formats 14 | ====================== 15 | 16 | 17 | Specs File Format 18 | ------------------ 19 | 20 | .. automodule:: PyExpLabSys.file_parsers.specs 21 | :members: 22 | :member-order: bysource 23 | :show-inheritance: 24 | 25 | Binary File Formats 26 | =================== 27 | 28 | .. automodule:: PyExpLabSys.file_parsers.chemstation 29 | :members: 30 | :member-order: bysource 31 | :show-inheritance: 32 | -------------------------------------------------------------------------------- /archive/rasppi75_pH_regulation/test_pump.py: -------------------------------------------------------------------------------- 1 | 2 | from __future__ import print_function 3 | 4 | import time 5 | from PyExpLabSys.drivers.wpi_al1000 import AL1000 6 | 7 | 8 | for baud in [19200]:#(300, 9600, 19200): 9 | print(baud) 10 | al1000 = AL1000( 11 | port="/dev/serial/by-id/usb-FTDI_USB-RS232_Cable_FTV9X9TM-if00-port0", 12 | baudrate=baud, 13 | ) 14 | print(al1000.set_vol(1)) 15 | print(al1000.set_rate(10)) 16 | print(al1000.start_program()) 17 | al1000.stop_program() 18 | #print(repr(al1000.get_firmware())) 19 | # while True: 20 | # print(al1000._send_command("VER")) 21 | 22 | -------------------------------------------------------------------------------- /doc/source/drivers-autogen-only/agilent_34410A.rst: -------------------------------------------------------------------------------- 1 | .. 2 | This file has been autogenerated 3 | 4 | If you wish to add more content e.g. usage examples please also move the file from the 5 | drivers-autogen-only folder to the drivers folder. 6 | 7 | .. _drivers-doc-agilent_34410A: 8 | 9 | ************************* 10 | The agilent_34410A module 11 | ************************* 12 | 13 | Autogenerated API documentation for agilent_34410A 14 | ================================================== 15 | 16 | .. automodule:: PyExpLabSys.drivers.agilent_34410A 17 | :members: 18 | :member-order: bysource 19 | :show-inheritance: 20 | 21 | -------------------------------------------------------------------------------- /doc/source/drivers-autogen-only/agilent_34972A.rst: -------------------------------------------------------------------------------- 1 | .. 2 | This file has been autogenerated 3 | 4 | If you wish to add more content e.g. usage examples please also move the file from the 5 | drivers-autogen-only folder to the drivers folder. 6 | 7 | .. _drivers-doc-agilent_34972A: 8 | 9 | ************************* 10 | The agilent_34972A module 11 | ************************* 12 | 13 | Autogenerated API documentation for agilent_34972A 14 | ================================================== 15 | 16 | .. automodule:: PyExpLabSys.drivers.agilent_34972A 17 | :members: 18 | :member-order: bysource 19 | :show-inheritance: 20 | 21 | -------------------------------------------------------------------------------- /doc/source/drivers-autogen-only/deltaco_TB_298.rst: -------------------------------------------------------------------------------- 1 | .. 2 | This file has been autogenerated 3 | 4 | If you wish to add more content e.g. usage examples please also move the file from the 5 | drivers-autogen-only folder to the drivers folder. 6 | 7 | .. _drivers-doc-deltaco_TB_298: 8 | 9 | ************************* 10 | The deltaco_TB_298 module 11 | ************************* 12 | 13 | Autogenerated API documentation for deltaco_TB_298 14 | ================================================== 15 | 16 | .. automodule:: PyExpLabSys.drivers.deltaco_TB_298 17 | :members: 18 | :member-order: bysource 19 | :show-inheritance: 20 | 21 | -------------------------------------------------------------------------------- /doc/source/drivers-autogen-only/honeywell_6000.rst: -------------------------------------------------------------------------------- 1 | .. 2 | This file has been autogenerated 3 | 4 | If you wish to add more content e.g. usage examples please also move the file from the 5 | drivers-autogen-only folder to the drivers folder. 6 | 7 | .. _drivers-doc-honeywell_6000: 8 | 9 | ************************* 10 | The honeywell_6000 module 11 | ************************* 12 | 13 | Autogenerated API documentation for honeywell_6000 14 | ================================================== 15 | 16 | .. automodule:: PyExpLabSys.drivers.honeywell_6000 17 | :members: 18 | :member-order: bysource 19 | :show-inheritance: 20 | 21 | -------------------------------------------------------------------------------- /doc/source/drivers-autogen-only/inficon_sqm160.rst: -------------------------------------------------------------------------------- 1 | .. 2 | This file has been autogenerated 3 | 4 | If you wish to add more content e.g. usage examples please also move the file from the 5 | drivers-autogen-only folder to the drivers folder. 6 | 7 | .. _drivers-doc-inficon_sqm160: 8 | 9 | ************************* 10 | The inficon_sqm160 module 11 | ************************* 12 | 13 | Autogenerated API documentation for inficon_sqm160 14 | ================================================== 15 | 16 | .. automodule:: PyExpLabSys.drivers.inficon_sqm160 17 | :members: 18 | :member-order: bysource 19 | :show-inheritance: 20 | 21 | -------------------------------------------------------------------------------- /doc/source/drivers-autogen-only/mks_925_pirani.rst: -------------------------------------------------------------------------------- 1 | .. 2 | This file has been autogenerated 3 | 4 | If you wish to add more content e.g. usage examples please also move the file from the 5 | drivers-autogen-only folder to the drivers folder. 6 | 7 | .. _drivers-doc-mks_925_pirani: 8 | 9 | ************************* 10 | The mks_925_pirani module 11 | ************************* 12 | 13 | Autogenerated API documentation for mks_925_pirani 14 | ================================================== 15 | 16 | .. automodule:: PyExpLabSys.drivers.mks_925_pirani 17 | :members: 18 | :member-order: bysource 19 | :show-inheritance: 20 | 21 | -------------------------------------------------------------------------------- /doc/source/drivers-autogen-only/vaisala_dmt143.rst: -------------------------------------------------------------------------------- 1 | .. 2 | This file has been autogenerated 3 | 4 | If you wish to add more content e.g. usage examples please also move the file from the 5 | drivers-autogen-only folder to the drivers folder. 6 | 7 | .. _drivers-doc-vaisala_dmt143: 8 | 9 | ************************* 10 | The vaisala_dmt143 module 11 | ************************* 12 | 13 | Autogenerated API documentation for vaisala_dmt143 14 | ================================================== 15 | 16 | .. automodule:: PyExpLabSys.drivers.vaisala_dmt143 17 | :members: 18 | :member-order: bysource 19 | :show-inheritance: 20 | 21 | -------------------------------------------------------------------------------- /doc/source/drivers-autogen-only/pfeiffer_qmg420.rst: -------------------------------------------------------------------------------- 1 | .. 2 | This file has been autogenerated 3 | 4 | If you wish to add more content e.g. usage examples please also move the file from the 5 | drivers-autogen-only folder to the drivers folder. 6 | 7 | .. _drivers-doc-pfeiffer_qmg420: 8 | 9 | ************************** 10 | The pfeiffer_qmg420 module 11 | ************************** 12 | 13 | Autogenerated API documentation for pfeiffer_qmg420 14 | =================================================== 15 | 16 | .. automodule:: PyExpLabSys.drivers.pfeiffer_qmg420 17 | :members: 18 | :member-order: bysource 19 | :show-inheritance: 20 | 21 | -------------------------------------------------------------------------------- /doc/source/drivers-autogen-only/pfeiffer_qmg422.rst: -------------------------------------------------------------------------------- 1 | .. 2 | This file has been autogenerated 3 | 4 | If you wish to add more content e.g. usage examples please also move the file from the 5 | drivers-autogen-only folder to the drivers folder. 6 | 7 | .. _drivers-doc-pfeiffer_qmg422: 8 | 9 | ************************** 10 | The pfeiffer_qmg422 module 11 | ************************** 12 | 13 | Autogenerated API documentation for pfeiffer_qmg422 14 | =================================================== 15 | 16 | .. automodule:: PyExpLabSys.drivers.pfeiffer_qmg422 17 | :members: 18 | :member-order: bysource 19 | :show-inheritance: 20 | 21 | -------------------------------------------------------------------------------- /doc/source/drivers-autogen-only/sensirion_sps30.rst: -------------------------------------------------------------------------------- 1 | .. 2 | This file has been autogenerated 3 | 4 | If you wish to add more content e.g. usage examples please also move the file from the 5 | drivers-autogen-only folder to the drivers folder. 6 | 7 | .. _drivers-doc-sensirion_sps30: 8 | 9 | ************************** 10 | The sensirion_sps30 module 11 | ************************** 12 | 13 | Autogenerated API documentation for sensirion_sps30 14 | =================================================== 15 | 16 | .. automodule:: PyExpLabSys.drivers.sensirion_sps30 17 | :members: 18 | :member-order: bysource 19 | :show-inheritance: 20 | 21 | -------------------------------------------------------------------------------- /doc/source/drivers-autogen-only/polyscience_4100.rst: -------------------------------------------------------------------------------- 1 | .. 2 | This file has been autogenerated 3 | 4 | If you wish to add more content e.g. usage examples please also move the file from the 5 | drivers-autogen-only folder to the drivers folder. 6 | 7 | .. _drivers-doc-polyscience_4100: 8 | 9 | *************************** 10 | The polyscience_4100 module 11 | *************************** 12 | 13 | Autogenerated API documentation for polyscience_4100 14 | ==================================================== 15 | 16 | .. automodule:: PyExpLabSys.drivers.polyscience_4100 17 | :members: 18 | :member-order: bysource 19 | :show-inheritance: 20 | 21 | -------------------------------------------------------------------------------- /doc/source/drivers-autogen-only/brooks_s_protocol.rst: -------------------------------------------------------------------------------- 1 | .. 2 | This file has been autogenerated 3 | 4 | If you wish to add more content e.g. usage examples please also move the file from the 5 | drivers-autogen-only folder to the drivers folder. 6 | 7 | .. _drivers-doc-brooks_s_protocol: 8 | 9 | **************************** 10 | The brooks_s_protocol module 11 | **************************** 12 | 13 | Autogenerated API documentation for brooks_s_protocol 14 | ===================================================== 15 | 16 | .. automodule:: PyExpLabSys.drivers.brooks_s_protocol 17 | :members: 18 | :member-order: bysource 19 | :show-inheritance: 20 | 21 | -------------------------------------------------------------------------------- /doc/source/drivers-autogen-only/rosemount_nga2000.rst: -------------------------------------------------------------------------------- 1 | .. 2 | This file has been autogenerated 3 | 4 | If you wish to add more content e.g. usage examples please also move the file from the 5 | drivers-autogen-only folder to the drivers folder. 6 | 7 | .. _drivers-doc-rosemount_nga2000: 8 | 9 | **************************** 10 | The rosemount_nga2000 module 11 | **************************** 12 | 13 | Autogenerated API documentation for rosemount_nga2000 14 | ===================================================== 15 | 16 | .. automodule:: PyExpLabSys.drivers.rosemount_nga2000 17 | :members: 18 | :member-order: bysource 19 | :show-inheritance: 20 | 21 | -------------------------------------------------------------------------------- /doc/source/drivers-autogen-only/vivo_technologies.rst: -------------------------------------------------------------------------------- 1 | .. 2 | This file has been autogenerated 3 | 4 | If you wish to add more content e.g. usage examples please also move the file from the 5 | drivers-autogen-only folder to the drivers folder. 6 | 7 | .. _drivers-doc-vivo_technologies: 8 | 9 | **************************** 10 | The vivo_technologies module 11 | **************************** 12 | 13 | Autogenerated API documentation for vivo_technologies 14 | ===================================================== 15 | 16 | .. automodule:: PyExpLabSys.drivers.vivo_technologies 17 | :members: 18 | :member-order: bysource 19 | :show-inheritance: 20 | 21 | -------------------------------------------------------------------------------- /doc/source/drivers-autogen-only/seeed_studio_relay.rst: -------------------------------------------------------------------------------- 1 | .. 2 | This file has been autogenerated 3 | 4 | If you wish to add more content e.g. usage examples please also move the file from the 5 | drivers-autogen-only folder to the drivers folder. 6 | 7 | .. _drivers-doc-seeed_studio_relay: 8 | 9 | ***************************** 10 | The seeed_studio_relay module 11 | ***************************** 12 | 13 | Autogenerated API documentation for seeed_studio_relay 14 | ====================================================== 15 | 16 | .. automodule:: PyExpLabSys.drivers.seeed_studio_relay 17 | :members: 18 | :member-order: bysource 19 | :show-inheritance: 20 | 21 | -------------------------------------------------------------------------------- /archive/rasppi75_pH_regulation/omega_test.py: -------------------------------------------------------------------------------- 1 | 2 | #from omegabus import OmegaBus 3 | #obus = OmegaBus("/dev/serial/by-id/usb-FTDI_USB-RS232_Cable_FTWZCGSW-if00-port0") 4 | #value = obus.read_value(1) 5 | #print(type(value), value) 6 | 7 | from PyExpLabSys.drivers.omegabus import OmegaBus 8 | obus = OmegaBus("/dev/serial/by-id/usb-FTDI_USB-RS232_Cable_FTWZCGSW-if00-port0", baud=9600) 9 | value = obus.read_value(1) 10 | 11 | def current_to_ph(value): 12 | """Convert current in milliamps between 4 and 20 to Ph between 0 and 14""" 13 | slope = 14/16 14 | ph = (value - 4) * slope 15 | return ph 16 | 17 | value = current_to_ph(value) 18 | print(type(value), value) 19 | -------------------------------------------------------------------------------- /doc/source/drivers-autogen-only/freescale_mma7660fc.rst: -------------------------------------------------------------------------------- 1 | .. 2 | This file has been autogenerated 3 | 4 | If you wish to add more content e.g. usage examples please also move the file from the 5 | drivers-autogen-only folder to the drivers folder. 6 | 7 | .. _drivers-doc-freescale_mma7660fc: 8 | 9 | ****************************** 10 | The freescale_mma7660fc module 11 | ****************************** 12 | 13 | Autogenerated API documentation for freescale_mma7660fc 14 | ======================================================= 15 | 16 | .. automodule:: PyExpLabSys.drivers.freescale_mma7660fc 17 | :members: 18 | :member-order: bysource 19 | :show-inheritance: 20 | 21 | -------------------------------------------------------------------------------- /doc/source/drivers-autogen-only/kjlc_pressure_gauge.rst: -------------------------------------------------------------------------------- 1 | .. 2 | This file has been autogenerated 3 | 4 | If you wish to add more content e.g. usage examples please also move the file from the 5 | drivers-autogen-only folder to the drivers folder. 6 | 7 | .. _drivers-doc-kjlc_pressure_gauge: 8 | 9 | ****************************** 10 | The kjlc_pressure_gauge module 11 | ****************************** 12 | 13 | Autogenerated API documentation for kjlc_pressure_gauge 14 | ======================================================= 15 | 16 | .. automodule:: PyExpLabSys.drivers.kjlc_pressure_gauge 17 | :members: 18 | :member-order: bysource 19 | :show-inheritance: 20 | 21 | -------------------------------------------------------------------------------- /doc/source/drivers-autogen-only/pfeiffer_turbo_pump.rst: -------------------------------------------------------------------------------- 1 | .. 2 | This file has been autogenerated 3 | 4 | If you wish to add more content e.g. usage examples please also move the file from the 5 | drivers-autogen-only folder to the drivers folder. 6 | 7 | .. _drivers-doc-pfeiffer_turbo_pump: 8 | 9 | ****************************** 10 | The pfeiffer_turbo_pump module 11 | ****************************** 12 | 13 | Autogenerated API documentation for pfeiffer_turbo_pump 14 | ======================================================= 15 | 16 | .. automodule:: PyExpLabSys.drivers.pfeiffer_turbo_pump 17 | :members: 18 | :member-order: bysource 19 | :show-inheritance: 20 | 21 | -------------------------------------------------------------------------------- /doc/source/drivers-autogen-only/sparkfun_quad_relay.rst: -------------------------------------------------------------------------------- 1 | .. 2 | This file has been autogenerated 3 | 4 | If you wish to add more content e.g. usage examples please also move the file from the 5 | drivers-autogen-only folder to the drivers folder. 6 | 7 | .. _drivers-doc-sparkfun_quad_relay: 8 | 9 | ****************************** 10 | The sparkfun_quad_relay module 11 | ****************************** 12 | 13 | Autogenerated API documentation for sparkfun_quad_relay 14 | ======================================================= 15 | 16 | .. automodule:: PyExpLabSys.drivers.sparkfun_quad_relay 17 | :members: 18 | :member-order: bysource 19 | :show-inheritance: 20 | 21 | -------------------------------------------------------------------------------- /doc/source/drivers-autogen-only/tdk_lambda_z_series.rst: -------------------------------------------------------------------------------- 1 | .. 2 | This file has been autogenerated 3 | 4 | If you wish to add more content e.g. usage examples please also move the file from the 5 | drivers-autogen-only folder to the drivers folder. 6 | 7 | .. _drivers-doc-tdk_lambda_z_series: 8 | 9 | ****************************** 10 | The tdk_lambda_z_series module 11 | ****************************** 12 | 13 | Autogenerated API documentation for tdk_lambda_z_series 14 | ======================================================= 15 | 16 | .. automodule:: PyExpLabSys.drivers.tdk_lambda_z_series 17 | :members: 18 | :member-order: bysource 19 | :show-inheritance: 20 | 21 | -------------------------------------------------------------------------------- /doc/source/drivers-autogen-only/xp_power_hpa_series.rst: -------------------------------------------------------------------------------- 1 | .. 2 | This file has been autogenerated 3 | 4 | If you wish to add more content e.g. usage examples please also move the file from the 5 | drivers-autogen-only folder to the drivers folder. 6 | 7 | .. _drivers-doc-xp_power_hpa_series: 8 | 9 | ****************************** 10 | The xp_power_hpa_series module 11 | ****************************** 12 | 13 | Autogenerated API documentation for xp_power_hpa_series 14 | ======================================================= 15 | 16 | .. automodule:: PyExpLabSys.drivers.xp_power_hpa_series 17 | :members: 18 | :member-order: bysource 19 | :show-inheritance: 20 | 21 | -------------------------------------------------------------------------------- /doc/source/drivers-autogen-only/analogdevices_ad5667.rst: -------------------------------------------------------------------------------- 1 | .. 2 | This file has been autogenerated 3 | 4 | If you wish to add more content e.g. usage examples please also move the file from the 5 | drivers-autogen-only folder to the drivers folder. 6 | 7 | .. _drivers-doc-analogdevices_ad5667: 8 | 9 | ******************************* 10 | The analogdevices_ad5667 module 11 | ******************************* 12 | 13 | Autogenerated API documentation for analogdevices_ad5667 14 | ======================================================== 15 | 16 | .. automodule:: PyExpLabSys.drivers.analogdevices_ad5667 17 | :members: 18 | :member-order: bysource 19 | :show-inheritance: 20 | 21 | -------------------------------------------------------------------------------- /doc/source/drivers-autogen-only/intellemetrics_il800.rst: -------------------------------------------------------------------------------- 1 | .. 2 | This file has been autogenerated 3 | 4 | If you wish to add more content e.g. usage examples please also move the file from the 5 | drivers-autogen-only folder to the drivers folder. 6 | 7 | .. _drivers-doc-intellemetrics_il800: 8 | 9 | ******************************* 10 | The intellemetrics_il800 module 11 | ******************************* 12 | 13 | Autogenerated API documentation for intellemetrics_il800 14 | ======================================================== 15 | 16 | .. automodule:: PyExpLabSys.drivers.intellemetrics_il800 17 | :members: 18 | :member-order: bysource 19 | :show-inheritance: 20 | 21 | -------------------------------------------------------------------------------- /doc/source/drivers-autogen-only/ocs_3l_oxygen_sensor.rst: -------------------------------------------------------------------------------- 1 | .. 2 | This file has been autogenerated 3 | 4 | If you wish to add more content e.g. usage examples please also move the file from the 5 | drivers-autogen-only folder to the drivers folder. 6 | 7 | .. _drivers-doc-ocs_3l_oxygen_sensor: 8 | 9 | ******************************* 10 | The ocs_3l_oxygen_sensor module 11 | ******************************* 12 | 13 | Autogenerated API documentation for ocs_3l_oxygen_sensor 14 | ======================================================== 15 | 16 | .. automodule:: PyExpLabSys.drivers.ocs_3l_oxygen_sensor 17 | :members: 18 | :member-order: bysource 19 | :show-inheritance: 20 | 21 | -------------------------------------------------------------------------------- /doc/source/drivers-autogen-only/powerwalker_ethernet.rst: -------------------------------------------------------------------------------- 1 | .. 2 | This file has been autogenerated 3 | 4 | If you wish to add more content e.g. usage examples please also move the file from the 5 | drivers-autogen-only folder to the drivers folder. 6 | 7 | .. _drivers-doc-powerwalker_ethernet: 8 | 9 | ******************************* 10 | The powerwalker_ethernet module 11 | ******************************* 12 | 13 | Autogenerated API documentation for powerwalker_ethernet 14 | ======================================================== 15 | 16 | .. automodule:: PyExpLabSys.drivers.powerwalker_ethernet 17 | :members: 18 | :member-order: bysource 19 | :show-inheritance: 20 | 21 | -------------------------------------------------------------------------------- /doc/source/drivers-autogen-only/xp_power_1500_series.rst: -------------------------------------------------------------------------------- 1 | .. 2 | This file has been autogenerated 3 | 4 | If you wish to add more content e.g. usage examples please also move the file from the 5 | drivers-autogen-only folder to the drivers folder. 6 | 7 | .. _drivers-doc-xp_power_1500_series: 8 | 9 | ******************************* 10 | The xp_power_1500_series module 11 | ******************************* 12 | 13 | Autogenerated API documentation for xp_power_1500_series 14 | ======================================================== 15 | 16 | .. automodule:: PyExpLabSys.drivers.xp_power_1500_series 17 | :members: 18 | :member-order: bysource 19 | :show-inheritance: 20 | 21 | -------------------------------------------------------------------------------- /PyExpLabSys/__init__.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | """The PyExpLabSys package contains drivers for various experimental 4 | equipment and data parsers for various softwares file types, both 5 | particularly pertaining to surface science.""" 6 | 7 | __author__ = 'CINF ' 8 | __email__ = 'knielsen@fysik.dtu.dk' 9 | __version__ = '0.1.dev0' 10 | __website__ = 'https://github.com/CINF/PyExpLabSys' 11 | __license__ = 'GNU GPL3' 12 | __description__ = 'The PyExpLabSys package contains drivers for various experimental equipment and data parsers for various softwares file types, both particularly pertaining to surface science.' 13 | __uri__ = 'https://github.com/CINF/PyExpLabSys' 14 | -------------------------------------------------------------------------------- /doc/source/drivers-autogen-only/microchip_tech_mcp3428.rst: -------------------------------------------------------------------------------- 1 | .. 2 | This file has been autogenerated 3 | 4 | If you wish to add more content e.g. usage examples please also move the file from the 5 | drivers-autogen-only folder to the drivers folder. 6 | 7 | .. _drivers-doc-microchip_tech_mcp3428: 8 | 9 | ********************************* 10 | The microchip_tech_mcp3428 module 11 | ********************************* 12 | 13 | Autogenerated API documentation for microchip_tech_mcp3428 14 | ========================================================== 15 | 16 | .. automodule:: PyExpLabSys.drivers.microchip_tech_mcp3428 17 | :members: 18 | :member-order: bysource 19 | :show-inheritance: 20 | 21 | -------------------------------------------------------------------------------- /doc/source/drivers-autogen-only/microchip_tech_mcp9808.rst: -------------------------------------------------------------------------------- 1 | .. 2 | This file has been autogenerated 3 | 4 | If you wish to add more content e.g. usage examples please also move the file from the 5 | drivers-autogen-only folder to the drivers folder. 6 | 7 | .. _drivers-doc-microchip_tech_mcp9808: 8 | 9 | ********************************* 10 | The microchip_tech_mcp9808 module 11 | ********************************* 12 | 13 | Autogenerated API documentation for microchip_tech_mcp9808 14 | ========================================================== 15 | 16 | .. automodule:: PyExpLabSys.drivers.microchip_tech_mcp9808 17 | :members: 18 | :member-order: bysource 19 | :show-inheritance: 20 | 21 | -------------------------------------------------------------------------------- /doc/source/drivers.rst: -------------------------------------------------------------------------------- 1 | 2 | .. _drivers: 3 | 4 | **************** 5 | Hardware Drivers 6 | **************** 7 | 8 | This section documents the hardware drivers developed at CINF. Most of 9 | the drivers are for equipment to surface science such as mass 10 | spectrometers and pressure gauges, but there are also some drivers for 11 | more general equipment like temperature read out units. 12 | 13 | .. The drivers components subpage has its own table of contents for everything 14 | .. that is below this level, which is contained in the files below. 15 | .. toctree:: 16 | :maxdepth: 4 17 | :glob: 18 | 19 | drivers/* 20 | 21 | 22 | 23 | .. drivers_pfeiffer 24 | .. drivers_four_d_systems 25 | .. drivers_bio_logic 26 | -------------------------------------------------------------------------------- /doc/source/drivers-autogen-only/stmicroelectronics_ais328dq.rst: -------------------------------------------------------------------------------- 1 | .. 2 | This file has been autogenerated 3 | 4 | If you wish to add more content e.g. usage examples please also move the file from the 5 | drivers-autogen-only folder to the drivers folder. 6 | 7 | .. _drivers-doc-stmicroelectronics_ais328dq: 8 | 9 | ************************************** 10 | The stmicroelectronics_ais328dq module 11 | ************************************** 12 | 13 | Autogenerated API documentation for stmicroelectronics_ais328dq 14 | =============================================================== 15 | 16 | .. automodule:: PyExpLabSys.drivers.stmicroelectronics_ais328dq 17 | :members: 18 | :member-order: bysource 19 | :show-inheritance: 20 | 21 | -------------------------------------------------------------------------------- /doc/source/drivers-autogen-only/stmicroelectronics_l3g4200d.rst: -------------------------------------------------------------------------------- 1 | .. 2 | This file has been autogenerated 3 | 4 | If you wish to add more content e.g. usage examples please also move the file from the 5 | drivers-autogen-only folder to the drivers folder. 6 | 7 | .. _drivers-doc-stmicroelectronics_l3g4200d: 8 | 9 | ************************************** 10 | The stmicroelectronics_l3g4200d module 11 | ************************************** 12 | 13 | Autogenerated API documentation for stmicroelectronics_l3g4200d 14 | =============================================================== 15 | 16 | .. automodule:: PyExpLabSys.drivers.stmicroelectronics_l3g4200d 17 | :members: 18 | :member-order: bysource 19 | :show-inheritance: 20 | 21 | -------------------------------------------------------------------------------- /PyExpLabSys/apps/bakeoutweb/runbakeoutweb.bash: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | 4 | 5 | helptext="\nRun the bakeout web application 6 | 7 | Usage: 8 | runbakeoutweb.bash machine [debug] 9 | " 10 | 11 | 12 | function help(){ 13 | echo -e "$helptext" 14 | } 15 | 16 | 17 | # Check that there are 1 or 2 arguments 18 | if [ $# -lt 1 ] || [ $# -gt 2 ];then 19 | help 20 | exit 1 21 | fi 22 | 23 | cd "$(dirname "$0")" 24 | 25 | export FLASK_APP=bakeoutweb.py 26 | export MACHINE=$1 27 | 28 | # Check whether debug mode is requested 29 | if [ $# -eq 2 ] && [ $2 == "debug" ];then 30 | echo "Running in debug mode" 31 | export FLASK_DEBUG=1 32 | python3 -m flask run --host=0.0.0.0 33 | else 34 | python3 -m flask run --host=0.0.0.0 35 | fi 36 | -------------------------------------------------------------------------------- /archive/canon_eos.py: -------------------------------------------------------------------------------- 1 | import subprocess 2 | import time 3 | 4 | while True: 5 | print 'Starting' 6 | retur = subprocess.check_output(['gphoto2', '--set-config', '/main/imgsettings/iso=2']) #ISO: 7 | print 'Iso chosen' 8 | retur = subprocess.check_output(['gphoto2', '--set-config', '/main/capturesettings/shutterspeed=10']) #Shutterspeed: 1/? 9 | print 'Shutterspeed chosen' 10 | retur = subprocess.check_output(['gphoto2', '--set-config', '/main/capturesettings/aperture=14']) #Aperture: ? 11 | print 'Aperture chosen' 12 | retur = subprocess.check_output(['gphoto2', '--capture-image-and-download']) 13 | print 'Image aquired' 14 | retur = subprocess.check_output(['mv', 'capt0000.jpg', '/usr/share/mini-httpd/html/']) 15 | print 'Finished' 16 | time.sleep(600) 17 | -------------------------------------------------------------------------------- /doc/source/common.rst: -------------------------------------------------------------------------------- 1 | ************************** 2 | Common Software Components 3 | ************************** 4 | 5 | This section documents the common software components at CINF. These 6 | are general purpose modules and classes that does not fit into the any 7 | of the other categories like ``drivers`` and ``parsers``. 8 | 9 | .. The common components subpage has its own table of contents for everything 10 | .. that is below this level, which is contained in the files below. 11 | .. toctree:: 12 | :maxdepth: 4 13 | 14 | common/database_saver.rst 15 | common/continuous_logger.rst 16 | common/plotters.rst 17 | common/sockets.rst 18 | common/socket_clients.rst 19 | common/utilities.rst 20 | common/text_plot.rst 21 | combos.rst 22 | settings.rst 23 | 24 | 25 | -------------------------------------------------------------------------------- /doc/source/drivers_autogen_only.rst: -------------------------------------------------------------------------------- 1 | 2 | .. _drivers_autogen_only: 3 | 4 | **************************************** 5 | Hardware Drivers Autogenerated Docs Only 6 | **************************************** 7 | 8 | This section documents the hardware drivers developed at CINF. Most of 9 | the drivers are for equipment to surface science such as mass 10 | spectrometers and pressure gauges, but there are also some drivers for 11 | more general equipment like temperature read out units. 12 | 13 | **The drivers in this section only has autogenerated API documentation.** 14 | 15 | .. The drivers components subpage has its own table of contents for everything 16 | .. that is below this level, which is contained in the files below. 17 | .. toctree:: 18 | :maxdepth: 4 19 | :glob: 20 | 21 | drivers-autogen-only/* 22 | -------------------------------------------------------------------------------- /archive/cinfkiosk/double_axis.py: -------------------------------------------------------------------------------- 1 | import sys 2 | 3 | import numpy as np 4 | from pyqtgraph import PlotWidget, AxisItem 5 | from PyQt4 import QtGui, QtCore 6 | 7 | 8 | class TimeAxisItem(AxisItem): 9 | """Only included to show that the point is to subclass""" 10 | 11 | 12 | class Example(QtGui.QWidget): 13 | def __init__(self): 14 | super(Example, self).__init__() 15 | self.setGeometry(300, 300, 400, 400) 16 | self.plot = PlotWidget(self, axisItems={'bottom': TimeAxisItem(orientation='bottom')}) 17 | self.plot.resize(300, 300) 18 | self.curve = self.plot.plot(np.linspace(0, 10, 100), np.random.random(100)) 19 | self.show() 20 | 21 | 22 | if __name__ == '__main__': 23 | app = QtGui.QApplication(sys.argv) 24 | ex = Example() 25 | sys.exit(app.exec_()) 26 | -------------------------------------------------------------------------------- /.readthedocs.yaml: -------------------------------------------------------------------------------- 1 | # .readthedocs.yaml 2 | # Read the Docs configuration file 3 | # See https://docs.readthedocs.io/en/stable/config-file/v2.html for details 4 | 5 | # Required 6 | version: 2 7 | 8 | # Set the version of Python and other tools you might need 9 | build: 10 | os: ubuntu-20.04 11 | tools: 12 | python: "3.9" 13 | # You can also specify other tool versions: 14 | # nodejs: "16" 15 | # rust: "1.55" 16 | # golang: "1.17" 17 | 18 | # Build documentation in the docs/ directory with Sphinx 19 | sphinx: 20 | configuration: doc/source/conf.py 21 | 22 | # If using Sphinx, optionally build your docs in additional formats such as PDF 23 | # formats: 24 | # - pdf 25 | 26 | # Optionally declare the Python requirements required to build your docs 27 | python: 28 | install: 29 | - requirements: requirements-doc.txt 30 | -------------------------------------------------------------------------------- /bootstrap/linux_basic_config.bash: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | 4 | # This script sets up locale and keyboard 5 | 6 | # Setup keyboard 7 | # 8 | # This changes the line that starts with XKBLAYOUT in 9 | # /etc/default/keyboard to: XKBLAYOUT="dk" 10 | echo "Making changes in /etc/default/keyboard" 11 | echo "Current keyboard layout line:" `grep XKBLAYOUT /etc/default/keyboard` 12 | sudo sed -i -e 's/XKBLAYOUT.*/XKBLAYOUT="dk"/g' /etc/default/keyboard 13 | echo "Keyboard line after change:" `grep XKBLAYOUT /etc/default/keyboard` 14 | 15 | # Change time zone 16 | echo 17 | echo "Making changes in /etc/timezone" 18 | echo "Current time zone setting:" `cat /etc/timezone` 19 | sudo sudo sed -i -e 's/.*/Europe\/Copenhagen/g' /etc/timezone 20 | echo "Time zone after change:" `cat /etc/timezone` 21 | 22 | # Reboot 23 | read -p "Press [Enter] to reboot..." 24 | sudo reboot 25 | -------------------------------------------------------------------------------- /.vim/syntax/channel.vim: -------------------------------------------------------------------------------- 1 | " Vim syntax file 2 | " Language: homemade colourscheme for channel_list used in mass_spec programs at surfcat 3 | " Maintainer: Alexander Krabbe 4 | " Latest revised 19I06 5 | 6 | if exists("b:current_syntax") 7 | finish 8 | endif 9 | 10 | " Keywords 11 | syn keyword celBlockCmd port amp_range mass speed masslabel repeat_interval label host command measurement_type 12 | 13 | syn keyword TitelBlock autorange comment ms_channel meta_channel 14 | 15 | " syn keyword outcomment # 16 | 17 | syn keyword celTodo contained TODO FIXME XXX NOTE 18 | 19 | " Matches 20 | 21 | syn match celComment "^#.*$" contains=celTodo 22 | 23 | " Regions 24 | 25 | let b:current_syntax = "channel" 26 | hi def link celBlockCmd Constant 27 | hi def link TitelBlock Statement 28 | " Statement 29 | hi def link celComment Comment 30 | " hi def link outcomment Constant 31 | 32 | -------------------------------------------------------------------------------- /tests/functional_test/fileparsers/test_chemstation/sequence_metadata.json: -------------------------------------------------------------------------------- 1 | [ 2 | { 3 | "sequence_start_timestruct_CONVERT": [ 4 | 2015, 5 | 1, 6 | 13, 7 | 11, 8 | 16, 9 | 49, 10 | 1, 11 | 13, 12 | -1 13 | ], 14 | "sequence_start": "13-Jan-15, 11:16:49", 15 | "acq_method": "Sine14.M", 16 | "sample_name": "NI cat" 17 | }, 18 | { 19 | "sequence_start_timestruct_CONVERT": [ 20 | 2016, 21 | 10, 22 | 6, 23 | 10, 24 | 47, 25 | 26, 26 | 3, 27 | 280, 28 | -1 29 | ], 30 | "sequence_start": "06-Oct-16, 10:47:26", 31 | "acq_method": "IREK_MEOH_2.M", 32 | "sample_name": "PtMgAl2O4" 33 | } 34 | ] -------------------------------------------------------------------------------- /PyExpLabSys/drivers/sparkfun_quad_relay.py: -------------------------------------------------------------------------------- 1 | import time 2 | import smbus 3 | 4 | 5 | class SparkFunQuadRelay: 6 | """Driver for the QWIIC SparkFun Quad Relay """ 7 | 8 | def __init__(self, address=0x6D): 9 | # Get I2C bus 10 | self.bus = smbus.SMBus(1) 11 | self.device_address = address 12 | 13 | def set_relay(self, relay_index, wanted_state): 14 | assert relay_index in range(1, 5) 15 | 16 | current_state = self.relay_status(relay_index) 17 | 18 | if not current_state == wanted_state: 19 | self.bus.write_byte(self.device_address, relay_index) 20 | return True 21 | 22 | def relay_status(self, relay_index): 23 | reply = self.bus.read_byte_data(self.device_address, 4 + relay_index) 24 | return reply > 0 25 | 26 | 27 | if __name__ == '__main__': 28 | relay = SparkFunQuadRelay() 29 | 30 | relay.set_relay(4, False) 31 | time.sleep(1.0) 32 | print(relay.relay_status(4)) 33 | -------------------------------------------------------------------------------- /PyExpLabSys/file_parsers/omicron.py: -------------------------------------------------------------------------------- 1 | #!/bin/env python3 2 | 3 | """File parser for the Omicron "Flattener" format""" 4 | 5 | import logging 6 | 7 | _LOG = logging.getLogger('omicron') 8 | _LOG.addHandler(logging.NullHandler()) 9 | 10 | 11 | class Flattener(object): 12 | """Class that represents a file in the Flattener format""" 13 | 14 | def __init__(self, filepath): 15 | """Initialize the Flatterner file 16 | 17 | Args: 18 | filepath (unicode): The path of the file to be parsed 19 | """ 20 | self._file = open(filepath, 'rb') 21 | _LOG.info('Parse flattener file: %s', filepath) 22 | 23 | 24 | def parse_test(): 25 | """Test parsing different files""" 26 | logging.basicConfig(level=logging.DEBUG) 27 | Flattener( 28 | '/home/cinf/PyExpLabSys/tests/testdata/omicron_flattener/' 29 | 'default_2016May11-091439_ESpHybrid_NanoSAM-ESpHybrid_NanoSAM_XPS' 30 | '--1_1.Detector.7_flat' 31 | ) 32 | 33 | 34 | if __name__ == "__main__": 35 | parse_test() 36 | -------------------------------------------------------------------------------- /tests/functional_test/fileparsers/test_chemstation/chemstation_data.json: -------------------------------------------------------------------------------- 1 | { 2 | "TCD3 C, Aux Signal - H2 (5.73999977112)": [ 3 | [ 4 | 0.0, 5 | 1809.60595703125 6 | ] 7 | ], 8 | "FID2 B, Back Signal - CO2 (12.071)": [ 9 | [ 10 | 0.0, 11 | 0.0 12 | ] 13 | ], 14 | "FID2 B, Back Signal - ?": [ 15 | [ 16 | 0.0, 17 | 816.847351074219 18 | ] 19 | ], 20 | "TCD3 C, Aux Signal - Ar (8.95544719696)": [ 21 | [ 22 | 0.0, 23 | 7526.13818359375 24 | ] 25 | ], 26 | "FID2 B, Back Signal - CO (9.421)": [ 27 | [ 28 | 0.0, 29 | 0.0 30 | ] 31 | ], 32 | "FID1 A, Front Signal - CH4 (2.62889790535)": [ 33 | [ 34 | 0.0, 35 | 0.0 36 | ] 37 | ], 38 | "FID2 B, Back Signal - CH4 (10.8715314865)": [ 39 | [ 40 | 0.0, 41 | 0.0 42 | ] 43 | ] 44 | } -------------------------------------------------------------------------------- /PyExpLabSys/common/massspec/qt.py: -------------------------------------------------------------------------------- 1 | """ Module that contains QT widgets for mass spectrometer channels and channel 2 | lists 3 | """ 4 | 5 | from PyQt4 import QtGui, QtCore 6 | from channel import Channel 7 | 8 | 9 | class QtMSChannel(object): 10 | """Mass spectrometer channel including separate widgets to change the 11 | values. These widgets are meant to be included separately in a grid. 12 | 13 | The widget defined are: 14 | active: A checkbox 15 | mass: A (??? float input) 16 | time: A (??? float input) 17 | delay: 18 | label: 19 | color: A colored button that activates a color selection dialog 20 | auto_label: 21 | """ 22 | 23 | def __init__(self, parent, channel): 24 | """ Initialize the QtMSChannel """ 25 | # Instantiate ??? 26 | self._channel = channel 27 | # Initialize widgets 28 | self._gui = {'active': QtGui.QCheckBox('Active', parent)} 29 | 30 | def gui(self, name): 31 | """ Return the GUI component with the given name """ 32 | return self._gui[name] 33 | -------------------------------------------------------------------------------- /archive/nh3_setup/rasppi09/socket_server.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import SocketServer 3 | #sys.path.append('../') 4 | 5 | #This specific raspberry pi handles temperature control 6 | class MyUDPHandler(SocketServer.BaseRequestHandler): 7 | 8 | def handle(self): 9 | global ion_gauge_pressure 10 | 11 | recieved_data = self.request[0].strip() 12 | data = "test" 13 | socket = self.request[1] 14 | 15 | if recieved_data[0:12] == "set_iongauge": 16 | val = float(recieved_data[12:].strip()) 17 | ion_gauge_pressure = val 18 | print val 19 | data = "ok" 20 | 21 | if recieved_data[0:13] == "read_iongauge": 22 | print ion_gauge_pressure 23 | data = str(ion_gauge_pressure) 24 | 25 | socket.sendto(data, self.client_address) 26 | 27 | if __name__ == "__main__": 28 | HOST, PORT = "130.225.87.218", 9999 #rasppi09 29 | 30 | ion_gauge_pressure = -1 31 | 32 | server = SocketServer.UDPServer((HOST, PORT), MyUDPHandler) 33 | server.serve_forever() 34 | -------------------------------------------------------------------------------- /bootstrap/.emacs: -------------------------------------------------------------------------------- 1 | ;; .emacs 2 | 3 | (add-to-list 'load-path "~/.emacs.d/lisp/") 4 | 5 | (require 'flymake) 6 | 7 | (when (load "flymake" t) 8 | (defun flymake-pyflakes-init () 9 | (let* ((temp-file (flymake-init-create-temp-buffer-copy 10 | 'flymake-create-temp-inplace)) 11 | (local-file (file-relative-name 12 | temp-file 13 | (file-name-directory buffer-file-name)))) 14 | (list "pycheckers" (list local-file)))) 15 | (add-to-list 'flymake-allowed-file-name-masks 16 | '("\\.py\\'" flymake-pyflakes-init))) 17 | 18 | (require 'flymake-cursor) 19 | 20 | ;;(add-hook 'python-mode-hook 'flymake-mode) 21 | (global-set-key (kbd "") 'flymake-start-syntax-check) 22 | (global-set-key (kbd "") 'flymake-display-err-menu-for-current-line) 23 | 24 | ;; enable visual feedback on selections 25 | (setq transient-mark-mode t) 26 | (setq column-number-mode t) 27 | 28 | ;; default to better frame titles 29 | (setq frame-title-format 30 | (concat "%b - emacs@" (system-name))) 31 | 32 | ;; default to unified diffs 33 | (setq diff-switches "-u") 34 | -------------------------------------------------------------------------------- /PyExpLabSys/common/decorators.py: -------------------------------------------------------------------------------- 1 | """This module contains general purpose decorators""" 2 | 3 | import functools 4 | 5 | 6 | def execute_on_exception(name_of_shutdown_method): 7 | """Decorates a method to execute a named method if an exception is raised 8 | 9 | Args: 10 | name_of_shutdown_method (str): The name of the method (on the same 11 | object as the decorated method) to call if the decorated methods 12 | raises an exception 13 | """ 14 | 15 | def decorator(method): 16 | """The decorator for the method""" 17 | 18 | @functools.wraps(method) 19 | def new_method(*args, **kwargs): 20 | """Decorated method""" 21 | 22 | # args[0] is the object (self) 23 | shutdown_method = getattr(args[0], name_of_shutdown_method) 24 | 25 | try: 26 | out = method(*args, **kwargs) 27 | except: 28 | shutdown_method() 29 | # Re-raise for good measure 30 | raise 31 | return out 32 | 33 | return new_method 34 | 35 | return decorator 36 | -------------------------------------------------------------------------------- /archive/rasppi75_pH_regulation/values_and_commands.txt: -------------------------------------------------------------------------------- 1 | 2 | #pH 5 +20% 3 | python ph_increment.py 5.0 --direction down --main-offset=2.0 --second-min=0.5 --second-max=0.6 --second-offset=0.5 4 | 5 | #pH 7 +20% 6 | python ph_increment.py 7.0 --direction down --main-offset=2.0 --second-min=0.8 --second-max=1 --second-offset=0.8 7 | 8 | # pH 8 +20% 9 | python ph_increment.py 8.0 --direction up --main-offset=2.0 --second-min=1.4 --second-max=1.9 --second-offset=1.9 10 | 11 | #pH 9 +20% NOT YET IDENTIFIED 12 | python ph_increment.py 5.0 --direction down --main-offset=2.0 --second-min=0.5 --second-max=0.6 --second-offset=.5 13 | 14 | #pH 5 15 | python ph_increment.py 5.0 --direction down --main-offset=2.0 --second-min=0.65 --second-max=0.8 --second-offset=0.6 16 | 17 | #pH 7 18 | python ph_increment.py 7.0 --direction down --main-offset=2.0 --second-min=0.9 --second-max=1.55 --second-offset=1.1 19 | 20 | # pH 8 21 | python ph_increment.py 8.0 --direction up --main-offset=2.0 --second-min=1.4 --second-max=1.9 --second-offset=1.9 22 | 23 | #pH 9 NOT YET IDENTIFIED 24 | python ph_increment.py 9.0 --direction up --main-offset=2.0 --second-min=1.7 --second-max=2.5 --second-offset=2.5 25 | -------------------------------------------------------------------------------- /tests/README.md: -------------------------------------------------------------------------------- 1 | This folder is for tests of different kinds, both unit test and 2 | integration tests and functional test. 3 | 4 | For this project we define: 5 | 6 | * **Unittest:** (non-controversially) as being the test of the single 7 | unit of code, isolated from everything else 8 | * **Integration test:** as being the test of any combination of units 9 | of code, except full function and not involving any hardware 10 | (equipment) 11 | * **Functional test:** as being the test of the complete function, 12 | including hardware (if required) 13 | 14 | Please order the tests with a folder for each of the categories (common, 15 | drivers, parsers etc.) and a file inside for each class. 16 | 17 | The tests are made to be run with pytest, which will automatically 18 | pick up tests from files and (classes and functions) that start with 19 | 'test'. To execute the test, enter e.g. the common folder and do: 20 | 21 | ```sh 22 | python -m pytest 23 | ``` 24 | to run all tests in there, or 25 | ```sh 26 | python -m pytest test_continous_logger.py 27 | ``` 28 | to run only the tests of the continous logger. 29 | 30 | More information about pytest can be read on the homepage: 31 | http://pytest.org/latest/ 32 | -------------------------------------------------------------------------------- /doc/source/index.rst: -------------------------------------------------------------------------------- 1 | .. PyExpLabSys documentation master file, created by 2 | sphinx-quickstart on Tue Dec 3 10:42:30 2013. 3 | You can adapt this file completely to your liking, but it should at least 4 | contain the root `toctree` directive. 5 | 6 | ####################################### 7 | Welcome to PyExpLabSys's documentation! 8 | ####################################### 9 | 10 | This page serves as documentation for the software activities at CINF. Of interest to the public are hardware drivers for experimental equipment and data logging clients but the page also contain documentation for setup specific code. 11 | 12 | Contents: 13 | 14 | .. There will be a table of contents on the main page, but only down two levels 15 | .. and it will include the content of the files liested below, which in 16 | .. themselves have their own table of contents 17 | .. toctree:: 18 | :maxdepth: 2 19 | 20 | overview 21 | user_notes 22 | common 23 | auxiliary 24 | file-parsers 25 | apps 26 | drivers 27 | drivers_autogen_only 28 | howtos 29 | developer-notes 30 | 31 | 32 | ################## 33 | Indices and tables 34 | ################## 35 | 36 | * :ref:`genindex` 37 | * :ref:`modindex` 38 | * :ref:`search` 39 | -------------------------------------------------------------------------------- /archive/rasppi75_pH_regulation/pid_opt_test.py: -------------------------------------------------------------------------------- 1 | 2 | 3 | import time 4 | from PyExpLabSys.common.database_saver import DataSetSaver, CustomColumn 5 | import credentials 6 | 7 | ## EDIT HERE 8 | comment = "First run" 9 | ## EDIT HERE 10 | 11 | 12 | 13 | 14 | # Create data set saver object 15 | data_set_saver = DataSetSaver( 16 | "measurements_dummy", "xy_values_dummy", credentials.USERNAME, credentials.PASSWORD, 17 | ) 18 | data_set_saver.start() 19 | 20 | # Create measurement specs i.e. entires entries in the metadata table 21 | data_set_time = time.time() 22 | metadata = { 23 | "time": CustomColumn(data_set_time, "FROM_UNIXTIME(%s)"), "comment": comment, 24 | "type" : 64, "preamp_range": 0, "sem_voltage": 0} 25 | 26 | # Only the labels differ, so we generate the metadata with a loop 27 | for label in ["p_korr", "i_korr", "total_korr", "ph_setpoint", "ph_value", "pump_rate"]: 28 | metadata["mass_label"] = label 29 | data_set_saver.add_measurement(label, metadata) 30 | 31 | 32 | 33 | 34 | # http://pyexplabsys.readthedocs.io/common/database_saver.html#PyExpLabSys.common.database_saver.DataSetSaver.save_point 35 | #data_set_saver.save_point() 36 | 37 | 38 | for n in range(100): 39 | data_set_saver.save_point("p_korr", (n, n*2)) 40 | 41 | 42 | data_set_saver.stop() 43 | -------------------------------------------------------------------------------- /PyExpLabSys/common/massspec/test.py: -------------------------------------------------------------------------------- 1 | """Module to test the mass spec common components""" 2 | 3 | 4 | import sys 5 | from PyQt4 import QtGui, QtCore 6 | from channel import MSChannel 7 | from qt import QtMSChannel 8 | 9 | 10 | class Test(QtGui.QWidget): 11 | """ Class to test the QtMSChannel """ 12 | 13 | def __init__(self): 14 | super(Test, self).__init__() 15 | self.channel = QtMSChannel(self, 10) 16 | self.widgets = {} 17 | 18 | grid = QtGui.QGridLayout() 19 | 20 | grid.addWidget(self.channel.gui('active')) 21 | 22 | self.setLayout(grid) 23 | self.show() 24 | 25 | 26 | def testgui(): 27 | """Test the gui""" 28 | app = QtGui.QApplication(sys.argv) 29 | test = Test() 30 | sys.exit(app.exec_()) 31 | 32 | 33 | def testchannel(): 34 | """Test the channels""" 35 | print "Test __str__ for channel for mass 10" 36 | channel1 = Channel(10.1) 37 | print channel1 38 | 39 | print '\nTest of to_dict' 40 | channel1_dict = channel1.to_dict 41 | print channel1_dict 42 | 43 | print '\nTest of from dict, change mass to 12' 44 | channel1_dict['mass'] = 12.0 45 | channel2 = Channel.from_dict(channel1_dict) 46 | print channel2 47 | 48 | 49 | if __name__ == '__main__': 50 | testchannel() 51 | -------------------------------------------------------------------------------- /archive/nidaq.py: -------------------------------------------------------------------------------- 1 | from nidaqmx import AnalogInputTask 2 | import numpy as np 3 | import math 4 | 5 | 6 | def readPressureAndTemperature(plot=False): 7 | RATE = 250.0 8 | DURATION = 5.0 9 | NUMBER_OF_SAMPLES = (int)(math.ceil(DURATION*RATE)) 10 | 11 | task = AnalogInputTask() 12 | 13 | #Ion pump 14 | task.create_voltage_channel('Dev2/ai2', terminal = 'rse', min_val=-1.0, max_val=1.0) 15 | #Turbo temperature 16 | task.create_voltage_channel('Dev2/ai4', terminal = 'rse', min_val=0, max_val=1.0) 17 | 18 | task.configure_timing_sample_clock(rate = RATE) 19 | #print task.get_convert_clock_rate() 20 | task.set_convert_clock_rate(1000) 21 | #print task.get_convert_clock_rate() 22 | task.start() 23 | 24 | #print task.get_ai_convert_max_rate() 25 | 26 | data = task.read(NUMBER_OF_SAMPLES, fill_mode='group_by_channel') 27 | del task 28 | 29 | if plot: 30 | from pylab import plot, show 31 | x = np.arange(0,DURATION,1.0/RATE) 32 | plot (x,data[0],'ro') 33 | plot (x,data[1],'bo') 34 | show () 35 | 36 | 37 | a = np.sum(data[0])/NUMBER_OF_SAMPLES 38 | ionpump = math.exp(a * 1000 * 0.124) * 2.9741e-9 39 | 40 | a = np.sum(data[1])/NUMBER_OF_SAMPLES 41 | turbo_temp = (a-0.4)/0.0195 42 | 43 | return(ionpump,turbo_temp) 44 | 45 | if __name__ == "__main__": 46 | print readPressureAndTemperature(True) -------------------------------------------------------------------------------- /PyExpLabSys/drivers/ti_ads1115.py: -------------------------------------------------------------------------------- 1 | import time 2 | import smbus 3 | 4 | 5 | class TI_ADS11x5(object): 6 | """ 7 | TI11x5 analog in 8 | """ 9 | 10 | def __init__(self): 11 | self.bus = smbus.SMBus(1) 12 | self.device_address = 0x49 13 | self.pga = { 14 | 2 / 3: 0x0000, 15 | 1: 0x0200, 16 | 2: 0x0400, 17 | 4: 0x0600, 18 | 8: 0x0800, 19 | 16: 0x0A00, 20 | } 21 | 22 | def read_sample(self, pga=1): 23 | config = 3 # Disable comperator 24 | data_rate = 0 # Slowest possible conversion 25 | config = config + self.pga[pga] + data_rate 26 | data0 = (config >> 8) & 0xFF 27 | data1 = config & 0xFF 28 | 29 | # Config is in register 1 30 | data = [data0, data1] 31 | self.bus.write_i2c_block_data(self.device_address, 0x01, data) 32 | 33 | # Value is in register 0 34 | time.sleep(0.3) 35 | data = self.bus.read_i2c_block_data(self.device_address, 0x00, 2) 36 | 37 | raw = 1.0 * (data[0] * 256 + data[1]) 38 | if raw > 32767: 39 | raw = raw - 65535 40 | value = 4.096 * raw / (pga * 2 ** 15) 41 | return value 42 | 43 | 44 | if __name__ == '__main__': 45 | ads = TI_ADS11x5() 46 | print(ads.read_sample(1)) 47 | -------------------------------------------------------------------------------- /PyExpLabSys/drivers/microchip_tech_mcp9808.py: -------------------------------------------------------------------------------- 1 | import time 2 | import smbus 3 | 4 | 5 | class MCP9808(object): 6 | """ Class for reading temperature from MCP9808 """ 7 | 8 | def __init__(self, i2cbus=1): 9 | self.bus = smbus.SMBus(i2cbus) 10 | self.device_address = 0x18 11 | 12 | def read_values(self): 13 | """ Read a value from the sensor """ 14 | self.bus.write_i2c_block_data(self.device_address, 0x01, [0x00, 0x00]) 15 | 16 | # Set range 17 | self.bus.write_byte_data(self.device_address, 0x08, 0x03) 18 | time.sleep(1) 19 | 20 | data = self.bus.read_i2c_block_data(self.device_address, 0x05, 2) 21 | temp_temp = ((data[0] & 0x1F) * 256) + data[1] 22 | temp = temp_temp * 0.0625 # Scale 23 | return temp 24 | 25 | def read_resolution(self): 26 | res = self.bus.read_byte_data(self.device_address, 0x08) 27 | print(res) 28 | 29 | def read_manufacturer_id(self): 30 | data = self.bus.read_i2c_block_data(self.device_address, 0x06, 2) 31 | man_id = data[1] 32 | print('ID is: {}'.format(hex(man_id))) 33 | return man_id 34 | 35 | 36 | if __name__ == '__main__': 37 | mcp9808 = MCP9808() 38 | mcp9808.read_manufacturer_id() 39 | mcp9808.read_resolution() 40 | print() 41 | print(mcp9808.read_values()) 42 | -------------------------------------------------------------------------------- /bootstrap/README.bootstrap_windows: -------------------------------------------------------------------------------- 1 | The bootstrap script expects: 2 | 3 | * That Python 2.7 and all the extra packages that PyExpLabSys requires has been installed. This is most easily accomplished with Python(x, y), see below. 4 | * That Git for Windows has already been installed. Get the installer from: http://git-scm.com/ 5 | * That the PyExpLabSys git archive has been cloned into C:\git\PyExpLabSys 6 | * That the script is run with admin right. See below. 7 | 8 | No parts of the script will cause problems if run more than once. 9 | 10 | 11 | About Python(x, y) 12 | ================== 13 | 14 | Python(x, y) is Python for scientific environments. It is a collection of packages that includes almost all of the packages that PyExpLabSys depend on and it is therefore by far the easiest way to get set up in a hurry. 15 | 16 | Download Python(x, y) from this page: https://code.google.com/p/pythonxy/wiki/Downloads 17 | 18 | When installing Python(x, y), leave all the default packages selected and make sure that the following extra packages are also selected: 19 | 20 | * pip 21 | * pyserial 22 | * minimalmodbus 23 | * pyodbc 24 | 25 | Running cmd with admin rights 26 | ============================= 27 | 28 | To open a cmd shell with admin right, which is required to run the bootstrap script: 29 | 30 | * Search for cmd in the Windows menu search field 31 | * Press ctrl-shift-enter 32 | * Confirm to run with admin rights 33 | -------------------------------------------------------------------------------- /PyExpLabSys/drivers/intellemetrics_il800.py: -------------------------------------------------------------------------------- 1 | """ Driver for IL800 deposition controller """ 2 | import serial 3 | 4 | 5 | class IL800(object): 6 | """ Driver for IL800 depostition controller """ 7 | 8 | def __init__(self, port): 9 | self.serial = serial.Serial(port, 9600, timeout=3, xonxoff=False, rtscts=True) 10 | 11 | def comm(self, command): 12 | """ Communicate with instrument """ 13 | self.serial.write(command + '\r') 14 | status = self.serial.read(2) 15 | if status[0] == '0': # Everything ok 16 | ret_value = ' ' 17 | while not ret_value[-1] == '\r': 18 | ret_value += self.serial.read() 19 | return ret_value[1:-1] 20 | 21 | def rate(self): 22 | """Return the deposition rate in nm/s""" 23 | rate = self.comm('CHKRATE') 24 | return float(rate) 25 | 26 | def thickness(self): 27 | """ Return the currently measured thickness in nm """ 28 | thickness = self.comm('CHKTHICKNESS') 29 | return float(thickness) 30 | 31 | def frequency(self): 32 | """ Return the qrystal frequency in Hz """ 33 | thickness = self.comm('CHKXTAL') 34 | return float(thickness) 35 | 36 | 37 | if __name__ == '__main__': 38 | IL800_UNIT = IL800('/dev/ttyUSB1') 39 | 40 | print(IL800_UNIT.rate()) 41 | print(IL800_UNIT.thickness()) 42 | print(IL800_UNIT.frequency()) 43 | -------------------------------------------------------------------------------- /PyExpLabSys/apps/bakeoutweb/static/frontpage.css: -------------------------------------------------------------------------------- 1 | 2 | .main{ 3 | width: 95%; 4 | background-color: #FFFFF0; 5 | } 6 | 7 | header { 8 | background-color: #228B22; 9 | } 10 | 11 | header h1 { 12 | padding:20px 0px 20px 20px; 13 | } 14 | 15 | footer { 16 | height: 100px; 17 | background-color: #228B22; 18 | } 19 | 20 | .circle { 21 | width: 50px; 22 | height: 50px; 23 | -webkit-border-radius: 25px; 24 | -moz-border-radius: 25px; 25 | border-radius: 25px; 26 | background: grey; 27 | margin: 0 auto; 28 | } 29 | 30 | a.header_links:link,a.header_links:visited{ 31 | color:#FFFFFF; 32 | } 33 | 34 | a.header_links:hover{ 35 | text-decoration:underline; 36 | } 37 | 38 | a:link,a:visited{ 39 | color:black; 40 | text-decoration:none; 41 | } 42 | 43 | a:hover{ 44 | color:#0C5DA5; 45 | text-decoration:underline; 46 | } 47 | 48 | 49 | table.nicetable{ 50 | border: 1px solid black; 51 | border-collapse: collapse; 52 | border-spacing: 0; 53 | } 54 | 55 | table.nicetable th{ 56 | border: 1px solid black; 57 | padding: 5px 12px; 58 | background-color: #333333; 59 | color: white; 60 | } 61 | 62 | table.nicetable td{ 63 | border: 1px solid black; 64 | padding: 2px 12px; 65 | } 66 | 67 | table.nicetable td.alert{ 68 | padding: 2px 8px; 69 | background-color: #FF0000; 70 | } 71 | 72 | table.nicetable td.all_good{ 73 | padding: 2px 8px; 74 | /* Pleasent green ;) */ 75 | background-color: #43AF11; 76 | } -------------------------------------------------------------------------------- /PyExpLabSys/apps/keithley_2450_probe_station/prepare_tsp_triggers.lua: -------------------------------------------------------------------------------- 1 | -- Prepare trigger to accept TSP-triggers 2 | tsplink.initialize() 3 | --- Clear trigger model 4 | trigger.model.load("Empty") 5 | node[2].trigger.model.load("Empty") 6 | 7 | -- Set tsp triggeren to send triggers from node 1 (gate) and accept 8 | -- triggers from node 2 (source-drain) 9 | tsplink.line[1].reset() 10 | tsplink.line[1].mode = tsplink.MODE_SYNCHRONOUS_MASTER 11 | tsplink.line[2].mode = tsplink.MODE_SYNCHRONOUS_ACCEPTOR 12 | trigger.tsplinkout[1].stimulus = trigger.EVENT_NOTIFY1 13 | trigger.tsplinkin[2].clear() 14 | trigger.tsplinkin[2].edge = trigger.EDGE_RISING 15 | 16 | -- Configure NOTIFY2 to trigger DMM 17 | trigger.digout[1].stimulus = trigger.EVENT_NOTIFY2 18 | 19 | node[2].tsplink.line[2].mode = node[2].tsplink.MODE_SYNCHRONOUS_MASTER 20 | node[2].tsplink.line[1].mode = node[2].tsplink.MODE_SYNCHRONOUS_ACCEPTOR 21 | node[2].trigger.tsplinkout[2].stimulus = node[2].trigger.EVENT_NOTIFY2 22 | node[2].trigger.tsplinkin[1].clear() 23 | node[2].trigger.tsplinkin[1].edge = node[2].trigger.EDGE_RISING 24 | 25 | -- Build actual trigger model 26 | trigger.model.setblock(1, trigger.BLOCK_NOTIFY, trigger.EVENT_NOTIFY1) 27 | trigger.model.setblock(2, trigger.BLOCK_NOTIFY, trigger.EVENT_NOTIFY2) 28 | trigger.model.setblock(3, trigger.BLOCK_MEASURE_DIGITIZE) 29 | 30 | node[2].trigger.model.setblock(1, node[2].trigger.BLOCK_WAIT, node[2].trigger.EVENT_TSPLINK1) 31 | node[2].trigger.model.setblock(2, node[2].trigger.BLOCK_MEASURE_DIGITIZE) 32 | -------------------------------------------------------------------------------- /PyExpLabSys/drivers/seeed_studio_relay.py: -------------------------------------------------------------------------------- 1 | import time 2 | import smbus 3 | 4 | bus = smbus.SMBus(1) 5 | 6 | 7 | class i2c_relay: 8 | global bus 9 | 10 | def __init__(self): 11 | self.address = 0x20 12 | self.reg_mode = 0x06 13 | self.reg_data = 0xFF 14 | self.write_bus() 15 | 16 | def write_bus(self): 17 | bus.write_byte_data(self.address, self.reg_mode, self.reg_data) 18 | 19 | def ON(self, num, echo=False): 20 | if num not in [1, 2, 3, 4]: 21 | raise ValueError( 22 | 'No relay port numbered ', 23 | num, 24 | ' available. Please specify a number from 1 to 4.', 25 | ) 26 | if echo: 27 | print('Turning relay', num, 'ON') 28 | self.reg_data &= ~(0x1 << (num - 1)) 29 | self.write_bus() 30 | 31 | def OFF(self, num, echo=False): 32 | if num not in [1, 2, 3, 4]: 33 | raise ValueError( 34 | 'No relay port numbered ', 35 | num, 36 | ' available. Please specify a number from 1 to 4.', 37 | ) 38 | if echo: 39 | print('Turning relay', num, 'OFF') 40 | self.reg_data |= 0x1 << (num - 1) 41 | self.write_bus() 42 | 43 | 44 | if __name__ == '__main__': 45 | relay = i2c_relay() 46 | for i in [1, 2, 3, 4]: 47 | relay.ON(i) 48 | time.sleep(0.5) 49 | for i in [1, 2, 3, 4]: 50 | relay.OFF(i) 51 | time.sleep(0.5) 52 | -------------------------------------------------------------------------------- /doc/source/drivers/four_d_systems.rst: -------------------------------------------------------------------------------- 1 | .. _drivers-doc-four_d_systems: 2 | 3 | ********************* 4 | The 4d Systems module 5 | ********************* 6 | 7 | Picaso Common 8 | ============= 9 | 10 | The 4d Systems module at present contains the Picaso Common driver, 11 | which at a minimum works for the Picaso uLCD-28PTU LCD display, but 12 | likely will also work for other displays in the same series. 13 | 14 | .. inheritance-diagram:: 15 | PyExpLabSys.drivers.four_d_systems.PicasoCommon 16 | PyExpLabSys.drivers.four_d_systems.PicasouLCD28PTU 17 | 18 | Usage Example 19 | ------------- 20 | 21 | .. code-block:: python 22 | 23 | import time 24 | from PyExpLabSys.drivers.four_d_systems import PicasouLCD28PTU 25 | 26 | # Text example 27 | picaso = PicasouLCD28PTU(serial_device='/dev/ttyUSB0', baudrate=9600) 28 | picaso.clear_screen() 29 | for index in range(5): 30 | picaso.move_cursor(index, index) 31 | picaso.put_string('CINF') 32 | 33 | # Touch example 34 | picaso.move_cursor(7, 0) 35 | picaso.put_string('Try and touch me!') 36 | picaso.touch_set('enable') 37 | for _ in range(25): 38 | time.sleep(0.2) 39 | print picaso.touch_get_status() 40 | print picaso.touch_get_coordinates() 41 | 42 | picaso.close() 43 | 44 | four_d_systems module 45 | --------------------- 46 | 47 | .. automodule:: PyExpLabSys.drivers.four_d_systems 48 | :members: 49 | :member-order: bysource 50 | :show-inheritance: 51 | :private-members: 52 | -------------------------------------------------------------------------------- /archive/ParallelPortBinaryOut.py: -------------------------------------------------------------------------------- 1 | import parallel 2 | 3 | class ParallelPortBinaryOut: 4 | """ Used to manually set the state of the 8 binary pins in a parallel port 5 | """ 6 | def __init__(self, port=0): 7 | self.parallel = parallel.Parallel(port=port) 8 | # list of states, port number are equal to list index, endianness is 9 | # handled in the setStates function 10 | self.state = [False]*8 11 | 12 | def setState(self, port=0, active=False): 13 | """ Set the state of to the boolean value of an input 14 | 15 | Keyword arguments 16 | port -- The port number (0-7) 17 | active -- The new state (True or False) or anything whose boolean value 18 | can be intertreted by "bool()" 19 | """ 20 | if not (0 <= port <= 7): 21 | raise Exception('Port number must be between 0 and 7') 22 | 23 | # Interprete the boolean value of "active" and set the state 24 | active = bool(active) 25 | self.state[port] = active 26 | self._update_hardware() 27 | 28 | def _update_hardware(self): 29 | """ Write the list of boolean values to the hardware """ 30 | # Reverse for correct endianness. Turn True and False into '1' and '0' 31 | state = [str(int(element)) for element in reversed(self.state)] 32 | # Combine into string and convert binary string to number 33 | state = int(''.join(state), 2) 34 | self.parallel.setData(state) 35 | 36 | if __name__ == "__main__": 37 | p = ParallelPortBinaryOut() 38 | -------------------------------------------------------------------------------- /PyExpLabSys/drivers/inficon_sqc310.py: -------------------------------------------------------------------------------- 1 | from PyExpLabSys.drivers.inficon_sqm160 import InficonSQM160 2 | 3 | 4 | class InficonSQC310(InficonSQM160): 5 | """ Driver for Inficon SQC310 QCM controller """ 6 | 7 | def __init__(self, port='/dev/ttyUSB0'): 8 | super().__init__(baudrate=19200) 9 | 10 | def crystal_frequency_and_life(self, channel=1): 11 | """ Read crystal life """ 12 | command = 'PA' + str(channel) 13 | value_string = self.comm(command) 14 | values_raw = value_string.split(b' ') 15 | active = values_raw[0] == b'1' 16 | frequency = float(values_raw[1]) 17 | life = float(values_raw[2]) 18 | return active, frequency, life 19 | 20 | def frequency(self, channel=1): 21 | _, frequency, _ = self.crystal_frequency_and_life(channel) 22 | return frequency 23 | 24 | def crystal_life(self, channel=1): 25 | _, _, life = self.crystal_frequency_and_life(channel) 26 | return life 27 | 28 | 29 | if __name__ == '__main__': 30 | INFICON = InficonSQC310() 31 | 32 | print() 33 | print('Controler version: ', INFICON.show_version()) 34 | 35 | print() 36 | print('Frequency and life 1: ', INFICON.crystal_frequency_and_life(1)) 37 | print('Frequency and life 2: ', INFICON.crystal_frequency_and_life(2)) 38 | 39 | print() 40 | print('Rate channel 1: ', INFICON.rate(1)) 41 | print('Rate channel 2: ', INFICON.rate(2)) 42 | 43 | print() 44 | print('Thinkness channel 1: ', INFICON.thickness(1)) 45 | print('Thinkness channel 2: ', INFICON.thickness(2)) 46 | -------------------------------------------------------------------------------- /PyExpLabSys/apps/tof/helper_scripts/lm_test.py: -------------------------------------------------------------------------------- 1 | import pickle 2 | import numpy as np 3 | import math 4 | 5 | # from numpy import sqrt, pi, exp, linspace, loadtxt 6 | from lmfit import Model 7 | import matplotlib.pyplot as plt 8 | 9 | Data = pickle.load(open('4160.p', 'rb'), encoding='latin1') 10 | times = [5.53] 11 | times = [11.455, 11.468] 12 | 13 | center = np.where(Data[:, 0] > np.mean(times))[0][0] 14 | 15 | Start = center - 125 # Display range 16 | End = center + 125 17 | x = Data[Start:End, 0] 18 | y = Data[Start:End, 1] 19 | 20 | 21 | def gaussian(x, amp, cen, wid): 22 | return amp * math.e ** (-1 * ((x - cen) ** 2) / wid) 23 | 24 | 25 | def double_gaussian(x, amp, cen, wid, amp2, cen2): 26 | peak1 = gaussian(x, amp, cen, wid) 27 | peak2 = gaussian(x, amp2, cen2, wid) 28 | return peak1 + peak2 29 | 30 | 31 | if len(times) == 1: 32 | gmod = Model(gaussian) 33 | result = gmod.fit(y, x=x, amp=max(y), cen=times[0], wid=0.000001) 34 | if len(times) == 2: 35 | center1 = np.where(Data[:, 0] > times[0])[0][0] 36 | max1 = max(Data[center1 - 10 : center1 + 10, 1]) 37 | 38 | center2 = np.where(Data[:, 0] > times[1])[0][0] 39 | max2 = max(Data[center2 - 10 : center2 + 10, 1]) 40 | 41 | gmod = Model(double_gaussian) 42 | result = gmod.fit( 43 | y, x=x, amp=max1, cen=times[0], amp2=max2, cen2=times[1], wid=0.000002 44 | ) 45 | 46 | print(result.params['amp'].value) 47 | 48 | print(result.fit_report()) 49 | print(result.success) 50 | 51 | plt.plot(x, y, 'bo') 52 | plt.plot(x, result.init_fit, 'k--') 53 | plt.plot(x, result.best_fit, 'r-') 54 | plt.show() 55 | -------------------------------------------------------------------------------- /PyExpLabSys/drivers/kjlc_pressure_gauge.py: -------------------------------------------------------------------------------- 1 | """ Module contains driver for KJLC 3000 pressure gauge """ 2 | import serial 3 | import time 4 | from PyExpLabSys.common.supported_versions import python2_and_3 5 | 6 | python2_and_3(__file__) 7 | 8 | KJLC = None 9 | 10 | 11 | class KJLC300(object): 12 | """ Class implements a KJLC interface """ 13 | 14 | def __init__(self, port): 15 | self.connection = serial.Serial( 16 | port, 17 | baudrate=1200, 18 | bytesize=8, 19 | parity='N', 20 | stopbits=1, 21 | timeout=1, 22 | writeTimeout=1, 23 | ) 24 | 25 | def close(self): 26 | """ Closes connection """ 27 | self.connection.close() 28 | 29 | def read_software_version(self): 30 | """ Reads software version """ 31 | self.connection.write('#01VER\r'.encode('ascii')) 32 | raw = self.connection.read(13) 33 | out = self._format_output(raw) 34 | return out 35 | 36 | def read_pressure(self): 37 | """ Reads pressure in Torr """ 38 | self.connection.write('#01RD\r'.encode('ascii')) 39 | raw = self.connection.read(13) 40 | out = self._format_output(raw) 41 | try: 42 | out = float(out) 43 | out = 1.33322 * out 44 | time.sleep(0.1) 45 | except ValueError: 46 | out = 'error' 47 | return out 48 | 49 | def _format_output(self, string): 50 | """Strip *, the adress and a space from the beginning and a CR from the 51 | end 52 | """ 53 | return string[4:-1] 54 | -------------------------------------------------------------------------------- /doc/source/_static/laser_control_client.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ 3 | Created on Thu Jul 17 15:39:24 2014 4 | 5 | @author: kenni 6 | """ 7 | 8 | import socket 9 | import json 10 | import time 11 | 12 | # REMEMBER to change the host name to the machine you are running the server 13 | # on, 'localhost' assumes that both are being run on the same machine 14 | HOST = 'localhost' 15 | PORT = 8500 16 | 17 | 18 | sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) 19 | 20 | def send_command(data): 21 | print 22 | command = 'json_wn#{}'.format(json.dumps(data)) 23 | print 'Sending command: {}'.format(command) 24 | sock.sendto(command, (HOST, PORT)) 25 | data, _ = sock.recvfrom(1024) 26 | if data.startswith('RET#'): 27 | return_value = data.split('#')[1] 28 | print 'Command successfull, returned: {}'.format(return_value) 29 | else: 30 | message = 'The laser did not understand the command. Return value '\ 31 | 'was: {}'.format(data) 32 | raise Exception(message) 33 | return json.loads(return_value) 34 | 35 | ### Main script 36 | # Update settings 37 | print send_command({'method': 'update_settings', 'power': 300, 'focus': 10}) 38 | # Change state 39 | print send_command({'method': 'state', 'state': 'active'}) 40 | # Get the temperature measurements back from the laser as they come in 41 | for _ in range(4): 42 | print send_command({'method': 'get_temperature'}) 43 | time.sleep(2.5) 44 | 45 | # Change state and stop 46 | print send_command({'method': 'state', 'state': 'idle'}) 47 | time.sleep(2) # Give it time to firing 48 | print send_command({'method': 'stop'}) 49 | -------------------------------------------------------------------------------- /PyExpLabSys/drivers/freescale_mma7660fc.py: -------------------------------------------------------------------------------- 1 | """ Driver for AIS328DQTR 3 axis accelerometer """ 2 | import time 3 | import os 4 | from PyExpLabSys.common.supported_versions import python2_and_3 5 | 6 | on_rtd = os.environ.get('READTHEDOCS', None) == 'True' 7 | python2_and_3(__file__) 8 | if on_rtd: 9 | pass 10 | else: 11 | import smbus 12 | 13 | 14 | class MMA7660FC(object): 15 | """ Class for reading accelerometer output """ 16 | 17 | def __init__(self): 18 | self.bus = smbus.SMBus(1) 19 | self.device_address = 0x4C 20 | # Turn on the device through MODE register (7) 21 | self.bus.write_byte_data(self.device_address, 0x07, 0x01) 22 | # Number of samples pr seconds, registor 8 23 | self.bus.write_byte_data(self.device_address, 0x08, 0x07) 24 | 25 | time.sleep(0.5) 26 | 27 | def read_values(self): 28 | """ Read a value from the sensor """ 29 | 30 | data = self.bus.read_i2c_block_data(0x4C, 0x00, 5) 31 | x_value = data[0] & 0x3F 32 | if x_value > 31: 33 | x_value = x_value - 64 34 | x_value = x_value * 1.5 / 32 35 | 36 | y_value = data[1] & 0x3F 37 | if y_value > 31: 38 | y_value = y_value - 64 39 | y_value = y_value * 1.5 / 32 40 | 41 | z_value = data[2] & 0x3F 42 | if z_value > 31: 43 | z_value = z_value - 64 44 | z_value = z_value * 1.5 / 32 45 | 46 | return (x_value, y_value, z_value) 47 | 48 | 49 | if __name__ == '__main__': 50 | MMA = MMA7660FC() 51 | for i in range(0, 20): 52 | time.sleep(0.05) 53 | print(MMA.read_values()) 54 | -------------------------------------------------------------------------------- /archive/cinfkiosk/test_pyqwt.py: -------------------------------------------------------------------------------- 1 | 2 | from __future__ import division, print_function 3 | 4 | import time 5 | import sys 6 | import numpy as np 7 | from qwt.qt import QtGui, QtCore 8 | from qwt import QwtPlot, QwtPlotCurve 9 | 10 | YS = 10 11 | POINTS = 10000 12 | FREQ = 10 13 | 14 | print("Points:", POINTS) 15 | print("Freq:", FREQ) 16 | print("Points per s:", POINTS * FREQ) 17 | 18 | 19 | x = np.linspace(0, 6.28, POINTS) 20 | ys = [np.sin(x + 6.28/YS*n) for n in range(YS)] 21 | 22 | 23 | 24 | class Example(QtGui.QWidget): 25 | 26 | def __init__(self): 27 | super(Example, self).__init__() 28 | self.initUI() 29 | 30 | 31 | self.current_y = 0 32 | 33 | self.timer = QtCore.QTimer() 34 | self.timer.timeout.connect(self.update_plot) 35 | self.timer.setInterval(1000/FREQ) 36 | self.timer.start() 37 | 38 | 39 | def initUI(self): 40 | 41 | self.setGeometry(300, 300, 1000, 1000) 42 | self.setWindowTitle('Icon') 43 | self.setWindowIcon(QtGui.QIcon('web.png')) 44 | self.plot = QwtPlot("Test", self) 45 | self.plot.resize(900, 900) 46 | self.curve = QwtPlotCurve("Curve 1") 47 | self.curve.attach(self.plot) 48 | self.show() 49 | 50 | def update_plot(self): 51 | self.curve.setData(x, ys[self.current_y]) 52 | self.current_y = (self.current_y + 1) % YS 53 | #print(POINTS * FREQ, "points per second") 54 | 55 | 56 | def main(): 57 | 58 | app = QtGui.QApplication(sys.argv) 59 | ex = Example() 60 | sys.exit(app.exec_()) 61 | 62 | 63 | if __name__ == '__main__': 64 | main() 65 | -------------------------------------------------------------------------------- /archive/byg/BYG-F0139/mymaster.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | from __future__ import print_function, division 4 | #import curses 5 | #import socket 6 | import threading 7 | import time 8 | #import socket 9 | #import json 10 | 11 | 12 | import sys 13 | sys.path.insert(1, '/home/pi/PyExpLabSys') 14 | 15 | #import credentials 16 | #import socketinfo 17 | #from PyExpLabSys.common.loggers import ContinuousLogger 18 | #ContinuousLogger.host = credentials.dbhost 19 | #ContinuousLogger.database = credentials.dbname 20 | #from PyExpLabSys.common.sockets import DateDataPullSocket 21 | #from PyExpLabSys.common.value_logger import ValueLogger 22 | 23 | 24 | 25 | 26 | if __name__ == '__main__': 27 | 28 | from mydatalogger import MainDatalogger 29 | MDL = MainDatalogger() 30 | MDL.daemon = True 31 | MDL.start() 32 | #time.sleep(4) 33 | 34 | from mymultiplexer import MainMultilogger 35 | MML = MainMultilogger() 36 | MML.daemon = True 37 | MML.start() 38 | #time.sleep(4) 39 | 40 | from mytui import MainTui 41 | MT = MainTui() 42 | MT.start() 43 | time.sleep(4) 44 | 45 | from mypid import MainPID 46 | MP = MainPID() 47 | MP.daemon = True 48 | MP.start() 49 | time.sleep(4) 50 | 51 | from mydigitalinout import MainDGIO 52 | DGIO = MainDGIO() 53 | DGIO.daemon = True 54 | DGIO.start() 55 | 56 | while MT.isAlive(): 57 | try: 58 | time.sleep(1) 59 | except (KeyboardInterrupt, SystemExit): 60 | MT.quit = True 61 | DGIO.quit = True 62 | MP.quit = True 63 | MT.quit = True 64 | MML.quit = True 65 | MDL.quit = True 66 | print('END') 67 | 68 | 69 | -------------------------------------------------------------------------------- /PyExpLabSys/drivers/tsl45315.py: -------------------------------------------------------------------------------- 1 | """ Driver for TSL45315 Digital Ambient Light Sensor """ 2 | import os 3 | 4 | on_rtd = os.environ.get('READTHEDOCS', None) == 'True' 5 | if on_rtd: 6 | pass 7 | else: 8 | import smbus 9 | import time 10 | from PyExpLabSys.common.supported_versions import python2_and_3 11 | 12 | python2_and_3(__file__) 13 | 14 | 15 | class TSL45315(object): 16 | """Class for reading pressure and temperature from 17 | TSL45315 Digital Ambient Light Sensor""" 18 | 19 | def __init__(self, integration_time=0): 20 | # Integration times: 21 | # 0: 400ms 22 | # 1: 200ms 23 | # 2: 100ms 24 | integration_times = {0: 0.4, 1: 0.2, 2: 0.1} 25 | self.integration_time = integration_times[integration_time] 26 | self.multiplier = 0.4 / self.integration_time 27 | print(self.multiplier) 28 | self.device_address = 0x29 29 | self.bus = smbus.SMBus(1) 30 | 31 | self.bus.write_byte_data(self.device_address, 0x80, 0x03) 32 | self.bus.write_byte_data(self.device_address, 0x81, integration_time) 33 | 34 | def read_id(self): 35 | value = self.bus.read_byte_data(self.device_address, 0x0A) 36 | print(value) 37 | 38 | def read_values(self): 39 | """ Read a value from the sensor """ 40 | time.sleep(self.integration_time) 41 | 42 | data = self.bus.read_i2c_block_data(self.device_address, 0x04 | 0x80, 2) 43 | value = data[0] + data[1] * 255 44 | return self.multiplier * value 45 | 46 | 47 | if __name__ == '__main__': 48 | SENSOR = TSL45315(integration_time=0) 49 | # print(SENSOR.read_id()) 50 | for i in range(0, 25): 51 | print(SENSOR.read_values()) 52 | -------------------------------------------------------------------------------- /PyExpLabSys/apps/qms/NOTES: -------------------------------------------------------------------------------- 1 | The code is split into 2. In this folder is tha app and there also 2 2 | drivers: 3 | * pfeiffer_qmg_420 4 | * pfeiffer_qmg_422 5 | 6 | mass_spec is main interface. Usually run by aditing run component in __main__ block. Consider making CLI interface. Type of qmg is setting. Is has methods for SEM and filament, mass scan, mass time and leak search. 7 | 8 | qms.py is the mass spectrometer. All *status_methods are get AND set. Data is passed into the SqlSaver queue as SQL queries. There are here methods for parsing channel list and running mass scan and mass time. 9 | 10 | qmg_meta_channels: Gets the meta channel part of the channel list and creates a UDP channel (threaded) for each meta channel. Support for local channels is implemented by putting a local_channels.py file in machine folder with a Local class. Only example for now is in microreactorNG-ms machine folder. 11 | 12 | REMEMBER that this mass spec configuration comes with 2 different qmg (electronics in rack) boxes and two different qme (electronic on mass spec) boxes, which gives a total for 4 different combincations, of which we have 3 13 | 14 | qmg-420 qmg-422 15 | qme-125 v v 16 | qme-400?? x v 17 | 18 | There is also a qmg-421, with only few? changes from 422. We have been unable to get the manual for it. 19 | 20 | 21 | The drivers in principle implements an interface, but it is not inforced. Mass time is run by setting channels list and settings asking mass time to only run it once, whereafter the driver is asked if there is a sample ready, which is assumed to be associated with the next channel in the list. 22 | 23 | NOTE: At present mass scan integration time is not exposed as settings and is only available by editing driver code. 24 | 25 | -------------------------------------------------------------------------------- /doc/source/drivers/pfeiffer.rst: -------------------------------------------------------------------------------- 1 | .. _drivers-doc-pfeiffer: 2 | 3 | ******************* 4 | The pfeiffer module 5 | ******************* 6 | 7 | The pfeiffer module contains drivers for equipment from Pfeiffer 8 | Vacuum. At present the module contains drivers for the :class:`TPG 261 9 | <.TPG261>` and :class:`TPG 262 <.TPG262>` pressure measurement and 10 | control units. 11 | 12 | TPG 26x 13 | ======= 14 | 15 | The TPG 261 and TPG 262 has the same communications protocol and 16 | therefore the driver has been implemented as a common driver in the 17 | :class:`.TPG26x` class, which the :class:`.TPG261` and 18 | :class:`.TPG262` classes inherit from, as illustrated below. 19 | 20 | .. inheritance-diagram:: PyExpLabSys.drivers.pfeiffer 21 | 22 | The driver implements only a sub set of the specification, but given 23 | that the ground work has already been done, it should be simple to 24 | implement more methods as they are needed. 25 | 26 | Usage Example 27 | ------------- 28 | 29 | The driver classes can be instantiated by specifying just the address 30 | of the serial communications port the unit is connected to: 31 | 32 | .. code-block:: python 33 | 34 | from PyExpLabSys.drivers.pfeiffer import TPG262 35 | tpg = TPG262(port='/dev/ttyUSB0') 36 | value, (status_code, status_string) = tpg.pressure_gauge(1) 37 | # or 38 | value, _ = tpg.pressure_gauge(1) 39 | unit = tpg.pressure_unit() 40 | print 'pressure is {} {}'.format(value, unit) 41 | 42 | If the baud rate on the TPG 26x unit has been changed away from the 43 | default setting of 9600, then the correct baud rate will need to be 44 | given as a parameter. 45 | 46 | pfeiffer module 47 | --------------- 48 | 49 | .. automodule:: PyExpLabSys.drivers.pfeiffer 50 | :members: 51 | :member-order: bysource 52 | :show-inheritance: 53 | -------------------------------------------------------------------------------- /PyExpLabSys/apps/socket_supervisor.py: -------------------------------------------------------------------------------- 1 | """ Module to check that local machine is living up to its duties """ 2 | import time 3 | from PyExpLabSys.common.utilities import get_logger 4 | from PyExpLabSys.common.sockets import DateDataPullSocket 5 | import threading 6 | import socket 7 | import sys 8 | 9 | sys.path.append('/home/pi/PyExpLabSys/machines/' + sys.argv[1]) 10 | import settings # pylint: disable=F0401 11 | from PyExpLabSys.common.supported_versions import python2_and_3 12 | 13 | python2_and_3(__file__) 14 | LOGGER = get_logger('Socket Supervisor') 15 | 16 | 17 | class SocketSupervisor(threading.Thread): 18 | """ Supervisor will check that a list of ports are still open """ 19 | 20 | def __init__(self): 21 | threading.Thread.__init__(self) 22 | self.quit = False 23 | self.ports = settings.ports 24 | self.setup = settings.setup 25 | self.pullsocket = DateDataPullSocket( 26 | self.setup + '-socket supervisor', 27 | [str(port) for port in self.ports], 28 | timeouts=len(self.ports) * [5], 29 | ) 30 | self.pullsocket.start() 31 | 32 | def run(self): 33 | """ Main loop """ 34 | while not self.quit: 35 | for port in self.ports: 36 | time.sleep(1) 37 | sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 38 | result = sock.connect_ex(('127.0.0.1', port)) 39 | if result == 0: 40 | self.pullsocket.set_point_now(str(port), True) 41 | print(port, True) 42 | else: 43 | self.pullsocket.set_point_now(str(port), False) 44 | print(port, False) 45 | 46 | 47 | if __name__ == '__main__': 48 | SP = SocketSupervisor() 49 | SP.start() 50 | -------------------------------------------------------------------------------- /tests/functional_test/fileparsers/test_chemstation/generate.py: -------------------------------------------------------------------------------- 1 | 2 | """Generate chemstation test data from working configuration""" 3 | 4 | import json 5 | from os import path 6 | 7 | from PyExpLabSys.file_parsers.chemstation import Sequence 8 | 9 | THIS_DIR = path.dirname(path.realpath(__file__)) 10 | SEQUENCES = ( 11 | Sequence(path.join(THIS_DIR, 'def_GC 2015-01-13 11-16-24')), 12 | Sequence(path.join(THIS_DIR, '05102016_CAL_CH4_5CM3')), 13 | ) 14 | 15 | 16 | def generate_sequence_metadata(): 17 | """Generate sequence metadata""" 18 | out = [] 19 | for seq in SEQUENCES: 20 | meta = seq.metadata 21 | meta['sequence_start_timestruct_CONVERT'] = tuple( 22 | meta.pop('sequence_start_timestruct') 23 | ) 24 | out.append(meta) 25 | 26 | with open('sequence_metadata.json', 'wb') as file_: 27 | json.dump(out, file_, indent=4) 28 | 29 | 30 | def generate_full_sequence_data(): 31 | """Generate full sequence data""" 32 | out = SEQUENCES[0].full_sequence_dataset() 33 | with open('chemstation_data.json', 'wb') as file_: 34 | json.dump(out, file_, indent=4) 35 | 36 | def generate_injection_metadata(): 37 | """Generate injections metadata""" 38 | out = [] 39 | for seq in SEQUENCES: 40 | injection_metadata = dict(seq.injections[0].metadata) 41 | for key in list(injection_metadata.keys()): 42 | if key.endswith('_timestruct'): 43 | injection_metadata[key + '_CONVERT'] =\ 44 | tuple(injection_metadata.pop(key)) 45 | out.append(injection_metadata) 46 | with open('injection_metadata.json', 'wb') as file_: 47 | json.dump(out, file_, indent=4) 48 | 49 | generate_sequence_metadata() 50 | generate_full_sequence_data() 51 | generate_injection_metadata() 52 | -------------------------------------------------------------------------------- /PyExpLabSys/apps/keithley_2450_probe_station/ps_dmm_reader.py: -------------------------------------------------------------------------------- 1 | import threading 2 | 3 | from PyExpLabSys.drivers.keithley_2100 import Keithley2100 4 | 5 | 6 | class ProbeStationDMMReader(threading.Thread): 7 | def __init__(self, visa_string): 8 | threading.Thread.__init__(self) 9 | self.daemon = True 10 | self.running = True 11 | 12 | # TODO - Visa string should of course not be hard-codet 13 | self.dmm = Keithley2100(visa_string) 14 | self._configure() 15 | self.value = self.measure() 16 | 17 | def _configure(self): 18 | """ 19 | Configure Model 2000 used for 2-point measurement 20 | The unit is set up to measure on the gaurd output of 21 | the 2450. 22 | """ 23 | self.dmm.clear_errors() 24 | self.dmm.measurement_function('volt:dc') 25 | self.dmm.measurement_range(0) 26 | self.dmm.integration_time(1) 27 | # Consider whether it makes sense to use external trigger. This would 28 | # sync the DMM to the 2450'ies but would also lock the measurement and 29 | # potentially slow down. The DMM is a sanity check that does not 30 | # strictly need to be 100% sync'ed to the actual measurement 31 | self.dmm.trigger_source(external=False) 32 | 33 | def measure(self): 34 | value = self.dmm.read() 35 | return value 36 | 37 | def run(self): 38 | while self.running: 39 | self.value = self.measure() 40 | 41 | 42 | if __name__ == '__main__': 43 | import time 44 | 45 | reader = ProbeStationDMMReader('USB0::1510::8448::8019151::0::INSTR') 46 | reader.start() 47 | t = time.time() 48 | 49 | dt = time.time() - t 50 | while dt < 25: 51 | print(reader.value) 52 | time.sleep(0.2) 53 | dt = time.time() - t 54 | reader.running = False 55 | -------------------------------------------------------------------------------- /PyExpLabSys/drivers/honeywell_6000.py: -------------------------------------------------------------------------------- 1 | """ Driver for HIH6000 class temperature and humidity sensors """ 2 | import os 3 | 4 | on_rtd = os.environ.get('READTHEDOCS', None) == 'True' 5 | if on_rtd: 6 | pass 7 | else: 8 | import smbus 9 | import time 10 | from PyExpLabSys.common.supported_versions import python2_and_3 11 | 12 | python2_and_3(__file__) 13 | 14 | 15 | class HIH6130(object): 16 | """Class for reading pressure and temperature from 17 | Honeywell HumidIcon HIH-6130/6131""" 18 | 19 | def __init__(self, i2cbus=1): 20 | self.bus = smbus.SMBus(i2cbus) 21 | self.device_address = 0x27 22 | 23 | def read_values(self): 24 | """ Read a value from the sensor """ 25 | self.bus.write_quick(0x27) 26 | time.sleep(0.05) 27 | result = self.bus.read_i2c_block_data(self.device_address, 0, 4) 28 | 29 | # Two upper bits of byte 0 are stauts bits 30 | status = (result[0] & 0b11000000) >> 6 31 | if status > 1: # Error 32 | return None 33 | 34 | # The rest of byte 0 is the most significant byte of the total 14 bit value 35 | hum_high = (result[0] & 0b111111) << 8 36 | # Add this to lower byte to fill in the lower 8 bit 37 | hum_total = hum_high + result[1] 38 | hum_calibrated = hum_total * 100.0 / (2 ** 14 - 1) 39 | 40 | # 3rd byte contans the upper 8 bits of temperature, make room to the six lower bits 41 | temp_high = result[2] << 6 42 | # 4th byte contains the lower six bits, shifted by two empty bits 43 | temp_low = +(result[3] & 0b11111100) >> 2 44 | temp = temp_high + temp_low 45 | temp_calibrated = (temp * 165.0 / (2 ** 14 - 1)) - 40 46 | return (hum_calibrated, temp_calibrated) 47 | 48 | 49 | if __name__ == '__main__': 50 | HIH = HIH6130() 51 | print(HIH.read_values()) 52 | -------------------------------------------------------------------------------- /PyExpLabSys/drivers/isotech_ips.py: -------------------------------------------------------------------------------- 1 | """ Driver for ISO-TECH IPS power supply series 2 | 3 | It has not been possible to get the device to give any 4 | meaningfull replys, but actually setting output values 5 | works. 6 | """ 7 | import serial 8 | import time 9 | 10 | 11 | class IPS(object): 12 | """ Driver for IPS power supply """ 13 | 14 | def __init__(self, port): 15 | self.serial = serial.Serial(port, 2400, timeout=10, xonxoff=False, rtscts=False) 16 | 17 | def comm(self, command): 18 | """ Communicate with instrument """ 19 | encoded_command = (command + '\r').encode('ascii') 20 | self.serial.write(encoded_command) 21 | # The unit will fail to run at more than 2Hz 22 | time.sleep(0.5) 23 | return True 24 | 25 | def set_vlimit_to_max(self): 26 | """ Set the voltage limit to the maximum the device deliver """ 27 | self.comm('SUM') 28 | 29 | def set_ilimit_to_max(self): 30 | """ Set the current limit to the maximum the device deliver """ 31 | self.comm('SIM') 32 | 33 | def set_relay_status(self, status=False): 34 | """ Turn the output on or off """ 35 | if status is True: 36 | self.comm('KOE') 37 | else: 38 | self.comm('KOD') 39 | 40 | def set_output_voltage(self, voltage): 41 | """ Set the output voltage """ 42 | self.comm('SV ' + '{:2.2f}'.format(voltage).zfill(5)) 43 | 44 | def set_voltage_limit(self, voltage): 45 | """ Set the voltage limit """ 46 | self.comm('SU ' + str(voltage)) 47 | 48 | def set_current_limit(self, current): 49 | """ Set the current limit """ 50 | self.comm('SI ' + '{:1.2f}'.format(current).zfill(3)) 51 | 52 | 53 | if __name__ == '__main__': 54 | ips = IPS('/dev/ttyUSB2') 55 | ips.set_relay_status(True) 56 | ips.set_output_voltage(5) 57 | -------------------------------------------------------------------------------- /PyExpLabSys/drivers/omega_cn7800.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """ Omega CN7800 Modbus driver. Might also work with other CN units. Settings 3 | on the device should be RTU and datalength 8 bit. 4 | """ 5 | 6 | import logging 7 | import serial 8 | import minimalmodbus 9 | 10 | LOGGER = logging.getLogger(__name__) 11 | # Make the logger follow the logging setup from the caller 12 | # LOGGER.addHandler(logging.NullHandler()) 13 | LOGGER.addHandler(logging.StreamHandler()) 14 | 15 | 16 | class CN7800(object): 17 | """Driver for the omega CN7800""" 18 | 19 | def __init__(self, port): 20 | self.comm = minimalmodbus.Instrument("/dev/serial/by-id/" + port, 1) 21 | self.comm.serial.baudrate = 9600 22 | self.comm.serial.parity = serial.PARITY_EVEN 23 | self.comm.serial.timeout = 0.5 24 | self.temperature = -999 25 | 26 | def read_temperature(self): 27 | """ Read the temperature from the device """ 28 | self.temperature = self.comm.read_register(0x1000, 1) 29 | return self.temperature 30 | 31 | def read_setpoint(self): 32 | """ Read the temperature setpoint """ 33 | setpoint = self.comm.read_register(0x1001, 1) 34 | return setpoint 35 | 36 | def write_setpoint(self, new_setpoint): 37 | """ Write a new setpoint to the device """ 38 | self.comm.write_register(0x1001, new_setpoint, 1) 39 | 40 | 41 | def main(): 42 | 43 | port = "usb-FTDI_USB-RS485_Cable_FT1F9WC2-if00-port0" 44 | # port = "/dev/ttyUSB0" 45 | omega = CN7800(port) 46 | print("Temperature is:", omega.read_temperature()) 47 | print("Set point is:", omega.read_setpoint()) 48 | print("Temperature type is:", type(omega.read_temperature())) 49 | print("Set point is:", omega.write_setpoint(float(30))) 50 | print("Set point is:", omega.read_setpoint()) 51 | 52 | 53 | if __name__ == "__main__": 54 | # Execute only if run as script 55 | main() 56 | -------------------------------------------------------------------------------- /PyExpLabSys/drivers/keithley_2700.py: -------------------------------------------------------------------------------- 1 | """ Simple driver for Keithley Model 2700 """ 2 | from PyExpLabSys.drivers.scpi import SCPI 3 | 4 | 5 | class Keithley2700(SCPI): 6 | """ Simple driver for Keithley Model 2700 """ 7 | 8 | def __init__(self, interface, device=None, gpib_address=None): 9 | if interface == 'serial': 10 | SCPI.__init__(self, interface='serial', device=device, baudrate=9600) 11 | self.scpi_comm('FORMAT:ELEMENTS READ') # Set short read-format 12 | if interface == 'gpib': 13 | SCPI.__init__(self, interface=interface, gpib_address=gpib_address) 14 | 15 | def select_measurement_function(self, function): 16 | """Select a measurement function. 17 | 18 | Keyword arguments: 19 | Function -- A string stating the wanted measurement function. 20 | 21 | """ 22 | 23 | values = [ 24 | 'CAPACITANCE', 25 | 'CONTINUITY', 26 | 'CURRENT', 27 | 'DIODE', 28 | 'FREQUENCY', 29 | 'RESISTANCE', 30 | 'FRESISTANCE', 31 | 'TEMPERATURE', 32 | 'VOLTAGE', 33 | ] 34 | return_value = False 35 | if function in values: 36 | return_value = True 37 | function_string = "FUNCTION " + "\"" + function + "\"" 38 | self.scpi_comm(function_string) 39 | return return_value 40 | 41 | def read(self): 42 | """ Read a value from the device """ 43 | value_raw = self.scpi_comm("READ?").split(',') 44 | value = float(value_raw[0][0:15]) 45 | timestamp = float(value_raw[1][0:10]) 46 | readings = int(value_raw[2][0:7]) 47 | return value, timestamp, readings 48 | 49 | 50 | if __name__ == '__main__': 51 | GPIB = 5 52 | MUX = Keithley2700(interface='gpib', gpib_address=GPIB) 53 | 54 | print(MUX.scpi_comm('ROUTE:SCAN?')) 55 | MUX.select_measurement_function('VOLTAGE') 56 | print(MUX.read()) 57 | -------------------------------------------------------------------------------- /PyExpLabSys/drivers/NI_USB_TC01.py: -------------------------------------------------------------------------------- 1 | import logging 2 | from time import sleep, time 3 | 4 | import nidaqmx 5 | from nidaqmx.constants import ThermocoupleType, TemperatureUnits 6 | 7 | # Setup logging 8 | LOG = logging.getLogger(__name__) 9 | LOG.addHandler(logging.NullHandler()) 10 | 11 | class ni_usb_tc01: 12 | """Driver for the NI USB-TC01 Thermocouple Device.""" 13 | 14 | def __init__(self, device_name="Dev1/ai0", thermocouple_type=ThermocoupleType.K): 15 | self.device_name = device_name 16 | self.thermocouple_type = thermocouple_type 17 | self.task = None 18 | 19 | def open(self): 20 | """Open the device and configure the thermocouple channel.""" 21 | self.task = nidaqmx.Task() 22 | self.task.ai_channels.add_ai_thrmcpl_chan( 23 | self.device_name, 24 | thermocouple_type=self.thermocouple_type, 25 | units=TemperatureUnits.DEG_C 26 | ) 27 | LOG.info(f"Opened NI USB-TC01 on {self.device_name} with thermocouple type {self.thermocouple_type}") 28 | 29 | def read_temperature(self): 30 | """Read the temperature from the thermocouple.""" 31 | if self.task is None: 32 | raise RuntimeError("Device not opened. Call open() before reading temperature.") 33 | 34 | temperature = self.task.read() 35 | LOG.info(f"Read temperature: {temperature:.2f} °C") 36 | return temperature 37 | 38 | def close(self): 39 | """Close the device.""" 40 | if self.task is not None: 41 | self.task.close() 42 | self.task = None 43 | LOG.info("Closed NI USB-TC01 device.") 44 | 45 | 46 | if __name__ == "__main__": 47 | tc01 = ni_usb_tc01(device_name="Dev2/ai0", thermocouple_type=ThermocoupleType.K) 48 | tc01.open() 49 | try: 50 | temp = tc01.read_temperature() 51 | print(f"Temperature: {temp:.2f} °C") 52 | except Exception as e: 53 | LOG.error(f"Error reading temperature: {e}") 54 | tc01.close() 55 | -------------------------------------------------------------------------------- /archive/multimeter/demo/plots/simple_qwt/plottest.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import time 3 | import random 4 | 5 | import numpy as np 6 | from PyQt4 import Qt, QtGui, QtCore 7 | 8 | from PyExpLabSys.common.plotters import DataPlotter 9 | 10 | 11 | class TestApp(QtGui.QWidget): 12 | """Test Qt application""" 13 | 14 | def __init__(self): 15 | super(TestApp, self).__init__() 16 | # Form plotnames 17 | self.plots_l = ['signal1', 'signal2'] 18 | self.plots_r = ['aux_signal1'] 19 | 20 | self.plotter = DataPlotter( 21 | self.plots_l, right_plotlist=self.plots_r, parent=self, 22 | left_log=True, title='Awesome plots', 23 | yaxis_left_label='Log sine, cos', yaxis_right_label='Noisy line', 24 | xaxis_label='Time since start [s]', 25 | legend='right', left_thickness=[2, 8], right_thickness=6, 26 | left_colors=['firebrick', 'darkolivegreen'], 27 | right_colors=['darksalmon']) 28 | 29 | hbox = QtGui.QHBoxLayout() 30 | hbox.addWidget(self.plotter.plot) 31 | self.setLayout(hbox) 32 | self.setGeometry(5, 5, 500, 500) 33 | 34 | self.start = time.time() 35 | QtCore.QTimer.singleShot(10, self.main) 36 | 37 | def main(self): 38 | """Simulate gathering one set of points and adding them to plot""" 39 | elapsed = time.time() - self.start 40 | value = (np.sin(elapsed) + 1.1) * 1E-9 41 | self.plotter.add_point('signal1', (elapsed, value)) 42 | value = (np.cos(elapsed) + 1.1) * 1E-8 43 | self.plotter.add_point('signal2', (elapsed, value)) 44 | value = elapsed + random.random() 45 | self.plotter.add_point('aux_signal1', (elapsed, value)) 46 | 47 | QtCore.QTimer.singleShot(100, self.main) 48 | 49 | 50 | def main(): 51 | """Main method""" 52 | app = Qt.QApplication(sys.argv) 53 | testapp = TestApp() 54 | testapp.show() 55 | sys.exit(app.exec_()) 56 | 57 | 58 | if __name__ == '__main__': 59 | main() 60 | -------------------------------------------------------------------------------- /PyExpLabSys/auxiliary/pid.py: -------------------------------------------------------------------------------- 1 | """ PID calculator """ 2 | import logging 3 | from PyExpLabSys.common.supported_versions import python2_and_3 4 | 5 | # Configure logger as library logger and set supported python versions 6 | LOGGER = logging.getLogger(__name__) 7 | LOGGER.addHandler(logging.NullHandler()) 8 | python2_and_3(__file__) 9 | 10 | 11 | class PID(object): 12 | """ PID calculator """ 13 | 14 | def __init__(self, pid_p=0.15, pid_i=0.0025, pid_d=0, p_max=54, p_min=0): 15 | LOGGER.debug('Starting PID') 16 | self.setpoint = -9999 17 | self.pid_p = pid_p 18 | self.pid_i = pid_i 19 | self.pid_d = pid_d 20 | self.p_max = p_max 21 | self.p_min = p_min 22 | self.error = 0 23 | self.int_err = 0 24 | 25 | def integration_contribution(self): 26 | """ Return the contribution from the i-term """ 27 | return self.pid_i * self.int_err 28 | 29 | def proportional_contribution(self): 30 | """ Return the contribution from the p-term """ 31 | return self.pid_p * self.error 32 | 33 | def integrated_error(self): 34 | """ Return the currently integrated error """ 35 | return self.int_err 36 | 37 | def reset_int_error(self): 38 | """ Reset the integration error """ 39 | self.int_err = 0 40 | 41 | def update_setpoint(self, setpoint): 42 | """ Update the setpoint """ 43 | LOGGER.debug('Setting setpoint to: ' + str(setpoint)) 44 | self.setpoint = setpoint 45 | return setpoint 46 | 47 | def wanted_power(self, value): 48 | """ Return the best estimate for wanted power """ 49 | self.error = self.setpoint - value 50 | power = self.pid_p * self.error 51 | power = power + self.pid_i * self.int_err 52 | if (power < self.p_max) and (power > self.p_min): 53 | self.int_err += self.error 54 | elif power > self.p_max: 55 | power = self.p_max 56 | elif power < self.p_min: 57 | power = self.p_min 58 | return power 59 | -------------------------------------------------------------------------------- /PyExpLabSys/drivers/NGC2D.py: -------------------------------------------------------------------------------- 1 | import serial 2 | import time 3 | 4 | 5 | class NGC2D_comm: 6 | def __init__(self, device): 7 | self.f = serial.Serial( 8 | port=device, 9 | # port='/dev/ttyUSB1', 10 | baudrate=9600, 11 | parity=serial.PARITY_NONE, 12 | stopbits=serial.STOPBITS_ONE, 13 | bytesize=serial.EIGHTBITS, 14 | xonxoff=False, 15 | ) 16 | time.sleep(1) 17 | 18 | def comm(self, command): 19 | if command == "Poll": 20 | comm = "*P0" 21 | elif command == "Control": 22 | comm = "*C0" 23 | elif command == "ResetError": 24 | comm = "*E0" 25 | elif command == "Status": 26 | comm = "*S0" 27 | else: 28 | print("Unknown Command") 29 | return None # Remember to test for None return value 30 | 31 | self.f.write(comm) 32 | time.sleep(1) 33 | # number = self.f.inWaiting() 34 | complete_string = self.f.read(self.f.inWaiting()) 35 | # self.f.close() 36 | # print complete_string 37 | return complete_string 38 | 39 | def ReadPressure(self): 40 | pressure_string = self.comm('Status') 41 | pressure = pressure_string.split("\r\n")[0][9:16] 42 | try: 43 | if pressure[0] == " ": 44 | print("Pressure Gauge is Off") 45 | return -1 46 | except: 47 | print(pressure) 48 | # print pressure 49 | return pressure 50 | 51 | def ReadPressureUnit(self): 52 | unit_string = self.comm("Status") 53 | unit_string = unit_string.split("\r\n")[0][17] 54 | if unit_string == "T": 55 | unit = "Torr" 56 | elif unit_string == "P": 57 | unit = "Pa" 58 | elif unit_string == "M": 59 | unit = "mBar" 60 | # print unit 61 | return unit 62 | 63 | 64 | if __name__ == '__main__': 65 | NG = NGC2D_comm('/dev/ttyUSB1') 66 | print("Pressure: " + str(NG.ReadPressure())) 67 | -------------------------------------------------------------------------------- /PyExpLabSys/thirdparty/cached_property.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | """Copy of the cached property project from 4 | https://github.com/pydanny/cached-property 5 | 6 | There is a copy in PyExpLabSys only to not introduce a dependency for such a 7 | small functionality 8 | 9 | All credits goes to the original author 10 | """ 11 | 12 | __author__ = 'Daniel Greenfeld' 13 | __email__ = 'pydanny@gmail.com' 14 | __version__ = '0.1.5' 15 | __license__ = 'BSD' 16 | 17 | import threading 18 | 19 | 20 | # pylint: disable=invalid-name,too-few-public-methods 21 | class cached_property(object): 22 | """A property that is only computed once per instance and then replaces 23 | itself with an ordinary attribute. Deleting the attribute resets the 24 | property. 25 | 26 | Source: https://github.com/bottlepy/bottle/commit/ 27 | fa7733e075da0d790d809aa3d2f53071897e6f76 28 | """ 29 | 30 | def __init__(self, func): 31 | self.__doc__ = getattr(func, '__doc__') 32 | self.func = func 33 | 34 | def __get__(self, obj, cls): 35 | if obj is None: 36 | return self 37 | value = obj.__dict__[self.func.__name__] = self.func(obj) 38 | return value 39 | 40 | 41 | # pylint: disable=invalid-name,too-few-public-methods 42 | class threaded_cached_property(cached_property): 43 | """A cached_property version for use in environments where multiple 44 | threads might concurrently try to access the property. 45 | """ 46 | 47 | def __init__(self, func): 48 | super(threaded_cached_property, self).__init__(func) 49 | self.lock = threading.RLock() 50 | 51 | def __get__(self, obj, cls): 52 | with self.lock: 53 | # Double check if the value was computed before the lock was 54 | # acquired. 55 | prop_name = self.func.__name__ 56 | if prop_name in obj.__dict__: 57 | return obj.__dict__[prop_name] 58 | 59 | # If not, do the calculation and release the lock. 60 | return super(threaded_cached_property, self).__get__(obj, cls) 61 | -------------------------------------------------------------------------------- /PyExpLabSys/drivers/omron_d6fph.py: -------------------------------------------------------------------------------- 1 | """Hint for implementation found at http://forum.arduino.cc/index.php?topic=285116.0 """ 2 | 3 | import smbus 4 | import time 5 | from PyExpLabSys.common.supported_versions import python2_and_3 6 | 7 | python2_and_3(__file__) 8 | 9 | 10 | class OmronD6fph(object): 11 | """Class for reading pressure and temperature from Omron D6F-PH series 12 | Ranging not implemented for all models""" 13 | 14 | def __init__(self): 15 | self.bus = smbus.SMBus(1) 16 | self.device_address = 0x6C 17 | self.full_range = 1000.0 18 | self.init_device() 19 | 20 | def init_device(self): 21 | """ Sensor needs to be initiated after power up """ 22 | init_command = [0x0B, 0x00] 23 | self.bus.write_i2c_block_data(self.device_address, 0, init_command) 24 | 25 | def read_value(self, command): 26 | """ Read a value from the sensor """ 27 | mcu_mode_command = [0xD0, 0x40, 0x18, 0x06] 28 | self.bus.write_i2c_block_data(self.device_address, 0, mcu_mode_command) 29 | time.sleep(0.033) 30 | self.bus.write_i2c_block_data(self.device_address, 0, command) 31 | self.bus.write_byte(self.device_address, 0x07) 32 | high = self.bus.read_byte(self.device_address) 33 | low = self.bus.read_byte(self.device_address) 34 | value = int(hex(high) + hex(low)[2:].zfill(2), 16) 35 | return value 36 | 37 | def read_pressure(self): 38 | """ Read the pressure value """ 39 | value = self.read_value([0xD0, 0x51, 0x2C]) 40 | # TODO: Implement range calculation for all sensor models 41 | pressure = (value - 1024) * self.full_range / 60000 - self.full_range / 2 42 | return pressure 43 | 44 | def read_temperature(self): 45 | """ Read the temperature value """ 46 | value = self.read_value([0xD0, 0x61, 0x2C]) 47 | temperature = (value - 10214) / 37.39 48 | return temperature 49 | 50 | 51 | if __name__ == '__main__': 52 | OMRON = OmronD6fph() 53 | print(OMRON.read_pressure()) 54 | print(OMRON.read_temperature()) 55 | -------------------------------------------------------------------------------- /PyExpLabSys/common/chiller_reader.py: -------------------------------------------------------------------------------- 1 | """ Module for monitoring a polyscience chiller """ 2 | from __future__ import print_function 3 | import threading 4 | import time 5 | import PyExpLabSys.drivers.polyscience_4100 as polyscience_4100 6 | from PyExpLabSys.common.supported_versions import python2_and_3 7 | 8 | python2_and_3(__file__) 9 | 10 | 11 | class ChillerReader(threading.Thread): 12 | """ Reader class that will monitor a polyscience chiller """ 13 | 14 | def __init__(self, serial_port): 15 | threading.Thread.__init__(self) 16 | self.chiller = polyscience_4100.Polyscience4100(serial_port) 17 | self.status = {} 18 | self.status['temp'] = -9999 19 | self.status['flow'] = -9999 20 | self.status['temp_amb'] = -9999 21 | self.status['pressure'] = -9999 22 | self.status['setpoint'] = -9999 23 | self.status['running'] = 'Off' 24 | self.ttl = 100 25 | self.quit = False 26 | self.daemon = True 27 | 28 | def value(self, channel): 29 | """ Return the value of the reader """ 30 | self.ttl = self.ttl - 1 31 | if self.ttl < 0: 32 | self.quit = True 33 | if channel == 0: 34 | return_val = self.status['temp'] 35 | if channel == 1: 36 | return_val = self.status['flow'] 37 | if channel == 2: 38 | return_val = self.status['temp_amb'] 39 | if channel == 3: 40 | return_val = self.status['pressure'] 41 | if channel == 4: 42 | return_val = self.status['setpoint'] 43 | return return_val 44 | 45 | def run(self): 46 | while not self.quit: 47 | print(self.ttl) 48 | self.status['temp'] = self.chiller.read_temperature() 49 | self.status['flow'] = self.chiller.read_flow_rate() 50 | self.status['temp_amb'] = self.chiller.read_ambient_temperature() 51 | self.status['pressure'] = self.chiller.read_pressure() 52 | self.status['setpoint'] = self.chiller.read_setpoint() 53 | self.status['running'] = self.chiller.read_status() 54 | self.ttl = 100 55 | time.sleep(1) 56 | -------------------------------------------------------------------------------- /archive/multimeter/demo/plots/qtseigner_qwt/simple_plot.ui: -------------------------------------------------------------------------------- 1 | 2 | 3 | PlotTest 4 | 5 | 6 | 7 | 0 8 | 0 9 | 965 10 | 585 11 | 12 | 13 | 14 | Form 15 | 16 | 17 | 18 | 19 | 0 20 | 10 21 | 961 22 | 571 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | Start 32 | 33 | 34 | 35 | 36 | 37 | 38 | Stop 39 | 40 | 41 | 42 | 43 | 44 | 45 | -18 46 | 47 | 48 | 18 49 | 50 | 51 | -8 52 | 53 | 54 | 55 | 56 | 57 | 58 | 1E-8 59 | 60 | 61 | 62 | 63 | 64 | 65 | Quit 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /archive/cinfkiosk/test_websocket.py: -------------------------------------------------------------------------------- 1 | 2 | #import sys 3 | import json 4 | import threading 5 | 6 | 7 | #from twisted.python import log 8 | from twisted.internet import reactor 9 | #log.startLogging(sys.stdout) 10 | 11 | from autobahn.twisted.websocket import (WebSocketClientProtocol, \ 12 | WebSocketClientFactory, connectWS) 13 | 14 | 15 | 16 | class MyClientProtocol(WebSocketClientProtocol): 17 | 18 | def onConnect(self, response): 19 | print("### Server connected: {0}".format(response.peer)) 20 | 21 | def onOpen(self): 22 | subscribe = { 23 | u'action': u'subscribe', 24 | u'subscriptions': [u'rasppi71:thetaprobe_main_chamber_pressure', 25 | u'rasppi25:thetaprobe_pressure_loadlock', 26 | u'rasppi71:thetaprobe_load_lock_roughing_pressure', 27 | u'rasppi71:thetaprobe_main_chamber_temperature'] 28 | } 29 | self.sendMessage(json.dumps(subscribe).encode('ascii')) 30 | print("### WebSocket connection open.") 31 | 32 | def onMessage(self, payload, isBinary): 33 | if isBinary: 34 | print("### Binary message received: {0} bytes".format(len(payload))) 35 | else: 36 | print("### Text message received: {0}".format(payload.decode('utf8'))) 37 | 38 | def onClose(self, wasClean, code, reason): 39 | print("### WebSocket connection closed: {0}".format(reason)) 40 | 41 | 42 | if __name__ == '__main__': 43 | 44 | factory = WebSocketClientFactory(url="wss://cinf-wsserver.fysik.dtu.dk:9002") 45 | factory.protocol = MyClientProtocol 46 | 47 | from twisted.internet import reactor, ssl 48 | if factory.isSecure: 49 | contextFactory = ssl.ClientContextFactory() 50 | else: 51 | contextFactory = None 52 | 53 | connectWS(factory, contextFactory) 54 | 55 | #reactor.connectTCP("https://cinf-wsserver.fysik.dtu.dk", 9002, factory) 56 | 57 | from threading import Thread 58 | 59 | Thread(target=reactor.run, args=(False,)).start() 60 | 61 | try: 62 | time.sleep(10000000) 63 | except KeyboardInterrupt: 64 | reactor.stop() 65 | 66 | #reactor.run() 67 | print("HH") 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /archive/cinfkiosk/test_pyqtgraph.py: -------------------------------------------------------------------------------- 1 | from __future__ import division, print_function 2 | 3 | import time 4 | import sys 5 | import numpy as np 6 | 7 | from pyqtgraph import PlotWidget, AxisItem 8 | 9 | from PyQt4 import QtGui, QtCore 10 | 11 | YS = 10 12 | POINTS = 10000 13 | FREQ = 10 14 | 15 | print("Points:", POINTS) 16 | print("Freq:", FREQ) 17 | print("Points per s:", POINTS * FREQ) 18 | 19 | 20 | x = np.linspace(0, 6.28, POINTS) 21 | ys = [np.sin(x + 6.28/YS*n) for n in range(YS)] 22 | 23 | 24 | class TimeAxisItem(AxisItem): 25 | def __init__(self, *args, **kwargs): 26 | super(TimeAxisItem, self).__init__(*args, **kwargs) 27 | 28 | def tickStrings(self, values, scale, spacing): 29 | """Return HH:mm:ss strings from unixtime values""" 30 | #out = [] 31 | #for value in values: 32 | # t = QDateTime() 33 | # t.setTime_t(value) 34 | # out.append(t.toString('HH:mm:ss')) 35 | return [str(value) for value in values] 36 | 37 | 38 | class Example(QtGui.QWidget): 39 | 40 | def __init__(self): 41 | super(Example, self).__init__() 42 | self.initUI() 43 | 44 | 45 | self.current_y = 0 46 | 47 | self.timer = QtCore.QTimer() 48 | self.timer.timeout.connect(self.update_plot) 49 | self.timer.setInterval(1000/FREQ) 50 | self.timer.start() 51 | 52 | 53 | def initUI(self): 54 | 55 | self.setGeometry(300, 300, 1000, 1000) 56 | self.setWindowTitle('Icon') 57 | self.setWindowIcon(QtGui.QIcon('web.png')) 58 | 59 | 60 | 61 | self.plot = PlotWidget(self, axisItems={'bottom': TimeAxisItem(orientation='bottom')}) 62 | self.plot.resize(900, 900) 63 | self.curve = self.plot.plot(x, ys[0]) 64 | #self.curve.attach(self.plot) 65 | self.show() 66 | 67 | def update_plot(self): 68 | self.curve.setData(x, ys[self.current_y]) 69 | self.current_y = (self.current_y + 1) % YS 70 | #print(POINTS * FREQ, "points per second") 71 | 72 | 73 | def main(): 74 | 75 | app = QtGui.QApplication(sys.argv) 76 | ex = Example() 77 | sys.exit(app.exec_()) 78 | 79 | 80 | if __name__ == '__main__': 81 | main() 82 | -------------------------------------------------------------------------------- /PyExpLabSys/auxiliary/rtd_calculator.py: -------------------------------------------------------------------------------- 1 | """ Calculates temperatures for an RTD """ 2 | from __future__ import print_function 3 | from PyExpLabSys.common.supported_versions import python2_and_3 4 | 5 | python2_and_3(__file__) 6 | 7 | 8 | class RtdCalculator(object): 9 | """Calculates temperatures for an RTD 10 | The class calculates the RTD temperature at 0C and then 11 | solves this equation for T, with T0 being 0: 12 | R = R0(1 + A(T-T0) + B(T-T0)^2) => 13 | R = R0(1 + AT + BT**2) => 14 | R0BT**2 + R0AT + R0-R = 0 15 | """ 16 | 17 | def __init__(self, calib_temperature, calib_resistance, material='Pt'): 18 | if material == 'Pt': 19 | self.coeff_a = 3.9803e-3 20 | self.coeff_b = -5.775e-7 21 | if material == 'Mo': 22 | self.coeff_a = 4.579e-3 23 | self.coeff_b = 0 # Not correct 24 | if material == 'W': 25 | self.coeff_a = 4.403e-3 26 | self.coeff_b = 0 # Not correct 27 | 28 | self.calib_temperature = calib_temperature 29 | self.calib_resistance = calib_resistance 30 | self.resistance_at_0 = calib_resistance / ( 31 | 1 + self.coeff_a * calib_temperature + self.coeff_b * calib_temperature ** 2 32 | ) 33 | 34 | def find_r(self, temperature): 35 | """ Find the resistance for a given temperature """ 36 | resistance = self.resistance_at_0 * ( 37 | 1 + self.coeff_a * temperature + self.coeff_b * temperature ** 2 38 | ) 39 | return resistance 40 | 41 | def find_temperature(self, resistance): 42 | """ Find the current temperature for given resistance """ 43 | A = self.coeff_a # pylint: disable=invalid-name 44 | B = self.coeff_b # pylint: disable=invalid-name 45 | R = resistance # pylint: disable=invalid-name 46 | R0 = self.resistance_at_0 # pylint: disable=invalid-name 47 | 48 | if B > 0: 49 | temperature = ( 50 | -1 * R0 * A + ((R0 * A) ** 2 - 4 * R0 * B * (R0 - R)) ** (0.5) 51 | ) / (2 * R0 * B) 52 | else: 53 | temperature = (R / R0 - 1) / A 54 | return temperature 55 | 56 | 57 | if __name__ == '__main__': 58 | RTD = RtdCalculator(150, 157) 59 | print(RTD.resistance_at_0) 60 | print(RTD.find_temperature(100)) 61 | -------------------------------------------------------------------------------- /PyExpLabSys/drivers/nxp_pcf8593.py: -------------------------------------------------------------------------------- 1 | import time 2 | import smbus 3 | 4 | 5 | class NXP_PCF8593(object): 6 | def __init__(self, i2c_address=0x51): 7 | self.bus = smbus.SMBus(1) 8 | self.device_address = i2c_address 9 | self.set_status() 10 | time.sleep(1) 11 | 12 | def set_status(self): 13 | control_and_status = self.bus.read_byte_data(self.device_address, 0x00) 14 | # print(control_and_status, bin(control_and_status)[2:].zfill(8)) 15 | 16 | enable_counter = 0b00100100 17 | self.bus.write_byte_data(self.device_address, 0x00, enable_counter) 18 | 19 | alarm_status = self.bus.read_byte_data(self.device_address, 0x08) 20 | # print(alarm_status, bin(alarm_status)[2:].zfill(8)) 21 | wanted_alarm = 0b00000010 22 | self.bus.write_byte_data(self.device_address, 0x08, enable_counter) 23 | 24 | def read_counter(self): 25 | data = self.bus.read_i2c_block_data(self.device_address, 0x01, 3) 26 | # print(data) 27 | # print( 28 | # hex(data[2])[2:].zfill(2), 29 | # hex(data[1])[2:].zfill(2), 30 | # hex(data[0])[2:].zfill(2) 31 | # ) 32 | try: 33 | low_digit = int(hex(data[0])[2:]) 34 | except ValueError: 35 | low_digit = 0 36 | try: 37 | middle_digit = int(hex(data[1])[2:]) 38 | except ValueError: 39 | middle_digit = 0 40 | try: 41 | high_digit = int(hex(data[2])[2:]) 42 | except ValueError: 43 | high_digit = 0 44 | count = high_digit * 10 ** 4 + middle_digit * 10 ** 2 + low_digit 45 | return count 46 | 47 | 48 | if __name__ == '__main__': 49 | pcf = NXP_PCF8593() 50 | time.sleep(1) 51 | 52 | wait_time = 2 53 | first_counter = pcf.read_counter() 54 | 55 | for i in range(0, 10): 56 | print() 57 | first_counter = pcf.read_counter() 58 | print('First count is: {}'.format(first_counter)) 59 | time.sleep(wait_time) 60 | second_counter = pcf.read_counter() 61 | print('Second count is: {}'.format(second_counter)) 62 | freq = (second_counter - first_counter) / wait_time 63 | print('Frequency is: {}'.format(freq)) 64 | print('Flow if this is an FT-210: {:.3f}mL/min'.format(60 * freq / 22)) 65 | -------------------------------------------------------------------------------- /PyExpLabSys/drivers/mks_925_pirani.py: -------------------------------------------------------------------------------- 1 | """ Driver for MKS 925 micro pirani """ 2 | from __future__ import print_function 3 | import time 4 | import logging 5 | import serial 6 | from PyExpLabSys.common.supported_versions import python2_and_3 7 | 8 | # Configure logger as library logger and set supported python versions 9 | LOGGER = logging.getLogger(__name__) 10 | LOGGER.addHandler(logging.NullHandler()) 11 | python2_and_3(__file__) 12 | 13 | 14 | class Mks925(object): 15 | """ Driver for MKS 925 micro pirani """ 16 | 17 | def __init__(self, port): 18 | self.ser = serial.Serial(port, 9600, timeout=2) 19 | time.sleep(0.1) 20 | 21 | def comm(self, command): 22 | """ Implement communication protocol """ 23 | prestring = b'@254' 24 | endstring = b';FF' 25 | self.ser.write(prestring + command.encode('ascii') + endstring) 26 | time.sleep(0.3) 27 | return_string = self.ser.read(self.ser.inWaiting()).decode() 28 | return return_string 29 | 30 | def read_pressure(self): 31 | """ Read the pressure from the device """ 32 | command = 'PR1?' 33 | error = 1 34 | while (error > 0) and (error < 10): 35 | signal = self.comm(command) 36 | signal = signal[7:-3] 37 | try: 38 | value = float(signal) 39 | error = 0 40 | except ValueError: 41 | error = error + 1 42 | value = -1.0 43 | return value 44 | 45 | def set_comm_speed(self, speed): 46 | """ Change the baud rate """ 47 | command = 'BR!' + str(speed) 48 | signal = self.comm(command) 49 | return signal 50 | 51 | def change_unit(self, unit): # STRING: TORR, PASCAL, MBAR 52 | """ Change the unit of the return value """ 53 | command = 'U!' + unit 54 | signal = self.comm(command) 55 | return signal 56 | 57 | def read_serial(self): 58 | """ Read the serial number of the device """ 59 | command = 'SN?' 60 | signal = self.comm(command) 61 | signal = signal[7:-3] 62 | return signal 63 | 64 | 65 | if __name__ == '__main__': 66 | MKS = Mks925('/dev/ttyUSB1') 67 | # print MKS.set_comm_speed(9600) 68 | print(MKS.change_unit('MBAR')) 69 | print("Pressure: " + str(MKS.read_pressure())) 70 | print('Serial: ' + str(MKS.read_serial())) 71 | -------------------------------------------------------------------------------- /PyExpLabSys/apps/bakeoutweb/templates/frontpage.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | The Bakeout Box Webapp 6 | 7 | 8 | 9 |
10 |

Bakeout Box Webapp

11 | 12 | 13 | 14 | {# table header #} 15 | 16 | 17 | {% for channel_number in range(1, 7) %} 18 | 19 | {% endfor %} 20 | 21 | {# table body #} 22 | {% for id_prefix, title, element in row_elements %} 23 | 24 | 25 | {% for channel_number in range(1, 7) %} 26 | 27 | {% endfor %} 28 | 29 | {% endfor %} 30 |
Channel {{ channel_number }}
{{ title }}{{ element.format(channel_number=channel_number)|safe }}
31 |

Using websocket: Unkonwn

32 |

Keymap

33 | 65 |
66 |
67 | 70 | 71 | 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /archive/nh3_setup/rasppi09/xgs600.py: -------------------------------------------------------------------------------- 1 | import serial 2 | import time 3 | 4 | class XGS600Driver(): 5 | 6 | def __init__(self): 7 | self.f = serial.Serial('/dev/ttyUSB0') 8 | 9 | def xgs_comm(self,command): 10 | comm = "#00" + command + "\r" 11 | 12 | self.f.write(comm) 13 | time.sleep(0.25) 14 | bytes = self.f.inWaiting() 15 | complete_string = self.f.read(bytes) 16 | complete_string = complete_string.replace('>','').replace('\r','') 17 | return(complete_string) 18 | 19 | 20 | def ReadAllPressures(self): 21 | pressure_string = self.xgs_comm("0F") 22 | #print pressure_string 23 | if len(pressure_string)>0: 24 | temp_pressure = pressure_string.replace(' ','').split(',') 25 | 26 | pressures = [] 27 | for press in temp_pressure: 28 | if press == 'OPEN': 29 | pressures.append(-1) 30 | else: 31 | try: 32 | pressures.append((float)(press)) 33 | except: 34 | pressures.append(-2) 35 | else: 36 | pressures = [-3] 37 | return(pressures) 38 | 39 | def ListAllGauges(self): 40 | gauge_string = self.xgs_comm("01") 41 | 42 | gauges = "" 43 | for i in range(0,len(gauge_string),2): 44 | gauge = gauge_string[i:i+2] 45 | if gauge == "10": 46 | gauges = gauges + str(i/2) + ": Hot Filament Gauge\n" 47 | if gauge == "FE": 48 | gauges = gauges + str(i/2) + ": Empty Slot\n" 49 | if gauge == "40": 50 | gauges = gauges + str(i/2) + ": Convection Board\n" 51 | if gauge == "3A": 52 | gauges = gauges + str(i/2) + ": Inverted Magnetron Board\n" 53 | 54 | 55 | return(gauges) 56 | 57 | 58 | def ReadSoftwareVersion(self): 59 | gauge_string = self.xgs_comm("05") 60 | return(gauge_string) 61 | 62 | 63 | def ReadPressureUnit(self): 64 | gauge_string = self.xgs_comm("13") 65 | unit = gauge_string.replace(' ','') 66 | if unit == "00": 67 | unit = "Torr" 68 | if unit == "01": 69 | unit = "mBar" 70 | if unit == "02": 71 | unit = "Pascal" 72 | return(unit) 73 | 74 | 75 | 76 | 77 | 78 | #print readAllPressures() 79 | 80 | #print listAllGauges() -------------------------------------------------------------------------------- /bootstrap/bootstrap_windows.bat: -------------------------------------------------------------------------------- 1 | 2 | :: This file will setup a Windows environment for use with PyExpLabSys 3 | 4 | @ECHO OFF 5 | if [%1]==[] GOTO usage 6 | GOTO :check_Permissions 7 | :parse 8 | if "%1"=="part1" GOTO path 9 | if "%1"=="path" GOTO path 10 | if "%1"=="git" GOTO git 11 | GOTO :eof 12 | 13 | :usage 14 | @ECHO. 15 | @ECHO Welcome to the bootstrap PyExpLabSys for windows script 16 | @ECHO. 17 | @ECHO NOTE: See the file README.bootstrap_windows for requirements for this 18 | @ECHO script. 19 | @ECHO. 20 | @ECHO Usage: bootstrap_windows.bat [SECTION] 21 | @ECHO. 22 | @ECHO Where SECTION indicates which part of the bootstrap script that should be 23 | @ECHO run. Possible value are listed below: 24 | @ECHO. 25 | @ECHO Section: 26 | @ECHO path Setup the PYTHONPATH to include PyExpLabSys 27 | @ECHO git Add common git aliasses and make it use color 28 | @ECHO. 29 | @ECHO part1 Both 'path' and 'git' 30 | GOTO :eof 31 | 32 | :check_Permissions 33 | ECHO. 34 | ECHO Administrative permissions required. Detecting permissions... 35 | 36 | net session >nul 2>&1 37 | if %errorLevel% == 0 ( 38 | ECHO Success: Administrative permissions confirmed. 39 | GOTO :parse 40 | ) else ( 41 | ECHO Failure: Current permissions inadequate. 42 | ECHO To open a command prompt as admin, search for cmd in Windows menu, 43 | ECHO press ctrl-shift-enter and confirm 44 | GOTO :eof 45 | ) 46 | 47 | 48 | :path 49 | @ECHO. 50 | @ECHO Add C:\git\PyExpLabSys to Python path by adding a new key subkey to: 51 | @ECHO HKEY_LOCAL_MACHINE\SOFTWARE\Python\PythonCore\2.7\PythonPath 52 | regedit /S PyExpLabSys.reg 53 | @ECHO ...Done 54 | if "%1"=="part1" GOTO git 55 | GOTO :eof 56 | 57 | :git 58 | @ECHO. 59 | @ECHO Setting up git with aliasses and color 60 | @ECHO Alias: ci "commit -v" 61 | "c:\Program Files\Git\bin\git.exe" config --global alias.ci "commit -v" 62 | @ECHO Alias: lol "log --graph --decorate --pretty=oneline --abbrev-commit" 63 | "c:\Program Files\Git\bin\git.exe" config --global alias.lol "log --graph --decorate --pretty=oneline --abbrev-commit" 64 | @ECHO Alias: ba "branch --all" 65 | "c:\Program Files\Git\bin\git.exe" config --global alias.ba "branch --all" 66 | @ECHO Alias: st "status" 67 | "c:\Program Files\Git\bin\git.exe" config --global alias.st "status" 68 | @ECHO Alias: cm "commit -m" 69 | "c:\Program Files\Git\bin\git.exe" config --global alias.cm "commit -m" 70 | @ECHO Color 71 | "c:\Program Files\Git\bin\git.exe" config --global color.ui true 72 | @ECHO ...DONE 73 | GOTO :eof 74 | -------------------------------------------------------------------------------- /PyExpLabSys/drivers/lascar.py: -------------------------------------------------------------------------------- 1 | """Driver for the EL-USB-RT temperature and humidity USB device from Lascar 2 | 3 | Calling read on the device will return either the temperature or the 4 | humidity. 5 | 6 | If the first byte is \x03 it is a temperature. The next 2 bytes is a unsigned 7 | integer which, is used to calculate the temperature as: 8 | 9 | temp = -100 * 0.1 * (unsigned_short) 10 | 11 | If the first byte is \x02 it is humidity. The next byte is an unsigned char, 12 | which is used to calculate the relative humidity as: 13 | 14 | humidity = 0.5 * (unsigned_char) 15 | 16 | """ 17 | 18 | from __future__ import division, print_function 19 | 20 | import struct 21 | 22 | try: 23 | import hid 24 | except (ImportError, AttributeError): 25 | print("Cannot import hid, can be install with pip") 26 | except SyntaxError: 27 | print("This module makes use of hid, which is only available for Python2") 28 | 29 | 30 | class ElUsbRt(object): 31 | """Driver for the EL-USB-RT device""" 32 | 33 | def __init__(self, device_path=None): 34 | if device_path is None: 35 | for dev in hid.enumerate(): 36 | if dev['product_string'] == 'EL USB RT': 37 | path = dev['path'] 38 | 39 | if path is None: 40 | message = 'No path give and unable to find it' 41 | raise ValueError(message) 42 | 43 | self.dev = hid.Device(path=path) 44 | 45 | def get_temperature_and_humidity(self): 46 | """Returns the temperature (in celcius, float) and relative humidity 47 | (in %, float) in a dict 48 | 49 | """ 50 | out = {} 51 | while len(out) < 2: 52 | string = self.dev.read(8) 53 | if string.startswith('\x03'): 54 | (frac,) = struct.unpack('H', string[1:]) 55 | out['temperature'] = -200 + frac * 0.1 56 | elif string.startswith('\x02'): 57 | (frac,) = struct.unpack('B', string[1:]) 58 | out['humidity'] = frac * 0.5 59 | return out 60 | 61 | def get_temperature(self): 62 | """Returns the temperature (in celcius, float)""" 63 | while True: 64 | string = self.dev.read(8) 65 | if string.startswith('\x03'): 66 | (frac,) = struct.unpack('H', string[1:]) 67 | return -200 + frac * 0.1 68 | 69 | 70 | if __name__ == '__main__': 71 | DEV = ElUsbRt() 72 | while True: 73 | print(DEV.get_temperature()) 74 | -------------------------------------------------------------------------------- /PyExpLabSys/drivers/stmicroelectronics_l3g4200d.py: -------------------------------------------------------------------------------- 1 | """ Driver for STMicroelectronics L3G4200D 3 axis gyroscope """ 2 | import time 3 | import os 4 | 5 | on_rtd = os.environ.get('READTHEDOCS', None) == 'True' 6 | if on_rtd: 7 | pass 8 | else: 9 | import smbus 10 | from PyExpLabSys.common.supported_versions import python2_and_3 11 | 12 | python2_and_3(__file__) 13 | 14 | 15 | class L3G4200D(object): 16 | """ Class for reading accelerometer output """ 17 | 18 | def __init__(self): 19 | self.bus = smbus.SMBus(1) 20 | self.device_address = 0x68 21 | # Set output data rate to 200, bandwidth cut-off to 12.5Hz 22 | self.bus.write_byte_data(self.device_address, 0x20, 0x4F) 23 | # Set full scale range, 0x00: 250dps, 0x30: 2000dps, block until lsb and msb are read 24 | self.full_scale = 250 # This should go in a self-consistent table... 25 | self.bus.write_byte_data(self.device_address, 0x23, 0x80) 26 | time.sleep(0.5) 27 | 28 | def who_am_i(self): 29 | """ Device identification """ 30 | id_byte = self.bus.read_byte_data(self.device_address, 0x0F) 31 | return id_byte 32 | 33 | def read_values(self): 34 | """ Read a value from the sensor """ 35 | byte1 = self.bus.read_byte_data(self.device_address, 0x28) 36 | byte2 = self.bus.read_byte_data(self.device_address, 0x29) 37 | 38 | x_value = byte2 * 256 + byte1 39 | if x_value > (2 ** 15) - 1: 40 | x_value = x_value - 2 ** 16 41 | x_value = 1.0 * x_value * self.full_scale / (2 ** 15) 42 | 43 | byte1 = self.bus.read_byte_data(self.device_address, 0x2A) 44 | byte2 = self.bus.read_byte_data(self.device_address, 0x2B) 45 | y_value = byte2 * 256 + byte1 46 | if y_value > (2 ** 15) - 1: 47 | y_value = y_value - 2 ** 16 48 | y_value = 1.0 * y_value * self.full_scale / (2 ** 15) 49 | 50 | byte1 = self.bus.read_byte_data(self.device_address, 0x2C) 51 | byte2 = self.bus.read_byte_data(self.device_address, 0x2D) 52 | z_value = byte2 * 256 + byte1 53 | if z_value > (2 ** 15) - 1: 54 | z_value = z_value - 2 ** 16 55 | z_value = 1.0 * z_value * self.full_scale / (2 ** 15) 56 | 57 | return (x_value, y_value, z_value) 58 | 59 | 60 | if __name__ == '__main__': 61 | L3G = L3G4200D() 62 | print(bin(L3G.who_am_i())) 63 | for i in range(0, 5): 64 | time.sleep(0.01) 65 | print(L3G.read_values()) 66 | -------------------------------------------------------------------------------- /PyExpLabSys/drivers/stmicroelectronics_ais328dq.py: -------------------------------------------------------------------------------- 1 | """ Driver for STMicroelectronics AIS328DQTR 3 axis accelerometer """ 2 | import os 3 | 4 | on_rtd = os.environ.get('READTHEDOCS', None) == 'True' 5 | if on_rtd: 6 | pass 7 | else: 8 | import smbus 9 | import time 10 | from PyExpLabSys.common.supported_versions import python2_and_3 11 | 12 | python2_and_3(__file__) 13 | 14 | 15 | class AIS328DQTR(object): 16 | """ Class for reading accelerometer output """ 17 | 18 | def __init__(self): 19 | self.bus = smbus.SMBus(1) 20 | self.device_address = 0x18 21 | # Set output data rate to 100, bandwidth low-pass cut-off to 74.5Hz 22 | print(hex(int('00101111', 2))) 23 | self.bus.write_byte_data(self.device_address, 0x20, 0x2F) 24 | # Set full scale range to 2g 25 | self.full_scale = 2 # This should go in a self-consistent table... 26 | self.bus.write_byte_data(self.device_address, 0x23, 0x80) 27 | time.sleep(0.5) 28 | 29 | def who_am_i(self): 30 | """ Device identification """ 31 | id_byte = self.bus.read_byte_data(self.device_address, 0x0F) 32 | return id_byte 33 | 34 | def read_values(self): 35 | """ Read a value from the sensor """ 36 | byte1 = self.bus.read_byte_data(self.device_address, 0x28) 37 | byte2 = self.bus.read_byte_data(self.device_address, 0x29) 38 | x_value = byte2 * 256 + byte1 39 | if x_value > (2 ** 15) - 1: 40 | x_value = x_value - (2 ** 16) 41 | x_value = 1.0 * x_value * self.full_scale / (2 ** 15) 42 | 43 | byte1 = self.bus.read_byte_data(self.device_address, 0x2A) 44 | byte2 = self.bus.read_byte_data(self.device_address, 0x2B) 45 | y_value = byte2 * 256 + byte1 46 | if y_value > (2 ** 15) - 1: 47 | y_value = y_value - (2 ** 16) 48 | y_value = 1.0 * y_value * self.full_scale / (2 ** 15) 49 | 50 | byte1 = self.bus.read_byte_data(self.device_address, 0x2C) 51 | byte2 = self.bus.read_byte_data(self.device_address, 0x2D) 52 | z_value = byte2 * 256 + byte1 53 | if z_value > (2 ** 15) - 1: 54 | z_value = z_value - (2 ** 16) 55 | z_value = 1.0 * z_value * self.full_scale / (2 ** 15) 56 | 57 | return (x_value, y_value, z_value) 58 | 59 | 60 | if __name__ == '__main__': 61 | AIS = AIS328DQTR() 62 | print(bin(AIS.who_am_i())) 63 | for i in range(0, 5): 64 | time.sleep(0.01) 65 | print(AIS.read_values()) 66 | -------------------------------------------------------------------------------- /PyExpLabSys/apps/transparency_measurement.py: -------------------------------------------------------------------------------- 1 | import time 2 | 3 | import numpy as np 4 | 5 | from PIL import Image 6 | from picamera import PiCamera 7 | 8 | # HEIGHT must be multiplum of 32 9 | # WIDTH must be multiplum of 16 10 | # HEIGHT = 1280 11 | # WIDTH = 720 12 | 13 | # HEIGHT = 3280 14 | # WIDTH = 2464 15 | 16 | HEIGHT = 1632 17 | WIDTH = 1232 18 | 19 | # HEIGHT = 800 20 | # WIDTH = 624 21 | 22 | # camera = PiCamera(resolution=(HEIGHT, WIDTH), framerate=30) 23 | 24 | camera = PiCamera( 25 | resolution=(HEIGHT, WIDTH), 26 | # framerate=Fraction(1, 6), 27 | framerate=5, 28 | sensor_mode=2, 29 | ) 30 | 31 | time.sleep(1) 32 | 33 | camera.exposure_mode = 'off' 34 | camera.shutter_speed = 10000 35 | camera.iso = 400 36 | camera.awb_mode = 'off' 37 | camera.awb_gains = (1.0, 1.0) 38 | # First image 39 | 40 | time.sleep(2) 41 | 42 | target = 0.1 43 | 44 | shutter = 1000 45 | for i in range(0, 10): 46 | intensities = [] 47 | camera.shutter_speed = shutter 48 | time.sleep(0.25) 49 | output = np.empty((WIDTH, HEIGHT, 3), dtype=np.uint8) 50 | # camera.capture(output, 'rgb', use_video_port=True) 51 | for i in range(0, 5): 52 | camera.capture(output, 'rgb', use_video_port=False) 53 | intensity = np.mean(output) / 256 54 | intensities.append(intensity) 55 | print(intensities) 56 | mean_int = np.mean(intensities) 57 | rel_int = target / mean_int 58 | shutter = int(shutter * rel_int) 59 | print('Rel Int: {:.3f}, Shutter: {}'.format(rel_int, shutter)) 60 | 61 | exit() 62 | 63 | 64 | t = time.time() 65 | output = np.empty((WIDTH, HEIGHT, 3), dtype=np.uint8) 66 | # camera.capture(output, 'rgb', use_video_port=True) 67 | camera.capture(output, 'rgb', use_video_port=False) 68 | exposure_time = time.time() - t 69 | print('Exposure time: {:.3f}'.format(exposure_time * 1000)) 70 | data = Image.fromarray(output) 71 | data.save('first.png') 72 | first_intensity = np.mean(output) / 256 73 | 74 | camera.shutter_speed = 10000 75 | 76 | print('Change sample') 77 | # time.sleep(2) 78 | 79 | 80 | # Second image 81 | output = np.empty((WIDTH, HEIGHT, 3), dtype=np.uint8) 82 | t = time.time() 83 | # camera.capture(output, 'rgb', use_video_port=True) 84 | camera.capture(output, 'rgb', use_video_port=False) 85 | exposure_time = time.time() - t 86 | print('Exposure time: {:.3f}ms'.format(exposure_time * 1000)) 87 | 88 | data = Image.fromarray(output) 89 | data.save('second.png') 90 | second_intensity = np.mean(output) / 256 91 | 92 | print( 93 | 'First: {}, Second: {}. Ratio: {}'.format( 94 | first_intensity, second_intensity, first_intensity / second_intensity 95 | ) 96 | ) 97 | -------------------------------------------------------------------------------- /doc/source/settings.rst: -------------------------------------------------------------------------------- 1 | .. _doc-settings: 2 | 3 | ******************* 4 | The settings module 5 | ******************* 6 | 7 | Settings for PyExpLabSys component are handled via the :class:`.Settings` class in the 8 | :mod:`settings` module. 9 | 10 | Getting started 11 | =============== 12 | 13 | To use the settings module instantiate a :class:`.Settings` object and access the settings 14 | as attributes:: 15 | 16 | >>> from PyExpLabSys.settings import Settings 17 | >>> settings = Settings() 18 | >>> settings.util_log_max_emails_per_period 19 | 5 20 | 21 | User settings can be modified at run time simply by assigning a new value to the 22 | attributes:: 23 | 24 | >>> settings.util_log_max_emails_per_period = 7 25 | >>> settings.util_log_max_emails_per_period 26 | 7 27 | 28 | Details 29 | ======= 30 | 31 | The settings are handled in two layers; **defaults** and **user settings**. 32 | 33 | The defaults are stored in the `PyExpLabSys/defaults.yaml 34 | `_ file. 35 | 36 | .. note:: 37 | It is not possible to write to a setting that does not have a default 38 | 39 | .. note:: 40 | In the defaults, a value of ``null`` is used to indicate a settings that must be 41 | overwritten by a user setting before any modules tries to use it. 42 | 43 | The user settings are stored in a user editable file. The path used is stored in the 44 | `settings.USERSETTINGS_PATH` variable. On Linux system the user settings path is 45 | ``~/.config.PyExpLabSys.user_settings.yaml``. 46 | 47 | .. note:: 48 | If the value is None, it means that your operating system is not yet supported 49 | by the settings module. This should be reported as an issue on Github. 50 | 51 | All :class:`.Settings` objects share the same settings, so changes made via one object 52 | will be used everywhere, in fact that is what makes it possible to modify settings at 53 | runtime (as shown above). **Do however note, that different modules reads the settings at 54 | different points in time. Some will read them when an object from that module is 55 | instantiated and others will read them at module import time**. That means, that for some 56 | modules it will be necessary to modify the settings before the rest of the PyExpLabSys 57 | modules is imported, in order to be able to modify them at runtime. At which point in time 58 | the settings are read should be stated in the module documentation. 59 | 60 | 61 | Auto-generated module documentation 62 | =================================== 63 | 64 | .. automodule:: PyExpLabSys.settings 65 | :members: 66 | :member-order: bysource 67 | :show-inheritance: 68 | -------------------------------------------------------------------------------- /PyExpLabSys/drivers/asair_aht20.py: -------------------------------------------------------------------------------- 1 | import smbus 2 | import time 3 | 4 | 5 | class AsairAht20(object): 6 | """Class for reading pressure and temperature from Omron D6F-PH series 7 | Ranging not implemented for all models""" 8 | 9 | def __init__(self): 10 | self.bus = smbus.SMBus(1) 11 | self.device_address = 0x38 12 | self.init_device() 13 | 14 | def _read_status(self): 15 | self.bus.write_byte(self.device_address, 0x71) 16 | response = self.bus.read_byte(self.device_address) 17 | # print('Status: {}, bin: {}'.format(response, bin(response))) 18 | return response 19 | 20 | def init_device(self): 21 | """ Sensor needs to be initiated after power up """ 22 | # Reset sensor: 23 | self.bus.write_byte(self.device_address, 0xBA) 24 | time.sleep(0.03) 25 | 26 | # Calibrate sensor: 27 | init_command = [0x08, 0x00] 28 | self.bus.write_i2c_block_data(self.device_address, 0xBE, init_command) 29 | 30 | calibrated = False 31 | while not calibrated: 32 | response = self._read_status() 33 | calibrated = response & 0b1000 34 | time.sleep(0.2) 35 | # Device is now calibrated and ready for operation 36 | return True 37 | 38 | def read_value(self): 39 | """ Read a value from the sensor """ 40 | read_command = [0x33, 0x00] 41 | self.bus.write_i2c_block_data(self.device_address, 0xAC, read_command) 42 | time.sleep(0.1) 43 | value = self.bus.read_i2c_block_data(self.device_address, 0x00, 6) 44 | # msg = 'State: {}, hex: {}, bin: {}' 45 | # print(msg.format(value[0], hex(value[0]), bin(value[0]))) 46 | # print('Humidity: {} {}'.format(value[1], value[2])) 47 | # print('Shared byte: {}'.format(value[3])) 48 | # print('Temperature: {}'.format(value[4] + value[5])) 49 | humidity_high = value[1] << 12 50 | humidity_mid = value[2] << 4 51 | humidity_low = value[3] >> 4 52 | humidity = humidity_high + humidity_mid + humidity_low 53 | humidity_cal = 100.0 * humidity / 2 ** 20 54 | 55 | temp_high = (value[3] & 0b00001111) << 16 56 | temp_mid = value[4] << 8 57 | temp_low = value[5] 58 | temperature = temp_high + temp_mid + temp_low 59 | temperature_cal = 200.0 * temperature / 2 ** 20 - 50 60 | return humidity_cal, temperature_cal 61 | 62 | 63 | if __name__ == '__main__': 64 | ASAIR = AsairAht20() 65 | humidity, temperature = ASAIR.read_value() 66 | print('Temperature: {:.2f}C, Humidity: {:.2f}%'.format(temperature, humidity)) 67 | -------------------------------------------------------------------------------- /PyExpLabSys/drivers/htc5500.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | 3 | """ Driver for the HTC 5500 Pro temperature controller """ 4 | 5 | import minimalmodbus 6 | from PyExpLabSys.common.supported_versions import python3_only 7 | 8 | python3_only(__file__) 9 | 10 | 11 | def hex_to_dec(hex_string): 12 | return int(hex_string, 16) 13 | 14 | 15 | class temperature_controller(object): 16 | def __init__(self, port, slave_adress=1): 17 | self.instrument = minimalmodbus.Instrument(port, slave_adress, mode='rtu') 18 | self.instrument.serial.baudrate = 9600 19 | self.instrument.serial.bytesize = 8 20 | self.instrument.serial.parity = minimalmodbus.serial.PARITY_EVEN 21 | self.instrument.serial.stopbits = 1 22 | self.instrument.serial.timeout = 1 # seconds 23 | 24 | def read_register(self, register): 25 | response = self.instrument.read_register(register) 26 | return response 27 | 28 | def write_register(self, register, setting): 29 | self.write_register(register, setting) 30 | 31 | def read_temperature(self): 32 | response = self.instrument.read_register(hex_to_dec('1000'), 1, signed=True) 33 | return response 34 | 35 | def read_set_temperature(self): 36 | response = self.instrument.read_register(hex_to_dec('1001'), 1, signed=True) 37 | return response 38 | 39 | def write_set_temperature(self, setting): 40 | # Resolution is 0.1 C 41 | self.instrument.write_register(hex_to_dec('1001'), setting, 1, signed=True) 42 | 43 | def read_control_method(self): 44 | response = self.instrument.read_register(hex_to_dec('1005')) 45 | return response 46 | 47 | def write_control_method(self, setting): 48 | # 0: PID, 1: ON/OFF, 2: manual tuning, 3: PID program control 49 | if setting == 0 or setting == 1 or setting == 2 or setting == 3: 50 | self.instrument.write_register(hex_to_dec('1005'), int(setting)) 51 | else: 52 | print('Wrong input') 53 | print('0: PID, 1: ON/OFF, 2: manual tuning, 3: PID grogram control') 54 | 55 | def read_run_stop(self): 56 | response = self.instrument.read_bit(hex_to_dec('0814')) 57 | return response 58 | 59 | def write_run_stop(self, setting): 60 | # 0: STOP, 1: RUN (default) 61 | if setting == 0 or setting == 1: 62 | self.instrument.write_bit(hex_to_dec('0814'), int(setting)) 63 | else: 64 | print('Wrong input') 65 | print('0: STOP, 1: RUN (default)') 66 | 67 | 68 | if __name__ == '__main__': 69 | port = '/dev/ttyUSB1' 70 | 71 | controller = temperature_controller(port, 1) 72 | -------------------------------------------------------------------------------- /tests/tmp/sockets/test_live_socket.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | """Test the LiveSocket """ 3 | 4 | import time 5 | import json 6 | import pytest 7 | import PyExpLabSys.common.sockets 8 | from PyExpLabSys.common.sockets import LiveSocket 9 | 10 | # Module variables 11 | HOST = '127.0.0.1' 12 | NAME = 'Usage statistics from giant moon laser' 13 | 14 | 15 | def send_and_resc(sock, command, port): 16 | """Helper UPD socket send and receive""" 17 | sock.sendto(command, (HOST, port)) 18 | data, _ = sock.recvfrom(1024) 19 | return data 20 | 21 | 22 | ### LiveSocket test 23 | def test_live_init(): 24 | codenames = ['name1', 'name2'] 25 | live_socket = LiveSocket(NAME, codenames, 1.0) 26 | live_socket.start() 27 | 28 | # Check that the port default is 8000 29 | assert(live_socket.port == 8000) 30 | 31 | data = PyExpLabSys.common.sockets.DATA 32 | # Check that data and last served are initialized and not with the same 33 | # objects 34 | for codename in codenames: 35 | assert(data[8000]['data'][codename] == 36 | data[8000]['last_served'][codename]) 37 | assert(not (data[8000]['data'][codename] is 38 | data[8000]['last_served'][codename])) 39 | 40 | # Check tha codenams and sane_interval is set correctly 41 | assert(data[8000]['codenames'] == codenames) 42 | assert(data[8000]['sane_interval'] - 1.0 < 1E-8) 43 | 44 | live_socket.stop() 45 | 46 | 47 | def test_live_multiple_variables(sock): 48 | codenames = ['name1', 'name2'] 49 | live_socket = LiveSocket(NAME, codenames, 1.0) 50 | live_socket.start() 51 | 52 | port = 8000 53 | 54 | # Test the 'codenames' command 55 | data = send_and_resc(sock, 'codenames', port) 56 | expected = ['name1', 'name2'] 57 | assert(json.loads(data) == expected) 58 | 59 | # Test the 'sane_interval' command 60 | data = send_and_resc(sock, 'sane_interval', port) 61 | assert(json.loads(data) - 1.0 < 1E-8) 62 | 63 | for n in range(3): 64 | now = time.time() 65 | live_socket.set_point('name1', (now, n)) 66 | live_socket.set_point('name2', (now, n+1)) 67 | 68 | # Test the 'data' command 69 | data = send_and_resc(sock, 'data', port) 70 | expected = [[now, n], [now, n+1]] 71 | assert(json.loads(data) == expected) 72 | 73 | time.sleep(0.1) 74 | 75 | live_socket.stop() 76 | 77 | 78 | def test_live_wrong_codename(): 79 | codenames = ['name1', 'name2'] 80 | live_socket = LiveSocket(NAME, codenames, 1.0) 81 | live_socket.start() 82 | 83 | # Test that trying to set an unknown name raises an exception 84 | with pytest.raises(ValueError): 85 | live_socket.set_point('bad name', (1, 2)) 86 | 87 | live_socket.stop() 88 | -------------------------------------------------------------------------------- /archive/nh3_setup/rasppi14/socket_server.py: -------------------------------------------------------------------------------- 1 | import sys 2 | import SocketServer 3 | #sys.path.append('../') 4 | 5 | #This specific raspberry pi handles temperature control 6 | class MyUDPHandler(SocketServer.BaseRequestHandler): 7 | 8 | def handle(self): 9 | global rosemount_calibrated 10 | global rosemount_raw 11 | global temperature_1 12 | global temperature_2 13 | global temperature_5 14 | 15 | recieved_data = self.request[0].strip() 16 | data = "test" 17 | socket = self.request[1] 18 | 19 | if recieved_data[0:24] == "set_rosemount_calibrated": 20 | val = float(recieved_data[24:].strip()) 21 | rosemount_calibrated = val 22 | print val 23 | data = "ok" 24 | 25 | if recieved_data[0:17] == "set_rosemount_raw": 26 | val = float(recieved_data[17:].strip()) 27 | rosemount_raw = val 28 | print val 29 | data = "ok" 30 | 31 | if recieved_data[0:17] == "set_temperature_1": 32 | val = float(recieved_data[17:].strip()) 33 | temperature_1 = val 34 | print val 35 | data = "ok" 36 | 37 | if recieved_data[0:17] == "set_temperature_5": 38 | val = float(recieved_data[17:].strip()) 39 | temperature_5 = val 40 | print val 41 | data = "ok" 42 | 43 | if recieved_data[0:17] == "set_temperature_2": 44 | val = float(recieved_data[17:].strip()) 45 | temperature_2 = val 46 | print val 47 | data = "ok" 48 | 49 | if recieved_data[0:25] == "read_rosemount_calibrated": 50 | print recieved_data[0:25] 51 | data = str(rosemount_calibrated) 52 | 53 | if recieved_data[0:18] == "read_rosemount_raw": 54 | print recieved_data[0:18] 55 | data = str(rosemount_raw) 56 | 57 | if recieved_data[0:18] == "read_temperature_1": 58 | print recieved_data[0:18] 59 | data = str(temperature_1) 60 | 61 | if recieved_data[0:18] == "read_temperature_2": 62 | print recieved_data[0:18] 63 | data = str(temperature_2) 64 | 65 | if recieved_data[0:18] == "read_temperature_5": 66 | print recieved_data[0:18] 67 | data = str(temperature_5) 68 | 69 | socket.sendto(data, self.client_address) 70 | 71 | if __name__ == "__main__": 72 | HOST, PORT = "130.225.86.183", 9999 #rasppi14 73 | 74 | rosemount_calibrated = -1 75 | rosemount_raw = -1 76 | temperature_1 = -1 77 | temperature_2 = -1 78 | temperature_5 = -1 79 | 80 | 81 | 82 | server = SocketServer.UDPServer((HOST, PORT), MyUDPHandler) 83 | server.serve_forever() 84 | -------------------------------------------------------------------------------- /PyExpLabSys/drivers/edwards_agc.py: -------------------------------------------------------------------------------- 1 | """ Driver and simple test case for Edwards Active Gauge Controler """ 2 | from __future__ import print_function 3 | import serial 4 | 5 | 6 | class EdwardsAGC(object): 7 | """Primitive driver for Edwards Active Gauge Controler 8 | Complete manual found at 9 | http://www.idealvac.com/files/brochures/Edwards_AGC_D386-52-880_IssueM.pdf""" 10 | 11 | def __init__(self, port='/dev/ttyUSB0'): 12 | self.serial = serial.Serial(port, baudrate=9600, timeout=0.5) 13 | 14 | def comm(self, command): 15 | """ Implements basic communication """ 16 | comm = command + "\r" 17 | for _ in range( 18 | 0, 10 19 | ): # Seems you no to query several times to get correct reply 20 | self.serial.write(comm.encode('ascii')) 21 | complete_string = self.serial.readline().decode() 22 | self.serial.write(comm.encode('ascii')) 23 | complete_string = self.serial.readline().decode() 24 | complete_string = complete_string.strip() 25 | return complete_string 26 | 27 | def gauge_type(self, gauge_number): 28 | """ Return the type of gauge """ 29 | types = { 30 | 0: 'Not Fitted', 31 | 1: '590 CM capacitance manometer', 32 | 15: 'Active strain gauge', 33 | 5: 'Pirani L low pressure', 34 | 20: 'Wide range gauge', 35 | } # Feel free to fill in.... 36 | 37 | type_number = int(self.comm('?GV ' + str(gauge_number))) 38 | gauge_type = types[type_number] 39 | return gauge_type 40 | 41 | def read_pressure(self, gauge_number): 42 | """ Read the pressure of a gauge """ 43 | pressure_string = self.comm('?GA ' + str(gauge_number)) 44 | pressure_value = float(pressure_string) 45 | return pressure_value 46 | 47 | def pressure_unit(self, gauge_number): 48 | """ Read the unit of a gauge """ 49 | units = {0: 'mbar', 1: 'torr'} 50 | unit_string = self.comm('?NU ' + str(gauge_number)) 51 | unit_number = int(unit_string) 52 | unit = units[unit_number] 53 | return unit 54 | 55 | def current_error(self): 56 | """ Read the current error code """ 57 | error_code = self.comm('?SY') 58 | return error_code 59 | 60 | def software_version(self): 61 | """ Return the software version of the controller """ 62 | return self.comm('?VE') 63 | 64 | 65 | if __name__ == '__main__': 66 | E_AGC = EdwardsAGC() 67 | print(E_AGC.gauge_type(4)) 68 | print(E_AGC.read_pressure(1)) 69 | print(E_AGC.read_pressure(2)) 70 | print(E_AGC.read_pressure(3)) 71 | print(E_AGC.read_pressure(4)) 72 | print(E_AGC.pressure_unit(1)) 73 | print(E_AGC.current_error()) 74 | -------------------------------------------------------------------------------- /bin/purpose: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import os 4 | import sys 5 | import textwrap 6 | from optparse import OptionParser 7 | 8 | 9 | def rasppi_key(key): 10 | """Returns zero padded raspberry pi numbers for sorting""" 11 | if key.startswith('rasppi'): 12 | return 'rasppi{:0>3}'.format(key.replace('rasppi', '')) 13 | return key 14 | 15 | 16 | def print_machine(machine, purpose, highlight=None): 17 | """Pretty prints a machine and its purpose""" 18 | if highlight is not None: 19 | purpose = purpose.replace(highlight, '\033[1m\033[35m{}\033[0m'.format(highlight)) 20 | machine = machine.replace(highlight, '\033[1m\033[35m{}\033[0m'.format(highlight)) 21 | 22 | # Add to the width of the machine padding, if there is a highligting in machine 23 | width = 23 24 | if '\033[1m\033[35m' in machine: 25 | width = 23 + 13 26 | 27 | wrapped = textwrap.wrap(purpose, 60) 28 | print('{{: <{}}}{{}}'.format(width).format(machine, wrapped[0])) 29 | for line in wrapped[1:]: 30 | print('{: <23}{}'.format('', line)) 31 | 32 | 33 | # Parse arguments 34 | usage = 'usage: purpose [optional search_term]\n\nIf a search term is '\ 35 | 'supplied, the search will be performed case insensitively, but the '\ 36 | 'search term will only be highted in the result if it is a case '\ 37 | 'sensitive match.' 38 | parser = OptionParser(usage=usage) 39 | options, args = parser.parse_args() 40 | 41 | 42 | if len(args) > 1: 43 | parser.print_help() 44 | sys.exit(0) 45 | 46 | 47 | machines_path = os.path.join(os.getenv("HOME"), 'PyExpLabSys', 'machines') 48 | machines = sorted(os.listdir(machines_path), key=rasppi_key) 49 | for machine in machines: 50 | purpose = os.path.join(machines_path, machine, 'PURPOSE') 51 | if os.path.isfile(purpose): 52 | with open(purpose) as file_: 53 | purpose = file_.read() 54 | 55 | # The purpose files have had two different formats, check for the new one 56 | purpose_lines = purpose.split('\n') 57 | # New format 58 | if len(purpose_lines) > 1 and\ 59 | purpose_lines[0].startswith('id:') and\ 60 | purpose_lines[1].startswith('purpose:'): 61 | # Strip the first two lines of id and shorthand purpose 62 | purpose = ''.join(purpose_lines[2:]).strip() 63 | if len(purpose) == 0: 64 | purpose = purpose_lines[1].replace('purpose:', '').strip() 65 | 66 | if len(args) == 0: 67 | print_machine(machine, purpose) 68 | else: 69 | search = args[0].lower() 70 | if search in purpose.lower() or search in machine: 71 | print_machine(machine, purpose, highlight=search) 72 | -------------------------------------------------------------------------------- /PyExpLabSys/common/supported_versions.py: -------------------------------------------------------------------------------- 1 | """Functions used to indicate and check for supported Python versions""" 2 | 3 | from __future__ import print_function 4 | import os 5 | import sys 6 | import warnings 7 | 8 | DOCRUN = os.environ.get('READTHEDOCS') == 'True' or 'sphinx' in sys.modules 9 | 10 | # We support 2.7 and above (which will never happen) or 3.3 and above 11 | PY2_MIN_VERSION = (2, 7) 12 | PY3_MIN_VERSION = (3, 3) 13 | 14 | # Check for valid versions 15 | VERSION = sys.version_info 16 | PY2_CHECK = VERSION.major == PY2_MIN_VERSION[0] and VERSION.minor >= PY2_MIN_VERSION[1] 17 | PY3_CHECK = VERSION.major == PY3_MIN_VERSION[0] and VERSION.minor >= PY3_MIN_VERSION[1] 18 | PY2_OR_3_CHECK = PY2_CHECK or PY3_CHECK 19 | 20 | # Warnings texts 21 | WARNING2OR3 = ( 22 | '\n' 23 | '========================================================================\n' 24 | '# The module: \'{filepath}\'\n' 25 | '# only supports Python {0}.{1} or above in the Python {0} series.\n' 26 | '# Your milages may vary!!!\n' 27 | '========================================================================\n' 28 | ) 29 | WARNING2AND3 = ( 30 | '\n' 31 | '========================================================================\n' 32 | '# The module: \'{filepath}\'\n' 33 | '# only supports Python {0}.{1} or above in the Python {0} series\n' 34 | '# OR Pythons {2}.{3} or above in the Python {2} series.\n' 35 | '# Your milages may vary!!!\n' 36 | '========================================================================\n' 37 | ) 38 | 39 | 40 | def python2_only(filepath): 41 | """Print out a warning if the Python version is not in the supported range of Python 2 42 | versions (>=2.7) 43 | """ 44 | if PY2_CHECK: 45 | return 46 | if not DOCRUN: 47 | warnings.warn(WARNING2OR3.format(*PY2_MIN_VERSION, filepath=filepath)) 48 | 49 | 50 | def python3_only(filepath): 51 | """Print out a warning if the Python version is not in the supported range of Python 3 52 | versions (>=3.3) 53 | """ 54 | if PY3_CHECK: 55 | return 56 | if not DOCRUN: 57 | warnings.warn(WARNING2OR3.format(*PY3_MIN_VERSION, filepath=filepath)) 58 | 59 | 60 | def python2_and_3(filepath): 61 | """Print out a warning if the Python version is not in the supported range of Python 2 or 3 62 | versions (>=2.7 or >=3.3) 63 | """ 64 | if PY2_OR_3_CHECK: 65 | return 66 | if not DOCRUN: 67 | warnings.warn( 68 | WARNING2AND3.format(*PY2_MIN_VERSION + PY3_MIN_VERSION, filepath=filepath) 69 | ) 70 | 71 | 72 | # Mark this file as being Python 2 and 3 compatible 73 | python2_and_3(__file__) 74 | 75 | 76 | if __name__ == '__main__': 77 | python2_only(__file__) 78 | python3_only(__file__) 79 | python2_and_3(__file__) 80 | --------------------------------------------------------------------------------