Exemple #1
0
class WriteBmrbChemShiftDepPopup(BasePopup):

    help_url = joinPath(getHelpUrlDir(), 'WriteBmrbChemShiftDep.html')

    def __init__(self, parent, project):

        self.project = project
        self.guiParent = parent
        self.selectedFormats = []
        self.defaultText = 'Select file'

        self.chainDict = {}
        self.chainList = []

        self.shiftListDict = {}
        self.shiftLists = []

        for shiftList in self.project.currentNmrProject.findAllMeasurementLists(
                className='ShiftList'):
            if shiftList.measurements != ():
                label = str(shiftList.serial) + ':' + str(shiftList.name)
                self.shiftListDict[label] = shiftList
                self.shiftLists.append(label)

        if not self.shiftLists:

            showError('Error', 'No shift lists available!')
            return

        BasePopup.__init__(self,
                           parent=parent,
                           title="Project '%s': " % project.name +
                           'Write BMRB chemical shift deposition file',
                           modal=False,
                           transient=True)

    def body(self, master):

        row = 0

        label = Label(master,
                      text="BMRB chemical shift deposition file writer.")
        label.grid(row=row, column=0, columnspan=2, sticky=Tkinter.W)

        row += 1

        label = Label(master, text="Shift lists:")
        label.grid(row=row, column=0, sticky=Tkinter.W)

        self.shiftListSelect = PulldownMenu(master,
                                            entries=self.shiftLists,
                                            callback=self.setChainList,
                                            do_initial_callback=False)
        self.shiftListSelect.grid(row=row, column=1, sticky=Tkinter.EW)

        row += 1

        label = Label(master, text="Chains (only one per file):")
        label.grid(row=row, column=0, sticky=Tkinter.W)

        self.chainListSelect = PulldownMenu(master, entries=self.chainList)
        self.chainListSelect.grid(row=row, column=1, sticky=Tkinter.EW)
        self.setChainList(0, self.shiftLists[0])

        row += 1

        label = Label(master, text="Chemical shift deposition file:")
        label.grid(row=row, column=0, sticky=Tkinter.W)

        self.fileButton = Tkinter.Button(master,
                                         text=self.defaultText,
                                         command=self.selectFile)
        self.fileButton.grid(row=row, column=1, sticky=Tkinter.W)

        row += 1

        texts = ['Write file']
        commands = [
            self.ok
        ]  # This calls 'ok' in BasePopup, this then calls 'apply' in here
        buttons = createDismissHelpButtonList(master,
                                              texts=texts,
                                              commands=commands,
                                              help_url=self.help_url)
        buttons.grid(row=row, columnspan=2, column=0)

    def setChainList(self, shiftListIndex, shiftListLabel):

        #
        # Has to be done... very slow this.
        #

        shiftList = self.shiftListDict[shiftListLabel]

        self.chainDict = {}
        self.chainList = []

        for shift in shiftList.measurements:

            if shift.resonance:

                rs = shift.resonance.resonanceSet

                if rs:
                    atom = rs.findFirstAtomSet().findFirstAtom()
                    chain = atom.residue.chain

                    if chain not in self.chainDict.values():
                        label = chain.molSystem.code + ":'" + chain.code + "'"
                        self.chainDict[label] = chain
                        self.chainList.append(label)

        self.chainListSelect.clearMenuItems()

        if self.chainList:
            self.chainListSelect.setup(self.chainList, 0)

    def selectFile(self):

        fileName = self.fileButton.__getitem__('text')

        if fileName == self.defaultText:
            fileName = 'bmrb.csdep'

        popup = FormatFilePopup(self,
                                file=fileName,
                                component='csdep',
                                format='bmrb')

        if popup.fileSelected:

            self.fileButton.config(text=popup.file)
            popup.destroy()

    def apply(self):

        shiftListLabel = self.shiftListSelect.getSelected()
        shiftList = self.shiftListDict[shiftListLabel]

        try:
            chainLabel = self.chainListSelect.getSelected()
            chain = self.chainDict[chainLabel]
        except:
            showError(
                "No chains",
                "No chains were present or selected. Try running linkResonances first."
            )
            return False

        fileName = self.fileButton.__getitem__('text')

        if fileName == self.defaultText:
            return False

        fileCreated = writeBmrbChemShiftDeposition(self.guiParent, chain,
                                                   shiftList, fileName)

        if fileCreated:
            showInfo("Success",
                     "Succesfully wrote chemical shift deposition file")
        else:
            showError("Not written",
                      "Error writing file %s. File not written" % fileName)
            return False

        return True
class CloudHomologueAssignPopup(BasePopup):

  def __init__(self, parent, *args, **kw):

    self.guiParent = parent
    self.project   = parent.getProject()
    self.molSystem = None
    self.chain     = None
    self.assignment = None
    self.scores     = []

    BasePopup.__init__(self, parent, title="Cloud Threader", **kw)
  
  def body(self, guiFrame):

    guiFrame.grid_columnconfigure(3, weight=1)
    
    row = 0
    label = Label(guiFrame, text='Molecular system: ')
    label.grid(row=row, column=0, sticky=Tkinter.NW)
    self.molSysPulldown = PulldownMenu(guiFrame, self.changeMolSystem, selected_index=-1, do_initial_callback=0)
    self.molSysPulldown.grid(row=row, column=1, sticky=Tkinter.NW)

    label = Label(guiFrame, text='Clouds files: ')
    label.grid(row=row, column=2, sticky=Tkinter.NW)
    self.filenameEntry = Entry(guiFrame,text='perfect00.pdb')
    self.filenameEntry.grid(row=row, column=3, sticky=Tkinter.NW)


    row += 1
    label = Label(guiFrame, text='Chain: ')
    label.grid(row=row, column=0, sticky=Tkinter.NW)
    self.chainPulldown = PulldownMenu(guiFrame, self.changeChain, selected_index=-1, do_initial_callback=0)
    self.chainPulldown.grid(row=row, column=1, sticky=Tkinter.NW)

    label = Label(guiFrame, text='Thread steps: ')
    label.grid(row=row, column=2, sticky=Tkinter.NW)
    self.numStepsEntry = IntEntry(guiFrame,text=3000)
    self.numStepsEntry.grid(row=row, column=3, sticky=Tkinter.NW)
    row += 1

    label = Label(guiFrame, text='Homologue PDB file: ')
    label.grid(row=row, column=0, sticky=Tkinter.NW)
    self.pdbEntry = Entry(guiFrame,text='')
    self.pdbEntry.grid(row=row, column=1, sticky=Tkinter.NW)

    label = Label(guiFrame, text='Dist. Threshold: ')
    label.grid(row=row, column=2, sticky=Tkinter.NW)
    self.distEntry = FloatEntry(guiFrame,text=3.0)
    self.distEntry.grid(row=row, column=3, sticky=Tkinter.NW)

    row += 1

    label = Label(guiFrame, text='Global score: ')
    label.grid(row=row, column=0, sticky=Tkinter.NW)
    self.globalScoreLabel = Label(guiFrame, text='')
    self.globalScoreLabel.grid(row=row, column=1, sticky=Tkinter.NW)

    label = Label(guiFrame, text='Assignment Threshold: ')
    label.grid(row=row, column=2, sticky=Tkinter.NW)
    self.thresholdEntry = FloatEntry(guiFrame,text=-4.5)
    self.thresholdEntry.grid(row=row, column=3, sticky=Tkinter.NW)

    row += 1
    guiFrame.grid_rowconfigure(row, weight=1)
    self.graph = ScrolledGraph(guiFrame, width=300, height=200)
    self.graph.grid(row=row, column=0, columnspan=4, sticky = Tkinter.NSEW)

    row += 1
    texts    = ['Run','Assign!']
    commands = [self.run, self.assignSpinSystems]
    bottomButtons = createDismissHelpButtonList(guiFrame,texts=texts,commands=commands,expands=0,help_url=None)
    bottomButtons.grid(row=row, column=0, columnspan=4, sticky=Tkinter.EW)
    self.assignButton = bottomButtons.buttons[1]

    for func in ('__init__','delete'):
      Implementation.registerNotify(self.updateMolSystems, 'ccp.molecule.MolSystem.MolSystem', func)
      Implementation.registerNotify(self.updateChains, 'ccp.molecule.MolSystem.Chain', func)
    
    self.updateMolSystems()
    self.updateChains()

  def update(self):
  
    if self.assignment and self.scores:
      self.assignButton.enable()
    else:
      self.assignButton.disable()  

  def run(self):
  
    if self.chain:
      pattern = self.filenameEntry.get()
      nSteps  = self.numStepsEntry.get() or 4000
      pdbFile = self.pdbEntry.get()
      dist    =  self.distEntry.get() or 3.0
      pgb     = ProgressBar(self, text='Searching', total=nSteps)
      files   = getFileNamesFromPattern(pattern , '.')
      if not files:
        return
      clouds  = getCloudsFromFile(files, self.chain.root)
       
      score, self.scores, self.assignment = cloudHomologueAssign(self.chain, clouds, pdbFile, dist, nSteps, self.graph, pgb)
 
      pgb.destroy()
      self.globalScoreLabel.set(str(score))
      self.update()

  def assignSpinSystems(self):
   
    if self.assignment and self.scores:
      if showWarning('Query','Are you sure?'):
        threshold = self.thresholdEntry.get() or -4.0
        i = 0
 
        for residue in self.assignment.keys():
          if self.scores[residue] > threshold:
            spinSystem = self.assignment[residue]
            assignSpinSystemResidue(spinSystem,residue=None)
 
        for residue in self.assignment.keys():
          if self.scores[residue] > threshold:
            i += 1
            spinSystem = self.assignment[residue]
            assignSpinSystemResidue(spinSystem,residue=residue)
      
      showWarning('Done','%d residues assigned' % i)
      
  def getMolSystems(self):
  
    names = []
    for molSystem in self.project.molSystems:
      if molSystem.chains:
        names.append( '%s' % (molSystem.code) )
    return names


  def changeMolSystem(self, i, name):
  
    self.molSystem = self.project.findFirstMolSystem(code=name)


  def updateMolSystems(self, *opt):
  
    names = self.getMolSystems()
    if names:
      if not self.molSystem:
        self.molSystem = self.project.findFirstMolSystem(code=names[0])
      self.molSysPulldown.setup(names, names.index(self.molSystem.code))


  def getChains(self):
  
    chains = []
    if self.molSystem:
      for chain in self.molSystem.chains:
        chains.append( [chain.code, chain] )
	
    return chains


  def changeChain(self, i, name=None):
    
    if not name:
      i = self.chainPulldown.selected_index
    
    chains = self.getChains()
    if chains:
      self.chain = chains[i][1]
    
    
  def updateChains(self, *chain):
  
    chains = self.getChains()
 
    if chains:
      names = [x[0] for x in chains]
      if (not self.chain) or (self.chain.code not in names):
        self.chain = chains[0][1]
      self.chainPulldown.setup(names, names.index(self.chain.code) )

    self.update()

  def destroy(self):

    for func in ('__init__','delete'):
      Implementation.unregisterNotify(self.updateMolSystems, 'ccp.molecule.MolSystem.MolSystem', func)
      Implementation.unregisterNotify(self.updateChains, 'ccp.molecule.MolSystem.Chain', func)

    BasePopup.destroy(self)
Exemple #3
0
class EditNoeClassesPopup(BasePopup):

  def __init__(self, parent, *args, **kw):

    self.guiParent = parent
    BasePopup.__init__(self, parent=parent, title='NOE Distance Classes', **kw)

  def body(self, guiFrame):
  
    self.noeClassChoice = None
    self.spectrum = None
    self.intensEntry = FloatEntry(self, returnCallback=self.setIntens, width=5)
    self.targetEntry = FloatEntry(self, returnCallback=self.setTarget, width=5)
    self.minEntry    = FloatEntry(self, returnCallback=self.setMin,    width=5)
    self.maxEntry    = FloatEntry(self, returnCallback=self.setMax,    width=5)
   
    row = 0

    label = Label(guiFrame, text='Spectrum: ', grid=(row,0))
    tipText = ''
    self.spectrumPulldown = PulldownMenu(guiFrame,self.changeSpectrum, grid=(row,1))

    row +=1

    guiFrame.expandGrid(row, 1)

    tipTexts = ['Lower bound of this intensity category. Values are relative to reference intensity.',
                'Target restraint distance for this category',
                'Lower bound distance for this category',
                'Upper bound distance for this category']
    headingList = ['Min. NOE\nIntensity','Target\nDist','Min\nDist','Max\nDist']
    editWidgets = [self.intensEntry,self.targetEntry,self.minEntry,self.maxEntry]
    editGetCallbacks = [self.getIntens,self.getTarget,self.getMin,self.getMax]
    editSetCallbacks = [self.setIntens,self.setTarget,self.setMin,self.setMax]
    
    self.noeClassMatrix = ScrolledMatrix(guiFrame,
                                         headingList=headingList,
                                         callback=self.selectClass,
                                         tipTexts=tipTexts,
                                         editWidgets=editWidgets,
                                         editSetCallbacks=editSetCallbacks,
                                         editGetCallbacks=editGetCallbacks,
                                         deleteFunc=self.deleteClass,
                                         grid=(row,0), gridSpan=(1,2))
                                         

    row +=1

    tipTexts = ['Add a new distance restraint category',
                'Deleted selected restraint categor']
    texts = ['Add Class','Delete Class']
    commands = [self.addClass,self.deleteClass]
    self.bottomButtons = UtilityButtonList(guiFrame, doClone=False, grid=(row,0),
                                           gridSpan=(1,2), tipTexts=tipTexts,
                                           commands=commands, texts=texts)

    for func in ('__init__','delete','setName'):
      self.registerNotify(self.updateSpectra, 'ccp.nmr.Nmr.Experiment', func)
      self.registerNotify(self.updateSpectra, 'ccp.nmr.Nmr.DataSource', func)

    self.updateSpectra()
    self.update()

  def open(self):
  
    self.updateSpectra()
    self.update()
    BasePopup.open(self)

  def updateSpectra(self, *opt):
    
    spectra = self.getSpectra()
    if not spectra:
      return
    
    names = [self.getSpectrumName(x) for x in spectra]
    if (not self.spectrum) or (self.spectrum not in spectra):
      self.spectrum = spectra[0]
    
    self.spectrumPulldown.setup(names, names.index(self.getSpectrumName(self.spectrum)) )
    
    self.update()

  def changeSpectrum(self, i, name):
  
    self.spectrum = self.getSpectra()[i]
    self.update()

  def getSpectrumName(self,spectrum):
  
    name = '%s:%s' % (spectrum.experiment.name,spectrum.name)
    return name
  
  def getSpectra(self):
  
    spectra = set()
    peakLists = getThroughSpacePeakLists(self.nmrProject)
    
    for peakList in peakLists:
      spectra.add(peakList.dataSource)
 
    spectra = list(spectra)
    spectra.sort()
 
    return spectra
    
  def selectClass(self, noeClass, row, col):
  
    if noeClass:
      self.noeClassChoice = (row, noeClass)
      
    if len(self.noeClassMatrix.objectList) > 1:
      self.bottomButtons.buttons[1].enable()
    else:
      self.bottomButtons.buttons[1].disable()

  def addClass(self):
  
    if self.spectrum:
      noeClass = [0.0,6.0,0.0,6.0]
 
      noeClasses = getIntensityDistanceTable(self.spectrum)
      noeClasses.append(noeClass)
      setSpectrumNoeDistanceClasses(self.spectrum, noeClasses)

      self.update()
  
  def deleteClass(self, *event):
    
    if self.spectrum:
      noeClasses = getIntensityDistanceTable(self.spectrum)

      if self.noeClassChoice and (self.noeClassChoice[1] in noeClasses):
        if len(noeClasses) > 1:
          (i,noeClass) = self.noeClassChoice
          noeClasses.remove(noeClass)
          self.noeClassChoice = None
          setSpectrumNoeDistanceClasses(self.spectrum, noeClasses)
          self.update()
    
  def setIntens(self, event):
  
    if self.noeClassChoice:
      val = self.intensEntry.get() or 0.0
      self.noeClassChoice[1][0] = val
      
    self.updateClass()
  
  def getIntens(self, row):
  
    if row:
      self.intensEntry.set(row[0])
  
  def setTarget(self, event):
  
    if self.noeClassChoice:
      val = self.targetEntry.get() or 0.0
      self.noeClassChoice[1][1] = val
      
    self.updateClass()
  
  def getTarget(self, row):
  
    if row:
      self.targetEntry.set(row[1])
  
  def setMin(self, event):
  
    if self.noeClassChoice:
      val = self.minEntry.get() or 0.0
      self.noeClassChoice[1][2] = val
      
    self.updateClass()
  
  def getMin(self, row):
  
    if row:
      self.minEntry.set(row[2])
  
  def setMax(self, event):
  
    if self.noeClassChoice:
      val = self.maxEntry.get() or 0.0
      self.noeClassChoice[1][3] = val
      
    self.updateClass()
  
  def getMax(self, row):
  
    if row:
      self.maxEntry.set(row[3])
    
  def getClasses(self):
  
    noeClasses = []
    if self.spectrum:
      noeClasses = getIntensityDistanceTable(self.spectrum)

    if noeClasses:
      for i in range(len(noeClasses)):
        (intens,target,minimum,maximum) = noeClasses[i]

        if minimum > maximum:
          (minimum,maximum) = (maximum,minimum)
        minimum = min(target, minimum)
        maximum = max(target, maximum)
        intens  = max(intens, 0.0)
        
        noeClasses[i] = [intens,target,minimum,maximum]
      noeClasses.sort()
      noeClasses.reverse()
    
    else:
      noeClasses = []
      if self.spectrum:
        # default
        noeClasses = getIntensityDistanceTable(self.spectrum)
      
    return noeClasses
    
  def updateClass(self):
  
    if self.spectrum and self.noeClassChoice:
      (i, noeClass) = self.noeClassChoice
      noeClasses = getIntensityDistanceTable(self.spectrum)
      noeClasses[i] = noeClass
      setSpectrumNoeDistanceClasses(self.spectrum, noeClasses)
      self.update()
    
  def update(self):


    textMatrix = []
    objectList = self.getClasses()
    
    if self.spectrum:
      if self.noeClassChoice and (len(objectList) > 1):
        self.bottomButtons.buttons[1].enable()
      else:
        self.bottomButtons.buttons[1].disable()
      self.bottomButtons.buttons[0].enable()
    else:
      self.bottomButtons.buttons[0].disable()
      self.bottomButtons.buttons[1].disable()
      
    for (intens,target,minimum,maximum) in objectList:
      datum = []
      datum.append(intens)
      datum.append(target)
      datum.append(minimum)
      datum.append(maximum)
      textMatrix.append(datum)
    
    self.noeClassMatrix.update(objectList=objectList,textMatrix=textMatrix)
    
    if self.spectrum:
      setSpectrumNoeDistanceClasses(self.spectrum,objectList)
  
  def destroy(self):

    for func in ('__init__','delete','setName'):
      self.unregisterNotify(self.updateSpectra, 'ccp.nmr.Nmr.Experiment', func)
      self.unregisterNotify(self.updateSpectra, 'ccp.nmr.Nmr.DataSource', func)

    BasePopup.destroy(self)
Exemple #4
0
class ConfirmSeqSpinSystemsPopup(BasePopup):
    def __init__(self, parent, *args, **kw):

        self.guiParent = parent
        self.spinSystems = []
        self.spectrum = None
        self.spectra = []
        self.waiting = 0
        self.shiftList = None
        self.spinSystem = None
        self.link = '-1'

        BasePopup.__init__(self,
                           parent=parent,
                           title="Confirm Sequential Spin System",
                           **kw)

    def body(self, guiFrame):

        guiFrame.grid_columnconfigure(0, weight=1)

        row = 0

        frame = Frame(guiFrame)
        frame.grid(row=row, column=0, sticky='nsew')
        frame.grid_columnconfigure(3, weight=1)

        label = Label(frame, text='Shift List:')
        label.grid(row=0, column=0, sticky='w')

        self.shiftListPulldown = PulldownMenu(frame,
                                              callback=self.setShiftList)
        self.shiftListPulldown.grid(row=0, column=1, sticky='w')

        label = Label(frame, text='Sequential Link Type:')
        label.grid(row=0, column=2, sticky='w')

        entries = ['-1', '-1,+1', '+1']
        self.linkPulldown = PulldownMenu(frame,
                                         callback=self.setLink,
                                         entries=entries,
                                         do_initial_callback=False,
                                         selected_index=entries.index(
                                             self.link))
        self.linkPulldown.grid(row=0, column=3, sticky='w')

        row += 1
        frame = LabelFrame(guiFrame, text='Link Atoms:')
        frame.grid(row=row, column=0, sticky='nsew')
        frame.grid_columnconfigure(0, weight=1)
        frame.grid_rowconfigure(0, weight=1)

        labels = ['C', 'CA', 'CB', 'CG', 'CD', 'H', 'HA', 'HB', 'HG', 'HD']
        selected = ['CA', 'CB']
        self.atomSelector = PartitionedSelector(frame,
                                                objects=labels,
                                                labels=labels,
                                                selected=selected,
                                                toggledBg='#808080',
                                                callback=self.changeAtoms,
                                                maxRowObjects=10)
        self.atomSelector.grid(row=0, column=0, sticky='ew')

        row += 1
        guiFrame.grid_rowconfigure(row, weight=1)

        frame = LabelFrame(guiFrame, text='Predicted Residue Assignments')
        frame.grid(row=row, column=0, sticky='nsew')
        frame.grid_columnconfigure(0, weight=1)
        frame.grid_rowconfigure(0, weight=1)

        headingList = [
            '#', 'Predicted\nResidue', 'Prob.', 'Links', 'CA', 'CA -1', 'CB',
            'CB -1'
        ]
        self.spinSystemMatrix = ScrolledMatrix(frame,
                                               headingList=headingList,
                                               callback=self.selectSpinSystem,
                                               multiSelect=1)
        self.spinSystemMatrix.grid(row=0, column=0, sticky='nsew')

        row += 1
        texts = ['Link Selected', 'Link All', 'Commit Assignment']
        commands = [
            self.linkSelectedSpinSystems, self.linkAllSpinSystems,
            self.commitAssignments
        ]
        buttonList = UtilityButtonList(guiFrame,
                                       texts=texts,
                                       commands=commands,
                                       helpUrl=self.help_url)
        buttonList.grid(row=row, column=0, sticky='ew')

        self.buttons = buttonList.buttons

        for func in ('__init__', 'delete'):
            for clazz in ('ccp.nmr.Nmr.ShiftList', ):
                self.registerNotify(self.updateShiftLists, clazz, func)

        for func in ('__init__', 'delete', 'setNmrChains', 'setResidue',
                     'setResonances', 'addResonance', 'removeResonance'):
            self.registerNotify(self.updateSpinSystemsAfter,
                                'ccp.nmr.Nmr.ResonanceGroup', func)

        self.updateShiftLists()

    def setLink(self, index, name):

        self.link = name
        self.updateSpinSystemsAfter()

    def updateButtons(self):

        if len(self.spinSystemMatrix.currentObjects) > 1:
            self.buttons[0].enable()
        else:
            self.buttons[0].disable()

        if self.spinSystemMatrix.objectList:
            self.buttons[1].enable()
        else:
            self.buttons[1].disable()

        if self.spinSystem:
            self.buttons[2].enable()
        else:
            self.buttons[2].disable()

    def changeAtoms(self, *opt):

        self.updateSpinSystemsAfter()

    def getShiftListNames(self, shiftLists):

        shiftListNames = []
        for shiftList in shiftLists:
            if not hasattr(shiftList, 'name'):
                shiftList.name = "ShiftList " + str(shiftList.serial)
            elif not shiftList.name:
                shiftList.name = "ShiftList " + str(shiftList.serial)
            shiftListNames.append(shiftList.name)

        return shiftListNames

    def updateShiftLists(self, *opt):

        shiftLists = list(
            self.nmrProject.findAllMeasurementLists(className='ShiftList'))
        shiftListNames = self.getShiftListNames(shiftLists)
        shiftList = None
        index = -1

        if shiftListNames:

            if self.shiftList in shiftLists:
                shiftList = self.shiftList
            else:
                shiftList = shiftLists[0]

            index = shiftLists.index(shiftList)

        self.shiftList = shiftList
        self.shiftListPulldown.setup(shiftListNames, index)

    def setShiftList(self, index, name=None):

        shiftLists = list(
            self.nmrProject.findAllMeasurementLists(className='ShiftList'))
        if shiftLists:
            self.shiftList = shiftLists[index]
        else:
            self.shiftList = None

        self.updateSpinSystemsAfter()

    def linkSelectedSpinSystems(self):

        spinSystems = self.spinSystemMatrix.currentObjects
        self.linkSpinSystems(spinSystems)

    def linkAllSpinSystems(self):

        spinSystems = self.spinSystemMatrix.objectList
        self.linkSpinSystems(spinSystems)

    def linkSpinSystems(self, spinSystems):

        data = []

        for spinSystem in spinSystems:
            residue, p = self.getProbableResidue(spinSystem)
            key = '%s%s%4.4d' % (residue.chain.molSystem.code,
                                 residue.chain.code, residue.seqCode)
            data.append([key, residue.seqCode, residue, spinSystem])

        data.sort()
        seqCodes = [x[1] for x in data]
        residues = [x[2] for x in data]
        spinSystems = [x[3] for x in data]

        N = len(data)
        for i in range(N):

            if i > 0:
                delta = seqCodes[i] - seqCodes[i - 1]
                if delta == 1 and (residues[i].chain is residues[i - 1].chain):
                    ss = findConnectedSpinSystem(spinSystems[i], delta=-1)
                    if ss:
                        mergeSpinSystems(
                            ss,
                            spinSystems[i -
                                        1])  # copy resonances across & delete

                    makeSeqSpinSystemLink(spinSystems[i - 1],
                                          spinSystems[i],
                                          delta=1)

            if i < N - 1:
                delta = seqCodes[i + 1] - seqCodes[i]
                if delta == 1 and (residues[i].chain is residues[i + 1].chain):
                    ss = findConnectedSpinSystem(spinSystems[i], delta=1)
                    if ss:
                        mergeSpinSystems(
                            ss,
                            spinSystems[i +
                                        1])  # copy resonances across & delete

                    makeSeqSpinSystemLink(spinSystems[i],
                                          spinSystems[i + 1],
                                          delta=1)

        self.updateSpinSystemsAfter()

    def commitAssignments(self):

        merge = showYesNo('Query', 'Merge with any existing spin systems?',
                          self)

        for spinSystem in self.spinSystemMatrix.currentObjects:
            if not spinSystem.residue:
                residue, p = self.getProbableResidue(spinSystem)
                assignSpinSystemResidue(spinSystem, residue, warnMerge=merge)

    def getProbableResidue(self, spinSystem):

        residue = None
        probability = 0.0

        if spinSystem.residue:
            return spinSystem.residue, 1.0

        data = []
        for residueProb in spinSystem.residueProbs:
            data.append((residueProb.weight, residueProb.possibility))
        data.sort()

        if data:
            residue, probability = data[-1]

        return residue, probability

    def getTentativeSpinSystems(self):

        spinSystemsList = []

        if self.project:

            for spinSystem in self.nmrProject.sortedResonanceGroups():
                if spinSystem.residueProbs and not spinSystem.residue:
                    #if spinSystem.residue:
                    residue, p = self.getProbableResidue(spinSystem)
                    key = '%s%s%4.4d' % (residue.chain.molSystem.code,
                                         residue.chain.code, residue.seqCode)
                    spinSystemsList.append((key, spinSystem))

        spinSystemsList.sort()

        return [x[1] for x in spinSystemsList]

    def updateSpinSystemsAfter(self, spinSystem=None):

        if self.waiting:
            return
        else:
            if spinSystem:
                if not spinSystem.residueProbs:
                    return
                if spinSystem.residue:
                    return

            self.waiting = True
            self.after_idle(self.updateSpinSystems)

    def getHeadings(self):

        headingList = ['#', 'Predicted\nResidue', 'Prob.', 'Links']

        atoms = self.atomSelector.getSelected()

        for atom in atoms:

            headingList.append(atom)

            if self.link == '-1':
                headingList.append('%s -1' % atom)
                headingList.append('D %s -1' % atom)

            elif self.link == '+1':
                headingList.append('%s +1' % atom)
                headingList.append('D %s +1' % atom)

            else:
                headingList.append('%s -1' % atom)
                headingList.append('D %s -1' % atom)
                headingList.append('%s +1' % atom)
                headingList.append('D %s +1' % atom)

        return headingList

    def addShiftData(self, spinSystem, datum):

        prevSS, nextSS = self.getConnectedSpinSystems(spinSystem)
        atoms = self.atomSelector.getSelected()
        dict = {}

        residue, p = self.getProbableResidue(spinSystem)
        prevRes = residue.chain.findFirstResidue(seqCode=residue.seqCode - 1)
        nextRes = residue.chain.findFirstResidue(seqCode=residue.seqCode + 1)
        prevSS0 = None
        nextSS0 = None
        for ss in self.getTentativeSpinSystems():
            if self.getProbableResidue(ss)[0] is prevRes:
                prevSS0 = ss
            if self.getProbableResidue(ss)[0] is nextRes:
                nextSS0 = ss
            if nextSS0 and prevSS0:
                break

        for atom in atoms:

            resonances = []
            resonancesPrev = []
            resonancesNext = []
            resonancesPrev0 = []
            resonancesNext0 = []
            for resonance0 in spinSystem.sortedResonances():
                for name in resonance0.assignNames:
                    if name[:2] == atom:
                        resonances.append(resonance0)
                        break

            text = ''
            if resonances:
                text = self.getResonanceText(resonances)
            datum.append(text)

            if prevSS and ('-1' in self.link):
                for resonance0 in prevSS.sortedResonances():
                    for name in resonance0.assignNames:
                        if name[:2] == atom:
                            resonancesPrev.append(resonance0)
                            break

            deltasPrev = []
            if prevSS0 and resonancesPrev:
                for resonance1 in prevSS0.sortedResonances():
                    for name1 in resonance1.assignNames:
                        if name1[:2] == atom:
                            shift1 = resonance1.findFirstShift(
                                parentList=self.shiftList)
                            deltas = []
                            for resonance2 in resonancesPrev:
                                shift2 = resonance2.findFirstShift(
                                    parentList=self.shiftList)
                                if shift1 and shift2:
                                    deltas.append(
                                        abs(shift1.value - shift2.value))

                            if deltas:
                                deltas.sort()
                                deltasPrev.append('%.2f' % deltas[0])
                            break

            if nextSS and ('+1' in self.link):
                for resonance0 in nextSS.sortedResonances():
                    for name in resonance0.assignNames:
                        if name[:2] == atom:
                            resonancesNext.append(resonance0)
                            break

            deltasNext = []
            if nextSS0 and resonancesNext:
                for resonance1 in nextSS0.sortedResonances():
                    for name1 in resonance1.assignNames:
                        if name1[:2] == atom:
                            shift1 = resonance1.findFirstShift(
                                parentList=self.shiftList)
                            deltas = []
                            for resonance2 in resonancesNext:
                                shift2 = resonance2.findFirstShift(
                                    parentList=self.shiftList)
                                if shift1 and shift2:
                                    deltas.append(
                                        abs(shift1.value - shift2.value))

                            if deltas:
                                deltas.sort()
                                deltasNext.append('%.2f' % deltas[0])
                            break

            if self.link == '-1':
                ppms = ''
                diff = ''
                if resonancesPrev:
                    ppms = self.getResonanceText(resonancesPrev)
                    diff = ','.join(deltasPrev)
                datum.append(ppms)
                datum.append(diff)

            elif self.link == '+1':
                ppms = ''
                diff = ''
                if resonancesNext:
                    ppms = self.getResonanceText(resonancesNext)
                    diff = ','.join(deltasNext)
                datum.append(ppms)
                datum.append(diff)

            else:
                ppms = ''
                diff = ''
                if resonancesPrev:
                    ppms = self.getResonanceText(resonancesPrev)
                    diff = ','.join(deltasPrev)
                datum.append(ppms)
                datum.append(diff)

                ppms = ''
                diff = ''
                if resonancesNext:
                    ppms = self.getResonanceText(resonancesNext)
                    diff = ','.join(deltasNext)
                datum.append(ppms)
                datum.append(diff)

    def updateSpinSystems(self):

        textMatrix = []
        objectList = []
        colorMatrix = []
        headingList = self.getHeadings()

        for spinSystem in self.getTentativeSpinSystems():

            residueText = None
            residue, probability = self.getProbableResidue(spinSystem)
            if residue:
                residueText = '%d%s' % (residue.seqCode,
                                        getResidueCode(residue))

            links = []
            color = '#D04040'

            if findConnectedSpinSystem(spinSystem, delta=-1):
                links.append('-1')

            if findConnectedSpinSystem(spinSystem, delta=1):
                links.append('+1')

            if len(links) == 2:
                color = '#40B040'
            elif len(links) == 1:
                color = '#B0B040'

            datum = []
            datum.append(spinSystem.serial)
            datum.append(residueText)
            datum.append(probability)
            datum.append(' '.join(links))

            self.addShiftData(spinSystem, datum)

            colors = [None] * len(headingList)
            colors[3] = color

            objectList.append(spinSystem)
            textMatrix.append(datum)
            colorMatrix.append(colors)

        if self.spinSystem not in objectList:
            self.spinSystem = None

        self.spinSystemMatrix.update(headingList=headingList,
                                     objectList=objectList,
                                     textMatrix=textMatrix,
                                     colorMatrix=colorMatrix)
        self.updateButtons()
        self.waiting = False

    def getResonanceText(self, resonances):

        shifts = []

        for resonance in resonances:
            shift = resonance.findFirstShift(parentList=self.shiftList)
            if shift:
                shifts.append('%.2f' % shift.value)

        return ','.join(shifts)

    def getConnectedSpinSystems(self, spinSystem):

        if self.link == '-1':
            prevSS = findConnectedSpinSystem(spinSystem, delta=-1)
            nextSS = None
        elif self.link == '+1':
            prevSS = None
            nextSS = findConnectedSpinSystem(spinSystem, delta=1)
        else:
            prevSS = findConnectedSpinSystem(spinSystem, delta=-1)
            nextSS = findConnectedSpinSystem(spinSystem, delta=1)

        return prevSS, nextSS

    def selectSpinSystem(self, object, row, col):

        self.spinSystem = object
        self.updateButtons()

    def destroy(self):

        for func in ('__init__', 'delete'):
            for clazz in ('ccp.nmr.Nmr.ShiftList', ):
                self.unregisterNotify(self.updateShiftLists, clazz, func)

        for func in ('__init__', 'delete', 'setNmrChains', 'setResidue',
                     'setResonances', 'addResonance', 'removeResonance'):
            self.unregisterNotify(self.updateSpinSystemsAfter,
                                  'ccp.nmr.Nmr.ResonanceGroup', func)

        BasePopup.destroy(self)
Exemple #5
0
class EditSymmetryPopup(BasePopup):

    def __init__(self, parent, project):

        self.parent         = parent
        self.ccpnProject    = project
        self.hProject        = project.currentHaddockProject
        self.molPartner     = None
        self.molecules      = []
        self.symmetrySet    = None
        self.symmetryOp     = None
        self.symmetryCode    = None
        self.waiting        = False

        BasePopup.__init__(self, parent=parent, title='Symmetry Operations')

        self.font = 'Helvetica 12'
        self.setFont()

    def body(self, guiFrame):

        guiFrame.grid_columnconfigure(0, weight=1)
        guiFrame.grid_rowconfigure(1, weight=1)

        frame = LabelFrame(guiFrame, text='Options')
        frame.grid(row=0,column=0,sticky='ew')
        frame.grid_columnconfigure(5, weight=1)

        # Choose type of symmetry set to define or change (if allready present in the model)
        self.molLabel = Label(frame, text='Symmetry Operator:')
        self.molLabel.grid(row=0,column=2,sticky='w')
        self.symmCodePulldown = PulldownMenu(frame, callback=self.setSymmCode, entries=['NCS','C2','C3','C5'], do_initial_callback=False)
        self.symmCodePulldown.grid(row=0,column=3,sticky='w')

        frame = LabelFrame(guiFrame, text='Symmetry Operations')
        frame.grid(row=1,column=0,sticky='nsew')
        frame.grid_columnconfigure(0, weight=1)
        frame.grid_rowconfigure(0, weight=1)

        self.molSysPulldown   = PulldownMenu(self, callback=self.setMolSystem, do_initial_callback=False)
        self.chainSelect      = MultiWidget(self, CheckButton, callback=self.setChains, minRows=0, useImages=False)
        self.segStartEntry    = IntEntry(self, returnCallback=self.setSegStart, width=6)
        self.segLengthEntry   = IntEntry(self, returnCallback=self.setSegLength, width=6)

        headings = ['#','Symmetry\noperator','Mol System','Chains','Start\nresidue','Segment\nlength']  
        editWidgets      = [None, None, self.molSysPulldown, self.chainSelect, self.segStartEntry, self.segLengthEntry] 
        editGetCallbacks = [None, None, self.getMolSystem, self.getChains, self.getSegStart, self.getSegLength]
        editSetCallbacks = [None, self.setSymmCode, self.setMolSystem, self.setChains, self.setSegStart, self.setSegLength]
        
        self.symmetryMatrix = ScrolledMatrix(frame,headingList=headings,
                                             callback=self.selectSymmetry,
                                             editWidgets=editWidgets,
                                             editGetCallbacks=editGetCallbacks,
                                             editSetCallbacks=editSetCallbacks)
        self.symmetryMatrix.grid(row=0,column=0,sticky='nsew')

        texts = ['Add Symmetry Set','Remove Symmetry Set']
        commands = [self.addSymmetrySet,self.removeSymmetrySet]
        self.buttonList = createDismissHelpButtonList(guiFrame, texts=texts, commands=commands, expands=True)
        self.buttonList.grid(row=2,column=0,sticky='ew')
        
        self.updateMolPartners()
        self.notify(self.registerNotify)

        #Temporary report of parameters
        print self.molSystem
        print self.molecules
        print self.symmetrySet
        print self.symmetryOp
        print self.symmetryCode

    def getMolSystem(self, partner):

        """Select molecular system from list of molsystems stored in the project"""

        names = []; index = -1
        molSystem = partner.molSystem
        molSystems = self.ccpnProject.sortedMolSystems()
        if molSystems:
            names = [ms.code for ms in molSystems]
            if molSystem not in molSystems: 
                molSystem = molSystems[0]
                index = molSystems.index(molSystem)

        self.molSysPulldown.setup(names, index)

    def getChains(self, partner):
  
        names  = []
        values = []

        molSystem = partner.molSystem
        if molSystem:
            for chain in molSystem.sortedChains():
                names.append(chain.code)

                if not partner.chains:
                  values.append(True)

                elif partner.findFirstChain(chain=chain):
                  values.append(True)

                else:
                  values.append(False)   

                self.chainSelect.set(values=values,options=names)   

        else:
            showWarning('Warning','Set Mol System or ensemble first',parent=self)
            self.symmetryMatrix.keyPressEscape()        
    
    def getSegLength(self, symmetryOp):
        
        if symmetryOp and symmetryOp.segmentLength: self.segLengthEntry.set(symmetryOp.segmentLength)

    def getSegStart(self):
    
        pass

    def setMolSystem(self, partner, name=None):
  
        """Get all molsystems as stored in the project as list"""

        index =  self.molSysPulldown.getSelectedIndex()
        molSystems = self.ccpnProject.sortedMolSystems()
  
        if molSystems:
            molSystem = molSystems[index]
            self.molPartner.molSystem = molSystem
            chains = molSystem.sortedChains()
            if (not self.molPartner.chains) and chains: setPartnerChains(self.molPartner,chains)

        self.updateAllAfter()

    def setChains(self, obj):

        """Get the list of chains for the selected molsystem"""

        if self.molPartner and self.molPartner.molSystem:
            if obj is not None:
                chains = self.molPartner.molSystem.sortedChains()
                values = self.chainSelect.get()
                chains = [chains[i] for i in range(len(values)) if values[i]]
                setPartnerChains(self.molPartner,chains)

        self.symmetryMatrix.keyPressEscape()  
        self.updateAllAfter()
        
    def setSegLength(self, event):
        
        value = self.segLengthEntry.get() or 1
        self.symmetryOp.segmentLength = value

    def setSegStart(self):
        
        pass    

    def setSymmCode(self, index, name=None): 

        self.symmetryCode = self.symmCodePulldown.getSelected()    

    def selectSymmetry(self, obj, row, col):
        
        self.symmetryOp = obj
        self.updateMolSysPulldown()

    def notify(self, notifyFunc):
  
        for func in ('__init__', 'delete', 'setSymmetryCode','setSegmentLength'):
            notifyFunc(self.updateAllAfter, 'molsim.Symmetry.Symmetry', func)

        for func in ('__init__', 'delete','setfirstSeqId'):
            notifyFunc(self.updateAllAfter, 'molsim.Symmetry.Segment', func)

    def addSymmetrySet(self):
            
        if not self.ccpnProject.molSystems:
            showWarning('Warning','No molecular systems present in CCPN project',parent=self)
            return

            molSystem = self.ccpnProject.findFirstMolSystem()
            partner = self.hProject.newHaddockPartner(code=molSystem.code, molSystem=molSystem)
            setPartnerChains(partner, molSystem.chains)

            self.updateAllAfter()
            
    def removeSymmetrySet(self):
        
        pass            
    
    def updateAllAfter(self, obj=None):

        if self.waiting: return
        else:
            self.waiting = True
            self.after_idle(self.updateSymmetries,
                            self.updateMolPartners)
    
    def updateMolPartners(self):

        textMatrix = []
        objectList = []

        for partner in self.hProject.sortedHaddockPartners():
            datum = [partner.code,
                     self.symmetryCode,
                     partner.molSystem.code,
                     ','.join([c.chain.code for c in partner.chains]),
                     partner.autoHistidinePstate and 'Yes' or 'No',
                     partner.isDna and 'Yes' or 'No']
            
            objectList.append(partner)
            textMatrix.append(datum)

        self.symmetryMatrix.update(objectList=objectList, textMatrix=textMatrix)
        self.updateMolSysPulldown()
    
    def updateMolSysPulldown(self):

        names = []
        index = -1

        partners = self.hProject.sortedHaddockPartners()

        if partners:
            if self.molPartner not in partners:
                self.molPartner = partners[0]

            names = ['Partner %s' % p.code for p in partners]
            index = partners.index(self.molPartner)

        else: self.molPartner = None

        self.molSysPulldown.setup(names, index)
        
    def updateSymmetries(self):

        textMatrix  = []; objectList  = []
        if self.symmetrySet:
            for symmetryOp in self.symmetrySet.symmetries:
                chains = []; segments = [] 
                length = symmetryOp.segmentLength

                for segment in symmetryOp.sortedSegments():
                    code = segment.chainCode
                    chain = self.molSystem.findFirstChain(code=code)

                    if chain:
                        chains.append(code)
                        seqId = segment.firstSeqId
                        residue1 = chain.findFirstResidue(seqId=seqId)
                        residue2 = chain.findFirstResidue(seqId=seqId+length-1)
                        segments.append('%s:%d-%d' % (code,residue1.seqCode,residue2.seqCode))

                datum = [symmetryOp.serial, symmetryOp.symmetryCode, length, '\n'.join(chains), '\n'.join(segments)]
                objectList.append(symmetryOp)
                textMatrix.append(datum)

        self.symmetryMatrix.update(objectList=objectList, textMatrix=textMatrix)
        self.waiting = False

    def destroy(self):

        self.notify(self.unregisterNotify)
        BasePopup.destroy(self)
class SetupStructureCalcFrame(Frame):
    def __init__(self, parent, application, *args, **kw):

        self.parent = parent
        self.molSystem = None
        self.constraintSet = None
        self.application = application
        self.project = application.project
        self.waiting = False
        self.tableObj = None

        Frame.__init__(self, parent=parent, **kw)
        self.grid_columnconfigure(3, weight=1)

        label = Label(self, text='Molecular system: ')
        label.grid(row=0, column=0, sticky='nw')
        self.molSysPulldown = PulldownMenu(
            self,
            self.changeMolSystem,
            tipText='Select which molecular system to use in the calculation')
        self.molSysPulldown.grid(row=0, column=1, sticky='nw')

        label = Label(self, text='Constraint Set: ')
        label.grid(row=0, column=2, sticky='nw')
        self.constraintSetPulldown = PulldownMenu(
            self,
            self.changeConstraintSet,
            tipText='Select which set of restraints to use in the calculation')
        self.constraintSetPulldown.grid(row=0, column=3, sticky='nw')

        self.shiftListPulldown = PulldownMenu(
            parent,
            callback=self.setShiftList,
            do_initial_callback=False,
            tipText='select the shift list to use in the calculation')

        tipTexts = [
            'The type of ccp object used in the calculation',
            'The identifier for the input data',
            'A toggle whether to use the data',
            'Whether to filter violated restraints',
            'Whether to keep CCPN assignments (otherwise new restraint assignments will be used)',
            'Whether the restraints are overly anbiguous and need refining',
            'The shift list to use for shift-peak matching'
        ]
        headingList = [
            'Input Class', 'Id', 'Use?', 'Filter\nViolated',
            'Keep\nAssignments?', 'Ambiguous\nProtocol', 'Shift List'
        ]
        editWidgets = [
            None, None, None, None, None, None, self.shiftListPulldown
        ]
        editGetCallbacks = [
            None, None, self.toggleUse, self.toggleFilterViol,
            self.toggleKeepAssign, self.toggleAmbig, self.getShiftList
        ]
        editSetCallbacks = [
            None, None, None, None, None, None, self.setShiftList
        ]

        self.grid_rowconfigure(1, weight=1)
        self.scrolledMatrix = ScrolledMatrix(self,
                                             headingList=headingList,
                                             editSetCallbacks=editSetCallbacks,
                                             editGetCallbacks=editGetCallbacks,
                                             editWidgets=editWidgets,
                                             multiSelect=True,
                                             tipTexts=tipTexts,
                                             callback=self.selectCell)

        self.scrolledMatrix.grid(row=1, column=0, columnspan=4, sticky='nsew')
        self.scrolledMatrix.doEditMarkExtraRules = self.doEditMarkExtraRules

        #texts    = ['','','']

        #commands = [None,None,None]

        #self.bottomButtons = ButtonList(self, texts=texts, expands=True, commands=commands)
        #self.bottomButtons.grid(row=2, column=0, columnspan=4, sticky='ew')

        self.updateMolSystems()
        self.updateConstraintSets()

        notify = self.application.registerNotify
        for func in ('__init__', 'delete'):
            notify(self.updateAfter, 'ccp.nmr.Nmr.PeakList', func)
            notify(self.updateConstraintSets,
                   'ccp.nmr.NmrConstraint.NmrConstraintStore', func)
            notify(self.updateMolSystems, 'ccp.molecule.MolSystem.MolSystem',
                   func)
            notify(self.updateMolSystems, 'ccp.molecule.MolSystem.Chain', func)

        for func in ('__init__', 'delete', 'setName'):
            notify(self.updateAfter, 'ccp.nmr.Nmr.Experiment', func)
            notify(self.updateAfter, 'ccp.nmr.Nmr.DataSource', func)

    def doEditMarkExtraRules(self, obj, row, col):

        className = obj.className
        if className == 'PeakList':
            if col == 5:
                return False

        elif className == 'DistanceConstraintList':
            if col in (4, 6):
                return False

        else:
            if col in (4, 5, 6):
                return False

        return True

    def toggleUse(self, obj):

        bool = not obj.setupStructureCalcFrameDict['use']
        obj.setupStructureCalcFrameDict['use'] = bool

        self.updateAfter()

    def toggleFilterViol(self, obj):

        bool = not obj.setupStructureCalcFrameDict['filter']
        obj.setupStructureCalcFrameDict['filter'] = bool

        self.updateAfter()

    def toggleKeepAssign(self, obj):

        bool = not obj.setupStructureCalcFrameDict['preserve']
        obj.setupStructureCalcFrameDict['preserve'] = bool

        self.updateAfter()

    def toggleAmbig(self, obj):

        bool = not obj.setupStructureCalcFrameDict['ambig']
        obj.setupStructureCalcFrameDict['ambig'] = bool

        self.updateAfter()

    def selectCell(self, obj, row, col):

        self.tableObj = obj

    def getShiftList(self, peakList):

        names = []
        index = -1
        shiftLists = getShiftLists(self.project.currentNmrProject)

        if shiftLists:
            shiftList = peakList.dataSource.experiment.shiftList

            if shiftList not in shiftLists:
                shiftList = shiftLists[0]

            names = [sl.name or str(sl.serial) for sl in shiftLists]
            index = shiftLists.index(shiftList)

        print "getShiftList", names, index

        self.shiftListPulldown.setup(names, index)

    def setShiftList(self, index, name=None):

        print "setShiftList", index, name

        if not name:
            index = self.shiftListPulldown.getSelectedIndex()

        shiftList = getShiftLists(self.project.currentNmrProject)[index]

        self.tableObj.setupStructureCalcFrameDict['shiftList'] = shiftList

        self.updateAfter()

    def updateMolSystems(self, *opt):

        names = []
        index = -1

        molSystems = self.getMolSystems()
        if molSystems:
            names = [ms.code for ms in molSystems]

            if self.molSystem not in molSystems:
                self.molSystem = molSystems[0]

            index = molSystems.index(self.molSystem)

        self.molSysPulldown.setup(names, index)

    def getMolSystems(self):

        molSystems = []

        if self.project:
            for molSystem in self.project.molSystems:
                if molSystem.chains:
                    molSystems.append(molSystem)

        return molSystems

    def getTableObjects(self):

        objs = []

        if self.project:
            objs = getThroughSpacePeakLists(self.project)

            if self.constraintSet:
                objs.extend(list(self.constraintSet.constraintLists))

        return objs

    def updateConstraintSets(self, obj=None):

        names = []
        index = -1

        if self.project and self.project.currentNmrProject:
            constraintSets = self.project.currentNmrProject.sortedNmrConstraintStores(
            )

            if constraintSets:
                if self.constraintSet not in constraintSets:
                    self.constraintSet = constraintSets[0]

                names = [str(cs.serial) for cs in constraintSets]
                index = constraintSets.index(self.constraintSet)

        names.append('<None>')

        self.constraintSetPulldown.setup(names, index)

    def changeMolSystem(self, i, name):

        self.molSystem = self.project.findFirstMolSystem(code=name)
        self.updateAfter()

    def changeConstraintSet(self, i, name):

        if name == '<None>':
            self.constraintSet = None
        else:
            self.constraintSet = self.project.currentNmrProject.sortedNmrConstraintStores(
            )[i]

        self.updateAfter()

    def update(self):

        textMatrix = []
        objectList = []
        #headingList = ['Input Class','Use?','Filter\nViolated',
        #               'Keep\nAssignments?','Ambigous\nProtocol','Shift List']

        for obj in self.getTableObjects():

            if not hasattr(obj, 'setupStructureCalcFrameDict'):
                obj.setupStructureCalcFrameDict = dict = {}
                dict['use'] = True
                dict['filter'] = True
                dict['preserve'] = False
                dict['ambig'] = False
                dict['shiftList'] = None
                new = True
            else:
                dict = obj.setupStructureCalcFrameDict
                new = False

            className = obj.className

            if className == 'PeakList':
                spectrum = obj.dataSource
                experiment = spectrum.experiment
                shiftList = dict['shiftList'] or experiment.shiftList

                if shiftList:
                    shiftListName = shiftList.name
                else:
                    shiftListName = '<None>'

                if new and (self.molSystem not in experiment.molSystems):
                    dict['use'] = False

                ident = '%s:%s:%d' % (experiment.name, spectrum.name,
                                      obj.serial)
                used = dict['use'] and 'Yes' or 'No'
                filtered = dict['filter'] and 'Yes' or 'No'
                preserved = dict['preserve'] and 'Yes' or 'No'
                ambig = None

            elif className == 'DistanceConstraintList':
                shiftListName = None

                if new:
                    dict['filter'] = True
                    dict['ambig'] = False

                ident = '%s:%d' % (obj.name or '', obj.serial)
                used = dict['use'] and 'Yes' or 'No'
                filtered = dict['filter'] and 'Yes' or 'No'
                preserved = None
                ambig = dict['ambig'] and 'Yes' or 'No'

            else:
                shiftListName = None

                if new:
                    dict['filter'] = False
                    dict['ambig'] = False

                ident = '%s:%d' % (obj.name or '', obj.serial)
                used = dict['use'] and 'Yes' or 'No'
                filtered = None
                preserved = None
                ambig = None

            datum = [
                className, ident, used, filtered, preserved, ambig,
                shiftListName
            ]

            textMatrix.append(datum)
            objectList.append(obj)

        self.waiting = False
        self.scrolledMatrix.update(textMatrix=textMatrix,
                                   objectList=objectList)

    def getAriaData(self):

        if not self.project:
            showWarning('Failure', 'No active project', parent=self)
            return

        if not self.molSystem:
            showWarning('Failure', 'No molecular system selected', parent=self)
            return

        if len(self.molSystem.chains) > 1:
            code = self.molSystem.findFirstChain().code
            code = askString('Multiple chains',
                             'Enter chain code:',
                             code,
                             parent=self)
            chain = self.molSystem.findFirstChain(code=code)

        else:
            chain = self.molSystem.findFirstChain()

        peakData = []
        dihedrals = []
        ambigs = []
        unambigs = []
        jCouplings = []

        for obj in self.scrolledMatrix.objectList:
            opts = obj.setupStructureCalcFrameDict

            if not opts['use']:
                continue

            className = obj.className
            key = getObjectKeyString(obj)

            if className == 'PeakList':
                shiftList = opts['shiftList']

                if not shiftList:
                    continue

                datum = {
                    'shifts': {
                        KEY_ID: getObjectKeyString(shiftList)
                    },
                    'peaks': {
                        KEY_ID: key
                    },
                    'use_assignments': opts['preserve'],
                    'trust_assigned_peaks': opts['filter']
                }

                peakData.append(datum)

            elif className == 'DistanceConstraintList':
                if opts['ambig']:
                    ambigs.append({
                        KEY_ID: key,
                        'filter_contributions': opts['filter']
                    })

                else:
                    unambigs.append({
                        KEY_ID: key,
                        'filter_contributions': opts['filter']
                    })

            elif className == 'JCouplingConstraintList':
                jCouplings.append({KEY_ID: key})

            elif className == 'DihedralConstraintList':
                dihedrals.append({KEY_ID: key})

        projFileName = os.path.join(self.project.url.path, self.project.path)
        dict = {
            KEY_GENERAL: {
                'project_name': self.project.name
            },
            KEY_CCPN: {
                'filename': projFileName
            },
            KEY_MOLECULAR_SYSTEM: {
                KEY_ID: getObjectKeyString(chain)
            },
            KEY_NOES: peakData,
            KEY_DIHEDRALS: dihedrals,
            KEY_DISTANCES_AMBIG: ambigs,
            KEY_DISTANCES_UNAMBIG: unambigs,
            KEY_JCOUPLINGS: jCouplings
        }

        return dict

    def updateAll(self):

        self.project = self.application.project

        self.updateMolSystems()
        self.updateConstraintSets()
        self.updateAfter()

    def updateAfter(self, obj=None):

        if self.waiting:
            return
        else:
            self.waiting = True
            self.after_idle(self.update)

    def destroy(self):

        notify = self.application.unregisterNotify
        for func in ('__init__', 'delete'):
            notify(self.updateAfter, 'ccp.nmr.Nmr.PeakList', func)
            notify(self.updateConstraintSets,
                   'ccp.nmr.NmrConstraint.NmrConstraintStore', func)
            notify(self.updateMolSystems, 'ccp.molecule.MolSystem.MolSystem',
                   func)
            notify(self.updateMolSystems, 'ccp.molecule.MolSystem.Chain', func)

        for func in ('__init__', 'delete', 'setName'):
            notify(self.updateAfter, 'ccp.nmr.Nmr.Experiment', func)
            notify(self.updateAfter, 'ccp.nmr.Nmr.DataSource', func)

        Frame.destroy(self)
class EditSymmetryPopup(BasePopup):
    def __init__(self, parent, project):

        self.parent = parent
        self.project = project
        self.singleMolecule = True
        self.molSystem = None
        self.molecules = []
        self.symmetrySet = None
        self.symmetryOp = None
        self.waiting = False

        BasePopup.__init__(self, parent=parent, title='Symmetry Operations')

    def body(self, guiFrame):

        guiFrame.grid_columnconfigure(0, weight=1)
        guiFrame.grid_rowconfigure(1, weight=1)

        frame = LabelFrame(guiFrame, text='Options')
        frame.grid(row=0, column=0, sticky='ew')
        frame.grid_columnconfigure(5, weight=1)

        label = Label(frame, text='MolSystem:')
        label.grid(row=0, column=0, sticky='w')
        self.molSystemPulldown = PulldownMenu(frame,
                                              callback=self.selectMolSystem)
        self.molSystemPulldown.grid(row=0, column=1, sticky='w')

        self.molLabel = Label(frame, text='Molecule:')
        self.molLabel.grid(row=0, column=2, sticky='w')
        self.moleculePulldown = PulldownMenu(frame,
                                             callback=self.selectMolecule)
        self.moleculePulldown.grid(row=0, column=3, sticky='w')

        label = Label(frame, text='Same Molecule Symmetry:')
        label.grid(row=0, column=4, sticky='w')
        self.molSelect = CheckButton(frame, callback=self.toggleSingleMolecule)
        self.molSelect.grid(row=0, column=5, sticky='w')
        self.molSelect.set(self.singleMolecule)

        frame = LabelFrame(guiFrame, text='Symmetry Operations')
        frame.grid(row=1, column=0, sticky='nsew')
        frame.grid_columnconfigure(0, weight=1)
        frame.grid_rowconfigure(0, weight=1)

        self.symmCodePulldown = PulldownMenu(self,
                                             callback=self.setSymmCode,
                                             do_initial_callback=False)
        self.segLengthEntry = IntEntry(self,
                                       returnCallback=self.setSegLength,
                                       width=6)
        self.setChainMulti = MultiWidget(self,
                                         CheckButton,
                                         callback=self.setChains,
                                         minRows=0,
                                         useImages=False)
        self.setSegmentMulti = MultiWidget(self,
                                           IntEntry,
                                           callback=self.setSegments,
                                           minRows=0,
                                           useImages=False)

        editWidgets = [
            None, self.symmCodePulldown, self.segLengthEntry,
            self.setChainMulti, self.setSegmentMulti
        ]
        editGetCallbacks = [
            None, self.getSymmCode, self.getSegLength, self.getChains,
            self.getSegments
        ]
        editSetCallbacks = [
            None, self.setSymmCode, self.setSegLength, self.setChains,
            self.setSegments
        ]

        headings = [
            '#', 'Symmetry\nType', 'Segment\nLength', 'Chains',
            'Segment\nPositions'
        ]
        self.symmetryMatrix = ScrolledMatrix(frame,
                                             headingList=headings,
                                             callback=self.selectSymmetry,
                                             editWidgets=editWidgets,
                                             editGetCallbacks=editGetCallbacks,
                                             editSetCallbacks=editSetCallbacks)
        self.symmetryMatrix.grid(row=0, column=0, sticky='nsew')

        texts = ['Add Symmetry Op', 'Remove Symmetrey Op']
        commands = [self.addSymmOp, self.removeSymmOp]
        buttonList = createDismissHelpButtonList(guiFrame,
                                                 texts=texts,
                                                 commands=commands,
                                                 expands=True)
        buttonList.grid(row=2, column=0, sticky='ew')

        self.updateMolSystems()
        self.updateMolecules()
        self.updateSymmetriesAfter()

        self.notify(self.registerNotify)

    def open(self):

        self.updateMolSystems()
        self.updateMolecules()
        self.updateSymmetriesAfter()

        BasePopup.open(self)

    def notify(self, notifyFunc):

        for func in ('__init__', 'delete', 'setSymmetryCode',
                     'setSegmentLength'):
            notifyFunc(self.updateSymmetriesAfter, 'molsim.Symmetry.Symmetry',
                       func)

        for func in ('__init__', 'delete', 'setfirstSeqId'):
            notifyFunc(self.updateSymmetriesAfter, 'molsim.Symmetry.Segment',
                       func)

    def getSymmCode(self, symmetryOp):
        """Get allowed symmetry operators from the model"""

        symmetryOpCodes = symmetryOp.parent.metaclass.container.getElement(
            'SymmetryOpCode').enumeration
        index = 0

        if symmetryOp.symmetryCode in symmetryOpCodes:
            index = symmetryOpCodes.index(symmetryOp.symmetryCode)

        self.symmCodePulldown.setup(symmetryOpCodes, index)

    def getSegLength(self, symmetryOp):

        if symmetryOp and symmetryOp.segmentLength:
            self.segLengthEntry.set(symmetryOp.segmentLength)

    def getChains(self, symmetryOp):

        chains = []
        for chain in self.molSystem.chains:
            if chain.residues:
                if chain.molecule in self.molecules: chains.append(chain.code)
        chains.sort()

        values = []
        for chain in chains:
            if symmetryOp.findFirstSegment(chainCode=chain):
                values.append(True)
            else:
                values.append(False)

        self.setChainMulti.set(values=values, options=chains)

    def getSegments(self, symmetryOp):

        values = []
        names = []

        if symmetryOp:
            for segment in symmetryOp.sortedSegments():
                names.append(segment.chainCode)
                values.append(segment.firstSeqId)

        n = len(values)
        self.setSegmentMulti.maxRows = n
        self.setSegmentMulti.minRows = n
        self.setSegmentMulti.set(values=values, options=names)

    def setSymmCode(self, index, name=None):
        """Set the symmetry code as NCS,C2,C3,C4,C5,C6"""

        if self.symmetryOp:
            symmCode = self.symmCodePulldown.getSelected()
            self.symmetryOp.symmetryCode = symmCode

    def setSegLength(self, event):

        value = self.segLengthEntry.get() or 1
        self.symmetryOp.segmentLength = value

    def setChains(self, obj):

        if self.symmetryOp and obj:
            codes = self.setChainMulti.options
            segment = self.symmetryOp.findFirstSegment()
            values = self.setChainMulti.get()

            if segment: seqId0 = segment.firstSeqId
            else: seqId0 = 1

            for i in range(len(values)):
                segment = self.symmetryOp.findFirstSegment(chainCode=codes[i])

                if segment and not values[i]: segment.delete()
                elif values[i] and not segment:
                    chain = self.molSystem.findFirstChain(code=codes[i])
                    residue = chain.findFirstResidue(seqid=seqId0)

                    if residue: seqId = seqId0
                    else:
                        residue = chain.sortedResidues()[0]
                        seqId = residue.seqId

                    residue2 = chain.findFirstResidue(
                        seqid=seqId + self.symmetryOp.segmentLength)
                    if not residue2:
                        residue2 = chain.sortedResidues()[-1]
                        self.symmetryOp.segmentLength = (residue2.seqId -
                                                         seqId) + 1

                    segment = self.symmetryOp.newSegment(chainCode=codes[i],
                                                         firstSeqId=seqId)

        self.symmetryMatrix.keyPressEscape()

    def setSegments(self, obj):

        if self.symmetryOp and obj:
            segments = self.symmetryOp.sortedSegments()
            values = self.setSegmentMulti.get()

            for i in range(len(values)):
                seqCode = values[i]
                chain = self.molSystem.findFirstChain(
                    code=segments[i].chainCode)
                residue = chain.findFirstResidue(seqCode=seqCode)

                if residue: seqId = residue.seqId
                if segments[i].firstSeqId != seqId:
                    segments[i].delete()
                    segments[i] = self.symmetryOp.newSegment(
                        chainCode=chain.code, firstSeqId=seqId)

        self.symmetryMatrix.keyPressEscape()

    def selectSymmetry(self, obj, row, col):

        self.symmetryOp = obj

    def addSymmOp(self):

        if self.molSystem:
            if not self.symmetrySet:
                self.symmetrySet = self.molSystem.findFirstMolSystemSymmetrySet(
                )

            if not self.symmetrySet:
                objGen = self.project.newMolSystemSymmetrySet
                self.symmetrySet = objGen(symmetrySetId=1,
                                          molSystem=self.molSystem)

            segLen = len(self.molSystem.findFirstChain().residues)
            symmetry = self.symmetrySet.newSymmetry(segmentLength=segLen)

    def removeSymmOp(self):

        if self.symmetryOp: self.symmetryOp.delete()

    def toggleSingleMolecule(self, boolean):

        self.singleMolecule = not boolean
        self.updateMolSystems()
        self.updateMolecules()

    def setMolecules(self, molecules):

        self.molecules = molecules
        if self.symmetrySet:
            for symmetryOp in self.symmetrySet.symmetries:
                for segment in symmetryOp.segments:
                    chain = self.molSystem.findFirstChain(
                        code=segment.chainCode)
                if chain and (chain.molecule not in molecules):
                    segment.delete()

    def selectMolecule(self, index, name):

        self.setMolecules(self.getMolecules()[index])
        self.updateSymmetries()

    def getMolecules(self):

        counts = {}
        moleculesList = []

        for chain in self.molSystem.chains:
            molecule = chain.molecule
            counts[molecule] = counts.get(molecule, 0) + 1

        molecules = counts.keys()
        if self.singleMolecule:
            for molecule in counts:
                if counts[molecule] > 1: moleculesList.append([
                        molecule,
                ])

        elif molecules:
            molecules = counts.keys()
            n = len(molecules)
            moleculesList.append([
                molecules[0],
            ])

            if n > 1:
                moleculesList.append([
                    molecules[1],
                ])
                moleculesList.append([molecules[0], molecules[1]])

            if n > 2:
                moleculesList.append([
                    molecules[2],
                ])
                moleculesList.append([molecules[1], molecules[2]])
                moleculesList.append(
                    [molecules[0], molecules[1], molecules[2]])

            if n > 3:
                moleculesList.append([
                    molecules[3],
                ])
                moleculesList.append([molecules[0], molecules[3]])
                moleculesList.append([molecules[1], molecules[3]])
                moleculesList.append([molecules[2], molecules[3]])
                moleculesList.append(
                    [molecules[0], molecules[1], molecules[3]])
                moleculesList.append(
                    [molecules[0], molecules[2], molecules[3]])
                moleculesList.append(
                    [molecules[1], molecules[2], molecules[3]])
                moleculesList.append(
                    [molecules[0], molecules[1], molecules[2], molecules[3]])

        return moleculesList

    def updateMolecules(self):

        names = []
        index = -1
        moleculesList = self.getMolecules()
        if moleculesList:
            if self.molecules not in moleculesList:
                self.setMolecules(moleculesList[0])
                self.symmetrySet = self.molSystem.findFirstMolSystemSymmetrySet(
                )

            index = moleculesList.index(self.molecules)

            names = []
            for molecules in moleculesList:
                names.append(','.join([mol.name for mol in molecules]))

        else:
            self.molecules = []

        self.moleculePulldown.setup(names, index)

    def selectMolSystem(self, index, name):

        self.molSystem = self.getMolSystems()[index]
        self.symmetrySet = self.molSystem.findFirstMolSystemSymmetrySet()
        self.updateSymmetries()

    def getMolSystems(self):

        molSystems = []
        for molSystem in self.project.sortedMolSystems():
            n = len(molSystem.chains)

            if self.singleMolecule and (n > 1): molSystems.append(molSystem)
            elif n > 0: molSystems.append(molSystem)

        return molSystems

    def updateMolSystems(self):

        names = []
        index = -1
        molSystems = self.getMolSystems()

        if molSystems:
            if self.molSystem not in molSystems: self.molSystem = molSystems[0]

            index = molSystems.index(self.molSystem)
            names = [ms.code for ms in molSystems]
        else:
            self.molSystem = None

        self.molSystemPulldown.setup(names, index)

    def updateSymmetriesAfter(self, obj=None):

        if self.waiting: return
        else:
            self.waiting = True
            self.after_idle(self.updateSymmetries)

    def updateSymmetries(self):

        textMatrix = []
        objectList = []
        if self.symmetrySet:
            for symmetryOp in self.symmetrySet.symmetries:
                chains = []
                segments = []
                length = symmetryOp.segmentLength

                for segment in symmetryOp.sortedSegments():
                    code = segment.chainCode
                    chain = self.molSystem.findFirstChain(code=code)

                    if chain:
                        chains.append(code)
                        seqId = segment.firstSeqId
                        residue1 = chain.findFirstResidue(seqId=seqId)
                        residue2 = chain.findFirstResidue(seqId=seqId +
                                                          length - 1)
                        segments.append(
                            '%s:%d-%d' %
                            (code, residue1.seqCode, residue2.seqCode))

                datum = [
                    symmetryOp.serial, symmetryOp.symmetryCode, length,
                    '\n'.join(chains), '\n'.join(segments)
                ]
                objectList.append(symmetryOp)
                textMatrix.append(datum)

        self.symmetryMatrix.update(objectList=objectList,
                                   textMatrix=textMatrix)
        self.waiting = False

    def destroy(self):

        self.notify(self.unregisterNotify)
        BasePopup.destroy(self)
