Logo Search packages:      
Sourcecode: pymol version File versions  Download package

ObjectDist.c

/* 
A* -------------------------------------------------------------------
B* This file contains source code for the PyMOL computer program
C* copyright 1998-2000 by Warren Lyford Delano of DeLano Scientific. 
D* -------------------------------------------------------------------
E* It is unlawful to modify or remove this copyright notice.
F* -------------------------------------------------------------------
G* Please see the accompanying LICENSE file for further information. 
H* -------------------------------------------------------------------
I* Additional authors of this source file include:
-* 
-* 
-*
Z* -------------------------------------------------------------------
*/
#include"os_predef.h"
#include"os_std.h"

#include"Base.h"
#include"OOMac.h"
#include"Vector.h"
#include"MemoryDebug.h"
#include"Err.h"
#include"Setting.h"
#include"Scene.h"
#include"Ray.h"
#include"ObjectDist.h"
#include"Selector.h"
#include"PConv.h"
#include"ObjectMolecule.h"
#include"Feedback.h"

void ObjectDistFree(ObjectDist *I);
void ObjectDistUpdate(ObjectDist *I);
int ObjectDistGetNFrames(ObjectDist *I);
void ObjectDistUpdateExtents(ObjectDist *I);

int ObjectDistGetLabelTxfVertex(ObjectDist *I,int state,int index,float *v)
{
  int result = 0;
  if(I->DSet) { 
    if(state<0) state=SettingGet_i(I->Obj.G,NULL,I->Obj.Setting,cSetting_state)-1;
    if(state<0) state=SceneGetState(I->Obj.G); 
    if(I->NDSet==1) state=0; /* static singletons always active here it seems */
    state = state % I->NDSet;
    {
      DistSet *ds = I->DSet[state];
    if((!ds)&&(SettingGet_b(I->Obj.G,I->Obj.Setting,NULL,cSetting_all_states))) {
      state=0;
      ds = I->DSet[state];
    }
    if(ds) {
      result = DistSetGetLabelVertex(ds,index,v);
    }}
  }
  return(result);
}

int ObjectDistMoveLabel(ObjectDist *I,int state,int index,float *v,int mode,int log)
{
  int result = 0;
  DistSet *ds;
  if(state<0) state=0;
  if(I->NDSet==1) state=0;
  state = state % I->NDSet;
  if((!I->DSet[state])&&(SettingGet_b(I->Obj.G,I->Obj.Setting,NULL,cSetting_all_states)))
    state=0;
  ds = I->DSet[state];
  if(ds) {
    result = DistSetMoveLabel(I->DSet[state],index,v,mode);
    ds->fInvalidateRep(ds,cRepLabel,cRepInvCoord);
    /*      ExecutiveUpdateCoordDepends(I->Obj.G,I);*/
  }
#if 0
  if(log) {
    OrthoLineType line,buffer;
    if(SettingGet(I->Obj.G,cSetting_logging)) {
      ObjectMoleculeGetAtomSele(I,index,buffer);
      sprintf(line,"cmd.translate_atom(\"%s\",%15.9f,%15.9f,%15.9f,%d,%d,%d)\n",
              buffer,v[0],v[1],v[2],state+1,mode,0);
      PLog(line,cPLog_no_flush);
    }
  }
#endif
  return(result);
}

