예제 #1
0
    def __init__(self, *args, **kwargs):
        self._app = Application.instance
        self.__topwin = kwargs.pop('topwin')
        Group.__init__(self, *args, **kwargs)
        frm = Frame(self)

        self.__center = ParamItem(frm)
        setMultiAttr(self.__center,
                     labelText='center(deg)',
                     entryText=0,
                     checkFunc=self._app.checkInt,
                     entryWidth=5,
                     labelWidth=10)
        self.__center.pack(side=TOP)
        self._app.balloon.bind_widget(
            self.__center, balloonmsg='Specify the beam center here.')

        self.__width = ParamItem(frm)
        setMultiAttr(self.__width,
                     labelText='width(deg)',
                     entryText=20,
                     checkFunc=self._app.checkInt,
                     entryWidth=5,
                     labelWidth=10)
        self.__width.pack(side=TOP)
        self._app.balloon.bind_widget(
            self.__width, balloonmsg='Specify the beam width here.')

        self.__uiImages = []

        imageAddBtn = ImageTk.PhotoImage(
            file=uiImagePath('Pattern_Add_Button.png'))
        self.__uiImages.append(imageAddBtn)
        btn = Button(frm, image=imageAddBtn, command=self.onAdd)
        btn.pack(side=LEFT)
        self._app.balloon.bind_widget(
            btn, balloonmsg='Add new beam to the ideal pattern.')

        imageDelBtn = ImageTk.PhotoImage(
            file=uiImagePath('Pattern_Del_Button.png'))
        self.__uiImages.append(imageDelBtn)
        btn = Button(frm, image=imageDelBtn, command=self.onDel)
        btn.pack(side=LEFT)
        self._app.balloon.bind_widget(
            btn, balloonmsg='Remove the selected beam in the listbox.')

        imageClrBtn = ImageTk.PhotoImage(
            file=uiImagePath('Pattern_Clear_Button.png'))
        self.__uiImages.append(imageClrBtn)
        btn = Button(frm, image=imageClrBtn, command=self.onClear)
        btn.pack(side=LEFT)
        self._app.balloon.bind_widget(
            btn, balloonmsg='Clear the listbox of the beam parameters.')

        imagePlotBtn = ImageTk.PhotoImage(
            file=uiImagePath('Pattern_Plot_Button.png'))
        self.__uiImages.append(imagePlotBtn)
        btn = Button(frm, image=imagePlotBtn, command=self.onPlotIdealPattern)
        btn.pack(side=LEFT)
        self._app.balloon.bind_widget(btn,
                                      balloonmsg='Plot the ideal pattern.')

        frm.pack(side=LEFT, fill=Y)

        self.__paramlist = ScrolledList(self)
        self.__paramlist.list.config(height=4, width=10)
        self.__paramlist.pack(side=LEFT)
        self.name = 'Edit Ideal Pattern'

        self.optgrp = None
예제 #2
0
    def __init__(self, *args, **kwargs):
        '''
nodeName:   The name of this node. Usually set by ModelNode.__setattr__ automatically.
figureMeta: Meta information of figure.
The rest parameters are passed to PanedWindow.__init__.
'''
        nodeName = kwargs.pop('nodeName', '')
        # lock

        super(FigureBook, self).__init__(nodeName=nodeName)

        figureMeta = None if 'figureMeta' not in kwargs \
            else kwargs.pop('figureMeta')
        kwargs['orient'] = HORIZONTAL

        panedWindow = PanedWindow(*args, **kwargs)

        panedWindow.config(sashwidth=4, sashrelief=GROOVE, bg='forestgreen')

        #        figureTabsStyle = Style()
        #        figureTabsStyle.configure('Figure.TNotebook', tabposition='sw')
        #        figureTabs    = Notebook(panedWindow, style='Figure.TNotebook')
        figureTabs = Notebook(panedWindow)

        self.figureTabs = figureTabs
        figureTabs.bind('<<NotebookTabChanged>>', self.onTabChange)
        self.lockAttribute('figureTabs')

        if figureMeta:
            self.makeFigures(figureMeta)

        self.lockElements()

        panedWindow.add(figureTabs, stretch='always')

        listPan = PanedWindow(panedWindow, orient=VERTICAL)
        listPan.config(sashwidth=4, sashrelief=GROOVE, bg='forestgreen')
        panedWindow.add(listPan, stretch='never')

        listFrm = Frame(listPan)
        listPan.add(listFrm, stretch='always')
        Label(listFrm, text='Curves', bg='#b5d6b0').pack(side=TOP, fill=X)
        self.__list = ScrolledList(listFrm, relief=GROOVE)
        self.__list.listConfig(width=20)
        self.__list.listClick = self.onListClick
        self.__list.pack(fill=BOTH, expand=YES)

        listFrm = Frame(listPan)
        listPan.add(listFrm, stretch='never')
        Label(listFrm, text='Indicators', bg='#b5d6b0').pack(side=TOP, fill=X)
        self.__indicatorListbox = ScrolledList(listFrm, relief=GROOVE)
        self.__indicatorListbox.listConfig(width=20)
        self.__indicatorListbox.pack(fill=BOTH, expand=YES)

        with self.attributeLock:
            setMultiAttr(
                self,
                panedWindow=panedWindow,
                gridGroupObserver=self.GridGroupObserver(self),
                axisGroupObserver=self.AxisGroupObserver(self),
                clearGroupObserver=self.ClearGroupObserver(self),
                labelGroupObserver=self.LabelGroupObserver(self),
                indicatorGroupObserver=self.IndicatorGroupObserver(self),
                dataFigureObserver=self.DataFigureObserver(self),
                dataPool=[])
