Example #1
0
 def savePrefs(self):
     """Save prefs to a preferences instance"""
     self.applyPrefs(self.prefsdialog.getValues())
     self.preferences = Preferences('DNATool2', {})
     for key in self.defaultprefs:
         self.preferences.set(key, self.__dict__[key])
     return
Example #2
0
 def __init__(self, parent=None, parentframe=None, DB=None, mode=None):
     """Instantiate class and check presence of DB data"""
     self.parent = parent
     if not self.parent:
         Frame.__init__(self)
         self.main = self.master
         self.main.title('PEAT Comparator')
         if DB == None:
             DB = self.openDB()
             if DB == None: return
     elif parentframe:
         self.main = Frame(master=parentframe)
         self.main.pack(fill=BOTH)
     else:
         self.main = Toplevel()
         self.main.title('Select Dataset')
         self.main.geometry('+300+200')
     if not self.parent:
         from Prefs import Preferences
         self.preferences = Preferences('PEAT', {})
     else:
         self.preferences = self.parent.preferences
     self.DB = DB
     self.Opt = Options(redraw=None)
     self.doGUI()
     return
Example #3
0
 def loadPrefs(self):
     """Load prefs from a preferences instance"""
     self.preferences = Preferences('DNATool2', {})
     temp = {}
     for key in self.defaultprefs:
         if not key in self.preferences.prefs:
             self.preferences.set(key, self.defaultprefs[key])
         temp[key] = self.preferences.get(key)
     self.applyPrefs(temp)
     return
Example #4
0
 def savePrefs(self):
     """Save prefs to a preferences instance"""
     self.applyPrefs(self.prefsdialog.getValues())
     self.preferences = Preferences('DNATool2',{})
     for key in self.defaultprefs:
         self.preferences.set(key, self.__dict__[key])
     return
Example #5
0
 def __init__(self, parent=None, parentframe=None, DB=None, mode=None):
     """Instantiate class and check presence of DB data"""
     self.parent = parent
     if not self.parent:
         Frame.__init__(self)
         self.main=self.master
         self.main.title('PEAT Comparator')
         if DB == None:
             DB = self.openDB()
             if DB==None: return
     elif parentframe:
         self.main = Frame(master=parentframe)
         self.main.pack(fill=BOTH)
     else:
         self.main=Toplevel()
         self.main.title('Select Dataset')
         self.main.geometry('+300+200')
     if not self.parent:
         from Prefs import Preferences
         self.preferences=Preferences('PEAT',{})
     else:
         self.preferences=self.parent.preferences        
     self.DB = DB
     self.Opt = Options(redraw=None)
     self.doGUI()
     return
Example #6
0
 def loadPrefs(self):
     """Load prefs from a preferences instance"""
     self.preferences = Preferences('DNATool2',{})
     temp = {}
     for key in self.defaultprefs:
         if not key in self.preferences.prefs:
             self.preferences.set(key, self.defaultprefs[key])
         temp[key] = self.preferences.get(key)
     self.applyPrefs(temp)
     return
Example #7
0
    def __init__(self, parent=None, data=None, datafile=None):
        "Initialize the application."
        self.parent = parent

        #If there is data to be loaded, show the dialog first
        if not self.parent:
            Frame.__init__(self)
            self.tablesapp_win = self.master

        else:
            self.tablesapp_win = Toplevel()

        # Get platform into a variable
        import platform
        self.currplatform = platform.system()
        if not hasattr(self, 'defaultsavedir'):
            self.defaultsavedir = os.getcwd()

        self.preferences = Preferences('TablesApp', {'check_for_update': 1})
        self.loadprefs()
        self.tablesapp_win.title('Tables Application')
        self.tablesapp_win.geometry('+200+200')
        self.x_size = 800
        self.y_size = 600
        self.createMenuBar()
        self.apptoolBar = ToolBar(self.tablesapp_win, self)
        self.apptoolBar.pack(fill=BOTH, expand=NO)
        #add find bar
        #self.createSearchBar()

        if data != None:
            self.data = data
            self.new_project(data)
        elif datafile != None:
            self.open_project(datafile)
        else:
            self.new_project()

        self.tablesapp_win.protocol('WM_DELETE_WINDOW', self.quit)
        return
    def __init__(self, parent=None, data=None, datafile=None):
        "Initialize the application."
        self.parent = parent

        # If there is data to be loaded, show the dialog first
        if not self.parent:
            Frame.__init__(self)
            self.tablesapp_win = self.master

        else:
            self.tablesapp_win = Toplevel()

        # Get platform into a variable
        import platform

        self.currplatform = platform.system()
        if not hasattr(self, "defaultsavedir"):
            self.defaultsavedir = os.getcwd()

        self.preferences = Preferences("TablesApp", {"check_for_update": 1})
        self.loadprefs()
        self.tablesapp_win.title("Tables Application")
        self.tablesapp_win.geometry("+200+200")
        self.x_size = 800
        self.y_size = 600
        self.createMenuBar()
        self.apptoolBar = ToolBar(self.tablesapp_win, self)
        self.apptoolBar.pack(fill=BOTH, expand=NO)
        # add find bar
        # self.createSearchBar()

        if data != None:
            self.data = data
            self.new_project(data)
        elif datafile != None:
            self.open_project(datafile)
        else:
            self.new_project()

        self.tablesapp_win.protocol("WM_DELETE_WINDOW", self.quit)
        return
Example #9
0
    def __init__(self,
                 parent=None,
                 peatinfo=None,
                 title=None,
                 data=None,
                 imgfile=None):
        "Initialize the application."
        self.parent = parent
        #If there is data to be loaded, show the dialog first
        if not self.parent:
            Frame.__init__(self)
            self.pilwin = self.master
            self.peatinfo = None
        else:
            self.pilwin = Toplevel()
            #self.peatinfo=peatinfo      #reference to peat protein/field
        if title != None:
            self.title = 'imgviewer_' + title
        else:
            self.title = 'PIL Image Viewer'
        self.pilwin.title(self.title)
        import platform
        self.currplatform = platform.system()
        if not hasattr(self, 'defaultsavedir'):
            self.defaultsavedir = os.getcwd()
        self.preferences = Preferences('PILViewer', {'check_for_update': 1})

        self.pilwin.geometry('+200+100')
        self.currentimage = None
        self.setupGUI()

        if imgfile != None:
            self.openFile(imgfile)
        elif data != None:
            self.currentimage = Image.frombuffer('RGB', (100, 100), data,
                                                 "raw", 'RGB', 0, 1)
            self.updateCanvas()
        return
Example #10
0
class App(Frame, GUI_help):
    """Data pipe GUI for importing and fitting of raw data.
       This class uses ekin provided an automated pipeline for fitting
       raw text data files and propagating errors.
       Uses a config file to store the pipeline settings"""

    def __init__(self, parent=None, rawfile=None, conffile=None):

        self.parent=parent
        if not self.parent:
            Frame.__init__(self)
            self.main=self.master
        else:
            self.main=Toplevel()
            self.master=self.main
        self.main.title('DNATool Desktop')
        self.main.protocol('WM_DELETE_WINDOW',self.quit)

        self.defaultprefs = {'rememberwindowsize':0,'orientation':'horizontal',
                             'alignmenttool':'clustal','clustalpath':'clustalw'}
        self.defaultopts = [('rememberwindowsize','checkbutton',1,'Remember window size'),
                            ('orientation','menu',('horizontal','vertical'),
                            'Default sideframe orientation'),
                            ('alignmenttool','menu',('clustal','muscle','needle'),
                            'External alignment tool'),
                            ('clustalpath','entry','','Path to Clustal')]
        self.loadPrefs()
        self.setGeometry()
        self.P = Project()
        self.primerdb = PrimerDatabase()
        self.setupApps()
        self.setupGUI()
        self.sidepane.selectpage('PrimerDB')
        return

    def setGeometry(self):
        if self.rememberwindowsize == 1 and self.preferences.has_key('lastwindowsize'):
            lastwindowsize = self.preferences.get('lastwindowsize')
            self.winsize = lastwindowsize
            #self.w = int(lastwindowsize.split('x')[0])
        else:
            self.winsize = self.getBestGeometry()
        self.main.geometry(self.winsize)

        return

    def getBestGeometry(self):
        """Calculate optimal geometry from screen size"""
        ws = self.main.winfo_screenwidth()
        hs = self.main.winfo_screenheight()
        self.w=w=ws/1.3; h=500
        x = (ws/2)-(w/2); y = (hs/2)-(h/2)
        g = '%dx%d+%d+%d' % (w,h,x,y)
        return g

    def saveGeometry(self):
        """Save current geometry before quitting"""
        g = self.main.geometry()
        self.preferences.set('lastwindowsize', g)
        return

    def setupApps(self):
        """Creates a dict of classes so that GUI frames like primer design
           can be dynamically added without explicit methods for each"""
        self.apps = {'Primer Design': PrimerDesignGUI,
                     'ORF Overview': ORFOverview,
                     'Sequence Analysis': SequenceAnalysis,
                     'Sequence Alignment Tool': SequenceAlignmentTool,
                     'Restriction Digest Summary': RestrictionDigestSummary,
                     'Blast Interface':BlastInterface,
                     'NotePad': TextEditor}
        return

    def loadPrefs(self):
        """Load prefs from a preferences instance"""
        self.preferences = Preferences('DNATool2',{})
        temp = {}
        for key in self.defaultprefs:
            if not key in self.preferences.prefs:
                self.preferences.set(key, self.defaultprefs[key])
            temp[key] = self.preferences.get(key)
        self.applyPrefs(temp)
        return

    def savePrefs(self):
        """Save prefs to a preferences instance"""
        self.applyPrefs(self.prefsdialog.getValues())
        self.preferences = Preferences('DNATool2',{})
        for key in self.defaultprefs:
            self.preferences.set(key, self.__dict__[key])
        return

    def applyPrefs(self, prefs=None):
        """Apply prefs from a given dict"""
        if prefs == None: prefs=self.defaultprefs
        for key in prefs:
            self.__dict__[key] = prefs[key]
        return

    def setupGUI(self):
        """Do GUI elements"""
        self.visibleapps = {}
        #bottom panel
        bottom = Frame(self.main,height=50)
        bottom.pack(side=BOTTOM,fill=BOTH,pady=1)
        #status bar
        sb = self.addStatusBar(bottom)
        tb = self.addWindowToolBar(bottom)
        tb.pack(side=LEFT,anchor='e',expand=1)

        self.m = PanedWindow(self.main,
                           orient=self.orientation,
                           sashwidth=2,
                           showhandle=True)
        self.m.pack(side=TOP,fill=BOTH,pady=2,expand=1)

        sc = self.sc = SequenceCanvas(self.m,parentapp=self,
                                      width=900,height=800)
        sc.pack(side=TOP,fill=BOTH,pady=2)
        self.m.add(sc)
        self.m.paneconfigure(sc,sticky='news',min=200)

        self.createMenuBar()
        self.createToolBar()
        self.createSidePane()
        if self.orientation == 'vertical':
            self.m.paneconfigure(self.sidepane,
                                      min=200)
        self.createPrimerDBGUI()
        self.createChildFrame(name='NotePad')
        return

    def createMenuBar(self):
        """Create the menu bar for the application. """
        self.menu=Menu(self.main)
        self.file_menu={'01Open Project':{'cmd':self.openProject},
                        '02Open Sequence':{'cmd':self.openSequence},
                        '05Quit':{'cmd':self.quit}}
        self.file_menu=self.create_pulldown(self.menu,self.file_menu)
        self.menu.add_cascade(label='File',menu=self.file_menu['var'])
        self.edit_menu={'01Undo':{'cmd':self.undo},
                        '02Copy':{'cmd':self.copy},
                        '03Select All':{'cmd':self.sc.selectAll},
                        '04Configure Restriction Enzymes':{'cmd':self.restrictionEnzymesDialog}}
        self.edit_menu=self.create_pulldown(self.menu,self.edit_menu)
        self.menu.add_cascade(label='Edit',menu=self.edit_menu['var'])

        self.primer_menu={'01Primer DB':{'cmd':self.createPrimerDBGUI}}
        self.primer_menu=self.create_pulldown(self.menu,self.primer_menu)
        self.menu.add_cascade(label='Primer Tools',menu=self.primer_menu['var'])

        self.seqanal_menu={'01x':{'cmd':self.openSequence}}
        self.seqanal_menu=self.create_pulldown(self.menu,self.seqanal_menu)
        self.menu.add_cascade(label='Sequence Analysis',menu=self.seqanal_menu['var'])

        self.view_menu=Menu(self.menu)
        self.menu.add_cascade(label='Tools',menu=self.view_menu)
        self.appsvars = {}
        for i in self.apps.keys():
            self.appsvars[i] = IntVar()
            def func(args):
                def new():
                    self.toggleApps(args)
                return new
            self.view_menu.add_checkbutton(label=i, onvalue=True,
                                            offvalue=False,
                                            command=func(i),
                                            variable=self.appsvars[i])

        self.help_menu={ '01Online Help':{'cmd': self.help},
                         '02About':{'cmd': self.about},}
        self.help_menu=self.create_pulldown(self.menu,self.help_menu)
        self.menu.add_cascade(label='Help',menu=self.help_menu['var'])
        self.main.config(menu=self.menu)
        return

    def createSidePane(self, width=200):
        """Side panel for various dialogs is tabbed notebook that can hold multiple
            dialogs at once """
        self.closeSidePane()
        self.sidepane = Frame(self.m,
                              bd=1,relief=RAISED)
        self.sidepane = Pmw.NoteBook(self.m)
        self.sidepane.component('hull').configure(relief='sunken',
                                                    borderwidth=1)
        self.m.paneconfigure(self.sidepane,
                                  width=width,
                                  sticky='news')
        self.m.add(self.sidepane)
        self.sidepane.setnaturalsize()
        return self.sidepane

    def closeSidePane(self):
        """Destroy sidepine"""
        if hasattr(self, 'sidepane'):
            self.m.forget(self.sidepane)
            self.sidepane.destroy()
        return

    def createChildFrame(self, sidepane=True, width=400, name=None):
        """Create a child frame in sidepane notebook or as toplevel"""
        geometry = '600x400+500+250'
        if sidepane == True:
            cframe = self.sidepane.add(name)
            self.sidepane.tab(name).configure(font='fixed 8',anchor='w')
            self.sidepane.selectpage(name)
        else:
            cframe = Toplevel()
            if name == None:
                title = 'default'
            else:
                title = name
            cframe.title(title)
        self.__dict__[name] = cframe
        #if name is a pre-defined app we load fetch the class
        if self.apps.has_key(name):
            cls = self.apps[name]
            inst = cls(cframe, parentapp=self)
            inst.pack(fill=BOTH,expand=1)
            self.appsvars[name].set(1)
            if hasattr(inst, 'geometry'):
                geometry = inst.geometry
        if sidepane == False:
            cframe.geometry(geometry)
        #bind frame close
        def func(evt):
            if hasattr(self, name):
                del self.__dict__[name]
            if name in self.appsvars:
                self.appsvars[name].set(0)
        cframe.bind("<Destroy>", func)
        return cframe

    def closeChildFrame(self):
        """Close sidepane frame"""
        name = self.sidepane.getcurselection()
        self.sidepane.delete(name)
        return

    def detachChildFrame(self):
        """Since we cannot actually detach frames in Tkinter, we
           remove the frame in the sidepane make a new toplevel window"""
        name = self.sidepane.getcurselection()
        self.sidepane.delete(name)
        if name == 'PrimerDB':
            fr = self.createPrimerDBGUI(sidepane=False)
        else:
            fr = self.createChildFrame(sidepane=False, name=name)
        return fr

    def toggleApps(self, name):
        """Remove or add apps from view"""
        print name
        if self.appsvars[name].get() == 1:
            if not hasattr(self, name):
                fr = self.createChildFrame(sidepane=True, name=name)
        else:
            if hasattr(self, name):
                if name in self.sidepane.pagenames():
                    self.sidepane.delete(name)
                else:
                    self.__dict__[name].destroy()
                    del self.__dict__[name]
        return

    def createToolBar(self):
        """Toolbar"""
        self.toolbar = ToolBar(self.main, self)
        self.toolbar.pack(side=TOP,fill=X,pady=1,before=self.m)
        img = Images.openproject()
        hlptxt="Open Project from file"
        self.toolbar.addButton('Open Project', self.openProject, img, hlptxt)
        img = Images.saveproject()
        hlptxt="Save Project"
        self.toolbar.addButton('Save Project', self.openProject, img, hlptxt)
        img = Images.undo()
        hlptxt="Undo"
        self.toolbar.addButton('Save Project', self.openProject, img, hlptxt)
        img = Images.zoomout()
        hlptxt="Zoom Out"
        self.toolbar.addButton('Save Project', self.sc.zoomOut, img, hlptxt)
        img = Images.zoomin()
        hlptxt="Zoom In"
        self.toolbar.addButton('Save Project', self.sc.zoomIn, img, hlptxt)
        img = Images.windowprefs()
        hlptxt="Seqeuence display preferences"
        self.toolbar.addButton('Seqeuence display preferences', self.sc.showPrefs,
                         img, hlptxt)
        img = Images.prefs()
        hlptxt="Preferences"
        self.toolbar.addButton('Preferences', self.globalPrefsDialog, img, hlptxt)
        return

    def addWindowToolBar(self, parent):
        """Toolbar for changing frame views"""
        toolbar = ToolBar(parent, self)
        img = Images.closeframe()
        hlptxt="Close current sideframe"
        toolbar.addButton('tile vertical', self.closeChildFrame, img, hlptxt)
        img = Images.detachframe()
        hlptxt="Detach current sideframe as seperate window"
        toolbar.addButton('tile vertical', self.detachChildFrame, img, hlptxt)
        img = Images.tilevertical()
        hlptxt="Tile frames vertically"
        toolbar.addButton('x', self.tileVertical, img, hlptxt)
        img = Images.tilehorizontal()
        hlptxt="Tile frames horizontally"
        toolbar.addButton('tile horizontal', self.tileHorizontal, img, hlptxt)
        return toolbar

    def addStatusBar(self, parent):
        fr = Frame(parent, width=100)
        Label(fr,text='status stuff').pack()
        fr.pack(fill=X,side=LEFT,anchor='w')
        return

    def removeAll(self):
        """Remove all widgets"""
        for w in self.main.children.values():
            w.destroy()
        return

    def tileHorizontal(self):
        """Re-arrange paned widgets horizontally"""
        if self.orientation == 'horizontal':
            return
        self.removeAll()
        self.orientation = 'horizontal'
        self.setupGUI()
        return

    def tileVertical(self):
        """Re-arrange paned widgets vertically"""
        if self.orientation == 'vertical':
            return
        self.removeAll()
        self.orientation = 'vertical'
        self.setupGUI()
        return

    def openSequence(self):
        """Load a sequence"""
        seq = Sequence()
        self.sc.loadSequence(seq)
        return

    def openProject(self, filename=None):
        """Load a project"""
        if filename == None:
            filename = Dialogs.openFilename(parent=self, ext='dtp')
        if not filename:
            return
        self.P.load(filename)
        #open sequence
        seq = self.P.DNAseq
        #print self.P.used_enzymes, self.P.cut_pos
        self.sc.project = self.P
        self.sc.update()

        #update primer db
        self.primerdb = PrimerDatabase(self.P.data['primer_dict'])
        self.pdbwin.database = self.primerdb
        self.pdbwin.update()
        return

    def copy(self):
        self.sc.copySequence()
        return

    def undo(self):
        return

    def createPrimerDBGUI(self, sidepane=True):
        """We create this individually to avoid confusion"""
        if hasattr(self, 'PrimerDB'):
            self.PrimerDB.lift()
            return
        fr = self.createChildFrame(name='PrimerDB',sidepane=sidepane)
        self.pdbwin = PrimerDBGUI(fr, database=self.primerdb)
        self.pdbwin.update()
        self.pdbwin.pack(fill=BOTH,expand=1)
        #bind window closing so it's automatically recreated in the sidepane
        if sidepane == False:
            def func(evt):
                self.createPrimerDBGUI()
            self.pdbwin.bind("<Destroy>", func)
        return fr

    def applyRestrSiteSettings(self):
        if hasattr(self, 'restrsitedialog'):
            vals = self.restrsitedialog.getValues()
        self.sc.update()
        return

    def restrictionEnzymesDialog(self, sidepane=True):
        defaults = {'uniquesitesonly':1,'showonlyenzymescutmax':50,
                    'ignorecutpos':1,'minlengthrecseq':5,'excludepromiscuous':1}
        options = [('uniquesitesonly','checkbutton',1,'Show unique sites only'),
                   ('showonlyenzymescutmax','scale',(1,100),'Show only enzymes that cut max'),
                   ('ignorecutpos','checkbutton',1,'Ignore cut position when finding isoschiziomers'),
                   ('minlengthrecseq','scale',(1,10),'Min length of recognition sequence'),
                   ('excludepromiscuous','checkbutton',1,'Exclude promiscuous enzymes')]
        geometry = '400x250+500+250'
        fr = self.createChildFrame(name='Configure Restriction Enzymes',sidepane=sidepane)
        self.restrsitedialog = Dialogs.GenericDialog(fr, options, defaults)
        defaults = {'uniquesitesonly':1,'showonlyenzymescutmax':50,
                    'ignorecutpos':1,'minlengthrecseq':5,'excludepromiscuous':1}
        self.restrsitedialog.pack(fill=BOTH,expand=1)
        return

    def applySettings(self):
        self.applyPrefs(self.prefsdialog.getValues())
        #self.removeAll()
        #self.setupGUI()
        #self.globalPrefsDialog()
        return

    def globalPrefsDialog(self, sidepane=True):
        curr = {}
        for key in self.defaultprefs:
            curr[key] = self.__dict__[key]
        fr = self.createChildFrame(name='Global settings', sidepane=sidepane)
        self.prefsdialog = Dialogs.PrefsDialog(fr, self, self.defaultopts,
                                                curr, self.applySettings)
        self.prefsdialog.pack(fill=BOTH,expand=1)
        return

    def help(self):
        import webbrowser
        link='http://code.google.com/p/peat/wiki/DNAtool'
        webbrowser.open(link,autoraise=1)
        return

    def about(self):
        win=Toplevel()
        win.geometry('+500+350')
        win.title('About DNATool')
        win.maxsize(width=400,height=400)
        logo = Images.logo()
        label = Label(win,image=logo)
        label.image = logo
        label.pack(fill=BOTH,padx=4,pady=4)
        text="""DNATool App, Version 2
             is a python desktop application for DNA sequence manipulation.
             Released under GPL v3
             (C) Copyright 2012- Damien Farrell """
        text=text.replace('\t','')
        text= ' '.join(text.split())
        Label(win,text=text,wraplength=400).pack(fill=Y,side=TOP,pady=4)
        return

    def quit(self):
        if self.rememberwindowsize == 1:
            self.saveGeometry()
        self.main.destroy()
        if not self.parent:
            sys.exit()
        return
Example #11
0
class SequenceCanvas(Pmw.ScrolledCanvas):
    """Canvas for drawing all graphical elements, sequences and restrictions sites"""
    def __init__(self, parent=None, parentapp=None,
                    width=400, height=400, bg='white', **kwargs):
        Pmw.ScrolledCanvas.__init__(self, parent, canvasmargin=2)
        self.parent = parent
        self.parentapp = parentapp
        self.project = None
        self.platform = platform.system()
        self.width=width
        self.height=height
        self.canvas = self.component('canvas')
        self.canvas.configure(bg='#f6f9f6',height=height, width=width)
        self.createBindings()

        self.defaultprefs = {'seqfont':'Courier', 'seqfontsize':13, 'fontstyle':'bold',
                              'basescale':15, 'restrfont':'Arial',
                              'backgrcolor':'#f6f9f6','seqcoloroption':2}
        fonts = ['Courier','Arial','Fixed','Tahoma','Times','Verdana']
        #we use the following to create the prefs dialog
        #list of tuples of the form name,type,default,label
        self.defaultopts = [('seqfont','menu',fonts,'Sequence font'),
                            ('seqfontsize','scale',(6,30), 'Sequence font size'),
                            ('fontstyle','menu',['normal','bold','italic'],'Font style'),
                            ('basescale','scale',(8,50), 'Base scale'),
                            ('restrfont','menu',fonts,'Restr site font'),
                            ('backgrcolor','color','#f6f9f6','Background color')]
        self.loadPrefs()
        self.baserow = self.height/2
        self.seqstart = 80
        self.siterowstart = 70
        self.orfoffset = 15
        self.yscale = 1.1

        #self.sequence = Utilities.createDummySequence(100)
        self.alignedsequences = []
        self.update()
        return

    def createBindings(self):
        """Bindings"""
        c = self.canvas
        c.bind("<Button-1>", self.handleLeftClick)
        c.bind("<B1-Motion>", self.handleLeftMotion)
        c.bind("<Button-3>", self.handleRightClick)
        c.bind_all("<Control-KeyPress-c>", self.copySequence)
        #c.bind("<ButtonRelease-3>",self.handleRightRelease)

        '''c.bind("<ButtonRelease-1>",self.handle_left_release)

        c.bind("<Shift-Button-1>", self.handle_left_shift_click)
        c.bind("<Shift-ButtonRelease-1>", self.handle_left_shift_release)
        c.bind("<B3-Motion>", self.handle_right_motion)

        c.bind_all("<Control-KeyPress-x>",self.cut_DNA)
        c.bind_all("<Control-KeyPress-v>",self.paste_DNA)
        c.bind_all("<Delete>",self.delete_DNA) '''
        return

    def loadPrefs(self):
        """Load prefs from a preferences instance"""
        self.preferences = Preferences('DNATool2',{})
        temp = {}
        for key in self.defaultprefs:
            if not key in self.preferences.prefs:
                self.preferences.set(key, self.defaultprefs[key])
            temp[key] = self.preferences.get(key)
        self.applyPrefs(temp)
        return

    def savePrefs(self):
        """Save prefs to a preferences instance"""
        self.preferences = Preferences('DNATool2',{})
        for key in self.defaultprefs:
            self.preferences.set(key, self.__dict__[key])
        return

    def applyPrefs(self, prefs=None):
        """Apply prefs from a given dict"""
        if prefs == None: prefs=self.defaultprefs
        for key in prefs:
            self.__dict__[key] = prefs[key]
        return

    def handleLeftClick(self, evt):
        """Handle left click"""
        if hasattr(self, 'rightmenu'):
            self.rightmenu.destroy()
        c = self.canvas
        if len(c.gettags(CURRENT))==0:
            return
        self.markPosition(evt)
        x=evt.x; y=evt.y
        items = c.find_closest(evt.x, evt.y, halo=14)
        x1,y1,x2,y2 = c.bbox(CURRENT)
        self.selecteditems = c.find_enclosed(x1-1, y1-1, x2+1, y2+1)
        return

    def handleLeftMotion(self, evt):
        c = self.canvas
        items = self.selecteditems
        current = c.gettags(CURRENT)
        if 'sitelabel' in current:
            self.dragMove(evt, items)
        elif 'sequence' in current:
            self.setSequenceSelection(evt)
        return

    def selectSequence(self, seq):
        """Select sequence just from seq values"""
        self.highlightSequence(seq)
        self.selectedrange = seq
        return

    def selectAll(self):
        sel = range(0,len(self.sequence))
        self.selectSequence(sel)
        return

    def setSequenceSelection(self, evt):
        """Select sequence from mouse action"""
        c = self.canvas
        x = self.oldx
        x2 = c.canvasx(evt.x)
        height = self.basescale/1.1
        y = self.baserow+height/2
        c.delete(c.find_withtag('seqselection'))
        rect = c.create_rectangle(x,y, x2, y-height, width=0,
            tag=('seqselection'),fill='yellow')
        x1,y1,x2,y2 = c.bbox(rect)
        items = c.find_overlapping(x1+2, y1, x2-2, y2)
        seq = range(self.getSeqPositionFromCoords(x),self.getSeqPositionFromCoords(x2))
        self.selectSequence(seq)
        return

    def highlightSequence(self, sequence):
        """Highlight section of sequence in different color"""
        self.colorSequence()
        c = self.canvas
        height = self.basescale/1.1
        y = self.baserow+height/2
        ignore = set(['seqbackground','seqselection'])
        for s in sequence:
            x = self.getBasePosition(s)
            items = c.find_overlapping(x-2, y-2, x, y+2)
            for i in items:
                if len(set(c.gettags(i)) & ignore) > 0:
                    continue
                c.itemconfig(i,fill='red')
                c.lift(i)
        return

    def getSeqPositionFromCoords(self,x):
        """From X and Y coordinate, return the DNA base number"""
        #if abs(y-self.baserow)>5:
        #    return None
        pos = int(float(x-self.seqstart+4.0)/self.basescale)
        return pos

    def markPosition(self, evt):
        c = self.canvas
        self.oldx = c.canvasx(evt.x)
        self.oldy = c.canvasy(evt.y)
        self.selectedtags = c.gettags(CURRENT)
        return

    def dragMove(self, evt, items=None, tags=None):
        """Handle mouse drag"""
        c = self.canvas
        x = c.canvasx(evt.x)
        y = c.canvasy(evt.y)
        diffx = x - self.oldx
        diffy = y - self.oldy
        self.oldx = x
        self.oldy = y
        name = c.gettags(CURRENT)[0]
        for i in items:
            c.move(i, diffx, diffy)
            self.drawSiteConnector(x, y, name, move=True)
        return

    def handleRightClick(self, evt):
        self.rightmenu = self.popupMenu(evt)
        return

    def popupMenu(self, evt):
        """Right click shows popup menu"""
        popupmenu = Menu(self.canvas, tearoff = 0)
        def popupFocusOut(evt):
            popupmenu.unpost()
        popupmenu.add_command(label="Show Prefs", command= self.showPrefs)
        popupmenu.add_command(label="Zoom in", command= self.zoomIn)
        popupmenu.add_command(label="Zoom out", command= self.zoomOut)
        popupmenu.bind("<FocusOut>", popupFocusOut)
        popupmenu.focus_set()
        popupmenu.post(evt.x_root, evt.y_root)
        return popupmenu

    def addSequences(self, sequences):
        self.alignedsequences = sequences
        return

    def update(self, sequence=None, enzymes=None, cutpos=None):
        """Update display of the current sequence(s)"""

        if sequence == None:
            X = self.getDatafromProject()
            if X == None:
                return
            else:
                sequence, enzymes, cutpos = X
        #remove previous
        self.clear()
        self.calculateScaling()
        self.drawDefaultLabels()
        #update sequence
        self.showSequence(sequence)
        self.colorSequence()
        self.drawSeqBackground()
        #if self.ORFselected == True:
        self.showAA3Seq(sequence)
        #draw restr sites
        if enzymes != None:
            self.showRestrictionSites(enzymes, cutpos)
        #update primers if selected
        #self.showPrimers()
        self.canvas.configure(bg=self.backgrcolor)
        return

    def getDatafromProject(self):

        if self.project != None:
            P = self.project
            if P.DNAseq == '':
                return
        else:
            return
        sequence = P.DNAseq
        enzymes = P.used_enzymes
        cutpos = P.cut_pos
        return sequence, enzymes, cutpos

    def clear(self):
        """Clear all"""
        c = self.canvas
        c.delete(ALL)
        return

    def calculateScaling(self):
        """Calculate font size dependant y-scaling to prevent crowding"""
        self.yscale = self.seqfontsize/10.0
        self.yscale=pow(self.yscale,0.05)
        return

    def getCurrentFont(self):
        """Generate current font from settings"""
        fontsize = self.seqfontsize
        fontstyle = self.fontstyle
        #create a font object
        if fontstyle != 'italic':
            seqfont = tkFont.Font (family=self.seqfont, size=fontsize,
                                    weight=fontstyle)
        else:
            seqfont = tkFont.Font (family=self.seqfont, size=fontsize,
                                    slant="italic")
        return seqfont

    def showSequence(self, sequence=None, row=None, tag=None):
        """Show sequence"""
        if sequence == None:
            return
        if row == None:
            row = self.baserow
        c = self.canvas
        seqfont = self.getCurrentFont()

        #dna sequence
        self.sequence = sequence
        #print sequence
        for i in range(len(sequence)):
            pos = self.getBasePosition(i)
            item = c.create_text(pos,row,
                            font=seqfont,text=sequence[i],
                            fill='black',anchor='w',tag=('seqtext','sequence'))
            if tag != None:
                c.itemconfig(i, tag=tag)
        self.seqend = self.getBasePosition(len(sequence))-self.seqstart
        self.canvas.configure(scrollregion=(0,0,self.seqend+100,self.height))
        self.centerPage()
        return

    def showMultiple(self, aligned=None, direction='up'):
        """Show multiple sequences aligned to the base one"""

        #print self.alignedsequences
        if aligned == None:
            aligned = self.alignedsequences
        self.clearMultiple()
        if len(aligned) == 0:
            return
        #move restr sites up
        self.clearRestrictionSites()
        if direction == 'up':
            inc = -15
        else:
            inc = 15
        row = self.baserow + inc
        print len(aligned)
        for s in aligned[:55]:
            self.showSequence(s, row, tag='aligned')
            row+=inc
            self.height+=20
        return

    def clearMultiple(self):
        """Clear multiple sequences"""
        c = self.canvas
        c.delete('aligned')
        self.update()
        return

    def showAASeq(self):

        return

    def showAA3Seq(self, sequence=None):
        """Show 3 letter code amino acid sequence"""
        if sequence == None:
            return
        c = self.canvas
        seqfont = self.getCurrentFont()

        y = (self.baserow+self.orfoffset)*self.yscale
        frame = 0
        AAseqs3,AAseqs1 = Mutation.translate(sequence)
        aaseq = AAseqs3[frame]
        #print aaseq
        for i in range(len(aaseq)):
            pos = self.getAAPosition(i)#,frame+1)
            c.create_text(pos,y,
                            font=seqfont,text=aaseq[i],
                            fill='black',tag=('aasequence'))
        for i in range(len(aaseq)):
            if i%5!=0:
                continue
            pos = self.getAAPosition(i)
            c.create_text(pos,y+45,
                            font='Courier 11',text=i,
                            fill='black',tag=('aasequence'))
            c.create_line(pos,y+35,pos,y+20,fill='red',width=2)
        return

    def colorSequence(self):
        """Color the dna sequence"""
        c = self.canvas
        items = c.find_withtag('seqtext')
        option = 2
        count=0
        clr = '#66CC00'
        for i in items:
            if option == 1:
                c.itemconfig(i, fill=clr)
            elif option == 2:
                if count % 3 == 0 and clr == '#66CC00':
                    clr='#999900'
                elif count % 3 == 0 and clr=='#999900':
                    clr='#66CC00'
                c.itemconfig(i, fill=clr)
            count=count+1
        return

    def drawDefaultLabels(self):
        """Draw objects that are permanent"""
        c = self.canvas
        item = c.create_text(5,self.baserow,font='Courier 10',text='DNA seq',
                        fill='darkgreen',anchor='w')
        y = (self.baserow+self.orfoffset)*self.yscale
        item = c.create_text(5,y,font='Courier 10',text='ORF',
                        fill='black',anchor='w')
        item = c.create_text(5,y+45,font='Courier 10',text='AA no.',
                        fill='gray',anchor='w')
        return

    def drawSeqBackground(self, color='white'):
        """Draw a background for a sequence"""
        c = self.canvas
        x = self.seqstart
        height = self.basescale
        y = self.baserow+height/2
        end = self.seqend
        rect = c.create_rectangle(x,y, x+end, y-height,
                                   width=0,tag=('seqbackground','sequence'),fill=color)
        c.tag_lower(rect)
        return rect

    def drawRestrictionSite(self, name, positions):
        """Draw restriction site(s) for a single enzyme"""
        c = self.canvas
        font = restrfont = str(self.restrfont)+' '+str(self.seqfontsize-2)
        done=[]
        if len(positions) == 1:
            #font = font+' underline'
            fill = '#FF9999'
        else:
            fill = '#F6FCE1'
        for pos in positions:
            uid = name+str(pos[0])
            self.restrictionsites[uid] = pos[0]
            if pos[0] in done: continue
            done.append(pos[0])
            x = self.getBasePosition(pos[0])
            y = self.baserow-self.siterowstart
            text = self.create_text(x,y,text=name,tags=(uid,'sitelabel','restrsite'),
                                        font=font,anchor='nw')

            x1,y1,x2,y2 = box = c.bbox(text)
            rect = c.create_rectangle(box,fill=fill,outline='gray',
                                        tags=(uid,'rect','restrsite'))
            items = c.find_withtag(uid)
            overlapping = c.find_overlapping(x1,y1,x2,y2)[:-2]
            #print pos, items, overlapping
            inc=-10
            while len(overlapping) > 1:
                for i in items:
                    c.move(i,0,inc)
                x1,y1,x2,y2 = c.bbox(i)
                overlapping = c.find_overlapping(x1,y1,x2,y2)[:-2]
                y=y+inc
            c.lift(text)
            self.drawSiteConnector(x,y,uid)
        return text

    def drawSiteConnector(self,x2,y2,uid,move=False):
        """Draw line connecting site label to sequence"""
        c = self.canvas
        pos = self.restrictionsites[uid]
        x1 = self.getBasePosition(pos)
        y1 = self.baserow-15

        if move==True:
            old = list(set(c.find_withtag(uid))&set(c.find_withtag('line')))
            for i in old:
                c.delete(i)
        line = c.create_line(x1,y1,x1,y2, fill='blue',
                              width=2,stipple='gray25',
                              tag=(uid,'line','restrsite'))
        c.tag_lower(line)
        line = c.create_line(x1,y2,x2,y2, fill='blue',
                              width=2,stipple='gray25',
                              tag=(uid,'line','restrsite'))
        c.tag_lower(line)
        return

    def moveItemByName(self, name, y):
        c = self.canvas
        items = c.find_withtag(name)
        for i in items:
            c.move(i, 0, y)
        return

    def showRestrictionSites(self, enzymes=None, cutpos=None):
        """Draw all restriction sites"""
        if enzymes==None:
            return
        self.restrictionsites = {}
        c = self.canvas
        for e in enzymes:
            if cutpos.has_key(e):
                positions = cutpos[e]
                r = self.drawRestrictionSite(e, positions)

        return

    def clearRestrictionSites(self):
        """Clear all restriction sites"""
        c = self.canvas
        #print c.find_withtag('restrsite')
        c.delete('restrsite')
        return

    def getBasePosition(self, pos):
        """Return the x position of the nth base on the canvas"""
        return self.seqstart + float(pos) * self.basescale

    def getAAPosition(self, pos, frame=None):
        pos = pos*3+1 #+float(frame)
        return self.getBasePosition(pos)

    def showPrimers(self):
        """Draw primers"""
        return

    def centerPage(self):
        """Center canvas on sequence after redraw"""
        top, bottom = self.yview()
        size = bottom - top
        if size==0: size=0.4
        middle = size * 0.4
        self.yview('moveto', middle)
        #print top, bottom
        #print middle
        return

    def zoomIn(self):
        """Zoom in by enlarging all elements"""
        c = self.canvas
        x1,x2 = self.xview()
        y1,y2 = self.yview()
        self.basescale = self.basescale*1.1
        self.seqfontsize = self.seqfontsize+1
        self.update()
        return

    def zoomOut(self):
        """Zoom out by reducing all elements"""
        if self.seqfontsize<7:
            return
        self.basescale = self.basescale/1.1
        self.seqfontsize = self.seqfontsize-1
        self.update()
        return

    def copySequence(self, evt=None):
        """Copy sequence text"""
        seqdata = ''.join([self.sequence[i] for i in self.selectedrange])
        self.parent.clipboard_clear()
        self.parent.clipboard_append(seqdata)
        return

    def showPrefs(self, evt=None):
        """Show preferences window"""
        fr = Toplevel(self.parent)
        fr.title('Sequence window preferences')
        def func():
            self.applyPrefs(self.prefsdialog.getValues())
            self.update()
        curr = {}
        for key in self.defaultprefs:
            curr[key] = self.__dict__[key]
        dlg = self.prefsdialog = Dialogs.PrefsDialog(fr, self, options=self.defaultopts,
                                    defaults=curr, callback=func)
        dlg.pack(fill=BOTH,expand=1)
        fr.geometry(dlg.geometry)
        fr.grab_set()
        fr.transient(self.parent)
        return
Example #12
0
class LabbookApp(Frame, GUI_help):
    """
    Labbook app
    """
    appname = 'Labbook client'

    def __init__(self,
                 parent=None,
                 peatinfo=None,
                 title=None,
                 data=None,
                 datafile=None):
        "Initialize the application."
        self.parent = parent

        #If there is data to be loaded, show the dialog first
        if self.parent == None:
            Frame.__init__(self)
            self.labbook_win = self.master
            self.peatinfo = None
        else:
            self.labbook_win = Toplevel()
            self.master = self.labbook_win
            self.peatinfo = peatinfo  #reference to peat protein/field
            self.DB = self.parent.DB  #ref to peat

        if title != None:
            self.title = 'subtable_' + title
        else:
            self.title = 'Labbook Tool'

        self.ID = 'Labbook'
        # Get platform into a variable
        import platform
        self.currplatform = platform.system()
        if not hasattr(self, 'defaultsavedir'):
            self.defaultsavedir = os.getcwd()

        self.preferences = Preferences('Labbook', {'check_for_update': 1})
        #self.loadprefs()
        if self.peatinfo:
            protein = self.peatinfo['record']
            field_name = self.peatinfo['column']
            self.labbook_win.title('Labbook: ' + protein + '_' + field_name)
        else:
            self.labbook_win.title(self.title)
        self.labbook_win.geometry('+200+100')
        self.x_size = 1000
        self.y_size = 500
        self.createMenuBar()
        self.apptoolBar = ToolBar(self.labbook_win, self)
        self.apptoolBar.pack(fill=BOTH, expand=NO)
        #add find bar
        #self.createSearchBar()

        if data != None:
            self.data = data
            self.new_project(data)
        elif datafile != None:
            self.open_project(filename=datafile)
        else:
            self.new_project()
        #add return to main PEAT db button
        if self.parent:
            Button(self.labbook_win,
                   text="Return to Database",
                   command=self.return_data).pack()
        self.labbook_win.protocol('WM_DELETE_WINDOW', self.quit)
        self.createBindings()
        self.clipboard = None
        return

    def createBindings(self):
        """Bind keys"""
        self.labbook_win.bind("<Control-n>", self.new_project)
        self.labbook_win.bind("<Control-o>", self.open_project)
        self.labbook_win.bind("<Control-s>", self.save_project)
        self.labbook_win.bind("<Control-q>", self.quit)
        self.labbook_win.bind("<Control-i>", self.import_csv)
        self.labbook_win.bind("<Control-e>", self.export_csv)

        return

    def createMenuBar(self):
        """Create the menu bar for the application. """
        self.menu = Menu(self.labbook_win)
        self.proj_menu = {
            '01New': {
                'cmd': self.new_project
            },
            '02Open': {
                'cmd': self.open_project
            },
            '03Close': {
                'cmd': self.close_project
            },
            '04Save': {
                'cmd': self.save_project
            },
            '05Save As': {
                'cmd': self.save_as_project
            },
            '06Preferences..': {
                'cmd': self.showPrefsDialog
            },
            '08Quit': {
                'cmd': self.quit
            }
        }
        if self.parent:
            self.proj_menu['08Return to Database'] = {'cmd': self.return_data}
        self.proj_menu = self.create_pulldown(self.menu, self.proj_menu)
        self.menu.add_cascade(label='Project', menu=self.proj_menu['var'])

        self.edit_menu = {
            '01Copy': {
                'cmd': self.copy
            },
            '02Paste': {
                'cmd': self.paste
            },
            '03Copy Columns': {
                'cmd': self.copyColumns
            },
            '04Paste Columns': {
                'cmd': self.pasteColumns
            }
        }
        self.edit_menu = self.create_pulldown(self.menu, self.edit_menu)
        self.menu.add_cascade(label='Edit', menu=self.edit_menu['var'])

        self.records_menu = {
            '01Add Row': {
                'cmd': self.add_Row
            },
            '02Delete Row': {
                'cmd': self.delete_Row
            },
            '03Add Column': {
                'cmd': self.add_Column
            },
            '04Delete Column': {
                'cmd': self.delete_Column
            },
            '05Auto Add Rows': {
                'cmd': self.autoAdd_Rows
            },
            '06Auto Add Columns': {
                'cmd': self.autoAdd_Columns
            },
            '07Find Cell': {
                'cmd': self.createSearchBar
            },
            '08Filter': {
                'cmd': self.showFilteringBar
            }
        }
        self.records_menu = self.create_pulldown(self.menu, self.records_menu)
        self.menu.add_cascade(label='Records', menu=self.records_menu['var'])

        self.sheet_menu = {
            '01Add Sheet': {
                'cmd': self.add_Sheet
            },
            '02Remove Sheet': {
                'cmd': self.delete_Sheet
            },
            '03Copy Sheet': {
                'cmd': self.copy_Sheet
            },
            '04Rename Sheet': {
                'cmd': self.rename_Sheet
            },
            '05Merge Sheet': {
                'cmd': self.merge_Sheet
            },
        }
        self.sheet_menu = self.create_pulldown(self.menu, self.sheet_menu)
        self.menu.add_cascade(label='Sheet', menu=self.sheet_menu['var'])

        self.IO_menu = {
            '01Import from csv file': {
                'cmd': self.import_csv
            },
            '02Export to csv file': {
                'cmd': self.export_csv
            },
            '03Import external fileset': {
                'cmd': self.import_fileset
            },
        }

        self.IO_menu = self.create_pulldown(self.menu, self.IO_menu)
        self.menu.add_cascade(label='Import/Export', menu=self.IO_menu['var'])

        self.view_menu = Menu(self.menu, tearoff=0)
        self.view_menu.add_radiobutton(label="Normal View",
                                       state=ACTIVE,
                                       command=self.normal_view)
        self.view_menu.add_radiobutton(label="Page View",
                                       command=self.page_view)
        self.view_menu.add_command(label="Show All", command=self.showAll)
        self.menu.add_cascade(label='View', menu=self.view_menu)

        #
        # Help menu
        #
        self.help_menu = {
            '01Online Help': {
                'cmd': self.online_documentation
            },
            '02About': {
                'cmd': self.about_Labbook
            }
        }
        self.help_menu = self.create_pulldown(self.menu, self.help_menu)
        self.menu.add_cascade(label='Help', menu=self.help_menu['var'])

        self.labbook_win.config(menu=self.menu)

        return

    def createSearchBar(self, event=None):
        """Add a find entry box"""
        frame = Frame(self.labbook_win)
        row = 0

        def close():
            frame.destroy()

        self.findtext = StringVar()
        self.findbox = Entry(frame,
                             textvariable=self.findtext,
                             width=30,
                             bg='white')
        self.findbox.grid(row=row,
                          column=1,
                          sticky='news',
                          columnspan=2,
                          padx=2,
                          pady=2)
        self.findbox.bind('<Return>', self.do_find_text)
        Label(frame, text='Find:').grid(row=row, column=0, sticky='ew')
        self.findagainbutton = Button(frame,
                                      text='Find Again',
                                      command=self.do_find_again)
        self.findagainbutton.grid(row=row,
                                  column=3,
                                  sticky='news',
                                  padx=2,
                                  pady=2)
        self.cbutton = Button(frame, text='Close', command=close)
        self.cbutton.grid(row=row, column=4, sticky='news', padx=2, pady=2)
        frame.pack(fill=BOTH, expand=NO)
        return

    def showFilteringBar(self):
        s = self.notebook.getcurselection()
        page = self.notebook.page(s)
        if not hasattr(self.currenttable,
                       'filterframe') or self.currenttable.filterframe == None:
            frame = self.currenttable.createFilteringBar(page)
            frame.grid(row=5, column=0, columnspan=3)
        return

    def showAll(self):
        """Show all recs"""
        self.currenttable.showAll()
        return

    def loadprefs(self):
        """Setup default prefs file if any of the keys are not present"""
        defaultprefs = {
            'textsize': 14,
            'windowwidth': 800,
            'windowheight': 600
        }
        for prop in defaultprefs.keys():
            try:
                self.preferences.get(prop)
            except:
                self.preferences.set(prop, defaultprefs[prop])
        print self.preferences.get('textsize')
        return

    def showPrefsDialog(self):
        self.prefswindow = self.currenttable.showtablePrefs()

        return

    def new_project(self, data=None):
        """Create a new table, with model and add the frame"""
        if hasattr(self, 'currenttable'):
            self.notebook.destroy()
            self.currenttable.destroy()

        #Create the sheets dict
        self.sheets = {}
        self.notebook = Pmw.NoteBook(self.labbook_win,
                                     raisecommand=self.setcurrenttable)
        self.notebook.pack(fill='both', expand=1, padx=4, pady=4)
        if data != None:
            for s in data.keys():
                sdata = data[s]
                #try:
                self.add_Sheet(s, sdata)
                #except:
                #    print 'skipping'
        else:
            #do the table adding stuff for the initial sheet
            self.add_Sheet('sheet1')
        self.notebook.setnaturalsize()
        self.setcurrenttable()
        return

    def open_project(self, event=None, filename=None):
        import os
        if filename == None:
            import tkFileDialog
            filename = tkFileDialog.askopenfilename(
                defaultextension='.labbook',
                initialdir=os.getcwd(),
                filetypes=[("Pickle file", "*.labbook"), ("All files", "*.*")],
                parent=self.labbook_win)
        if os.path.isfile(filename):
            fd = open(filename)
            import pickle
            data = pickle.load(fd)
            fd.close()
        self.new_project(data)
        self.filename = filename
        return

    def save_project(self, event=None):
        if not hasattr(self, 'filename'):
            self.save_as_project()
        elif self.filename == None:
            self.save_as_project()
        else:
            self.do_save_project(self.filename)

        return

    def save_as_project(self):
        """Save as a new filename"""
        import tkFileDialog, os
        filename = tkFileDialog.asksaveasfilename(
            parent=self.labbook_win,
            defaultextension='.labbook',
            initialdir=self.defaultsavedir,
            filetypes=[("Labbook project", "*.labbook"), ("All files", "*.*")])
        if not filename:
            print 'Returning'
            return
        self.filename = filename
        self.do_save_project(self.filename)
        return

    def do_save_project(self, filename):
        """Get model dicts and write all to pickle file"""
        data = {}
        for s in self.sheets.keys():
            currtable = self.sheets[s]
            model = currtable.getModel()
            data[s] = model.getData()

        fd = open(filename, 'w')
        import pickle
        pickle.dump(data, fd)
        fd.close()
        return

    def close_project(self):
        if hasattr(self, 'currenttable'):
            #self.notebook.destroy()
            self.currenttable.destroy()
        return

    def import_csv(self):
        importer = TableImporter()
        #just use the dialog to load and import the file
        importdialog = importer.import_Dialog(self.labbook_win)
        self.labbook_win.wait_window(importdialog)
        modeldata = importer.modeldata
        self.add_Sheet(sheetdata=modeldata)
        return

    def export_csv(self):
        exporter = TableExporter()
        exporter.ExportTableData(self.currenttable)
        return

    def import_fileset(self):
        """Import a series of external files in a folder"""
        if self.parent == None:
            import tkMessageBox
            tkMessageBox.showwarning(
                "Not available", "You can't use this feature outside PEAT.")
            return

        from Extfile import FileHandler
        fh = FileHandler(parent=self)
        fh.importFileset(DB=self.DB, callback=self.currenttable.redrawTable)

        return

    def add_Sheet(self, sheetname=None, sheetdata=None, model=None):
        """Add a new sheet - handles all the table creation stuff"""
        def checksheet_name(name):
            if name == '':
                tkMessageBox.showwarning("Whoops", "Name should not be blank.")
                return 0
            if self.sheets.has_key(name):
                tkMessageBox.showwarning("Name exists",
                                         "Sheet name already exists!")
                return 0

        noshts = len(self.notebook.pagenames())
        if sheetname == None:
            sheetname = tkSimpleDialog.askstring("New sheet name?",
                                                 "Enter sheet name:",
                                                 initialvalue='sheet' +
                                                 str(noshts + 1),
                                                 parent=self.labbook_win)
        checksheet_name(sheetname)
        page = self.notebook.add(sheetname)
        #Create the model if none provided
        if model == None:
            if sheetdata != None:
                model = LabbookTableModel(sheetdata)
            else:
                model = LabbookTableModel(rows=10, columns=5)

        #create the table: we pass the parent instance of peat
        #and peat row/col if present
        self.currenttable = LabbookTable(parent=page,
                                         model=model,
                                         sheetname=sheetname,
                                         peat=self.parent,
                                         peatinfo=self.peatinfo)

        #Load preferences into table
        self.currenttable.loadPrefs(self.preferences)
        #This handles all the canvas and header in the frame passed to constructor
        self.currenttable.createTableFrame()
        #add the table to the sheet dict
        self.sheets[sheetname] = self.currenttable
        self.saved = 0
        return sheetname

    def delete_Sheet(self, s=None):
        """Delete a sheet"""
        if s == None:
            s = self.notebook.getcurselection()
        print s
        self.notebook.delete(s)
        del self.sheets[s]
        return

    def copy_Sheet(self, newname=None):
        """Copy a sheet"""
        newdata = self.currenttable.getModel().getData().copy()
        if newname == None:
            self.add_Sheet(None, newdata)
        else:
            self.add_Sheet(newname, newdata)
        return

    def rename_Sheet(self):
        """Rename a sheet"""
        s = self.notebook.getcurselection()
        newname = tkSimpleDialog.askstring("New sheet name?",
                                           "Enter new sheet name:",
                                           initialvalue=s)
        if newname == None:
            return
        self.copy_Sheet(newname)
        self.delete_Sheet()
        return

    def merge_Sheet(self):
        """Merge 2 sheets"""
        if len(self.sheets) < 2:
            return

        def domerge():
            name = shs.getvalue()[0]
            newmodel = self.sheets[name].model
            curr.model.merge(newmodel)
            self.currenttable.redrawTable()
            return

        s = self.notebook.getcurselection()
        curr = self.sheets[s]
        fr = Toplevel()
        fr.title('Select sheet to merge')
        self.set_centered_geometry(self.labbook_win, fr)
        shs = self.sheetsSelector(fr)
        Button(fr, text='Merge', command=domerge).pack(side=TOP)
        return

    def setcurrenttable(self, event=None):
        """Set the currenttable so that menu items work with visible sheet"""
        try:
            s = self.notebook.getcurselection()
            self.currenttable = self.sheets[s]
        except:
            pass
        return

    def add_Row(self):
        """Add a new row"""
        self.currenttable.add_Row()
        self.saved = 0
        return

    def delete_Row(self):
        """Delete currently selected row"""
        self.currenttable.delete_Row()
        self.saved = 0
        return

    def add_Column(self):
        """Add a new column"""
        self.currenttable.add_Column()
        self.saved = 0
        return

    def delete_Column(self):
        """Delete currently selected column in table"""
        self.currenttable.delete_Column()
        self.saved = 0
        return

    def autoAdd_Rows(self):
        """Auto add x rows"""
        self.currenttable.autoAdd_Rows()
        self.saved = 0
        return

    def autoAdd_Columns(self):
        """Auto add x rows"""
        self.currenttable.autoAdd_Columns()
        self.saved = 0
        return

    def copy(self):
        """Copy current selection to internal clipboard"""
        T = self.currenttable
        self.clipboard = T.copyCell()
        return

    def paste(self):
        print self.clipboard
        return

    def copyColumns(self):
        """Copy columns"""
        self.currenttable.getSelectedColumn()
        self.clipboard = self.currenttable.copyColumns()
        return

    def pasteColumns(self):
        """Paste columns"""
        self.currenttable.pasteColumns(self.clipboard)
        return

    def findValue(self):
        self.currenttable.findValue()
        return

    def do_find_text(self, event=None):
        """Find the text in the table"""
        if not hasattr(self, 'currenttable'):
            return
        import string
        if string.strip(self.findtext.get()) == '':
            return
        searchstring = self.findtext.get()
        if self.currenttable != None:
            self.currenttable.findValue(searchstring)
        return

    def do_find_again(self, event=None):
        """Find again"""
        if not hasattr(self, 'currenttable'):
            return
        searchstring = self.findtext.get()
        if self.currenttable != None:
            self.currenttable.findValue(searchstring, findagain=1)
        return

    def plot(self, event=None):
        self.currenttable.plot_Selected()
        return

    def plotSetup(self, event=None):
        self.currenttable.plotSetup()
        return

    def normal_view(self, event=None):
        self.currenttable.paging_Off()
        return

    def page_view(self, event=None):
        self.currenttable.paging = 1
        self.currenttable.redrawTable()
        return

    def return_data(self, event=None):
        """Return the data to PEAT"""
        returndata = {}
        for s in self.sheets.keys():
            currtable = self.sheets[s]
            model = currtable.getModel()
            returndata[s] = model.getData()

        self.parent.templabbookdata = returndata.copy()
        self.quit()
        return

    def sheetsSelector(self, frame):
        """Show list of sheets"""
        names = self.sheets.keys()
        labbooklist = Pmw.ScrolledListBox(frame,
                                          labelpos='nw',
                                          label_text='Sheets',
                                          listbox_height=8)
        labbooklist.pack(fill=BOTH, expand=1)
        labbooklist.setlist(names)
        return labbooklist

    def about_Labbook(self):
        self.ab_win = Toplevel()
        self.ab_win.geometry('+100+350')
        self.ab_win.title('About Labbook')

        import PEAT_images
        logo = PEAT_images.labbook_logo()
        label = Label(self.ab_win, image=logo)
        label.image = logo
        label.grid(row=0, column=0, sticky='news', padx=4, pady=4)

        text = [
            'Labbook ', 'Part of Protein Engineering and Analysis Tool',
            'A spreadsheet-like table for PEAT.'
        ]
        row = 1
        for line in text:
            tmp = Label(self.ab_win, text=line)
            tmp.grid(row=row, column=0, sticky='news', padx=4)
            row = row + 1
        return

    def online_documentation(self, event=None):
        """Open the online documentation"""
        import webbrowser
        link = 'http://enzyme.ucd.ie/PEAT/'
        webbrowser.open(link, autoraise=1)
        return

    def quit(self, event=None):
        self.labbook_win.destroy()

        return
Example #13
0
class TablesApp(Frame):
    """
    Tables app
    """
    def __init__(self,parent=None,data=None,datafile=None):
        "Initialize the application."
        self.parent=parent

        #If there is data to be loaded, show the dialog first
        if not self.parent:
            Frame.__init__(self)
            self.tablesapp_win=self.master

        else:
            self.tablesapp_win=Toplevel()

        # Get platform into a variable
        import platform
        self.currplatform=platform.system()
        if not hasattr(self,'defaultsavedir'):
            self.defaultsavedir = os.getcwd()

        self.preferences=Preferences('TablesApp',{'check_for_update':1})
        self.loadprefs()
        self.tablesapp_win.title('Tables Application')
        self.tablesapp_win.geometry('+200+200')
        self.x_size=800
        self.y_size=600
        self.createMenuBar()
        self.apptoolBar = ToolBar(self.tablesapp_win, self)
        self.apptoolBar.pack(fill=BOTH, expand=NO)
        #add find bar
        #self.createSearchBar()

        if data != None:
            self.data = data
            self.new_project(data)
        elif datafile != None:
            self.open_project(datafile)
        else:
            self.new_project()

        self.tablesapp_win.protocol('WM_DELETE_WINDOW',self.quit)
        return

    def createMenuBar(self):
        """Create the menu bar for the application. """
        self.menu=Menu(self.tablesapp_win)
        self.proj_menu={'01New':{'cmd':self.new_project},
                        '02Open':{'cmd':self.open_project},
                        '03Close':{'cmd':self.close_project},
                        '04Save':{'cmd':self.save_project},
                        '05Save As':{'cmd':self.save_as_project},
                        '06Preferences..':{'cmd':self.showPrefsDialog},
                        '08Quit':{'cmd':self.quit}}
        if self.parent:
            self.proj_menu['08Return to Database']={'cmd':self.return_data}
        self.proj_menu=self.create_pulldown(self.menu,self.proj_menu)
        self.menu.add_cascade(label='Project',menu=self.proj_menu['var'])

        self.records_menu={'01Add Row':{'cmd':self.add_Row},
                         '02Delete Row':{'cmd':self.delete_Row},
                         '03Add Column':{'cmd':self.add_Column},
                         '04Delete Column':{'cmd':self.delete_Column},
                         '05Auto Add Rows':{'cmd':self.autoAdd_Rows},
                         '06Auto Add Columns':{'cmd':self.autoAdd_Columns},
                         '07Find':{'cmd':self.createSearchBar},
                         }
        self.records_menu=self.create_pulldown(self.menu,self.records_menu)
        self.menu.add_cascade(label='Records',menu=self.records_menu['var'])

        self.sheet_menu={'01Add Sheet':{'cmd':self.add_Sheet},
                         '02Remove Sheet':{'cmd':self.delete_Sheet},
                         '03Copy Sheet':{'cmd':self.copy_Sheet},
                         '04Rename Sheet':{'cmd':self.rename_Sheet},
                         }
        self.sheet_menu=self.create_pulldown(self.menu,self.sheet_menu)
        self.menu.add_cascade(label='Sheet',menu=self.sheet_menu['var'])

        self.IO_menu={'01Import from csv file':{'cmd':self.import_cvs},
                      '02Export to csv file':{'cmd':self.export_cvs},
                      }

        self.IO_menu=self.create_pulldown(self.menu,self.IO_menu)
        self.menu.add_cascade(label='Import/Export',menu=self.IO_menu['var'])


        self.view_menu = Menu(self.menu, tearoff=0)
        self.view_menu.add_radiobutton(label="Normal View", state=ACTIVE,command=self.normal_view)
        self.view_menu.add_radiobutton(label="Page View", command=self.page_view)
        self.menu.add_cascade(label='View',menu=self.view_menu)

        #
        # Help menu
        #
        self.help_menu={'01Online Help':{'cmd':self.online_documentation},
                        '02About':{'cmd':self.about_Tables}}
        self.help_menu=self.create_pulldown(self.menu,self.help_menu)
        self.menu.add_cascade(label='Help',menu=self.help_menu['var'])

        self.tablesapp_win.config(menu=self.menu)

        return

    def create_pulldown(self,menu,dict):
        #
        # Create a pulldown in var from the info in dict
        #
        var=Menu(menu,tearoff=0)
        items=dict.keys()
        items.sort()
        for item in items:
            if item[-3:]=='sep':
                var.add_separator()
            else:
                #
                # Do we have a command?
                #
                command=None
                if dict[item].has_key('cmd'):
                    command=dict[item]['cmd']
                #
                # Put the command in there
                #
                if dict[item].has_key('sc'):
                    var.add_command(label='%-25s %9s' %(item[2:],dict[item]['sc']),command=command)
                else:
                    var.add_command(label='%-25s' %(item[2:]),command=command)
        dict['var']=var
        return dict

    def createSearchBar(self, event=None):
        """Add a find entry box"""
        frame = Frame(self.tablesapp_win)
        row=0
        def close():
            frame.destroy()
        self.findtext=StringVar()
        self.findbox=Entry(frame,textvariable=self.findtext,width=30,bg='white')
        self.findbox.grid(row=row,column=1,sticky='news',columnspan=2,padx=2,pady=2)
        self.findbox.bind('<Return>',self.do_find_text)
        Label(frame,text='Find:').grid(row=row,column=0,sticky='ew')
        self.findagainbutton=Button(frame,text='Find Again', command=self.do_find_again)
        self.findagainbutton.grid(row=row,column=3,sticky='news',padx=2,pady=2)
        self.cbutton=Button(frame,text='Close', command=close)
        self.cbutton.grid(row=row,column=4,sticky='news',padx=2,pady=2)
        frame.pack(fill=BOTH, expand=NO)
        return


    def loadprefs(self):
        """Setup default prefs file if any of the keys are not present"""
        defaultprefs = {'textsize':14,
                         'windowwidth': 800 ,'windowheight':600}
        for prop in defaultprefs.keys():
            try:
                self.preferences.get(prop)
            except:
                self.preferences.set(prop, defaultprefs[prop])

        return

    def showPrefsDialog(self):
        self.prefswindow = self.currenttable.showtablePrefs()

        return


    def new_project(self, data=None):
        """Create a new table, with model and add the frame"""
        if hasattr(self,'currenttable'):
            self.notebook.destroy()
            self.currenttable.destroy()

        #Create the sheets dict
        self.sheets = {}
        self.notebook = Pmw.NoteBook(self.tablesapp_win, raisecommand=self.setcurrenttable)
        self.notebook.pack(fill='both', expand=1, padx=4, pady=4)
        if data !=None:
            for s in data.keys():
                sdata = data[s]
                try:
                    self.add_Sheet(s ,sdata)
                except:
                    print 'skipping'
        else:
            #do the table adding stuff for the initial sheet
            self.add_Sheet('sheet1')
        self.notebook.setnaturalsize()
        return

    def open_project(self, filename=None):
        if filename == None:
            filename=tkFileDialog.askopenfilename(defaultextension='.tbleprj"',
                                                      initialdir=os.getcwd(),
                                                      filetypes=[("Pickle file","*.tbleprj"),
                                                                 ("All files","*.*")],
                                                      parent=self.tablesapp_win)
        if os.path.isfile(filename):
            fd=open(filename)
            data=pickle.load(fd)
            fd.close()
        self.new_project(data)
        self.filename=filename
        return

    def save_project(self):
        if not hasattr(self, 'filename'):
            self.save_as_project()
        elif self.filename == None:
            self.save_as_project()
        else:
            self.do_save_project(self.filename)

        return

    def save_as_project(self):
        """Save as a new filename"""
        filename=tkFileDialog.asksaveasfilename(parent=self.tablesapp_win,
                                                defaultextension='.tblprj',
                                                initialdir=self.defaultsavedir,
                                                filetypes=[("TableApp project","*.tblprj"),
                                                           ("All files","*.*")])
        if not filename:
            print 'Returning'
            return
        self.filename=filename
        self.do_save_project(self.filename)
        return

    def do_save_project(self, filename):
        """Get model dicts and write all to pickle file"""
        data={}
        for s in self.sheets.keys():
            currtable = self.sheets[s]
            model = currtable.getModel()
            data[s] = model.getData()

        fd=open(filename,'w')
        pickle.dump(data,fd)
        fd.close()
        return

    def close_project(self):
        if hasattr(self,'currenttable'):
            #self.notebook.destroy()
            self.currenttable.destroy()
        return

    def import_cvs(self):
        importer = TableImporter()
        #datafile = importer.open_File(self.tablesapp_win)

        #just use the dialog to load and import the file
        importdialog = importer.import_Dialog(self.tablesapp_win)
        self.tablesapp_win.wait_window(importdialog)
        model = TableModel()
        model.importDict(importer.data)
        sheetdata = {}
        sheetdata['sheet1'] = model.getData()
        self.new_project(sheetdata)
        return

    def export_cvs(self):
        exporter = TableExporter()
        exporter.ExportTableData(self.currenttable)
        return


    def add_Sheet(self, sheetname=None, sheetdata=None):
        """Add a new sheet - handles all the table creation stuff"""
        def checksheet_name(name):
            if name == '':
                tkMessageBox.showwarning("Whoops", "Name should not be blank.")
                return 0
            if self.sheets.has_key(name):
                tkMessageBox.showwarning("Name exists", "Sheet name already exists!")
                return 0
        noshts = len(self.notebook.pagenames())
        if sheetname == None:
            sheetname = tkSimpleDialog.askstring("New sheet name?", "Enter sheet name:",
                                                initialvalue='sheet'+str(noshts+1))
        checksheet_name(sheetname)
        page = self.notebook.add(sheetname)
        #Create the table and model if data present
        if sheetdata != None:
            model = TableModel(sheetdata)
            self.currenttable = MyTable(page, model)
        else:
            self.currenttable = MyTable(page)

        #Load preferences into table
        self.currenttable.loadPrefs(self.preferences)
        #This handles all the canvas and header in the frame passed to constructor
        self.currenttable.createTableFrame()
        #add the table to the sheet dict
        self.sheets[sheetname] = self.currenttable
        self.saved = 0
        return sheetname

    def delete_Sheet(self):
        """Delete a sheet"""
        s = self.notebook.getcurselection()
        self.notebook.delete(s)
        del self.sheets[s]
        return

    def copy_Sheet(self, newname=None):
        """Copy a sheet"""
        newdata = self.currenttable.getModel().getData().copy()
        if newname==None:
            self.add_Sheet(None, newdata)
        else:
            self.add_Sheet(newname, newdata)
        return

    def rename_Sheet(self):
        """Rename a sheet"""
        s = self.notebook.getcurselection()
        newname = tkSimpleDialog.askstring("New sheet name?", "Enter new sheet name:",
                                                initialvalue=s)
        if newname == None:
            return
        self.copy_Sheet(newname)
        self.delete_Sheet()
        return

    def setcurrenttable(self, event):
        """Set the currenttable so that menu items work with visible sheet"""
        try:
            s = self.notebook.getcurselection()
            self.currenttable = self.sheets[s]
        except:
            pass
        return

    def add_Row(self):
        """Add a new row"""
        self.currenttable.add_Row()
        self.saved = 0
        return

    def delete_Row(self):
        """Delete currently selected row"""
        self.currenttable.delete_Row()
        self.saved = 0
        return

    def add_Column(self):
        """Add a new column"""
        self.currenttable.add_Column()
        self.saved = 0
        return

    def delete_Column(self):
        """Delete currently selected column in table"""
        self.currenttable.delete_Column()
        self.saved = 0
        return

    def autoAdd_Rows(self):
        """Auto add x rows"""
        self.currenttable.autoAdd_Rows()
        self.saved = 0
        return

    def autoAdd_Columns(self):
        """Auto add x rows"""
        self.currenttable.autoAdd_Columns()
        self.saved = 0
        return

    def findValue(self):
        self.currenttable.findValue()
        return

    def do_find_text(self, event=None):
        """Find the text in the table"""
        if not hasattr(self,'currenttable'):
            return
        import string
        if string.strip(self.findtext.get())=='':
            return
        searchstring=self.findtext.get()
        if self.currenttable!=None:
            self.currenttable.findValue(searchstring)
        return

    def do_find_again(self, event=None):
        """Find again"""
        if not hasattr(self,'currenttable'):
            return
        searchstring=self.findtext.get()
        if self.currenttable!=None:
            self.currenttable.findValue(searchstring, findagain=1)
        return

    def plot(self, event=None):
        self.currenttable.plot_Selected()
        return

    def plotSetup(self, event=None):
        self.currenttable.plotSetup()
        return

    def normal_view(self,event=None):
        self.currenttable.paging_Off()
        return

    def page_view(self,event=None):
        self.currenttable.paging = 1
        self.currenttable.redrawTable()
        return

    def about_Tables(self):
        self.ab_win=Toplevel()
        self.ab_win.geometry('+100+350')
        self.ab_win.title('About TablesApp')

        import Table_images
        logo = Table_images.tableapp_logo()
        label = Label(self.ab_win,image=logo)
        label.image = logo
        label.grid(row=0,column=0,sticky='news',padx=4,pady=4)

        text=['Tables Sample App ','Shows the use of Tablecanvas class for tkinter',
                'Copyright (C) Damien Farrell 2008', 'This program is free software; you can redistribute it and/or',
                'modify it under the terms of the GNU General Public License',
                'as published by the Free Software Foundation; either version 2',
                'of the License, or (at your option) any later version.']
        row=1
        for line in text:
            tmp=Label(self.ab_win,text=line)
            tmp.grid(row=row,column=0,sticky='news',padx=4)
            row=row+1
        return

    def online_documentation(self,event=None):
        """Open the online documentation"""
        import webbrowser
        link='http://sourceforge.net/projects/tkintertable/'
        webbrowser.open(link,autoraise=1)
        return

    def quit(self):
        self.tablesapp_win.destroy()

        return
