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

MoleculeList.C

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

Generated on Thu Apr 18 02:44:56 2024 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002