예제 #3
0
class EditGroup(Group):
    def __init__(self, *args, **kwargs):
        self._app = Application.instance
        self.__topwin = kwargs.pop('topwin')
        Group.__init__(self, *args, **kwargs)
        frm = Frame(self)

        self.__center = ParamItem(frm)
        setMultiAttr(self.__center,
                     labelText='center(deg)',
                     entryText=0,
                     checkFunc=self._app.checkInt,
                     entryWidth=5,
                     labelWidth=10)
        self.__center.pack(side=TOP)
        self._app.balloon.bind_widget(
            self.__center, balloonmsg='Specify the beam center here.')

        self.__width = ParamItem(frm)
        setMultiAttr(self.__width,
                     labelText='width(deg)',
                     entryText=20,
                     checkFunc=self._app.checkInt,
                     entryWidth=5,
                     labelWidth=10)
        self.__width.pack(side=TOP)
        self._app.balloon.bind_widget(
            self.__width, balloonmsg='Specify the beam width here.')

        self.__uiImages = []

        imageAddBtn = ImageTk.PhotoImage(
            file=uiImagePath('Pattern_Add_Button.png'))
        self.__uiImages.append(imageAddBtn)
        btn = Button(frm, image=imageAddBtn, command=self.onAdd)
        btn.pack(side=LEFT)
        self._app.balloon.bind_widget(
            btn, balloonmsg='Add new beam to the ideal pattern.')

        imageDelBtn = ImageTk.PhotoImage(
            file=uiImagePath('Pattern_Del_Button.png'))
        self.__uiImages.append(imageDelBtn)
        btn = Button(frm, image=imageDelBtn, command=self.onDel)
        btn.pack(side=LEFT)
        self._app.balloon.bind_widget(
            btn, balloonmsg='Remove the selected beam in the listbox.')

        imageClrBtn = ImageTk.PhotoImage(
            file=uiImagePath('Pattern_Clear_Button.png'))
        self.__uiImages.append(imageClrBtn)
        btn = Button(frm, image=imageClrBtn, command=self.onClear)
        btn.pack(side=LEFT)
        self._app.balloon.bind_widget(
            btn, balloonmsg='Clear the listbox of the beam parameters.')

        imagePlotBtn = ImageTk.PhotoImage(
            file=uiImagePath('Pattern_Plot_Button.png'))
        self.__uiImages.append(imagePlotBtn)
        btn = Button(frm, image=imagePlotBtn, command=self.onPlotIdealPattern)
        btn.pack(side=LEFT)
        self._app.balloon.bind_widget(btn,
                                      balloonmsg='Plot the ideal pattern.')

        frm.pack(side=LEFT, fill=Y)

        self.__paramlist = ScrolledList(self)
        self.__paramlist.list.config(height=4, width=10)
        self.__paramlist.pack(side=LEFT)
        self.name = 'Edit Ideal Pattern'

        self.optgrp = None

    def onAdd(self):
        self.__paramlist.list.insert(
            END, '{0}, {1}'.format(self.__center.getInt(),
                                   self.__width.getInt()))

    def onDel(self):
        self.__paramlist.list.delete(ANCHOR)

    def onClear(self):
        self.__paramlist.clear()

    def onPlotIdealPattern(self):
        printCode = True
        center, width = self.beamData
        self.__topwin.setIdealPattern(center, width)
        self.__topwin.plotIdealPattern()

    @property
    def beamData(self):
        beamParams = self.__paramlist.list.get(0, END)
        if not beamParams:
            self._app.printError('An error occurred!')
            self._app.printTip([{
                'type':
                'text',
                'content':
                '''This exception happens when the listbox of the beam parameters are empty.
To make a valid ideal pattern, at least one beam should be specified.
'''
            }])
            return
        center, width = zip(
            *[map(float, param.split(',')) for param in beamParams])
        return center, width
예제 #4
0
class EditGroup(Group):
    def __init__(self, *args, **kwargs):
        self._app = Scripting.root_node
        self.__topwin = kwargs.pop('topwin')
        Group.__init__(self, *args, **kwargs)
        frm = Frame(self)
        
        self.__center = LabeledEntry(frm)
        set_attributes(self.__center,        
            label_text   = 'center(deg)',        
            entry_text   = 0,    
            checker_function   = self._app.check_int,
            entry_width  = 5,    
            label_width  = 10
        )                       
        self.__center.pack(side=TOP)        
        self._app.balloon.bind_widget(self.__center, balloonmsg='Specify the beam center here.')
        
        self.__width = LabeledEntry(frm)
        set_attributes(self.__width,
            label_text   = 'width(deg)',
            entry_text   = 20,
            checker_function   = self._app.check_int,
            entry_width  = 5,
            label_width  = 10
        )
        self.__width.pack(side=TOP)
        self._app.balloon.bind_widget(self.__width, balloonmsg='Specify the beam width here.')
        
        self.__gui_images = []
                
                
        imageAddBtn = ImageTk.PhotoImage(
            file=get_gui_image_path('Pattern_Add_Button.png')
        )
        self.__gui_images.append(imageAddBtn)
        btn = Button(frm, image=imageAddBtn, command=self._on_add_button_click)
        btn.pack(side=LEFT)
        self._app.balloon.bind_widget(btn, balloonmsg='Add new beam to the ideal pattern.')
        
        imageDelBtn = ImageTk.PhotoImage(
            file=get_gui_image_path('Pattern_Del_Button.png')
        )
        self.__gui_images.append(imageDelBtn)
        btn = Button(frm, image=imageDelBtn, command=self._on_delete_button_click)
        btn.pack(side=LEFT)
        self._app.balloon.bind_widget(btn, balloonmsg='Remove the selected beam in the listbox.')
        
        imageClrBtn = ImageTk.PhotoImage(
            file=get_gui_image_path('Pattern_Clear_Button.png')
        )
        self.__gui_images.append(imageClrBtn)
        btn = Button(frm, image=imageClrBtn, command=self._on_clear_button_click)
        btn.pack(side=LEFT)
        self._app.balloon.bind_widget(btn, balloonmsg='Clear the listbox of the beam parameters.')
        
        imagePlotBtn = ImageTk.PhotoImage(
            file=get_gui_image_path('Pattern_Plot_Button.png')
        )
        self.__gui_images.append(imagePlotBtn)
        btn = Button(frm, image=imagePlotBtn, command=self._on_plot_ideal_pattern)
        btn.pack(side=LEFT)
        self._app.balloon.bind_widget(btn, balloonmsg='Plot the ideal pattern.')
        
        frm.pack(side=LEFT, fill=Y)
        
        self.__paramlist = ScrolledList(self)
        self.__paramlist.list.config(height=4, width=10)
        self.__paramlist.pack(side=LEFT)
        self.name = 'Edit Ideal Pattern'
        
        self.optgrp = None
        
    def _on_add_button_click(self):
        self.__paramlist.list.insert(END, '{0}, {1}'.format(self.__center.get_int(), self.__width.get_int()))
        
    def _on_delete_button_click(self):
        self.__paramlist.list.delete(ANCHOR)
        
    def _on_clear_button_click(self):
        self.__paramlist.clear()
        
    def _on_plot_ideal_pattern(self):
        with code_printer:
            center, width = self.beam_data
            self.__topwin.set_ideal_pattern(center, width)
            self.__topwin.plot_ideal_pattern()
        
    @property
    def beam_data(self):
        beamParams = self.__paramlist.list.get(0, END)
        if not beamParams:
            self._app.print_error('An error occurred!')
            self._app.print_tip(
                [
                    {
                        'type':'text',
                        'content':'''This exception happens when the listbox of the beam parameters are empty.
To make a valid ideal pattern, at least one beam should be specified.
'''
                    }
                ]
            )
            return
        center, width = zip(*[map(float, param.split(',')) for param in beamParams])
        return center, width            
