Live visualisation#

Learning how to use the PlotClient to look at the reconstruction while it is still running.

There many use cases where it can be useful to communicate between a remote process running the reconstruction and a local client process that wants to receive live information about the status of the reconstruction. In PtyPy, this is possible via ZMQ socket communication.

Running the reconstruction in Python script#

First, we copy a YAML config file ./config/dls_i08_nanogold_spiral.yaml from one of the previous examples making sure that we turn on the interaction server p.io.interaction.server

p.io = u.Param()
p.io.home = "./"
p.io.rfile = "recons/%(run)s_%(engine)s_%(iterations)04d.ptyr"
p.io.autosave = u.Param(active=False)
p.io.autoplot = u.Param(active=False)
p.io.interaction = u.Param(active=True)
p.io.interaction.server = u.Param()
p.io.interaction.server.port = 5580
p.io.interaction.server.address = "tcp://127.0.0.1"

sending updates on localhost (127.0.0.1) at port 9001. We then create a Python run script reading from this config file

with open("./ptypy_run_dls_i08_nanogold.py", "w") as f:
    f.write("""\
import ptypy
ptypy.load_ptyscan_module("hdf5_loader")
ptypy.load_gpu_engines("cupy")  
p = ptypy.utils.param_from_yaml("config/dls_i08_nanogold_spiral.yaml")
P = ptypy.core.Ptycho(p,level=5)
""")

and execute the run script in a terminal

srun -n 4 -c 2 --gpus-per-task=1 --gpu-bin=None python ptypy_run_dls_i08_nanogold.py

with open("./ptypy_run_dls_i08_nanogold.py", "w") as f:
    f.write("""\
import ptypy
ptypy.load_ptyscan_module("hdf5_loader")
ptypy.load_gpu_engines("cupy")  
p = ptypy.utils.param_from_yaml("config/dls_i08_nanogold_spiral.yaml")
P = ptypy.core.Ptycho(p,level=5)
""")

Running the plot client in this notebook#

While the processing script is running in a separate process, we just need to connect our client to the same address and port

import ptypy

client = ptypy.utils.Param()
client.port = 5580
client.address = "tcp://127.0.0.1"

and start an instance of the PlotClient

pc = ptypy.utils.PlotClient(client)
pc.start()

and use its get_data() function to get updates

plotter.pr, plotter.ob, runtime = pc.get_data()

on probe, object and runtime information. We can also use the MPLplotter create a plot that is updated by repeatedly executing a cell with this code

from IPython import display
plotter = ptypy.utils.MPLplotter()
initialised = False
if (pc.status == pc.DATA):
    plotter.pr, plotter.ob, runtime = pc.get_data()
    plotter.runtime.update(runtime)
    if not initialised:
        plotter.update_plot_layout()
    plotter.plot_all()
    plotter.draw()
    display.clear_output(wait=True)
    display.display(plotter.plot_fig)

import ptypy

# Client parameters
client = ptypy.utils.Param()
client.port = 5580
client.address = "tcp://127.0.0.1"

# Create instance of plotclient
pc = ptypy.utils.PlotClient(client)

# start listening
pc.start()
# Refresh this cell multiple time 
# to see updates on the reconstruction
# while the script is running in a separate process
layout = ptypy.utils.plot_client.TEMPLATES["jupyter"]
plotter = ptypy.utils.MPLplotter(pars=layout)
initialised = False
if (pc.status == pc.DATA):
    plotter.pr, plotter.ob, runtime = pc.get_data()
    plotter.runtime.update(runtime)
    if not initialised:
        plotter.update_plot_layout()
    plotter.plot_all()
    plotter.draw()
    plotter.plot_fig