def rotamerizeFromAtomSpecs(atomSpec1, atomSpec2, ignoreDensity=False): """Rotamerize a stretch of nucleotides ARGUMENTS: atomSpec1 - an atom spec specifying the start of the stretch atomSpec2 - an atom spec specifying the end of the stretch OPTIONAL ARGUMENTS: ignoreDensity - ignore the density when performing the minimization defaults to False RETURNS: False if there is a problem with the selected nucleotides None otherwise """ #stop waiting for the user to cancel the rotamerize __setMenuToRotamerize() global waitingForClicks waitingForClicks = False #print "atom 1 = ", atomSpec1 #print "atom 2 = ", atomSpec2 #unpack the atom descriptions (mol1, chain1, startResNum, startInsCode, startAtom, alt1) = atomSpec1[1:] (mol2, chain2, endResNum, endInsCode, endAtom, alt2) = atomSpec2[1:] #make sure that the picked atoms define a single stretch of RNA if mol1 != mol2: print "Rotamerize atoms are not in the same molecule" add_status_bar_text("Rotamerize atoms are not in the same molecule") return False if chain1 != chain2: print "Rotamerize atoms are not in the same chain" add_status_bar_text("Rotamerize atoms are not in the same chain") return False molNum = mol1 chain = chain1 startResFull = str(startResNum) + str(startInsCode) endResFull = str(endResNum) + str(endInsCode) try: pseudoMol = PseudoMolecule(createFromMolecule=molNum, chain=chain, batons=False) except PseudoMoleculeError, err: #if creating the PseudoMolecule raises an error, then it means that molecule we clicked on contains #anisotropic temperature records and we're using a version of Coot that's older than rev 3631 #so clear_and_update_molecule can't handle anisotropic records print err #add_status_bar_text(str(err)) #Since this isn't an intuitive problem (i.e. it's far less obvious for the user than "you clicked on #two different chains"), we create a dialog box instead of a status bar message createRCraneErrorDialog(str(err) + "\n\nRotamerization canceled.") return False
def rotamerizeFromAtomSpecs(atomSpec1, atomSpec2, ignoreDensity = False): """Rotamerize a stretch of nucleotides ARGUMENTS: atomSpec1 - an atom spec specifying the start of the stretch atomSpec2 - an atom spec specifying the end of the stretch OPTIONAL ARGUMENTS: ignoreDensity - ignore the density when performing the minimization defaults to False RETURNS: False if there is a problem with the selected nucleotides None otherwise """ #stop waiting for the user to cancel the rotamerize __setMenuToRotamerize() global waitingForClicks waitingForClicks = False #print "atom 1 = ", atomSpec1 #print "atom 2 = ", atomSpec2 #unpack the atom descriptions (mol1, chain1, startResNum, startInsCode, startAtom, alt1) = atomSpec1[1:] (mol2, chain2, endResNum, endInsCode, endAtom, alt2) = atomSpec2[1:] #make sure that the picked atoms define a single stretch of RNA if mol1 != mol2: print "Rotamerize atoms are not in the same molecule" add_status_bar_text("Rotamerize atoms are not in the same molecule") return False if chain1 != chain2: print "Rotamerize atoms are not in the same chain" add_status_bar_text("Rotamerize atoms are not in the same chain") return False molNum = mol1 chain = chain1 startResFull = str(startResNum) + str(startInsCode) endResFull = str(endResNum) + str(endInsCode) try: pseudoMol = PseudoMolecule(createFromMolecule = molNum, chain = chain, batons = False) except PseudoMoleculeError, err: #if creating the PseudoMolecule raises an error, then it means that molecule we clicked on contains #anisotropic temperature records and we're using a version of Coot that's older than rev 3631 #so clear_and_update_molecule can't handle anisotropic records print err #add_status_bar_text(str(err)) #Since this isn't an intuitive problem (i.e. it's far less obvious for the user than "you clicked on #two different chains"), we create a dialog box instead of a status bar message createRCraneErrorDialog(str(err) + "\n\nRotamerization canceled.") return False
def pickAtoms(ignoreDensity=False): """Prompt the user to pick two atoms to rotamerize a stretch of nucleotides. Alternatively, if we're already waiting for the user to pick atoms, then cancel the pending picks. ARGUMENTS: None OPTIONAL ARGUMENTS: ignoreDensity - ignore the density when performing the minimization defaults to False RETURNS: None """ #create the citation pop-up if necessary createCitationPopup() global waitingForClicks #make sure that we're not waiting on a pending extendChain call extendChain.clearPendingExtendChain() if waitingForClicks: #if we're already in the middle of a rotamerize call, then cancel the pending rotamerize print "Rotamerize cancelled" add_status_bar_text("Rotamerize cancelled") clear_pending_picks( ) #tell Coot to stop waiting for the user to click on atoms __setMenuToRotamerize() waitingForClicks = False else: #if we're not in the middle of a rotamerize call, then start one #make sure that there is a refinement map set if not ignoreDensity and imol_refinement_map() == -1: print "No refinement map set for RCrane rotamerize" selectMapDialog(pickAtoms) return print "Click on 2 atoms (in the same molecule)" add_status_bar_text( "Pick 2 atoms [Ctrl Left-mouse rotates the view]...") __setMenuToCancel() waitingForClicks = True user_defined_click( 2, lambda atomSpec1, atomSpec2: rotamerizeFromAtomSpecs( atomSpec1, atomSpec2, ignoreDensity))
def pickAtoms(ignoreDensity = False): """Prompt the user to pick two atoms to rotamerize a stretch of nucleotides. Alternatively, if we're already waiting for the user to pick atoms, then cancel the pending picks. ARGUMENTS: None OPTIONAL ARGUMENTS: ignoreDensity - ignore the density when performing the minimization defaults to False RETURNS: None """ #create the citation pop-up if necessary createCitationPopup() global waitingForClicks #make sure that we're not waiting on a pending extendChain call extendChain.clearPendingExtendChain() if waitingForClicks: #if we're already in the middle of a rotamerize call, then cancel the pending rotamerize print "Rotamerize cancelled" add_status_bar_text("Rotamerize cancelled") clear_pending_picks() #tell Coot to stop waiting for the user to click on atoms __setMenuToRotamerize() waitingForClicks = False else: #if we're not in the middle of a rotamerize call, then start one #make sure that there is a refinement map set if not ignoreDensity and imol_refinement_map() == -1: print "No refinement map set for RCrane rotamerize" selectMapDialog(pickAtoms) return print "Click on 2 atoms (in the same molecule)" add_status_bar_text("Pick 2 atoms [Ctrl Left-mouse rotates the view]...") __setMenuToCancel() waitingForClicks = True user_defined_click(2, lambda atomSpec1, atomSpec2: rotamerizeFromAtomSpecs(atomSpec1, atomSpec2, ignoreDensity))
def pickAtoms(): """Prompt the user to pick an atoms to extend a stretch of nucleotides. Alternatively, if we're already waiting for the user to pick an atom, then cancel the pending pick. ARGUMENTS: None RETURNS: None """ #create the citation pop-up if necessary createCitationPopup() #make sure that we're not waiting on a pending rotamerize call rotamerize.clearPendingRotamerize() global waitingForClicks if waitingForClicks: #if we're already in the middle of an extend chain call, then cancel the pending call print "Rotamerize cancelled" add_status_bar_text("Extend chain cancelled") clear_pending_picks( ) #tell Coot to stop waiting for the user to click on atoms __setMenuToExtendChain() waitingForClicks = False else: #if we're not in the middle of a extend chain call, then start one #make sure that there is a refinement map set if imol_refinement_map() == -1: print "No refinement map set for RCrane extend chain" selectMapDialog(pickAtoms) return print "Click on a nucleotide to extend" add_status_bar_text( "Pick a nucleotide [Ctrl Left-mouse rotates the view]...") __setMenuToCancel() waitingForClicks = True user_defined_click(1, extendChainFromAtomSpec)
def pickAtoms(): """Prompt the user to pick an atoms to extend a stretch of nucleotides. Alternatively, if we're already waiting for the user to pick an atom, then cancel the pending pick. ARGUMENTS: None RETURNS: None """ #create the citation pop-up if necessary createCitationPopup() #make sure that we're not waiting on a pending rotamerize call rotamerize.clearPendingRotamerize() global waitingForClicks if waitingForClicks: #if we're already in the middle of an extend chain call, then cancel the pending call print "Rotamerize cancelled" add_status_bar_text("Extend chain cancelled") clear_pending_picks() #tell Coot to stop waiting for the user to click on atoms __setMenuToExtendChain() waitingForClicks = False else: #if we're not in the middle of a extend chain call, then start one #make sure that there is a refinement map set if imol_refinement_map() == -1: print "No refinement map set for RCrane extend chain" selectMapDialog(pickAtoms) return print "Click on a nucleotide to extend" add_status_bar_text("Pick a nucleotide [Ctrl Left-mouse rotates the view]...") __setMenuToCancel() waitingForClicks = True user_defined_click(1, extendChainFromAtomSpec)
def __decideDirectionFromAtom(atomName, resNum): """Determine the direction to extend the chain based on the atom name (for use with isolated nuclotides) ARGUMENTS: atomName - the atom name resNum - the residue number of the current nucleotide (used in reporting errors) RETURNS: False if the direction cannot be determined from the atom name 3 or 5 otherwise EFFECTS: if the direction cannot be determined from the atom name, an error will be reported to the user (and False will be returned) """ if atomName in ATOMS3P: return 3 elif atomName in ATOMS5P: return 5 else: print "Nucleotide " + resNum + " is an isolated nucleotide. Please select either the O5' or" print "O3' atom to extend in the 5' or 3' direction, respectively." add_status_bar_text("Must select either O5' or O3' of isolated nucleotides.") return False
def __decideDirectionFromAtom(atomName, resNum): """Determine the direction to extend the chain based on the atom name (for use with isolated nuclotides) ARGUMENTS: atomName - the atom name resNum - the residue number of the current nucleotide (used in reporting errors) RETURNS: False if the direction cannot be determined from the atom name 3 or 5 otherwise EFFECTS: if the direction cannot be determined from the atom name, an error will be reported to the user (and False will be returned) """ if atomName in ATOMS3P: return 3 elif atomName in ATOMS5P: return 5 else: print "Nucleotide " + resNum + " is an isolated nucleotide. Please select either the O5' or" print "O3' atom to extend in the 5' or 3' direction, respectively." add_status_bar_text( "Must select either O5' or O3' of isolated nucleotides.") return False
#starting suite of this residue, then start the minimization at the previous nucleotide startIndex -= 1 startResFull = pseudoMol.resNumFull(startIndex) if ((endIndex + 1) < pseudoMol.getNumNts() and endAtom.strip() == "O3'" and pseudoMol.connectedToNextFromIndex(endIndex)): #if we're not at the last nucleotide and the user clicked on an atom belonging exclusively to the #ending suite of this residue, then include the next residue in the minimization endIndex += 1 endResFull = pseudoMol.resNumFull(endIndex) #warn the user if they haven't selected an entire suite if startIndex == endIndex: print "You must select at least one suite (two residues) to rotamerize." add_status_bar_text( "You must select at least one suite (two residues) to rotamerize.") return False #make sure that the selected residues are all connected for curIndex in range(startIndex, endIndex): if not pseudoMol.connectedToNextFromIndex(curIndex): print "Nucleotides " + pseudoMol.resNumFull( curIndex) + " and " + pseudoMol.resNumFull( curIndex + 1) + " are not connected. Cannot rotamerize." add_status_bar_text("Nucleotides " + pseudoMol.resNumFull(curIndex) + " and " + pseudoMol.resNumFull(curIndex + 1) + " are not connected. Cannot rotamerize.") return False #note that this loop does not check to see if the last nucleotide is connectedToNext, since that's not required
nextResIsPhosOnly = False if connectedToNext: nextResIsPhosOnly = pseudoMol.isOnlyPhosGroupFromIndex(resIndex+1) extendDir = None #the direction to extend the chain in if curResIsPhosOnly: if connectedToPrev: #we're building on a 3' phosphate extendDir = 3 else: #the selected residue is an isolated phosphate group, so we can't do anything print "Nucleotide " + resNumFull + " is an isolated phosphate group. Cannot extend." add_status_bar_text("Nucleotide " + resNumFull + " is an isolated phosphate group. Cannot extend.") return False elif nextResIsPhosOnly: if connectedToPrev: #we're at the 3' end of the chain and there is a 3' phosphate extendDir = 3 resIndex += 1 #increment the resIndex so that it points to the real last residue of the segment curResIsPhosOnly = True resNumFull = pseudoMol.resNumFull(resIndex) #update the residue name in case we need to use it for later error messages else: #we're dealing with a single nt containing a 3' phosphate #we need to decide direction based on the atom clicked extendDir = __decideDirectionFromAtom(atom, resNumFull) if not extendDir: return False #if we couldn't determine a direction from the atom, then cancel
nextResIsPhosOnly = False if connectedToNext: nextResIsPhosOnly = pseudoMol.isOnlyPhosGroupFromIndex(resIndex + 1) extendDir = None #the direction to extend the chain in if curResIsPhosOnly: if connectedToPrev: #we're building on a 3' phosphate extendDir = 3 else: #the selected residue is an isolated phosphate group, so we can't do anything print "Nucleotide " + resNumFull + " is an isolated phosphate group. Cannot extend." add_status_bar_text( "Nucleotide " + resNumFull + " is an isolated phosphate group. Cannot extend.") return False elif nextResIsPhosOnly: if connectedToPrev: #we're at the 3' end of the chain and there is a 3' phosphate extendDir = 3 resIndex += 1 #increment the resIndex so that it points to the real last residue of the segment curResIsPhosOnly = True resNumFull = pseudoMol.resNumFull( resIndex ) #update the residue name in case we need to use it for later error messages else: #we're dealing with a single nt containing a 3' phosphate #we need to decide direction based on the atom clicked
startIndex -= 1 startResFull = pseudoMol.resNumFull(startIndex) if ((endIndex + 1) < pseudoMol.getNumNts() and endAtom.strip() == "O3'" and pseudoMol.connectedToNextFromIndex(endIndex)): #if we're not at the last nucleotide and the user clicked on an atom belonging exclusively to the #ending suite of this residue, then include the next residue in the minimization endIndex += 1 endResFull = pseudoMol.resNumFull(endIndex) #warn the user if they haven't selected an entire suite if startIndex == endIndex: print "You must select at least one suite (two residues) to rotamerize." add_status_bar_text("You must select at least one suite (two residues) to rotamerize.") return False #make sure that the selected residues are all connected for curIndex in range(startIndex, endIndex): if not pseudoMol.connectedToNextFromIndex(curIndex): print "Nucleotides " + pseudoMol.resNumFull(curIndex) + " and " + pseudoMol.resNumFull(curIndex+1) + " are not connected. Cannot rotamerize." add_status_bar_text("Nucleotides " + pseudoMol.resNumFull(curIndex) + " and " + pseudoMol.resNumFull(curIndex+1) + " are not connected. Cannot rotamerize.") return False #note that this loop does not check to see if the last nucleotide is connectedToNext, since that's not required for curIndex in range(startIndex, endIndex+1): #make sure that the selected residues aren't modified nucleotides curResType = pseudoMol.resTypeFromIndex(curIndex) if curResType not in STANDARD_BASES: