PlotGUI.py
# -*- coding: utf-8 -*-
## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ##
# PlotGUI.py --- Plotting class
# --------------------------------
# Copyright (c) 2018
# Laurent CAPOCCHI
# University of Corsica
# --------------------------------
# Version 1.0 last modified: 06/03/18
## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ##
#
# GENERAL NOTES AND REMARKS:
#
## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ##
## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ##
#
# GLOBAL VARIABLES AND FUNCTIONS
#
## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ## ##
import wx
import os
import sys
import math
import threading
import csv
import bisect
_ = wx.GetTranslation
import wx.lib.agw.aui as aui
try:
import matplotlib as mpl
import matplotlib.figure as fig
from matplotlib.backends.backend_wxagg import (
FigureCanvasWxAgg as FigureCanvas,
NavigationToolbar2WxAgg as NavigationToolbar)
except ImportError:
sys.stdout.write("matplotlib module not found. You need it if you plan to use models like QuickScope.\n")
# for spectrum
try:
from numpy import *
except ImportError:
platform_sys = os.name
if platform_sys in ('nt', 'mac'):
sys.stdout.write("Numpy module not found. Go to www.scipy.numpy.org.\n")
elif platform_sys == 'posix':
sys.stdout.write("Numpy module not found. Install python-numpy (ubuntu) package.\n")
else:
sys.stdout.write("Unknown operating system.\n")
sys.exit()
else:
#This module requires the Numeric/numarray or NumPy module, which could not be imported.
import wx.lib.plot as plot
from Utilities import smooth
LColour = ('black', 'red', 'green', 'blue', 'yellow', 'gray', 'magenta', 'maroon', 'orange', 'salmon', 'pink', 'plum')
Markers = ('circle', 'triangle', 'square', 'cross', 'triangle_down', 'plus', 'dot')
def get_limit(d):
""" Function which give the limits of d
"""
L1,L2 = [],[]
for c in d:
bisect.insort(L1, float(c[0]))
bisect.insort(L2, float(c[1]))
### 0.5 in order to visualize the max and min value correctly
return L1[0],L1[-1],L2[0]-0.5,L2[-1]+0.5
def PlotManager(parent, label, atomicModel, xl, yl):
""" Manager for the plotting process which depends of the fusion option of QuickScope.
"""
### there is a active simulation thread ?
dyn_flag = True in ['Simulator' in a.getName() for a in threading.enumerate()[1:]]
### plots are superposed ?
fusion_flag = atomicModel.fusion
### data to plot
data = atomicModel if dyn_flag else atomicModel.results
if data == {}:
wx.MessageBox(_('Data set is empty.\nOnly for QuickScope: Please verify if the received data are float or int.'), _('Info'), wx.OK|wx.ICON_INFORMATION)
return
if data is None:
wx.MessageBox(_('DEVS model is empty.'), _('Info'), wx.OK|wx.ICON_INFORMATION)
return
if dyn_flag:
if fusion_flag:
frame = DynamicPlot(parent, wx.NewIdRef(), _("Plotting %s")%label, data, xLabel=xl, yLabel=yl)
frame.CenterOnParent()
frame.Show()
else:
for key in atomicModel.results:
frame = DynamicPlot(parent, wx.NewIdRef(), _("%s on port %s")%(label,str(key)), data, xLabel = xl, yLabel = yl, iport=key)
frame.CenterOnParent()
frame.Show()
else:
### values to plot are string (for state for instance) ?
str_data_flag = isinstance(data[0][0][-1], str) if isinstance(data, dict) else isinstance(data[0][-1], str)
if str_data_flag or fusion_flag:
frame = StaticPlot(parent, wx.NewIdRef(), _("Plotting %s")%label, data, xLabel=xl, yLabel=yl, legend=atomicModel.blockModel.label, fusion=fusion_flag)
frame.SetBlockModel(atomicModel)
frame.CenterOnParent()
frame.Show()
else:
for key in data:
frame = StaticPlot(parent, wx.NewIdRef(), _("%s on port %s")%(label,str(key)), data[key], xLabel = xl, yLabel = yl, legend = atomicModel.blockModel.label)
frame.CenterOnParent()
frame.Show()
class PlotPanel(wx.Panel):
def __init__(self, parent, id=-1, dpi=None, **kwargs):
wx.Panel.__init__(self, parent, id=id, **kwargs)
self.figure = fig.Figure(dpi=dpi, figsize=(2, 2))
self.canvas = FigureCanvas(self, -1, self.figure)
self.toolbar = NavigationToolbar(self.canvas)
self.toolbar.Realize()
sizer = wx.BoxSizer(wx.VERTICAL)
sizer.Add(self.canvas, 1, wx.EXPAND)
sizer.Add(self.toolbar, 0, wx.LEFT | wx.EXPAND)
self.SetSizer(sizer)
self.SetAutoLayout(True)
class PlotNotebook(wx.Panel):
def __init__(self, parent, id=-1):
wx.Panel.__init__(self, parent, id=id)
self.nb = aui.AuiNotebook(self)
sizer = wx.BoxSizer()
sizer.Add(self.nb, 1, wx.EXPAND)
self.SetSizer(sizer)
self.SetAutoLayout(True)
def add(self, name="plot"):
page = PlotPanel(self.nb)
self.nb.AddPage(page, name)
return page.figure
class PlotFrame(wx.Frame):
def __init__(self, parent=None, id=wx.NewIdRef(), title="Time Plotting"):
""" Constructor.
"""
wx.Frame.__init__(self, parent, id, title, size=(800, 500), style=wx.DEFAULT_FRAME_STYLE|wx.CLIP_CHILDREN)
self.type = "PlotLine"
self.normalize = False
self.home = HOME_PATH
self.client = plot.PlotCanvas(self)
self.InitUI()
self.Layout()
def InitUI(self):
##Now Create the menu bar and items
self.mainmenu = wx.MenuBar()
menu = wx.Menu()
setup = menu.Append(wx.NewIdRef(), _('Page Setup'), _('Setup the printer page'))
file_print_preview = menu.Append(wx.NewIdRef(), _('Print Preview'), _('Show the current plot on page'))
file_print = menu.Append(wx.NewIdRef(), _('Print'), _('Print the current plot'))
file_save = menu.Append(wx.NewIdRef(), _('Save Plot'), _('Save current plot'))
file_export = menu.Append(wx.NewIdRef(), _('Export Plot'), _('Export current plot'))
file_exit = menu.Append(wx.NewIdRef(), _('&Exit'), _('Enough of this already!'))
self.mainmenu.Append(menu, _('&File'))
menu = wx.Menu()
plotRedraw = menu.Append(wx.NewIdRef(), _('&Redraw'), _('Redraw plots'))
plotScale = menu.Append(wx.NewIdRef(), _('&Scale'), _('Scale canvas'))
type_submenu = wx.Menu()
line = type_submenu.Append(wx.MenuItem(menu, wx.NewIdRef(), _('Line'), kind=wx.ITEM_RADIO))
scatter = type_submenu.Append(wx.MenuItem(menu, wx.NewIdRef(), _('Scatter'), kind=wx.ITEM_RADIO))
bar = type_submenu.Append(wx.MenuItem(menu, wx.NewIdRef(), _('Bar'), kind=wx.ITEM_RADIO))
square = type_submenu.Append(wx.MenuItem(menu, wx.NewIdRef(), _('Square'), kind=wx.ITEM_RADIO))
menu.Append(wx.NewIdRef(), _('Type'), type_submenu)
enable_submenu = wx.Menu()
self.enableTitle = enable_submenu.Append(wx.NewIdRef(), _('&Title'), _('Enable title'), kind=wx.ITEM_CHECK)
self.enableTitle.Check(True)
self.enableZoom = enable_submenu.Append(wx.NewIdRef(), _('&Zoom'), _('Enable zoom'), kind=wx.ITEM_CHECK)
self.enableGrid = enable_submenu.Append(wx.NewIdRef(), _('Grid'), _('Enable grid'), kind=wx.ITEM_CHECK)
self.enableGrid.Check(True)
self.enableDrag = enable_submenu.Append(wx.NewIdRef(), _('Drag'), _('Enable drag'), kind=wx.ITEM_CHECK)
self.enableLegend = enable_submenu.Append(wx.NewIdRef(), _('&Legend'), _('Turn on legend'), kind=wx.ITEM_CHECK)
self.enablePointLabel = enable_submenu.Append(wx.NewIdRef(), _('&Point Label'), _('Show closest point'), kind=wx.ITEM_CHECK)
self.norm = enable_submenu.Append(wx.NewIdRef(), _('Normalize'), _('Normalize Y axis'), kind=wx.ITEM_CHECK)
menu.Append(wx.NewIdRef(), _('Enable'), enable_submenu)
setx_submenu = wx.Menu()
self.enableXStep = setx_submenu.Append(wx.NewIdRef(), _('Step'), _('X with step'), kind=wx.ITEM_RADIO)
self.enableXDefault = setx_submenu.Append(wx.NewIdRef(), _('Default'), _('X with Simulation Time (Default)'), kind=wx.ITEM_RADIO)
self.enableXDefault.Check(True)
menu.Append(wx.NewIdRef(), _('Set X'), setx_submenu)
setTitle = menu.Append(wx.NewIdRef(), _('Set Title'), _('Define title'))
setXLabel = menu.Append(wx.NewIdRef(), _('Set X Label'), _('Define x label'))
setYLabel = menu.Append(wx.NewIdRef(), _('Set Y Label'), _('Define y label'))
scrUp = menu.Append(wx.NewIdRef(), _('Scroll Up 1'), _('Move View Up 1 Unit'))
scrRt = menu.Append(wx.NewIdRef(), _('Scroll Rt 2'), _('Move View Right 2 Units'))
reset = menu.Append(wx.NewIdRef(), _('&Plot Reset'), _('Reset to original plot'))
self.mainmenu.Append(menu, _('&Plot'))
self.SetMenuBar(self.mainmenu)
self.Bind(wx.EVT_MENU, self.OnFilePageSetup, setup)
self.Bind(wx.EVT_MENU, self.OnFilePrintPreview, file_print_preview)
self.Bind(wx.EVT_MENU, self.OnFilePrint, file_print)
self.Bind(wx.EVT_MENU, self.OnSaveFile, file_save)
self.Bind(wx.EVT_MENU, self.OnExportFile, file_export)
self.Bind(wx.EVT_MENU, self.OnFileExit, file_exit)
self.Bind(wx.EVT_MENU,self.OnPlotRedraw, plotRedraw)
self.Bind(wx.EVT_MENU,self.OnPlotLine, line)
self.Bind(wx.EVT_MENU,self.OnPlotScatter, scatter)
self.Bind(wx.EVT_MENU,self.OnPlotBar, bar)
self.Bind(wx.EVT_MENU,self.OnPlotSquare, square)
self.Bind(wx.EVT_MENU,self.OnPlotScale, plotScale)
self.Bind(wx.EVT_MENU,self.OnEnableXStep, self.enableXStep)
self.Bind(wx.EVT_MENU,self.OnEnableXDefault, self.enableXDefault)
self.Bind(wx.EVT_MENU,self.OnEnableTitle, self.enableTitle)
self.Bind(wx.EVT_MENU,self.OnEnableZoom, self.enableZoom)
self.Bind(wx.EVT_MENU,self.OnEnableGrid, self.enableGrid)
self.Bind(wx.EVT_MENU,self.OnEnableDrag, self.enableDrag)
self.Bind(wx.EVT_MENU,self.OnEnableLegend, self.enableLegend)
self.Bind(wx.EVT_MENU,self.OnEnablePointLabel, self.enablePointLabel)
self.Bind(wx.EVT_MENU,self.OnEnableNormalize, self.norm)
self.Bind(wx.EVT_MENU,self.OnTitleSetting, setTitle)
self.Bind(wx.EVT_MENU,self.OnXLabelSetting, setXLabel)
self.Bind(wx.EVT_MENU,self.OnYLabelSetting, setYLabel)
self.Bind(wx.EVT_MENU,self.OnScrUp, scrUp)
self.Bind(wx.EVT_MENU,self.OnScrRt, scrRt)
self.Bind(wx.EVT_MENU,self.OnReset, reset)
self.client.canvas.Bind(wx.EVT_LEFT_DOWN, self.OnMouseLeftDown)
self.client.canvas.Bind(wx.EVT_MOTION, self.OnMotion)
self.Bind(wx.EVT_CLOSE, self.OnQuit)
### A status bar to tell people what's happening
self.CreateStatusBar(1)
### create tool bar
self.BuildToolbar()
vbox = wx.BoxSizer(wx.VERTICAL)
vbox.Add(self.client, 1, wx.EXPAND)
self.SetSizer(vbox)
def BuildToolbar(self):
""" Create ToolBar.
"""
tb = self.CreateToolBar()
#tb = wx.ToolBar(self, style=wx.TB_HORIZONTAL|wx.NO_BORDER|wx.TB_FLAT)
tb.SetToolBitmapSize((16,16))
zoomLabel, zoomId = self.enableZoom.GetItemLabelText(), self.enableZoom.GetId()
titleLabel, titleId = self.enableTitle.GetItemLabelText(), self.enableTitle.GetId()
gridLabel, gridId = self.enableGrid.GetItemLabelText(), self.enableGrid.GetId()
legendLabel, legendId = self.enableLegend.GetItemLabelText(), self.enableLegend.GetId()
dragLabel, dragId = self.enableDrag.GetItemLabelText(), self.enableDrag.GetId()
pointLabel, pointId = self.enablePointLabel.GetItemLabelText(), self.enablePointLabel.GetId()
normalizedLabel, normalizedId = self.norm.GetItemLabelText(), self.norm.GetId()
if wx.VERSION_STRING < '4.0':
tb.AddCheckLabelTool(zoomId, zoomLabel, wx.Bitmap(os.path.join(ICON_PATH_16_16,'toggle-zoom.png')), shortHelp=_('Enable zoom'), longHelp='')
titletb = tb.AddCheckLabelTool(titleId, titleLabel, wx.Bitmap(os.path.join(ICON_PATH_16_16,'toggle-title.png')), shortHelp=_('Enable title'), longHelp='')
gridtb = tb.AddCheckLabelTool(gridId, gridLabel, wx.Bitmap(os.path.join(ICON_PATH_16_16,'toggle-grid.png')), shortHelp='Enable grid', longHelp='')
tb.AddCheckLabelTool(legendId, legendLabel, wx.Bitmap(os.path.join(ICON_PATH_16_16,'toggle-legend.png')), shortHelp=_('Turn on legend'), longHelp='')
tb.AddCheckLabelTool(dragId, dragLabel, wx.Bitmap(os.path.join(ICON_PATH_16_16,'toggle-drag.png')), shortHelp=_('Enable drag'), longHelp='')
tb.AddCheckLabelTool(pointId, pointLabel, wx.Bitmap(os.path.join(ICON_PATH_16_16,'toggle-point.png')), shortHelp=_('Show closest point'), longHelp='')
tb.AddCheckLabelTool(normalizedId, normalizedLabel, wx.Bitmap(os.path.join(ICON_PATH_16_16,'toggle-norm.png')), shortHelp=_('Normalize'), longHelp=_('Normalize Y axis'))
else:
tb.AddCheckTool(zoomId, zoomLabel, wx.Bitmap(os.path.join(ICON_PATH_16_16,'toggle-zoom.png')), shortHelp=_('Enable zoom'), longHelp='')
titletb = tb.AddCheckTool(titleId, titleLabel, wx.Bitmap(os.path.join(ICON_PATH_16_16,'toggle-title.png')), shortHelp=_('Enable title'), longHelp='')
gridtb = tb.AddCheckTool(gridId, gridLabel, wx.Bitmap(os.path.join(ICON_PATH_16_16,'toggle-grid.png')), shortHelp='Enable grid', longHelp='')
tb.AddCheckTool(legendId, legendLabel, wx.Bitmap(os.path.join(ICON_PATH_16_16,'toggle-legend.png')), shortHelp=_('Turn on legend'), longHelp='')
tb.AddCheckTool(dragId, dragLabel, wx.Bitmap(os.path.join(ICON_PATH_16_16,'toggle-drag.png')), shortHelp=_('Enable drag'), longHelp='')
tb.AddCheckTool(pointId, pointLabel, wx.Bitmap(os.path.join(ICON_PATH_16_16,'toggle-point.png')), shortHelp=_('Show closest point'), longHelp='')
tb.AddCheckTool(normalizedId, normalizedLabel, wx.Bitmap(os.path.join(ICON_PATH_16_16,'toggle-norm.png')), shortHelp=_('Normalize'), longHelp=_('Normalize Y axis'))
titletb.Toggle(True)
gridtb.Toggle(True)
tb.Realize()
def OnMove(self, event):
"""
"""
event.Skip()
def OnMouseLeftDown(self,event):
"""
"""
self.SetStatusText(_("Left Mouse Down at Point: (%.4f, %.4f)") % self.client._getXY(event))
event.Skip() #allows plotCanvas OnMouseLeftDown to be called
def drawPointLabel(self, dc, nearest):
"""
"""
ptx, pty = nearest["scaledXY"]
dc.SetPen(wx.Pen(wx.BLACK))
dc.SetBrush(wx.Brush(wx.WHITE, 106)) # wx.PENSTYLE_TRANSPARENT = 106
dc.SetLogicalFunction(wx.INVERT)
dc.CrossHair(ptx, pty)
dc.DrawRectangle(ptx-3, pty-3, 7, 7)
dc.SetLogicalFunction(wx.COPY)
x,y = nearest["pointXY"] # data values
self.SetStatusText("%s: x = %.4f, y = %.4f" % (nearest['legend'],x,y))
def OnMotion(self, event):
"""
"""
#show closest point (when enbled)
if self.client.enablePointLabel and self.client.pointLabelFunc:
#make up dict with info for the pointLabel
#I've decided to mark the closest point on the closest curve
dlst= self.client.GetClosestPoint(self.client._getXY(event), pointScaled= True)
if dlst: #returns [] if none
curveNum, legend, pIndex, pointXY, scaledXY, distance = dlst
#make up dictionary to pass to my user function (see DrawPointLabel)
mDataDict = {"curveNum":curveNum, "legend":legend, "pIndex":pIndex, "pointXY":pointXY, "scaledXY":scaledXY}
#pass dict to update the pointLabel
self.client.UpdatePointLabel(mDataDict)
event.Skip() #go to next handler
def OnFilePageSetup(self, event):
"""
"""
self.client.PageSetup()
def OnFilePrintPreview(self, event):
"""
"""
self.client.PrintPreview()
def OnFilePrint(self, event):
"""
"""
try:
self.client.Printout()
except AttributeError as info:
sys.stderr.write("Error: %s"%info)
def OnExportFile(self, event):
"""
"""
pass
def OnSaveFile(self, event):
"""
"""
dlg = wx.FileDialog(self, message=_('Save file as...'), defaultDir=self.home, defaultFile='', wildcard="*.jpg*", style=wx.SAVE | wx.OVERWRITE_PROMPT)
if dlg.ShowModal() == wx.ID_OK:
path = dlg.GetPath()
self.home = os.path.dirname(path)
else:
path = ''
dlg.Destroy()
if path != '':
self.client.SaveFile(path)
def OnFileExit(self, event):
"""
"""
self.Close()
def OnPlotRedraw(self,event):
"""
"""
eval("self.On%s(event)"%self.type)
self.client.Redraw()
def OnEnableNormalize(self, event):
"""
"""
self.normalize = not self.normalize
self.OnPlotRedraw(event)
def OnPlotScale(self, event):
"""
"""
if self.client.last_draw != None:
graphics, xAxis, yAxis= self.client.last_draw
self.client.Draw(graphics,(1,3.05),(0,1))
def OnEnableZoom(self, event):
"""
"""
self.client.enableZoom = event.IsChecked()
#self.mainmenu.Check(self.enableZoom.GetId(), not event.IsChecked())
def OnEnableGrid(self, event):
"""
"""
self.client.enableGrid = event.IsChecked()
def OnEnableDrag(self, event):
"""
"""
self.client.enableDrag = event.IsChecked()
#self.mainmenu.Check(self.enableDrag.GetId(), not event.IsChecked())
def OnEnableTitle(self, event):
"""
"""
self.client.enableTitle = event.IsChecked()
def OnEnableLegend(self, event):
"""
"""
self.client.enableLegend = event.IsChecked()
def OnEnablePointLabel(self, event):
"""
"""
self.client.enablePointLabel = event.IsChecked()
def OnEnableXStep(self, event):
"""
"""
pass
def OnEnableXDefault(self, event):
"""
"""
pass
def OnTitleSetting(self, event):
"""
"""
pass
def OnXLabelSetting(self, event):
"""
"""
pass
def OnYLabelSetting(self, event):
"""
"""
pass
def OnScrUp(self, event):
"""
"""
self.client.ScrollUp(1)
def OnScrRt(self,event):
"""
"""
self.client.ScrollRight(2)
def OnReset(self,event):
"""
"""
self.client.Reset()
def resetDefaults(self):
"""Just to reset the fonts back to the PlotCanvas defaults"""
self.client.SetFont(wx.Font(10, wx.FONTFAMILY_SWISS, wx.FONTSTYLE_NORMAL, wx.FONTWEIGHT_NORMAL))
self.client.SetFontSizeAxis(10)
self.client.SetFontSizeLegend(7)
self.client.setLogScale((False,False))
self.client.SetXSpec('auto')
self.client.SetYSpec('auto')
def OnQuit(self, event):
"""
"""
self.Destroy()
class StaticPlot(PlotFrame):
"""
"""
def __init__(self, parent = None, id = wx.NewIdRef(), title = "Time Plotting", data = None, xLabel = 'Time [s]', yLabel = 'Amplitude [A]', typ = 'PlotLine', legend='', fusion=False):
""" @data : [(t,y)...]
"""
# local copy
self.data = data
self.xLabel = xLabel
self.yLabel = yLabel
self.step = False
self.typ = typ
self.title = title
self.legend = legend
self.fusion_flag = fusion
### Block model (from Collector lib)
self.block = None
### if values to plot are string (for state for instance)
### the frame used to display the data is not PlotFrame.
if (isinstance(data, dict) and isinstance(data[0][0][-1], str)) or (isinstance(data, list) and isinstance(data[0][-1], str)):
wx.Frame.__init__(self, parent, id, title, size=(800, 500), style=wx.DEFAULT_FRAME_STYLE|wx.CLIP_CHILDREN)
self.normalize = False
self.OnPlotStep()
else:
PlotFrame.__init__(self, parent, id, title)
menu = wx.Menu()
### display legend if more than 1 curve to display
if isinstance(self.data,dict) and len(self.data.keys())>1:
self.client.enableLegend = True
### update GUI
tb = self.GetToolBar()
tb.ToggleTool(self.enableLegend.GetId(),self.client.enableLegend)
self.enableLegend.Check(self.client.enableLegend)
### with fusion
if self.fusion_flag:
for i in range(len(self.data)):
self.Bind(wx.EVT_MENU,self.OnPlotSpectrum, menu.Append(wx.NewIdRef(), _('Signal %d')%i, _('Spectrum Plot')))
self.Bind(wx.EVT_MENU,self.OnPlotAllSpectrum, menu.Append(wx.NewIdRef(), _('All'), _('Spectrum Plot')))
else:
self.Bind(wx.EVT_MENU,self.OnPlotSpectrum, menu.Append(wx.NewIdRef(), _('Signal'), _('Spectrum Plot')))
self.mainmenu.Append(menu, _('&Spectrum'))
menu = wx.Menu()
self.Bind(wx.EVT_MENU,self.OnRMSE, menu.Append(wx.NewIdRef(), _('RMSE'), _('Root Mean Square Error')))
self.mainmenu.Append(menu, _('&Error'))
menu = wx.Menu()
self.Bind(wx.EVT_MENU, self.OnMean, menu.Append(wx.NewIdRef(), _('Mean'), _('Mean of the curve')))
self.mainmenu.Append(menu, _('&Mean'))
### call self.On<PlotLine>()
getattr(self,'On%s'%self.typ)()
def Normalize(self, data):
m = max(a[1] for a in data)
return [(b[0], b[1]/m) for b in data]
def SetBlockModel(self,block):
self.block = block
### call self.On<PlotLine>()
getattr(self,'On%s'%self.typ)()
def getInputLabels(self,data):
### find input label if it is defined b the user
input_labels = {i:f"in{i}" for i in data.keys()}
if self.block:
a = self.block.getBlockModel().getInputLabels()
if a!={}:
input_labels = a
return input_labels
def OnPlotStep(self, event=None)-> None:
"""
"""
data = self.data
plotter = PlotNotebook(self)
x,y = zip(*data[0])
axes1 = plotter.add(self.title).gca()
axes1.set_xlabel(_('Time'), fontsize=16)
axes1.set_ylabel(_('Label'), fontsize=16)
axes1.step(x, y, LColour[0], label='Inport 0')
axes1.grid(True)
#axes1.set_title(_("Plotting %s")%label)
### with fusion
if self.fusion_flag:
### if multiple inputs
if len(data) >= 2:
for k,v in data.items():
if v != data[0]:
x,y = zip(*v)
axes1.step(x, y, LColour[k+1],label='Inport %s'%str(k))
### show legend only of mulitple inputs
axes1.legend()
else:
### if multiple inputs
if len(data) >= 2:
for k,v in data.items():
if v != data[0]:
x,y = zip(*v)
ax = plotter.add(_("%s - Inport %s")%(self.title,str(k))).gca()
ax.set_xlabel(_('Time'), fontsize=16)
ax.set_ylabel(_('Label'), fontsize=16)
ax.step(x, y, LColour[k])
ax.grid(True)
#axes1.set_title(_("Plotting %s")%label)
def OnPlotLine(self, event=None)-> None:
"""
"""
data = self.data
### without fusion
if isinstance(data, list):
data = [(i if self.step else x[0], x[1]) for i,x in enumerate(data)]
if self.normalize:
data = self.Normalize(data)
line = plot.PolyLine(data, legend = 'Port 0 (%s)'%self.legend, colour = 'black', width = 1)
self.gc = plot.PlotGraphics([line], self.title, self.xLabel, self.yLabel)
xMin,xMax,yMin,yMax = get_limit(data)
### with fusion (see attribut _fusion of QuickScope)
else:
L=[]
xMin, xMax, yMin, yMax = 0.0,0.0,0.0,0.0
data_list = list(data.values())
input_labels = self.getInputLabels(data)
for ind, dd in enumerate(data_list):
try:
cc = LColour[ind]
except IndexError:
cc = LColour[0]
if self.normalize:
dd = self.Normalize(dd)
L.append(plot.PolyLine(dd, legend = f'Port {input_labels[ind]}', colour = cc, width=1))
a,b,c,d = get_limit(dd)
if float(a) < float(xMin): xMin=float(a)
if float(b) > float(xMax): xMax=float(b)
if float(c) < float(yMin): yMin=float(c)
if float(d) > float(yMax): yMax=float(d)
self.gc = plot.PlotGraphics(L, self.title, self.xLabel, self.yLabel)
self.client.Draw(self.gc, xAxis = (float(xMin),float(xMax)), yAxis = (float(yMin),float(yMax)))
def OnPlotSquare(self, event=None)->None:
"""
"""
data = self.data
## without fusion
if isinstance(data, list):
### formatage des données spécifique au square
data = []
for v1,v2 in zip(self.data,[(self.data[i+1][0], self.data[i][1]) for i in range(len(self.data)-1)]):
data.append(v1)
data.append(v2)
if self.normalize:
data = self.Normalize(data)
line = plot.PolyLine(data, legend = 'Port 0 (%s)'%self.legend, colour = 'black', width = 1)
self.gc = plot.PlotGraphics([line], self.title, self.xLabel, self.yLabel)
### gestion automatique des bornes
xMin,xMax,yMin,yMax = get_limit(data)
##avec fusion (voir attribut 'fusion' de QuickScope)
else:
L = []
xMin, xMax, yMin, yMax = 0.0,0.0,0.0,0.0
data_list = list(data.values())
input_labels = self.getInputLabels(data)
for ind,d in enumerate(data_list):
### formatage des données spécifique au square
dd = []
for v1,v2 in zip(d,[ (d[i+1][0], d[i][1]) for i in range(len(d)-1)]):
dd.append(v1)
dd.append(v2)
### gestion des couleures
try:
c = LColour[ind]
except IndexError:
c = LColour[0]
if self.normalize:
m = max([a[1] for a in dd])
dd = [(b[0], b[1]/m) for b in dd]
L.append(plot.PolyLine(dd, legend = f'Port {input_labels[ind]}', colour = c, width=1))
### gestion automatique des bornes
a,b,c,d = get_limit(dd)
if float(a) < float(xMin): xMin=float(a)
if float(b) > float(xMax): xMax=float(b)
if float(c) < float(yMin): yMin=float(c)
if float(d) > float(yMax): yMax=float(d)
self.gc = plot.PlotGraphics(L, self.title, self.xLabel, self.yLabel)
self.client.Draw(self.gc, xAxis = (float(xMin),float(xMax)), yAxis = (float(yMin),float(yMax)))
def OnPlotScatter(self, event=None):
data = self.data
## sans fusion
if isinstance(data, list):
if self.normalize:
data = self.Normalize(data)
markers = plot.PolyMarker(data, colour = LColour[0], marker = Markers[0], size = 1)
line = plot.PolyLine(data, legend = 'Port 0 (%s)'%self.legend, colour = LColour[0], width = 1)
self.gc = plot.PlotGraphics([line, markers], self.title, self.xLabel, self.yLabel)
xMin,xMax,yMin,yMax = get_limit(data)
##avec fusion (voir attribut _fusion de QuickScope)
else:
L=[]
xMin, xMax, yMin, yMax = 0.0,0.0,0.0,0.0
data_list = list(data.values())
for ind,dd in enumerate(data_list):
try:
c = LColour[ind]
except IndexError:
c = LColour[0]
try:
m = Markers[ind]
except IndexError:
m = Markers[0]
if self.normalize:
m = max([a[1] for a in dd])
d = [(b[0], b[1]/m) for b in dd]
L.append(plot.PolyLine(dd, legend = 'Port 0 %s'%self.legend, colour=c, width=1))
L.append(plot.PolyMarker(dd, colour=c, marker=m, size=1))
a,b,c,d = get_limit(dd)
if float(a) < float(xMin): xMin=float(a)
if float(b) > float(xMax): xMax=float(b)
if float(c) < float(yMin): yMin=float(c)
if float(d) > float(yMax): yMax=float(d)
self.gc = plot.PlotGraphics(L, self.title, self.xLabel, self.yLabel)
self.client.Draw(self.gc, xAxis = (float(xMin),float(xMax)), yAxis = (float(yMin),float(yMax)))
def OnPlotBar(self, event=None):
data = self.data
## sans fusion
if isinstance( data, list):
line = [plot.PolyLine([(c[0], 0), (c[0],c[1])], legend='', colour='gray', width=25) for c in data]
self.gc = plot.PlotGraphics(line, self.title, self.xLabel, self.yLabel)
xMin,xMax,yMin,yMax = get_limit(data)
##avec fusion (voir attribut _fusion de QuickScope)
else:
L=[]
xMin, xMax, yMin, yMax = 0.0,0.0,0.0,0.0
for k in data:
dd = data[k]
for c in dd:
L.append(plot.PolyLine([(c[0], 0), (c[0],c[1])], legend='', colour='gray', width=25))
a,b,c,d = get_limit(dd)
if float(a) < float(xMin): xMin=float(a)
if float(b) > float(xMax): xMax=float(b)
if float(c) < float(yMin): yMin=float(c)
if float(d) > float(yMax): yMax=float(d)
self.gc = plot.PlotGraphics(L, self.title, self.xLabel, self.yLabel)
self.client.Draw(self.gc, xAxis = (float(xMin),float(xMax)), yAxis = (float(yMin),float(yMax)))
def OnMean(self, evt):
"""
"""
if isinstance(self.data, dict):
r = 0.0
else:
r = sum(c[-1] for c in self.data) / len(self.data)
wx.MessageBox('Mean: %f'%r, _('Info'), wx.OK|wx.ICON_INFORMATION)
def OnRMSE(self,evt):
""" Get RMSE.
"""
if isinstance(self.data, dict):
c1,c2 = self.data.values()
assert(len(c1)==len(c2))
diffcarr = map(lambda a,b: pow(float(a[-1])-float(b[-1]),2), c1,c2)
r = sqrt(sum(diffcarr)/len(c1))
wx.MessageBox('RMSE: %f'%r, _('Info'), wx.OK|wx.ICON_INFORMATION)
else:
wx.MessageBox('RMSE needs two curves!', _('Error'), wx.OK|wx.ICON_ERROR)
# for k,s in self.atomicModel.results.items():
# frame = Spectrum(self,wx.NewIdRef(), title= _("Spectrum of signal %d")%k,data = s)
# frame.Center()
# frame.Show()
def OnPlotAllSpectrum(self, evt=None):
"""
"""
for k,s in list(self.data.items()):
frame = Spectrum(self,wx.NewIdRef(), title= _("Spectrum of signal %d")%k,data=s)
frame.Center()
frame.Show()
def OnPlotSpectrum(self, evt=None):
"""
"""
# si mode fusion
if isinstance(self.data,dict):
#menu = evt.GetEventObject()
item=self.mainmenu.FindItemById(evt.GetId())
# permet d'identifier le numero du signal
i = int(item.GetLabel().split(' ')[-1])
frame = Spectrum(self,wx.NewIdRef(), title= _("Spectrum of signal "),data = self.data[i])
else:
frame = Spectrum(self,wx.NewIdRef(), title= _("Spectrum of signal "),data = self.data)
frame.Center()
frame.Show()
def OnEnableXStep(self, event):
"""
"""
self.step = True
eval("self.On%s()"%self.typ)
self.gc.setXLabel("Step")
self.client.Redraw()
def OnEnableXDefault(self, event):
"""
"""
self.step = False
eval("self.On%s()"%self.typ)
self.gc.setXLabel("Time [s]")
self.client.Redraw()
def OnTitleSetting(self, event):
"""
"""
dlg = wx.TextEntryDialog(self, _('Enter new title'),_('Title Entry'))
dlg.SetValue(self.title)
if dlg.ShowModal() == wx.ID_OK:
self.title = dlg.GetValue()
self.gc.setTitle(self.title)
self.client.Redraw()
dlg.Destroy()
def OnXLabelSetting(self, event):
"""
"""
dlg = wx.TextEntryDialog(self, _('Enter new X label'),_('Label Entry'))
dlg.SetValue(self.xLabel)
if dlg.ShowModal() == wx.ID_OK:
self.xLabel = dlg.GetValue()
self.gc.setXLabel(self.xLabel)
self.client.Redraw()
dlg.Destroy()
def OnYLabelSetting(self, event):
"""
"""
dlg = wx.TextEntryDialog(self, _('Enter new Y label'),_('Label Entry'))
dlg.SetValue(self.yLabel)
if dlg.ShowModal() == wx.ID_OK:
self.yLabel = dlg.GetValue()
self.gc.setYLabel(self.yLabel)
self.client.Redraw()
dlg.Destroy()
def OnExportFile(self, event):
""" Export in CSV format
"""
dlg = wx.FileDialog(self, message=_('Export file as...'), defaultDir=self.home, defaultFile='', wildcard="*.csv*", style=wx.SAVE | wx.OVERWRITE_PROMPT)
if dlg.ShowModal() == wx.ID_OK:
path = dlg.GetPath()
self.home = os.path.dirname(path)
else:
path = ''
dlg.Destroy()
if path != '':
d = [(0,0)]
### TODO: adapt to consider all of the tab (not only 0)
data = self.data[0] if isinstance(self.data, dict) else self.data
for i,x in enumerate(data):
if x[0] != d[-1][0]:
d.append((x[0],x[1]))
else:
d[-1] = (x[0],x[1])
d=d[1:]
if self.step:
d = [(i, x[1]) for i,x in enumerate(d)]
with open(path, 'w') as csvFile:
writer = csv.writer(csvFile, delimiter=' ')
writer.writerows(d)
class DynamicPlot(PlotFrame):
"""
"""
def __init__(self, parent=None, id=wx.NewIdRef(), title="", atomicModel=None, xLabel="", yLabel="", iport=None):
"""
@parent: parent class
@id: class id
@title: title of frame
@xLabel: label for x axe
@yLabel: label for y axe
@iport: the number of port when the fusion option is disabled.
@atomicModel: QuicScope atomic model used for its data
"""
PlotFrame.__init__(self, parent, id, title)
# local copy
self.parent = parent
self.atomicModel = atomicModel
self.xLabel = xLabel
self.yLabel = yLabel
self.iport = iport
self.title = ""
# simulation thread
self.sim_thread = None
diagram = parent.diagram
diagram_name = os.path.splitext(os.path.basename(diagram.last_name_saved))[0]
# for all thread without the mainTread (the first is devsimpy)
for thread in threading.enumerate()[1:]:
# if the thread is for the current diagram
if diagram_name in thread.name:
self.sim_thread = thread
break
menu = wx.Menu()
### si mode fusion
if self.iport is None:
for i in self.atomicModel.results:
self.Bind(wx.EVT_MENU, self.OnPlotSpectrum, menu.Append(wx.NewIdRef(), _('Signal %s')%str(i), _('Spectrum Plot')))
self.Bind(wx.EVT_MENU, self.OnPlotAllSpectrum, menu.Append(wx.NewIdRef(), _('All'), _('Spectrum Plot')))
else:
self.Bind(wx.EVT_MENU, self.OnPlotSpectrum, menu.Append(wx.NewIdRef(), _('Signal %s')%str(self.iport), _('Spectrum Plot')))
self.mainmenu.Append(menu, _('&Spectrum'))
self.timer = wx.Timer(self)
### DEFAULT_PLOT_DYN_FREQ can be configured in preference-> simulation
self.timer.Start(milliseconds=DEFAULT_PLOT_DYN_FREQ)
self.Bind(wx.EVT_TIMER, self.OnPlotRedraw)
#self.Bind(wx.EVT_TIMER, self.OnTimerEvent)
#self.Bind(wx.EVT_PAINT, getattr(self, "On%s"%self.type))
self.Bind(wx.EVT_CLOSE, self.OnQuit)
getattr(self, "On%s"%self.type)()
def OnTimerEvent(self, event):
#self.GetEventHandler().ProcessEvent(wx.PaintEvent())
self.OnPlotRedraw(event)
def Normalize(self, data):
m = max(a[1] for a in data)
return [(b[0], b[1]/m) for b in data]
def OnPlotLine(self, event=None)->None:
""" Plot process depends to the timer event.
"""
#if self.timer.IsRunning():
### unbinding paint event
# if self.type != "PlotLine":
# self.type = "PlotLine"
# self.Unbind(wx.EVT_PAINT)
# self.Bind(wx.EVT_PAINT, getattr(self, "On%s"%self.type))
### without fusion
if self.iport is not None:
data = self.atomicModel.results[self.iport]
if self.normalize:
data = self.Normalize(data)
line = plot.PolyLine(data, legend = 'Port 0 (%s)'%self.atomicModel.getBlockModel().label, colour = 'black', width = 1)
self.gc = plot.PlotGraphics([line], self.title, self.xLabel, self.yLabel)
xMin,xMax,yMin,yMax = get_limit(data)
### with fusion (look QuickScope attribut _fusion)
else:
data = self.atomicModel.results
label = self.atomicModel.getBlockModel().label
L = []
xMin, xMax, yMin, yMax = 0,0,0,0
data_list = list(data.values())
for ind,dd in enumerate(data_list):
#ind = data_list.index(d)
try:
cc = LColour[ind]
except IndexError:
cc = LColour[0]
if self.normalize:
m = max([a[1] for a in dd])
dd = [(b[0], b[1]/m) for b in dd]
L.append(plot.PolyLine(dd, legend = 'Port %s (%s)'%(str(ind), label), colour = cc, width=1))
a,b,c,d = get_limit(dd)
if float(a) < float(xMin): xMin=float(a)
if float(b) > float(xMax): xMax=float(b)
if float(c) < float(yMin): yMin=float(c)
if float(d) > float(yMax): yMax=float(d)
self.gc = plot.PlotGraphics(L, self.title, self.xLabel, self.yLabel)
try:
self.client.Draw(self.gc, xAxis = (float(xMin),float(xMax)), yAxis = (float(yMin),float(yMax)))
except Exception:
sys.stdout.write(_("Error trying to plot"))
# if self.sim_thread is None or not self.sim_thread.isAlive():
# self.timer.Stop()
def OnPlotSquare(self, event):
#if self.timer.IsRunning():
### unbinding paint event
# if self.type != "PlotSquare":
# self.type = "PlotSquare"
# self.Unbind(wx.EVT_PAINT)
# self.Bind(wx.EVT_PAINT, getattr(self, "On%s"%self.type))
## without fusion
if self.iport is not None:
d = self.atomicModel.results[self.iport]
### formating data for square
data = []
for v1,v2 in zip(d,[ (d[i+1][0], d[i][1]) for i in range(len(d)-1)]):
data.append(v1)
data.append(v2)
if self.normalize:
m = max([a[1] for a in data])
data = [(b[0], b[1]/m) for b in data]
line = plot.PolyLine(data, legend='Port 0 (%s)'%self.atomicModel.getBlockModel().label, colour='black', width=1)
self.gc = plot.PlotGraphics([line], self.title, self.xLabel, self.yLabel)
### dynamic managment of bounds
xMin,xMax,yMin,yMax = get_limit(data)
### with fusion ('fusion' attribut of QuickScope)
else:
data = self.atomicModel.results
label = self.atomicModel.getBlockModel().label
L = []
xMin, xMax = 0,0
yMin, yMax = 0,0
data_list = list(data.values())
for ind,d in enumerate(data_list):
### data processing
dd = []
for v1,v2 in zip(d,[ (d[i+1][0], d[i][1]) for i in range(len(d)-1)]):
dd.append(v1)
dd.append(v2)
### color
try:
c = LColour[ind]
except IndexError:
c = LColour[0]
if self.normalize:
m = max([a[1] for a in dd])
dd = [(b[0], b[1]/m) for b in dd]
### data construct
L.append(plot.PolyLine(dd, legend='Port %s (%s)'%(str(ind),label), colour=c, width=1))
### limit managment
a,b,c,d = get_limit(dd)
if float(a) < float(xMin): xMin=float(a)
if float(b) > float(xMax): xMax=float(b)
if float(c) < float(yMin): yMin=float(c)
if float(d) > float(yMax): yMax=float(d)
self.gc = plot.PlotGraphics(L, self.title, self.xLabel, self.yLabel)
try:
self.client.Draw(self.gc, xAxis = (float(xMin),float(xMax)), yAxis = (float(yMin),float(yMax)))
except Exception:
sys.stdout.write(_("Error trying to plot"))
cond = self.sim_thread.isAlive() if hasattr(self.sim_thread,'isAlive') else self.sim_thread.is_alive()
if self.sim_thread is None or not cond:
self.timer.Stop()
def OnPlotScatter(self, event):
"""
"""
#if self.timer.IsRunning():
### unbinding paint event
# if self.type != "PlotScatter":
# self.type = "PlotScatter"
# self.Unbind(wx.EVT_PAINT)
# self.Bind(wx.EVT_PAINT, getattr(self, "On%s"%self.type))
## without fusion
if self.iport is not None:
data = self.atomicModel.results[self.iport]
if self.normalize:
data = self.Normalize(data)
markers = plot.PolyMarker(data, colour=LColour[0], marker=Markers[0], size=1)
line = plot.PolyLine(data, legend='Port 0 (%s)'%self.atomicModel.getBlockModel().label, colour=LColour[0], width=1)
self.gc = plot.PlotGraphics([line, markers], self.title, self.xLabel, self.yLabel)
xMin,xMax,yMin,yMax = get_limit(data)
## with fusion (see attribut _fusion of QuickScope)
else:
data = self.atomicModel.results
label = self.atomicModel.getBlockModel().label
L = []
xMin, xMax = 0,0
yMin, yMax = 0,0
data_list = list(data.values())
for ind,dd in enumerate(data_list):
#ind = data.values().index(d)
try:
c = LColour[ind]
except IndexError:
c = LColour[0]
try:
m = Markers[ind]
except IndexError:
m = Markers[0]
if self.normalize:
m = max([a[1] for a in dd])
dd = [(b[0], b[1]/m) for b in dd]
L.append(plot.PolyLine(dd, colour=c, width=1))
L.append(plot.PolyMarker(dd, legend='Port %s (%s)'%(str(ind), label), colour=c, marker=m, size=1))
a,b,c,d = get_limit(dd)
if float(a) < float(xMin): xMin=float(a)
if float(b) > float(xMax): xMax=float(b)
if float(c) < float(yMin): yMin=float(c)
if float(d) > float(yMax): yMax=float(d)
self.gc = plot.PlotGraphics(L, self.title, self.xLabel, self.yLabel)
try:
self.client.Draw(self.gc, xAxis = (float(xMin),float(xMax)), yAxis = (float(yMin),float(yMax)))
except Exception:
sys.stdout.write(_("Error trying to plot"))
cond = self.sim_thread.isAlive() if hasattr(self.sim_thread,'isAlive') else self.sim_thread.is_alive()
if self.sim_thread is None or not cond:
self.timer.Stop()
def OnPlotBar(self,event):
#if self.timer.IsRunning():
### unbinding paint event
# if self.type != "PlotBar":
# self.type = "PlotBar"
# self.Unbind(wx.EVT_PAINT)
# self.Bind(wx.EVT_PAINT, getattr(self, "On%s"%self.type))
## without fusion
if self.iport is not None:
data = self.atomicModel.results[self.iport]
line = [plot.PolyLine([(c[0], 0), (c[0],c[1])], legend='', colour='gray', width=25) for c in data]
self.gc = plot.PlotGraphics(line, self.title, self.xLabel, self.yLabel)
xMin,xMax,yMin,yMax = get_limit(data)
## with fusion (see attribut _fusion of QuickScope)
else:
data = self.atomicModel.results
L=[]
xMin, xMax, yMin, yMax = 0,0,0,0
data_list = list(data.values())
for ind,dd in enumerate(data_list):
#ind = data_list.index(d)
try:
c = LColour[ind]
except IndexError:
c = LColour[0]
for c in dd:
L.append(plot.PolyLine([(c[0], 0), (c[0],c[1])], legend='', colour='gray', width=25))
a,b,c,d = get_limit(dd)
if float(a) < float(xMin): xMin=float(a)
if float(b) > float(xMax): xMax=float(b)
if float(c) < float(yMin): yMin=float(c)
if float(d) > float(yMax): yMax=float(d)
self.gc = plot.PlotGraphics(L, self.title, self.xLabel, self.yLabel)
try:
self.client.Draw(self.gc, xAxis = (float(xMin),float(xMax)), yAxis = (float(yMin),float(yMax)))
except Exception:
sys.stdout.write(_("Error trying to plot"))
cond = self.sim_thread.isAlive() if hasattr(self.sim_thread,'isAlive') else self.sim_thread.is_alive()
if self.sim_thread is None or not cond:
self.timer.Stop()
def OnPlotAllSpectrum(self,evt):
""" Plot all spectrum.
"""
for k,s in list(self.atomicModel.results.items()):
frame = Spectrum(self,wx.NewIdRef(), title= _("Spectrum of signal %d")%k,data = s)
frame.Center()
frame.Show()
def OnPlotSpectrum(self, evt):
""" Plot spectrum.
"""
item = self.mainmenu.FindItemById(evt.GetId())
# allow signal number identification
i = int(item.GetLabel().split(' ')[-1])
frame = Spectrum(self, wx.NewIdRef(), title= _("Spectrum of signal"), data=self.atomicModel.results[i])
frame.Center()
frame.Show()
def OnTitleSetting(self, event):
dlg = wx.TextEntryDialog(self, _('Enter a new title'), _('Title Entry'))
dlg.SetValue(self.title)
if dlg.ShowModal() == wx.ID_OK:
self.title = dlg.GetValue()
self.gc.setTitle(self.title)
self.client.Redraw()
dlg.Destroy()
def OnXLabelSetting(self, event):
dlg = wx.TextEntryDialog(self, _('Enter a new X label'), _('Label Entry'))
dlg.SetValue(self.xLabel)
if dlg.ShowModal() == wx.ID_OK:
self.xLabel = dlg.GetValue()
self.gc.setXLabel(self.xLabel)
self.client.Redraw()
dlg.Destroy()
def OnYLabelSetting(self, event):
dlg = wx.TextEntryDialog(self, _('Enter a new Y label'), _('Label Entry'))
dlg.SetValue(self.yLabel)
if dlg.ShowModal() == wx.ID_OK:
self.yLabel = dlg.GetValue()
self.gc.setYLabel(self.yLabel)
self.client.Redraw()
dlg.Destroy()
class Spectrum(StaticPlot):
def __init__(self, parent=None, id=wx.NewIdRef(), title="", data=[]):
""" @data : [(x,y)...]
"""
# total time
duree = data[-1][0]
signal=[c[1] for c in data]
Nb_pts=len(signal)
#interpolation B-splines
#dx=1
#newx=r_[0:Nb_pts:duree]
#y=array(self.signal)
#newy=cspline1d_eval(cspline1d(y),newx,dx=dx,x0=y[0])
#self.signal=newy
### number of points for fft
p=1
while(pow(2,p)<=Nb_pts):
p+=1
N=float(pow(2,p))
assert(pow(2,p)>= Nb_pts)
### windows
signal = smooth(array(signal),window_len=10,window="hamming")
### frequence d'echantillonnage
Fe = 1.0/(float(duree)/float(len(signal)))
### FFT
Y = fft.fft(signal,int(N))
Y = abs(fft.fftshift(Y))
F = [Fe*i/N for i in range(int(-N/2), int(N/2))]
### normalization
Max = max(Y)
Y = [20*math.log(i/Max,10) for i in Y]
### freqencies max and min for the plot
FMin, FMax=0,200
F_plot, Y_plot=[],[]
for i in range(len(F)):
if FMin<F[i]<FMax:
F_plot.append(F[i])
Y_plot.append(Y[i])
### data processing
self.data = list(map(lambda a,b: (a,b), F_plot, Y_plot))
#self.data = [(a,b) for a in F_plot for b in Y_plot]
# call the frame
StaticPlot.__init__(self, parent, id, title, self.data, xLabel=_('Frequency [Hz]'),yLabel=_('Amplitude [dB]'))
self.OnPlotLine()
# range for fred and amplitude
# self.sldh.SetRange(1, 300)
# self.sldv.SetRange(0, 150)
# start freq 100
# self.sldh.SetValue(100)
# start amplitude 0
# self.sldv.SetValue(0)
# Bind the Sliders
# self.Bind(wx.EVT_SLIDER, self.sliderUpdate, id=self.sldh.GetId())
# self.Bind(wx.EVT_SLIDER, self.sliderUpdate, id=self.sldv.GetId())
# def sliderUpdate(self, event):
# posh = self.sldh.GetValue()
# posv = self.sldv.GetValue()
# self.Redraw(self.Rescale(posv,posh))
def Redraw(self,data:list=[]):
"""Redraw the client
Args:
data (list, optional): data to redraw. Defaults to [].
"""
size=self.client.GetSize()
self.client.Clear()
self.client.SetInitialSize(size=size)
#xLabel=_('Frequency [Hz]')
#yLabel=_('Amplitude [dB]')
line = plot.PolyLine(data, legend='', colour='black', width=1)
gc = plot.PlotGraphics([line], '', self.xLabel, self.yLabel)
xMin,xMax,yMin,yMax = get_limit(data)
self.client.Draw(gc, xAxis= (float(xMin),float(xMax)), yAxis= (float(yMin),float(yMax)))
def Rescale(self,FMin:int=0,FMax:int=200)->list:
""" Rescale the plot
Args:
FMin (int, optional): min frequency. Defaults to 0.
FMax (int, optional): max frequency. Defaults to 200.
Returns:
list: [description]
"""
F,Y,F_plot, Y_plot=[],[],[],[]
for f,v in self.data:
F.append(f)
Y.append(v)
for i in range(len(F)):
if FMin<F[i]<FMax:
F_plot.append(F[i])
Y_plot.append(Y[i])
# formate les donnees pour Plot
return list(map(lambda a,b: (a,b), F_plot, Y_plot))
#return [(a,b) for a in F_plot for b in Y_plot]