Snapshot
This commit is contained in:
@@ -34,7 +34,7 @@ This is needed whenever you edit the scan or device files.
|
||||
In order to start the BEC console interface, you first need to activate the corresponding venv.
|
||||
This will also start the BEC GUI in a separate process and window:
|
||||
```
|
||||
source /data/test/x05la-test-bec/bec_deployment/bev_venv/bin/activate
|
||||
source /data/test/x05la-test-bec/test/bec_venv/bin/activate
|
||||
bec
|
||||
```
|
||||
|
||||
@@ -43,16 +43,14 @@ bec
|
||||
The BEC is deployed to a beamline specific network mounted folder that contains the main
|
||||
repositories for the current installation, you can check it by:
|
||||
```
|
||||
[gac-x05la@x05la-bec-001 ~]$ ls -ltr /data/test/x05la-test-bec/bec_deployment/
|
||||
total 4
|
||||
drwxr-xr-x 7 gac-x05la unx-sls 4096 Aug 20 15:10 ophyd_devices
|
||||
drwxr-xr-x 8 gac-x05la unx-sls 4096 Aug 20 15:10 bec_widgets
|
||||
drwxr-xr-x 6 gac-x05la unx-sls 4096 Aug 20 15:11 bec_venv
|
||||
-rw-r--r-- 1 gac-x05la unx-sls 326 Aug 20 15:15 bec_config.yaml
|
||||
-rw-r--r-- 1 gac-x05la unx-sls 289 Aug 20 15:15 bec_client_config.yaml
|
||||
drwxr-xr-x 15 gac-x05la unx-sls 4096 Aug 29 13:06 bec
|
||||
drwxr-xr-x 7 gac-x05la unx-sls 4096 Sep 3 13:28 tomcat_bec
|
||||
drwxr-xr-x 2 gac-x05la unx-sls 4096 Sep 6 11:22 logs
|
||||
(bec_venv) [gac-x05la@x05la-bec-001 ~]$ ls -ltr /data/test/x05la-test-bec/test/
|
||||
total 3
|
||||
drwxr-xr-x 7 gac-x05la unx-nogroup 4096 Nov 19 15:25 ophyd_devices
|
||||
drwxr-xr-x 8 gac-x05la unx-nogroup 4096 Nov 19 15:25 bec_widgets
|
||||
drwxr-xr-x 6 gac-x05la unx-nogroup 4096 Nov 19 15:26 bec_venv
|
||||
-rw-r--r-- 1 gac-x05la unx-nogroup 451 Nov 19 15:29 bec_config.yaml
|
||||
drwxr-xr-x 6 gac-x05la unx-nogroup 4096 Nov 27 13:35 tomcat_bec
|
||||
drwxr-xr-x 15 gac-x05la unx-nogroup 4096 Nov 27 14:03 bec
|
||||
```
|
||||
A short summary of the folder structure:
|
||||
- bec_venv : The actual installation directory of the BEC framework
|
||||
@@ -61,8 +59,9 @@ A short summary of the folder structure:
|
||||
- ophyd_devices : Git repo as installation directory for shared ophyd devices
|
||||
- tomcat_bec : Git repo as installation directory for Tomcat specific **scans, devices and configs.**
|
||||
|
||||
In short: You should use the bec_venv and only edit the tomcat_bec folder. And this is easily done
|
||||
in Visual Studio Code, a really handy IDE if you have a fast connection:
|
||||
In short: You should activate the installation in the bec_venv directory and only edit the
|
||||
tomcat_bec folder. And this is easily done in Visual Studio Code, a really handy IDE if you
|
||||
have a fast connection:
|
||||
```
|
||||
code &
|
||||
```
|
||||
@@ -111,24 +110,26 @@ If the previous two configuration attempts were unsuccesfull the bec_device_serv
|
||||
without any devices. A single missing or mistyped IOC will cause a configuration failure, so once
|
||||
you fixed you configs you can reload your YAML config file:
|
||||
```
|
||||
bec.config.update_session_with_file("/data/test/x05la-test-bec/bec_deployment/tomcat_bec/tomcat_bec/device_configs/microxas_test_bed.yaml")
|
||||
bec.config.update_session_with_file("/data/test/x05la-test-bec/test/tomcat_bec/tomcat_bec/device_configs/microxas_test_bed.yaml")
|
||||
```
|
||||
If a single, unnecesary device doesn't come up , just comment it out.
|
||||
|
||||
|
||||
## Early tests with GigaFrost and Aerotech
|
||||
|
||||
The main goal of the testbench is to test the various infrastructure component foreseen at the
|
||||
The main goal of the testbench is to test the various infrastructure components foreseen at the
|
||||
Tomcat beamlines and ensure their collaboration. Namely the rotation stage with the Aerotech smart
|
||||
controller, the GigaFrost camera and the Standard-DAQ recording system. The individual repositories
|
||||
have more documentation on the components, but as a short summary, the Aerotech Automation1 IOC is
|
||||
a recently developed EPICS driver, the GigaFrost IOC is an ancient offshoot of Helge's camera driver
|
||||
and the std-DAQ is a non-EPICS device that is controlled via a hybrid websocket and REST interface.
|
||||
and the stdDAQ is a non-EPICS device that is controlled via a hybrid websocket and REST interface.
|
||||
The DAQ also provides preview streams with hardcoded throttling.
|
||||
|
||||
Note that the standard bluesky event model applies, i.e. configure sets up the device, stage and
|
||||
trigger for stepping interface and kickoff and collect for flyers. This will be updated with the
|
||||
recently updated event model. Redundant staging raises an exception.
|
||||
Note that while in the bluesky event model a manual configuration step sets up the device for a
|
||||
scan. Followed by commands stage and trigger for stepping interface and kickoff and collect for
|
||||
flyers. While in the BEC event model, stage is called on all enabled deviced on the deviceserver.
|
||||
Calling stage also configures the device from the scaninfo. Moreover all steges are called in
|
||||
parallel, regardless of device order. Redundant staging raises an exception.
|
||||
|
||||
### Seeing is believing (GUI)
|
||||
|
||||
@@ -141,116 +142,70 @@ caqtdm -macro "P=X02DA-ES1-SMP1" aeroauto1_ControllerOverview.ui
|
||||
```
|
||||
|
||||
The std-DAQ doesn't have control panels, but the BEC can display the hard-coded preview streams.
|
||||
The *daq_stream1* preview forwards displays 1 frames at a maximum of 5 Hz.
|
||||
The *daq_stream0* preview forwards displays 1 frames at a maximum of 5 Hz.
|
||||
So we just need to add the correct widgets to the GUI:
|
||||
```
|
||||
gui.add_dock('tomolive')
|
||||
gui.panels['tomolive'].add_widget('BECFigure').image('daq_stream1')
|
||||
```
|
||||
|
||||
### Short run with the GigaFrost and std-DAQ
|
||||
|
||||
This is a short, recorded test run with 2016x2016 frames at 100 Hz with the GigaFrost. The current
|
||||
GigaFrost ophyd device includes the std-DAQ client, but they will probably be separated.
|
||||
```
|
||||
# Configure
|
||||
d = {'ntotal': 1000000, 'nimages': 555, 'exposure': 5, 'period': 10}
|
||||
dev.gfclient.configure(d)
|
||||
# Stage GF, DAQ and preview
|
||||
dev.gfclient.stage()
|
||||
dev.daq_stream0.stage()
|
||||
# Trigger a few sequences
|
||||
def.gfclient.trigger()
|
||||
def.gfclient.trigger()
|
||||
# Unstage
|
||||
def.gfclient.unstage()
|
||||
dev.daq_stream0.unstage()
|
||||
gui.panels['tomolive'].add_widget('BECFigure').image('daq_stream0')
|
||||
```
|
||||
|
||||
|
||||
## Reseting the Automation1 iSMC
|
||||
## BEC scans at the testbench
|
||||
|
||||
The concept of scans is slightly different in bluesky and BEC. Bluesky strictly separates
|
||||
the device logic in ophyd from the scan logic in plans. Devices are passed in as arguments
|
||||
allowing finetuning their roles.
|
||||
|
||||
On the other hand, BEC has two scan interfaces and additional device specific scan logic is
|
||||
placed on the ophyd device itself. The general idea is that the lower-level BEC scans should
|
||||
be completely generic with absolutely minimal logic (although some examples counter this
|
||||
argument). BEC devices live on the DeviceServer, and automatically participate in scans
|
||||
whenever they are enabled. This puts the configuration role either on the ophyd device from
|
||||
the scainfo or in the high level interface that anyways manages the enabling/disabling of devices.
|
||||
|
||||
The current repository has several implemented scans to test compliance with standard BEC
|
||||
interfaces and partly cover the old EPICS IOC functionality.
|
||||
|
||||
- If a device is enabled for a scan it will be staged
|
||||
- I.e. by the time stage finishes it must be configured
|
||||
- This can be either manual or from the scan parameters
|
||||
- Some scan parameters will overwrite the configuration (can be removed...)
|
||||
- Certain scan kwargs will trigger the reconfiguration of a device
|
||||
- The device will not try to make sure that the received configuration is correct
|
||||
|
||||
|
||||
|
||||
parameters
|
||||
|
||||
### anotherstepscan
|
||||
|
||||
Simple software step scan in the low-level API that almost calls the standard BEC scan routine. Its
|
||||
only difference is that it overrides the burst to use Gigafrost's HW burst mode. The ophyd devices
|
||||
are capable to allocate the required number of points for DAQ and position readback.
|
||||
|
||||
There's some electrical disturbance at SLS that can bring the system to a problematic state. A workaround is to remotely reset the iSMC:
|
||||
```
|
||||
dev.es1_ismc.reset()
|
||||
```
|
||||
|
||||
FIXME: There is a known desync in PSO inputs upon iSMC restart that requires restarting the IOC.
|
||||
|
||||
|
||||
|
||||
|
||||
## Scans at the testbench
|
||||
|
||||
The current repository has several implemented scans, often offering different solutions to the
|
||||
same problem using different APIs while providing similar functionality. The BEC itself has two
|
||||
scan APIs for low- and highlevel scans, and the fastest scans can be directly implemented on the
|
||||
Automation1 iSMC. The implemented BEC scans combine motor motion, PSO triggering, Gigafrost and
|
||||
stdDAQ control and position capture in internal or external triggering mode. They were
|
||||
intentionally designed to provide the same interface, althogh not every combination was tested.
|
||||
|
||||
As I was unsure about the various triggering modes of the Gigafrost, so currently it's implemented
|
||||
with only sofware trigger that is compatible with the standard bluesky step scanning interface.
|
||||
|
||||
|
||||
### demostepscan
|
||||
|
||||
Simple step scan in the scripting API that performs the device configuration and hands over to
|
||||
a standard BEC scan routine. Note that there's absolutely no readback from the GigaFrost so we
|
||||
don't know when it finished acquiring.
|
||||
```
|
||||
def demostepscan(scan_start, scan_end, steps, exp_time=0.005, burst_at_each_point=1, settling_time=0, sync='event')
|
||||
```
|
||||
|
||||
### gigastep
|
||||
|
||||
Simple step scan in the low level API that performs the device configuration loops over each
|
||||
position in BEC and reads back the position data. Note that there's absolutely no readback from the GigaFrost so we
|
||||
don't know when it finished acquiring.
|
||||
```
|
||||
scans.gigastep(scan_start, scan_end, steps, exp_time=0.005, settling_time=0.2, burst_at_each_point = 1, sync='event')
|
||||
def demosanotherstepscantepscan(scan_start, scan_end, steps, exp_time=0.005, burst_at_each_point=1, settling_time=0, sync='event')
|
||||
```
|
||||
|
||||
### snapnstep
|
||||
|
||||
Scripted step scan that sets up all components, creates an AeroScript file from template and
|
||||
executes it on the Automation1 iSMC controller. Upon succesfull completion it reads back the
|
||||
positions from the data capture.
|
||||
|
||||
NOTE: This scan just launches the GigaFrost, but hardware triggering is currently not implemented.
|
||||
AeroScript controlled high-speed step-scan that sets up the devices and calls the corresponding
|
||||
low-level scan API to substitute the jinja2 template file and launch the script. PSO and data
|
||||
readback are configured and launched internally. It also waits for the script to finish.
|
||||
```
|
||||
scans.snapnstep(scan_start, scan_end, steps, exp_time=0.005, settling_time=0.2, burst_at_each_point = 1, sync='event')
|
||||
anothersnapnstepscan(33, 180, 180, exp_time=0.005, exp_frames=1800, repeats=10)
|
||||
```
|
||||
|
||||
|
||||
### sequencescan
|
||||
|
||||
Scripted scan that sets up all components, creates an AeroScript file from template and executes it
|
||||
on the Automation1 iSMC controller. Upon succesfull completion it reads back the positions from the
|
||||
data capture. Position readback works wth both internal and external triggers.
|
||||
|
||||
NOTE: This scan just launches the GigaFrost, but hardware triggering is currently not implemented.
|
||||
### anothersequencescan
|
||||
|
||||
AeroScript controlled fly scan that sets up the devices and calls the corresponding low-level scan
|
||||
to substitute the jinja2 template file and launch the script. PSO and data readback are configured
|
||||
and launched internally. It also waits for the script to finish. It might have problems with
|
||||
configuring the readback of the number of repeats because that's done on the IOC,
|
||||
```
|
||||
scans.sequencescan(scan_start, gate_high, gate_low, repeats=1, repmode="PosNeg", exp_time=0.005, exp_frames=180, roix=2016, roiy=2016, sync="pso")
|
||||
anothersequencescan(33, 180, 180, exp_time=0.005, exp_frames=1800, repeats=10)
|
||||
```
|
||||
|
||||
|
||||
### demosequencescan
|
||||
|
||||
Basic sequence scan in the high level API that calls the corresponding low-level scan with some
|
||||
extra checks.
|
||||
```
|
||||
demosequencescan(scan_start, gate_high, gate_low, repeats=1, repmode="PosNeg", exp_time=0.005, exp_frames=180, roix=2016, roiy=2016, sync="pso")
|
||||
```
|
||||
|
||||
|
||||
### becsequencescan
|
||||
|
||||
Basic sequence scan script in BEC's high level interface. It a performs all trigger configurations
|
||||
movements and readback from BEC.
|
||||
```
|
||||
becsequencescan(scan_start, gate_high, gate_low, repeats=1, repmode="PosNeg", exp_time=0.005, exp_frames=180, roix=2016, roiy=2016, sync="pso")
|
||||
```
|
||||
|
||||
|
||||
|
||||
@@ -27,11 +27,14 @@ class AcquireDark(Acquire):
|
||||
"""
|
||||
super().__init__(**kwargs)
|
||||
self.burst_at_each_point = num
|
||||
self.shutter = "hx" # change to the correct shutter device
|
||||
self.scan_motors = ["eyex"] # change to the correct shutter device
|
||||
#self.shutter = "eyex" # change to the correct shutter device
|
||||
self.dark_shutter_pos = 0 ### change with a variable
|
||||
|
||||
def scan_core(self):
|
||||
# close the shutter
|
||||
yield from self.stubs.set_and_wait(device=[self.shutter], positions=[0])
|
||||
yield from self._move_scan_motors_and_wait(self.dark_shutter_pos)
|
||||
#yield from self.stubs.set_and_wait(device=[self.shutter], positions=[0])
|
||||
yield from super().scan_core()
|
||||
|
||||
|
||||
|
||||
@@ -94,7 +94,7 @@ def anothersequencescan(
|
||||
|
||||
Example:
|
||||
--------
|
||||
>>> demosequencescan(33, 180, 180, exp_time=0.005, exp_frames=1800, repeats=10)
|
||||
>>> anothersequencescan(33, 180, 180, exp_time=0.005, exp_frames=1800, repeats=10)
|
||||
"""
|
||||
if not bl_check_beam():
|
||||
raise RuntimeError("Beamline is not in ready state")
|
||||
@@ -146,7 +146,7 @@ def anothersnapnstepscan(
|
||||
|
||||
Example:
|
||||
--------
|
||||
>>> demosequencescan(33, 180, 180, exp_time=0.005, exp_frames=1800, repeats=10)
|
||||
>>> anothersnapnstepscan(33, 180, 180, exp_time=0.005, exp_frames=1800, repeats=10)
|
||||
"""
|
||||
if not bl_check_beam():
|
||||
raise RuntimeError("Beamline is not in ready state")
|
||||
|
||||
49
tomcat_bec/scripts/scans_fede.py
Normal file
49
tomcat_bec/scripts/scans_fede.py
Normal file
@@ -0,0 +1,49 @@
|
||||
def fede_darks(num, exp_time=None, exp_period=None, roix=None, roiy=None):
|
||||
""" Fede dark scan
|
||||
|
||||
This is a small BEC user-space scan that sets up the gigafrost and calls
|
||||
the low-level dark collection scan.
|
||||
|
||||
Example:
|
||||
--------
|
||||
tutorialdarks(num=100, exp_time=5)
|
||||
"""
|
||||
###### TODO check how to pass only the required arguments
|
||||
###### TODO what we want is a function common to PCO.edge and GF
|
||||
# Configure gigafrost
|
||||
cfg = {}
|
||||
if exp_time != None:
|
||||
cfg.update({"exposure_time_ms": exp_time})
|
||||
if exp_period != None:
|
||||
cfg.update({"exposure_period_ms": exp_period})
|
||||
if roix != None:
|
||||
cfg.update({"image_width": roix})
|
||||
if roiy != None:
|
||||
cfg.update({"image_height": roiy})
|
||||
|
||||
dev.gfcam.configure(d=cfg)
|
||||
|
||||
dev.gfcam.cfgAcqMode.set(1).wait()
|
||||
dev.gfcam.cfgEnableExt.set(0).wait()
|
||||
dev.gfcam.cfgEnableSoft.set(0).wait()
|
||||
dev.gfcam.cfgEnableAlways.set(1).wait()
|
||||
|
||||
dev.gfcam.cfgTrigExt.set(0).wait()
|
||||
dev.gfcam.cfgTrigSoft.set(0).wait()
|
||||
dev.gfcam.cfgTrigTimer.set(0).wait()
|
||||
dev.gfcam.cfgTrigAuto.set(1).wait()
|
||||
|
||||
dev.gfcam.cfgExpExt.set(0).wait()
|
||||
dev.gfcam.cfgExpSoft.set(0).wait()
|
||||
dev.gfcam.cfgExpTimer.set(1).wait()
|
||||
|
||||
dev.gfcam.cfgCntStartBit.set(0).wait()
|
||||
|
||||
# Commit changes to GF
|
||||
dev.gfcam.cmdSetParam.set(1).wait()
|
||||
|
||||
|
||||
print("Handing over to 'scans.acquire_dark")
|
||||
scans.acquire_dark(num=num)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user