<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.pymol.org/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Sunhwan</id>
	<title>PyMOL Wiki - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.pymol.org/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Sunhwan"/>
	<link rel="alternate" type="text/html" href="https://wiki.pymol.org/index.php/Special:Contributions/Sunhwan"/>
	<updated>2026-05-14T14:56:22Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.35.1</generator>
	<entry>
		<id>https://wiki.pymol.org/index.php?title=Plane_Wizard&amp;diff=12935</id>
		<title>Plane Wizard</title>
		<link rel="alternate" type="text/html" href="https://wiki.pymol.org/index.php?title=Plane_Wizard&amp;diff=12935"/>
		<updated>2010-10-04T18:16:32Z</updated>

		<summary type="html">&lt;p&gt;Sunhwan: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;This wizard has a simple purpose - to draw a cgo plane that passes through three points picked by the user. Most of the wizard itself was copied from the measure wizard.&lt;br /&gt;
&lt;br /&gt;
To use, put it in the same directory as the other wizards. This is not quality code, and there may be bugs, but it seems to work okay.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;source lang=&amp;quot;python&amp;quot;&amp;gt;&lt;br /&gt;
import pymol&lt;br /&gt;
from pymol import cmd&lt;br /&gt;
from pymol.wizard import Wizard&lt;br /&gt;
from chempy import cpv&lt;br /&gt;
from pymol.cgo import *&lt;br /&gt;
&lt;br /&gt;
def makePrimitive(cgo, name):&lt;br /&gt;
    cmd.set('auto_zoom', 0, quiet=1)&lt;br /&gt;
    cmd.load_cgo(cgo, name)&lt;br /&gt;
    cmd.set('auto_zoom', 1, quiet=1)&lt;br /&gt;
&lt;br /&gt;
def point(p):&lt;br /&gt;
    x, y, z = p&lt;br /&gt;
    return [COLOR, 1, 1, 1, SPHERE, float(x), float(y), float(z), 0.5]&lt;br /&gt;
&lt;br /&gt;
def line(p1, p2):&lt;br /&gt;
    x1, y1, z1 = p1&lt;br /&gt;
    x2, y2, z2 = p2&lt;br /&gt;
    return [CYLINDER, float(x1), float(y1), float(z1), float(x2), float(y2), float(z2), 0.25, 1, 1, 1, 1, 1, 1]&lt;br /&gt;
&lt;br /&gt;
def plane(corner1, corner2, corner3, corner4, normal):&lt;br /&gt;
    planeObj = []&lt;br /&gt;
    planeObj.extend(point(corner1))&lt;br /&gt;
    planeObj.extend(point(corner2))&lt;br /&gt;
    planeObj.extend(point(corner3))&lt;br /&gt;
    planeObj.extend(point(corner4))&lt;br /&gt;
    planeObj.extend(line(corner1, corner2))&lt;br /&gt;
    planeObj.extend(line(corner2, corner3))&lt;br /&gt;
    planeObj.extend(line(corner3, corner4))&lt;br /&gt;
    planeObj.extend(line(corner4, corner1))&lt;br /&gt;
&lt;br /&gt;
    planeObj.extend([COLOR, 0.8, 0.8, 0.8])&lt;br /&gt;
    planeObj.extend([BEGIN, TRIANGLE_STRIP])&lt;br /&gt;
    planeObj.append(NORMAL)&lt;br /&gt;
    planeObj.extend(normal)&lt;br /&gt;
    for corner in [corner1, corner2, corner3, corner4, corner1]:&lt;br /&gt;
        planeObj.append(VERTEX)&lt;br /&gt;
        planeObj.extend(corner)&lt;br /&gt;
    planeObj.append(END)&lt;br /&gt;
    return planeObj&lt;br /&gt;
&lt;br /&gt;
def planeFromPoints(point1, point2, point3, facetSize):&lt;br /&gt;
    v1 = cpv.normalize(cpv.sub(point2, point1))&lt;br /&gt;
    v2 = cpv.normalize(cpv.sub(point3, point1))&lt;br /&gt;
    normal = cpv.cross_product(v1, v2)&lt;br /&gt;
    v2 = cpv.cross_product(normal, v1)&lt;br /&gt;
    x = cpv.scale(v1, facetSize)&lt;br /&gt;
    y = cpv.scale(v2, facetSize)&lt;br /&gt;
    center = point2&lt;br /&gt;
    corner1 = cpv.add(cpv.add(center, x), y)&lt;br /&gt;
    corner2 = cpv.sub(cpv.add(center, x), y)&lt;br /&gt;
    corner3 = cpv.sub(cpv.sub(center, x), y)&lt;br /&gt;
    corner4 = cpv.add(cpv.sub(center, x), y)&lt;br /&gt;
    return plane(corner1, corner2, corner3, corner4, normal)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
class PlaneWizard(Wizard):&lt;br /&gt;
&lt;br /&gt;
    def __init__(self):&lt;br /&gt;
        Wizard.__init__(self)&lt;br /&gt;
&lt;br /&gt;
        # some attributes to do with picking&lt;br /&gt;
        self.pick_count = 0&lt;br /&gt;
        self.object_count = 0&lt;br /&gt;
        self.object_prefix = &amp;quot;pw&amp;quot;&lt;br /&gt;
&lt;br /&gt;
        # the plane facet size (the 'radius' of the section of plane we show)&lt;br /&gt;
        self.facetSize = 5&lt;br /&gt;
&lt;br /&gt;
        self.selection_mode = cmd.get_setting_legacy(&amp;quot;mouse_selection_mode&amp;quot;)&lt;br /&gt;
        cmd.set(&amp;quot;mouse_selection_mode&amp;quot;,0) # set selection mode to atomic&lt;br /&gt;
        cmd.deselect()&lt;br /&gt;
&lt;br /&gt;
    def reset(self):&lt;br /&gt;
        cmd.delete(self.object_prefix + &amp;quot;*&amp;quot;)&lt;br /&gt;
        cmd.delete(&amp;quot;sele*&amp;quot;)&lt;br /&gt;
        cmd.delete(&amp;quot;_indicate*&amp;quot;)&lt;br /&gt;
        cmd.unpick()&lt;br /&gt;
        cmd.refresh_wizard()&lt;br /&gt;
&lt;br /&gt;
    def delete_all(self):&lt;br /&gt;
        cmd.delete(&amp;quot;plane*&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
    def cleanup(self):&lt;br /&gt;
        cmd.set(&amp;quot;mouse_selection_mode&amp;quot;,self.selection_mode) # restore selection mode&lt;br /&gt;
        self.reset()&lt;br /&gt;
        self.delete_all()&lt;br /&gt;
&lt;br /&gt;
    def get_prompt(self):&lt;br /&gt;
        self.prompt = None&lt;br /&gt;
        if self.pick_count == 0:&lt;br /&gt;
            self.prompt = [ 'Please click on the first atom...']&lt;br /&gt;
        elif self.pick_count == 1:&lt;br /&gt;
            self.prompt = [ 'Please click on the second atom...' ]&lt;br /&gt;
        elif self.pick_count == 2:&lt;br /&gt;
            self.prompt = [ 'Please click on the third atom...' ]&lt;br /&gt;
        return self.prompt&lt;br /&gt;
&lt;br /&gt;
    def do_select(self, name):&lt;br /&gt;
        # &amp;quot;edit&amp;quot; only this atom, and not others with the object prefix&lt;br /&gt;
        try:&lt;br /&gt;
            cmd.edit(&amp;quot;%s and not %s*&amp;quot; % (name, self.object_prefix))&lt;br /&gt;
            self.do_pick(0)&lt;br /&gt;
        except pymol.CmdException, pmce:&lt;br /&gt;
            print pmce&lt;br /&gt;
&lt;br /&gt;
    def pickNextAtom(self, atom_name):&lt;br /&gt;
        # transfer the click selection to a named selection&lt;br /&gt;
        cmd.select(atom_name, &amp;quot;(pk1)&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
        # delete the click selection&lt;br /&gt;
        cmd.unpick()&lt;br /&gt;
&lt;br /&gt;
        # using the magic of indicate, highlight stuff&lt;br /&gt;
        indicate_selection = &amp;quot;_indicate&amp;quot; + self.object_prefix&lt;br /&gt;
        cmd.select(indicate_selection, atom_name)&lt;br /&gt;
        cmd.enable(indicate_selection)&lt;br /&gt;
&lt;br /&gt;
        self.pick_count += 1&lt;br /&gt;
        self.error = None&lt;br /&gt;
&lt;br /&gt;
        # necessary to force update of the prompt&lt;br /&gt;
        cmd.refresh_wizard()&lt;br /&gt;
&lt;br /&gt;
    def do_pick(self, picked_bond):&lt;br /&gt;
&lt;br /&gt;
        # this shouldn't actually happen if going through the &amp;quot;do_select&amp;quot;&lt;br /&gt;
        if picked_bond:&lt;br /&gt;
            self.error = &amp;quot;Error: please select bonds, not atoms&amp;quot;&lt;br /&gt;
            print self.error&lt;br /&gt;
            return&lt;br /&gt;
&lt;br /&gt;
        atom_name = self.object_prefix + str(self.pick_count)&lt;br /&gt;
        if self.pick_count &amp;lt; 2:&lt;br /&gt;
            self.pickNextAtom(atom_name)&lt;br /&gt;
        else:&lt;br /&gt;
            self.pickNextAtom(atom_name)&lt;br /&gt;
&lt;br /&gt;
            point1 = cmd.get_atom_coords(&amp;quot;(%s%s)&amp;quot; % (self.object_prefix, &amp;quot;0&amp;quot;))&lt;br /&gt;
            point2 = cmd.get_atom_coords(&amp;quot;(%s%s)&amp;quot; % (self.object_prefix, &amp;quot;1&amp;quot;))&lt;br /&gt;
            point3 = cmd.get_atom_coords(&amp;quot;(%s%s)&amp;quot; % (self.object_prefix, &amp;quot;2&amp;quot;))&lt;br /&gt;
            plane = planeFromPoints(point1, point2, point3, self.facetSize)&lt;br /&gt;
&lt;br /&gt;
            planeName = &amp;quot;plane-%02d&amp;quot; % self.object_count&lt;br /&gt;
            self.object_count += 1&lt;br /&gt;
            makePrimitive(plane, planeName)&lt;br /&gt;
            cmd.show(&amp;quot;cgo&amp;quot;, &amp;quot;plane*&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
            self.pick_count = 0&lt;br /&gt;
            self.reset()&lt;br /&gt;
&lt;br /&gt;
    def get_panel(self):&lt;br /&gt;
        return [&lt;br /&gt;
            [ 1, 'Plane Wizard',''],&lt;br /&gt;
            [ 2, 'Reset','cmd.get_wizard().reset()'],&lt;br /&gt;
            [ 2, 'Delete All Planes' , 'cmd.get_wizard().delete_all()'],&lt;br /&gt;
            [ 2, 'Done','cmd.set_wizard()'],&lt;br /&gt;
        ]&lt;br /&gt;
&lt;br /&gt;
# create an instance&lt;br /&gt;
&lt;br /&gt;
wiz = PlaneWizard()&lt;br /&gt;
&lt;br /&gt;
# make this the active wizard&lt;br /&gt;
&lt;br /&gt;
cmd.set_wizard(wiz)&lt;br /&gt;
&amp;lt;/source&amp;gt;&lt;br /&gt;
[[Category:Script_Library|Plane Wizard]]&lt;br /&gt;
[[Category:Math_Scripts]]&lt;/div&gt;</summary>
		<author><name>Sunhwan</name></author>
	</entry>
</feed>