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

AtomSel.C

Go to the documentation of this file.
00001 /***************************************************************************
00002  *cr                                                                       
00003  *cr            (C) Copyright 1995-2011 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: AtomSel.C,v $
00013  *      $Author: johns $        $Locker:  $                $State: Exp $
00014  *      $Revision: 1.165 $      $Date: 2011/12/05 19:14:38 $
00015  *
00016  ***************************************************************************
00017  * DESCRIPTION:
00018  * 
00019  * Parse and maintain the data for selecting atoms.
00020  *
00021  ***************************************************************************/
00022 
00023 #include <math.h>
00024 #include <stdlib.h>
00025 #include <stdio.h>
00026 #include <ctype.h>
00027 #include <string.h>
00028 
00029 #if defined(ARCH_AIX4)
00030 #include <strings.h>
00031 #endif
00032 
00033 #include "Atom.h"
00034 #include "AtomSel.h"
00035 #include "DrawMolecule.h"
00036 #include "MoleculeList.h"
00037 #include "VMDApp.h"
00038 #include "Inform.h"
00039 #include "SymbolTable.h"
00040 #include "ParseTree.h"
00041 #include "JRegex.h"
00042 #include "VolumetricData.h"
00043 #include "PeriodicTable.h"
00044 #include "DrawRingsUtils.h"
00045 
00046 // 'all'
00047 static int atomsel_all(void * ,int, int *) {
00048   return 1;
00049 }
00050 
00051 // 'none'
00052 static int atomsel_none(void *, int num, int *flgs) {
00053   for (int i=num-1; i>=0; i--) {
00054     flgs[i] = FALSE;
00055   }
00056   return 1;
00057 }
00058 
00059 #define generic_atom_data(fctnname, datatype, field)                   \
00060 static int fctnname(void *v, int num, datatype *data, int *flgs) {     \
00061   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;      \
00062   for (int i=0; i<num; i++) {                                          \
00063     if (flgs[i]) {                                                     \
00064       data[i] = atom_sel_mol->atom(i)->field;                          \
00065     }                                                                  \
00066   }                                                                    \
00067   return 1;                                                            \
00068 }
00069 
00070 
00071 #define generic_set_atom_data(fctnname, datatype, fieldtype, field)    \
00072 static int fctnname(void *v, int num, datatype *data, int *flgs) {     \
00073   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;      \
00074   int i;                                                               \
00075   for (i=0; i<num; i++) {                                              \
00076     if (flgs[i]) {                                                     \
00077       atom_sel_mol->atom(i)->field = (fieldtype) data[i];              \
00078     }                                                                  \
00079   }                                                                    \
00080   return 1;                                                            \
00081 }
00082 
00083 
00084 // 'name'
00085 static int atomsel_name(void *v, int num, const char **data, int *flgs) {
00086   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;
00087   for (int i=0; i<num; i++) {
00088     if (flgs[i])
00089       data[i] = (atom_sel_mol->atomNames).name(
00090                   atom_sel_mol->atom(i)->nameindex);
00091   }
00092   return 1;
00093 }
00094 
00095 
00096 // 'type'
00097 static int atomsel_type(void *v, int num, const char **data, int *flgs) {
00098   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;
00099   for (int i=0; i<num; i++) {
00100     if (flgs[i])
00101       data[i] = (atom_sel_mol->atomTypes).name(
00102                   atom_sel_mol->atom(i)->typeindex);
00103   }
00104   return 1;
00105 }
00106 
00107 // XXX probably only use this for internal testing
00108 // 'backbonetype'
00109 static int atomsel_backbonetype(void *v, int num, const char **data, int *flgs) {
00110   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;
00111   for (int i=0; i<num; i++) {
00112     if (flgs[i]) {
00113       switch (atom_sel_mol->atom(i)->atomType) {
00114         case ATOMNORMAL:
00115           data[i] = "normal";
00116           break;
00117 
00118         case ATOMPROTEINBACK:
00119           data[i] = "proteinback";
00120           break;
00121 
00122         case ATOMNUCLEICBACK:
00123           data[i] = "nucleicback";
00124           break;
00125 
00126         case ATOMHYDROGEN:
00127           data[i] = "hydrogen";
00128           break;
00129 
00130         default:
00131           data[i] = "unknown";
00132           break;
00133       }
00134     }
00135   }
00136   return 1;
00137 }
00138 
00139 
00140 // XXX probably only use this for internal testing
00141 // 'residuetype'
00142 static int atomsel_residuetype(void *v, int num, const char **data, int *flgs) {
00143   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;
00144   for (int i=0; i<num; i++) {
00145     if (flgs[i]) {
00146       switch (atom_sel_mol->atom(i)->residueType) {
00147         case RESNOTHING:
00148           data[i] = "nothing";
00149           break;
00150 
00151         case RESPROTEIN:
00152           data[i] = "protein";
00153           break;
00154 
00155         case RESNUCLEIC:
00156           data[i] = "nucleic";
00157           break;
00158 
00159         case RESWATERS:
00160           data[i] = "waters";
00161           break;
00162 
00163         default:
00164           data[i] = "unknown";
00165           break;
00166       }
00167     }
00168   }
00169   return 1;
00170 }
00171 
00172 
00173 // 'atomicnumber'
00174 generic_atom_data(atomsel_atomicnumber, int, atomicnumber)
00175 
00176 static int atomsel_set_atomicnumber(void *v, int num, int *data, int *flgs) {
00177   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;
00178   int i;
00179   for (i=0; i<num; i++) {
00180     if (flgs[i]) {
00181       atom_sel_mol->atom(i)->atomicnumber = (int) data[i];
00182     }
00183   }
00184   // when user sets data fields they are marked as valid fields in BaseMolecule
00185   atom_sel_mol->set_dataset_flag(BaseMolecule::ATOMICNUMBER);
00186   return 1;
00187 }
00188 
00189 
00190 // 'element'
00191 static int atomsel_element(void *v, int num, const char **data, int *flgs) {
00192   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;
00193   for (int i=0; i<num; i++) {
00194     if (flgs[i])
00195       data[i] = get_pte_label(atom_sel_mol->atom(i)->atomicnumber);
00196   }
00197   return 1;
00198 }
00199 static int atomsel_set_element(void *v, int num, const char **data, int *flgs) {
00200   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;
00201   for (int i=0; i<num; i++) {
00202     if (flgs[i]) {
00203       int idx = get_pte_idx_from_string((const char *)(data[i]));
00204       atom_sel_mol->atom(i)->atomicnumber = idx;
00205     }
00206   }
00207   // when user sets data fields they are marked as valid fields in BaseMolecule
00208   atom_sel_mol->set_dataset_flag(BaseMolecule::ATOMICNUMBER);
00209   return 1;
00210 }
00211 
00212 
00213 // 'index'
00214 static int atomsel_index(void *v, int num, int *data, int *flgs) { 
00215   for (int i=0; i<num; i++) {
00216     if (flgs[i]) {
00217       data[i] = i; // zero-based
00218     }
00219   }
00220   return 1;
00221 }
00222 
00223 
00224 // 'serial' (one-based atom index)
00225 static int atomsel_serial(void *v, int num, int *data, int *flgs) { 
00226   for (int i=0; i<num; i++) {
00227     if (flgs[i]) {
00228       data[i] = i + 1; // one-based
00229     }
00230   }
00231   return 1;
00232 }
00233 
00234 
00235 // 'fragment'
00236 static int atomsel_fragment(void *v, int num, int *data, int *flgs) {
00237   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;
00238   for (int i=0; i<num; i++) {
00239     if (flgs[i]) {
00240       int residue = atom_sel_mol->atom(i)->uniq_resid;
00241       data[i] = (atom_sel_mol->residue(residue))->fragment;
00242     }
00243   }
00244   return 1;
00245 }
00246 
00247 
00248 // 'numbonds'
00249 generic_atom_data(atomsel_numbonds, int, bonds)
00250 
00251 
00252 // 'residue'
00253 generic_atom_data(atomsel_residue, int, uniq_resid)
00254 
00255 
00256 // 'resname'
00257 static int atomsel_resname(void *v, int num, const char **data, int *flgs) {
00258   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;
00259   for (int i=0; i<num; i++) {
00260     if (flgs[i])
00261       data[i] = (atom_sel_mol->resNames).name(
00262                  atom_sel_mol->atom(i)->resnameindex);
00263   }
00264   return 1;
00265 }
00266 
00267 
00268 // 'altloc'
00269 static int atomsel_altloc(void *v, int num, const char **data, int *flgs) {
00270   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;                 
00271   for (int i=0; i<num; i++) {
00272     if (flgs[i])
00273       data[i] = (atom_sel_mol->altlocNames).name(
00274         atom_sel_mol->atom(i)->altlocindex);
00275   }
00276   return 1;
00277 }
00278 static int atomsel_set_altloc(void *v, int num, const char **data, int *flgs) {
00279   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;                 
00280   NameList<int> &arr = atom_sel_mol->altlocNames;
00281   for (int i=0; i<num; i++) {
00282     if (flgs[i]) {
00283       int ind = arr.add_name((const char *)(data[i]), arr.num());
00284       atom_sel_mol->atom(i)->altlocindex = ind;
00285     }
00286   }
00287   // when user sets data fields they are marked as valid fields in BaseMolecule
00288   atom_sel_mol->set_dataset_flag(BaseMolecule::ALTLOC);
00289   return 1;
00290 }
00291 
00292 
00293 // 'insertion'
00294 generic_atom_data(atomsel_insertion, const char *, insertionstr)
00295 
00296 
00297 // 'chain'
00298 static int atomsel_chain(void *v, int num, const char **data, int *flgs) {
00299   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;                 
00300   for (int i=0; i<num; i++) {
00301     if (flgs[i])
00302       data[i] = (atom_sel_mol->chainNames).name(
00303                   atom_sel_mol->atom(i)->chainindex);
00304   }
00305   return 1;
00306 }
00307 
00308 
00309 // 'segname'
00310 static int atomsel_segname(void *v, int num, const char **data, int *flgs) {
00311   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;
00312   for (int i=0; i<num; i++) {
00313     if (flgs[i])
00314       data[i] = (atom_sel_mol->segNames).name(
00315                  atom_sel_mol->atom(i)->segnameindex);
00316   }
00317   return 1;
00318 }
00319 
00320 
00321 // The next few set functions affect the namelists kept in BaseMolecule
00322 static int atomsel_set_name(void *v, int num, const char **data, int *flgs) {
00323   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;
00324   NameList<int> &arr = atom_sel_mol->atomNames;
00325   for (int i=0; i<num; i++) {
00326     if (flgs[i]) {
00327       int ind = arr.add_name((const char *)(data[i]), arr.num());
00328       atom_sel_mol->atom(i)->nameindex = ind;
00329     }
00330   }
00331   return 1;
00332 }
00333 
00334 static int atomsel_set_type(void *v, int num, const char **data, int *flgs) {
00335   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;
00336   NameList<int> &arr = atom_sel_mol->atomTypes;
00337   for (int i=0; i<num; i++) {
00338     if (flgs[i]) {
00339       int ind = arr.add_name((const char *)(data[i]), arr.num());
00340       atom_sel_mol->atom(i)->typeindex = ind;
00341     }
00342   }
00343   return 1;
00344 }
00345 
00346 static int atomsel_set_resname(void *v, int num, const char **data, int *flgs) {
00347   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;
00348   NameList<int> &arr = atom_sel_mol->resNames;
00349   for (int i=0; i<num; i++) {
00350     if (flgs[i]) {
00351       int ind = arr.add_name((const char *)(data[i]), arr.num());
00352       atom_sel_mol->atom(i)->resnameindex = ind;
00353     }
00354   }
00355   return 1;
00356 }
00357 
00358 static int atomsel_set_chain(void *v, int num, const char **data, int *flgs) {
00359   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;
00360   NameList<int> &arr = atom_sel_mol->chainNames;
00361   for (int i=0; i<num; i++) {
00362     if (flgs[i]) {
00363       int ind = arr.add_name((const char *)(data[i]), arr.num());
00364       atom_sel_mol->atom(i)->chainindex = ind;
00365     }
00366   }
00367   return 1;
00368 }
00369 
00370 static int atomsel_set_segname(void *v, int num, const char **data, int *flgs) {
00371   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;
00372   NameList<int> &arr = atom_sel_mol->segNames;
00373   for (int i=0; i<num; i++) {
00374     if (flgs[i]) {
00375       int ind = arr.add_name((const char *)(data[i]), arr.num());
00376       atom_sel_mol->atom(i)->segnameindex = ind;
00377     }
00378   }
00379   return 1;
00380 }
00381 
00382 
00383 // 'radius'
00384 static int atomsel_radius(void *v, int num, double *data, int *flgs) {
00385   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;
00386   float *radius = atom_sel_mol->radius();
00387   for (int i=0; i<num; i++)
00388     if (flgs[i]) data[i] = radius[i];
00389   return 1;
00390 }
00391 static int atomsel_set_radius(void *v, int num, double *data, int *flgs) {
00392   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;
00393   float *radius = atom_sel_mol->radius();
00394   for (int i=0; i<num; i++)
00395     if (flgs[i]) radius[i] = (float) data[i];
00396 
00397   // when user sets data fields they are marked as valid fields in BaseMolecule
00398   atom_sel_mol->set_dataset_flag(BaseMolecule::RADIUS);
00399 
00400   // Force min/max atom radii to be updated since we've updated the data
00401   atom_sel_mol->set_radii_changed();
00402 
00403   return 1;
00404 }
00405 
00406 
00407 // 'mass'
00408 static int atomsel_mass(void *v, int num, double *data, int *flgs) {
00409   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;
00410   float *mass = atom_sel_mol->mass();
00411   for (int i=0; i<num; i++)
00412     if (flgs[i]) data[i] = mass[i];
00413   return 1;
00414 }
00415 static int atomsel_set_mass(void *v, int num, double *data, int *flgs) {
00416   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;
00417   float *mass = atom_sel_mol->mass();
00418   for (int i=0; i<num; i++)
00419     if (flgs[i]) mass[i] = (float) data[i];
00420   // when user sets data fields they are marked as valid fields in BaseMolecule
00421   atom_sel_mol->set_dataset_flag(BaseMolecule::MASS);
00422   return 1;
00423 }
00424 
00425 
00426 // 'charge'
00427 static int atomsel_charge(void *v, int num, double *data, int *flgs) {
00428   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;
00429   float *charge = atom_sel_mol->charge();
00430   for (int i=0; i<num; i++)
00431     if (flgs[i]) data[i] = charge[i];
00432   return 1;
00433 }
00434 static int atomsel_set_charge(void *v, int num, double *data, int *flgs) {
00435   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;
00436   float *charge = atom_sel_mol->charge();
00437   for (int i=0; i<num; i++)
00438     if (flgs[i]) charge[i] = (float) data[i];
00439   // when user sets data fields they are marked as valid fields in BaseMolecule
00440   atom_sel_mol->set_dataset_flag(BaseMolecule::CHARGE);
00441   return 1;
00442 }
00443 
00444 
00445 // 'beta'
00446 static int atomsel_beta(void *v, int num, double *data, int *flgs) {
00447   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;
00448   float *beta = atom_sel_mol->beta();
00449   for (int i=0; i<num; i++)
00450     if (flgs[i]) data[i] = beta[i];
00451   return 1;
00452 }
00453 static int atomsel_set_beta(void *v, int num, double *data, int *flgs) {
00454   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;
00455   float *beta = atom_sel_mol->beta();
00456   for (int i=0; i<num; i++)
00457     if (flgs[i]) beta[i] = (float) data[i];
00458   // when user sets data fields they are marked as valid fields in BaseMolecule
00459   atom_sel_mol->set_dataset_flag(BaseMolecule::BFACTOR);
00460   return 1;
00461 }
00462 
00463 
00464 // 'occupancy?'
00465 static int atomsel_occupancy(void *v, int num, double *data, int *flgs) {
00466   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;
00467   float *occupancy = atom_sel_mol->occupancy();
00468   for (int i=0; i<num; i++)
00469     if (flgs[i]) data[i] = occupancy[i];
00470   return 1;
00471 }
00472 static int atomsel_set_occupancy(void *v, int num, double *data, int *flgs) {
00473   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;
00474   float *occupancy = atom_sel_mol->occupancy();
00475   for (int i=0; i<num; i++)
00476     if (flgs[i]) occupancy[i] = (float) data[i];
00477   // when user sets data fields they are marked as valid fields in BaseMolecule
00478   atom_sel_mol->set_dataset_flag(BaseMolecule::OCCUPANCY);
00479   return 1;
00480 }
00481 
00482 
00483 // 'resid'
00484 static int atomsel_resid(void *v, int num, int *data, int *flgs) {
00485   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;
00486   for (int i=0; i<num; i++) {
00487     if (flgs[i]) {
00488       data[i] = atom_sel_mol->atom(i)->resid;
00489     }
00490   }
00491   return 1;
00492 }
00493 static int atomsel_set_resid(void *v, int num, int *data, int *flgs) {
00494   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;
00495   for (int i=0; i<num; i++) {
00496     if (flgs[i])
00497       atom_sel_mol->atom(i)->resid = data[i];
00498   }
00499   return 1;
00500 }
00501 
00502 
00503 
00504 #define generic_atom_boolean(fctnname, comparison)                    \
00505 static int fctnname(void *v, int num, int *flgs) {                    \
00506   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;     \
00507   for (int i=0; i<num; i++) {                                         \
00508     if (flgs[i]) {                                                    \
00509       flgs[i] = atom_sel_mol->atom(i)->comparison;                    \
00510     }                                                                 \
00511   }                                                                   \
00512   return 1;                                                           \
00513 }
00514 
00515 // 'backbone'
00516 static int atomsel_backbone(void *v, int num, int *flgs) {
00517   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;
00518   for (int i=0; i<num; i++) {
00519     if (flgs[i]) {
00520       const MolAtom *a = atom_sel_mol->atom(i);
00521       flgs[i] = (a->atomType == ATOMPROTEINBACK ||
00522                  a->atomType == ATOMNUCLEICBACK);
00523     }
00524   }
00525   return 1;
00526 }
00527 
00528 // 'h' (hydrogen)
00529 generic_atom_boolean(atomsel_hydrogen, atomType == ATOMHYDROGEN)
00530 
00531 
00532 // 'protein'
00533 generic_atom_boolean(atomsel_protein, residueType == RESPROTEIN)
00534 
00535 
00536 // 'nucleic'
00537 generic_atom_boolean(atomsel_nucleic, residueType == RESNUCLEIC)
00538 
00539 
00540 // 'water'
00541 generic_atom_boolean(atomsel_water, residueType == RESWATERS)
00542 
00543 #define generic_sstruct_boolean(fctnname, comparison)                    \
00544 static int fctnname(void *v, int num, int *flgs) {                       \
00545   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;        \
00546   atom_sel_mol->need_secondary_structure(1);                             \
00547   for (int i=0; i<num; i++) {                                            \
00548     int s;                                                               \
00549     if (flgs[i]) {                                                       \
00550       s = atom_sel_mol->residue(                                         \
00551                                   atom_sel_mol->atom(i)->uniq_resid      \
00552                                   )->sstruct;                            \
00553       if (!comparison) {                                                 \
00554         flgs[i] = 0;                                                     \
00555       }                                                                  \
00556     }                                                                    \
00557   }                                                                      \
00558   return 1;                                                              \
00559 }
00560 
00561 // once I define a structure, I don't need to recompute; hence the 
00562 //   need_secondary_structure(0);
00563 #define generic_set_sstruct_boolean(fctnname, newval)                    \
00564 static int fctnname(void *v, int num, int *data, int *flgs) {            \
00565   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;        \
00566   atom_sel_mol->need_secondary_structure(0);                             \
00567   for (int i=0; i<num; i++) {                                            \
00568     if (flgs[i] && data[i]) {                                            \
00569         atom_sel_mol->residue(atom_sel_mol->atom(i)->uniq_resid)         \
00570           ->sstruct = newval;                                            \
00571     }                                                                    \
00572   }                                                                      \
00573   return 1;                                                              \
00574 }
00575 
00576 
00577 // XXX recursive routines should be replaced by an iterative version with
00578 // it's own stack, so that huge molecules don't overflow the stack
00579 static void recursive_find_sidechain_atoms(BaseMolecule *mol, int *sidechain,
00580                                            int atom_index) {
00581   // Have I been here before?
00582   if (sidechain[atom_index] == 2) 
00583     return;
00584 
00585   // Is this a backbone atom
00586   MolAtom *atom = mol->atom(atom_index);
00587   if (atom->atomType == ATOMPROTEINBACK ||
00588       atom->atomType == ATOMNUCLEICBACK) return;
00589   
00590   // mark this atom
00591   sidechain[atom_index] = 2;
00592 
00593   // try the atoms to which this is bonded
00594   for (int i=0; i<atom->bonds; i++) {
00595     recursive_find_sidechain_atoms(mol, sidechain, atom->bondTo[i]);
00596   }
00597 }
00598 
00599 // give an array where 1 indicates an atom on the sidechain, find the
00600 // connected atoms which are also on the sidechain
00601 static void find_sidechain_atoms(BaseMolecule *mol, int *sidechain) {
00602   for (int i=0; i<mol->nAtoms; i++) {
00603     if (sidechain[i] == 1) {
00604       recursive_find_sidechain_atoms(mol, sidechain, i);
00605     }
00606   }
00607 }
00608 
00609 
00610 // 'sidechain' is tricky.  I start from a protein CA, pick a bond which
00611 // isn't along the backbone (and discard it once if it is a hydrogen),
00612 // and follow the atoms until I stop at another backbone atom or run out
00613 // of atoms
00614 static int atomsel_sidechain(void *v, int num, int *flgs) {
00615   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;               
00616   const float *mass = atom_sel_mol->mass();
00617   int *seed = new int[num];
00618   int i;
00619 
00620   // generate a list of the "CB" atoms (or whatever they are)
00621   for (i=0; i<num; i++) {
00622     seed[i] = 0;
00623   }
00624 
00625   // get the CA and HA2 name index
00626   int CA = atom_sel_mol->atomNames.typecode((char *) "CA");
00627 
00628   // for each protein
00629   for (int pfrag=atom_sel_mol->pfragList.num()-1; pfrag>=0; pfrag--) {
00630     // get a residue
00631     Fragment &frag = *(atom_sel_mol->pfragList[pfrag]);
00632     for (int res = frag.num()-1; res >=0; res--) {
00633       // find the CA
00634       int atomid = atom_sel_mol->find_atom_in_residue(CA, frag[res]);
00635       if (atomid < 0) {
00636         msgErr << "atomselection: sidechain: cannot find CA" << sendmsg;
00637         continue;
00638       }
00639       // find at most two neighbors which are not on the backbone
00640       MolAtom *atom = atom_sel_mol->atom(atomid);
00641       int b1 = -1, b2 = -1;
00642       for (i=0; i<atom->bonds; i++) {
00643         int bondtype = atom_sel_mol->atom(atom->bondTo[i])->atomType;
00644         if (bondtype == ATOMNORMAL || bondtype == ATOMHYDROGEN) {
00645           if (b1 == -1) {
00646             b1 = atom->bondTo[i];
00647           } else {
00648             if (b2 == -1) {
00649               b2 = atom->bondTo[i];
00650             } else {
00651               msgErr << "atomselection: sidechain: protein residue index " 
00652                      << res << ", C-alpha index " << i << " has more than "
00653                      << "two non-backbone bonds; ignoring the others"
00654                      << sendmsg;
00655             }
00656           }
00657         }
00658       }
00659       if (b1 == -1) 
00660         continue;
00661 
00662       if (b2 != -1) {  // find the right one
00663         // first check the number of atoms and see if I have a lone H
00664         int c1 = atom_sel_mol->atom(b1)->bonds;
00665         int c2 = atom_sel_mol->atom(b2)->bonds;
00666         if (c1 == 1 && c2 > 1) {
00667           b1 = b2;
00668         } else if (c2 == 1 && c1 > 1) {
00669           b1 = b1;
00670         } else if (c1 ==1 && c2 == 1) {
00671           // check the masses
00672           float m1 = mass[b1];
00673           float m2 = mass[b2];
00674           if (m1 > 2.3 && m2 <= 2.3) {
00675             b1 = b2;
00676           } else if (m2 > 2.3 && m1 <= 2.3) {
00677             b1 = b1;
00678           } else if (m1 <= 2.0 && m2 <= 2.3) {
00679             // should have two H's, find the "first" of these
00680             if (strcmp(
00681               (atom_sel_mol->atomNames).name(atom_sel_mol->atom(b1)->nameindex),
00682               (atom_sel_mol->atomNames).name(atom_sel_mol->atom(b2)->nameindex)
00683               ) > 0) {
00684               b1 = b2;
00685             } // else b1 = b1
00686           } else {
00687             msgErr << "atomselect: sidechain:  protein residue index " 
00688                    << res << ", C-alpha index " << i << " has sidechain-like "
00689                    << "atom (indices " << b1 << " and " << b2 << "), and "
00690                    << "I cannot determine which to call a sidechain -- "
00691                    << "I'll guess" << sendmsg;
00692             if (strcmp(
00693               (atom_sel_mol->atomNames).name(atom_sel_mol->atom(b1)->nameindex),
00694               (atom_sel_mol->atomNames).name(atom_sel_mol->atom(b2)->nameindex)
00695               ) > 0) {
00696               b1 = b2;
00697             }
00698           } // punted
00699         } // checked connections and masses
00700       } // found the right one; it is b1.
00701       seed[b1] = 1;
00702 
00703     } // loop over residues
00704   } // loop over protein fragments
00705 
00706   // do the search for all the sidechain atoms (returned in seed)
00707   find_sidechain_atoms(atom_sel_mol, seed);
00708 
00709   // set the return values
00710   for (i=0; i<num; i++) {
00711     if (flgs[i]) 
00712       flgs[i] = (seed[i] != 0);
00713   }
00714 
00715   delete [] seed;
00716 
00717   return 1;
00718 }
00719 
00720 
00721 // which of these are helices?
00722 generic_sstruct_boolean(atomsel_helix, (s == SS_HELIX_ALPHA ||
00723                                         s == SS_HELIX_3_10  ||
00724                                         s == SS_HELIX_PI))
00725 generic_sstruct_boolean(atomsel_alpha_helix, (s == SS_HELIX_ALPHA))
00726 generic_sstruct_boolean(atomsel_3_10_helix, (s == SS_HELIX_3_10))
00727 generic_sstruct_boolean(atomsel_pi_helix, (s == SS_HELIX_PI))
00728 
00729 // Makes the residue into a HELIX_ALPHA
00730 generic_set_sstruct_boolean(atomsel_set_helix, SS_HELIX_ALPHA)
00731 // Makes the residue into a HELIX_3_10
00732 generic_set_sstruct_boolean(atomsel_set_3_10_helix, SS_HELIX_3_10)
00733 // Makes the residue into a HELIX_PI
00734 generic_set_sstruct_boolean(atomsel_set_pi_helix, SS_HELIX_PI)
00735 
00736 // which of these are beta sheets?
00737 generic_sstruct_boolean(atomsel_sheet, (s == SS_BETA ||
00738                                         s == SS_BRIDGE ))
00739 generic_sstruct_boolean(atomsel_extended_sheet, (s == SS_BETA))
00740 generic_sstruct_boolean(atomsel_bridge_sheet, (s == SS_BRIDGE ))
00741 
00742 // Makes the residue into a BETA
00743 generic_set_sstruct_boolean(atomsel_set_sheet, SS_BETA)
00744 generic_set_sstruct_boolean(atomsel_set_bridge_sheet, SS_BRIDGE)
00745 
00746 // which of these are coils?
00747 generic_sstruct_boolean(atomsel_coil, (s == SS_COIL))
00748 
00749 // Makes the residue into COIL
00750 generic_set_sstruct_boolean(atomsel_set_coil, SS_COIL)
00751 
00752 // which of these are TURNS?
00753 generic_sstruct_boolean(atomsel_turn, (s == SS_TURN))
00754 
00755 // Makes the residue into TURN
00756 generic_set_sstruct_boolean(atomsel_set_turn, SS_TURN)
00757 
00758 // return the sstruct information as a 1 character string
00759 static int atomsel_sstruct(void *v, int num, const char **data, int *flgs) {
00760   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;
00761   atom_sel_mol->need_secondary_structure(1);
00762   for (int i=0; i<num; i++) {
00763     if (flgs[i]) {
00764       switch(atom_sel_mol->residue(atom_sel_mol->atom(i)->uniq_resid)->sstruct) {
00765         case SS_HELIX_ALPHA: data[i] = "H"; break;
00766         case SS_HELIX_3_10 : data[i] = "G"; break;
00767         case SS_HELIX_PI   : data[i] = "I"; break;
00768         case SS_BETA       : data[i] = "E"; break;
00769         case SS_BRIDGE     : data[i] = "B"; break;
00770         case SS_TURN       : data[i] = "T"; break;
00771         default:
00772         case SS_COIL       : data[i] = "C"; break;
00773       }
00774     }
00775   }
00776   return 1;
00777 }
00778 
00779 
00780 // set the secondary structure based on a string value
00781 static int atomsel_set_sstruct(void *v, int num, const char **data, int *flgs) {
00782   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;
00783   char c;
00784   // Defining it here so remind myself that I don't need STRIDE (or
00785   // whoever) to do it automatically
00786   atom_sel_mol->need_secondary_structure(0);
00787   for (int i=0; i<num; i++) {
00788     if (flgs[i]) {
00789       if (strlen(data[i]) == 0) {
00790         msgErr << "cannot set a 0 length secondary structure string"
00791                << sendmsg;
00792       } else {
00793         c = ((const char *) data[i])[0];
00794         if (strlen(data[i]) > 1) {
00795           while (1) {
00796  if (!strcasecmp((const char *) data[i], "helix")) { c = 'H'; break;}
00797  if (!strcasecmp((const char *) data[i], "alpha")) { c = 'H'; break;}
00798  if (!strcasecmp((const char *) data[i], "alpha_helix")) { c = 'H'; break;}
00799  if (!strcasecmp((const char *) data[i], "alphahelix"))  { c = 'H'; break;}
00800  if (!strcasecmp((const char *) data[i], "alpha helix")) { c = 'H'; break;}
00801 
00802  if (!strcasecmp((const char *) data[i], "pi"))        { c = 'I'; break;}
00803  if (!strcasecmp((const char *) data[i], "pi_helix"))  { c = 'I'; break;}
00804  if (!strcasecmp((const char *) data[i], "pihelix"))   { c = 'I'; break;}
00805  if (!strcasecmp((const char *) data[i], "pi helix"))  { c = 'I'; break;}
00806 
00807  if (!strcasecmp((const char *) data[i], "310"))       { c = 'G'; break;}
00808  if (!strcasecmp((const char *) data[i], "310_helix")) { c = 'G'; break;}
00809  if (!strcasecmp((const char *) data[i], "3_10"))      { c = 'G'; break;}
00810  if (!strcasecmp((const char *) data[i], "3"))         { c = 'G'; break;}
00811  if (!strcasecmp((const char *) data[i], "310 helix")) { c = 'G'; break;}
00812  if (!strcasecmp((const char *) data[i], "3_10_helix")){ c = 'G'; break;}
00813  if (!strcasecmp((const char *) data[i], "3_10 helix")){ c = 'G'; break;}
00814  if (!strcasecmp((const char *) data[i], "3 10 helix")){ c = 'G'; break;}
00815  if (!strcasecmp((const char *) data[i], "helix_3_10")){ c = 'G'; break;}
00816  if (!strcasecmp((const char *) data[i], "helix 3 10")){ c = 'G'; break;}
00817  if (!strcasecmp((const char *) data[i], "helix3_10")) { c = 'G'; break;}
00818  if (!strcasecmp((const char *) data[i], "helix310"))  { c = 'G'; break;}
00819 
00820  if (!strcasecmp((const char *) data[i], "beta"))      { c = 'E'; break;}
00821  if (!strcasecmp((const char *) data[i], "betasheet")) { c = 'E'; break;}
00822  if (!strcasecmp((const char *) data[i], "beta_sheet")){ c = 'E'; break;}
00823  if (!strcasecmp((const char *) data[i], "beta sheet")){ c = 'E'; break;}
00824  if (!strcasecmp((const char *) data[i], "sheet"))     { c = 'E'; break;}
00825  if (!strcasecmp((const char *) data[i], "strand"))    { c = 'E'; break;}
00826  if (!strcasecmp((const char *) data[i], "beta_strand"))  { c = 'E'; break;}
00827  if (!strcasecmp((const char *) data[i], "beta strand"))  { c = 'E'; break;}
00828 
00829  if (!strcasecmp((const char *) data[i], "turn"))  { c = 'T'; break;}
00830 
00831  if (!strcasecmp((const char *) data[i], "coil"))     { c = 'C'; break;}
00832  if (!strcasecmp((const char *) data[i], "unknown"))  { c = 'C'; break;}
00833  c = 'X';
00834  break;
00835           } // while (1)
00836         }
00837         // and set the value
00838         int s = SS_COIL;
00839         switch ( c ) {
00840         case 'H':
00841         case 'h': s = SS_HELIX_ALPHA; break;
00842         case '3':
00843         case 'G':
00844         case 'g': s = SS_HELIX_3_10; break;
00845         case 'P':  // so you can say 'pi'
00846         case 'p':
00847         case 'I':
00848         case 'i': s = SS_HELIX_PI; break;
00849         case 'S':  // for "sheet"
00850         case 's':
00851         case 'E':
00852         case 'e': s = SS_BETA; break;
00853         case 'B':
00854         case 'b': s = SS_BRIDGE; break;
00855         case 'T':
00856         case 't': s = SS_TURN; break;
00857         case 'L': // L is from PHD and may be an alternate form
00858         case 'l':
00859         case 'C':
00860         case 'c': s = SS_COIL; break;
00861         default: {
00862           msgErr << "Unknown sstruct assignment: '"
00863             << (const char *) data[i] << "'" << sendmsg;
00864           s = SS_COIL; break;
00865         }
00866         }
00867         atom_sel_mol->residue(atom_sel_mol->atom(i)->uniq_resid)->sstruct = s;
00868       }
00869     }
00870   }
00871   return 1;
00872 }
00873 
00874 
00876 //      and leave the rest alone.
00877 // It is slower this way, but easier to understand
00878 static void mark_atoms_given_residue(DrawMolecule *mol, int residue, int *on)
00879 {
00880   ResizeArray<int> *atoms = &(mol->residueList[residue]->atoms);
00881   for (int i= atoms->num()-1; i>=0; i--) {
00882      on[(*atoms)[i]] = TRUE;
00883   }
00884 }
00885 
00886 
00887 // macro for either protein or nucleic fragments
00888 #define fragment_data(fctn, fragtype)                                         \
00889 static int fctn(void *v, int num, int *data, int *)                           \
00890 {                                                                             \
00891   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;                     \
00892    int *tmp = new int[num];                                                   \
00893    int i;                                                                     \
00894    for (i=num-1; i>=0; i--) {  /* clear the arrays */                 \
00895       tmp[i] = 0;                                                             \
00896       data[i] = -1;  /* default is -1 for 'not a [np]frag' */                 \
00897    }                                                                          \
00898    /* for each fragment */                                                    \
00899    for ( i=atom_sel_mol->fragtype.num()-1; i>=0; i--) {                       \
00900       /* for each residues of the fragment */                                 \
00901       int j;                                                                  \
00902       for (j=atom_sel_mol->fragtype[i]->num()-1; j>=0; j--) {                 \
00903          /* mark the atoms in the fragment */                                 \
00904          mark_atoms_given_residue(atom_sel_mol,(*atom_sel_mol->fragtype[i])[j], tmp);      \
00905       }                                                                       \
00906       /* and label them with the appropriate number */                        \
00907       for (j=num-1; j>=0; j--) {                                              \
00908          if (tmp[j]) {                                                        \
00909             data[j] = i;                                                      \
00910             tmp[j] = 0;                                                       \
00911          }                                                                    \
00912       }                                                                       \
00913    }                                                                          \
00914    delete [] tmp;                                                             \
00915    return 1;                                                                  \
00916 }
00917 
00918 fragment_data(atomsel_pfrag, pfragList)
00919 fragment_data(atomsel_nfrag, nfragList)
00920 
00921 static Timestep *selframe(DrawMolecule *atom_sel_mol, int which_frame) {
00922   Timestep *r;
00923   switch (which_frame) {
00924    case AtomSel::TS_LAST: r = atom_sel_mol->get_last_frame(); break;
00925 
00926    case AtomSel::TS_NOW : r = atom_sel_mol->current(); break;
00927    default: {
00928      if (!atom_sel_mol->get_frame(which_frame)) {
00929        r = atom_sel_mol->get_last_frame();
00930 
00931      } else {
00932        r = atom_sel_mol->get_frame(which_frame);
00933      }
00934    }
00935   }
00936   return r;
00937 }
00938 
00939 
00940 #if defined(VMDWITHCARBS)
00941 // 'pucker'
00942 static int atomsel_pucker(void *v, int num, double *data, int *flgs) {
00943   int i;
00944   SmallRing *ring;
00945   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;
00946   memset(data, 0, num*sizeof(double));
00947   int which_frame = ((atomsel_ctxt *)v)->which_frame;
00948   Timestep *ts = selframe(atom_sel_mol, which_frame);
00949   if (!ts || !ts->pos) {
00950     return 1;
00951   }
00952 
00953   // XXX We're hijacking the ring list in BaseMolecule at present.
00954   //     It might be better to build our own independent one, but
00955   //     this way there's only one ring list in memory at a time.
00956   atom_sel_mol->find_small_rings_and_links(5, 6);
00957 
00958   for (i=0; i < atom_sel_mol->smallringList.num(); i++) {
00959     ring = atom_sel_mol->smallringList[i];
00960     int N = ring->num();
00961 
00962     // accept rings of size 5 or 6
00963     if (N >= 5 && N <= 6) {
00964       float pucker = hill_reilly_ring_pucker((*ring), ts->pos);
00965       
00966       int j;
00967       for (j=0; j<N; j++) {
00968         int ind = (*ring)[j];
00969         if (flgs[ind])
00970           data[ind] = pucker;
00971       }
00972     }
00973   }
00974 
00975   return 1;
00976 }
00977 #endif
00978 
00979 static int atomsel_user(void *v, int num, double *data, int *flgs) {
00980   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;                     
00981   int which_frame = ((atomsel_ctxt *)v)->which_frame;
00982   Timestep *ts = selframe(atom_sel_mol, which_frame);
00983   if (!ts || !ts->user) {
00984     memset(data, 0, num*sizeof(double));
00985     return 1;                                                           
00986   }
00987   for (int i=0; i<num; i++) {                                         
00988     if (flgs[i]) {                                                            
00989       data[i] = ts->user[i];                                          
00990     }                                                                         
00991   }                                                                           
00992   return 1;                                                                  
00993 }
00994 static int atomsel_set_user(void *v, int num, double *data, int *flgs) {
00995   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;                     
00996   int which_frame = ((atomsel_ctxt *)v)->which_frame;
00997   Timestep *ts = selframe(atom_sel_mol, which_frame);
00998   if (!ts) return 0;
00999   if (!ts->user) {
01000     ts->user= new float[num];
01001     memset(ts->user, 0, num*sizeof(float));
01002   }
01003   for (int i=0; i<num; i++) {                                         
01004     if (flgs[i]) {                                                            
01005       ts->user[i] = (float)data[i];                                           
01006     }                                                                         
01007   }                                                                           
01008   return 1;                                                                  
01009 }
01010 
01011 static int atomsel_user2(void *v, int num, double *data, int *flgs) {
01012   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;                     
01013   int which_frame = ((atomsel_ctxt *)v)->which_frame;
01014   Timestep *ts = selframe(atom_sel_mol, which_frame);
01015   if (!ts || !ts->user2) {
01016     memset(data, 0, num*sizeof(double));
01017     return 1;                                                           
01018   }
01019   for (int i=0; i<num; i++) {                                         
01020     if (flgs[i]) {                                                            
01021       data[i] = ts->user2[i];                                         
01022     }                                                                         
01023   }                                                                           
01024   return 1;                                                                  
01025 }
01026 static int atomsel_set_user2(void *v, int num, double *data, int *flgs) {
01027   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;                     
01028   int which_frame = ((atomsel_ctxt *)v)->which_frame;
01029   Timestep *ts = selframe(atom_sel_mol, which_frame);
01030   if (!ts) return 0;
01031   if (!ts->user2) {
01032     ts->user2= new float[num];
01033     memset(ts->user2, 0, num*sizeof(float));
01034   }
01035   for (int i=0; i<num; i++) {                                         
01036     if (flgs[i]) {                                                            
01037       ts->user2[i] = (float)data[i];                                          
01038     }                                                                         
01039   }                                                                           
01040   return 1;                                                                  
01041 }
01042 
01043 static int atomsel_user3(void *v, int num, double *data, int *flgs) {
01044   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;                     
01045   int which_frame = ((atomsel_ctxt *)v)->which_frame;
01046   Timestep *ts = selframe(atom_sel_mol, which_frame);
01047   if (!ts || !ts->user3) {
01048     memset(data, 0, num*sizeof(double));
01049     return 1;                                                           
01050   }
01051   for (int i=0; i<num; i++) {                                         
01052     if (flgs[i]) {                                                            
01053       data[i] = ts->user3[i];                                         
01054     }                                                                         
01055   }                                                                           
01056   return 1;                                                                  
01057 }
01058 static int atomsel_set_user3(void *v, int num, double *data, int *flgs) {
01059   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;                     
01060   int which_frame = ((atomsel_ctxt *)v)->which_frame;
01061   Timestep *ts = selframe(atom_sel_mol, which_frame);
01062   if (!ts) return 0;
01063   if (!ts->user3) {
01064     ts->user3= new float[num];
01065     memset(ts->user3, 0, num*sizeof(float));
01066   }
01067   for (int i=0; i<num; i++) {                                         
01068     if (flgs[i]) {                                                            
01069       ts->user3[i] = (float)data[i];                                          
01070     }                                                                         
01071   }                                                                           
01072   return 1;                                                                  
01073 }
01074 
01075 static int atomsel_user4(void *v, int num, double *data, int *flgs) {
01076   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;                     
01077   int which_frame = ((atomsel_ctxt *)v)->which_frame;
01078   Timestep *ts = selframe(atom_sel_mol, which_frame);
01079   if (!ts || !ts->user4) {
01080     memset(data, 0, num*sizeof(double));
01081     return 1;                                                           
01082   }
01083   for (int i=0; i<num; i++) {                                         
01084     if (flgs[i]) {                                                            
01085       data[i] = ts->user4[i];                                         
01086     }                                                                         
01087   }                                                                           
01088   return 1;                                                                  
01089 }
01090 static int atomsel_set_user4(void *v, int num, double *data, int *flgs) {
01091   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;                     
01092   int which_frame = ((atomsel_ctxt *)v)->which_frame;
01093   Timestep *ts = selframe(atom_sel_mol, which_frame);
01094   if (!ts) return 0;
01095   if (!ts->user4) {
01096     ts->user4= new float[num];
01097     memset(ts->user4, 0, num*sizeof(float));
01098   }
01099   for (int i=0; i<num; i++) {                                         
01100     if (flgs[i]) {                                                            
01101       ts->user4[i] = (float)data[i];                                          
01102     }                                                                         
01103   }                                                                           
01104   return 1;                                                                  
01105 }
01106 
01107 
01108 
01109 static int atomsel_xpos(void *v, int num, double *data, int *flgs) {
01110   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;                     
01111   int which_frame = ((atomsel_ctxt *)v)->which_frame;
01112   Timestep *ts = selframe(atom_sel_mol, which_frame);
01113   int i;
01114   if (!ts) {
01115     for (i=0; i<num; i++) 
01116       if (flgs[i]) data[i] = 0.0;
01117     return 0;                                                           
01118   }
01119   for (i=0; i<num; i++) {                                             
01120     if (flgs[i]) {                                                            
01121       data[i] = ts->pos[3*i + 0];                                             
01122     }                                                                         
01123   }                                                                           
01124   return 1;                                                                  
01125 }
01126 
01127 static int atomsel_ypos(void *v, int num, double *data, int *flgs) {
01128   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;                     
01129   int which_frame = ((atomsel_ctxt *)v)->which_frame;
01130   Timestep *ts = selframe(atom_sel_mol, which_frame);
01131   int i;
01132   if (!ts) {
01133     for (i=0; i<num; i++) 
01134       if (flgs[i]) data[i] = 0.0;
01135     return 0;                                                           
01136   }
01137   for (i=0; i<num; i++) {                                             
01138     if (flgs[i]) {                                                            
01139       data[i] = ts->pos[3*i + 1];                                             
01140     }                                                                         
01141   }                                                                           
01142   return 1;                                                                  
01143 }
01144 
01145 static int atomsel_zpos(void *v, int num, double *data, int *flgs) {
01146   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;                     
01147   int which_frame = ((atomsel_ctxt *)v)->which_frame;
01148   Timestep *ts = selframe(atom_sel_mol, which_frame);
01149   int i;
01150   if (!ts) {
01151     for (i=0; i<num; i++) 
01152       if (flgs[i]) data[i] = 0.0;
01153     return 0;                                                           
01154   }
01155   for (i=0; i<num; i++) {                                             
01156     if (flgs[i]) {                                                            
01157       data[i] = ts->pos[3*i + 2];                                             
01158     }                                                                         
01159   }                                                                           
01160   return 1;                                                                  
01161 }
01162 
01163 static int atomsel_ufx(void *v, int num, double *data, int *flgs) {
01164   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;                     
01165   int which_frame = ((atomsel_ctxt *)v)->which_frame;
01166   Timestep *ts = selframe(atom_sel_mol, which_frame);
01167   int i;
01168   if (!ts || !ts->force) {
01169     for (i=0; i<num; i++) 
01170       if (flgs[i]) data[i] = 0.0;
01171     return 0;                                                           
01172   }
01173   for (i=0; i<num; i++) {                                             
01174     if (flgs[i]) {                                                            
01175       data[i] = ts->force[3*i + 0];                                           
01176     }                                                                         
01177   }                                                                           
01178   return 1;                                                                  
01179 }
01180 
01181 static int atomsel_ufy(void *v, int num, double *data, int *flgs) {
01182   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;                     
01183   int which_frame = ((atomsel_ctxt *)v)->which_frame;
01184   Timestep *ts = selframe(atom_sel_mol, which_frame);
01185   int i;
01186   if (!ts || !ts->force) {
01187     for (i=0; i<num; i++) 
01188       if (flgs[i]) data[i] = 0.0;
01189     return 0;                                                           
01190   }
01191   for (i=0; i<num; i++) {                                             
01192     if (flgs[i]) {                                                            
01193       data[i] = ts->force[3*i + 1];                                           
01194     }                                                                         
01195   }                                                                           
01196   return 1;                                                                  
01197 }
01198 
01199 static int atomsel_ufz(void *v, int num, double *data, int *flgs) {
01200   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;                     
01201   int which_frame = ((atomsel_ctxt *)v)->which_frame;
01202   Timestep *ts = selframe(atom_sel_mol, which_frame);
01203   int i;
01204   if (!ts || !ts->force) {
01205     for (i=0; i<num; i++) 
01206       if (flgs[i]) data[i] = 0.0;
01207     return 0;                                                           
01208   }
01209   for (i=0; i<num; i++) {                                             
01210     if (flgs[i]) {                                                            
01211       data[i] = ts->force[3*i + 2];                                           
01212     }                                                                         
01213   }                                                                           
01214   return 1;                                                                  
01215 }
01216 
01217 #define atomsel_get_vel(name, offset) \
01218 static int atomsel_##name(void *v, int num, double *data, int *flgs) {  \
01219   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;       \
01220   int which_frame = ((atomsel_ctxt *)v)->which_frame;  \
01221   Timestep *ts = selframe(atom_sel_mol, which_frame);  \
01222   int i;                                               \
01223   if (!ts || !ts->vel) {                               \
01224     for (i=0; i<num; i++)                              \
01225       if (flgs[i]) data[i] = 0.0;                      \
01226     return 0;                                          \
01227   }                                                    \
01228   for (i=0; i<num; i++) {                              \
01229     if (flgs[i]) {                                     \
01230       data[i] = ts->vel[3*i + (offset)];               \
01231     }                                                  \
01232   }                                                    \
01233   return 1;                                            \
01234 }                                                      
01235 
01236 atomsel_get_vel(vx, 0)
01237 atomsel_get_vel(vy, 1)
01238 atomsel_get_vel(vz, 2)
01239 
01240 static int atomsel_phi(void *v, int num, double *data, int *flgs) {
01241   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;                     
01242   int which_frame = ((atomsel_ctxt *)v)->which_frame;
01243   Timestep *ts = selframe(atom_sel_mol, which_frame);
01244   int i;
01245   if (!ts) {
01246     for (i=0; i<num; i++) data[i] = 0;
01247     return 0;  
01248   } 
01249   const float *r = ts->pos; 
01250   for (i=0; i<num; i++) {
01251     if (!flgs[i]) continue;
01252     MolAtom *atom = atom_sel_mol->atom(i);
01253     int resid = atom->uniq_resid;
01254     int N = atom_sel_mol->find_atom_in_residue("N", resid);
01255     int CA = atom_sel_mol->find_atom_in_residue("CA", resid);
01256     int C = atom_sel_mol->find_atom_in_residue("C", resid);
01257 
01258     // Find the index of the C atom from the previous residue by searching
01259     // the atoms bonded to N for an atom named "C".  
01260     if (N < 0) {
01261       data[i] = 0;
01262       continue;
01263     }
01264     MolAtom *atomN = atom_sel_mol->atom(N);
01265     int cprev = -1;
01266     for (int j=0; j<atomN->bonds; j++) {
01267       int aindex = atomN->bondTo[j];
01268       int nameindex = atom_sel_mol->atom(aindex)->nameindex;
01269       if (!strcmp(atom_sel_mol->atomNames.name(nameindex), "C")) {
01270         cprev = aindex;
01271         break;
01272       }
01273     }
01274     if (cprev >= 0 && CA >= 0 && C >= 0) 
01275       data[i] = dihedral(r+3*cprev, r+3*N, r+3*CA, r+3*C);
01276     else
01277       data[i] = 0.0; 
01278   }
01279   return 0;
01280 }
01281 
01282 static int atomsel_psi(void *v, int num, double *data, int *flgs) {
01283   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;                     
01284   int which_frame = ((atomsel_ctxt *)v)->which_frame;
01285   Timestep *ts = selframe(atom_sel_mol, which_frame);
01286   int i;
01287   if (!ts) {
01288     for (i=0; i<num; i++) data[i] = 0;
01289     return 0;  
01290   } 
01291   const float *r = ts->pos; 
01292   for (i=0; i<num; i++) {
01293     if (!flgs[i]) continue;
01294     MolAtom *atom = atom_sel_mol->atom(i);
01295     int resid = atom->uniq_resid;
01296     int N = atom_sel_mol->find_atom_in_residue("N", resid);
01297     int CA = atom_sel_mol->find_atom_in_residue("CA", resid);
01298     int C = atom_sel_mol->find_atom_in_residue("C", resid);
01299 
01300     // Find the index of the N atom from the next residue by searching the
01301     // atoms bonded to C for an atom named "N".
01302     if (C < 0) {
01303       data[i] = 0;
01304       continue;
01305     }
01306     MolAtom *atomC = atom_sel_mol->atom(C);
01307     int nextn = -1;
01308     for (int j=0; j<atomC->bonds; j++) {
01309       int aindex = atomC->bondTo[j];
01310       int nameindex = atom_sel_mol->atom(aindex)->nameindex;
01311       if (!strcmp(atom_sel_mol->atomNames.name(nameindex), "N")) {
01312         nextn = aindex;
01313         break;
01314       }
01315     }
01316     if (nextn >= 0 && N >= 0 && CA >= 0) 
01317       data[i] = dihedral(r+3*N, r+3*CA, r+3*C, r+3*nextn);
01318     else
01319       data[i] = 0.0; 
01320   }
01321   return 0;
01322 }
01323 
01324 static int atomsel_set_phi(void *v, int num, double *data, int *flgs) {
01325   // We rotate about the N-CA bond
01326   // 0. Get the current value of phi
01327   // 1. Translate, putting CA at the origin
01328   // 2. Compute the axis along N-CA
01329   // 3. Rotate just the N-terminus about the given axis
01330   // 4. Undo the translation
01331 
01332   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;                     
01333   SymbolTable *table = ((atomsel_ctxt *)v)->table;
01334   int which_frame = ((atomsel_ctxt *)v)->which_frame;
01335   Timestep *ts = selframe(atom_sel_mol, which_frame);
01336   int i;
01337   if (!ts) {
01338     return 0;  
01339   } 
01340   float *r = ts->pos; 
01341 
01342   // Go through the residues; if the residue contains all the necessary atoms,
01343   // check to see if the CA of the residue is on.  If it is, proceed with the
01344   // rotation. 
01345   for (i=0; i<atom_sel_mol->fragList.num(); i++) {
01346     Fragment *frag = atom_sel_mol->fragList[i];
01347     int nfragres = frag->residues.num();
01348     if (nfragres < 2) continue;
01349     int C = atom_sel_mol->find_atom_in_residue("C", frag->residues[0]);
01350     // Start at second residue since I need the previous residue for phi
01351     for (int ires = 1; ires < nfragres; ires++) {
01352       int resid = frag->residues[ires];
01353       int cprev = C;
01354       int N = atom_sel_mol->find_atom_in_residue("N", resid);
01355       int CA = atom_sel_mol->find_atom_in_residue("CA", resid);
01356       C = atom_sel_mol->find_atom_in_residue("C", resid);
01357       if (cprev < 0 || N < 0 || CA < 0 || C < 0) continue;
01358       if (!flgs[CA]) continue;
01359       float CApos[3], Npos[3], axis[3];
01360       vec_copy(CApos, r+3*CA);
01361       vec_copy(Npos, r+3*N);
01362       vec_sub(axis, Npos, CApos);
01363       vec_normalize(axis); 
01364       double oldphi = dihedral(r+3*cprev, Npos, CApos, r+3*C);
01365       // Select the N-terminal part of the fragment, which includes all
01366       // residues up to the current one, plus N and NH of the curent one.
01367       // I'm just going to create a new atom selection for now.
01368       
01369       AtomSel *nterm = new AtomSel(table, atom_sel_mol->id());
01370       char buf[100];
01371       sprintf(buf, 
01372         "(fragment %d and residue < %d) or (residue %d and name N NH CA)",
01373         i, resid, resid);
01374       if (nterm->change(buf, atom_sel_mol) == AtomSel::NO_PARSE) {
01375         msgErr << "set phi: internal atom selection error" << sendmsg;
01376         msgErr << buf << sendmsg; 
01377         delete nterm;
01378         continue;
01379       }
01380       Matrix4 mat;
01381       mat.transvec(axis[0], axis[1], axis[2]);
01382       mat.rot((float) (data[CA]-oldphi), 'x');
01383       mat.transvecinv(axis[0], axis[1], axis[2]); 
01384         
01385       for (int j=0; j<num; j++) {
01386         if (nterm->on[j]) {
01387           float *pos = r+3*j;
01388           vec_sub(pos, pos, CApos);
01389           mat.multpoint3d(pos, pos);
01390           vec_add(pos, pos, CApos); 
01391         }
01392       }
01393       delete nterm;
01394     }
01395   }
01396   return 0;
01397 }
01398 
01399 static int atomsel_set_psi(void *v, int num, double *data, int *flgs) {
01400   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;
01401   SymbolTable *table = ((atomsel_ctxt *)v)->table;
01402   int which_frame = ((atomsel_ctxt *)v)->which_frame;
01403   Timestep *ts = selframe(atom_sel_mol, which_frame);
01404   if (!ts) {
01405     return 0; 
01406   }
01407   float *r = ts->pos;
01408 
01409   for (int i=0; i<atom_sel_mol->fragList.num(); i++) {
01410     Fragment *frag = atom_sel_mol->fragList[i];
01411     int nfragres = frag->residues.num();
01412     if (nfragres < 2) continue;
01413     int N = atom_sel_mol->find_atom_in_residue("N", frag->residues[nfragres-1]);
01414     for (int ires = nfragres-2; ires >= 0; ires--) {
01415       int resid = frag->residues[ires];
01416       int nextn = N;
01417       N = atom_sel_mol->find_atom_in_residue("N", resid);
01418       int CA = atom_sel_mol->find_atom_in_residue("CA", resid);
01419       int C = atom_sel_mol->find_atom_in_residue("C", resid);
01420       if (nextn < 0 || N < 0 || CA < 0 || C < 0) continue;
01421       if (!flgs[CA]) continue;
01422       float CApos[3], Cpos[3], axis[3];
01423       vec_copy(CApos, r+3*CA);
01424       vec_copy(Cpos, r+3*C);
01425       vec_sub(axis, Cpos, CApos);
01426       vec_normalize(axis);
01427       double oldpsi = dihedral(r+3*N, CApos, Cpos, r+3*nextn);
01428 
01429       AtomSel *cterm = new AtomSel(table, atom_sel_mol->id());
01430       char buf[100];
01431       sprintf(buf,
01432         "(fragment %d and residue > %d) or (residue %d and name CA C O)",
01433         i, resid, resid);
01434       if (cterm->change(buf, atom_sel_mol) == AtomSel::NO_PARSE) {
01435         msgErr << "set psi: internal atom selection error" << sendmsg;
01436         msgErr << buf << sendmsg;
01437         delete cterm;
01438         continue;
01439       }
01440 
01441       Matrix4 mat;
01442       mat.transvec(axis[0], axis[1], axis[2]);
01443       mat.rot((float) (data[CA]-oldpsi), 'x');
01444       mat.transvecinv(axis[0], axis[1], axis[2]);
01445 
01446       for (int j=0; j<num; j++) {
01447         if (cterm->on[j]) {
01448           float *pos = r+3*j;
01449           vec_sub(pos, pos, CApos);
01450           mat.multpoint3d(pos, pos);
01451           vec_add(pos, pos, CApos);
01452         }
01453       }
01454       delete cterm;
01455     }
01456   }
01457   return 0;
01458 }
01459 
01460 #define set_position_data(fctn, offset)                                       \
01461 static int fctn(void *v, int num, double *data, int *flgs)                    \
01462 {                                                                             \
01463   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;                     \
01464   int which_frame = ((atomsel_ctxt *)v)->which_frame;                                 \
01465   Timestep *ts = selframe(atom_sel_mol, which_frame);                         \
01466   if (!ts) return 0;                                                          \
01467   for (int i=num-1; i>=0; i--) {                                              \
01468     if (flgs[i]) {                                                            \
01469       ts->pos[3*i + offset] = (float) data[i];                                \
01470     }                                                                         \
01471   }                                                                           \
01472   return 1;                                                                   \
01473 }
01474 
01475 
01476 set_position_data(atomsel_set_xpos, 0)
01477 set_position_data(atomsel_set_ypos, 1)
01478 set_position_data(atomsel_set_zpos, 2)
01479 
01480 #define set_force_data(fctn, offset)                                          \
01481 static int fctn(void *v, int num, double *data, int *flgs)                    \
01482 {                                                                             \
01483   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;                     \
01484   int which_frame = ((atomsel_ctxt *)v)->which_frame;                                 \
01485   Timestep *ts = selframe(atom_sel_mol, which_frame);                         \
01486   if (!ts) return 0;                                                          \
01487   if (!ts->force) {                                                           \
01488     ts->force = new float[3*num];                                             \
01489     memset(ts->force, 0, 3*num*sizeof(float));                                \
01490   }                                                                           \
01491   for (int i=num-1; i>=0; i--) {                                              \
01492     if (flgs[i]) {                                                            \
01493       ts->force[3*i + offset] = (float) data[i];                              \
01494     }                                                                         \
01495   }                                                                           \
01496   return 1;                                                                   \
01497 }
01498 
01499 set_force_data(atomsel_set_ufx, 0)
01500 set_force_data(atomsel_set_ufy, 1)
01501 set_force_data(atomsel_set_ufz, 2)
01502 
01503 #define set_vel_data(fctn, offset)                                            \
01504 static int fctn(void *v, int num, double *data, int *flgs)                    \
01505 {                                                                             \
01506   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;                     \
01507   int which_frame = ((atomsel_ctxt *)v)->which_frame;                                 \
01508   Timestep *ts = selframe(atom_sel_mol, which_frame);                         \
01509   if (!ts) return 0;                                                          \
01510   if (!ts->vel) {                                                           \
01511     ts->vel= new float[3*num];                                             \
01512     memset(ts->vel, 0, 3*num*sizeof(float));                                \
01513   }                                                                           \
01514   for (int i=num-1; i>=0; i--) {                                              \
01515     if (flgs[i]) {                                                            \
01516       ts->vel[3*i + offset] = (float) data[i];                              \
01517     }                                                                         \
01518   }                                                                           \
01519   return 1;                                                                   \
01520 }
01521 
01522 set_vel_data(atomsel_set_vx, 0)
01523 set_vel_data(atomsel_set_vy, 1)
01524 set_vel_data(atomsel_set_vz, 2)
01525 
01526 extern "C" {
01527   double atomsel_square(double x) { return x*x; }
01528 }
01529 
01530 // this is different than the previous.  It allows me to search for a
01531 // given regex sequence.  For instace, given the protein sequence
01532 //   WAPDTYLVAPDAQD
01533 // the selection: sequence APDT
01534 //  will select only the 2nd through 5th terms
01535 // the selection: sequence APD
01536 //  will select 2nd through 4th, and 9th to 11th.
01537 // the selection: sequence "A.D"
01538 //  will get 2-4 and 9-14
01539 // and so on.
01540 //   If a residue name is not normal, it becomes an X
01541 
01542 // I am handed a list of strings for this selection
01543 //  (eg, sequence APD "A.D" A to D)
01544 // Since there are no non-standard residue names (ie, no '*')
01545 // I'll interpret everything as a regex.  Also, phrases like
01546 // "X to Y" are interpreted as "X.*Y"
01547 
01548 static int atomsel_sequence(void *v, int argc, const char **argv, int *types,
01549                             int num, int *flgs)
01550 {
01551    DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;                     
01552    int i;
01553    // make a temporary array for marking the selected atoms
01554    int *selected = new int[num];
01555    for (i=0; i<num; i++) {
01556       selected[i] = FALSE;
01557    }
01558    // make the list of regex'es
01559    JRegex **regex = (JRegex **) malloc( argc * sizeof(JRegex *));
01560    int num_r = 0;
01561    {
01562       JString pattern;
01563       for (i=0; i<argc; i++) {
01564          pattern  = argv[i];
01565          if (types[i] >= 3) {  // get the next term (if a "to" element)
01566             pattern += ".*";
01567             pattern += argv[++i];
01568          }
01569          regex[num_r] = new JRegex(pattern);
01570          num_r ++;
01571       }
01572    } // constructed the regex array
01573    if (num_r == 0) {
01574       return 0;
01575    }
01576 
01577    // construct a list of sequences from each protein (pfraglist)
01578    // and nucleic acid (nfragList)
01579    for (int fragcount=0; fragcount <2; fragcount++) {
01580       int pcount = atom_sel_mol->pfragList.num();
01581       int ncount = atom_sel_mol->nfragList.num();
01582       for (i=0; i< (fragcount == 0 ? pcount : ncount); i++) {
01583          int size = (fragcount == 0 ? atom_sel_mol->pfragList[i]->num()
01584                                     : atom_sel_mol->nfragList[i]->num());
01585          char *s = new char[size+1]; // so that it can be NULL-terminated
01586          char *t = s;
01587          int *mark = new int[size];
01588          
01589          for (int j=0; j<size; j++) {
01590             int residuenum = ((fragcount == 0) ?
01591                   (*atom_sel_mol->pfragList[i])[j] :  
01592                   (*atom_sel_mol->nfragList[i])[j]);
01593             int atomnum = (atom_sel_mol->residueList[residuenum]->atoms[0]);
01594             MolAtom *atom = atom_sel_mol->atom(atomnum);
01595             const char *resname = (atom_sel_mol->resNames).name(atom->resnameindex);
01596             mark[j] = FALSE;
01597             if (fragcount == 0) {
01598                // protein translations
01599          // PDB names
01600                if (!strcasecmp( resname, "GLY")) {*t++ = 'G'; continue;}
01601                if (!strcasecmp( resname, "ALA")) {*t++ = 'A'; continue;}
01602                if (!strcasecmp( resname, "VAL")) {*t++ = 'V'; continue;}
01603                if (!strcasecmp( resname, "PHE")) {*t++ = 'F'; continue;}
01604                if (!strcasecmp( resname, "PRO")) {*t++ = 'P'; continue;}
01605                if (!strcasecmp( resname, "MET")) {*t++ = 'M'; continue;}
01606                if (!strcasecmp( resname, "ILE")) {*t++ = 'I'; continue;}
01607                if (!strcasecmp( resname, "LEU")) {*t++ = 'L'; continue;}
01608                if (!strcasecmp( resname, "ASP")) {*t++ = 'D'; continue;}
01609                if (!strcasecmp( resname, "GLU")) {*t++ = 'E'; continue;}
01610                if (!strcasecmp( resname, "LYS")) {*t++ = 'K'; continue;}
01611                if (!strcasecmp( resname, "ARG")) {*t++ = 'R'; continue;}
01612                if (!strcasecmp( resname, "SER")) {*t++ = 'S'; continue;}
01613                if (!strcasecmp( resname, "THR")) {*t++ = 'T'; continue;}
01614                if (!strcasecmp( resname, "TYR")) {*t++ = 'Y'; continue;}
01615                if (!strcasecmp( resname, "HIS")) {*t++ = 'H'; continue;}
01616                if (!strcasecmp( resname, "CYS")) {*t++ = 'C'; continue;}
01617                if (!strcasecmp( resname, "ASN")) {*t++ = 'N'; continue;}
01618                if (!strcasecmp( resname, "GLN")) {*t++ = 'Q'; continue;}
01619                if (!strcasecmp( resname, "TRP")) {*t++ = 'W'; continue;}
01620          // CHARMM names
01621          if (!strcasecmp( resname, "HSE")) {*t++ = 'H'; continue;}
01622          if (!strcasecmp( resname, "HSD")) {*t++ = 'H'; continue;}
01623          if (!strcasecmp( resname, "HSP")) {*t++ = 'H'; continue;}
01624          // AMBER names
01625          if (!strcasecmp( resname, "CYX")) {*t++ = 'C'; continue;}
01626             } else {
01627                // nucleic acid translations
01628                if (!strcasecmp( resname, "ADE")) {*t++ = 'A'; continue;}
01629                if (!strcasecmp( resname, "A")) {*t++ = 'A'; continue;}
01630                if (!strcasecmp( resname, "THY")) {*t++ = 'T'; continue;}
01631                if (!strcasecmp( resname, "T")) {*t++ = 'T'; continue;}
01632                if (!strcasecmp( resname, "CYT")) {*t++ = 'C'; continue;}
01633                if (!strcasecmp( resname, "C")) {*t++ = 'C'; continue;}
01634                if (!strcasecmp( resname, "GUA")) {*t++ = 'G'; continue;}
01635                if (!strcasecmp( resname, "G")) {*t++ = 'G'; continue;}
01636             }
01637             // then I have no idea
01638             *t++ = 'X';
01639          }  // end loop 'j'; constructed the sequence for this protein
01640          *t = 0; // terminate the string
01641          
01642 //       msgInfo << "sequence " << i << " is: " << s << sendmsg;
01643          // which of the residues match the regex(es)?
01644          for (int r=0; r<num_r; r++) {
01645             int len, start = 0, offset;
01646             while ((offset = (regex[r]->search(s, strlen(s), len, start)))
01647                    != -1) {
01648                // then there was a match from offset to offset+len
01649 //             msgInfo << "start " << start << " offset " << offset << " len "
01650 //                     << len << sendmsg;
01651                for (int loop=offset; loop<offset+len; loop++) {
01652                   mark[loop] = 1;
01653                }
01654                start = offset+len;
01655             }
01656          }
01657          
01658          // the list of selected residues is in mark
01659          // turn on the right atoms
01660          for (int marked=0; marked<size; marked++) {
01661             if (mark[marked]) {
01662                int residuenum = (fragcount == 0 ?
01663                                  (*atom_sel_mol->pfragList[i])[marked] :
01664                                  (*atom_sel_mol->nfragList[i])[marked]);
01665                for (int atomloop=0;
01666                     atomloop< atom_sel_mol->residueList[residuenum]->
01667                     atoms.num(); atomloop++) {
01668                   selected[atom_sel_mol->residueList[residuenum]->
01669                            atoms[atomloop]]=TRUE;
01670                }
01671             }
01672          }
01673          delete [] mark;
01674          delete [] s;
01675       } // end loop i over the fragments
01676    }  // end loop 'fragcount'
01677 
01678 
01679    // get rid of the compiled regex's
01680    for (i=0; i<num_r; i++) {
01681       delete regex[i];
01682    }
01683    // copy the 'selected' array into 'flgs'
01684    for (i=0; i<num; i++) {
01685       flgs[i] = flgs[i] && selected[i];
01686    }
01687    return 1;
01688 }
01689 
01690 /************ support for RasMol selections ******************/
01692 // the full form of a primitive is (seems to be)
01693 //   {[<resname>]}{<resid>}{:<chain>}{.<atom name>}
01694 // if resname is only alpha, the [] can be dropped
01695 // if chain is alpha, the : can be dropped
01696 // resname only contains * if it is the first one ?
01697 // ? cannot go in the resid
01698 // * can only replace the whole field
01699 static int atomsel_rasmol_primitive(void *v, int argc, const char **argv, int *,
01700                                     int num, int *flgs)
01701 {
01702   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;                     
01703   SymbolTable *table = ((atomsel_ctxt *)v)->table;
01704 
01705   // for each word, (ignoring the quote flags)
01706   for (int word=0; word<argc; word++) {
01707     const char *rnm0 = argv[word]; // resname start
01708     const char *rnm1;              // and end position
01709     const char *rid0, *rid1;
01710     if (*rnm0 == '*') {
01711       rnm1 = rnm0 + 1;
01712       rid0 = rnm1;
01713     } else if (*rnm0 == '[') {
01714       rnm0++;
01715       rnm1 = rnm0;
01716       while (*rnm1 && *rnm1 != ']') { // find trailing bracket
01717         rnm1 ++;
01718       }
01719       if (rnm1 == rnm0) {  // for cases like [] and "["
01720         rid0 = rnm1;
01721       } else {
01722         if (*rnm1==']') {  // for cases like [so4]
01723           rid0 = rnm1+1;
01724         } else {           // for (incorrect) cases like [so4
01725           rid0 = rnm1;
01726         }
01727       }
01728     } else { // then must be alpha or ?
01729       rnm1 = rnm0;
01730       while (isalpha(*rnm1) || *rnm1 == '?') {  // find first non-alpha
01731         rnm1++;
01732       }
01733       rid0 = rnm1;
01734     }
01735     // got the resname
01736 
01737     // parse the resid
01738     rid1 = rid0;
01739     if (*rid1 == '*') {
01740       rid1++;
01741     } else {
01742       while (isdigit(*rid1)) {
01743         rid1++;
01744       }
01745     }
01746 
01747     // if this is the : delimiter, skip over it
01748     const char *chn0, *chn1;
01749     if (*rid1 == ':') {
01750       chn0 = rid1 + 1;
01751     } else {
01752       chn0 = rid1;
01753     }
01754 
01755     // get the chain
01756     // seek the . or end of string
01757     chn1 = chn0;
01758     while (*chn1 && *chn1 != '.') {
01759       chn1++;
01760     }
01761 
01762     const char *nm0, *nm1;
01763     if (*chn1 == '.') {
01764       nm0 = chn1 + 1;
01765     } else {
01766       nm0 = chn1;
01767     }
01768     nm1 = nm0;
01769     // seek the end of string
01770     while (*nm1) {
01771       nm1++;
01772     }
01773     
01774 
01775     // save the info into strings
01776     JString resname, resid, chain, name;
01777     const char *s;
01778     for (s=rnm0; s<rnm1; s++) {
01779       resname += *s;
01780     }
01781     for (s=rid0; s<rid1; s++) {
01782       resid += *s;
01783     }
01784     for (s=chn0; s<chn1; s++) {
01785       chain += *s;
01786     }
01787     for (s=nm0; s<nm1; s++) {
01788       name += *s;
01789     }
01790     //    msgInfo << "resname: " << (const char *) resname << sendmsg;
01791     //    msgInfo << "resid: " << (const char *) resid << sendmsg;
01792     //    msgInfo << "chain: " << (const char *) chain << sendmsg;
01793     //    msgInfo << "name: " << (const char *) name << sendmsg;
01794 
01795     // convert to the VMD regex ( ? => .? and * => .*)
01796     //   (however, if there is a * for the whole field, delete the field)
01797     if (resname == "*") resname = "";
01798     if (resid == "*") resid = "";
01799     if (chain == "*") chain = "";
01800     if (name == "*") name = "";
01801     resname.gsub("?", ".?"); resname.gsub("*", ".*");
01802     resid.gsub("?", ".?"); resid.gsub("*", ".*");
01803     chain.gsub("?", ".?"); chain.gsub("*", ".*");
01804     name.gsub("?", ".?"); name.gsub("*", ".*");
01805     // make everything upcase
01806     resname.upcase();
01807     resid.upcase();
01808     chain.upcase();
01809     name.upcase();
01810 
01811     // construct a new search
01812     JString search;
01813     if (resname != "") {
01814       search = "resname ";
01815       search += '"';
01816       search += resname;
01817       search += '"';
01818     }
01819     if (resid != "") {
01820       if (search != "") {
01821         search += " and resid ";
01822       } else {
01823         search = "resid ";
01824       }
01825       search += '"';
01826       search += resid;
01827       search += '"';
01828     }
01829     // if the chain length > 1, it is a segname
01830     int is_segname = chain.length() > 1;
01831     if (chain != "") {
01832       if (search != "") {
01833         search += (is_segname ? " and segname " : " and chain ");
01834       } else {
01835         search = (is_segname ? "segname " : "chain ");
01836       }
01837       search += '"';
01838       search += chain;
01839       search += '"';
01840     }
01841     if (name != "") {
01842       if (search != "") {
01843         search += " and name ";
01844       } else {
01845         search = "name ";
01846       }
01847       search += '"';
01848       search += name;
01849       search += '"';
01850     }
01851     msgInfo << "Search = " << search << sendmsg;
01852 
01853     if (search == "") {
01854       search = "all";
01855     }
01856     // and do the search
01857     AtomSel *atomSel = new AtomSel(table, atom_sel_mol->id());
01858     if (atomSel->change((const char *) search, atom_sel_mol) ==
01859         AtomSel::NO_PARSE) {
01860       msgErr << "rasmol: cannot understand: " << argv[word] << sendmsg;
01861       delete atomSel;
01862       continue;
01863     }
01864     
01865     // save the results
01866     {
01867       for (int i=0; i<num; i++) {
01868         flgs[i] = flgs[i] && atomSel->on[i];
01869       }
01870     }
01871     delete atomSel;
01872   }
01873   return 1;
01874 }
01875 
01876 int atomsel_custom_singleword(void *v, int num, int *flgs) {
01877   SymbolTable *table = ((atomsel_ctxt *)v)->table;
01878   const char *singleword = ((atomsel_ctxt *)v)->singleword;
01879   if (!singleword) {
01880     msgErr << "Internal error, atom selection macro called without context"
01881            << sendmsg;
01882     return 0;
01883   }
01884   const char *macro = table->get_custom_singleword(singleword);
01885   if (!macro) {
01886     msgErr << "Internal error, atom selection macro has lost its defintion."
01887            << sendmsg;
01888     return 0;
01889   }
01890   // Create new AtomSel based on the macro
01891   DrawMolecule *mol = ((atomsel_ctxt *)v)->atom_sel_mol;
01892   AtomSel *atomSel = new AtomSel(table, mol->id());
01893   atomSel->which_frame = ((atomsel_ctxt *)v)->which_frame;
01894   if (atomSel->change(macro, mol) == AtomSel::NO_PARSE) {
01895     msgErr << "Unable to parse macro: " << macro << sendmsg;
01896     delete atomSel;
01897     return 0;
01898   }
01899   for (int i=0; i<num; i++) {
01900     flgs[i] = flgs[i] && atomSel->on[i];
01901   }
01902   delete atomSel;
01903   return 1;
01904 }
01905 
01906 
01907 
01908 
01909 // These functions allow voxel values from volumetric data loaded in a molecule
01910 // to be used in atom selections. Three keywords are implemented: volN returns
01911 // the value of the voxel under the selected atom, interpvolN returns the 
01912 // voxel value interpolated from neighboring voxels, and volindexN returns the 
01913 // numerical index of the underlying voxel (I found the latter useful, however
01914 // its usefulness might be too marginal to be included into VMD?)
01915 
01916 // This is a hack because the volume names are hardcoded. Ideally, VMD should
01917 // invent an "array keyword" which would contain a parsable index (e.g. 
01918 // "vol#2"). Right now, the first M keywords are hard-coded, and any volN with
01919 // N greater than M will not work. This is because adding an array keyword
01920 // involves a considerable amount of work, but perhaps this should be considered
01921 // eventually...
01922 
01923 // NOTE: if a coordinate lies outside the volmap range, a value of NAN is
01924 // assigned. Since NAN != NAN, NAN atoms will automatically never be included 
01925 // in selections (which is what we want!). Furthermore, "$sel get vol0" would
01926 // return a Tcl-parsable NAN to easily allow the user to identify coords that
01927 // lie outside the valid range.
01928 
01929 #ifndef NAN //not a number
01930   const float NAN = sqrtf(-1.f); //need some kind of portable NAN definition
01931 #endif
01932 
01933 
01934 static int atomsel_volume_array(void *v, int num, double *data, int *flgs, int array_index) {
01935   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;                     
01936   int which_frame = ((atomsel_ctxt *)v)->which_frame;
01937   Timestep *ts = selframe(atom_sel_mol, which_frame);
01938   const VolumetricData *voldata = atom_sel_mol->get_volume_data(array_index);
01939   int i;
01940   if (!ts || !voldata) {
01941     if (!ts) msgErr << "atomselect: non-existent timestep." << sendmsg;
01942     if (!voldata) msgErr << "atomselect: volumetric map volume#" << array_index << " does not exist." << sendmsg;
01943     for (i=0; i<num; i++) if (flgs[i]) data[i] = NAN;
01944     return 0;                                                           
01945   }
01946   for (i=0; i<num; i++) {                                             
01947     if (flgs[i])                                                              
01948       data[i] = voldata->voxel_value_from_coord(ts->pos[3*i], ts->pos[3*i+1], ts->pos[3*i+2]);          
01949   }                                                                           
01950   return 1;                                                                  
01951 }
01952 
01953 
01954 static int atomsel_interp_volume_array(void *v, int num, double *data, int *flgs, int array_index) {
01955   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;                     
01956   int which_frame = ((atomsel_ctxt *)v)->which_frame;
01957   Timestep *ts = selframe(atom_sel_mol, which_frame);
01958   const VolumetricData *voldata = atom_sel_mol->get_volume_data(array_index);
01959   int i;
01960   if (!ts || !voldata) {
01961     if (!ts) msgErr << "atomselect: non-existent timestep." << sendmsg;
01962     if (!voldata) msgErr << "atomselect: volumetric map volume#" << array_index << " does not exist." << sendmsg;
01963     for (i=0; i<num; i++) if (flgs[i]) data[i] = NAN;
01964     return 0;                                                           
01965   }
01966   for (i=0; i<num; i++) {                                             
01967     if (flgs[i])                                                              
01968       data[i] = voldata->voxel_value_interpolate_from_coord(ts->pos[3*i], ts->pos[3*i+1], ts->pos[3*i+2]);              
01969   }                                                                           
01970   return 1;                                                                  
01971 }
01972 
01973 
01974 static int atomsel_gridindex_array(void *v, int num, double *data, int *flgs, int array_index) {
01975   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;                     
01976   int which_frame = ((atomsel_ctxt *)v)->which_frame;
01977   Timestep *ts = selframe(atom_sel_mol, which_frame);
01978   const VolumetricData *voldata = atom_sel_mol->get_volume_data(array_index);
01979   int i;
01980   if (!ts || !voldata) {
01981     if (!ts) msgErr << "atomselect: non-existent timestep." << sendmsg;
01982     if (!voldata) msgErr << "atomselect: volumetric map volume#" << array_index << " does not exist." << sendmsg;
01983     for (i=0; i<num; i++) if (flgs[i]) data[i] = NAN;
01984     return 0;                                                           
01985   }
01986   for (i=0; i<num; i++) {                                             
01987     if (flgs[i])                                                              
01988       data[i] = voldata->voxel_index_from_coord(ts->pos[3*i], ts->pos[3*i+1], ts->pos[3*i+2]);          
01989   }                                                                           
01990   return 1;                                                                  
01991 }
01992 
01993 
01994 static int atomsel_gridindex0(void *v, int num, double *data, int *flgs) {                                                            
01995   return atomsel_gridindex_array(v, num, data, flgs, 0);                                                                   
01996 }
01997 static int atomsel_gridindex1(void *v, int num, double *data, int *flgs) {                                                            
01998   return atomsel_gridindex_array(v, num, data, flgs, 1);                                                                   
01999 }
02000 static int atomsel_gridindex2(void *v, int num, double *data, int *flgs) {                                                            
02001   return atomsel_gridindex_array(v, num, data, flgs, 2);                                                                   
02002 }
02003 static int atomsel_gridindex3(void *v, int num, double *data, int *flgs) {                                                            
02004   return atomsel_gridindex_array(v, num, data, flgs, 3);                                                                   
02005 }
02006 static int atomsel_gridindex4(void *v, int num, double *data, int *flgs) {                                                            
02007   return atomsel_gridindex_array(v, num, data, flgs, 4);                                                                   
02008 }
02009 static int atomsel_gridindex5(void *v, int num, double *data, int *flgs) {                                                            
02010   return atomsel_gridindex_array(v, num, data, flgs, 5);                                                                   
02011 }
02012 static int atomsel_gridindex6(void *v, int num, double *data, int *flgs) {                                                            
02013   return atomsel_gridindex_array(v, num, data, flgs, 6);                                                                   
02014 }
02015 static int atomsel_gridindex7(void *v, int num, double *data, int *flgs) {                                                            
02016   return atomsel_gridindex_array(v, num, data, flgs, 7);                                                                   
02017 }
02018 
02019 
02020 // 'volume0'
02021 static int atomsel_volume0(void *v, int num, double *data, int *flgs) {                                                       
02022   return atomsel_volume_array(v, num, data, flgs, 0);                                                              
02023 }
02024 static int atomsel_volume1(void *v, int num, double *data, int *flgs) {                                                       
02025   return atomsel_volume_array(v, num, data, flgs, 1);                                                              
02026 }
02027 static int atomsel_volume2(void *v, int num, double *data, int *flgs) {                                                       
02028   return atomsel_volume_array(v, num, data, flgs, 2);                                                              
02029 }
02030 static int atomsel_volume3(void *v, int num, double *data, int *flgs) {                                                       
02031   return atomsel_volume_array(v, num, data, flgs, 3);                                                              
02032 }
02033 static int atomsel_volume4(void *v, int num, double *data, int *flgs) {                                                       
02034   return atomsel_volume_array(v, num, data, flgs, 4);                                                              
02035 }
02036 static int atomsel_volume5(void *v, int num, double *data, int *flgs) {                                                       
02037   return atomsel_volume_array(v, num, data, flgs, 5);                                                              
02038 }
02039 static int atomsel_volume6(void *v, int num, double *data, int *flgs) {                                                       
02040   return atomsel_volume_array(v, num, data, flgs, 6);                                                              
02041 }
02042 static int atomsel_volume7(void *v, int num, double *data, int *flgs) {                                                       
02043   return atomsel_volume_array(v, num, data, flgs, 7);                                                              
02044 }
02045 
02046 
02047 // 'interpolated_volume0'
02048 static int atomsel_interp_volume0(void *v, int num, double *data, int *flgs) {                                                        
02049   return atomsel_interp_volume_array(v, num, data, flgs, 0);                                                               
02050 }
02051 static int atomsel_interp_volume1(void *v, int num, double *data, int *flgs) {                                                        
02052   return atomsel_interp_volume_array(v, num, data, flgs, 1);                                                               
02053 }
02054 static int atomsel_interp_volume2(void *v, int num, double *data, int *flgs) {                                                        
02055   return atomsel_interp_volume_array(v, num, data, flgs, 2);                                                               
02056 }
02057 static int atomsel_interp_volume3(void *v, int num, double *data, int *flgs) {                                                        
02058   return atomsel_interp_volume_array(v, num, data, flgs, 3);                                                               
02059 }
02060 static int atomsel_interp_volume4(void *v, int num, double *data, int *flgs) {                                                        
02061   return atomsel_interp_volume_array(v, num, data, flgs, 4);                                                               
02062 }
02063 static int atomsel_interp_volume5(void *v, int num, double *data, int *flgs) {                                                        
02064   return atomsel_interp_volume_array(v, num, data, flgs, 5);                                                               
02065 }
02066 static int atomsel_interp_volume6(void *v, int num, double *data, int *flgs) {                                                        
02067   return atomsel_interp_volume_array(v, num, data, flgs, 6);                                                               
02068 }
02069 static int atomsel_interp_volume7(void *v, int num, double *data, int *flgs) {                                                        
02070   return atomsel_interp_volume_array(v, num, data, flgs, 7);                                                               
02071 }
02072 
02073 
02074 
02075 
02076 void atomSelParser_init(SymbolTable *atomSelParser) {
02077   atomSelParser->add_keyword("name", atomsel_name, atomsel_set_name);
02078   atomSelParser->add_keyword("type", atomsel_type, atomsel_set_type);
02079 
02080   // XXX probably only use these two for testing of BaseMolecule::analyze()
02081   atomSelParser->add_keyword("backbonetype", atomsel_backbonetype, NULL);
02082   atomSelParser->add_keyword("residuetype", atomsel_residuetype, NULL);
02083 
02084   atomSelParser->add_keyword("index", atomsel_index, NULL);
02085   atomSelParser->add_keyword("serial", atomsel_serial, NULL);
02086   atomSelParser->add_keyword("atomicnumber", atomsel_atomicnumber, atomsel_set_atomicnumber);
02087   atomSelParser->add_keyword("element", atomsel_element, atomsel_set_element);
02088   atomSelParser->add_keyword("residue", atomsel_residue, NULL);
02089   atomSelParser->add_keyword("resname", atomsel_resname, atomsel_set_resname);
02090   atomSelParser->add_keyword("altloc", atomsel_altloc, atomsel_set_altloc);
02091   atomSelParser->add_keyword("resid", atomsel_resid, atomsel_set_resid);
02092   atomSelParser->add_keyword("insertion", atomsel_insertion, NULL);
02093   atomSelParser->add_keyword("chain", atomsel_chain, atomsel_set_chain);
02094   atomSelParser->add_keyword("segname", atomsel_segname, atomsel_set_segname);
02095   atomSelParser->add_keyword("segid", atomsel_segname, atomsel_set_segname);
02096 
02097   atomSelParser->add_singleword("all", atomsel_all, NULL);
02098   atomSelParser->add_singleword("none", atomsel_none, NULL);
02099 
02100   atomSelParser->add_keyword("fragment", atomsel_fragment, NULL);
02101   atomSelParser->add_keyword("pfrag", atomsel_pfrag, NULL);
02102   atomSelParser->add_keyword("nfrag", atomsel_nfrag, NULL);
02103   atomSelParser->add_keyword("numbonds", atomsel_numbonds, NULL);
02104 
02105   atomSelParser->add_singleword("backbone", atomsel_backbone, NULL);
02106   atomSelParser->add_singleword("sidechain", 
02107                                atomsel_sidechain, NULL);
02108   atomSelParser->add_singleword("protein", atomsel_protein, NULL);
02109   atomSelParser->add_singleword("nucleic", atomsel_nucleic, NULL);
02110   atomSelParser->add_singleword("water", atomsel_water, NULL);
02111   atomSelParser->add_singleword("waters", atomsel_water, NULL);
02112   atomSelParser->add_singleword("vmd_fast_hydrogen", atomsel_hydrogen, NULL);
02113 
02114   // secondary structure functions
02115   atomSelParser->add_singleword("helix", 
02116                                 atomsel_helix, atomsel_set_helix);
02117   atomSelParser->add_singleword("alpha_helix", 
02118                                 atomsel_alpha_helix, atomsel_set_helix);
02119   atomSelParser->add_singleword("helix_3_10", 
02120                                 atomsel_3_10_helix, atomsel_set_3_10_helix);
02121   atomSelParser->add_singleword("pi_helix", 
02122                                 atomsel_pi_helix, atomsel_set_pi_helix);
02123   atomSelParser->add_singleword("sheet", atomsel_sheet, atomsel_set_sheet);
02124   atomSelParser->add_singleword("betasheet", atomsel_sheet, atomsel_set_sheet);
02125   atomSelParser->add_singleword("beta_sheet",atomsel_sheet, atomsel_set_sheet);
02126   atomSelParser->add_singleword("extended_beta", atomsel_extended_sheet, 
02127                                 atomsel_set_sheet);
02128   atomSelParser->add_singleword("bridge_beta", atomsel_bridge_sheet, 
02129                                 atomsel_set_bridge_sheet);
02130   atomSelParser->add_singleword("turn", atomsel_turn, atomsel_set_turn);
02131   atomSelParser->add_singleword("coil", atomsel_coil, atomsel_set_coil);
02132   atomSelParser->add_keyword("structure",atomsel_sstruct, atomsel_set_sstruct);
02133 
02134 #if defined(VMDWITHCARBS)
02135   atomSelParser->add_keyword("pucker", atomsel_pucker, NULL);
02136 #endif
02137 
02138   atomSelParser->add_keyword("user",  atomsel_user,  atomsel_set_user);
02139   atomSelParser->add_keyword("user2", atomsel_user2, atomsel_set_user2);
02140   atomSelParser->add_keyword("user3", atomsel_user3, atomsel_set_user3);
02141   atomSelParser->add_keyword("user4", atomsel_user4, atomsel_set_user4);
02142 
02143   atomSelParser->add_keyword("x", atomsel_xpos, atomsel_set_xpos);
02144   atomSelParser->add_keyword("y", atomsel_ypos, atomsel_set_ypos);
02145   atomSelParser->add_keyword("z", atomsel_zpos, atomsel_set_zpos);
02146   atomSelParser->add_keyword("vx", atomsel_vx, atomsel_set_vx);
02147   atomSelParser->add_keyword("vy", atomsel_vy, atomsel_set_vy);
02148   atomSelParser->add_keyword("vz", atomsel_vz, atomsel_set_vz);
02149   atomSelParser->add_keyword("ufx", atomsel_ufx, atomsel_set_ufx);
02150   atomSelParser->add_keyword("ufy", atomsel_ufy, atomsel_set_ufy);
02151   atomSelParser->add_keyword("ufz", atomsel_ufz, atomsel_set_ufz);
02152   atomSelParser->add_keyword("phi", atomsel_phi, atomsel_set_phi);
02153   atomSelParser->add_keyword("psi", atomsel_psi, atomsel_set_psi);
02154   atomSelParser->add_keyword("radius", atomsel_radius, 
02155                              atomsel_set_radius);
02156   atomSelParser->add_keyword("mass", atomsel_mass, atomsel_set_mass);
02157   atomSelParser->add_keyword("charge", atomsel_charge, 
02158                              atomsel_set_charge);
02159   atomSelParser->add_keyword("beta", atomsel_beta, atomsel_set_beta);
02160   atomSelParser->add_keyword("occupancy", 
02161                              atomsel_occupancy, atomsel_set_occupancy);
02162 
02163   atomSelParser->add_stringfctn("sequence", atomsel_sequence);
02164   atomSelParser->add_stringfctn("rasmol", 
02165                                 atomsel_rasmol_primitive);
02166 
02167   // three letters for resname, 1 or more letters for resid
02169   //   atomSelParser->add_singleword("[a-zA-Z][a-zA-Z][a-zA-Z][0-9]+",
02170   //                            "resnameID", atomsel_resname_resid,
02171   //                            NULL);
02172 
02173   // and a few functions for good measure
02174   // Note: These functions must return the same output for given input.
02175   //       Functions like rand() will break some optimizations in the 
02176   //       atom selection code otherwise.
02177   atomSelParser->add_cfunction("sqr", atomsel_square);
02178   atomSelParser->add_cfunction("sqrt", sqrt);
02179   atomSelParser->add_cfunction("abs", fabs);
02180   atomSelParser->add_cfunction("floor", floor);
02181   atomSelParser->add_cfunction("ceil", ceil);
02182   atomSelParser->add_cfunction("sin", sin);
02183   atomSelParser->add_cfunction("cos", cos);
02184   atomSelParser->add_cfunction("tan", tan);
02185   atomSelParser->add_cfunction("atan", atan);
02186   atomSelParser->add_cfunction("asin", asin);
02187   atomSelParser->add_cfunction("acos", acos);
02188   atomSelParser->add_cfunction("sinh", sinh);
02189   atomSelParser->add_cfunction("cosh", cosh);
02190   atomSelParser->add_cfunction("tanh", tanh);
02191   atomSelParser->add_cfunction("exp", exp);
02192   atomSelParser->add_cfunction("log", log);
02193   atomSelParser->add_cfunction("log10", log10);
02194   
02195   
02196 
02197   atomSelParser->add_keyword("volindex0", atomsel_gridindex0, NULL);
02198   atomSelParser->add_keyword("volindex1", atomsel_gridindex1, NULL);
02199   atomSelParser->add_keyword("volindex2", atomsel_gridindex2, NULL);
02200   atomSelParser->add_keyword("volindex3", atomsel_gridindex3, NULL);
02201   atomSelParser->add_keyword("volindex4", atomsel_gridindex4, NULL);
02202   atomSelParser->add_keyword("volindex5", atomsel_gridindex5, NULL);
02203   atomSelParser->add_keyword("volindex6", atomsel_gridindex6, NULL);
02204   atomSelParser->add_keyword("volindex7", atomsel_gridindex7, NULL);
02205   atomSelParser->add_keyword("vol0", atomsel_volume0, NULL);
02206   atomSelParser->add_keyword("vol1", atomsel_volume1, NULL);
02207   atomSelParser->add_keyword("vol2", atomsel_volume2, NULL);
02208   atomSelParser->add_keyword("vol3", atomsel_volume3, NULL);
02209   atomSelParser->add_keyword("vol4", atomsel_volume4, NULL);
02210   atomSelParser->add_keyword("vol5", atomsel_volume5, NULL);
02211   atomSelParser->add_keyword("vol6", atomsel_volume6, NULL);
02212   atomSelParser->add_keyword("vol7", atomsel_volume7, NULL);
02213   atomSelParser->add_keyword("interpvol0", atomsel_interp_volume0, NULL);
02214   atomSelParser->add_keyword("interpvol1", atomsel_interp_volume1, NULL);
02215   atomSelParser->add_keyword("interpvol2", atomsel_interp_volume2, NULL);
02216   atomSelParser->add_keyword("interpvol3", atomsel_interp_volume3, NULL);
02217   atomSelParser->add_keyword("interpvol4", atomsel_interp_volume4, NULL);
02218   atomSelParser->add_keyword("interpvol5", atomsel_interp_volume5, NULL);
02219   atomSelParser->add_keyword("interpvol6", atomsel_interp_volume6, NULL);
02220   atomSelParser->add_keyword("interpvol7", atomsel_interp_volume7, NULL);
02221 }
02222 
02223 
02225 // constructor; parse string and see if OK
02226 AtomSel::AtomSel(SymbolTable *st, int id)
02227 : ID(id) {
02228   
02229   // initialize variables
02230   table = st;
02231   selected = NO_PARSE;
02232   firstsel = 0;
02233   lastsel = NO_PARSE;
02234   on = NULL;
02235   cmdStr = NULL;
02236   tree = NULL;
02237   num_atoms = 0;
02238   which_frame = TS_NOW;
02239   do_update = 0;
02240 }
02241 
02242 // destructor; free up space and make all pointers invalid
02243 AtomSel::~AtomSel(void) {
02244   table = NULL;
02245   num_atoms = 0;
02246   selected = NO_PARSE;
02247   firstsel = 0;
02248   lastsel = NO_PARSE;
02249   delete [] on;
02250   on = NULL;
02251   delete tree;
02252   delete [] cmdStr;
02253 }
02254 
02255 int AtomSel::change(const char *newcmd, DrawMolecule *mol) {
02256   if (newcmd) {
02257     ParseTree *newtree = table->parse(newcmd);
02258     if (!newtree) {
02259       return NO_PARSE;
02260     }
02261     delete [] cmdStr;
02262     cmdStr = stringdup(newcmd);
02263     delete tree;
02264     tree = newtree;
02265   }
02266   
02267   // and evaluate
02268   atomsel_ctxt context(table, mol, which_frame, NULL);
02269 
02270   // resize flags array if necessary
02271   if (num_atoms != mol->nAtoms || (on == NULL)) {
02272     if (on) delete [] on;
02273     on = new int[mol->nAtoms];
02274     num_atoms = mol->nAtoms;
02275   }
02276 
02277   tree->use_context(&context);
02278   int rc = tree->evaluate(mol->nAtoms, on);
02279 
02280   // store parse return code before we postprocess
02281   int ret_code = rc ? PARSE_SUCCESS : NO_EVAL;
02282 
02283   // find the first selected atom, the last selected atom,
02284   // and the total number of selected atoms
02285   selected = 0;
02286   firstsel = 0;
02287   lastsel = NO_PARSE;
02288   int i;
02289 
02290   // find the first selected atom, if any
02291   for (i=0; i<num_atoms; i++) if (on[i]) break;
02292 
02293   // detect if no atoms were selected, 
02294   // otherwise we just found the first selected atom
02295   if (i == num_atoms)
02296     return ret_code;
02297   else
02298     firstsel = i;
02299 
02300   // count the number of selected atoms (there are only 0s and 1s)
02301   // and determine the index of the last selected atom
02302   for (i=firstsel; i<num_atoms; i++) {
02303     selected += on[i];
02304     if (on[i])
02305       lastsel = i;
02306   }
02307 
02308   return ret_code;
02309 }
02310 
02311 
02312 // return the current coordinates (or NULL if error)
02313 float *AtomSel::coordinates(MoleculeList *mlist) const {
02314   Timestep *ts = timestep(mlist);
02315   if (ts) return ts->pos;
02316   return NULL;
02317 }
02318 
02319 
02320 // return the current timestep (or NULL if error)
02321 Timestep *AtomSel::timestep(MoleculeList *mlist) const {
02322   DrawMolecule *mymol = mlist->mol_from_id(molid()); 
02323 
02324   if (!mymol) {
02325     msgErr << "No molecule" << sendmsg;
02326     return NULL;  // no molecules
02327   }
02328 
02329   switch (which_frame) {
02330     case TS_LAST: 
02331       return mymol->get_last_frame();
02332 
02333     case TS_NOW: 
02334       return mymol->current();
02335 
02336     default:
02337       // if past end of coords return last coord
02338       if (!mymol->get_frame(which_frame)) { 
02339         return mymol->get_last_frame(); 
02340       }
02341   }
02342 
02343   return mymol->get_frame(which_frame);
02344 }
02345 
02346 
02347 int AtomSel::get_frame_value(const char *s, int *val) {
02348   *val = 1;
02349   if (!strcmp(s, "last")) {
02350     *val = TS_LAST;
02351   }
02352   if (!strcmp(s, "first")) {
02353     *val = 0;
02354   }
02355   if (!strcmp(s, "now")) {
02356     *val = TS_NOW;
02357   }
02358   if (*val == 1) {
02359     int new_frame = atoi(s);
02360     *val = new_frame;
02361     if (new_frame < 0) {
02362       return -1;
02363     }
02364   }
02365   return 0;
02366 }

Generated on Wed May 16 01:49:01 2012 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002