├── docs
├── release-notes.md
├── api
│ ├── types.md
│ ├── config.md
│ ├── enumerations.md
│ ├── connection.md
│ ├── interfaces
│ │ ├── gpib.md
│ │ ├── sdk.md
│ │ ├── vxi11.md
│ │ ├── hislip.md
│ │ ├── serial.md
│ │ ├── socket.md
│ │ ├── zeromq.md
│ │ ├── prologix.md
│ │ └── index.md
│ ├── backends
│ │ ├── nidaq.md
│ │ ├── pyvisa.md
│ │ └── index.md
│ └── exceptions.md
├── license.md
├── resources
│ ├── types.md
│ ├── multi_message_based.md
│ ├── aim-tti
│ │ └── mx_series.md
│ ├── mks
│ │ └── pr4000b.md
│ ├── nkt
│ │ └── nktpdll.md
│ ├── raicol
│ │ └── tec.md
│ ├── dataray
│ │ └── wincamd.md
│ ├── energetiq
│ │ └── eq99.md
│ ├── isotech
│ │ └── millik.md
│ ├── omega
│ │ └── ithx.md
│ ├── picotech
│ │ ├── pt104.md
│ │ ├── picoscope.md
│ │ └── types.md
│ ├── vaisala
│ │ ├── ptu300.md
│ │ └── ptb330.md
│ ├── cmi
│ │ └── sia3.md
│ ├── optosigma
│ │ └── shot702.md
│ ├── thorlabs
│ │ └── fwxx2c.md
│ ├── optronic_labs
│ │ ├── ol756.md
│ │ └── olxxa.md
│ ├── greisinger
│ │ └── gmh3000.md
│ ├── electron_dynamics
│ │ └── tc_series.md
│ ├── princeton_instruments
│ │ └── arc_instrument.md
│ ├── avantes
│ │ └── avaspec.md
│ └── index.md
├── assets
│ └── images
│ │ └── favicon.ico
├── schema
│ ├── any.md
│ ├── status.md
│ ├── firmware.md
│ ├── component.md
│ ├── financial.md
│ ├── measurand.md
│ ├── accessories.md
│ ├── adjustment.md
│ ├── alteration.md
│ ├── competency.md
│ ├── conditions.md
│ ├── maintenance.md
│ ├── planned_task.md
│ ├── deserialised.md
│ ├── completed_task.md
│ ├── quality_manual.md
│ ├── specifications.md
│ ├── performance_check.md
│ ├── acceptance_criteria.md
│ ├── capital_expenditure.md
│ ├── reference_materials.md
│ ├── specified_requirements.md
│ ├── report.md
│ ├── digital_report.md
│ ├── equipment.md
│ ├── index.md
│ └── file.md
├── javascripts
│ └── arithmatex.js
├── webapp.md
├── getting-started
│ └── index.md
└── index.md
├── packages
├── validate
│ ├── CHANGELOG.md
│ ├── src
│ │ └── msl
│ │ │ └── equipment_validate
│ │ │ └── py.typed
│ ├── tests
│ │ ├── registers
│ │ │ ├── do_not_modify_this_file.txt
│ │ │ ├── duplicate_id_a.xml
│ │ │ └── duplicate_id_b.xml
│ │ ├── conftest.py
│ │ └── test_osc8.py
│ ├── LICENSE.txt
│ └── README.md
└── resources
│ ├── src
│ └── msl
│ │ ├── equipment_resources
│ │ ├── py.typed
│ │ ├── aim_tti
│ │ │ └── __init__.py
│ │ ├── omega
│ │ │ └── __init__.py
│ │ ├── energetiq
│ │ │ └── __init__.py
│ │ ├── dataray
│ │ │ └── __init__.py
│ │ ├── raicol
│ │ │ ├── __init__.py
│ │ │ └── tec.py
│ │ ├── thorlabs
│ │ │ └── __init__.py
│ │ ├── greisinger
│ │ │ └── __init__.py
│ │ ├── vaisala
│ │ │ └── __init__.py
│ │ ├── cmi
│ │ │ └── __init__.py
│ │ ├── princeton_instruments
│ │ │ └── __init__.py
│ │ ├── picotech
│ │ │ └── __init__.py
│ │ ├── optronic_labs
│ │ │ └── __init__.py
│ │ ├── isotech
│ │ │ └── __init__.py
│ │ ├── mks
│ │ │ └── __init__.py
│ │ ├── optosigma
│ │ │ └── __init__.py
│ │ ├── electron_dynamics
│ │ │ └── __init__.py
│ │ ├── nkt
│ │ │ └── __init__.py
│ │ ├── __init__.py
│ │ ├── types.py
│ │ └── avantes
│ │ │ └── __init__.py
│ │ └── equipment
│ │ └── resources
│ │ └── thorlabs
│ │ ├── __init__.py
│ │ └── kinesis
│ │ ├── callbacks.py
│ │ ├── __init__.py
│ │ └── messages.py
│ ├── README.md
│ ├── examples
│ ├── picotech
│ │ ├── pt104_find.py
│ │ ├── ps5000a_find.py
│ │ ├── pt104.py
│ │ ├── ps5000a_block_mode.py
│ │ ├── ps5000a_data_ready_callback.py
│ │ ├── ps5000a_streaming_ready_callback.py
│ │ ├── ps5000a_AWG_builtin.py
│ │ └── ps5000a_block_ready_callback.py
│ ├── omega
│ │ └── ithx.py
│ ├── avantes
│ │ ├── find_devices.py
│ │ └── avaspec_callback.py
│ ├── raicol
│ │ └── tec_oven.py
│ ├── cmi
│ │ └── sia.py
│ ├── mks
│ │ └── pr4000b.py
│ ├── electron_dynamics
│ │ └── tc_series.py
│ ├── thorlabs
│ │ ├── fw212c.py
│ │ ├── kinesis_device_info.py
│ │ ├── mff101.py
│ │ ├── ksc101.py
│ │ ├── kdc101.py
│ │ ├── kst101.py
│ │ └── lts150.py
│ ├── vaisala
│ │ ├── ptb330.py
│ │ └── ptu300.py
│ ├── princeton_instruments
│ │ └── find_devices.py
│ ├── energetiq
│ │ └── eq99.py
│ ├── nkt
│ │ └── find_devices.py
│ ├── optronic_laboratories
│ │ ├── ol756.py
│ │ └── ol83a.py
│ ├── isotech
│ │ ├── milliskanner.py
│ │ └── millik.py
│ ├── aim_tti
│ │ └── mx100tp.py
│ ├── greisinger
│ │ └── gmh3710.py
│ ├── optosigma
│ │ └── shot702.py
│ └── dataray
│ │ └── wincamd.py
│ ├── LICENSE.txt
│ └── tests
│ └── test_greisinger_gmh3000.py
├── src
└── msl
│ └── equipment
│ ├── py.typed
│ ├── resources
│ └── __init__.py
│ ├── __about__.py
│ ├── interfaces
│ └── __init__.py
│ ├── record_types.py
│ ├── enumerations.py
│ └── __init__.py
├── tests
├── resources
│ ├── gpib.dll
│ ├── gpib.so
│ ├── gpib.dylib
│ ├── irradiance.xlsx
│ ├── mass
│ │ ├── not-a-register.xml
│ │ └── .hidden
│ │ │ └── bad.xml
│ ├── config.xml
│ ├── connections.xml
│ ├── gpib.h
│ ├── gpib.cpp
│ └── light
│ │ └── register.xml
├── test_nidaq.py
└── test_record_types.py
├── docs-old
├── _api
│ ├── msl.equipment.rst
│ ├── msl.equipment.utils.rst
│ ├── msl.equipment.vxi11.rst
│ ├── msl.equipment.config.rst
│ ├── msl.equipment.hislip.rst
│ ├── msl.equipment.factory.rst
│ ├── msl.equipment.database.rst
│ ├── msl.equipment.connection.rst
│ ├── msl.equipment.constants.rst
│ ├── msl.equipment.exceptions.rst
│ ├── msl.equipment.connection_demo.rst
│ ├── msl.equipment.connection_gpib.rst
│ ├── msl.equipment.connection_sdk.rst
│ ├── msl.equipment.resources.utils.rst
│ ├── msl.equipment.connection_nidaq.rst
│ ├── msl.equipment.connection_pyvisa.rst
│ ├── msl.equipment.connection_serial.rst
│ ├── msl.equipment.connection_socket.rst
│ ├── msl.equipment.connection_zeromq.rst
│ ├── msl.equipment.connection_prologix.rst
│ ├── msl.equipment.resources.cmi.sia3.rst
│ ├── msl.equipment.resources.omega.ithx.rst
│ ├── msl.equipment.dns_service_discovery.rst
│ ├── msl.equipment.connection_tcpip_vxi11.rst
│ ├── msl.equipment.resources.vaisala.ptb330.rst
│ ├── msl.equipment.resources.vaisala.ptu300.rst
│ ├── msl.equipment.connection_tcpip_hislip.rst
│ ├── msl.equipment.resources.energetiq.eq99.rst
│ ├── msl.equipment.resources.isotech.millik.rst
│ ├── msl.equipment.connection_message_based.rst
│ ├── msl.equipment.resources.avantes.avaspec.rst
│ ├── msl.equipment.resources.bentham.benhw32.rst
│ ├── msl.equipment.resources.bentham.benhw64.rst
│ ├── msl.equipment.resources.bentham.errors.rst
│ ├── msl.equipment.resources.bentham.tokens.rst
│ ├── msl.equipment.resources.picotech.errors.rst
│ ├── msl.equipment.resources.picotech.pt104.rst
│ ├── msl.equipment.resources.thorlabs.fwxx2c.rst
│ ├── msl.equipment.resources.aim_tti.mx_series.rst
│ ├── msl.equipment.resources.greisinger.gmh3000.rst
│ ├── msl.equipment.resources.optosigma.shot702.rst
│ ├── msl.equipment.resources.raicol.raicol_tec.rst
│ ├── msl.equipment.resources.nkt.nktpdll.rst
│ ├── msl.equipment.resources.dataray.datarayocx_32.rst
│ ├── msl.equipment.resources.dataray.datarayocx_64.rst
│ ├── msl.equipment.resources.thorlabs.kinesis.enums.rst
│ ├── msl.equipment.resources.mks_instruments.pr4000b.rst
│ ├── msl.equipment.resources.thorlabs.kinesis.errors.rst
│ ├── msl.equipment.resources.picotech.picoscope.enums.rst
│ ├── msl.equipment.resources.picotech.picoscope.helper.rst
│ ├── msl.equipment.resources.picotech.picoscope.ps2000.rst
│ ├── msl.equipment.resources.picotech.picoscope.ps3000.rst
│ ├── msl.equipment.resources.picotech.picoscope.ps4000.rst
│ ├── msl.equipment.resources.picotech.picoscope.ps5000.rst
│ ├── msl.equipment.resources.picotech.picoscope.ps6000.rst
│ ├── msl.equipment.resources.thorlabs.kinesis.messages.rst
│ ├── msl.equipment.resources.thorlabs.kinesis.structs.rst
│ ├── msl.equipment.resources.picotech.picoscope.channel.rst
│ ├── msl.equipment.resources.picotech.picoscope.ps2000a.rst
│ ├── msl.equipment.resources.picotech.picoscope.ps3000a.rst
│ ├── msl.equipment.resources.picotech.picoscope.ps4000a.rst
│ ├── msl.equipment.resources.picotech.picoscope.ps5000a.rst
│ ├── msl.equipment.resources.picotech.picoscope.structs.rst
│ ├── msl.equipment.resources.thorlabs.kinesis.callbacks.rst
│ ├── msl.equipment.resources.electron_dynamics.tc_series.rst
│ ├── msl.equipment.resources.picotech.picoscope.callbacks.rst
│ ├── msl.equipment.resources.picotech.picoscope.functions.rst
│ ├── msl.equipment.resources.picotech.picoscope.picoscope.rst
│ ├── msl.equipment.resources.thorlabs.kinesis.api_functions.rst
│ ├── msl.equipment.resources.thorlabs.kinesis.filter_flipper.rst
│ ├── msl.equipment.resources.thorlabs.kinesis.kcube_solenoid.rst
│ ├── msl.equipment.resources.thorlabs.kinesis.motion_control.rst
│ ├── msl.equipment.resources.picotech.picoscope.picoscope_api.rst
│ ├── msl.equipment.resources.optronic_laboratories.ol756ocx_32.rst
│ ├── msl.equipment.resources.optronic_laboratories.ol756ocx_64.rst
│ ├── msl.equipment.resources.picotech.picoscope.picoscope_2k3k.rst
│ ├── msl.equipment.resources.nkt.rst
│ ├── msl.equipment.resources.thorlabs.kinesis.kcube_dc_servo.rst
│ ├── msl.equipment.resources.cmi.rst
│ ├── msl.equipment.resources.omega.rst
│ ├── msl.equipment.resources.princeton_instruments.arc_instrument.rst
│ ├── msl.equipment.resources.aim_tti.rst
│ ├── msl.equipment.resources.avantes.rst
│ ├── msl.equipment.resources.thorlabs.kinesis.benchtop_stepper_motor.rst
│ ├── msl.equipment.resources.thorlabs.kinesis.kcube_stepper_motor.rst
│ ├── msl.equipment.resources.optosigma.rst
│ ├── msl.equipment.resources.raicol.rst
│ ├── msl.equipment.resources.thorlabs.kinesis.integrated_stepper_motors.rst
│ ├── msl.equipment.resources.isotech.rst
│ ├── msl.equipment.resources.energetiq.rst
│ ├── msl.equipment.resources.greisinger.rst
│ ├── msl.equipment.resources.mks_instruments.rst
│ ├── msl.equipment.resources.electron_dynamics.rst
│ ├── msl.equipment.resources.vaisala.rst
│ ├── msl.equipment.resources.dataray.rst
│ ├── msl.equipment.resources.princeton_instruments.rst
│ ├── msl.equipment.resources.optronic_laboratories.ol_current_source.rst
│ ├── msl.equipment.resources.picotech.rst
│ ├── msl.equipment.resources.thorlabs.rst
│ ├── msl.equipment.resources.bentham.rst
│ ├── msl.equipment.resources.optronic_laboratories.rst
│ ├── msl.equipment.record_types.rst
│ ├── msl.equipment.resources.thorlabs.kinesis.rst
│ ├── msl.equipment.resources.rst
│ └── msl.equipment.resources.picotech.picoscope.rst
├── _templates
│ └── layout.html
├── examples.rst
├── _static
│ └── custom.css
└── install.rst
├── .gitignore
├── CHANGELOG.md
├── .github
└── workflows
│ ├── ci.yml
│ └── docs.yml
├── LICENSE.txt
└── README.md
/docs/release-notes.md:
--------------------------------------------------------------------------------
1 | --8<-- "CHANGELOG.md"
2 |
--------------------------------------------------------------------------------
/packages/validate/CHANGELOG.md:
--------------------------------------------------------------------------------
1 |
2 | ### unreleased
3 |
--------------------------------------------------------------------------------
/docs/api/types.md:
--------------------------------------------------------------------------------
1 | # types
2 |
3 | ::: msl.equipment._types
4 |
--------------------------------------------------------------------------------
/docs/api/config.md:
--------------------------------------------------------------------------------
1 | # Config
2 |
3 | ::: msl.equipment.config
4 |
--------------------------------------------------------------------------------
/src/msl/equipment/py.typed:
--------------------------------------------------------------------------------
1 | # Marker file for PEP 561 (inline types)
--------------------------------------------------------------------------------
/docs/license.md:
--------------------------------------------------------------------------------
1 | # License
2 |
3 | ```
4 | --8<-- "LICENSE.txt"
5 | ```
--------------------------------------------------------------------------------
/docs/resources/types.md:
--------------------------------------------------------------------------------
1 | # types
2 |
3 | ::: msl.equipment_resources.types
4 |
--------------------------------------------------------------------------------
/docs/api/enumerations.md:
--------------------------------------------------------------------------------
1 | # enumerations
2 |
3 | ::: msl.equipment.enumerations
4 |
--------------------------------------------------------------------------------
/packages/validate/src/msl/equipment_validate/py.typed:
--------------------------------------------------------------------------------
1 | # Marker file for PEP 561 (inline types)
--------------------------------------------------------------------------------
/packages/resources/src/msl/equipment_resources/py.typed:
--------------------------------------------------------------------------------
1 | # Marker file for PEP 561 (inline types)
--------------------------------------------------------------------------------
/tests/resources/gpib.dll:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MSLNZ/msl-equipment/HEAD/tests/resources/gpib.dll
--------------------------------------------------------------------------------
/tests/resources/gpib.so:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MSLNZ/msl-equipment/HEAD/tests/resources/gpib.so
--------------------------------------------------------------------------------
/tests/resources/gpib.dylib:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MSLNZ/msl-equipment/HEAD/tests/resources/gpib.dylib
--------------------------------------------------------------------------------
/docs/assets/images/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MSLNZ/msl-equipment/HEAD/docs/assets/images/favicon.ico
--------------------------------------------------------------------------------
/docs/resources/multi_message_based.md:
--------------------------------------------------------------------------------
1 | # MultiMessageBased
2 |
3 | ::: msl.equipment_resources.multi_message_based
4 |
--------------------------------------------------------------------------------
/tests/resources/irradiance.xlsx:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/MSLNZ/msl-equipment/HEAD/tests/resources/irradiance.xlsx
--------------------------------------------------------------------------------
/docs/resources/aim-tti/mx_series.md:
--------------------------------------------------------------------------------
1 | # MX Series DC Power Supply
2 |
3 | ::: msl.equipment_resources.aim_tti.mx_series
4 |
--------------------------------------------------------------------------------
/packages/validate/tests/registers/do_not_modify_this_file.txt:
--------------------------------------------------------------------------------
1 | The SHA-256 checksum of this file must remain constant. Do not modify.
--------------------------------------------------------------------------------
/docs/resources/mks/pr4000b.md:
--------------------------------------------------------------------------------
1 | # PR4000B
2 |
3 | ::: msl.equipment_resources.mks.pr4000b
4 | options:
5 | inherited_members: false
6 |
--------------------------------------------------------------------------------
/docs/resources/nkt/nktpdll.md:
--------------------------------------------------------------------------------
1 | # NKTPDLL
2 |
3 | ::: msl.equipment_resources.nkt.nktpdll
4 | options:
5 | inherited_members: false
6 |
--------------------------------------------------------------------------------
/docs/resources/raicol/tec.md:
--------------------------------------------------------------------------------
1 | # TEC Oven
2 |
3 | ::: msl.equipment_resources.raicol.tec
4 | options:
5 | inherited_members: false
6 |
--------------------------------------------------------------------------------
/docs/resources/dataray/wincamd.md:
--------------------------------------------------------------------------------
1 | # WinCamD
2 |
3 | ::: msl.equipment_resources.dataray.wincamd
4 | options:
5 | inherited_members: false
--------------------------------------------------------------------------------
/docs/resources/energetiq/eq99.md:
--------------------------------------------------------------------------------
1 | # EQ-99
2 |
3 | ::: msl.equipment_resources.energetiq.eq99
4 | options:
5 | inherited_members: false
6 |
--------------------------------------------------------------------------------
/docs/resources/isotech/millik.md:
--------------------------------------------------------------------------------
1 | # milliK
2 |
3 | ::: msl.equipment_resources.isotech.millik
4 | options:
5 | inherited_members: false
6 |
--------------------------------------------------------------------------------
/docs/resources/omega/ithx.md:
--------------------------------------------------------------------------------
1 | # ITHX iServer
2 |
3 | ::: msl.equipment_resources.omega.ithx
4 | options:
5 | inherited_members: false
6 |
--------------------------------------------------------------------------------
/docs/resources/picotech/pt104.md:
--------------------------------------------------------------------------------
1 | # PT-104
2 |
3 | ::: msl.equipment_resources.picotech.pt104
4 | options:
5 | inherited_members: false
6 |
--------------------------------------------------------------------------------
/docs/resources/vaisala/ptu300.md:
--------------------------------------------------------------------------------
1 | # PTU300
2 |
3 | ::: msl.equipment_resources.vaisala.ptu300
4 | options:
5 | inherited_members: false
6 |
--------------------------------------------------------------------------------
/docs/resources/cmi/sia3.md:
--------------------------------------------------------------------------------
1 | # Switched Integrator Amplifier
2 |
3 | ::: msl.equipment_resources.cmi.sia3
4 | options:
5 | inherited_members: false
--------------------------------------------------------------------------------
/docs/schema/any.md:
--------------------------------------------------------------------------------
1 | # Any
2 |
3 | ::: msl.equipment.schema.Any
4 | options:
5 | show_root_full_path: false
6 | show_root_heading: true
7 |
--------------------------------------------------------------------------------
/docs/resources/optosigma/shot702.md:
--------------------------------------------------------------------------------
1 | # SHOT-702
2 |
3 | ::: msl.equipment_resources.optosigma.shot702
4 | options:
5 | inherited_members: false
6 |
--------------------------------------------------------------------------------
/docs/resources/picotech/picoscope.md:
--------------------------------------------------------------------------------
1 | # PicoScope
2 |
3 | ::: msl.equipment_resources.picotech.picoscope
4 | options:
5 | inherited_members: false
6 |
--------------------------------------------------------------------------------
/docs/resources/thorlabs/fwxx2c.md:
--------------------------------------------------------------------------------
1 | # FW102C/FW212C
2 |
3 | ::: msl.equipment_resources.thorlabs.fwxx2c
4 | options:
5 | inherited_members: false
6 |
--------------------------------------------------------------------------------
/docs/resources/optronic_labs/ol756.md:
--------------------------------------------------------------------------------
1 | # OL 756
2 |
3 | ::: msl.equipment_resources.optronic_labs.ol756ocx_64
4 | options:
5 | inherited_members: false
6 |
--------------------------------------------------------------------------------
/docs/schema/status.md:
--------------------------------------------------------------------------------
1 | # Status
2 |
3 | ::: msl.equipment.schema.Status
4 | options:
5 | show_root_full_path: false
6 | show_root_heading: true
7 |
--------------------------------------------------------------------------------
/docs/resources/optronic_labs/olxxa.md:
--------------------------------------------------------------------------------
1 | # OL 16A, 65A, 83A
2 |
3 | ::: msl.equipment_resources.optronic_labs.olxxa
4 | options:
5 | inherited_members: false
6 |
--------------------------------------------------------------------------------
/docs/schema/firmware.md:
--------------------------------------------------------------------------------
1 | # Firmware
2 |
3 | ::: msl.equipment.schema.Firmware
4 | options:
5 | show_root_full_path: false
6 | show_root_heading: true
7 |
--------------------------------------------------------------------------------
/docs/api/connection.md:
--------------------------------------------------------------------------------
1 | # Connection
2 |
3 | ::: msl.equipment.schema.Connection
4 | options:
5 | show_root_full_path: false
6 | show_root_heading: true
7 |
--------------------------------------------------------------------------------
/docs/api/interfaces/gpib.md:
--------------------------------------------------------------------------------
1 | # GPIB
2 |
3 | ::: msl.equipment.interfaces.gpib.GPIB
4 | options:
5 | show_root_full_path: false
6 | show_root_heading: true
7 |
--------------------------------------------------------------------------------
/docs/api/interfaces/sdk.md:
--------------------------------------------------------------------------------
1 | # SDK
2 |
3 | ::: msl.equipment.interfaces.sdk.SDK
4 | options:
5 | show_root_full_path: false
6 | show_root_heading: true
7 |
--------------------------------------------------------------------------------
/docs/schema/component.md:
--------------------------------------------------------------------------------
1 | # Component
2 |
3 | ::: msl.equipment.schema.Component
4 | options:
5 | show_root_full_path: false
6 | show_root_heading: true
7 |
--------------------------------------------------------------------------------
/docs/schema/financial.md:
--------------------------------------------------------------------------------
1 | # Financial
2 |
3 | ::: msl.equipment.schema.Financial
4 | options:
5 | show_root_full_path: false
6 | show_root_heading: true
7 |
--------------------------------------------------------------------------------
/docs/schema/measurand.md:
--------------------------------------------------------------------------------
1 | # Measurand
2 |
3 | ::: msl.equipment.schema.Measurand
4 | options:
5 | show_root_full_path: false
6 | show_root_heading: true
7 |
--------------------------------------------------------------------------------
/docs/api/backends/nidaq.md:
--------------------------------------------------------------------------------
1 | # NIDAQ
2 |
3 | ::: msl.equipment.interfaces.nidaq.NIDAQ
4 | options:
5 | show_root_full_path: false
6 | show_root_heading: true
7 |
--------------------------------------------------------------------------------
/docs/api/interfaces/vxi11.md:
--------------------------------------------------------------------------------
1 | # VXI11
2 |
3 | ::: msl.equipment.interfaces.vxi11.VXI11
4 | options:
5 | show_root_full_path: false
6 | show_root_heading: true
7 |
--------------------------------------------------------------------------------
/docs/resources/greisinger/gmh3000.md:
--------------------------------------------------------------------------------
1 | # GMH 3000 Series thermometer
2 |
3 | ::: msl.equipment_resources.greisinger.gmh3000
4 | options:
5 | inherited_members: false
6 |
--------------------------------------------------------------------------------
/docs/schema/accessories.md:
--------------------------------------------------------------------------------
1 | # Accessories
2 |
3 | ::: msl.equipment.schema.Accessories
4 | options:
5 | show_root_full_path: false
6 | show_root_heading: true
7 |
--------------------------------------------------------------------------------
/docs/schema/adjustment.md:
--------------------------------------------------------------------------------
1 | # Adjustment
2 |
3 | ::: msl.equipment.schema.Adjustment
4 | options:
5 | show_root_full_path: false
6 | show_root_heading: true
7 |
--------------------------------------------------------------------------------
/docs/schema/alteration.md:
--------------------------------------------------------------------------------
1 | # Alteration
2 |
3 | ::: msl.equipment.schema.Alteration
4 | options:
5 | show_root_full_path: false
6 | show_root_heading: true
7 |
--------------------------------------------------------------------------------
/docs/schema/competency.md:
--------------------------------------------------------------------------------
1 | # Competency
2 |
3 | ::: msl.equipment.schema.Competency
4 | options:
5 | show_root_full_path: false
6 | show_root_heading: true
7 |
--------------------------------------------------------------------------------
/docs/schema/conditions.md:
--------------------------------------------------------------------------------
1 | # Conditions
2 |
3 | ::: msl.equipment.schema.Conditions
4 | options:
5 | show_root_full_path: false
6 | show_root_heading: true
7 |
--------------------------------------------------------------------------------
/docs/schema/maintenance.md:
--------------------------------------------------------------------------------
1 | # Maintenance
2 |
3 | ::: msl.equipment.schema.Maintenance
4 | options:
5 | show_root_full_path: false
6 | show_root_heading: true
7 |
--------------------------------------------------------------------------------
/docs/schema/planned_task.md:
--------------------------------------------------------------------------------
1 | # PlannedTask
2 |
3 | ::: msl.equipment.schema.PlannedTask
4 | options:
5 | show_root_full_path: false
6 | show_root_heading: true
7 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.rst:
--------------------------------------------------------------------------------
1 | msl.equipment package
2 | =====================
3 |
4 | .. automodule:: msl.equipment
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
--------------------------------------------------------------------------------
/docs/api/backends/pyvisa.md:
--------------------------------------------------------------------------------
1 | # PyVISA
2 |
3 | ::: msl.equipment.interfaces.pyvisa.PyVISA
4 | options:
5 | show_root_full_path: false
6 | show_root_heading: true
7 |
--------------------------------------------------------------------------------
/docs/api/interfaces/hislip.md:
--------------------------------------------------------------------------------
1 | # HiSLIP
2 |
3 | ::: msl.equipment.interfaces.hislip.HiSLIP
4 | options:
5 | show_root_full_path: false
6 | show_root_heading: true
7 |
--------------------------------------------------------------------------------
/docs/api/interfaces/serial.md:
--------------------------------------------------------------------------------
1 | # Serial
2 |
3 | ::: msl.equipment.interfaces.serial.Serial
4 | options:
5 | show_root_full_path: false
6 | show_root_heading: true
7 |
--------------------------------------------------------------------------------
/docs/api/interfaces/socket.md:
--------------------------------------------------------------------------------
1 | # Socket
2 |
3 | ::: msl.equipment.interfaces.socket.Socket
4 | options:
5 | show_root_full_path: false
6 | show_root_heading: true
7 |
--------------------------------------------------------------------------------
/docs/api/interfaces/zeromq.md:
--------------------------------------------------------------------------------
1 | # ZeroMQ
2 |
3 | ::: msl.equipment.interfaces.zeromq.ZeroMQ
4 | options:
5 | show_root_full_path: false
6 | show_root_heading: true
7 |
--------------------------------------------------------------------------------
/docs/schema/deserialised.md:
--------------------------------------------------------------------------------
1 | # Deserialised
2 |
3 | ::: msl.equipment.schema.Deserialised
4 | options:
5 | show_root_full_path: false
6 | show_root_heading: true
7 |
--------------------------------------------------------------------------------
/docs/resources/electron_dynamics/tc_series.md:
--------------------------------------------------------------------------------
1 | # TC Temperature Controller
2 |
3 | ::: msl.equipment_resources.electron_dynamics.tc_series
4 | options:
5 | inherited_members: false
--------------------------------------------------------------------------------
/docs/schema/completed_task.md:
--------------------------------------------------------------------------------
1 | # CompletedTask
2 |
3 | ::: msl.equipment.schema.CompletedTask
4 | options:
5 | show_root_full_path: false
6 | show_root_heading: true
7 |
--------------------------------------------------------------------------------
/docs/schema/quality_manual.md:
--------------------------------------------------------------------------------
1 | # QualityManual
2 |
3 | ::: msl.equipment.schema.QualityManual
4 | options:
5 | show_root_full_path: false
6 | show_root_heading: true
7 |
--------------------------------------------------------------------------------
/docs/schema/specifications.md:
--------------------------------------------------------------------------------
1 | # Specifications
2 |
3 | ::: msl.equipment.schema.Specifications
4 | options:
5 | show_root_full_path: false
6 | show_root_heading: true
7 |
--------------------------------------------------------------------------------
/docs/api/interfaces/prologix.md:
--------------------------------------------------------------------------------
1 | # Prologix
2 |
3 | ::: msl.equipment.interfaces.prologix.Prologix
4 | options:
5 | show_root_full_path: false
6 | show_root_heading: true
7 |
--------------------------------------------------------------------------------
/docs/schema/performance_check.md:
--------------------------------------------------------------------------------
1 | # PerformanceCheck
2 |
3 | ::: msl.equipment.schema.PerformanceCheck
4 | options:
5 | show_root_full_path: false
6 | show_root_heading: true
7 |
--------------------------------------------------------------------------------
/docs-old/_templates/layout.html:
--------------------------------------------------------------------------------
1 | {% extends "!layout.html" %}
2 |
3 | {% block extrahead %}
4 |
5 | {% endblock %}
--------------------------------------------------------------------------------
/docs/resources/picotech/types.md:
--------------------------------------------------------------------------------
1 | # Enums/Structs
2 |
3 | ::: msl.equipment_resources.picotech.status.PicoInfo
4 | options:
5 | show_root_full_path: false
6 | show_root_heading: true
7 |
--------------------------------------------------------------------------------
/docs/resources/princeton_instruments/arc_instrument.md:
--------------------------------------------------------------------------------
1 | # ARC Instrument SDK
2 |
3 | ::: msl.equipment_resources.princeton_instruments.arc_instrument
4 | options:
5 | inherited_members: false
6 |
--------------------------------------------------------------------------------
/docs/schema/acceptance_criteria.md:
--------------------------------------------------------------------------------
1 | # AcceptanceCriteria
2 |
3 | ::: msl.equipment.schema.AcceptanceCriteria
4 | options:
5 | show_root_full_path: false
6 | show_root_heading: true
7 |
--------------------------------------------------------------------------------
/docs/schema/capital_expenditure.md:
--------------------------------------------------------------------------------
1 | # CapitalExpenditure
2 |
3 | ::: msl.equipment.schema.CapitalExpenditure
4 | options:
5 | show_root_full_path: false
6 | show_root_heading: true
7 |
--------------------------------------------------------------------------------
/docs/schema/reference_materials.md:
--------------------------------------------------------------------------------
1 | # ReferenceMaterials
2 |
3 | ::: msl.equipment.schema.ReferenceMaterials
4 | options:
5 | show_root_full_path: false
6 | show_root_heading: true
7 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.utils.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.utils module
2 | ==========================
3 |
4 | .. automodule:: msl.equipment.utils
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.vxi11.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.vxi11 module
2 | ==========================
3 |
4 | .. automodule:: msl.equipment.vxi11
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs/schema/specified_requirements.md:
--------------------------------------------------------------------------------
1 | # SpecifiedRequirements
2 |
3 | ::: msl.equipment.schema.SpecifiedRequirements
4 | options:
5 | show_root_full_path: false
6 | show_root_heading: true
7 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.config.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.config module
2 | ===========================
3 |
4 | .. automodule:: msl.equipment.config
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.hislip.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.hislip module
2 | ===========================
3 |
4 | .. automodule:: msl.equipment.hislip
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.factory.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.factory module
2 | ============================
3 |
4 | .. automodule:: msl.equipment.factory
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.database.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.database module
2 | =============================
3 |
4 | .. automodule:: msl.equipment.database
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.connection.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.connection module
2 | ===============================
3 |
4 | .. automodule:: msl.equipment.connection
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.constants.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.constants module
2 | ==============================
3 |
4 | .. automodule:: msl.equipment.constants
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.exceptions.rst:
--------------------------------------------------------------------------------
1 | msl\.equipment\.exceptions module
2 | =================================
3 |
4 | .. automodule:: msl.equipment.exceptions
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.connection_demo.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.connection_demo module
2 | ====================================
3 |
4 | .. automodule:: msl.equipment.connection_demo
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.connection_gpib.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.connection\_gpib module
2 | =====================================
3 |
4 | .. automodule:: msl.equipment.connection_gpib
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.connection_sdk.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.connection_sdk module
2 | ===================================
3 |
4 | .. automodule:: msl.equipment.connection_sdk
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.resources.utils.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.resources.utils module
2 | ====================================
3 |
4 | .. automodule:: msl.equipment.resources.utils
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.connection_nidaq.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.connection\_nidaq module
2 | ======================================
3 |
4 | .. automodule:: msl.equipment.connection_nidaq
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.connection_pyvisa.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.connection_pyvisa module
2 | ======================================
3 |
4 | .. automodule:: msl.equipment.connection_pyvisa
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.connection_serial.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.connection_serial module
2 | ======================================
3 |
4 | .. automodule:: msl.equipment.connection_serial
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.connection_socket.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.connection_socket module
2 | ======================================
3 |
4 | .. automodule:: msl.equipment.connection_socket
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.connection_zeromq.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.connection\_zeromq module
2 | =======================================
3 |
4 | .. automodule:: msl.equipment.connection_zeromq
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.connection_prologix.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.connection\_prologix module
2 | =========================================
3 |
4 | .. automodule:: msl.equipment.connection_prologix
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/packages/resources/src/msl/equipment_resources/aim_tti/__init__.py:
--------------------------------------------------------------------------------
1 | """Resources for equipment from Aim-TTi."""
2 |
3 | from __future__ import annotations
4 |
5 | from .mx_series import MXSeries
6 |
7 | __all__: list[str] = [
8 | "MXSeries",
9 | ]
10 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.resources.cmi.sia3.rst:
--------------------------------------------------------------------------------
1 | msl\.equipment\.resources\.cmi\.sia3 module
2 | ===========================================
3 |
4 | .. automodule:: msl.equipment.resources.cmi.sia3
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.resources.omega.ithx.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.resources.omega.ithx module
2 | =========================================
3 |
4 | .. automodule:: msl.equipment.resources.omega.ithx
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs/resources/vaisala/ptb330.md:
--------------------------------------------------------------------------------
1 | # PTB330
2 |
3 | ::: msl.equipment_resources.vaisala.ptb330
4 | options:
5 | inherited_members: true
6 | filters: [PTB330, ^device_info$, units, check_for_errors, get_format, get_reading_str, set_format, set_units]
7 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.dns_service_discovery.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.dns\_service\_discovery module
2 | ============================================
3 |
4 | .. automodule:: msl.equipment.dns_service_discovery
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/packages/resources/src/msl/equipment_resources/omega/__init__.py:
--------------------------------------------------------------------------------
1 | """Resources for equipment from [OMEGA](https://www.omega.co.uk/)."""
2 |
3 | from __future__ import annotations
4 |
5 | from .ithx import ITHX
6 |
7 | __all__: list[str] = [
8 | "ITHX",
9 | ]
10 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.connection_tcpip_vxi11.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.connection\_tcpip\_vxi11 module
2 | =============================================
3 |
4 | .. automodule:: msl.equipment.connection_tcpip_vxi11
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.resources.vaisala.ptb330.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.resources.vaisala.ptb330 package
2 | ==============================================
3 |
4 | .. automodule:: msl.equipment.resources.vaisala.ptb330
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.resources.vaisala.ptu300.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.resources.vaisala.ptu300 package
2 | ==============================================
3 |
4 | .. automodule:: msl.equipment.resources.vaisala.ptu300
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.connection_tcpip_hislip.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.connection\_tcpip\_hislip module
2 | ==============================================
3 |
4 | .. automodule:: msl.equipment.connection_tcpip_hislip
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.resources.energetiq.eq99.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.resources.energetiq.eq99 module
2 | =============================================
3 |
4 | .. automodule:: msl.equipment.resources.energetiq.eq99
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.resources.isotech.millik.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.resources.isotech.millik module
2 | =============================================
3 |
4 | .. automodule:: msl.equipment.resources.isotech.millik
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/packages/resources/src/msl/equipment_resources/energetiq/__init__.py:
--------------------------------------------------------------------------------
1 | """Resources for equipment from [Energetiq](https://www.energetiq.com/)."""
2 |
3 | from __future__ import annotations
4 |
5 | from .eq99 import EQ99
6 |
7 | __all__: list[str] = [
8 | "EQ99",
9 | ]
10 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.connection_message_based.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.connection_message_based module
2 | =============================================
3 |
4 | .. automodule:: msl.equipment.connection_message_based
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.resources.avantes.avaspec.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.resources.avantes.avaspec module
2 | ==============================================
3 |
4 | .. automodule:: msl.equipment.resources.avantes.avaspec
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.resources.bentham.benhw32.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.resources.bentham.benhw32 module
2 | ==============================================
3 |
4 | .. automodule:: msl.equipment.resources.bentham.benhw32
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.resources.bentham.benhw64.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.resources.bentham.benhw64 module
2 | ==============================================
3 |
4 | .. automodule:: msl.equipment.resources.bentham.benhw64
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.resources.bentham.errors.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.resources.bentham.errors module
2 | =============================================
3 |
4 | .. automodule:: msl.equipment.resources.bentham.errors
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.resources.bentham.tokens.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.resources.bentham.tokens module
2 | =============================================
3 |
4 | .. automodule:: msl.equipment.resources.bentham.tokens
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.resources.picotech.errors.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.resources.picotech.errors module
2 | ==============================================
3 |
4 | .. automodule:: msl.equipment.resources.picotech.errors
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.resources.picotech.pt104.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.resources.picotech.pt104 module
2 | =============================================
3 |
4 | .. automodule:: msl.equipment.resources.picotech.pt104
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.resources.thorlabs.fwxx2c.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.resources.thorlabs.fwxx2c module
2 | ==============================================
3 |
4 | .. automodule:: msl.equipment.resources.thorlabs.fwxx2c
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/packages/resources/src/msl/equipment_resources/dataray/__init__.py:
--------------------------------------------------------------------------------
1 | """Resources for equipment from [DataRay](https://www.dataray.com/)."""
2 |
3 | from __future__ import annotations
4 |
5 | from .wincamd import WinCamD
6 |
7 | __all__: list[str] = [
8 | "WinCamD",
9 | ]
10 |
--------------------------------------------------------------------------------
/packages/resources/src/msl/equipment_resources/raicol/__init__.py:
--------------------------------------------------------------------------------
1 | """Resources for equipment from [Raicol Crystals](https://raicol.com/)."""
2 |
3 | from __future__ import annotations
4 |
5 | from .tec import RaicolTEC
6 |
7 | __all__: list[str] = [
8 | "RaicolTEC",
9 | ]
10 |
--------------------------------------------------------------------------------
/packages/resources/src/msl/equipment_resources/thorlabs/__init__.py:
--------------------------------------------------------------------------------
1 | """Resources for equipment from [Thorlabs](https://www.thorlabs.com/)."""
2 |
3 | from __future__ import annotations
4 |
5 | from .fwxx2c import FWxx2C
6 |
7 | __all__: list[str] = [
8 | "FWxx2C",
9 | ]
10 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.resources.aim_tti.mx_series.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.resources.aim\_tti.mx_series module
2 | =================================================
3 |
4 | .. automodule:: msl.equipment.resources.aim_tti.mx_series
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.resources.greisinger.gmh3000.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.resources.greisinger.gmh3000 module
2 | =================================================
3 |
4 | .. automodule:: msl.equipment.resources.greisinger.gmh3000
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.resources.optosigma.shot702.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.resources.optosigma.shot702 module
2 | ================================================
3 |
4 | .. automodule:: msl.equipment.resources.optosigma.shot702
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.resources.raicol.raicol_tec.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.resources.raicol.raicol\_tec module
2 | =================================================
3 |
4 | .. automodule:: msl.equipment.resources.raicol.raicol_tec
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/packages/resources/src/msl/equipment_resources/greisinger/__init__.py:
--------------------------------------------------------------------------------
1 | """Resources for equipment from [Greisinger](https://www.greisinger.de/)."""
2 |
3 | from __future__ import annotations
4 |
5 | from .gmh3000 import GMH3000
6 |
7 | __all__: list[str] = [
8 | "GMH3000",
9 | ]
10 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.resources.nkt.nktpdll.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.resources.nkt.nktpdll module
2 | ==========================================
3 |
4 | .. automodule:: msl.equipment.resources.nkt.nktpdll
5 | :members:
6 | :member-order: bysource
7 | :undoc-members:
8 | :show-inheritance:
9 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Global directories
2 | __pycache__/
3 |
4 | # Global files
5 | *.py[codz]
6 |
7 | # Root directories
8 | /.cache/
9 | /.idea/
10 | /.vscode/
11 | /.venv/
12 | /dist/
13 | /site/
14 | /venv/
15 |
16 | # Root files
17 | /uv.lock
18 |
19 | # Auto-generated during build
20 | /**/_version.py
21 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.resources.dataray.datarayocx_32.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.resources.dataray.datarayocx\_32 module
2 | =====================================================
3 |
4 | .. automodule:: msl.equipment.resources.dataray.datarayocx_32
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.resources.dataray.datarayocx_64.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.resources.dataray.datarayocx\_64 module
2 | =====================================================
3 |
4 | .. automodule:: msl.equipment.resources.dataray.datarayocx_64
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.resources.thorlabs.kinesis.enums.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.resources.thorlabs.kinesis.enums module
2 | =====================================================
3 |
4 | .. automodule:: msl.equipment.resources.thorlabs.kinesis.enums
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs/schema/report.md:
--------------------------------------------------------------------------------
1 | # Report
2 |
3 | ::: msl.equipment.schema.Report
4 | options:
5 | show_root_full_path: false
6 | show_root_heading: true
7 |
8 | ::: msl.equipment.schema.IssuingLaboratory
9 | options:
10 | show_root_full_path: false
11 | show_root_heading: true
12 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.resources.mks_instruments.pr4000b.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.resources.mks\_instruments.pr4000b module
2 | =======================================================
3 |
4 | .. automodule:: msl.equipment.resources.mks_instruments.pr4000b
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.resources.thorlabs.kinesis.errors.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.resources.thorlabs.kinesis.errors module
2 | ======================================================
3 |
4 | .. automodule:: msl.equipment.resources.thorlabs.kinesis.errors
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs/javascripts/arithmatex.js:
--------------------------------------------------------------------------------
1 | window.MathJax = {
2 | tex: {
3 | inlineMath: [["\\(", "\\)"]],
4 | displayMath: [["\\[", "\\]"]],
5 | processEscapes: true,
6 | processEnvironments: true
7 | },
8 | options: {
9 | ignoreHtmlClass: ".*|",
10 | processHtmlClass: "arithmatex"
11 | }
12 | };
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.resources.picotech.picoscope.enums.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.resources.picotech.picoscope.enums module
2 | =======================================================
3 |
4 | .. automodule:: msl.equipment.resources.picotech.picoscope.enums
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.resources.picotech.picoscope.helper.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.resources.picotech.picoscope.helper module
2 | ========================================================
3 |
4 | .. automodule:: msl.equipment.resources.picotech.picoscope.helper
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.resources.picotech.picoscope.ps2000.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.resources.picotech.picoscope.ps2000 module
2 | ========================================================
3 |
4 | .. automodule:: msl.equipment.resources.picotech.picoscope.ps2000
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.resources.picotech.picoscope.ps3000.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.resources.picotech.picoscope.ps3000 module
2 | ========================================================
3 |
4 | .. automodule:: msl.equipment.resources.picotech.picoscope.ps3000
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.resources.picotech.picoscope.ps4000.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.resources.picotech.picoscope.ps4000 module
2 | ========================================================
3 |
4 | .. automodule:: msl.equipment.resources.picotech.picoscope.ps4000
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.resources.picotech.picoscope.ps5000.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.resources.picotech.picoscope.ps5000 module
2 | ========================================================
3 |
4 | .. automodule:: msl.equipment.resources.picotech.picoscope.ps5000
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.resources.picotech.picoscope.ps6000.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.resources.picotech.picoscope.ps6000 module
2 | ========================================================
3 |
4 | .. automodule:: msl.equipment.resources.picotech.picoscope.ps6000
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.resources.thorlabs.kinesis.messages.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.resources.thorlabs.kinesis.messages module
2 | ========================================================
3 |
4 | .. automodule:: msl.equipment.resources.thorlabs.kinesis.messages
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.resources.thorlabs.kinesis.structs.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.resources.thorlabs.kinesis.structs module
2 | =======================================================
3 |
4 | .. automodule:: msl.equipment.resources.thorlabs.kinesis.structs
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs-old/examples.rst:
--------------------------------------------------------------------------------
1 | .. _equipment-examples:
2 |
3 | ========
4 | Examples
5 | ========
6 | Some example scripts that illustrate how to use MSL-Equipment to communicate
7 | with equipment can be found in the repository_.
8 |
9 | .. _repository: https://github.com/MSLNZ/msl-equipment/tree/main/msl/examples/equipment
10 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.resources.picotech.picoscope.channel.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.resources.picotech.picoscope.channel module
2 | =========================================================
3 |
4 | .. automodule:: msl.equipment.resources.picotech.picoscope.channel
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.resources.picotech.picoscope.ps2000a.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.resources.picotech.picoscope.ps2000a module
2 | =========================================================
3 |
4 | .. automodule:: msl.equipment.resources.picotech.picoscope.ps2000a
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.resources.picotech.picoscope.ps3000a.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.resources.picotech.picoscope.ps3000a module
2 | =========================================================
3 |
4 | .. automodule:: msl.equipment.resources.picotech.picoscope.ps3000a
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.resources.picotech.picoscope.ps4000a.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.resources.picotech.picoscope.ps4000a module
2 | =========================================================
3 |
4 | .. automodule:: msl.equipment.resources.picotech.picoscope.ps4000a
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.resources.picotech.picoscope.ps5000a.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.resources.picotech.picoscope.ps5000a module
2 | =========================================================
3 |
4 | .. automodule:: msl.equipment.resources.picotech.picoscope.ps5000a
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.resources.picotech.picoscope.structs.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.resources.picotech.picoscope.structs module
2 | =========================================================
3 |
4 | .. automodule:: msl.equipment.resources.picotech.picoscope.structs
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.resources.thorlabs.kinesis.callbacks.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.resources.thorlabs.kinesis.callbacks module
2 | =========================================================
3 |
4 | .. automodule:: msl.equipment.resources.thorlabs.kinesis.callbacks
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs/schema/digital_report.md:
--------------------------------------------------------------------------------
1 | # DigitalReport
2 |
3 | ::: msl.equipment.schema.DigitalReport
4 | options:
5 | show_root_full_path: false
6 | show_root_heading: true
7 |
8 | ::: msl.equipment.schema.DigitalFormat
9 | options:
10 | show_root_full_path: false
11 | show_root_heading: true
12 |
--------------------------------------------------------------------------------
/packages/resources/src/msl/equipment_resources/vaisala/__init__.py:
--------------------------------------------------------------------------------
1 | """Resources for equipment from [Vaisala](https://www.vaisala.com/en)."""
2 |
3 | from __future__ import annotations
4 |
5 | from .ptb330 import PTB330
6 | from .ptu300 import PTU300
7 |
8 | __all__: list[str] = [
9 | "PTB330",
10 | "PTU300",
11 | ]
12 |
--------------------------------------------------------------------------------
/src/msl/equipment/resources/__init__.py:
--------------------------------------------------------------------------------
1 | """Import the `msl-equipment-resources` package (if installed)."""
2 |
3 | from __future__ import annotations
4 |
5 | import contextlib
6 |
7 | with contextlib.suppress(ImportError):
8 | from msl.equipment_resources import * # pyright: ignore[reportWildcardImportFromLibrary] # noqa: F403
9 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.resources.electron_dynamics.tc_series.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.resources.electron\_dynamics.tc\_series module
2 | ============================================================
3 |
4 | .. automodule:: msl.equipment.resources.electron_dynamics.tc_series
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.resources.picotech.picoscope.callbacks.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.resources.picotech.picoscope.callbacks module
2 | ===========================================================
3 |
4 | .. automodule:: msl.equipment.resources.picotech.picoscope.callbacks
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.resources.picotech.picoscope.functions.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.resources.picotech.picoscope.functions module
2 | ===========================================================
3 |
4 | .. automodule:: msl.equipment.resources.picotech.picoscope.functions
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.resources.picotech.picoscope.picoscope.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.resources.picotech.picoscope.picoscope module
2 | ===========================================================
3 |
4 | .. automodule:: msl.equipment.resources.picotech.picoscope.picoscope
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/packages/resources/src/msl/equipment_resources/cmi/__init__.py:
--------------------------------------------------------------------------------
1 | """Resources for equipment from the Czech Metrology Institute."""
2 |
3 | from __future__ import annotations
4 |
5 | from .sia3 import SIA3, IntegrationTime, PreScale
6 |
7 | __all__: list[str] = [
8 | "SIA3",
9 | "IntegrationTime",
10 | "PreScale",
11 | ]
12 |
--------------------------------------------------------------------------------
/packages/resources/src/msl/equipment_resources/princeton_instruments/__init__.py:
--------------------------------------------------------------------------------
1 | """Wrapper around the `ARC_Instrument.dll` SDK from Princeton Instruments."""
2 |
3 | from __future__ import annotations
4 |
5 | from .arc_instrument import PrincetonInstruments
6 |
7 | __all__: list[str] = [
8 | "PrincetonInstruments",
9 | ]
10 |
--------------------------------------------------------------------------------
/tests/resources/mass/not-a-register.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 | true
9 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.resources.thorlabs.kinesis.api_functions.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.resources.thorlabs.kinesis.api_functions module
2 | =============================================================
3 |
4 | .. automodule:: msl.equipment.resources.thorlabs.kinesis.api_functions
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.resources.thorlabs.kinesis.filter_flipper.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.resources.thorlabs.kinesis.filter_flipper module
2 | ==============================================================
3 |
4 | .. automodule:: msl.equipment.resources.thorlabs.kinesis.filter_flipper
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.resources.thorlabs.kinesis.kcube_solenoid.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.resources.thorlabs.kinesis.kcube_solenoid module
2 | ==============================================================
3 |
4 | .. automodule:: msl.equipment.resources.thorlabs.kinesis.kcube_solenoid
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.resources.thorlabs.kinesis.motion_control.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.resources.thorlabs.kinesis.motion_control module
2 | ==============================================================
3 |
4 | .. automodule:: msl.equipment.resources.thorlabs.kinesis.motion_control
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/packages/resources/src/msl/equipment_resources/picotech/__init__.py:
--------------------------------------------------------------------------------
1 | """Resources for equipment from [Pico Technology](https://www.picotech.com/)."""
2 |
3 | from __future__ import annotations
4 |
5 | from .picoscope import PicoScope
6 | from .pt104 import PT104
7 |
8 | __all__: list[str] = [
9 | "PT104",
10 | "PicoScope",
11 | ]
12 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.resources.picotech.picoscope.picoscope_api.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.resources.picotech.picoscope.picoscope_api module
2 | ===============================================================
3 |
4 | .. automodule:: msl.equipment.resources.picotech.picoscope.picoscope_api
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/packages/resources/src/msl/equipment_resources/optronic_labs/__init__.py:
--------------------------------------------------------------------------------
1 | """Resources for equipment from [Optronic Laboratories](https://optroniclabs.com/)."""
2 |
3 | from __future__ import annotations
4 |
5 | from .ol756ocx_64 import OL756
6 | from .olxxa import OLxxA
7 |
8 | __all__: list[str] = [
9 | "OL756",
10 | "OLxxA",
11 | ]
12 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.resources.optronic_laboratories.ol756ocx_32.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.resources.optronic\_laboratories.ol756ocx\_32 module
2 | ==================================================================
3 |
4 | .. automodule:: msl.equipment.resources.optronic_laboratories.ol756ocx_32
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.resources.optronic_laboratories.ol756ocx_64.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.resources.optronic\_laboratories.ol756ocx\_64 module
2 | ==================================================================
3 |
4 | .. automodule:: msl.equipment.resources.optronic_laboratories.ol756ocx_64
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.resources.picotech.picoscope.picoscope_2k3k.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.resources.picotech.picoscope.picoscope_2k3k module
2 | ================================================================
3 |
4 | .. automodule:: msl.equipment.resources.picotech.picoscope.picoscope_2k3k
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/src/msl/equipment/__about__.py:
--------------------------------------------------------------------------------
1 | """Project information."""
2 |
3 | from __future__ import annotations
4 |
5 | from ._version import __version__, version_tuple
6 |
7 | __all__: list[str] = ["__version__", "version_tuple"]
8 | __author__: str = "Measurement Standards Laboratory of New Zealand"
9 | __copyright__: str = f"\xa9 2017 - 2025, {__author__}"
10 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.resources.nkt.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.resources.nkt package
2 | ===================================
3 |
4 | .. automodule:: msl.equipment.resources.nkt
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
9 | Submodules
10 | ----------
11 |
12 | .. toctree::
13 |
14 | msl.equipment.resources.nkt.nktpdll
15 |
16 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.resources.thorlabs.kinesis.kcube_dc_servo.rst:
--------------------------------------------------------------------------------
1 | msl\.equipment\.resources\.thorlabs\.kinesis\.kcube\_dc\_servo module
2 | =====================================================================
3 |
4 | .. automodule:: msl.equipment.resources.thorlabs.kinesis.kcube_dc_servo
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.resources.cmi.rst:
--------------------------------------------------------------------------------
1 | msl\.equipment\.resources\.cmi package
2 | ======================================
3 |
4 | .. automodule:: msl.equipment.resources.cmi
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
9 | Submodules
10 | ----------
11 |
12 | .. toctree::
13 |
14 | msl.equipment.resources.cmi.sia3
15 |
16 |
--------------------------------------------------------------------------------
/docs/api/exceptions.md:
--------------------------------------------------------------------------------
1 | # exceptions
2 |
3 | ::: msl.equipment.interfaces.message_based.MSLConnectionError
4 | options:
5 | show_root_full_path: false
6 | show_root_heading: true
7 |
8 | ::: msl.equipment.interfaces.message_based.MSLTimeoutError
9 | options:
10 | show_root_full_path: false
11 | show_root_heading: true
12 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.resources.omega.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.resources.omega package
2 | =====================================
3 |
4 | .. automodule:: msl.equipment.resources.omega
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
9 | Submodules
10 | ----------
11 |
12 | .. toctree::
13 |
14 | msl.equipment.resources.omega.ithx
15 |
16 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.resources.princeton_instruments.arc_instrument.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.resources.princeton\_instruments.arc\_instrument module
2 | =====================================================================
3 |
4 | .. automodule:: msl.equipment.resources.princeton_instruments.arc_instrument
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.resources.aim_tti.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.resources.aim\_tti package
2 | ========================================
3 |
4 | .. automodule:: msl.equipment.resources.aim_tti
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
9 | Submodules
10 | ----------
11 |
12 | .. toctree::
13 |
14 | msl.equipment.resources.aim_tti.mx_series
15 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.resources.avantes.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.resources.avantes package
2 | =======================================
3 |
4 | .. automodule:: msl.equipment.resources.avantes
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
9 | Submodules
10 | ----------
11 |
12 | .. toctree::
13 |
14 | msl.equipment.resources.avantes.avaspec
15 |
16 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.resources.thorlabs.kinesis.benchtop_stepper_motor.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.resources.thorlabs.kinesis.benchtop\_stepper\_motor module
2 | ========================================================================
3 |
4 | .. automodule:: msl.equipment.resources.thorlabs.kinesis.benchtop_stepper_motor
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.resources.thorlabs.kinesis.kcube_stepper_motor.rst:
--------------------------------------------------------------------------------
1 | msl\.equipment\.resources\.thorlabs\.kinesis\.kcube\_stepper\_motor module
2 | ==========================================================================
3 |
4 | .. automodule:: msl.equipment.resources.thorlabs.kinesis.kcube_stepper_motor
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.resources.optosigma.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.resources.optosigma package
2 | =========================================
3 |
4 | .. automodule:: msl.equipment.resources.optosigma
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
9 | Submodules
10 | ----------
11 |
12 | .. toctree::
13 |
14 | msl.equipment.resources.optosigma.shot702
15 |
16 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.resources.raicol.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.resources.raicol package
2 | ======================================
3 |
4 | .. automodule:: msl.equipment.resources.raicol
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
9 | Submodules
10 | ----------
11 |
12 | .. toctree::
13 | :maxdepth: 4
14 |
15 | msl.equipment.resources.raicol.raicol_tec
16 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.resources.thorlabs.kinesis.integrated_stepper_motors.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.resources.thorlabs.kinesis.integrated_stepper_motors module
2 | =========================================================================
3 |
4 | .. automodule:: msl.equipment.resources.thorlabs.kinesis.integrated_stepper_motors
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
--------------------------------------------------------------------------------
/packages/resources/src/msl/equipment_resources/isotech/__init__.py:
--------------------------------------------------------------------------------
1 | """Resources for equipment from [IsoTech](https://isotech.co.uk/)."""
2 |
3 | from __future__ import annotations
4 |
5 | from .millik import Current, MilliK, Resistance, Type, Voltage
6 |
7 | __all__: list[str] = [
8 | "Current",
9 | "MilliK",
10 | "Resistance",
11 | "Type",
12 | "Voltage",
13 | ]
14 |
--------------------------------------------------------------------------------
/packages/resources/src/msl/equipment_resources/mks/__init__.py:
--------------------------------------------------------------------------------
1 | """Resources for equipment from [MKS](https://www.mks.com/) Instruments."""
2 |
3 | from __future__ import annotations
4 |
5 | from .pr4000b import PR4000B, UNIT, LimitMode, SignalMode, Tag
6 |
7 | __all__: list[str] = [
8 | "PR4000B",
9 | "UNIT",
10 | "LimitMode",
11 | "SignalMode",
12 | "Tag",
13 | ]
14 |
--------------------------------------------------------------------------------
/packages/resources/src/msl/equipment_resources/optosigma/__init__.py:
--------------------------------------------------------------------------------
1 | """Resources for equipment from [OptoSigma](https://jp.optosigma.com/en_jp/)."""
2 |
3 | from __future__ import annotations
4 |
5 | from .shot702 import SHOT702, Mode, Speed, State, Status
6 |
7 | __all__: list[str] = [
8 | "SHOT702",
9 | "Mode",
10 | "Speed",
11 | "State",
12 | "Status",
13 | ]
14 |
--------------------------------------------------------------------------------
/tests/resources/mass/.hidden/bad.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | This is an invalid XML document, but since it is within a ".hidden" folder
4 | (folder name starts with .) this file is not parsed when Config.registers()
5 | recursively looks for register files within the tests directory.
6 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.resources.isotech.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.resources.isotech package
2 | =======================================
3 |
4 | .. automodule:: msl.equipment.resources.isotech
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
9 | Submodules
10 | ----------
11 |
12 | .. toctree::
13 | :maxdepth: 4
14 |
15 | msl.equipment.resources.isotech.millik
16 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.resources.energetiq.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.resources.energetiq package
2 | =========================================
3 |
4 | .. automodule:: msl.equipment.resources.energetiq
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
9 | Submodules
10 | ----------
11 |
12 | .. toctree::
13 | :maxdepth: 4
14 |
15 | msl.equipment.resources.energetiq.eq99
16 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.resources.greisinger.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.resources.greisinger package
2 | ==========================================
3 |
4 | .. automodule:: msl.equipment.resources.greisinger
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
9 | Submodules
10 | ----------
11 |
12 | .. toctree::
13 | :maxdepth: 4
14 |
15 | msl.equipment.resources.greisinger.gmh3000
16 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.resources.mks_instruments.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.resources.mks\_instruments package
2 | ================================================
3 |
4 | .. automodule:: msl.equipment.resources.mks_instruments
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
9 | Submodules
10 | ----------
11 |
12 | .. toctree::
13 |
14 | msl.equipment.resources.mks_instruments.pr4000b
15 |
--------------------------------------------------------------------------------
/docs/webapp.md:
--------------------------------------------------------------------------------
1 | # Web Application
2 |
3 | !!! info
4 | Development on the web application has not started.
5 |
6 | The web application provides a server for running a website that allows people to search for equipment records with equipment registers and (maybe) to add equipment records to a register.
7 |
8 | ## Install
9 |
10 | Eventually...
11 |
12 | ```console
13 | pip install msl-equipment-webapp
14 | ```
15 |
--------------------------------------------------------------------------------
/docs/api/backends/index.md:
--------------------------------------------------------------------------------
1 | # Backends
2 |
3 | The following classes may be used to interface with equipment using external packages
4 |
5 | * [NIDAQ][] — Use the [NIDAQmx](https://nidaqmx-python.readthedocs.io/en/stable/index.html) package to establish a connection to the equipment
6 | * [PyVISA][] — Use the [PyVISA](https://pyvisa.readthedocs.io/en/stable/index.html) package to establish a connection to the equipment
7 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.resources.electron_dynamics.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.resources.electron\_dynamics package
2 | ==================================================
3 |
4 | .. automodule:: msl.equipment.resources.electron_dynamics
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
9 | Submodules
10 | ----------
11 |
12 | .. toctree::
13 |
14 | msl.equipment.resources.electron_dynamics.tc_series
15 |
16 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.resources.vaisala.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.resources.vaisala package
2 | =======================================
3 |
4 | .. automodule:: msl.equipment.resources.vaisala
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
9 | Submodules
10 | ----------
11 |
12 | .. toctree::
13 | :maxdepth: 4
14 |
15 | msl.equipment.resources.vaisala.ptu300
16 | msl.equipment.resources.vaisala.ptb330
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.resources.dataray.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.resources.dataray package
2 | =======================================
3 |
4 | .. automodule:: msl.equipment.resources.dataray
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
9 | Submodules
10 | ----------
11 |
12 | .. toctree::
13 |
14 | msl.equipment.resources.dataray.datarayocx_32
15 | msl.equipment.resources.dataray.datarayocx_64
16 |
17 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.resources.princeton_instruments.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.resources.princeton\_instruments package
2 | ======================================================
3 |
4 | .. automodule:: msl.equipment.resources.princeton_instruments
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
9 | Submodules
10 | ----------
11 |
12 | .. toctree::
13 |
14 | msl.equipment.resources.princeton_instruments.arc_instrument
15 |
16 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.resources.optronic_laboratories.ol_current_source.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.resources.optronic\_laboratories.ol\_current\_source module
2 | =========================================================================
3 |
4 | .. automodule:: msl.equipment.resources.optronic_laboratories.ol_current_source
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 | :exclude-members: ol_current_source_factory, OLCurrentSourceGPIB, OLCurrentSourceASRL
9 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.resources.picotech.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.resources.picotech package
2 | ========================================
3 |
4 | .. automodule:: msl.equipment.resources.picotech
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
9 | Subpackages
10 | -----------
11 |
12 | .. toctree::
13 |
14 | msl.equipment.resources.picotech.errors
15 | msl.equipment.resources.picotech.picoscope
16 | msl.equipment.resources.picotech.pt104
17 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.resources.thorlabs.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.resources.thorlabs package
2 | ========================================
3 |
4 | .. automodule:: msl.equipment.resources.thorlabs
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
9 | Subpackages
10 | -----------
11 |
12 | .. toctree::
13 |
14 | msl.equipment.resources.thorlabs.kinesis
15 |
16 | Submodules
17 | ----------
18 |
19 | .. toctree::
20 |
21 | msl.equipment.resources.thorlabs.fwxx2c
22 |
23 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.resources.bentham.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.resources.bentham package
2 | =======================================
3 |
4 | .. automodule:: msl.equipment.resources.bentham
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
9 | Submodules
10 | ----------
11 |
12 | .. toctree::
13 |
14 | msl.equipment.resources.bentham.benhw32
15 | msl.equipment.resources.bentham.benhw64
16 | msl.equipment.resources.bentham.errors
17 | msl.equipment.resources.bentham.tokens
18 |
19 |
--------------------------------------------------------------------------------
/packages/resources/README.md:
--------------------------------------------------------------------------------
1 | # msl-equipment-resources
2 |
3 | Resources to communicate with equipment.
4 |
5 | ## Compatibility
6 | `msl-equipment` is tested with Python 3.8+ on Windows, Linux and macOS; however, some of the [resources] might not work for your application because the resource may depend on an external dependency (e.g., the SDK provided by a manufacturer) and this external dependency might not be available for your operating system.
7 |
8 | [resources]: https://msl-equipment.readthedocs.io/en/latest/resources.html
9 |
--------------------------------------------------------------------------------
/packages/validate/tests/conftest.py:
--------------------------------------------------------------------------------
1 | from __future__ import annotations
2 |
3 | import pytest
4 | from msl.equipment_validate.validate import Info, Summary
5 |
6 |
7 | @pytest.fixture
8 | def reset_summary() -> None:
9 | for item in dir(Summary):
10 | if item.startswith("num"):
11 | setattr(Summary, item, 0)
12 | elif item.startswith("unchecked"):
13 | setattr(Summary, item, ())
14 |
15 |
16 | @pytest.fixture
17 | def info() -> Info:
18 | return Info(url="register.xml", exit_first=False, uri_scheme=None, debug_name="Name", no_colour=True)
19 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.resources.optronic_laboratories.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.resources.optronic\_laboratories package
2 | ======================================================
3 |
4 | .. automodule:: msl.equipment.resources.optronic_laboratories
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
9 | Submodules
10 | ----------
11 |
12 | .. toctree::
13 | :maxdepth: 4
14 |
15 | msl.equipment.resources.optronic_laboratories.ol756ocx_32
16 | msl.equipment.resources.optronic_laboratories.ol756ocx_64
17 | msl.equipment.resources.optronic_laboratories.ol_current_source
18 |
--------------------------------------------------------------------------------
/docs/schema/equipment.md:
--------------------------------------------------------------------------------
1 | # Equipment
2 |
3 | ::: msl.equipment.schema.Equipment
4 | options:
5 | show_root_full_path: false
6 | show_root_heading: true
7 |
8 | ::: msl.equipment.schema.Latest
9 | options:
10 | show_root_full_path: false
11 | show_root_heading: true
12 |
13 | ::: msl.equipment.schema.LatestPerformanceCheck
14 | options:
15 | show_root_full_path: false
16 | show_root_heading: true
17 |
18 | ::: msl.equipment.schema.LatestReport
19 | options:
20 | show_root_full_path: false
21 | show_root_heading: true
22 |
--------------------------------------------------------------------------------
/packages/resources/examples/picotech/pt104_find.py:
--------------------------------------------------------------------------------
1 | """Print the PT-104 Data Logger's that are connected to the computer."""
2 |
3 | import os
4 |
5 | from msl.equipment.resources import PT104
6 |
7 | # Optional: Ensure that the Pico Technology SDK directory is available on PATH (if not already)
8 | # Alternatively, you can specify the full path to the library file as an argument to enumerate_units()
9 | os.environ["PATH"] += os.pathsep + r"C:\Program Files\Pico Technology\SDK\lib"
10 |
11 | print("The following PT-104's were found:")
12 | for unit in PT104.enumerate_units():
13 | print(f" {unit}")
14 |
--------------------------------------------------------------------------------
/docs/api/interfaces/index.md:
--------------------------------------------------------------------------------
1 | # Interfaces
2 |
3 | Generic interface classes for computer control
4 |
5 | * [Interface][msl.equipment.schema.Interface] — Base class for all interfaces
6 | * [MessageBased][msl.equipment.interfaces.message_based.MessageBased] — Base class for all message-based interfaces
7 |
8 | ::: msl.equipment.schema.Interface
9 | options:
10 | show_root_full_path: false
11 | show_root_heading: true
12 |
13 | ::: msl.equipment.interfaces.message_based.MessageBased
14 | options:
15 | show_root_full_path: false
16 | show_root_heading: true
17 |
--------------------------------------------------------------------------------
/packages/resources/examples/picotech/ps5000a_find.py:
--------------------------------------------------------------------------------
1 | """Print the PicoScopes that are connected to the computer."""
2 |
3 | import os
4 |
5 | from msl.equipment.resources import PicoScope
6 |
7 | # Optional: Ensure that the Pico Technology SDK directory is available on PATH (if not already)
8 | # Alternatively, you can specify the full path to the library file as an argument to enumerate_units()
9 | os.environ["PATH"] += os.pathsep + r"C:\Program Files\Pico Technology\SDK\lib"
10 |
11 | print("The following PicoScope's were found:")
12 | for unit in PicoScope.enumerate_units("ps5000a"):
13 | print(f" {unit}")
14 |
--------------------------------------------------------------------------------
/packages/resources/src/msl/equipment/resources/thorlabs/__init__.py:
--------------------------------------------------------------------------------
1 | """
2 | Resources for equipment from `Thorlabs `_.
3 | """
4 | from __future__ import annotations
5 |
6 | from .fwxx2c import FilterWheelXX2C
7 | from .kinesis import enums
8 | from .kinesis import structs
9 | from .kinesis.benchtop_stepper_motor import BenchtopStepperMotor
10 | from .kinesis.callbacks import MotionControlCallback
11 | from .kinesis.filter_flipper import FilterFlipper
12 | from .kinesis.integrated_stepper_motors import IntegratedStepperMotors
13 | from .kinesis.kcube_dc_servo import KCubeDCServo
14 | from .kinesis.kcube_solenoid import KCubeSolenoid
15 | from .kinesis.kcube_stepper_motor import KCubeStepperMotor
16 | from .kinesis.motion_control import MotionControl
17 |
--------------------------------------------------------------------------------
/packages/resources/src/msl/equipment_resources/electron_dynamics/__init__.py:
--------------------------------------------------------------------------------
1 | """Resources for equipment from Electron Dynamics Ltd."""
2 |
3 | from __future__ import annotations
4 |
5 | from .tc_series import (
6 | Alarm,
7 | AlarmType,
8 | Control,
9 | ControlType,
10 | Method,
11 | Output,
12 | Polarity,
13 | PowerUpState,
14 | Sensor,
15 | SensorType,
16 | Setpoint,
17 | Status,
18 | TCSeries,
19 | Unit,
20 | )
21 |
22 | __all__: list[str] = [
23 | "Alarm",
24 | "AlarmType",
25 | "Control",
26 | "ControlType",
27 | "Method",
28 | "Output",
29 | "Polarity",
30 | "PowerUpState",
31 | "Sensor",
32 | "SensorType",
33 | "Setpoint",
34 | "Status",
35 | "TCSeries",
36 | "Unit",
37 | ]
38 |
--------------------------------------------------------------------------------
/src/msl/equipment/interfaces/__init__.py:
--------------------------------------------------------------------------------
1 | """Interfaces for computer control."""
2 |
3 | from __future__ import annotations
4 |
5 | from .gpib import GPIB
6 | from .hislip import HiSLIP
7 | from .message_based import MessageBased, MSLConnectionError, MSLTimeoutError
8 | from .nidaq import NIDAQ
9 | from .prologix import Prologix
10 | from .pyvisa import PyVISA
11 | from .sdk import SDK
12 | from .serial import Serial
13 | from .socket import Socket
14 | from .vxi11 import VXI11
15 | from .zeromq import ZeroMQ
16 |
17 | __all__: list[str] = [
18 | "GPIB",
19 | "NIDAQ",
20 | "SDK",
21 | "VXI11",
22 | "HiSLIP",
23 | "MSLConnectionError",
24 | "MSLTimeoutError",
25 | "MessageBased",
26 | "Prologix",
27 | "PyVISA",
28 | "Serial",
29 | "Socket",
30 | "ZeroMQ",
31 | ]
32 |
--------------------------------------------------------------------------------
/tests/resources/config.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 30
5 | true
6 | OD: 2.0
7 |
8 | smtp.server.nz
9 | 25
10 | me@measurement.govt.nz
11 | you@measurement.govt.nz
12 |
13 |
14 |
15 |
16 |
17 |
18 | tests/resources/mass
19 | tests/resources/light
20 |
21 | tests/resources/connections.xml
22 |
23 |
--------------------------------------------------------------------------------
/docs-old/_static/custom.css:
--------------------------------------------------------------------------------
1 | .red {
2 | color: red;
3 | }
4 |
5 | .blue {
6 | color: blue;
7 | font-style: italic;
8 | }
9 |
10 | /* allow table to wrap the text */
11 | .wy-table-responsive table th {
12 | white-space: normal;
13 | }
14 |
15 | /* fix rendering of @property methods on ReadTheDocs */
16 | .rst-content dl:not(.docutils) .property {
17 | display: revert;
18 | }
19 | html.writer-html4 .rst-content dl:not(.docutils) .property, html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.glossary):not(.simple) .property {
20 | display: revert;
21 | }
22 | html.writer-html4 .rst-content dl:not(.docutils) .property, html.writer-html5 .rst-content dl[class]:not(.option-list):not(.field-list):not(.footnote):not(.citation):not(.glossary):not(.simple) .property {
23 | display: revert;
24 | padding-right: 8px;
25 | max-width: 100%;
26 | }
--------------------------------------------------------------------------------
/packages/resources/examples/omega/ithx.py:
--------------------------------------------------------------------------------
1 | """Example showing how to communicate with an OMEGA iTHX Series Temperature and Humidity Chart Recorder."""
2 |
3 | from __future__ import annotations
4 |
5 | from typing import TYPE_CHECKING
6 |
7 | from msl.equipment import Connection
8 |
9 | if TYPE_CHECKING:
10 | from msl.equipment.resources import ITHX
11 |
12 |
13 | connection = Connection(
14 | "TCP::192.168.1.100::2000", # update for your OMEGA iServer
15 | manufacturer="OMEGA",
16 | model="iTHX-W3", # update for your OMEGA iServer
17 | timeout=2,
18 | )
19 |
20 | # Connect to the iServer
21 | ithx: ITHX = connection.connect()
22 |
23 | # Read the temperature, relative humidity and dewpoint
24 | print(f"T {ithx.temperature()} °C")
25 | print(f"H {ithx.humidity()} %")
26 | print(f"DP {ithx.dewpoint(celsius=False)} °F")
27 |
28 | # Disconnect from the iServer
29 | ithx.disconnect()
30 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Release Notes
2 |
3 | ---
4 |
5 | ## 0.2.0 (2025-03-28)
6 |
7 | ***Added:***
8 |
9 | - support for Python 3.12 and 3.13
10 | - `find-equipment` console script
11 | - `msl.equipment.connection_gpib.ConnectionGPIB` class
12 | - `msl.equipment.resources.greisinger.gmh3000.GMH3000` resource
13 | - `msl.equipment.resources.isotech.millik.MilliK` resource
14 | - `msl.equipment.resources.vaisala.ptu300.PTU300` resource
15 | - `msl.equipment.resources.vaisala.ptb330.PTB330` resource
16 |
17 | ***Fixed:***
18 |
19 | - issue [#9](https://github.com/MSLNZ/msl-equipment/issues/9) — Missing functions from Avantes AvaSpec DLL
20 | - issue [#8](https://github.com/MSLNZ/msl-equipment/issues/8) — Invalid URL for LXI XML identification document
21 |
22 | ***Removed:***
23 |
24 | - support for Python 2.7, 3.5, 3.6 and 3.7
25 |
26 | ## 0.1.0 (2023-06-18)
27 |
28 | Initial release.
29 |
30 | It is also the last release to support Python 2.7, 3.5, 3.6 and 3.7
31 |
--------------------------------------------------------------------------------
/.github/workflows/ci.yml:
--------------------------------------------------------------------------------
1 | name: CI
2 |
3 | on: [push, pull_request]
4 |
5 | env:
6 | PY_COLORS: 1
7 | COLUMNS: 110
8 |
9 | jobs:
10 | test:
11 | name: Test
12 | runs-on: ${{ matrix.os }}-latest
13 | timeout-minutes: 10
14 | strategy:
15 | fail-fast: false
16 | matrix:
17 | os: [ubuntu, windows, macos]
18 | python-version: ["3.8", "3.9", "3.10", "3.11", "3.12", "3.13", "3.14"]
19 | steps:
20 | - name: Checkout repository
21 | uses: actions/checkout@v5
22 | - name: Install locales (Ubuntu)
23 | if: ${{ matrix.os == 'ubuntu' }}
24 | run: |
25 | sudo apt-get update
26 | sudo apt-get install -y language-pack-en language-pack-de
27 | - name: Install uv
28 | uses: astral-sh/setup-uv@v6
29 | with:
30 | enable-cache: false
31 | - name: Run tests
32 | run: uv run --all-packages --python ${{ matrix.python-version }} --no-dev --group test -- pytest
33 |
--------------------------------------------------------------------------------
/packages/resources/examples/avantes/find_devices.py:
--------------------------------------------------------------------------------
1 | """Example showing how to find all AvaSpec devices that are available.
2 |
3 | The AvaSpec shared library may require a Visual C++ Redistributable Package to be installed (on Windows).
4 | """
5 |
6 | import os
7 |
8 | from msl.equipment.resources import AvaSpec
9 |
10 | # You can either specify the full path to the SDK
11 | # (e.g., C:/AvaSpecX64-DLL_9.7/avaspecx64.dll) in the Avantes.find()
12 | # function, or, you can add the directory where the avaspecx64 library file is located
13 | # to your PATH environment variable
14 | os.environ["PATH"] += os.pathsep + r"C:\AvaSpecX64-DLL_9.7"
15 |
16 | devices = AvaSpec.find()
17 | if devices:
18 | print("Found the following Avantes devices: ")
19 | for device in devices:
20 | print(f" SerialNumber: {device.SerialNumber}")
21 | print(f" UserFriendlyName: {device.UserFriendlyName}")
22 | print(f" Status: {device.Status}")
23 | else:
24 | print("Could not find any AvaSpec devices")
25 |
--------------------------------------------------------------------------------
/docs/resources/avantes/avaspec.md:
--------------------------------------------------------------------------------
1 | # AvaSpec SDK
2 |
3 | Wrapper around the `avaspec` SDK from [Avantes](https://www.avantes.com/){:target="_blank"}.
4 |
5 | The wrapper was written using v9.7.0.0 of the SDK. The `avaspec` SDK may require a Visual C++ Redistributable Package to be installed (on Windows).
6 |
7 | The main class is [AvaSpec][msl.equipment_resources.avantes.avaspec.AvaSpec] and the [Enums and Structs][avaspec-enums-structs] are available once the `avantes` module is imported, for example,
8 |
9 | ```python
10 | from msl.equipment.resources import avantes
11 |
12 | cfg = avantes.MeasConfigType()
13 | cfg.m_IntegrationTime = 5 # in milliseconds
14 | cfg.m_NrAverages = 1 # number of averages
15 | ```
16 |
17 | ::: msl.equipment_resources.avantes.avaspec.AvaSpec
18 | options:
19 | show_root_full_path: false
20 | show_root_heading: true
21 |
22 | ## Enums and Structs {: #avaspec-enums-structs }
23 |
24 | ::: msl.equipment_resources.avantes.avaspec
25 | options:
26 | filters: ["!AvaSpec"]
27 |
--------------------------------------------------------------------------------
/packages/resources/examples/raicol/tec_oven.py:
--------------------------------------------------------------------------------
1 | """Example showing how to control a TEC (Peltier-based) oven from Raicol Crystals."""
2 |
3 | from __future__ import annotations
4 |
5 | import time
6 | from typing import TYPE_CHECKING
7 |
8 | from msl.equipment import Connection
9 |
10 | if TYPE_CHECKING:
11 | from msl.equipment.resources import RaicolTEC
12 |
13 | connection = Connection(
14 | "COM4", # update for your oven
15 | manufacturer="Raicol Crystals",
16 | model="TEC 20-60",
17 | )
18 |
19 | # connect to the TEC controller
20 | tec: RaicolTEC = connection.connect()
21 |
22 | # set the setpoint temperature, in Celsius
23 | tec.set_setpoint(25.0)
24 |
25 | # get the setpoint temperature
26 | print("setpoint=", tec.get_setpoint())
27 |
28 | # turn the TEC on
29 | tec.on()
30 |
31 | # read the current temperature
32 | for _ in range(30):
33 | time.sleep(1)
34 | print("temperature=", tec.temperature())
35 |
36 | # turn the TEC off
37 | tec.off()
38 |
39 | # disconnect from the TEC controller
40 | tec.disconnect()
41 |
--------------------------------------------------------------------------------
/packages/resources/examples/cmi/sia.py:
--------------------------------------------------------------------------------
1 | """Example showing how to communicate with a Switched Integrator Amplifier (SIA)."""
2 |
3 | from __future__ import annotations
4 |
5 | from typing import TYPE_CHECKING
6 |
7 | from msl.equipment import Connection
8 | from msl.equipment.resources import cmi
9 |
10 | if TYPE_CHECKING:
11 | from msl.equipment.resources import SIA3
12 |
13 | connection = Connection(
14 | "COM3", # update for your amplifier
15 | manufacturer="CMI",
16 | model="SIA3",
17 | )
18 |
19 | # Connect to the amplifier
20 | sia: SIA3 = connection.connect()
21 |
22 | # These are equivalent to set the pre-scale factor to 7
23 | sia.set_ps(cmi.PreScale.PS_7) # use the enum
24 | sia.set_ps(7) # use the enum value
25 |
26 | # These are equivalent to set the integration time to 2 seconds
27 | sia.set_integration_time(cmi.IntegrationTime.TIME_2s) # use the enum
28 | sia.set_integration_time("2s") # use the last part of the enum member name
29 | sia.set_integration_time(14) # use the enum value
30 |
31 | # Disconnect from the amplifier
32 | sia.disconnect()
33 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.record_types.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.record_types module
2 | =================================
3 |
4 | Records from :ref:`equipment-database`\'s or :ref:`connections-database`\'s.
5 |
6 | .. autoclass:: msl.equipment.record_types.EquipmentRecord
7 | :members:
8 | :show-inheritance:
9 | :inherited-members:
10 |
11 | .. autoclass:: msl.equipment.record_types.CalibrationRecord
12 | :members:
13 | :show-inheritance:
14 | :inherited-members:
15 |
16 | .. autoclass:: msl.equipment.record_types.MeasurandRecord
17 | :members:
18 | :show-inheritance:
19 | :inherited-members:
20 |
21 | .. autoclass:: msl.equipment.record_types.MaintenanceRecord
22 | :members:
23 | :show-inheritance:
24 | :inherited-members:
25 |
26 | .. autoclass:: msl.equipment.record_types.ConnectionRecord
27 | :members:
28 | :show-inheritance:
29 | :inherited-members:
30 |
31 | .. autoclass:: msl.equipment.record_types.RecordDict
32 | :members:
33 | :show-inheritance:
34 | :no-undoc-members:
35 |
36 | .. autoclass:: msl.equipment.record_types.Record
37 | :members:
38 | :show-inheritance:
39 |
--------------------------------------------------------------------------------
/packages/resources/src/msl/equipment_resources/nkt/__init__.py:
--------------------------------------------------------------------------------
1 | """Resources for equipment from [NKT Photonics](https://www.nktphotonics.com/)."""
2 |
3 | from __future__ import annotations
4 |
5 | from .nktpdll import (
6 | NKT,
7 | DateTime,
8 | DeviceMode,
9 | DeviceStatus,
10 | DeviceStatusCallback,
11 | ParameterSet,
12 | PointToPoint,
13 | PortStatus,
14 | PortStatusCallback,
15 | RegisterData,
16 | RegisterPriority,
17 | RegisterStatus,
18 | RegisterStatusCallback,
19 | Unit,
20 | device_status_callback,
21 | port_status_callback,
22 | register_status_callback,
23 | )
24 |
25 | __all__: list[str] = [
26 | "NKT",
27 | "DateTime",
28 | "DeviceMode",
29 | "DeviceStatus",
30 | "DeviceStatusCallback",
31 | "ParameterSet",
32 | "PointToPoint",
33 | "PortStatus",
34 | "PortStatusCallback",
35 | "RegisterData",
36 | "RegisterPriority",
37 | "RegisterStatus",
38 | "RegisterStatusCallback",
39 | "Unit",
40 | "device_status_callback",
41 | "port_status_callback",
42 | "register_status_callback",
43 | ]
44 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.resources.thorlabs.kinesis.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.resources.thorlabs.kinesis package
2 | ================================================
3 |
4 | .. automodule:: msl.equipment.resources.thorlabs.kinesis
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
9 | Submodules
10 | ----------
11 |
12 | .. toctree::
13 |
14 | msl.equipment.resources.thorlabs.kinesis.api_functions
15 | msl.equipment.resources.thorlabs.kinesis.benchtop_stepper_motor
16 | msl.equipment.resources.thorlabs.kinesis.callbacks
17 | msl.equipment.resources.thorlabs.kinesis.enums
18 | msl.equipment.resources.thorlabs.kinesis.errors
19 | msl.equipment.resources.thorlabs.kinesis.filter_flipper
20 | msl.equipment.resources.thorlabs.kinesis.integrated_stepper_motors
21 | msl.equipment.resources.thorlabs.kinesis.kcube_dc_servo
22 | msl.equipment.resources.thorlabs.kinesis.kcube_solenoid
23 | msl.equipment.resources.thorlabs.kinesis.kcube_stepper_motor
24 | msl.equipment.resources.thorlabs.kinesis.messages
25 | msl.equipment.resources.thorlabs.kinesis.motion_control
26 | msl.equipment.resources.thorlabs.kinesis.structs
27 |
--------------------------------------------------------------------------------
/src/msl/equipment/record_types.py:
--------------------------------------------------------------------------------
1 | """Deprecated classes."""
2 |
3 | from __future__ import annotations
4 |
5 | import warnings
6 | from typing import Any
7 |
8 | from .schema import Connection, Equipment
9 |
10 |
11 | class _Warn:
12 | show: bool = True
13 |
14 | @staticmethod
15 | def warn() -> None:
16 | msg = (
17 | "The EquipmentRecord and ConnectionRecord classes are deprecated and will be removed in a future release. "
18 | "Replace `EquipmentRecord` with `Equipment` and replace `ConnectionRecord` with `Connection`."
19 | )
20 | warnings.warn(msg, FutureWarning, stacklevel=3)
21 | _Warn.show = False
22 |
23 |
24 | def EquipmentRecord(**kwargs: Any) -> Equipment: # noqa: ANN401, N802
25 | """Deprecated. Replace `EquipmentRecord` with `Equipment`."""
26 | if _Warn.show:
27 | _Warn.warn()
28 | return Equipment(**kwargs)
29 |
30 |
31 | def ConnectionRecord(**kwargs: Any) -> Connection: # noqa: ANN401, N802
32 | """Deprecated. Replace `ConnectionRecord` with `Connection`."""
33 | if _Warn.show:
34 | _Warn.warn()
35 | return Connection(**kwargs)
36 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2017 - 2025, Measurement Standards Laboratory of New Zealand
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.resources.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.resources package
2 | ===============================
3 |
4 | .. automodule:: msl.equipment.resources
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
9 | Submodules
10 | ----------
11 |
12 | .. toctree::
13 |
14 | msl.equipment.resources.utils
15 |
16 | Subpackages
17 | -----------
18 |
19 | .. toctree::
20 |
21 | msl.equipment.resources.aim_tti
22 | msl.equipment.resources.avantes
23 | msl.equipment.resources.bentham
24 | msl.equipment.resources.cmi
25 | msl.equipment.resources.dataray
26 | msl.equipment.resources.electron_dynamics
27 | msl.equipment.resources.energetiq
28 | msl.equipment.resources.greisinger
29 | msl.equipment.resources.isotech
30 | msl.equipment.resources.mks_instruments
31 | msl.equipment.resources.nkt
32 | msl.equipment.resources.omega
33 | msl.equipment.resources.optosigma
34 | msl.equipment.resources.optronic_laboratories
35 | msl.equipment.resources.picotech
36 | msl.equipment.resources.princeton_instruments
37 | msl.equipment.resources.raicol
38 | msl.equipment.resources.thorlabs
39 | msl.equipment.resources.vaisala
40 |
--------------------------------------------------------------------------------
/packages/resources/LICENSE.txt:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2025, Measurement Standards Laboratory of New Zealand
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/packages/validate/LICENSE.txt:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2025, Measurement Standards Laboratory of New Zealand
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
--------------------------------------------------------------------------------
/packages/resources/examples/mks/pr4000b.py:
--------------------------------------------------------------------------------
1 | """Example showing how to communicate with a PR4000B Flow and Pressure controller from MKS."""
2 |
3 | from __future__ import annotations
4 |
5 | from typing import TYPE_CHECKING
6 |
7 | from msl.equipment import Connection, Parity
8 |
9 | if TYPE_CHECKING:
10 | from msl.equipment.resources import PR4000B
11 |
12 |
13 | connection = Connection(
14 | "COM3", # update for your controller
15 | manufacturer="MKS Instruments",
16 | model="PR4000BF2V2",
17 | baud_rate=9600, # the baud rate can be changed on the PR4000B
18 | parity=Parity.ODD, # the parity can be changed on the PR4000B
19 | )
20 |
21 | # connect to the controller
22 | mks: PR4000B = connection.connect()
23 |
24 | # get the identity of the controller
25 | identity = mks.identity()
26 | print(f"Identity: {identity}")
27 |
28 | # reset to the default pressure configuration
29 | mks.default("pressure")
30 |
31 | # set the pressure range for channel 2 to be 133 Pa
32 | mks.set_range(2, 133, "Pa")
33 |
34 | # read the pressure from channel 2
35 | pressure = mks.get_actual_value(2)
36 | print(f"pressure: {pressure}")
37 |
38 | # disconnect from the controller
39 | mks.disconnect()
40 |
--------------------------------------------------------------------------------
/packages/resources/examples/electron_dynamics/tc_series.py:
--------------------------------------------------------------------------------
1 | """Example showing how to communicate with a TC Series Temperature Controller from Electron Dynamics Ltd."""
2 |
3 | from __future__ import annotations
4 |
5 | from typing import TYPE_CHECKING
6 |
7 | from msl.equipment import Connection
8 | from msl.equipment.resources import electron_dynamics as ed
9 |
10 | if TYPE_CHECKING:
11 | from msl.equipment.resources import TCSeries
12 |
13 |
14 | connection = Connection(
15 | "COM5", # update for your controller
16 | manufacturer="Electron Dynamics",
17 | model="TC Lite",
18 | )
19 |
20 | # Connect to the Temperature Controller
21 | tc: TCSeries = connection.connect()
22 |
23 | # Get all available information about the Temperature Controller
24 | print(f"alarm: {tc.get_alarm()}")
25 | print(f"control: {tc.get_control()}")
26 | print(f"output: {tc.get_output()}")
27 | print(f"sensor: {tc.get_sensor()}")
28 | print(f"setpoint: {tc.get_setpoint()}")
29 | print(f"status: {tc.get_status()}")
30 |
31 | # Set the sensor to be PT100
32 | tc.set_sensor(ed.Sensor(type=ed.SensorType.PT100, x2=0, x=0.722, c=0.02, unit=ed.Unit.C, averaging=False))
33 |
34 | # Disconnect from the Controller
35 | tc.disconnect()
36 |
--------------------------------------------------------------------------------
/packages/resources/examples/thorlabs/fw212c.py:
--------------------------------------------------------------------------------
1 | """Example showing how to communicate with a FW102C/FW212C Motorized Filter Wheel."""
2 |
3 | from __future__ import annotations
4 |
5 | from typing import TYPE_CHECKING
6 |
7 | from msl.equipment import Connection
8 |
9 | if TYPE_CHECKING:
10 | from msl.equipment.resources import FWxx2C
11 |
12 |
13 | connection = Connection(
14 | "COM6",
15 | manufacturer="Thorlabs",
16 | model="FW212C", # alternatively FW102C (can also include the NEB suffix)
17 | )
18 |
19 | # Connect to the filter wheel
20 | wheel: FWxx2C = connection.connect()
21 |
22 | # Print the mode settings
23 | print(f"Is in fast speed mode? {wheel.fast_mode}")
24 | print(f"Are sensors always on? {wheel.sensor_mode}")
25 | print(f"Is in output trigger mode? {wheel.output_mode}")
26 |
27 | # Make the filter wheel return to the first position if it is at
28 | # the last position, otherwise increment to the next position
29 | print(f"Initial position is {wheel.position}")
30 |
31 | if wheel.position == wheel.position_count:
32 | wheel.position = 1
33 | else:
34 | wheel.position += 1
35 |
36 | print(f"Final position is {wheel.position}")
37 |
38 | # Disconnect from the filter wheel
39 | wheel.disconnect()
40 |
--------------------------------------------------------------------------------
/packages/resources/examples/vaisala/ptb330.py:
--------------------------------------------------------------------------------
1 | """Example showing how to communicate with a Vaisala PTB330 Barometer."""
2 |
3 | from __future__ import annotations
4 |
5 | from pprint import pprint
6 | from typing import TYPE_CHECKING
7 |
8 | from msl.equipment import Connection
9 |
10 | if TYPE_CHECKING:
11 | from msl.equipment.resources import PTB330
12 |
13 |
14 | connection = Connection(
15 | "COM3", # update for your device
16 | manufacturer="Vaisala",
17 | model="PTB330",
18 | serial="L2310094",
19 | )
20 |
21 | # Connect to the device
22 | ptb: PTB330 = connection.connect()
23 |
24 | # Display information about the device
25 | pprint(ptb.device_info)
26 |
27 | # A mapping between a quantity and the unit to use for the quantity
28 | ptb.set_units({"P": "hPa", "P3h": "mbar", "TP1": "'C"})
29 | print("Units set:", ptb.units)
30 |
31 | # Set the format that data will be returned as
32 | ptb.set_format('4.3 P " " 4.3 P3h " " 2.1 TP1 #r #n')
33 |
34 | # There are two ways to check the format string that has been set
35 | print(ptb.get_format())
36 | print(ptb.device_info["Output format"])
37 |
38 | # Get a reading from the device (in the specified format)
39 | print(ptb.get_reading_str())
40 |
41 | # Disconnect from the device
42 | ptb.disconnect()
43 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | > [!IMPORTANT]
2 | > This repository is undergoing a significant refactoring. Do not install from source since it will be in an unknown state. The next release will have breaking changes with the v0.x release series.
3 |
4 | # MSL-Equipment
5 |
6 | [](https://github.com/MSLNZ/msl-equipment/actions/workflows/ci.yml)
7 | [](https://github.com/MSLNZ/msl-equipment/actions/workflows/docs.yml)
8 |
9 | The purpose of `msl-equipment` is to manage information about equipment and to interface with equipment for computer control. The information that is managed is focused on testing and calibration laboratories that are accredited for the [ISO/IEC 17025] standard.
10 |
11 | ## Install
12 | To install `msl-equipment` run
13 |
14 | ```console
15 | pip install https://github.com/MSLNZ/msl-equipment/releases/download/v0.2.0/msl_equipment-0.2.0-py3-none-any.whl
16 | ```
17 |
18 | ## Documentation
19 | The documentation for `msl-equipment` can be found [here].
20 |
21 | [ISO/IEC 17025]: https://www.iso.org/ISO-IEC-17025-testing-and-calibration-laboratories.html
22 | [here]: https://mslnz.github.io/msl-equipment/dev/
--------------------------------------------------------------------------------
/docs/schema/index.md:
--------------------------------------------------------------------------------
1 | # Schema Classes
2 |
3 | Class representations of the [XML Schema Definition](https://mslnz.github.io/equipment-register-schema/latest/){:target="_blank"} for an equipment register.
4 |
5 | The primary class is [Register][] which contains a sequence of [Equipment][] classes that are each composed of the following classes:
6 |
7 | * [AcceptanceCriteria][]
8 | * [Accessories][]
9 | * [Adjustment][]
10 | * [Alteration][]
11 | * [CapitalExpenditure][]
12 | * [Competency][]
13 | * [CompletedTask][]
14 | * [Component][]
15 | * [Conditions][]
16 | * [CVDEquation][] (Callendar-Van Dusen equation, uses the [cvdCoefficients][type_cvdCoefficients]{:target="_blank"})
17 | * [Deserialised][] (opposite of [serialised][type_serialised]{:target="_blank"})
18 | * [DigitalReport][]
19 | * [Equation][]
20 | * [File][]
21 | * [Financial][]
22 | * [Firmware][]
23 | * [Maintenance][]
24 | * [Measurand][]
25 | * [PerformanceCheck][]
26 | * [PlannedTask][]
27 | * [QualityManual][]
28 | * [ReferenceMaterials][]
29 | * [Report][]
30 | * [Specifications][]
31 | * [SpecifiedRequirements][]
32 | * [Status][]
33 | * [Table][]
34 |
35 | The [Any][] class is used as a base class for elements that are currently represented by the [any][type_any]{:target="_blank"} type in the XML Schema Definition.
36 |
--------------------------------------------------------------------------------
/packages/resources/examples/princeton_instruments/find_devices.py:
--------------------------------------------------------------------------------
1 | """Example showing how to find all devices from Princeton Instruments."""
2 |
3 | from msl.equipment.resources import PrincetonInstruments
4 |
5 | # Load the SDK (update the path for your computer)
6 | PrincetonInstruments.init(r"C:\Program Files (x86)\Princeton Instruments\ARC_Instrument_x64.dll")
7 |
8 | major, minor, build = PrincetonInstruments.ver()
9 | print(f"Using version {major}.{minor}.{build} of the SDK")
10 |
11 | # Find all devices from Princeton Instruments
12 | num_found = PrincetonInstruments.search_for_inst()
13 | print(f"Found {num_found} device(s):")
14 | for enum in range(num_found):
15 | model = PrincetonInstruments.get_enum_preopen_model(enum)
16 | serial = PrincetonInstruments.get_enum_preopen_serial(enum)
17 | port = PrincetonInstruments.get_enum_preopen_com(enum)
18 | print(f" Model#: {model!r}, Serial#: {serial} -> at COM{port}")
19 |
20 | # List all Monochromator's that are available
21 | print("Monochromator's available:")
22 | for enum in range(num_found):
23 | try:
24 | model = PrincetonInstruments.get_mono_preopen_model(enum)
25 | except RuntimeError:
26 | continue
27 | else:
28 | print(f" {model!r} at COM{PrincetonInstruments.get_enum_preopen_com(enum)}")
29 |
--------------------------------------------------------------------------------
/packages/resources/examples/vaisala/ptu300.py:
--------------------------------------------------------------------------------
1 | """Example showing how to communicate with a Vaisala PTU300-series Barometer."""
2 |
3 | from __future__ import annotations
4 |
5 | from pprint import pprint
6 | from typing import TYPE_CHECKING
7 |
8 | from msl.equipment import Connection
9 |
10 | if TYPE_CHECKING:
11 | from msl.equipment.resources import PTU300
12 |
13 |
14 | connection = Connection(
15 | "COM3", # update for your device
16 | manufacturer="Vaisala",
17 | model="PTU300",
18 | serial="P4040154",
19 | )
20 |
21 | # Connect to the device
22 | ptu: PTU300 = connection.connect()
23 |
24 | # Display information about the device
25 | pprint(ptu.device_info)
26 |
27 | # A mapping between a quantity and the unit to use for the quantity
28 | ptu.set_units({"P": "hPa", "P3h": "hPa", "T": "'C", "RH": "%RH"})
29 | print("Units set:", ptu.units)
30 |
31 | # Set the format that data will be returned as
32 | ptu.set_format('4.3 P " " U5 " " 3.3 T " " U5" " 3.3 RH " " U5" " SN " " #r #n')
33 |
34 | # There are two ways to check the format string that has been set
35 | print(ptu.get_format())
36 | print(ptu.device_info["Output format"])
37 |
38 | # Get a reading from the device (in the specified format)
39 | print(ptu.get_reading_str())
40 |
41 | # Disconnect from the device
42 | ptu.disconnect()
43 |
--------------------------------------------------------------------------------
/packages/resources/examples/energetiq/eq99.py:
--------------------------------------------------------------------------------
1 | """Example showing how to communicate with an EQ-99 Manager from Energetiq."""
2 |
3 | from __future__ import annotations
4 |
5 | import time
6 | from typing import TYPE_CHECKING
7 |
8 | from msl.equipment import Connection
9 |
10 | if TYPE_CHECKING:
11 | from msl.equipment.resources import EQ99
12 |
13 | connection = Connection(
14 | "COM6", # update for your Manager
15 | manufacturer="Energetiq",
16 | model="EQ-99",
17 | )
18 |
19 | # connect to the Manager
20 | eq99: EQ99 = connection.connect()
21 |
22 | # get the total number of running hours of the lamp
23 | print(f"Lamp runtime is {eq99.get_lamp_runtime()} hours")
24 |
25 | # turn the output on
26 | eq99.set_output_state(enable=True)
27 |
28 | # wait for the lamp to turn on
29 | t0 = time.time()
30 | while True:
31 | bit_mask = eq99.condition_register()
32 | if bit_mask & 1 << 5: # index 5 represents the "Lamp on" state
33 | print("Lamp is on")
34 | break
35 |
36 | time.sleep(1)
37 | dt = int(time.time() - t0)
38 | print(f"Elapsed time: {dt} seconds, bit mask: {bit_mask}")
39 |
40 | # do other stuff while the lamp is on
41 | time.sleep(5)
42 |
43 | # turn the output off when done
44 | eq99.set_output_state(enable=False)
45 |
46 | # disconnect from the Manager
47 | eq99.disconnect()
48 |
--------------------------------------------------------------------------------
/packages/resources/src/msl/equipment/resources/thorlabs/kinesis/callbacks.py:
--------------------------------------------------------------------------------
1 | """
2 | A callback to register for a :class:`~msl.equipment.resources.thorlabs.kinesis.motion_control.MotionControl`
3 | message queue.
4 |
5 | .. code-block:: python
6 |
7 | from msl.equipment import Config
8 | from msl.equipment.resources.thorlabs import MotionControlCallback
9 |
10 | @MotionControlCallback
11 | def msg_callback():
12 | print('MotionControlCallback: ', flipper.convert_message(*flipper.get_next_message()))
13 |
14 | # The "example2.xml" configuration file contains the following element:
15 | #
16 |
17 | db = Config('config.xml').database()
18 |
19 | flipper = db.equipment['filter_flipper'].connect()
20 | flipper.register_message_callback(msg_callback)
21 |
22 | # ... do stuff with the `flipper` ...
23 |
24 | """
25 | from __future__ import annotations
26 |
27 | import sys
28 |
29 | if sys.platform == 'win32':
30 | from ctypes import WINFUNCTYPE
31 | FUNCTYPE = WINFUNCTYPE
32 | else:
33 | from ctypes import CFUNCTYPE
34 | FUNCTYPE = CFUNCTYPE
35 |
36 | MotionControlCallback = FUNCTYPE(None)
37 | """
38 | A callback to register for a :class:`~msl.equipment.resources.thorlabs.kinesis.motion_control.MotionControl`
39 | message queue.
40 | """
41 |
--------------------------------------------------------------------------------
/docs-old/_api/msl.equipment.resources.picotech.picoscope.rst:
--------------------------------------------------------------------------------
1 | msl.equipment.resources.picotech.picoscope package
2 | ==================================================
3 |
4 | .. automodule:: msl.equipment.resources.picotech.picoscope
5 | :members:
6 | :undoc-members:
7 | :show-inheritance:
8 |
9 | Submodules
10 | ----------
11 |
12 | .. toctree::
13 |
14 | msl.equipment.resources.picotech.picoscope.callbacks
15 | msl.equipment.resources.picotech.picoscope.channel
16 | msl.equipment.resources.picotech.picoscope.enums
17 | msl.equipment.resources.picotech.picoscope.functions
18 | msl.equipment.resources.picotech.picoscope.helper
19 | msl.equipment.resources.picotech.picoscope.picoscope
20 | msl.equipment.resources.picotech.picoscope.picoscope_2k3k
21 | msl.equipment.resources.picotech.picoscope.picoscope_api
22 | msl.equipment.resources.picotech.picoscope.ps2000
23 | msl.equipment.resources.picotech.picoscope.ps2000a
24 | msl.equipment.resources.picotech.picoscope.ps3000
25 | msl.equipment.resources.picotech.picoscope.ps3000a
26 | msl.equipment.resources.picotech.picoscope.ps4000
27 | msl.equipment.resources.picotech.picoscope.ps4000a
28 | msl.equipment.resources.picotech.picoscope.ps5000
29 | msl.equipment.resources.picotech.picoscope.ps5000a
30 | msl.equipment.resources.picotech.picoscope.ps6000
31 | msl.equipment.resources.picotech.picoscope.structs
32 |
33 |
--------------------------------------------------------------------------------
/packages/validate/README.md:
--------------------------------------------------------------------------------
1 | # msl-equipment-validate
2 |
3 | [](https://github.com/MSLNZ/msl-equipment/actions/workflows/ci.yml)
4 | [](https://github.com/MSLNZ/msl-equipment/actions/workflows/docs.yml)
5 |
6 | A command-line tool to validate equipment registers and connection files that are used by [msl-equipment](https://pypi.org/project/msl-equipment/).
7 |
8 | ## Install
9 | `msl-equipment-validate` is available on [PyPI](https://pypi.org/project/msl-equipment-validate/) and can be installed with a variety of Python package managers (e.g., pip, pipx, uv, ...). The following command uses pip
10 |
11 | ```console
12 | pip install msl-equipment-validate
13 | ```
14 |
15 | If you used a package manager that does not automatically add the `msl-equipment-validate` executable to your PATH environment variable (without activating a [virtual environment](https://docs.python.org/3/library/venv.html)), you may want to add the directory to where the `msl-equipment-validate` executable is located to your PATH. This will allow you to validate XML documents from any directory without having to first activate a virtual environment.
16 |
17 | ## Documentation
18 | The documentation for `msl-equipment-validate` can be found [here](https://mslnz.github.io/msl-equipment/dev/validate).
19 |
--------------------------------------------------------------------------------
/docs/getting-started/index.md:
--------------------------------------------------------------------------------
1 | # Getting Started
2 |
3 | Three concepts are used by `msl-equipment`
4 |
5 | 1. [Equipment registers][] — to comply with the [ISO/IEC 17025]{:target="_blank"} standard
6 | 2. [Connections][] — to interface with equipment for computer control
7 | 3. [Configuration files][] — define requirements for a measurement (links items 1 and 2 together)
8 |
9 | You do not need to use all three concepts for your application. You can choose to only use the [equipment-register classes][schema-classes] to help manage information about the equipment in your laboratory and use a different Python package to communicate with equipment. Similarly, you can choose to use one of the supported [backends][connections-backend] for communication. You can choose to ignore the [equipment registers][] concept and solely use the package to [communicate with equipment][connections-python-examples]. You can also choose to not use `msl-equipment` at all, but just use the [Schema][er-schema] to create equipment registers that comply with [ISO/IEC 17025]{:target="_blank"}. Since an equipment register is written in the eXtensible Markup Language (XML) file format, it may be parsed by many programming languages. This allows people to share a common equipment register but use different programming languages to read information from the same equipment register.
10 |
11 | [ISO/IEC 17025]: https://www.iso.org/ISO-IEC-17025-testing-and-calibration-laboratories.html
12 |
--------------------------------------------------------------------------------
/packages/resources/examples/nkt/find_devices.py:
--------------------------------------------------------------------------------
1 | """Example showing how to find all devices from NKT Photonics."""
2 |
3 | from __future__ import annotations
4 |
5 | from msl.equipment.resources import NKT
6 |
7 | # When installing the SDK a NKTP_SDK_PATH environment variable is created
8 | # and this variable specifies the path to the DLL file; however, you
9 | # can also explicitly specify the path to the DLL file.
10 | NKT.load_sdk("C:/NKTPDLL.dll")
11 |
12 | print("Finding all available ports...")
13 | all_ports = NKT.get_all_ports()
14 | print(f" Found the following ports: {all_ports}")
15 |
16 | # Open all ports (in Auto and Live modes)
17 | print("Opening all ports (in Auto and Live modes)...")
18 | NKT.open_ports(*all_ports)
19 |
20 | # All ports returned by the get_open_ports() function have modules
21 | # (ports without modules will be closed automatically)
22 | opened_ports = NKT.get_open_ports()
23 | print(f" Devices from NKT Photonics are open on the following ports: {opened_ports}")
24 |
25 | # Traverse the opened_ports list and retrieve information about the device types and the addresses
26 | # See the Register Files section in the SDK manual
27 | all_types = NKT.device_get_all_types(*opened_ports)
28 | for name, types in all_types.items():
29 | print(f" Port: {name}")
30 | for module, device_id in types.items():
31 | print(f" ModuleType={module} DeviceID={device_id}")
32 |
33 | # Close all ports
34 | NKT.close_ports()
35 | print("Closed all ports")
36 |
--------------------------------------------------------------------------------
/packages/resources/src/msl/equipment_resources/__init__.py:
--------------------------------------------------------------------------------
1 | """Custom resources for communicating with equipment."""
2 |
3 | from __future__ import annotations
4 |
5 | from . import avantes, cmi, electron_dynamics, isotech, mks, nkt, optosigma
6 | from .aim_tti import MXSeries
7 | from .avantes import AvaSpec
8 | from .cmi import SIA3
9 | from .dataray import WinCamD
10 | from .electron_dynamics import TCSeries
11 | from .energetiq import EQ99
12 | from .greisinger import GMH3000
13 | from .isotech import MilliK
14 | from .mks import PR4000B
15 | from .nkt import NKT
16 | from .omega import ITHX
17 | from .optosigma import SHOT702
18 | from .optronic_labs import OL756, OLxxA
19 | from .picotech import PT104, PicoScope, picoscope
20 | from .princeton_instruments import PrincetonInstruments
21 | from .raicol import RaicolTEC
22 | from .thorlabs import FWxx2C
23 | from .vaisala import PTB330, PTU300
24 |
25 | __all__: list[str] = [
26 | "EQ99",
27 | "GMH3000",
28 | "ITHX",
29 | "NKT",
30 | "OL756",
31 | "PR4000B",
32 | "PT104",
33 | "PTB330",
34 | "PTU300",
35 | "SHOT702",
36 | "SIA3",
37 | "AvaSpec",
38 | "FWxx2C",
39 | "MXSeries",
40 | "MilliK",
41 | "OLxxA",
42 | "PicoScope",
43 | "PrincetonInstruments",
44 | "RaicolTEC",
45 | "TCSeries",
46 | "WinCamD",
47 | "avantes",
48 | "cmi",
49 | "electron_dynamics",
50 | "isotech",
51 | "mks",
52 | "nkt",
53 | "optosigma",
54 | "picoscope",
55 | ]
56 |
--------------------------------------------------------------------------------
/packages/resources/examples/optronic_laboratories/ol756.py:
--------------------------------------------------------------------------------
1 | """Example showing how to communicate with an Optronic Laboratories 756 UV-VIS spectroradiometer."""
2 |
3 | from __future__ import annotations
4 |
5 | from typing import TYPE_CHECKING
6 |
7 | from msl.equipment import Connection
8 |
9 | if TYPE_CHECKING:
10 | from msl.equipment.resources import OL756
11 |
12 |
13 | connection = Connection(
14 | "SDK::OL756SDKACTIVEX.OL756SDKActiveXCtrl.1",
15 | manufacturer="Optronic Laboratories Inc",
16 | model="756",
17 | serial="05001009",
18 | mode=1, # connection mode: 0=RS232, 1=USB
19 | com_port=1, # the COM port number (if using RS232 mode)
20 | )
21 |
22 | # Connect to the spectroradiometer
23 | ol756: OL756 = connection.connect()
24 |
25 | # Load the settings from flash memory
26 | ol756.import_registry()
27 | ol756.read_ol756_flash_settings()
28 |
29 | # Get some information from the spectroradiometer
30 | start = ol756.get_start_wavelength()
31 | end = ol756.get_ending_wavelength()
32 | increment = ol756.get_increment()
33 | print(f"SDK version: {ol756.get_ocx_version()}")
34 | print(f"Wavelength scan range: {start} .. {end} @ {increment} nm")
35 |
36 | # Acquire a scan
37 | ol756.send_down_parameters(0) # Point to point scan. Must be called before take_point_to_point_measurement
38 | ol756.take_point_to_point_measurement(0) # Irradiance type
39 |
40 | # Get the data
41 | data = ol756.get_signal_array()
42 | print(data)
43 |
44 | # Disconnect from the spectroradiometer
45 | ol756.disconnect()
46 |
--------------------------------------------------------------------------------
/docs-old/install.rst:
--------------------------------------------------------------------------------
1 | .. _equipment-install:
2 |
3 | =====================
4 | Install MSL-Equipment
5 | =====================
6 |
7 | To install MSL-Equipment run
8 |
9 | .. code-block:: console
10 |
11 | pip install https://github.com/MSLNZ/msl-equipment/releases/download/v0.2.0/msl_equipment-0.2.0-py3-none-any.whl
12 |
13 | Alternatively, using the `MSL Package Manager`_ run
14 |
15 | .. code-block:: console
16 |
17 | msl install equipment
18 |
19 | .. _equipment-dependencies:
20 |
21 | Dependencies
22 | ------------
23 | * Python 3.8+
24 | * msl-loadlib_
25 | * msl-io_
26 | * numpy_
27 | * pyserial_
28 | * pyzmq_
29 |
30 | Optional Dependencies
31 | ---------------------
32 | * PyVISA_
33 | * PyVISA-py_
34 | * NI-DAQmx_
35 |
36 | Some of the :ref:`equipment-resources` might not work in your application
37 | because the resource might depend on an external dependency (e.g., the SDK
38 | provided by a manufacturer) and this external dependency might not be
39 | available for your operating system.
40 |
41 | .. _MSL Package Manager: https://msl-package-manager.readthedocs.io/en/stable/
42 | .. _PyVISA: https://pyvisa.readthedocs.io/en/stable/
43 | .. _PyVISA-py: https://pyvisa-py.readthedocs.io/en/stable/
44 | .. _NI-DAQmx: https://nidaqmx-python.readthedocs.io/en/stable/
45 | .. _numpy: https://www.numpy.org/
46 | .. _msl-loadlib: https://msl-loadlib.readthedocs.io/en/stable/
47 | .. _msl-io: https://msl-io.readthedocs.io/en/latest/
48 | .. _pyserial: https://pythonhosted.org/pyserial/
49 | .. _pyzmq: https://pyzmq.readthedocs.io/en/stable/
50 |
--------------------------------------------------------------------------------
/packages/resources/src/msl/equipment_resources/types.py:
--------------------------------------------------------------------------------
1 | """Custom type annotations."""
2 |
3 | from __future__ import annotations
4 |
5 | from ctypes import _Pointer, c_int32 # pyright: ignore[reportPrivateUsage]
6 | from typing import Callable
7 |
8 | AvaSpecCallback = Callable[[_Pointer[c_int32], _Pointer[c_int32]], None]
9 | """Callback handler for the [AvaSpec][msl.equipment_resources.avantes.avaspec.AvaSpec] SDK."""
10 |
11 | NKTPortStatusCallback = Callable[[str, int, int, int, int], None]
12 | """Callback handler for the [NKT][msl.equipment_resources.nkt.nktpdll.NKT] SDK when the status of a port changes."""
13 |
14 | NKTDeviceStatusCallback = Callable[[str, int, int, int, int], None]
15 | """Callback handler for the [NKT][msl.equipment_resources.nkt.nktpdll.NKT] SDK when the status of a device changes."""
16 |
17 | NKTRegisterStatusCallback = Callable[[str, int, int, int, int, int, int], None]
18 | """Callback handler for the [NKT][msl.equipment_resources.nkt.nktpdll.NKT] SDK when the status of a register changes."""
19 |
20 | PicoTechBlockReadyCallback = Callable[[int, int, None], None]
21 | """Block-ready callback handler for the [PicoScope][msl.equipment_resources.picotech.picoscope.PicoScope] SDK."""
22 |
23 | PicoTechDataReadyCallback = Callable[[int, int, int, int, None], None]
24 | """Data-ready callback handler for the [PicoScope][msl.equipment_resources.picotech.picoscope.PicoScope] SDK."""
25 |
26 | PicoTechStreamingReadyCallback = Callable[[int, int, int, int, int, int, int, None], None]
27 | """Streaming-ready callback handler for the [PicoScope][msl.equipment_resources.picotech.picoscope.PicoScope] SDK."""
28 |
--------------------------------------------------------------------------------
/tests/resources/connections.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | MSLE.M.092
5 | COM1
6 |
7 |
8 | MSLE.M.001
9 | GPIB::22
10 | MSL
11 |
12 |
13 | MSLE.M.100
14 | TCPIP::dev.company.com::hislip0
15 |
16 |
17 |
18 | MSLE.O.231
19 | SDK::library.dll
20 |
21 |
22 |
23 | MSLE.O.103
24 | TCPIP::192.168.1.100
25 |
26 |
27 |
28 | MSLE.O.061
29 | TCP::192.168.1.100::5000
30 |
31 |
32 |
33 | MSLE.O.023
34 | ASRL/dev/ttyS1
35 | PyVISA
36 | Manufacturer
37 | Model
38 | Serial
39 |
40 | 19200
41 | \n
42 | \r
43 | \r\n
44 | 10.2
45 | true
46 |
47 |
48 |
49 |
50 |
--------------------------------------------------------------------------------
/packages/resources/examples/optronic_laboratories/ol83a.py:
--------------------------------------------------------------------------------
1 | """Example showing how to communicate with an Optronic Laboratories 83A DC Current Source."""
2 |
3 | from __future__ import annotations
4 |
5 | from typing import TYPE_CHECKING
6 |
7 | from msl.equipment import Connection
8 |
9 | if TYPE_CHECKING:
10 | from msl.equipment.resources import OLxxA
11 |
12 |
13 | connection = Connection(
14 | "COM3", # update for your current source
15 | manufacturer="Optronic Laboratories",
16 | model="83A",
17 | # address=1, # internal address of device (optional)
18 | )
19 |
20 | # Connect to the current source
21 | ol83a: OLxxA = connection.connect()
22 |
23 | # Turn the output off
24 | ol83a.turn_off()
25 |
26 | # Select a lamp
27 | ol83a.select_lamp(9)
28 |
29 | # Get target information: lamp number, target value, target unit
30 | print(f"target info: {ol83a.target_info()}")
31 |
32 | # Get the output state (on or off)
33 | print(f"is the output on? {ol83a.state()}")
34 |
35 | # Set the target current
36 | actual = ol83a.set_current(0.2345)
37 | print(f"the actual current that was set is {actual}")
38 |
39 | # Get the system status byte of the latest command that was executed
40 | print(f"system status byte: {ol83a.system_status_byte:b}")
41 |
42 | # Read the output current, voltage and wattage
43 | print(f"output current is {ol83a.get_current()} A")
44 | print(f"output voltage is {ol83a.get_voltage()} V")
45 | print(f"output wattage is {ol83a.get_wattage()} W")
46 |
47 | # Get the number of hours for lamp 9
48 | hours = ol83a.get_option(9, 40)
49 | print(f"hours: {hours}")
50 |
51 | # Disconnect from the current source
52 | ol83a.disconnect()
53 |
--------------------------------------------------------------------------------
/src/msl/equipment/enumerations.py:
--------------------------------------------------------------------------------
1 | """Enumeration constants."""
2 |
3 | from __future__ import annotations
4 |
5 | import enum
6 |
7 | import serial
8 |
9 |
10 | class Backend(enum.Enum):
11 | """The backend library to use for communication with the equipment.
12 |
13 | Attributes:
14 | MSL (str): "MSL"
15 | PyVISA (str): "PyVISA"
16 | NIDAQ (str): "NIDAQ"
17 | """
18 |
19 | MSL = "MSL"
20 | PyVISA = "PyVISA"
21 | NIDAQ = "NIDAQ"
22 |
23 |
24 | class Parity(enum.Enum):
25 | """The parity type to use for Serial communication.
26 |
27 | Attributes:
28 | NONE (str): "N"
29 | ODD (str): "O"
30 | EVEN (str): "E"
31 | MARK (str): "M"
32 | SPACE (str): "S"
33 | """
34 |
35 | NONE = serial.PARITY_NONE
36 | ODD = serial.PARITY_ODD
37 | EVEN = serial.PARITY_EVEN
38 | MARK = serial.PARITY_MARK
39 | SPACE = serial.PARITY_SPACE
40 |
41 |
42 | class StopBits(enum.Enum):
43 | """The number of stop bits to use for Serial communication.
44 |
45 | Attributes:
46 | ONE (int): 1
47 | ONE_POINT_FIVE (float): 1.5
48 | TWO (int): 2
49 | """
50 |
51 | ONE = serial.STOPBITS_ONE
52 | ONE_POINT_FIVE = serial.STOPBITS_ONE_POINT_FIVE
53 | TWO = serial.STOPBITS_TWO
54 |
55 |
56 | class DataBits(enum.IntEnum):
57 | """The number of data bits to use for Serial communication.
58 |
59 | Attributes:
60 | FIVE (int): 5
61 | SIX (int): 6
62 | SEVEN (int): 7
63 | EIGHT (int): 8
64 | """
65 |
66 | FIVE = serial.FIVEBITS
67 | SIX = serial.SIXBITS
68 | SEVEN = serial.SEVENBITS
69 | EIGHT = serial.EIGHTBITS
70 |
--------------------------------------------------------------------------------
/packages/resources/src/msl/equipment_resources/avantes/__init__.py:
--------------------------------------------------------------------------------
1 | """Wrapper around the `avaspec.dll` SDK from Avantes."""
2 |
3 | # cSpell: ignore Meas Resp Sens
4 | from __future__ import annotations
5 |
6 | from .avaspec import (
7 | AvaSpec,
8 | AvsIdentityType,
9 | BroadcastAnswerType,
10 | ControlSettingsType,
11 | DarkCorrectionType,
12 | DetectorType,
13 | DeviceConfigType,
14 | DeviceStatus,
15 | DynamicStorageType,
16 | EthernetSettingsType,
17 | HeartbeatRespType,
18 | InterfaceType,
19 | IrradianceType,
20 | MeasConfigType,
21 | MeasureCallback,
22 | OemDataType,
23 | ProcessControlType,
24 | SensType,
25 | SmoothingType,
26 | SpectrumCalibrationType,
27 | SpectrumCorrectionType,
28 | StandAloneType,
29 | TecControlType,
30 | TempSensorType,
31 | TimeStampType,
32 | TriggerType,
33 | avaspec_callback,
34 | )
35 |
36 | __all__: list[str] = [
37 | "AvaSpec",
38 | "AvsIdentityType",
39 | "BroadcastAnswerType",
40 | "ControlSettingsType",
41 | "DarkCorrectionType",
42 | "DetectorType",
43 | "DeviceConfigType",
44 | "DeviceStatus",
45 | "DynamicStorageType",
46 | "EthernetSettingsType",
47 | "HeartbeatRespType",
48 | "InterfaceType",
49 | "IrradianceType",
50 | "MeasConfigType",
51 | "MeasureCallback",
52 | "OemDataType",
53 | "ProcessControlType",
54 | "SensType",
55 | "SmoothingType",
56 | "SpectrumCalibrationType",
57 | "SpectrumCorrectionType",
58 | "StandAloneType",
59 | "TecControlType",
60 | "TempSensorType",
61 | "TimeStampType",
62 | "TriggerType",
63 | "avaspec_callback",
64 | ]
65 |
--------------------------------------------------------------------------------
/.github/workflows/docs.yml:
--------------------------------------------------------------------------------
1 | name: Docs
2 |
3 | on:
4 | push:
5 | branches: ['main']
6 | tags:
7 | - '*'
8 | pull_request:
9 | branches: ['main']
10 |
11 | permissions:
12 | contents: write
13 | pages: write
14 | id-token: write
15 |
16 | # Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
17 | # However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
18 | concurrency:
19 | group: 'pages'
20 | cancel-in-progress: false
21 |
22 | jobs:
23 | deploy:
24 | name: Build and deploy documentation
25 | runs-on: ubuntu-latest
26 | steps:
27 | - name: Checkout repository
28 | uses: actions/checkout@v5
29 | with:
30 | fetch-depth: 0 # fetch all commits/branches
31 | - name: Install uv
32 | uses: astral-sh/setup-uv@v6
33 | with:
34 | enable-cache: false
35 | - name: Configure Git for GitHub Actions bot
36 | run: |
37 | git config --local user.name "github-actions[bot]"
38 | git config --local user.email "github-actions[bot]@users.noreply.github.com"
39 | - name: Validate docs
40 | run: uv run --all-packages -- mkdocs build --strict
41 | - name: Deploy dev docs
42 | if: github.ref == 'refs/heads/main'
43 | run: |
44 | uv run --all-packages -- mike deploy --push --update-aliases dev
45 | - name: Deploy release docs
46 | if: github.ref_type == 'tag'
47 | run: |
48 | uv run --all-packages -- mike deploy --push --update-aliases ${{ github.ref_name }} latest
49 | uv run --all-packages -- mike set-default --push latest
50 |
--------------------------------------------------------------------------------
/packages/resources/examples/isotech/milliskanner.py:
--------------------------------------------------------------------------------
1 | """Example showing how to communicate with an IsoTech millisKanner (via a milliK)."""
2 |
3 | from __future__ import annotations
4 |
5 | from typing import TYPE_CHECKING
6 |
7 | from msl.equipment import Connection
8 |
9 | if TYPE_CHECKING:
10 | from msl.equipment.resources import MilliK
11 |
12 | connection = Connection(
13 | "COM6", # could also be a Socket, e.g., "TCP::10.12.102.30::1000"
14 | manufacturer="IsoTech",
15 | model="milliK",
16 | )
17 |
18 | # Connect to the milliK device (automatically configures for REMOTE mode)
19 | thermometer: MilliK = connection.connect()
20 |
21 | # Print information about the device
22 | print("Number of devices connected:", thermometer.num_devices)
23 | print("Connected devices:", thermometer.connected_devices)
24 | print("Available channel numbers:", thermometer.channel_numbers)
25 |
26 | # Configure channels using the largest resistance value that is expected for that channel
27 | resistances = [13000, 470, 220, 820, 3300, 100, 1800, 100]
28 | for i, r in enumerate(resistances, start=10): # here the sensors are all on the first millisKanner only
29 | thermometer.configure_resistance_measurement(channel=i, resistance=r)
30 |
31 | # Read resistance for a specific channel, returning 5 readings
32 | print("Resistance values for Channel 13:", thermometer.read_channel(13, n=5))
33 |
34 | # Once the desired channels have been configured, you can yield values from them all
35 | # Here, we request the average resistance of 5 readings for every configured channel
36 | for ch, resistance in thermometer.read_all_channels(n=5):
37 | print(f"Channel {ch}:", resistance)
38 |
39 | # Disconnect from the milliK device (automatically configures for LOCAL mode)
40 | thermometer.disconnect()
41 |
--------------------------------------------------------------------------------
/packages/resources/examples/thorlabs/kinesis_device_info.py:
--------------------------------------------------------------------------------
1 | """
2 | This example shows how to get information about Kinesis devices
3 | found on USB ports (that are not already connected to).
4 | """
5 | import os
6 | import sys
7 |
8 | from msl.equipment.resources.thorlabs import MotionControl
9 |
10 | # ensure that the Kinesis folder is available on PATH
11 | os.environ['PATH'] += os.pathsep + 'C:/Program Files/Thorlabs/Kinesis'
12 |
13 | print('Building the device list...')
14 | MotionControl.build_device_list()
15 |
16 | n_devices = MotionControl.get_device_list_size()
17 | if n_devices == 0:
18 | print('There are no devices in the device list')
19 | sys.exit(0)
20 | elif n_devices == 1:
21 | print('There is 1 device in the device list')
22 | else:
23 | print('There are {} devices in the device list'.format(n_devices))
24 |
25 | all_devices = MotionControl.get_device_list()
26 | print('The serial numbers of all the devices are: {}'.format(all_devices))
27 |
28 | filter_flippers = MotionControl.get_device_list(MotionControl.Filter_Flipper)
29 | print('The Filter Flipper\'s that are connected are: {}'.format(filter_flippers))
30 |
31 | lts = MotionControl.get_device_list(MotionControl.Long_Travel_Stage)
32 | print('The Long Travel Stage\'s that are connected are: {}'.format(lts))
33 |
34 | devices = MotionControl.get_device_list(MotionControl.Filter_Flipper, MotionControl.Long_Travel_Stage)
35 | print('The Filter Flipper\'s and Long Travel Stage\'s that are connected are: {}'.format(devices))
36 |
37 | info = MotionControl.get_device_info(all_devices[0])
38 | print('The device info for the device with serial# {} is:'.format(all_devices[0]))
39 | for item in dir(info):
40 | if item.startswith('_'):
41 | continue
42 | print(' {}: {}'.format(item, getattr(info, item)))
43 |
--------------------------------------------------------------------------------
/packages/resources/examples/thorlabs/mff101.py:
--------------------------------------------------------------------------------
1 | """
2 | This example communicates with a Thorlabs
3 | Filter Flipper (MFF101 or MFF102).
4 | """
5 | import os
6 | import time
7 |
8 | from msl.equipment import (
9 | EquipmentRecord,
10 | ConnectionRecord,
11 | Backend,
12 | )
13 | from msl.equipment.resources.thorlabs import MotionControl
14 |
15 | # ensure that the Kinesis folder is available on PATH
16 | os.environ['PATH'] += os.pathsep + 'C:/Program Files/Thorlabs/Kinesis'
17 |
18 | record = EquipmentRecord(
19 | manufacturer='Thorlabs',
20 | model='MFF101/M', # specify MFF102 if you have the 2" version
21 | serial='37871232', # update for your device
22 | connection=ConnectionRecord(
23 | backend=Backend.MSL,
24 | address='SDK::Thorlabs.MotionControl.FilterFlipper.dll',
25 | ),
26 | )
27 |
28 | # Build the device list before connecting to the Filter Flipper
29 | MotionControl.build_device_list()
30 |
31 | # connect to the Filter Flipper
32 | flipper = record.connect()
33 | print('Connected to {}'.format(flipper))
34 |
35 | # wait a little bit for the Thorlabs SDK to open the serial port
36 | time.sleep(1)
37 |
38 | # start polling at 200 ms
39 | flipper.start_polling(200)
40 |
41 | position = flipper.get_position()
42 | print('Flipper is at position {}'.format(position))
43 |
44 | # move the flipper to the other position and wait for the move to finish
45 | position = 1 if position == 2 else 2
46 | print('Moving the flipper to position {}'.format(position))
47 | flipper.move_to_position(position)
48 | while flipper.get_position() != position:
49 | print(' waiting...')
50 | time.sleep(0.1)
51 | print('Move done. Flipper is now at position {}'.format(flipper.get_position()))
52 |
53 | # stop polling and close the connection
54 | flipper.stop_polling()
55 | flipper.disconnect()
56 |
--------------------------------------------------------------------------------
/packages/resources/examples/isotech/millik.py:
--------------------------------------------------------------------------------
1 | """Example showing how to communicate with an IsoTech milliK Precision Thermometer."""
2 |
3 | from __future__ import annotations
4 |
5 | from typing import TYPE_CHECKING
6 |
7 | from msl.equipment import Connection
8 |
9 | if TYPE_CHECKING:
10 | from msl.equipment.resources import MilliK
11 |
12 |
13 | connection = Connection(
14 | "TCP::10.12.102.30::1000", # could also be a Serial port, e.g., "COM4"
15 | manufacturer="IsoTech",
16 | model="milliK",
17 | timeout=5,
18 | )
19 |
20 | # Connect to the milliK device (automatically configures for REMOTE mode)
21 | thermometer: MilliK = connection.connect()
22 |
23 | # Print information about the device
24 | print("Number of devices connected:", thermometer.num_devices)
25 | print("Connected devices:", thermometer.connected_devices)
26 | print("Available channel numbers:", thermometer.channel_numbers)
27 |
28 | # Configure channel 1 for resistance measurements
29 | # Specify the largest resistance value that is expected to be measured
30 | thermometer.configure_resistance_measurement(channel=1, resistance=130)
31 |
32 | # Configure channel 2 for voltage measurements with reference junction compensation
33 | # enabled for a Type K thermocouple
34 | thermometer.configure_voltage_measurement(channel=2, rjc=True, thermocouple="K")
35 |
36 | # Read measurement data for a specific channel, returning n readings
37 | print("Resistance value for Channel 1:", thermometer.read_channel(1))
38 | print("Voltage values for Channel 2:", thermometer.read_channel(2, n=5))
39 |
40 | # Read a value from all configured channels
41 | for channel, value in thermometer.read_all_channels():
42 | print(f"Channel {channel}:", value)
43 |
44 | # Disconnect from the milliK device (automatically configures for LOCAL mode)
45 | thermometer.disconnect()
46 |
--------------------------------------------------------------------------------
/packages/resources/examples/aim_tti/mx100tp.py:
--------------------------------------------------------------------------------
1 | """Example showing how to communicate with an MX100TP DC power supply."""
2 |
3 | from __future__ import annotations
4 |
5 | import time
6 | from typing import TYPE_CHECKING
7 |
8 | from msl.equipment import Connection
9 |
10 | if TYPE_CHECKING:
11 | from msl.equipment.resources import MXSeries
12 |
13 |
14 | connection = Connection(
15 | "COM5", # if using the USB or RS232 port (update the port number)
16 | # "TCP::169.254.100.2::9221", # if using the LAN port (update the IP address)
17 | # "GPIB::5", # if using the GPIB port (must also disable termination characters)
18 | # "Prologix::169.254.100.5::1234::GPIB::5", # if using Prologix hardware (update the hardware address)
19 | manufacturer="Aim-TTi",
20 | model="MX100TP",
21 | timeout=5,
22 | # termination=None, # uncomment if using GPIB
23 | # escape_characters=False, # uncomment if using Prologix
24 | )
25 |
26 | # The output channel to use
27 | channel = 1
28 |
29 | # Establish the connection to the DC power supply
30 | tti: MXSeries = connection.connect()
31 |
32 | # Turn the output on and set the voltage to 0.1 volts
33 | tti.turn_on(channel)
34 | tti.set_voltage(channel, 0.1)
35 | voltage = tti.get_voltage(channel)
36 | print(f"The output of channel {channel} is {voltage}V")
37 |
38 | # Increment the output voltage by 0.1 volts for each iteration
39 | tti.set_voltage_step_size(channel, 0.1)
40 | for _ in range(10):
41 | tti.increment_voltage(channel)
42 | setpoint = tti.get_voltage_setpoint(channel)
43 | voltage = tti.get_voltage(channel)
44 | current = tti.get_current(channel)
45 | print(f"V_set={setpoint}V, V_out={voltage}V, I_out={current}A")
46 | time.sleep(0.5)
47 |
48 | # Turn off all outputs (the multi-off feature)
49 | tti.turn_off_multi()
50 |
51 | # Disconnect from the DC power supply
52 | tti.disconnect()
53 |
--------------------------------------------------------------------------------
/tests/resources/gpib.h:
--------------------------------------------------------------------------------
1 | // gpib.h
2 | // Mocks a GPIB library for testing purposes.
3 | //
4 |
5 | #if defined(_MSC_VER)
6 | // Microsoft
7 | #define EXPORT __declspec(dllexport)
8 | #elif defined(__GNUC__)
9 | // G++
10 | #define EXPORT __attribute__((visibility("default")))
11 | #else
12 | # error "Unknown EXPORT semantics"
13 | #endif
14 |
15 | int EARG = 4;
16 | int END = 0x2000;
17 | int TIMO = 0x4000;
18 | int ERR = 0x8000;
19 |
20 | extern "C" {
21 | EXPORT volatile long ibcntl;
22 |
23 | EXPORT int ThreadIbsta( void );
24 | EXPORT int ThreadIberr( void );
25 | EXPORT int ThreadIbcnt( void );
26 | EXPORT int ibask( int ud, int option, int *value );
27 | EXPORT int ibcac( int ud, int synchronous );
28 | EXPORT int ibclr( int ud );
29 | EXPORT int ibcmd( int ud, const void *cmd, long cnt );
30 | EXPORT int ibconfig( int ud, int option, int value );
31 | EXPORT int ibdev( int board_index, int pad, int sad, int timo, int send_eoi, int eosmode );
32 | EXPORT int ibgts(int ud, int shadow_handshake);
33 | EXPORT int iblines( int ud, short *line_status );
34 | EXPORT int ibln( int ud, int pad, int sad, short *found_listener );
35 | EXPORT int ibloc( int ud );
36 | EXPORT int ibonl( int ud, int onl );
37 | EXPORT int ibpct( int ud );
38 | EXPORT int ibrd( int ud, void *buf, long count );
39 | EXPORT int ibrsp( int ud, char *spr );
40 | EXPORT int ibsic( int ud );
41 | EXPORT int ibspb( int ud, short *sp_bytes );
42 | EXPORT int ibtrg( int ud );
43 | EXPORT int ibwait( int ud, int mask );
44 | EXPORT int ibwrt( int ud, const void *buf, long count );
45 | EXPORT int ibwrta( int ud, const void *buf, long count );
46 |
47 | #if defined(_MSC_VER)
48 | EXPORT int ibfindW(const wchar_t *dev);
49 | #else
50 | EXPORT int ibfind( const char *dev );
51 | EXPORT void ibvers( char **version);
52 | #endif
53 | }
--------------------------------------------------------------------------------
/packages/resources/examples/greisinger/gmh3710.py:
--------------------------------------------------------------------------------
1 | """Example showing how to communicate with an GMH3710 thermometer from Greisinger, GHM Group."""
2 |
3 | from __future__ import annotations
4 |
5 | from typing import TYPE_CHECKING
6 |
7 | from msl.equipment import Connection
8 |
9 | if TYPE_CHECKING:
10 | from msl.equipment.resources import GMH3000
11 |
12 | connection = Connection(
13 | "COM4", # change for your thermometer
14 | manufacturer="Greisinger",
15 | model="GMH3710-GE",
16 | timeout=2,
17 | # gmh_address=11 # Optional: change for your thermometer, default gmh_address is 1
18 | )
19 |
20 | thermometer: GMH3000 = connection.connect()
21 |
22 | # Read information about the device
23 | unit = thermometer.unit()
24 | print("Current value", thermometer.value(), unit)
25 | print("Minimum value", thermometer.min_value(), unit)
26 | print("Maximum value", thermometer.max_value(), unit)
27 | print("Measurement range", thermometer.measurement_range())
28 | print("Display range", thermometer.display_range())
29 | print("Scale correction", thermometer.scale_correction())
30 | print("Offset correction", thermometer.offset_correction())
31 | print("Channel count", thermometer.channel_count())
32 | print("Power-off time", thermometer.power_off_time())
33 | print("Resolution", thermometer.resolution())
34 | print("ID (serial) number", thermometer.id_number())
35 | print("Firmware version", thermometer.firmware_version())
36 |
37 | # Check if the battery is low
38 | bit_mask = thermometer.status()
39 | print(f"System status: {bit_mask}")
40 | if bit_mask & 1 << 15:
41 | print("Warning! Battery is low")
42 |
43 | # Clears the minimum and maximum values that are stored in the device
44 | # thermometer.clear_min_value()
45 | # thermometer.clear_max_value()
46 |
47 | # Sets the power-off time to 30 minutes
48 | # thermometer.set_power_off_time(30)
49 |
50 | # Disconnect from the device
51 | thermometer.disconnect()
52 |
--------------------------------------------------------------------------------
/packages/resources/tests/test_greisinger_gmh3000.py:
--------------------------------------------------------------------------------
1 | from __future__ import annotations
2 |
3 | import os
4 | import threading
5 | import time
6 |
7 | try:
8 | import pty
9 | except ImportError:
10 | pty = None
11 |
12 | import pytest
13 |
14 | from msl.equipment import ConnectionRecord
15 | from msl.equipment import EquipmentRecord
16 | from msl.equipment.exceptions import GreisingerError
17 |
18 |
19 | def easybus_server(port):
20 | os.read(port, 3) # value() request
21 | os.write(port, b'\xfe\x05&q\x00H\xf7\x80\t') # 21.76
22 | os.read(port, 3) # value() request
23 | os.write(port, b'\xFE\x05&\x72\xFF\x84\x00\xFC\x05') # -0.04
24 | os.read(port, 6) # min measurement range request
25 | os.write(port, b'\xfe\xf5\xf8O\x00g\xbf0\xe3') # -200.0
26 | os.read(port, 6) # max measurement range request
27 | os.write(port, b'\xfe\xf5\xf8N\x00r\x964\xec') # 850.0
28 | os.read(port, 3) # value() request
29 | os.write(port, b'\xfe\r\x1ep\xf6\x91\xdf\xed\x0b') # "No sensor" error code
30 |
31 |
32 | @pytest.mark.skipif(pty is None, reason='pty is not available')
33 | def test_easybus():
34 | # simulate a Serial port
35 | primary, secondary = pty.openpty()
36 |
37 | thread = threading.Thread(target=easybus_server, args=(primary,), daemon=True)
38 | thread.start()
39 |
40 | time.sleep(0.5) # allow some time for the easybus server to start
41 |
42 | record = EquipmentRecord(
43 | manufacturer='Greisinger',
44 | model='GMH3710-GE',
45 | connection=ConnectionRecord(
46 | address='ASRL' + os.ttyname(secondary),
47 | properties={'timeout': 5},
48 | )
49 | )
50 |
51 | dev = record.connect()
52 | assert dev.value() == 21.76
53 | assert dev.value() == -0.04
54 | assert dev.measurement_range() == (-200.0, 850.0)
55 | with pytest.raises(GreisingerError, match='No sensor'):
56 | dev.value()
57 |
--------------------------------------------------------------------------------
/docs/resources/index.md:
--------------------------------------------------------------------------------
1 | # Resources
2 |
3 | Resources are custom classes for interfacing with specific equipment. In previous releases of `msl-equipment` (versions < 1.0), the resources were automatically bundled with `msl-equipment`. As of v1.0, the resources are maintained in another package, `msl-equipment-resources`, that must be installed separately.
4 |
5 | Some of the resources might not work in your application because the resource might depend on an external dependency, e.g., the Software Development Kit (SDK) provided by a manufacturer, and this external dependency might not be available for your operating system.
6 |
7 | !!! examples
8 | There are examples on how to use the resources in the [repository](https://github.com/MSLNZ/msl-equipment/tree/main/packages/resources/examples){:target="_blank"}.
9 |
10 | !!! danger "Attention"
11 | Companies that sell equipment that are used for scientific research are identified in this guide in order to illustrate how to adequately use `msl-equipment-resources` in your application. Such identification is not intended to imply recommendation or endorsement by the Measurement Standards Laboratory of New Zealand, nor is it intended to imply that the companies identified are necessarily the best for the purpose.
12 |
13 | ## Install
14 |
15 | Installing `msl-equipment-resources` will also install `msl-equipment`
16 |
17 | ```console
18 | pip install msl-equipment-resources
19 | ```
20 |
21 | ## Create a new resource
22 |
23 | TODO...
24 |
25 | ## Multiple interfaces
26 |
27 | If the equipment supports multiple interfaces for message-based protocols (e.g., [Socket][msl.equipment.interfaces.socket.Socket], [Serial][msl.equipment.interfaces.serial.Serial], [GPIB][msl.equipment.interfaces.gpib.GPIB], ...) you can create a resource that inherits from the [MultiMessageBased][msl.equipment_resources.multi_message_based.MultiMessageBased] class. Upon calling [super][] in the subclass, the connection is established with the appropriate protocol class.
28 |
--------------------------------------------------------------------------------
/packages/resources/examples/thorlabs/ksc101.py:
--------------------------------------------------------------------------------
1 | """
2 | This example shows how to communicate with a SH05 (shutter)
3 | connected to a KSC101 (KCube Solenoid).
4 | """
5 | import os
6 | import time
7 |
8 | from msl.equipment import (
9 | EquipmentRecord,
10 | ConnectionRecord,
11 | Backend,
12 | )
13 | from msl.equipment.resources.thorlabs import MotionControl
14 |
15 | # ensure that the Kinesis folder is available on PATH
16 | os.environ['PATH'] += os.pathsep + 'C:/Program Files/Thorlabs/Kinesis'
17 |
18 | record = EquipmentRecord(
19 | manufacturer='Thorlabs',
20 | model='KSC101',
21 | serial='68000297', # update for your device
22 | connection=ConnectionRecord(
23 | backend=Backend.MSL,
24 | address='SDK::Thorlabs.MotionControl.KCube.Solenoid.dll',
25 | ),
26 | )
27 |
28 |
29 | def is_open():
30 | return shutter.get_operating_state() == 1
31 |
32 |
33 | # avoid the FT_DeviceNotFound error
34 | MotionControl.build_device_list()
35 |
36 | # connect to the KCube Solenoid
37 | shutter = record.connect()
38 | print('Connected to {}'.format(shutter))
39 |
40 | # start polling at 200 ms
41 | shutter.start_polling(200)
42 |
43 | # set the operating mode to SC_OperatingModes.SC_Manual
44 | shutter.set_operating_mode('Manual')
45 |
46 | for i in range(5):
47 |
48 | # set the operating state to SC_OperatingStates.SC_Active
49 | print('Opening the shutter...')
50 | shutter.set_operating_state('Active')
51 | while not is_open():
52 | time.sleep(0.05)
53 | print(' Is the shutter open? {}'.format(is_open()))
54 |
55 | time.sleep(1)
56 |
57 | # set the operating state to SC_OperatingStates.SC_Inactive
58 | print('Closing the shutter...')
59 | shutter.set_operating_state('Inactive')
60 | while is_open():
61 | time.sleep(0.05)
62 | print(' Is the shutter open? {}'.format(is_open()))
63 |
64 | time.sleep(1)
65 |
66 | # stop polling and close the connection
67 | shutter.stop_polling()
68 | shutter.disconnect()
69 |
--------------------------------------------------------------------------------
/packages/validate/tests/test_osc8.py:
--------------------------------------------------------------------------------
1 | import sys
2 |
3 | import pytest
4 | from msl.equipment_validate import osc8
5 |
6 | file = "does-not-exist.txt:4:10"
7 |
8 |
9 | @pytest.mark.parametrize(
10 | ("command", "expect"),
11 | [
12 | ("vs", False),
13 | ("vs://ftp", False),
14 | ("vs://file/", False),
15 | ("vs://file/a", True),
16 | ("vs://file/a:10", True),
17 | ("vs://file/a:10:5", True),
18 | ("vs://ftp/a:10:5", False),
19 | ("vs://file//path/to/file.xml:10:5", True),
20 | ("vs://file//C:\\path\\to\\file.xml:10:5", True),
21 | ("vs://file//C:\\path\\to file\\ with spaces.xml:10:5", True),
22 | ],
23 | )
24 | def test_regex(command: str, expect: bool) -> None: # noqa: FBT001
25 | assert osc8.uri_scheme_handler(command) is expect
26 |
27 |
28 | def test_uri_scheme_handler_invalid_command() -> None:
29 | assert not osc8.uri_scheme_handler(f"pycharm://wrong/{file}")
30 |
31 |
32 | def test_uri_scheme_handler_unknown() -> None:
33 | assert not osc8.uri_scheme_handler(f"unknown://file/{file}")
34 |
35 |
36 | def test_uri_scheme_handler_notepad_pp() -> None:
37 | assert osc8.uri_scheme_handler(f"n++://file/{file}")
38 |
39 |
40 | def test_uri_scheme_handler_pycharm() -> None:
41 | assert osc8.uri_scheme_handler(f"pycharm://file/{file}")
42 |
43 |
44 | def test_uri_scheme_handler_vs() -> None:
45 | assert osc8.uri_scheme_handler(f"vs://file/{file}")
46 |
47 |
48 | def test_uri_scheme_handler_vscode() -> None:
49 | # vscode registers it's own handler in the Windows registry
50 | assert not osc8.uri_scheme_handler(f"vscode://file/{file}")
51 |
52 |
53 | @pytest.mark.skipif(sys.platform != "win32", reason="only test on Windows, requires winreg")
54 | def test_register_uri_scheme_vscode() -> None:
55 | assert not osc8.register_uri_scheme("vscode")
56 |
57 |
58 | @pytest.mark.skipif(sys.platform != "win32", reason="only test on Windows, requires winreg")
59 | def test_unregister_uri_scheme_vscode() -> None:
60 | assert not osc8.unregister_uri_scheme("vscode")
61 |
--------------------------------------------------------------------------------
/tests/test_nidaq.py:
--------------------------------------------------------------------------------
1 | from __future__ import annotations
2 |
3 | # pyright: reportUnknownMemberType=false, reportUnknownVariableType=false
4 | import nidaqmx # type: ignore[import-untyped] # pyright: ignore[reportMissingTypeStubs]
5 | import pytest
6 |
7 | from msl.equipment import NIDAQ, Connection, Equipment
8 |
9 |
10 | def test_equivalent_to_importing_nidaqmx() -> None:
11 | daq = NIDAQ(Equipment(connection=Connection(address="Dev1")))
12 |
13 | assert f"{daq.address}/ai0" == "Dev1/ai0"
14 |
15 | assert daq.CtrFreq is nidaqmx.CtrFreq
16 | assert daq.CtrTick is nidaqmx.CtrTick
17 | assert daq.CtrTime is nidaqmx.CtrTime
18 | assert daq.DaqError is nidaqmx.DaqError
19 | assert daq.DaqReadError is nidaqmx.DaqReadError
20 | assert daq.DaqResourceWarning is nidaqmx.DaqResourceWarning
21 | assert daq.DaqWarning is nidaqmx.DaqWarning
22 | assert daq.DaqWriteError is nidaqmx.DaqWriteError
23 | assert daq.GRPC_SERVICE_INTERFACE_NAME is nidaqmx.GRPC_SERVICE_INTERFACE_NAME
24 | assert daq.GrpcSessionOptions is nidaqmx.GrpcSessionOptions
25 | assert daq.Scale is nidaqmx.Scale
26 | assert daq.Task is nidaqmx.Task
27 | assert daq.constants is nidaqmx.constants
28 | assert daq.error_codes is nidaqmx.error_codes
29 | assert daq.errors is nidaqmx.errors
30 | assert daq.grpc_session_options is nidaqmx.grpc_session_options
31 | assert daq.scale is nidaqmx.scale
32 | assert daq.system is nidaqmx.system
33 | assert daq.task is nidaqmx.task
34 | assert daq.types is nidaqmx.types
35 | assert daq.utils is nidaqmx.utils
36 | assert daq.version is nidaqmx.version
37 |
38 | # these must not raise AttributeError
39 | assert daq.stream_readers
40 | assert daq.stream_writers
41 |
42 | with pytest.raises(AttributeError):
43 | _ = nidaqmx.doesnotexist
44 |
45 | with pytest.raises(AttributeError):
46 | _ = daq.doesnotexist
47 |
48 |
49 | def test_no_connection_instance() -> None:
50 | with pytest.raises(TypeError, match=r"A Connection is not associated"):
51 | _ = NIDAQ(Equipment())
52 |
--------------------------------------------------------------------------------
/packages/resources/examples/optosigma/shot702.py:
--------------------------------------------------------------------------------
1 | """Example showing how to communicate with a SHOT-702 (2-axis stage controller) from OptoSigma."""
2 |
3 | from __future__ import annotations
4 |
5 | import time
6 | from typing import TYPE_CHECKING
7 |
8 | from msl.equipment import Connection
9 |
10 | if TYPE_CHECKING:
11 | from msl.equipment.resources import SHOT702, optosigma
12 |
13 |
14 | connection = Connection(
15 | "COM1", # update for your controller
16 | manufacturer="OptoSigma",
17 | model="SHOT-702",
18 | timeout=2,
19 | )
20 |
21 |
22 | def print_status(status: optosigma.Status) -> None:
23 | """Callback function that is used by the "wait" method."""
24 | print(f" p1={status.position1}, p2={status.position2}, state={status.state!r}, is_moving={status.is_moving}")
25 |
26 |
27 | # connect to the controller
28 | shot: SHOT702 = connection.connect()
29 |
30 | # move stage 1 to the home position
31 | print("Homing...")
32 | shot.home(1)
33 |
34 | # wait for the stage to finish moving while printing the status
35 | shot.wait(print_status)
36 |
37 | # move stage 1 to a position
38 | print("Move to 10000...")
39 | shot.move_absolute(1, 10000)
40 |
41 | # wait for the stage to finish moving while printing the status
42 | shot.wait(print_status)
43 |
44 | # move stage 1 by -1000
45 | print("Move by -1000...")
46 | shot.move_relative(1, -1000)
47 |
48 | # wait for the stage to finish moving while printing the status
49 | shot.wait(print_status)
50 |
51 | # get the status of the stages
52 | status = shot.status()
53 | print("position1={}, position2={}, state={}, is_moving={}".format(*status))
54 |
55 | # start moving stage 1 at the minimum speed in the + direction for 5 seconds
56 | print("Start moving stage 1 for 5 seconds...")
57 | shot.move(1, "+")
58 | time.sleep(5)
59 |
60 | # slowly stop stage 1
61 | print("Stopping stage 1")
62 | shot.stop_slowly(1)
63 |
64 | # get the status of the stages
65 | status = shot.status()
66 | print("position1={}, position2={}, state={}, is_moving={}".format(*status))
67 |
68 | # disconnect from the controller
69 | shot.disconnect()
70 |
--------------------------------------------------------------------------------
/packages/resources/examples/dataray/wincamd.py:
--------------------------------------------------------------------------------
1 | """Example showing how to communicate with a WinCamD beam-profiling camera from DataRay.
2 |
3 | Tested with the WinCamD-LCM-8.0E45 (x64) software version.
4 | """
5 |
6 | from __future__ import annotations
7 |
8 | from typing import TYPE_CHECKING
9 |
10 | from msl.equipment import Connection
11 |
12 | if TYPE_CHECKING:
13 | from msl.equipment.resources import WinCamD
14 |
15 | connection = Connection(
16 | "SDK::DATARAYOCX",
17 | manufacturer="DataRay",
18 | model="WinCamD",
19 | # plateau_uniformity=True, # these are some examples of the properties that can be specified
20 | # full_scale_filter=0.5,
21 | )
22 |
23 | # Connect to the camera (a GUI will be displayed).
24 | # The GUI must remain open to have access to the DataRay OCX library.
25 | # The text "Error in oglInitialize invalid operation" might be printed, ignore it.
26 | camera: WinCamD = connection.connect()
27 |
28 | # Wait until the camera has been configured (e.g., set the image size, ROI, major/minor mode, ...)
29 | camera.wait_to_configure()
30 |
31 | # Capture an image,
32 | camera.capture()
33 |
34 | # and then you can get information about the image
35 | print("image", camera.image)
36 | print("profile_x", camera.profile_x)
37 | print("profile_y", camera.profile_y)
38 | print("pixel_size", camera.pixel_size)
39 | print("centroid", camera.centroid)
40 | print("roi", camera.roi)
41 | print("xc", camera.xc)
42 | print("xg", camera.xg)
43 | print("xp", camera.xp)
44 | print("yc", camera.yc)
45 | print("yg", camera.yg)
46 | print("yp", camera.yp)
47 | print("major", camera.major)
48 | print("mean", camera.mean)
49 | print("minor", camera.minor)
50 | print("orientation", camera.orientation)
51 | print("plateau_uniformity", camera.plateau_uniformity)
52 | print("homogeneity", camera.homogeneity)
53 | print("adc_peak_percent", camera.adc_peak_percent)
54 | print("effective_2w", camera.effective_2w)
55 | print("ellipticity", camera.ellipticity)
56 | print("exposure_time", camera.exposure_time)
57 |
58 | # You can also access properties of the SDK
59 | print("ImagerGain", camera.sdk.ImagerGain)
60 | print("CameraType", camera.sdk.CameraType())
61 |
62 | # Disconnect from the camera (also closes the GUI)
63 | camera.disconnect()
64 |
--------------------------------------------------------------------------------
/packages/validate/tests/registers/duplicate_id_a.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | MSLE.M.001
5 | Sky-net
6 | T-1000
7 | 00000000001
8 | A mimetic poly-alloy (liquid metal)
9 |
10 | Kibble Balance
11 | Active
12 | false
13 | true
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | MSLE.M.003
24 | Sky-net
25 | T-1000
26 | 00000000003
27 | A mimetic poly-alloy (liquid metal)
28 |
29 | Kibble Balance
30 | Active
31 | false
32 | true
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 | MSLE.M.002
43 | Sky-net
44 | T-1000
45 | 00000000002
46 | A mimetic poly-alloy (liquid metal)
47 |
48 | Kibble Balance
49 | Active
50 | false
51 | true
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/packages/validate/tests/registers/duplicate_id_b.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | MSLE.M.004
5 | Sky-net
6 | T-1000
7 | 00000000004
8 | A mimetic poly-alloy (liquid metal)
9 |
10 | Kibble Balance
11 | Active
12 | false
13 | true
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | MSLE.M.002
24 | Sky-net
25 | T-1000
26 | 00000000002
27 | A mimetic poly-alloy (liquid metal)
28 |
29 | Kibble Balance
30 | Active
31 | false
32 | true
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 | MSLE.M.005
43 | Sky-net
44 | T-1000
45 | 00000000005
46 | A mimetic poly-alloy (liquid metal)
47 |
48 | Kibble Balance
49 | Active
50 | false
51 | true
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
--------------------------------------------------------------------------------
/docs/index.md:
--------------------------------------------------------------------------------
1 | # Overview
2 |
3 | !!! info
4 | The docs are being rewritten. See [here](https://msl-equipment.readthedocs.io/en/latest/index.html) for the old docs.
5 |
6 | The purpose of `msl-equipment` is to manage information about equipment and to interface with equipment for computer control. The information that is managed is focused on testing and calibration laboratories that are accredited for the [ISO/IEC 17025](https://www.iso.org/ISO-IEC-17025-testing-and-calibration-laboratories.html){:target="_blank"} standard, but the information may also be selectively specified for laboratories that are not required to meet the standard. See the [Getting Started][] page to learn how information is managed and how equipment is controlled.
7 |
8 | ## Install
9 |
10 | The `msl-equipment` [repository](https://github.com/MSLNZ/msl-equipment/){:target="_blank"} is organised as a [workspace project](https://docs.astral.sh/uv/concepts/projects/workspaces/){:target="_blank"} that is split across multiple packages: `msl-equipment`, [msl-equipment-resources][resources], [msl-equipment-validate][validate], and [msl-equipment-webapp][web-application].
11 |
12 | The core package is `msl-equipment` and it is available through the [Python Package Index](https://pypi.org/project/msl-equipment/){:target="_blank"}. It can be installed using a variety of package managers
13 |
14 | === "pip"
15 | ```console
16 | pip install msl-equipment
17 | ```
18 |
19 | === "uv"
20 | ```console
21 | uv add msl-equipment
22 | ```
23 |
24 | === "poetry"
25 | ```console
26 | poetry add msl-equipment
27 | ```
28 |
29 | === "pdm"
30 | ```console
31 | pdm add msl-equipment
32 | ```
33 |
34 | ### Dependencies
35 |
36 | The `msl-equipment` package depends on the following packages: [msl-loadlib](https://mslnz.github.io/msl-loadlib/latest/), [numpy](https://www.numpy.org/){:target="_blank"}, [pyserial](https://pyserial.readthedocs.io/en/latest/){:target="_blank"}, [pyzmq](https://pyzmq.readthedocs.io/en/stable/){:target="_blank"}
37 |
38 | The following packages are optional dependencies that may be installed to interface with equipment: [msl-equipment-resources][resources], [NI-DAQmx](https://nidaqmx-python.readthedocs.io/en/stable/){:target="_blank"}, [PyVISA](https://pyvisa.readthedocs.io/en/stable/){:target="_blank"}, [PyVISA-py](https://pyvisa.readthedocs.io/projects/pyvisa-py/en/stable/){:target="_blank"}
39 |
--------------------------------------------------------------------------------
/packages/resources/examples/avantes/avaspec_callback.py:
--------------------------------------------------------------------------------
1 | """Example showing how to use a callback with an AvaSpec-2048L spectrometer.
2 |
3 | The AvaSpec shared library may require a Visual C++ Redistributable Package to be installed (on Windows).
4 | """
5 |
6 | from __future__ import annotations
7 |
8 | import time
9 | from typing import TYPE_CHECKING
10 |
11 | from msl.equipment import Connection
12 | from msl.equipment.resources import avantes
13 |
14 | if TYPE_CHECKING:
15 | from ctypes import _Pointer, c_int32 # pyright: ignore[reportPrivateUsage]
16 |
17 | from msl.equipment.resources import AvaSpec
18 |
19 |
20 | @avantes.avaspec_callback
21 | def callback(handle: _Pointer[c_int32], info: _Pointer[c_int32]) -> None:
22 | """This function is called every time a measurement scan is available."""
23 | print(f"The DLL handle is: {handle.contents.value}")
24 | if info.contents.value == 0: # equals 0 if everything is okay (see manual)
25 | print(f" callback data: {ava.get_data()}")
26 |
27 |
28 | connection = Connection(
29 | "SDK::C:/Path/to/avaspecx64.dll", # update path to avaspec library
30 | manufacturer="Avantes",
31 | model="AvaSpec-2048L", # update for your device
32 | serial="1807344U1", # update for your device
33 | )
34 |
35 | # initializes the Avantes SDK and establishes the connection to the spectrometer
36 | ava: AvaSpec = connection.connect()
37 |
38 | # get the number of pixels that the spectrometer has
39 | num_pixels = ava.get_num_pixels()
40 | print(f"The spectrometer has {num_pixels} pixels")
41 |
42 | # get the wavelength value of each pixel
43 | wavelengths = ava.get_lambda()
44 |
45 | # enable the 16-bit AD converter
46 | ava.use_high_res_adc(enable=True)
47 |
48 | # prepare the measurement type of the spectrometer
49 | # (the values of just a few parameters are updated here, see the manual for more details)
50 | cfg = avantes.MeasConfigType()
51 | cfg.m_StopPixel = num_pixels - 1
52 | cfg.m_IntegrationTime = 5 # in milliseconds
53 | cfg.m_NrAverages = 1 # number of averages
54 | ava.prepare_measure(cfg)
55 |
56 | # start continuous measurements
57 | # (use a callback function to be notified when a measurement is ready)
58 | ava.measure_callback(-1, callback)
59 |
60 | # get as many scans as possible for 2 seconds
61 | time.sleep(2)
62 |
63 | # stop continuous measurements
64 | ava.stop_measure()
65 |
66 | # disconnect from the spectrometer
67 | ava.disconnect()
68 |
--------------------------------------------------------------------------------
/packages/resources/examples/picotech/pt104.py:
--------------------------------------------------------------------------------
1 | """Example showing how to communicate with a PT-104 Data Logger.
2 |
3 | This examples assumes that a voltage is applied to channel 1 and a PT100 is connected to channel 2.
4 | """
5 |
6 | from __future__ import annotations
7 |
8 | import os
9 | import time
10 | from typing import TYPE_CHECKING
11 |
12 | from msl.equipment import Connection
13 |
14 | if TYPE_CHECKING:
15 | from msl.equipment.resources import PT104
16 |
17 |
18 | connection = Connection(
19 | "SDK::usbpt104", # Alternatively, specify the full path to the SDK, "SDK::path/to/lib/usbpt104"
20 | manufacturer="PicoTech",
21 | model="PT-104",
22 | serial="JO332/224", # Change for your device
23 | ip_address="192.168.1.20:1875", # Optional: Specify the IP address and port (change for your device)
24 | # open_via_ip=True, # Optional: True: connect via ethernet, False: connect via USB (default)
25 | )
26 |
27 | # Optional: Ensure that the Pico Technology SDK is available on PATH (if not already)
28 | os.environ["PATH"] += os.pathsep + r"C:\Program Files\Pico Technology\SDK\lib"
29 |
30 | # Connect to the PT-104
31 | pt104: PT104 = connection.connect()
32 |
33 | # Get all available information about the PT-104
34 | print(pt104.get_unit_info())
35 |
36 | # Use the enum value to get the calibration date and do not print the member-name prefix
37 | info = pt104.get_unit_info(5, prefix=False)
38 | print(f"The PT-104 was calibrated on {info}")
39 |
40 | # Use the enum member name to get the MAC address
41 | print(pt104.get_unit_info("mac_address"))
42 |
43 | # Get the details of the ethernet connection
44 | enabled, ip_address, port = pt104.get_ip_details()
45 | print(f"Ethernet enabled? {enabled}")
46 | print(f"Address: {ip_address}:{port}")
47 |
48 | # Set channel 1 to measure the resistance of a PT1000 in a 4-wire arrangement
49 | pt104.set_channel(1, pt104.Mode.RESISTANCE_TO_10K, 4)
50 |
51 | # Set channel 2 to measure the temperature of a PT100 in a 4-wire arrangement
52 | pt104.set_channel(2, pt104.Mode.PT100, 4)
53 |
54 | # Wait for the samples to be available
55 | # A measurement cycle takes about 1 second per active channel
56 | # 2 channels are active, so we should wait at least 2 seconds
57 | time.sleep(3)
58 |
59 | # Read the values
60 | ch1 = pt104.get_value(1)
61 | ch2 = pt104.get_value(2)
62 | print(f"Resistance={ch1}, Temperature={ch2}")
63 |
64 | # Disconnect from the Data Logger
65 | pt104.disconnect()
66 |
--------------------------------------------------------------------------------
/tests/resources/gpib.cpp:
--------------------------------------------------------------------------------
1 | // gpib.cpp
2 | // Mocks a GPIB library for testing purposes.
3 | //
4 | // Compiled using:
5 | // cl /LD gpib.cpp /link /OUT:gpib.dll
6 | // g++ gpib.cpp -fPIC -shared -Bstatic -Wall -o gpib.so
7 | // g++ gpib.cpp -fPIC -shared -Bstatic -Wall -o gpib.dylib
8 | //
9 | #include "gpib.h"
10 | #include
11 |
12 | int ThreadIbsta( void ) { return 0; }
13 | int ThreadIberr( void ) { return EARG; }
14 | int ThreadIbcnt( void ) {
15 | return 10; // pretend 10 bytes are sent or received.
16 | }
17 | int ibask( int ud, int option, int *value ) {
18 | if (option == 0x03) {
19 | *value = 11; // timeout of 1 second
20 | }
21 | return 0;
22 | }
23 | int ibcac( int ud, int synchronous ) { return synchronous + 10; }
24 | int ibclr( int ud ) { return TIMO; }
25 | int ibcmd( int ud, const void *cmd, long cnt ) { return ERR; }
26 | int ibconfig( int ud, int option, int value ) { return 22; }
27 | int ibdev( int board_index, int pad, int sad, int timo, int send_eoi, int eosmode ) {
28 | if (board_index == 3) {
29 | return -1;
30 | }
31 | return 3;
32 | }
33 | int ibgts(int ud, int shadow_handshake) { return shadow_handshake + 1; }
34 | int iblines( int ud, short *line_status ) { *line_status=24; return 0; }
35 | int ibln( int ud, int pad, int sad, short *found_listener ) {
36 | if ((ud == 0 && pad == 5 && sad ==0 ) || (ud == 15 && pad == 11 && sad == 0) || (ud == 15 && pad == 11 && sad == 123)) {
37 | *found_listener = 1;
38 | return 0;
39 | };
40 | return ERR;
41 | }
42 | int ibloc( int ud ) { return 25; }
43 | int ibonl( int ud, int onl ) { return 26; }
44 | int ibpct( int ud ) { return 27; }
45 | int ibrd( int ud, void *buf, long count ) {
46 | memset(buf, 'A', 10);
47 | return END;
48 | }
49 | int ibrsp( int ud, char *spr ) { memset(spr, 'p', 1); return 0; }
50 | int ibsic( int ud ) { return 29; }
51 | int ibspb( int ud, short *sp_bytes ) { *sp_bytes=30; return 0; }
52 | int ibtrg( int ud ) { return 31; }
53 | int ibwait( int ud, int mask ) { return 32; }
54 | int ibwrt( int ud, const void *buf, long count ) { return 33; }
55 | int ibwrta( int ud, const void *buf, long count ) { return 34; }
56 |
57 | #if defined(_MSC_VER)
58 | int ibfindW(const wchar_t *dev) {
59 | if (wcscmp(dev, L"bad") == 0) return -1;
60 | return 2;
61 | }
62 | #else
63 | int ibfind( const char *dev ) {
64 | if (strcmp(dev, "bad") == 0) return -1;
65 | return 2;
66 | }
67 | void ibvers( char **version) { *version = (char*)"1.2"; }
68 | #endif
69 |
--------------------------------------------------------------------------------
/packages/resources/src/msl/equipment/resources/thorlabs/kinesis/__init__.py:
--------------------------------------------------------------------------------
1 | """
2 | Wrapper package around the Thorlabs.MotionControl.C_API.
3 |
4 | The Kinesis software can be downloaded from the `Thorlabs website`_
5 |
6 | .. _Thorlabs website:
7 | https://www.thorlabs.com/software_pages/ViewSoftwarePage.cfm?Code=Motion_Control
8 | """
9 | from __future__ import annotations
10 |
11 |
12 | def _print(cls, fcns, header_filename):
13 | # useful when creating/updating a new wrapper class
14 |
15 | from msl.equipment.resources.utils import CHeader
16 | from msl.equipment.resources.utils import camelcase_to_underscore as convert
17 |
18 | def get_comment(lines, name):
19 | # used when creating a new wrapper class
20 | comments = []
21 | found_it = False
22 | for line in lines:
23 | if name in line and '__cdecl' in line:
24 | found_it = True
25 | continue
26 | if found_it:
27 | if line.startswith('///'):
28 | comments.append(line[3:].strip())
29 | else:
30 | break
31 | return ' """{}\n """'.format(' \n '.join(comments[::-1]))
32 |
33 | already_defined = (vars(cls))
34 |
35 | header = CHeader('C:/Program Files/Thorlabs/Kinesis/' + header_filename, remove_comments=False)
36 | lines = header.get_lines()[::-1]
37 |
38 | for item in sorted(fcns):
39 | method_name = item[0].replace('MMIparams', 'MmiParams')
40 | method_name = method_name.replace('LEDswitches', 'LedSwitches')
41 | method_name = convert(method_name.split('_')[1])
42 | args_p = ''
43 | args_c = ''
44 | for i, arg in enumerate(item[3]):
45 | if i == 0 and 'c_char_p' in str(arg[0]):
46 | args_c += 'self._serial, '
47 | elif 'PyCPointerType' in str(type(arg[0])):
48 | args_c += 'byref({}), '.format(convert(arg[1]))
49 | else:
50 | a = convert(arg[1])
51 | args_p += '{}, '.format(a)
52 | args_c += '{}, '.format(a)
53 |
54 | if method_name in already_defined:
55 | continue
56 |
57 | args_p = args_p[:-2]
58 | if args_p:
59 | print(' def {}(self, {}):'.format(method_name, args_p))
60 | else:
61 | print(' def {}(self):'.format(method_name))
62 | print(get_comment(lines, item[0]))
63 | print(' return self.sdk.{}({})\n'.format(item[0], args_c[:-2]))
64 |
--------------------------------------------------------------------------------
/packages/resources/examples/picotech/ps5000a_block_mode.py:
--------------------------------------------------------------------------------
1 | """Acquire PicoScope data in Block Mode."""
2 |
3 | from __future__ import annotations
4 |
5 | import os
6 | from typing import TYPE_CHECKING
7 |
8 | from msl.equipment import Connection
9 |
10 | if TYPE_CHECKING:
11 | from msl.equipment.resources import PicoScope
12 |
13 | connection = Connection(
14 | "SDK::ps5000a", # Alternatively, specify the full path to the SDK, "SDK::path/to/lib/ps5000a"
15 | manufacturer="Pico Technology",
16 | model="5244B", # Update for your PicoScope
17 | serial="DY135/055", # Update for your PicoScope
18 | # resolution="16bit", # Optional: Specify the device resolution (bit depth)
19 | )
20 |
21 | # Optional: Ensure that the Pico Technology SDK directory is available on PATH (if not already)
22 | os.environ["PATH"] += os.pathsep + r"C:\Program Files\Pico Technology\SDK\lib"
23 |
24 | print("Example :: Using block mode")
25 |
26 | # Connect to the PicoScope
27 | scope: PicoScope = connection.connect()
28 |
29 | # Enable Channel A and set the voltage range to be +/- 1V
30 | scope.set_channel("A", range="1V")
31 |
32 | # Request to sample the voltage every 1 ms, for 20 ms
33 | # Returns the sampling interval and the number of samples that will be acquired
34 | actual_dt, num_samples = scope.set_timebase(1e-3, 20e-3)
35 | print(f"The actual time between samples is {actual_dt} seconds and there will be {num_samples} samples")
36 |
37 | # Channel A is the trigger source with a trigger threshold value of 0.0 V and a timeout of 0.1 second
38 | scope.set_trigger("A", threshold=0.0, timeout=0.1)
39 |
40 | # Start acquisition
41 | wait_time = scope.run_block()
42 | print(f"Acquiring the samples should take approximately {wait_time} seconds")
43 |
44 | # Wait until all requested samples are acquired (polls scope to see if it is ready)
45 | scope.wait_until_ready()
46 |
47 | # Set the data buffer for Channel A
48 | scope.set_data_buffer("A")
49 |
50 | # Fill the data buffer of Channel A with the values saved in the PicoScope's internal memory
51 | num_acquired, overflow_mask = scope.get_values()
52 | print(f"Number of samples acquired is {num_acquired}")
53 | print(f"Overflow bit mask => {overflow_mask}")
54 |
55 | # Get the time when the trigger occurred
56 | trigger_time = scope.get_trigger_time_offset64()
57 | print(f"Trigger occurred at {trigger_time} seconds")
58 |
59 | # Stop the oscilloscope from sampling data
60 | scope.stop()
61 |
62 | print("The voltages are:")
63 | print(scope.channel["A"].volts)
64 |
65 | print("The raw ADU counts are:")
66 | print(scope.channel["A"].adu)
67 |
68 | # Disconnect from the scope
69 | scope.disconnect()
70 |
--------------------------------------------------------------------------------
/packages/resources/examples/picotech/ps5000a_data_ready_callback.py:
--------------------------------------------------------------------------------
1 | """This example handles post-collection data returned by the driver.
2 |
3 | It registers a DataReady callback function that the driver calls when the data has been collected.
4 | """
5 |
6 | from __future__ import annotations
7 |
8 | import os
9 | import time
10 | from typing import TYPE_CHECKING
11 |
12 | from msl.equipment import Connection
13 | from msl.equipment.resources import picoscope as ps
14 |
15 | if TYPE_CHECKING:
16 | from msl.equipment.resources import PicoScope
17 |
18 | connection = Connection(
19 | "SDK::ps5000a", # Alternatively, specify the full path to the SDK, "SDK::path/to/lib/ps5000a"
20 | manufacturer="Pico Technology",
21 | model="5244B", # Update for your PicoScope
22 | serial="DY135/055", # Update for your PicoScope
23 | # resolution="16bit", # Optional: Specify the device resolution (bit depth)
24 | )
25 |
26 | # Optional: Ensure that the Pico Technology SDK directory is available on PATH (if not already)
27 | os.environ["PATH"] += os.pathsep + r"C:\Program Files\Pico Technology\SDK\lib"
28 |
29 |
30 | @ps.data_ready
31 | def my_data_ready(handle: int, status: int, num_samples: int, overflow: int, _: None) -> None:
32 | """Called when post-data collection is ready."""
33 | print(f"Callback: Data ready! {handle=}, {status=}, {num_samples=}, {overflow=}")
34 | print("The voltages are:")
35 | print(scope.channel["A"].volts)
36 |
37 |
38 | print("Example :: Using block mode with a DataReady callback")
39 |
40 | # Connect to the PicoScope
41 | scope: PicoScope = connection.connect()
42 |
43 | # Enable Channel A and set the voltage range to be +/- 1V
44 | scope.set_channel(ps.Channel.A, range=ps.Range.R_1V)
45 |
46 | # Request to sample the voltage every 1 ms, for 100 ms
47 | actual_dt, num_samples = scope.set_timebase(1e-3, 100e-3)
48 | print(f"The actual time between samples is {actual_dt} seconds and there will be {num_samples} samples")
49 |
50 | # Channel A is the trigger source with a trigger threshold value of 0.0 V and a timeout of 0.1 second
51 | scope.set_trigger(ps.Channel.A, threshold=0.0, timeout=0.1)
52 |
53 | print("Start data acquisition...")
54 | _ = scope.run_block()
55 | scope.wait_until_ready()
56 |
57 | # Set the data buffer for Channel A
58 | scope.set_data_buffer("A")
59 |
60 | print("Start data-ready callback...")
61 | scope.get_values_async(my_data_ready)
62 |
63 | # Sleep to make sure the callback function gets called before this script terminates
64 | time.sleep(0.1)
65 |
66 | # Stop the oscilloscope from sampling data
67 | scope.stop()
68 |
69 | # Disconnect from the scope
70 | scope.disconnect()
71 |
--------------------------------------------------------------------------------
/packages/resources/src/msl/equipment_resources/raicol/tec.py:
--------------------------------------------------------------------------------
1 | """Control a TEC (Peltier-based) oven from [Raicol Crystals](https://raicol.com/){:target="_blank"}."""
2 |
3 | from __future__ import annotations
4 |
5 | from typing import TYPE_CHECKING
6 |
7 | from msl.equipment.interfaces import MSLConnectionError, Serial
8 |
9 | if TYPE_CHECKING:
10 | from msl.equipment.schema import Equipment
11 |
12 |
13 | class RaicolTEC(Serial, manufacturer=r"Raicol", model=r"TEC"):
14 | """Control a TEC (Peltier-based) oven from [Raicol Crystals](https://raicol.com/){:target="_blank"}."""
15 |
16 | def __init__(self, equipment: Equipment) -> None:
17 | """Control a TEC (Peltier-based) oven from Raicol Crystals.
18 |
19 | Args:
20 | equipment: An [Equipment][] instance.
21 | """
22 | super().__init__(equipment)
23 | self.write_termination: bytes = b"\n"
24 |
25 | def get_setpoint(self) -> float:
26 | """Get the setpoint temperature.
27 |
28 | Returns:
29 | The setpoint temperature, in Celsius.
30 | """
31 | return float(self.query("Get_T_Set", size=6)[2:])
32 |
33 | def off(self) -> None:
34 | """Turn the TEC off."""
35 | reply = self.query("OFF", size=4)
36 | if reply != "ofOK":
37 | msg = "Cannot turn the TEC off"
38 | raise MSLConnectionError(self, msg)
39 |
40 | def on(self) -> None:
41 | """Turn the TEC on."""
42 | reply = self.query("ON", size=4)
43 | if reply != "onOK":
44 | msg = "Cannot turn the TEC on"
45 | raise MSLConnectionError(self, msg)
46 |
47 | def set_setpoint(self, temperature: float) -> None:
48 | """Set the setpoint temperature.
49 |
50 | Args:
51 | temperature: The setpoint temperature, in Celsius. Must be in the range [20.1, 60.0].
52 | """
53 | t = round(temperature, 1)
54 | if t < 20.1 or t > 60.0: # noqa: PLR2004
55 | msg = f"The setpoint temperature must be between 20.1 and 60.0, got {t}"
56 | raise ValueError(msg)
57 |
58 | reply = self.query(f"Set_T{t:.1f}", size=4, delay=0.05)
59 | if reply != "stOK":
60 | msg = "Cannot change the setpoint temperature"
61 | raise MSLConnectionError(self, msg)
62 |
63 | def temperature(self) -> float:
64 | """Returns the current temperature of the oven.
65 |
66 | The temperature is measured by a PT1000 sensor that is located near the crystal in the metallic mount.
67 |
68 | Returns:
69 | The temperature of the oven, in Celsius.
70 | """
71 | return float(self.query("Data_T", size=7)[2:])
72 |
--------------------------------------------------------------------------------
/packages/resources/examples/picotech/ps5000a_streaming_ready_callback.py:
--------------------------------------------------------------------------------
1 | """Acquire PicoScope data in Streaming Mode."""
2 |
3 | from __future__ import annotations
4 |
5 | import os
6 | from typing import TYPE_CHECKING
7 |
8 | from msl.equipment import Connection
9 | from msl.equipment.resources import picoscope as ps
10 |
11 | if TYPE_CHECKING:
12 | from msl.equipment.resources import PicoScope
13 |
14 | connection = Connection(
15 | "SDK::ps5000a", # Alternatively, specify the full path to the SDK, "SDK::path/to/lib/ps5000a"
16 | manufacturer="Pico Technology",
17 | model="5244B", # Update for your PicoScope
18 | serial="DY135/055", # Update for your PicoScope
19 | # resolution="16bit", # Optional: Specify the device resolution (bit depth)
20 | )
21 |
22 | # Optional: Ensure that the Pico Technology SDK directory is available on PATH (if not already)
23 | os.environ["PATH"] += os.pathsep + r"C:\Program Files\Pico Technology\SDK\lib"
24 |
25 |
26 | @ps.streaming_ready
27 | def my_streaming_ready(
28 | handle: int,
29 | num_samples: int,
30 | start_index: int,
31 | overflow: int,
32 | trigger_at: int,
33 | triggered: int,
34 | auto_stop: int,
35 | _: None,
36 | ) -> None:
37 | """Called when a stream is ready."""
38 | print(f"{handle=}, {num_samples=}, {start_index=}, {overflow=}, {trigger_at=}, {triggered=}, {auto_stop=}")
39 | scope.streaming_done = bool(auto_stop)
40 |
41 |
42 | print("Example :: Using streaming mode")
43 |
44 | # Connect to the PicoScope
45 | scope: PicoScope = connection.connect()
46 |
47 | # Enable Channel A and set the voltage range to be +/- 10V
48 | scope.set_channel(ps.Channel.A, range=ps.Range.R_10V)
49 |
50 | # Request to sample the voltage every 1 ms, for 5 s
51 | # Returns the sampling interval and the number of samples that will be acquired
52 | actual_dt, num_samples = scope.set_timebase(1e-3, 5)
53 | print(f"The actual time between samples is {actual_dt} seconds and there will be {num_samples} samples")
54 |
55 | # Channel A is the trigger source with a trigger threshold value of 0.0 V and a timeout of 0.1 second
56 | scope.set_trigger(ps.Channel.A, threshold=0.0, timeout=0.1)
57 |
58 | # Set the data buffer for Channel A to hold the samples
59 | scope.set_data_buffer(channel=ps.Channel.A)
60 |
61 | # Start streaming mode
62 | _ = scope.run_streaming()
63 | while not scope.streaming_done:
64 | scope.get_streaming_latest_values(my_streaming_ready)
65 |
66 | print("Stopping the PicoScope")
67 | scope.stop()
68 |
69 | print("The voltages are:")
70 | print(scope.channel["A"].volts)
71 |
72 | print("The raw ADU counts are:")
73 | print(scope.channel["A"].adu)
74 |
75 | # Disconnect from the scope
76 | scope.disconnect()
77 |
--------------------------------------------------------------------------------
/packages/resources/examples/thorlabs/kdc101.py:
--------------------------------------------------------------------------------
1 | """
2 | This example shows how to communicate with Thorlabs
3 | KDC101, KCube DC Servo.
4 | """
5 | import os
6 | from pprint import pprint
7 |
8 | from msl.equipment import (
9 | EquipmentRecord,
10 | ConnectionRecord,
11 | Backend,
12 | )
13 | from msl.equipment.resources.thorlabs import MotionControl
14 |
15 | # ensure that the Kinesis folder is available on PATH
16 | os.environ['PATH'] += os.pathsep + 'C:/Program Files/Thorlabs/Kinesis'
17 |
18 | record = EquipmentRecord(
19 | manufacturer='Thorlabs',
20 | model='KDC101',
21 | serial='27251265', # update for your device
22 | connection=ConnectionRecord(
23 | backend=Backend.MSL,
24 | address='SDK::Thorlabs.MotionControl.KCube.DCServo.dll',
25 | ),
26 | )
27 |
28 |
29 | def wait():
30 | motor.clear_message_queue()
31 | while True:
32 | status = motor.convert_message(*motor.wait_for_message())['id']
33 | if status == 'Homed' or status == 'Moved':
34 | break
35 | position = motor.get_position()
36 | real = motor.get_real_value_from_device_unit(position, 'DISTANCE')
37 | print(' at position {} [device units] {:.3f} [real-world units]'.format(position, real))
38 |
39 |
40 | # avoid the FT_DeviceNotFound error
41 | MotionControl.build_device_list()
42 |
43 | # connect to the KCube DC Servo
44 | motor = record.connect()
45 | print('Connected to {}'.format(motor))
46 |
47 | # load the configuration settings, so that we can call
48 | # the get_real_value_from_device_unit() method
49 | motor.load_settings()
50 |
51 | # start polling at 200 ms
52 | motor.start_polling(200)
53 |
54 | # home the device
55 | print('Homing...')
56 | motor.home()
57 | wait()
58 | print('Homing done. At position {} [device units]'.format(motor.get_position()))
59 |
60 | # move to position 100000
61 | print('Moving to 100000...')
62 | motor.move_to_position(100000)
63 | wait()
64 | print('Moving done. At position {} [device units]'.format(motor.get_position()))
65 |
66 | # move by a relative amount of -5000
67 | print('Moving by -5000...')
68 | motor.move_relative(-5000)
69 | wait()
70 | print('Moving done. At position {} [device units]'.format(motor.get_position()))
71 |
72 | # jog forwards
73 | print('Jogging forwards by {} [device units]'.format(motor.get_jog_step_size()))
74 | motor.move_jog('Forwards')
75 | wait()
76 | print('Jogging done. At position {} [device units]'.format(motor.get_position()))
77 |
78 | # stop polling and close the connection
79 | motor.stop_polling()
80 | motor.disconnect()
81 |
82 | # you can access the default settings for the motor to pass to the set_*() methods
83 | print('\nThe default motor settings are:')
84 | pprint(motor.settings)
85 |
--------------------------------------------------------------------------------
/packages/resources/examples/thorlabs/kst101.py:
--------------------------------------------------------------------------------
1 | """
2 | This example shows how to communicate with Thorlabs
3 | KST101, KCube Stepper Motor.
4 | """
5 | import os
6 | from pprint import pprint
7 |
8 | from msl.equipment import (
9 | EquipmentRecord,
10 | ConnectionRecord,
11 | Backend,
12 | )
13 | from msl.equipment.resources.thorlabs import MotionControl
14 |
15 | # ensure that the Kinesis folder is available on PATH
16 | os.environ['PATH'] += os.pathsep + 'C:/Program Files/Thorlabs/Kinesis'
17 |
18 | record = EquipmentRecord(
19 | manufacturer='Thorlabs',
20 | model='KST101',
21 | serial='26000908', # update for your device
22 | connection=ConnectionRecord(
23 | backend=Backend.MSL,
24 | address='SDK::Thorlabs.MotionControl.KCube.StepperMotor.dll',
25 | ),
26 | )
27 |
28 |
29 | def wait():
30 | motor.clear_message_queue()
31 | while True:
32 | status = motor.convert_message(*motor.wait_for_message())['id']
33 | if status == 'Homed' or status == 'Moved':
34 | break
35 | position = motor.get_position()
36 | real = motor.get_real_value_from_device_unit(position, 'DISTANCE')
37 | print(' at position {} [device units] {:.3f} [real-world units]'.format(position, real))
38 |
39 |
40 | # avoid the FT_DeviceNotFound error
41 | MotionControl.build_device_list()
42 |
43 | # connect to the KCube Stepper Motor
44 | motor = record.connect()
45 | print('Connected to {}'.format(motor))
46 |
47 | # load the configuration settings, so that we can call
48 | # the get_real_value_from_device_unit() method
49 | motor.load_settings()
50 |
51 | # start polling at 200 ms
52 | motor.start_polling(200)
53 |
54 | # home the device
55 | print('Homing...')
56 | motor.home()
57 | wait()
58 | print('Homing done. At position {} [device units]'.format(motor.get_position()))
59 |
60 | # move to position 100000
61 | print('Moving to 100000...')
62 | motor.move_to_position(100000)
63 | wait()
64 | print('Moving done. At position {} [device units]'.format(motor.get_position()))
65 |
66 | # move by a relative amount of -5000
67 | print('Moving by -5000...')
68 | motor.move_relative(-5000)
69 | wait()
70 | print('Moving done. At position {} [device units]'.format(motor.get_position()))
71 |
72 | # jog forwards
73 | print('Jogging forwards by {} [device units]'.format(motor.get_jog_step_size()))
74 | motor.move_jog('Forwards')
75 | wait()
76 | print('Jogging done. At position {} [device units]'.format(motor.get_position()))
77 |
78 | # stop polling and close the connection
79 | motor.stop_polling()
80 | motor.disconnect()
81 |
82 | # you can access the default settings for the motor to pass to the set_*() methods
83 | print('\nThe default motor settings are:')
84 | pprint(motor.settings)
85 |
--------------------------------------------------------------------------------
/docs/schema/file.md:
--------------------------------------------------------------------------------
1 | # File
2 |
3 |
13 |
14 | Suppose you have a variable named `file` (which is an instance of [File][msl.equipment.schema.File]) that represents the following information in an equipment register for data that is stored in a Spreadsheet
15 |
16 | ```xml
17 |
18 | tests\resources\irradiance.xlsx
19 | 7a91267cfb529388a99762b891ee4b7a12463e83b5d55809f76a0c8e76c71886
20 |
21 | ```
22 |
23 | You can access *sha256* and *comment* as attributes of `file`
24 |
25 | ```pycon
26 | >>> file.sha256
27 | '7a91267cfb529388a99762b891ee4b7a12463e83b5d55809f76a0c8e76c71886'
28 | >>> file.comment
29 | 'FEL T647'
30 |
31 | ```
32 |
33 | The *url* and *attributes* attributes of `file` can be used with the [read_table][msl.io.tables.read_table]{:target="_blank"} function of [msl-io](https://mslnz.github.io/msl-io/latest/){:target="_blank"} to read the Spreadsheet data
34 |
35 | ```pycon
36 | >>> from msl.io import read_table
37 | >>> table = read_table(file.url, **file.attributes)
38 | >>> print(table.metadata.header)
39 | ['Wavelength' 'Irradiance' 'u(Irradiance)']
40 | >>> table
41 |
42 | >>> print(table)
43 | array([[2.500000e+02, 1.818000e-02, 2.033000e-02],
44 | [3.000000e+02, 1.847800e-01, 1.755000e-02],
45 | [3.500000e+02, 8.084500e-01, 1.606000e-02],
46 | [4.000000e+02, 2.213550e+00, 1.405000e-02],
47 | [4.500000e+02, 4.490040e+00, 1.250000e-02],
48 | [5.000000e+02, 7.451350e+00, 1.200000e-02],
49 | [5.500000e+02, 1.075753e+01, 1.152000e-02],
50 | [6.000000e+02, 1.403809e+01, 1.102000e-02],
51 | [6.500000e+02, 1.699469e+01, 1.103000e-02],
52 | [7.000000e+02, 1.944093e+01, 1.077000e-02]])
53 |
54 | ```
55 |
56 | !!! note
57 | Passing `**file.attributes` to [read_table][msl.io.tables.read_table]{:target="_blank"} works as expected provided that the XML attributes of the `` element are valid keyword arguments to [read_table][msl.io.tables.read_table]{:target="_blank"}. See [Read a table](https://mslnz.github.io/msl-io/latest/#read-a-table){:target="_blank"} for more examples from [msl-io](https://mslnz.github.io/msl-io/latest/){:target="_blank"}, in particular, specifying `dtype="header"` will return a structured dataset which would behave similar to the [Table][table] example in `msl-equipment` (i.e., accessing columns by header name).
58 |
59 | ::: msl.equipment.schema.File
60 | options:
61 | show_root_full_path: false
62 | show_root_heading: true
63 |
--------------------------------------------------------------------------------
/src/msl/equipment/__init__.py:
--------------------------------------------------------------------------------
1 | """Manage and interface with equipment in the laboratory."""
2 |
3 | from __future__ import annotations
4 |
5 | from .__about__ import __version__, version_tuple
6 | from .config import Config
7 | from .enumerations import Backend, DataBits, Parity, StopBits
8 | from .interfaces import (
9 | GPIB,
10 | NIDAQ,
11 | SDK,
12 | VXI11,
13 | HiSLIP,
14 | MessageBased,
15 | MSLConnectionError,
16 | MSLTimeoutError,
17 | Prologix,
18 | PyVISA,
19 | Serial,
20 | Socket,
21 | )
22 | from .readings import Readings
23 | from .record_types import ConnectionRecord, EquipmentRecord
24 | from .schema import (
25 | AcceptanceCriteria,
26 | Accessories,
27 | Adjustment,
28 | Alteration,
29 | CapitalExpenditure,
30 | Competency,
31 | CompletedTask,
32 | Component,
33 | Conditions,
34 | Connection,
35 | CVDEquation,
36 | Deserialised,
37 | DigitalFormat,
38 | DigitalReport,
39 | Equation,
40 | Equipment,
41 | Evaluable,
42 | File,
43 | Financial,
44 | Firmware,
45 | Interface,
46 | IssuingLaboratory,
47 | Maintenance,
48 | Measurand,
49 | PerformanceCheck,
50 | PlannedTask,
51 | QualityManual,
52 | Range,
53 | ReferenceMaterials,
54 | Register,
55 | Report,
56 | Specifications,
57 | SpecifiedRequirements,
58 | Status,
59 | Table,
60 | )
61 |
62 | __all__: list[str] = [
63 | "GPIB",
64 | "NIDAQ",
65 | "SDK",
66 | "VXI11",
67 | "AcceptanceCriteria",
68 | "Accessories",
69 | "Adjustment",
70 | "Alteration",
71 | "Backend",
72 | "CVDEquation",
73 | "CapitalExpenditure",
74 | "Competency",
75 | "CompletedTask",
76 | "Component",
77 | "Conditions",
78 | "Config",
79 | "Connection",
80 | "ConnectionRecord",
81 | "DataBits",
82 | "Deserialised",
83 | "DigitalFormat",
84 | "DigitalReport",
85 | "Equation",
86 | "Equipment",
87 | "EquipmentRecord",
88 | "Evaluable",
89 | "File",
90 | "Financial",
91 | "Firmware",
92 | "HiSLIP",
93 | "Interface",
94 | "IssuingLaboratory",
95 | "MSLConnectionError",
96 | "MSLTimeoutError",
97 | "Maintenance",
98 | "Measurand",
99 | "MessageBased",
100 | "Parity",
101 | "PerformanceCheck",
102 | "PlannedTask",
103 | "Prologix",
104 | "PyVISA",
105 | "QualityManual",
106 | "Range",
107 | "Readings",
108 | "ReferenceMaterials",
109 | "Register",
110 | "Report",
111 | "Serial",
112 | "Socket",
113 | "Specifications",
114 | "SpecifiedRequirements",
115 | "Status",
116 | "StopBits",
117 | "Table",
118 | "__version__",
119 | "version_tuple",
120 | ]
121 |
122 | from . import resources as resources
123 |
--------------------------------------------------------------------------------
/tests/test_record_types.py:
--------------------------------------------------------------------------------
1 | from __future__ import annotations
2 |
3 | from typing import TYPE_CHECKING
4 |
5 | from msl.equipment import Backend, ConnectionRecord, EquipmentRecord
6 | from msl.equipment.record_types import _Warn # pyright: ignore[reportPrivateUsage]
7 |
8 | if TYPE_CHECKING:
9 | import pytest
10 |
11 |
12 | def test_warning_connection_record(recwarn: pytest.WarningsRecorder) -> None:
13 | _Warn.show = True
14 |
15 | equipment = EquipmentRecord(
16 | manufacturer="A",
17 | model="B",
18 | serial="C",
19 | connection=ConnectionRecord(
20 | address="COM1",
21 | backend=Backend.MSL,
22 | manufacturer="A",
23 | model="B",
24 | serial="C",
25 | timeout=10,
26 | ),
27 | )
28 |
29 | assert equipment.manufacturer == "A"
30 | assert equipment.model == "B"
31 | assert equipment.serial == "C"
32 | assert equipment.connection is not None
33 | assert equipment.connection.address == "COM1"
34 | assert equipment.connection.backend == Backend.MSL
35 | assert equipment.connection.manufacturer == "A"
36 | assert equipment.connection.model == "B"
37 | assert equipment.connection.serial == "C"
38 | assert equipment.connection.properties == {"timeout": 10}
39 |
40 | # Warnings issued once
41 | _ = EquipmentRecord(connection=ConnectionRecord(address="A", backend="MSL"))
42 | _ = EquipmentRecord(connection=ConnectionRecord(address="A", backend="PyVISA"))
43 | _ = EquipmentRecord(connection=ConnectionRecord(address="A", backend="NIDAQ"))
44 |
45 | assert len(recwarn) == 1
46 | w = recwarn.pop(FutureWarning)
47 | assert issubclass(w.category, FutureWarning)
48 | assert w.lineno == 19
49 | assert w.filename == __file__
50 | assert str(w.message).endswith(
51 | "Replace `EquipmentRecord` with `Equipment` and replace `ConnectionRecord` with `Connection`."
52 | )
53 |
54 |
55 | def test_warning_equipment_record(recwarn: pytest.WarningsRecorder) -> None:
56 | _Warn.show = True
57 |
58 | equipment = EquipmentRecord(manufacturer="A", model="B", serial="C")
59 |
60 | assert equipment.manufacturer == "A"
61 | assert equipment.model == "B"
62 | assert equipment.serial == "C"
63 | assert equipment.connection is None
64 |
65 | # Warnings issued once
66 | _ = EquipmentRecord(manufacturer="D", model="E", serial="F")
67 | _ = EquipmentRecord(manufacturer="G", model="H", serial="I")
68 | _ = EquipmentRecord(manufacturer="J", model="K", serial="L")
69 |
70 | assert len(recwarn) == 1
71 | w = recwarn.pop(FutureWarning)
72 | assert issubclass(w.category, FutureWarning)
73 | assert w.lineno == 58
74 | assert w.filename == __file__
75 | assert str(w.message).endswith(
76 | "Replace `EquipmentRecord` with `Equipment` and replace `ConnectionRecord` with `Connection`."
77 | )
78 |
--------------------------------------------------------------------------------
/packages/resources/examples/picotech/ps5000a_AWG_builtin.py:
--------------------------------------------------------------------------------
1 | """This example samples a sine wave that is created by the Arbitrary Waveform Generator (AWG).
2 |
3 | The output of the AWG must be connected to Channel A.
4 | """
5 |
6 | from __future__ import annotations
7 |
8 | import os
9 | from typing import TYPE_CHECKING
10 |
11 | import numpy as np
12 |
13 | from msl.equipment import Connection
14 |
15 | if TYPE_CHECKING:
16 | from msl.equipment.resources import PicoScope
17 |
18 | connection = Connection(
19 | "SDK::ps5000a", # Alternatively, specify the full path to the SDK, "SDK::path/to/lib/ps5000a"
20 | manufacturer="Pico Technology",
21 | model="5244B", # Update for your PicoScope
22 | serial="DY135/055", # Update for your PicoScope
23 | # resolution="16bit", # Optional: Specify the device resolution (bit depth)
24 | )
25 |
26 | # Optional: Ensure that the Pico Technology SDK directory is available on PATH (if not already)
27 | os.environ["PATH"] += os.pathsep + r"C:\Program Files\Pico Technology\SDK\lib"
28 |
29 | print("Example :: Builtin AWG waveform")
30 |
31 | # Connect to the PicoScope
32 | scope: PicoScope = connection.connect()
33 |
34 | # Enable Channel A and set the voltage range to be +/- 10V
35 | scope.set_channel("A", range="10V")
36 |
37 | # Request to sample voltage every 1 us, for 200 us
38 | # Returns the sampling interval and the number of samples that will be acquired
39 | actual_dt, num_samples = scope.set_timebase(1e-6, 200e-6)
40 | print(f"The actual time between samples is {actual_dt} seconds and there will be {num_samples} samples")
41 |
42 | # Use Channel A as the trigger source at 1V and wait forever for a trigger event
43 | scope.set_trigger("A", threshold=1.0, timeout=None)
44 |
45 | # Create a sine wave
46 | scope.set_sig_gen_builtin_v2(start_frequency=10e3, peak_to_peak=2.0, offset_voltage=0.4)
47 |
48 | # Start acquisition
49 | _ = scope.run_block()
50 |
51 | # Wait until all requested samples are collected
52 | scope.wait_until_ready()
53 |
54 | # Set the data buffer for Channel A
55 | scope.set_data_buffer("A")
56 |
57 | # Fill the data buffer of Channel A with the values saved in the PicoScope's internal memory
58 | num_acquired, overflow_mask = scope.get_values()
59 | print(f"Number of samples acquired is {num_acquired}")
60 | print(f"Overflow bit mask => {overflow_mask}")
61 |
62 | # Stop the oscilloscope from sampling data
63 | scope.stop()
64 |
65 | # Calculate the timestamps.
66 | # In this example pre_trigger=0 since it was not specified when run_block() was called
67 | # so adjusting the times by `pre_trigger` seconds is not necessary.
68 | t0 = -scope.pre_trigger
69 | t1 = (actual_dt * num_samples) - scope.pre_trigger
70 | times = np.arange(t0, t1, actual_dt)
71 |
72 | volts = scope.channel["A"].volts
73 |
74 | print("The AWG output:")
75 | for t, v in zip(times, volts):
76 | print(f"{t:.2e} {v:f}")
77 |
78 | # Disconnect from the scope
79 | scope.disconnect()
80 |
--------------------------------------------------------------------------------
/tests/resources/light/register.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | MSLE.O.231
5 | MSL
6 | 3458A
7 | 0123456789
8 | A digital multimeter
9 |
10 | Spectrophotometer
11 | Active
12 | false
13 | true
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 | MSLE.O.103
24 | MSL
25 | Single
26 | B02
27 | Single element photodiode
28 |
29 | Spectrophotometer
30 | Active
31 | false
32 | true
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 | MSLE.O.061
43 | MSL
44 | Mono
45 | 123
46 | Monochromator f=500mm
47 |
48 | Spectrophotometer
49 | Active
50 | false
51 | true
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 | MSLE.O.023
62 | MSL
63 | Model
64 | abc
65 | Temperature probe
66 |
67 | Spectrophotometer
68 | Active
69 | true
70 | true
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
--------------------------------------------------------------------------------
/packages/resources/examples/thorlabs/lts150.py:
--------------------------------------------------------------------------------
1 | """
2 | This example shows how to communicate with Thorlabs LTS150,
3 | 150-mm Translation Stage with Stepper Motor.
4 |
5 | By changing the value of the `model` number (see below),
6 | this script can be used to control:
7 |
8 | * Long Travel Stages (LTS150 and LTS300)
9 | * Lab Jack (MLJ050, MLJ150)
10 | * Cage Rotator (K10CR1)
11 | """
12 | import os
13 | from pprint import pprint
14 |
15 | from msl.equipment import (
16 | EquipmentRecord,
17 | ConnectionRecord,
18 | Backend,
19 | )
20 | from msl.equipment.resources.thorlabs import MotionControl
21 |
22 | # ensure that the Kinesis folder is available on PATH
23 | os.environ['PATH'] += os.pathsep + 'C:/Program Files/Thorlabs/Kinesis'
24 |
25 | record = EquipmentRecord(
26 | manufacturer='Thorlabs',
27 | model='LTS150/M', # update for your device
28 | serial='45870601', # update for your device
29 | connection=ConnectionRecord(
30 | backend=Backend.MSL,
31 | address='SDK::Thorlabs.MotionControl.IntegratedStepperMotors.dll',
32 | ),
33 | )
34 |
35 |
36 | def wait():
37 | motor.clear_message_queue()
38 | while True:
39 | status = motor.convert_message(*motor.wait_for_message())['id']
40 | if status == 'Homed' or status == 'Moved':
41 | break
42 | position = motor.get_position()
43 | real = motor.get_real_value_from_device_unit(position, 'DISTANCE')
44 | print(' at position {} [device units] {:.3f} [real-world units]'.format(position, real))
45 |
46 |
47 | # Build the device list before connecting to the Integrated Stepper Motor
48 | MotionControl.build_device_list()
49 |
50 | # connect to the Integrated Stepper Motor
51 | motor = record.connect()
52 | print('Connected to {}'.format(motor))
53 |
54 | # initialize
55 | motor.enable_channel()
56 | motor.load_settings()
57 |
58 | # start polling at 200 ms
59 | motor.start_polling(200)
60 |
61 | # home the device
62 | print('Homing...')
63 | motor.home()
64 | wait()
65 | print('Homing done. At position {} [device units]'.format(motor.get_position()))
66 |
67 | # move to position 100000
68 | print('Moving to 100000...')
69 | motor.move_to_position(100000)
70 | wait()
71 | print('Moving done. At position {} [device units]'.format(motor.get_position()))
72 |
73 | # move by a relative amount of -5000
74 | print('Moving by -5000...')
75 | motor.move_relative(-5000)
76 | wait()
77 | print('Moving done. At position {} [device units]'.format(motor.get_position()))
78 |
79 | # jog forwards
80 | print('Jogging forwards by {} [device units]'.format(motor.get_jog_step_size()))
81 | motor.move_jog('Forwards')
82 | wait()
83 | print('Jogging done. At position {} [device units]'.format(motor.get_position()))
84 |
85 | # stop polling and close the connection
86 | motor.stop_polling()
87 | motor.disconnect()
88 |
89 | # you can access the default settings for the motor to pass to the set_*() methods
90 | print('\nThe default motor settings are:')
91 | pprint(motor.settings)
92 |
--------------------------------------------------------------------------------
/packages/resources/examples/picotech/ps5000a_block_ready_callback.py:
--------------------------------------------------------------------------------
1 | """Acquire PicoScope data in Block-Ready Mode using a callback function.
2 |
3 | The callback function is notified when the data block has been acquired.
4 | """
5 |
6 | from __future__ import annotations
7 |
8 | import os
9 | import time
10 | from typing import TYPE_CHECKING
11 |
12 | from msl.equipment import Connection
13 | from msl.equipment.resources import picoscope as ps
14 |
15 | if TYPE_CHECKING:
16 | from msl.equipment.resources import PicoScope
17 |
18 | connection = Connection(
19 | "SDK::ps5000a", # Alternatively, specify the full path to the SDK, "SDK::path/to/lib/ps5000a"
20 | manufacturer="Pico Technology",
21 | model="5244B", # Update for your PicoScope
22 | serial="DY135/055", # Update for your PicoScope
23 | # resolution="16bit", # Optional: Specify the device resolution (bit depth)
24 | )
25 |
26 | # Optional: Ensure that the Pico Technology SDK directory is available on PATH (if not already)
27 | os.environ["PATH"] += os.pathsep + r"C:\Program Files\Pico Technology\SDK\lib"
28 |
29 |
30 | @ps.block_ready
31 | def run_done(handle: int, status: int, _: None) -> None:
32 | """Called when all samples have been acquired."""
33 | print(f"Callback: Data acquisition is done! {handle=}, {status=}")
34 |
35 | # Set the data buffer for Channel A
36 | scope.set_data_buffer("A")
37 |
38 | # Fill the data buffer of Channel A with the values saved in the PicoScope's internal memory
39 | num_acquired, overflow_mask = scope.get_values()
40 | print(f"Number of samples acquired {num_acquired}")
41 | print(f"Overflow bit mask => {overflow_mask}")
42 |
43 | print(f"The time between samples is {scope.dt} seconds")
44 | print("The voltages are:")
45 | print(scope.channel["A"].volts)
46 |
47 |
48 | print("Example :: Using block-ready mode with a callback function")
49 |
50 | # Connect to the PicoScope
51 | scope: PicoScope = connection.connect()
52 |
53 | # Enable Channel A and set the voltage range to be +/- 1V
54 | scope.set_channel(ps.Channel.A, range=ps.Range.R_1V)
55 |
56 | # Request to sample the voltage every 1 ms, for 20 ms
57 | actual_dt, num_samples = scope.set_timebase(1e-3, 20e-3)
58 | print(f"The actual time between samples is {actual_dt} seconds and there will be {num_samples} samples")
59 |
60 | # Channel A is the trigger source with a trigger threshold value of 0.0 V and a timeout of 0.1 second
61 | scope.set_trigger(ps.Channel.A, threshold=0.0, timeout=0.1)
62 |
63 | print("Start data acquisition...")
64 |
65 | # Pass in our callback function to be notified when data acquisition is finished
66 | wait_time = scope.run_block(callback=run_done)
67 | print(f"Acquiring the samples should take approximately {wait_time} seconds")
68 |
69 | # Sleep to make sure the callback function gets called before this script terminates
70 | time.sleep(wait_time * 1.5)
71 |
72 | print("Stopping the PicoScope")
73 | scope.stop()
74 |
75 | # Disconnect from the scope
76 | scope.disconnect()
77 |
--------------------------------------------------------------------------------
/packages/resources/src/msl/equipment/resources/thorlabs/kinesis/messages.py:
--------------------------------------------------------------------------------
1 | """
2 | Device Message Queue defined in Thorlabs Kinesis v1.14.18
3 |
4 | The device message queue allows the internal events raised by the device to be
5 | monitored by the DLLs owner.
6 |
7 | The device raises many different events, usually associated with a change of state.
8 |
9 | These messages are temporarily stored in the DLL and can be accessed using the
10 | appropriate message functions.
11 |
12 | The message consists of 3 components, a messageType, a messageID and messageData::
13 |
14 | WORD messageType
15 | WORD messageID
16 | WORD messageData
17 |
18 | """
19 | from __future__ import annotations
20 |
21 | #: MessageTypes
22 | MessageTypes = {
23 | 0: 'GenericDevice',
24 | 1: 'GenericPiezo',
25 | 2: 'GenericMotor',
26 | 3: 'GenericDCMotor',
27 | 4: 'GenericSimpleMotor',
28 | 5: 'RackDevice',
29 | 6: 'Laser',
30 | 7: 'TECCtlr',
31 | 8: 'Quad',
32 | 9: 'NanoTrak',
33 | 10: 'Specialized',
34 | 11: 'Solenoid',
35 | }
36 |
37 | #: GenericDevice
38 | GenericDevice = {
39 | 0: 'settingsInitialized',
40 | 1: 'settingsUpdated',
41 | 2: 'settingsExtern',
42 | 3: 'error',
43 | 4: 'close',
44 | 5: 'settingsReset',
45 | }
46 |
47 | #: GenericMotor
48 | GenericMotor = {
49 | 0: 'Homed',
50 | 1: 'Moved',
51 | 2: 'Stopped',
52 | 3: 'LimitUpdated',
53 | }
54 |
55 | #: GenericDCMotor
56 | GenericDCMotor = {
57 | 0: 'error',
58 | 1: 'status',
59 | }
60 |
61 | #: GenericPiezo
62 | GenericPiezo = {
63 | 0: 'maxVoltageChanged',
64 | 1: 'controlModeChanged',
65 | 2: 'statusChanged',
66 | 3: 'maxTravelChanged',
67 | 4: 'TSG_Status',
68 | 5: 'TSG_DisplayModeChanged',
69 | }
70 |
71 | #: RackDevice
72 | RackDevice = {
73 | 0: 'RackCountEstablished',
74 | 1: 'RackBayState',
75 | }
76 |
77 | #: Quad
78 | Quad = {
79 | 0: 'statusChanged',
80 | }
81 |
82 | #: TECCtlr
83 | TECCtlr = {
84 | 0: 'statusChanged',
85 | 2: 'displaySettingsChanged',
86 | 3: 'feedbackParamsChanged',
87 | }
88 |
89 | #: Laser
90 | Laser = {
91 | 0: 'statusChanged',
92 | 1: 'controlSourceChanged',
93 | 2: 'displayModeChanged',
94 | }
95 |
96 | #: Solenoid
97 | Solenoid = {
98 | 0: 'statusChanged',
99 | }
100 |
101 | #: NanoTrak
102 | NanoTrak = {
103 | 0: 'statusChanged',
104 | }
105 |
106 | #: Specialized
107 | Specialized = {}
108 |
109 | #: GenericSimpleMotor
110 | GenericSimpleMotor = {}
111 |
112 | #: MessageID
113 | MessageID = {
114 | 'GenericDevice': GenericDevice,
115 | 'GenericPiezo': GenericPiezo,
116 | 'GenericMotor': GenericMotor,
117 | 'GenericDCMotor': GenericDCMotor,
118 | 'GenericSimpleMotor': GenericSimpleMotor,
119 | 'RackDevice': RackDevice,
120 | 'Laser': Laser,
121 | 'TECCtlr': TECCtlr,
122 | 'Quad': Quad,
123 | 'NanoTrak': NanoTrak,
124 | 'Specialized': Specialized,
125 | 'Solenoid': Solenoid,
126 | }
127 |
--------------------------------------------------------------------------------