#! /usr/bin/awk -f
#
#
#	Jiggles a pdb file's coordinates by some random value
#	run like this:
#
#	jigglepdb.awk seed=2343 shift=1.0 old.pdb >! jiggled.pdb
# 	(use a different seed when you want a different output file)
#
BEGIN {

    if(! shift)  shift = 0.5
    if(! Bshift) Bshift = shift
    if(seed) srand(seed+0)
    
    print "REMARK jiggled by dXYZ=", shift, "dB=", Bshift
    print "REMARK random number seed: " seed+0
}

/^ATOM/ || /^HETATM/ {

    if(debug) print tolower($0)

#######################################################################################
    electrons = substr($0, 67,6)
    XPLORSegid = substr($0, 73, 4)    	# XPLOR-style segment ID
    split(XPLORSegid, a)
    XPLORSegid = a[1];
    Element = substr($0, 67)

    Atomnum= substr($0,  7, 5)+0
    Element= substr($0, 13, 2);
    Greek= substr($0, 15, 2);
    split(Element Greek, a)
    Atom   = a[1];
    Conf   = substr($0, 17, 1)		# conformer letter
    Restyp = substr($0, 18, 3)
    Segid  = substr($0, 22, 1)    	# O/Brookhaven-style segment ID
    Resnum = substr($0, 23, 4)+0
    X      = substr($0, 31, 8)+0
    Y      = substr($0, 39, 8)+0
    Z      = substr($0, 47, 8)+0
    Occ    = substr($0, 55, 6)+0
    Bfac   = substr($0, 61, 6)+0
#   rest   = substr($0, 67)
    ATOM   = toupper(substr($0, 1, 6))
#######################################################################################

    # pick a random direction
    norm = 0;
    while(! norm)
    {
	dX = rand()-0.5;
	dY = rand()-0.5;
	dZ = rand()-0.5;
	# calculate its length
	norm = sqrt(dX*dX + dY*dY + dZ*dZ);
    }
    
    # pick a (gaussian) random distance to move
    dR = gaussrand(shift)
    
    # move the atom
    X += dR * dX / norm;
    Y += dR * dY / norm;
    Z += dR * dZ / norm;
    
    # pick a random shift on B-factor
    Bfac += gaussrand(Bshift)
    
    # now print out the new atom
    printf("%6s%5d %2s%-2s%1s%3s %1s%4d     %7.3f %7.3f %7.3f %5.2f%6.2f%4d  %-4s%2s\n",ATOM, Atomnum,Element,Greek,Conf,Restyp,Segid,Resnum,X,Y,Z,Occ,Bfac,electrons,XPLORSegid,Element);	
}

# also print everything else
! /^ATOM/ && ! /^HETATM/



#######################################################################################
# function for producing a random number on a gaussian distribution
function gaussrand(sigma){
    if(! sigma) sigma=1
    rsq=0
    while((rsq >= 1)||(rsq == 0))
    {
	x=2.0*rand()-1.0
	y=2.0*rand()-1.0
	rsq=x*x+y*y
    }
    fac = sqrt(-2.0*log(rsq)/rsq);
    return sigma*x*fac
}

