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)
Beispiel #2
0
class MeccanoPopup(BasePopup):

  def __init__(self, parent, project, *args, **kw):
  
    self.alignMedium = None
    self.chain = None
    self.constraint = None
    self.constraintSet = None
    self.molSystem = None
    self.project = project
    self.run = None
    self.shiftList = None
    self.tensor = None

    
    BasePopup.__init__(self, parent=parent, title='MECCANO', *args, **kw)

    self.curateNotifiers(self.registerNotify)

  def body(self, guiFrame):
  
    guiFrame.grid_columnconfigure(0, weight=1)
    guiFrame.grid_rowconfigure(0, weight=1)

    options = ['Parameters','Restraints','Alignment Media & Tensors','About Meccano']
    tabbedFrame = TabbedFrame(guiFrame, options=options)
    tabbedFrame.grid(row=0, column=0, sticky='nsew')
    
    frameA, frameB, frameC, frameD = tabbedFrame.frames
    frameA.grid_columnconfigure(1, weight=1)
    frameA.grid_rowconfigure(13, weight=1)
    frameB.grid_columnconfigure(1, weight=1)
    frameB.grid_rowconfigure(1, weight=1)
    frameC.grid_columnconfigure(0, weight=1)
    frameC.grid_rowconfigure(1, weight=1)
    frameD.grid_columnconfigure(0, weight=1)
    frameD.grid_rowconfigure(0, weight=1)
    
    texts = ['Run MECCANO!']
    commands = [self.runMeccano]
    bottomButtons = createDismissHelpButtonList(guiFrame, texts=texts,
                                                commands=commands, expands=True)
    bottomButtons.grid(row=1, column=0, sticky='ew')

    if not Meccano:
      bottomButtons.buttons[0].disable()
  
    # Parameters
        
    row = 0
    label = Label(frameA, text='Calculation Run:')
    label.grid(row=row,column=0,sticky='w')
    self.runPulldown = PulldownList(frameA, callback=self.selectRun)
    self.runPulldown.grid(row=row,column=1,sticky='w')
    
    row += 1    
    label = Label(frameA, text='Shift List (for CO):')
    label.grid(row=row,column=0,sticky='w')
    self.shiftListPulldown = PulldownList(frameA, callback=self.selectShiftList)
    self.shiftListPulldown.grid(row=row,column=1,sticky='w')
           
    row += 1    
    label = Label(frameA, text='Keep Copy of Used Shifts:')
    label.grid(row=row,column=0,sticky='w')
    self.toggleCopyShifts = CheckButton(frameA)
    self.toggleCopyShifts.grid(row=row,column=1,sticky='w')
    self.toggleCopyShifts.set(True)
        
    row += 1    
    label = Label(frameA, text='Molecular System:')
    label.grid(row=row,column=0,sticky='w')
    self.molSystemPulldown = PulldownList(frameA, callback=self.selectMolSystem)
    self.molSystemPulldown.grid(row=row,column=1,sticky='w')
        
    row += 1    
    label = Label(frameA, text='Chain:')
    label.grid(row=row,column=0,sticky='w')
    self.chainPulldown = PulldownList(frameA, callback=self.selectChain)
    self.chainPulldown.grid(row=row,column=1,sticky='w')
    self.chainPulldown.bind('<Leave>', self.updateRunParams) 
        
    row += 1    
    label = Label(frameA, text='First Peptide Plane:')
    label.grid(row=row,column=0,sticky='w')
    self.firstResEntry = IntEntry(frameA, text=None, width=8)
    self.firstResEntry.grid(row=row,column=1,sticky='w')
    self.firstResEntry.bind('<Leave>', self.updateRunParams) 
        
    row += 1    
    label = Label(frameA, text='Last Peptide Plane:')
    label.grid(row=row,column=0,sticky='w')
    self.lastResEntry = IntEntry(frameA, text=None, width=8)
    self.lastResEntry.grid(row=row,column=1,sticky='w')
    self.lastResEntry.bind('<Leave>', self.updateRunParams) 
        
    row += 1    
    label = Label(frameA, text='Max Num Optimisation Steps:')
    label.grid(row=row,column=0,sticky='w')
    self.maxOptStepEntry = IntEntry(frameA, text=500, width=8)
    self.maxOptStepEntry.grid(row=row,column=1,sticky='w')
    self.maxOptStepEntry.bind('<Leave>', self.updateRunParams) 
        
    row += 1    
    label = Label(frameA, text='Num Optimisation Peptide Planes:')
    label.grid(row=row,column=0,sticky='w')
    self.numOptPlaneEntry = IntEntry(frameA, text=2, width=8)
    self.numOptPlaneEntry.grid(row=row,column=1,sticky='w')
    self.numOptPlaneEntry.bind('<Leave>', self.updateRunParams) 
        
    row += 1    
    label = Label(frameA, text='Min Num Optimisation Hits:')
    label.grid(row=row,column=0,sticky='w')
    self.numOptHitsEntry = IntEntry(frameA, text=5, width=8)
    self.numOptHitsEntry.grid(row=row,column=1,sticky='w')
    self.numOptHitsEntry.bind('<Leave>', self.updateRunParams) 

    row += 1    
    label = Label(frameA, text='File Name Prefix:')
    label.grid(row=row,column=0,sticky='w')
    self.pdbFileEntry = Entry(frameA, text='Meccano', width=8)
    self.pdbFileEntry.grid(row=row,column=1,sticky='w')
    self.pdbFileEntry.bind('<Leave>', self.updateRunParams) 
           
    row += 1    
    label = Label(frameA, text='Write Output File (.out):')
    label.grid(row=row,column=0,sticky='w')
    self.toggleWriteOutFile = CheckButton(frameA)
    self.toggleWriteOutFile.grid(row=row,column=1,sticky='w')
    self.toggleWriteOutFile.set(False)
    self.toggleWriteOutFile.bind('<Leave>', self.updateRunParams) 
           
    row += 1    
    label = Label(frameA, text='Write PDB File (.pdb):')
    label.grid(row=row,column=0,sticky='w')
    self.toggleWritePdbFile = CheckButton(frameA)
    self.toggleWritePdbFile.grid(row=row,column=1,sticky='w')
    self.toggleWritePdbFile.set(True)
    self.toggleWritePdbFile.bind('<Leave>', self.updateRunParams) 
    
    if not Meccano:
      row += 1    
      label = Label(frameA, text='The Meccano executable is not available (it needs to be compiled)', fg='red')
      label.grid(row=row,column=0,columnspan=2,sticky='w')

    # Restraints
    
    label = Label(frameB, text='Constraint Set:')
    label.grid(row=0,column=0,sticky='w')
    
    self.constraintSetPulldown = PulldownList(frameB, callback=self.selectConstraintSet)
    self.constraintSetPulldown.grid(row=0,column=1,sticky='w')
    
    self.alignMediumPulldown= PulldownList(self, callback=self.setAlignMedium)
    
    headingList = ['#','List Type','Use?','Alignment\nMedium','Num\nRestraints']
    editWidgets      = [None,None,None,self.alignMediumPulldown,None]
    editGetCallbacks = [None,None,self.toggleUseRestraints,self.getAlignMedium,None]
    editSetCallbacks = [None,None,None,self.setAlignMedium,None]
    self.restraintMatrix = ScrolledMatrix(frameB,
                                          headingList=headingList,
                                          editSetCallbacks=editSetCallbacks,
                                          editGetCallbacks=editGetCallbacks, 
                                          editWidgets=editWidgets,
                                          callback=None,
                                          multiSelect=True)
    self.restraintMatrix.grid(row=1,column=0,columnspan=2,sticky='nsew')
    
    
    # Alignment Media
    
    div = LabelDivider(frameC,text='Alignment Media')
    div.grid(row=0,column=0,sticky='ew')
    
    self.mediumNameEntry = Entry(self, returnCallback=self.setMediumName)
    self.mediumDetailsEntry = Entry(self, returnCallback=self.setMediumDetails)
    
    headingList = ['#','Name','Details','Static Tensor','Dynamic Tensor']
    editWidgets      = [None, self.mediumNameEntry, self.mediumDetailsEntry, None, None]
    editGetCallbacks = [None, self.getMediumName, self.getMediumDetails, None, None]
    editSetCallbacks = [None, self.setMediumName, self.setMediumDetails, None, None]
    self.mediaMatrix = ScrolledMatrix(frameC,
                                      headingList=headingList,
                                      editSetCallbacks=editSetCallbacks,
                                      editGetCallbacks=editGetCallbacks, 
                                      editWidgets=editWidgets,
                                      callback=self.selectAlignMedium,
                                      multiSelect=True)
                                 
    self.mediaMatrix.grid(row=1,column=0,sticky='nsew')
     
    
    texts = ['Add Alignment medium','Remove Alignment Medium']
    commands = [self.addAlignMedium,self.removeAlignMedium]
    buttonList = ButtonList(frameC, texts=texts, commands=commands, expands=True)
    buttonList.grid(row=2,column=0,sticky='nsew')
    
    self.editAxialEntry = FloatEntry(self, returnCallback=self.setAxial)
    self.editRhombicEntry = FloatEntry(self, returnCallback=self.setRhombic)
    self.editAlphaEulerEntry = FloatEntry(self, returnCallback=self.setEulerAlpha)
    self.editBetaEulerEntry = FloatEntry(self, returnCallback=self.setEulerBeta)
    self.editGammaEulerEntry = FloatEntry(self, returnCallback=self.setEulerGamma)
    
    
    div = LabelDivider(frameC,text='Alignment Tensors')
    div.grid(row=3,column=0,sticky='ew')
    
    headingList = ['Type', u'Axial (\u03B6)',u'Rhombic (\u03B7)',
                   u'Euler \u03B1',u'Euler \u03B2',u'Euler \u03B3']
    editWidgets      = [None,self.editAxialEntry,
                        self.editRhombicEntry,self.editAlphaEulerEntry,
                        self.editBetaEulerEntry,self.editGammaEulerEntry]
    editSetCallbacks = [None,self.setAxial,self.setRhombic,
                        self.setEulerAlpha,self.setEulerBeta,self.setEulerGamma]
    editGetCallbacks = [None,self.getAxial,self.getRhombic,
                        self.getEulerAlpha,self.getEulerBeta,self.getEulerGamma]
                   
    self.tensorMatrix = ScrolledMatrix(frameC, maxRows=2,
                                       headingList=headingList,
                                       editSetCallbacks=editSetCallbacks,
                                       editGetCallbacks=editGetCallbacks, 
                                       editWidgets=editWidgets,
                                       callback=self.selectTensor,
                                       multiSelect=True)
                                          
    self.tensorMatrix.grid(row=4,column=0,sticky='nsew')
    
    texts = ['Add Static Tensor','Add Dynamic Tensor','Remove Tensor']
    commands = [self.addStaticTensor,self.addDynamicTensor,self.removeTensor]
    buttonList = ButtonList(frameC,texts=texts, commands=commands, expands=True)
    buttonList.grid(row=5,column=0,sticky='ew')
       
    # About
    
    label = Label(frameD, text='About Meccano...')
    label.grid(row=0,column=0,sticky='w')
  
    #
  
    self.geometry('500x400')

    self.updateShiftLists()
    self.updateMolSystems()
    self.updateResidueRanges()
    self.updateConstraintSets()
    self.updateAlignMedia()
    self.updateRuns()
    
  def close(self):
  
    self.updateRunParams()
    
    BasePopup.close(self)
  
  def destroy(self):
  
    self.updateRunParams()
    self.curateNotifiers(self.unregisterNotify)
    
    BasePopup.destroy(self)
  
  def curateNotifiers(self, notifyFunc):
  
    for func in ('__init__', 'delete'):
      notifyFunc(self.updateConstraintSetsAfter, 'ccp.nmr.NmrConstraint.NmrConstraintStore', func)
    
    for func in ('__init__', 'delete','setName','setConditionState'):
      for clazz in ('ccp.nmr.NmrConstraint.CsaConstraintList',
                    'ccp.nmr.NmrConstraint.DihedralConstraintList',
                    'ccp.nmr.NmrConstraint.DistanceConstraintList',
                    'ccp.nmr.NmrConstraint.HBondConstraintList',
                    'ccp.nmr.NmrConstraint.JCouplingConstraintList',
                    'ccp.nmr.NmrConstraint.RdcConstraintList'):
        notifyFunc(self.updateConstraintListsAfter, clazz, func)
        
    for func in ('__init__', 'delete',):
      for clazz in ('ccp.nmr.NmrConstraint.CsaConstraint',
                    'ccp.nmr.NmrConstraint.DihedralConstraint',
                    'ccp.nmr.NmrConstraint.DistanceConstraint',
                    'ccp.nmr.NmrConstraint.HBondConstraint',
                    'ccp.nmr.NmrConstraint.JCouplingConstraint',
                    'ccp.nmr.NmrConstraint.RdcConstraint'):
        notifyFunc(self.updateConstraintsAfter, clazz, func)    
    
    for func in ('__init__', 'delete'):
      notifyFunc(self.updateShiftListsAfter,'ccp.nmr.Nmr.ShiftList', func)

    for func in ('__init__', 'delete'):
      notifyFunc(self.updateMolSystemsAfter,'ccp.molecule.MolSystem.MolSystem', func)

    for func in ('__init__', 'delete'):
      notifyFunc(self.updateChainsAfter,'ccp.molecule.MolSystem.Chain', func)

    for func in ('__init__', 'delete','setDynamicAlignment',
                 'setStaticAlignment','setName','setDetails'):
      notifyFunc(self.updateAlignMediaAfter,'ccp.nmr.NmrConstraint.ConditionState', func)

  def updateAlignMediaAfter(self, alignMedium):
  
     if alignMedium.nmrConstraintStore is self.constraintSet:
       self.after_idle(self.updateAlignMedia)
 
       if alignMedium is self.alignMedium:
         self.after_idle(self.updateTensors)

  def updateConstraintSetsAfter(self, constraintSet):
  
     self.after_idle(self.updateConstraintSets)

  def updateShiftListsAfter(self, shiftList):
  
     self.after_idle(self.updateShiftLists)

  def updateMolSystemsAfter(self, molSystem):
  
     self.after_idle(self.updateMolSystems)

  def updateChainsAfter(self, chain):
  
     self.after_idle(self.updateChains)
  
  def updateConstraintsAfter(self, constraint):
  
     if constraint.parent.parent is self.constraintSet:
       self.after_idle(self.updateConstraintLists)
  
  def updateConstraintListsAfter(self, constraintList):
  
     if constraintList.parent is self.constraintSet:
       self.after_idle(self.updateConstraintLists)
    
  def runMeccano(self):
    
    #
    #
    # Input checks first
    #
    #
  
    warning = ''
    if not self.molSystem:
      warning += 'No molecular system selected\n'
    
    if not self.chain:
      warning += 'No chain selected\n'
  
    if not self.constraintSet:
      warning += 'No selected constraint set\n'  
    else:
      constraintLists = [cl for cl in self.constraintSet.constraintLists if cl.useForMeccano]  
      if not constraintLists:
        warning += 'No constraint lists selected for use\n'   
 
    first, last = self.updateResidueRanges()
    if (last-first) < 2:
      warning += 'Too few peptide planes selected\n'         
  
    if warning:
      showWarning('Cannot run MECCANO','Encountered the following problems:\n' + warning)
      return
      
    if not self.run:
      self.run = self.makeSimRun()
      
    self.updateRunParams()
    
    if self.toggleCopyShifts.get() and self.shiftList:
      shiftList = self.run.findFirstOutputMeasurementList(className='ShiftList')
      
      if not shiftList:
        shiftList = self.project.currentNmrProject.newShiftList(name='Meccano Input')
        
      self.run.setOutputMeasurementLists([shiftList,])
    
      shiftDict = {}
      for shift in shiftList.shifts:
        shiftDict[shift.resonance] = shift
      
    
      for shift in self.shiftList.shifts:
        resonance = shift.resonance
        resonanceSet = resonance.resonanceSet
        
        if resonanceSet:
          atom = resonanceSet.findFirstAtomSet().findFirstAtom()
          
          if (atom.name == 'C') and (atom.residue.molResidue.molType == 'protein'):
            shift2 = shiftDict.get(resonance)
            if shift2:
              shift2.value = shift.value
              shift2.error = shift.error
              
            else:
              shiftList.newShift(resonance=resonance, value=shift.value, error=shift.error)  
    
    #
    #
    # Accumulate data from CCPN data model & GUI
    #
    #

    # Sequence

    residues = self.chain.sortedResidues()
    residueDict = {}
    
    seqData = []
    for residue in residues:
      molResidue = residue.molResidue
      
      code1Letter = molResidue.chemComp.code1Letter
      
      if not code1Letter:
        msg = 'Encountered non-standard residue type: %s'
        showWarning('Cannot run MECCANO', msg % residue.ccpCode)
        return
     
      seqCode = residue.seqCode
      seqData.append((seqCode, code1Letter))
      residueDict[seqCode] = residue.chemCompVar.chemComp.code3Letter

    # Media, RDCs & Dihedrals

    rdcLists = []
    dihedralLists = []

    for constraintList in constraintLists:
      if constraintList.className == 'RdcConsraintList':
        if constraintList.conditionState:
          rdcLists.append(constraintList)
      
      elif constraintList.className == 'DihedralConstraintList':
        dihedralLists.append(dihedralLists)
    
    f = PI_OVER_180  
    mediaData = []
    for constraintList in rdcLists:
      medium = constraintList.conditionState
      dynamicTensor = medium.dynamicAlignment
      staticTensor = medium.staticAlignment
    
      if not (dynamicTensor or staticTensor):
        continue
    
      if dynamicTensor:
        dynamicTensorData = ['Dynamic', dynamicTensor.aAxial, dynamicTensor.aRhombic,
                             f*dynamicTensor.alpha, f*dynamicTensor.beta, f*dynamicTensor.gamma]
   
      if staticTensor:
        staticTensorData = ['Static', staticTensor.aAxial, staticTensor.aRhombic,
                            f*staticTensor.alpha, f*staticTensor.beta, f*staticTensor.gamma]
      
      if not dynamicTensor:
        dynamicTensorData = staticTensorData
      
      elif not staticTensor:
        staticTensorData = dynamicTensorData
      
      rdcData = []
      for restraint in constraintList.constraints:
        items = list(restraint.items)
        
        if len(items) != 1:
          continue
          
        resonanceA, resonanceB = [fr.resonance for fr in items[0].resonances] 
        
        resonanceSetA = resonanceA.resonanceSet
        if not resonanceSetA:
          continue
        
        resonanceSetB = resonanceB.resonanceSet
        if not resonanceSetB:
          continue
        
        resNameA = getResonanceName(resonanceA)
        resNameB = getResonanceName(resonanceB)
          
        residueA = resonanceSetA.findFirstAtomSet().findFirstAtom().residue  
        residueB = resonanceSetB.findFirstAtomSet().findFirstAtom().residue  
        
        seqA = residueA.seqCode
        seqB = residueB.seqCode
        
        value = restraint.targetValue
        error = restraint.error
        
        if error is None:
          key = [resNameA,resNameB]
          key.sort()
          sigma = DEFAULT_ERRORS.get(tuple(key), 1.0)
        
        rdcData.append([seqA, resNameA, seqB, resNameB, value, error])
      
      mediaData.append((dynamicTensorData,staticTensorData,rdcData))
      
    oneTurn = 360.0
    dihedralDict = {}
    for constraintList in dihedralLists:
      for restraint in constraintList.constraints:
        items = list(restraint.items)
        
        if len(items) != 1:
          continue
        
        item = items[0]
        resonances = [fr.resonance for fr in item.resonances] 
        
        resonanceSets = [r.resonanceSet for r in resonances]
        
        if None in resonanceSets:
          continue
          
        atoms = [rs.findFirstAtomSet().findFirstAtom() for rs in resonanceSets]  
    
        atomNames = [a.name for a in atoms]
        
        if atomNames == PHI_ATOM_NAMES:
          isPhi = True
        elif atomNames == PSI_ATOM_NAMES:
          isPhi = False
        else:
          continue
    
        residue = atoms[2].residue
        
        if residue.chain is not self.chain:
          continue
        
        if isPhi:
          residuePrev = getLinkedResidue(residue, linkCode='prev')
          
          if not residuePrev:
            continue
            
          atomC0 = residuePrev.findFirstAtom(name='C')
          atomN  = residue.findFirstAtom(name='N')
          atomCa = residue.findFirstAtom(name='CA')
          atomC  = residue.findFirstAtom(name='C')
          atoms2 = [atomC0, atomN, atomCa, atomC]
          
        else:
          residueNext = getLinkedResidue(residue, linkCode='next')
          
          if not residueNext:
            continue
          
          atomN  = residue.findFirstAtom(name='N')
          atomCa = residue.findFirstAtom(name='CA')
          atomC  = residue.findFirstAtom(name='C')
          atomN2 = residueNext.findFirstAtom(name='N')
          atoms2 = [atomN, atomCa, atomC, atomN2]
          
        if atoms != atoms2:
          continue
        
        value = item.targetValue
        error = item.error
        
        if error is None:
          upper = item.upperLimit
          lower = item.lowerLimit
          
          if (upper is not None) and (lower is not None):
            dUpper = angleDifference(value, lower, oneTurn)
            dLower = angleDifference(upper, value, oneTurn)
            error  = max(dUpper, dLower)
            
          elif lower is not None:
            error = angleDifference(value, lower, oneTurn)
            
          elif upper is not None:
            error = angleDifference(upper, value, oneTurn)
            
          else:
            error = 30.0 # Arbitrary, but sensible for TALOS, DANGLE
        
        seqCode = residue.seqCode
        if not dihedralDict.has_key(seqCode):
          dihedralDict[seqCode] = [None, None, None, None] # Phi, Psi, PhiErr, PsiErr
        
        if isPhi:
          dihedralDict[seqCode][0] = value
          dihedralDict[seqCode][2] = error
        else:
          dihedralDict[seqCode][1] = value
          dihedralDict[seqCode][3] = error
          
          
    phipsiData = []
    seqCodes = dihedralDict.keys()
    seqCodes.sort()
    
    for seqCode in seqCodes:
      data = dihedralDict[seqCode]
      
      if None not in data:
        phi, psi, phiErr, psiErr = data
        phipsiData.append((seqCode, phi, psi, phiErr, psiErr))
        
    
    # User options
    
    firstPPlaneFrag = self.firstResEntry.get() or 1
    lastPPlaneFrag  = self.lastResEntry.get() or 1
    ppNbMin         = self.numOptPlaneEntry.get() or 1
    minValueBest    = self.numOptHitsEntry.get() or 2
    maxValueBest    = self.maxOptStepEntry.get() or 5

    strucData = Meccano.runFwd(firstPPlaneFrag, lastPPlaneFrag, ppNbMin,
                               minValueBest, maxValueBest, RAMACHANDRAN_DATABASE,
                               seqData, mediaData, phipsiData)
   
    if strucData:
      fileName = 'CcpnMeccanoPdb%f.pdb' % time.time()
      fileObj = open(fileName, 'w')
 
      ch = self.chain.pdbOneLetterCode.strip()
      if not ch:
        ch = self.chain.code[0].upper()
 
        i = 1
        for atomType, resNb, x, y, z in strucData:
          resType = residueDict.get(resNb, '???')
          line = PDB_FORMAT % ('ATOM',i,'%-3s' % atomType,'',resType,ch,resNb,'',x,y,z,1.0,1.0)
 
          i += 1

      fileObj.close()
      
      ensemble = getStructureFromFile(self.molSystem, fileName)
      
      
      if not self.toggleWritePdbFile.get():
        os.unlink(fileName)
         
      self.run.outputEnsemble = ensemble
      self.run = None
    
    self.updateRuns()

  def getMediumName(self, alignMedium):
  
    self.mediumNameEntry.set(alignMedium.name)
    
  def getMediumDetails(self, alignMedium):
  
    self.mediumDetailsEntry.set(alignMedium.details)
    
  def setMediumName(self, event): 

    value = self.mediumNameEntry.get()
    self.alignMedium.name = value or None
    
  def setMediumDetails(self, event): 

    value = self.mediumDetailsEntry.get()
    self.alignMedium.details = value or None
      
  def setAlignMedium(self, alignMedium):

    if self.constraintSet:
      self.constraintSet.conditionState = alignMedium
    
  def getAlignMedium(self, constraintList):

    media = self.getAlignmentMedia()
    names = [am.name for am in media]
    
    if constraintList.conditionState in media:
      index = media.index(constraintList.conditionState)
    else:
      index = 0
  
    self.alignMediumPulldown.setup(names, media, index)

  def toggleUseRestraints(self, constraintList):
 
    bool = constraintList.useForMeccano
    bool = not bool
 
    if bool and (not constraintList.conditionState) \
     and (constraintList.className == 'RdcConsraintList'):
      msg = 'Cannot use RDC restraint list for Meccano '
      msg += 'unless it is first associated with an amigment medium'
      showWarning('Warning', msg, parent=self)
    else:
      constraintList.useForMeccano = bool
      
    self.updateConstraintLists()
 
  def addStaticTensor(self):
  
    if self.alignMedium:
      tensor = Implementation.SymmTracelessMatrix(aAxial=0.0,aRhombic=0.0,
                                                  alpha=0.0,beta=0.0,
                                                  gamma=0.0)
      

      self.alignMedium.staticAlignment = tensor
 
      self.updateAlignMediaAfter(self.alignMedium)
 
  def addDynamicTensor(self):
  
    if self.alignMedium:
      tensor = Implementation.SymmTracelessMatrix(aAxial=0.0,aRhombic=0.0,
                                                  alpha=0.0,beta=0.0,
                                                  gamma=0.0)
      self.alignMedium.dynamicAlignment = tensor
      
      self.updateAlignMediaAfter(self.alignMedium)
  
  def removeTensor(self):
  
    if self.alignMedium and self.tensor:
      if self.tensor is self.alignMedium.dynamicAlignment:
        self.alignMedium.dynamicAlignment = None
        
      elif self.tensor is self.alignMedium.staticAlignment:
        self.alignMedium.staticAlignment = None
      
      self.updateAlignMediaAfter(self.alignMedium)
        
  def addAlignMedium(self):
  
    if self.constraintSet:
      medium = self.constraintSet.newConditionState()
      medium.name = 'Align Medium %d' % medium.serial   
  
  def removeAlignMedium(self):

    if self.alignMedium:
      self.alignMedium.delete()

  def updateTensor(self, aAxial=None, aRhombic=None, alpha=None, beta=None, gamma=None):
  
    aAxial   = aAxial   or self.tensor.aAxial
    aRhombic = aRhombic or self.tensor.aRhombic
    alpha    = alpha    or self.tensor.alpha
    beta     = beta     or self.tensor.beta
    gamma    = gamma    or self.tensor.gamma
    
    tensor = Implementation.SymmTracelessMatrix(aAxial=aAxial,
                                                aRhombic=aRhombic,
                                                alpha=alpha,beta=beta,
                                                gamma=gamma)
 
    if self.alignMedium:
      if self.tensor is self.alignMedium.dynamicAlignment:
        self.alignMedium.dynamicAlignment = tensor
        
      elif self.tensor is self.alignMedium.staticAlignment:
        self.alignMedium.staticAlignment = tensor
 
    self.tensor = tensor
 
  def setAxial(self, event): 
  
    value = self.editAxialEntry.get()
    self.updateTensor(aAxial=value)
    self.updateTensors()
    
  def setRhombic(self,  event): 
  
    value = self.editRhombicEntry.get()
    self.updateTensor(aRhombic=value)
    self.updateTensors()
   
  def setEulerAlpha(self,  event): 
  
    value = self.editAlphaEulerEntry.get()
    self.updateTensor(alpha=value)
    self.updateTensors()
    
  def setEulerBeta(self,  event): 
  
    value = self.editBetaEulerEntry.get()
    self.updateTensor(beta=value)
    self.updateTensors()
    
  def setEulerGamma(self,  event): 
  
    value = self.editGammaEulerEntry.get()
    self.updateTensor(gamma=value)
    self.updateTensors()

  def getAxial(self, tensor): 
  
    value = tensor.aAxial
    self.editAxialEntry.set(value)
     
  def getRhombic(self, tensor): 
  
    value = tensor.aRhombic
    self.editRhombicEntry.set(value)
     
  def getEulerAlpha(self, tensor): 
  
    value = tensor.alpha
    self.editAlphaEulerEntry.set(value)
     
  def getEulerBeta(self, tensor): 
  
    value = tensor.beta
    self.editBetaEulerEntry.set(value)
     
  def getEulerGamma(self, tensor): 
  
    value = tensor.gamma
    self.editGammaEulerEntry.set(value)
 
  def selectTensor(self, tensor, row, col):
  
    self.tensor = tensor
 
  def selectAlignMedium(self, alignMedium, row, col):
  
    self.alignMedium = alignMedium
    self.updateTensors()
 
  def getAlignmentMedia(self):
  
    if self.constraintSet:
      return self.constraintSet.sortedConditionStates()
    else:
      return []
 
  def updateAlignMedia(self):

    textMatrix = []
    objectList = []
    
    if self.constraintSet:
      objectList = self.getAlignmentMedia()
        
      for conditionState in objectList:
         
         staticTensor = None
         dyamicTensor = None
         tensor = conditionState.dynamicAlignment
         if tensor:
           vals = (tensor.aAxial, tensor.aRhombic, tensor.alpha, tensor.beta, tensor.gamma)
           dyamicTensor = u'\u03B6:%.3f \u03B7:%.3f \u03B1:%.3f \u03B2:%.3f \u03B3:%.3f ' % vals

         tensor = conditionState.staticAlignment
         if tensor:
           vals = (tensor.aAxial, tensor.aRhombic, tensor.alpha, tensor.beta, tensor.gamma)
           staticTensor = u'\u03B6:%.3f \u03B7:%.3f \u03B1:%.3f \u03B2:%.3f \u03B3:%.3f ' % vals
           
         datum = [conditionState.serial,
                  conditionState.name,
                  conditionState.details,
                  dyamicTensor,
                  staticTensor]
         textMatrix.append(datum)

         if dyamicTensor or staticTensor:
           if not self.alignMedium:
             self.alignMedium = conditionState
   
    self.mediaMatrix.update(textMatrix=textMatrix, objectList=objectList)
      
    if self.alignMedium:
      self.mediaMatrix.selectObject(self.alignMedium)
 
  def updateTensors(self):
    
    textMatrix = []
    objectList = []
    conditionState = self.alignMedium
    
    if conditionState:
    
      tensor = conditionState.dynamicAlignment
      if tensor:
        datum = ['Dynamic', tensor.aAxial, tensor.aRhombic,
                 tensor.alpha, tensor.beta, tensor.gamma]
        textMatrix.append(datum)
        objectList.append(tensor)
      
      tensor = conditionState.staticAlignment
      if tensor:
        datum = ['Static', tensor.aAxial, tensor.aRhombic,
                 tensor.alpha, tensor.beta, tensor.gamma]
        textMatrix.append(datum)
        objectList.append(tensor)

    self.tensorMatrix.update(textMatrix=textMatrix, objectList=objectList)  
 
  def getMolSystems(self):
  
    molSystems = []
    
    for molSystem in self.project.sortedMolSystems():
      if molSystem.chains:
        molSystems.append(molSystem)
        
    return molSystems    
     
     
  def updateMolSystems(self, *notifyObj):
  
    index = 0
    names = []
    
    molSystems = self.getMolSystems()
    molSystem = self.molSystem
    
    if molSystems:
      if molSystem not in molSystems:
        molSystem = molSystems[0]
      
      index = molSystems.index(molSystem)
      names = [ms.code for ms in molSystems] 
    
    else:
      self.molSystem = None
    
    if self.molSystem is not molSystem:
      if self.run:
        self.run.molSystem = molSystem
        
      self.molSystem = molSystem
      self.updateChains()
    
    self.molSystemPulldown.setup(texts=names, objects=molSystems, index=index)
    
  
  def selectMolSystem(self, molSystem):
  
    if self.molSystem is not molSystem:
      if self.run:
        self.run.molSystem = molSystem
        
      self.molSystem = molSystem
      self.updateChains()
     
     
  def updateChains(self, *notifyObj):
  
    index = 0
    names = []
    chains = []
    chain = self.chain
    
    if self.molSystem:
      chains = [c for c in self.molSystem.sortedChains() if c.residues]
    
    if chains: 
      if chain not in chains:
        chain = chains[0]
        
      index = chains.index(chain)
      names = [c.code for c in chains]
    
    if chain is not self.chain:
      self.chain = chain
      self.updateResidueRanges()
    
    self.chainPulldown.setup(texts=names, objects=chains, index=index)
     
  def selectChain(self, chain):
  
    if chain is not self.chain:
      self.chain = chain
      self.updateResidueRanges()

  def updateResidueRanges(self):
  
    first = self.firstResEntry.get()
    last = self.lastResEntry.get()
    
    if self.chain:
      residues = self.chain.sortedResidues()
      firstSeq = residues[0].seqCode
      lastSeq = residues[-2].seqCode
      
      if first < firstSeq:
        first = firstSeq
     
      if last == first:
        last = lastSeq
      
      elif last > lastSeq:
        last = lastSeq
        
      if first > last:
        last, first = first, last    
      
  
    self.firstResEntry.set(first)
    self.lastResEntry.set(last)
 
    return first, last

  def getConstraintSets(self):
  
    constraintSets = []
    nmrProject = self.project.currentNmrProject
    
    for constraintSet in nmrProject.sortedNmrConstraintStores():
      for constraintList in constraintSet.constraintLists:
        if constraintList.className not in ('ChemShiftConstraintList','somethingElse'):
          constraintSets.append(constraintSet)
          break
    
    return constraintSets
  
  def updateConstraintSets(self, *notifyObj):

    index = 0
    names = []
    constraintSets = self.getConstraintSets()
    constraintSet = self.constraintSet

    if constraintSets:
      if constraintSet not in constraintSets:
        constraintSet = constraintSets[0]
        
      index = constraintSets.index(constraintSet)
      names = ['%d' % cs.serial for cs in constraintSets]
    
    if constraintSet is not self.constraintSet:
      if self.run:
        self.run.inputConstraintStore = constraintSet
    
      self.constraintSet = constraintSet
      self.updateConstraintLists()    
    
    self.constraintSetPulldown.setup(texts=names, objects=constraintSets, index=index)

  def selectConstraintSet(self, constraintSet):
  
    if self.constraintSet is not constraintSet:
      if self.run:
        self.run.inputConstraintStore = constraintSet
        
      self.constraintSet = constraintSet
      self.updateConstraintLists() 
  
  def getConstraintLists(self):
  
    constraintLists = []
    if self.constraintSet:
      for constraintList in self.constraintSet.sortedConstraintLists():
        if constraintList.className not in ('ChemShiftConstraintList','somethingElse'):
          constraintLists.append(constraintList)
  
    return constraintLists
    
  def updateConstraintLists(self, *notifyObj):
  
    textMatrix = []
    objectList = self.getConstraintLists()
    
    for constraintList in objectList:
      if not hasattr(constraintList, 'useForMeccano'):
        if constraintList.conditionState \
         or (constraintList.className != 'RdcConstraintList'):
          bool = True
        else:
          bool = False  
      
        constraintList.useForMeccano = bool
    
      if constraintList.conditionState:
        alignMedium = constraintList.conditionState.name
      else:
        alignMedium = None
    
      datum = [constraintList.serial,
               constraintList.className[:-14],
               constraintList.useForMeccano and 'Yes' or 'No',
               alignMedium,
               len(constraintList.constraints)]
  
      textMatrix.append(datum)
  
    self.restraintMatrix.update(textMatrix=textMatrix, objectList=objectList)
  
  def selectConstraint(self, obj, row, column):
  
    if self.constraint is not obj:
      self.constraint = obj

  def getSimStore(self):
  
    simStore = self.project.findFirstNmrSimStore(name='meccano')
    if not simStore:
      simStore = self.project.newNmrSimStore(name='meccano')
    
    return simStore

  def getRuns(self):
  
    runs = [None, ]
    
    if self.molSystem and self.constraintSet:
      simStore = self.getSimStore()
      runs += simStore.sortedRuns()
    
    return runs
  
  def updateRuns(self, *notifyObj):
  
    index = 0
    names = ['<New>']
    runs = self.getRuns()
    run = self.run

    if runs:
      if run not in runs:
        run = runs[0]
    
      index = runs.index(run)
      names += [r.serial for r in runs if r]
    
    if run is not self.run:
      self.updateConstraintSets()
      self.updateMolSystems()
      self.updateShiftLists()
    
    self.runPulldown.setup(names, runs, index)
  
  def updateRunParams(self, event=None):
  
    if self.run and self.molSystem and self.constraintSet:
      simRun = self.run
      
      simRun.inputConstraintStore = self.constraintSet
      simRun.molSystem = self.molSystem
      
      if self.shiftList:
        simRun.setInputMeasurementLists([self.shiftList,])                 

      simRun.newRunParameter(code='FirstPepPlane',id=1, 
                             intValue=self.firstResEntry.get() or 0)
      simRun.newRunParameter(code='LastPepPlane' ,id=1, 
                             intValue=self.lastResEntry.get() or 0)
      simRun.newRunParameter(code='MaxOptSteps',  id=1, 
                             intValue=self.maxOptStepEntry.get() or 0)
      simRun.newRunParameter(code='NumOptPlanes', id=1, 
                             intValue=self.numOptPlaneEntry.get() or 0)
      simRun.newRunParameter(code='MinOptHits',   id=1, 
                             intValue=self.numOptHitsEntry.get() or 0)
  
  def makeSimRun(self, template=None):

    simStore = self.getSimStore()
   
    if template:
      molSystem = template.molSystem
      constraintSet = template.inputConstraintStore
      shiftList = template.findFirstInputMeasurementList(className='ShiftList')
      protocol = template.annealProtocol
    else:
      molSystem = self.molSystem
      constraintSet = self.constraintSet
      shiftList = self.shiftList
      protocol = self.annealProtocol
    
    simRun = simStore.newRun(annealProtocol=protocol,
                             molSystem=molSystem,
                             inputConstraintStore=protocol)
    
    if shiftList:
      simRun.addInputMeasurementList(shiftList)                 
    
    if template:
      for param in template.runParameters:
        simRun.newRunParameter(code=param.code,
                               id=param.id,
                               booleanValue=param.booleanValue,
                               floatValue=param.floatValue,
                               intValue=param.intValue,
                               textValue=param.textValue)
    else:
       if self.chain:
         chainCode = self.chain.code
       else:
         chaincode = 'A'
    
       simRun.newRunParameter(code='FirstPepPlane',id=1, 
                              intValue=self.firstResEntry.get() or 0)
       simRun.newRunParameter(code='LastPepPlane' ,id=1, 
                              intValue=self.lastResEntry.get() or 0)
       simRun.newRunParameter(code='MaxOptSteps',  id=1, 
                              intValue=self.maxOptStepEntry.get() or 0)
       simRun.newRunParameter(code='NumOptPlanes', id=1, 
                              intValue=self.numOptPlaneEntry.get() or 0)
       simRun.newRunParameter(code='MinOptHits',   id=1, 
                              intValue=self.numOptHitsEntry.get() or 0)
       simRun.newRunParameter(code='ChainCode',    id=1,
                              textValue=chainCode)

    return simRun
 
  def selectRun(self, simRun):
  
    if self.run is not simRun:
      if simRun:
        if simRun.outputEnsemble:
          msg  = 'Selected run has already been used to generate a structure.'
          msg += 'A new run will be setup based on the selection.'
          showWarning('Warning',msg)
          simRun = self.makeSimRun(template=simRun)
 
        molSystem = simRun.molSystem
        constraintSet = simRun.inputConstraintStore
        shiftList = simRun.findFirstInputMeasurementList(className='ShiftList')
 
        if molSystem and (self.molSystem is not molSystem):
          self.molSystem = molSystem
          self.updateMolSystems()
 
        if constraintSet and (self.constraintSet is not constraintSet):
          self.constraintSet = constraintSet
          self.updateConstraintSets()
    
        if shiftList and (self.shiftList is not shiftList): 
          self.shiftList = shiftList
          self.updateShiftLists()
        
        firstPepPlane = simRun.findFirstrunParameter(code='FirstPepPlane')
        lastPepPlane = simRun.findFirstrunParameter(code='LastPepPlane')
        maxOptSteps = simRun.findFirstrunParameter(code='MaxOptSteps')
        numOptPlanes = simRun.findFirstrunParameter(code='NumOptPlanes')
        minOptHits = simRun.findFirstrunParameter(code='MinOptHits')
        chainCode = simRun.findFirstrunParameter(code='ChainCode')

        
        if firstPepPlane is not None:
          self.firstResEntry.set(firstPepPlane.intValue or 0)
        
        if lastPepPlane is not None:
          self.lastResEntry.set(lastPepPlane.intValue or 0)
          
        if maxOptSteps is not None:
          self.maxOptStepEntry.set(maxOptSteps.intValue or 0)
            
        if numOptPlanes is not None:
          self.numOptPlaneEntry.set(numOptPlanes.intValue or 0)
          
        if minOptHits is not None:
          self.numOptHitsEntry.set(minOptHits.intValue or 0)
           
        if chainCode is not None:
          chainCode = chainCode.textValue or 'A'
          if self.molSystem:
            chain = self.molSystem.findFirsChain(code=chainCode)
 
            if chain:
              self.selectChain(chain) 
                 
      self.run = simRun

  def updateShiftLists(self, *notifyObj):
    
    index = 0
    names = []
    nmrProject = self.project.currentNmrProject
    
    shiftLists = nmrProject.findAllMeasurementLists(className='ShiftList')
    shiftLists = [(sl.serial, sl) for sl in shiftLists]
    shiftLists.sort()
    shiftLists = [x[1] for x in shiftLists]
    
    shiftList = self.shiftList

    if shiftLists:
      if shiftList not in shiftLists:
        shiftList = shiftLists[0]
    
      index = shiftLists.index(shiftList)
      names = ['%d'% sl.serial for sl in shiftLists]
    
    if shiftList is not self.shiftList:
      if self.run:
        self.run.setInputMeasurementLists([shiftList])
  
    self.shiftListPulldown.setup(texts=names, objects=shiftLists, index=index)

  def selectShiftList(self, shiftList):
  
    if shiftList is not self.shiftList:
      if self.run:
        self.run.setInputMeasurementLists([shiftList])
      
      self.shiftList = shiftList                   
Beispiel #3
0
class PeakSeparatorGui(BasePopup):
    """
  **Separate Merged Peaks Using Peak Models**

  The Peak Separator code uses a Markov Chain Monte Carlo search which, using
  idealised peak shapes, attempts to deconvolve overlapped peak regions into 
  their separate constituent peaks.
  
  This routine is also suitable for accurately fitting model shapes to single
  peaks in order to calculate precise intensities.
  
  **Options Peak Separator Parameters**
  *Min. Number of peaks* is by default set to one, it is not possible to set 
  this to a value less than one.
  *Max. Number of peaks* is by default set to one, increasing this value allows
  the search routine to fit more models. The best fit may be found with fewer than
  the maximum number models. Higher numbers slow the routine, and setting this
  value to 0 allows the routine to (effectively) fit unlimited peaks.
  *Only pick positive peaks*. If you are not interested in negative peaks, removing
  the possibility of fitting negative peaks can reduce search time.
  *Peak Model* fits the spectra with either a Gaussian peak model or a Lorentzian
  peak model.

  **Options Region**
  *Peak List* choose which peak list newly picked peaks should be added to. Peaks
  picked using this method will have their details appended with 'PeakSepartor' 
  so you know where they came from.
  *Region Table* shows which area of the current spectrum is about to be searched.
  *Add Region*. Once an area of spectra has been highlighted clicking this button
  will pass it's details on to the Peak Separator.
  *Reset All* will reset all search parameters.
  *Separate Peaks* will run the Peak Separator code with your current settings. This
  may take a few minutes to run, depending on the size of the spectral region being
  searched, the number of peaks being fitted and the speed of your machine. Please
  wait while this completes.
  
  After a successful Peak Separation run, the found peaks will be added to the 
  selected peak list. These peaks intensties (volume) have been found using the
  peak model selected.

  **Advanced Settings Tab**
  *Rate* affects the speed of the Markov Chain Monte Carlo routine. A smaller value
  results in longer execution, but possibly higher quality results. The default 
  setting is deemed sensible for the majority of runs.
  *Line Width* offers a finer degree of control over maximum and minimum peak widths
  for each dimension. The default values are *very* stupid and could do with 
  re-checking for each experiment.
  *Re-Pick Entire Peak List* if you would like to use the Peak Separator to repick
  *every* peak in your peak list, try this option - but note that this may take
  a very long time!

  """
    def __init__(self, parent, programName='Peak Separator', **kw):

        self.parent = parent
        self.programName = programName
        self.versionInfo = 'Version 0.2'
        self.help_url = 'http://www.ccpn.ac.uk/'

        self.window = None
        self.waiting = False
        self.rootWindow = None

        # just used for display - PeakSeparator will not see this
        self._minSigmaHz = None
        self._maxSigmaHz = None

        self.customSigma = False
        self.rePickPeakList = False

        self._sampleStartPpm = None
        self._sampleEndPpm = None

        try:
            self.project = parent.project
        except:
            pass

        self.params = PeakSeparatorParams()

        BasePopup.__init__(self,
                           parent=parent,
                           title=programName,
                           location='+100+100',
                           **kw)

        if not self.analysisProject:
            print '&&& init: No analysis project found ...'
        try:
            if parent.argumentServer:
                self.argServer = parent.argumentServer
            else:
                print '&&& init: No argument server found...'
        except:
            print '&&& init: Test'

    ###########################################################################

    def body(self, guiFrame):

        self.geometry('450x500')

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

        options = ['Peak Separator', 'Advanced Settings']

        tabbedFrame = TabbedFrame(guiFrame, options=options)
        tabbedFrame.grid(row=0, column=0, sticky='nsew')

        buttons = UtilityButtonList(tabbedFrame.sideFrame,
                                    helpUrl=self.help_url)
        buttons.grid(row=0, column=0, sticky='e')

        self.tabbedFrame = tabbedFrame
        frameA, frameB = tabbedFrame.frames

        #
        # FrameA : Main Settings
        #

        frameA.grid_columnconfigure(1, weight=1)
        row = 0  # Label row

        row += 1
        div = LabelDivider(frameA, text='Peak Separator Parameters')
        div.grid(row=row, column=0, columnspan=2, sticky='ew')

        row += 1
        label = Label(frameA, text='Min. number of peaks:')
        label.grid(row=row, column=0, sticky='w')
        self.minPeaksEntry = IntEntry(frameA, returnCallback=self.applyChange, width=10, \
              tipText='Minimum number of peaks to find (must be > 0)')
        self.minPeaksEntry.grid(row=row, column=1, sticky='n')
        self.minPeaksEntry.bind('<Leave>', self.applyChange, '+')

        row += 1
        label = Label(frameA, text='Max. number of peaks:')
        label.grid(row=row, column=0, sticky='w')
        self.maxPeaksEntry = IntEntry(frameA, returnCallback=self.applyChange, width=10, \
              tipText='Maximum number of peaks to find (0 is unlimited - not recommended)')
        self.maxPeaksEntry.grid(row=row, column=1, sticky='n')
        self.maxPeaksEntry.bind('<Leave>', self.applyChange, '+')

        row += 1
        label = Label(frameA, text='Only pick positive peaks:')
        label.grid(row=row, column=0, sticky='w')
        entries = ['False', 'True']
        self.posPeaksButtons = RadioButtons(
            frameA,
            entries=entries,
            select_callback=self.applyChange,
            direction='horizontal',
            tipTexts=[
                'Search for both positive and negative intensity peaks',
                'Limit search to only positive peaks'
            ])
        self.posPeaksButtons.grid(row=row, column=1, sticky='n')

        row += 1
        label = Label(frameA, text='Peak Model:')
        label.grid(row=row, column=0, sticky='w')
        ### G/L Mixture works, but volume calculation involves Gamma function
        # entries = ['Gaussian', 'Lorentzian', 'G/L Mixture']
        entries = ['Gaussian', 'Lorentzian']
        self.shapeButtons = RadioButtons(
            frameA,
            entries=entries,
            select_callback=self.applyChange,
            direction='horizontal',
            tipTexts=[
                'Choose a Gaussian model peak shape to fit to peaks',
                'Choose a Lorentzian model peak shape to fit to peaks'
            ])
        self.shapeButtons.grid(row=row, column=1, sticky='n')

        row += 1
        div = LabelDivider(frameA,
                           text='Region',
                           tipText='Region that search will limit itself to')
        div.grid(row=row, column=0, columnspan=2, sticky='ew')

        row += 1
        label = Label(frameA, text='Peak List:')
        label.grid(row=row, column=0, sticky='nw')
        self.peakListPulldown = PulldownList(
            frameA,
            callback=self.setManuallyPickPeakList,
            tipText='Select which peak list new peaks are to be added to')
        self.peakListPulldown.grid(row=row, column=1, sticky='nw')

        # tricky scrolled matrix
        row += 1
        self.regionTable = None
        frameA.grid_rowconfigure(row, weight=1)
        headings = ('dim.', 'start (ppm)', 'end (ppm)', 'actual size')

        self.editDimEntry = IntEntry(self,
                                     returnCallback=self.applyChange,
                                     width=5,
                                     tipText='Dimension number')
        self.editStartEntry = FloatEntry(self,
                                         returnCallback=self.applyChange,
                                         width=5,
                                         tipText='Search area lower bound')
        self.editEndEntry = FloatEntry(self,
                                       returnCallback=self.applyChange,
                                       width=5,
                                       tipText='Search area upper bound')

        editWidgets = [
            self.editDimEntry, self.editStartEntry, self.editEndEntry, None
        ]

        editGetCallbacks = [None, None, None, None]
        editSetCallbacks = [None, None, None, None]

        self.regionTable = ScrolledMatrix(frameA,
                                          headingList=headings,
                                          multiSelect=False,
                                          editWidgets=editWidgets,
                                          editGetCallbacks=editGetCallbacks,
                                          editSetCallbacks=editSetCallbacks,
                                          initialRows=5)

        self.regionTable.grid(row=row, column=0, columnspan=2, sticky='nsew')

        # Run Button
        row += 1
        texts = ['Add Region']
        commands = [self.updateFromRegion]
        self.addResetButtons = ButtonList(
            frameA,
            texts=texts,
            commands=commands,
            tipTexts=['Add selected specrtral region'])
        self.addResetButtons.grid(row=row, column=0, columnspan=2, sticky='ew')

        row += 1
        texts = ['Separate Peaks']
        commands = [self.runPeakSeparator]
        self.runButton = ButtonList(frameA,
                                    texts=texts,
                                    commands=commands,
                                    expands=True,
                                    tipTexts=['Run peak search now'])
        self.runButton.grid(row=row, column=0, columnspan=2, sticky='nsew')

        #
        # FrameB : Further Settings
        #

        frameB.grid_columnconfigure(0, weight=1)

        row = 0

        div = LabelDivider(frameB, text='Rate:')
        div.grid(row=row, column=0, columnspan=2, sticky='ew')
        row += 1

        label = Label(frameB, text='Rate of MCMC step size change')
        label.grid(row=row, column=0, columnspan=1, sticky='w')

        self.rateEntry = FloatEntry(frameB, returnCallback=self.applyChange, width=10, \
              tipText='Rate effects speed of run, smaller values take longer but may produce better results')
        self.rateEntry.grid(row=row, column=1, sticky='n')
        self.rateEntry.bind('<Leave>', self.applyChange, '+')
        self.rateEntry.set(self.params.rate)

        # tricky scrolled matrix for line width
        row += 2
        div = LabelDivider(frameB, text='Line Width (Hz):')
        div.grid(row=row, column=0, columnspan=2, sticky='ew')

        row += 1
        label = Label(frameB, text="Descr.")
        label.grid(row=row, rowspan=2, column=0, sticky='w')

        row += 1
        self.lineWidthTable = None
        frameB.grid_rowconfigure(row, weight=1)
        lineWidthHeadings = ('dim.', 'min. σ (Hz)', 'max. σ (Hz)')

        self.editMinSigmaEntry = FloatEntry(self,
                                            returnCallback=self.applyChange,
                                            width=5,
                                            tipText='Minimum line width (Hz)')
        self.editMaxSigmaEntry = FloatEntry(self,
                                            returnCallback=self.applyChange,
                                            width=5,
                                            tipText='Maximum line width (Hz)')

        # self.editDimEntry is also from regionTable
        initialWidthRows = 4

        editLineWidthWidgets = [
            None, self.editMinSigmaEntry, self.editMaxSigmaEntry
        ]
        editLineWidthGetCallbacks = [None, self.getSigmaMin, self.getSigmaMax]
        editLineWidthSetCallbacks = [None, self.setSigmaMin, self.setSigmaMax]

        self.lineWidthTable = ScrolledMatrix(
            frameB,
            headingList=lineWidthHeadings,
            multiSelect=False,
            editWidgets=editLineWidthWidgets,
            editGetCallbacks=editLineWidthGetCallbacks,
            editSetCallbacks=editLineWidthSetCallbacks,
            initialRows=initialWidthRows)

        self.lineWidthTable.grid(row=row,
                                 column=0,
                                 columnspan=2,
                                 sticky='nsew')

        # option to 'repick' exisiting peak list
        row += initialWidthRows
        div = LabelDivider(frameB, text='(optional - repick entire peak list)')
        div.grid(row=row, column=0, columnspan=2, sticky='ew')
        row += 1

        self.repickListPulldown = PulldownList(
            frameB,
            callback=self.setRePickPeakList,
            tipText=
            'Select which peak list to repick (new peaks will be put into a new peak list)'
        )
        self.repickListPulldown.grid(row=row, column=0, sticky='nw')

        texts = ['Repick Peak List']
        commands = [self.runRepickPeaks]
        self.runButton = ButtonList(
            frameB,
            texts=texts,
            commands=commands,
            expands=True,
            tipTexts=['Repick selected peak list into a new peak list.'])
        self.runButton.grid(row=row, column=1, columnspan=1, sticky='nsew')

        row += 1
        div = LabelDivider(frameB)
        row += 1
        texts = ['Separate Peaks']
        commands = [self.runPeakSeparator]
        self.runButton = ButtonList(frameB,
                                    texts=texts,
                                    commands=commands,
                                    expands=True,
                                    tipTexts=['Run peak search now'])
        self.runButton.grid(row=row, column=0, columnspan=2, sticky='nsew')

        self.setWidgetEntries()

        self.administerNotifiers(self.registerNotify)

    def administerNotifiers(self, notifyFunc):

        for func in ('__init__', 'delete'):
            notifyFunc(self.updateAfter, 'ccp.nmr.Nmr.PeakList', func)

        notifyFunc(self.updateAfter, 'ccp.nmr.Nmr.Experiment', 'setName')
        notifyFunc(self.updateAfter, 'ccp.nmr.Nmr.DataSource', 'setName')

    def destroy(self):

        self.administerNotifiers(self.unregisterNotify)
        BasePopup.destroy(self)

    ###########################################################################
    # update parameters from PS Region

    def updateFromRegion(self):

        if not self.params.peakList:
            print '&&& update from region: Need a peak list'
            return

        if (self.argServer.parent.currentRegion) == None:
            showError('No Region',
                      'Please select a peak region to be separated')
            return

        self.rePickPeakList = False

        getRegionParams(self.params, argServer=self.argServer)

        if not self.customSigma: self.initSigmaParams()

        self.setWidgetEntries()

    ###########################################################################
    # update parameters from PS PeakList

    def updateFromPeakList(self):

        if not self.params.peakList:
            print '&&& update from peakList: Need a peak list'
            return

        getPeakListParams(self.params)

        if not self.customSigma: self.initSigmaParams()

        self.setWidgetEntries()

    ###########################################################################
    # Run the C library!

    def runPeakSeparator(self):
        """ run the peak separator """

        # hack for Macs - focus isn't always lost on mouse move
        # so bind event not always called. Shouldn't affect other OS.
        self.applyChange()

        if not self.params.peakList:
            print '&&& Peak list not yet set'
        else:
            # SeparatePeakRoutine(self.params, self.params.peakList, routine='pymc' )
            SeparatePeakRoutine(self.params,
                                self.params.peakList,
                                routine='bayesys')

    def runRepickPeaks(self):
        """ Run the Peak Separator on entire chosen peak list """
        # hack for Macs - focus isn't always lost on mouse move
        # so bind event not always called. Shouldn't affect other OS.
        self.applyChange()

        if not self.params.peakList:
            print '&&& Peak list not yet set'
        else:
            SeparatePeaksInPeakList(self.params)

    ###########################################################################

    def setWidgetEntries(self):

        ### Page One widgets
        self.minPeaksEntry.set(self.params.minAtoms)
        self.maxPeaksEntry.set(self.params.maxAtoms)

        if self.params.positivePeaks == 1:
            self.posPeaksButtons.set('True')  # only pick pos peaks
        else:
            self.posPeaksButtons.set('False')

        # do something fancy if different shapes for each dim!
        n = self.params.peakShape - 3  # shape is only 3, 4, (5)
        self.shapeButtons.setIndex(n)

        if self.project is not None:
            self.updatePeakListList()
        self.updateSpectrumWindow()

        if self.params.sampleStart and self.params.peakList:

            if not self.rePickPeakList:
                objectList = []
                textMatrix = []

                if len(self.params.samplePpmStart) != self.params.Ndim: return

                for i in range(self.params.Ndim):
                    dim_entry = []
                    dim_entry.append('%2d' % (i + 1))
                    dim_entry.append('%7.3f' % self.params.samplePpmStart[i])
                    dim_entry.append('%7.3f' % self.params.samplePpmEnd[i])
                    dim_entry.append('%3d' % self.params.sampleSize[i])
                    textMatrix.append(dim_entry)

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

        ### Page Two widgets
        self.rateEntry.set(self.params.rate)

        if self.params.peakList and self.params.Ndim:

            textMatrix = []
            objectList = []

            for i in range(self.params.Ndim):
                if self.params.isFreqDim[i]:
                    dim_entry = []
                    objectList.append(i)
                    dim_entry.append('%2d' % (i + 1))
                    dim_entry.append('%7.3f' % self._minSigmaHz[i])
                    dim_entry.append('%7.3f' % self._maxSigmaHz[i])
                    textMatrix.append(dim_entry)

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

    def applyChange(self, *event):
        """ Upon change, add settings to params """

        # Page One apply changes
        self.params.minAtoms = self.minPeaksEntry.get()
        self.params.maxAtoms = self.maxPeaksEntry.get()

        if self.posPeaksButtons.get() == 'True':  # asked only pick pos peaks
            self.params.positivePeaks = 1
        else:
            self.params.positivePeaks = 0

        # do something fancy if different shapes for each dim!
        n = self.shapeButtons.getIndex()  # shape is only 3, 4, (5)
        self.params.peakShape = n + 3

        # Page Two apply changes
        self.params.rate = float(self.rateEntry.get())

        self.updateSigmaParams()

    ###########################################################################
    # Peak list functions provide PeakSeparator some inherited params

    def getPeakListList(self):
        """ given a spectrum, get list of peak lists """
        project = self.project

        peakLists = []
        for experiment in self.nmrProject.experiments:
            for spectrum in experiment.dataSources:
                for peakList in spectrum.peakLists:
                    peakLists.append([
                        '%s:%s:%d' %
                        (experiment.name, spectrum.name, peakList.serial),
                        peakList
                    ])
        peakLists.sort()
        return peakLists

    def updatePeakListList(self):
        """ set the peaklist list in the pulldown menu """
        peakListData = self.getPeakListList()

        index = -1
        names = []
        peakList = self.params.peakList

        if peakListData:
            names = [x[0] for x in peakListData]
            peakLists = [x[1] for x in peakListData]

            if peakList not in peakLists:
                peakList = peakLists[0]

            index = peakLists.index(peakList)

        else:
            peakList = None
            peakLists = []

        if peakList is not self.params.peakList:
            self.params.peakList = peakList

        self.peakListPulldown.setup(names, peakLists, index)
        self.repickListPulldown.setup(names, peakLists, index)

    def setRePickPeakList(self, peakList):
        """ Set the peak list to be repicked (and hit a Flag) """
        self.rePickPeakList = True
        self.setPeakList(peakList)

    def setManuallyPickPeakList(self, peakList):
        """ Set the peak list to add new peaks to (and hit a Flag) """
        self.rePickPeakList = False
        self.setPeakList(peakList)

    def setPeakList(self, peakList):
        """ Sets the Peak List """
        if peakList is not self.params.peakList:
            self.params.peakList = peakList
            # # interrogate the peak list and get all the usefull parameters out
            self.updateFromPeakList()
            self.updateSpectrumWindow()
            self.setWidgetEntries()

    ###########################################################################
    # TBD I suspect this is for matching region with peak list, but may be obsolete now

    def getSpectrumWindowList(self):
        """ get list of windows which spectrum could be in """
        windows = {}
        if self.params.peakList:
            views = getSpectrumViews(self.params.peakList.dataSource)
            for view in views:
                windows[view.spectrumWindowPane.spectrumWindow] = None

        return [[w.name, w] for w in windows.keys()]

    def updateSpectrumWindow(self):
        """ update the spectrum window """
        windowData = self.getSpectrumWindowList()

        index = -1
        names = []
        window = self.rootWindow

        if windowData:
            names = [x[0] for x in windowData]
            windows = [x[1] for x in windowData]

            if window not in windows:
                window = windows[0]

            index = windows.index(window)

        else:
            window = None
            windows = []

        if window is not self.rootWindow:
            self.rootWindow = window

    ###########################################################################
    # get and set sigma stuff
    def setSigmaMin(self, dim):

        value = self.editMinSigmaEntry.get()
        self._minSigmaHz[dim] = value

        # dont go and re-write users settings
        self.customSigma = True

        # make sure changes are in params object
        self.updateSigmaParams(dim)
        self.setWidgetEntries()

    def getSigmaMin(self, dim):

        if dim is not None:
            self.editMinSigmaEntry.set(self._minSigmaHz[dim])

    def setSigmaMax(self, dim):

        value = self.editMaxSigmaEntry.get()
        self._maxSigmaHz[dim] = value

        # dont go and re-write users settings
        self.customSigma = True

        # make sure changes are in params object
        self.updateSigmaParams(dim)
        self.setWidgetEntries()

    def getSigmaMax(self, dim):

        if dim is not None:
            self.editMaxSigmaEntry.set(self._maxSigmaHz[dim])

    def updateSigmaParams(self, dim=None):
        """ updateSigmaParams Just updates the parameters (params obj) for sigma values. 
        If dim is None, do this for each dim
    """

        dataDimRefs = self.params.dataDimRefs

        if not dataDimRefs: return

        if not self.params.minSigma or len(
                self.params.minSigma) != self.params.Ndim:
            self.params.minSigma = [0.] * self.params.Ndim

        if not self.params.maxSigma or len(
                self.params.maxSigma) != self.params.Ndim:
            self.params.maxSigma = [0.] * self.params.Ndim

        def updateSigmaParam(dim, dataDimRefs):
            """ Convert and update sigma for dim """

            if self.params.isFreqDim[dim]:
                # note factor of two!
                self.params.minSigma[dim] = self.rHz2pnt(
                    self._minSigmaHz[dim], dataDimRefs[dim]) / 2.
                self.params.maxSigma[dim] = self.rHz2pnt(
                    self._maxSigmaHz[dim], dataDimRefs[dim]) / 2.
            else:
                self.params.minSigma[dim] = 1.0
                self.params.maxSigma[dim] = 1.0

        if dim:
            updateSigmaParam(dim, dataDimRefs)
        else:
            for dim in range(self.params.Ndim):
                updateSigmaParam(dim, dataDimRefs)

    # utility functions for sigma values
    def pnt2rHz(self, point, dataDimRef):
        """ Point to relative Hz frequency relative to frequency at Zeroeth point
        Necessary when (for example) looking for width of peak in Hz
    """
        assert point, dataDimRef

        sigmaBase = pnt2hz(0, dataDimRef)
        sigmaHz = pnt2hz(point, dataDimRef)

        return abs(sigmaHz - sigmaBase)

    def rHz2pnt(self, freq, dataDimRef):
        """ Relative Hz to point frequency relative to frequency at Zeroeth point
        Necessary when (for example) looking for width of peak in Hz
    """
        assert freq, dataDimRef

        sigmaBase = hz2pnt(0, dataDimRef)
        sigmaPoint = hz2pnt(freq, dataDimRef)

        return abs(sigmaPoint - sigmaBase)

    def initSigmaParams(self):
        """ Set some initial default values for sigma """

        self._minSigmaHz = []
        self._maxSigmaHz = []

        if self.params.Ndim:
            for dim in range(self.params.Ndim):
                self._minSigmaHz.append(6.)
                self._maxSigmaHz.append(28.)

    ###########################################################################

    def updateAll(self):

        self.updateSpectrumWindow()
        self.updatePeakListList()

        self.waiting = False

    def updateAfter(self, obj=None):

        if self.waiting:
            return
        else:
            self.waiting = True
            self.after_idle(self.updateAll)
Beispiel #4
0
class BackupProjectPopup(BasePopup):
    """
  **Create Automatic Project Backup**

  The purpose of this dialog is to allow the user to create backups
  of their project automatically.  The XML files for the backup go
  into a separate directory from the project itself.  If the project
  directory is called PROJECTDIR then the default for the backup
  directory is PROJECTDIR_backup, although that can be changed to
  something else in this dialog.

  Other than the backup directory, the user can specify the frequency
  of the backup, in minutes.

  The "Apply Auto Settings" does not have to be applied if the user
  has changed the on/off setting or if the user has changed the
  Auto-backup frequency and entered a carriage return.

  The "Do Immediate Backup" is in case the user wants to do a backup
  then and there.

  There is no backup for the backup.
  """

    on_off_entries = ['on', 'off']

    def __init__(self, parent, help_msg='', help_url='', *args, **kw):

        self.help_msg = help_msg
        self.help_url = help_url

        BasePopup.__init__(self, parent=parent, title='Project : Backup', **kw)

    def body(self, guiFrame):

        self.geometry('500x130')

        guiFrame.grid_columnconfigure(2, weight=1)
        guiFrame.grid_rowconfigure(3, weight=1)

        self.alarm_id = None

        row = 0
        tipText = 'Browse for the directory into which project backups will be made'
        button = Button(guiFrame,
                        text='Directory:',
                        command=self.selectDir,
                        grid=(row, 0),
                        tipText=tipText,
                        sticky='ew')

        repository = self.project.findFirstRepository(name='backup')
        if repository:
            text = repository.url.path
        else:  # this is trouble, but should not happen
            text = ''

        tipText = 'Enter the name of the directory into which project backups will be made'
        self.dir_entry = Entry(guiFrame,
                               text=text,
                               tipText=tipText,
                               width=40,
                               returnCallback=self.applyAuto,
                               grid=(row, 1),
                               gridSpan=(1, 2),
                               sticky='ew')

        row += 1
        label = Label(guiFrame, text='Auto-backup:', grid=(row, 0))
        if self.analysisProject.doAutoBackup:
            ind = 0
        else:
            ind = 1

        tipTexts = [
            'Toggle the timed automatic backup on',
            'Toggle the timed automatic backup off'
        ]
        self.on_off_buttons = RadioButtons(guiFrame,
                                           entries=self.on_off_entries,
                                           tipTexts=tipTexts,
                                           select_callback=self.applyAuto,
                                           selected_index=ind,
                                           grid=(row, 1))

        row += 1
        tipText = 'The number of minutes to wait before automatic project backups'
        label = Label(guiFrame, text='Auto-backup frequency:', grid=(row, 0))

        self.freq_entry = IntEntry(guiFrame,
                                   text=self.analysisProject.autoBackupFreq,
                                   returnCallback=self.applyAuto,
                                   tipText=tipText)
        self.freq_entry.grid(row=row, column=1)

        label = Label(guiFrame, text=' (minutes)', grid=(row, 2))

        row = row + 1
        # Blank for expansion

        row = row + 1
        texts = ['Apply Auto Settings', 'Do Immediate Backup']
        commands = [self.applyAuto, self.applyManual]
        tipTexts = [
            'Commit the specified settings and commence automated CCPN project backup',
            'Backup the CCPN project now, into the specified backup directory'
        ]
        buttons = UtilityButtonList(guiFrame,
                                    texts=texts,
                                    commands=commands,
                                    doClone=False,
                                    helpMsg=self.help_msg,
                                    helpUrl=self.help_url,
                                    tipTexts=tipTexts,
                                    grid=(row, 0),
                                    gridSpan=(1, 3),
                                    sticky='nsew')

    def selectDir(self):

        popup = FileSelectPopup(self, show_file=False)
        dir = popup.getDirectory()
        popup.destroy()

        if (dir):
            self.dir_entry.set(dir)
            self.setDir()

    def setDir(self):

        directory = self.dir_entry.get()
        if not directory:
            showWarning('No directory',
                        'No directory specified, not setting backup directory',
                        parent=self)
            return

        if not os.path.abspath(directory):
            directory = joinPath(os.getcwd(), directory)

        if os.path.exists(directory):
            if not os.path.isdir(directory):
                showWarning('Path not directory',
                            'Path "%s" exists but is not a directory' %
                            directory,
                            parent=self)
                return
        else:
            if showYesNo(
                    'Directory does not exist',
                    'Directory "%s" does not exist, should it be created?' %
                    directory,
                    parent=self):
                os.mkdir(directory)
            else:
                showWarning(
                    'Directory not created',
                    'Directory "%s" not created so not setting backup directory'
                    % directory,
                    parent=self)
                return

        repository = self.project.findFirstRepository(name='backup')
        if not repository:
            showWarning(
                'No backup repository',
                'No backup repository found (something wrong somewhere)',
                parent=self)
            return

        url = repository.url
        if url.path != directory:
            repository.url = Url(path=normalisePath(directory))

    def setFreq(self):

        freq = self.freq_entry.get()

        if (freq is None):
            freq = 0

        self.analysisProject.autoBackupFreq = freq

    def setInfo(self):

        self.setFreq()
        self.setDir()

        on_off = (self.on_off_buttons.get() == 'on')
        self.analysisProject.doAutoBackup = on_off

    def applyAuto(self, *event):

        self.setInfo()
        on_off = self.on_off_buttons.get()
        if on_off == 'on':
            self.parent.setBackupOn()
        else:
            self.parent.setBackupOff()

    def applyManual(self):

        self.setDir()
        self.parent.doBackup()
Beispiel #5
0
class PrintFrame(Frame):

  def __init__(self, parent, getOption = None, setOption = None,
               haveTicks = False, doOutlineBox = True, *args, **kw):

    self.getOption = getOption
    self.setOption = setOption
    self.haveTicks = haveTicks
    self.doOutlineBox = doOutlineBox

    Frame.__init__(self, parent=parent, *args, **kw)

    self.file_select_popup = None

    self.getOptionValues()

    try:
      size_index = paper_types.index(self.paper_type)
    except:
      size_index = 0

    try:
      other_unit_index = paper_units.index(self.other_unit)
    except:
      other_unit_index = 0

    try:
      orientation_index = paper_orientations.index(self.paper_orientation)
    except:
      orientation_index = 0

    try:
      style_index = style_choices.index(self.output_style)
    except:
      style_index = 0

    try:
      format_index = format_choices.index(self.output_format)
    except:
      format_index = 0

    if haveTicks:
      try:
        tick_location_index = tick_locations.index(self.tick_location)
      except:
        tick_location_index = 0

    self.grid_columnconfigure(1, weight=1)

    row = 0
    button = Button(self, text='File:', command=self.findFile,
                    tipText='Select location to save print file')
    button.grid(row=row, column=0, sticky='e')
    self.file_entry = Entry(self, width=40, text=self.file_name,
                tipText='Location where file is saved on disk')
    self.file_entry.grid(row=row, column=1, sticky='ew')

    row += 1
    label = Label(self, text='Title:')
    label.grid(row=row, column=0, sticky='e')
    self.title_entry = Entry(self, width=40, text=self.title,
                    tipText='Title of the printout, displayed at top')
    self.title_entry.grid(row=row, column=1, sticky='ew')

    row += 1
    label = Label(self, text='X axis label:')
    label.grid(row=row, column=0, sticky='e')
    self.x_axis_entry = Entry(self, width=40, text=self.x_axis_label,
                    tipText='X axis label for the printout')
    self.x_axis_entry.grid(row=row, column=1, sticky='ew')

    row += 1
    label = Label(self, text='Y axis label:')
    label.grid(row=row, column=0, sticky='e')
    self.y_axis_entry = Entry(self, width=40, text=self.y_axis_label,
                    tipText='Y axis label for the printout')
    self.y_axis_entry.grid(row=row, column=1, sticky='ew')

    row += 1
    frame = Frame(self)
    frame.grid(row=row, column=0, columnspan=2, sticky='ew')
    frame.grid_columnconfigure(4, weight=1)
    
    label = Label(frame, text='Paper size:')
    label.grid(row=0, column=0, sticky='e')
    entries = []
    for t in paper_types:
      if t == Output.other_paper_type:
        entry = t
      else:
        (w, h, u) = paper_sizes[t]
        entry = t + ' (%2.1f %s x %2.1f %s)' % (w, u, h, u)
      entries.append(entry)
    self.size_menu = PulldownList(frame, callback=self.changedSize,
                                  texts=entries, index=size_index,
                                  tipText='The paper size for the printout')
    self.size_menu.grid(row=0, column=1, sticky='w')

    self.other_frame = Frame(frame)

    self.other_frame.grid_columnconfigure(0, weight=1)
    self.other_entry = FloatEntry(self.other_frame, text=self.other_size,
                                  isArray=True,
                                  tipText='The size of the Other paper in both dimensions; this requires two values, space or comma separated')
    self.other_entry.grid(row=0, column=0, sticky='ew')
    self.other_unit_menu= PulldownList(self.other_frame, texts=paper_units,
                                       index=other_unit_index,
                                       tipText='The unit for the Other paper size')
    self.other_unit_menu.grid(row=0, column=1, sticky='ew')

    row += 1
    frame = Frame(self)
    frame.grid(row=row, column=0, columnspan=4, sticky='ew')
    frame.grid_columnconfigure(1, weight=1)
    frame.grid_columnconfigure(3, weight=1)
    frame.grid_columnconfigure(5, weight=1)

    label = Label(frame, text='Orientation:')
    label.grid(row=0, column=0, sticky='e')
    self.orientation_menu = PulldownList(frame, texts=paper_orientations,
                                         index=orientation_index,
                                         tipText='Whether the paper should be set in Portrait or Landscape mode')
    self.orientation_menu.grid(row=0, column=1, sticky='w')

    label = Label(frame, text='  Style:')
    label.grid(row=0, column=2, sticky='e')
    self.style_menu = PulldownList(frame, texts=style_choices,
                                   index=style_index,
                                   tipText='Whether the printout should be in colour or black and white')
    self.style_menu.grid(row=0, column=3, sticky='w')

    label = Label(frame, text='  Format:')
    label.grid(row=0, column=4, sticky='e')
    self.format_menu = PulldownList(frame, callback=self.changedFormat,
                                    texts=format_choices, index=format_index,
                                    tipText='Whether to save as PS, EPS or PDF')

    self.format_menu.grid(row=0, column=5, sticky='w')

    if haveTicks:

      row += 1
      frame = Frame(self)
      frame.grid(row=row, column=0, columnspan=4, sticky='ew')
      frame.grid_columnconfigure(1, weight=1)
      frame.grid_columnconfigure(3, weight=1)
      
      label = Label(frame, text='Tick Location:')
      label.grid(row=0, column=0, sticky='e')
      self.tick_menu = PulldownList(frame, texts=tick_locations,
                                    index=tick_location_index,
                                    tipText='Whether the tick marks appear on the inside or outside of the frame')
      self.tick_menu.grid(row=0, column=1, sticky='w')

      label = Label(frame, text='  Tick Placement:')
      label.grid(row=0, column=2, sticky='e')
      if self.tick_placement is None:
        selected = None
      else:
        selected = [(x in self.tick_placement) for x in tick_placements]
      self.tick_buttons = CheckButtons(frame, entries=tick_placements,
                                       selected=selected,
                                       tipTexts=('Whether the tick marks appear on the top and/or bottom and/or left and/or right',))
      self.tick_buttons.grid(row=0, column=3, sticky='w')

      row += 1
      frame = Frame(self)
      frame.grid(row=row, column=0, columnspan=4, sticky='ew')
      frame.grid_columnconfigure(1, weight=1)
      frame.grid_columnconfigure(3, weight=1)
      
      label = Label(frame, text='Tick Font:')
      label.grid(row=0, column=0, sticky='e')
      self.tick_font_list = FontList(frame, mode='Print',
                            selected=self.tick_font,
                            extraTexts=[PrintTicks.no_tick_text],
                            tipText='The font used for the tick mark labels')
      self.tick_font_list.grid(row=0, column=1, sticky='w')

      label = Label(frame, text='Tick Spacing:')
      label.grid(row=0, column=2, sticky='e')
      # TBD: put preferred choice in data model
      self.spacing_menu = PulldownList(frame, texts=spacing_choices, index=0,
                                       callback=self.changedSpacing,
                                       tipText='Whether the program should automatically calculate the major/minor tick spacings and how many decimal places are used for the ticks, or whether the these are specified manually')
      self.spacing_menu.grid(row=0, column=3, sticky='w')

      ff = self.spacing_frame = Frame(frame)
      ff.grid_columnconfigure(1, weight=1)
      ff.grid_columnconfigure(2, weight=1)
      label = Label(ff, text='Tick Spacing')
      label.grid(row=0, column=0, sticky='w')
      label = Label(ff, text='Major')
      label.grid(row=0, column=1, sticky='ew')
      label = Label(ff, text='Minor')
      label.grid(row=0, column=2, sticky='ew')
      label = Label(ff, text='Decimals')
      label.grid(row=0, column=3, sticky='ew')
      label = Label(ff, text='X:')
      label.grid(row=1, column=0, sticky='w')
      self.x_major_entry = FloatEntry(ff, tipText='The spacing in display units of the major tick marks in the X dimension')
      self.x_major_entry.grid(row=1, column=1, sticky='ew')
      self.x_minor_entry = FloatEntry(ff, tipText='The spacing in display units of the minor tick marks in the X dimension (not printed if left blank)')
      self.x_minor_entry.grid(row=1, column=2, sticky='ew')
      self.x_decimal_entry = IntEntry(ff, tipText='The number of decimal places for the tick numbers in the X dimension')
      self.x_decimal_entry.grid(row=1, column=3, sticky='ew')
      label = Label(ff, text='Y:')
      label.grid(row=2, column=0, sticky='w')
      self.y_major_entry = FloatEntry(ff, tipText='The spacing in display units of the major tick marks in the Y dimension')
      self.y_major_entry.grid(row=2, column=1, sticky='ew')
      self.y_minor_entry = FloatEntry(ff, tipText='The spacing in display units of the minor tick marks in the Y dimension (not printed if left blank)')
      self.y_minor_entry.grid(row=2, column=2, sticky='ew')
      self.y_decimal_entry = IntEntry(ff, tipText='The number of decimal places for the tick numbers in the Y dimension')
      self.y_decimal_entry.grid(row=2, column=3, sticky='ew')

      row += 1
      frame = Frame(self)
      frame.grid(row=row, column=0, columnspan=4, sticky='ew')
      frame.grid_columnconfigure(1, weight=1)
      
      label = Label(frame, text='Tick Length:')
      label.grid(row=0, column=0, sticky='e')
      # TBD: put preferred choice in data model
      self.tick_length_menu = PulldownList(frame, texts=tick_length_choices, index=0,
                                       callback=self.changedLength,
                                       tipText='Whether the program should automatically calculate the major/minor tick lengths, or whether the these are specified manually')
      self.tick_length_menu.grid(row=0, column=1, sticky='w')

      ff = self.length_frame = Frame(frame)
      ff.grid_columnconfigure(1, weight=1)
      label = Label(ff, text='  Major length:')
      label.grid(row=0, column=0, sticky='w')
      self.length_major_entry = FloatEntry(ff, tipText='The length in points of the major tick marks')
      self.length_major_entry.grid(row=0, column=1, sticky='w')
      label = Label(ff, text='Minor length:')
      label.grid(row=0, column=2, sticky='w')
      self.length_minor_entry = FloatEntry(ff, tipText='The length in points of the minor tick marks')
      self.length_minor_entry.grid(row=0, column=3, sticky='w')

    row += 1
    frame = Frame(self)
    frame.grid(row=row, column=0, columnspan=4, sticky='ew')
    frame.grid_columnconfigure(3, weight=1)
    frame.grid_columnconfigure(4, weight=1)

    label = Label(frame, text='Scaling:')
    label.grid(row=0, column=0, sticky='e')
    # TBD: put preferred choice in data model
    self.scaling_menu = PulldownList(frame, texts=scaling_choices, index=0,
                                     callback=self.changedScaling,
                                     tipText='Whether the plot should be scaled as a percentage of the maximum size that would fit on the paper, or instead should be specified by the number of cms or inches per unit')
    self.scaling_menu.grid(row=0, column=1, sticky='ew')

    self.scaling_scale = Scale(frame, orient=Tkinter.HORIZONTAL, value=self.scaling, tipText='The percentage of the maximum size that would fit on the paper that the plot is scaled by')
    self.scaling_scale.grid(row=0, column=2, columnspan=3, sticky='ew')

    self.x_scaling_label = Label(frame, text='X:')
    self.x_scaling_entry = FloatEntry(frame, tipText='The scaling that should be used in the X dimension as cms or inches per unit')
    self.y_scaling_label = Label(frame, text='Y:')
    self.y_scaling_entry = FloatEntry(frame, tipText='The scaling that should be used in the Y dimension as cms or inches per unit')

    row += 1
    frame = Frame(self)
    frame.grid(row=row, column=0, columnspan=4, sticky='w')
    frame.grid_columnconfigure(2, weight=1)
  
    label = Label(frame, text='Include:')
    label.grid(row=0, column=0, sticky='e')
    tipTexts = ('Whether the time and date should be included in the printout',
                'Whether the file name should be included in the printout')
    if self.border_decoration is None:
      selected = None
    else:
      selected = [(x in self.border_decoration) for x in border_decorations]
    self.border_buttons = CheckButtons(frame, entries=border_decorations,
                                       selected=selected,
                                       tipTexts=tipTexts)
    self.border_buttons.grid(row=0, column=1, sticky='w')

    label = Label(frame, text='    Using Font:')
    label.grid(row=0, column=2, sticky='e')
    self.border_font_list = FontList(frame, mode='Print',
                          selected=self.border_font,
                          tipText='The font used for the border texts')
    self.border_font_list.grid(row=0, column=3, sticky='w')

    row += 1
    label = Label(self, text='Line width:')
    label.grid(row=row, column=0, sticky='w')
    self.linewidth_entry = FloatEntry(self, width=10,
                                  text=self.linewidth,
                                  tipText='Line width for drawing')
    self.linewidth_entry.grid(row=row, column=1, sticky='w')
 
  def destroy(self):

    self.setOptionValues()

    if self.file_select_popup:
      self.file_select_popup.destroy()

    Frame.destroy(self)

  def getOptionValues(self):

    getOption = self.getOption
    if getOption:

      file_name = getOption('FileName', defaultValue='')
      title = getOption('Title', defaultValue='')
      x_axis_label = getOption('XAxisLabel', defaultValue='')
      y_axis_label = getOption('YAxisLabel', defaultValue='')
      paper_type = getOption('PaperSize', defaultValue=paper_types[0])
      paper_type = paper_type_dict.get(paper_type, paper_types[0])
      other_height = getOption('OtherHeight', defaultValue=10)
      other_width = getOption('OtherWidth', defaultValue=10)
      other_size = [other_height, other_width]
      other_unit = getOption('OtherUnit', defaultValue=paper_units[0])
      paper_orientation = getOption('Orientation', defaultValue=paper_orientations[0])
      in_color = getOption('InColor', defaultValue=True)
      if in_color:
        output_style = style_choices[0]
      else:
        output_style = style_choices[1]
      format_option = getOption('OutputFormat', defaultValue=format_options[0])
      output_format = format_choices[format_options.index(format_option)]
      if self.haveTicks:
        tick_outside = getOption('TickOutside', defaultValue=tick_locations[0])
        if tick_outside:
          tick_location = tick_locations.index(PrintTicks.Outside)
        else:
          tick_location = tick_locations.index(PrintTicks.Inside)
        tick_placement = getTickPlacement1(getOption('TickPlacement', defaultValue='nsew'))
      dateTime = getOption('ShowsDateTime', defaultValue=True)
      fileName = getOption('ShowsFileName', defaultValue=True)
      border_font = getOption('BorderFont', defaultValue='Helvetica 10')
      border_decoration = []
      if dateTime:
        border_decoration.append(border_decorations[0])
      if fileName:
        border_decoration.append(border_decorations[1])

      if self.haveTicks:
        spacing_choice = getOption('SpacingChoice', defaultValue=spacing_choices[0])
        x_major = getOption('XMajor', defaultValue=1.0)
        x_minor = getOption('XMinor', defaultValue=1.0)
        x_decimal = getOption('XDecimal', defaultValue=3)
        y_major = getOption('YMajor', defaultValue=1.0)
        y_minor = getOption('YMinor', defaultValue=1.0)
        y_decimal = getOption('YDecimal', defaultValue=3)

        tick_length_choice = getOption('TickLengthChoice', defaultValue=tick_length_choices[0])
        tick_major = getOption('TickMajor', defaultValue=10)
        tick_minor = getOption('TickMinor', defaultValue=5)

      scaling_choice = getOption('ScalingChoice', defaultValue=scaling_choices[0])
      scaling = getOption('Scaling', defaultValue=0.7)
      scaling = int(round(100.0 * scaling))
      x_scaling = getOption('XScaling', defaultValue=1.0)
      y_scaling = getOption('YScaling', defaultValue=1.0)

      if self.haveTicks:
        tick_font = getOption('TickFont', defaultValue='Helvetica 10')

      linewidth = getOption('LineWidth', defaultValue=Output.default_linewidth)

    else:
      file_name = ''
      title = ''
      x_axis_label = ''
      y_axis_label = ''
      paper_type = paper_types[0]
      other_unit = paper_units[0]
      other_size = ''
      paper_orientation = paper_orientations[0]
      output_style = style_choices[0]
      output_format = format_choices[0]
      if self.haveTicks:
        tick_location = tick_locations[0]
        tick_placement = tick_placements
      border_decoration = border_decorations
      border_font = 'Helvetica 10'
      if self.haveTicks:
        spacing_choice = spacing_choices[0]
        x_major = 1.0
        x_minor = 1.0
        x_decimal = 3
        y_major = 1.0
        y_minor = 1.0
        y_decimal = 3
        tick_length_choice = tick_length_choices[0]
        tick_major = 10
        tick_minor = 5
      scaling_choice = scaling_choices[0]
      scaling = 70
      x_scaling = 1.0
      y_scaling = 1.0
      if self.haveTicks:
        tick_font = 'Helvetica 10'
      linewidth = Output.default_linewidth

    if not self.haveTicks:
      tick_location = None
      tick_placement = None
      spacing_choice = spacing_choices[0]
      x_major = 1.0
      x_minor = 1.0
      x_decimal = 3
      y_major = 1.0
      y_minor = 1.0
      y_decimal = 3
      tick_font = 'Helvetica 10'
      tick_length_choice = tick_length_choices[0]
      tick_major = 10
      tick_minor = 5

    self.file_name = file_name
    self.title = title
    self.x_axis_label = x_axis_label
    self.y_axis_label = y_axis_label
    self.paper_type = paper_type
    self.other_unit = other_unit
    self.other_size = other_size
    self.paper_orientation = paper_orientation
    self.output_style = output_style
    self.output_format = output_format
    self.tick_location = tick_location
    self.tick_placement = tick_placement
    self.border_decoration = border_decoration
    self.border_font = border_font

    self.spacing_choice = spacing_choice
    self.x_major = x_major
    self.x_minor = x_minor
    self.x_decimal = x_decimal
    self.y_major = y_major
    self.y_minor = y_minor
    self.y_decimal = y_decimal

    self.scaling_choice = scaling_choices[0]
    self.scaling = scaling
    self.x_scaling = x_scaling
    self.y_scaling = y_scaling

    self.tick_font = tick_font
    self.linewidth = linewidth

    self.tick_length_choice = tick_length_choice
    self.tick_major = tick_major
    self.tick_minor = tick_minor

  def setOptionValues(self):

    if not hasattr(self, 'file_entry'):
      # it looks like on destroy can have function called but file_entry deleted already
      return

    self.file_name = file_name = self.file_entry.get()
    self.title = title = self.title_entry.get()
    self.x_axis_label = x_axis_label = self.x_axis_entry.get()
    self.y_axis_label = y_axis_label = self.y_axis_entry.get()

    n = self.size_menu.getSelectedIndex()
    self.paper_type = paper_type = paper_types[n]
    if paper_type == Output.other_paper_type:
      other_size = self.other_entry.get()
      other_unit = self.other_unit_menu.getText()
    else:
      other_size = None
      other_unit = None
    self.other_size = other_size
    self.other_unit = other_unit

    self.paper_orientation = paper_orientation = self.orientation_menu.getText()
    self.output_style = output_style = self.style_menu.getText()
    self.output_format = output_format = self.format_menu.getText()

    if self.haveTicks:
      tick_location = self.tick_menu.getText()
      tick_placement = self.tick_buttons.getSelected()
    else:
      tick_location = tick_placement = None
    self.tick_location = tick_location
    self.tick_placement = tick_placement

    self.border_decoration = border_decoration = self.border_buttons.getSelected()
    self.border_font = border_font = self.border_font_list.getText()

    if self.haveTicks:
      self.spacing_choice = spacing_choice = self.spacing_menu.getText()
      if spacing_choice != spacing_choices[0]:
        self.x_major = self.x_major_entry.get()
        self.x_minor = self.x_minor_entry.get()
        self.x_decimal = self.x_decimal_entry.get()
        self.y_major = self.y_major_entry.get()
        self.y_minor = self.y_minor_entry.get()
        self.y_decimal = self.y_decimal_entry.get()

      self.tick_length_choice = tick_length_choice = self.tick_length_menu.getText()
      if tick_length_choice != tick_length_choices[0]:
        self.tick_major = self.length_major_entry.get()
        self.tick_minor = self.length_minor_entry.get()

    self.scaling_choice = scaling_choice = self.scaling_menu.getText()
    if self.scaling_choice == scaling_choices[0]:
      scaling = self.scaling_scale.get()
      self.scaling = int(round(scaling))
    else:
      self.x_scaling = self.x_scaling_entry.get()
      self.y_scaling = self.y_scaling_entry.get()

    if self.haveTicks:
      self.tick_font = self.tick_font_list.getText()

    self.linewidth = self.linewidth_entry.get()

    setOption = self.setOption
    if setOption:
      setOption('FileName', value=file_name)
      setOption('Title', value=title)
      setOption('XAxisLabel', value=x_axis_label)
      setOption('YAxisLabel', value=y_axis_label)
      if paper_type == Output.other_paper_type:
        setOption('OtherHeight', value=other_size[0])
        setOption('OtherWidth', value=other_size[1])
        setOption('OtherUnit', value=other_unit)
      else:
        paper_type = paper_type_inverse_dict[paper_type]
        setOption('PaperSize', value=paper_type)
      setOption('Orientation', value=paper_orientation)
      in_color = (output_style == style_choices[0])
      setOption('InColor', value=in_color)
      output_format = format_options[format_choices.index(output_format)]
      setOption('OutputFormat', value=output_format)
      if self.haveTicks:
        tick_outside = (tick_location == PrintTicks.Outside)
        setOption('TickOutside', value=tick_outside)
        tick_placement = getTickPlacement2(tick_placement)
        setOption('TickPlacement', value=tick_placement)
      dateTime = (border_decorations[0] in border_decoration)
      fileName = (border_decorations[1] in border_decoration)
      setOption('ShowsDateTime', value=dateTime)
      setOption('ShowsFileName', value=fileName)
      setOption('BorderFont', value=border_font)

      if self.haveTicks:
        setOption('SpacingChoice', value=spacing_choice)
        if spacing_choice != spacing_choices[0]:
          setOption('XMajor', self.x_major)
          setOption('XMinor', self.x_minor)
          setOption('XDecimal', self.x_decimal)
          setOption('YMajor', self.y_major)
          setOption('YMinor', self.y_minor)
          setOption('YDecimal', self.y_decimal)

        setOption('TickLengthChoice', value=tick_length_choice)
        if tick_length_choice != tick_length_choices[0]:
          setOption('TickMajor', self.tick_major)
          setOption('TickMinor', self.tick_minor)

      setOption('ScalingChoice', value=scaling_choice)
      if scaling_choice == scaling_choices[0]:
        setOption('Scaling', value=0.01*self.scaling)
      else:
        setOption('XScaling', value=self.x_scaling)
        setOption('YScaling', value=self.y_scaling)

      if self.haveTicks:
        setOption('TickFont', self.tick_font)

      setOption('LineWidth', self.linewidth)

  def findFile(self):

    if self.file_select_popup:
      self.file_select_popup.open()
    else:
      file_types = [ FileType('All', ['*']),
                     FileType('PostScript', ['*.ps', '*.eps']),
                     FileType('PDF', ['*.pdf', '*.ai']) ]
      self.file_select_popup = FileSelectPopup(self, file_types=file_types)

    file = self.file_select_popup.getFile()
    if file:
      self.file_entry.set(file)

  def changedSize(self, entry):

    if entry == Output.other_paper_type:
      self.other_frame.grid(row=0, column=2, columnspan=2, sticky='w')
    else:
      self.other_frame.grid_forget()

  def changedFormat(self, entry):

    file_suffix = file_suffixes.get(entry)
    if not file_suffix:
      return

    file_name = self.file_entry.get()
    if not file_name:
      return

    for suffix in format_suffixes:
      if file_name.endswith(suffix):
        if suffix != file_suffix:
          n = len(suffix)
          file_name = file_name[:-n] + file_suffix
          self.file_entry.set(file_name)
        break
    else:
      file_name = file_name + file_suffix
      self.file_entry.set(file_name)

  def changedScaling(self, choice):

    if choice == scaling_choices[0]:
      self.scaling_scale.grid(row=0, column=2, columnspan=3, sticky='ew')
      self.x_scaling_label.grid_forget()
      self.x_scaling_entry.grid_forget()
      self.y_scaling_label.grid_forget()
      self.y_scaling_entry.grid_forget()
    else:
      self.scaling_scale.grid_forget()
      self.x_scaling_label.grid(row=0, column=2, sticky='w')
      self.x_scaling_entry.grid(row=0, column=3, columnspan=2, sticky='ew')
      self.y_scaling_label.grid(row=1, column=2, sticky='w')
      self.y_scaling_entry.grid(row=1, column=3, columnspan=2, sticky='ew')

    self.setOptionValues()

  def changedSpacing(self, choice):

    if choice == spacing_choices[0]:
      self.spacing_frame.grid_forget()
    else:
      self.spacing_frame.grid(row=1, column=1, columnspan=3, sticky='ew')

    self.setOptionValues()

  def changedLength(self, choice):

    if choice == tick_length_choices[0]:
      self.length_frame.grid_forget()
    else:
      self.length_frame.grid(row=1, column=0, columnspan=4, sticky='ew')

    self.setOptionValues()

  # width and height are of plot, in pixels
  def getOutputHandler(self, pixel_width, pixel_height, unit_width=1.0, unit_height=1.0, fonts=None):

    if not fonts:
      fonts = []
    else:
      fonts = list(fonts)

    for n in range(len(fonts)):
      if fonts[n] == 'Times':
        fonts[n] = 'Times-Roman'

    self.setOptionValues()

    if not self.file_name:
      showError('No file', 'No file specified', parent=self)
      return None

    x_scaling = y_scaling = 1.0
    if self.scaling_choice != scaling_choices[0]:
      try:
        x_scaling = float(self.x_scaling)
      except:
        showError('Bad X Scaling', 'Specified X Scaling must be floating point', parent=self)
        return None
      try:
        y_scaling = float(self.y_scaling)
      except:
        showError('Bad Y Scaling', 'Specified Y Scaling must be floating point', parent=self)
        return None

    if os.path.exists(self.file_name):
      if not showYesNo('File exists', 'File "%s" exists, overwrite?' % self.file_name, parent=self):
        return None

    if self.paper_type == Output.other_paper_type:
      paper_size = self.other_size + [ self.other_unit ]
    else:
      paper_size = paper_sizes[self.paper_type]

    output_scaling = self.scaling / 100.0

    border_font = self.border_font
    (font, size) = border_font.split()
    size = int(size)
    border_text = {}
    for decoration in self.border_decoration:
      if decoration == 'Time and Date':
        location = 'se'
        text = time.ctime(time.time())
      elif decoration == 'File Name':
        location = 'sw'
        text = self.file_name
      else:
        continue # should not be here
      border_text[location] = (text, font, size)
    if self.title:
      location = 'n'
      border_text[location] = (self.title, font, size+6)

    if font not in fonts:
      fonts.append(font)

    if self.haveTicks and self.tick_location == PrintTicks.Outside:
      axis_label_offset = 2
    else:
      axis_label_offset = 0
     
    outputHandler = PrintHandler.getOutputHandler(self.file_name,
                              pixel_width, pixel_height,
                              unit_width, unit_height,
                              scaling_choice=self.scaling_choice,
                              output_scaling=output_scaling,
                              w_scaling=x_scaling,
                              h_scaling=y_scaling,
                              paper_size=paper_size,
                              paper_orientation=self.paper_orientation,
                              output_style=self.output_style,
                              output_format=self.output_format,
                              border_text=border_text,
                              x_axis_label=self.x_axis_label,
                              y_axis_label=self.y_axis_label,
                              axis_label_font=font,
                              axis_label_size=size,
                              axis_label_offset=axis_label_offset,
                              fonts=fonts,
                              linewidth=self.linewidth,
                              do_outline_box=self.doOutlineBox)

    return outputHandler

  def getAspectRatio(self):

    self.setOptionValues()

    if self.paper_type == Output.other_paper_type:
      paper_size = self.other_size
    else:
      paper_size = paper_sizes[self.paper_type]

    r = paper_size[1] / paper_size[0]
    if self.paper_orientation == 'Landscape':
      r = 1.0 / r

    return r
