Exemple #1
0
class ProtocolsWin(wx.Frame):
    def __init__(self, W, H, scriptdir):
        if (platform.system() == "Darwin"):
            self.stdwinx = 0; self.stdwiny = 24
        else:
            self.stdwinx = 0; self.stdwiny = 0
        self.stdwinw = 370; self.stdwinh = H-40
        self.screenH = H; self.screenW = W
        winx = self.stdwinx; winy = self.stdwiny
        winw = self.stdwinw; winh = self.stdwinh
        self.scriptdir = scriptdir
        homedir = os.path.expanduser("~")
        # Try to get the save values from the cfg file
        try:
            if (platform.system() == "Windows"):
                f = open(homedir + "\\InteractiveROSETTA\\protwindow.cfg", "r")
            else:
                f = open(homedir + "/.InteractiveROSETTA/protwindow.cfg", "r")
            for aline in f:
                if (aline.find("[OFFSET X]") >= 0):
                    winx = winx + int(aline.split()[len(aline.split())-1])
                elif (aline.find("[OFFSET Y]") >= 0):
                    winy = winy + int(aline.split()[len(aline.split())-1])
                elif (aline.find("[OFFSET WIDTH]") >= 0):
                    winw = winw + int(aline.split()[len(aline.split())-1])
                elif (aline.find("[OFFSET HEIGHT]") >= 0):
                    winh = winh + int(aline.split()[len(aline.split())-1])
            f.close()
        except:
            pass
        if (winx > self.screenW - 100):
            winx = self.stdwinx
        if (winy > self.screenH - 100):
            winy = self.stdwiny
        # Catch bad cached sizes
        if (winw < 200):
            winw = self.stdwinw
        if (winh < 200):
            winh = self.stdwinh
        # Maybe the screen resolution has changed and the saved dimensions put the windows in
        # weird places, so default them to better positions and the user can change them later
        #if (winw < 350):
        #    winw = 370
        #elif (winw > W):
        #    winw = 370
        #if (winx < 0):
        #    winx = 0
        #elif (winx > W-winw):
        #    winx = W-winw
        #if (winh > H - 40):
        #    winh = H - 40
        #if (winy < 0):
        #    winy = 0
        #elif (winy > H-winh):
        #    winh = H-40
        wx.Frame.__init__(self, None, -1, "InteractiveROSETTA - Protocols", size=(winw, winh))
        self.SetPosition((winx, winy))
        self.SetBackgroundColour("#333333")
        self.SetSizeHints(330, 560, 370, H)
        self.SetIcon(icon.GetIcon())
        self.Show()

        self.Protocols = ProtocolsPanel(self, winw, winh)
        self.Selection = SelectPanel(self, winw, winh)
        self.Protocols.setSelectWin(self.Selection)
        self.Selection.setProtPanel(self.Protocols)

        self.saveTimer = wx.Timer(self)
        self.Bind(wx.EVT_TIMER, self.saveWindowData, self.saveTimer)
        self.Bind(wx.EVT_SIZE, self.windowGeometryChange)
        self.Bind(wx.EVT_MOTION, self.windowGeometryChange)
        self.Bind(wx.EVT_ACTIVATE, self.focusEvent)

        # Start the Rosetta daemon that will run in the background looking for job input files generated
        # by the main GUI
        # It could be the case that the user was in the middle of a protocol, then quits suddenly so the
        # daemon doesn't terminate itself because it's in the middle of a protocol
        # The the user restarts the GUI before the daemon has a chance to finish the protocol
        # This checks to see if the daemon is already active and doesn't spawn a new one if one is already
        # running
        stillrunning = False
        count = 0
        for proc in psutil.process_iter():
            try:
                if (platform.system() == "Windows"):
                    if (len(proc.cmdline()) >= 3 and proc.cmdline()[0].find("python") >= 0 and proc.cmdline()[2].find("from multiprocessing.forking") >= 0):
                        stillrunning = True
                        break
                else:
                    # On Unix systems you just have to make sure two instances of python are running
                    # because there isn't any forking information in the daemon's instance of python
                    if (len(proc.cmdline()) >= 2 and proc.cmdline()[0].find("python") >= 0 and proc.cmdline()[1].find("InteractiveROSETTA.py") >= 0):
                        count = count + 1
            except:
                # In Windows it will crash if you try to read process information for the Administrator
                # Doesn't matter though since InteractiveROSETTA is run by a non-Administrator
                # But we need to catch these errors since we don't know which processes are admin ones
                pass
        if (platform.system() != "Windows" and count == 2):
            stillrunning = True
        if (not(stillrunning)):
            print "Starting Rosetta protocol daemon..."
            #if (platform.system() == "Linux"):
                #self.daemon_process = subprocess.Popen(args=["cd " + self.scriptdir + "/scripts" + "; python", "daemon.py"], shell=False)
            #else:
            self.daemon_process = multiprocessing.Process(target=daemonLoop)
            self.daemon_process.start()

    def restartDaemon(self):
        # This function kills the current daemon process and starts a new one
        # This function is called whenever the protocol panel changes to a different protocol
        # This function is necessary because on Windows PyRosetta can start to use well over
        # 4GB of memory if the daemon has loaded memory from multiple protocols
        # Killing the daemon and restarting it clears up that memory so the user's computer
        # doesn't slow down as it moves a lot of stuff into swap space
        savedir = os.getcwd()
        os.chdir(self.scriptdir)
        self.daemon_process.terminate()
        print "Restarting Rosetta protocol daemon..."
        self.daemon_process = multiprocessing.Process(target=daemonLoop)
        self.daemon_process.start()
        os.chdir(savedir)

    def focusEvent(self, event):
        if (event.GetActive()):
            # Protocols read selection information from the sequence window, so update the sequence window
            # If we're going from PyMOL->Protocols, since updates usually happen on the sequence window focus event
            self.seqWin.selectUpdate(False) # Update PyMOL changes in sequence
            self.Protocols.activate()
        event.Skip()

    def setSeqWin(self, seqWin):
        self.seqWin = seqWin
        self.Protocols.setSeqWin(seqWin)
        self.Selection.setSeqWin(seqWin)

    def windowGeometryChange(self, event):
        # This function starts a timer that will write out the size and position of this window to a cfg file
        # so the orientation is saved and can be loaded the next time InteractiveROSETTA is started
        if (not(self.saveTimer.IsRunning())):
            self.saveTimer.Start(5000)
        # We have to do some finagling if this window gets resized because the minimum height
        # of the specific protocol panel needs to be at least 300
        # If the window is shrunk, the protocol panel will shrink down to 300 but then the select
        # panel needs to shrink
        (w, h) = self.GetSize()
        return
        if (h > 560):
            try:
                self.Protocols.protPanel.SetSize((w, h-330))
                self.Protocols.protPanel.SetScrollbars(1, 1, 320, 800)
            except:
                pass
            (x, y) = self.Selection.GetPosition()
            self.Selection.SetPosition((x, h-270))
            self.Selection.SetSize((w-20, self.Selection.GetSize()[1]))
        event.Skip()

    def saveWindowData(self, event):
        homedir = os.path.expanduser("~")
        data = []
        try:
            if (platform.system() == "Windows"):
                f = open(homedir + "\\InteractiveROSETTA\\protwindow.cfg", "r")
            else:
                f = open(homedir + "/.InteractiveROSETTA/protwindow.cfg", "r")
            for aline in f:
                data.append(aline)
            f.close()
        except:
            pass
        if (platform.system() == "Windows"):
            f = open(homedir + "\\InteractiveROSETTA\\protwindow.cfg", "w")
        else:
            f = open(homedir + "/.InteractiveROSETTA/protwindow.cfg", "w")
        itemsFound = [False, False, False, False] # [offX, offY, offW, offH]
        (x, y) = self.GetPosition()
        (w, h) = self.GetSize()
        for aline in data:
            if (aline.find("[OFFSET X]") >= 0):
                itemsFound[0] = True
                f.write("[OFFSET X] " + str(x-self.stdwinx) + "\n")
            elif (aline.find("[OFFSET Y]") >= 0):
                itemsFound[1] = True
                f.write("[OFFSET Y] " + str(y-self.stdwiny) + "\n")
            elif (aline.find("[OFFSET WIDTH]") >= 0):
                itemsFound[2] = True
                f.write("[OFFSET WIDTH] " + str(w-self.stdwinw) + "\n")
            elif (aline.find("[OFFSET HEIGHT]") >= 0):
                itemsFound[3] = True
                f.write("[OFFSET HEIGHT] " + str(h-self.stdwinh) + "\n")
            else:
                f.write(aline)
        for i in range(0, len(itemsFound)):
            if (not(itemsFound[i])):
                if (i == 0):
                    f.write("[OFFSET X] " + str(x-self.stdwinx) + "\n")
                elif (i == 1):
                    f.write("[OFFSET Y] " + str(y-self.stdwiny) + "\n")
                elif (i == 2):
                    f.write("[OFFSET WIDTH] " + str(w-self.stdwinw) + "\n")
                elif (i == 3):
                    f.write("[OFFSET HEIGHT] " + str(h-self.stdwinh) + "\n")
        f.close()