|
| 1 | +# Replaying documents |
| 2 | + |
| 3 | +All {external+bluesky:doc}`callbacks <callbacks>` in bluesky operate on a data structure called a {external+bluesky:doc}`document <documents>`. These documents represent the metadata and data emitted by a bluesky scan. |
| 4 | + |
| 5 | +```{tip} |
| 6 | +The schema of these documents is defined formally by the bluesky {external+event_model:doc}`event model <explanations/data-model>`. However, the implementation details of these documents are not important for simply replaying them. |
| 7 | +
|
| 8 | +If instead you wish to write a tool to consume bluesky documents _without_ using the callbacks provided in this library or in bluesky, please {external+ibex_user_manual:ref}`get in touch with experiment controls <report_a_problem>` for advice. |
| 9 | +``` |
| 10 | + |
| 11 | +All bluesky {external+bluesky:doc}`callbacks <callbacks>` consume {external+bluesky:doc}`documents <documents>` as their source of data or metadata. This means that historic documents can be replayed into one or more callbacks. This facilitates: |
| 12 | +- Replaying documents into plotting callbacks to 'replot' a scan |
| 13 | +- Replaying documents into (potentially different) fitting callbacks, to experiment with different fitting routines |
| 14 | +- Developing entirely new callbacks using data from historic scans |
| 15 | + |
| 16 | +## Document storage and replay from file |
| 17 | + |
| 18 | +The IBEX {py:obj}`RunEngine <ibex_bluesky_core.run_engine.get_run_engine>` instance is configured to automatically save the raw documents from any scan - these are saved into |
| 19 | +``` |
| 20 | +c:\Instrument\var\logs\bluesky\raw_documents |
| 21 | +``` |
| 22 | +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. |
| 23 | + |
| 24 | +These files are organised as line-delimited JSON dictionaries. The filename is the unique identifier of the scan. |
| 25 | + |
| 26 | +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 {py:obj}`LivePlot <ibex_bluesky_core.callbacks.LivePlot>` callback to regenerate a matplotlib plot, as well as re-running a Gaussian fit using the {py:obj}`LiveFit <ibex_bluesky_core.callbacks.LiveFit>` callback and displaying that on the plot using {external+bluesky:py:obj}`LiveFitPlot <bluesky.callbacks.mpl_plotting.LiveFitPlot>`. |
| 27 | + |
| 28 | +```python |
| 29 | +import json |
| 30 | +import matplotlib.pyplot as plt |
| 31 | +from ibex_bluesky_core.callbacks import LivePlot, LiveFit |
| 32 | +from ibex_bluesky_core.fitting import Gaussian |
| 33 | +from bluesky.callbacks import LiveFitPlot |
| 34 | + |
| 35 | + |
| 36 | +def replot_scan(path_to_save_file: str, y_name: str, x_name: str): |
| 37 | + # Prepare a set of matplotlib axes to plot onto |
| 38 | + plt.close("all") |
| 39 | + plt.show() |
| 40 | + _, ax = plt.subplots() |
| 41 | + |
| 42 | + # Example callbacks for plotting and fitting - the exact callbacks |
| 43 | + # to use when replotting a scan can be chosen freely. |
| 44 | + live_plot = LivePlot(y_name, x_name, marker="x", linestyle="none", ax=ax) |
| 45 | + live_fit = LiveFit(Gaussian.fit(), y=y_name, x=x_name) |
| 46 | + live_fit_plot = LiveFitPlot(livefit=live_fit, ax=ax, num_points=10000) |
| 47 | + |
| 48 | + # Open the relevant save-file |
| 49 | + with open(path_to_save_file) as f: |
| 50 | + for line in f: |
| 51 | + # Load the JSON representation of this document. |
| 52 | + document = json.loads(line) |
| 53 | + # Pass the document to arbitrary callbacks. |
| 54 | + live_plot(document["type"], document["document"]) |
| 55 | + live_fit_plot(document["type"], document["document"]) |
| 56 | +``` |
0 commit comments