Example #1
0
    def __init__(self, parent=None, id=-1, xlabel=AxisInfos("Delay",du["time"]), ylabel=AxisInfos("Distance",du["length"]), xscale="linear", yscale="linear"):
        """
        
            Initialization.
            
            Parameters:
                parent    -    parent window (wx.Window)
                id        -    id (int)
                xlabel    -    label and units of abscissa axis (terapy.axedit.AxisInfos)
                ylabel    -    label and units of ordinate axis (terapy.axedit.AxisInfos)
                xscale    -    abscissa scale type (linear or log)
                yscale    -    ordinate scale type (linear or log)
        
        """
        PlotPanel.__init__(self,parent,id)
        PlotCanvas.__init__(self,parent,id)
        
        fig = self.get_figure()
        self.axes = fig.gca()
        self.axes.grid(True)
        self.axes.set_autoscale_on(True)
        self.axes.set_xscale(xscale)
        self.axes.set_yscale(yscale)
        
        # must make a copy of labels, otherwise same instance is used for every plot
        xlabel = xlabel.copy()
        ylabel = ylabel.copy()

        # re-format axis units into current default units 
        xlabel.units = FormatUnits(xlabel.units)
        ylabel.units = FormatUnits(ylabel.units)
        for x in [xlabel,ylabel]: x.units._magnitude = 1.0
        self.labels = [xlabel, ylabel]
        self.SetLabels()
        
        self.dim = 2
        self.set_zoom(False)
        self.set_location(False)
        self.set_selection(False)
        # generate colormap
        cdict = {'red': ((0.0, 0.0, 0.0),(0.5, 1.0, 1.0),(1.0, 1.0, 0.0)),
                'green': ((0.0, 0.0, 0.0),(0.5, 1.0, 1.0),(1.0, 0.0, 0.0)),
                'blue': ((0.0, 0.0, 1.0),(0.5, 1.0, 1.0),(1.0, 0.0, 0.0))}
        self._2d_cmap = LinearSegmentedColormap('my_colormap',cdict,256)        
        cdict = {'red': ((0.0, 0.0, 1.0),(1.0, 1.0, 0.0)),
                'green': ((0.0, 0.0, 1.0),(1.0, 0.0, 0.0)),
                'blue': ((0.0, 0.0, 1.0),(1.0, 0.0, 0.0))}
        self._2d_cmap_pos = LinearSegmentedColormap('my_colormap_pos',cdict,256)
        
        cdict = {'red': ((0.0, 0.0, 0.0),(1.0, 1.0, 0.0)),
                'green': ((0.0, 0.0, 0.0),(1.0, 1.0, 0.0)),
                'blue': ((0.0, 0.0, 1.0),(1.0, 1.0, 0.0))}
        self._2d_cmap_neg = LinearSegmentedColormap('my_colormap_neg',cdict,256)

        # send color change event to notify history from change
        pub.sendMessage("plot.color_change")

        self.Bind(wx.EVT_LEFT_DCLICK, self.OnLeftDblClick, self)
Example #2
0
 def __init__(self, parent=None, id=-1, xlabel=AxisInfos("Delay",du["time"]), ylabel=AxisInfos("Signal",du["voltage"]), xscale="linear", yscale="linear"):
     """
     
         Initialization.
         
         Parameters:
             parent    -    parent window (wx.Window)
             id        -    id (int)
             xlabel    -    label and units of abscissa axis (terapy.axedit.AxisInfos)
             ylabel    -    label and units of ordinate axis (terapy.axedit.AxisInfos)
             xscale    -    abscissa scale type (linear or log)
             yscale    -    ordinate scale type (linear or log)
     
     """
     PlotPanel.__init__(self,parent,id)
     PlotCanvas.__init__(self,parent,id)
     
     fig = self.get_figure()
     self.axes = fig.gca()
     self.axes.grid(True)
     self.axes.set_autoscale_on(True)
     self.axes.set_xscale(xscale)
     self.axes.set_yscale(yscale)
     
     # must make a copy of labels, otherwise same instance is used for every plot
     xlabel = xlabel.copy()
     ylabel = ylabel.copy()
     
     # re-format axis units into current default units 
     xlabel.units = FormatUnits(xlabel.units)
     ylabel.units = FormatUnits(ylabel.units)
     for x in [xlabel,ylabel]: x.units._magnitude = 1.0
     self.labels = [xlabel, ylabel]
     self.SetLabels()
     
     self.Bind(wx.EVT_LEFT_DCLICK, self.OnLeftDblClick, self)
     self.Bind(wx.EVT_RIGHT_DOWN, self.OnRightClick, self)
