Skip to content

Commit

Permalink
Merge branch 'main' into 493-v2-lakeshore
Browse files Browse the repository at this point in the history
  • Loading branch information
prjemian committed Jan 17, 2022
2 parents 237a2ae + dd6fcec commit a3c3c92
Show file tree
Hide file tree
Showing 10 changed files with 183 additions and 5 deletions.
Binary file removed .coverage
Binary file not shown.
3 changes: 2 additions & 1 deletion .github/workflows/unit-tests-pytest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ['3.7', '3.8', '3.9', '3.10']
# python-version: ['3.7', '3.8', '3.9', '3.10']
python-version: ['3.7', '3.8', '3.9']
max-parallel: 5

steps:
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
# local developer code
dev_*.py

# unit test
.coverage

db/
log/
pid/
Expand Down
3 changes: 3 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ Breaking Changes
Moved ``apsbss`` support to new ``apsbss`` package (install with either ``pip``
or ``conda``). See https://bcda-aps.github.io/apsbss/ for details.

Can use Python 3.7 - 3.9. Cannot use Python 3.10 yet due to upstream limitation
from databroker and intake packages.

Moved ``command_list_as_table()`` from `utils` into ``plans/command_list``.

``callbacks/``: ``DocumentCollectorCallback``, ``document_contents_callback``, and
Expand Down
2 changes: 1 addition & 1 deletion apstools/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
__platforms__ = "any"
__zip_safe__ = False
__exclude_project_dirs__ = "docs examples resources".split()
__python_version_required__ = ">=3.7"
__python_version_required__ = ">=3.7, <3.10"

__package_name__ = __project__
__long_description__ = __description__
Expand Down
4 changes: 4 additions & 0 deletions apstools/devices/positioner_soft_done.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,11 @@
from ophyd import EpicsSignalRO
from ophyd.signal import EpicsSignalBase
import logging
import time


logger = logging.getLogger(__name__)
SHORT_DELAY_FOR_EPICS = 2.0 / 60 # two 60Hz clock cycles


class PVPositionerSoftDone(PVPositioner):
Expand Down Expand Up @@ -200,6 +202,8 @@ def stop(self, *, success=False):
"""
if not self.inposition:
self.setpoint.put(self.position)
time.sleep(SHORT_DELAY_FOR_EPICS)
self.cb_readback() # re-evaluate soft done Signal


# -----------------------------------------------------------------------------
Expand Down
165 changes: 165 additions & 0 deletions apstools/devices/tests/test_positioner_soft_done.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
from ophyd import EpicsSignal

from ..positioner_soft_done import PVPositionerSoftDone
from ..positioner_soft_done import PVPositionerSoftDoneWithStop
from ...utils import run_in_thread

import pytest
import time

IOC = "gp:"
PV_PREFIX = f"{IOC}gp:"
SHORT_DELAY_FOR_EPICS = 0.02


@pytest.fixture(scope="function")
def rbv():
"Writable readback value for tests."
rbv = EpicsSignal(f"{PV_PREFIX}float1", name="rbv")
rbv.wait_for_connection()
yield rbv


@pytest.fixture(scope="function")
def prec():
"PV precision."
prec = EpicsSignal(f"{PV_PREFIX}float1.PREC", name="prec")
prec.wait_for_connection()
yield prec


@run_in_thread
def delayed_complete(pos, readback, delay=1):
"Time-delayed completion of positioner move."
time.sleep(delay)
readback.put(pos.setpoint.get())


@run_in_thread
def delayed_stop(pos, delay=1):
"Time-delayed stop of `pos`."
time.sleep(delay)
pos.stop()


def test_same_sp_and_rb():
with pytest.raises(ValueError) as exc:
PVPositionerSoftDone("", name="pos")
assert str(exc.value).endswith("must have different values")


@pytest.mark.parametrize(
"device, has_inposition",
[
[PVPositionerSoftDone, False],
[PVPositionerSoftDoneWithStop, True]
]
)
def test_structure(device, has_inposition):
"actual PVs not necessary for this test"
pos = device("", readback_pv="r", setpoint_pv="v", name="pos")
assert isinstance(pos, device)
assert hasattr(pos, "inposition") is has_inposition
assert pos.precision is None
assert pos.prefix == ""
assert pos.readback.pvname == "r"
assert pos.report_dmov_changes.get() is False
assert pos.setpoint.pvname == "v"
assert pos.done.get() is True
assert pos.done_value is True
assert pos.target.get() is None
assert pos.tolerance.get() == -1


def test_put_and_stop(rbv, prec):
device = PVPositionerSoftDoneWithStop

# the positioner to test
pos = device(PV_PREFIX, readback_pv="float1", setpoint_pv="float2", name="pos")
pos.wait_for_connection()
assert pos.tolerance.get() == -1
assert pos.precision == prec.get()

# ensure starting value at 0.0
pos.setpoint.put(0)
rbv.put(1) # make the readback to different
time.sleep(SHORT_DELAY_FOR_EPICS)
assert not pos.inposition

rbv.put(0) # make the readback match
time.sleep(SHORT_DELAY_FOR_EPICS)
assert pos.position == 0.0

assert pos.done.get() is True
assert pos.done_value is True
assert pos.inposition

# change the setpoint
pos.setpoint.put(1)
time.sleep(SHORT_DELAY_FOR_EPICS)
assert not pos.inposition

# change the readback to match
rbv.put(1)
time.sleep(SHORT_DELAY_FOR_EPICS)
assert pos.inposition

# change the setpoint
pos.setpoint.put(0)
time.sleep(SHORT_DELAY_FOR_EPICS)
assert not pos.inposition

# move the readback part-way, but move is not over yet
rbv.put(0.5)
time.sleep(SHORT_DELAY_FOR_EPICS)
assert not pos.inposition

# force a stop now
pos.stop()
time.sleep(SHORT_DELAY_FOR_EPICS)
pos.cb_readback()
time.sleep(SHORT_DELAY_FOR_EPICS)
assert pos.setpoint.get() == 0.5
assert pos.readback.get() == 0.5
assert pos.position == 0.5
assert pos.inposition


def test_move_and_stop(rbv):
device = PVPositionerSoftDoneWithStop

# the positioner to test
pos = device(PV_PREFIX, readback_pv="float1", setpoint_pv="float2", name="pos")
pos.wait_for_connection()

# move to non-zero
longer_delay = 5*SHORT_DELAY_FOR_EPICS
delayed_complete(pos, rbv, delay=longer_delay)
# t0 = time.time() # time it
target = 5.43
pos.move(target) # readback set by delayed_complete()
# dt = time.time() - t0
time.sleep(SHORT_DELAY_FOR_EPICS)
# assert dt >= longer_delay
assert pos.inposition

# move that is stopped before reaching the target
# t0 = time.time() # time it
delayed_stop(pos, longer_delay)
assert pos.inposition

pos.move(target - 1) # readback set by delayed_stop()
# dt = time.time() - t0
# assert dt >= longer_delay
time.sleep(SHORT_DELAY_FOR_EPICS)
assert pos.setpoint.get() == target
assert pos.position == target
assert pos.inposition

# move to 0.0
delayed_complete(pos, rbv, delay=longer_delay)
pos.move(0)
time.sleep(SHORT_DELAY_FOR_EPICS)
assert pos.setpoint.get() == 0
assert pos.position == 0
assert pos.inposition
2 changes: 2 additions & 0 deletions apstools/synApps/tests/test_luascript.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
IOC = "gp:"
PV_PREFIX = f"{IOC}set1:"
EMPIRICAL_DELAY = 0.5
SHORT_DELAY_FOR_EPICS = 2. / 60

# TODO: test a luascript file, where to put the file in the IOC?
# LUA_SCRIPT_PATH
Expand Down Expand Up @@ -99,6 +100,7 @@ def test_compute(code, a, b, nval, aa, bb, sval):
lua_all = UserScriptsDevice(PV_PREFIX, name="user")
lua_all.wait_for_connection()
lua_all.enable.put("Enable")
time.sleep(SHORT_DELAY_FOR_EPICS)
assert lua_all.enable.get(as_string=True) == "Enable"

lua_all.reset()
Expand Down
4 changes: 2 additions & 2 deletions conda/meta.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,10 @@ build:

requirements:
host:
- python >=3.7
- python >=3.7, < 3.10
- pip
run:
- python >=3.7
- python >=3.7, < 3.10
- bluesky >=1.6.7
- databroker >=1.2.3
- h5py
Expand Down
2 changes: 1 addition & 1 deletion environment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ channels:
- aps-anl-tag
- nsls2forge
dependencies:
- python >=3.7
- python >=3.7, <3.10
- bluesky >=1.6.7
- databroker >=1.2.3
- databroker-pack
Expand Down

0 comments on commit a3c3c92

Please sign in to comment.