Example #14
0
class Comparator(Frame, GUI_help):
    def __init__(self, parent=None, parentframe=None, DB=None, mode=None):
        """Instantiate class and check presence of DB data"""
        self.parent = parent
        if not self.parent:
            Frame.__init__(self)
            self.main = self.master
            self.main.title('PEAT Comparator')
            if DB == None:
                DB = self.openDB()
                if DB == None: return
        elif parentframe:
            self.main = Frame(master=parentframe)
            self.main.pack(fill=BOTH)
        else:
            self.main = Toplevel()
            self.main.title('Select Dataset')
            self.main.geometry('+300+200')
        if not self.parent:
            from Prefs import Preferences
            self.preferences = Preferences('PEAT', {})
        else:
            self.preferences = self.parent.preferences
        self.DB = DB
        self.Opt = Options(redraw=None)
        self.doGUI()
        return

    def openDB(self):
        import tkFileDialog
        filename = tkFileDialog.askopenfilename(defaultextension='.fs',
                                                initialdir=os.getcwd(),
                                                filetypes=[("zodb fs", "*.fs"),
                                                           ("All files", "*.*")
                                                           ])
        if filename != None:
            from Base import PDatabase
            DB = PDatabase(local=filename)
            return DB
        return None

    def doGUI(self):
        """Data selection dialog"""
        import tkFont
        dwin = self.main

        self.recs = self.DB.getRecs()
        fields = self.DB.getFields() + ['Structure']

        yscrollbar = Scrollbar(dwin, orient='vertical', width=12)
        yscrollbar.grid(row=1, column=2, sticky='news', padx=2)
        recsbox = Listbox(dwin,
                          bg='white',
                          exportselection=0,
                          height=18,
                          width=20,
                          yscrollcommand=yscrollbar.set,
                          selectmode=EXTENDED)
        yscrollbar.config(command=recsbox.yview)
        Label(dwin, text='Records:').grid(row=0, column=0, sticky='news')
        recsbox.grid(row=1,
                     column=0,
                     columnspan=2,
                     sticky='news',
                     padx=1,
                     pady=3)
        recsbox.config(state=NORMAL)

        y1scrollbar = Scrollbar(dwin, orient='vertical', width=12)
        y1scrollbar.grid(row=1, column=5, sticky='news', padx=2)
        colsbox = Listbox(dwin,
                          bg='white',
                          exportselection=0,
                          height=20,
                          width=20,
                          yscrollcommand=y1scrollbar.set,
                          selectmode=EXTENDED)

        y1scrollbar.config(command=colsbox.yview)
        Label(dwin, text='Fields:').grid(row=0, column=3, sticky='news')
        colsbox.grid(row=1,
                     column=3,
                     columnspan=2,
                     sticky='news',
                     padx=1,
                     pady=3)
        colsbox.config(state=NORMAL)
        dwin.rowconfigure(1, weight=1)
        dwin.columnconfigure(0, weight=1)
        for r in self.recs:
            recsbox.insert('end', r)
        for f in fields:
            colsbox.insert('end', f)

        def dorecslist():
            recsbox.delete(0, END)
            if srecsvar.get() == True:
                self.recs = self.parent.table.get_selectedRecordNames()
            else:
                self.recs = self.DB.getRecs()
            for r in self.recs:
                recsbox.insert('end', r)
            return

        other = Frame(dwin)
        other.grid(row=2,
                   column=0,
                   columnspan=7,
                   sticky='news',
                   padx=1,
                   pady=3)
        srecsvar = BooleanVar()
        srecsvar.set(False)
        Checkbutton(other,
                    text='use only selected records',
                    variable=srecsvar,
                    command=dorecslist).pack(side=LEFT, fill=BOTH)
        from Dialogs import PEATDialog
        self.pb = PEATDialog.createBusyBar(other)
        self.pb.pack(side=RIGHT, fill=BOTH, padx=5)
        d1 = Frame(dwin)
        d1.grid(row=1, column=6, columnspan=2, sticky='news', padx=1, pady=3)

        def display():
            srecs = [self.recs[int(item)] for item in recsbox.curselection()]
            sfields = [fields[int(item)] for item in colsbox.curselection()]
            slabel = entry1.getvalue()
            if len(srecs) == 0 or len(sfields) == 0:
                return
            g = groupby.getcurselection()

            if 'Structure' in sfields:
                self.displayStructure(srecs)
                sfields.remove('Structure')
            self.displayEkin(srecs,
                             sfields,
                             slabel,
                             html=htmlvar.get(),
                             overlay=overlayvar.get(),
                             groupby=g)

            return

        def preview():
            srecs = [self.recs[int(item)] for item in recsbox.curselection()]
            sfields = [fields[int(item)] for item in colsbox.curselection()]
            if len(srecs) == 0 or len(sfields) == 0:
                st.insert(END, 'Choose recs/fields!')
                return
            st.delete(1.0, END)
            slabel = entry1.getvalue()
            sl = self.findNames(srecs, sfields, slabel)
            st.insert(END, str(sl))
            return

        def closedialog():
            dwin.destroy()
            if not self.parent:
                sys.exit()
            return

        entry1 = Pmw.EntryField(d1,
                                labelpos='n',
                                value='',
                                command=preview,
                                label_text='Data label:')
        entry1.pack(side=TOP, fill=BOTH)
        Button(d1, text='Preview', command=preview).pack(side=TOP, fill=BOTH)
        Button(d1, text='Plot Options',
               command=self.Opt.plotSetup).pack(side=TOP, fill=BOTH)
        groupby = Pmw.OptionMenu(d1,
                                 labelpos='w',
                                 label_text='Group By:',
                                 items=('field', 'record', 'none'),
                                 menubutton_width=8)
        groupby.pack(side=TOP, fill=BOTH)
        htmlvar = BooleanVar()
        htmlvar.set(False)
        overlayvar = BooleanVar()
        overlayvar.set(False)
        self.orientvar = BooleanVar()
        self.orientvar.set(False)
        Button(d1, text='Display', command=display,
               bg='#FFFF99').pack(side=TOP, fill=BOTH)
        #Checkbutton(d1, text='send to web page', variable=htmlvar).pack(side=TOP,fill=BOTH)
        Checkbutton(d1, text='overlay plots',
                    variable=overlayvar).pack(side=TOP, fill=BOTH)
        Checkbutton(d1, text='orient vertical',
                    variable=self.orientvar).pack(side=TOP, fill=BOTH)
        st = Pmw.ScrolledText(d1,
                              labelpos='n',
                              label_text='Data Labels found:',
                              usehullsize=1,
                              hull_width=200,
                              hull_height=220,
                              text_wrap='char')
        st.pack(side=TOP, fill=BOTH)
        Button(d1, text='Close', command=closedialog).pack(side=TOP, fill=BOTH)

        return

    def findNames(self, srecs, sfields, slabel):
        """Get datasets list from search string"""
        if slabel == '':
            s = re.compile('[a-z]*\d', re.IGNORECASE)
        else:
            s = re.compile(slabel, re.IGNORECASE)
        slabels = []
        for r in srecs:
            rec = self.DB[r]
            for f in sfields:
                if f == 'Structure':
                    if rec.Structure != None:
                        slabels.append('has structure')
                    continue
                self.pb.update()
                ftype = self.DB.userfields[f]['field_type']

                if not rec.has_key(f):
                    continue
                E = rec[f]
                for d in E.datasets:
                    self.pb.update()
                    if s.match(d) and not d in slabels:
                        slabels.append(d)
        return slabels

    def displayStructure(self, srecs):
        """Display a structure"""
        app = self.preferences.get('molgraphApplication')
        path = self.preferences.get('molgraphAppPath')
        DBActions.DB = self.DB
        if DBActions.yasara != None:
            DBActions.yasara.Clear()

        colors = ['green', 250, 270, 290, 310, 320, 340]
        i = 0
        for r in srecs:
            color = colors[i]
            i += 1
            DBActions.displayStructure(r, 'Structure', app, path, color, False)

        #try to align objects
        Y = DBActions.yasara
        if hasattr(Y, 'objects') and len(Y.objects) > 1:
            Y.AlignMultiAll()
        return

    def displayEkin(self,
                    srecs,
                    sfields,
                    slabel='',
                    html=False,
                    overlay=False,
                    cols=None,
                    groupby='field'):
        """Format and display ekin plots from given recs/fields/label,
           plots can be grouped according to field if required"""

        from Ekin.Base import EkinProject
        tmppath = os.getcwd()
        slabels = self.findNames(srecs, sfields, slabel)
        all_labels = self.findNames(srecs, sfields, '')
        if len(slabels) == 0:
            return

        def insert(En, r, f, grp='field'):
            """reused in both loops"""
            E = self.DB[r][f]
            for d in all_labels:
                edata = E.getDataset(d)
                if edata != None:
                    if grp == 'field':
                        name = r + ' ' + d
                    elif grp == 'record':
                        name = f + ' ' + d
                    else:
                        name = r + ' ' + f + ' ' + d
                    En.insertDataset(edata,
                                     name,
                                     fit=E.getFitData(d),
                                     replace=True)

        #create ekinprojects grouped by field or record, or just one big one
        ekprojects = {}

        if groupby == 'none':
            En = ekprojects['all'] = EkinProject()
        if groupby == 'field' or groupby == 'none':
            for f in sfields:
                if groupby == 'field':
                    En = ekprojects[f] = EkinProject()
                for r in srecs:
                    if not self.DB[r].has_key(f):
                        continue
                    insert(En, r, f, grp=groupby)
        elif groupby == 'record':
            for r in srecs:
                En = ekprojects[r] = EkinProject()
                for f in sfields:
                    if not self.DB[r].has_key(f):
                        continue
                    insert(En, r, f, grp=groupby)

        if html == True:
            from Ekin.Web import EkinWeb
            ew = EkinWeb()
            dirs = ['plots', 'csv']
            for p in dirs:
                if not os.path.exists(os.path.join(tmppath, p)):
                    os.mkdir(os.path.join(tmppath, p))
                    ew.showEkinPlots(project=En,
                                     outfile=os.path.join(
                                         tmppath, 'plots.html'),
                                     imgpath=os.path.join(tmppath, 'plots'),
                                     path='plots/',
                                     title='PEAT plots',
                                     columns=3)
            import webbrowser
            webbrowser.open('plots.html', autoraise=1)
        else:
            if groupby == 'field': t = sfields
            else: t = srecs
            if self.orientvar.get() == 1: orient = VERTICAL
            else: orient = HORIZONTAL
            cwin = ComparatorWin('Comparing %s' % t,
                                 labels=all_labels,
                                 selected=slabels,
                                 orient=orient)
            cwin.Opt = self.Opt
            for e in ekprojects:
                En = ekprojects[e]
                En.name = e
                plotframe = cwin.add(E=En, selected=slabels, overlay=overlay)
            cwin.configSize()

        return
Example #15
0
 def getClustalPath(self):
     from Prefs import Preferences
     preferences = Preferences('DNATool2', {})
     return preferences.get('clustalpath')
Example #16
0
    def __init__(self,
                 parent=None,
                 peatinfo=None,
                 title=None,
                 data=None,
                 datafile=None):
        "Initialize the application."
        self.parent = parent

        #If there is data to be loaded, show the dialog first
        if self.parent == None:
            Frame.__init__(self)
            self.labbook_win = self.master
            self.peatinfo = None
        else:
            self.labbook_win = Toplevel()
            self.master = self.labbook_win
            self.peatinfo = peatinfo  #reference to peat protein/field
            self.DB = self.parent.DB  #ref to peat

        if title != None:
            self.title = 'subtable_' + title
        else:
            self.title = 'Labbook Tool'

        self.ID = 'Labbook'
        # Get platform into a variable
        import platform
        self.currplatform = platform.system()
        if not hasattr(self, 'defaultsavedir'):
            self.defaultsavedir = os.getcwd()

        self.preferences = Preferences('Labbook', {'check_for_update': 1})
        #self.loadprefs()
        if self.peatinfo:
            protein = self.peatinfo['record']
            field_name = self.peatinfo['column']
            self.labbook_win.title('Labbook: ' + protein + '_' + field_name)
        else:
            self.labbook_win.title(self.title)
        self.labbook_win.geometry('+200+100')
        self.x_size = 1000
        self.y_size = 500
        self.createMenuBar()
        self.apptoolBar = ToolBar(self.labbook_win, self)
        self.apptoolBar.pack(fill=BOTH, expand=NO)
        #add find bar
        #self.createSearchBar()

        if data != None:
            self.data = data
            self.new_project(data)
        elif datafile != None:
            self.open_project(filename=datafile)
        else:
            self.new_project()
        #add return to main PEAT db button
        if self.parent:
            Button(self.labbook_win,
                   text="Return to Database",
                   command=self.return_data).pack()
        self.labbook_win.protocol('WM_DELETE_WINDOW', self.quit)
        self.createBindings()
        self.clipboard = None
        return
Example #17
0
class TablesApp(Frame):
    """
    Tables app
    """
    def __init__(self, parent=None, data=None, datafile=None):
        "Initialize the application."
        self.parent = parent

        #If there is data to be loaded, show the dialog first
        if not self.parent:
            Frame.__init__(self)
            self.tablesapp_win = self.master

        else:
            self.tablesapp_win = Toplevel()

        # Get platform into a variable
        import platform
        self.currplatform = platform.system()
        if not hasattr(self, 'defaultsavedir'):
            self.defaultsavedir = os.getcwd()

        self.preferences = Preferences('TablesApp', {'check_for_update': 1})
        self.loadprefs()
        self.tablesapp_win.title('Tables Application')
        self.tablesapp_win.geometry('+200+200')
        self.x_size = 800
        self.y_size = 600
        self.createMenuBar()
        self.apptoolBar = ToolBar(self.tablesapp_win, self)
        self.apptoolBar.pack(fill=BOTH, expand=NO)
        #add find bar
        #self.createSearchBar()

        if data != None:
            self.data = data
            self.new_project(data)
        elif datafile != None:
            self.open_project(datafile)
        else:
            self.new_project()

        self.tablesapp_win.protocol('WM_DELETE_WINDOW', self.quit)
        return

    def createMenuBar(self):
        """Create the menu bar for the application. """
        self.menu = Menu(self.tablesapp_win)
        self.proj_menu = {
            '01New': {
                'cmd': self.new_project
            },
            '02Open': {
                'cmd': self.open_project
            },
            '03Close': {
                'cmd': self.close_project
            },
            '04Save': {
                'cmd': self.save_project
            },
            '05Save As': {
                'cmd': self.save_as_project
            },
            '06Preferences..': {
                'cmd': self.showPrefsDialog
            },
            '08Quit': {
                'cmd': self.quit
            }
        }
        if self.parent:
            self.proj_menu['08Return to Database'] = {'cmd': self.return_data}
        self.proj_menu = self.create_pulldown(self.menu, self.proj_menu)
        self.menu.add_cascade(label='Project', menu=self.proj_menu['var'])

        self.records_menu = {
            '01Add Row': {
                'cmd': self.add_Row
            },
            '02Delete Row': {
                'cmd': self.delete_Row
            },
            '03Add Column': {
                'cmd': self.add_Column
            },
            '04Delete Column': {
                'cmd': self.delete_Column
            },
            '05Auto Add Rows': {
                'cmd': self.autoAdd_Rows
            },
            '06Auto Add Columns': {
                'cmd': self.autoAdd_Columns
            },
            '07Find': {
                'cmd': self.createSearchBar
            },
        }
        self.records_menu = self.create_pulldown(self.menu, self.records_menu)
        self.menu.add_cascade(label='Records', menu=self.records_menu['var'])

        self.sheet_menu = {
            '01Add Sheet': {
                'cmd': self.add_Sheet
            },
            '02Remove Sheet': {
                'cmd': self.delete_Sheet
            },
            '03Copy Sheet': {
                'cmd': self.copy_Sheet
            },
            '04Rename Sheet': {
                'cmd': self.rename_Sheet
            },
        }
        self.sheet_menu = self.create_pulldown(self.menu, self.sheet_menu)
        self.menu.add_cascade(label='Sheet', menu=self.sheet_menu['var'])

        self.IO_menu = {
            '01Import from csv file': {
                'cmd': self.import_cvs
            },
            '02Export to csv file': {
                'cmd': self.export_cvs
            },
        }

        self.IO_menu = self.create_pulldown(self.menu, self.IO_menu)
        self.menu.add_cascade(label='Import/Export', menu=self.IO_menu['var'])

        self.view_menu = Menu(self.menu, tearoff=0)
        self.view_menu.add_radiobutton(label="Normal View",
                                       state=ACTIVE,
                                       command=self.normal_view)
        self.view_menu.add_radiobutton(label="Page View",
                                       command=self.page_view)
        self.menu.add_cascade(label='View', menu=self.view_menu)

        #
        # Help menu
        #
        self.help_menu = {
            '01Online Help': {
                'cmd': self.online_documentation
            },
            '02About': {
                'cmd': self.about_Tables
            }
        }
        self.help_menu = self.create_pulldown(self.menu, self.help_menu)
        self.menu.add_cascade(label='Help', menu=self.help_menu['var'])

        self.tablesapp_win.config(menu=self.menu)

        return

    def create_pulldown(self, menu, dict):
        #
        # Create a pulldown in var from the info in dict
        #
        var = Menu(menu, tearoff=0)
        items = dict.keys()
        items.sort()
        for item in items:
            if item[-3:] == 'sep':
                var.add_separator()
            else:
                #
                # Do we have a command?
                #
                command = None
                if dict[item].has_key('cmd'):
                    command = dict[item]['cmd']
                #
                # Put the command in there
                #
                if dict[item].has_key('sc'):
                    var.add_command(label='%-25s %9s' %
                                    (item[2:], dict[item]['sc']),
                                    command=command)
                else:
                    var.add_command(label='%-25s' % (item[2:]),
                                    command=command)
        dict['var'] = var
        return dict

    def createSearchBar(self, event=None):
        """Add a find entry box"""
        frame = Frame(self.tablesapp_win)
        row = 0

        def close():
            frame.destroy()

        self.findtext = StringVar()
        self.findbox = Entry(frame,
                             textvariable=self.findtext,
                             width=30,
                             bg='white')
        self.findbox.grid(row=row,
                          column=1,
                          sticky='news',
                          columnspan=2,
                          padx=2,
                          pady=2)
        self.findbox.bind('<Return>', self.do_find_text)
        Label(frame, text='Find:').grid(row=row, column=0, sticky='ew')
        self.findagainbutton = Button(frame,
                                      text='Find Again',
                                      command=self.do_find_again)
        self.findagainbutton.grid(row=row,
                                  column=3,
                                  sticky='news',
                                  padx=2,
                                  pady=2)
        self.cbutton = Button(frame, text='Close', command=close)
        self.cbutton.grid(row=row, column=4, sticky='news', padx=2, pady=2)
        frame.pack(fill=BOTH, expand=NO)
        return

    def loadprefs(self):
        """Setup default prefs file if any of the keys are not present"""
        defaultprefs = {
            'textsize': 14,
            'windowwidth': 800,
            'windowheight': 600
        }
        for prop in defaultprefs.keys():
            try:
                self.preferences.get(prop)
            except:
                self.preferences.set(prop, defaultprefs[prop])

        return

    def showPrefsDialog(self):
        self.prefswindow = self.currenttable.showtablePrefs()

        return

    def new_project(self, data=None):
        """Create a new table, with model and add the frame"""
        if hasattr(self, 'currenttable'):
            self.notebook.destroy()
            self.currenttable.destroy()

        #Create the sheets dict
        self.sheets = {}
        self.notebook = Pmw.NoteBook(self.tablesapp_win,
                                     raisecommand=self.setcurrenttable)
        self.notebook.pack(fill='both', expand=1, padx=4, pady=4)
        if data != None:
            for s in data.keys():
                sdata = data[s]
                try:
                    self.add_Sheet(s, sdata)
                except:
                    print 'skipping'
        else:
            #do the table adding stuff for the initial sheet
            self.add_Sheet('sheet1')
        self.notebook.setnaturalsize()
        return

    def open_project(self, filename=None):
        if filename == None:
            filename = tkFileDialog.askopenfilename(
                defaultextension='.tbleprj"',
                initialdir=os.getcwd(),
                filetypes=[("Pickle file", "*.tbleprj"), ("All files", "*.*")],
                parent=self.tablesapp_win)
        if os.path.isfile(filename):
            fd = open(filename)
            data = pickle.load(fd)
            fd.close()
        self.new_project(data)
        self.filename = filename
        return

    def save_project(self):
        if not hasattr(self, 'filename'):
            self.save_as_project()
        elif self.filename == None:
            self.save_as_project()
        else:
            self.do_save_project(self.filename)

        return

    def save_as_project(self):
        """Save as a new filename"""
        filename = tkFileDialog.asksaveasfilename(
            parent=self.tablesapp_win,
            defaultextension='.tblprj',
            initialdir=self.defaultsavedir,
            filetypes=[("TableApp project", "*.tblprj"), ("All files", "*.*")])
        if not filename:
            print 'Returning'
            return
        self.filename = filename
        self.do_save_project(self.filename)
        return

    def do_save_project(self, filename):
        """Get model dicts and write all to pickle file"""
        data = {}
        for s in self.sheets.keys():
            currtable = self.sheets[s]
            model = currtable.getModel()
            data[s] = model.getData()

        fd = open(filename, 'w')
        pickle.dump(data, fd)
        fd.close()
        return

    def close_project(self):
        if hasattr(self, 'currenttable'):
            #self.notebook.destroy()
            self.currenttable.destroy()
        return

    def import_cvs(self):
        importer = TableImporter()
        #datafile = importer.open_File(self.tablesapp_win)

        #just use the dialog to load and import the file
        importdialog = importer.import_Dialog(self.tablesapp_win)
        self.tablesapp_win.wait_window(importdialog)
        model = TableModel()
        model.importDict(importer.data)
        sheetdata = {}
        sheetdata['sheet1'] = model.getData()
        self.new_project(sheetdata)
        return

    def export_cvs(self):
        exporter = TableExporter()
        exporter.ExportTableData(self.currenttable)
        return

    def add_Sheet(self, sheetname=None, sheetdata=None):
        """Add a new sheet - handles all the table creation stuff"""
        def checksheet_name(name):
            if name == '':
                tkMessageBox.showwarning("Whoops", "Name should not be blank.")
                return 0
            if self.sheets.has_key(name):
                tkMessageBox.showwarning("Name exists",
                                         "Sheet name already exists!")
                return 0

        noshts = len(self.notebook.pagenames())
        if sheetname == None:
            sheetname = tkSimpleDialog.askstring("New sheet name?",
                                                 "Enter sheet name:",
                                                 initialvalue='sheet' +
                                                 str(noshts + 1))
        checksheet_name(sheetname)
        page = self.notebook.add(sheetname)
        #Create the table and model if data present
        if sheetdata != None:
            model = TableModel(sheetdata)
            self.currenttable = MyTable(page, model)
        else:
            self.currenttable = MyTable(page)

        #Load preferences into table
        self.currenttable.loadPrefs(self.preferences)
        #This handles all the canvas and header in the frame passed to constructor
        self.currenttable.createTableFrame()
        #add the table to the sheet dict
        self.sheets[sheetname] = self.currenttable
        self.saved = 0
        return sheetname

    def delete_Sheet(self):
        """Delete a sheet"""
        s = self.notebook.getcurselection()
        self.notebook.delete(s)
        del self.sheets[s]
        return

    def copy_Sheet(self, newname=None):
        """Copy a sheet"""
        newdata = self.currenttable.getModel().getData().copy()
        if newname == None:
            self.add_Sheet(None, newdata)
        else:
            self.add_Sheet(newname, newdata)
        return

    def rename_Sheet(self):
        """Rename a sheet"""
        s = self.notebook.getcurselection()
        newname = tkSimpleDialog.askstring("New sheet name?",
                                           "Enter new sheet name:",
                                           initialvalue=s)
        if newname == None:
            return
        self.copy_Sheet(newname)
        self.delete_Sheet()
        return

    def setcurrenttable(self, event):
        """Set the currenttable so that menu items work with visible sheet"""
        try:
            s = self.notebook.getcurselection()
            self.currenttable = self.sheets[s]
        except:
            pass
        return

    def add_Row(self):
        """Add a new row"""
        self.currenttable.add_Row()
        self.saved = 0
        return

    def delete_Row(self):
        """Delete currently selected row"""
        self.currenttable.delete_Row()
        self.saved = 0
        return

    def add_Column(self):
        """Add a new column"""
        self.currenttable.add_Column()
        self.saved = 0
        return

    def delete_Column(self):
        """Delete currently selected column in table"""
        self.currenttable.delete_Column()
        self.saved = 0
        return

    def autoAdd_Rows(self):
        """Auto add x rows"""
        self.currenttable.autoAdd_Rows()
        self.saved = 0
        return

    def autoAdd_Columns(self):
        """Auto add x rows"""
        self.currenttable.autoAdd_Columns()
        self.saved = 0
        return

    def findValue(self):
        self.currenttable.findValue()
        return

    def do_find_text(self, event=None):
        """Find the text in the table"""
        if not hasattr(self, 'currenttable'):
            return
        import string
        if string.strip(self.findtext.get()) == '':
            return
        searchstring = self.findtext.get()
        if self.currenttable != None:
            self.currenttable.findValue(searchstring)
        return

    def do_find_again(self, event=None):
        """Find again"""
        if not hasattr(self, 'currenttable'):
            return
        searchstring = self.findtext.get()
        if self.currenttable != None:
            self.currenttable.findValue(searchstring, findagain=1)
        return

    def plot(self, event=None):
        self.currenttable.plot_Selected()
        return

    def plotSetup(self, event=None):
        self.currenttable.plotSetup()
        return

    def normal_view(self, event=None):
        self.currenttable.paging_Off()
        return

    def page_view(self, event=None):
        self.currenttable.paging = 1
        self.currenttable.redrawTable()
        return

    def about_Tables(self):
        self.ab_win = Toplevel()
        self.ab_win.geometry('+100+350')
        self.ab_win.title('About TablesApp')

        import Table_images
        logo = Table_images.tableapp_logo()
        label = Label(self.ab_win, image=logo)
        label.image = logo
        label.grid(row=0, column=0, sticky='news', padx=4, pady=4)

        text = [
            'Tables Sample App ',
            'Shows the use of Tablecanvas class for tkinter',
            'Copyright (C) Damien Farrell 2008',
            'This program is free software; you can redistribute it and/or',
            'modify it under the terms of the GNU General Public License',
            'as published by the Free Software Foundation; either version 2',
            'of the License, or (at your option) any later version.'
        ]
        row = 1
        for line in text:
            tmp = Label(self.ab_win, text=line)
            tmp.grid(row=row, column=0, sticky='news', padx=4)
            row = row + 1
        return

    def online_documentation(self, event=None):
        """Open the online documentation"""
        import webbrowser
        link = 'http://sourceforge.net/projects/tkintertable/'
        webbrowser.open(link, autoraise=1)
        return

    def quit(self):
        self.tablesapp_win.destroy()

        return
Example #18
0
class Comparator(Frame, GUI_help):

    def __init__(self, parent=None, parentframe=None, DB=None, mode=None):
        """Instantiate class and check presence of DB data"""
        self.parent = parent
        if not self.parent:
            Frame.__init__(self)
            self.main=self.master
            self.main.title('PEAT Comparator')
            if DB == None:
                DB = self.openDB()
                if DB==None: return
        elif parentframe:
            self.main = Frame(master=parentframe)
            self.main.pack(fill=BOTH)
        else:
            self.main=Toplevel()
            self.main.title('Select Dataset')
            self.main.geometry('+300+200')
        if not self.parent:
            from Prefs import Preferences
            self.preferences=Preferences('PEAT',{})
        else:
            self.preferences=self.parent.preferences        
        self.DB = DB
        self.Opt = Options(redraw=None)
        self.doGUI()
        return

    def openDB(self):
        import tkFileDialog
        filename=tkFileDialog.askopenfilename(defaultextension='.fs',
                                       initialdir=os.getcwd(),
                                       filetypes=[("zodb fs","*.fs"),("All files","*.*")])
        if filename != None:        
            from Base import PDatabase
            DB = PDatabase(local=filename)
            return DB
        return None
        
    def doGUI(self):
        """Data selection dialog"""
        import tkFont
        dwin = self.main
        
        self.recs = self.DB.getRecs()
        fields = self.DB.getFields() + ['Structure']

        yscrollbar=Scrollbar(dwin,orient='vertical',width=12)
        yscrollbar.grid(row=1,column=2,sticky='news',padx=2)
        recsbox=Listbox(dwin,bg='white',
                         exportselection=0,
                         height=18,
                         width=20,
                         yscrollcommand=yscrollbar.set,
                         selectmode=EXTENDED)
        yscrollbar.config(command=recsbox.yview)
        Label(dwin,text='Records:').grid(row=0,column=0,sticky='news')
        recsbox.grid(row=1,column=0,columnspan=2,sticky='news',padx=1,pady=3)
        recsbox.config(state=NORMAL)

        y1scrollbar=Scrollbar(dwin,orient='vertical',width=12)
        y1scrollbar.grid(row=1,column=5,sticky='news',padx=2)
        colsbox=Listbox(dwin,bg='white',
                         exportselection=0,
                         height=20,
                         width=20,
                         yscrollcommand=y1scrollbar.set,
                         selectmode=EXTENDED)

        y1scrollbar.config(command=colsbox.yview)
        Label(dwin,text='Fields:').grid(row=0,column=3,sticky='news')
        colsbox.grid(row=1,column=3,columnspan=2,sticky='news',padx=1,pady=3)
        colsbox.config(state=NORMAL)
        dwin.rowconfigure(1, weight=1)
        dwin.columnconfigure(0, weight=1)
        for r in self.recs:
            recsbox.insert('end', r)
        for f in fields:
            colsbox.insert('end', f)

        def dorecslist():
            recsbox.delete(0, END)
            if srecsvar.get() == True:
                self.recs = self.parent.table.get_selectedRecordNames()
            else:
                self.recs = self.DB.getRecs()
            for r in self.recs:
                recsbox.insert('end', r)
            return

        other = Frame(dwin)
        other.grid(row=2,column=0,columnspan=7,sticky='news',padx=1,pady=3)
        srecsvar = BooleanVar(); srecsvar.set(False)
        Checkbutton(other, text='use only selected records', variable=srecsvar,
                        command=dorecslist).pack(side=LEFT,fill=BOTH)
        from Dialogs import PEATDialog
        self.pb=PEATDialog.createBusyBar(other)
        self.pb.pack(side=RIGHT,fill=BOTH,padx=5)
        d1 = Frame(dwin)
        d1.grid(row=1,column=6,columnspan=2,sticky='news',padx=1,pady=3)

        def display():
            srecs = [self.recs[int(item)] for item in recsbox.curselection()]
            sfields = [fields[int(item)] for item in colsbox.curselection()]
            slabel = entry1.getvalue()
            if len(srecs)==0 or len(sfields)==0:
                return
            g=groupby.getcurselection()

            if 'Structure' in sfields:
                self.displayStructure(srecs)         
                sfields.remove('Structure')    
            self.displayEkin(srecs, sfields, slabel, html=htmlvar.get(),
                               overlay=overlayvar.get(), groupby=g)
            
            return

        def preview():
            srecs = [self.recs[int(item)] for item in recsbox.curselection()]
            sfields = [fields[int(item)] for item in colsbox.curselection()]
            if len(srecs)==0 or len(sfields)==0:
                st.insert(END, 'Choose recs/fields!')
                return
            st.delete(1.0, END)
            slabel = entry1.getvalue()            
            sl = self.findNames(srecs, sfields, slabel)
            st.insert(END, str(sl))
            return

        def closedialog():
            dwin.destroy()
            if not self.parent:
                sys.exit()
            return

        entry1 = Pmw.EntryField(d1,
                    labelpos = 'n',
                    value = '',
                    command=preview,
                    label_text = 'Data label:')
        entry1.pack(side=TOP,fill=BOTH)
        Button(d1, text='Preview', command=preview).pack(side=TOP,fill=BOTH)
        Button(d1, text='Plot Options', command=self.Opt.plotSetup).pack(side=TOP,fill=BOTH)
        groupby = Pmw.OptionMenu (d1,
                labelpos = 'w',
                label_text = 'Group By:',
                items = ('field','record','none'),
                menubutton_width = 8 )
        groupby.pack(side=TOP,fill=BOTH)
        htmlvar = BooleanVar(); htmlvar.set(False)
        overlayvar = BooleanVar(); overlayvar.set(False)
        self.orientvar = BooleanVar(); self.orientvar.set(False)
        Button(d1, text='Display', command=display, bg='#FFFF99').pack(side=TOP,fill=BOTH)
        #Checkbutton(d1, text='send to web page', variable=htmlvar).pack(side=TOP,fill=BOTH)        
        Checkbutton(d1, text='overlay plots', variable=overlayvar).pack(side=TOP,fill=BOTH)
        Checkbutton(d1, text='orient vertical', variable=self.orientvar).pack(side=TOP,fill=BOTH)
        st = Pmw.ScrolledText(d1,
                labelpos = 'n',
                label_text='Data Labels found:',
                usehullsize = 1,
                hull_width = 200,
                hull_height = 220,
                text_wrap='char')
        st.pack(side=TOP,fill=BOTH)
        Button(d1, text='Close', command=closedialog).pack(side=TOP,fill=BOTH)

        return

    def findNames(self, srecs, sfields, slabel):
        """Get datasets list from search string"""
        if slabel == '':
            s = re.compile('[a-z]*\d',re.IGNORECASE)
        else:
            s = re.compile(slabel, re.IGNORECASE)
        slabels = []
        for r in srecs:
            rec = self.DB[r]
            for f in sfields:
                if f == 'Structure':
                    if rec.Structure != None:                    
                        slabels.append('has structure')
                    continue
                self.pb.update()
                ftype = self.DB.userfields[f]['field_type']

                if not rec.has_key(f):
                    continue
                E = rec[f]
                for d in E.datasets:
                    self.pb.update()
                    if s.match(d) and not d in slabels:
                        slabels.append(d)
        return slabels

    def displayStructure(self, srecs):
        """Display a structure"""
        app = self.preferences.get('molgraphApplication')
        path = self.preferences.get('molgraphAppPath')
        DBActions.DB = self.DB
        if DBActions.yasara != None:
            DBActions.yasara.Clear()

        colors = ['green',250,270,290,310,320,340]
        i=0
        for r in srecs:
            color = colors[i]
            i+=1
            DBActions.displayStructure(r, 'Structure', app, path, color, False)

        #try to align objects
        Y = DBActions.yasara
        if hasattr(Y, 'objects') and len(Y.objects)>1:
            Y.AlignMultiAll()
        return
   
    def displayEkin(self, srecs, sfields, slabel='', html=False,
                        overlay=False, cols=None, groupby='field'):
        """Format and display ekin plots from given recs/fields/label,
           plots can be grouped according to field if required"""

        from Ekin.Base import EkinProject
        tmppath = os.getcwd()
        slabels = self.findNames(srecs, sfields, slabel)
        all_labels = self.findNames(srecs, sfields, '')
        if len(slabels) == 0:
            return

        def insert(En, r, f, grp='field'):
            """reused in both loops"""
            E = self.DB[r][f]
            for d in all_labels:
                edata = E.getDataset(d)
                if edata != None:
                    if grp=='field':
                        name = r+' '+d
                    elif grp=='record':
                        name = f+' '+d
                    else:
                        name = r+' '+f+' '+d
                    En.insertDataset(edata, name,
                                     fit=E.getFitData(d), replace=True)

        #create ekinprojects grouped by field or record, or just one big one
        ekprojects = {}
        
        if groupby == 'none':
            En = ekprojects['all'] = EkinProject()
        if groupby == 'field' or groupby == 'none':
            for f in sfields:
                if groupby == 'field':
                    En = ekprojects[f] = EkinProject()
                for r in srecs:
                    if not self.DB[r].has_key(f):
                        continue
                    insert(En, r, f, grp=groupby)
        elif groupby == 'record':
            for r in srecs:
                En = ekprojects[r] = EkinProject()
                for f in sfields:
                    if not self.DB[r].has_key(f):
                        continue
                    insert(En, r, f, grp=groupby)

        if html == True:
            from Ekin.Web import EkinWeb
            ew = EkinWeb()
            dirs=['plots', 'csv']
            for p in dirs:
                if not os.path.exists(os.path.join(tmppath, p)):
                    os.mkdir(os.path.join(tmppath, p))
                    ew.showEkinPlots(project=En,
                              outfile=os.path.join(tmppath, 'plots.html'),
                              imgpath=os.path.join(tmppath, 'plots'),
                              path='plots/',
                              title='PEAT plots',
                              columns=3)
            import webbrowser
            webbrowser.open('plots.html',autoraise=1)
        else:
            if groupby=='field': t=sfields
            else: t=srecs
            if self.orientvar.get() == 1: orient=VERTICAL
            else: orient = HORIZONTAL
            cwin = ComparatorWin('Comparing %s' %t, labels=all_labels,
                                 selected=slabels, orient=orient)
            cwin.Opt = self.Opt
            for e in ekprojects:
                En = ekprojects[e]
                En.name = e                
                plotframe = cwin.add(E=En, selected=slabels, overlay=overlay)
            cwin.configSize()

        return       
Example #19
0
class App(Frame, GUI_help):
    """Data pipe GUI for importing and fitting of raw data.
       This class uses ekin provided an automated pipeline for fitting
       raw text data files and propagating errors.
       Uses a config file to store the pipeline settings"""
    def __init__(self, parent=None, rawfile=None, conffile=None):

        self.parent = parent
        if not self.parent:
            Frame.__init__(self)
            self.main = self.master
        else:
            self.main = Toplevel()
            self.master = self.main
        self.main.title('DNATool Desktop')
        self.main.protocol('WM_DELETE_WINDOW', self.quit)

        self.defaultprefs = {
            'rememberwindowsize': 0,
            'orientation': 'horizontal',
            'alignmenttool': 'clustal',
            'clustalpath': 'clustalw'
        }
        self.defaultopts = [
            ('rememberwindowsize', 'checkbutton', 1, 'Remember window size'),
            ('orientation', 'menu', ('horizontal', 'vertical'),
             'Default sideframe orientation'),
            ('alignmenttool', 'menu', ('clustal', 'muscle', 'needle'),
             'External alignment tool'),
            ('clustalpath', 'entry', '', 'Path to Clustal')
        ]
        self.loadPrefs()
        self.setGeometry()
        self.P = Project()
        self.primerdb = PrimerDatabase()
        self.setupApps()
        self.setupGUI()
        self.sidepane.selectpage('PrimerDB')
        return

    def setGeometry(self):
        if self.rememberwindowsize == 1 and self.preferences.has_key(
                'lastwindowsize'):
            lastwindowsize = self.preferences.get('lastwindowsize')
            self.winsize = lastwindowsize
            #self.w = int(lastwindowsize.split('x')[0])
        else:
            self.winsize = self.getBestGeometry()
        self.main.geometry(self.winsize)

        return

    def getBestGeometry(self):
        """Calculate optimal geometry from screen size"""
        ws = self.main.winfo_screenwidth()
        hs = self.main.winfo_screenheight()
        self.w = w = ws / 1.3
        h = 500
        x = (ws / 2) - (w / 2)
        y = (hs / 2) - (h / 2)
        g = '%dx%d+%d+%d' % (w, h, x, y)
        return g

    def saveGeometry(self):
        """Save current geometry before quitting"""
        g = self.main.geometry()
        self.preferences.set('lastwindowsize', g)
        return

    def setupApps(self):
        """Creates a dict of classes so that GUI frames like primer design
           can be dynamically added without explicit methods for each"""
        self.apps = {
            'Primer Design': PrimerDesignGUI,
            'ORF Overview': ORFOverview,
            'Sequence Analysis': SequenceAnalysis,
            'Sequence Alignment Tool': SequenceAlignmentTool,
            'Restriction Digest Summary': RestrictionDigestSummary,
            'Blast Interface': BlastInterface,
            'NotePad': TextEditor
        }
        return

    def loadPrefs(self):
        """Load prefs from a preferences instance"""
        self.preferences = Preferences('DNATool2', {})
        temp = {}
        for key in self.defaultprefs:
            if not key in self.preferences.prefs:
                self.preferences.set(key, self.defaultprefs[key])
            temp[key] = self.preferences.get(key)
        self.applyPrefs(temp)
        return

    def savePrefs(self):
        """Save prefs to a preferences instance"""
        self.applyPrefs(self.prefsdialog.getValues())
        self.preferences = Preferences('DNATool2', {})
        for key in self.defaultprefs:
            self.preferences.set(key, self.__dict__[key])
        return

    def applyPrefs(self, prefs=None):
        """Apply prefs from a given dict"""
        if prefs == None: prefs = self.defaultprefs
        for key in prefs:
            self.__dict__[key] = prefs[key]
        return

    def setupGUI(self):
        """Do GUI elements"""
        self.visibleapps = {}
        #bottom panel
        bottom = Frame(self.main, height=50)
        bottom.pack(side=BOTTOM, fill=BOTH, pady=1)
        #status bar
        sb = self.addStatusBar(bottom)
        tb = self.addWindowToolBar(bottom)
        tb.pack(side=LEFT, anchor='e', expand=1)

        self.m = PanedWindow(self.main,
                             orient=self.orientation,
                             sashwidth=2,
                             showhandle=True)
        self.m.pack(side=TOP, fill=BOTH, pady=2, expand=1)

        sc = self.sc = SequenceCanvas(self.m,
                                      parentapp=self,
                                      width=900,
                                      height=800)
        sc.pack(side=TOP, fill=BOTH, pady=2)
        self.m.add(sc)
        self.m.paneconfigure(sc, sticky='news', min=200)

        self.createMenuBar()
        self.createToolBar()
        self.createSidePane()
        if self.orientation == 'vertical':
            self.m.paneconfigure(self.sidepane, min=200)
        self.createPrimerDBGUI()
        self.createChildFrame(name='NotePad')
        return

    def createMenuBar(self):
        """Create the menu bar for the application. """
        self.menu = Menu(self.main)
        self.file_menu = {
            '01Open Project': {
                'cmd': self.openProject
            },
            '02Open Sequence': {
                'cmd': self.openSequence
            },
            '05Quit': {
                'cmd': self.quit
            }
        }
        self.file_menu = self.create_pulldown(self.menu, self.file_menu)
        self.menu.add_cascade(label='File', menu=self.file_menu['var'])
        self.edit_menu = {
            '01Undo': {
                'cmd': self.undo
            },
            '02Copy': {
                'cmd': self.copy
            },
            '03Select All': {
                'cmd': self.sc.selectAll
            },
            '04Configure Restriction Enzymes': {
                'cmd': self.restrictionEnzymesDialog
            }
        }
        self.edit_menu = self.create_pulldown(self.menu, self.edit_menu)
        self.menu.add_cascade(label='Edit', menu=self.edit_menu['var'])

        self.primer_menu = {'01Primer DB': {'cmd': self.createPrimerDBGUI}}
        self.primer_menu = self.create_pulldown(self.menu, self.primer_menu)
        self.menu.add_cascade(label='Primer Tools',
                              menu=self.primer_menu['var'])

        self.seqanal_menu = {'01x': {'cmd': self.openSequence}}
        self.seqanal_menu = self.create_pulldown(self.menu, self.seqanal_menu)
        self.menu.add_cascade(label='Sequence Analysis',
                              menu=self.seqanal_menu['var'])

        self.view_menu = Menu(self.menu)
        self.menu.add_cascade(label='Tools', menu=self.view_menu)
        self.appsvars = {}
        for i in self.apps.keys():
            self.appsvars[i] = IntVar()

            def func(args):
                def new():
                    self.toggleApps(args)

                return new

            self.view_menu.add_checkbutton(label=i,
                                           onvalue=True,
                                           offvalue=False,
                                           command=func(i),
                                           variable=self.appsvars[i])

        self.help_menu = {
            '01Online Help': {
                'cmd': self.help
            },
            '02About': {
                'cmd': self.about
            },
        }
        self.help_menu = self.create_pulldown(self.menu, self.help_menu)
        self.menu.add_cascade(label='Help', menu=self.help_menu['var'])
        self.main.config(menu=self.menu)
        return

    def createSidePane(self, width=200):
        """Side panel for various dialogs is tabbed notebook that can hold multiple
            dialogs at once """
        self.closeSidePane()
        self.sidepane = Frame(self.m, bd=1, relief=RAISED)
        self.sidepane = Pmw.NoteBook(self.m)
        self.sidepane.component('hull').configure(relief='sunken',
                                                  borderwidth=1)
        self.m.paneconfigure(self.sidepane, width=width, sticky='news')
        self.m.add(self.sidepane)
        self.sidepane.setnaturalsize()
        return self.sidepane

    def closeSidePane(self):
        """Destroy sidepine"""
        if hasattr(self, 'sidepane'):
            self.m.forget(self.sidepane)
            self.sidepane.destroy()
        return

    def createChildFrame(self, sidepane=True, width=400, name=None):
        """Create a child frame in sidepane notebook or as toplevel"""
        geometry = '600x400+500+250'
        if sidepane == True:
            cframe = self.sidepane.add(name)
            self.sidepane.tab(name).configure(font='fixed 8', anchor='w')
            self.sidepane.selectpage(name)
        else:
            cframe = Toplevel()
            if name == None:
                title = 'default'
            else:
                title = name
            cframe.title(title)
        self.__dict__[name] = cframe
        #if name is a pre-defined app we load fetch the class
        if self.apps.has_key(name):
            cls = self.apps[name]
            inst = cls(cframe, parentapp=self)
            inst.pack(fill=BOTH, expand=1)
            self.appsvars[name].set(1)
            if hasattr(inst, 'geometry'):
                geometry = inst.geometry
        if sidepane == False:
            cframe.geometry(geometry)
        #bind frame close
        def func(evt):
            if hasattr(self, name):
                del self.__dict__[name]
            if name in self.appsvars:
                self.appsvars[name].set(0)

        cframe.bind("<Destroy>", func)
        return cframe

    def closeChildFrame(self):
        """Close sidepane frame"""
        name = self.sidepane.getcurselection()
        self.sidepane.delete(name)
        return

    def detachChildFrame(self):
        """Since we cannot actually detach frames in Tkinter, we
           remove the frame in the sidepane make a new toplevel window"""
        name = self.sidepane.getcurselection()
        self.sidepane.delete(name)
        if name == 'PrimerDB':
            fr = self.createPrimerDBGUI(sidepane=False)
        else:
            fr = self.createChildFrame(sidepane=False, name=name)
        return fr

    def toggleApps(self, name):
        """Remove or add apps from view"""
        print name
        if self.appsvars[name].get() == 1:
            if not hasattr(self, name):
                fr = self.createChildFrame(sidepane=True, name=name)
        else:
            if hasattr(self, name):
                if name in self.sidepane.pagenames():
                    self.sidepane.delete(name)
                else:
                    self.__dict__[name].destroy()
                    del self.__dict__[name]
        return

    def createToolBar(self):
        """Toolbar"""
        self.toolbar = ToolBar(self.main, self)
        self.toolbar.pack(side=TOP, fill=X, pady=1, before=self.m)
        img = Images.openproject()
        hlptxt = "Open Project from file"
        self.toolbar.addButton('Open Project', self.openProject, img, hlptxt)
        img = Images.saveproject()
        hlptxt = "Save Project"
        self.toolbar.addButton('Save Project', self.openProject, img, hlptxt)
        img = Images.undo()
        hlptxt = "Undo"
        self.toolbar.addButton('Save Project', self.openProject, img, hlptxt)
        img = Images.zoomout()
        hlptxt = "Zoom Out"
        self.toolbar.addButton('Save Project', self.sc.zoomOut, img, hlptxt)
        img = Images.zoomin()
        hlptxt = "Zoom In"
        self.toolbar.addButton('Save Project', self.sc.zoomIn, img, hlptxt)
        img = Images.windowprefs()
        hlptxt = "Seqeuence display preferences"
        self.toolbar.addButton('Seqeuence display preferences',
                               self.sc.showPrefs, img, hlptxt)
        img = Images.prefs()
        hlptxt = "Preferences"
        self.toolbar.addButton('Preferences', self.globalPrefsDialog, img,
                               hlptxt)
        return

    def addWindowToolBar(self, parent):
        """Toolbar for changing frame views"""
        toolbar = ToolBar(parent, self)
        img = Images.closeframe()
        hlptxt = "Close current sideframe"
        toolbar.addButton('tile vertical', self.closeChildFrame, img, hlptxt)
        img = Images.detachframe()
        hlptxt = "Detach current sideframe as seperate window"
        toolbar.addButton('tile vertical', self.detachChildFrame, img, hlptxt)
        img = Images.tilevertical()
        hlptxt = "Tile frames vertically"
        toolbar.addButton('x', self.tileVertical, img, hlptxt)
        img = Images.tilehorizontal()
        hlptxt = "Tile frames horizontally"
        toolbar.addButton('tile horizontal', self.tileHorizontal, img, hlptxt)
        return toolbar

    def addStatusBar(self, parent):
        fr = Frame(parent, width=100)
        Label(fr, text='status stuff').pack()
        fr.pack(fill=X, side=LEFT, anchor='w')
        return

    def removeAll(self):
        """Remove all widgets"""
        for w in self.main.children.values():
            w.destroy()
        return

    def tileHorizontal(self):
        """Re-arrange paned widgets horizontally"""
        if self.orientation == 'horizontal':
            return
        self.removeAll()
        self.orientation = 'horizontal'
        self.setupGUI()
        return

    def tileVertical(self):
        """Re-arrange paned widgets vertically"""
        if self.orientation == 'vertical':
            return
        self.removeAll()
        self.orientation = 'vertical'
        self.setupGUI()
        return

    def openSequence(self):
        """Load a sequence"""
        seq = Sequence()
        self.sc.loadSequence(seq)
        return

    def openProject(self, filename=None):
        """Load a project"""
        if filename == None:
            filename = Dialogs.openFilename(parent=self, ext='dtp')
        if not filename:
            return
        self.P.load(filename)
        #open sequence
        seq = self.P.DNAseq
        #print self.P.used_enzymes, self.P.cut_pos
        self.sc.project = self.P
        self.sc.update()

        #update primer db
        self.primerdb = PrimerDatabase(self.P.data['primer_dict'])
        self.pdbwin.database = self.primerdb
        self.pdbwin.update()
        return

    def copy(self):
        self.sc.copySequence()
        return

    def undo(self):
        return

    def createPrimerDBGUI(self, sidepane=True):
        """We create this individually to avoid confusion"""
        if hasattr(self, 'PrimerDB'):
            self.PrimerDB.lift()
            return
        fr = self.createChildFrame(name='PrimerDB', sidepane=sidepane)
        self.pdbwin = PrimerDBGUI(fr, database=self.primerdb)
        self.pdbwin.update()
        self.pdbwin.pack(fill=BOTH, expand=1)
        #bind window closing so it's automatically recreated in the sidepane
        if sidepane == False:

            def func(evt):
                self.createPrimerDBGUI()

            self.pdbwin.bind("<Destroy>", func)
        return fr

    def applyRestrSiteSettings(self):
        if hasattr(self, 'restrsitedialog'):
            vals = self.restrsitedialog.getValues()
        self.sc.update()
        return

    def restrictionEnzymesDialog(self, sidepane=True):
        defaults = {
            'uniquesitesonly': 1,
            'showonlyenzymescutmax': 50,
            'ignorecutpos': 1,
            'minlengthrecseq': 5,
            'excludepromiscuous': 1
        }
        options = [('uniquesitesonly', 'checkbutton', 1,
                    'Show unique sites only'),
                   ('showonlyenzymescutmax', 'scale', (1, 100),
                    'Show only enzymes that cut max'),
                   ('ignorecutpos', 'checkbutton', 1,
                    'Ignore cut position when finding isoschiziomers'),
                   ('minlengthrecseq', 'scale', (1, 10),
                    'Min length of recognition sequence'),
                   ('excludepromiscuous', 'checkbutton', 1,
                    'Exclude promiscuous enzymes')]
        geometry = '400x250+500+250'
        fr = self.createChildFrame(name='Configure Restriction Enzymes',
                                   sidepane=sidepane)
        self.restrsitedialog = Dialogs.GenericDialog(fr, options, defaults)
        defaults = {
            'uniquesitesonly': 1,
            'showonlyenzymescutmax': 50,
            'ignorecutpos': 1,
            'minlengthrecseq': 5,
            'excludepromiscuous': 1
        }
        self.restrsitedialog.pack(fill=BOTH, expand=1)
        return

    def applySettings(self):
        self.applyPrefs(self.prefsdialog.getValues())
        #self.removeAll()
        #self.setupGUI()
        #self.globalPrefsDialog()
        return

    def globalPrefsDialog(self, sidepane=True):
        curr = {}
        for key in self.defaultprefs:
            curr[key] = self.__dict__[key]
        fr = self.createChildFrame(name='Global settings', sidepane=sidepane)
        self.prefsdialog = Dialogs.PrefsDialog(fr, self, self.defaultopts,
                                               curr, self.applySettings)
        self.prefsdialog.pack(fill=BOTH, expand=1)
        return

    def help(self):
        import webbrowser
        link = 'http://code.google.com/p/peat/wiki/DNAtool'
        webbrowser.open(link, autoraise=1)
        return

    def about(self):
        win = Toplevel()
        win.geometry('+500+350')
        win.title('About DNATool')
        win.maxsize(width=400, height=400)
        logo = Images.logo()
        label = Label(win, image=logo)
        label.image = logo
        label.pack(fill=BOTH, padx=4, pady=4)
        text = """DNATool App, Version 2
             is a python desktop application for DNA sequence manipulation.
             Released under GPL v3
             (C) Copyright 2012- Damien Farrell """
        text = text.replace('\t', '')
        text = ' '.join(text.split())
        Label(win, text=text, wraplength=400).pack(fill=Y, side=TOP, pady=4)
        return

    def quit(self):
        if self.rememberwindowsize == 1:
            self.saveGeometry()
        self.main.destroy()
        if not self.parent:
            sys.exit()
        return
