-
Notifications
You must be signed in to change notification settings - Fork 0
Fix scalers with SAXS/WAXS #568
Comments
Bluesky will not take control of any detector or other devices but
described in the plan. With have to investigate the code to determine what
is happening. I do not suspect bluesky is telling scalers not to count if
they are not given as detectors in the plan.
…On Sun, Oct 30, 2022, 12:53 PM Jan Ilavsky ***@***.***> wrote:
Assigned #568 <#568> to
@prjemian <https://github.com/prjemian>.
—
Reply to this email directly, view it on GitHub
<#568 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AARMUMFA34ZJTXHKFBJ2NADWF2Y2NANCNFSM6AAAAAARSMOQJE>
.
You are receiving this because you were assigned.Message ID:
***@***.***>
|
We are looking for two things:
Looking at SAXS (WAXS is same), this is in scans.py. None of these lines outside areaDetectorAcquire should have any impact on scalers...
So we need to look inside area_detector.py in areaDetectorAcquire, but none of these look suspicious. The only actionable lines seem to be 68-70:
|
Sounds like scalers are being staged for the AD image acquisition. Not what we want. |
These lines start the two scalers counting using ophyd methods (unknown to the RE). The |
After the scalers are started counting: https://github.com/APS-USAXS/usaxs-bluesky/blob/a803031b8c806c74949ff53fab1ef4cc3cb2f678/instrument/plans/scans.py#L877-L881 then the scalers are stopped: https://github.com/APS-USAXS/usaxs-bluesky/blob/a803031b8c806c74949ff53fab1ef4cc3cb2f678/instrument/plans/scans.py#L885-L899 So far, no staging commands for either scaler. |
The text This shoots down the theory that the |
See a suggestion: #569 (comment) |
In my simulator, using scaler test codefrom bluesky import plan_stubs as bps
from bluesky import plans as bp
from bluesky import preprocessors as bpp
from instrument.devices import adsimdet
from instrument.devices import scaler1
for k in "acquire_time acquire_period".split():
if k in adsimdet.cam.stage_sigs:
adsimdet.cam.stage_sigs.pop(k)
def usaxs_issue_568():
@bpp.monitor_during_decorator([scaler1.count])
def _acquire_image():
yield from bp.count([adsimdet])
yield from bps.mv(
scaler1.preset_time, 30,
adsimdet.cam.acquire_time, 5,
adsimdet.cam.acquire_period, 5.01,
)
yield from bps.mv(scaler1.count, 1)
yield from _acquire_image()
yield from bps.mv(scaler1.count, 0) this the test run: In [6]: %run -i /tmp/usaxs_568.py
In [7]: RE(usaxs_issue_568())
Transient Scan ID: 366 Time: 2022-10-31 11:52:28
Persistent Unique Scan ID: '1464876a-7932-4975-a407-b4659169e710'
New stream: 'scaler1_count_monitor'
New stream: 'primary'
+-----------+------------+
| seq_num | time |
+-----------+------------+
| 1 | 11:52:33.2 |
+-----------+------------+
generator count ['1464876a'] (scan num: 366)
Out[7]: ('1464876a-7932-4975-a407-b4659169e710',)
In [8]: RE(usaxs_issue_568())
Transient Scan ID: 367 Time: 2022-10-31 11:52:40
Persistent Unique Scan ID: 'fbf66649-0f40-4563-8cf4-606c1bfb252c'
New stream: 'scaler1_count_monitor'
New stream: 'primary'
+-----------+------------+
| seq_num | time |
+-----------+------------+
| 1 | 11:52:45.5 |
+-----------+------------+
generator count ['fbf66649'] (scan num: 367)
Out[8]: ('fbf66649-0f40-4563-8cf4-606c1bfb252c',) Now, examine the monitor stream to see if the scaler was stopped or restarted during area detector acquisition: In [9]: run = cat[-1]
In [10]: run
Out[10]:
BlueskyRun
uid='fbf66649-0f40-4563-8cf4-606c1bfb252c'
exit_status='success'
2022-10-31 11:52:40.489 -- 2022-10-31 11:52:45.520
Streams:
* scaler1_count_monitor
* primary
In [11]: run.scaler1_count_monitor.read()
Out[11]:
<xarray.Dataset>
Dimensions: (time: 1)
Coordinates:
* time (time) float64 1.667e+09
Data variables:
scaler1_count (time) int64 1 Only one event in the scaler's monitor stream, that's the initial value. |
note: If we add the scaler to the |
So, our data acquisition procedure should be similar to this prototype I used for testing: def usaxs_issue_568():
@bpp.monitor_during_decorator([scaler1.count])
def _acquire_image():
yield from bp.count([adsimdet])
yield from bps.mv(
scaler1.preset_time, 30,
adsimdet.cam.acquire_time, 5,
adsimdet.cam.acquire_period, 5.01,
)
yield from bps.mv(scaler1.count, 1)
logger.info("scaler1.time: %s", scaler1.time.get())
yield from _acquire_image()
logger.info("scaler1.time: %s", scaler1.time.get())
yield from bps.mv(scaler1.count, 0)
logger.info("scaler1.time: %s", scaler1.time.get()) |
Also, code such as https://github.com/APS-USAXS/usaxs-bluesky/blob/a803031b8c806c74949ff53fab1ef4cc3cb2f678/instrument/plans/scans.py#L832-L834 could be replaced with @restorable_stage_sigs([saxs_det.hdf1])
def _inner_plan_steps():
saxs_det.hdf1.stage_sigs["file_template"] = ad_file_template
saxs_det.hdf1.stage_sigs["file_write_mode"] = "Single"
saxs_det.hdf1.stage_sigs["blocking_callbacks"] = "No"
# ... where this is a new decorator I just developed: def stage_sigs_wrapper(user_plan, devices):
"""
Save stage_sigs from each device and restore after the user_plan.
The user_plan is free to modify the stage_sigs of each device
without further need to preserve original values.
"""
def display(preface):
for device in devices:
logger.debug(
"%s: %s.stage_sigs: %s", preface, device.name, device.stage_sigs
)
def _restore():
for device in reversed(devices):
device.stage_sigs = original[device].copy()
display("AFTER restore")
original = {}
display("ORIGINAL")
for device in devices:
original[device] = device.stage_sigs.copy()
try:
display("BEFORE plan")
yield from user_plan
display("AFTER plan")
finally:
_restore()
restorable_stage_sigs = make_decorator(stage_sigs_wrapper) |
Code changes for this issue should be done in a branch, to allow immediate rollback (switching branches) until the code is accepted and merged. |
Aha! The shutters are controlled by a user transform in EPICS. |
note: this was a copy of the settings from |
The values in the transform should be changed from 1 to 0, changing the logic of how the scalers are triggered (and fixing this issue). Because of this transform, it is not necessary for bluesky to trigger either scaler. We plan to drop the branch and make this last change in |
The fix works as tested! |
We have unexpected behavior of our S/WAXS code.
We expect that scaler0 and scaler1 collect I0 (ungated and gated) during AD exposure.
In our scans.py our code sets time in lines 849-865 parameters needed for this collection. Lines 867/869 triggers the data collection on scaler0 and scaler1. Lines 865-899 stop counting and collect I0 values for AD to save in Nexus writer.
Unluckily, this fails: Currently we set the values and trigger the scalers counting, but BS seems to stop scaler0 and scaler1 counting during SAXS/SAXS AD data collection. So we hav eshort counting before AD triggers and short collection after it triggers, but we completely miss the time when we need these scalers to be collecting data.
I suspect that BS (bps.count) stops the scaler0 and scaler1 during the counting since it is not instructed to collect the data on them and does not ignore them as spec used to so (and BS used to do in prior incarnation) .
The text was updated successfully, but these errors were encountered: