Skip to content
Snippets Groups Projects
Commit 56680e49 authored by Francois POLACK's avatar Francois POLACK
Browse files

Feat: Graphic line interpolation of the curve added to the RMS slope graphs

parent c84081ee
No related branches found
No related tags found
No related merge requests found
# -*- coding: utf-8 -*-
'''
This file is part of the Superflat Evaluation Toolkit
Evaluation of surface height data based on PSD tools
This file defines the ActiveFigure class, which is the main storage element of surface height measurements
'''
__author__ = "François Polack"
__copyright__ = "2022, Superflat-PCP project"
__email__ = "superflat-pcp@synchrotron-soleil.fr"
__version__ = "0.1.0"
import numpy as np
import warnings
import matplotlib.pyplot as plt
import matplotlib.figure as fig
# from matplotlib.patches import PathPatch
# from matplotlib.path import Path
from matplotlib.backend_tools import ToolBase, RubberbandBase, ToolToggleBase #, ToolCursorPosition #
class LineMode(ToolToggleBase):
from pathlib import Path
default_keymap = ('ctrl+L','ctrl+l')
description =" line drawing mode"
image=str(Path(__file__).parent)+"/line-48.png"
def __init__(self, *args, **kwargs):
self.figure=kwargs['figure']
kwargs={}
super().__init__(*args, **kwargs)
def trigger(self, sender, event, data=None):
#on trigger update tool button state and call set_linemode on figure
super().trigger(sender, event, data=data)
# print('figure is', self.figure, 'state=', self.toggled)
# if self.toggled:
# sender.toolmanager.trigger_tool('Line_tool', sender=self, data=('init',()))
# else:
# sender.toolmanager.trigger_tool('Line_tool', sender=self, data=('quit',()))
self.figure.set_linemode(self.toggled)
class LineTool(RubberbandBase):
""" Tool button switch to line drawing mode
The trigger associated functions change the cursor to indicate activity
"""
# keyboard shortcut
description = 'Line drawing tool'
def __init__(self, *args, **kwargs):
self.figure=kwargs['figure']
kwargs={}
super().__init__(*args, **kwargs)
def draw_rubberband(self, *data):
x=[self.figure.node_x[-1], data[0]]
y=[self.figure.node_y[-1], data[1]]
# print("RB tool", cmd ,':', pos)
# if cmd=='init':
# print('activate line tool', self.figure)
# elif cmd == 'quit':
# print('quit line tool', self.figure)
def remove_rubberband(self):
print('quit RB tool')
class Crms_fig(fig.Figure):
def __init__(self,*args, **kwargs):
super().__init__(*args,**kwargs)
self.cid=self.canvas.mpl_connect('button_press_event', self.button_press)
self.canvas.mpl_connect('draw_event', self.on_draw)
self.linemode=False
self.lineedit=False
self.vertices=[]
self.index=-1 #active vertex last one is default for line construction
self.mvcid=0 #mouse move connection
self.brcid=0 # button release connection
self.epsilon= 5
def set_linemode(self, state) :
self.linemode=state
if state:
print('linemode on')
if len(self.vertices) >0:
self.lineedit=True
self.canvas.set_cursor(3)
else:
print('linemode off')
self.lineedit=False
self.canvas.set_cursor(1)
def on_draw(self, event):
"""Callback for draws."""
self.background = self.canvas.copy_from_bbox(self.gca().bbox)
# self.ax.draw_artist(self.pathpatch)
# self.ax.draw_artist(self.line)
# self.canvas.blit(self.ax.bbox)
def get_vertex_index(self,event):
#xy=self.line.get_data()
xyt = self.line.get_transform().transform(self.vertices) # converts point coordinates into pixel units
xt, yt = xyt[:, 0], xyt[:, 1]
d = np.sqrt((xt - event.x)**2 + (yt - event.y)**2)
ind = d.argmin()
return ind if d[ind] < self.epsilon else None
def get_insert_index(self,event):
#xy=self.line.get_data()
xyt = self.line.get_transform().transform(self.vertices) # converts point coordinates into pixel units
point=[event.x,event.y]
segments=np.diff(xyt,1,0) # 1st order finite difference with respect to axis 0
unitvects=(segments.transpose()/np.linalg.norm(segments, axis=1)) # beware shape is (2,N)
distances=(np.array(point)-np.array(xyt))[:-1,:]
t=np.dot(distances, unitvects).diagonal()
d2=distances -(unitvects*t).transpose()
tnorm=t/np.linalg.norm(segments, axis=1)
d=np.linalg.norm(d2, axis=1)
# print(unitvects)
print(tnorm)
# print(d2)
print(d)
# U2=np.square(np.linalg.norm(segments, axis=1))
# d=np.sqrt((np.square(U2)-np.square(UV))/U2)
# xt, yt = xyt[:, 0], xyt[:, 1]
# d = np.sqrt((xt - event.x)**2 + (yt - event.y)**2)
ind = d.argmin()
return ind if d[ind] < self.epsilon and tnorm[ind] > 0 and tnorm[ind] < 1. else None
def button_press(self, event):
if event.inaxes is self.gca().axes and self.linemode:
if self.lineedit:
index=self.get_vertex_index(event)
if index!= None:
print( '>>', index, self.vertices[index])
self.index=index
self.mvcid = self.canvas.mpl_connect('motion_notify_event', self.on_mouse_move)
self.brcid = self.canvas.mpl_connect('button_release_event', self.on_button_release)
else:
# print('>>', event.modifiers)
if 'ctrl' in event.modifiers:
index=self.get_insert_index(event)
print("add point",index)
return
if event.dblclick:
#self.canvas.manager.toolmanager.trigger_tool('Line_tool', sender=self)
event.canvas.mpl_disconnect(self.mvcid)
self.mvcid=0
print("vertices", self.vertices)
self.lineedit=True
else:
self.vertices.append((event.xdata,event.ydata))
vertex=self.vertices.copy()
vertex.append((event.xdata,event.ydata))
x,y=zip(*vertex)
# print(x, y)
# print('vertices', self.vertices)
if len(self.vertices) == 1:
self.line,=self.gca().plot(x,y,'g', marker='s', markerfacecolor='r',animated=True)
self.mvcid = self.canvas.mpl_connect('motion_notify_event', self.on_mouse_move)
else:
self.line.set_data(list(x),list(y))
def on_mouse_move(self, event):
# print('on move')
if event.inaxes is self.gca().axes and self.linemode:
x,y=self.line.get_data()
x[self.index]=event.xdata
y[self.index]=event.ydata
self.line.set_data(x,y)
# print(self.line.get_data())
self.canvas.restore_region(self.background)
self.gca().draw_artist(self.line)
self.canvas.blit(self.gca().bbox)
def on_button_release(self,event):
if event.inaxes is self.gca().axes and self.lineedit:
self.vertices[self.index]=(event.xdata,event.ydata)
x,y=zip(*self.vertices)
self.line.set_data(list(x),list(y))
event.canvas.mpl_disconnect(self.mvcid)
event.canvas.mpl_disconnect(self.brcid)
self.brcid=self.mvcid=0
def create_crms_figure(**kwargs):
import warnings
#activating special toolbar
stdmgr=plt.rcParams['toolbar']
warnings.simplefilter('ignore', category=UserWarning)
plt.rcParams['toolbar'] = 'toolmanager'
warnings.resetwarnings()
csfig=plt.figure(FigureClass=Crms_fig, **kwargs) # new plot window
# csfig.canvas.manager.toolmanager.add_tool('Line_tool', LineTool, figure=csfig) # manager.add_tool
csfig.canvas.manager.toolmanager.add_tool('Line_mode', LineMode, figure=csfig) #now unused
# csfig.canvas.manager.toolbar.add_tool('Line_mode', 'Special', -1) #container.add_tool
csfig.canvas.manager.toolbar.add_toolitem('Line_mode', 'Special', -1, LineMode.image, LineMode.description, True) #container.add_tool
#switching back to standard pyplot toolbar
plt.rcParams['toolbar'] = stdmgr
return csfig
\ No newline at end of file
...@@ -759,7 +759,9 @@ class HeightMap(object): ...@@ -759,7 +759,9 @@ class HeightMap(object):
The cumulative rms slope error is the square root of the slope CPSD The cumulative rms slope error is the square root of the slope CPSD
""" """
plt.figure(figsize=fig.figaspect(0.5)) # new plot window from crmsfig import create_crms_figure
csfig=create_crms_figure(figsize=fig.figaspect(0.5)) # new plot window
if tangential: if tangential:
plt.plot(self.sf*1e-3, self.srms*1e6) plt.plot(self.sf*1e-3, self.srms*1e6)
plt.title('Cumulated RMS tangential slopes {}'.format(comment)) plt.title('Cumulated RMS tangential slopes {}'.format(comment))
......
line-48.png

459 B

0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment