Plotting spherical polar mapping dataΒΆ
The below code creates and interactive plot, with the mapped data for a set radius on the left, and a plot of all selected vectors on the right. To select a vector simply click anywhere on the left hand 2d plot and the selected point will have its associated vector plotted on the right-hand side 3d axis, along with a star marker on the left-hand side plot. To clear all selected vectors from the right-hand side plot and star markers from the left-hand plot click the 'clear vectors' button displayed as a widget in the cell output.
[1]:
#import the required modules
#----------------------------
import h5py
import ipywidgets as wg
import matplotlib.pyplot as plt
import numpy as np
from mpl_toolkits.mplot3d import Axes3D
from matplotlib.collections import PathCollection
from scipy.spatial.transform import Rotation as R
import transformations as tf
[2]:
#define functions needed for plotting
#--------------------------------------
markers=[]
def drawarrow(vec1,vec2,axs,col,style='-',alp=1):
axs.quiver(vec1[0],vec1[1],vec1[2],vec2[0],vec2[1],vec2[2],color = col,arrow_length_ratio=0.1,ls=style,alpha=alp)
def point2vec(axes,counts,r_int,th_int,phi_int,zoom,click=False):
global updating
if updating:
return
#ax2.cla()
markernew=ax1.scatter(phi_int,th_int,marker='*',s=50,c='aqua',ec='black')
markers.append(markernew)
vector0=[0,0,0]
rstart,rstop,rstep=axes[0][1:4]
thstart,thstop,thstep=axes[1][1:4]
phistart,phistop,phistep=axes[2][1:4]
thetarad=thstart+(th_int*thstep)
phirad=phistart+(phi_int*phistep)
radius=rstart+(r_int*rstep)
if click==False:
title = ax1.get_title().split('=')[0]
ax1.cla()
ax1.set_title(title+f"={radius}")
ax1.imshow(counts[r_int,:,:],norm='log',cmap='jet')
theta=np.degrees(thetarad)
phi=np.degrees(phirad)
vector1=[0,0,radius]
rotyzmat=R.from_euler('x', theta, degrees=True)
rotxymat=R.from_euler('z',phi,degrees=True)
totalrot=rotxymat*rotyzmat
plotexitvec=totalrot.apply(vector1)
ax1.set_ylabel('theta: angle from +z axis')
ax1.set_xlabel('phi: angle from +x axis')
drawarrow(vector0,plotexitvec,ax2,'orange')
ax2.set_xlim(-zoom,zoom)
ax2.set_xlabel('x')
ax2.set_ylim(-zoom,zoom)
ax2.set_ylabel('y')
ax2.set_zlim(-zoom,zoom)
ax2.set_zlabel('z')
[34]:
#setup the active figure
#-------------------------
%matplotlib qt
#other options are available for interactive plotting e.g %matplotlib widget
fig = plt.figure(figsize=(20, 10))
fig.canvas.manager.set_window_title("Spherical polar plot and vector selection")
ax1 = fig.add_subplot(121)
ax2= fig.add_subplot(122, projection='3d')
#import data from hdf5 file
#--------------------
filename='/dls/science/users/rpy65944/output/mapped_scan_519528_1.hdf5'
datah5=h5py.File(filename)
ax1.set_title(filename+'\n radius=1')
#'/dls/science/users/rpy65944/output/mapped_scan_519445_1.hdf5')
counts=datah5['binoculars/counts']
#grab axis details from file
axinfo=datah5['binoculars/axes']
r_ax=np.array(axinfo['h'])
th_ax=np.array(axinfo['k'])
phi_ax=np.array(axinfo['l'])
axes=[r_ax,th_ax,phi_ax]
#setup widgets and start the interactive sliders, button and plot
slider_r = wg.IntSlider(value=1, min=0, max=np.shape(counts)[0]-1, step=1,description='select radius',description_width ='300px',layout=wg.Layout(width='350px'))
slider_r.style.description_width='150px'
slider_th = wg.IntSlider(value=1, min=0, max=np.shape(counts)[1]-1, step=1,description='select theta value',description_width ='300px',layout=wg.Layout(width='350px'))
slider_th.style.description_width='150px'
slider_phi = wg.IntSlider(value=1, min=0, max=np.shape(counts)[2]-1, step=1,description='select phi value',description_width ='300px',layout=wg.Layout(width='350px'))
slider_phi.style.description_width='150px'
slider_zoom=wg.FloatSlider(value=1, min=0, max=5.00, step=0.1,description='select zoom value',description_width ='300px',layout=wg.Layout(width='350px'))
slider_zoom.style.description_width='150px'
clear_button=wg.Button(description="clear vectors")
click_sliders=[slider_th,slider_phi]
updating=False
def onclick(event):
global updating,axes,counts,click_sliders
if event.inaxes == ax1:
updating=True
#ax2.cla()
newth=int(event.ydata)
newphi=int(event.xdata)
click_sliders=[slider_th,slider_phi]
newslidevals=[newth,newphi]
for i,slider in enumerate(click_sliders):
slider.value=newslidevals[i]
updating=False
point2vec(axes,counts,r_int=slider_r.value,th_int=slider_th.value,phi_int=slider_phi.value,zoom=slider_zoom.value,click=True)
fig.canvas.draw_idle()
def clearaxmarkers():
scatter_markers = [artist for artist in ax1.collections if isinstance(artist, PathCollection)]
for marker in scatter_markers:
marker.remove()
ax2.cla()
clear_button.on_click(lambda b: clearaxmarkers())
display(clear_button)
fig.canvas.mpl_connect('button_press_event', onclick)
wg.interact(point2vec,axes=wg.fixed(axes),counts=wg.fixed(counts),r_int=slider_r,th_int=slider_th,phi_int=slider_phi,zoom=slider_zoom)
[34]:
<function __main__.point2vec(axes, counts, r_int, th_int, phi_int, zoom, click=False)>
[10]:
ax1.set_title(filename)
[10]:
Text(0.5, 1.0, '/dls/science/users/rpy65944/output/mapped_scan_519528_19.hdf5')
[24]:
[37]:
[ ]: