Skip to content

Commit ce670b9

Browse files
authored
Merge branch 'colinoflynn:master' into master
2 parents ad743e9 + e71dee8 commit ce670b9

File tree

10 files changed

+314
-123
lines changed

10 files changed

+314
-123
lines changed

.github/workflows/pypi.yaml

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# https://packaging.python.org/en/latest/guides/publishing-package-distribution-releases-using-github-actions-ci-cd-workflows/
2+
name: Publish Python 🐍 distributions 📦 to PyPI and TestPyPI
3+
4+
on:
5+
- push
6+
7+
jobs:
8+
build-n-publish:
9+
name: Build and publish Python 🐍 distributions 📦 to PyPI and TestPyPI
10+
if: startsWith(github.ref, 'refs/tags')
11+
runs-on: ubuntu-latest
12+
steps:
13+
- uses: actions/checkout@master
14+
with:
15+
# https://github.com/actions/checkout#fetch-all-history-for-all-tags-and-branches
16+
fetch-depth: 0
17+
- name: Set up Python
18+
uses: actions/setup-python@v1
19+
with:
20+
python-version: "3.10"
21+
- name: Install pypa/build
22+
run: python -m pip install build --user
23+
- name: Build a binary wheel and a source tarball
24+
run: python -m build --sdist --wheel --outdir dist/ .
25+
- name: Publish distribution 📦 to PyPI
26+
uses: pypa/gh-action-pypi-publish@release/v1
27+
with:
28+
user: __token__
29+
password: ${{ secrets.PYPI_API_TOKEN }}
30+
print_hash: true
31+
verify_metadata: true

.github/workflows/test.yml

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
name: Testing
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
pull_request:
8+
9+
jobs:
10+
build:
11+
runs-on: ubuntu-latest
12+
strategy:
13+
matrix:
14+
python-version: ['3.7', '3.11']
15+
16+
steps:
17+
- uses: actions/checkout@v1
18+
- name: Set up Python ${{ matrix.python-version }}
19+
uses: actions/setup-python@v2
20+
with:
21+
python-version: ${{ matrix.python-version }}
22+
- name: Install dependencies
23+
run: |
24+
python -m pip install --upgrade pip
25+
python -m pip install flake8 numpy
26+
- name: Test with tox
27+
run: |
28+
flake8 picoscope setup.py
29+
flake8 examples/*

.travis.yml

Lines changed: 0 additions & 21 deletions
This file was deleted.

README.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,19 @@ python setup.py develop
4646
You will require the PicoScope DLLs for this package to work. The easiest method is to install the latest PicoScope software
4747
or SDK from https://www.picotech.com/downloads .
4848

49+
You may need to add the PicoScope install directory to the path, especially if changing between versions. Be sure you have installed a matching 32-bit or 64-bit version for your Python install.
50+
51+
```
52+
import os
53+
picoinstallpath = os.path.normpath(r"C:\Program Files\Pico Technology\PicoScope 7 T&M Early Access")
54+
if picoinstallpath not in os.environ['PATH']:
55+
print("Adding Pico Install to Path")
56+
os.environ['PATH'] = picoinstallpath + os.pathsep + os.environ['PATH']
57+
else:
58+
print("Pico Install Already on Path")
59+
```
60+
61+
4962
#### Linux
5063
Install the PicoScope Beta for Linux version of PicoScope as describe under Getting DLL's (above). Currently this is the only way to install the shared libraries (SDK)
5164

examples/test_ps4000a.py

Lines changed: 137 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,153 @@
1-
from picoscope import ps4000a
1+
# -*- coding: utf-8 -*-
2+
"""
3+
Testing the ps4000a Series.
4+
"""
5+
6+
# Imports
27
import matplotlib.pyplot as plt
38
import numpy as np
9+
from picoscope import ps4000a
410
import time
511

6-
ps = ps4000a.PS4000a()
712

8-
# rapid block mode
13+
def test_general_unit_calls(picoscope):
14+
"""Test general unit calls."""
15+
picoscope.flashLed()
16+
print(picoscope.getAllUnitInfo())
17+
assert not picoscope.ping(), "Ping failed."
18+
print("General unit calls test passed.")
19+
20+
21+
def test_timebase(ps):
22+
"""Test the timebase methods."""
23+
# Preparation
24+
ps.memorySegments(1)
25+
# Tests
26+
if ps.model == "4444":
27+
data = ((20e-9, 3),
28+
(40e-9, 4))
29+
else:
30+
data = ((25e-9, 1),
31+
(100e-9, 7))
32+
for (t, timebase) in data:
33+
text = f"time {t} does not fit timebase {timebase}."
34+
assert ps.getTimeBaseNum(t) == timebase, "timebasenum: " + text
35+
assert ps.getTimestepFromTimebase(timebase) == t, "Timestep " + text
36+
timestep, _ = ps._lowLevelGetTimebase(timebase, 10, None, 0)
37+
assert timestep == t, f"lowLevel: {timestep} != {t}"
38+
print("Timebase test passed.")
39+
40+
41+
def test_deviceResolution(ps):
42+
"""Test setting/getting device resolution."""
43+
if ps.model == "4444":
44+
ps.setResolution("12")
45+
assert ps.resolution == "12", "Resolution was not set."
46+
# assert ps.getResolution() == "12" not implemented yet
47+
print("Device resolution test passed.")
48+
else:
49+
print("Model does not support resolution.")
50+
51+
52+
def test_rapid_block_mode(ps,
53+
n_captures=100,
54+
sample_interval=100e-9, # 100 ns
55+
sample_duration=2e-3, # 1 ms
56+
):
57+
"""Test the rapid block mode."""
58+
# Configuration of Picoscope
59+
ps.setChannel(channel="A", coupling="DC", VRange=1)
60+
ps.setChannel(channel="B", enabled=False)
61+
62+
ps.setSamplingInterval(sample_interval, sample_duration)
63+
ps.setSimpleTrigger("A", threshold_V=0.1, timeout_ms=1)
64+
65+
samples_per_segment = ps.memorySegments(n_captures)
66+
ps.setNoOfCaptures(n_captures)
67+
68+
data = np.zeros((n_captures, samples_per_segment), dtype=np.int16)
69+
70+
# Measurement
71+
t1 = time.time()
72+
73+
ps.runBlock()
74+
ps.waitReady()
75+
76+
t2 = time.time()
77+
print("Time to record data to scope: ", str(t2 - t1))
78+
79+
ps.getDataRawBulk(data=data)
80+
81+
t3 = time.time()
82+
print("Time to copy to RAM: ", str(t3 - t2))
983

10-
ps.setChannel(channel="A", coupling="DC", VRange=1)
11-
ps.setChannel(channel="B", enabled=False)
12-
ps.setChannel(channel="C", enabled=False)
13-
ps.setChannel(channel="D", enabled=False)
84+
plt.imshow(data[:, 0:ps.noSamples], aspect='auto', interpolation='none',
85+
cmap=plt.cm.hot)
86+
plt.colorbar()
87+
plt.show()
88+
print("Rapid block mode test passed.")
1489

15-
n_captures = 100
16-
sample_interval = 100e-9 # 100 ns
17-
sample_duration = 2e-3 # 1 ms
18-
ps.setResolution('12') # Resolution can only be set on the PS4444
19-
ps.setSamplingInterval(sample_interval, sample_duration)
20-
ps.setSimpleTrigger("A", threshold_V=0.1, timeout_ms=1)
2190

22-
samples_per_segment = ps.memorySegments(n_captures)
23-
ps.setNoOfCaptures(n_captures)
91+
def data_ready(handle, status, noOfSamples, overflow, pParameter=None):
92+
"""Show the asynchronously received data."""
93+
if status == 0:
94+
print(f"{noOfSamples} samples received with overflow: {overflow}")
95+
plt.plot(data)
96+
plt.show()
97+
print("Data reading asynchronously test passed.")
98+
else:
99+
print(f"Data receiving error {status}.")
24100

25-
data = np.zeros((n_captures, samples_per_segment), dtype=np.int16)
26101

27-
t1 = time.time()
102+
def test_read_async(handle=None, status=0, pParameter=None):
103+
"""Test reading data asynchronously."""
104+
if status == 0:
105+
print("Block is ready and can be read.")
106+
channel, numSamples = config
107+
global data
108+
data = np.empty(numSamples, dtype=np.int16)
109+
if not isinstance(channel, int):
110+
channel = ps.CHANNELS[channel]
111+
ps._lowLevelSetDataBuffer(channel, data, 0, 0)
112+
ps._lowLevelGetValuesAsync(numSamples, 0, 1, 0, 0, data_ready, None)
113+
print("Get values async started.")
114+
else:
115+
print("Data is not ready. RunBlock had an error.")
28116

29-
ps.runBlock()
30-
ps.waitReady()
31117

32-
t2 = time.time()
33-
print("Time to record data to scope: ", str(t2 - t1))
118+
def test_runBlock_async(picoscope, channel="A", sample_interval=100e-9,
119+
sample_duration=2e-3):
120+
"""Test running a block asynchronously."""
121+
# Configuration of Picoscope
122+
global ps
123+
ps = picoscope
124+
ps.setChannel(channel=channel, coupling="DC", VRange=1)
125+
ps.memorySegments(1)
126+
ps.setNoOfCaptures(1)
127+
i, samples, m = ps.setSamplingInterval(sample_interval, sample_duration)
128+
ps.setSimpleTrigger("A", threshold_V=0.1, timeout_ms=1)
34129

35-
ps.getDataRawBulk(data=data)
130+
global config
131+
config = channel, samples
132+
# Run the block
133+
ps.runBlock(callback=test_read_async)
134+
print("Run Block started, waiting 2 s.")
135+
time.sleep(2)
136+
print("Run block finished")
36137

37-
t3 = time.time()
38-
print("Time to copy to RAM: ", str(t3 - t2))
39138

40-
plt.imshow(data[:, 0:ps.noSamples], aspect='auto', interpolation='none',
41-
cmap=plt.cm.hot)
42-
plt.colorbar()
43-
plt.show()
139+
if __name__ == "__main__":
140+
"""Run all the tests."""
141+
# Initialize the picoscope
142+
ps = ps4000a.PS4000a()
44143

45-
ps.close()
144+
try:
145+
# Run tests.
146+
test_general_unit_calls(ps)
147+
test_deviceResolution(ps)
148+
test_rapid_block_mode(ps)
149+
test_runBlock_async(ps)
150+
finally:
151+
# Close the connection
152+
ps.close()
153+
print("All tests passed.")

picoscope/picobase.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -887,11 +887,11 @@ def setAWGSimple(self, waveform, duration, offsetVoltage=None,
887887

888888
deltaPhase = self.getAWGDeltaPhase(sampling_interval)
889889

890-
actual_druation = self.setAWGSimpleDeltaPhase(
890+
actual_duration = self.setAWGSimpleDeltaPhase(
891891
waveform, deltaPhase, offsetVoltage, pkToPk, indexMode, shots,
892892
triggerType, triggerSource)
893893

894-
return (actual_druation, deltaPhase)
894+
return (actual_duration, deltaPhase)
895895

896896
def setAWGSimpleDeltaPhase(self, waveform, deltaPhase, offsetVoltage=None,
897897
pkToPk=None, indexMode="Single", shots=1,
@@ -1183,4 +1183,6 @@ def changePowerSource(self, powerstate):
11831183
powerstate = 0x119
11841184
elif powerstate == "PICO_POWER_SUPPLY_NOT_CONNECTED":
11851185
powerstate = 0x11A
1186+
elif powerstate == "PICO_USB3_0_DEVICE_NON_USB3_0_PORT":
1187+
powerstate = 0x11E
11861188
self._lowLevelChangePowerSource(powerstate)

0 commit comments

Comments
 (0)