-
Notifications
You must be signed in to change notification settings - Fork 3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
custom visualization callback for dichroism scans #42
Comments
The X axis could be energy, magnetic field, positioner, or other (as selected by user) |
This aspect is an optional part of a dichroism scan. It's not easy to preset default parameters so this should be avoided. The processed stream should report the polarization, not the PZT value. The polarization as used today is |
Is the inner scan the ipython-polar/profile_bluesky/startup/instrument/plans/local_scans.py Lines 19 to 37 in fe86149
|
@gfabbris Can you make a sketch of the desired visualization? Nothing fancy, just to give an idea what & how to show. |
The plot itself is not too complicated. It'd be something like the one below, with the XANES on the top panel and the XMCD in the bottom. This is how you calculate the XANES and XMCD if you are reading from the database:
Besides plotting, the callback would ideally save the processed data to another stream. |
Hello, @gfabbris. I am leading an effort to build better visualization widgets for Bluesky. I mentioned to @prjemian that I would like to try them on some data at APS, and he suggested that your problem would be a good test case for my work. A primary goal is to make it easy to perform transformations on the data on the way to plotting, exactly as in your example above. (We have separate but related on saving the processed data. I'd like to set that aside at first, but we could incorporate that too, later.) The widgets are designed to fit into web-based applications, Jupyter, and desktop applications (Qt). Pete mentioned that visualization in Jupyter might be of particular interest to you at this point. Is that right? If you are willing to be a "test user" then I think the best first step would be to share with me some data that I can use to build a small example. We have a command-line tool for packing up scans into a "portable databroker" or sorts. I'd ask you install that tool and export some scans. For example, to send scans 135, 136, 137 plotted in your example above: pip install databroker-pack
databroker-pack mongodb_config --copy-external --query '{"scan_id": {"$in": [135, 136, 137]}}' exported_scans
# Be careful about the use of single-quotes and double-quotes above; they matter. This will create a directory @prjemian I got
which looks like the name of the databroker of interest here. Please correct me if I'm wrong. |
That's right. In this repo, the file is |
I see databroker-pack is a conda package from the |
@gfabbris : Note that other search criteria are possible, using the mongodb-query language. |
Just chiming in to provide a heartbeat on this. Our new visualization tools have been fast-moving but are now "annealing" into a stable-ish form. @AbbyGi and I put most of today in working this example and exploring different approaches (with some help from @tacaswell). I expect to report back sometime next week with a working example ready for use and feedback. |
By configuring ophyd devices differently, we can make thing easier for downstream code (visualization, analysis, ...). The metadata reported by the scan of the
but the two-motor scan over temperature is giving us imprecise metadata:
Bluesky's intention is that that should include just one item per axis, "the thing to plot against". The setpoints should be omitted from that list, then, and we should only have the readbacks. That is, I want this to say:
This can be accomplished by changing this
from
I see the same issue in another scan:
It's not immediately clear to me where in the profile that is configured. We can work around this by adding some logic to the visualization code ("If there are a pair of keys that start the same but end in |
Sounds good. I will go through the devices and clean up the hints. |
Yeah, looks great! |
Hello @gfabbris and @prjemian. @danielballan and I have finished up a working example to use, located in a gist here. There's a README included to guide you through using it. Please give it a try and let us know what you think! |
@AbbyGi and @danielballan, thanks!! I tested at the beamline computer and it works well for the saved data. We are in shutdown now, x-rays will be back in a couple of weeks and I will test the live data part then. I'd automate a plot like this to happen only for
Does that look ok to you? Perhaps there is a better way to automate this plot? |
Great to hear. Thanks again for taking the time. We look forward to hearing how live visualization goes. Off the top of my head, I think defining the model.figures.clear() clear the runs model.runs.clear() or manually add some saved scans alongside your live ones. model.add_run(db[172]) It can also be useful to access the # We should add a convenience method for this snippet....
for figure_view in view.figures.values():
mpl_figure = figure_view.figure # a normal matplotlib.figure.Figure object
mpl_figure.savefig(f"{figure_view.model.title}.png") My hypothesis is that it will be best to subscribe model = AutoXanes()
RE.subscribe(stream_documents_to_runs(model))
view = QtFigures(model)
view.show() and make A second reason for going this path is that That's my thinking at this moment, but I think anything is worth trying at this point as long as we stay flexible and open-minded. This is somewhat new territory for the collaboration, and we'll be learning together as we go. |
Yeah, it will be good to have access to |
Yesterday I went to the lab and turned on some detectors so that I could test the live plotting without x-rays. It works, but I had to make one change, the
ValueError happens if this is not done because it will try to run the THIS DOESN'T WORK... SEE BELOW |
I forgot to say that the way that the plot is automated now is by watching a
Is this better? |
Actually, I did some extra tests, and the solution above doesn't quite work. The problem is how to make the plotter only operate when the number of points is a multiple of 4. |
I managed to make it work by doing this:
So when the number of points is not a multiple of 4 it will just replot the last time that it was. |
But I also realized another issue. The XANES/XMCD plot rendering is not automatically update when a new point is available. But it does update if I resize the screen (note that I'm just plotting random numbers at every step because the detector are reading zero...). I suppose this is just some Qt settings? plot.mov |
We are just catching up on this, as @AbbyGi and I have been in trainings 9-5 all week.
Yes, this looks great.
Exactly what we intended. A minor suggestion: use I managed to make it work by doing this: def xanes(monitor, detector):
if array(detector).size < 4:
return 0
rng = 4*(array(detector).size//4)
absorption = log(array(monitor)[:rng] / array(detector)[:rng]).reshape(-1, 4)
return absorption.mean(axis=1) I think that rather than changing def handle_new_stream(self, run, stream_name):
...
if run.primary.to_dask()[self._detector].size < 4:
# Nothing to do;l this is too short.
return I prefer that approach because (1) It keep the control of over whether we plot together in one place. Thanks for providing a clear demonstration of the failure to automatically update in Qt. Yes, this must be some detail of Qt that we are not getting quite right. We will consult our local Qt experts and get back to you on this. |
If it is redrawing on resize then we know the Qt mainloop is running like we expect and processing Qt event (good!), however we are clearly losing the As an aside, is the previously plotted data jumping around like it does expected? |
At your convenience, @gfabbris, would you please try to run the following and let us know if it live-updates properly. This will help us isolate whether the problem is a general one with your installation or something specific about the XANES plot. ipython --gui=qt In [1]: %run -m bluesky_widgets.examples.ipy_qt_figures
In [2]: motor.delay = 0.5
In [3]: RE(plan()) |
It turns out, the plot update is fine. The issue is that the plot starts in a small window (that I didn't realize was plotting the data), and because I used our beamline setup, a separate window also plots the data, but this one doesn't update correctly (note that the qt_test.py is the same as the ipy_qt_figures but it doesn't run the plan): qttest.movA couple of questions:
|
@tacaswell - It was jumping around because I was just generating a new set of random numbers at every event. I didn't remember I could use the @danielballan - Adding the size check to the |
In my early discussions with @prjemian about this, we considered creating a new stream that would hold the processed XANES/XMCD. Maybe that's a good solution? I believe the callback would look somewhat like this: https://blueskyproject.io/bluesky/callbacks.html#secondary-event-stream |
Yes. For whatever reason, it does not initialize small for me, so I will rely on use to test my proposed solution. Please see instructions at bluesky/bluesky-widgets#98.
My guess is that you are doing
and/or import matplotlib.pyplot as plt
plt.ion() either of which turn on "interactive plotting," which causes matplotlib to eagerly display figures in stand-alone windows rather than letting us place them intentionally. (Does that sound accurate to you, @tacaswell?) The fix would be to find wherever you are running that in your profile and remove it, or else override it with
Ah, you are correct of course. I'll circle back later with a better suggestion. |
This is a useful discussion. I have responded in a new issue, #75, to avoid entangling it with the plotting discussion here. |
Yeah, we do turn on interactive plotting during startup... I'll use |
It looks like we should be able to be compatible with FYI, I just released bluesky-widgets v0.0.7 on PyPI with the sizing fix, so you can go back to running on a standard release if you like. |
Action items from discussion today:
|
Just chiming in to say, attention in the group has recently been elsewhere, but this is still a going concern. We are doing related work this week, should have some concrete to report back in a couple weeks. |
Sounds good. I plan to test the current XMCD plotter in an experiment this week. I did some minor tweaks to it. One thing that I found particularly useful is the ability to start a new plot (using the same scanning positioner) without closing the old one (but this may not be the best way to do this).
|
visualize (plot) energy and (phase retarder fast rotation) PZT scans for polarization direction with this sequence in the primary data stream
Process this group as a single event in a separate stream and visualize from that stream
Both streams are saved to the databroker and available during and after the experiment.
The text was updated successfully, but these errors were encountered: