CCL Home Page
Up Directory CCL stercalc.c
/**************************************************************************/
/**************************************************************************/
/**************************   "steric"   **********************************/
/**************************************************************************/
/*************     Program to calculate ligand cone    ********************/
/*************     angles as a measure of steric size  ********************/
/**************************************************************************/
/**************************************************************************/

/**************************************************************************/
/******************  main calculation routines   **************************/
/**************************************************************************/
/******************        This module is        **************************/
/******************      system independant      **************************/
/**************************************************************************/

#include 
#include 
#include 
#include 
#include 

#include "sterdefn.h"      /* declaration of structures and globals       */
#include "stercomm.h"      /* definitions of all menu command options     */
#include "sterfile.h"      /* file input and output functions             */
#include "stergrp.h"       /* file with group dependant functions         */
#include "stercalc.h"      /* main calculation routines                   */
#include "stermem.h"       /* dynamic memory management module            */
#include "stertext.h"      /* all text functions for text mode            */
#include "steraid.h"       /* additional functions needed                 */
#include "craig.h"         /* functions for craig solid angle             */
#include "proja.h"         /* functions for projected area                */
#include "leach.h"         /* functions for old leach solid angle         */
#include "sterover.h"      /* steric overlap (VAO and SAO) calculations   */

#ifdef _RYAN_
#include "ryan.h"          /* functions for ryan solid angle              */
#endif

/**************************************************************************/
/**************************************************************************/

void Initialize_Steric_Parameter(Ster *ster, char *name, char type
                                 ,double min, double max)
{
  strcpy(ster->name,name); /* steric parameter name                       */
  ster->type=type;         /* type of calculation performed               */
  ster->tot_val=0.0;       /* total value of steric parameter             */
  ster->err_val=0.0;       /* calculated maximum error, if any            */
  ster->tot_con=0.0;       /* conformer average steric parameter          */
  ster->err_con=0.0;       /* calculated maximum error of conf. average   */
  ster->max_val=0.0;       /* maximum value in profile                    */
  ster->pr_area=0.0;       /* area under radial profile                   */
  ster->peak_R=0.0;        /* radius at profile peak                      */
  ster->min=min;
  ster->max=max;           /* min and max profile range                   */
  ster->size=0;            /* array size                                  */
  ster->val=NULL;          /* pointer to profile array                    */
  ster->conf=NULL;         /* pointer to individual conformer memory      */
/* next and prev pointers have already been assigned, do not fiddle !!!   */
}

/**************************************************************************/

Ster *Get_Steric_Type(Ster *ster, char *name, char type, Set *set)
{
  Ster *current=NULL;
  if((ster!=NULL)&&(ster->type==type)) return(ster);
  for(current=First_Steric(ster);current!=NULL;current=current->next)
  {
    if(current->type==type) return(current);
  }
  if(current==NULL)
  {
    if((current=New_Steric(ster))!=NULL)
    {
      if(type==S_ANGU)
        Initialize_Steric_Parameter(current,name,type,set->a_min,set->a_max);
      else
        Initialize_Steric_Parameter(current,name,type,set->min,set->max);
    }
    else return(ster);
  }
  return(current);
}

/**************************************************************************/

Ster *Which_Ster(char arg, Ster *ster, Set *set)
{
  Ster *S=NULL;
  switch(arg)
  {
    case ANGU : S=Get_Steric_Type(ster,S_ANGUS,S_ANGU,set); break;
    case CONE : S=Get_Steric_Type(ster,S_CONES,S_CONE,set); break;
    case TOLM : S=Get_Steric_Type(ster,S_TOLMS,S_TOLM,set); break;
    case OLDL : S=Get_Steric_Type(ster,S_OLDLS,S_OLDL,set); break;
    case RYAN : S=Get_Steric_Type(ster,S_RYANS,S_RYAN,set); break;
    case CRAI : S=Get_Steric_Type(ster,S_CRAIS,S_CRAI,set); break;
    case NUME : S=Get_Steric_Type(ster,S_NUMES,S_NUME,set); break;
    case VAOV : S=Get_Steric_Type(ster,S_VAOVS,S_VAOV,set); break;
    case SAOV : S=Get_Steric_Type(ster,S_SAOVS,S_SAOV,set); break;
    case VOLM : S=Get_Steric_Type(ster,S_VOLMS,S_VOLM,set); break;
    case PROJ : S=Get_Steric_Type(ster,S_PROJS,S_PROJ,set); break;
    default   : return(NULL);
  }
  return(S);
}

/**************************************************************************/
/**************************************************************************/

void Set_Projected_XY(Mol *M, double theta, double phi)
{
  int n=0;
  Atms *at=NULL;
  Vector Y;

  Y=unit_vector(cross_product(M->plane,M->plane_x));
  for(at=First_Atom(M->atoms),n=0;at!=NULL;at=at->next)
  {
    n++; if(n>M->num_atoms) Error_Message(E_ATMNUM,"Set Projected XY");
    if(at->stat&MAIN_BIT)
    {
      at->tv.x=cos(theta)*dot_product(at->v,M->plane_x);
      at->tv.y=cos(phi)*dot_product(at->v,Y);
      at->tv.z=0.0;
      at->tradius=at->radius;
    }
  }
}

/**************************************************************************/

void Set_Total_SVAngles(Mol *M)
{
  int n=0;
  Atms *at=NULL;
  double dis=0.0, rad=0.0;

  for(at=First_Atom(M->atoms),n=0;at!=NULL;at=at->next)
  {
    n++; if(n>M->num_atoms) Error_Message(E_ATMNUM,"Set Total SVAngles");
    if(at->stat&MAIN_BIT)
    {
      dis=at->distance;
      rad=at->radius;
      if (rad==0) at->SVangle=0.0;
      else if (rad>dis) at->SVangle=PI;
      else if (rad==dis) at->SVangle=PI_2;
      else at->SVangle=asin(rad/dis);
    }
    else at->SVangle=0.0;
    if(at->SVangle>=PI) Error_Message(E_SVTOBG,"Set Total SVAngles");
  }
}

/**************************************************************************/

void Set_Radial_SVAngles(Mol *M, double Prad)
{
  Atms *at=NULL;
  int n=0;
  double dis=0.0, rad=0.0;

  for(at=First_Atom(M->atoms),n=0;at!=NULL;at=at->next)
  {
    n++; if(n>M->num_atoms) Error_Message(E_ATMNUM,"Set Radial SVAngles");
    if(at->stat&MAIN_BIT)
    {
      dis=at->distance;
      rad=at->radius;
      if (rad==0) at->SVangle=0.0;
      else if ((Prad>(dis-rad))&&(Prad<(dis+rad)))
      at->SVangle=cosrule_angle(Prad,dis,rad);
      else at->SVangle=0.0;
    }
    else at->SVangle=0.0;
    if(at->SVangle>=PI) Error_Message(E_SVTOBG,"Set Radial SVAngles");
  }
}

/**************************************************************************/

int Get_Theta_Positions(Mol *M)
{
  Vector V={0.0,0.0,0.0};
  double D=0.0;
  Atms *at=NULL;
  int n=0;

  if((M==NULL)||(M->atoms==NULL)) return(0);
  if((M->main_atom!=NULL)
   &&(Vcmp(M->main_atom->v,Vequal(0.0,0.0,0.0))))
  {
    V=unit_vector(M->main_atom->v);
  }
  else 
  {
    for(at=First_Atom(M->atoms),n=0;at!=NULL;at=at->next)
    {
      n++; if(n>M->num_atoms) Error_Message(E_ATMNUM,"Get Theta Positions");
      if(!AlmostZero(at->SVangle))
      {
        V=Vsum(V,at->v);
        D+=at->distance;
      }
    }
    D/=(double)n;
    V=SxV(1.0/(double)n,V);
    if(Vmag(V)atoms)->v;
    V=unit_vector(V);
  }
  for(at=First_Atom(M->atoms),n=0;at!=NULL;at=at->next)
  {
    n++; if(n>M->num_atoms) Error_Message(E_ATMNUM,"Get Theta Positions");
    if(!AlmostZero(at->SVangle)) at->theta=VangleV(V,at->v);
  }
  M->basis_z=VequalV(V);
  return(1);
}

/**************************************************************************/
/*******************  cone angle aids  ************************************/
/**************************************************************************/

double Find_Total_Cone(Mol *M)
{
  Atms *at=NULL;
  double T=0.0;
  int n=0;

  for(at=First_Atom(M->atoms),n=0;at!=NULL;at=at->next)
  {
    n++; if(n>M->num_atoms) Error_Message(E_ATMNUM,"Find Total Cone");
    if(!AlmostZero(at->SVangle)) T=fmax(T,at->SVangle+at->theta);
  }
  return(T);
}

/**************************************************************************/

double calc_cone(double alpha, double theta, double phi, double Pang)
{
  double T,D,a,b,c;
  double sin_cone,cos_cone;

  if(alpha<=0.0) return(0.0);
/*  if(phi>=PI) phi=phi-2*PI;  */
  if(AlmostZero(theta)) return(alpha);

  T=sin(theta)*(cos(phi)*cos(Pang)+sin(phi)*sin(Pang));
  a=T*T+cos(theta)*cos(theta);
  b=-2*T*cos(alpha);
  c=cos(alpha)*cos(alpha)-cos(theta)*cos(theta);
  D=b*b-4*a*c;
  if(D<0.0)
  {
    if(!AlmostZero(D)) return(0.0);
    else D=0.0;
  }
  else D=sqrt(D);

/* check that correct root is chosen out of two possible intersepts       */ 
  if(phi>Pang+PI) phi-=2*PI;
  if(phiPI/2.0) D*=-1.0;

  sin_cone=(D-b)/(2*a);
  if(sin_cone<0.0) return(0.0);

  b=-2*cos(theta)*cos(alpha);
  c=cos(alpha)*cos(alpha)-T*T;
  D=b*b-4*a*c;
  if(D<0.0)
  {
    if(!AlmostZero(D)) return(0.0);
    else D=0.0;
  }
  else D=sqrt(D);
 
/* check that correct root is chosen out of two possible intersepts       */ 
  if(phi>Pang+PI) phi-=2*PI;
  if(phiPI/2.0) D*=-1.0;

  cos_cone=(-D-b)/(2*a);

  return(acos(cos_cone));
}

/**************************************************************************/
/*******************  steric value calculations  **************************/
/**************************************************************************/

double Find_Min_Cone(Mol *M, double Pang)
{
  double cone=0.0;
  Atms *at=NULL;
  int n=0;

  for(at=First_Atom(M->atoms),n=0;at!=NULL;at=at->next)
  {
    n++; if(n>M->num_atoms) Error_Message(E_ATMNUM,"Find Min Cone");
    cone=fmax(cone,calc_cone(at->SVangle,at->theta,at->phi,Pang));
  }
  return(cone);
}

/**************************************************************************/

double Single_Atom_Solid_Angle(Atms *atoms, unsigned mode)
{
  double solid;
  char line[100];
  if (atoms->SVangle==PI) solid=2*PI;
  else if (atoms->SVangle>PI) solid=4*PI;
  else solid=2*(PI)*(1-cos(atoms->SVangle));  /*<- single atom solid angle*/
  if(mode&VIS_BIT)
  {
    sprintf(line,"single(%s[%d]): [%f]",atoms->name,Get_Atom_Number(atoms),solid);
    Out_Message(line,O_BLANK);
  }
  return(solid);
}

/**************************************************************************/
/*******************  main menu options  **********************************/
/**************************************************************************/

double Cone(Mol *M, Ster *ster)
{
  ster->tot_val=2.0*Find_Total_Cone(M);
  ster->err_val=0.0;
  return(ster->tot_val);
}

/**************************************************************************/

double Tolman(Mol *M, Ster *ster)
{
  ster->tot_val=Find_Max_Group_SVangles(M);
  ster->err_val=0.0;
  return(ster->tot_val);
}

/**************************************************************************/

double Solid_Leach(Mol *M, Ster *ster, Set *set, unsigned mode)
{
  ster->tot_val=Craig_Counting(M,set->eps,mode);
  ster->err_val=set->eps;
  return(ster->tot_val);
}

/**************************************************************************/

double Solid_Ryan(Mol *M, Ster *ster, Set *set, unsigned mode)
{
  ster->tot_val=0.0;
#ifdef _RYAN_
  ster->tot_val=Convert_To_NSA(M,set->eps,mode);
#endif
  ster->err_val=set->eps;
  return(ster->tot_val);
}

/**************************************************************************/

double Solid_Craig(Mol *M, Ster *ster, Set *set, unsigned mode)
{
  ster->tot_val=New_Craig_Counting(M,set->eps,mode);
  ster->err_val=set->eps;
  return(ster->tot_val);
}

/**************************************************************************/

double Molecular_Projection(Mol *M, Ster *ster, Set *set, unsigned mode)
{
  ster->tot_val=New_Craig_Counting_P(M,mode);
  ster->err_val=set->eps;
  return(ster->tot_val);
}

/**************************************************************************/

double VA_Overlap(Mol *M, Ster *ster, Set *set, unsigned mode)
{
  ster->tot_val=Steric_Overlap(M,set,mode);
  ster->err_val=0.0;
  return(ster->tot_val);
}

/**************************************************************************/

double SA_Overlap(Mol *M, Ster *ster, Set *set, unsigned mode)
{
  ster->tot_val=Steric_Overlap(M,set,mode|SA_OV);
  ster->err_val=set->eps;
  return(ster->tot_val);
}

/**************************************************************************/

int Find_Encompassing_Box(Mol *M, int gnum, Vector *min, Vector *max, Vector *d)
{
  Vector average={0.0,0.0,0.0};
  Atms *A=NULL;
  double V=0.0;
  char line[LINELEN];
  int count;
  Grps *group=NULL;

  if(M==NULL) return(0);
  if((gnum)&&((group=Goto_Group(M->groups,gnum))==NULL)) gnum=0;
  if((gnum)&&(group->main==NULL)) gnum=0;

/* find centre of molecule */

  for(A=First_Atom(M->atoms),count=0;A!=NULL;A=A->next)
  {
    if(((A->stat&MAIN_BIT)&&(gnum==0))||(gnum==A->group))
    {
      average=Vsum(average,A->v);
      count++;
    }
  }
  if(count==0) return(0);
  average=SxV(1.0/(double)count,average);
  min->x=average.x;  max->x=average.x;
  min->y=average.y;  max->y=average.y;
  min->z=average.z;  max->z=average.z;

/* find encompassing box */

  for(A=First_Atom(M->atoms),count=0;A!=NULL;count++,A=A->next)
  {
    if(((A->stat&MAIN_BIT)&&(gnum==0))||(gnum==A->group))
    {
      if(min->x>A->v.x-A->radius) min->x=A->v.x-A->radius;
      if(max->xv.x+A->radius) max->x=A->v.x+A->radius;

      if(min->y>A->v.y-A->radius) min->y=A->v.y-A->radius;
      if(max->yv.y+A->radius) max->y=A->v.y+A->radius;

      if(min->z>A->v.z-A->radius) min->z=A->v.z-A->radius;
      if(max->zv.z+A->radius) max->z=A->v.z+A->radius;
    }
  }
  if(gnum)                            /* make sure box encompasses sphere */
  {
    if(min->x>group->main->v.x-group->volrad) min->x=group->main->v.x-group->volrad;
    if(max->xmain->v.x+group->volrad) max->x=group->main->v.x+group->volrad;

    if(min->y>group->main->v.y-group->volrad) min->y=group->main->v.y-group->volrad;
    if(max->ymain->v.y+group->volrad) max->y=group->main->v.y+group->volrad;

    if(min->z>group->main->v.z-group->volrad) min->z=group->main->v.z-group->volrad;
    if(max->zmain->v.z+group->volrad) max->z=group->main->v.z+group->volrad;
  }

  d->x=max->x-min->x; d->y=max->y-min->y; d->z=max->z-min->z;
  V=d->x*d->y*d->z;

  sprintf(line,"average x=%f y=%f z=%f",average.x,average.y,average.z);
  Out_Message(line,O_NEWLN);
  sprintf(line,"min     x=%f y=%f z=%f",min->x,min->y,min->z);
  Out_Message(line,O_NEWLN);
  sprintf(line,"max     x=%f y=%f z=%f",max->x,max->y,max->z);
  Out_Message(line,O_NEWLN);
  sprintf(line,"D       x=%f y=%f z=%f",d->x,d->y,d->z);
  Out_Message(line,O_NEWLN);
  sprintf(line,"V=%f",V);
  Out_Message(line,O_NEWLN);
  
  return(1);
}

/**************************************************************************/

int Vector_In_Cell(Mol *M, Vector *p)
{
  Vector h={0.0,0.0,0.0};
  Atms *A=NULL;
  double v2=0.0;
  
  for(A=First_Atom(M->atoms);A!=NULL;A=A->next)
  {
    if(strcmp(A->type,"A")==0)
    {
      v2=Vmag(A->v);
      v2*=v2;
      switch(A->name[1])
      {
        case '1' : h.x=dot_product(A->v,*p)/v2; break;
        case '2' : h.y=dot_product(A->v,*p)/v2; break;
        case '3' : h.z=dot_product(A->v,*p)/v2; break;
        default  : break;
      }
    }
  }
  if((h.x>=0.0)&&(h.x<1.0)
   &&(h.y>=0.0)&&(h.y<1.0)
   &&(h.z>=0.0)&&(h.z<1.0)) return(1);
  return(0);
}

/**************************************************************************/

int Vector_In_Sphere(Mol *M, Vector *p, int gnum)
{
  Grps *group=NULL;
  if(gnum<0) gnum*=-1;
  if(gnum==0) return(1);
  if((group=Goto_Group(M->groups,gnum))==NULL) return(1);
  if(AlmostZero(group->volrad)) return(1);
  if(group->main==NULL) return(1);
  if(Vmag(Vdif(group->main->v,*p))>group->volrad) return(0);
  return(1);
}

/**************************************************************************/

int Test_Atoms_Volume(Mol *M, int gnum, Vector *p, int count)
{
  Atms *A=NULL;

  if(gnum<0)
  {
    count++;
    for(A=First_Atom(M->atoms);A!=NULL;A=A->next)
    {
      if(!A->stat&MAIN_BIT) continue;
      if(-1*gnum==A->group) continue;
      if(Vmag(Vdif(A->v,*p))radius)
      {
        count--;
        break;
      }
    }
  }
  else if(gnum==0)
  {
    for(A=First_Atom(M->atoms);A!=NULL;A=A->next)
    {
      if((A->stat&MAIN_BIT)
       &&(Vmag(Vdif(A->v,*p))radius))
      {
        count++;
        break;
      }
    }
  }
  else
  {
    for(A=First_Atom(M->atoms);A!=NULL;A=A->next)
    {
      if((A->stat&MAIN_BIT)
       &&(gnum==A->group)
       &&(Vmag(Vdif(A->v,*p))radius))
      {
        count++;
        break;
      }
    }
  }
  return(count);
}

/**************************************************************************/

double Monte_Carlo_Volume(Mol *M, Set *set, int gnum
                         ,Vector *min, Vector *d, unsigned mode)
{
  Vector p={0.0,0.0,0.0};
  double V,v=0.0;
  long count=0,i=0,n=0,o=0,l=0;
  time_t t,tp;
  char line[LINELEN];
  double T_val=0.0;
  double tot_val=0.0;
  double dat_val=0.0;
  double cel_val=0.0;
  double sph_val=0.0;

  V=d->x*d->y*d->z;
  t=time(&t);
  tp=t;
  srand(t);
  while(imaxmcv)
  {
    i++;
    p.x=min->x+((double)rand()/(double)RAND_MAX)*d->x;
    p.y=min->y+((double)rand()/(double)RAND_MAX)*d->y;
    p.z=min->z+((double)rand()/(double)RAND_MAX)*d->z;
    if((mode==VOL_UC)&&(!Vector_In_Cell(M,&p))) continue;
    o++;
    if((mode==VOL_RD)&&(!Vector_In_Sphere(M,&p,gnum))) continue;
    n++;
    count=Test_Atoms_Volume(M,gnum,&p,count);
    dat_val=V*(double)count/(double)i;
    t=time(&t);
    if(t-tp>set->tgap)
    {
      tp=t;
      sprintf(line,"n= %ld in N= %ld -> V= %f",count,i,dat_val);
      Out_Message(line,O_NEWLN);
    }
    if(i>set->avmmcv)
    {
      l++;
      T_val+=dat_val;
      v=tot_val;
      tot_val=T_val/(double)(l);
      if((i>set->minmcv)
       &&(!AlmostZero(tot_val))
       &&(fabs(v-tot_val)/tot_valveps)) break;
    }
  }
  sprintf(line,"Data   n= %ld in N= %ld -> V= %f",count,i,tot_val);
  Out_Message(line,O_NEWLN);
  cel_val=V*(double)o/(double)i;
  sprintf(line,"Cell   n= %ld in N= %ld -> V= %f",o,i,cel_val);
  Out_Message(line,O_NEWLN);
  sph_val=V*(double)n/(double)i;
  sprintf(line,"Sphere n= %ld in N= %ld -> V= %f",n,i,sph_val);
  Out_Message(line,O_NEWLN);
  return(tot_val);
}

/**************************************************************************/

double Fixed_Grid_Volume(Mol *M, Set *set, int gnum, Vector *min, Vector *max
                        ,Vector *d, long *total, unsigned mode)
{
  Vector p={0.0,0.0,0.0};
  double V,v=0.0;
  long count=0,i=0,n=0,o=0;
  char line[LINELEN];
  double tot_val=0.0;
  double cel_val=0.0;
  double sph_val=0.0;

  V=d->x*d->y*d->z;
  d->x/=set->vx; d->y/=set->vy; d->z/=set->vz;
  v=d->x*d->y*d->z;
  
  count=0;
  for(i=0,p.x=min->x;p.x<=max->x;p.x+=d->x)
  {
    for(p.y=min->y;p.y<=max->y;p.y+=d->y)
    {
      for(p.z=min->z;p.z<=max->z;p.z+=d->z,i++)
      {
        if((mode==VOL_UC)&&(!Vector_In_Cell(M,&p))) continue;
        o++;
        if((mode==VOL_RD)&&(!Vector_In_Sphere(M,&p,gnum))) continue;
        n++;
        count=Test_Atoms_Volume(M,gnum,&p,count);
      }
    }
  }
  tot_val=V*(double)count/(double)i;
  *total=i;
  sprintf(line,"Data   n= %ld in N= %ld -> V= %f",count,i,tot_val);
  Out_Message(line,O_NEWLN);
  cel_val=V*(double)o/(double)i;
  sprintf(line,"Cell   n= %ld in N= %ld -> V= %f",o,i,cel_val);
  Out_Message(line,O_NEWLN);
  sph_val=V*(double)n/(double)i;
  sprintf(line,"Sphere n= %ld in N= %ld -> V= %f",n,i,sph_val);
  Out_Message(line,O_NEWLN);
  return(tot_val);
}

/**************************************************************************/

double Molecular_Volume(Mol *M, Ster *ster, Set *set, Grps *group)
{
  Vector min={0.0,0.0,0.0}, max={0.0,0.0,0.0}, d={0.0,0.0,0.0};
  double V;
  long total;
  double tot_val=0.0;
  double err_val=0.0;
  int gnum=0;
  unsigned mode=0;

  if(group!=NULL) gnum=Get_Group_Number(group);
  if((gnum>0)&&(group->volrad>0.0)) mode=VOL_RD;

/* find encompassing box */

  Find_Encompassing_Box(M,gnum,&min,&max,&d);
  if((group!=NULL)&&(group->mode&CAVV_BIT)) gnum*=-1;

/* choose two ways of calulating volume */

  if(set->mode&MTC_BIT)   /* Monte Carlo approach */
  {
    tot_val=Monte_Carlo_Volume(M,set,gnum,&min,&d,mode);
    err_val=set->veps;
  }
  else                    /* systemmatic approach */
  {
    tot_val=Fixed_Grid_Volume(M,set,gnum,&min,&max,&d,&total,mode);
    err_val=V/(double)total;
  }

  if(ster!=NULL)
  {
    ster->tot_val=tot_val;
    ster->err_val=err_val;
  }
  if(group!=NULL)
  {
    if(group->mode&CAVV_BIT)
    {
      if(group->mode&RADV_BIT) group->radcav=tot_val;
      else group->cavity=tot_val;
    }
    else group->volume=tot_val;
  }
  return(tot_val);
}

/**************************************************************************/

double Solid_Numerical(Mol *M, Ster *ster, Set *set, double Prad)
{
  int n=0;
  double cone=0.0;
  double Pang=0.0;
  double total[2]={0.0,0.0};
  double gap;

  gap=2*PI/(double)(set->n_size);
  for(n=0;nn_size;n++)
  {
    Pang=gap*n;
    cone=Find_Min_Cone(M,Pang);
    if(set->contour!=NULL)
      fprintf(set->contour,"%10.6f %10.6f %10.6f\n",Prad,Pang,cone);
    total[0]+=(1.0-cos(cone))*gap;
    if((n/2)*2==n) total[1]+=(1.0-cos(cone))*2*gap;
  }
  if((set->contour!=NULL)&&(set->mode&PERS_BIT)) fprintf(set->contour,"\n");
  ster->tot_val=total[0];
  ster->err_val=fabs(total[1]-total[0]);
  return(ster->tot_val);
}

/**************************************************************************/
/**************************************************************************/
/**************************************************************************/

int Calc_Total_Steric(Mol *M, Ster *ster, Set *set, unsigned mode)
{
  char perc='%';
  char line[LINELEN];

  sprintf(line,"Calculating total %s for %s ligand",ster->name,M->name);
  Out_Message(line,O_NEWLN);
  Set_Projected_XY(M,M->plane_T,M->plane_P);
  Set_Total_SVAngles(M);
  switch(mode)
  {
    case CONE : Cone(M,ster); break;
    case TOLM : Tolman(M,ster); break;
    case OLDL : Solid_Leach(M,ster,set,VIS_BIT|((MOVG_BIT|SCOR_BIT)&set->mode)); break;
    case RYAN : Solid_Ryan(M,ster,set,VIS_BIT); break;
    case CRAI : Solid_Craig(M,ster,set,VIS_BIT); break;
    case NUME : Solid_Numerical(M,ster,set,0.0); break;
    case VAOV : VA_Overlap(M,ster,set,VIS_BIT); break;
    case SAOV : SA_Overlap(M,ster,set,VIS_BIT); break;
    case VOLM : Molecular_Volume(M,ster,set,NULL); break;
    case PROJ : Molecular_Projection(M,ster,set,VIS_BIT); break;
    default   : return(0);
  }
  if((mode==CONE)||(mode==TOLM)||(mode==VAOV))
    sprintf(line,"Total %s for %s: %8.5f(%7.5f)rad %6.2fdeg %4.0f%c circle"
                ,ster->name,M->name
                ,ster->tot_val,ster->err_val,RtoD(ster->tot_val)
                ,100.0*ster->tot_val/(PI*2),perc);
  else if(mode==VOLM)
    sprintf(line,"Total %s for %s: %8.5f(%7.5f)cubic angstroms"
                ,ster->name,M->name
                ,ster->tot_val,ster->err_val);
  else if(mode==PROJ)
    sprintf(line,"Total %s for %s: %8.5f(%7.5f)square angstroms"
                ,ster->name,M->name
                ,ster->tot_val,ster->err_val);
  else
    sprintf(line,"Total %s for %s: %8.5f(%7.5f)sr %6.2fdeg %4.0f%c sphere"
                ,ster->name,M->name
                ,ster->tot_val,ster->err_val,StoD(ster->tot_val)
                ,100.0*ster->tot_val/(PI*4),perc);
  Out_Message(line,O_NEWLN);
  return(1);
}

/**************************************************************************/
/**************************************************************************/
/**************************************************************************/

