[Chimera-users] Re: Gaussians
Thomas Goddard
goddard at cgl.ucsf.edu
Wed Dec 10 23:36:11 PST 2003
Hi Lars,
I'm not sure what you mean by visualizing some Gaussians. If you
mean you want to make a volume which contains some specified Gaussians
then I can give you a separate Python program that will do that.
I already wrote it for another user. It is included at the end of
this email. It outputs a netcdf format volume file.
Tom
% ./spots.py
Make a volume array that is the sum of specified Gaussians.
The first line of the input file has the grid cell size.
Each subsequent line has 5 fields giving x, y, z, width, height.
A volume grid is made that includes each Gaussian out to 3 widths.
The resulting volume is written in netcdf format.
Syntax: spots.py <infile> <outfile>
% cat spotfile
.5
15.49100 7.05000 17.16500 0.38 1.00
14.94600 7.55000 15.88800 0.35 1.00
16.01100 7.60400 14.81400 0.34 1.00
...
% ./spots.py spotfile gspottest.nc
The spots.py code follows. Note that it contains a path to your
Chimera installation because it needs Chimera modules to write the
netcdf volume.
#!/usr/bin/env python
# -----------------------------------------------------------------------------
# Make a volume array that is the sum of specified Gaussians.
# The resulting volume is written in netcdf format.
#
# Syntax: spots.py <infile> <outfile>
#
# The input file has a grid cell size on the first line followed by one
# line per gaussian with 5 fields specifying x, y, z, width, height.
#
import os.path
import sys
# Need Chimera path to use VolumeData and Numeric modules
CHIMERA_PATH = '/usr/local/chimera'
sys.path.insert(0, os.path.join(CHIMERA_PATH, 'lib'))
sys.path.insert(0, os.path.join(CHIMERA_PATH, 'share'))
import Numeric
# -----------------------------------------------------------------------------
#
def make_spot_grid(path):
step_size, spot_parameters = read_spots(path)
range = 3 # in spot widths
xyz_min, xyz_max = bounding_box(spot_parameters, range)
xyz_origin = xyz_min
xyz_step = (step_size, step_size, step_size)
xyz_size = map(lambda a,b: a - b, xyz_max, xyz_min)
import math
grid_size = map(lambda s, step, math=math: 1 + int(math.ceil(s/step)),
xyz_size, xyz_step)
a = spot_array(spot_parameters, range, xyz_origin, step_size, grid_size)
from VolumeData import Array_Grid_Data
g = Array_Grid_Data(a, xyz_origin, xyz_step)
return g
# -----------------------------------------------------------------------------
#
def read_spots(path):
f = open(path, 'r')
lines = f.readlines()
f.close()
step_size = float(lines[0])
spot_params = []
for line in lines[1:]:
params = map(float, line.split())
spot_params.append(params)
return step_size, spot_params
# -----------------------------------------------------------------------------
#
def bounding_box(spot_parameters, range):
xmin = ymin = zmin = None
xmax = ymax = zmax = None
for x, y, z, w, h in spot_parameters:
pad = range * w
if xmin == None or x - pad < xmin: xmin = x - pad
if ymin == None or y - pad < ymin: ymin = y - pad
if zmin == None or z - pad < zmin: zmin = z - pad
if xmax == None or x + pad > xmax: xmax = x + pad
if ymax == None or y + pad > ymax: ymax = y + pad
if zmax == None or z + pad > zmax: zmax = z + pad
return (xmin, ymin, zmin), (xmax, ymax, zmax)
# -----------------------------------------------------------------------------
#
def spot_array(spot_parameters, range, xyz_origin, step_size, grid_size):
shape = list(grid_size)
shape.reverse() # array indices are z, y, x.
array = Numeric.zeros(shape, Numeric.Float)
for x, y, z, width, height in spot_parameters:
add_spot((x,y,z), width, height, range, xyz_origin, step_size, array)
return array
# -----------------------------------------------------------------------------
#
def add_spot(xyz, width, height, srange, xyz_origin, step_size, array):
ijk = map(lambda a,b,s=step_size: (a - b)/s, xyz, xyz_origin)
w = width / step_size
w2 = w * w
r = srange * width / step_size
import math
imin, jmin, kmin = map(lambda l, r=r, math=math: int(math.floor(l-r)), ijk)
imax, jmax, kmax = map(lambda l, r=r, math=math: int(math.ceil(l+r)), ijk)
for k in range(kmin, kmax+1):
for j in range(jmin, jmax+1):
for i in range(imin, imax+1):
di, dj, dk = i-ijk[0], j-ijk[1], k-ijk[2]
s2 = di*di + dj*dj + dk*dk
e = height * math.exp(-s2/(2*w2))
array[k,j,i] += e
# -----------------------------------------------------------------------------
#
def bfactor_backbone_spots(path, molecule = None):
if molecule == None:
import chimera
molecule = chimera.openModels.list()[0]
out = open(path, 'w')
out.write('.5\n') # step size
import math
for a in molecule.atoms:
if a.name in ('C', 'N', 'CA') and hasattr(a, 'bfactor'):
x, y, z = a.coord().xyz.data()
w = math.sqrt(a.bfactor / (8 * math.pi**2))
h = 1
out.write('%8.5f %8.5f %8.5f %6.2f %6.2f\n' % (x,y,z,w,h))
out.close()
# -----------------------------------------------------------------------------
#
def syntax():
msg = ('Make a volume array that is the sum of specified Gaussians.\n' +
'The first line of the input file has the grid cell size.\n' +
'Each subsequent line has 5 fields giving x, y, z, width, height.\n' +
'A volume grid is made that includes each Gaussian out to 3 widths.\n' +
'The resulting volume is written in netcdf format.\n' +
'Syntax: spots.py <infile> <outfile>\n')
sys.stderr.write(msg)
sys.exit(1)
# -----------------------------------------------------------------------------
#
def run_command():
if len(sys.argv) != 3:
syntax()
inpath = sys.argv[1]
outpath = sys.argv[2]
grid = make_spot_grid(inpath)
from VolumeData.netcdf.netcdf_grid import write_grid_as_netcdf
write_grid_as_netcdf(grid, outpath)
# -----------------------------------------------------------------------------
#
if __name__ == '__main__':
run_command()
More information about the Chimera-users
mailing list