예제 #5
0
class FigureBook(Observable, FigureList):
    '''FigureBook is a widget including multiple DataFigure objects and a Tkinter list widget. 
It is used to show the different aspects of a mathematical object.
For example, FigureBook is used to show the envelope, phase, autocorrelation, and FTM of a vector.

FigureBook supports Observable protocal. When some of its properties change, it will notify its observers, 
and its notifyObservers method will pass the following paramters to its observers:
----Grid Properties----
majorGrid:  Bool, indicates that whether the major grid is on or off.
minorGrid:  Bool, indicates the minor grid.
----Axis Limits----
xLim:       the lower and upper limits of the x axis.
yLim:       the lower and upper limits of the y axis.
----Tick----
majorXTick: the x axis' tick of the major grid.
majorYTick: the y axis' ...
minorXTick: the x axis' tick of the minor grid.
minorYTick: the y axis' ...'''
    class GridGroupObserver(object):
        '''This class is used by FigureBook. FigureBook is a class supports observable protocal.
Meanwhile, FigureBook can also observe other objects. This class, GridGroupObserver, can be used to observe
an instance of the GridGroup class.     
    '''
        def __init__(self, figureBook):
            self.__figureBook = figureBook

        def update(self, majorGrid, minorGrid, props=None):
            printCode = True
            if not props:
                props = {'major': {}, 'minor': {}}
            currentFigure = self.__figureBook.currentFigure

            currentFigure.grid(majorGrid, which='major', **props['major'])
            currentFigure.grid(minorGrid, which='minor', **props['minor'])

    class AxisGroupObserver(object):
        def __init__(self, figureBook):
            self.__figureBook = figureBook

        def update(self,
                   xLim,
                   yLim,
                   majorXTick,
                   majorYTick,
                   minorXTick,
                   minorYTick,
                   autoScale=False):
            printCode = True
            currentFigure = self.__figureBook.currentFigure
            if autoScale:
                currentFigure.autoScale()
                return
            lim = list(xLim)
            if currentFigure.isPolar:
                lim = list(deg2rad(lim))
                majorXTick = deg2rad(majorXTick)
                if minorXTick is not None:
                    minorXTick = deg2rad(minorXTick)
            lim.extend(yLim)
            currentFigure.axis(lim)
            for XY in ('X', 'Y'):
                for mm in ('major', 'minor'):
                    currentFigure.setTick(mm + XY + 'Tick',
                                          locals()[mm + XY + 'Tick'])

    class ClearGroupObserver(object):
        def __init__(self, figureBook):
            self.__figureBook = figureBook

        def update(self, delType):
            printCode = True
            if delType == 'all':

                self.__figureBook.clear()
            elif delType == 'sel':
                self.__figureBook.deleteSelLines(idx=None)
            else:
                return

    class LabelGroupObserver(object):
        def __init__(self, figureBook):
            self.__figureBook = figureBook

        def update(self, labelType, labelString):
            nameMap = {
                'title': 'setTitle',
                'xlabel': 'setXLabel',
                'ylabel': 'setYLabel'
            }
            printCode = True
            currentFigure = self.__figureBook.currentFigure
            getattr(currentFigure, nameMap[labelType])(labelString)

    class IndicatorGroupObserver(object):
        def __init__(self, figureBook):
            self.__figureBook = figureBook

        def update(self, meta):
            printCode = True
            if meta['type'] in ('axvspan', 'axhspan'):
                if meta['type'] == 'axvspan':
                    theMin = meta['xmin']
                    theMax = meta['xmax']
                else:
                    theMin = meta['ymin']
                    theMax = meta['ymax']
                props = meta['props']
                #                self.__figureBook.currentFigure.indicators.axvspan(xmin, xmax, **props)
                getattr(self.__figureBook.currentFigure.indicators,
                        meta['type'])(theMin, theMax, **props)
                self.__figureBook.updateIndicatorList()

    class DataFigureObserver(object):
        def __init__(self, figureBook):
            self.__figureBook = figureBook

        def update(self, *args, **kwargs):
            self.__figureBook.notifyObservers(*args, **kwargs)

    def __init__(self, *args, **kwargs):
        '''
nodeName:   The name of this node. Usually set by ModelNode.__setattr__ automatically.
figureMeta: Meta information of figure.
The rest parameters are passed to PanedWindow.__init__.
'''
        nodeName = kwargs.pop('nodeName', '')
        # lock

        super(FigureBook, self).__init__(nodeName=nodeName)

        figureMeta = None if 'figureMeta' not in kwargs \
            else kwargs.pop('figureMeta')
        kwargs['orient'] = HORIZONTAL

        panedWindow = PanedWindow(*args, **kwargs)

        panedWindow.config(sashwidth=4, sashrelief=GROOVE, bg='forestgreen')

        #        figureTabsStyle = Style()
        #        figureTabsStyle.configure('Figure.TNotebook', tabposition='sw')
        #        figureTabs    = Notebook(panedWindow, style='Figure.TNotebook')
        figureTabs = Notebook(panedWindow)

        self.figureTabs = figureTabs
        figureTabs.bind('<<NotebookTabChanged>>', self.onTabChange)
        self.lockAttribute('figureTabs')

        if figureMeta:
            self.makeFigures(figureMeta)

        self.lockElements()

        panedWindow.add(figureTabs, stretch='always')

        listPan = PanedWindow(panedWindow, orient=VERTICAL)
        listPan.config(sashwidth=4, sashrelief=GROOVE, bg='forestgreen')
        panedWindow.add(listPan, stretch='never')

        listFrm = Frame(listPan)
        listPan.add(listFrm, stretch='always')
        Label(listFrm, text='Curves', bg='#b5d6b0').pack(side=TOP, fill=X)
        self.__list = ScrolledList(listFrm, relief=GROOVE)
        self.__list.listConfig(width=20)
        self.__list.listClick = self.onListClick
        self.__list.pack(fill=BOTH, expand=YES)

        listFrm = Frame(listPan)
        listPan.add(listFrm, stretch='never')
        Label(listFrm, text='Indicators', bg='#b5d6b0').pack(side=TOP, fill=X)
        self.__indicatorListbox = ScrolledList(listFrm, relief=GROOVE)
        self.__indicatorListbox.listConfig(width=20)
        self.__indicatorListbox.pack(fill=BOTH, expand=YES)

        with self.attributeLock:
            setMultiAttr(
                self,
                panedWindow=panedWindow,
                gridGroupObserver=self.GridGroupObserver(self),
                axisGroupObserver=self.AxisGroupObserver(self),
                clearGroupObserver=self.ClearGroupObserver(self),
                labelGroupObserver=self.LabelGroupObserver(self),
                indicatorGroupObserver=self.IndicatorGroupObserver(self),
                dataFigureObserver=self.DataFigureObserver(self),
                dataPool=[])

    def append(self, val):
        val.addObserver(self.dataFigureObserver)
        return super(FigureBook, self).append(val)

    def notifyObservers(self, **kwargs):
        cf = self.currentFigure
        props = [
            'majorGrid', 'minorGrid', 'xLim', 'yLim', 'majorXTick',
            'majorYTick', 'minorXTick', 'minorYTick'
        ]
        for p in props:
            if p not in kwargs:
                kwargs[p] = getattr(cf, p)
        if cf.isPolar:
            kwargs['xLim'] = rad2deg(kwargs['xLim'])
            kwargs['majorXTick'] = rad2deg(kwargs['majorXTick'])
            if kwargs['minorXTick'] is not None:
                kwargs['minorXTick'] = rad2deg(kwargs['minorXTick'])
        super(FigureBook, self).notifyObservers(**kwargs)

    def pack(self, *args, **kwargs):
        self.panedWindow.pack(*args, **kwargs)

    def makeFigures(self, figureMeta):
        for meta in figureMeta:
            frm = Frame(self.figureTabs)
            fig = DataFigure(frm, isPolar=meta['polar'])
            self.figureTabs.add(frm, text=meta['name'])
            self.append(fig)

    @property
    def currentFigure(self):
        return self[self.figureTabs.index(CURRENT)]

    @property
    def currentFigureIndex(self):
        return self.figureTabs.index(CURRENT)

    def plot(self, *args, **kwargs):
        try:
            curveName = kwargs.pop('curveName')
        except KeyError:
            curveName = 'curve'

        for fig in self:
            fig.plotFunction(*args, **kwargs)
        self.__list.insert(END, curveName)

        if 'color' in kwargs:
            color = colorMap[kwargs['color']]
        else:
            color = colorMap[self[0].lineObjects[-1][0].get_color()]
        self.__list.itemConfig(END, fg=color)
        self.notifyObservers()

    @Scripting.printable
    def clear(self):
        for fig in self:
            fig.clear()
        self.__list.clear()
        del self.dataPool[:]
        self.currentFigure.indicators.clear()
        self.updateIndicatorList()

    def onTabChange(self, event):
        self.notifyObservers()
        self.updateIndicatorList()

    def onListClick(self, index, label):
        index = int(index)
        for figure in self:
            for line in figure.lineObjects:
                pyplot.setp(line, linewidth=1)
            pyplot.setp(figure.lineObjects[index], linewidth=2)
            figure.update()

    @Scripting.printable
    def exportMatlabScript(self, filename):
        with open(filename, 'w') as file:
            for figure in self:
                print('%Generated by WaveSyn.', 'figure;', sep='\n', file=file)
                for line in figure.lineObjects:
                    params = {}
                    for name in ('xdata', 'ydata', 'color'):
                        params[name] = pyplot.getp(line[0], name)
                    params['func'] = 'polar' if figure.isPolar else 'plot'
                    params['xdata'] = ','.join(
                        (str(i) for i in params['xdata']))
                    params['ydata'] = ','.join(
                        (str(i) for i in params['ydata']))
                    print("{func}([{xdata}], [{ydata}], '{color}');hold on".
                          format(**params),
                          file=file)
                    # To do: Grid

    @Scripting.printable
    def deleteSelLines(self, idx=None):
        if idx is None:
            idx = self.__list.curSelection  # idx is a tuple of strings.
            if len(idx) <= 0:
                return
            if len(idx) > 1:
                raise ValueError, 'Multi-selection is not supported.'
            idx = int(idx[0])
        for fig in self:
            fig.lineObjects[idx][0].remove()
            del fig.lineObjects[idx]
            fig.update()
        self.__list.delete(idx)
        del self.dataPool[idx]

    def updateIndicatorList(self):
        iList = self.__indicatorListbox
        iList.delete(0, END)
        meta = self.currentFigure.indicators.meta
        for m in meta:
            if m['type'] == 'axvspan':
                xmin = m['xmin']
                xmax = m['xmax']
                iList.insert(END, '{0}|{1}/{2}'.format('axvspan', xmin, xmax))
            elif m['type'] == 'axhspan':
                ymin = m['ymin']
                ymax = m['ymax']
                iList.insert(END, '{0}|{1}/{2}'.format('axhspan', ymin, ymax))
