Replaying documents
All callbacks in bluesky operate on a data structure called a document. These documents represent the metadata and data emitted by a bluesky scan.
Tip
The schema of these documents is defined formally by the bluesky event model. However, the implementation details of these documents are not important for simply replaying them.
If instead you wish to write a tool to consume bluesky documents without using the callbacks provided in this library or in bluesky, please get in touch with experiment controls for advice.
All bluesky callbacks consume documents as their source of data or metadata. This means that historic documents can be replayed into one or more callbacks. This facilitates:
Replaying documents into plotting callbacks to ‘replot’ a scan
Replaying documents into (potentially different) fitting callbacks, to experiment with different fitting routines
Developing entirely new callbacks using data from historic scans
Document storage and replay from file
The IBEX RunEngine instance is configured to automatically save the raw documents from any scan - these are saved into
c:\Instrument\var\logs\bluesky\raw_documents
They are subsequently moved to a backups area after 10 days; if you need access to old scans, please contact experiment controls for the exact path you will need.
These files are organised as line-delimited JSON dictionaries. The filename is the unique identifier of the scan.
Documents can be loaded from their save files and replayed into arbitrary callbacks - which can be a completely different set of callbacks than were used during the scan. The following example shows replay into a LivePlot callback to regenerate a matplotlib plot, as well as re-running a Gaussian fit using the LiveFit callback and displaying that on the plot using LiveFitPlot.
import json
import matplotlib.pyplot as plt
from ibex_bluesky_core.callbacks import LivePlot, LiveFit
from ibex_bluesky_core.fitting import Gaussian
from bluesky.callbacks import LiveFitPlot
def replot_scan(path_to_save_file: str, y_name: str, x_name: str):
# Prepare a set of matplotlib axes to plot onto
plt.close("all")
plt.show()
_, ax = plt.subplots()
# Example callbacks for plotting and fitting - the exact callbacks
# to use when replotting a scan can be chosen freely.
live_plot = LivePlot(y_name, x_name, marker="x", linestyle="none", ax=ax)
live_fit = LiveFit(Gaussian.fit(), y=y_name, x=x_name)
live_fit_plot = LiveFitPlot(livefit=live_fit, ax=ax, num_points=10000)
# Open the relevant save-file
with open(path_to_save_file) as f:
for line in f:
# Load the JSON representation of this document.
document = json.loads(line)
# Pass the document to arbitrary callbacks.
live_plot(document["type"], document["document"])
live_fit_plot(document["type"], document["document"])