Exemple #8
0
class ProchiralStatusPopup(TemporaryBasePopup):

    help_url = joinPath(getHelpUrlDir(), 'ProchiralStatus.html')

    def __init__(self, parent, chainList, chainAtomSetsDict):

        self.chainList = chainList
        self.chainAtomSetsDict = chainAtomSetsDict

        self.resParentDict = {}
        self.resParentList = []

        self.resParentChainLabelDict = {}
        self.resParentChainLabelList = {}

        self.chainResonancesDict = {}

        for resParent in self.chainAtomSetsDict.keys():
            if isinstance(resParent, NmrConstraint.NmrConstraintStore):
                strucGens = resParent.structureGenerations
                strucGenSerials = [str(sg.serial) for sg in strucGens]
                strucGenLabel = string.join(strucGenSerials, ',')
                resParentLabel = "Constraint set %d (strucGens %s)" % (
                    resParent.serial, strucGenSerials)
            else:
                resParentLabel = "Nmr project %s" % resParent.name

            self.resParentDict[resParentLabel] = resParent
            self.resParentList.append(resParentLabel)

            self.chainResonancesDict[resParent] = {}

            self.resParentChainLabelDict[resParent] = {}
            self.resParentChainLabelList[resParent] = []

            for chain in self.chainList:
                self.project = chain.root
                if self.chainAtomSetsDict[resParent].has_key(
                        chain) and self.chainAtomSetsDict[resParent][chain]:
                    chainLabel = "Molecular system '%s':Chain '%s' (molecule '%s')" % (
                        chain.molSystem.code, chain.code, chain.molecule.name)
                    self.resParentChainLabelList[resParent].append(chainLabel)
                    self.resParentChainLabelDict[resParent][chainLabel] = chain

                    self.chainResonancesDict[resParent][chain] = []

        # modal = true means that it won't continue unless this one returns value
        TemporaryBasePopup.__init__(
            self,
            parent=parent,
            title="Project '%s': " % self.project.name +
            'Set status prochiral atoms/resonances',
            modal=False,
            transient=True)

    def body(self, master):

        #
        # Setup header
        #

        row = 0

        label = Label(master, text='Select the resonance list:')
        label.grid(row=row, column=0, sticky=Tkinter.EW)

        label = Label(master, text='Select the chain:')
        label.grid(row=row, column=1, sticky=Tkinter.EW)

        row += 1

        self.resParentSelect = PulldownMenu(master,
                                            entries=self.resParentList,
                                            callback=self.setupResParentList,
                                            do_initial_callback=False)
        self.resParentSelect.grid(row=row, column=0, sticky=Tkinter.EW)

        self.chainSelect = PulldownMenu(master,
                                        entries=[],
                                        callback=self.setupProchiralList,
                                        do_initial_callback=False)
        self.chainSelect.grid(row=row, column=1, sticky=Tkinter.EW)

        row += 1

        separator = Separator(master, height=3)
        separator.setColor('black', bgColor='black')
        separator.grid(row=row, columnspan=2, sticky=Tkinter.EW)

        row += 1

        # THIS BIT TELLS MASTER TO CONFIGURE WINDOW ON INSIDE WIDGET!!
        master.grid_rowconfigure(row, weight=1)
        for i in range(2):
            master.grid_columnconfigure(i, weight=1)

        self.prochiralListFrame = ScrolledFrame(master,
                                                width=200,
                                                doExtraConfig=False)
        self.prochiralListFrame.grid(row=row,
                                     column=0,
                                     columnspan=2,
                                     sticky=Tkinter.NSEW)
        self.prochiralListFrameRow = row
        self.prochiralListFrameMaster = master

        row = row + 1

        texts = ['Set all', 'Set chain']
        commands = [
            self.ok, self.setStereo
        ]  # This calls 'ok' in BasePopup, this then calls 'apply' in here
        buttons = createDismissHelpButtonList(master,
                                              texts=texts,
                                              commands=commands,
                                              dismiss_text='Exit',
                                              help_url=self.help_url)
        buttons.grid(row=row, column=0, columnspan=2, sticky=Tkinter.EW)

        self.resParentSelect.callback(0, self.resParentList[0])

    def setupResParentList(self, listIndex, resParentLabel):

        resParent = self.resParentDict[resParentLabel]
        self.resParent = resParent

        self.chainSelect.setup(self.resParentChainLabelList[self.resParent], 0)
        self.chainSelect.callback(
            0, self.resParentChainLabelList[self.resParent][0])

    def setupProchiralList(self, listIndex, chainLabel):

        chain = self.resParentChainLabelDict[self.resParent][chainLabel]
        self.chain = chain

        self.prochiralListFrame.destroy()
        self.prochiralListFrame = ScrolledFrame(self.prochiralListFrameMaster,
                                                width=200,
                                                doExtraConfig=False)
        self.prochiralListFrame.grid(row=self.prochiralListFrameRow,
                                     column=0,
                                     columnspan=2,
                                     sticky=Tkinter.NSEW)

        #
        # TODO: also handle case one resonance, two atomSets!?!?
        #

        frameRow = 0
        x = y = 0

        frame = self.prochiralListFrame.frame

        self.resonanceObjects = {}
        self.resonanceLabelDict = {}

        #
        # Reuse previous settings...
        #

        if len(self.chainResonancesDict[self.resParent][chain]) == len(
                self.chainAtomSetsDict[self.resParent][chain]):
            usePreviousSettings = True
        else:
            usePreviousSettings = False

        for i in range(0, len(self.chainAtomSetsDict[self.resParent][chain])):
            atomSetGroup = self.chainAtomSetsDict[self.resParent][chain][i]

            isStereo = False
            hasResonances = False
            isValidCase = False

            resonances = []

            if usePreviousSettings and self.chainResonancesDict[
                    self.resParent][chain][i]:

                resonances = self.chainResonancesDict[
                    self.resParent][chain][i][3]
                isStereo = self.chainResonancesDict[
                    self.resParent][chain][i][0]
                hasResonances = True
                isValidCase = True

            else:

                for atomSet in atomSetGroup:
                    resonanceSets = atomSet.sortedResonanceSets()

                    if resonanceSets:
                        hasResonances = True

                        for resonanceSet in resonanceSets:
                            for resonance in resonanceSet.sortedResonances():
                                if resonance not in resonances:
                                    resonances.append(resonance)

                        if len(resonanceSets) == 1:
                            isValidCase = True
                            if len(resonanceSet.atomSets) == 1:
                                isStereo = True

                    else:
                        # Case only one resonance but stereo assigned
                        resonances.append(0)

                if len(resonances) == 1:
                    # Case only one resonance, not stereo assigned
                    resonances.append(None)

            #
            # Set up only for valid cases
            #

            if hasResonances and isValidCase:

                if not usePreviousSettings:
                    self.chainResonancesDict[self.resParent][chain].append(
                        [isStereo, False, False, resonances])

                residue = atomSetGroup[0].findFirstAtom().residue
                ccpCode = residue.molResidue.ccpCode
                seqCode = residue.seqCode

                rowspan = 2

                checkButton = CheckButton(
                    frame,
                    selected=isStereo,
                    callback=lambda status=isStereo, fr=frameRow, item=i, setup
                    =False: self.toggleResonances(status, fr, item, setup))
                checkButton.grid(row=frameRow,
                                 rowspan=rowspan,
                                 column=0,
                                 sticky=Tkinter.EW)

                label = Label(frame, text=ccpCode, width=5)
                label.grid(row=frameRow,
                           rowspan=rowspan,
                           column=1,
                           sticky=Tkinter.E)
                label = Label(frame, text=str(seqCode), width=5)
                label.grid(row=frameRow,
                           rowspan=rowspan,
                           column=2,
                           sticky=Tkinter.W)

                #
                # Set up the atom names
                #

                for j in range(0, len(atomSetGroup)):
                    atomSet = atomSetGroup[j]
                    label = Label(frame, text=atomSet.name)
                    label.grid(row=frameRow + j,
                               column=3,
                               sticky=Tkinter.E,
                               ipadx=4)

                #
                # Set up the resonances
                #

                self.resonanceObjects[frameRow] = {
                    True: [[], []],
                    False: [[], []]
                }

                resonanceLabelList = []

                for resonance in resonances:

                    if not resonance:

                        resonanceLabel = 'unknown'

                    else:

                        if hasattr(resonance, 'shifts') and resonance.shifts:
                            shiftLabel = " (shifts: "

                            for shift in resonance.sortedShifts():
                                shiftLabel += "%.2f, " % shift.value

                            shiftLabel = shiftLabel[:-2] + ")"

                        else:
                            shiftLabel = ""

                        resonanceLabel = "'%d.%s'%s" % (
                            seqCode, resonance.name, shiftLabel)
                        self.resonanceLabelDict[resonanceLabel] = resonance

                    resonanceLabelList.append(resonanceLabel)

                separator = Separator(frame, height=1, width=30)
                separator.setColor('black', bgColor='black')
                separator.grid(row=frameRow, column=4, sticky=Tkinter.EW)
                self.resonanceObjects[frameRow][True][0].append(separator)

                separator = CrossLine(frame,
                                      height=20,
                                      width=30,
                                      canvas_bg=frame['bg'],
                                      color='dimgray')
                self.resonanceObjects[frameRow][False][0].append(separator)

                resonanceList = PulldownMenu(
                    frame,
                    entries=resonanceLabelList,
                    callback=lambda selInd=x, selItem=y, fr=frameRow, item=i:
                    self.setProchiralLabels(selInd, selItem, fr, item),
                    do_initial_callback=False,
                    label_color='red')
                resonanceList.grid(row=frameRow, column=5, sticky=Tkinter.EW)
                self.resonanceObjects[frameRow][True][0].append(resonanceList)

                resonanceLabel = Label(frame,
                                       text="%s" % resonanceLabelList[0],
                                       fg='dimgray')
                self.resonanceObjects[frameRow][False][0].append(
                    resonanceLabel)

                separator = Separator(frame, height=1, width=30)
                separator.setColor('black', bgColor='black')
                separator.grid(row=frameRow + 1, column=4)
                self.resonanceObjects[frameRow][True][1].append(separator)

                self.resonanceObjects[frameRow][False][1].append(None)

                resonanceLabel = Label(frame,
                                       text="%s" % resonanceLabelList[1],
                                       fg='red')
                resonanceLabel.grid(row=frameRow + 1,
                                    column=5,
                                    sticky=Tkinter.EW)
                self.resonanceObjects[frameRow][True][1].append(resonanceLabel)

                resonanceLabel = Label(frame,
                                       text="%s" % resonanceLabelList[1],
                                       fg='dimgray')
                self.resonanceObjects[frameRow][False][1].append(
                    resonanceLabel)

                if not isStereo:
                    checkButton.callback(isStereo, setup=True)

                separator = Separator(frame, height=1)
                separator.setColor('black', bgColor='black')
                separator.grid(row=frameRow + rowspan,
                               columnspan=6,
                               sticky=Tkinter.EW)

                frameRow += rowspan + 1

            elif not usePreviousSettings:
                self.chainResonancesDict[self.resParent][chain].append(None)

        return True

    def setProchiralLabels(self, selInd, selItem, fr, item):

        resonanceLabel = self.resonanceObjects[fr][True][0][1].entries[selInd]
        self.resonanceObjects[fr][False][0][1].set(resonanceLabel)

        selInd = not selInd
        resonanceLabel = self.resonanceObjects[fr][True][0][1].entries[selInd]
        self.resonanceObjects[fr][True][1][1].set(resonanceLabel)
        self.resonanceObjects[fr][False][1][1].set(resonanceLabel)

        self.chainResonancesDict[self.resParent][
            self.chain][item][2] = not self.chainResonancesDict[
                self.resParent][self.chain][item][2]
        self.chainResonancesDict[self.resParent][self.chain][item][3].reverse()

    def toggleResonances(self, status, frameRow, item, setup):

        if not setup:
            self.chainResonancesDict[self.resParent][
                self.chain][item][0] = status
            self.chainResonancesDict[self.resParent][
                self.chain][item][1] = not self.chainResonancesDict[
                    self.resParent][self.chain][item][1]

        for i in range(0, len(self.resonanceObjects[frameRow])):

            #
            # Remove other widgets from grid
            #

            rpds = self.resonanceObjects[frameRow][not status][i]
            for rpd in rpds:
                if rpd:
                    rpd.grid_forget()

            #
            # Set current widgets
            #

            rpds = self.resonanceObjects[frameRow][status][i]

            for j in range(0, len(rpds)):
                rpd = rpds[j]

                if rpd:
                    keywds = {}

                    if j == 1:
                        keywds['sticky'] = Tkinter.W

                    if j == 0:
                        if not status:
                            keywds['rowspan'] = 2

                    rpd.grid(row=frameRow + i, column=4 + j, **keywds)

    def setStereo(self, chain=None):

        if not chain:
            chain = self.chain

        if self.chainResonancesDict[self.resParent][chain]:
            for i in range(
                    0, len(self.chainResonancesDict[self.resParent][chain])):

                atomSetGroup = self.chainAtomSetsDict[self.resParent][chain][i]
                (stereoStatus, stereoStatusChanged, resChanged, resonances
                 ) = self.chainResonancesDict[self.resParent][chain][i]

                if stereoStatusChanged or (stereoStatus and resChanged):

                    residue = atomSetGroup[0].findFirstAtom().residue
                    ccpCode = residue.molResidue.ccpCode
                    seqCode = residue.seqCode

                    atomText = "%s/%s" % (atomSetGroup[0].name,
                                          atomSetGroup[1].name)

                    if stereoStatusChanged:
                        if stereoStatus:
                            stereoText = "non-stereospecific to stereospecific."
                        else:
                            stereoText = "stereospecific to non-stereospecific."

                        print "  Warning: Changed '%s.%d' prochiral resonances for atoms %s from %s" % (
                            ccpCode, seqCode, atomText, stereoText)
                        self.chainResonancesDict[
                            self.resParent][chain][i][1] = False
                        self.chainResonancesDict[
                            self.resParent][chain][i][2] = False

                        if stereoStatus:
                            resonanceSet = atomSetGroup[
                                0].findFirstResonanceSet()

                            if resonances[0]:
                                resonanceSet.removeAtomSet(atomSetGroup[1])

                            if resonances[1]:

                                if not resonances[0]:
                                    # Remove right atom set if only one resonance...
                                    resonanceSet.removeAtomSet(atomSetGroup[0])
                                else:
                                    # Only create a new resonance set if two resonances present!
                                    resonanceSet.removeResonance(resonances[1])

                                    if isinstance(
                                            self.resParent,
                                            NmrConstraint.NmrConstraintStore):
                                        newResonanceSet = self.resParent.newFixedResonanceSet(
                                            resonances=[resonances[1]],
                                            atomSets=[atomSetGroup[1]])
                                    else:
                                        newResonanceSet = self.resParent.newResonanceSet(
                                            resonances=[resonances[1]],
                                            atomSets=[atomSetGroup[1]])

                        else:

                            if resonances[0]:
                                resonanceSet = atomSetGroup[
                                    0].findFirstResonanceSet()
                                if resonances[1]:
                                    atomSetGroup[1].findFirstResonanceSet(
                                    ).delete()
                                    resonanceSet.addResonance(resonances[1])
                                resonanceSet.addAtomSet(atomSetGroup[1])

                            elif resonances[1]:
                                resonanceSet = atomSetGroup[1].resonanceSets[0]
                                resonanceSet.addAtomSet(atomSetGroup[0])

                    elif stereoStatus and resChanged:
                        print "  Warning: Changed resonance assignment for '%s.%d' stereospecifically assigned atoms %s." % (
                            ccpCode, seqCode, atomText)
                        self.chainResonancesDict[
                            self.resParent][chain][i][2] = False

                        resonanceSets = []

                        for i in range(0, 2):
                            if atomSetGroup[i].resonanceSets:
                                resonanceSets.append(
                                    atomSetGroup[i].findFirstResonanceSet())
                            else:
                                resonanceSets.append(None)

                        for i in range(0, 2):
                            resonanceSet = resonanceSets[i]

                            if resonanceSet:
                                resonanceSet.addAtomSet(atomSetGroup[not i])
                                resonanceSet.removeAtomSet(atomSetGroup[i])

    def apply(self):

        for chain in self.chainList:
            self.setStereo(chain=chain)

        return True
Exemple #9
0
class EditResStructuresPopup(BasePopup):
    def __init__(self, parent, *args, **kw):

        self.guiParent = parent
        self.structure = None
        self.constraintSet = None
        self.cloud = None
        self.cloudRmsdDict = {}
        self.strucRmsdDict = {}
        self.waiting = False

        BasePopup.__init__(self,
                           parent=parent,
                           title="Resonance Cloud Structures",
                           **kw)

    def body(self, guiFrame):

        row = 0
        guiFrame.grid_columnconfigure(1, weight=1)
        guiFrame.grid_rowconfigure(0, weight=0)
        guiFrame.grid_rowconfigure(1, weight=1)

        self.generationLabel = Label(guiFrame, text='Structure Generation:')

        constraintSets = []
        constraintSetNames = []
        index = -1
        for constraintSet in self.project.nmrConstraintStores:
            index += 1
            constraintSets.append(constraintSet)
            constraintSetNames.append(str(constraintSet.serial))
            self.constraintSet = constraintSet

        self.constrSetPulldown = PulldownMenu(guiFrame,
                                              self.changeConstraintSet,
                                              constraintSetNames,
                                              selected_index=index,
                                              do_initial_callback=False)

        self.generationLabel.grid(row=row, column=0, columnspan=1, sticky='e')
        self.constrSetPulldown.grid(row=row,
                                    column=1,
                                    columnspan=1,
                                    sticky='w')

        strucLabel = Label(guiFrame, text='Comparison structure')
        strucLabel.grid(row=row, column=2, sticky='e')
        self.strucPulldown = PulldownMenu(guiFrame,
                                          entries=self.getStructures(),
                                          callback=self.setStructure,
                                          selected_index=0,
                                          do_initial_callback=False)
        self.strucPulldown.grid(row=row, column=3, sticky='w')

        sdTolLabel = Label(guiFrame, text='Tolerance (SDs):')
        sdTolLabel.grid(row=row, column=4, sticky='e')
        self.sdToleranceEntry = FloatEntry(guiFrame, text=2.0, width=6)
        self.sdToleranceEntry.grid(row=row, column=5, stick='w')

        row += 1
        colHeadings = ['#', 'File name', 'RMSD to mean', 'RMSD to structure']
        self.scrolledMatrix = ScrolledMatrix(guiFrame,
                                             initialRows=10,
                                             headingList=colHeadings,
                                             callback=self.selectCell,
                                             objectList=[],
                                             textMatrix=[
                                                 [],
                                             ])
        self.scrolledMatrix.grid(row=row,
                                 column=0,
                                 columnspan=6,
                                 sticky='nsew')

        row += 1
        texts = [
            'Calc\nRMSD', 'Make Cloud\nfrom structure', 'Delete', 'Delete\nbad'
        ]
        commands = [
            self.calcRmsd, self.makeStrucCloud, self.deleteCloud,
            self.filterClouds
        ]
        self.bottomButtons = UtilityButtonList(guiFrame,
                                               texts=texts,
                                               expands=False,
                                               commands=commands,
                                               helpUrl=self.help_url)
        self.bottomButtons.grid(row=row, column=0, columnspan=6, sticky='nsew')
        self.update()

        for func in ('__init__', 'delete'):
            self.registerNotify(self.updateStructureGen,
                                'ccp.nmr.Nmr.StructureGeneration', func)

    def open(self):

        self.updateAfter()
        BasePopup.open(self)

    def getStructures(self):

        names = [
            '<None>',
        ]
        for molSystem in self.project.sortedMolSystems():
            for structure in molSystem.sortedStructureEnsembles():
                names.append('%s:%d' % (molSystem.name, structure.ensembleId))

        return names

    def setStructure(self, index, name=None):

        if index < 1:
            self.structure = None
        else:
            structures = []
            for molSystem in self.project.sortedMolSystems():
                for structure in molSystem.sortedStructureEnsembles():
                    structures.append(structure)

            self.structure = structures[index - 1]

    def filterClouds(self):

        if self.constraintSet:
            sdTolerance = self.sdToleranceEntry.get() or 2.0
            keptClouds = []
            clouds = self.guiParent.application.getValues(
                self.constraintSet, 'clouds')

            meanGroupRmsds = []
            for cloud in clouds:
                rmsd = self.cloudRmsdDict.get(cloud)
                if rmsd is not None:
                    meanGroupRmsds.append(rmsd)

            meanRmsd = 0.0
            N = 0
            for rmsd in meanGroupRmsds:
                meanRmsd += rmsd
                N += 1

            if N > 0:
                meanRmsd /= float(N)

            sd = 0.0
            for rmsd in meanGroupRmsds:
                sd += (rmsd - meanRmsd) * (rmsd - meanRmsd)

            if N > 0:
                sd /= float(N - 1)

            sd = sqrt(sd)

            print meanRmsd, '+/-', sd

            n = 0
            for cloud in clouds:
                rmsd = self.cloudRmsdDict.get(cloud)
                if rmsd is None:
                    keptClouds.append(cloud)
                elif abs(rmsd - meanRmsd) > (sdTolerance * sd):
                    print 'Cloud %s is bad' % (cloud)
                else:
                    keptClouds.append(cloud)

            self.guiParent.application.setValues(self.constraintSet,
                                                 'clouds',
                                                 values=keptClouds)
            self.updateAfter()

    def makeStrucCloud(self):

        if self.structure:
            serials = self.guiParent.application.getValues(
                self.constraintSet, 'cloudsResonances')
            pdbFileName = 'CloudForStructure.pdb'
            #from ccpnmr.clouds.AtomCoordList import AtomCoordList
            from ccpnmr.c.AtomCoordList import AtomCoordList
            atomCoordList = AtomCoordList()
            resDict = {}
            hmass = 25

            print "L1", len(serials)

            for resonance in self.nmrProject.resonances:
                resDict[resonance.serial] = resonance

            print "L2", len(resDict)

            resonances = []
            for serial in serials:
                if resDict.get(serial) is not None:
                    resonances.append(resDict[serial])

            print "L3", len(resonances)

            C = 0
            for resonance in resonances:
                resonanceSet = resonance.resonanceSet
                if resonanceSet:
                    i = resonanceSet.sortedResonances().index(resonance)
                    atomSet = resonance.resonanceSet.sortedAtomSets()[i]
                    coords = getAtomSetCoords(atomSet, self.structure)
                    coord = coords[0]
                    atomCoordList.add(hmass, coord.x, coord.y, coord.z)

                    C += 1
            print "L4", len(atomCoordList)

            from ccpnmr.clouds.FilterClouds import writeTypedPdbCloud
            writeTypedPdbCloud(atomCoordList, pdbFileName, resonances)

            clouds = self.guiParent.application.getValues(
                self.constraintSet, 'clouds')
            clouds.append(pdbFileName)

            self.guiParent.application.setValues(self.constraintSet,
                                                 'clouds',
                                                 values=clouds)
            self.updateAfter()

    def calcRmsd(self):

        if self.constraintSet:
            clouds = self.guiParent.application.getValues(
                self.constraintSet, 'clouds')
            from ccpnmr.clouds.FilterClouds import filterClouds
            rmsds = filterClouds(clouds)
            n = len(clouds)

            for i in range(n):
                cloud = clouds[i]
                rmsd = rmsds[i]
                self.cloudRmsdDict[cloud] = rmsd

            self.updateAfter()

    def changeConstraintSet(self, i, name):

        project = self.project
        if project.nmrConstraintStores:
            constraintSet = project.nmrConstraintStores[i]
        else:
            constraintSet = None

        if constraintSet is not self.constraintSet:
            self.constraintSet = constraintSet
            self.cloud = None

        self.updateAfter()

    def deleteCloud(self):

        if self.constraintSet and self.cloud and showOkCancel(
                'Confirm', 'Really delete resonance cloud?', parent=self):
            clouds = self.guiParent.application.getValues(
                self.constraintSet, 'clouds')
            if clouds:
                clouds.remove(self.cloud)
                self.cloud = None
                self.guiParent.application.setValues(self.constraintSet,
                                                     'clouds',
                                                     values=clouds)
                self.updateAfter()

    def selectCell(self, cloud, row, col):

        self.cloud = cloud
        self.bottomButtons.buttons[1].enable()

    def updateAfter(self, *opt):

        if self.waiting:
            return
        else:
            self.waiting = True
            self.after_idle(self.update)

    def getConstraintSetNames(self):

        names = []
        constraintSets = self.project.nmrConstraintStores
        for set in constraintSets:
            names.append('%d' % set.serial)

        return names

    def updateStructureGen(self, *opt):

        project = self.project
        constraintSets = self.project.sortedNmrConstraintStores

        if constraintSets:
            constraintSetNames = self.getConstraintSetNames()

            # set defaults
            if self.constraintSet not in constraintSets:
                self.constraintSet = constraintSets[0]
                self.cloud = None

            i = constraintSets.index(self.constraintSet)
            self.constrSetPulldown.setup(constraintSetNames, i)

        else:
            self.constraintSet = None
            self.cloud = None
            self.constrSetPulldown.setup([], -1)

    def destroy(self):

        for func in ('__init__', 'delete'):
            self.unregisterNotify(self.updateStructureGen,
                                  'ccp.nmr.Nmr.StructureGeneration', func)

        BasePopup.destroy(self)

    def update(self):

        objectList = []
        textMatrix = []
        if self.constraintSet:
            clouds = self.guiParent.application.getValues(
                self.constraintSet, 'clouds')
            if clouds:
                objectList = list(clouds)

        i = 0
        for cloud in objectList:
            i += 1
            datum = []
            datum.append(i)
            datum.append(cloud)
            datum.append(self.cloudRmsdDict.get(cloud) or '-')
            datum.append(self.strucRmsdDict.get(cloud) or '-')
            textMatrix.append(datum)

        if not self.cloud:
            self.bottomButtons.buttons[1].disable()

        self.scrolledMatrix.update(objectList=objectList,
                                   textMatrix=textMatrix)
        self.waiting = False
