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