I have tweaked a script by Tsjerk Wassenaar that can remove atoms out of a unit cell. I have encountered 2 problems. First is even though i knew the Atom i wanted to remove from the model i had no easy way to do it because i didn't found any unique identifier for an Atom in the atom class.
So what i did was to treat each object separately. This seems to work.
The other problem is that pymol segfaults with big selections. I think the problem is the number of
logical operations in the selection and not the string size.

Here is the script:

from pymol import cmd
import math

## Determining the determinant of matrix a ##

def det(a):
return a[0][0]*(a[1][1]*a[2][2]-a[2][1]*a[1][2])-a[1][0]*(a[0][1]*a[2][2]-a[2][1]*a[0][2])+a[2][0]*(a[0][1]*a[1][2]-
                                                                                
                        a[1][1]*a[0][2])

## Basic inversion of a 3x3-matrix a ##
def minv(a):
    c = 1/det(a)
    return [[ c*(a[1][1]*a[2][2]-a[2][1]*a[1][2]),
              -c*(a[0][1]*a[2][2]-a[2][1]*a[0][2]),
              c*(a[0][1]*a[1][2]-a[1][1]*a[0][2]) ],
            [ -c*(a[1][0]*a[2][2]-a[2][0]*a[1][2]),
              c*(a[0][0]*a[2][2]-a[2][0]*a[0][2]),
              -c*(a[0][0]*a[1][2]-a[1][0]*a[0][2]) ],
            [ c*(a[1][0]*a[2][1]-a[2][0]*a[1][1]),
              -c*(a[0][0]*a[2][1]-a[2][0]*a[0][1]),
              c*(a[0][0]*a[1][1]-a[1][0]*a[0][1]) ]]

## Multiplying a vector b by matrix a ##
def mvmult(a, b):
    return [ a[0][0]*b[0]+a[0][1]*b[1]+a[0][2]*b[2],
             a[1][0]*b[0]+a[1][1]*b[1]+a[1][2]*b[2],
             a[2][0]*b[0]+a[2][1]*b[1]+a[2][2]*b[2] ]

##############################################
## Protein / image operations ################
##############################################
# p should be the pdb molecule from which the # unit cell information will be derived

def rmoutside(p = None):
    if p == None:
        print '# Error: No box specified! #'
        return
    objects = cmd.get_names("objects")
    cmd.select("out_of_box","none")
    for j in range(len(objects)):
        print objects[j]
        if(cmd.get_type(objects[j]) == "object:molecule"):
            sel = "("+str(objects[j])+")"
            sel = cmd.get_model(sel)
            par = cmd.get_symmetry(p)
            par[3] = par[3]/360*2*math.pi
            par[4] = par[4]/360*2*math.pi
            par[5] = par[5]/360*2*math.pi

            v_a = [par[0],0,0]
            v_b = [math.cos(par[5])*par[1],math.sin(par[5])*par[1],0]
            v_c = [par[2]*math.cos(par[4]),
                   
par[1]*par[2]*math.cos(par[3])-par[2]*math.cos(par[4])*v_b[0],
                   
math.sqrt(par[2]*par[2]-par[2]*math.cos(par[4])*par[2]*math.cos(par[4])-
                             
par[1]*par[2]*math.cos(par[3])-par[2]*math.cos(par[4])*v_b[0]*par[1]*par[2]*math.cos(par[3])-par[2]*math.cos(par[4])*v_b[0])]
            b = [ v_a,v_b,v_c ]

# b should now be a box-matrix: [ [ x1, y1, z1 ], [ x2, y2, z2 ], [ x3, y3, z3 ] ]
            S = [ [b[0][0], b[1][0], b[2][0]],
                  [b[0][1], b[1][1], b[2][1]],
                  [b[0][2], b[1][2], b[2][2]] ]
            T = minv(S)
            list = "out_of_box";
            for i in range(len(sel.atom)):
                sel.atom[i].coord = mvmult(T, sel.atom[i].coord)
if sel.atom[i].coord[0] < 0 or sel.atom[i].coord[0] > 1 or sel.atom[i].coord[1] < 0 or sel.atom[i].coord[1] > 1 or sel.atom[i].coord[2] < 0 or se\
l.atom[i].coord[2] > 1:
list = "(index "+str(sel.atom[i].index)+" and "+str(objects[j])+") or " + list

# this is to try to make sure pymol doesn't seg fault # so when we already have a big list for selection make the selection and empty the list
                    if(len(list) > 2000):
                        cmd.select("out_of_box", list)
                        list = "out_of_box"
                    else:
                        sel.atom[i].coord = mvmult(S, sel.atom[i].coord)
            cmd.select("out_of_box", list)


Reply via email to