Skip to content
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

Enable grid and cursor in plots #52

Open
wants to merge 3 commits into
base: InNextRelease
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 46 additions & 27 deletions SignalIntegrity/App/SParameterViewerWindow.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@
from matplotlib import rcParams
rcParams.update({'figure.autolayout': True})

from mpldatacursor import datacursor

class NavigationToolbar(NavigationToolbar2Tk):
def __init__(self, canvas, window,homeCallback=None):
NavigationToolbar2Tk.__init__(self,canvas,window)
Expand Down Expand Up @@ -260,7 +262,6 @@ def __init__(self, parent,sp,filename=None,title=None,buttonLabels=None):
self.topLeftToolbar = NavigationToolbar( self.topLeftCanvas, topLeftFrame ,self.onTopLeftHome)
self.topLeftToolbar.update()
self.topLeftCanvas._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=1)
self.topLeftToolbar.pan()

self.topRightFigure=Figure(figsize=(plotWidth,plotHeight), dpi=plotDPI)
self.topRightPlot=self.topRightFigure.add_subplot(111)
Expand All @@ -269,7 +270,6 @@ def __init__(self, parent,sp,filename=None,title=None,buttonLabels=None):
self.topRightToolbar = NavigationToolbar( self.topRightCanvas, topRightFrame ,self.onTopRightHome)
self.topRightToolbar.update()
self.topRightCanvas._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=1)
self.topRightToolbar.pan()
self.topRightCanvasControlsFrame=tk.Frame(topRightFrame)
self.topRightCanvasControlsFrame.pack(side=tk.TOP, fill=tk.X, expand=tk.NO)
tk.Button(self.topRightCanvasControlsFrame,text='unwrap',command=self.onUnwrap).pack(side=tk.LEFT,expand=tk.NO,fill=tk.NONE)
Expand All @@ -283,7 +283,6 @@ def __init__(self, parent,sp,filename=None,title=None,buttonLabels=None):
self.bottomLeftToolbar = NavigationToolbar( self.bottomLeftCanvas, bottomLeftFrame ,self.onBottomLeftHome)
self.bottomLeftToolbar.update()
self.bottomLeftCanvas._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=1)
self.bottomLeftToolbar.pan()

self.bottomRightFigure=Figure(figsize=(plotWidth,plotHeight), dpi=plotDPI)
self.bottomRightPlot=self.bottomRightFigure.add_subplot(111)
Expand All @@ -292,7 +291,6 @@ def __init__(self, parent,sp,filename=None,title=None,buttonLabels=None):
self.bottomRightToolbar = NavigationToolbar( self.bottomRightCanvas, bottomRightFrame , self.onBottomRightHome)
self.bottomRightToolbar.update()
self.bottomRightCanvas._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=1)
self.bottomRightToolbar.pan()

