Scan Steps

A Scan object partitions the event stream of an Array into sequential scan steps — for example, one step per delay value in a pump-probe scan. It is always accessible via array.scan.

What Is a Scan?

Internally, the Scan stores:

  • step_lengths — a list [n0, n1, n2, ...] where ni is the number of events in step i.

  • parameter — a dict mapping parameter names to their per-step values, e.g. {"delay_ps": {"values": [-1.0, 0.0, 0.5, 1.0, ...]}}.

from escape.storage.example_data import make_scan

sig = make_scan(n_steps=10, n_events_per_step=500, scan_par_name="delay_ps",
                scan_par_values=list(range(-5, 5)))

print(sig.scan)
# Scan over 10 steps
# Parameters delay_ps

print(sig.scan.step_lengths)   # [500, 500, 500, ...]

Parameter Table

par_steps returns a pandas.DataFrame with one row per step:

print(sig.scan.par_steps)
#    delay_ps  step_length
# 0      -5.0          500
# 1      -4.0          500
# ...

Accessing Individual Steps

Subscript the scan to retrieve a step as an ordinary Array:

step0 = sig.scan[0]       # first step
step5 = sig.scan[5]       # sixth step
last  = sig.scan[-1]      # last step

# Slices return an Array covering those steps:
first3 = sig.scan[0:3]    # steps 0, 1, 2 concatenated

Each returned Array has step_lengths=[n] and the parameter values for that step, so it behaves exactly like a single-step scan.

Per-Step Statistics

All statistics methods on Scan iterate over steps and return a list — one value per step:

means  = sig.scan.nanmean()   # list of per-step means
stds   = sig.scan.nanstd()    # list of per-step std devs
meds   = sig.scan.nanmedian() # list of per-step medians
counts = sig.scan.count()     # list of event counts per step

For multi-dimensional data the axis argument is forwarded:

# Mean image per step for a 3-D (events, rows, cols) array
step_mean_imgs = img_arr.scan.mean(axis=0)   # list of 2-D arrays

Combined statistics:

med, mad = sig.scan.median_and_mad()

Plotting a Scan

scan.plot() produces an errorbar plot with the scan parameter on the x-axis and the per-step median (with 1σ confidence of the mean) on the y-axis:

import matplotlib.pyplot as plt

sig.scan.plot()
plt.xlabel("delay / ps")
plt.ylabel("signal (a.u.)")
plt.tight_layout()
plt.show()

Step Histogram

scan.hist() plots a 2-D colour map of per-step value histograms — useful for visualising shot-to-shot fluctuations along a scan:

x, bins, hdata = sig.compute().scan.hist(bins=50, normalize_to="max")

Scan Arithmetic

Binary operators applied between a Scan and a scalar (or a list with the same length as the scan) perform per-step operations:

# Subtract the per-step mean from each step's data
step_means = sig.scan.nanmean()
corrected  = sig.scan - step_means   # escape.Array

Number of Events Per Step

sig.scan.count()           # list of ints

Merging Scans from Multiple Runs

merge_scans() combines data from several scans at the same parameter points, pooling events together:

sig_run1 = make_scan(n_steps=5, scan_par_name="angle")
sig_run2 = make_scan(n_steps=5, scan_par_name="angle")

merged = sig_run1.scan.merge_scans(sig_run2.scan,
                                   roundto_interval=0.01,
                                   par_name="angle")