Quick Start¶
This page walks through the most common operations using synthetic data that is included with the package.
Creating Synthetic Data¶
import numpy as np
import matplotlib.pyplot as plt
import escape
from escape.storage.example_data import make_scan, make_pump_probe_scan
# Ten-step delay scan, 500 events per step
sig = make_scan(
n_steps=10,
n_events_per_step=500,
scan_par_name="delay_ps",
scan_par_values=np.linspace(-1, 4, 10),
name="bragg_intensity",
seed=0,
)
print(sig)
print(sig.scan)
Per-Step Statistics and Plotting¶
# Per-step statistics
means = sig.scan.nanmean()
stds = sig.scan.nanstd()
counts = sig.scan.count()
# Built-in scan plot (median ± σ/√N)
fig, ax = plt.subplots()
sig.scan.plot(axis=ax, fmt="o-")
ax.set_xlabel("delay / ps")
ax.set_ylabel("Bragg intensity (a.u.)")
plt.tight_layout()
plt.show()
Boolean Filtering¶
# Keep only events with signal above a threshold
strong = sig.filter(0.7, 1.5) # keep 0.7 ≤ sig ≤ 1.5
print(f"Before filter: {len(sig)} events")
print(f"After filter: {len(strong)} events")
# Re-plot on the filtered data
fig, ax = plt.subplots()
strong.scan.plot(axis=ax, fmt="s-", label="filtered")
sig.scan.plot(axis=ax, fmt="o--", label="all")
ax.legend()
plt.show()
Normalisation with Index Alignment¶
sig, i0, pump_on, delay = make_pump_probe_scan(n_steps=10, seed=1)
# Division auto-aligns on common pulse IDs
sig_norm = sig / i0
# Separate pump-on and pump-off shots
sig_on = sig_norm[~pump_on] # laser ON
sig_off = sig_norm[pump_on] # laser OFF (reference)
# Per-step pump/probe ratio
ratio = sig_on.scan / sig_off.scan.nanmean(axis=0)
fig, ax = plt.subplots()
ratio.scan.plot(axis=ax, fmt="o-")
ax.axhline(1.0, ls="--", color="k")
ax.set_xlabel("delay / ps")
ax.set_ylabel("relative signal")
plt.tight_layout()
plt.show()
Applying a Custom Function with map_index_blocks¶
from escape.storage.example_data import make_image_scan
imgs = make_image_scan(n_steps=3, n_events_per_step=50, seed=2)
# Sum a region of interest per event
roi = imgs[:, 25:45, 25:45]
roi_sum = roi.nansum(axis=(1, 2))
print(roi_sum.shape) # (150,)
# Or apply a custom function to each chunk:
def hot_pixel_mask(block, threshold=200):
out = block.copy()
out[out > threshold] = np.nan
return out
imgs_clean = imgs.map_index_blocks(hot_pixel_mask, 200)
mean_img = imgs_clean.scan[0].mean(axis=0).compute()
fig, ax = plt.subplots()
ax.imshow(mean_img, cmap="viridis")
ax.set_title("Mean image (step 0, hot-pixel masked)")
plt.tight_layout()
plt.show()
Storing Results to HDF5¶
import h5py
with h5py.File("quickstart_results.h5", "w") as fh:
sig.store(fh, "signal")
i0.store(fh, "i0")
ratio.store(fh, "ratio")
# Reload
with h5py.File("quickstart_results.h5", "r") as fh:
ratio_loaded = escape.Array.load_from_h5(fh, "ratio")
print(ratio_loaded.scan)