static DistSet *ObjectDistGetDistSetFromM4XBond(PyMOLGlobals *G,
                                                ObjectMolecule *obj, 
                                                M4XBondType *hb, int n_hb,
                                                int state,int nbr_sele)
{
  int min_id,max_id,range,*lookup = NULL;
  int nv = 0;
  float *vv=NULL;
  DistSet *ds;
  ds = DistSetNew(G);
  vv = VLAlloc(float,10);
  
  /* this routine only works if IDs cover a reasonable range --
     should rewrite using a hash table */
  
  if(obj->NAtom) {
    
    /* determine range */

    {
      int a,cur_id;
      cur_id = obj->AtomInfo[0].id;
      min_id = cur_id;
      max_id = cur_id;
      for(a=1;a<obj->NAtom;a++) {
        cur_id = obj->AtomInfo[a].id;
        if(min_id>cur_id) min_id = cur_id;
        if(max_id<cur_id) max_id = cur_id;
      }
    }

    /* create cross-reference table */

    {
      int a,offset;
      
      range = max_id - min_id + 1;
      lookup = Calloc(int,range);
      for(a=0;a<obj->NAtom;a++) {
        offset = obj->AtomInfo[a].id - min_id;
        if(lookup[offset])
          lookup[offset] = -1;
        else {
          lookup[offset] = a+1;
        }
      }
    }
    
    /* iterate through IDs and get pairs */
    {
      AtomInfoType *ai1,*ai2;
      int at1,at2;
      CoordSet *cs;
      
      float *vv0,*vv1,dist;
      int idx1,idx2;
      
      int i,offset1,offset2;
      int sele_flag = false;
      
      for(i=0;i<n_hb;i++) {
        offset1 = hb[i].atom1-min_id;
        offset2 = hb[i].atom2-min_id;
        if((offset1>=0)&&(offset1<range)&&(offset2>=0)&&(offset2<range)) {
          at1 = lookup[offset1]-1;
          at2 = lookup[offset2]-1;
          if((at1>=0)&&(at2>=0)&&(at1!=at2)&&(state<obj->NCSet)) {
            cs=obj->CSet[state];

            if(cs) { 
              ai1=obj->AtomInfo+at1;
              ai2=obj->AtomInfo+at2;
              
              sele_flag =false;
              
              if(nbr_sele>=0) {
                if(SelectorIsMember(G,ai1->selEntry,nbr_sele))
                  sele_flag=true;
                if(SelectorIsMember(G,ai2->selEntry,nbr_sele))
                  sele_flag=true;
              } else {
                sele_flag =true;
              }
              
              if(sele_flag) {
                if(obj->DiscreteFlag) {
                  if(cs==obj->DiscreteCSet[at1]) {
                    idx1=obj->DiscreteAtmToIdx[at1];
                  } else {
                    idx1=-1;
                  }
                } else {
                  idx1=cs->AtmToIdx[at1];
                }
                
                if(obj->DiscreteFlag) {
                  if(cs==obj->DiscreteCSet[at2]) {
                    idx2=obj->DiscreteAtmToIdx[at2];
                  } else {
                    idx2=-1;
                  }
                  
                } else {
                  idx2=cs->AtmToIdx[at2];
                }
                
                if((idx1>=0)&&(idx2>=0)) {
                  dist=(float)diff3f(cs->Coord+3*idx1,cs->Coord+3*idx2);
                  VLACheck(vv,float,(nv*3)+5);
                  vv0 = vv+ (nv*3);
                  vv1 = cs->Coord+3*idx1;
                  *(vv0++) = *(vv1++);
                  *(vv0++) = *(vv1++);
                  *(vv0++) = *(vv1++);
                  vv1 = cs->Coord+3*idx2;
                  *(vv0++) = *(vv1++);
                  *(vv0++) = *(vv1++);
                  *(vv0++) = *(vv1++);
                  nv+=2;
                }
              }
            }
          }
        }
      }
    }
  }
  
  FreeP(lookup);
  ds->NIndex = nv;
  ds->Coord = vv;
  return(ds);
  
}

ObjectDist *ObjectDistNewFromM4XBond(PyMOLGlobals *G,ObjectDist *oldObj,
                                      struct ObjectMolecule *objMol,
                                      struct M4XBondType *hbond,
                                     int n_hbond,int nbr_sele)
{
  int a;
  ObjectDist *I;
  int n_state;
  if(!oldObj)
    I=ObjectDistNew(G);
  else {
    I=oldObj;
    for(a=0;a<I->NDSet;a++)
      if(I->DSet[a]) {
        if(I->DSet[a]->fFree)
          I->DSet[a]->fFree(I->DSet[a]);
        I->DSet[a]=NULL;
      }
    I->NDSet=0;
  }
  n_state = objMol->NCSet;
  for(a=0;a<n_state;a++)
    {
      VLACheck(I->DSet,DistSet*,a);
      
      I->DSet[a] = ObjectDistGetDistSetFromM4XBond(G,objMol,hbond,n_hbond,a,nbr_sele);
      
      if(I->DSet[a]) {
        I->DSet[a]->Obj = I;
        I->NDSet=a+1;
      }
    } 
  ObjectDistUpdateExtents(I);
  
  SceneChanged(G);
  return(I);
}

/*========================================================================*/

void ObjectDistUpdateExtents(ObjectDist *I)
{
  float maxv[3] = {FLT_MAX,FLT_MAX,FLT_MAX};
  float minv[3] = {-FLT_MAX,-FLT_MAX,-FLT_MAX};
  int a;
  DistSet *ds;

  /* update extents */
  copy3f(maxv,I->Obj.ExtentMin);
  copy3f(minv,I->Obj.ExtentMax);
  I->Obj.ExtentFlag=false;
  for(a=0;a<I->NDSet;a++) {
    ds = I->DSet[a];
    if(ds) {
      if(DistSetGetExtent(ds,I->Obj.ExtentMin,I->Obj.ExtentMax))
        I->Obj.ExtentFlag=true;
    }
  }
}


#ifndef _PYMOL_NOPY
static PyObject *ObjectDistDSetAsPyList(ObjectDist *I)
{
  PyObject *result = NULL;
  int a;
  result = PyList_New(I->NDSet);
  for(a=0;a<I->NDSet;a++) {
    if(I->DSet[a]) {
      PyList_SetItem(result,a,DistSetAsPyList(I->DSet[a]));
    } else {
      PyList_SetItem(result,a,Py_None);
      Py_INCREF(Py_None);
    }
  }
  return(PConvAutoNone(result));
}
#endif
#ifndef _PYMOL_NOPY
static int ObjectDistDSetFromPyList(ObjectDist *I,PyObject *list)
{
  int ok=true;
  int a;
  if(ok) ok=PyList_Check(list);
  if(ok) {
    VLACheck(I->DSet,DistSet*,I->NDSet);
    for(a=0;a<I->NDSet;a++) {
      if(ok) ok = DistSetFromPyList(I->Obj.G,PyList_GetItem(list,a),&I->DSet[a]);
      if(ok) I->DSet[a]->Obj = I;
    }
  }
  return(ok);
}
#endif
/*========================================================================*/
PyObject *ObjectDistAsPyList(ObjectDist *I)
{
#ifdef _PYMOL_NOPY
  return NULL;
#else

  PyObject *result = NULL;

  /* first, dump the atoms */

  result = PyList_New(4);
  PyList_SetItem(result,0,ObjectAsPyList(&I->Obj));
  PyList_SetItem(result,1,PyInt_FromLong(I->NDSet));
  PyList_SetItem(result,2,ObjectDistDSetAsPyList(I));
  PyList_SetItem(result,3,PyInt_FromLong(I->CurDSet));

#if 0

  CObject Obj;
  struct DistSet **DSet;
  int NDSet;
  int CurDSet;

#endif

  return(PConvAutoNone(result));  
#endif
}

int ObjectDistNewFromPyList(PyMOLGlobals *G,PyObject *list,ObjectDist **result)
{
#ifdef _PYMOL_NOPY
  return 0;
#else

  int ok = true;
  ObjectDist *I=NULL;
  (*result) = NULL;
  
  if(ok) ok=PyList_Check(list);

  I=ObjectDistNew(G);
  if(ok) ok = (I!=NULL);

  if(ok) ok = ObjectFromPyList(G,PyList_GetItem(list,0),&I->Obj);
  if(ok) ok = PConvPyIntToInt(PyList_GetItem(list,1),&I->NDSet);
  if(ok) ok = ObjectDistDSetFromPyList(I,PyList_GetItem(list,2));
  if(ok) ok = PConvPyIntToInt(PyList_GetItem(list,3),&I->CurDSet);
  
  ObjectDistInvalidateRep(I,cRepAll);
  if(ok) {
    (*result) = I;
    ObjectDistUpdateExtents(I);
  }
  else {
    /* cleanup? */
  }

  return(ok);
#endif
}


/*========================================================================*/
int ObjectDistGetNFrames(ObjectDist *I)
{
  return I->NDSet;
}
/*========================================================================*/
void ObjectDistUpdate(ObjectDist *I)
{
  int a;
  OrthoBusyPrime(I->Obj.G);
  for(a=0;a<I->NDSet;a++)
       if(I->DSet[a]) { 
         OrthoBusySlow(I->Obj.G,a,I->NDSet);
      /*       printf(" ObjectDist: updating state %d of \"%s\".\n" , a+1, I->Obj.Name);*/
      if(I->DSet[a]->fUpdate)
        I->DSet[a]->fUpdate(I->DSet[a],a);
       }
}
/*========================================================================*/
void ObjectDistInvalidateRep(ObjectDist *I,int rep)
{
  int a;
  PRINTFD(I->Obj.G,FB_ObjectDist)
    " ObjectDistInvalidateRep: entered.\n"
    ENDFD;

  for(a=0;a<I->NDSet;a++) 
       if(I->DSet[a]) {  
      if(I->DSet[a]->fInvalidateRep)
        I->DSet[a]->fInvalidateRep(I->DSet[a],rep,cRepInvAll);
       }
}
/*========================================================================*/
static void ObjectDistRender(ObjectDist *I,RenderInfo *info)
{
  int a;
  int state = info->state;
  int pass = info->pass;
  CRay *ray = info->ray;

  if((pass==0)||(pass==-1)) {
    ObjectPrepareContext(&I->Obj,ray);
    if(state<0) {
      for(a=0;a<I->NDSet;a++)
        if(I->DSet[a])
          if(I->DSet[a]->fRender)
            I->DSet[a]->fRender(I->DSet[a],info);
    } else if(state<I->NDSet) {
      I->CurDSet=state % I->NDSet;
      if(I->DSet[I->CurDSet]) {
        if(I->DSet[I->CurDSet]->fRender)
          I->DSet[I->CurDSet]->fRender(I->DSet[I->CurDSet],info);
      }
    } else if(I->NDSet==1) { /* if only one coordinate set, assume static */
      if(I->DSet[0]->fRender)
        I->DSet[0]->fRender(I->DSet[0],info);
    }
  }
}

static CSetting **ObjectDistGetSettingHandle(ObjectDist *I,int state)
{
  if(state<0) {
    return(&I->Obj.Setting);
  } else if(state<I->NDSet) {
    if(I->DSet[state]) {
      return(&I->DSet[state]->Setting);
    } else {
      return(NULL);
    }
  } else {
    return(NULL);
  }
}

/*========================================================================*/
ObjectDist *ObjectDistNew(PyMOLGlobals *G)
{
  OOAlloc(G,ObjectDist);
  ObjectInit(G,(CObject*)I);
  I->Obj.type=cObjectDist;
  I->DSet=VLAMalloc(10,sizeof(DistSet*),5,true); /* auto-zero */
  I->NDSet=0;
  I->Obj.fRender=(void (*)(struct CObject *, RenderInfo *info))ObjectDistRender;
  I->Obj.fFree= (void (*)(struct CObject *))ObjectDistFree;
  I->Obj.fUpdate= (void (*)(struct CObject *)) ObjectDistUpdate;
  I->Obj.fGetNFrame = (int (*)(struct CObject *)) ObjectDistGetNFrames;
  I->Obj.fGetSettingHandle = (CSetting **(*)(struct CObject *,int state))
    ObjectDistGetSettingHandle;
  I->Obj.fDescribeElement = NULL;
  I->CurDSet=0;
  I->Obj.Color=ColorGetIndex(G,"dash");
  return(I);
}

/*========================================================================*/
static void ObjectDistReset(PyMOLGlobals *G,ObjectDist *I)
{
  int a;
  for(a=0;a<I->NDSet;a++)
    if(I->DSet[a]) {
      if(I->DSet[a]->fFree)
          I->DSet[a]->fFree(I->DSet[a]);
      I->DSet[a]=NULL;
    }
  I->NDSet=0;
}

/*========================================================================*/
ObjectDist *ObjectDistNewFromSele(PyMOLGlobals *G,ObjectDist *oldObj,
                                  int sele1,int sele2,int mode,float cutoff,
                                  int labels,int reset,float *result,int state)
{
  int a,mn;
  float dist_sum=0.0,dist;
  int dist_cnt = 0;
  int n_state1,n_state2,state1,state2;
  ObjectDist *I;
  if(!oldObj)
    I=ObjectDistNew(G);
  else {
    I=oldObj;
    if(reset) 
      ObjectDistReset(G,I);
  }
  *result = 0.0;
  mn = 0;
  SelectorUpdateTable(G);
  n_state1 = SelectorGetSeleNCSet(G,sele1);
  n_state2 = SelectorGetSeleNCSet(G,sele2);
  mn = n_state1;
  if(n_state2>mn) mn = n_state2;
  if(mn) {
    for(a=0;a<mn;a++) {
      if(state>=0) {
        if(state>=mn)
          break;
        a = state;
      }
        
      VLACheck(I->DSet,DistSet*,a);
      if(n_state1>1)
        state1=a;
      else
        state1=0;
      if(n_state2>1)
        state2=a;
      else
        state2=0;
      I->DSet[a] = SelectorGetDistSet(G,I->DSet[a],sele1,state1,sele2,
                                      state2,mode,cutoff,&dist);
      if(I->DSet[a]) {
        dist_sum+=dist;
        dist_cnt++;
        I->DSet[a]->Obj = I;
        I->NDSet=a+1;
      }

      if(state>=0)
        break;
    }
  } 
  ObjectDistUpdateExtents(I);
  ObjectDistInvalidateRep(I,cRepAll);

  if(dist_cnt)
    (*result) = dist_sum/dist_cnt;
  SceneChanged(G);
  return(I);
}

ObjectDist *ObjectDistNewFromAngleSele(PyMOLGlobals *G,ObjectDist *oldObj,
                                       int sele1, int sele2, int sele3, int mode,
                                       int labels,float *result, int reset,
                                       int state)
{
  int a,mn;
  float angle_sum=0.0;
  int angle_cnt=0;
  int n_state1,n_state2,n_state3, state1,state2,state3;
  ObjectDist *I;

  if(!oldObj) /* create object if new */
    I=ObjectDistNew(G);
  else { /* otherwise, use existing object */
    I=oldObj;
    if(reset) { /* if reseting, then clear out all existing coordinate sets */
      ObjectDistReset(G,I);
    }
  }
  *result = 0.0;

  /* count number of states in each selection */

  SelectorUpdateTable(G);
  n_state1 = SelectorGetSeleNCSet(G,sele1);
  n_state2 = SelectorGetSeleNCSet(G,sele2);  
  n_state3 = SelectorGetSeleNCSet(G,sele3);

  /* figure out the total number of states */

  mn = n_state1;
  if(n_state2>mn) mn = n_state2;
  if(n_state3>mn) mn = n_state3;

  if(mn) {
    for(a=0;a<mn;a++) {
      if(state>=0) {
        if(state>mn)
          break;
        a = state;
      }
      /* treat selections with one state as static singletons */
      
      if(n_state1>1)
        state1=a;
      else
        state1=0;
      if(n_state2>1)
        state2=a;
      else
        state2=0;
      if(n_state3>1)
        state3=a;
      else
        state3=0;
      
      VLACheck(I->DSet,DistSet*,a);
      I->DSet[a] = SelectorGetAngleSet(G,I->DSet[a],sele1,state1,sele2,
                                       state2,sele3,state3,mode,&angle_sum,
                                       &angle_cnt);
      
      if(I->DSet[a]) {
        I->DSet[a]->Obj = I;
        if(I->NDSet<=a) I->NDSet = a+1;
      }
      if(state>=0)
        break;
    }  
  }
  /* else {
     VLAFreeP(I->DSet);
     OOFreeP(I);
     }
  */
  ObjectDistUpdateExtents(I);
  ObjectDistInvalidateRep(I,cRepAll);
  if(angle_cnt)
    (*result) = angle_sum/angle_cnt;

  SceneChanged(G);
  return(I);
}

ObjectDist *ObjectDistNewFromDihedralSele(PyMOLGlobals *G,ObjectDist *oldObj,
                                        int sele1, int sele2, int sele3, int sele4,
                                        int mode, int labels, float *result,
                                          int reset,int state)
{
  int a,mn;
  float angle_sum=0.0;
  int angle_cnt=0;
  int n_state1,n_state2,n_state3,n_state4, state1,state2,state3,state4;
  ObjectDist *I;

  if(!oldObj) /* create object if new */
    I=ObjectDistNew(G);
  else { /* otherwise, use existing object */
    I=oldObj;
    if(reset) { /* if reseting, then clear out all existing coordinate sets */
      ObjectDistReset(G,I);
    }
  }
  *result = 0.0;

  /* count number of states in each selection */

  SelectorUpdateTable(G);

  n_state1 = SelectorGetSeleNCSet(G,sele1);
  n_state2 = SelectorGetSeleNCSet(G,sele2);  
  n_state3 = SelectorGetSeleNCSet(G,sele3);
  n_state4 = SelectorGetSeleNCSet(G,sele4);

  /* figure out the total number of states */

  mn = n_state1;
  if(n_state2>mn) mn = n_state2;
  if(n_state3>mn) mn = n_state3;
  if(n_state4>mn) mn = n_state4;

  if(mn) {
    for(a=0;a<mn;a++) {
      if(state>=0) {
        if(state>mn)
          break;
        a = state;
      }
      /* treat selections with one state as static singletons */
      
      if(n_state1>1)
        state1=a;
      else
        state1=0;
      if(n_state2>1)
        state2=a;
      else
        state2=0;
      if(n_state3>1)
        state3=a;
      else
        state3=0;
      if(n_state4>1)
        state4=a;
      else
        state4=0;
      
      VLACheck(I->DSet,DistSet*,a);
      I->DSet[a] = SelectorGetDihedralSet(G,I->DSet[a],sele1,state1,sele2,
                                          state2,sele3,state3,sele4,state4,
                                          mode,&angle_sum,
                                          &angle_cnt);
      
      if(I->DSet[a]) {
        I->DSet[a]->Obj = I;
        if(I->NDSet<=a) I->NDSet = a+1;
      }

      if(state>=0)
        break;
    }
  } 
  /* else {
     VLAFreeP(I->DSet);
     OOFreeP(I);
     }
  */
  ObjectDistUpdateExtents(I);
  ObjectDistInvalidateRep(I,cRepAll);

  if(angle_cnt)
    (*result) = angle_sum/angle_cnt;

  SceneChanged(G);
  return(I);
}

/*========================================================================*/
void ObjectDistFree(ObjectDist *I)
{
  int a;
  SceneObjectDel(I->Obj.G,(CObject*)I);
  for(a=0;a<I->NDSet;a++)
       if(I->DSet[a]) {
      if(I->DSet[a]->fFree)
        I->DSet[a]->fFree(I->DSet[a]);
            I->DSet[a]=NULL;
       }
  VLAFreeP(I->DSet);
  ObjectPurge(&I->Obj);
  OOFreeP(I);
}


Generated by  Doxygen 1.6.0   Back to index