#! /bin/awk -f # # Generate a superhelix # # This program reads one line from standard input containing 10 numbers (Crick parameters) which have default values: # R0 = 4.809 # superhelical radius (Angstroms) # pitch = -109.642 # superhelical pitch (residues/superturn) # phi = 13.214 # phase of helix vs superhelix (degrees) # helicies = 2 # number of helicies in oligomer # nres = 33 # number of aa residues in each helix # R1 = 2.269 # intra-helical radius (Angstroms) # d = 1.497 # intra-helical rise/residue (Angstroms) # w1 = 101.808 # intra-helical twist/residue (degrees) # W = 0 # rotation of superhelix (degrees) # zc = 0 # z-offset from origin (Angstroms) # # # You may list less than 10 numbers and/or replace one of these numbers with a "-" to use the default value # # Example of how to run it: # echo "4.8 -110 - 3 33 - - - 10 -20 " | awk -f supertwist.awk > test.pdb # # BEGIN{ } { R0 = $1; pitch = $2; phi = $3; helicies = $4; nres = $5; R1 = $6; d = $7; w1 = $8; W = $9; zc = $10; R2 = $11 phi2 = $12 z2 = $13 supertwist(R0,pitch,phi,helicies,nres,R1,d,w1,zc,W) } function supertwist(R0,pitch,phi,helicies,nres,R1,d,w1,zc,W) { PI = 2*atan2(1,0) # "-" indicates default value (GCN4) if(R0 == "-") R0 = "" if(pitch == "-") pitch = "" if(helicies == "-") helicies = "" if(nres == "-") nres = "" if(phi=="-") phi = "" if(zc == "-") zc = "" if(W == "-") W = "" if(R1== "-") R1 = "" if(d == "-") d = "" if(w1== "-") w1 = "" # sensible defaults? (classic gcn4 dimer) if(R0 == "") R0 = 4.809 # superhelical radius (Angstroms) if(pitch == "") pitch = -109.642 # superhelical pitch (residues/superturn) if(helicies == "") helicies = 2 # number of helicies in oligomer if(nres == "") nres = 33 # number of aa residues in each helix if(phi=="") phi = 13.214 # phase of helix vs superhelix (degrees) if(zc == "") zc = 0 # z-offset from origin (Angstroms) if(W == "") W = 0 # rotation of superhelix (degrees) if(R1== "") R1 = 2.269 # helical radius (Angstroms) if(d == "") d = 1.497 # helical rise/residue (Angstroms) if(w1== "") w1 = 101.808 # helical twist/residue (degrees) # convert to radians phi *= PI/180 W *= PI/180 w1 *= PI/180 # superhelical twist/residue if(pitch == "0") w0 = 0 if(pitch+0 != 0) w0 = 2*PI/pitch # sanity check if(w0^2 > (d/R0)^2) { # supertwist is tighter than helical twist print "REMARK WARNING: helical pitch changed to", (2*PI)/w0 w0=d/R0 } if(helicies < 1) helicies = 1 if(nres < 0) nres = -nres if(nres < 1) nres = 1 # helical crossing angle alpha = asin(R0*w0/d) for(i=0;i optional function next_atom(atom1,atom2,atom3, chi, angle, bond) { # default bond angle and length of new bond if(chi == "") chi = 0 if(angle == "") angle = 109.5 if(bond == "") { bond = 1.54 # assume some double-bond character in non-tetrahedral bonds if(angle != 109.5) bond = 1.4 } # compute components of "new_atom"-"atom3" vector, relative to chi==0 defined by "bond1" axis_component["length"] = bond*sin(3.1415927*(angle-90)/180) chi0_component["length"] = -bond*cos(3.1415927*(angle-90)/180)*cos(3.1415927*(chi)/180) chi90_component["length"] = -bond*cos(3.1415927*(angle-90)/180)*sin(3.1415927*(chi)/180) # now we know the coordinates of the new atom vector in "local" coordinates # we need to construct a basis for converting them to "global" coordinates # vector subtration of atoms lying on rotation axis axis["X"] = atom3["X"]-atom2["X"] axis["Y"] = atom3["Y"]-atom2["Y"] axis["Z"] = atom3["Z"]-atom2["Z"] # vector subtraction of atoms defining "zero" rotation around the axis bond1["X"] = atom2["X"]-atom1["X"] bond1["Y"] = atom2["Y"]-atom1["Y"] bond1["Z"] = atom2["Z"]-atom1["Z"] # protect against singular vectors if(((axis["X"]^2 + axis["Y"]^2 + axis["Z"]^2) == 0)||((bond1["X"]^2 + bond1["Y"]^2 + bond1["Z"]^2)==0)) { new_atom["X"] = 0; new_atom["Y"] = 0; new_atom["Z"] = 0; return 0 } # normalize the "axis" vector axis["length"] = sqrt( (axis["X"]*axis["X"]) + ( axis["Y"]*axis["Y"]) + (axis["Z"]*axis["Z"])); axis["X"] = axis["X"]/axis["length"] axis["Y"] = axis["Y"]/axis["length"] axis["Z"] = axis["Z"]/axis["length"] axis["length"] = 1 # compute amount of "bond1" that needs to be removed in order to orthogonalize it to "axis" bond1_dot_axis = ( (axis["X"]*bond1["X"]) + (axis["Y"]*bond1["Y"]) + (axis["Z"]*bond1["Z"]) ) # Dot product # subtract the projection from bond1 bond1["X"] = bond1["X"] - bond1_dot_axis*axis["X"] bond1["Y"] = bond1["Y"] - bond1_dot_axis*axis["Y"] bond1["Z"] = bond1["Z"] - bond1_dot_axis*axis["Z"] # normalize the "bond1" vector to make the "chi0" reference vector bond1["length"] = sqrt((bond1["X"]*bond1["X"]) + (bond1["Y"]*bond1["Y"]) +(bond1["Z"]*bond1["Z"]) ); chi0["X"] = bond1["X"]/bond1["length"] chi0["Y"] = bond1["Y"]/bond1["length"] chi0["Z"] = bond1["Z"]/bond1["length"] chi0["length"] = 1 # now make the "other" basis vector to complete the right-handed, # orthonormal basis, using a cross-product chi90["X"] = axis["Y"] * chi0["Z"] - axis["Z"] * chi0["Y"]; chi90["Y"] = axis["Z"] * chi0["X"] - axis["X"] * chi0["Z"]; chi90["Z"] = axis["X"] * chi0["Y"] - axis["Y"] * chi0["X"]; # we now have three unit vectors forming a basis of rotation about the "atom2-atom3" bond # the "axis" component of the new atom, offset from atom3, will be 0.514A out along "axis" axis_component["X"] = axis_component["length"]*axis["X"] axis_component["Y"] = axis_component["length"]*axis["Y"] axis_component["Z"] = axis_component["length"]*axis["Z"] # apply the "x-y" values from the given chi angle chi0_component["X"] = chi0_component["length"]*chi0["X"] chi0_component["Y"] = chi0_component["length"]*chi0["Y"] chi0_component["Z"] = chi0_component["length"]*chi0["Z"] chi90_component["X"] = chi90_component["length"]*chi90["X"] chi90_component["Y"] = chi90_component["length"]*chi90["Y"] chi90_component["Z"] = chi90_component["length"]*chi90["Z"] # now generate a "new" atom, in the original coordinate system new_atom["X"] = atom3["X"] + axis_component["X"] + chi0_component["X"] + chi90_component["X"] new_atom["Y"] = atom3["Y"] + axis_component["Y"] + chi0_component["Y"] + chi90_component["Y"] new_atom["Z"] = atom3["Z"] + axis_component["Z"] + chi0_component["Z"] + chi90_component["Z"] return 1 } function asin(_sin) { #print "atan2("_sin","sqrt(1-_sin*_sin)")="atan2(_sin,sqrt(1-_sin*_sin)) return atan2(_sin,sqrt(1-_sin*_sin)) }