Example #20
0
class SequenceCanvas(Pmw.ScrolledCanvas):
    """Canvas for drawing all graphical elements, sequences and restrictions sites"""
    def __init__(self,
                 parent=None,
                 parentapp=None,
                 width=400,
                 height=400,
                 bg='white',
                 **kwargs):
        Pmw.ScrolledCanvas.__init__(self, parent, canvasmargin=2)
        self.parent = parent
        self.parentapp = parentapp
        self.project = None
        self.platform = platform.system()
        self.width = width
        self.height = height
        self.canvas = self.component('canvas')
        self.canvas.configure(bg='#f6f9f6', height=height, width=width)
        self.createBindings()

        self.defaultprefs = {
            'seqfont': 'Courier',
            'seqfontsize': 13,
            'fontstyle': 'bold',
            'basescale': 15,
            'restrfont': 'Arial',
            'backgrcolor': '#f6f9f6',
            'seqcoloroption': 2
        }
        fonts = ['Courier', 'Arial', 'Fixed', 'Tahoma', 'Times', 'Verdana']
        #we use the following to create the prefs dialog
        #list of tuples of the form name,type,default,label
        self.defaultopts = [
            ('seqfont', 'menu', fonts, 'Sequence font'),
            ('seqfontsize', 'scale', (6, 30), 'Sequence font size'),
            ('fontstyle', 'menu', ['normal', 'bold', 'italic'], 'Font style'),
            ('basescale', 'scale', (8, 50), 'Base scale'),
            ('restrfont', 'menu', fonts, 'Restr site font'),
            ('backgrcolor', 'color', '#f6f9f6', 'Background color')
        ]
        self.loadPrefs()
        self.baserow = self.height / 2
        self.seqstart = 80
        self.siterowstart = 70
        self.orfoffset = 15
        self.yscale = 1.1

        #self.sequence = Utilities.createDummySequence(100)
        self.alignedsequences = []
        self.update()
        return

    def createBindings(self):
        """Bindings"""
        c = self.canvas
        c.bind("<Button-1>", self.handleLeftClick)
        c.bind("<B1-Motion>", self.handleLeftMotion)
        c.bind("<Button-3>", self.handleRightClick)
        c.bind_all("<Control-KeyPress-c>", self.copySequence)
        #c.bind("<ButtonRelease-3>",self.handleRightRelease)
        '''c.bind("<ButtonRelease-1>",self.handle_left_release)

        c.bind("<Shift-Button-1>", self.handle_left_shift_click)
        c.bind("<Shift-ButtonRelease-1>", self.handle_left_shift_release)
        c.bind("<B3-Motion>", self.handle_right_motion)

        c.bind_all("<Control-KeyPress-x>",self.cut_DNA)
        c.bind_all("<Control-KeyPress-v>",self.paste_DNA)
        c.bind_all("<Delete>",self.delete_DNA) '''
        return

    def loadPrefs(self):
        """Load prefs from a preferences instance"""
        self.preferences = Preferences('DNATool2', {})
        temp = {}
        for key in self.defaultprefs:
            if not key in self.preferences.prefs:
                self.preferences.set(key, self.defaultprefs[key])
            temp[key] = self.preferences.get(key)
        self.applyPrefs(temp)
        return

    def savePrefs(self):
        """Save prefs to a preferences instance"""
        self.preferences = Preferences('DNATool2', {})
        for key in self.defaultprefs:
            self.preferences.set(key, self.__dict__[key])
        return

    def applyPrefs(self, prefs=None):
        """Apply prefs from a given dict"""
        if prefs == None: prefs = self.defaultprefs
        for key in prefs:
            self.__dict__[key] = prefs[key]
        return

    def handleLeftClick(self, evt):
        """Handle left click"""
        if hasattr(self, 'rightmenu'):
            self.rightmenu.destroy()
        c = self.canvas
        if len(c.gettags(CURRENT)) == 0:
            return
        self.markPosition(evt)
        x = evt.x
        y = evt.y
        items = c.find_closest(evt.x, evt.y, halo=14)
        x1, y1, x2, y2 = c.bbox(CURRENT)
        self.selecteditems = c.find_enclosed(x1 - 1, y1 - 1, x2 + 1, y2 + 1)
        return

    def handleLeftMotion(self, evt):
        c = self.canvas
        items = self.selecteditems
        current = c.gettags(CURRENT)
        if 'sitelabel' in current:
            self.dragMove(evt, items)
        elif 'sequence' in current:
            self.setSequenceSelection(evt)
        return

    def selectSequence(self, seq):
        """Select sequence just from seq values"""
        self.highlightSequence(seq)
        self.selectedrange = seq
        return

    def selectAll(self):
        sel = range(0, len(self.sequence))
        self.selectSequence(sel)
        return

    def setSequenceSelection(self, evt):
        """Select sequence from mouse action"""
        c = self.canvas
        x = self.oldx
        x2 = c.canvasx(evt.x)
        height = self.basescale / 1.1
        y = self.baserow + height / 2
        c.delete(c.find_withtag('seqselection'))
        rect = c.create_rectangle(x,
                                  y,
                                  x2,
                                  y - height,
                                  width=0,
                                  tag=('seqselection'),
                                  fill='yellow')
        x1, y1, x2, y2 = c.bbox(rect)
        items = c.find_overlapping(x1 + 2, y1, x2 - 2, y2)
        seq = range(self.getSeqPositionFromCoords(x),
                    self.getSeqPositionFromCoords(x2))
        self.selectSequence(seq)
        return

    def highlightSequence(self, sequence):
        """Highlight section of sequence in different color"""
        self.colorSequence()
        c = self.canvas
        height = self.basescale / 1.1
        y = self.baserow + height / 2
        ignore = set(['seqbackground', 'seqselection'])
        for s in sequence:
            x = self.getBasePosition(s)
            items = c.find_overlapping(x - 2, y - 2, x, y + 2)
            for i in items:
                if len(set(c.gettags(i)) & ignore) > 0:
                    continue
                c.itemconfig(i, fill='red')
                c.lift(i)
        return

    def getSeqPositionFromCoords(self, x):
        """From X and Y coordinate, return the DNA base number"""
        #if abs(y-self.baserow)>5:
        #    return None
        pos = int(float(x - self.seqstart + 4.0) / self.basescale)
        return pos

    def markPosition(self, evt):
        c = self.canvas
        self.oldx = c.canvasx(evt.x)
        self.oldy = c.canvasy(evt.y)
        self.selectedtags = c.gettags(CURRENT)
        return

    def dragMove(self, evt, items=None, tags=None):
        """Handle mouse drag"""
        c = self.canvas
        x = c.canvasx(evt.x)
        y = c.canvasy(evt.y)
        diffx = x - self.oldx
        diffy = y - self.oldy
        self.oldx = x
        self.oldy = y
        name = c.gettags(CURRENT)[0]
        for i in items:
            c.move(i, diffx, diffy)
            self.drawSiteConnector(x, y, name, move=True)
        return

    def handleRightClick(self, evt):
        self.rightmenu = self.popupMenu(evt)
        return

    def popupMenu(self, evt):
        """Right click shows popup menu"""
        popupmenu = Menu(self.canvas, tearoff=0)

        def popupFocusOut(evt):
            popupmenu.unpost()

        popupmenu.add_command(label="Show Prefs", command=self.showPrefs)
        popupmenu.add_command(label="Zoom in", command=self.zoomIn)
        popupmenu.add_command(label="Zoom out", command=self.zoomOut)
        popupmenu.bind("<FocusOut>", popupFocusOut)
        popupmenu.focus_set()
        popupmenu.post(evt.x_root, evt.y_root)
        return popupmenu

    def addSequences(self, sequences):
        self.alignedsequences = sequences
        return

    def update(self, sequence=None, enzymes=None, cutpos=None):
        """Update display of the current sequence(s)"""

        if sequence == None:
            X = self.getDatafromProject()
            if X == None:
                return
            else:
                sequence, enzymes, cutpos = X
        #remove previous
        self.clear()
        self.calculateScaling()
        self.drawDefaultLabels()
        #update sequence
        self.showSequence(sequence)
        self.colorSequence()
        self.drawSeqBackground()
        #if self.ORFselected == True:
        self.showAA3Seq(sequence)
        #draw restr sites
        if enzymes != None:
            self.showRestrictionSites(enzymes, cutpos)
        #update primers if selected
        #self.showPrimers()
        self.canvas.configure(bg=self.backgrcolor)
        return

    def getDatafromProject(self):

        if self.project != None:
            P = self.project
            if P.DNAseq == '':
                return
        else:
            return
        sequence = P.DNAseq
        enzymes = P.used_enzymes
        cutpos = P.cut_pos
        return sequence, enzymes, cutpos

    def clear(self):
        """Clear all"""
        c = self.canvas
        c.delete(ALL)
        return

    def calculateScaling(self):
        """Calculate font size dependant y-scaling to prevent crowding"""
        self.yscale = self.seqfontsize / 10.0
        self.yscale = pow(self.yscale, 0.05)
        return

    def getCurrentFont(self):
        """Generate current font from settings"""
        fontsize = self.seqfontsize
        fontstyle = self.fontstyle
        #create a font object
        if fontstyle != 'italic':
            seqfont = tkFont.Font(family=self.seqfont,
                                  size=fontsize,
                                  weight=fontstyle)
        else:
            seqfont = tkFont.Font(family=self.seqfont,
                                  size=fontsize,
                                  slant="italic")
        return seqfont

    def showSequence(self, sequence=None, row=None, tag=None):
        """Show sequence"""
        if sequence == None:
            return
        if row == None:
            row = self.baserow
        c = self.canvas
        seqfont = self.getCurrentFont()

        #dna sequence
        self.sequence = sequence
        #print sequence
        for i in range(len(sequence)):
            pos = self.getBasePosition(i)
            item = c.create_text(pos,
                                 row,
                                 font=seqfont,
                                 text=sequence[i],
                                 fill='black',
                                 anchor='w',
                                 tag=('seqtext', 'sequence'))
            if tag != None:
                c.itemconfig(i, tag=tag)
        self.seqend = self.getBasePosition(len(sequence)) - self.seqstart
        self.canvas.configure(scrollregion=(0, 0, self.seqend + 100,
                                            self.height))
        self.centerPage()
        return

    def showMultiple(self, aligned=None, direction='up'):
        """Show multiple sequences aligned to the base one"""

        #print self.alignedsequences
        if aligned == None:
            aligned = self.alignedsequences
        self.clearMultiple()
        if len(aligned) == 0:
            return
        #move restr sites up
        self.clearRestrictionSites()
        if direction == 'up':
            inc = -15
        else:
            inc = 15
        row = self.baserow + inc
        print len(aligned)
        for s in aligned[:55]:
            self.showSequence(s, row, tag='aligned')
            row += inc
            self.height += 20
        return

    def clearMultiple(self):
        """Clear multiple sequences"""
        c = self.canvas
        c.delete('aligned')
        self.update()
        return

    def showAASeq(self):

        return

    def showAA3Seq(self, sequence=None):
        """Show 3 letter code amino acid sequence"""
        if sequence == None:
            return
        c = self.canvas
        seqfont = self.getCurrentFont()

        y = (self.baserow + self.orfoffset) * self.yscale
        frame = 0
        AAseqs3, AAseqs1 = Mutation.translate(sequence)
        aaseq = AAseqs3[frame]
        #print aaseq
        for i in range(len(aaseq)):
            pos = self.getAAPosition(i)  #,frame+1)
            c.create_text(pos,
                          y,
                          font=seqfont,
                          text=aaseq[i],
                          fill='black',
                          tag=('aasequence'))
        for i in range(len(aaseq)):
            if i % 5 != 0:
                continue
            pos = self.getAAPosition(i)
            c.create_text(pos,
                          y + 45,
                          font='Courier 11',
                          text=i,
                          fill='black',
                          tag=('aasequence'))
            c.create_line(pos, y + 35, pos, y + 20, fill='red', width=2)
        return

    def colorSequence(self):
        """Color the dna sequence"""
        c = self.canvas
        items = c.find_withtag('seqtext')
        option = 2
        count = 0
        clr = '#66CC00'
        for i in items:
            if option == 1:
                c.itemconfig(i, fill=clr)
            elif option == 2:
                if count % 3 == 0 and clr == '#66CC00':
                    clr = '#999900'
                elif count % 3 == 0 and clr == '#999900':
                    clr = '#66CC00'
                c.itemconfig(i, fill=clr)
            count = count + 1
        return

    def drawDefaultLabels(self):
        """Draw objects that are permanent"""
        c = self.canvas
        item = c.create_text(5,
                             self.baserow,
                             font='Courier 10',
                             text='DNA seq',
                             fill='darkgreen',
                             anchor='w')
        y = (self.baserow + self.orfoffset) * self.yscale
        item = c.create_text(5,
                             y,
                             font='Courier 10',
                             text='ORF',
                             fill='black',
                             anchor='w')
        item = c.create_text(5,
                             y + 45,
                             font='Courier 10',
                             text='AA no.',
                             fill='gray',
                             anchor='w')
        return

    def drawSeqBackground(self, color='white'):
        """Draw a background for a sequence"""
        c = self.canvas
        x = self.seqstart
        height = self.basescale
        y = self.baserow + height / 2
        end = self.seqend
        rect = c.create_rectangle(x,
                                  y,
                                  x + end,
                                  y - height,
                                  width=0,
                                  tag=('seqbackground', 'sequence'),
                                  fill=color)
        c.tag_lower(rect)
        return rect

    def drawRestrictionSite(self, name, positions):
        """Draw restriction site(s) for a single enzyme"""
        c = self.canvas
        font = restrfont = str(
            self.restrfont) + ' ' + str(self.seqfontsize - 2)
        done = []
        if len(positions) == 1:
            #font = font+' underline'
            fill = '#FF9999'
        else:
            fill = '#F6FCE1'
        for pos in positions:
            uid = name + str(pos[0])
            self.restrictionsites[uid] = pos[0]
            if pos[0] in done: continue
            done.append(pos[0])
            x = self.getBasePosition(pos[0])
            y = self.baserow - self.siterowstart
            text = self.create_text(x,
                                    y,
                                    text=name,
                                    tags=(uid, 'sitelabel', 'restrsite'),
                                    font=font,
                                    anchor='nw')

            x1, y1, x2, y2 = box = c.bbox(text)
            rect = c.create_rectangle(box,
                                      fill=fill,
                                      outline='gray',
                                      tags=(uid, 'rect', 'restrsite'))
            items = c.find_withtag(uid)
            overlapping = c.find_overlapping(x1, y1, x2, y2)[:-2]
            #print pos, items, overlapping
            inc = -10
            while len(overlapping) > 1:
                for i in items:
                    c.move(i, 0, inc)
                x1, y1, x2, y2 = c.bbox(i)
                overlapping = c.find_overlapping(x1, y1, x2, y2)[:-2]
                y = y + inc
            c.lift(text)
            self.drawSiteConnector(x, y, uid)
        return text

    def drawSiteConnector(self, x2, y2, uid, move=False):
        """Draw line connecting site label to sequence"""
        c = self.canvas
        pos = self.restrictionsites[uid]
        x1 = self.getBasePosition(pos)
        y1 = self.baserow - 15

        if move == True:
            old = list(set(c.find_withtag(uid)) & set(c.find_withtag('line')))
            for i in old:
                c.delete(i)
        line = c.create_line(x1,
                             y1,
                             x1,
                             y2,
                             fill='blue',
                             width=2,
                             stipple='gray25',
                             tag=(uid, 'line', 'restrsite'))
        c.tag_lower(line)
        line = c.create_line(x1,
                             y2,
                             x2,
                             y2,
                             fill='blue',
                             width=2,
                             stipple='gray25',
                             tag=(uid, 'line', 'restrsite'))
        c.tag_lower(line)
        return

    def moveItemByName(self, name, y):
        c = self.canvas
        items = c.find_withtag(name)
        for i in items:
            c.move(i, 0, y)
        return

    def showRestrictionSites(self, enzymes=None, cutpos=None):
        """Draw all restriction sites"""
        if enzymes == None:
            return
        self.restrictionsites = {}
        c = self.canvas
        for e in enzymes:
            if cutpos.has_key(e):
                positions = cutpos[e]
                r = self.drawRestrictionSite(e, positions)

        return

    def clearRestrictionSites(self):
        """Clear all restriction sites"""
        c = self.canvas
        #print c.find_withtag('restrsite')
        c.delete('restrsite')
        return

    def getBasePosition(self, pos):
        """Return the x position of the nth base on the canvas"""
        return self.seqstart + float(pos) * self.basescale

    def getAAPosition(self, pos, frame=None):
        pos = pos * 3 + 1  #+float(frame)
        return self.getBasePosition(pos)

    def showPrimers(self):
        """Draw primers"""
        return

    def centerPage(self):
        """Center canvas on sequence after redraw"""
        top, bottom = self.yview()
        size = bottom - top
        if size == 0: size = 0.4
        middle = size * 0.4
        self.yview('moveto', middle)
        #print top, bottom
        #print middle
        return

    def zoomIn(self):
        """Zoom in by enlarging all elements"""
        c = self.canvas
        x1, x2 = self.xview()
        y1, y2 = self.yview()
        self.basescale = self.basescale * 1.1
        self.seqfontsize = self.seqfontsize + 1
        self.update()
        return

    def zoomOut(self):
        """Zoom out by reducing all elements"""
        if self.seqfontsize < 7:
            return
        self.basescale = self.basescale / 1.1
        self.seqfontsize = self.seqfontsize - 1
        self.update()
        return

    def copySequence(self, evt=None):
        """Copy sequence text"""
        seqdata = ''.join([self.sequence[i] for i in self.selectedrange])
        self.parent.clipboard_clear()
        self.parent.clipboard_append(seqdata)
        return

    def showPrefs(self, evt=None):
        """Show preferences window"""
        fr = Toplevel(self.parent)
        fr.title('Sequence window preferences')

        def func():
            self.applyPrefs(self.prefsdialog.getValues())
            self.update()

        curr = {}
        for key in self.defaultprefs:
            curr[key] = self.__dict__[key]
        dlg = self.prefsdialog = Dialogs.PrefsDialog(fr,
                                                     self,
                                                     options=self.defaultopts,
                                                     defaults=curr,
                                                     callback=func)
        dlg.pack(fill=BOTH, expand=1)
        fr.geometry(dlg.geometry)
        fr.grab_set()
        fr.transient(self.parent)
        return