Difference between revisions of "Supercell"

From PyMOLWiki
Jump to navigation Jump to search
(categories)
(symexpcell)
Line 2: Line 2:
  
 
Can display multiple copies of the unit cell.
 
Can display multiple copies of the unit cell.
 +
Can also fill the unit cell (and its copies) with symmetry mates.
  
 
See [http://sourceforge.net/mailarchive/forum.php?thread_name=l2vdcf611bd1004140816zeca28714mf76b9f72008099ab%40mail.gmail.com&forum_name=pymol-users thread on pymol-users mailing list].
 
See [http://sourceforge.net/mailarchive/forum.php?thread_name=l2vdcf611bd1004140816zeca28714mf76b9f72008099ab%40mail.gmail.com&forum_name=pymol-users thread on pymol-users mailing list].
Line 12: Line 13:
 
supercell 2,1,1, 2x19, green
 
supercell 2,1,1, 2x19, green
 
supercell 1,1,2, 2x19, orange, name=super2
 
supercell 1,1,2, 2x19, orange, name=super2
 +
supercell 1,1,2, 2x19, orange, name=super2, withmates=1
 
</source>
 
</source>
  
Line 21: Line 23:
  
 
PyMOL python script (load with `run supercell.py`)
 
PyMOL python script (load with `run supercell.py`)
Usage: See "help supercell"
+
Usage: See "help supercell" and "help symexpcell"
 
'''
 
'''
  
from pymol import cmd, cgo
+
from pymol import cmd, cgo, xray
 
from math import cos, sin, radians, sqrt
 
from math import cos, sin, radians, sqrt
 
import numpy
 
import numpy
Line 43: Line 45:
 
return basis * edges # numpy.array multiplication!
 
return basis * edges # numpy.array multiplication!
  
def supercell(a=1, b=1, c=1, object=None, color='blue', name='supercell'):
+
def supercell(a=1, b=1, c=1, object=None, color='blue', name='supercell', withmates=0):
 
'''
 
'''
 
DESCRIPTION
 
DESCRIPTION
Line 53: Line 55:
 
USAGE
 
USAGE
  
     supercell a, b, c [, object [, color [, name]]]
+
     supercell a, b, c [, object [, color [, name [, withmates]]]]
  
 
ARGUMENTS
 
ARGUMENTS
Line 65: Line 67:
  
 
     name = string: name of the cgo object to create {default: supercell}
 
     name = string: name of the cgo object to create {default: supercell}
 +
 +
    withmates = bool: also create symmetry mates in displayed cells
 +
    {default: 0}
  
 
SEE ALSO
 
SEE ALSO
Line 73: Line 78:
 
if object is None:
 
if object is None:
 
object = cmd.get_object_list()[0]
 
object = cmd.get_object_list()[0]
 +
withmates = int(withmates)
  
 
sym = cmd.get_symmetry(object)
 
sym = cmd.get_symmetry(object)
Line 111: Line 117:
 
obj.append(cgo.VERTEX)
 
obj.append(cgo.VERTEX)
 
obj.extend((shift + vj[j] + vi).tolist())
 
obj.extend((shift + vj[j] + vi).tolist())
 +
 +
if withmates:
 +
symexpcell('m%d%d%d_' % tuple(t), object, *t)
  
 
cmd.delete(name)
 
cmd.delete(name)
 
cmd.load_cgo(obj, name)
 
cmd.load_cgo(obj, name)
  
 +
def symexpcell(prefix='mate', object=None, a=0, b=0, c=0):
 +
'''
 +
DESCRIPTION
 +
 +
    Creates all symmetry-related objects for the specified object that
 +
    occur with their bounding box center within the unit cell.
 +
 +
USAGE
 +
 +
    symexpcell prefix, object, [a, b, c]
 +
 +
ARGUMENTS
 +
 +
    prefix = string: prefix of new objects
 +
 +
    object = string: object for which to create symmetry mates
 +
 +
    a, b, c = integer: create neighboring cell {default: 0,0,0}
 +
 +
SEE ALSO
 +
 +
    symexp
 +
'''
 +
if object is None:
 +
object = cmd.get_object_list()[0]
 +
 +
sym = cmd.get_symmetry(object)
 +
cell_edges = sym[0:3]
 +
cell_angles = sym[3:6]
 +
spacegroup = sym[6]
 +
 +
basis = cellbasis(cell_angles, cell_edges)
 +
basis = numpy.matrix(basis)
 +
 +
extent = cmd.get_extent(object)
 +
center = sum(numpy.array(extent)) * 0.5
 +
center = numpy.matrix(center.tolist() + [1.0]).T
 +
center_cell = basis.I * center
 +
 +
extra_shift = [[float(i)] for i in (a,b,c)]
 +
 +
i = 0
 +
matrices = xray.sg_sym_to_mat_list(spacegroup)
 +
for mat in matrices:
 +
i += 1
 +
 +
mat = numpy.matrix(mat)
 +
shift = numpy.floor(mat * center_cell)
 +
mat[0:3,3] -= shift[0:3,0]
 +
mat[0:3,3] += extra_shift
 +
 +
mat = basis * mat * basis.I
 +
mat_list = list(mat.flat)
 +
 +
name = '%s%d' % (prefix, i)
 +
cmd.create(name, object)
 +
cmd.transform_object(name, mat_list)
 +
cmd.color(i+1, name)
 +
 +
cmd.extend('symexpcell', symexpcell)
 
cmd.extend('supercell', supercell)
 
cmd.extend('supercell', supercell)
 
</source>
 
</source>

Revision as of 05:30, 17 April 2010

Overview

Can display multiple copies of the unit cell. Can also fill the unit cell (and its copies) with symmetry mates.

See thread on pymol-users mailing list.

Example

run supercell.py
fetch 2x19, async=0
supercell 2,1,1, 2x19, green
supercell 1,1,2, 2x19, orange, name=super2
supercell 1,1,2, 2x19, orange, name=super2, withmates=1

The Code

'''
(c) 2010 Thomas Holder

PyMOL python script (load with `run supercell.py`)
Usage: See "help supercell" and "help symexpcell"
'''

from pymol import cmd, cgo, xray
from math import cos, sin, radians, sqrt
import numpy

def cellbasis(angles, edges):
	'''
	For the unit cell with given angles and edge lengths calculate the basis
	transformation (vectors) as a 4x4 numpy.array
	'''
	rad = [radians(i) for i in angles]
	basis = numpy.identity(4)
	basis[0][1] = cos(rad[2])
	basis[1][1] = sin(rad[2])
	basis[0][2] = cos(rad[1])
	basis[1][2] = (cos(rad[0]) - basis[0][1]*basis[0][2])/basis[1][1]
	basis[2][2] = sqrt(1 - basis[0][2]**2 - basis[1][2]**2)
	edges.append(1.0)
	return basis * edges # numpy.array multiplication!

def supercell(a=1, b=1, c=1, object=None, color='blue', name='supercell', withmates=0):
	'''
DESCRIPTION

    Draw a supercell, as requested by Nicolas Bock on the pymol-users
    mailing list (Subject: [PyMOL] feature request: supercell construction
    Date: 04/12/2010 10:12:17 PM (Mon, 12 Apr 2010 14:12:17 -0600))

USAGE

    supercell a, b, c [, object [, color [, name [, withmates]]]]

ARGUMENTS

    a, b, c = integer: repeat cell in x,y,z direction a,b,c times
    {default: 1,1,1}

    object = string: name of object to take cell definition from

    color = string: color of cell {default: blue}

    name = string: name of the cgo object to create {default: supercell}

    withmates = bool: also create symmetry mates in displayed cells
    {default: 0}

SEE ALSO

    show cell

	'''
	if object is None:
		object = cmd.get_object_list()[0]
	withmates = int(withmates)

	sym = cmd.get_symmetry(object)
	cell_edges = sym[0:3]
	cell_angles = sym[3:6]

	basis = cellbasis(cell_angles, cell_edges)
	assert isinstance(basis, numpy.ndarray)

	ts = list()
	for i in range(int(a)):
		for j in range(int(b)):
			for k in range(int(c)):
				ts.append([i,j,k])

	obj = [
		cgo.BEGIN,
		cgo.LINES,
		cgo.COLOR,
	]
	obj.extend(cmd.get_color_tuple(color))
	
	for t in ts:
		shift = basis[0:3,0:3] * t
		shift = shift[:,0] + shift[:,1] + shift[:,2]
	
		for i in range(3):
			vi = basis[0:3,i]
			vj = [
				numpy.array([0.,0.,0.]),
				basis[0:3,(i+1)%3],
				basis[0:3,(i+2)%3],
				basis[0:3,(i+1)%3] + basis[0:3,(i+2)%3]
			]
			for j in range(4):
				obj.append(cgo.VERTEX)
				obj.extend((shift + vj[j]).tolist())
				obj.append(cgo.VERTEX)
				obj.extend((shift + vj[j] + vi).tolist())

		if withmates:
			symexpcell('m%d%d%d_' % tuple(t), object, *t)

	cmd.delete(name)
	cmd.load_cgo(obj, name)

def symexpcell(prefix='mate', object=None, a=0, b=0, c=0):
	'''
DESCRIPTION

    Creates all symmetry-related objects for the specified object that
    occur with their bounding box center within the unit cell.

USAGE

    symexpcell prefix, object, [a, b, c]

ARGUMENTS

    prefix = string: prefix of new objects

    object = string: object for which to create symmetry mates

    a, b, c = integer: create neighboring cell {default: 0,0,0}

SEE ALSO

    symexp
	'''
	if object is None:
		object = cmd.get_object_list()[0]

	sym = cmd.get_symmetry(object)
	cell_edges = sym[0:3]
	cell_angles = sym[3:6]
	spacegroup = sym[6]

	basis = cellbasis(cell_angles, cell_edges)
	basis = numpy.matrix(basis)

	extent = cmd.get_extent(object)
	center = sum(numpy.array(extent)) * 0.5
	center = numpy.matrix(center.tolist() + [1.0]).T
	center_cell = basis.I * center

	extra_shift = [[float(i)] for i in (a,b,c)]

	i = 0
	matrices = xray.sg_sym_to_mat_list(spacegroup)
	for mat in matrices:
		i += 1

		mat = numpy.matrix(mat)
		shift = numpy.floor(mat * center_cell)
		mat[0:3,3] -= shift[0:3,0]
		mat[0:3,3] += extra_shift

		mat = basis * mat * basis.I
		mat_list = list(mat.flat)

		name = '%s%d' % (prefix, i)
		cmd.create(name, object)
		cmd.transform_object(name, mat_list)
		cmd.color(i+1, name)

cmd.extend('symexpcell', symexpcell)
cmd.extend('supercell', supercell)