Online Data Processing for Streamline HT-XRPD#
Fully automated powder diffraction (data acquisition and processing).
Usage#
DEMO_SESSION [1]: from blissoda.demo.streamline_scanner import streamline_scanner,sample_changer
DEMO_SESSION [2]: streamline_scanner.eject()
DEMO_SESSION [3]: streamline_scanner.load()
DEMO_SESSION [4]: streamline_scanner.calib(0.1, sample_index=3)
DEMO_SESSION [5]: streamline_scanner.run(0.1, nholders=None, current_holder=False, sample_indices=None)
The arguments of calib and run are the same as sct with some additional keyword arguments. When streamline_scanner.optimize_exposure_per is set to “sample” or “baguette” the exposure time provided is the maximally allowed exposure time, the actual exposure time might be shorter.
If the active workflow requires calibration, a calibration scan must be performed before calling run().
The calibration is done by selecting one specific sample sample_index. The automated run` is done on either
the currently loaded holder
N holders from the loading tray
all holders from the loading tray
Installation#
Worker (data processing)#
Install an Ewoks worker with the following dependencies:
pip install ewoksjob[blissworker]
pip install ewoksxrpd
Bliss (acquisition control)#
Add ewoks configuration to beacon.
Dependencies installed in the bliss environment
pip install blissoda[streamline]
Install and configure the streamline sample changer.
Add this to the bliss session setup script that needs the streamline scanner
from blissoda.streamline.streamline_scanner import StreamlineScanner as _StreamlineScanner
streamline_scanner = _StreamlineScanner()
Control flow diagram#
Experiment-level control flow for measuring samples automatically with data processing.
DEMO_SESSION [5]: streamline_scanner.run(0.1, nholders=None, current_holder=False, sample_indices=None)
flowchart TD
%% Start of experiment
START[run] --> CALREQ{Workflow needs calibration}
CALREQ -- yes --> CALOK{Calibration available}
CALOK -- yes --> ENABLE
CALREQ -- no --> ENABLE
ENABLE[Enable vibration and translation]
ENABLE --> MODE{Current holder}
%% Current holder path
MODE -- yes --> LOAD1[Load holder]
LOAD1 --> RH1[Run holder]
%% Loop holders path
MODE -- no --> LOOP1{Remaining holders or last holder?}
LOOP1 -- yes --> EJ1[Eject holder]
EJ1 --> LD1[Load holder]
LD1 --> RH2[Run holder]
RH2 --> LOOP1
LOOP1 -- no --> EJLAST[Eject last holder]
Per-holder execution: each sample in the holder is measured automatically.
Base scanner#
flowchart TD
RUN[Run holder] --> MV_SAMPLE
MV_SAMPLE["Move to sample"] --> MEASURE
MEASURE["Bliss sct command"] --> DATAPROC
DATAPROC["Data processing"] --> MV_SAMPLE
ID31 scanner#
flowchart TD
RUN[Run holder] --> MV_SAMPLE
MV_SAMPLE["Move to sample"] --> ROCKIT
ROCKIT["Rock sample / move motor"] --> EXP_OPT
EXP_OPT["Exposure optimization"] --> DECIDE{"Optimize exposure per?"}
DECIDE -->|None| USEGIVEN
DECIDE -->|Baguette| OPT_BAGUETTE
DECIDE -->|Sample| HASQR{"Has QR code?"}
HASQR -->|No| USEGIVEN
HASQR -->|Yes| OPT_SAMPLE
USEGIVEN["Use given exposure"] --> SHOPEN
OPT_BAGUETTE["Optimize exposure (ascan)"] --> OPT
OPT_SAMPLE["Optimize exposure (ct)"] --> OPT
OPT["Use optimized exposure"] --> SHOPEN
SHOPEN[ID31 open shutter] --> MEASURE
MEASURE["Bliss sct command"] --> RESULT{"Result"}
RESULT -->|Success| DATAPROC
RESULT -->|Pilatus protection error| DATAPROC
DATAPROC["Data processing"] --> MV_SAMPLE
SES-lab scanner#
flowchart TD
RUN[Run holder] --> MV_SAMPLE
MV_SAMPLE["Move to sample"] --> MEASURE
MEASURE["Do nothing"] --> MV_SAMPLE