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

MoleculeList.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: MoleculeList.C,v $
00013  *      $Author: johns $        $Locker:  $             $State: Exp $
00014  *      $Revision: 1.115 $      $Date: 2008/03/27 19:36:41 $
00015  *
00016  ***************************************************************************
00017  * DESCRIPTION:
00018  *
00019  * The MoleculeList class, which is a list of the molecules being displayed.
00020  * This is a Displayable object, where each molecule is a child Displayable.
00021  *
00022  ***************************************************************************/
00023 
00024 #include <stdio.h>
00025 #include <ctype.h>
00026 
00027 #include "MoleculeList.h"
00028 #include "Inform.h"
00029 #include "Scene.h"
00030 #include "MaterialList.h"
00031 #include "VMDApp.h"
00032 #include "ParseTree.h"
00033 #include "MoleculeGraphics.h" 
00034 
00035 // default atom selection
00036 #define DEFAULT_ATOMSEL "all"
00037 
00039 MoleculeList::MoleculeList(VMDApp *vmdapp, Scene *sc) 
00040         : app(vmdapp), scene (sc), molList(8) {
00041 
00042   topMol = NULL;
00043   defaultAtomColor = AtomColorName[DEFAULT_ATOMCOLOR];
00044   defaultAtomRepresentation = AtomRepInfo[DEFAULT_ATOMREP].name;
00045   defaultAtomSelection = DEFAULT_ATOMSEL;
00046   defaultAtomMaterial = app->materialList->material_name(0);
00047 
00048   currAtomRep = new AtomRep();
00049   currAtomSel = stringdup(DEFAULT_ATOMSEL);
00050   currMaterial = 0;
00051   lastCenter[0] = 0;
00052   lastCenter[1] = 0;
00053   lastCenter[2] = 0;
00054   lastCenter[3] = 1;
00055 
00056 #if defined(MLIST_USE_HASH)
00057   inthash_init(&indexIDhash, 5003); // initialize ID to index hash table
00058 #endif
00059 
00060   init_colors();
00061 }
00062 
00063 
00065 MoleculeList::~MoleculeList(void) {
00066   int i;
00067 
00068   // delete all added molecules
00069   for (i=0; i < num(); i++) {
00070     delete molecule(i);
00071   }
00072 
00073 #if defined(MLIST_USE_HASH)
00074   inthash_destroy(&indexIDhash); // destroy ID to index hash table
00075 #endif
00076 
00077   delete currAtomColor;
00078   delete currAtomRep;
00079   delete [] currAtomSel;
00080 }
00081 
00082 // do action when a new color list is provided
00083 void MoleculeList::init_colors(void) {
00084   // create atom color object
00085   currAtomColor = new AtomColor(this, scene);
00086   
00087   // create new color name categories
00088   colorCatIndex[MLCAT_NAMES] = scene->add_color_category("Name");
00089   colorCatIndex[MLCAT_TYPES] = scene->add_color_category("Type");
00090   colorCatIndex[MLCAT_ELEMENTS] = scene->add_color_category("Element");
00091   colorCatIndex[MLCAT_RESNAMES] = scene->add_color_category("Resname");
00092   colorCatIndex[MLCAT_RESTYPES] = scene->add_color_category("Restype");
00093   colorCatIndex[MLCAT_CHAINS] = scene->add_color_category("Chain");
00094   colorCatIndex[MLCAT_SEGNAMES] = scene->add_color_category("Segname");
00095   colorCatIndex[MLCAT_CONFORMATIONS] = scene->add_color_category("Conformation");
00096   colorCatIndex[MLCAT_MOLECULES] = scene->add_color_category("Molecule");
00097   colorCatIndex[MLCAT_SPECIAL] = scene->add_color_category("Highlight");
00098   colorCatIndex[MLCAT_SSTRUCT] = scene->add_color_category("Structure");
00099   colorCatIndex[MLCAT_SURFACES] = scene->add_color_category("Surface");
00100 
00101   // ensure that Restype Unassigned has a color
00102   scene->add_color_item(
00103       colorCatIndex[MLCAT_RESTYPES], "Unassigned", scene->color_index("cyan"));
00104   scene->add_color_item(
00105       colorCatIndex[MLCAT_ELEMENTS], "X", scene->color_index("cyan"));
00106 }
00107 
00108 
00110 
00111 // put new names from given molecule into color lists
00112 void MoleculeList::add_color_names(int molIndx) {
00113   int i, indx, catIndx;
00114   char newname[2];
00115   NameList<int> *molnames;
00116   Molecule *m;
00117   
00118   strcpy(newname, " "); // clear and add a NUL char
00119 
00120   // make sure this molecule is in the list already, otherwise just return
00121   if(!(m = molecule(molIndx))) 
00122     return;
00123   
00124   // for the given molecule, go through the NameList objects, and add them
00125   // to the color categories.  For new names, the color to use is the
00126   // color for the new index, mod # of total colors
00127   
00128   // atom names ... use upcased first non-numeric character as the name
00129   molnames = &(m->atomNames);
00130   int numatomnames = molnames->num();
00131   catIndx = colorCatIndex[MLCAT_NAMES];
00132   for (i=0; i < numatomnames; i++) {
00133     // get first non-numeric char of name, and convert to upper case
00134     const char *c = molnames->name(i);
00135 
00136     while (*c && isdigit(*c)) 
00137       c++;
00138 
00139     if (!(*c)) 
00140       c = molnames->name(i);
00141 
00142     newname[0] = (char)toupper(*c);
00143  
00144     // add this single-char name to color list; if it exists, get color
00145     indx = scene->add_color_item(catIndx, newname, 
00146              scene->num_category_items(catIndx) % VISCLRS);
00147     
00148     // for the molecule, set the color for this name
00149     molnames->set_data(i, indx);
00150   }
00151   
00152   // atom types ... use upcased first non-numeric character as the name
00153   molnames = &(m->atomTypes);
00154   int numatomtypes = molnames->num();
00155   catIndx = colorCatIndex[MLCAT_TYPES];
00156   for (i=0; i < numatomtypes; i++) {
00157     // get first non-numeric char of name, and convert to upper case
00158     const char *c = molnames->name(i);
00159 
00160     while (*c && isdigit(*c)) 
00161       c++;
00162 
00163     if (!(*c)) 
00164       c = molnames->name(i);
00165 
00166     newname[0] = (char)toupper(*c);
00167     
00168     // add this single-char name to color list; if it exists, get color
00169     indx = scene->add_color_item(catIndx, newname, 
00170              scene->num_category_items(catIndx) % VISCLRS);
00171     
00172     // for the molecule, set the color for this name
00173     molnames->set_data(i, indx);
00174   }
00175   
00176   // residue names and types ... use full name
00177   molnames = &(m->resNames);
00178   int numresnames = molnames->num();
00179   catIndx = colorCatIndex[MLCAT_RESNAMES];
00180   for (i=0; i < numresnames; i++) {
00181     indx = scene->add_color_item(catIndx, molnames->name(i), 
00182              scene->num_category_items(catIndx) % VISCLRS);
00183     molnames->set_data(i, indx);
00184     
00185     // check for residue types
00186     if (resTypes.typecode(molnames->name(i)) < 0) {
00187       // the residue has not been added to the restype list yet
00188       resTypes.add_name(molnames->name(i), "Unassigned");
00189     }
00190   }
00191 
00192   // chain names ... use full name
00193   molnames = &(m->chainNames);
00194   int numchainnames = molnames->num();
00195   catIndx = colorCatIndex[MLCAT_CHAINS];
00196   for (i=0; i < numchainnames; i++) {
00197     indx = scene->add_color_item(catIndx, molnames->name(i), 
00198              scene->num_category_items(catIndx) % VISCLRS);
00199     molnames->set_data(i, indx);
00200   }
00201 
00202   // segment names ... use full name
00203   molnames = &(m->segNames);
00204   int numsegnames = molnames->num();
00205   catIndx = colorCatIndex[MLCAT_SEGNAMES];
00206   for (i=0; i < numsegnames; i++) {
00207     indx = scene->add_color_item(catIndx, molnames->name(i), 
00208              scene->num_category_items(catIndx) % VISCLRS);
00209     molnames->set_data(i, indx);
00210   }
00211 
00212   // conformation names ... use full name, but special-case "" to be "all"
00213   molnames = &(m->altlocNames);
00214   int numconformations = molnames->num();
00215   catIndx = colorCatIndex[MLCAT_CONFORMATIONS];
00216   for (i=0; i < numconformations; i++) {
00217     const char *confname = molnames->name(i);
00218     if (confname[0] == '\0') {
00219       confname = "all";
00220     }
00221     indx = scene->add_color_item(catIndx, confname, 
00222              scene->num_category_items(catIndx) % VISCLRS);
00223     molnames->set_data(i, indx);
00224   }
00225 
00226   // molecule name ... use full name
00227   catIndx = colorCatIndex[MLCAT_MOLECULES];
00228   char buf[20];
00229   sprintf(buf, "%d", m->id());
00230   scene->add_color_item(catIndx, buf, 
00231         scene->num_category_items(catIndx) % VISCLRS);
00232 }
00233 
00234 
00235 // add a new molecule
00236 void MoleculeList::add_molecule(Molecule *newmol) {
00237   int newmolindex;
00238 
00239   // add the molecule to our list of molecules
00240   molList.append(newmol);
00241   newmolindex = molList.num() - 1;
00242 
00243 #if defined(MLIST_USE_HASH)
00244   // enhash the newly loaded molid for molid to molindex translation
00245   inthash_insert(&indexIDhash, newmol->id(), newmolindex);
00246 #endif
00247 
00248   // make the newly loaded molecule top
00249   make_top(newmolindex);
00250 }
00251 
00252 
00253 // set the top molecule ...
00254 // make sure the given molecule is in the list; if not, do not do anything
00255 void MoleculeList::make_top(Molecule *m) {
00256   if (!m) {
00257     topMol = m;
00258   } else if (m && mol_index_from_id(m->id()) >= 0) {
00259     topMol = m;
00260   }
00261 }
00262 
00263 
00264 // delete the molecule by its id
00265 int MoleculeList::del_molecule(int id) {
00266   Molecule *m, *newtopmol = NULL;
00267 
00268   // for this particular case, must make sure index is correct
00269   if (!(m = mol_from_id(id)))
00270     return FALSE;
00271 
00272   int n = mol_index_from_id(id);
00273 
00274   // must change the top molecule, if necessary
00275   if (is_top(n)) {
00276     if (n+1 < num()) {             // is there a molecule following this one?
00277       newtopmol = molecule(n+1);   // get it
00278     } else if (n-1 >= 0) {         // is there a molecule before this one?
00279       newtopmol = molecule(n-1);   // get it
00280     } else {
00281       newtopmol = topMol;          // signal there are NO molecules now
00282     }
00283   }
00284  
00285   delete m;                         // delete the molecule data structure
00286   molList.remove(n);                // remove the molecule from the list
00287 #if defined(MLIST_USE_HASH)
00288   // completely rebuild the hash table since all of
00289   // the molindex values are different now.
00290   // XXX this can cause N^2 performance when deleting all molecules.
00291   inthash_destroy(&indexIDhash);    // destroy ID to index hash table
00292   int molcount = num();
00293   int ml;
00294   inthash_init(&indexIDhash, 5003); // initialize ID to index hash table
00295   for (ml=0; ml<molcount; ml++) {
00296     inthash_insert(&indexIDhash, molecule(ml)->id(), ml);
00297   }
00298 #endif
00299  
00300   // now, change the top molecule if necessary
00301   if (newtopmol != NULL) {
00302     if (newtopmol != topMol) {
00303       make_top(newtopmol);
00304     } else {
00305       make_top((Molecule *)NULL);
00306     }
00307   }
00308 
00309   return TRUE;
00310 }
00311 
00312 
00313 // delete all molecules (linear time in worst case)
00314 int MoleculeList::del_all_molecules(void) {
00315   int lastmol;
00316   while ((lastmol=num()) > 0) {
00317     int n = lastmol - 1;
00318     Molecule *m = molecule(n);      // retrieve last molecule in the list
00319     delete m;                       // delete the molecule data structure
00320     molList.remove(n);              // remove the molecule from the list
00321   }
00322   inthash_destroy(&indexIDhash);    // destroy ID to index hash table
00323   inthash_init(&indexIDhash, 5003); // initialize ID to index hash table
00324   make_top((Molecule *)NULL);       // signal there are NO molecules now
00325 
00326   return TRUE;
00327 }
00328 
00329 int MoleculeList::set_default_color(const char *s) {
00330   AtomColor ac(this, scene);
00331   int success = ac.change(s);
00332   if (success) {
00333     defaultAtomColor = s;
00334   }
00335   return success;
00336 }
00337 
00338 int MoleculeList::set_default_representation(const char *s) {
00339   AtomRep ar;
00340   int success = ar.change(s);
00341   if (success) {
00342     defaultAtomRepresentation = s;
00343   }
00344   return success;
00345 }
00346 
00347 int MoleculeList::set_default_selection(const char *s) {
00348   ParseTree *tree = app->atomSelParser->parse(s);
00349   if (!tree) return FALSE;
00350   delete tree;
00351   defaultAtomSelection = s;
00352   return TRUE;
00353 }
00354 
00355 int MoleculeList::set_default_material(const char *s) {
00356   if (app->materialList->material_index(s) < 0)
00357     return FALSE;
00358   defaultAtomMaterial = s;
00359   return TRUE;
00360 }
00361 
00362 // set current atom coloring method
00363 int MoleculeList::set_color(char *s) {
00364   return (currAtomColor->change(s));
00365 }
00366 
00367 
00368 // set current atom representation method
00369 int MoleculeList::set_representation(char *s) {
00370   return (currAtomRep->change(s));
00371 }
00372 
00373 
00374 // set current atom selection
00375 int MoleculeList::set_selection(const char *s) {
00376   // check that the selection text can be parsed
00377   ParseTree *tree = app->atomSelParser->parse(s);
00378   if (!tree) return FALSE;
00379   delete tree;
00380   delete [] currAtomSel;
00381   currAtomSel = stringdup(s);
00382   return TRUE;
00383 }
00384 
00385 
00386 // set current material
00387 int MoleculeList::set_material(char *s) {
00388   currMaterial = app->materialList->material_index(s);
00389   if (currMaterial < 0) {
00390     currMaterial = 0;
00391     msgErr << "Invalid material specified: " << s << sendmsg;
00392     msgErr << "Using default: " << app->materialList->material_name(0)
00393            << sendmsg;
00394     return 0;
00395   }
00396   return 1;
00397 }
00398 
00399 
00400 // return the current material
00401 const char *MoleculeList::material(void) {
00402   return app->materialList->material_name(currMaterial);
00403 }
00404 
00405 
00406 // add a new representation to the nth molecule, copying from the current one
00407 int MoleculeList::add_rep(int n) {
00408   Molecule *mol = molecule(n);
00409   if (!mol) return FALSE;
00410   AtomColor *ac = new AtomColor(*currAtomColor);
00411   AtomRep *ar = new AtomRep(*currAtomRep);
00412   AtomSel *as = new AtomSel(app->atomSelParser, mol->id());
00413   const Material *mat = app->materialList->material(currMaterial);
00414   as->change(currAtomSel, mol);
00415   ac->find(mol);
00416   mol->add_rep(ac, ar, as, mat);
00417   return TRUE;
00418 }
00419 
00420 
00421 // change the graphics representation m, for the specified molecule n, to
00422 // the new settings.  Return success.
00423 int MoleculeList::change_rep(int m, int n) {
00424   Molecule *mol = molecule(n);
00425   if (!mol) return FALSE;
00426   return (mol->change_rep(m, currAtomColor, currAtomRep, currAtomSel) &&
00427           change_repmat(m, n, material()));
00428 }
00429 
00430 
00431 // change just the coloring method for the mth rep in the nth molecule.
00432 int MoleculeList::change_repcolor(int m, int n, char *s) {
00433   Molecule *mol = molecule(n);
00434   if (mol) {
00435     AtomColor ac(*currAtomColor);
00436     if (ac.change(s))
00437       return (mol->change_rep(m, &ac, NULL, NULL));
00438   }
00439   return FALSE;
00440 }
00441   
00442 
00443 // change just the representation for the mth rep in the nth molecule.
00444 int MoleculeList::change_repmethod(int m, int n, char *s) {
00445   Molecule *mol = molecule(n);
00446   if (mol) {
00447     AtomRep ar(*currAtomRep);
00448     if (ar.change(s))
00449       return (mol->change_rep(m, NULL, &ar, NULL));
00450   }
00451   return FALSE;
00452 }
00453   
00454 
00455 // change just the selection for the mth rep in the nth molecule.
00456 int MoleculeList::change_repsel(int m, int n, const char *s) {
00457   Molecule *mol = molecule(n);
00458   if (!mol) return FALSE;
00459   ParseTree *tree = app->atomSelParser->parse(s);
00460   if (!tree) return FALSE;
00461   delete tree;
00462   return (mol->change_rep(m, NULL, NULL, s));
00463 }
00464 
00465 
00466 // change the material for the mth rep in the nth molecule.
00467 int MoleculeList::change_repmat(int m, int n, const char *s) {
00468   Molecule *mol = molecule(n);
00469   if (mol) {
00470     int ind = app->materialList->material_index(s);
00471     if (ind >= 0) {
00472       DrawMolItem *d = mol->component(m);
00473       if (d) {
00474         d->change_material(app->materialList->material(ind));  
00475         return TRUE;
00476       }
00477     }
00478   }
00479   return FALSE;
00480 }
00481 
00482 
00483 // delete a graphics representation m, for molecule n, return success.
00484 int MoleculeList::del_rep(int m, int n) {
00485   Molecule *mol = molecule(n);
00486   if (mol != NULL)
00487     return (mol->del_rep(m) != 0);
00488   return 0;
00489 }
00490 
00491 // derive scaling and centering values from the current top molecule's
00492 // proper centering location, and scaled to fit in (-1 ... 1) box
00493 void MoleculeList::center_from_top_molecule_reps() {
00494   float x, y, z;
00495   
00496   if (topMol && topMol->cov(x,y,z)) {
00497     lastCenter[0] = x;
00498     lastCenter[1] = y;
00499     lastCenter[2] = z;
00500     lastCenter[3] = topMol->scale_factor();
00501   }
00502 }
00503 
00504 // apply the current centering transforms to the top molecule only
00505 void MoleculeList::center_top_molecule(void) {
00506   if (topMol) {
00507     topMol->reset_transformation();
00508     topMol->mult_scale(lastCenter[3]);
00509     topMol->add_cent_trans(-lastCenter[0], -lastCenter[1], -lastCenter[2]);
00510   }
00511 }
00512  
00513 // apply the current centering transforms to all molecules
00514 void MoleculeList::center_all_molecules(void) {
00515   int i;
00516   int n = num();
00517   for (i=0; i<n; i++) {
00518     molecule(i)->reset_transformation();
00519     molecule(i)->mult_scale(lastCenter[3]);
00520     molecule(i)->add_cent_trans(-lastCenter[0], -lastCenter[1], -lastCenter[2]);
00521   }
00522 }
00523 
00524 
00525 // For the given Pickable, determine if it is a molecule or a representation
00526 // of a molecule, and return the proper pointer if it is (NULL otherwise)
00527 Molecule *MoleculeList::check_pickable(Pickable *pobj) {
00528   int i, j, mnum, repnum;
00529 
00530   // loop over all molecules 
00531   mnum = num();
00532   for (i=0; i < mnum; i++) {
00533     // check this molecule to see if it matches
00534     Molecule *mol = molecule(i);
00535     if (pobj == mol)
00536       return mol;
00537 
00538     // and check each of its representations to see if they match
00539     repnum = mol->components();
00540     for (j=0; j < repnum; j++)
00541       if (pobj == mol->component(j))
00542         return mol;
00543 
00544     // check MoleculeGraphics pointer
00545     if (pobj == mol->moleculeGraphics()) 
00546       return mol;
00547   }
00548 
00549   return NULL; // if here, nothing found
00550 }
00551 

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