def changeMolName(self, molName): newMolName = askString('Enter molecule name', 'New name for molecule', molName, self) if newMolName and newMolName != molName: if newMolName in self.molNames: showError("Molecule name present", "This molecule name is already present!") elif self.project.findFirstMolecule(name=newMolName): # TODO TODO: allow user to select an existing molecule?!?! showError( "Molecule exists", "A molecule with this name already exists in the data model." ) else: moleculeInfo = self.localCreateMoleculeDict[molName] self.localCreateMoleculeDict[newMolName] = moleculeInfo del self.localCreateMoleculeDict[molName] # # Clean out text... # for molName in self.molNames: self.warningCode[molName].set("") self.resetInfo() self.setupWidgets()
def checkDangleStore(self): if not self.dangleStore: N = len(self.project.dangleStores) + 1 name = askString('Request', 'Dangle Run Name:', 'Run%d' % N, parent=self) if not name: return None for character in whitespace: if character in name: showWarning('Failure', 'Name cannot contain whitespace', parent=self) return None if self.project.findFirstDangleStore(name=name): showWarning('Failure', 'Name already used', parent=self) return None self.dangleStore = self.project.newDangleStore(name=name) self.updateDangleStorePulldown()
def setAtomTypeDefault(self): if self.scheme: atomName = askString( 'Query', 'Specify atom name to set\ndefault abundance for', 'H', parent=self) if not atomName: return atomLabels = [] for chemCompLabel in self.scheme.chemCompLabels: if chemCompLabel.molType == self.molType: for isotopomer in chemCompLabel.isotopomers: # Multiple because of isotopes and subTypes atomLabels += isotopomer.findAllAtomLabels( name=atomName) if atomLabels: for atomLabel in atomLabels: isotope = atomLabel.isotope weight = self.defaultAbun.get(isotope, 100.0 * isotope.abundance) atomLabel.weight = weight else: data = (atomName, self.scheme.name) msg = 'Atom name %s does not match any atoms in %s scheme isotopomers' % data showWarning('Failure', msg)
def createDir(self): from memops.gui.DataEntry import askString msg = 'Enter new sub-directory name' dirName = askString('New directory', msg, parent=self) if dirName: dirName = joinPath(self.directory, dirName) if os.path.exists(dirName): msg = 'Directory "%s" already exists' % dirName showError('Directory exists', msg, parent=self) else: os.mkdir(dirName) self.updateFileList()
def makeNewScheme(self): name = askString('Input text', 'New Scheme Code:', '', parent=self) if name: scheme = self.project.findFirstLabelingScheme(name=name) if scheme: showWarning('Failure', 'Scheme name already in use') else: scheme = self.project.newLabelingScheme(name=name) self.scheme = scheme else: showWarning('Failure', 'No name specified')
def updateMenuAttr(self, attr, value): if (value == otherMenuText): # TBD: assumes all open enumerations are strings (probably true) dataType = attr.dataType value = askString('Input entry', 'Input new entry for "%s"' % attr.name, parent=self) if (value is None): self.cancelEditAttr() return self.updateAttr(attr, value)
def newProject(self): if self.project: # Project already present if not self.closeProject(): # If we don't close the current project do nothing return name = askString(title='Project name', prompt='Enter project name:',parent=self) if name: # Make the API Project object project = Implementation.MemopsRoot(name=name) nmrProject = project.newNmrProject(name = project.name) self.initProject(project)
def commitAll(self): """ commit ALL current changes to local git repo In the long term, we should probably choose what to track """ if not self.repo: self.initiate() repo = self.repo try: repo.git.add( os.path.join(self.repoLocation, '.') ) except: raise message = askString( 'git commit -m', 'Please enter your git commit message (blank for default)') if not message: repo.git.commit(message='Auto git commit CCPN project') else: repo.git.commit(message=message)
def copyScheme(self): if self.scheme: name = askString('Input text', 'New Scheme Code:', '', parent=self) scheme = self.project.findFirstLabelingScheme(name=name) if scheme: showWarning('Failure', 'Scheme name already in use') return if name: newScheme = copySubTree(self.scheme, self.project, topObjectParameters={'name': name}) else: showWarning('Failure', 'No name specified') else: showWarning('Failure', 'No scheme selected to copy')
def apply(self): selectedPeakLists = self.peakListBox.getSelectedItems() for peakListLabel in selectedPeakLists: self.peakLists.append(self.peakListDict[peakListLabel]) chemShiftList = self.shiftListDict[self.shiftListSelect.getSelected()] if not chemShiftList: chemShiftListName = askString("Enter chemical shift list name", "New chemical shift list name", '', self) else: chemShiftListName = chemShiftList.name useAllContribs = self.useAllContribs.isSelected() defaultShiftError = {} for nucl in self.defaultShiftError.keys(): defaultShiftError[nucl] = returnFloat( self.defaultShiftError[nucl].get()) listCreated = createChemShifts(self.peakLists, guiParent=self.parent, multiDialog=self.parent.multiDialog, shiftList=chemShiftList, useAllContribs=useAllContribs, defaultShiftError=defaultShiftError, shiftListName=chemShiftListName) if listCreated: showInfo( "Success", "Succesfully created a chemical shift list from peaklist(s)") return True
def __init__(self, root): self.root = root self.font = DEFAULT_FONT # Application object needed to store application-specific data with project self.application = Application(name=PROGRAM_NAME) self.versionInfo = VERSION ccpnProjectName = askString( "CCPN project name", 'Please give a name to this import session:') self.fcWrapper = FormatConverterWrapper( ccpnProjectName=ccpnProjectName, guiRoot=self) self.project = self.fcWrapper.formatConversion.ccpnProject # Application popup is a superclass of memops.editor.BasePoup BasePopup.__init__(self, parent=root, title=PROGRAM_NAME, location='+100+100', class_=self.application.name) self.setTitle(PROGRAM_NAME)
def apply(self): self.refExperiment = self.table.currentObject names = [ exp.name for exp in self.project.currentNmrProject.sortedExperiments() ] while 1: self.name = askString('Give the name of the experiment', 'Experiment name:', initial_value=self.expName, parent=self.parent) if (self.name in names): showError('Repeated experiment name', 'Name already used - choose another.') else: break self.skip = 0 return True
def makeStructureEnsemble(strucDict, molSystem, modelNames=None, doWarnings=False, checkTruncation=True, fixAtomNames=True): """Makes structure ensemble from a structure dictionary [model][chainCode][resNum][atomName] = (x,y,z coords) in a mol system. Options to supress warnings and thus automatically link non-identical, but similar chains or make a new chain if none is found, NB chains and resides are those present in FIRST model atoms are taken from all models, and missing atoms are given x=y=z = 0.0; occupancy=0.0 .. describe:: Input Dictionary, MolSystem.MolSystem, Boolean .. describe:: Output MolStructures.StructureEnsemble """ # Rasmus Fogh 20/6/2011: Changed to new MolStructure model # Rasmus Fogh 4/5/2013:Added automatic name fixing: 2HB -> HB2 # # Set up, and create structure ensemble # ll = sorted(strucDict.keys()) firstModelId = ll[0] project = molSystem.root ensembles = molSystem.sortedStructureEnsembles() if ensembles: eId = ensembles[-1].ensembleId + 1 else: eId = 1 ensemble = project.newStructureEnsemble(molSystem=molSystem, ensembleId=eId) #models = [] #for m in strucDict.keys(): # models.append((m, ensemble.newModel())) # # record data list - for creating and processing records in reading order # recordDataList = [] recordDataDict = {} coordResidues = {} allMsResidues = {} usedChains = [] failedAtoms = [] msAtomDict = {} atomCheckDict = {} systemAtoms = set() chainsDict = strucDict[firstModelId] # match or make chains chCodes = list(chainsDict.keys()) chCodes.sort() nOrigChCodes = len(chCodes) for iChCode, chCode in enumerate(chCodes): resDict = chainsDict[chCode] seqIds = resDict.keys() seqIds.sort() chemComps = [] ccpCodes = [] seqIdsGood = [] # get list of good chemcomps molTypes = set() resNames = [] for seqId in seqIds: ll = resDict[seqId].keys() resName = resDict[seqId][ll[0]]['resName'] atomNames = [tt[0] for tt in ll] chemComp = DataConvertLib.getBestChemComp(project, resName, atomNames) resNames.append(resName) if chemComp: chemComps.append(chemComp) ccpCodes.append(chemComp.ccpCode) seqIdsGood.append(seqId) molTypes.add(chemComp.molType) if not seqIdsGood: msg = 'Could not find any matching CCPN ChemComps for sequence: ' msg += ' '.join(resNames) showWarning('Structure Creation Failed', msg) continue #get matching MolSystem chains seqIds = seqIdsGood msChains, mappings = findMatchingChains(molSystem, ccpCodes, excludeChains=usedChains, doWarning=doWarnings, molTypes=molTypes) nChains = len(msChains) if nChains == 1: msChain = msChains[0] mapping = mappings[0] elif nChains: from memops.gui.DataEntry import askString codes = [c.code for c in msChains] msg = 'Structure chain %s matches %d \nCCPN chains' % (chCode, nChains) msg += ' equally well: %s\n' % (' '.join(codes), ) msg += 'Which CCPN chain should be linked to?' if chCode in codes: default = chCode else: default = codes[0] choice = None while choice not in codes: choice = askString('Query', msg, default) or '' choice = choice.strip() index = codes.index(choice) msChain = msChains[index] mapping = mappings[index] else: msChain = None if nChains: nRes = len(mapping) startPair = 0 endPair = nRes - 1 for i in range(nRes): residueA, residueB = mapping[i] if residueA and residueB: startPair = i break for endTrunc in range(nRes): j = endPair - endTrunc residueA, residueB = mapping[j] if residueA and residueB: endPair = j break mismatch = [] for i in range(startPair, endPair + 1): if None in mapping[i]: mismatch.append(i) break if doWarnings: if checkTruncation and ((endTrunc > 10) or (startPair > 10)): msg = 'Structure truncated (Start:%s, End:%s) ' % ( startPair, endTrunc) msg += 'compared to existing chain. Really link to chain %s?' % msChain.code msg += ' (Otherwise a new chain will be made)' if not showYesNo('Query', msg): msChain = None if mismatch and msChain is not None: msg = 'Imperfect match: %s non-terminal mismatches, ' % len( mismatch) msg += 'compared to existing chain. Really link to chain %s?' % msChain.code msg += ' (Otherwise a new chain will be made)' if not showYesNo('Query', msg): msChain = None else: if checkTruncation and (startPair or endTrunc): print( 'WARNING, Structure truncated (Start:%s, End:%s) rel. to existing chain.' % (startPair, endTrunc)) if mismatch: print 'WARNING, Imperfect match: %s non-terminal mismatches' % len( mismatch) if not msChain: # no matching chain - make new one # use existing chain code from PDB file if possible sysChainCode = chCode.strip() if not sysChainCode or molSystem.findFirstChain(code=sysChainCode): sysChainCode = nextChainCode(molSystem) if molTypes == set(('DNA', )) and iChCode <= nOrigChCodes: # check for special case: # double stranded DNA with a single chain code oneLetterCodes = [cc.code1Letter for cc in chemComps] if None not in oneLetterCodes: # All ChemComps are (variants of) Std bases. # Not sure certain, but this should mostly work. nCodes = len(oneLetterCodes) halfway, remainder = divmod(nCodes, 2) if not remainder: # even number of codes resMap = {'A': 'T', 'T': 'A', 'G': 'C', 'C': 'G'} for ii in range(halfway): if oneLetterCodes[ii] != resMap[oneLetterCodes[ -1 - ii]]: break else: # the second half is the reverse complement of the first half. # treat as two separate DNA chains # Move second half to a new chain, and remove from this chain. newChCode = chCode while newChCode in chCodes: newChCode = chr(ord(newChCode) + 1) newResDict = chainsDict[newChCode] = {} for ii in range(halfway, nCodes): iix = seqIds[ii] newResDict[iix] = resDict[iix] del resDict[iix] # put both chains on end of list for later (re)processing chCodes.append(chCode) chCodes.append(newChCode) continue codes = (molSystem.code, sysChainCode) msg = 'Structure residue sequence (chain %s) not in molecular system. ' % chCode msg += 'Make new molecular system %s chain (%s) for this sequence?' % codes if not doWarnings or (not molSystem.chains) or ( doWarnings and showOkCancel('Confirm', msg)): atomNames = resDict[seqIds[0]].keys() molType = chemComps[0].molType ccpCodes0 = [] startNum = resDict[seqIds[0]][atomNames[0]]['seqCode'] project = molSystem.root molecule = makeMolecule(project, molType, []) for i in range(len(seqIds)): chemComp = chemComps[i] if (chemComp.molType != molType) or ( i and (seqIds[i] != seqIds[i - 1] + 1)): newMolResidues = addMolResidues(molecule, molType, ccpCodes0, startNum=startNum) # set seqCodes and seqInsertCodes xSeqIds = seqIds[i - len(newMolResidues):i] for j, x in enumerate(xSeqIds): rr = newMolResidues[j] for dummy in resDict[x]: # future-safe of getting a random atomDict for seqId x dd = resDict[x][dummy] break rr.seqCode = dd['seqCode'] rr.seqInsertCode = dd['insertCode'] ccpCodes0 = [ chemComp.ccpCode, ] molType = chemComp.molType startNum = seqIds[i] else: ccpCodes0.append(chemComp.ccpCode) if ccpCodes0: addMolResidues(molecule, molType, ccpCodes0, startNum=startNum) msChain = makeChain(molSystem, molecule, code=sysChainCode) resMapping = {} for i, residue in enumerate(msChain.sortedResidues()): resMapping[i] = residue # TBD deal with HETATMs, proper Molecule name, # store CCPN xml as non-standard naming system? else: continue else: # msChain is not None sysChainCode = msChain.code resMapping = {} for i, residue in mapping: resMapping[i] = residue usedChains.append(msChain) atomNamesList = [] msResidues = [] for j, seqId in enumerate(seqIds): atomNames = [tt[0] for tt in resDict[seqId].keys()] if fixAtomNames: # change names to get right naming system. for ii, name in enumerate(atomNames): if name[0] in '123': atomNames[ii] = name[1:] + name[0] atomNamesList.append(atomNames) msResidue = resMapping.get(j) msResidues.append(msResidue) namingSystem = DataConvertLib.getBestNamingSystem( msResidues, atomNamesList) coordChain = ensemble.newChain(code=sysChainCode) #ensemble.override = True # # Done making chain - start adding residues to chain # for j, seqId in enumerate(seqIds): msResidue = msResidues[j] if not msResidue: # Structure is bigger continue resName = ccpCodes[j] ccpCode = msResidue.ccpCode if doWarnings: if resName != ccpCode: msg = 'Residue names [%s,%s] don\'t match\nin' msg += ' loaded molecular system\nchain %s position %d' data = (resName, ccpCode, chCode, seqId) showWarning('Warning', msg % data) continue if msResidue is None: msg = 'No equivalent molecular system residue' msg += '\nfor PDB chain %s residue %d' showWarning('Warning', msg % (chCode, seqId)) continue coordResidue = coordChain.newResidue( seqCode=msResidue.seqCode, seqInsertCode=msResidue.seqInsertCode, seqId=msResidue.seqId) coordResidues[(chCode, seqId)] = coordResidue allMsResidues[(chCode, seqId)] = msResidue # # Now make atoms # for atomKey, coordDict in resDict[seqId].items(): atomName, altLoc = atomKey key = '%s:%s:%s' % (atomName, msResidue, namingSystem) if key in msAtomDict: systemAtom = msAtomDict.get(key) else: systemAtom = DataConvertLib.findMatchingMolSystemAtom( atomName, msResidue, namingSystem, systemAtoms, fixAtomNames=fixAtomNames) msAtomDict[key] = systemAtom if (systemAtom is None) or atomCheckDict.get( (systemAtom, altLoc)): #print '### failing', atomName failedAtoms.append( '%s %d %s %4s' % (chCode, seqId, msResidue.ccpCode, atomName)) continue systemAtoms.add(systemAtom) #print '### adding', atomName, systemAtom.name atomCheckDict[(systemAtom, altLoc)] = True tt = (coordDict.get('recordId'), (chCode, seqId, atomKey), coordResidue, systemAtom.name, coordDict) recordDataList.append(tt) recordDataDict[(chCode, seqId, atomKey)] = tt # # Finished getting data for reading order from first model # # Now loop over other models and add new atoms to existing residues # ignoring new residues and chains, to cater for varying atom presence # for modelInd, chainsDict in sorted(strucDict.items()[1:]): for chCode, resDict in sorted(chainsDict.items()): for seqId, atomDict in sorted(resDict.items()): coordResidue = coordResidues.get((chCode, seqId)) msResidue = allMsResidues.get((chCode, seqId)) if coordResidue is None or msResidue is None: continue for atomKey, coordDict in atomDict.items(): tt = recordDataDict.get((chCode, seqId, atomKey)) if tt is None: # new atom, make new record atomName, altLoc = atomKey key = '%s:%s:%s' % (atomName, msResidue, namingSystem) if key in msAtomDict: systemAtom = msAtomDict.get(key) else: systemAtom = DataConvertLib.findMatchingMolSystemAtom( atomName, msResidue, namingSystem, systemAtoms, fixAtomNames=fixAtomNames) msAtomDict[key] = systemAtom if (systemAtom is None) or atomCheckDict.get( (systemAtom, altLoc)): failedAtoms.append( '%s %d %s %4s' % (chCode, seqId, msResidue.ccpCode, atomName)) continue print '### NBNB add extra atom:', (chCode, seqId, atomKey) systemAtoms.add(systemAtom) atomCheckDict[(systemAtom, altLoc)] = True tt = (coordDict.get('recordId'), (chCode, seqId, atomKey), coordResidue, systemAtom.name, coordDict) recordDataList.append(tt) recordDataDict[(chCode, seqId, atomKey)] = tt # # Finished getting data for reading order # # sort by recordId. If not set - or if duplicate recordId # will sort by full key. recordDataList.sort() # nAtoms = len(recordDataList) # # Create atoms # for tt in recordDataList: recordId, fullKey, coordResidue, atomName, coordDict = tt # make coordAtom coordResidue.newAtom(name=atomName, altLocationCode=fullKey[2][1]) # # set data for all models # kk = 0 for modelInd, chainsDict in sorted(strucDict.items()): #create model model = ensemble.newModel() if modelNames: model.name = modelNames[kk] kk += 1 # set up for data reading coordinates = [0.0] * (3 * nAtoms ) # NB deliberate this is 0.0, not None # There might be atoms missing in other models occupancies = [1.0] * nAtoms bFactors = [0.0] * nAtoms ii = 0 jj = 0 hasOccupancies = False hasBFactors = False for tt in recordDataList: recordId, fullKey, coordResidue, atomName, coordDict = tt resDict = chainsDict.get(fullKey[0]) if resDict: atomDict = resDict.get(fullKey[1]) if atomDict: coordDict = atomDict.get(fullKey[2]) #try: # xxx = atomDict[fullKey[2]] # coordDict = xxx #except: # print '###', atomDict.keys(), tt if coordDict: # get data for model coordinates[jj] = coordDict['x'] jj += 1 coordinates[jj] = coordDict['y'] jj += 1 coordinates[jj] = coordDict['z'] jj += 1 occupancy = coordDict.get('occupancy', 1.0) if occupancy != 1.0: occupancies[ii] = occupancy hasOccupancies = True bFactor = coordDict.get('bFactor', 0.0) if bFactor != 0.0: bFactors[ii] = bFactor hasBFactors = True ii += 1 else: # This atom not found in this model # Just leave default values, set occupancy to 0 # and increment indices # NBNB this leaves coordinates as 0.0 NBNBNB occupancies[ii] = 0.0 hasOccupancies = True ii += 1 jj += 3 # fill data into model model.setSubmatrixData('coordinates', coordinates) if hasOccupancies: model.setSubmatrixData('occupancies', occupancies) if hasBFactors: model.setSubmatrixData('bFactors', bFactors) # final validity check try: ensemble.checkAllValid() except: ensemble.delete() return # reset switches #ensemble.override = False if failedAtoms: ll = sorted(set(failedAtoms)) ll = [x for x in ll if not ('Q' in x[-5:] or '*' in x[-5:])] #skipAtoms = (' HT1', ' HT2', ' HT3', ' 1HT', ' 2HT', ' 3HT', ' OXT', # ' OT1', ' OT2', ' 1H', ' 2H', ' 3H') #ll = [x for x in failedAtoms # if 'Q' not in x # and not [x.endswith(y) for y in skipAtoms]] if ll: print( '## WARNING %s failed atoms. Unique, non-pesudo atoms are:' % len(failedAtoms), ', '.join(ll)) if failedAtoms and doWarnings: msg = 'No equivalent molecular system atoms for PDB atoms: %s' showWarning('Warning', msg % (' '.join(failedAtoms))) if not ensemble.coordChains: ensemble.delete() ensemble = None return ensemble
def setGraphTitle(self, event): self.title = askString('Text Entry', 'Enter graph title', self.title, self) self.drawAfter()
def getAriaData(self): if not self.project: showWarning('Failure', 'No active project', parent=self) return if not self.molSystem: showWarning('Failure', 'No molecular system selected', parent=self) return if len(self.molSystem.chains) > 1: code = self.molSystem.findFirstChain().code code = askString('Multiple chains', 'Enter chain code:', code, parent=self) chain = self.molSystem.findFirstChain(code=code) else: chain = self.molSystem.findFirstChain() peakData = [] dihedrals = [] ambigs = [] unambigs = [] jCouplings = [] for obj in self.scrolledMatrix.objectList: opts = obj.setupStructureCalcFrameDict if not opts['use']: continue className = obj.className key = getObjectKeyString(obj) if className == 'PeakList': shiftList = opts['shiftList'] if not shiftList: continue datum = { 'shifts': { KEY_ID: getObjectKeyString(shiftList) }, 'peaks': { KEY_ID: key }, 'use_assignments': opts['preserve'], 'trust_assigned_peaks': opts['filter'] } peakData.append(datum) elif className == 'DistanceConstraintList': if opts['ambig']: ambigs.append({ KEY_ID: key, 'filter_contributions': opts['filter'] }) else: unambigs.append({ KEY_ID: key, 'filter_contributions': opts['filter'] }) elif className == 'JCouplingConstraintList': jCouplings.append({KEY_ID: key}) elif className == 'DihedralConstraintList': dihedrals.append({KEY_ID: key}) projFileName = os.path.join(self.project.url.path, self.project.path) dict = { KEY_GENERAL: { 'project_name': self.project.name }, KEY_CCPN: { 'filename': projFileName }, KEY_MOLECULAR_SYSTEM: { KEY_ID: getObjectKeyString(chain) }, KEY_NOES: peakData, KEY_DIHEDRALS: dihedrals, KEY_DISTANCES_AMBIG: ambigs, KEY_DISTANCES_UNAMBIG: unambigs, KEY_JCOUPLINGS: jCouplings } return dict