Example #3
0
    def __init__(self, parent = None, dim = 1):
        """
        
            Initialization.
            
            Parameters:
                parent    -    parent window (wx.Window)
                dim       -    dimension (int)
        
        """
        wx.Panel.__init__(self, parent)
        from terapy.core import left_width
        self.bank = None
        self.dim = dim
        
        # filter list
        self.list = FilterList(self, -1, style=wx.LC_REPORT|wx.LC_NO_HEADER)
        self.list.SetMinSize((left_width,-1))
        
        self.list.InsertColumn(0,"Name")
        self.img_list = wx.ImageList(16,16)
        from terapy.core.tooltip import ToolTip
        ToolTip("Double click  ->  Change properties\nRight click   ->  Menu\nShift+Left    ->  Enable/disable","Usage",self.list)
        
        modules = GetModules(self.dim)
        for x in modules:
            self.img_list.Add(x().get_icon())
        
        self.list.SetImageList(self.img_list,wx.IMAGE_LIST_SMALL)
        
        # window preview
        self.label_plot = wx.StaticText(self, -1, "Apodization window")
        self.plot_filter = PlotPanel(self, -1)
        self.plot_filter.SetMinSize((max([left_width-50,0]),100))

        # further controls
        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.sizer.Add(self.list, 1, wx.EXPAND|wx.ALL, 2)
        hbox = wx.BoxSizer(wx.HORIZONTAL)
        self.button_up = wx.BitmapButton(self, -1, wx.Image(icon_path + "go-up.png").ConvertToBitmap())
        self.button_down = wx.BitmapButton(self, -1, wx.Image(icon_path + "go-down.png").ConvertToBitmap())
        self.button_add = wx.BitmapButton(self, -1, wx.Image(icon_path + "list-add.png").ConvertToBitmap())
        self.button_remove = wx.BitmapButton(self, -1, wx.Image(icon_path + "list-remove.png").ConvertToBitmap())
        hbox.Add(self.button_up, 0, wx.EXPAND|wx.ALL, 2)
        hbox.Add(self.button_down, 0, wx.EXPAND|wx.ALL, 2)
        hbox.Add(self.button_add, 0, wx.EXPAND|wx.ALL, 2)
        hbox.Add(self.button_remove, 0, wx.EXPAND|wx.ALL, 2)
        self.sizer.Add(hbox, 0, wx.EXPAND|wx.LEFT|wx.RIGHT, 2)
        self.sizer.Add(self.label_plot, 0, wx.EXPAND|wx.TOP, 2)
        self.sizer.Add(self.plot_filter, 0, wx.EXPAND|wx.TOP, 2)
        
        # bindings
        self.Bind(wx.EVT_LIST_ITEM_RIGHT_CLICK, self.OnFilterListRightClick, self.list)
        self.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.OnFilterDoubleClick, self.list)
        self.list.Bind(wx.EVT_LIST_BEGIN_DRAG, self.OnStartDrag, self.list)
        self.list.Bind(wx.EVT_RIGHT_DOWN, self.OnFilterListRightClick)
        self.list.Bind(wx.EVT_LEFT_DOWN, self.OnFilterLeftClick)
        self.Bind(wx.EVT_BUTTON, lambda x:self.OnMove(-1), self.button_up)
        self.Bind(wx.EVT_BUTTON, lambda x:self.OnMove(+1), self.button_down)
        self.Bind(wx.EVT_BUTTON, self.OnFilterListRightClick, self.button_add)
        self.Bind(wx.EVT_BUTTON, self.OnRemoveFilter, self.button_remove)
        
        # pubsub bindings
        pub.subscribe(self.SetReference, "history.set_reference")
        pub.subscribe(self.SetFilterBank, "plot.set_filters")
        pub.subscribe(self.EnableControl, "plot.enable_filters")
        pub.subscribe(self.OnFilterUpdate, "plot.apply_filters")
        pub.subscribe(self.UpdateFilterDisplay, "plot.switch_canvas")
        pub.subscribe(self.RefreshFilters, "filter.change")
        pub.subscribe(self.OnSaveDefaultFilters, "filter.save_default")
        
        # drag and drop enable
        self.list.SetDropTarget(FilterDrop(self.OnEndDrag))
        
        # filter preview
        figFi = self.plot_filter.get_figure()
        axeFi =  figFi.gca()
        axeFi.get_xaxis().set_visible(False)
        axeFi.get_yaxis().set_visible(False)
        self.plot_filter.set_zoom(False)
        self.plot_filter.set_selection(False)
        self.plot_filter.set_location(False)
        self.plot_filter.set_cursor(False)
        self.plot_filter.set_crosshairs(False)
        self.line_filter = Line2D([-1.5,-1,-1,1,1,1.5],[0,0,1,1,0,0])
        axeFi.add_line(self.line_filter)
        axeFi.add_line(Line2D([-1,-1],[-1,2],ls='--',color='k'))
        axeFi.add_line(Line2D([1,1],[-1,2],ls='--',color='k'))
        self.line_filter.set_visible(True)
        axeFi.set_xlim(-1.5,1.5)
        axeFi.set_ylim(-0.5,1.5)
        self.plot_filter.draw()
        
        # display fitting stuff 
        self.SetAutoLayout(True)
        self.SetSizer(self.sizer)
        self.sizer.Fit(self)
        self.sizer.SetSizeHints(self)
