Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

revise AD plugin prime support #470

Merged
merged 6 commits into from
Jan 12, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,20 @@ Change History
* auto-detection of command list format (Excel or text)
* use *openpyxl* instead of *xlrd* and *pandas* to read Excel

* `#470 <https://github.com/BCDA-APS/apstools/pull/470>`_
Area Detector plugin preparation & detection.

* ``AD_plugin_primed()`` re-written completely
* ``AD_prime_plugin()`` replaced by ``AD_prime_plugin2()``

* `#463 <https://github.com/BCDA-APS/apstools/pull/463>`_
Remove deprecated features.

* ``apstools.suspenders.SuspendWhenChanged()``
* ``apstools.utils.plot_prune_fifo()``
* ``apstools.utils.show_ophyd_symbols()``
* ``apstools.synapps.asyn.AsynRecord.binary_output_maxlength()``
* ``AD_warmed_up()``

:1.3.9: released 2020-11-30

Expand Down
135 changes: 75 additions & 60 deletions apstools/devices.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
~AD_plugin_primed
~AD_prime_plugin
~AD_setup_FrameType
~AD_warmed_up

DETECTOR / SCALER SUPPORT

Expand Down Expand Up @@ -1695,13 +1694,13 @@ def AD_setup_FrameType(prefix, scheme="NeXus"):
epics.caput(template.format(prefix, "_RBV", field), value)


def AD_plugin_primed(detector_plugin):
def AD_plugin_primed(plugin):
"""
Has area detector pushed an NDarray to the file writer plugin? True or False

PARAMETERS

detector_plugin
plugin
*obj* :
area detector plugin to be *primed* (such as ``detector.hdf1``)

Expand All @@ -1717,7 +1716,8 @@ def AD_plugin_primed(detector_plugin):
file writer plugin "Capture" is set to 1 (Start). In such case,
first acquire at least one image with the file writer plugin enabled.

PARAMETERS
Also issue in apstools (needs a robust method to detect if primed):
https://github.com/BCDA-APS/apstools/issues/464

Since Area Detector release 2.1 (2014-10-14).

Expand All @@ -1727,86 +1727,101 @@ def AD_plugin_primed(detector_plugin):
in the plugin. This removes the need to initialize the plugin
with a dummy frame before starting capture.
"""
old_capture = detector_plugin.capture.get()
old_file_write_mode = detector_plugin.file_write_mode.get()
if old_capture == 1:
return True

detector_plugin.file_write_mode.put(1)
detector_plugin.capture.put(1)
verdict = detector_plugin.capture.get() == 1
detector_plugin.capture.put(old_capture)
detector_plugin.file_write_mode.put(old_file_write_mode)
return verdict


def AD_prime_plugin(detector, detector_plugin):
cam = plugin.parent.cam
tests = []

for obj in (cam, plugin):
test = np.array(obj.array_size.get()).sum() != 0
tests.append(test)
if not test:
logger.debug("'%s' image size is zero", obj.name)

checks = dict(
array_size = False,
color_mode = True,
data_type = True,
)
for key, as_string in checks.items():
c = getattr(cam, key).get(as_string=as_string)
p = getattr(plugin, key).get(as_string=as_string)
test = c == p
tests.append(test)
if not test:
logger.debug("%s does not match", key)

return False not in tests


def AD_prime_plugin(detector, plugin):
"""
Prime this area detector's file writer plugin.
Collect and push an NDarray to the file writer plugin.
Works with HDF and JPEG file writers, maybe others.

PARAMETERS

detector
*obj* :
area detector (such as ``detector``)
detector_plugin
plugin
*obj* :
area detector plugin to be *primed* (such as ``detector.hdf1``)

EXAMPLE::

AD_prime_plugin(detector, detector.hdf1)

"""
old_enable = detector_plugin.enable.get()
old_mode = detector_plugin.file_write_mode.get()
nm = f"{plugin.parent.name}.{plugin.attr_name}"
warnings.warn(f"Use AD_prime_plugin2({nm}) instead.")
AD_prime_plugin2(plugin)

detector_plugin.enable.put(1)
# next step is important:
# SET the write mode to "Single" (0) or plugin's Capture=1 won't stay
detector_plugin.file_write_mode.put(0)
detector_plugin.capture.put(1)
detector.cam.acquire.put(1)

# reset things
detector_plugin.file_write_mode.put(old_mode)
detector_plugin.enable.put(old_enable)
def AD_prime_plugin2(plugin):
"""
Prime this area detector's file writer plugin.

Collect and push an NDarray to the file writer plugin.
Works with all file writer plugins.

def AD_warmed_up(detector):
"""
Has area detector pushed an NDarray to the HDF5 plugin? True or False
Based on ``ophyd.areadetector.plugins.HDF5Plugin.warmup()``.

**DEPRECATED**:
PARAMETERS

:func:`AD_warmed_up` is now superceded by
:func:`AD_plugin_primed`. To be removed by 2021.
plugin
*obj* :
area detector plugin to be *primed* (such as ``detector.hdf1``)

Works around an observed issue: #598
https://github.com/NSLS-II/ophyd/issues/598#issuecomment-414311372
EXAMPLE::

AD_prime_plugin2(detector.hdf1)

If detector IOC has just been started and has not yet taken an image
with the HDF5 plugin, then a TimeoutError will occur as the
HDF5 plugin "Capture" is set to 1 (Start). In such case,
first acquire at least one image with the HDF5 plugin enabled.
"""
warnings.warn(
"Deprecated: ``AD_warmed_up()`` superceded by ``AD_plugin_primed()``."
" Will be removed in 2021."
)
old_capture = detector.hdf1.capture.get()
old_file_write_mode = detector.hdf1.file_write_mode.get()
if old_capture == 1:
return True

detector.hdf1.file_write_mode.put(1)
detector.hdf1.capture.put(1)
verdict = detector.hdf1.capture.get() == 1
detector.hdf1.capture.put(old_capture)
detector.hdf1.file_write_mode.put(old_file_write_mode)
return verdict
if AD_plugin_primed(plugin):
logger.debug("'%s' plugin is already primed", plugin.name)
return

sigs = OrderedDict(
[
(plugin.enable, 1),
(plugin.parent.cam.array_callbacks, 1), # set by number
(plugin.parent.cam.image_mode, "Single"),
(plugin.parent.cam.trigger_mode, "Internal"),
# just in case the acquisition time is set very long...
(plugin.parent.cam.acquire_time, 1),
(plugin.parent.cam.acquire_period, 1),
(plugin.parent.cam.acquire, 1), # set by number
]
)

original_vals = {sig: sig.get() for sig in sigs}

for sig, val in sigs.items():
time.sleep(0.1) # abundance of caution
set_and_wait(sig, val)

time.sleep(2) # wait for acquisition

for sig, val in reversed(list(original_vals.items())):
time.sleep(0.1)
set_and_wait(sig, val)


class AD_EpicsHdf5FileName(FileStorePluginBase): # lgtm [py/missing-call-to-init]
Expand Down