Beispiel #6
0
class WidgetCountPopup(BasePopup):

    on_off_entries = ['on', 'off']

    def __init__(self, parent, help_msg='', help_url='', *args, **kw):

        self.help_msg = help_msg
        self.help_url = help_url

        BasePopup.__init__(self,
                           parent=parent,
                           title='Widget Count',
                           *args,
                           **kw)

    def body(self, master):

        self.alarm_id = None
        self.root_widget = getRoot(self)

        row = 0
        label = Label(master, text='Widget count:')
        label.grid(row=row, column=0, sticky=Tkinter.W)
        self.count_label = Label(master,
                                 text='',
                                 tipText='Number of Tkinter widget objects')
        self.count_label.grid(row=row, column=1, sticky=Tkinter.W)

        row = row + 1
        ind = 1
        label = Label(master, text='Auto count:')
        label.grid(row=row, column=0, sticky=Tkinter.W)
        self.on_off_buttons = RadioButtons(master,
                                           entries=self.on_off_entries,
                                           select_callback=self.applyAuto,
                                           selected_index=ind)
        self.on_off_buttons.grid(row=row, column=1, sticky=Tkinter.EW)

        row = row + 1
        label = Label(master, text='Auto frequency:')
        label.grid(row=row, column=0, sticky=Tkinter.W)
        self.freq_entry = IntEntry(master,
                                   text=60,
                                   returnCallback=self.applyAuto)
        self.freq_entry.grid(row=row, column=1, sticky=Tkinter.EW)
        label = Label(master, text='seconds')
        label.grid(row=row, column=2, sticky=Tkinter.W)

        row = row + 1
        texts = ['Do Immediate Count']
        commands = [self.applyManual]
        buttons = createDismissHelpButtonList(master,
                                              texts=texts,
                                              commands=commands,
                                              help_msg=self.help_msg,
                                              help_url=self.help_url)
        buttons.grid(row=row, column=0, columnspan=3, sticky=Tkinter.EW)

        self.doCount()

    def applyAuto(self, *event):

        on_off = self.on_off_buttons.get()
        if on_off == 'on':
            self.setCountOn()
        else:
            self.setCountOff()

    def applyManual(self):

        self.doCount()

    def setCountOn(self):

        self.setCountOff()

        freq = self.freq_entry.get()
        if freq is not None and freq > 0:
            freq *= 1000  # convert from sec to msec
            self.alarm_id = self.after(freq, self.doCountAuto)

    def setCountOff(self):

        if self.alarm_id:
            self.after_cancel(self.alarm_id)
            self.alarm_id = None

    def doCountAuto(self):

        if self.on_off_buttons.get() == 'on':
            self.doCount()
            freq = self.freq_entry.get()
            if freq is not None and freq > 0:
                freq *= 1000  # convert from sec to msec
                self.alarm_id = self.after(freq, self.doCountAuto)

    def doCount(self):

        count = getWidgetCount(self.root_widget)
        self.count_label.set('%d' % count)
Beispiel #7
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)