예제 #6
0
 def __init__(self, *args, **kwargs):
     self._app = Scripting.root_node
     self.__topwin = kwargs.pop('topwin')
     Group.__init__(self, *args, **kwargs)
     frm = Frame(self)
     
     self.__center = LabeledEntry(frm)
     set_attributes(self.__center,        
         label_text   = 'center(deg)',        
         entry_text   = 0,    
         checker_function   = self._app.check_int,
         entry_width  = 5,    
         label_width  = 10
     )                       
     self.__center.pack(side=TOP)        
     self._app.balloon.bind_widget(self.__center, balloonmsg='Specify the beam center here.')
     
     self.__width = LabeledEntry(frm)
     set_attributes(self.__width,
         label_text   = 'width(deg)',
         entry_text   = 20,
         checker_function   = self._app.check_int,
         entry_width  = 5,
         label_width  = 10
     )
     self.__width.pack(side=TOP)
     self._app.balloon.bind_widget(self.__width, balloonmsg='Specify the beam width here.')
     
     self.__gui_images = []
             
             
     imageAddBtn = ImageTk.PhotoImage(
         file=get_gui_image_path('Pattern_Add_Button.png')
     )
     self.__gui_images.append(imageAddBtn)
     btn = Button(frm, image=imageAddBtn, command=self._on_add_button_click)
     btn.pack(side=LEFT)
     self._app.balloon.bind_widget(btn, balloonmsg='Add new beam to the ideal pattern.')
     
     imageDelBtn = ImageTk.PhotoImage(
         file=get_gui_image_path('Pattern_Del_Button.png')
     )
     self.__gui_images.append(imageDelBtn)
     btn = Button(frm, image=imageDelBtn, command=self._on_delete_button_click)
     btn.pack(side=LEFT)
     self._app.balloon.bind_widget(btn, balloonmsg='Remove the selected beam in the listbox.')
     
     imageClrBtn = ImageTk.PhotoImage(
         file=get_gui_image_path('Pattern_Clear_Button.png')
     )
     self.__gui_images.append(imageClrBtn)
     btn = Button(frm, image=imageClrBtn, command=self._on_clear_button_click)
     btn.pack(side=LEFT)
     self._app.balloon.bind_widget(btn, balloonmsg='Clear the listbox of the beam parameters.')
     
     imagePlotBtn = ImageTk.PhotoImage(
         file=get_gui_image_path('Pattern_Plot_Button.png')
     )
     self.__gui_images.append(imagePlotBtn)
     btn = Button(frm, image=imagePlotBtn, command=self._on_plot_ideal_pattern)
     btn.pack(side=LEFT)
     self._app.balloon.bind_widget(btn, balloonmsg='Plot the ideal pattern.')
     
     frm.pack(side=LEFT, fill=Y)
     
     self.__paramlist = ScrolledList(self)
     self.__paramlist.list.config(height=4, width=10)
     self.__paramlist.pack(side=LEFT)
     self.name = 'Edit Ideal Pattern'
     
     self.optgrp = None
예제 #7
0
    def __init__(self, *args, **kwargs):
        """
nodeName:   The name of this node. Usually set by ModelNode.__setattr__ automatically.
figureMeta: Meta information of figure.
The rest parameters are passed to PanedWindow.__init__.
"""
        nodeName = kwargs.pop("nodeName", "")
        # lock

        super(FigureBook, self).__init__(nodeName=nodeName)

        figureMeta = None if "figureMeta" not in kwargs else kwargs.pop("figureMeta")
        kwargs["orient"] = HORIZONTAL

        panedWindow = PanedWindow(*args, **kwargs)

        panedWindow.config(sashwidth=4, sashrelief=GROOVE, bg="forestgreen")

        #        figureTabsStyle = Style()
        #        figureTabsStyle.configure('Figure.TNotebook', tabposition='sw')
        #        figureTabs    = Notebook(panedWindow, style='Figure.TNotebook')
        figureTabs = Notebook(panedWindow)

        self.figureTabs = figureTabs
        figureTabs.bind("<<NotebookTabChanged>>", self.onTabChange)
        self.lockAttribute("figureTabs")

        if figureMeta:
            self.makeFigures(figureMeta)

        self.lockElements()

        panedWindow.add(figureTabs, stretch="always")

        listPan = PanedWindow(panedWindow, orient=VERTICAL)
        listPan.config(sashwidth=4, sashrelief=GROOVE, bg="forestgreen")
        panedWindow.add(listPan, stretch="never")

        listFrm = Frame(listPan)
        listPan.add(listFrm, stretch="always")
        Label(listFrm, text="Curves", bg="#b5d6b0").pack(side=TOP, fill=X)
        self.__list = ScrolledList(listFrm, relief=GROOVE)
        self.__list.listConfig(width=20)
        self.__list.listClick = self.onListClick
        self.__list.pack(fill=BOTH, expand=YES)

        listFrm = Frame(listPan)
        listPan.add(listFrm, stretch="never")
        Label(listFrm, text="Indicators", bg="#b5d6b0").pack(side=TOP, fill=X)
        self.__indicatorListbox = ScrolledList(listFrm, relief=GROOVE)
        self.__indicatorListbox.listConfig(width=20)
        self.__indicatorListbox.pack(fill=BOTH, expand=YES)

        with self.attributeLock:
            setMultiAttr(
                self,
                panedWindow=panedWindow,
                gridGroupObserver=self.GridGroupObserver(self),
                axisGroupObserver=self.AxisGroupObserver(self),
                clearGroupObserver=self.ClearGroupObserver(self),
                labelGroupObserver=self.LabelGroupObserver(self),
                indicatorGroupObserver=self.IndicatorGroupObserver(self),
                dataFigureObserver=self.DataFigureObserver(self),
                dataPool=[],
            )
예제 #8
0
class FigureBook(Observable, FigureList):
    """FigureBook is a widget including multiple DataFigure objects and a Tkinter list widget. 
It is used to show the different aspects of a mathematical object.
For example, FigureBook is used to show the envelope, phase, autocorrelation, and FTM of a vector.

FigureBook supports Observable protocal. When some of its properties change, it will notify its observers, 
and its notifyObservers method will pass the following paramters to its observers:
----Grid Properties----
majorGrid:  Bool, indicates that whether the major grid is on or off.
minorGrid:  Bool, indicates the minor grid.
----Axis Limits----
xLim:       the lower and upper limits of the x axis.
yLim:       the lower and upper limits of the y axis.
----Tick----
majorXTick: the x axis' tick of the major grid.
majorYTick: the y axis' ...
minorXTick: the x axis' tick of the minor grid.
minorYTick: the y axis' ..."""

    class GridGroupObserver(object):
        """This class is used by FigureBook. FigureBook is a class supports observable protocal.
Meanwhile, FigureBook can also observe other objects. This class, GridGroupObserver, can be used to observe
an instance of the GridGroup class.     
    """

        def __init__(self, figureBook):
            self.__figureBook = figureBook

        def update(self, majorGrid, minorGrid, props=None):
            printCode = True
            if not props:
                props = {"major": {}, "minor": {}}
            currentFigure = self.__figureBook.currentFigure

            currentFigure.grid(majorGrid, which="major", **props["major"])
            currentFigure.grid(minorGrid, which="minor", **props["minor"])

    class AxisGroupObserver(object):
        def __init__(self, figureBook):
            self.__figureBook = figureBook

        def update(self, xLim, yLim, majorXTick, majorYTick, minorXTick, minorYTick, autoScale=False):
            printCode = True
            currentFigure = self.__figureBook.currentFigure
            if autoScale:
                currentFigure.autoScale()
                return
            lim = list(xLim)
            if currentFigure.isPolar:
                lim = list(deg2rad(lim))
                majorXTick = deg2rad(majorXTick)
                if minorXTick is not None:
                    minorXTick = deg2rad(minorXTick)
            lim.extend(yLim)
            currentFigure.axis(lim)
            for XY in ("X", "Y"):
                for mm in ("major", "minor"):
                    currentFigure.setTick(mm + XY + "Tick", locals()[mm + XY + "Tick"])

    class ClearGroupObserver(object):
        def __init__(self, figureBook):
            self.__figureBook = figureBook

        def update(self, delType):
            printCode = True
            if delType == "all":

                self.__figureBook.clear()
            elif delType == "sel":
                self.__figureBook.deleteSelLines(idx=None)
            else:
                return

    class LabelGroupObserver(object):
        def __init__(self, figureBook):
            self.__figureBook = figureBook

        def update(self, labelType, labelString):
            nameMap = {"title": "setTitle", "xlabel": "setXLabel", "ylabel": "setYLabel"}
            printCode = True
            currentFigure = self.__figureBook.currentFigure
            getattr(currentFigure, nameMap[labelType])(labelString)

    class IndicatorGroupObserver(object):
        def __init__(self, figureBook):
            self.__figureBook = figureBook

        def update(self, meta):
            printCode = True
            if meta["type"] in ("axvspan", "axhspan"):
                if meta["type"] == "axvspan":
                    theMin = meta["xmin"]
                    theMax = meta["xmax"]
                else:
                    theMin = meta["ymin"]
                    theMax = meta["ymax"]
                props = meta["props"]
                #                self.__figureBook.currentFigure.indicators.axvspan(xmin, xmax, **props)
                getattr(self.__figureBook.currentFigure.indicators, meta["type"])(theMin, theMax, **props)
                self.__figureBook.updateIndicatorList()

    class DataFigureObserver(object):
        def __init__(self, figureBook):
            self.__figureBook = figureBook

        def update(self, *args, **kwargs):
            self.__figureBook.notifyObservers(*args, **kwargs)

    def __init__(self, *args, **kwargs):
        """
nodeName:   The name of this node. Usually set by ModelNode.__setattr__ automatically.
figureMeta: Meta information of figure.
The rest parameters are passed to PanedWindow.__init__.
"""
        nodeName = kwargs.pop("nodeName", "")
        # lock

        super(FigureBook, self).__init__(nodeName=nodeName)

        figureMeta = None if "figureMeta" not in kwargs else kwargs.pop("figureMeta")
        kwargs["orient"] = HORIZONTAL

        panedWindow = PanedWindow(*args, **kwargs)

        panedWindow.config(sashwidth=4, sashrelief=GROOVE, bg="forestgreen")

        #        figureTabsStyle = Style()
        #        figureTabsStyle.configure('Figure.TNotebook', tabposition='sw')
        #        figureTabs    = Notebook(panedWindow, style='Figure.TNotebook')
        figureTabs = Notebook(panedWindow)

        self.figureTabs = figureTabs
        figureTabs.bind("<<NotebookTabChanged>>", self.onTabChange)
        self.lockAttribute("figureTabs")

        if figureMeta:
            self.makeFigures(figureMeta)

        self.lockElements()

        panedWindow.add(figureTabs, stretch="always")

        listPan = PanedWindow(panedWindow, orient=VERTICAL)
        listPan.config(sashwidth=4, sashrelief=GROOVE, bg="forestgreen")
        panedWindow.add(listPan, stretch="never")

        listFrm = Frame(listPan)
        listPan.add(listFrm, stretch="always")
        Label(listFrm, text="Curves", bg="#b5d6b0").pack(side=TOP, fill=X)
        self.__list = ScrolledList(listFrm, relief=GROOVE)
        self.__list.listConfig(width=20)
        self.__list.listClick = self.onListClick
        self.__list.pack(fill=BOTH, expand=YES)

        listFrm = Frame(listPan)
        listPan.add(listFrm, stretch="never")
        Label(listFrm, text="Indicators", bg="#b5d6b0").pack(side=TOP, fill=X)
        self.__indicatorListbox = ScrolledList(listFrm, relief=GROOVE)
        self.__indicatorListbox.listConfig(width=20)
        self.__indicatorListbox.pack(fill=BOTH, expand=YES)

        with self.attributeLock:
            setMultiAttr(
                self,
                panedWindow=panedWindow,
                gridGroupObserver=self.GridGroupObserver(self),
                axisGroupObserver=self.AxisGroupObserver(self),
                clearGroupObserver=self.ClearGroupObserver(self),
                labelGroupObserver=self.LabelGroupObserver(self),
                indicatorGroupObserver=self.IndicatorGroupObserver(self),
                dataFigureObserver=self.DataFigureObserver(self),
                dataPool=[],
            )

    def append(self, val):
        val.addObserver(self.dataFigureObserver)
        return super(FigureBook, self).append(val)

    def notifyObservers(self, **kwargs):
        cf = self.currentFigure
        props = ["majorGrid", "minorGrid", "xLim", "yLim", "majorXTick", "majorYTick", "minorXTick", "minorYTick"]
        for p in props:
            if p not in kwargs:
                kwargs[p] = getattr(cf, p)
        if cf.isPolar:
            kwargs["xLim"] = rad2deg(kwargs["xLim"])
            kwargs["majorXTick"] = rad2deg(kwargs["majorXTick"])
            if kwargs["minorXTick"] is not None:
                kwargs["minorXTick"] = rad2deg(kwargs["minorXTick"])
        super(FigureBook, self).notifyObservers(**kwargs)

    def pack(self, *args, **kwargs):
        self.panedWindow.pack(*args, **kwargs)

    def makeFigures(self, figureMeta):
        for meta in figureMeta:
            frm = Frame(self.figureTabs)
            fig = DataFigure(frm, isPolar=meta["polar"])
            self.figureTabs.add(frm, text=meta["name"])
            self.append(fig)

    @property
    def currentFigure(self):
        return self[self.figureTabs.index(CURRENT)]

    @property
    def currentFigureIndex(self):
        return self.figureTabs.index(CURRENT)

    def plot(self, *args, **kwargs):
        try:
            curveName = kwargs.pop("curveName")
        except KeyError:
            curveName = "curve"

        for fig in self:
            fig.plotFunction(*args, **kwargs)
        self.__list.insert(END, curveName)

        if "color" in kwargs:
            color = colorMap[kwargs["color"]]
        else:
            color = colorMap[self[0].lineObjects[-1][0].get_color()]
        self.__list.itemConfig(END, fg=color)
        self.notifyObservers()

    @Scripting.printable
    def clear(self):
        for fig in self:
            fig.clear()
        self.__list.clear()
        del self.dataPool[:]
        self.currentFigure.indicators.clear()
        self.updateIndicatorList()

    def onTabChange(self, event):
        self.notifyObservers()
        self.updateIndicatorList()

    def onListClick(self, index, label):
        index = int(index)
        for figure in self:
            for line in figure.lineObjects:
                pyplot.setp(line, linewidth=1)
            pyplot.setp(figure.lineObjects[index], linewidth=2)
            figure.update()

    @Scripting.printable
    def exportMatlabScript(self, filename):
        with open(filename, "w") as file:
            for figure in self:
                print("%Generated by WaveSyn.", "figure;", sep="\n", file=file)
                for line in figure.lineObjects:
                    params = {}
                    for name in ("xdata", "ydata", "color"):
                        params[name] = pyplot.getp(line[0], name)
                    params["func"] = "polar" if figure.isPolar else "plot"
                    params["xdata"] = ",".join((str(i) for i in params["xdata"]))
                    params["ydata"] = ",".join((str(i) for i in params["ydata"]))
                    print("{func}([{xdata}], [{ydata}], '{color}');hold on".format(**params), file=file)
                    # To do: Grid

    @Scripting.printable
    def deleteSelLines(self, idx=None):
        if idx is None:
            idx = self.__list.curSelection  # idx is a tuple of strings.
            if len(idx) <= 0:
                return
            if len(idx) > 1:
                raise ValueError, "Multi-selection is not supported."
            idx = int(idx[0])
        for fig in self:
            fig.lineObjects[idx][0].remove()
            del fig.lineObjects[idx]
            fig.update()
        self.__list.delete(idx)
        del self.dataPool[idx]

    def updateIndicatorList(self):
        iList = self.__indicatorListbox
        iList.delete(0, END)
        meta = self.currentFigure.indicators.meta
        for m in meta:
            if m["type"] == "axvspan":
                xmin = m["xmin"]
                xmax = m["xmax"]
                iList.insert(END, "{0}|{1}/{2}".format("axvspan", xmin, xmax))
            elif m["type"] == "axhspan":
                ymin = m["ymin"]
                ymax = m["ymax"]
                iList.insert(END, "{0}|{1}/{2}".format("axhspan", ymin, ymax))
예제 #9
0
 def __init__(self, *args, **kwargs):
     self._app = Application.instance
     self.__topwin = kwargs.pop('topwin')
     Group.__init__(self, *args, **kwargs)
     frm = Frame(self)
     
     self.__center = ParamItem(frm)
     setMultiAttr(self.__center,        
         labelText   = 'center(deg)',        
         entryText   = 0,    
         checkFunc   = self._app.checkInt,
         entryWidth  = 5,    
         labelWidth  = 10
     )                       
     self.__center.pack(side=TOP)        
     self._app.balloon.bind_widget(self.__center, balloonmsg='Specify the beam center here.')
     
     self.__width = ParamItem(frm)
     setMultiAttr(self.__width,
         labelText   = 'width(deg)',
         entryText   = 20,
         checkFunc   = self._app.checkInt,
         entryWidth  = 5,
         labelWidth  = 10
     )
     self.__width.pack(side=TOP)
     self._app.balloon.bind_widget(self.__width, balloonmsg='Specify the beam width here.')
     
     self.__uiImages = []
             
             
     imageAddBtn = ImageTk.PhotoImage(
         file=uiImagePath('Pattern_Add_Button.png')
     )
     self.__uiImages.append(imageAddBtn)
     btn = Button(frm, image=imageAddBtn, command=self.onAdd)
     btn.pack(side=LEFT)
     self._app.balloon.bind_widget(btn, balloonmsg='Add new beam to the ideal pattern.')
     
     imageDelBtn = ImageTk.PhotoImage(
         file=uiImagePath('Pattern_Del_Button.png')
     )
     self.__uiImages.append(imageDelBtn)
     btn = Button(frm, image=imageDelBtn, command=self.onDel)
     btn.pack(side=LEFT)
     self._app.balloon.bind_widget(btn, balloonmsg='Remove the selected beam in the listbox.')
     
     imageClrBtn = ImageTk.PhotoImage(
         file=uiImagePath('Pattern_Clear_Button.png')
     )
     self.__uiImages.append(imageClrBtn)
     btn = Button(frm, image=imageClrBtn, command=self.onClear)
     btn.pack(side=LEFT)
     self._app.balloon.bind_widget(btn, balloonmsg='Clear the listbox of the beam parameters.')
     
     imagePlotBtn = ImageTk.PhotoImage(
         file=uiImagePath('Pattern_Plot_Button.png')
     )
     self.__uiImages.append(imagePlotBtn)
     btn = Button(frm, image=imagePlotBtn, command=self.onPlotIdealPattern)
     btn.pack(side=LEFT)
     self._app.balloon.bind_widget(btn, balloonmsg='Plot the ideal pattern.')
     
     frm.pack(side=LEFT, fill=Y)
     
     self.__paramlist = ScrolledList(self)
     self.__paramlist.list.config(height=4, width=10)
     self.__paramlist.pack(side=LEFT)
     self.name = 'Edit Ideal Pattern'
     
     self.optgrp = None
예제 #10
0
class EditGroup(Group):
    def __init__(self, *args, **kwargs):
        self._app = Application.instance
        self.__topwin = kwargs.pop('topwin')
        Group.__init__(self, *args, **kwargs)
        frm = Frame(self)
        
        self.__center = ParamItem(frm)
        setMultiAttr(self.__center,        
            labelText   = 'center(deg)',        
            entryText   = 0,    
            checkFunc   = self._app.checkInt,
            entryWidth  = 5,    
            labelWidth  = 10
        )                       
        self.__center.pack(side=TOP)        
        self._app.balloon.bind_widget(self.__center, balloonmsg='Specify the beam center here.')
        
        self.__width = ParamItem(frm)
        setMultiAttr(self.__width,
            labelText   = 'width(deg)',
            entryText   = 20,
            checkFunc   = self._app.checkInt,
            entryWidth  = 5,
            labelWidth  = 10
        )
        self.__width.pack(side=TOP)
        self._app.balloon.bind_widget(self.__width, balloonmsg='Specify the beam width here.')
        
        self.__uiImages = []
                
                
        imageAddBtn = ImageTk.PhotoImage(
            file=uiImagePath('Pattern_Add_Button.png')
        )
        self.__uiImages.append(imageAddBtn)
        btn = Button(frm, image=imageAddBtn, command=self.onAdd)
        btn.pack(side=LEFT)
        self._app.balloon.bind_widget(btn, balloonmsg='Add new beam to the ideal pattern.')
        
        imageDelBtn = ImageTk.PhotoImage(
            file=uiImagePath('Pattern_Del_Button.png')
        )
        self.__uiImages.append(imageDelBtn)
        btn = Button(frm, image=imageDelBtn, command=self.onDel)
        btn.pack(side=LEFT)
        self._app.balloon.bind_widget(btn, balloonmsg='Remove the selected beam in the listbox.')
        
        imageClrBtn = ImageTk.PhotoImage(
            file=uiImagePath('Pattern_Clear_Button.png')
        )
        self.__uiImages.append(imageClrBtn)
        btn = Button(frm, image=imageClrBtn, command=self.onClear)
        btn.pack(side=LEFT)
        self._app.balloon.bind_widget(btn, balloonmsg='Clear the listbox of the beam parameters.')
        
        imagePlotBtn = ImageTk.PhotoImage(
            file=uiImagePath('Pattern_Plot_Button.png')
        )
        self.__uiImages.append(imagePlotBtn)
        btn = Button(frm, image=imagePlotBtn, command=self.onPlotIdealPattern)
        btn.pack(side=LEFT)
        self._app.balloon.bind_widget(btn, balloonmsg='Plot the ideal pattern.')
        
        frm.pack(side=LEFT, fill=Y)
        
        self.__paramlist = ScrolledList(self)
        self.__paramlist.list.config(height=4, width=10)
        self.__paramlist.pack(side=LEFT)
        self.name = 'Edit Ideal Pattern'
        
        self.optgrp = None
        
    def onAdd(self):
        self.__paramlist.list.insert(END, '{0}, {1}'.format(self.__center.getInt(), self.__width.getInt()))
        
    def onDel(self):
        self.__paramlist.list.delete(ANCHOR)
        
    def onClear(self):
        self.__paramlist.clear()
        
    def onPlotIdealPattern(self):
        printCode   = True
        center, width = self.beamData
        self.__topwin.setIdealPattern(center, width)
        self.__topwin.plotIdealPattern()
        
    @property
    def beamData(self):
        beamParams = self.__paramlist.list.get(0, END)
        if not beamParams:
            self._app.printError('An error occurred!')
            self._app.printTip(
                [
                    {
                        'type':'text',
                        'content':'''This exception happens when the listbox of the beam parameters are empty.
To make a valid ideal pattern, at least one beam should be specified.
'''
                    }
                ]
            )
            return
        center, width = zip(*[map(float, param.split(',')) for param in beamParams])
        return center, width