Exemple #10
0
class PredictKarplusPopup(BasePopup):
    def __init__(self, parent, *args, **kw):

        self.waiting = False
        self.molSystem = None
        self.residue = None
        self.jCouplings = []
        self.atomNames = []
        self.measureJCouplingList = None
        self.predictJCouplingList = None

        self.coeffAtomNames = []
        self.coefficients = {}
        self.coefficient = None
        for i in range(3):
            self.coefficients[i] = {}

        BasePopup.__init__(
            self,
            parent=parent,
            title='Predict Karplus Coefficients from J Coupling',
            **kw)

        self.updateJCouplingLists()
        self.updateMolSystems()
        self.updateAfter()

    def body(self, guiFrame):

        guiFrame.grid_columnconfigure(0, weight=1, minsize=500)

        row = 0

        frame = LabelFrame(guiFrame, text='General Options')
        frame.grid(row=row, column=0, sticky='nsew')
        frame.grid_columnconfigure(1, weight=1)

        label = Label(frame, text='Molecular System:')
        label.grid(row=0, column=0, sticky='w')
        self.molSystemPulldown = PulldownMenu(frame,
                                              self.changeMolSystem,
                                              do_initial_callback=False)
        self.molSystemPulldown.grid(row=0, column=1, sticky='w')

        label = Label(frame, text='Measured J coupling list:')
        label.grid(row=0, column=2, sticky='w')
        self.measureCouplingListPulldown = PulldownMenu(
            frame, self.changeMeasureCouplingList)
        self.measureCouplingListPulldown.grid(row=0, column=3, sticky='w')

        label = Label(frame, text='Predicted J coupling list:')
        label.grid(row=0, column=4, sticky='w')
        self.predictCouplingListPulldown = PulldownMenu(
            frame, self.changePredictCouplingList)
        self.predictCouplingListPulldown.grid(row=0, column=5, sticky='w')

        row += 1
        guiFrame.grid_rowconfigure(row, weight=1)

        frame = LabelFrame(guiFrame, text='Angles & 3J Couplings')
        frame.grid(row=row, column=0, sticky='nsew')
        frame.grid_columnconfigure(0, weight=1)
        frame.grid_rowconfigure(0, weight=1)

        headingList = ['Residue', 'Phi', 'Chi^2']
        editWidgets = [None, None, None]
        editGetCallbacks = [None, None, None]
        editSetCallbacks = [None, None, None]

        self.jCouplingEntry = FloatEntry(
            self, width=8, returnCallback=lambda event: self.setJCoupling())
        i = 0
        for names in couplingAtoms:
            headingList.extend(
                ['Pred\nJ(%s,%s)' % names,
                 'Expt\nJ(%s,%s)' % names])
            editWidgets.extend([None, self.jCouplingEntry])
            editGetCallbacks.extend(
                [None, lambda obj, i=i: self.getJCoupling(obj, i)])
            editSetCallbacks.extend(
                [None, lambda event, i=i: self.setJCoupling(i)])
            i += 1

        self.couplingMatrix = ScrolledMatrix(frame,
                                             headingList=headingList,
                                             editWidgets=editWidgets,
                                             editGetCallbacks=editGetCallbacks,
                                             editSetCallbacks=editSetCallbacks,
                                             callback=self.selectJCoupling,
                                             multiSelect=False)
        self.couplingMatrix.grid(row=0, column=0, sticky='nsew')
        self.couplingMatrix.doEditMarkExtraRules = self.doEditMarkExtraRules

        row += 1

        frame = LabelFrame(guiFrame, text='Karplus Coefficients')
        frame.grid(row=row, column=0, sticky='nsew')
        frame.grid_columnconfigure(0, weight=1)
        frame.grid_rowconfigure(0, weight=1)

        headingList = ['Phase']
        editWidgets = [
            None,
        ]
        editGetCallbacks = [
            None,
        ]
        editSetCallbacks = [
            None,
        ]

        self.coefficientEntry = FloatEntry(
            self, width=8, returnCallback=lambda event: self.setCoefficient())
        for names in couplingAtoms:
            headingList.append('J(%s,%s)' % names)
            editWidgets.append(self.coefficientEntry)
            editGetCallbacks.append(
                lambda obj, n=names: self.getCoefficient(obj, n))
            editSetCallbacks.append(
                lambda event, n=names: self.setCoefficient(n))

        headingList = [
            'Phase', 'J(H,HA)', 'J(H,C)', 'J(H,CB)', 'J(C,HA)', 'J(C,C)',
            'J(C,CB)'
        ]
        self.coefficientMatrix = ScrolledMatrix(
            frame,
            headingList=headingList,
            editWidgets=editWidgets,
            editGetCallbacks=editGetCallbacks,
            editSetCallbacks=editSetCallbacks,
            callback=self.selectCoefficient,
            maxRows=3,
            multiSelect=False)
        self.coefficientMatrix.grid(row=0, column=0, sticky='nsew')

        row += 1
        texts = []
        commands = []
        self.bottomButtons = UtilityButtonList(guiFrame,
                                               commands=commands,
                                               texts=texts,
                                               helpUrl=self.help_url)
        self.bottomButtons.grid(row=row, column=0, sticky='ew')

        for func in ('__init__', 'delete', 'setValue', 'setError'):
            for clazz in ('ccp.nmr.Nmr.JCoupling', ):
                self.registerNotify(self.updateAfter, clazz, func)

        for func in ('__init__', 'delete'):
            for clazz in ('ccp.nmr.Nmr.JCouplingList', ):
                self.registerNotify(self.updateJCouplingLists, clazz, func)

    def getJCouplingLists(self, isSimulated=False):

        jCouplingLists = self.nmrProject.findAllMeasurementLists(
            className='JCouplingList', isSimulated=isSimulated)

        return jCouplingLists

    def updateJCouplingLists(self, *obj):

        jCouplingLists = self.getJCouplingLists(isSimulated=False)
        names = [
            '%d:%s' % (jcl.serial, jcl.name or '') for jcl in jCouplingLists
        ]
        names.append('<New>')
        index = -1

        if jCouplingLists:
            if self.measureJCouplingList in jCouplingLists:
                index = jCouplingLists.index(self.measureJCouplingList)

            else:
                self.measureJCouplingList = jCouplingLists[0]
                index = 0
        else:
            self.measureJCouplingList = None

        self.measureCouplingListPulldown.setup(names, index)

        jCouplingLists = self.getJCouplingLists(isSimulated=True)
        names = ['%d:%s' % (jcl.serial, jcl.name) for jcl in jCouplingLists]
        names.append('<New>')
        index = -1

        if jCouplingLists:
            if self.predictJCouplingList in jCouplingLists:
                index = jCouplingLists.index(self.predictJCouplingList)

            else:
                self.predictJCouplingList = jCouplingLists[0]
                index = 0
        else:
            self.predictJCouplingList = None

        self.predictCouplingListPulldown.setup(names, index)

    def changeMeasureCouplingList(self, index, name):

        if name == '<New>':
            self.measureJCouplingList = None

        else:
            jCouplingLists = self.getJCouplingLists()
            jCouplingList = jCouplingLists[index]

            if jCouplingList is not self.measureJCouplingList:
                self.measureJCouplingList = jCouplingList

                if self.predictJCouplingList is self.measureJCouplingList:
                    for jCouplingList2 in jCouplingLists:
                        if self.measureJCouplingList is not jCouplingList2:
                            self.predictJCouplingList = jCouplingList2
                            break

                    else:
                        self.predictJCouplingList = None

        self.updateAfter()

    def changePredictCouplingList(self, index, name):

        if name == '<New>':
            self.predictJCouplingList = None
            self.updateAfter()

        else:
            jCouplingLists = self.getJCouplingLists()
            jCouplingList = jCouplingLists[index]

            if jCouplingList is not self.predictJCouplingList:
                self.predictJCouplingList = jCouplingList

                if self.predictJCouplingList is self.measureJCouplingList:
                    for jCouplingList2 in jCouplingLists:
                        if self.predictJCouplingList is not jCouplingList2:
                            self.measureJCouplingList = jCouplingList2
                            break

                    else:
                        self.measureJCouplingList = None

        self.updateAfter()

    def doEditMarkExtraRules(self, obj, row, col):

        i = (col - 3) / 2

        if i > -1:
            atoms = couplingAtoms[i]
            residue = obj[0]

            for atomName in atoms:
                if not residue.findFirstAtom(name=atomName):
                    return False

        return True

    def open(self):

        self.updateMolSystems()

        BasePopup.open(self)

    def selectJCoupling(self, object, row, col):

        self.residue = object[0]
        self.jCouplings = object[1:]

    def selectCoefficient(self, object, row, col):

        self.coefficient = object

    def getCoefficient(self, object, atomNames):

        self.coeffAtomNames = atomNames

        coefficient = self.coefficients[object].get(atomNames)

        self.coefficientEntry.set(coefficient)

    def setCoefficient(self, atomNames=None):

        if not atomNames:
            atomNames = self.coeffAtomNames

        value = self.coefficientEntry.get()
        if atomNames and (self.coefficient is not None):
            self.coefficients[self.coefficient][atomNames] = value
            #print self.coefficient, atomNames,  value

        self.updateCoefficients()

    def getJCoupling(self, object, index):

        atomNames = couplingAtoms[index]
        self.atomNames = atomNames

        coupling = object[index + 1]

        if not coupling:
            residue = object[0]
            coupling = self.getResidueJCoupling(self.measureJCouplingList,
                                                residue, atomNames)

        if coupling:
            value = coupling.value
        else:
            value = None

        self.jCouplingEntry.set(value)

    def setJCoupling(self, index=None):

        if not index:
            atomNames = self.atomNames
            index = couplingAtoms.index(atomNames)
        else:
            atomNames = couplingAtoms[index]

        value = self.jCouplingEntry.get()
        if self.residue and atomNames:
            coupling = self.jCouplings[index]

            if value is None:
                if coupling:
                    if showOkCancel('Confirm',
                                    'Really remove J coupling?',
                                    parent=self):

                        coupling.delete()

            else:
                if not coupling:
                    self.setResidueJCoupling(self.measureJCouplingList,
                                             self.residue,
                                             atomNames,
                                             value,
                                             isSimulated=False)

                else:
                    coupling.setValue(value)

    def getResidueJCoupling(self, jCouplingList, residue, atomNames):

        if jCouplingList:
            return getResidueJCoupling(jCouplingList, residue, atomNames)

    def setResidueJCoupling(self,
                            jCouplingList,
                            residue,
                            atomNames,
                            value,
                            isSimulated=False):

        if jCouplingList is None:
            jCouplingList = self.nmrProject.newJCouplingList(
                isSimulated=isSimulated)

            if isSimulated:
                self.predictJCouplingList = jCouplingList
            else:
                self.measureJCouplingList = jCouplingList

        setResidueJCoupling(jCouplingList, self.residue, atomNames, value)

    def updateMolSystems(self, *obj):

        index = -1
        names = []

        molSystems = self.project.sortedMolSystems()
        if molSystems:

            if self.molSystem not in molSystems:
                self.molSystem = molSystems[0]

            names = [ms.code for ms in molSystems]
            index = molSystems.index(self.molSystem)

        self.molSystemPulldown.setup(names, index)

    def changeMolSystem(self, index, name):

        molSystems = self.project.sortedMolSystems()

        if molSystems:
            molSystem = molSystems[index]
        else:
            molSystem = None

        if molSystem is not self.molSystem:
            self.molSystem = molSystem
            self.updateAfter()

    def updateAfter(self, object=None):

        current = False
        if object and (object.className == 'JCoupling'):
            for resonance in object.resonances:
                resonanceSet = resonance.resonanceSet

                if resonanceSet:
                    molSystem = resonanceSet.findFirstAtomSet().findFirstAtom(
                    ).topObject

                    if molSystem is self.molSystem:
                        current = True
                        break

        else:
            current = True

        if self.waiting or (not current):
            return
        else:
            self.waiting = True
            self.after_idle(self.update)

    def update(self):

        textMatrix = []
        objectList = []

        if self.molSystem:
            chains = self.molSystem.sortedChains()

            if len(chains) > 1:
                doChains = False
            else:
                doChains = True

            for chain in chains:
                if doChains:
                    chainCode = chain.code
                else:
                    chainCode = ''

                for residue in chain.sortedResidues():
                    name = '%s%d%s' % (chainCode, residue.seqCode,
                                       getResidueCode(residue))
                    phi = 0.0
                    chiSq = 0.0
                    datum = [name, phi, chiSq]

                    object = [
                        residue,
                    ]
                    for atomNames in couplingAtoms:
                        couplingM = self.getResidueJCoupling(
                            self.measureJCouplingList, residue, atomNames)
                        couplingP = self.getResidueJCoupling(
                            self.predictJCouplingList, residue, atomNames)

                        pred = None
                        expt = None

                        if couplingM:
                            expt = couplingM.value

                        if couplingP:
                            pred = couplingP.value

                        datum.append(pred)
                        datum.append(expt)
                        object.append(couplingM)

                    objectList.append(object)
                    textMatrix.append(datum)

        self.couplingMatrix.update(textMatrix=textMatrix,
                                   objectList=objectList)

        self.updateCoefficients()

        self.waiting = False

    def updateCoefficients(self):

        textMatrix = []
        objectList = []
        for i in range(3):
            name = 'C%d' % i
            datum = [
                name,
            ]

            for atomNames in couplingAtoms:
                datum.append(self.coefficients[i].get(atomNames))

            textMatrix.append(datum)
            objectList.append(i)

        self.coefficientMatrix.update(textMatrix=textMatrix,
                                      objectList=objectList)

    def destroy(self):

        for func in ('__init__', 'delete', 'setValue', 'setError'):
            for clazz in ('ccp.nmr.Nmr.JCoupling', ):
                self.unregisterNotify(self.updateAfter, clazz, func)

        for func in ('__init__', 'delete'):
            for clazz in ('ccp.nmr.Nmr.JCouplingList', ):
                self.unregisterNotify(self.updateJCouplingLists, clazz, func)

        BasePopup.destroy(self)
Exemple #11
0
class BacusPopup(BasePopup):

  def __init__(self, parent, *args, **kw):

  
    self.project    = parent.project
    self.hNoesy    = None
    self.nNoesy     = None
    self.cNoesy     = None
    self.shiftList  = None

    BasePopup.__init__(self, parent, title="BACUS control module", **kw)
  
  def body(self, guiParent):
    
    guiParent.grid_columnconfigure(0, weight=1)

    row = 0
    guiParent.grid_rowconfigure(row, weight=1)
    inputFrame = LabelFrame(guiParent, text='Inputs:')
    inputFrame.grid(row=row, column=0, sticky=Tkinter.NSEW)
 
    label = Label(inputFrame, text='NOESY:')
    label.grid(row=0, column=0, sticky=Tkinter.NW)
    
    self.hNoesyPulldown = PulldownMenu(inputFrame,callback=self.setHNoesy)
    self.hNoesyPulldown.grid(row=0, column=1, sticky=Tkinter.NW)

    label = Label(inputFrame, text='15N NOESY:')
    label.grid(row=1, column=0, sticky=Tkinter.NW)
    
    self.nNoesyPulldown = PulldownMenu(inputFrame,callback=self.setNNoesy)
    self.nNoesyPulldown.grid(row=1, column=1, sticky=Tkinter.NW)
    
    label = Label(inputFrame, text='13C NOESY:')
    label.grid(row=2, column=0, sticky=Tkinter.NW)
 
    self.cNoesyPulldown = PulldownMenu(inputFrame,callback=self.setCNoesy)
    self.cNoesyPulldown.grid(row=2, column=1, sticky=Tkinter.NW)
    
    label = Label(inputFrame, text='Shift List:')
    label.grid(row=3, column=0, sticky=Tkinter.NW)
 
    self.shiftListPulldown = PulldownMenu(inputFrame,callback=self.setShiftList)
    self.shiftListPulldown.grid(row=3, column=1, sticky=Tkinter.NW)
    
    label = Label(inputFrame, text='2d BACUS executable:')
    label.grid(row=4, column=0, sticky=Tkinter.NW)
    
    self.executableEntry = Entry(inputFrame, text='/home/tjs23/clouds/justin/SpiBacusMidge/bacus/bacus_tjs.exe')
    self.executableEntry.grid(row=4, column=1, sticky=Tkinter.NW)

    self.executableButton = Button(inputFrame, text='Choose file', command=self.chooseExecutable)
    self.executableButton.grid(row=5, column=1, sticky=Tkinter.EW)
    
    row += 1
    outputFrame = LabelFrame(guiParent, text='Output:')
    outputFrame.grid(row=row, column=0, sticky=Tkinter.NSEW)
 
    row += 1
    texts    = ['Run BACUS 2d','Run BACUS 3d']
    commands = [self.runBacus,self.runBacus3d]
    self.bottomButtons = createDismissHelpButtonList(guiParent,texts=texts,commands=commands,expands=0,help_url=None)
    self.bottomButtons.grid(row=row, column=0, sticky=Tkinter.EW)
    
    self.update()    
  
  
  def chooseExecutable(self):
  
    fileTypes = [FileType('Table', ['*.exe']), FileType('All', ['*'])]
    fileSelectPopup = FileSelectPopup(self, file_types = fileTypes,
                                      title = 'Choose 2d BACUS executable', dismiss_text = 'Cancel',
                                      selected_file_must_exist = False)

    fileName = fileSelectPopup.getFile() 
    if fileName:
      self.executableEntry.set(fileName)
  
  
  def update(self):
 
    # set defaults via pulldown callbacks

    names = [self.getPeakListlabel(x) for x in self.gethNoesys()]
    if names:
      self.hNoesyPulldown.setup(names,0)
    else:
      self.hNoesyPulldown.setup([],-1)

    names = [self.getPeakListlabel(x) for x in self.getNNoesys()]
    if names:
      self.nNoesyPulldown.setup(names,0)
    else:
      self.nNoesyPulldown.setup([],-1)

    names = [self.getPeakListlabel(x) for x in self.getCNoesys()]
    if names:
      self.cNoesyPulldown.setup(names,0)
    else:
      self.cNoesyPulldown.setup([],-1)
  
    names = ['Shift List %d' % x.serial for x in self.getShiftLists()]
    if names:
      self.shiftListPulldown.setup(names,0)
    else:
      self.shiftListPulldown.setup([],-1)
  
    self.updateButtons()
  
  
  def updateButtons(self):
    
    if ( self.cNoesy or self.nNoesy ) and self.shiftList:
      self.bottomButtons.buttons[1].enable()
    else:
      self.bottomButtons.buttons[1].disable()
      
      
    if self.hNoesy and self.executableEntry.get() and self.shiftList:
      self.bottomButtons.buttons[0].enable()
    else:
      self.bottomButtons.buttons[0].disable()
    
  
  def runBacus3d(self, fileRoot='CCPN1'):
  
    if ( self.cNoesy or self.nNoesy ) and self.shiftList:
      run3dBacus(fileRoot,self.shiftList,self.cNoesy,self.nNoesy)
 
  def runBacus(self, fileRoot='CCPN1'):
     
    executable = self.executableEntry.get()
    if self.hNoesy and self.shiftList and executable:
      run2dBacus(fileRoot, executable, self.hNoesy,  self.shiftList)


  def getPeakListlabel(self, peakList):
  
    return '%s:%s:%d' % (peakList.dataSource.experiment.name, peakList.dataSource.name, peakList.serial)
  
  
  def getShiftLists(self):
  
    shiftLists = []
    if self.project:
      nmrProject = self.project.currentNmrProject
      shiftLists = nmrProject.findAllMeasurementLists(className='ShiftList')
    
    return list(shiftLists)
  
  
  def setShiftList(self, index, name=None):
  
    shiftLists = self.getShiftLists()
    if shiftLists:
      self.shiftList = shiftLists[index]
    else:
      self.shiftList = None
    
  def gethNoesys(self):
  
    peakLists = []
    if self.project:
      for experiment in self.project.currentNmrProject.experiments:
        for spectrum in experiment.dataSources:
          isotopes = getSpectrumIsotopes(spectrum)
          if isotopes == ['1H', '1H']:
            for peakList in spectrum.peakLists:
              #if 'NOE' in experiment.name.upper():
              #  peakLists.insert(0, peakList)
              #else:
              peakLists.append(peakList)
    
    return peakLists
  
  def getNNoesys(self):
  
    peakLists = []
    if self.project:
      for experiment in self.project.currentNmrProject.experiments:
        for spectrum in experiment.dataSources:
          isotopes = getSpectrumIsotopes(spectrum)
          isotopes.sort()
          if isotopes == ['15N', '1H', '1H']:
            for peakList in spectrum.peakLists:
              #if 'NOE' in experiment.name.upper():
              #  peakLists.insert(0, peakList)
              #else:
              peakLists.append(peakList)
    
    return peakLists
  
  
  def getCNoesys(self):
  
    peakLists = []
    if self.project:
      for experiment in self.project.currentNmrProject.experiments:
        for spectrum in experiment.dataSources:
          isotopes = getSpectrumIsotopes(spectrum)
          isotopes.sort()
          if isotopes == ['13C', '1H', '1H']:
            for peakList in spectrum.peakLists:
              if 'NOE' in experiment.name.upper():
                peakLists.insert(0, peakList)
              else:
                peakLists.append(peakList)
    
    return peakLists
        
        
  def setHNoesy(self, index, name=None):
 
    peakLists = self.gethNoesys()
    if peakLists:
      self.hNoesy = peakLists[index]
    else:
      self.hNoesy = None
        
        
  def setNNoesy(self, index, name=None):
 
    peakLists = self.getNNoesys()
    if peakLists:
      self.nNoesy = peakLists[index]
    else:
      self.nNoesy = None

 
  def setCNoesy(self, index, name=None):
  
    peakLists = self.getCNoesys()
    if peakLists:
      self.cNoesy = peakLists[index]
    else:
      self.cNoesy = None
 

  def destroy(self):

    BasePopup.destroy(self)
Exemple #12
0
class HcloudsMdPopup(BasePopup):
    def __init__(self, parent, *args, **kw):

        self.guiParent = parent
        self.project = parent.getProject()
        self.waiting = 0

        self.constraintSet = None
        self.constrLists = [None] * 4
        self.numClouds = 100
        self.filePrefix = 't_intra_'
        self.cloudsFiles = []
        self.adcAtomTypes = 'HN'

        # step num, initial temp, final temp, cooling steps, MD steps, MD tau, rep scale
        self.coolingScheme = []
        self.coolingScheme.append([1, 1, 1, 3, 500, 0.001, 0])
        self.coolingScheme.append([2, 80000, 4000, 19, 1000, 0.001, 0])
        self.coolingScheme.append([3, 4000, 1, 5, 500, 0.001, 0])
        self.coolingScheme.append([4, 15000, 1, 3, 1000, 0.001, 0])
        self.coolingScheme.append([5, 1, 1, 5, 500, 0.001, 0])
        self.coolingScheme.append([6, 8000, 1, 3, 1000, 0.001, 0])
        self.coolingScheme.append([7, 1, 1, 5, 500, 0.001, 0])
        self.coolingScheme.append([8, 3000, 25, 60, 2500, 0.001, 1])
        self.coolingScheme.append([9, 25, 25, 1, 7500, 0.001, 1])
        self.coolingScheme.append([10, 10, 10, 1, 7500, 0.001, 1])
        self.coolingScheme.append([11, 0.01, 0.01, 1, 7500, 0.0005, 1])

        self.coolingStep = None

        BasePopup.__init__(self,
                           parent,
                           title="Hydrogen Cloud Molecular Dynamics",
                           **kw)

    def body(self, guiFrame):

        self.mdInitTempEntry = FloatEntry(self,
                                          text='',
                                          returnCallback=self.setMdInitTemp)
        self.mdFinTempEntry = FloatEntry(self,
                                         text='',
                                         returnCallback=self.setMdFinTemp)
        self.mdCoolStepsEntry = IntEntry(self,
                                         text='',
                                         returnCallback=self.setMdCoolSteps)
        self.mdSimStepsEntry = IntEntry(self,
                                        text='',
                                        returnCallback=self.setMdSimSteps)
        self.mdTauEntry = FloatEntry(self,
                                     text='',
                                     returnCallback=self.setMdTau)
        self.mdRepScaleEntry = FloatEntry(self,
                                          text='',
                                          returnCallback=self.setMdRepScale)

        guiFrame.grid_columnconfigure(0, weight=1)

        row = 0
        guiFrame.grid_rowconfigure(row, weight=1)
        frame = LabelFrame(guiFrame, text='Input constraints')
        frame.grid(row=row, column=0, sticky=Tkinter.NSEW)
        frame.grid_columnconfigure(2, weight=1)

        srow = 0
        label = Label(frame, text='Constraint set:')
        label.grid(row=srow, column=0, sticky=Tkinter.W)
        self.constraintSetPulldown = PulldownMenu(
            frame,
            callback=self.changeConstraintSet,
            selected_index=0,
            do_initial_callback=0)
        self.constraintSetPulldown.grid(row=srow, column=1, sticky=Tkinter.W)

        srow += 1
        label = Label(frame, text='Dist constraint list 1:')
        label.grid(row=srow, column=0, sticky=Tkinter.W)
        self.distance1Pulldown = PulldownMenu(
            frame,
            callback=self.changeDistance1ConstraintList,
            selected_index=0,
            do_initial_callback=0)
        self.distance1Pulldown.grid(row=srow, column=1, sticky=Tkinter.W)
        self.numConstr1Label = Label(frame, text='Constraints: 0')
        self.numConstr1Label.grid(row=srow, column=2, sticky=Tkinter.W)

        srow += 1
        label = Label(frame, text='Dist constraint list 2:')
        label.grid(row=srow, column=0, sticky=Tkinter.W)
        self.distance2Pulldown = PulldownMenu(
            frame,
            callback=self.changeDistance2ConstraintList,
            selected_index=0,
            do_initial_callback=0)
        self.distance2Pulldown.grid(row=srow, column=1, sticky=Tkinter.W)
        self.numConstr2Label = Label(frame, text='Constraints: 0')
        self.numConstr2Label.grid(row=srow, column=2, sticky=Tkinter.W)

        srow += 1
        label = Label(frame, text='Dist constraint list 3:')
        label.grid(row=srow, column=0, sticky=Tkinter.W)
        self.distance3Pulldown = PulldownMenu(
            frame,
            callback=self.changeDistance3ConstraintList,
            selected_index=0,
            do_initial_callback=0)
        self.distance3Pulldown.grid(row=srow, column=1, sticky=Tkinter.W)
        self.numConstr3Label = Label(frame, text='Constraints: 0')
        self.numConstr3Label.grid(row=srow, column=2, sticky=Tkinter.W)

        srow += 1
        label = Label(frame, text='Dist constraint list 4:')
        label.grid(row=srow, column=0, sticky=Tkinter.W)
        self.distance4Pulldown = PulldownMenu(
            frame,
            callback=self.changeDistance4ConstraintList,
            selected_index=0,
            do_initial_callback=0)
        self.distance4Pulldown.grid(row=srow, column=1, sticky=Tkinter.W)
        self.numConstr4Label = Label(frame, text='Constraints: 0')
        self.numConstr4Label.grid(row=srow, column=2, sticky=Tkinter.W)

        row += 1
        frame0 = LabelFrame(guiFrame, text='Cooling scheme')
        frame0.grid(row=row, column=0, sticky=Tkinter.NSEW)
        frame0.grid_columnconfigure(1, weight=1)

        f0row = 0
        frame0.grid_rowconfigure(f0row, weight=1)
        colHeadings = [
            'Step', 'Initial\nTemp.', 'Final\nTemp.', 'Cooling\nSteps',
            'MD Steps', 'MD Tau', 'Rep.\nScale'
        ]
        editWidgets = [
            None, self.mdInitTempEntry, self.mdFinTempEntry,
            self.mdCoolStepsEntry, self.mdSimStepsEntry, self.mdTauEntry,
            self.mdRepScaleEntry
        ]
        editGetCallbacks = [
            None, self.getMdInitTemp, self.getMdFinTemp, self.getMdCoolSteps,
            self.getMdSimSteps, self.getMdTau, self.getMdRepScale
        ]
        editSetCallbacks = [
            None, self.setMdInitTemp, self.setMdFinTemp, self.setMdCoolSteps,
            self.setMdSimSteps, self.setMdTau, self.setMdRepScale
        ]
        self.coolingSchemeMatrix = ScrolledMatrix(
            frame0,
            editSetCallbacks=editSetCallbacks,
            editGetCallbacks=editGetCallbacks,
            editWidgets=editWidgets,
            maxRows=9,
            initialRows=12,
            headingList=colHeadings,
            callback=self.selectCoolingStep,
            objectList=self.coolingScheme,
            textMatrix=self.coolingScheme)
        self.coolingSchemeMatrix.grid(row=f0row,
                                      column=0,
                                      columnspan=4,
                                      sticky=Tkinter.NSEW)

        f0row += 1
        texts = ['Move earlier', 'Move later', 'Add step', 'Remove step']
        commands = [
            self.moveStepEarlier, self.moveStepLater, self.addCoolingStep,
            self.removeCoolingStep
        ]
        self.coolingSchemeButtons = ButtonList(frame0,
                                               expands=1,
                                               commands=commands,
                                               texts=texts)
        self.coolingSchemeButtons.grid(row=f0row,
                                       column=0,
                                       columnspan=4,
                                       sticky=Tkinter.EW)

        row += 1
        guiFrame.grid_rowconfigure(row, weight=1)
        frame1 = LabelFrame(guiFrame, text='Dynamics control')
        frame1.grid(row=row, column=0, sticky=Tkinter.NSEW)
        frame1.grid_columnconfigure(1, weight=1)

        f1row = 0
        label20 = Label(frame1, text='Number of clouds:')
        label20.grid(row=f1row, column=0, sticky=Tkinter.NW)
        self.numCloudsEntry = IntEntry(frame1,
                                       text=1,
                                       returnCallback=self.setNumClouds,
                                       width=10)
        self.numCloudsEntry.grid(row=f1row, column=1, sticky=Tkinter.NW)
        label21 = Label(frame1, text='Cloud file prefix:')
        label21.grid(row=f1row, column=2, sticky=Tkinter.NW)
        self.filePrefixEntry = Entry(frame1,
                                     text='t_intra_',
                                     returnCallback=self.setFilePrefix,
                                     width=10)
        self.filePrefixEntry.grid(row=f1row, column=3, sticky=Tkinter.NW)

        f1row += 1
        texts = ['Start molecular dynamics', 'Show dynamics progress']
        commands = [self.startMd, self.showMdProgress]
        self.mdButtons = ButtonList(frame1,
                                    expands=1,
                                    commands=commands,
                                    texts=texts)
        self.mdButtons.grid(row=f1row,
                            column=0,
                            columnspan=4,
                            sticky=Tkinter.NSEW)

        row += 1
        self.bottomButtons = createDismissHelpButtonList(guiFrame,
                                                         expands=0,
                                                         help_url=None)
        self.bottomButtons.grid(row=row, column=0, sticky=Tkinter.EW)

        self.update()

        for func in ('__init__', 'delete', 'setName'):
            for clazz in ('ccp.nmr.NmrConstraint.DistanceConstraintList', ):
                Implementation.registerNotify(self.updateConstraintLists,
                                              clazz, func)
        for func in ('__init__', 'delete'):
            Implementation.registerNotify(
                self.updateConstraintSets,
                'ccp.nmr.NmrConstraint.NmrConstraintStore', func)

    def getContraintSetNames(self):

        names = []
        constraintSets = self.project.currentNmrProject.nmrConstraintStores
        for set in constraintSets:
            names.append('%d' % set.serial)

        return names

    def changeConstraintSet(self, i, name):

        project = self.project
        if project.currentNmrProject.nmrConstraintStores:
            constraintSet = project.currentNmrProject.sortedNmrConstraintStores(
            )[i]
        else:
            constraintSet = None

        if constraintSet is not self.constraintSet:
            self.constraintSet = constraintSet

        self.updateConstraintLists()
        self.update()

    def updateConstraintLists(self, *opt):

        constrListData = self.getConstraintLists()
        constrListNames = [x[0] for x in constrListData]
        constraintLists = [x[1] for x in constrListData]
        # copes with self.constraintSet being None

        if constrListNames:
            i = 0
            for constraintList in self.constrLists:
                if constraintList not in constraintLists:
                    if i == 0:
                        self.constrLists[i] = constraintLists[0]
                    else:
                        self.constrLists[i] = None
                i += 1

            constraintLists.append(None)
            constrListNames.append('<None>')
            self.distance1Pulldown.setup(
                constrListNames, constraintLists.index(self.constrLists[0]))
            self.distance2Pulldown.setup(
                constrListNames, constraintLists.index(self.constrLists[1]))
            self.distance3Pulldown.setup(
                constrListNames, constraintLists.index(self.constrLists[2]))
            self.distance4Pulldown.setup(
                constrListNames, constraintLists.index(self.constrLists[3]))

        else:
            self.constrLists = [None] * 4
            self.distance1Pulldown.setup([], -1)
            self.distance2Pulldown.setup([], -1)
            self.distance3Pulldown.setup([], -1)
            self.distance4Pulldown.setup([], -1)

    def updateConstraintSets(self, *opt):

        project = self.project
        constraintSets = list(project.currentNmrProject.nmrConstraintStores)
        if constraintSets:
            constraintSetNames = self.getContraintSetNames()

            # set defaults
            if self.constraintSet not in constraintSets:
                self.constraintSet = constraintSets[0]

            if self.constraintSet:
                j = 0
                for constraintList in self.constrLists:
                    if constraintList and (constraintList.nmrConstraintStore
                                           is not self.constraintSet):
                        if self.constraintSet.constraintLists and j == 0:
                            self.constrLists[
                                j] = self.constraintSet.constraintLists[0]
                        else:
                            self.constrLists[j] = None
                    j += 1

            else:
                self.constrLists = [None] * 4

            i = constraintSets.index(self.constraintSet)
            self.constraintSetPulldown.setup(constraintSetNames, i)

        else:
            self.constraintSet = None
            self.constrLists = [None] * 4
            self.constraintSetPulldown.setup([], -1)

    def getConstraintListName(self, constraintList):

        if constraintList.name:
            listName = ':%s' % (constraintList.name)
        else:
            listName = ''

        name = '%d:%d:%s%s' % (constraintList.nmrConstraintStore.serial,
                               constraintList.serial,
                               constraintList.className[:-14], listName)
        return name

    def getConstraintLists(self):

        constraintLists = []
        if self.constraintSet:
            for constraintList in self.constraintSet.constraintLists:
                if constraintList.className == 'DistanceConstraintList':
                    name = self.getConstraintListName(constraintList)
                    constraintLists.append([name, constraintList])

        return constraintLists

    def changeDistance1ConstraintList(self, i, name):
        self.changeDistanceConstraintList(i, name, 0)

    def changeDistance2ConstraintList(self, i, name):
        self.changeDistanceConstraintList(i, name, 1)

    def changeDistance3ConstraintList(self, i, name):
        self.changeDistanceConstraintList(i, name, 2)

    def changeDistance4ConstraintList(self, i, name):
        self.changeDistanceConstraintList(i, name, 3)

    def changeDistanceConstraintList(self, i, name, listNum):

        project = self.project
        constraintLists = self.getConstraintLists()

        if constraintLists and (i < 4):
            self.constrLists[listNum] = constraintLists[i][1]
        else:
            self.constrLists[listNum] = None

        self.update()

    def startMd(self):

        self.setNumClouds()
        self.setFilePrefix()
        if ((self.constrLists != [None] * 4) and (self.numClouds > 0)
                and self.filePrefix):

            resDict = {}
            for resonance in self.guiParent.project.currentNmrProject.resonances:
                resDict[resonance.serial] = resonance

            constraints = []

            constraintStore = None
            for dcl in self.constrLists:
                if dcl:
                    constraintStore = dcl.nmrConstraintStore
                    constraints.extend(list(dcl.constraints))

            resonances = []
            for constraint in constraints:
                for item in constraint.items:
                    for fixedResonance in item.resonances:
                        if fixedResonance.resonanceSerial is None:
                            resonance = newResonance(
                                self.guiParent.project,
                                isotopeCode=fixedResonance.isotopeCode)
                            resonance.setName(fixedResonance.name)
                            fixedResonance.setResonanceSerial(resonance.serial)
                            resDict[resonance.serial] = resonance
                            if fixedResonance.resonanceSet:
                                atomSets = list(
                                    fixedResonance.resonanceSet.atomSets)
                                assignAtomsToRes(atomSets, resonance)

                        if resDict.get(
                                fixedResonance.resonanceSerial) is not None:
                            resonances.append(
                                resDict[fixedResonance.resonanceSerial])
                            resDict[fixedResonance.resonanceSerial] = None

            resonances, intraConstraintList = self.makeIntraConstraints(
                resonances, constraintStore)
            constraints.extend(list(intraConstraintList.constraints))
            resonances, interConstraintList = self.makeInterConstraints(
                resonances, constraintStore)
            constraints.extend(list(interConstraintList.constraints))

            startMdProcess(self.numClouds, constraints, resonances,
                           self.coolingScheme, self.filePrefix)

            #structGen = self.distanceConstraintList.structureGeneration

            serials = []
            for resonance in resonances:
                serials.append(resonance.serial)
            clouds = []
            for i in range(self.numClouds):
                clouds.append('%s%3.3d.pdb' % (self.filePrefix, i))
            self.guiParent.application.setValues(constraintStore,
                                                 'clouds',
                                                 values=clouds)
            self.guiParent.application.setValues(constraintStore,
                                                 'cloudsResonances',
                                                 values=serials)

            # do better than this check for creation

    def makeInterConstraints(self, resonances, constraintSet):

        from ccpnmr.analysis.core.ConstraintBasic import getFixedResonance
        from ccpnmr.analysis.core.AssignmentBasic import findConnectedSpinSystem

        project = constraintSet.root
        constraintList = constraintSet.newDistanceConstraintList()
        constraintList.name = 'Seq connections'

        resDict = {}
        spinSystemDict = {}
        for resonance in resonances:
            resDict[resonance] = True
            spinSystem = resonance.resonanceGroup
            if spinSystem:
                spinSystemDict[spinSystem] = None

        spinSystems = spinSystemDict.keys()

        for spinSystem in spinSystems:
            nextSpinSystem = findConnectedSpinSystem(spinSystem, delta=1)
            if nextSpinSystem:
                ca = spinSystem.newAtoms.get('CA')
                c = spinSystem.newAtoms.get('C')
                n = nextSpinSystem.newAtoms.get('N')

                if ca and c and n:
                    if resDict.get(ca) is None:
                        resonances.append(ca)
                    if resDict.get(c) is None:
                        resonances.append(c)
                    if resDict.get(n) is None:
                        resonances.append(n)

                    c_n = constraintList.newDistanceConstraint(
                        weight=1.0,
                        origData=1.0,
                        targetValue=1.32,
                        upperLimit=1.35,
                        lowerLimit=1.29,
                        error=0.06)

                    # below based on angle constraints
                    ca_n = constraintList.newDistanceConstraint(
                        weight=1.0,
                        origData=1.0,
                        targetValue=2.415,
                        upperLimit=2.513,
                        lowerLimit=2.316,
                        error=0.197)

                    frCa = getFixedResonance(constraintSet, ca)
                    frC = getFixedResonance(constraintSet, c)
                    frN = getFixedResonance(constraintSet, n)

                    item = ca_n.newDistanceConstraintItem(
                        resonances=[frCa, frN])
                    item = c_n.newDistanceConstraintItem(resonances=[frC, frN])

        return resonances, constraintList

    def makeIntraConstraints(self, resonances, constraintSet):

        from ccpnmr.analysis.core.ConstraintBasic import getFixedResonance

        project = constraintSet.root
        constraintList = constraintSet.newDistanceConstraintList()
        constraintList.name = 'Backbone intra'

        dict = {}
        for resonance in resonances:
            if resonance.resonanceGroup and resonance.assignNames:
                dict[resonance] = 1
                resonance.resonanceGroup.newAtoms = {}

        for resonance in dict.keys():
            ss = resonance.resonanceGroup
            if resonance.assignNames[0] == 'H':
                for resonance2 in ss.resonances:
                    if dict.get(resonance2
                                ) and resonance2.assignNames[0][:2] == 'HA':

                        ca = ss.newAtoms.get('CA')
                        if ca is None:
                            ca = project.newResonance(isotopeCode='13C',
                                                      assignNames=[
                                                          'CA',
                                                      ])
                            resonances.append(ca)

                        c = ss.newAtoms.get('C')
                        if c is None:
                            c = project.newResonance(isotopeCode='13C',
                                                     assignNames=[
                                                         'C',
                                                     ])
                            resonances.append(c)

                        n = ss.newAtoms.get('N')
                        if n is None:
                            n = project.newResonance(isotopeCode='15N',
                                                     assignNames=[
                                                         'N',
                                                     ])
                            resonances.append(n)

                        ss.newAtoms['C'] = c
                        ss.newAtoms['CA'] = ca
                        ss.newAtoms['N'] = n

                        frCa = getFixedResonance(constraintSet, ca)
                        frC = getFixedResonance(constraintSet, c)
                        frN = getFixedResonance(constraintSet, n)
                        frH = getFixedResonance(constraintSet, resonance)
                        frha = getFixedResonance(constraintSet, resonance2)

                        h_n = constraintList.newDistanceConstraint(
                            weight=1.0,
                            origData=1.0,
                            targetValue=1.01,
                            upperLimit=1.1,
                            lowerLimit=0.9,
                            error=0.2)
                        n_ca = constraintList.newDistanceConstraint(
                            weight=1.0,
                            origData=1.0,
                            targetValue=1.465,
                            upperLimit=1.50,
                            lowerLimit=1.43,
                            error=0.07)
                        ca_c = constraintList.newDistanceConstraint(
                            weight=1.0,
                            origData=1.0,
                            targetValue=1.525,
                            upperLimit=1.55,
                            lowerLimit=1.50,
                            error=0.05)

                        # below based on angle constraints
                        n_c = constraintList.newDistanceConstraint(
                            weight=1.0,
                            origData=1.0,
                            targetValue=2.464,
                            upperLimit=2.572,
                            lowerLimit=2.356,
                            error=0.216)

                        item = h_n.newDistanceConstraintItem(
                            resonances=[frH, frN])
                        item = n_ca.newDistanceConstraintItem(
                            resonances=[frN, frCa])
                        item = ca_c.newDistanceConstraintItem(
                            resonances=[frCa, frC])
                        item = n_c.newDistanceConstraintItem(
                            resonances=[frN, frC])

                        if ss.newAtoms.get('CAHA') is None:
                            ca_ha = constraintList.newDistanceConstraint(
                                weight=1.0,
                                origData=1.0,
                                targetValue=1.09,
                                upperLimit=1.19,
                                lowerLimit=0.99,
                                error=0.2)
                            item = ca_ha.newDistanceConstraintItem(
                                resonances=[frC, frha])
                            ss.newAtoms['CAHA'] = 1

            if resonance.assignNames[0][:2] == 'HA':
                for resonance2 in ss.resonances:
                    if dict.get(resonance2
                                ) and resonance2.assignNames[0][:2] == 'HB':

                        ca = ss.newAtoms.get('CA')
                        if ca is None:
                            ca = project.newResonance(isotopeCode='13C',
                                                      assignNames=[
                                                          'CA',
                                                      ])
                            resonances.append(ca)

                        cb = ss.newAtoms.get('CB')
                        if cb is None:
                            cb = project.newResonance(isotopeCode='13C',
                                                      assignNames=[
                                                          'CB',
                                                      ])
                            resonances.append(cb)

                        ss.newAtoms['CA'] = cb
                        ss.newAtoms['CB'] = ca
                        ss.newAtoms['CAHA'] = 1

                        frCA = getFixedResonance(constraintSet, ca)
                        frCB = getFixedResonance(constraintSet, cb)
                        frHA = getFixedResonance(constraintSet, resonance)
                        frHB = getFixedResonance(constraintSet, resonance2)

                        c_b = constraintList.newDistanceConstraint(
                            weight=1.0,
                            origData=1.0,
                            targetValue=1.09,
                            upperLimit=1.19,
                            lowerLimit=0.99,
                            error=0.2)
                        c_c = constraintList.newDistanceConstraint(
                            weight=1.0,
                            origData=1.0,
                            targetValue=1.53,
                            upperLimit=1.56,
                            lowerLimit=1.51,
                            error=0.05)

                        item = c_b.newDistanceConstraintItem(
                            resonances=[frCB, frHB])
                        item = c_c.newDistanceConstraintItem(
                            resonances=[frCA, frCB])

                        if ss.newAtoms.get('CAHA') is None:
                            c_a = constraintList.newDistanceConstraint(
                                weight=1.0,
                                origData=1.0,
                                targetValue=1.09,
                                upperLimit=1.19,
                                lowerLimit=0.99,
                                error=0.2)
                            item = c_a.newDistanceConstraintItem(
                                resonances=[frCA, frHA])
                            ss.newAtoms['CAHA'] = 1

        return resonances, constraintList

    def showMdProgress(self):

        n = 0
        m = self.numClouds
        for i in range(m):
            pdbFileName = '%s%3.3d.pdb' % (self.filePrefix, i)
            if os.path.exists(pdbFileName):
                n += 1

        p = n * 100 / float(m)
        text = 'Done %d of %d clouds (%1.2f)%%' % (n, m, p)
        showInfo('MD Progress', text)

    def setFilePrefix(self, text=None):

        if not text:
            text = self.filePrefixEntry.get()

        if text:
            self.filePrefix = text

    def setNumClouds(self, n=None, *event):

        if not n:
            n = self.numCloudsEntry.get()

        if n:
            self.numClouds = int(n)

    def update(self):

        self.updateConstraintSets()
        self.updateConstraintLists()

        if (self.constrLists != [None] * 4) and self.coolingScheme:
            self.mdButtons.buttons[0].enable()
            self.mdButtons.buttons[1].enable()
        else:
            self.mdButtons.buttons[0].disable()
            self.mdButtons.buttons[1].disable()

        if self.constrLists[0]:
            self.numConstr1Label.set('Constraints: ' +
                                     str(len(self.constrLists[0].constraints)))
        else:
            self.numConstr1Label.set('Constraints: 0')

        if self.constrLists[1]:
            self.numConstr2Label.set('Constraints: ' +
                                     str(len(self.constrLists[1].constraints)))
        else:
            self.numConstr2Label.set('Constraints: 0')

        if self.constrLists[2]:
            self.numConstr3Label.set('Constraints: ' +
                                     str(len(self.constrLists[2].constraints)))
        else:
            self.numConstr3Label.set('Constraints: 0')

        if self.constrLists[3]:
            self.numConstr4Label.set('Constraints: ' +
                                     str(len(self.constrLists[3].constraints)))
        else:
            self.numConstr4Label.set('Constraints: 0')

    def getMdInitTemp(self, coolingStep):

        self.mdInitTempEntry.set(coolingStep[1])

    def getMdFinTemp(self, coolingStep):

        self.mdFinTempEntry.set(coolingStep[2])

    def getMdCoolSteps(self, coolingStep):

        self.mdCoolStepsEntry.set(coolingStep[3])

    def getMdSimSteps(self, coolingStep):

        self.mdSimStepsEntry.set(coolingStep[4])

    def getMdTau(self, coolingStep):

        self.mdTauEntry.set(coolingStep[5])

    def getMdRepScale(self, coolingStep):

        self.mdRepScaleEntry.set(coolingStep[6])

    def setMdInitTemp(self, event):

        value = self.mdInitTempEntry.get()
        if value is not None:
            self.coolingStep[1] = value

        self.updateCoolingScheme()

    def setMdFinTemp(self, event):

        value = self.mdFinTempEntry.get()
        if value is not None:
            self.coolingStep[2] = value

        self.updateCoolingScheme()

    def setMdCoolSteps(self, event):

        value = self.mdCoolStepsEntry.get()
        if value is not None:
            self.coolingStep[3] = value

        self.updateCoolingScheme()

    def setMdSimSteps(self, event):

        value = self.mdSimStepsEntry.get()
        if value is not None:
            self.coolingStep[4] = value

        self.updateCoolingScheme()

    def setMdTau(self, event):

        value = self.mdTauEntry.get()
        if value is not None:
            self.coolingStep[5] = value

        self.updateCoolingScheme()

    def setMdRepScale(self, event):

        value = self.mdRepScaleEntry.get()
        if value is not None:
            self.coolingStep[6] = value

        self.updateCoolingScheme()

    def selectCoolingStep(self, object, row, col):

        self.coolingStep = object

    def moveStepEarlier(self):

        if self.coolingStep:
            i = self.coolingStep[0] - 1
            if i > 0:
                coolingStep = self.coolingScheme[i - 1]
                coolingStep[0] = i + 1
                self.coolingStep[0] = i
                self.coolingScheme[i - 1] = self.coolingStep
                self.coolingScheme[i] = coolingStep

                self.updateCoolingScheme()
                self.coolingSchemeMatrix.hilightObject(self.coolingStep)

    def moveStepLater(self):

        if self.coolingStep:
            i = self.coolingStep[0] - 1
            if i < len(self.coolingScheme) - 1:
                coolingStep = self.coolingScheme[i + 1]
                coolingStep[0] = i + 1
                self.coolingStep[0] = i + 2
                self.coolingScheme[i + 1] = self.coolingStep
                self.coolingScheme[i] = coolingStep

                self.updateCoolingScheme()
                self.coolingSchemeMatrix.hilightObject(self.coolingStep)

    def addCoolingStep(self):

        i = len(self.coolingScheme) + 1
        datum = [i, 3000, 100, 10, 2500, 0.001, 1]

        self.coolingScheme.append(datum)
        self.updateCoolingScheme()

    def removeCoolingStep(self):

        if self.coolingStep:
            coolingScheme = []
            i = 0
            for coolingStep in self.coolingScheme:
                if coolingStep is not self.coolingStep:
                    i += 1
                    coolingStep[0] = i
                    coolingScheme.append(coolingStep)

            self.coolingScheme = coolingScheme
            self.updateCoolingScheme()

    def updateCoolingScheme(self):

        objectList = self.coolingScheme
        textMatrix = self.coolingScheme
        self.coolingSchemeMatrix.update(objectList=objectList,
                                        textMatrix=textMatrix)

    def updateMidgeParams(self):

        data = [
            self.specFreq, self.maxIter, self.mixTime, self.corrTime,
            self.leakRate, self.maxIntens
        ]

        self.midgeParamsMatrix.update(textMatrix=[
            data,
        ])

    def destroy(self):

        for func in ('__init__', 'delete', 'setName'):
            for clazz in ('ccp.nmr.NmrConstraint.DistanceConstraintList', ):
                Implementation.unregisterNotify(self.updateConstraintLists,
                                                clazz, func)
        for func in ('__init__', 'delete'):
            Implementation.unregisterNotify(
                self.updateConstraintSets,
                'ccp.nmr.NmrConstraint.NmrConstraintStore', func)

        BasePopup.destroy(self)