diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 0447f5ba..c7750715 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -34,7 +34,7 @@ repos: - id: remove-tabs - id: forbid-tabs - repo: https://github.com/python-jsonschema/check-jsonschema - rev: 0.27.0 + rev: 0.27.1 hooks: - id: check-readthedocs - id: check-dependabot @@ -50,7 +50,7 @@ repos: hooks: - id: blacken-docs - repo: https://github.com/lyz-code/yamlfix/ - rev: 1.13.0 + rev: 1.15.0 hooks: - id: yamlfix - repo: https://github.com/executablebooks/mdformat @@ -122,12 +122,12 @@ repos: always_run: true args: [., --min=10] - repo: https://github.com/charliermarsh/ruff-pre-commit - rev: v0.1.1 + rev: v0.1.4 hooks: - id: ruff args: [--fix, --exit-non-zero-on-fix] - repo: https://github.com/psf/black - rev: 23.10.0 + rev: 23.10.1 hooks: - id: black - repo: https://github.com/PyCQA/docformatter diff --git a/CHANGELOG.md b/CHANGELOG.md index 6b7dd4ed..7d1babbf 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,6 +18,16 @@ ______________________________________________________________________ Things to be included in the next release go here. +### Added + +- New examples added to the basic usage guide showing how to use the commands for some scope drivers +- Added an example showing how to change the VISA backend that is used for connecting to devices +- Added a new support table in the Readme showing the API support for Software Solutions + +### Changed + +- Updated the support level tables in the Readme + ### Removed - Removed some outdated and broken API files diff --git a/README.rst b/README.rst index 748170ba..468ed1de 100644 --- a/README.rst +++ b/README.rst @@ -164,8 +164,8 @@ Basic Script print(scope) -Supported Devices -~~~~~~~~~~~~~~~~~ +Supported Devices & Software Solutions +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .. admonition:: Legend :class: hint @@ -194,33 +194,33 @@ Supported Devices | Control", "| Python API | Validation | Status" - :term:`AFGs `, **AFG3000**, :term:`PI`, ✅, 🚧 + :term:`AFGs `, **AFG3000**, :term:`PI`, ✅, , **AFG31xxx**, :term:`PI`, ✅, - :term:`AWGs `, **AWG5000**, :term:`PI`, ✅, 🚧 - , **AWG5200**, :term:`PI`, ✅, 🚧 - , **AWG7000**, :term:`PI`, ✅, 🚧 - , **AWG70000**, :term:`PI`, ✅, 🚧 - :term:`Scopes `, **2 Series MSO**, :term:`PI`, ✅, 🚧 - , **3 Series MDO**, :term:`PI`, ✅, 🚧 - , **4 Series MSO**, :term:`PI`, ✅, 🚧 - , **5 Series MSO**, :term:`PI`, ✅, 🚧 - , **5 Series B MSO**, :term:`PI`, ✅, 🚧 - , **5 Series MSO (LP)**, :term:`PI`, ✅, 🚧 - , **6 Series MSO**, :term:`PI`, ✅, 🚧 - , **6 Series B MSO**, :term:`PI`, ✅, 🚧 - , **6 Series LPD**, :term:`PI`, ✅, 🚧 - , **MSO2000/B**, :term:`PI`, ✅, 🚧 - , **DPO2000/B**, :term:`PI`, ✅, 🚧 - , **MDO3000**, :term:`PI`, ✅, 🚧 - , **MDO4000/B/C**, :term:`PI`, ✅, 🚧 - , **MSO4000/B**, :term:`PI`, ✅, 🚧 - , **DPO4000/B**, :term:`PI`, ✅, 🚧 - , **MSO5000/B**, :term:`PI`, ✅, 🚧 - , **DPO5000/B**, :term:`PI`, ✅, 🚧 - , **DPO7000/C**, :term:`PI`, ✅, 🚧 + :term:`AWGs `, **AWG5000**, :term:`PI`, ✅, + , **AWG5200**, :term:`PI`, ✅, + , **AWG7000**, :term:`PI`, ✅, + , **AWG70000**, :term:`PI`, ✅, + :term:`Scopes `, **2 Series MSO**, :term:`PI`, ✅, ✅ + , **3 Series MDO**, :term:`PI`, ✅, + , **4 Series MSO**, :term:`PI`, ✅, ✅ + , **5 Series MSO**, :term:`PI`, ✅, ✅ + , **5 Series B MSO**, :term:`PI`, ✅, ✅ + , **5 Series MSO (LP)**, :term:`PI`, ✅, ✅ + , **6 Series MSO**, :term:`PI`, ✅, ✅ + , **6 Series B MSO**, :term:`PI`, ✅, ✅ + , **6 Series LPD**, :term:`PI`, ✅, ✅ + , **MSO2000/B**, :term:`PI`, ✅, + , **DPO2000/B**, :term:`PI`, ✅, + , **MDO3000**, :term:`PI`, ✅, + , **MDO4000/B/C**, :term:`PI`, ✅, + , **MSO4000/B**, :term:`PI`, ✅, + , **DPO4000/B**, :term:`PI`, ✅, + , **MSO5000/B**, :term:`PI`, ✅, + , **DPO5000/B**, :term:`PI`, ✅, ✅ + , **DPO7000/C**, :term:`PI`, ✅, ✅ , **DPO70000/C/D/DX/SX**, :term:`PI`, ✅, 🚧 , **DSA70000/C/D**, :term:`PI`, ✅, 🚧 - , **MSO70000/C/DX**, :term:`PI`, ✅, 🚧 + , **MSO70000/C/DX**, :term:`PI`, ✅, ✅ , **TSOVu**, :term:`PI`, ✅, , **TekScope**, :term:`PI`, ✅, :term:`PSUs `, **2200**, :term:`PI`, ✅, @@ -230,21 +230,37 @@ Supported Devices , **2280S**, :term:`PI`, ✅, , **2281S**, :term:`PI`, ✅, :term:`SMUs `, **24xx Standard**, :term:`PI`, ✅, - , **24xx Interactive**, :term:`TSP`, ✅, 🚧 - , **26xxB**, :term:`TSP`, ✅, 🚧 - , **Model 2601B-PULSE**, :term:`TSP`, ✅, 🚧 + , **24xx Interactive**, :term:`TSP`, ✅, ✅ + , **26xxB**, :term:`TSP`, ✅, ✅ + , **Model 2601B-PULSE**, :term:`TSP`, ✅, , **Model 2606B**, :term:`TSP`, ✅, 🚧 - , **2651A**, :term:`TSP`, ✅, 🚧 - , **2657A**, :term:`TSP`, ✅, 🚧 + , **2651A**, :term:`TSP`, ✅, + , **2657A**, :term:`TSP`, ✅, , **6430 (electrometer)**, :term:`PI`, ✅, , **6514 (electrometer)**, :term:`PI`, ✅, , **6517B (electrometer)**, :term:`PI`, ✅, :term:`MTs `, **TMT4**, :term:`API`, ✅, - :term:`DMMs `, **DMM6500**, :term:`TSP`, ✅, 🚧 - , **DMM7510**, :term:`TSP`, ✅, 🚧 + :term:`DMMs `, **DMM6500**, :term:`TSP`, ✅, + , **DMM7510**, :term:`TSP`, ✅, , **DMM7512**, :term:`TSP`, ✅, - :term:`DAQs `, **DAQ6510**, :term:`TSP`, ✅, 🚧 - :term:`SSs `, **3706A**, :term:`TSP`, ✅, 🚧 + :term:`DAQs `, **DAQ6510**, :term:`TSP`, ✅, + :term:`SSs `, **3706A**, :term:`TSP`, ✅, + +.. csv-table:: Software Solution Support Levels + :name: software-solution-support-table + :align: center + :header-rows: 1 + :widths: auto + :stub-columns: 1 + :class: custom-table-center-cells device-support-table + + "| Software + | Solution", "| Command + | Type", "| Basic + | Control", "| Python API + | Validation + | Status" + :term:`DPOJET`, :term:`PI`, ✅, ✅ Supported Connections ~~~~~~~~~~~~~~~~~~~~~ diff --git a/docs/basic_usage.md b/docs/basic_usage.md index cc89f6c5..18357612 100644 --- a/docs/basic_usage.md +++ b/docs/basic_usage.md @@ -30,6 +30,16 @@ language: python --- ``` +## VISA backend selection + +The `DeviceManager` can be configured to use VISA backends from different VISA implementations. + +```{literalinclude} ../examples/miscellaneous/visa_connection_selectivity.py +--- +language: python +--- +``` + ## Alias usage Devices can be given custom alias names and can be referenced by that alias. @@ -105,6 +115,28 @@ language: python --- ``` +## Configuring a measurement on a single sequence + +A scope can be configured for a measurement on a single acquisition by setting the appropriate acquisition parameters +and adding the desired measurement on the selected channel. + +```{literalinclude} ../examples/scopes/tekscope/get_acquisition_data.py +--- +language: python +--- +``` + +## Adding DPOJET measurements and plots + +DPOJET measurements and plots can be added on a DPO70KSX/C/7KC/DPO5KB scope. +Measurements report can be saved in a `.pdf` format. + +```{literalinclude} ../examples/scopes/tekscope_70k/dpojet/adding_dpojet_measurements.py +--- +language: python +--- +``` + ## Directly accessing the PyVISA resource object The [PyVISA](https://pyvisa.readthedocs.io/en/latest/) resource object can be directly diff --git a/docs/glossary.md b/docs/glossary.md index 3e88e876..f48099da 100644 --- a/docs/glossary.md +++ b/docs/glossary.md @@ -18,6 +18,9 @@ DAQ DMM : Digital Multimeter +DPOJET +: A jitter, noise, timing, and eye diagram analysis tool for Tektronix Performance Digital Oscilloscopes + LP : Low Profile diff --git a/examples/miscellaneous/visa_connection_selectivity.py b/examples/miscellaneous/visa_connection_selectivity.py new file mode 100644 index 00000000..389c6d8e --- /dev/null +++ b/examples/miscellaneous/visa_connection_selectivity.py @@ -0,0 +1,18 @@ +"""An example script to choose visa from different visa resources.""" +from tm_devices import DeviceManager +from tm_devices.helpers import PYVISA_PY_BACKEND, SYSTEM_DEFAULT_VISA_BACKEND + +with DeviceManager(verbose=True) as device_manager: + # Explicitly specify to use the system VISA backend, this is the default, + # **this code is not required** to use the system default. + device_manager.visa_library = SYSTEM_DEFAULT_VISA_BACKEND + # The above code can also be replaced by: + device_manager.visa_library = "@ivi" + + # To use the PyVISA-py backend + device_manager.visa_library = PYVISA_PY_BACKEND + # The above code can also be replaced by: + device_manager.visa_library = "@py" + + scope = device_manager.add_scope("127.0.0.1") + print(scope) # This prints basic information of the connected scope. diff --git a/examples/scopes/tekscope/get_acquisition_data.py b/examples/scopes/tekscope/get_acquisition_data.py new file mode 100644 index 00000000..9bd6f32e --- /dev/null +++ b/examples/scopes/tekscope/get_acquisition_data.py @@ -0,0 +1,48 @@ +"""An example script for connecting and configuring scope for acquisition.""" +from tm_devices import DeviceManager +from tm_devices.drivers import MSO6B +from tm_devices.helpers import PYVISA_PY_BACKEND + +with DeviceManager(verbose=True) as device_manager: + # Enable resetting the devices when connecting and closing + device_manager.setup_cleanup_enabled = True + device_manager.teardown_cleanup_enabled = True + + # Use the PyVISA-py backend + device_manager.visa_library = PYVISA_PY_BACKEND + + # Creating Scope driver object by providing ip address. + scope: MSO6B = device_manager.add_scope("127.0.0.1") # pyright: ignore[reportGeneralTypeIssues] + + # Make channel 1 ON + scope.commands.display.waveview1.ch[1].state.write("ON") + + # Set channel 1 vertical scale to 10mV + scope.commands.ch[1].scale.write(10e-3) + + # Set horizontal record length to 20000 + scope.commands.horizontal.recordlength.write(20000) + + # Set horizontal position to 100 + scope.commands.horizontal.position.write(10) + + # Set trigger type to Edge + scope.commands.trigger.a.type.write("EDGE") + + # Acquisition setup + scope.commands.acquire.state.write("OFF") + scope.commands.acquire.mode.write("Sample") + scope.commands.acquire.stopafter.write("Sequence") + + # Adding measurements + scope.commands.measurement.addmeas.write("AMPLitude") + scope.commands.measurement.addmeas.write("PK2PK") + scope.commands.measurement.meas[1].source.write("CH1") + scope.commands.measurement.meas[2].source.write("CH1") + + # Get the measurements values + scope.commands.acquire.state.write("ON") + + if int(scope.commands.opc.query()) == 1: + scope.commands.measurement.meas[1].results.currentacq.mean.query() + scope.commands.measurement.meas[2].results.currentacq.maximum.query() diff --git a/examples/scopes/tekscope_70k/dpojet/adding_dpojet_measurements.py b/examples/scopes/tekscope_70k/dpojet/adding_dpojet_measurements.py new file mode 100644 index 00000000..6342dd61 --- /dev/null +++ b/examples/scopes/tekscope_70k/dpojet/adding_dpojet_measurements.py @@ -0,0 +1,51 @@ +"""An example of adding dpojet measurements and plots.""" + +from tm_devices import DeviceManager +from tm_devices.drivers import MSO70KDX +from tm_devices.helpers import PYVISA_PY_BACKEND + +with DeviceManager(verbose=True) as device_manager: + # Enable resetting the devices when connecting and closing + device_manager.setup_cleanup_enabled = True + device_manager.teardown_cleanup_enabled = True + + # Use the PyVISA-py backend + device_manager.visa_library = PYVISA_PY_BACKEND + + # Creating one 7K/70K/SX Scope driver object by providing ip address. + scope: MSO70KDX = device_manager.add_scope( + "127.0.0.1" + ) # pyright: ignore[reportGeneralTypeIssues] + + # Starting DPOJET + scope.commands.dpojet.activate.write() + scope.commands.dpojet.version.query() + + # CLear all measurements + scope.commands.dpojet.clearallmeas.write() + + # Add few DPOJET measurements + scope.commands.dpojet.addmeas.write("Period") + scope.commands.dpojet.addmeas.write("Pduty") + scope.commands.dpojet.addmeas.write("RiseTime") + scope.commands.dpojet.addmeas.write("acrms") + + # Add few DPOJET plots for these measurements + scope.commands.dpojet.addplot.write("spectrum, MEAS1") + scope.commands.dpojet.addplot.write("dataarray, MEAS2") + scope.commands.dpojet.addplot.write("TimeTrend, MEAS3") + scope.commands.dpojet.addplot.write("histogram, MEAS4") + + # Start a measurement + scope.commands.dpojet.state.write("single") + + # Get the measurement values for the current acquisition data + scope.commands.dpojet.meas[1].results.currentacq.max.query() + scope.commands.dpojet.meas[1].results.currentacq.population.query() + + # Save all plots + scope.commands.dpojet.saveallplots.write() + + # Save the report + scope.commands.dpojet.report.savewaveforms.write("1") + scope.commands.dpojet.report.write("EXECUTE") diff --git a/pyproject.toml b/pyproject.toml index 377aef3e..514c8bea 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -116,7 +116,7 @@ pip = ">=22.0" poetry = ">=1.5.1" pre-commit = ">=2.20.0" pylint = {extras = ["spelling"], version = ">=3.0"} -pyright = ">=1.1.329" +pyright = ">=1.1.334" pyroma = ">=4.2" pytest = ">=7.1.2" pytest-cov = ">=3.0.0" @@ -124,7 +124,7 @@ pytest-html = ">=4.0" pytest-order = ">=1.0.1" pytest-profiling = ">=1.7.0" python-semantic-release = ">=8.0" -ruff = ">=0.0.292" +ruff = ">=0.1.4" safety = ">=2.1.1" sphinx-autoapi = ">=2.0.0" sphinx-copybutton = ">=0.5.1"