Re: [chimera-dev] [Chimera-users] Volume covered by a group of atoms

On May 9, 2010, at 10:14 PM, Miguel Ortiz Lombardia wrote:
Dear all,
I would like to represent as a volume the space that would be covered by a set of atoms that are bound by "torsionable" bonds when one systematically modifies those torsion angles. An example would be the side-chain of an amino acid; imagine I would like to have a glimpse of what part of the space could be occupied by that side- chain. As a first approximation I wouldn't care about clashes.
I would appreciate if someone can point me to an existing way of obtaining such representation or to an algorithm that could be implemented within chimera (which I would be happy to share with other interested people; if I manage to code it, that's it!)
Hi Miguel, This problem has two parts: adjusting the torsions and visualizing the result. Adjusting the Torsions If you're adjusting the chi angles of an amino acid, then this is easy in Chimera. Each such residue has chi1/chi2/chi3 attributes that you can set, e.g.: for chi1 in range(0, 360, 10): r.chi1 = chi1 for chi2 in range(0, 360, 10): r.chi2 = chi2 for chi3 in range(0, 360, 10): r.chi3 = chi3 do something You'd probably actually want to write the code as a recursive routine, since otherwise it is awkward to handle the fact that some residues have different numbers of chi angles than others. You might also want to change your angle increment based on the recursion depth. If you're changing torsions that aren't the well-known amino acid chi angles, then you'll have to resort to Chimera's more generic torsion- adjustment facilities, the core of which are in the BondRotMgr module. Specifically, if 'b' is the bond you want to adjust, then: from BondRotMgr import bondRotMgr torsion = bondRotMgr.rotationForBond(b) and then torsion.increment(amount) will increment the torsion angle by 'amount' degrees (from its current position). If you want to set the dihedral to a certain value (rather than just increment from the current position) then you will have to measure the dihedral you care about with: chimera.dihedral(a1.xformCoord(), a2.xformCoord(), a3.xformCoord(), a4.xformCoord()) and then use the appropriate increment value, or use chimera.phipsi._setAngle(bond, newAngle, curAngle) [in the latter case you don't have to call rotationForBond yourself]. Visualizing the Result There are a bunch of possibilities of course. I'll touch on two: a bunch of spheres, and an actual volume. 1) As you change the torsion, you can use each atom's .coord() method to get Point instances which can be used to place helium atoms at those positions with BuildStructure.placeHelium(). You could put the heliums in the same model or in a new model (by providing a model name to your first call of placeHelium()). 2) Computing a volume is not too hard conceptually. Basically you decide on a grid spacing and then make a dictionary that maps xyz grid addresses to occupancy counts (omitting counts of zero). Then you find the lower and upper bounds for each axis, create a 3D array with corresponding dimensions, and populate that array with your counts. Then you can open that in Volume Viewer and use all the Volume Viewer facilities to look at the occupancy. There is code that does just this in Movie.gui, it's MovieDialog's computeVolume method. The line: gridData = {} initializes the occupancy-count dictionary and the loop that immediately follows that populates the dictionary. Most of the loop isn't relevant for you (getting the right coordinate set and adjusting for "hold selection steady") but the very end of the loop is, the part that maps coordinates into xyz grid addresses and adjusts the corresponding count. Then after that the loop the "generate volume" and "show volume" sections are largely relevant. --Eric Eric Pettersen UCSF Computer Graphics Lab http://www.cgl.ucsf.edu

Hi Eric, Thanks a lot for your explanations! In fact, I want to do this not for an amino acid side-chain (that was an easy-to-see example) but for a group in a small molecule. so I will need the BondRotMgr module. First, I need to figure out how to select the bonds explicitly in the script. I thought that something like bond1 = selection.OSLSelection(':2.C@C1|:2.C@C2') bond2 = selection.OSLSelection(':2.C@C5|:2.C@C7') (...) would work, but it doesn't. So far I have fond in the examples how to go through all the bonds in a molecule (or a residue) but not how to make a explicit selection of the bond. Is that possible at all or should I go through the molecule (or residue) list of bonds and pick the one I want based on two atom selections? Cheers, Miguel Le 10 mai 2010 à 23:33, Eric Pettersen a écrit :
On May 9, 2010, at 10:14 PM, Miguel Ortiz Lombardia wrote:
Dear all,
I would like to represent as a volume the space that would be covered by a set of atoms that are bound by "torsionable" bonds when one systematically modifies those torsion angles. An example would be the side-chain of an amino acid; imagine I would like to have a glimpse of what part of the space could be occupied by that side-chain. As a first approximation I wouldn't care about clashes.
I would appreciate if someone can point me to an existing way of obtaining such representation or to an algorithm that could be implemented within chimera (which I would be happy to share with other interested people; if I manage to code it, that's it!)
Hi Miguel, This problem has two parts: adjusting the torsions and visualizing the result.
Adjusting the Torsions
If you're adjusting the chi angles of an amino acid, then this is easy in Chimera. Each such residue has chi1/chi2/chi3 attributes that you can set, e.g.:
for chi1 in range(0, 360, 10): r.chi1 = chi1 for chi2 in range(0, 360, 10): r.chi2 = chi2 for chi3 in range(0, 360, 10): r.chi3 = chi3 do something
You'd probably actually want to write the code as a recursive routine, since otherwise it is awkward to handle the fact that some residues have different numbers of chi angles than others. You might also want to change your angle increment based on the recursion depth. If you're changing torsions that aren't the well-known amino acid chi angles, then you'll have to resort to Chimera's more generic torsion-adjustment facilities, the core of which are in the BondRotMgr module. Specifically, if 'b' is the bond you want to adjust, then:
from BondRotMgr import bondRotMgr torsion = bondRotMgr.rotationForBond(b)
and then torsion.increment(amount) will increment the torsion angle by 'amount' degrees (from its current position). If you want to set the dihedral to a certain value (rather than just increment from the current position) then you will have to measure the dihedral you care about with: chimera.dihedral(a1.xformCoord(), a2.xformCoord(), a3.xformCoord(), a4.xformCoord()) and then use the appropriate increment value, or use chimera.phipsi._setAngle(bond, newAngle, curAngle) [in the latter case you don't have to call rotationForBond yourself].
Visualizing the Result
There are a bunch of possibilities of course. I'll touch on two: a bunch of spheres, and an actual volume.
1) As you change the torsion, you can use each atom's .coord() method to get Point instances which can be used to place helium atoms at those positions with BuildStructure.placeHelium(). You could put the heliums in the same model or in a new model (by providing a model name to your first call of placeHelium()).
2) Computing a volume is not too hard conceptually. Basically you decide on a grid spacing and then make a dictionary that maps xyz grid addresses to occupancy counts (omitting counts of zero). Then you find the lower and upper bounds for each axis, create a 3D array with corresponding dimensions, and populate that array with your counts. Then you can open that in Volume Viewer and use all the Volume Viewer facilities to look at the occupancy.
There is code that does just this in Movie.gui, it's MovieDialog's computeVolume method. The line:
gridData = {}
initializes the occupancy-count dictionary and the loop that immediately follows that populates the dictionary. Most of the loop isn't relevant for you (getting the right coordinate set and adjusting for "hold selection steady") but the very end of the loop is, the part that maps coordinates into xyz grid addresses and adjusts the corresponding count. Then after that the loop the "generate volume" and "show volume" sections are largely relevant.
--Eric
Eric Pettersen UCSF Computer Graphics Lab http://www.cgl.ucsf.edu
-- This message has been scanned for viruses and dangerous content by MailScanner, and is believed to be clean.
-- Miguel Architecture et Fonction des Macromolécules Biologiques (UMR6098) CNRS, Universités d'Aix-Marseille I & II Case 932, 163 Avenue de Luminy, 13288 Marseille cedex 9, France Tel: +33(0) 491 82 55 93 Fax: +33(0) 491 26 67 20 e-mail: miguel.ortiz-lombardia@afmb.univ-mrs.fr Web: http://www.pangea.org/mol/spip.php?rubrique2

Ooops, I made a blind reply and my message went to the wrong list. Never mind, I found that this: mybonds = [':2.C@CP3-CPG',':2.C@CPG-OPA'] bondlist = mol.bonds mybondlist = [] for bond in bondlist: if str(bond) in mybonds: mybondlist.append(bond) selects the bonds I want. Perhaps not the most efficient way but it works. Now I can go for the real stuff. Thanks a lot Eric! Miguel Début du message réexpédié :
De : Miguel Ortiz Lombardia <miguel.ortiz-lombardia@afmb.univ-mrs.fr> Date : 11 mai 2010 03:39:47 HAEC À : chimera-dev@cgl.ucsf.edu Objet : Rép : [Chimera-users] Volume covered by a group of atoms
Hi Eric,
Thanks a lot for your explanations! In fact, I want to do this not for an amino acid side-chain (that was an easy-to-see example) but for a group in a small molecule. so I will need the BondRotMgr module.
First, I need to figure out how to select the bonds explicitly in the script. I thought that something like
bond1 = selection.OSLSelection(':2.C@C1|:2.C@C2') bond2 = selection.OSLSelection(':2.C@C5|:2.C@C7') (...)
would work, but it doesn't.
So far I have fond in the examples how to go through all the bonds in a molecule (or a residue) but not how to make a explicit selection of the bond. Is that possible at all or should I go through the molecule (or residue) list of bonds and pick the one I want based on two atom selections?
Cheers,
Miguel
Le 10 mai 2010 à 23:33, Eric Pettersen a écrit :
On May 9, 2010, at 10:14 PM, Miguel Ortiz Lombardia wrote:
Dear all,
I would like to represent as a volume the space that would be covered by a set of atoms that are bound by "torsionable" bonds when one systematically modifies those torsion angles. An example would be the side-chain of an amino acid; imagine I would like to have a glimpse of what part of the space could be occupied by that side-chain. As a first approximation I wouldn't care about clashes.
I would appreciate if someone can point me to an existing way of obtaining such representation or to an algorithm that could be implemented within chimera (which I would be happy to share with other interested people; if I manage to code it, that's it!)
Hi Miguel, This problem has two parts: adjusting the torsions and visualizing the result.
Adjusting the Torsions
If you're adjusting the chi angles of an amino acid, then this is easy in Chimera. Each such residue has chi1/chi2/chi3 attributes that you can set, e.g.:
for chi1 in range(0, 360, 10): r.chi1 = chi1 for chi2 in range(0, 360, 10): r.chi2 = chi2 for chi3 in range(0, 360, 10): r.chi3 = chi3 do something
You'd probably actually want to write the code as a recursive routine, since otherwise it is awkward to handle the fact that some residues have different numbers of chi angles than others. You might also want to change your angle increment based on the recursion depth. If you're changing torsions that aren't the well-known amino acid chi angles, then you'll have to resort to Chimera's more generic torsion-adjustment facilities, the core of which are in the BondRotMgr module. Specifically, if 'b' is the bond you want to adjust, then:
from BondRotMgr import bondRotMgr torsion = bondRotMgr.rotationForBond(b)
and then torsion.increment(amount) will increment the torsion angle by 'amount' degrees (from its current position). If you want to set the dihedral to a certain value (rather than just increment from the current position) then you will have to measure the dihedral you care about with: chimera.dihedral(a1.xformCoord(), a2.xformCoord(), a3.xformCoord(), a4.xformCoord()) and then use the appropriate increment value, or use chimera.phipsi._setAngle(bond, newAngle, curAngle) [in the latter case you don't have to call rotationForBond yourself].
Visualizing the Result
There are a bunch of possibilities of course. I'll touch on two: a bunch of spheres, and an actual volume.
1) As you change the torsion, you can use each atom's .coord() method to get Point instances which can be used to place helium atoms at those positions with BuildStructure.placeHelium(). You could put the heliums in the same model or in a new model (by providing a model name to your first call of placeHelium()).
2) Computing a volume is not too hard conceptually. Basically you decide on a grid spacing and then make a dictionary that maps xyz grid addresses to occupancy counts (omitting counts of zero). Then you find the lower and upper bounds for each axis, create a 3D array with corresponding dimensions, and populate that array with your counts. Then you can open that in Volume Viewer and use all the Volume Viewer facilities to look at the occupancy.
There is code that does just this in Movie.gui, it's MovieDialog's computeVolume method. The line:
gridData = {}
initializes the occupancy-count dictionary and the loop that immediately follows that populates the dictionary. Most of the loop isn't relevant for you (getting the right coordinate set and adjusting for "hold selection steady") but the very end of the loop is, the part that maps coordinates into xyz grid addresses and adjusts the corresponding count. Then after that the loop the "generate volume" and "show volume" sections are largely relevant.
--Eric
Eric Pettersen UCSF Computer Graphics Lab http://www.cgl.ucsf.edu
-- This message has been scanned for viruses and dangerous content by MailScanner, and is believed to be clean.
-- Miguel
Architecture et Fonction des Macromolécules Biologiques (UMR6098) CNRS, Universités d'Aix-Marseille I & II Case 932, 163 Avenue de Luminy, 13288 Marseille cedex 9, France Tel: +33(0) 491 82 55 93 Fax: +33(0) 491 26 67 20 e-mail: miguel.ortiz-lombardia@afmb.univ-mrs.fr Web: http://www.pangea.org/mol/spip.php?rubrique2
-- Miguel Architecture et Fonction des Macromolécules Biologiques (UMR6098) CNRS, Universités d'Aix-Marseille I & II Case 932, 163 Avenue de Luminy, 13288 Marseille cedex 9, France Tel: +33(0) 491 82 55 93 Fax: +33(0) 491 26 67 20 e-mail: miguel.ortiz-lombardia@afmb.univ-mrs.fr Web: http://www.pangea.org/mol/spip.php?rubrique2

On May 11, 2010, at 1:29 AM, Miguel Ortiz Lombardia wrote:
Ooops, I made a blind reply and my message went to the wrong list.
Never mind, I found that this:
mybonds = [':2.C@CP3-CPG',':2.C@CPG-OPA'] bondlist = mol.bonds mybondlist = [] for bond in bondlist: if str(bond) in mybonds: mybondlist.append(bond)
selects the bonds I want. Perhaps not the most efficient way but it works. Now I can go for the real stuff.
Hi Miguel, I'm glad you found something that worked. Your first try didn't work for a couple of reasons: (1) Selections are collective containers like lists, and (2) OSLSelections don't contain bonds. Here's what I would have done: a1, a2 = selection.OSLSelection(':2.C@C1,C2').atoms() bond1 = (set(a1.bonds)|set(a2.bonds)).pop() Basically, use OSLSelection to get the two atoms, then intersect their bond lists. It should be slightly more efficient than your loop (though it probably makes no real difference unless this is going to execute hundreds or thousands of times). The efficiency comes from OSLSelection first finding the residues that match, then finding the atoms in those that match. --Eric
Début du message réexpédié :
De : Miguel Ortiz Lombardia <miguel.ortiz-lombardia@afmb.univ-mrs.fr> Date : 11 mai 2010 03:39:47 HAEC À : chimera-dev@cgl.ucsf.edu Objet : Rép : [Chimera-users] Volume covered by a group of atoms
Hi Eric,
Thanks a lot for your explanations! In fact, I want to do this not for an amino acid side-chain (that was an easy-to-see example) but for a group in a small molecule. so I will need the BondRotMgr module.
First, I need to figure out how to select the bonds explicitly in the script. I thought that something like
bond1 = selection.OSLSelection(':2.C@C1|:2.C@C2') bond2 = selection.OSLSelection(':2.C@C5|:2.C@C7') (...)
would work, but it doesn't.
So far I have fond in the examples how to go through all the bonds in a molecule (or a residue) but not how to make a explicit selection of the bond. Is that possible at all or should I go through the molecule (or residue) list of bonds and pick the one I want based on two atom selections?
participants (2)
-
Eric Pettersen
-
Miguel Ortiz Lombardia