int Calc_Radial_Profile(Mol *M, Ster *ster, Set *set, unsigned mode)
{
  char perc='%';
  int n=0;
  double value=0.0;
  double area=0.0;
  double tot_old=0.0;
  double err_old=0.0;
  double Prad=0.0;
  double gap=0.0;
  char line[LINELEN];

  New_Profile(ster,set->size);
  if(!ster->size) return(0);
  if(set->mode&RSET_BIT)
  {
    ster->min=set->min;
    ster->max=set->max;
  }
  else if(set->mode&RDEF_BIT)
  {
    ster->min=M->minR;
    ster->max=M->maxR;
  }
  ster->max_val=0.0;

  sprintf(line,"Calculating the %s radial profile for %s ligand",ster->name,M->name);
  Out_Message(line,O_NEWLN);

  tot_old=ster->tot_val;
  err_old=ster->err_val;
  gap=(ster->max-ster->min)/(ster->size-1);
  for(n=0;nsize;n++)
  {
    Prad=ster->min+gap*n;
    Set_Radial_SVAngles(M,Prad);
    switch(mode)
    {
      case CONE : value=Cone(M,ster); break;
      case TOLM : value=Tolman(M,ster); break;
      case OLDL : value=Solid_Leach(M,ster,set,(MOVG_BIT|SCOR_BIT)&set->mode); break;
      case RYAN : value=Solid_Ryan(M,ster,set,0); break;
      case CRAI : value=Solid_Craig(M,ster,set,0); break;
      case NUME : value=Solid_Numerical(M,ster,set,Prad); break;
      case VAOV : value=VA_Overlap(M,ster,set,0); break;
      case SAOV : value=SA_Overlap(M,ster,set,0); break;
      default   : return(0);
    }
    area+=value*gap;
    ster->val[n]=value;
    if(ster->max_valmax_val=value;
      ster->peak_R=Prad;
    }
    ster->max_val=fmax(ster->max_val,value);
    if((mode==CONE)||(mode==TOLM)||(mode==VAOV))
      sprintf(line,"\r%-3d, %-8s: %s at %6.3f Angstroms is %6.3f radians  ",
        ster->size-n-1,M->name,ster->name,Prad,value);
    else
      sprintf(line,"\r%-3d, %-8s: %s at %6.3f Angstroms is %6.3f steradians  ",
        ster->size-n-1,M->name,ster->name,Prad,value);
    Out_Message(line,O_CARET);
  }
  ster->tot_val=tot_old;
  ster->err_val=err_old;
  ster->pr_area=area;
  if((mode==CONE)||(mode==TOLM)||(mode==VAOV))
  {
    sprintf(line,"Maximum %s for %s was %8.5frad %6.2fdeg %4.0f%c circle"
                ,ster->name,M->name,ster->max_val,RtoD(ster->max_val)
                ,100.0*ster->max_val/(PI*2),perc);
    Out_Message(line,O_NEWLN);
    sprintf(line,"Area under %s profile for %s was %8.5frad.angstroms"
                ,ster->name,M->name,ster->pr_area);
    Out_Message(line,O_NEWLN);
  }
  else
  {
    sprintf(line,"Maximum %s for %s was %8.5fsr %6.2fdeg %4.0f%c sphere"
                ,ster->name,M->name,ster->max_val,StoD(ster->max_val)
                ,100.0*ster->max_val/(PI*4),perc);
    Out_Message(line,O_NEWLN);
    sprintf(line,"Area under %s profile for %s was %8.5fsr.angstroms"
                ,ster->name,M->name,ster->pr_area);
    Out_Message(line,O_NEWLN);
  }
  sprintf(line,"Radius at %s profile peak for %s was %8.5fangstroms"
              ,ster->name,M->name,ster->peak_R);
  Out_Message(line,O_NEWLN);
  if((!AlmostZero(ster->tot_val))&&(ster->max_val>ster->tot_val))
  {
    Error_Message(E_MTOBIG,"Calc Radial Profile");
    if(mode==OLDL) Error_Message(E_MTBOLD,"Calc Radial Profile");
  }
  if(ster->max_val<0.0) Error_Message(E_MTOSML,"Calc Radial Profile");
  return(1);
}

/**************************************************************************/

int Calc_Angular_Profile(Mol *M, Ster *ster, Set *set)
{
  char perc='%';
  int n=0;
  double cone=0.0;
  double Pang=0.0;
  double total[2]={0.0,0.0};
  double error=0.0;
  double gap=0.0;
  char line[LINELEN];

  New_Profile(ster,set->size);
  if(!ster->size) return(0);
  if(set->mode&RSET_BIT)
  {
    ster->min=set->a_min;
    ster->max=set->a_max;
  }
  else if(set->mode&RDEF_BIT)
  {
    ster->min=0.0;
    ster->max=2*PI;
  }
  ster->max_val=0.0;

  sprintf(line,"Calculating the %s angular profile for %s ligand",ster->name,M->name);
  Out_Message(line,O_NEWLN);

  Set_Total_SVAngles(M);

  gap=(ster->max-ster->min)/((double)ster->size);
  for(n=0;nsize;n++)
  {
    Pang=ster->min+n*gap;
    cone=Find_Min_Cone(M,Pang);
    ster->val[n]=cone;
    ster->max_val=fmax(ster->max_val,cone);
    total[0]+=(1.0-cos(cone))*gap;
    if((n/2)*2==n) total[1]+=(1.0-cos(cone))*2*gap;
    sprintf(line,"\r%-3d, %-8s: Cone-angle at %6.3f Radians is %6.3f radians ",
	ster->size-n-1,M->name,Pang,cone);
    Out_Message(line,O_CARET);
  }
  error=fabs(total[1]-total[0]);
  sprintf(line,"Maximum %s for %s was %8.5frad %6.2fdeg %4.0f%c circle"
              ,ster->name,M->name,ster->max_val,RtoD(ster->max_val)
              ,100.0*ster->max_val/(PI*2),perc);
  Out_Message(line,O_NEWLN);
  sprintf(line,"Total Solid Angle for %s: %8.5f(%7.5f)sr %4.0f%c sphere"
		,M->name,total[0],error,100.0*total[0]/(PI*4),perc);
  Out_Message(line,O_NEWLN);
  if((!AlmostZero(ster->tot_val))&&(ster->max_val>ster->tot_val))
    Error_Message(E_MTOBIG,"Calc Angular Profile");
  if(ster->max_val<0.0) Error_Message(E_MTOSML,"Calc Angular Profile");
  return(1);
}

/**************************************************************************/

int Calc_Projection_Map(Mol *M, Ster *ster, Set *set)
{
  char perc='%';
  int n=0;
  double cone=0.0;
  double Pang=0.0;
  double total[2]={0.0,0.0};
  double error=0.0;
  double gap=0.0;
  char line[LINELEN];

  New_Profile(ster,set->size);
  if(!ster->size) return(0);
  if(set->mode&RSET_BIT)
  {
    ster->min=set->a_min;
    ster->max=set->a_max;
  }
  else if(set->mode&RDEF_BIT)
  {
    ster->min=0.0;
    ster->max=2*PI;
  }
  ster->max_val=0.0;

  sprintf(line,"Calculating the %s angular profile for %s ligand",ster->name,M->name);
  Out_Message(line,O_NEWLN);

  Set_Total_SVAngles(M);

  gap=(ster->max-ster->min)/((double)ster->size);
  for(n=0;nsize;n++)
  {
    Pang=ster->min+n*gap;
    cone=Find_Min_Cone(M,Pang);
    ster->val[n]=cone;
    ster->max_val=fmax(ster->max_val,cone);
    total[0]+=(1.0-cos(cone))*gap;
    if((n/2)*2==n) total[1]+=(1.0-cos(cone))*2*gap;
    sprintf(line,"\r%-3d, %-8s: Cone-angle at %6.3f Radians is %6.3f radians ",
	ster->size-n-1,M->name,Pang,cone);
    Out_Message(line,O_CARET);
  }
  error=fabs(total[1]-total[0]);
  sprintf(line,"Maximum %s for %s was %8.5frad %6.2fdeg %4.0f%c circle"
              ,ster->name,M->name,ster->max_val,RtoD(ster->max_val)
              ,100.0*ster->max_val/(PI*2),perc);
  Out_Message(line,O_NEWLN);
  sprintf(line,"Total Solid Angle for %s: %8.5f(%7.5f)sr %4.0f%c sphere"
		,M->name,total[0],error,100.0*total[0]/(PI*4),perc);
  Out_Message(line,O_NEWLN);
  if((!AlmostZero(ster->tot_val))&&(ster->max_val>ster->tot_val))
    Error_Message(E_MTOBIG,"Calc Angular Profile");
  if(ster->max_val<0.0) Error_Message(E_MTOSML,"Calc Angular Profile");
  return(1);
}

