<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.pymol.org/index.php?action=history&amp;feed=atom&amp;title=Bounding_Box</id>
	<title>Bounding Box - Revision history</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.pymol.org/index.php?action=history&amp;feed=atom&amp;title=Bounding_Box"/>
	<link rel="alternate" type="text/html" href="https://wiki.pymol.org/index.php?title=Bounding_Box&amp;action=history"/>
	<updated>2026-05-28T01:56:39Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.35.1</generator>
	<entry>
		<id>https://wiki.pymol.org/index.php?title=Bounding_Box&amp;diff=6499&amp;oldid=prev</id>
		<title>Pyadmin: 6 revisions</title>
		<link rel="alternate" type="text/html" href="https://wiki.pymol.org/index.php?title=Bounding_Box&amp;diff=6499&amp;oldid=prev"/>
		<updated>2014-03-28T01:49:04Z</updated>

		<summary type="html">&lt;p&gt;6 revisions&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import math&lt;br /&gt;
from pymol import querying&lt;br /&gt;
from pymol.cgo import *&lt;br /&gt;
from pymol import cmd&lt;br /&gt;
&lt;br /&gt;
#NOTE!! : These packages (numarray, Scientific) must be present in pymol's &lt;br /&gt;
#'$PYMOLDIR/py23/lib/python2.3/site-packages/' directory!!&lt;br /&gt;
# OR..if you are using Mac PyMOL 0.99beta19 or later then the system installs will be used&lt;br /&gt;
from numarray import *&lt;br /&gt;
from numarray.ma import average&lt;br /&gt;
from numarray import linear_algebra as la&lt;br /&gt;
&lt;br /&gt;
from Scientific.Geometry import Vector, Tensor, Transformation&lt;br /&gt;
&lt;br /&gt;
def boundingBox(selectionName, colourRGB=[1,1,1]):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        The main function to call : &lt;br /&gt;
&lt;br /&gt;
                run &amp;quot;box.py&amp;quot;&lt;br /&gt;
                boundingBox(&amp;quot;peptide&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
        Should make a box around &amp;quot;peptide&amp;quot; (assuming it exists!). For a different colour use:&lt;br /&gt;
&lt;br /&gt;
                boundingBox(&amp;quot;peptide&amp;quot;, colourRGB=[1, 0, 1])&lt;br /&gt;
&lt;br /&gt;
        Or whatever. The box should be a cgo called 'peptide-box' (for this example).&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        model = querying.get_model(selectionName)&lt;br /&gt;
        coords = model.get_coord_list()&lt;br /&gt;
&lt;br /&gt;
        #find the least square plane through the coordinates&lt;br /&gt;
        eigenvalues, eigenvectors, centroid = findPlaneWithEigenVectors(coords)&lt;br /&gt;
        normal = eigenvectors[eigenvalues.argmin()]&lt;br /&gt;
        eigenvectors.remove(normal)&lt;br /&gt;
&lt;br /&gt;
        #orient the axes correctly&lt;br /&gt;
        x, y, normal = orientAxes(eigenvectors[0], eigenvectors[1], normal)&lt;br /&gt;
&lt;br /&gt;
        #determine the dimensions and the structure's orientation wrt the origin&lt;br /&gt;
        minDimensions, rotation = findMinDimensionsAndRotation(coords, centroid, x, y, normal)&lt;br /&gt;
&lt;br /&gt;
        #'create' the box(IE: make the corners) and 'draw' it (IE: make a cgo)&lt;br /&gt;
        box = makeBox(minDimensions, rotation, centroid)&lt;br /&gt;
        drawBox(box, selectionName, colourRGB)&lt;br /&gt;
&lt;br /&gt;
def findPlaneWithEigenVectors(coords):&lt;br /&gt;
        centroid = average(coords)&lt;br /&gt;
        coords -= centroid&lt;br /&gt;
        B = matrixmultiply(transpose(coords), coords)&lt;br /&gt;
        eigenvalues, eigenvectors = la.eigenvectors(B)&lt;br /&gt;
        #return eigenvalues, [Vector(e) for e in eigenvectors], Vector(centroid)&lt;br /&gt;
        return eigenvalues, [Vector([i for i in e]) for e in eigenvectors], Vector(centroid) #not sure why I had to make this change!&lt;br /&gt;
&lt;br /&gt;
def orientAxes(x, y, z):&lt;br /&gt;
        XcrossY = x.cross(y)&lt;br /&gt;
        #ZXY = around(math.degrees(z.angle(XcrossY)))&lt;br /&gt;
        ZXY = int(around(math.degrees(z.angle(XcrossY)))) #again, a bit of a hack!&lt;br /&gt;
        if (ZXY == 180): x, y = y, x&lt;br /&gt;
        return x, y, z&lt;br /&gt;
&lt;br /&gt;
def makeBox(dimensions, rotation, centroid):&lt;br /&gt;
        x, y, z = dimensions&lt;br /&gt;
        v = [[]] * 8&lt;br /&gt;
&lt;br /&gt;
        #make a cuboid with the lower corner on the origin&lt;br /&gt;
        v[0] = [0, 0, 0]                # [0, 0, 0]&lt;br /&gt;
        v[1] = [x, 0, 0]                # [1, 0, 0]&lt;br /&gt;
        v[2] = [x, y, 0]                # [1, 1, 0]&lt;br /&gt;
        v[3] = [x, 0, z]                # [1, 0, 1]&lt;br /&gt;
        v[4] = [0, y, 0]                # [0, 1, 0]&lt;br /&gt;
        v[5] = [0, 0, z]                # [0, 0, 1]&lt;br /&gt;
        v[6] = [0, y, z]                # [0, 1, 1]&lt;br /&gt;
        v[7] = [x, y, z]                # [1, 1, 1]&lt;br /&gt;
&lt;br /&gt;
        #move to the origin, THEN move to the centroid of the points, then rotate&lt;br /&gt;
        translationToOrigin = Transformation.Translation(-Vector(x/2, y/2, z/2))&lt;br /&gt;
        translationToCentroid = Transformation.Translation(centroid)&lt;br /&gt;
        transform = translationToCentroid * rotation * translationToOrigin&lt;br /&gt;
&lt;br /&gt;
        #use the Transformation to transform the corners of the box&lt;br /&gt;
        v = [transform(Vector(i)) for i in v]&lt;br /&gt;
&lt;br /&gt;
        bot =  [v[0], v[1], v[2], v[4]] # O, x, xy, y&lt;br /&gt;
        top =  [v[7], v[3], v[5], v[6]] # xyz, xz, z, yz&lt;br /&gt;
        minL = [v[0], v[4], v[6], v[5]] # O, y, yz, z&lt;br /&gt;
        minR = [v[0], v[5], v[3], v[1]] # O, z, xz, x&lt;br /&gt;
        maxL = [v[4], v[2], v[7], v[6]] # y, xy, xyz, yz&lt;br /&gt;
        maxR = [v[3], v[1], v[2], v[7]] # xz, x, xy, xyz&lt;br /&gt;
        box = [bot, minR, minL, maxR, maxL, top]&lt;br /&gt;
&lt;br /&gt;
        return box&lt;br /&gt;
&lt;br /&gt;
def drawBox(box, name, colourRGB):&lt;br /&gt;
        boxObj = []&lt;br /&gt;
        for side in box:&lt;br /&gt;
                boxObj.append(BEGIN)&lt;br /&gt;
                boxObj.append(LINE_STRIP)&lt;br /&gt;
                boxObj.append(COLOR)&lt;br /&gt;
                boxObj.extend(colourRGB)&lt;br /&gt;
                for point in side:&lt;br /&gt;
                        boxObj.append(VERTEX)&lt;br /&gt;
                        boxObj.extend(point)&lt;br /&gt;
                boxObj.append(END)&lt;br /&gt;
&lt;br /&gt;
        cmd.set('auto_zoom', 0)&lt;br /&gt;
        cmd.load_cgo(boxObj, &amp;quot;%s-box&amp;quot; % name)&lt;br /&gt;
        cmd.set('auto_zoom', 1)&lt;br /&gt;
&lt;br /&gt;
def findMinDimensionsAndRotation(coords, centroid, x, y, z):&lt;br /&gt;
        O = Vector(0, 0, 0)&lt;br /&gt;
        X = Vector(1, 0, 0)&lt;br /&gt;
        Y = Vector(0, 1, 0)&lt;br /&gt;
        Z = Vector(0, 0, 1)&lt;br /&gt;
&lt;br /&gt;
        #Create a Transformation t = |x, y, z| . |X, Y, Z| ^ -1&lt;br /&gt;
        mfinal = array([array(X), array(Y), array(Z)])&lt;br /&gt;
        morig = array([array(x), array(y), array(z)])&lt;br /&gt;
        rotmatrix = matrixmultiply(morig, transpose(mfinal))&lt;br /&gt;
        tTotal = Transformation.Rotation(Tensor(rotmatrix))&lt;br /&gt;
&lt;br /&gt;
        #Transform the coordinates and find the min, max dimensions&lt;br /&gt;
        coordArray = array([array(tTotal(Vector(c))) for c in coords])&lt;br /&gt;
        minDimensions = [max(coordArray[:,i]) - min(coordArray[:,i]) for i in range(3)]&lt;br /&gt;
&lt;br /&gt;
        #Now, compose the inverse rotation used to move the bounding box to the right place&lt;br /&gt;
        tForward = Transformation.Rotation(Tensor(matrixmultiply(mfinal, transpose(morig))))&lt;br /&gt;
&lt;br /&gt;
        return minDimensions, tForward&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Script_Library|Bounding Box]]&lt;br /&gt;
[[Category:Math_Scripts]]&lt;/div&gt;</summary>
		<author><name>Pyadmin</name></author>
	</entry>
	<entry>
		<id>https://wiki.pymol.org/index.php?title=Bounding_Box&amp;diff=6497&amp;oldid=prev</id>
		<title>Gilleain: fixed to work again. not sure what has changed!</title>
		<link rel="alternate" type="text/html" href="https://wiki.pymol.org/index.php?title=Bounding_Box&amp;diff=6497&amp;oldid=prev"/>
		<updated>2005-10-20T04:25:20Z</updated>

		<summary type="html">&lt;p&gt;fixed to work again. not sure what has changed!&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import math&lt;br /&gt;
from pymol import querying&lt;br /&gt;
from pymol.cgo import *&lt;br /&gt;
from pymol import cmd&lt;br /&gt;
&lt;br /&gt;
#NOTE!! : These packages (numarray, Scientific) must be present in pymol's &lt;br /&gt;
#'$PYMOLDIR/py23/lib/python2.3/site-packages/' directory!!&lt;br /&gt;
# OR..if you are using Mac PyMOL 0.99beta19 or later then the system installs will be used&lt;br /&gt;
from numarray import *&lt;br /&gt;
from numarray.ma import average&lt;br /&gt;
from numarray import linear_algebra as la&lt;br /&gt;
&lt;br /&gt;
from Scientific.Geometry import Vector, Tensor, Transformation&lt;br /&gt;
&lt;br /&gt;
def boundingBox(selectionName, colourRGB=[1,1,1]):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        The main function to call : &lt;br /&gt;
&lt;br /&gt;
                run &amp;quot;box.py&amp;quot;&lt;br /&gt;
                boundingBox(&amp;quot;peptide&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
        Should make a box around &amp;quot;peptide&amp;quot; (assuming it exists!). For a different colour use:&lt;br /&gt;
&lt;br /&gt;
                boundingBox(&amp;quot;peptide&amp;quot;, colourRGB=[1, 0, 1])&lt;br /&gt;
&lt;br /&gt;
        Or whatever. The box should be a cgo called 'peptide-box' (for this example).&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        model = querying.get_model(selectionName)&lt;br /&gt;
        coords = model.get_coord_list()&lt;br /&gt;
&lt;br /&gt;
        #find the least square plane through the coordinates&lt;br /&gt;
        eigenvalues, eigenvectors, centroid = findPlaneWithEigenVectors(coords)&lt;br /&gt;
        normal = eigenvectors[eigenvalues.argmin()]&lt;br /&gt;
        eigenvectors.remove(normal)&lt;br /&gt;
&lt;br /&gt;
        #orient the axes correctly&lt;br /&gt;
        x, y, normal = orientAxes(eigenvectors[0], eigenvectors[1], normal)&lt;br /&gt;
&lt;br /&gt;
        #determine the dimensions and the structure's orientation wrt the origin&lt;br /&gt;
        minDimensions, rotation = findMinDimensionsAndRotation(coords, centroid, x, y, normal)&lt;br /&gt;
&lt;br /&gt;
        #'create' the box(IE: make the corners) and 'draw' it (IE: make a cgo)&lt;br /&gt;
        box = makeBox(minDimensions, rotation, centroid)&lt;br /&gt;
        drawBox(box, selectionName, colourRGB)&lt;br /&gt;
&lt;br /&gt;
def findPlaneWithEigenVectors(coords):&lt;br /&gt;
        centroid = average(coords)&lt;br /&gt;
        coords -= centroid&lt;br /&gt;
        B = matrixmultiply(transpose(coords), coords)&lt;br /&gt;
        eigenvalues, eigenvectors = la.eigenvectors(B)&lt;br /&gt;
        #return eigenvalues, [Vector(e) for e in eigenvectors], Vector(centroid)&lt;br /&gt;
        return eigenvalues, [Vector([i for i in e]) for e in eigenvectors], Vector(centroid) #not sure why I had to make this change!&lt;br /&gt;
&lt;br /&gt;
def orientAxes(x, y, z):&lt;br /&gt;
        XcrossY = x.cross(y)&lt;br /&gt;
        #ZXY = around(math.degrees(z.angle(XcrossY)))&lt;br /&gt;
        ZXY = int(around(math.degrees(z.angle(XcrossY)))) #again, a bit of a hack!&lt;br /&gt;
        if (ZXY == 180): x, y = y, x&lt;br /&gt;
        return x, y, z&lt;br /&gt;
&lt;br /&gt;
def makeBox(dimensions, rotation, centroid):&lt;br /&gt;
        x, y, z = dimensions&lt;br /&gt;
        v = [[]] * 8&lt;br /&gt;
&lt;br /&gt;
        #make a cuboid with the lower corner on the origin&lt;br /&gt;
        v[0] = [0, 0, 0]                # [0, 0, 0]&lt;br /&gt;
        v[1] = [x, 0, 0]                # [1, 0, 0]&lt;br /&gt;
        v[2] = [x, y, 0]                # [1, 1, 0]&lt;br /&gt;
        v[3] = [x, 0, z]                # [1, 0, 1]&lt;br /&gt;
        v[4] = [0, y, 0]                # [0, 1, 0]&lt;br /&gt;
        v[5] = [0, 0, z]                # [0, 0, 1]&lt;br /&gt;
        v[6] = [0, y, z]                # [0, 1, 1]&lt;br /&gt;
        v[7] = [x, y, z]                # [1, 1, 1]&lt;br /&gt;
&lt;br /&gt;
        #move to the origin, THEN move to the centroid of the points, then rotate&lt;br /&gt;
        translationToOrigin = Transformation.Translation(-Vector(x/2, y/2, z/2))&lt;br /&gt;
        translationToCentroid = Transformation.Translation(centroid)&lt;br /&gt;
        transform = translationToCentroid * rotation * translationToOrigin&lt;br /&gt;
&lt;br /&gt;
        #use the Transformation to transform the corners of the box&lt;br /&gt;
        v = [transform(Vector(i)) for i in v]&lt;br /&gt;
&lt;br /&gt;
        bot =  [v[0], v[1], v[2], v[4]] # O, x, xy, y&lt;br /&gt;
        top =  [v[7], v[3], v[5], v[6]] # xyz, xz, z, yz&lt;br /&gt;
        minL = [v[0], v[4], v[6], v[5]] # O, y, yz, z&lt;br /&gt;
        minR = [v[0], v[5], v[3], v[1]] # O, z, xz, x&lt;br /&gt;
        maxL = [v[4], v[2], v[7], v[6]] # y, xy, xyz, yz&lt;br /&gt;
        maxR = [v[3], v[1], v[2], v[7]] # xz, x, xy, xyz&lt;br /&gt;
        box = [bot, minR, minL, maxR, maxL, top]&lt;br /&gt;
&lt;br /&gt;
        return box&lt;br /&gt;
&lt;br /&gt;
def drawBox(box, name, colourRGB):&lt;br /&gt;
        boxObj = []&lt;br /&gt;
        for side in box:&lt;br /&gt;
                boxObj.append(BEGIN)&lt;br /&gt;
                boxObj.append(LINE_STRIP)&lt;br /&gt;
                boxObj.append(COLOR)&lt;br /&gt;
                boxObj.extend(colourRGB)&lt;br /&gt;
                for point in side:&lt;br /&gt;
                        boxObj.append(VERTEX)&lt;br /&gt;
                        boxObj.extend(point)&lt;br /&gt;
                boxObj.append(END)&lt;br /&gt;
&lt;br /&gt;
        cmd.set('auto_zoom', 0)&lt;br /&gt;
        cmd.load_cgo(boxObj, &amp;quot;%s-box&amp;quot; % name)&lt;br /&gt;
        cmd.set('auto_zoom', 1)&lt;br /&gt;
&lt;br /&gt;
def findMinDimensionsAndRotation(coords, centroid, x, y, z):&lt;br /&gt;
        O = Vector(0, 0, 0)&lt;br /&gt;
        X = Vector(1, 0, 0)&lt;br /&gt;
        Y = Vector(0, 1, 0)&lt;br /&gt;
        Z = Vector(0, 0, 1)&lt;br /&gt;
&lt;br /&gt;
        #Create a Transformation t = |x, y, z| . |X, Y, Z| ^ -1&lt;br /&gt;
        mfinal = array([array(X), array(Y), array(Z)])&lt;br /&gt;
        morig = array([array(x), array(y), array(z)])&lt;br /&gt;
        rotmatrix = matrixmultiply(morig, transpose(mfinal))&lt;br /&gt;
        tTotal = Transformation.Rotation(Tensor(rotmatrix))&lt;br /&gt;
&lt;br /&gt;
        #Transform the coordinates and find the min, max dimensions&lt;br /&gt;
        coordArray = array([array(tTotal(Vector(c))) for c in coords])&lt;br /&gt;
        minDimensions = [max(coordArray[:,i]) - min(coordArray[:,i]) for i in range(3)]&lt;br /&gt;
&lt;br /&gt;
        #Now, compose the inverse rotation used to move the bounding box to the right place&lt;br /&gt;
        tForward = Transformation.Rotation(Tensor(matrixmultiply(mfinal, transpose(morig))))&lt;br /&gt;
&lt;br /&gt;
        return minDimensions, tForward&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
&lt;br /&gt;
[[Category:Script_Library|Bounding Box]]&lt;/div&gt;</summary>
		<author><name>Gilleain</name></author>
	</entry>
	<entry>
		<id>https://wiki.pymol.org/index.php?title=Bounding_Box&amp;diff=6495&amp;oldid=prev</id>
		<title>Tree at 22:15, 8 March 2005</title>
		<link rel="alternate" type="text/html" href="https://wiki.pymol.org/index.php?title=Bounding_Box&amp;diff=6495&amp;oldid=prev"/>
		<updated>2005-03-08T22:15:44Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;table class=&quot;diff diff-contentalign-left diff-editfont-monospace&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 22:15, 8 March 2005&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l127&quot; &gt;Line 127:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 127:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;/source&amp;gt;&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;/source&amp;gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt;−&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #ffe49c; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;[[Category:Scripting_Script_Library|&lt;del class=&quot;diffchange diffchange-inline&quot;&gt;Measure Distance&lt;/del&gt;]]&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt;+&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;[[Category:Scripting_Script_Library|&lt;ins class=&quot;diffchange diffchange-inline&quot;&gt;Bounding Box&lt;/ins&gt;]]&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;</summary>
		<author><name>Tree</name></author>
	</entry>
	<entry>
		<id>https://wiki.pymol.org/index.php?title=Bounding_Box&amp;diff=6494&amp;oldid=prev</id>
		<title>Tree at 22:14, 8 March 2005</title>
		<link rel="alternate" type="text/html" href="https://wiki.pymol.org/index.php?title=Bounding_Box&amp;diff=6494&amp;oldid=prev"/>
		<updated>2005-03-08T22:14:57Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;table class=&quot;diff diff-contentalign-left diff-editfont-monospace&quot; data-mw=&quot;interface&quot;&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;col class=&quot;diff-marker&quot; /&gt;
				&lt;col class=&quot;diff-content&quot; /&gt;
				&lt;tr class=&quot;diff-title&quot; lang=&quot;en&quot;&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;← Older revision&lt;/td&gt;
				&lt;td colspan=&quot;2&quot; style=&quot;background-color: #fff; color: #202122; text-align: center;&quot;&gt;Revision as of 22:14, 8 March 2005&lt;/td&gt;
				&lt;/tr&gt;&lt;tr&gt;&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot; id=&quot;mw-diff-left-l126&quot; &gt;Line 126:&lt;/td&gt;
&lt;td colspan=&quot;2&quot; class=&quot;diff-lineno&quot;&gt;Line 126:&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;         return minDimensions, tForward&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;         return minDimensions, tForward&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;/source&amp;gt;&lt;/div&gt;&lt;/td&gt;&lt;td class='diff-marker'&gt; &lt;/td&gt;&lt;td style=&quot;background-color: #f8f9fa; color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #eaecf0; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&amp;lt;/source&amp;gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot;&gt; &lt;/td&gt;&lt;td class='diff-marker'&gt;+&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;tr&gt;&lt;td colspan=&quot;2&quot;&gt; &lt;/td&gt;&lt;td class='diff-marker'&gt;+&lt;/td&gt;&lt;td style=&quot;color: #202122; font-size: 88%; border-style: solid; border-width: 1px 1px 1px 4px; border-radius: 0.33em; border-color: #a3d3ff; vertical-align: top; white-space: pre-wrap;&quot;&gt;&lt;div&gt;&lt;ins style=&quot;font-weight: bold; text-decoration: none;&quot;&gt;[[Category:Scripting_Script_Library|Measure Distance]]&lt;/ins&gt;&lt;/div&gt;&lt;/td&gt;&lt;/tr&gt;
&lt;/table&gt;</summary>
		<author><name>Tree</name></author>
	</entry>
	<entry>
		<id>https://wiki.pymol.org/index.php?title=Bounding_Box&amp;diff=6493&amp;oldid=prev</id>
		<title>Gilleain at 19:46, 8 March 2005</title>
		<link rel="alternate" type="text/html" href="https://wiki.pymol.org/index.php?title=Bounding_Box&amp;diff=6493&amp;oldid=prev"/>
		<updated>2005-03-08T19:46:07Z</updated>

		<summary type="html">&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import math&lt;br /&gt;
from pymol import querying&lt;br /&gt;
from pymol.cgo import *&lt;br /&gt;
from pymol import cmd&lt;br /&gt;
&lt;br /&gt;
#NOTE!! : These packages (numarray, Scientific) must be present in pymol's &lt;br /&gt;
#'$PYMOLDIR/py23/lib/python2.3/site-packages/' directory!!&lt;br /&gt;
from numarray import *&lt;br /&gt;
from numarray.ma import average&lt;br /&gt;
from numarray import linear_algebra as la&lt;br /&gt;
&lt;br /&gt;
from Scientific.Geometry import Vector, Tensor, Transformation&lt;br /&gt;
&lt;br /&gt;
def boundingBox(selectionName, colourRGB=[1,1,1]):&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        The main function to call : &lt;br /&gt;
&lt;br /&gt;
                run &amp;quot;box.py&amp;quot;&lt;br /&gt;
                boundingBox(&amp;quot;peptide&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
        Should make a box around &amp;quot;peptide&amp;quot; (assuming it exists!). For a different colour use:&lt;br /&gt;
&lt;br /&gt;
                boundingBox(&amp;quot;peptide&amp;quot;, colourRGB=[1, 0, 1])&lt;br /&gt;
&lt;br /&gt;
        Or whatever. The box should be a cgo called 'peptide-box' (for this example).&lt;br /&gt;
        &amp;quot;&amp;quot;&amp;quot;&lt;br /&gt;
        model = querying.get_model(selectionName)&lt;br /&gt;
        coords = model.get_coord_list()&lt;br /&gt;
&lt;br /&gt;
        #find the least square plane through the coordinates&lt;br /&gt;
        eigenvalues, eigenvectors, centroid = findPlaneWithEigenVectors(coords)&lt;br /&gt;
        normal = eigenvectors[eigenvalues.argmin()]&lt;br /&gt;
        eigenvectors.remove(normal)&lt;br /&gt;
&lt;br /&gt;
        #orient the axes correctly&lt;br /&gt;
        x, y, normal = orientAxes(eigenvectors[0], eigenvectors[1], normal)&lt;br /&gt;
&lt;br /&gt;
        #determine the dimensions and the structure's orientation wrt the origin&lt;br /&gt;
        minDimensions, rotation = findMinDimensionsAndRotation(coords, centroid, x, y, normal)&lt;br /&gt;
&lt;br /&gt;
        #'create' the box(IE: make the corners) and 'draw' it (IE: make a cgo)&lt;br /&gt;
        box = makeBox(minDimensions, rotation, centroid)&lt;br /&gt;
        drawBox(box, selectionName, colourRGB)&lt;br /&gt;
&lt;br /&gt;
def findPlaneWithEigenVectors(coords):&lt;br /&gt;
        centroid = average(coords)&lt;br /&gt;
        coords -= centroid&lt;br /&gt;
        B = matrixmultiply(transpose(coords), coords)&lt;br /&gt;
        eigenvalues, eigenvectors = la.eigenvectors(B)&lt;br /&gt;
        return eigenvalues, [Vector(e) for e in eigenvectors], Vector(centroid)&lt;br /&gt;
&lt;br /&gt;
def orientAxes(x, y, z):&lt;br /&gt;
        XcrossY = x.cross(y)&lt;br /&gt;
        ZXY = around(math.degrees(z.angle(XcrossY)))&lt;br /&gt;
        if (ZXY == 180): x, y = y, x&lt;br /&gt;
        return x, y, z&lt;br /&gt;
&lt;br /&gt;
def makeBox(dimensions, rotation, centroid):&lt;br /&gt;
        x, y, z = dimensions&lt;br /&gt;
        v = [[]] * 8&lt;br /&gt;
&lt;br /&gt;
        #make a cuboid with the lower corner on the origin&lt;br /&gt;
        v[0] = [0, 0, 0]                # [0, 0, 0]&lt;br /&gt;
        v[1] = [x, 0, 0]                # [1, 0, 0]&lt;br /&gt;
        v[2] = [x, y, 0]                # [1, 1, 0]&lt;br /&gt;
        v[3] = [x, 0, z]                # [1, 0, 1]&lt;br /&gt;
        v[4] = [0, y, 0]                # [0, 1, 0]&lt;br /&gt;
        v[5] = [0, 0, z]                # [0, 0, 1]&lt;br /&gt;
        v[6] = [0, y, z]                # [0, 1, 1]&lt;br /&gt;
        v[7] = [x, y, z]                # [1, 1, 1]&lt;br /&gt;
&lt;br /&gt;
        #move to the origin, THEN move to the centroid of the points, then rotate&lt;br /&gt;
        translationToOrigin = Transformation.Translation(-Vector(x/2, y/2, z/2))&lt;br /&gt;
        translationToCentroid = Transformation.Translation(centroid)&lt;br /&gt;
        transform = translationToCentroid * rotation * translationToOrigin&lt;br /&gt;
&lt;br /&gt;
        #use the Transformation to transform the corners of the box&lt;br /&gt;
        v = [transform(Vector(i)) for i in v]&lt;br /&gt;
&lt;br /&gt;
        bot =  [v[0], v[1], v[2], v[4]] # O, x, xy, y&lt;br /&gt;
        top =  [v[7], v[3], v[5], v[6]] # xyz, xz, z, yz&lt;br /&gt;
        minL = [v[0], v[4], v[6], v[5]] # O, y, yz, z&lt;br /&gt;
        minR = [v[0], v[5], v[3], v[1]] # O, z, xz, x&lt;br /&gt;
        maxL = [v[4], v[2], v[7], v[6]] # y, xy, xyz, yz&lt;br /&gt;
        maxR = [v[3], v[1], v[2], v[7]] # xz, x, xy, xyz&lt;br /&gt;
        box = [bot, minR, minL, maxR, maxL, top]&lt;br /&gt;
&lt;br /&gt;
        return box&lt;br /&gt;
&lt;br /&gt;
def drawBox(box, name, colourRGB):&lt;br /&gt;
        boxObj = []&lt;br /&gt;
        for side in box:&lt;br /&gt;
                boxObj.append(BEGIN)&lt;br /&gt;
                boxObj.append(LINE_STRIP)&lt;br /&gt;
                boxObj.append(COLOR)&lt;br /&gt;
                boxObj.extend(colourRGB)&lt;br /&gt;
                for point in side:&lt;br /&gt;
                        boxObj.append(VERTEX)&lt;br /&gt;
                        boxObj.extend(point)&lt;br /&gt;
                boxObj.append(END)&lt;br /&gt;
&lt;br /&gt;
        cmd.set('auto_zoom', 0)&lt;br /&gt;
        cmd.load_cgo(boxObj, &amp;quot;%s-box&amp;quot; % name)&lt;br /&gt;
        cmd.set('auto_zoom', 1)&lt;br /&gt;
&lt;br /&gt;
def findMinDimensionsAndRotation(coords, centroid, x, y, z):&lt;br /&gt;
        O = Vector(0, 0, 0)&lt;br /&gt;
        X = Vector(1, 0, 0)&lt;br /&gt;
        Y = Vector(0, 1, 0)&lt;br /&gt;
        Z = Vector(0, 0, 1)&lt;br /&gt;
&lt;br /&gt;
        #Create a Transformation t = |x, y, z| . |X, Y, Z| ^ -1&lt;br /&gt;
        mfinal = array([array(X), array(Y), array(Z)])&lt;br /&gt;
        morig = array([array(x), array(y), array(z)])&lt;br /&gt;
        rotmatrix = matrixmultiply(morig, transpose(mfinal))&lt;br /&gt;
        tTotal = Transformation.Rotation(Tensor(rotmatrix))&lt;br /&gt;
&lt;br /&gt;
        #Transform the coordinates and find the min, max dimensions&lt;br /&gt;
        coordArray = array([array(tTotal(Vector(c))) for c in coords])&lt;br /&gt;
        minDimensions = [max(coordArray[:,i]) - min(coordArray[:,i]) for i in range(3)]&lt;br /&gt;
&lt;br /&gt;
        #Now, compose the inverse rotation used to move the bounding box to the right place&lt;br /&gt;
        tForward = Transformation.Rotation(Tensor(matrixmultiply(mfinal, transpose(morig))))&lt;br /&gt;
&lt;br /&gt;
        return minDimensions, tForward&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;/div&gt;</summary>
		<author><name>Gilleain</name></author>
	</entry>
</feed>