self.controlsFrame = tk.Frame(self.dialogFrame)
self.controlsFrame.pack(side=tk.TOP,fill=tk.X,expand=tk.NO)
Expand Down Expand Up @@ -458,16 +456,16 @@ def onLogScale(self):
def ZoomJoinActivations(self):
self.Zoom['Frequencies']['Join']['All'].Activate(self.Zoom['Frequencies']['JoinWithOthers'].Bool())
self.Zoom['Frequencies']['Join']['OffDiagonal'].Activate(self.Zoom['Frequencies']['JoinWithOthers'].Bool() and not self.Zoom['Frequencies']['Join']['All'].Bool() and self.Zoom['AreSParameterLike'])
self.Zoom['Frequencies']['Join']['Reciprocals'].Activate(self.Zoom['Frequencies']['JoinWithOthers'].Bool() and not self.Zoom['Frequencies']['Join']['All'].Bool() and not self.Zoom['Frequencies']['Join']['OffDiagonal'].Bool() and self.Zoom['AreSParameterLike'])
self.Zoom['Frequencies']['Join']['Reciprocals'].Activate(self.Zoom['Frequencies']['JoinWithOthers'].Bool() and not self.Zoom['Frequencies']['Join']['All'].Bool() and not self.Zoom['Frequencies']['Join']['OffDiagonal'].Bool() and self.Zoom['AreSParameterLike'])
self.Zoom['Frequencies']['Join']['Reflects'].Activate(self.Zoom['Frequencies']['JoinWithOthers'].Bool() and not self.Zoom['Frequencies']['Join']['All'].Bool() and self.Zoom['AreSParameterLike'])
self.Zoom['Times']['Join']['All'].Activate(self.Zoom['Times']['JoinWithOthers'].Bool())
self.Zoom['Times']['Join']['OffDiagonal'].Activate(self.Zoom['Times']['JoinWithOthers'].Bool() and not self.Zoom['Times']['Join']['All'].Bool() and self.Zoom['AreSParameterLike'])
self.Zoom['Times']['Join']['Reciprocals'].Activate(self.Zoom['Times']['JoinWithOthers'].Bool() and not self.Zoom['Times']['Join']['All'].Bool() and not self.Zoom['Times']['Join']['OffDiagonal'].Bool() and self.Zoom['AreSParameterLike'])
self.Zoom['Times']['Join']['Reciprocals'].Activate(self.Zoom['Times']['JoinWithOthers'].Bool() and not self.Zoom['Times']['Join']['All'].Bool() and not self.Zoom['Times']['Join']['OffDiagonal'].Bool() and self.Zoom['AreSParameterLike'])
self.Zoom['Times']['Join']['Reflects'].Activate(self.Zoom['Times']['JoinWithOthers'].Bool() and not self.Zoom['Times']['Join']['All'].Bool() and self.Zoom['AreSParameterLike'])
verticalsActive = self.Zoom['Vertical']['JoinMagnitudeWithOthers'].Bool() or self.Zoom['Vertical']['JoinPhaseWithOthers'].Bool() or self.Zoom['Vertical']['JoinImpulseWithOthers'].Bool() or self.Zoom['Vertical']['JoinStepImpedanceWithOthers'].Bool()
self.Zoom['Vertical']['Join']['All'].Activate(verticalsActive)
self.Zoom['Vertical']['Join']['OffDiagonal'].Activate(verticalsActive and not self.Zoom['Vertical']['Join']['All'].Bool() and self.Zoom['AreSParameterLike'])
self.Zoom['Vertical']['Join']['Reciprocals'].Activate(verticalsActive and not self.Zoom['Vertical']['Join']['All'].Bool() and not self.Zoom['Vertical']['Join']['OffDiagonal'].Bool() and self.Zoom['AreSParameterLike'])
self.Zoom['Vertical']['Join']['Reciprocals'].Activate(verticalsActive and not self.Zoom['Vertical']['Join']['All'].Bool() and not self.Zoom['Vertical']['Join']['OffDiagonal'].Bool() and self.Zoom['AreSParameterLike'])
self.Zoom['Vertical']['Join']['Reflects'].Activate(verticalsActive and not self.Zoom['Vertical']['Join']['All'].Bool() and self.Zoom['AreSParameterLike'])
SignalIntegrity.App.Preferences.SaveToFile()

Expand Down Expand Up @@ -955,14 +953,16 @@ def PlotSParameter(self):
else:
for i in range(len(x)-1):
if self.LogScaleDoer.Bool():
self.topLeftPlot.semilogx(x[i:i+2],y[i:i+2],linewidth=lw[i],color='blue')
lines=self.topLeftPlot.semilogx(x[i:i+2],y[i:i+2],linewidth=lw[i],color='blue')
else:
self.topLeftPlot.plot(x[i:i+2],y[i:i+2],linewidth=lw[i],color='blue')
lines=self.topLeftPlot.plot(x[i:i+2],y[i:i+2],linewidth=lw[i],color='blue')
else:
if self.LogScaleDoer.Bool():
self.topLeftPlot.semilogx(x,y)
lines=self.topLeftPlot.semilogx(x,y)
else:
self.topLeftPlot.plot(x,y)
lines=self.topLeftPlot.plot(x,y)

datacursor(lines,formatter="f: {x:.3f}\nmag: {y:.2f}".format,display='multiple',draggable=True)

if self.ShowPassivityViolationsDoer.Bool():
self.topLeftPlot.scatter(
Expand Down Expand Up @@ -998,6 +998,8 @@ def PlotSParameter(self):
self.topLeftPlot.set_ylabel('magnitude (dB)',fontsize=10)
self.topLeftPlot.set_xlabel('frequency ('+self.freqLabel+')',fontsize=10)

self.topLeftPlot.grid(True, 'both')

TD = self.plotProperties['Delay']
frph=fr._DelayBy(-TD)

Expand All @@ -1014,14 +1016,16 @@ def PlotSParameter(self):
else:
for i in range(len(x)-1):
if self.LogScaleDoer.Bool():
self.topRightPlot.semilogx(x[i:i+2],y[i:i+2],linewidth=lw[i],color='blue')
lines=self.topRightPlot.semilogx(x[i:i+2],y[i:i+2],linewidth=lw[i],color='blue')
else:
self.topRightPlot.plot(x[i:i+2],y[i:i+2],linewidth=lw[i],color='blue')
lines=self.topRightPlot.plot(x[i:i+2],y[i:i+2],linewidth=lw[i],color='blue')
else:
if self.LogScaleDoer.Bool():
self.topRightPlot.semilogx(x,y)
lines=self.topRightPlot.semilogx(x,y)
else:
self.topRightPlot.plot(x,y)
lines=self.topRightPlot.plot(x,y)

datacursor(lines,formatter="f: {x:.3f}\nphi: {y:.1f}".format,display='multiple',draggable=True)

self.topRightPlotProperties=self.plotProperties['Phase']
self.topRightLabel.config(text='Phase')
Expand Down Expand Up @@ -1050,6 +1054,8 @@ def PlotSParameter(self):
self.topRightPlot.set_ylabel('phase (degrees)',fontsize=10)
self.topRightPlot.set_xlabel('frequency ('+self.freqLabel+')',fontsize=10)

self.topRightPlot.grid(True, 'both')

if ir is not None:
if self.buttonLabels[self.toPort-1][self.fromPort-1][:2]=='i/' or self.buttonLabels[self.toPort-1][self.fromPort-1][:3]=='di/':
print('Integrate')
Expand All @@ -1065,7 +1071,9 @@ def PlotSParameter(self):

x=ir.Times(timeLabelDivisor)

self.bottomLeftPlot.plot(x,y)
lines=self.bottomLeftPlot.plot(x,y)

datacursor(lines,formatter="t: {x:.3f}\namp: {y:.3f}".format,display='multiple',draggable=True)

if self.ShowCausalityViolationsDoer.Bool():
minv=0.00001; maxv=0.1
Expand Down Expand Up @@ -1105,6 +1113,8 @@ def PlotSParameter(self):
self.bottomLeftPlot.set_ylabel('amplitude',fontsize=10)
self.bottomLeftPlot.set_xlabel('time ('+timeLabel+')',fontsize=10)

self.bottomLeftPlot.grid(True)

firFilter=ir.FirFilter()
stepWaveformTimeDescriptor=ir.td/firFilter.FilterDescriptor()
stepWaveform=si.td.wf.StepWaveform(stepWaveformTimeDescriptor)
Expand Down Expand Up @@ -1169,7 +1179,9 @@ def PlotSParameter(self):
self.bottomRightPlotProperties['MaxY']=max(max(y)*1.05,0.1)
self.bottomRightPlotProperties['YInitialized']=True

self.bottomRightPlot.plot(x,y)
lines=self.bottomRightPlot.plot(x,y)

datacursor(lines,formatter="t: {x:.3f}\namp: {y:.3f}".format,display='multiple',draggable=True)

if self.ShowCausalityViolationsDoer.Bool():
self.bottomRightPlot.scatter(
Expand All @@ -1196,6 +1208,8 @@ def PlotSParameter(self):
self.bottomRightPlot.set_ylim(bottom=self.bottomRightPlotProperties['MinY']*self.bottomRightPlotProperties['M']+self.bottomRightPlotProperties['B'])
self.bottomRightPlot.set_ylim(top=self.bottomRightPlotProperties['MaxY']*self.bottomRightPlotProperties['M']+self.bottomRightPlotProperties['B'])

self.bottomRightPlot.grid(True)

self.topLeftCanvas.draw()
self.topRightCanvas.draw()
self.bottomLeftCanvas.draw()
Expand Down Expand Up @@ -1260,14 +1274,16 @@ def onDelayEntered(self,event):
else:
for i in range(len(x)-1):
if self.LogScaleDoer.Bool():
self.topRightPlot.semilogx(x[i:i+2],y[i:i+2],linewidth=lw[i],color='blue')
lines=self.topRightPlot.semilogx(x[i:i+2],y[i:i+2],linewidth=lw[i],color='blue')
else:
self.topRightPlot.plot(x[i:i+2],y[i:i+2],linewidth=lw[i],color='blue')
lines=self.topRightPlot.plot(x[i:i+2],y[i:i+2],linewidth=lw[i],color='blue')
else:
if self.LogScaleDoer.Bool():
self.topRightPlot.semilogx(x,y)
lines=self.topRightPlot.semilogx(x,y)
else:
self.topRightPlot.plot(x,y)
lines=self.topRightPlot.plot(x,y)

datacursor(lines,formatter="f: {x:.3f}\nphi: {y:.1f}".format,display='multiple',draggable=True)

if not self.topRightPlotProperties['XInitialized']:
self.topRightPlotProperties['MinX']=min(x)
Expand All @@ -1292,6 +1308,9 @@ def onDelayEntered(self,event):

self.topRightPlot.set_ylabel('phase (degrees)',fontsize=10)
self.topRightPlot.set_xlabel('frequency ('+self.freqLabel+')',fontsize=10)

self.topRightPlot.grid(True, 'both')

self.topRightCanvas.draw()
self.topRightToolbar.update()

Expand Down Expand Up @@ -1365,7 +1384,7 @@ def onMatplotlib2TikZ(self):
try:
si.test.PlotTikZ(filename,self.topLeftFigure)
except:
messagebox.showerror('Export LaTeX','LaTeX could not be generated or written ')
messagebox.showerror('Export LaTeX','LaTeX could not be generated or written ')
fp=FileParts(filename.replace('_Magnitude.tex', '').replace('Magnitude.tex', ''))
filename=fp.filename

Expand All @@ -1379,7 +1398,7 @@ def onMatplotlib2TikZ(self):
try:
si.test.PlotTikZ(filename,self.topRightFigure)
except:
messagebox.showerror('Export LaTeX','LaTeX could not be generated or written ')
messagebox.showerror('Export LaTeX','LaTeX could not be generated or written ')
fp=FileParts(filename.replace('_Phase.tex', '').replace('Phase.tex', ''))
filename=fp.filename

Expand All @@ -1393,7 +1412,7 @@ def onMatplotlib2TikZ(self):
try:
si.test.PlotTikZ(filename,self.bottomLeftFigure)
except:
messagebox.showerror('Export LaTeX','LaTeX could not be generated or written ')
messagebox.showerror('Export LaTeX','LaTeX could not be generated or written ')
fp=FileParts(filename.replace('_ImpulseResponse.tex', '').replace('ImpulseResponse.tex', ''))
filename=fp.filename

Expand All @@ -1411,7 +1430,7 @@ def onMatplotlib2TikZ(self):

def onHelp(self):
if Doer.helpKeys is None:
messagebox.showerror('Help System','Cannot find or open this help element')
messagebox.showerror('Help System','Cannot find or open this help element')
return
Doer.helpKeys.Open('sec:S-parameter-Viewer')

Expand All @@ -1432,7 +1451,7 @@ def onEnforceCausality(self):
self.sp.EnforceCausality()
self.UpdatePropertiesFromSParameters()
self.PlotSParameter()

def onEnforceBothPassivityAndCausality(self):
self.sp.EnforceBothPassivityAndCausality(maxIterations=30,causalityThreshold=1e-5)
self.UpdatePropertiesFromSParameters()
Expand Down Expand Up @@ -1469,7 +1488,7 @@ def onSelection(self,x):
filename=self.spList[x][1]
title=self.spList[x][2]
self.buttonLabels=self.spList[x][3]

self.filename=self.spList[x][1]
self.fileparts=FileParts(filename)
if title is None:
Expand Down
22 changes: 16 additions & 6 deletions SignalIntegrity/App/Simulator.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@

from matplotlib.figure import Figure

from mpldatacursor import datacursor

import math
from numpy import mean,std

Expand Down Expand Up @@ -159,7 +161,6 @@ def __init__(self, parent):

toolbar = NavigationToolbar2Tk( self.canvas, self )
toolbar.update()
toolbar.pan()
self.canvas._tkcanvas.pack(side=tk.TOP, fill=tk.BOTH, expand=1)

controlsFrame = tk.Frame(self)
Expand Down Expand Up @@ -284,7 +285,9 @@ def PlotWaveformsFrequencyContent(self,density=False):
fcName=str(self.waveformNamesList[wfi])
fcColor=self.waveformColorIndexList[wfi]

self.plt.plot(fcFrequencies,fcValues,label=fcName,c=fcColor)
lines=self.plt.plot(fcFrequencies,fcValues,label=fcName,c=fcColor)

datacursor(lines,formatter="f: {x:.3f}\nmag: {y:.3f}".format,display='multiple',draggable=True)

if minv != None or minvStd != None:
minv = max(minv,minvStd)
Expand All @@ -301,6 +304,8 @@ def PlotWaveformsFrequencyContent(self,density=False):
if self.maxy != None:
self.plt.set_ylim(top=self.maxy)

self.plt.grid(True)

self.ZoomsInitialized=True
self.f.canvas.draw()

Expand Down Expand Up @@ -439,11 +444,14 @@ def PlotWaveformsTimeDomain(self):
plotlog=False
plotdB=False
if plotlog:
self.plt.semilogy(wfTimes,wf.Values('abs'),label=wfName,c=wfColor)
lines=self.plt.semilogy(wfTimes,wf.Values('abs'),label=wfName,c=wfColor)
datacursor(lines,formatter="t: {x:.3f}\namp: {y:.3f}".format,display='multiple',draggable=True)
elif plotdB:
self.plt.plot(wfTimes,[max(20.*math.log10(abs(a)),-200.) for a in wf.Values('abs')],label=wfName,c=wfColor)
lines=self.plt.plot(wfTimes,[max(20.*math.log10(abs(a)),-200.) for a in wf.Values('abs')],label=wfName,c=wfColor)
datacursor(lines,formatter="t: {x:.3f}\namp: {y:.2f}".format,display='multiple',draggable=True)
else:
self.plt.plot(wfTimes,wfValues,label=wfName,c=wfColor)
lines=self.plt.plot(wfTimes,wfValues,label=wfName,c=wfColor)
datacursor(lines,formatter="t: {x:.3f}\namp: {y:.3f}".format,display='multiple',draggable=True)
minv=min(wfValues) if minv is None else min(minv,min(wfValues))
maxv=max(wfValues) if maxv is None else max(maxv,max(wfValues))

Expand All @@ -460,6 +468,8 @@ def PlotWaveformsTimeDomain(self):
if self.maxy != None:
self.plt.set_ylim(top=self.maxy)

self.plt.grid(True)

self.ZoomsInitialized=True
self.f.canvas.draw()

Expand Down Expand Up @@ -517,7 +527,7 @@ def onMatplotlib2TikZ(self):
messagebox.showerror('Export LaTeX','LaTeX could not be generated or written ')
def onHelp(self):
if Doer.helpKeys is None:
messagebox.showerror('Help System','Cannot find or open this help element')
messagebox.showerror('Help System','Cannot find or open this help element')
return
Doer.helpKeys.Open('sec:Simulator-Dialog')

Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@
dataValue=eval(token[1].strip().strip(os.linesep))
globals()['__'+keyValue+'__']=dataValue

install_requires=['setuptools>=24.2.0','pip>=9.0.0','numpy>=1.13.0','matplotlib>=2.2.3','urllib3>=1.22.0']
install_requires=['setuptools>=24.2.0','pip>=9.0.0','numpy>=1.13.0','matplotlib>=2.2.3','urllib3>=1.22.0','mpldatacursor>='0.7.1']

pathToIcons='SignalIntegrity/App/icons/png'
pathToMoreIcons=pathToIcons+'/16x16/actions'
Expand Down