Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members   Related Pages  

GeometryMol.C

Go to the documentation of this file.
00001 /***************************************************************************
00002  *cr                                                                       
00003  *cr            (C) Copyright 1995-2008 The Board of Trustees of the           
00004  *cr                        University of Illinois                       
00005  *cr                         All Rights Reserved                        
00006  *cr                                                                   
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010  * RCS INFORMATION:
00011  *
00012  *      $RCSfile: GeometryMol.C,v $
00013  *      $Author: johns $        $Locker:  $                $State: Exp $
00014  *      $Revision: 1.45 $      $Date: 2008/03/27 19:36:39 $
00015  *
00016  ***************************************************************************
00017  * DESCRIPTION:
00018  *
00019  * A base class for all Geometry objects which measure information about
00020  * atoms in a molecule.  A molecule Geometry monitor is assumed to operate
00021  * on N atoms, and be able to calculate a single floating-point value for
00022  * those atoms.  (i.e. the angle formed by three atoms in space)
00023  *
00024  ***************************************************************************/
00025 
00026 #include "GeometryMol.h"
00027 #include "MoleculeList.h"
00028 #include "Molecule.h"
00029 #include "Displayable.h"
00030 #include "DispCmds.h"
00031 #include "utilities.h"
00032 #include "VMDApp.h"
00033 #include "TextEvent.h"
00034 #include "CommandQueue.h"
00035 
00037 class GeometryMonitor : public DrawMoleculeMonitor {
00038 private:
00039   GeometryMol *mygeo;
00040 
00041 public:
00042   GeometryMonitor(GeometryMol *g, int id) : mygeo(g), molid(id) { }
00043   void notify(int id) {
00044     mygeo->calculate();
00045     mygeo->update();
00046   }
00047   const int molid;
00048 };
00049 
00051 GeometryMol::GeometryMol(int n, int *mols, int *atms, const int *cells, 
00052     MoleculeList *mlist, CommandQueue *cq, Displayable *d) 
00053 : Displayable(d) {
00054 
00055   objIndex = new int[n];
00056   comIndex = new int[n];
00057   cellIndex = new int[3*n];
00058   if (cells) {
00059     memcpy(cellIndex, cells, 3*n*sizeof(int));
00060   } else {
00061     memset(cellIndex, 0, 3*n*sizeof(int));
00062   }
00063   geomValue = 0.0;
00064   numItems = n;
00065   hasValue = TRUE;
00066 
00067   my_color = 8;
00068   my_text_size = 1.0f;
00069   my_text_offset[0] = my_text_offset[1] = 0;
00070   my_text_format = "%R%d:%a";
00071 
00072   molList = mlist;
00073   cmdqueue = cq;
00074   gmName = NULL;
00075   uniquegmName = NULL;
00076 
00077   for(int i=0; i < numItems; i++) {
00078     objIndex[i] = mols[i];
00079     comIndex[i] = atms[i];
00080     
00081     // make sure an atom is not repeated in this list
00082     if(i > 0 && objIndex[i-1]==objIndex[i] && comIndex[i-1]==comIndex[i] &&
00083         !memcmp(cellIndex+3*i, cellIndex+3*(i-1), 3*sizeof(int))) {
00084       // set a bogus value for the first atom index, to make the
00085       // check_mol routine fail
00086       comIndex[0] = (-1);
00087     }
00088 
00089     Molecule *m = molList->mol_from_id(mols[i]);
00090     if (m) {
00091       GeometryMonitor *mon = new GeometryMonitor(this, objIndex[i]);
00092       m->register_monitor(mon);
00093       monitors.append(mon);
00094     }
00095   }
00096 
00097   // sort the items properly
00098   sort_items();
00099 
00100   // create the name for this object
00101   geom_set_name();
00102 }
00103 
00104 
00106 GeometryMol::~GeometryMol(void) {
00107   // delete name if necessary
00108   if(gmName)
00109     delete [] gmName;
00110   if(uniquegmName)
00111     delete [] uniquegmName;
00112   delete [] objIndex;
00113   delete [] comIndex;
00114   delete [] cellIndex;
00115   for (int i=0; i<monitors.num(); i++) {
00116     GeometryMonitor *mon = monitors[i];
00117     Molecule *m = molList->mol_from_id(mon->molid);
00118     if (m) m->unregister_monitor(mon);
00119     delete mon; 
00120   }
00121 }
00122 
00123 
00125 
00126 void GeometryMol::atom_full_name(char *buf, Molecule *mol, int ind) {
00127   sprintf(buf, "%-d/%-d", mol->id(), ind);
00128 }
00129 
00130 void GeometryMol::atom_short_name(char *buf, Molecule *mol, int ind) {
00131   MolAtom *nameAtom = mol->atom(ind);
00132   sprintf(buf, "%s%d:%s",
00133                 mol->resNames.name(nameAtom->resnameindex),
00134                 nameAtom->resid,
00135                 mol->atomNames.name(nameAtom->nameindex));
00136 }
00137 
00138 void GeometryMol::atom_formatted_name(JString &str, Molecule *mol, int ind) {
00139   MolAtom *atom = mol->atom(ind);
00140   str = my_text_format;
00141   char buf[32];
00142   // resname
00143   JString resname = mol->resNames.name(atom->resnameindex);
00144   str.gsub("%R", (const char *)resname);
00145   // resname in campel case
00146   resname.to_camel();
00147   str.gsub("%r", (const char *)resname);
00148   // resid
00149   sprintf(buf, "%d", atom->resid);
00150   str.gsub("%d", buf);
00151   // atom name
00152   str.gsub("%a", mol->atomNames.name(atom->nameindex));
00153   // atom charge
00154   sprintf(buf, "%4.3f", mol->charge()[ind]);
00155   str.gsub("%q", buf);
00156   // atom index
00157   sprintf(buf, "%d", ind);
00158   str.gsub("%i", buf);
00159 }
00160 
00161 // set the name of this item
00162 void GeometryMol::geom_set_name(void) {
00163   char namebuf[256];
00164   char namebuf2[256];
00165   char cellbuf[256];
00166   Molecule *mol;
00167   register int i;
00168 
00169   if(items() < 1)
00170     return;
00171 
00172   // put first name in string
00173   if((mol = check_mol(objIndex[0], comIndex[0]))) {
00174     atom_full_name(namebuf, mol, comIndex[0]);
00175     atom_short_name(namebuf2, mol, comIndex[0]);
00176     sprintf(cellbuf, "-%d-%d-%d", cellIndex[0], cellIndex[1], cellIndex[2]);
00177     strcat(namebuf, cellbuf);
00178   } else
00179     return;
00180 
00181   // put rest of names in string in format: n1/n2/n3/.../nN
00182   for(i = 1; i < items(); i++) {
00183     if((mol = check_mol(objIndex[i], comIndex[i]))) {
00184       strcat(namebuf, "/");
00185       atom_full_name(namebuf+strlen(namebuf), mol, comIndex[i]);
00186       strcat(namebuf2, "/");
00187       atom_short_name(namebuf2+strlen(namebuf2), mol, comIndex[i]);
00188       sprintf(cellbuf, "-%d-%d-%d", cellIndex[3*i+0], cellIndex[3*i+1],
00189           cellIndex[3*i+2]);
00190       strcat(namebuf, cellbuf);
00191     } else {
00192       return;
00193     }
00194   }
00195   
00196   // now make a copy of this name
00197   if(gmName)
00198     delete [] gmName;
00199   if(uniquegmName)
00200     delete [] uniquegmName;
00201 
00202   uniquegmName = stringdup(namebuf);
00203   gmName = stringdup(namebuf2);
00204 }
00205 
00206 
00207 // sort the elements in the list, so that the lowest atom index is first
00208 // (but preserve the relative order, i.e. a-b-c or c-b-a)
00209 void GeometryMol::sort_items(void) {
00210   register int i,j;
00211 
00212   // swap order if first component index > last component index
00213   if( (comIndex[0] > comIndex[items()- 1]) ||
00214       (comIndex[0] == comIndex[items()-1] &&
00215                 objIndex[0] > objIndex[items()-1]) ) {
00216     for(i=0, j=(items() - 1); i < j; i++, j--) {
00217       int tmpindex = comIndex[i];
00218       comIndex[i] = comIndex[j];
00219       comIndex[j] = tmpindex;
00220       tmpindex = objIndex[i];
00221       objIndex[i] = objIndex[j];
00222       objIndex[j] = tmpindex;
00223       int celltmp[3];
00224       memcpy(celltmp, cellIndex+3*i, 3*sizeof(int));
00225       memcpy(cellIndex+3*i, cellIndex+3*j, 3*sizeof(int));
00226       memcpy(cellIndex+3*j, celltmp, 3*sizeof(int));
00227     }
00228   }
00229 }
00230 
00231 
00232 // check whether the given molecule & atom index is OK
00233 // if OK, return Molecule pointer; otherwise, return NULL
00234 Molecule *GeometryMol::check_mol(int m, int a) {
00235 
00236   Molecule *mol = molList->mol_from_id(m);
00237 
00238   if(!mol || a < 0 || a >= mol->nAtoms)
00239     mol = NULL;
00240   
00241   return mol;
00242 }
00243 
00244 
00245 // for the given Molecule, find the TRANSFORMED coords for the given atom
00246 // return Molecule pointer if successful, NULL otherwise.
00247 Molecule *GeometryMol::transformed_atom_coord(int ind, float *pos) {
00248   Molecule *mol;
00249 
00250   // only return value if molecule is legal and atom is displayed
00251   int a=comIndex[ind];
00252   if((mol = normal_atom_coord(ind, pos)) && mol->atom_displayed(a)) {
00253 
00254     // now multiply it by the molecule's tranformation matrix
00255     (mol->tm).multpoint3d(pos, pos);
00256 
00257     // calculation was successful; return the molecule pointer
00258     return mol;
00259   }
00260   
00261   // if here, error (i.e. atom not displayed, or not proper mol id)
00262   return NULL;
00263 }
00264 
00265 
00266 // for the given Molecule, find the UNTRANSFORMED coords for the given atom
00267 // return Molecule pointer if successful, NULL otherwise.
00268 Molecule *GeometryMol::normal_atom_coord(int ind, float *pos) {
00269   Timestep *now;
00270   Molecule *mol;
00271 
00272   int m=objIndex[ind];
00273   int a=comIndex[ind];
00274   const int *cell = cellIndex+3*ind;
00275 
00276   // get the molecule pointer, and get the coords for the current timestep
00277   if((mol = check_mol(m, a)) && (now = mol->current())) {
00278     memcpy((void *)pos, (void *)(now->pos + 3*a), 3*sizeof(float));
00279     
00280     // Apply periodic image transformation before returning
00281     Matrix4 mat;
00282     now->get_transform_from_cell(cell, mat);
00283     mat.multpoint3d(pos, pos);
00284     
00285     return mol;
00286   }
00287   
00288   // if here, error (i.e. atom not displayed, or not proper mol id)
00289   return NULL;
00290 }
00291 
00292 
00293 // draws a line between the two given points
00294 void GeometryMol::display_line(float *p1, float *p2, VMDDisplayList *d) {
00295   DispCmdLine cmdLineGeom;
00296   cmdLineGeom.putdata(p1, p2, d);
00297 }
00298 
00299 
00300 // print given text at current valuePos position
00301 void GeometryMol::display_string(const char *str, VMDDisplayList *d) {
00302   DispCmdTextOffset cmdTextOffset;
00303   cmdTextOffset.putdata(my_text_offset[0], my_text_offset[1], d);
00304 
00305   DispCmdTextSize cmdTextSize;
00306   cmdTextSize.putdata(my_text_size, d);
00307 
00308   DispCmdText cmdTextGeom;
00309   cmdTextGeom.putdata(valuePos, str, d);
00310 }
00311 
00313 
00314 // return the name of this geometry marker; by default, just blank
00315 const char *GeometryMol::name(void) {
00316   return (gmName ? gmName : "");
00317 }
00318 
00319 
00320 // return 'unique' name of the marker, which should be different than
00321 // other names for different markers of this same type
00322 const char *GeometryMol::unique_name(void) {
00323   return (uniquegmName ? uniquegmName : name());
00324 }
00325 
00326 
00327 // check whether the geometry value can still be calculated
00328 int GeometryMol::ok(void) {
00329   register int i;
00330   
00331   for(i=0; i < numItems; i++)
00332     if(!check_mol(objIndex[i], comIndex[i]))
00333       return FALSE;
00334 
00335   return TRUE;
00336 }
00337 
00338 
00339 // calculate a whole list of items, if this object can do so.  Return success.
00340 int GeometryMol::calculate_all(ResizeArray<float> &valArray) {
00341   int i, max_ts, orig_ts;
00342 
00343   // use the first molecule to determine which frames to cycle through
00344   Molecule *mol = molList->mol_from_id(objIndex[0]);
00345   if( ! has_value() || !mol )
00346     return FALSE;
00347 
00348   // get the max & current frame number, and make sure there are frames
00349   max_ts = mol->numframes()-1;
00350   if((orig_ts = mol->frame()) < 0)
00351     return FALSE;
00352 
00353   // go through all the frames, calculating values
00354   for(i=0; i <= max_ts; i++) {
00355     mol->override_current_frame(i);
00356     valArray.append(calculate());
00357   }
00358   
00359   // reset the current frame and current value of this geometry monitor
00360   mol->override_current_frame(orig_ts);
00361   calculate();
00362   
00363   return TRUE;
00364 }
00365 
00366 // save the text of a selection to the interpreter variable "vmd_pick_selection"
00367 // The format is of the form "index %d %d %d .... %d" for each atom picked.
00368 // (If nothing is picked, the text is "none")
00369 void GeometryMol::set_pick_selection(int , int num, int *atoms) {
00370   cmdqueue->runcommand(new PickSelectionEvent(num, atoms));
00371 }
00372 
00373 void GeometryMol::set_pick_selection() {
00374   cmdqueue->runcommand(new PickSelectionEvent(0, 0));
00375 }
00376     
00377 void GeometryMol::set_pick_value(double newval) {
00378   cmdqueue->runcommand(new PickValueEvent(newval));
00379 }
00380 

Generated on Sat Aug 30 01:26:44 2008 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002