Skip to content

Commit 45c8e07

Browse files
authored
Merge pull request #278 from ISISComputingGroup/Ticket156_replot_scans
Document how to replay documents into new callbacks (e.g. how to replot a scan)
2 parents 37a90ca + be146b5 commit 45c8e07

File tree

4 files changed

+62
-0
lines changed

4 files changed

+62
-0
lines changed

doc/callbacks/plotting.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,3 +110,7 @@ def plan():
110110
# Add a PNG saving callback
111111
png_callback = PlotPNGSaver(y="y_variable", x="x_variable", ax=ax, output_dir=Path("C://", "Some", "Custom", "Directory"), postfix="test123")
112112
```
113+
114+
## Replotting a previous scan
115+
116+
See {doc}`/replotting_scans` for information about how to replay bluesky documents into an arbitrary set of callbacks, which can be used to replot a previous scan.

doc/conf.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -92,4 +92,5 @@
9292
"matplotlib": ("https://matplotlib.org", None),
9393
"lmfit": ("https://lmfit.github.io/lmfit-py/", None),
9494
"typing_extensions": ("https://typing-extensions.readthedocs.io/en/latest/", None),
95+
"ibex_user_manual": ("https://isiscomputinggroup.github.io/ibex_user_manual/", None),
9596
}

doc/index.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ plan_stubs/*
7171
:caption: Reference
7272
7373
_api
74+
replotting_scans
7475
architectural_decisions
7576
developer_information
7677
```

doc/replotting_scans.md

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
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

Comments
 (0)