/**************************************************************************/
/**************************************************************************/
/**************************************************************************/

int Calculate_Areas_OneD(Mol *M, Set *set, char mode)
{
  int n=0;
  double area=0.0;
  double angle=0.0;
  double maxang=0.0;
  double gap=0.0;
  char line[LINELEN];
  char name[LINELEN];
  Ster *ster=NULL;

  if((ster=Which_Ster(PROJ,M->ster,set))==NULL) return(0);
  M->ster=ster;
  if(mode==PHIP) New_Profile(ster,set->p_size);
  else           New_Profile(ster,set->t_size);
  if(!ster->size) return(0);
  ster->max_val=0.0;

  switch(mode)
  {
    case PHIP :
      ster->min=M->plane_minP;
      ster->max=M->plane_maxP;
      M->plane_P=M->plane_maxP;
      strcpy(name,"Phi");
      break;
    default :
      ster->min=M->plane_minT;
      ster->max=M->plane_maxT;
      M->plane_T=M->plane_maxT;
      strcpy(name,"Theta");
      break;
  }

  sprintf(line,"Calculating the %s vs %s 1D profile for %s ligand",ster->name,name,M->name);
  Out_Message(line,O_NEWLN);

  gap=(ster->max-ster->min)/((double)ster->size);
  for(n=0;nsize;n++)
  {
    angle=ster->min+n*gap;
    if(mode==PHIP) Set_Projected_XY(M,M->plane_T,angle);
    else           Set_Projected_XY(M,angle,M->plane_P);
    area=Molecular_Projection(M,ster,set,0);
    ster->val[n]=area;
    if(area>ster->max_val)
    {
      ster->max_val=area;
      maxang=angle;
    }
    sprintf(line,"%-3d, %-8s: Projected area at %6.3f radians is %6.3f square angstroms ",
	ster->size-n-1,M->name,angle,area);
    Out_Message(line,O_CARET);
  }
  sprintf(line,"Maximum %s for %s was %8.5f square angstroms at %6.3f radians"
              ,ster->name,M->name,ster->max_val,maxang);
  Out_Message(line,O_NEWLN);
  if(ster->max_val<0.0) Error_Message(E_MTOSML,"Calculate Areas OneD");
  return(1);
}

/**************************************************************************/

int Calculate_Areas_TwoD(Mol *M, Set *set)
{
  int n=0,l=0;
  double area=0.0;
  double theta=0.0, phi=0.0;
  double maxtheta=0.0, maxphi=0.0;
  double gapT=0.0;
  double gapP=0.0;
  char line[LINELEN];
  Ster *ster=NULL;

  if((ster=Which_Ster(PROJ,M->ster,set))==NULL) return(0);
  M->ster=ster;
  New_Profile(ster,set->p_size*set->t_size);
  if(!ster->size) return(0);
  ster->min=M->plane_minT*M->plane_minP;
  ster->max=M->plane_maxT*M->plane_maxP;
  ster->max_val=0.0;

  sprintf(line,"Calculating the %s vs theta and phi 2D profile for %s ligand",ster->name,M->name);
  Out_Message(line,O_NEWLN);

  gapT=(M->plane_maxT-M->plane_minT)/((double)set->t_size);
  gapP=(M->plane_maxP-M->plane_minP)/((double)set->p_size);
  for(n=0;nt_size;n++)
  {
    theta=M->plane_minT+n*gapT;
    for(l=0;lp_size;l++)
    {
      phi=M->plane_minP+l*gapP;
      if(n*l>=ster->size) Error_Message(E_EXRANG,"Calculate Areas TwoD");
      Set_Projected_XY(M,theta,phi);
      area=Molecular_Projection(M,ster,set,0);
      ster->val[n]=area;
      if(area>ster->max_val)
      {
        ster->max_val=area;
        maxtheta=theta;
        maxphi=phi;
      }
      sprintf(line,"%-6d, %-8s: Projected area at (%6.3f,%6.3f) is %6.3f square angstroms ",
	ster->size-n*set->p_size-l-1,M->name,theta,phi,area);
      Out_Message(line,O_CARET);
    }
  }
  M->plane_T=theta;
  M->plane_P=phi;
  sprintf(line,"Maximum %s for %s was %8.5f square angstroms at %6.3f x %6.3f"
              ,ster->name,M->name,ster->max_val,maxtheta,maxphi);
  Out_Message(line,O_NEWLN);
  if(ster->max_val<0.0) Error_Message(E_MTOSML,"Calculate Areas TwoD");
  return(1);
}

/**************************************************************************/
/**************************************************************************/
/**************************************************************************/

int Calc_Conformer_Average(Mol *M, Ster *ster, Set *set, unsigned mode)
{
  Conf *first=NULL;
  Conf *current=NULL;
  Conf *prev=NULL;
  Atms *at=NULL;
  unsigned n,i,num;
  double Ec=0.0, value=0.0, temp=0.0, mole=0.0;
  double tot_tmp=0.0, err_tmp=0.0;
  char line[LINELEN];
  char Tname[50];
  unsigned fmode=F_CONFOR;
  FILE *TF;
  int Natoms;
  char s[30][9];
  Vector V={0.0,0.0,0.0};
  long fpos=0;

  if(M==NULL) return(0);
  if((at=First_Atom(M->atoms))==NULL) return(0);
  strcpy(Tname,M->Fname);
  New_Extension(Tname,".trj");
  if((TF=Open_Input_File(Tname,&fmode))==NULL)
  {
    sprintf(line,"Enter name of trajectory file : ");
    Get_Input_Line(line,set->input);
    if((TF=Open_Input_File(Tname,&fmode))==NULL)
    {
      Error_Message(E_CONFOP,"Calc Conformer Average");
      return(0);
    }
  }
  if(fmode!=F_CONFOR)
  {
    fclose(TF);
    Error_Message(E_NOTCNF,"Calc Conformer Average");
    return(0);
  }

  if(ster->conf!=NULL) ster->conf=Close_All_Conformers(ster->conf);
  get_next_line(TF,"Totmovatm:",line);
  sscanf(line,"%s%d",s[0],&Natoms);
  if(Natoms!=M->num_atoms)
  {
    Error_Message(E_CONFAT,"Calc Conformer Average");
    fclose(TF);
    return(0);
  }

  sprintf(line,"Calculating the individual conformer %ss",ster->name);
  Out_Message(line,O_NEWLN);

  tot_tmp=ster->tot_val;
  err_tmp=ster->err_val;
  if(M->origin!=NULL) V=VequalV(M->origin->v);
  for(i=1;(fpos=get_next_line(TF,"Time:",line))!=0;fseek(TF,fpos,0),i++)
  {
	if(fgets(line,148,TF)==NULL) break;
	if(fgets(line,148,TF)==NULL) break;
    if(sscanf(line,"%lf%lf",&temp,&Ec)<2) break;
    if(!get_next_line(TF,"Cordinat:",line)) break;

    for(num=0;num1) sscanf(line+9,"%d%lf%lf%lf%d%lf%lf%lf"
	    ,&num,&(Goto_Atom(at,num+1)->v.x),&(Goto_Atom(at,num+1)->v.y),&(Goto_Atom(at,num+1)->v.z)
	    ,&num,&(Goto_Atom(at,num+2)->v.x),&(Goto_Atom(at,num+2)->v.y),&(Goto_Atom(at,num+2)->v.z));
      else sscanf(line+9,"%d%lf%lf%lf"
	    ,&num,&(Goto_Atom(at,num+1)->v.x),&(Goto_Atom(at,num+1)->v.y),&(Goto_Atom(at,num+1)->v.z));
	  if((fgets(line,148,TF)==NULL)||(num>Natoms)) break;
    }
                         /* clear the atomic count for counting algorithm */

    for(at=First_Atom(M->atoms),n=0;at!=NULL;at=at->next)
    {
      n++; if(n>M->num_atoms) Error_Message(E_ATMNUM,"Calc Conformer Average");
      at->count=0;
    }
    if((at=First_Atom(M->atoms))==NULL) break;

                         /* calculate the relevant steric parameter value */

    if(M->origin) V=VequalV(M->origin->v);
    Calculate_Parameters(M,V,set);
    Set_Total_SVAngles(M);
    value=0.0;
    switch(mode)
    {
      case CONE : value=Cone(M,ster); break;
      case TOLM : value=Tolman(M,ster); break;
      case OLDL : value=Solid_Leach(M,ster,set,(MOVG_BIT|SCOR_BIT)&set->mode); break;
      case RYAN : value=Solid_Ryan(M,ster,set,0); break;
      case CRAI : value=Solid_Craig(M,ster,set,0); break;
      case NUME : value=Solid_Numerical(M,ster,set,0.0); break;
      case VAOV : value=VA_Overlap(M,ster,set,0); break;
      case SAOV : value=SA_Overlap(M,ster,set,0); break;
      default   : break;
    }
                  /* store steric value, conformer energy and temperature */

    if((current=New_Conformer(current))==NULL) break;
    if(ster->conf==NULL) ster->conf=current;
    current->value=value;
    current->Ec=Ec;
    current->temperature=temp;
    current->mol=0.0;
    sprintf(line,"%-3d, %-8s: value= %f  (Ec=%7.4f)"
	            ,i,M->name,value,Ec);
    Out_Message(line,O_NEWLN);
  }
  ster->tot_val=tot_tmp;
  ster->err_val=err_tmp;
  value=0.0;
  temp=0.0;
  sprintf(line,"Calculating the current molar ratios for %s ligand",M->name);
  Out_Message(line,O_NEWLN);
  if((first=First_Conformer(current))==NULL)
  {
    fclose(TF);
    return(0);
  }
  for(current=first,i=1;current!=NULL;current=current->next,i++)
  {
    mole=0.0;
    for(prev=first;prev!=NULL;prev=prev->next)
    {
      mole+=pow(E,(current->Ec-prev->Ec)/(GAS*current->temperature));
    }
    mole=1/(mole);
    temp+=mole;
    current->mol=mole;
    value+=current->value*mole;
    sprintf(line,"%-3d, %-8s: (mol=%8.6f)*(value=%8.6f)  =>  %8.6f sr "
	            ,i,M->name,mole,current->value,current->value*mole);
    Out_Message(line,O_NEWLN);
  }
  Out_Message("",O_NEWLN);
  ster->conf=first;
  ster->tot_con=value/temp;
  ster->err_con=0.0;

  sprintf(line,"Tot          : (value=%8.6f)/(mol=%8.6f)  =>  %8.6f sr"
	          ,value,temp,ster->tot_con);
  Out_Message(line,O_NEWLN);

  if((mode==CONE)||(mode==TOLM)||(mode==VAOV))
    sprintf(line,"Conformer Averaged %s for %s is %f radians (%f *2pi)\n"
	            ,ster->name,M->name,ster->tot_con,ster->tot_con/(2*PI));
  else
    sprintf(line,"Conformer Averaged %s for %s is %f steradians (%f *4pi)\n"
	            ,ster->name,M->name,ster->tot_con,ster->tot_con/(4*PI));
  Out_Message(line,O_NEWLN);
  return(1);
}


/**************************************************************************/
/******************  The End ...  *****************************************/
/**************************************************************************/

Modified: Fri Dec 8 17:00:00 1995 GMT
Page accessed 1105 times since Sat Apr 17 22:00:04 1999 GMT