Exemple #1
0
 def init_slider_frame(self):
     self.slider_frame = SliderFrame(self,self, v=self.d.get_v())
     self.slider_frame.grid(column=1, row=0, sticky="")
Exemple #2
0
class PooGUI(tk.Frame):
    """the main frame with the GUI, contains three sections and a menu bar
        - the main section is the plotting area using matplotlib
        - in the top right are sliders,
        - bottom right is a list of samples

        we have the following objects:
            -sList: a list of all samples
            -hList: a list of all hyperbolas
            -data: the raw SNP data (mbsData obj?)
            -coords: data structure with coordinates
            -psi: np.array[s1,s2] : psi
            -v: constant multiplier of hyperbolas
            -xlim, ylim: plotting limits
        """
#---------------------------------------------------------------------
#   drawing stuff for points, should eventually be moved to an 
#       appropriate plotting class,psi, data
#---------------------------------------------------------------------

    def dummyElements(self):
        #vars I need
        self.activeCanvas
        self.canvas['H'] #replace with self.canvas[]...
        self.canvas['Psi']
        self.sample_frame
        self.origin_frame
        self.slider_frame
        self.bgi
        self.matrixTL
        self.psimatrix
        #vars in config
        self.lwd #should be in either plot...
        self.threshold
        #vars in Data
        self.v
        self.clusters
        self.psi
        self.data
        self.psi_sum
        self.oList
        self.hList #??
        self.sList #???
        #vars I don't need

        #maybees

    def __init__(self, master=None):
        """the main constructor of the frame. As it is quite big,
        i split it up into subfunctions for the various ui parts.
        Might be worth to instead use children classes instead.

        The main app window will have a status bar at the bottom with
        progress messages and stuff. The main window will be
        the square matplotlib canvas on the right and a narrowish bar
        with samples, sliders, etc on the right
        """
        tk.Frame.__init__(self, master, relief=tk.SUNKEN)

        self.master = master
        self.d = Data(self)
        self.c = Config(O)
        
        self.canvas = dict()
        self.d.sList = []
        self.d.oList = []
        self.init_canvas_hyperbolas()
        self.init_canvas_pwp(active=True)
        self.init_sample_frame()
        #self.init_statusbar()
        self.init_slider_frame()
        self.init_menubar()

        #enable expansion
        tk.Grid.rowconfigure(self,1,weight=10)
        tk.Grid.rowconfigure(self,2,weight=1)
        tk.Grid.columnconfigure(self,1,weight=1)
        tk.Grid.columnconfigure(self,2,weight=1)
        tk.Grid.columnconfigure(self,0,weight=2)

    def initPsiMatrix(self,master):
        """initializes Matrix containing psi values
        should do the following:
            1. display matrix of Edits? MatrixWidget
            2. load data and display it
            3. colorcode
        """
        self.matrixTL = tk.Toplevel(master)
        self.psi_matrix = SimpleTable(self.matrixTL)
        self.psi_matrix.grid(sticky="nsew")
        self.psi_matrix.fill(self.d.sList,self.d.pairwise_stats['psi'])
        self.psi_matrix.fill_labels(self.d.sList)

    def init_menubar(self):
        """
        this function loads and populates the menubar, and will register its events
        """
        self.menubar = tk.Menu(self)

        menu = tk.Menu(self.menubar, tearoff=0)
        self.menubar.add_cascade(label="File", menu=menu)
        menu.add_command(label="Load SNP",command=self.loadSNP)
        menu.add_command(label="Load Coords", command=self.loadCoords)
        menu.add_command(label="Load Background Image", command=self.loadBGI)
        menu.add_command(label="Save plot", command=self.save_plot)
        menu.add_command(label="Quit", command=self.quit)

        menu = tk.Menu(self.menubar, tearoff=0)
        self.menubar.add_cascade(label="Edit", menu=menu)
        menu.add_command(label="Set Reference Coordinates")

        menu = tk.Menu(self.menubar, tearoff=0)
        self.menubar.add_cascade(label="View", menu=menu)
        menu.add_command(label="Hyperbolas", 
                         command=self.showHyperbolaCanvas)
        menu.add_command(label="Pairwise Psi", 
                         command=self.showPsiCanvas)

        menu = tk.Menu(self.menubar, tearoff=0)
        self.menubar.add_cascade(label="Run", menu=menu)
        menu.add_command(label="Find Origin All", command=self.optimizeAll)
        menu.add_command(label="Find Origin Visible")

        try:
            self.master.config(menu=self.menubar)
        except AttributeError:
            # master is a toplevel window (Python 1.4/Tkinter 1.63)
            self.master.tk.call(master, "config", "-menu", self.menubar)

    def init_canvas_hyperbolas(self, active=False):
        """
        this function creates the matplotlib canvas that will be used 
        to draw stuff
        master: parent frame
        active: is this displayed on startup?
        """
        self.canvas['H'] = HyperbolaCanvas(self, self.c,
                                           self.d.sList,
                                           self.d, width=300, height=300)
        self.canvas['H'].grid(column=0,row=0,rowspan=3,sticky="ewns")
        if not active:
            self.canvas['H'].hide()
        else:
            self.activeCanvas = self.canvas['H']

    def init_canvas_pwp(self, active=False):
        """
        this function creates the matplotlib canvas that will be used 
        to draw stuff
        master: parent frame
        active: is this displayed on startup?
        """
        self.canvas['Psi'] = PWPCanvas(self, self.c, self.d.sList,
                                       self.d, width=300, height=300)
        self.canvas['Psi'].grid(column=0,row=0,rowspan=3,sticky="ewns")
        if not active:
            self.canvas['Psi'].hide()
        else:
            self.activeCanvas = self.canvas['Psi']

    def init_statusbar(self):
        """function that creates a status bar at the bottom of the window"""
        self.sb = StatusBar(self)
        self.sb.grid(row=3,column=0,columnspan=2, sticky="ew")
    
    def init_slider_frame(self):
        self.slider_frame = SliderFrame(self,self, v=self.d.get_v())
        self.slider_frame.grid(column=1, row=0, sticky="")
    
    def init_sample_frame(self):
        self.sample_frame = SampleFrame(self, width=200, height=100)
        self.origin_frame = OriginFrame(self, width=200, height=100)
        for i in range(4):
            self.add_sample( SampleUI(master=self.sample_frame,
                                        data=self.d, config=self.c,
                                        cluster=None, text="SS%d"%i) )
            self.d.sList[i].grid(column=0,row=i)
        self.sample_frame.grid(column=1, row=1, sticky="ns")
        self.origin_frame.grid(column=1, row=2, sticky="ns")

#--------------------------------------------------

    def reset_sample_list(self):
        #reset everything:
        for sampleUI in self.d.sList:
            sampleUI.destroy()
        self.d.sList = []

        self.canvas['H'].samples = []
        self.canvas['Psi'].samples = []

    def add_sample(self, s):
        self.d.sList.append(s)
        self.canvas['H'].samples.append(s)
        self.canvas['Psi'].samples.append(s)

    def changeV(self,ele,val):
        """ 
        function that updates hyperbola when v is changed
        """

        #see if the value is actually a float, if not, return
        self.d.set_v( float( val.get() ))
        #update, whole thing, there might be a more efficient way to do this
        self.canvas['H'].update_()
        if self.activeCanvas == self.canvas['H']:
            self.activeCanvas.redraw()

    def changeLwd(self,val):
        """ 
        function that updates hyperbola when v is changed
        """

        print "Changing lwd" , val.get()
        #see if the value is actually a float, if not, return
        self.c.psi_lwd = float( val.get() )
        #redraw, whole thing, there might be a more efficient way to do this
        self.canvas['Psi'].update_()
        if self.activeCanvas ==self.canvas['Psi']:
            self.activeCanvas.redraw()
      
    def changeThreshold(self,val):
        """ 
        function that updates hyperbola when v is changed
        """

        print "Changing threshold" , val.get()
        #see if the value is actually a float, if not, return
        self.c.psi_threshold = float( val.get() )
        #update, whole thing, there might be a more efficient way to do this
        self.canvas['Psi'].update_()

        if self.activeCanvas ==self.canvas['Psi']:
            self.activeCanvas.redraw()
#---------------------------------------------------------------------
#   optimizing, should move to data
#---------------------------------------------------------------------
    def optimizeAll(self):
        ev,msev, pv,dv = [],[],[],[]
        activeStat = self.d.get_active_stat
        for cluster_id in self.d.clusters:
            cluster = self.d.clusters[cluster_id]
            n_pops = cluster.n_pops
            if n_pops <= 3:
                print "Warning, Cluster too small"
            data = np.empty((n_pops * (n_pops -1 ) /2, 5 ))
            row = 0
            for i, s1 in enumerate(cluster.pops):
                for j0, s2 in enumerate(cluster.pops[i+1:]):
                    j = i+j0 + 1
                    data[row] = s1.get_x(), s1.get_y(), \
                                s2.get_x(), s2.get_y(), \
                                self.d.get_active_stat(s1.pop, s2.pop)
                    row += 1
            e,mse,p,d = optimize.tdoa3(data,x0=O["opt_start"])
            print e[0]
            ev.append(e[0])
            msev.append(mse)
            pv.append(p)
            dv.append(d)
            self.d.set_v( e[0][0] )
            self.slider_frame.v_scale.set( e[0][0] )
            self.canvas['H'].update_()
            if self.activeCanvas == self.canvas['H']:
                self.activeCanvas.redraw()

            if cluster.origin is None:
                opt = \
                InferredOrigin(master=self.origin_frame,x=e[0][1],y=e[0][2],
                               text="Origin "+cluster.name)
                opt.set_color("red")
                cluster.origin = opt
            else:
                opt = cluster.origin
                opt.tX.set("%2.2f"%(e[0][1]))
                opt.tY.set("%2.2f"%(e[0][2]))
                opt.set_x(e[0][1])
                opt.set_y(e[0][2])
                opt.update_()
                print "UPDATED ORIGN"

            self.d.oList.append(opt)
            opt.grid(in_=self.origin_frame)
            self.canvas['H'].panel.add_artist( opt.circH )
            self.canvas['H'].update_()
            self.canvas['Psi'].panel.add_artist( opt.circP )
            #origins shouldn't be movable
            #opt.circH.connect()
            #opt.circP.connect()
            self.activeCanvas.redraw()
        return ev, msev, pv, dv


#------------------------------------Hyperbola---------------------------------
#   loading files and data
#---------------------------------------------------------------------
    def loadSNP(self,f=None):
        """loads SNP and saves them in data"""
        if f == None:
            f = tkFileDialog.askopenfile(mode='r')
        self.d.load_snp( np.loadtxt(f) )
        self.canvas['H'].draw_all_hyperbolas()
        self.canvas['Psi'].draw_all_pairwise_psi()
        self.initPsiMatrix(self.master)

#---------------------------- Sorting stuff ------------------------
#   this set of functions handles all the sorting of elements
#--------------------------------------------------


    def update_sample_order(self):
        """
            when the samples are sorted and have to be reordered, this function
            does it
        """
        self.d.sList = sorted(self.d.sList)
        self.sample_frame.update_sample_order(self.d.sList)
        self.psi_matrix.update_sample_order(self.d.sList)

#--------------------------------------------------
    def loadCoords(self,f=None):
        """loads Coords, creates the corresponding UI elements
            and the circles for plotting
        """

        default_cluster = self.d.default_cluster
        self.reset_sample_list()

        if f is None:
            f = tkFileDialog.askopenfile(mode='r',initialfile="coords.txt")
	    print f
	else:
	    f = open( f )

        for i,line in enumerate(f):
            p = Population()
            p.load_line(line)
            self.d.add_pop(p)

            sUI = SampleUIWPop(pop=p, master=self.sample_frame, 
                               config = self.c, data=self.d,
                               cluster=default_cluster)
            sUI.grid(column=0,row=i, sticky="ew")

            #create plotting circles and register events
            self.canvas['H'].panel.add_artist( sUI.circH )
            self.canvas['Psi'].panel.add_artist( sUI.circP )
            sUI.circH.connect()
            sUI.circP.connect()
            
            self.add_sample( sUI )

        self.nCoords = len( self.d.sList )
        self.activeCanvas.redraw()

    def loadPsi(self,f=None):
        """loads Psi directly. Assumes Coordinates are already loaded"""
        if f is None:
            f = tkFileDialog.askopenfile(mode='r',initialfile="psi.txt")

        self.d.add_pw_stat('psi', AntiCommutativePWStat(f=pw_psi))
        if self.d.pw_default_stat is None:
            self.d.set_pw_default_stat('psi')

        psiRaw = np.loadtxt(f, dtype="S100")
        for row in psiRaw:
            self.d.pairwise_stats['psi'][ row[0], row[1] ] =  float(row[2])

        psi_sum = psi_sum_cluster(self.d.pairwise_stats['psi'],
                                  self.d.sList)
        self.d.add_single_pop_stat('psi_sum',psi_sum)
        self.d.sort_stat="psi_sum"

        self.initPsiMatrix(self.master)
        self.d.update_all_colors()
        self.d.update_sample_order()
            
        #self.set_colors()
        self.canvas['H'].draw_all_hyperbolas()
        self.canvas['Psi'].draw_all_pairwise_psi()

        
    def loadBGI(self, f=None):
        """loads Background image"""
        if f is None:
            f = tkFileDialog.askopenfile(mode='r')

        try:
            self.bgi = mpimg.imread(f)
        except:
            raise ValueError("could not read image file, see"+ \
                             " matplotlib.image.imread for"+ \
                             " supported formats")
        self.canvas['H'].addBGI(self.bgi)
        self.canvas['Psi'].addBGI(self.bgi)

    def removeBGI(self):
        self.canvas['H'].removeBGI()
        self.canvas['Psi'].removeBGI()
        self.activeCanvas.redraw()

    def save_plot(self, f=None):
        if f == None:
            f = tkFileDialog.asksaveasfilename(initialfile="plot.pdf")
        self.activeCanvas.fig.savefig(f)

        


#---------------------------------------------------------------------
# various constructors
#---------------------------------------------------------------------

    def loadOptions(self):
        self.lwd = O['psi_lwd']
        self.threshold = O['psi_threshold']





#---------------------------------------------------------------------
#   other stuff
#---------------------------------------------------------------------
    def quit(self):
        """quits app"""
        print "bye"
        root.quit()
        root.destroy()

    def showPsiCanvas(self):
        self.canvas['H'].hide()
        self.canvas['Psi'].show()
        self.activeCanvas = self.canvas['Psi']
        for s in self.d.sList:
            s.updateCircles()
        self.activeCanvas.redraw()

    def showHyperbolaCanvas(self):
        self.canvas['H'].show()
        self.activeCanvas = self.canvas['H']
        self.canvas['Psi'].hide()
        for s in self.d.sList:
            s.updateCircles()
        self.activeCanvas.redraw()