Example #4
0
class FilterControl(wx.Panel):
    """
    
        Filter bank control widget
    
    """
    def __init__(self, parent = None, dim = 1):
        """
        
            Initialization.
            
            Parameters:
                parent    -    parent window (wx.Window)
                dim       -    dimension (int)
        
        """
        wx.Panel.__init__(self, parent)
        from terapy.core import left_width
        self.bank = None
        self.dim = dim
        
        # filter list
        self.list = FilterList(self, -1, style=wx.LC_REPORT|wx.LC_NO_HEADER)
        self.list.SetMinSize((left_width,-1))
        
        self.list.InsertColumn(0,"Name")
        self.img_list = wx.ImageList(16,16)
        from terapy.core.tooltip import ToolTip
        ToolTip("Double click  ->  Change properties\nRight click   ->  Menu\nShift+Left    ->  Enable/disable","Usage",self.list)
        
        modules = GetModules(self.dim)
        for x in modules:
            self.img_list.Add(x().get_icon())
        
        self.list.SetImageList(self.img_list,wx.IMAGE_LIST_SMALL)
        
        # window preview
        self.label_plot = wx.StaticText(self, -1, "Apodization window")
        self.plot_filter = PlotPanel(self, -1)
        self.plot_filter.SetMinSize((max([left_width-50,0]),100))

        # further controls
        self.sizer = wx.BoxSizer(wx.VERTICAL)
        self.sizer.Add(self.list, 1, wx.EXPAND|wx.ALL, 2)
        hbox = wx.BoxSizer(wx.HORIZONTAL)
        self.button_up = wx.BitmapButton(self, -1, wx.Image(icon_path + "go-up.png").ConvertToBitmap())
        self.button_down = wx.BitmapButton(self, -1, wx.Image(icon_path + "go-down.png").ConvertToBitmap())
        self.button_add = wx.BitmapButton(self, -1, wx.Image(icon_path + "list-add.png").ConvertToBitmap())
        self.button_remove = wx.BitmapButton(self, -1, wx.Image(icon_path + "list-remove.png").ConvertToBitmap())
        hbox.Add(self.button_up, 0, wx.EXPAND|wx.ALL, 2)
        hbox.Add(self.button_down, 0, wx.EXPAND|wx.ALL, 2)
        hbox.Add(self.button_add, 0, wx.EXPAND|wx.ALL, 2)
        hbox.Add(self.button_remove, 0, wx.EXPAND|wx.ALL, 2)
        self.sizer.Add(hbox, 0, wx.EXPAND|wx.LEFT|wx.RIGHT, 2)
        self.sizer.Add(self.label_plot, 0, wx.EXPAND|wx.TOP, 2)
        self.sizer.Add(self.plot_filter, 0, wx.EXPAND|wx.TOP, 2)
        
        # bindings
        self.Bind(wx.EVT_LIST_ITEM_RIGHT_CLICK, self.OnFilterListRightClick, self.list)
        self.Bind(wx.EVT_LIST_ITEM_ACTIVATED, self.OnFilterDoubleClick, self.list)
        self.list.Bind(wx.EVT_LIST_BEGIN_DRAG, self.OnStartDrag, self.list)
        self.list.Bind(wx.EVT_RIGHT_DOWN, self.OnFilterListRightClick)
        self.list.Bind(wx.EVT_LEFT_DOWN, self.OnFilterLeftClick)
        self.Bind(wx.EVT_BUTTON, lambda x:self.OnMove(-1), self.button_up)
        self.Bind(wx.EVT_BUTTON, lambda x:self.OnMove(+1), self.button_down)
        self.Bind(wx.EVT_BUTTON, self.OnFilterListRightClick, self.button_add)
        self.Bind(wx.EVT_BUTTON, self.OnRemoveFilter, self.button_remove)
        
        # pubsub bindings
        pub.subscribe(self.SetReference, "history.set_reference")
        pub.subscribe(self.SetFilterBank, "plot.set_filters")
        pub.subscribe(self.EnableControl, "plot.enable_filters")
        pub.subscribe(self.OnFilterUpdate, "plot.apply_filters")
        pub.subscribe(self.UpdateFilterDisplay, "plot.switch_canvas")
        pub.subscribe(self.RefreshFilters, "filter.change")
        pub.subscribe(self.OnSaveDefaultFilters, "filter.save_default")
        
        # drag and drop enable
        self.list.SetDropTarget(FilterDrop(self.OnEndDrag))
        
        # filter preview
        figFi = self.plot_filter.get_figure()
        axeFi =  figFi.gca()
        axeFi.get_xaxis().set_visible(False)
        axeFi.get_yaxis().set_visible(False)
        self.plot_filter.set_zoom(False)
        self.plot_filter.set_selection(False)
        self.plot_filter.set_location(False)
        self.plot_filter.set_cursor(False)
        self.plot_filter.set_crosshairs(False)
        self.line_filter = Line2D([-1.5,-1,-1,1,1,1.5],[0,0,1,1,0,0])
        axeFi.add_line(self.line_filter)
        axeFi.add_line(Line2D([-1,-1],[-1,2],ls='--',color='k'))
        axeFi.add_line(Line2D([1,1],[-1,2],ls='--',color='k'))
        self.line_filter.set_visible(True)
        axeFi.set_xlim(-1.5,1.5)
        axeFi.set_ylim(-0.5,1.5)
        self.plot_filter.draw()
        
        # display fitting stuff 
        self.SetAutoLayout(True)
        self.SetSizer(self.sizer)
        self.sizer.Fit(self)
        self.sizer.SetSizeHints(self)
        
    def RefreshFilters(self, inst=None):
        """
        
            Refresh displayed filter list.
            
            Parameters:
                inst    -    pubsub event data (FilterBank)
        
        """
        if inst!=None:
            if inst!=self.bank: return
        # store currently selected items
        sels = []
        itm = self.list.GetFirstSelected()
        while itm>-1:
            sels.append(itm)
            itm = self.list.GetNextSelected(itm)
        # rebuild filter list
        modules = GetModules(self.dim)
        self.list.DeleteAllItems()
        if not(isinstance(self.bank,FilterBank)): return
        for ft in self.bank.filters:
            if modules.count(ft.__class__)>0:
                n = modules.index(ft.__class__)
                self.list.InsertImageStringItem(self.list.GetItemCount(),ft.name,n)
                f = self.list.GetItemFont(self.list.GetItemCount()-1)
                f.SetPointSize(10)
                if ft.is_active:
                    f.SetStyle(wx.FONTSTYLE_NORMAL)
                else:
                    f.SetStyle(wx.FONTSTYLE_ITALIC)
                self.list.SetItemFont(self.list.GetItemCount()-1,f)
        # select previously selected items
        for x in sels:
            self.list.Select(x, True)
    
    def SetFilterBank(self, inst):
        """
        
            Set filter bank through pubsub.
            
            Parameters:
                inst    -    pubsub event data (FilterBank)
        
        """
        self.bank = inst
        self.RefreshFilters()
    
    def EnableControl(self, inst):
        """
        
            Set control to given state (through pubsub)
            
            Parameters:
                inst    -    pubsub event data (bool)
        
        """
        self.Enable(inst)
    
    def LoadFilterList(self, event=None, fname=""):
        """
        
            Load filter bank from given file or open dialog box.
            Set result to displayed filter bank.
            
            Parameters:
                event    -    wx.Event
                fname    -    file name (str, open dialog box if empty)
        
        """
        if fname=="":
            dlg = wx.FileDialog(self, "Choose input file", os.getcwd(),"", "Configuration file (*.ini)|*.ini|All files (*.*)|*.*", wx.OPEN)
            if dlg.ShowModal() != wx.ID_OK:
                dlg.Destroy()
                return
            fname = dlg.GetPath()
            dlg.Destroy()
        
        self.bank.LoadFilterList(fname)
        self.RefreshFilters()
        self.OnFilterUpdate()
        
    def SaveFilterList(self, event=None, fname=""):
        """
        
            Save current filter list to given file.
            
            Parameters:
                event    -    wx.Event
                fname    -    file name (str)
        
        """
        dlg = wx.TextEntryDialog(self,message="Filter bank name",defaultValue=self.bank.name)
        if dlg.ShowModal()!=wx.ID_OK:
            dlg.Destroy()
            return
        self.bank.name = dlg.GetValue()
        dlg.Destroy()
        
        if fname=="":
            dlg = wx.FileDialog(self, "Choose output file", os.getcwd(),"", "Configuration file (*.ini)|*.ini|All files (*.*)|*.*", wx.SAVE)
            if dlg.ShowModal() != wx.ID_OK:
                dlg.Destroy()
                return
            fname = dlg.GetPath()
            dlg.Destroy()
        self.bank.SaveFilterList(fname)
    
    def OnSaveDefaultFilters(self, inst=None):
        """
        
            Save current list of filters as default.
            
            Parameters:
                inst    -    pubsub argument (not used)
        
        """
        from terapy.core import filter_file
        if filter_file==None:
            pub.sendMessage("set_status_text",inst="No filter file defined. Can't save!")
            return # no filter file defined, can't save
        if self.bank==None:
            pub.sendMessage("set_status_text",inst="No active filter bank. Can't save!")
            return # filter control is empty, as no filter bank is active
        
        old_name = self.bank.name
        self.bank.name = "Default filter bank"
        
        try:
            self.bank.SaveFilterList(filter_file)
            pub.sendMessage("set_status_text",inst="Default filters saved.")
        except:
            pub.sendMessage("set_status_text",inst="Can't write in filter file!")
        
        self.bank.name = old_name

    
    def OnFilterUpdate(self, inst=None):
        """
        
            Actions triggered by changes in filter bank.
            
            Parameters:
                inst    -    pubsub event data or wx.Event
        
        """
        self.bank.RecomputeReference()
        for x in self.bank.children:
            x.RecomputeReference()
        pub.sendMessage("filter.change", inst=self.bank)
    
    def OnFilterLeftClick(self, event = None):
        """
        
            Actions triggered by left mouse button click on filter list.
            
            Parameters:
                event    -    wx.Event
        
        """
        # either rename or enable/disable filter (if shift key is pressed)
        itm = self.list.HitTest(event.GetPosition())[0]
        if event.ShiftDown() and itm>-1: # enable/disable shift-clicked filter 
            self.OnEnableFilter(itm)
        else:
            event.Skip()
    
    def OnFilterDoubleClick(self, event = None):
        """
        
            Actions triggered by left double click on filter list.
            
            Parameters:
                event    -    wx.Event
        
        """
        # change filter properties
        if self.bank.filters[event.GetIndex()].set_filter(self):
            self.UpdateFilterDisplay()
            self.OnFilterUpdate()
        event.Skip()
    
    def OnMove(self, disp):
        """
        
            Move selected filter by given amount within list.
            
            Parameters:
                disp    -    displacement (int)
        
        """
        # move item by 'disp' positions in the list
        pos = self.list.GetFirstSelected()
        if pos+disp<0 or pos+disp>self.list.GetItemCount()-1 or pos<0: return
        itm = self.list.GetItem(pos)
        itm.SetId(pos+disp)
        self.list.DeleteItem(pos)
        self.list.InsertItem(itm)
        self.list.Select(pos+disp, True)
        p1 = self.bank.filters[pos]
        self.bank.filters[pos] = self.bank.filters[pos+disp]
        self.bank.filters[pos+disp] = p1
        self.UpdateFilterDisplay()
        self.OnFilterUpdate()
        
    def OnStartDrag(self, event = None):
        """
        
            Actions initiating a drag and drop event.
            
            Parameters:
                event    -    wx.Event
        
        """
        ds = wx.DropSource(self.list)
        p = FilterDragObject()
        p.SetData("ft")
        ds.SetData(p)
        ds.DoDragDrop(flags=wx.Drag_DefaultMove)
        
    def OnEndDrag(self, x, y, data):
        """
        
        Actions after a drag and drop event.
            
        Parameters:
            x,y    -    drop position (int)
            data   -    dropped data (str)
                        not used - assume instead that selected list item has been dragged
        
        """
        ditm = self.list.HitTest((x,y))[0]
        oitm = self.list.GetFirstSelected()
        self.OnMove(ditm-oitm)
    
    def OnFilterListRightClick(self, event = None):
        """
        
            Actions following a right mouse button click.
            
            Parameters:
                event    -    wx.Event
        
        """
        if self.bank==None: return
        # pop up menu with filter-related actions
        menuAdd = wx.Menu()
        modules = GetModules(self.dim)
        for n in range(len(modules)): # build Add menu
            md = modules[n]()
            if md.is_visible:
                if self.bank.HasReference() and md.is_reference:
                    # don't allow adding 2 reference filters
                    pass
                else:
                    mitem = wx.MenuItem(menuAdd,id=wx.NewId(),text=modules[n].__extname__)
                    mitem.SetBitmap(modules[n]().get_icon())
                    menuAdd.AppendItem(mitem)
                    self.Bind(wx.EVT_MENU, functools.partial(self.OnAddFilter,md), id=mitem.Id)
        
        if event.EventType == wx.EVT_BUTTON.evtType[0]: # menu can be triggered by pressing + button
            # in this case, only the Add menu should appear
            self.menuPosition = self.button_add.Position
            menu = menuAdd
        else:
            menu = wx.Menu()
            self.menuPosition = event.GetPosition()
            menu.AppendSubMenu(menuAdd,"&Add...")
            mitem = menu.Append(id=wx.NewId(),text="&Remove")
            self.Bind(wx.EVT_MENU, self.OnRemoveFilter, id=mitem.Id)
            # if right-click is above an item, add enable/disable menu option
            itm = self.list.HitTest(event.GetPosition())[0]
            if itm>-1:
                if self.bank.filters[itm].is_active:
                    mitem = menu.Append(id=wx.NewId(), text="&Disable")
                else:
                    mitem = menu.Append(id=wx.NewId(), text="&Enable")
                self.Bind(wx.EVT_MENU, lambda x: self.OnEnableFilter(itm), id=mitem.Id)
            # Load/Save filter list
            mitem = menu.Append(id=wx.NewId(),text="&Load filter list")
            self.Bind(wx.EVT_MENU, self.LoadFilterList, id=mitem.Id)
            mitem = menu.Append(id=wx.NewId(),text="&Save filter list")
            self.Bind(wx.EVT_MENU, self.SaveFilterList, id=mitem.Id)
        self.PopupMenu(menu)
    
    def OnEnableFilter(self, pos):
        """
        
            Enable/Disable filter at given position.
            
            Parameters:
                pos    -    position (int)
        
        """
        # enable/disable filter
        state = not(self.bank.filters[pos].is_active)
        self.bank.filters[pos].is_active = state
        f = self.list.GetItemFont(pos)
        f.SetPointSize(10)
        if state:
            f.SetStyle(wx.FONTSTYLE_NORMAL)
        else:
            f.SetStyle(wx.FONTSTYLE_ITALIC)
        self.list.SetItemFont(pos,f)
        self.UpdateFilterDisplay()
        self.OnFilterUpdate()
    
    def OnRemoveFilter(self, event = None):
        """
        
            Actions following a filter delete request
            
            Parameters:
                event    -    wx.Event
        
        """
        # remove selected filter
        pos = self.list.GetFirstSelected()
        sels = []
        while pos>-1:
            sels.append(pos)
            pos = self.list.GetNextSelected(pos)
        for pos in sels[-1::-1]:
            ft = self.bank.filters.pop(pos)
            self.list.DeleteItem(pos)
            if ft.is_reference:
                pub.sendMessage("filter.clear_reference", inst=ft.source) # send clear reference message with ref array
        if len(sels)>0:
            # update display
            self.UpdateFilterDisplay()
            self.OnFilterUpdate()
    
    def OnAddFilter(self, ft, event = None):
        """
        
            Add given filter to current filter bank.
            
            Parameters:
                ft    -    filter (Filter)
                event -    wx.Event
        
        """
        # add filter selected in menu
        modules = GetModules(self.dim)
        idx = modules.index(ft.__class__)
        if ft.set_filter(self):
            # if filter 'set' procedure succeeded, add filter to list in adequate position
            itm = self.list.HitTest(self.menuPosition)
            if itm[0]==-1: # test if click didn't occur above an item
                pos = self.list.GetItemCount()
                if self.list.GetFirstSelected()>-1: # if not, test if one list item is selected
                    pos = self.list.GetFirstSelected()
            else: # otherwise, insert before clicked item
                pos = itm[0]
            self.list.InsertImageStringItem(pos,ft.__extname__,idx)
            self.bank.InsertFilter(pos, ft)
        # update reference plot if necessary, update display
        self.UpdateFilterDisplay()
        self.OnFilterUpdate()
    
    def SetReference(self, inst):
        """
        
            Set given array as reference.
             
            Parameters:
                inst    -    data array (DataArray)
                              or pubsub event data
        
        """
        # set reference from external source (i.e. not from filter control itself)
        # will act on currently displayed filter bank
        if not(isinstance(inst,DataArray)):
            inst = inst.data
        
        # search for existing reference
        ref_ft = None
        for ft in self.bank.filters:
            if ft.is_reference:
                ref_ft = ft
                break
        
        # if no reference, search for adequate filter and add to filter list
        if ref_ft==None:
            modules = GetModules(self.dim)
            # build list of potential filters
            flist = []
            for n in range(len(modules)):
                ft = modules[n]()
                if ft.is_reference:
                    flist.append(ft)
            if len(flist)==1: # if only one type exists, add this one
                flist[0].source = inst
                self.bank.AppendFilter(flist[0])
            elif len(flist)>1: # otherwise, propose a list to the user
                dlg = ReferenceFilterSelectionDialog(flist = flist)
                if dlg.ShowModal() == wx.ID_OK:
                    idx = dlg.GetValue()
                    flist[idx].source = inst
                    self.bank.AppendFilter(flist[idx])
        else:
            ref_ft.source = inst
        
    def RemoveReference(self, inst=None):
        """
        
            Remove reference filter, is any.
            
            Parameters:
                inst    -    pubsub event data
        
        """
        # remove reference filter
        if self.bank.RemoveReference() != None:
            self.RefreshFilters()
    
    def UpdateFilterDisplay(self, inst=None):
        """
        
            Update display of apodization window.
            
            Parameters:
                inst    -    pubsub event data
        
        """
        # update apodization filter preview
        arr = DataArray(shape=[201])
        arr.coords = [np.linspace(-1.0,1.0,201)]
        arr.data = np.ones(201) 
        is_before_ft = True
        if isinstance(self.bank,FilterBank):
            for ft in self.bank.filters:
                if ft.is_pre_filter and is_before_ft and ft.is_active:
                    ft.apply_filter(arr)
                if ft.is_transform:
                    is_before_ft = False
        data_x = np.concatenate(([-1.5,-1.0], arr.coords[0], [1.0,1.5]))
        data_y = np.concatenate(([0.0,0.0], arr.data, [0.0,0.0]))
        self.line_filter.set_data(data_x, data_y)
        self.plot_filter.draw()