Main Page   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-2008 The Board of Trustees of the           
00004  *cr                        University of Illinois                       
00005  *cr                         All Rights Reserved                        
00006  *cr                                                                   
00007  ***************************************************************************/
00008 
00009 /***************************************************************************
00010  * RCS INFORMATION:
00011  *
00012  *      $RCSfile: AtomSel.C,v $
00013  *      $Author: johns $        $Locker:  $                $State: Exp $
00014  *      $Revision: 1.157 $      $Date: 2008/03/27 19:36:35 $
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 
00045 // 'all'
00046 static int atomsel_all(void * ,int, int *) {
00047   return 1;
00048 }
00049 
00050 // 'none'
00051 static int atomsel_none(void *, int num, int *flgs) {
00052   for (int i=num-1; i>=0; i--) {
00053     flgs[i] = FALSE;
00054   }
00055   return 1;
00056 }
00057 
00058 #define generic_atom_data(fctnname, datatype, field)                   \
00059 static int fctnname(void *v, int num, datatype *data, int *flgs) {     \
00060   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;      \
00061   for (int i=0; i<num; i++) {                                          \
00062     if (flgs[i]) {                                                     \
00063       data[i] = atom_sel_mol->atom(i)->field;                          \
00064     }                                                                  \
00065   }                                                                    \
00066   return 1;                                                            \
00067 }
00068 
00069 
00070 #define generic_set_atom_data(fctnname, datatype, fieldtype, field)    \
00071 static int fctnname(void *v, int num, datatype *data, int *flgs) {     \
00072   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;      \
00073   int i;                                                               \
00074   for (i=0; i<num; i++) {                                              \
00075     if (flgs[i]) {                                                     \
00076       atom_sel_mol->atom(i)->field = (fieldtype) data[i];              \
00077     }                                                                  \
00078   }                                                                    \
00079   return 1;                                                            \
00080 }
00081 
00082 
00083 // 'name'
00084 static int atomsel_name(void *v, int num, const char **data, int *flgs) {
00085   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;
00086   for (int i=0; i<num; i++) {
00087     if (flgs[i])
00088       data[i] = (atom_sel_mol->atomNames).name(
00089                   atom_sel_mol->atom(i)->nameindex);
00090   }
00091   return 1;
00092 }
00093 
00094 
00095 // 'type'
00096 static int atomsel_type(void *v, int num, const char **data, int *flgs) {
00097   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;
00098   for (int i=0; i<num; i++) {
00099     if (flgs[i])
00100       data[i] = (atom_sel_mol->atomTypes).name(
00101                   atom_sel_mol->atom(i)->typeindex);
00102   }
00103   return 1;
00104 }
00105 
00106 // XXX probably only use this for internal testing
00107 // 'backbonetype'
00108 static int atomsel_backbonetype(void *v, int num, const char **data, int *flgs) {
00109   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;
00110   for (int i=0; i<num; i++) {
00111     if (flgs[i]) {
00112       switch (atom_sel_mol->atom(i)->atomType) {
00113         case ATOMNORMAL:
00114           data[i] = "normal";
00115           break;
00116 
00117         case ATOMPROTEINBACK:
00118           data[i] = "proteinback";
00119           break;
00120 
00121         case ATOMNUCLEICBACK:
00122           data[i] = "nucleicback";
00123           break;
00124 
00125         case ATOMHYDROGEN:
00126           data[i] = "hydrogen";
00127           break;
00128 
00129         default:
00130           data[i] = "unknown";
00131           break;
00132       }
00133     }
00134   }
00135   return 1;
00136 }
00137 
00138 
00139 // XXX probably only use this for internal testing
00140 // 'residuetype'
00141 static int atomsel_residuetype(void *v, int num, const char **data, int *flgs) {
00142   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;
00143   for (int i=0; i<num; i++) {
00144     if (flgs[i]) {
00145       switch (atom_sel_mol->atom(i)->residueType) {
00146         case RESNOTHING:
00147           data[i] = "nothing";
00148           break;
00149 
00150         case RESPROTEIN:
00151           data[i] = "protein";
00152           break;
00153 
00154         case RESNUCLEIC:
00155           data[i] = "nucleic";
00156           break;
00157 
00158         case RESWATERS:
00159           data[i] = "waters";
00160           break;
00161 
00162         default:
00163           data[i] = "unknown";
00164           break;
00165       }
00166     }
00167   }
00168   return 1;
00169 }
00170 
00171 
00172 // 'atomicnumber'
00173 generic_atom_data(atomsel_atomicnumber, int, atomicnumber)
00174 generic_set_atom_data(atomsel_set_atomicnumber, int, int, atomicnumber)
00175 
00176 
00177 // 'element'
00178 static int atomsel_element(void *v, int num, const char **data, int *flgs) {
00179   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;
00180   for (int i=0; i<num; i++) {
00181     if (flgs[i])
00182       data[i] = get_pte_label(atom_sel_mol->atom(i)->atomicnumber);
00183   }
00184   return 1;
00185 }
00186 static int atomsel_set_element(void *v, int num, const char **data, int *flgs) {
00187   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;
00188   for (int i=0; i<num; i++)
00189     if (flgs[i]) {
00190       int idx = get_pte_idx_from_string((const char *)(data[i]));
00191       atom_sel_mol->atom(i)->atomicnumber = idx;
00192     }
00193   return 1;
00194 }
00195 
00196 
00197 // 'index'
00198 static int atomsel_index(void *v, int num, int *data, int *flgs) { 
00199   for (int i=0; i<num; i++) {
00200     if (flgs[i]) {
00201       data[i] = i; // zero-based
00202     }
00203   }
00204   return 1;
00205 }
00206 
00207 
00208 // 'serial' (one-based atom index)
00209 static int atomsel_serial(void *v, int num, int *data, int *flgs) { 
00210   for (int i=0; i<num; i++) {
00211     if (flgs[i]) {
00212       data[i] = i + 1; // one-based
00213     }
00214   }
00215   return 1;
00216 }
00217 
00218 
00219 // 'fragment'
00220 static int atomsel_fragment(void *v, int num, int *data, int *flgs) {
00221   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;
00222   for (int i=0; i<num; i++) {
00223     if (flgs[i]) {
00224       int residue = atom_sel_mol->atom(i)->uniq_resid;
00225       data[i] = (atom_sel_mol->residue(residue))->fragment;
00226     }
00227   }
00228   return 1;
00229 }
00230 
00231 
00232 // 'numbonds'
00233 generic_atom_data(atomsel_numbonds, int, bonds)
00234 
00235 
00236 // 'residue'
00237 generic_atom_data(atomsel_residue, int, uniq_resid)
00238 
00239 
00240 // 'resname'
00241 static int atomsel_resname(void *v, int num, const char **data, int *flgs) {
00242   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;
00243   for (int i=0; i<num; i++) {
00244     if (flgs[i])
00245       data[i] = (atom_sel_mol->resNames).name(
00246                  atom_sel_mol->atom(i)->resnameindex);
00247   }
00248   return 1;
00249 }
00250 
00251 
00252 // 'altloc'
00253 static int atomsel_altloc(void *v, int num, const char **data, int *flgs) {
00254   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;                 
00255   for (int i=0; i<num; i++) {
00256     if (flgs[i])
00257       data[i] = (atom_sel_mol->altlocNames).name(
00258         atom_sel_mol->atom(i)->altlocindex);
00259   }
00260   return 1;
00261 }
00262 static int atomsel_set_altloc(void *v, int num, const char **data, int *flgs) {
00263   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;                 
00264   NameList<int> &arr = atom_sel_mol->altlocNames;
00265   for (int i=0; i<num; i++)
00266     if (flgs[i]) {
00267       int ind = arr.add_name((const char *)(data[i]), arr.num());
00268       atom_sel_mol->atom(i)->altlocindex = ind;
00269     }
00270   return 1;
00271 }
00272 
00273 
00274 // 'insertion'
00275 generic_atom_data(atomsel_insertion, const char *, insertionstr)
00276 
00277 
00278 // 'chain'
00279 static int atomsel_chain(void *v, int num, const char **data, int *flgs) {
00280   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;                 
00281   for (int i=0; i<num; i++) {
00282     if (flgs[i])
00283       data[i] = (atom_sel_mol->chainNames).name(
00284                   atom_sel_mol->atom(i)->chainindex);
00285   }
00286   return 1;
00287 }
00288 
00289 
00290 // 'segname'
00291 static int atomsel_segname(void *v, int num, const char **data, int *flgs) {
00292   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;
00293   for (int i=0; i<num; i++) {
00294     if (flgs[i])
00295       data[i] = (atom_sel_mol->segNames).name(
00296                  atom_sel_mol->atom(i)->segnameindex);
00297   }
00298   return 1;
00299 }
00300 
00301 
00302 // The next few set functions affect the namelists kept in BaseMolecule
00303 static int atomsel_set_name(void *v, int num, const char **data, int *flgs) {
00304   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;
00305   NameList<int> &arr = atom_sel_mol->atomNames;
00306   for (int i=0; i<num; i++) {
00307     if (flgs[i]) {
00308       int ind = arr.add_name((const char *)(data[i]), arr.num());
00309       atom_sel_mol->atom(i)->nameindex = ind;
00310     }
00311   }
00312   return 1;
00313 }
00314 
00315 static int atomsel_set_type(void *v, int num, const char **data, int *flgs) {
00316   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;
00317   NameList<int> &arr = atom_sel_mol->atomTypes;
00318   for (int i=0; i<num; i++) {
00319     if (flgs[i]) {
00320       int ind = arr.add_name((const char *)(data[i]), arr.num());
00321       atom_sel_mol->atom(i)->typeindex = ind;
00322     }
00323   }
00324   return 1;
00325 }
00326 
00327 static int atomsel_set_resname(void *v, int num, const char **data, int *flgs) {
00328   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;
00329   NameList<int> &arr = atom_sel_mol->resNames;
00330   for (int i=0; i<num; i++) {
00331     if (flgs[i]) {
00332       int ind = arr.add_name((const char *)(data[i]), arr.num());
00333       atom_sel_mol->atom(i)->resnameindex = ind;
00334     }
00335   }
00336   return 1;
00337 }
00338 
00339 static int atomsel_set_chain(void *v, int num, const char **data, int *flgs) {
00340   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;
00341   NameList<int> &arr = atom_sel_mol->chainNames;
00342   for (int i=0; i<num; i++) {
00343     if (flgs[i]) {
00344       int ind = arr.add_name((const char *)(data[i]), arr.num());
00345       atom_sel_mol->atom(i)->chainindex = ind;
00346     }
00347   }
00348   return 1;
00349 }
00350 
00351 static int atomsel_set_segname(void *v, int num, const char **data, int *flgs) {
00352   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;
00353   NameList<int> &arr = atom_sel_mol->segNames;
00354   for (int i=0; i<num; i++) {
00355     if (flgs[i]) {
00356       int ind = arr.add_name((const char *)(data[i]), arr.num());
00357       atom_sel_mol->atom(i)->segnameindex = ind;
00358     }
00359   }
00360   return 1;
00361 }
00362 
00363 
00364 // 'radius'
00365 static int atomsel_radius(void *v, int num, double *data, int *flgs) {
00366   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;
00367   float *radius = atom_sel_mol->radius();
00368   for (int i=0; i<num; i++)
00369     if (flgs[i]) data[i] = radius[i];
00370   return 1;
00371 }
00372 static int atomsel_set_radius(void *v, int num, double *data, int *flgs) {
00373   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;
00374   float *radius = atom_sel_mol->radius();
00375   for (int i=0; i<num; i++)
00376     if (flgs[i]) radius[i] = (float) data[i];
00377   return 1;
00378 }
00379 
00380 
00381 // 'mass'
00382 static int atomsel_mass(void *v, int num, double *data, int *flgs) {
00383   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;
00384   float *mass = atom_sel_mol->mass();
00385   for (int i=0; i<num; i++)
00386     if (flgs[i]) data[i] = mass[i];
00387   return 1;
00388 }
00389 static int atomsel_set_mass(void *v, int num, double *data, int *flgs) {
00390   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;
00391   float *mass = atom_sel_mol->mass();
00392   for (int i=0; i<num; i++)
00393     if (flgs[i]) mass[i] = (float) data[i];
00394   return 1;
00395 }
00396 
00397 
00398 // 'charge'
00399 static int atomsel_charge(void *v, int num, double *data, int *flgs) {
00400   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;
00401   float *charge = atom_sel_mol->charge();
00402   for (int i=0; i<num; i++)
00403     if (flgs[i]) data[i] = charge[i];
00404   return 1;
00405 }
00406 static int atomsel_set_charge(void *v, int num, double *data, int *flgs) {
00407   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;
00408   float *charge = atom_sel_mol->charge();
00409   for (int i=0; i<num; i++)
00410     if (flgs[i]) charge[i] = (float) data[i];
00411   return 1;
00412 }
00413 
00414 
00415 // 'beta'
00416 static int atomsel_beta(void *v, int num, double *data, int *flgs) {
00417   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;
00418   float *beta = atom_sel_mol->beta();
00419   for (int i=0; i<num; i++)
00420     if (flgs[i]) data[i] = beta[i];
00421   return 1;
00422 }
00423 static int atomsel_set_beta(void *v, int num, double *data, int *flgs) {
00424   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;
00425   float *beta = atom_sel_mol->beta();
00426   for (int i=0; i<num; i++)
00427     if (flgs[i]) beta[i] = (float) data[i];
00428   return 1;
00429 }
00430 
00431 
00432 // 'occupancy?'
00433 static int atomsel_occupancy(void *v, int num, double *data, int *flgs) {
00434   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;
00435   float *occupancy = atom_sel_mol->occupancy();
00436   for (int i=0; i<num; i++)
00437     if (flgs[i]) data[i] = occupancy[i];
00438   return 1;
00439 }
00440 static int atomsel_set_occupancy(void *v, int num, double *data, int *flgs) {
00441   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;
00442   float *occupancy = atom_sel_mol->occupancy();
00443   for (int i=0; i<num; i++)
00444     if (flgs[i]) occupancy[i] = (float) data[i];
00445   return 1;
00446 }
00447 
00448 
00449 // 'resid'
00450 static int atomsel_resid(void *v, int num, int *data, int *flgs) {
00451   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;
00452   for (int i=0; i<num; i++) {
00453     if (flgs[i]) {
00454       data[i] = atom_sel_mol->atom(i)->resid;
00455     }
00456   }
00457   return 1;
00458 }
00459 static int atomsel_set_resid(void *v, int num, int *data, int *flgs) {
00460   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;
00461   for (int i=0; i<num; i++) {
00462     if (flgs[i])
00463       atom_sel_mol->atom(i)->resid = data[i];
00464   }
00465   return 1;
00466 }
00467 
00468 
00469 
00470 #define generic_atom_boolean(fctnname, comparison)                    \
00471 static int fctnname(void *v, int num, int *flgs) {                    \
00472   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;     \
00473   for (int i=0; i<num; i++) {                                         \
00474     if (flgs[i]) {                                                    \
00475       flgs[i] = atom_sel_mol->atom(i)->comparison;                    \
00476     }                                                                 \
00477   }                                                                   \
00478   return 1;                                                           \
00479 }
00480 
00481 // 'backbone'
00482 static int atomsel_backbone(void *v, int num, int *flgs) {
00483   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;
00484   for (int i=0; i<num; i++) {
00485     if (flgs[i]) {
00486       const MolAtom *a = atom_sel_mol->atom(i);
00487       flgs[i] = (a->atomType == ATOMPROTEINBACK ||
00488                  a->atomType == ATOMNUCLEICBACK);
00489     }
00490   }
00491   return 1;
00492 }
00493 
00494 // 'h' (hydrogen)
00495 generic_atom_boolean(atomsel_hydrogen, atomType == ATOMHYDROGEN)
00496 
00497 
00498 // 'protein'
00499 generic_atom_boolean(atomsel_protein, residueType == RESPROTEIN)
00500 
00501 
00502 // 'nucleic'
00503 generic_atom_boolean(atomsel_nucleic, residueType == RESNUCLEIC)
00504 
00505 
00506 // 'water'
00507 generic_atom_boolean(atomsel_water, residueType == RESWATERS)
00508 
00509 #define generic_sstruct_boolean(fctnname, comparison)                    \
00510 static int fctnname(void *v, int num, int *flgs) {                       \
00511   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;        \
00512   atom_sel_mol->need_secondary_structure(1);                             \
00513   for (int i=0; i<num; i++) {                                            \
00514     int s;                                                               \
00515     if (flgs[i]) {                                                       \
00516       s = atom_sel_mol->residue(                                         \
00517                                   atom_sel_mol->atom(i)->uniq_resid      \
00518                                   )->sstruct;                            \
00519       if (!comparison) {                                                 \
00520         flgs[i] = 0;                                                     \
00521       }                                                                  \
00522     }                                                                    \
00523   }                                                                      \
00524   return 1;                                                              \
00525 }
00526 
00527 // once I define a structure, I don't need to recompute; hence the 
00528 //   need_secondary_structure(0);
00529 #define generic_set_sstruct_boolean(fctnname, newval)                    \
00530 static int fctnname(void *v, int num, int *data, int *flgs) {            \
00531   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;        \
00532   atom_sel_mol->need_secondary_structure(0);                             \
00533   for (int i=0; i<num; i++) {                                            \
00534     if (flgs[i] && data[i]) {                                            \
00535         atom_sel_mol->residue(atom_sel_mol->atom(i)->uniq_resid)         \
00536           ->sstruct = newval;                                            \
00537     }                                                                    \
00538   }                                                                      \
00539   return 1;                                                              \
00540 }
00541 
00542 
00543 // XXX recursive routines should be replaced by an iterative version with
00544 // it's own stack, so that huge molecules don't overflow the stack
00545 static void recursive_find_sidechain_atoms(BaseMolecule *mol, int *sidechain,
00546                                            int atom_index) {
00547   // Have I been here before?
00548   if (sidechain[atom_index] == 2) 
00549     return;
00550 
00551   // Is this a backbone atom
00552   MolAtom *atom = mol->atom(atom_index);
00553   if (atom->atomType == ATOMPROTEINBACK ||
00554       atom->atomType == ATOMNUCLEICBACK) return;
00555   
00556   // mark this atom
00557   sidechain[atom_index] = 2;
00558 
00559   // try the atoms to which this is bonded
00560   for (int i=0; i<atom->bonds; i++) {
00561     recursive_find_sidechain_atoms(mol, sidechain, atom->bondTo[i]);
00562   }
00563 }
00564 
00565 // give an array where 1 indicates an atom on the sidechain, find the
00566 // connected atoms which are also on the sidechain
00567 static void find_sidechain_atoms(BaseMolecule *mol, int *sidechain) {
00568   for (int i=0; i<mol->nAtoms; i++) {
00569     if (sidechain[i] == 1) {
00570       recursive_find_sidechain_atoms(mol, sidechain, i);
00571     }
00572   }
00573 }
00574 
00575 
00576 // 'sidechain' is tricky.  I start from a protein CA, pick a bond which
00577 // isn't along the backbone (and discard it once if it is a hydrogen),
00578 // and follow the atoms until I stop at another backbone atom or run out
00579 // of atoms
00580 static int atomsel_sidechain(void *v, int num, int *flgs) {
00581   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;               
00582   const float *mass = atom_sel_mol->mass();
00583   int *seed = new int[num];
00584   int i;
00585 
00586   // generate a list of the "CB" atoms (or whatever they are)
00587   for (i=0; i<num; i++) {
00588     seed[i] = 0;
00589   }
00590 
00591   // get the CA and HA2 name index
00592   int CA = atom_sel_mol->atomNames.typecode((char *) "CA");
00593 
00594   // for each protein
00595   for (int pfrag=atom_sel_mol->pfragList.num()-1; pfrag>=0; pfrag--) {
00596     // get a residue
00597     Fragment &frag = *(atom_sel_mol->pfragList[pfrag]);
00598     for (int res = frag.num()-1; res >=0; res--) {
00599       // find the CA
00600       int atomid = atom_sel_mol->find_atom_in_residue(CA, frag[res]);
00601       if (atomid < 0) {
00602         msgErr << "atomselection: sidechain: cannot find CA" << sendmsg;
00603         continue;
00604       }
00605       // find at most two neighbors which are not on the backbone
00606       MolAtom *atom = atom_sel_mol->atom(atomid);
00607       int b1 = -1, b2 = -1;
00608       for (i=0; i<atom->bonds; i++) {
00609         int bondtype = atom_sel_mol->atom(atom->bondTo[i])->atomType;
00610         if (bondtype == ATOMNORMAL || bondtype == ATOMHYDROGEN) {
00611           if (b1 == -1) {
00612             b1 = atom->bondTo[i];
00613           } else {
00614             if (b2 == -1) {
00615               b2 = atom->bondTo[i];
00616             } else {
00617               msgErr << "atomselection: sidechain: protein residue index " 
00618                      << res << ", C-alpha index " << i << " has more than "
00619                      << "two non-backbone bonds; ignoring the others"
00620                      << sendmsg;
00621             }
00622           }
00623         }
00624       }
00625       if (b1 == -1) 
00626         continue;
00627 
00628       if (b2 != -1) {  // find the right one
00629         // first check the number of atoms and see if I have a lone H
00630         int c1 = atom_sel_mol->atom(b1)->bonds;
00631         int c2 = atom_sel_mol->atom(b2)->bonds;
00632         if (c1 == 1 && c2 > 1) {
00633           b1 = b2;
00634         } else if (c2 == 1 && c1 > 1) {
00635           b1 = b1;
00636         } else if (c1 ==1 && c2 == 1) {
00637           // check the masses
00638           float m1 = mass[b1];
00639           float m2 = mass[b2];
00640           if (m1 > 2.3 && m2 <= 2.3) {
00641             b1 = b2;
00642           } else if (m2 > 2.3 && m1 <= 2.3) {
00643             b1 = b1;
00644           } else if (m1 <= 2.0 && m2 <= 2.3) {
00645             // should have two H's, find the "first" of these
00646             if (strcmp(
00647               (atom_sel_mol->atomNames).name(atom_sel_mol->atom(b1)->nameindex),
00648               (atom_sel_mol->atomNames).name(atom_sel_mol->atom(b2)->nameindex)
00649               ) > 0) {
00650               b1 = b2;
00651             } // else b1 = b1
00652           } else {
00653             msgErr << "atomselect: sidechain:  protein residue index " 
00654                    << res << ", C-alpha index " << i << " has sidechain-like "
00655                    << "atom (indices " << b1 << " and " << b2 << "), and "
00656                    << "I cannot determine which to call a sidechain -- "
00657                    << "I'll guess" << sendmsg;
00658             if (strcmp(
00659               (atom_sel_mol->atomNames).name(atom_sel_mol->atom(b1)->nameindex),
00660               (atom_sel_mol->atomNames).name(atom_sel_mol->atom(b2)->nameindex)
00661               ) > 0) {
00662               b1 = b2;
00663             }
00664           } // punted
00665         } // checked connections and masses
00666       } // found the right one; it is b1.
00667       seed[b1] = 1;
00668 
00669     } // loop over residues
00670   } // loop over protein fragments
00671 
00672   // do the search for all the sidechain atoms (returned in seed)
00673   find_sidechain_atoms(atom_sel_mol, seed);
00674 
00675   // set the return values
00676   for (i=0; i<num; i++) {
00677     if (flgs[i]) 
00678       flgs[i] = (seed[i] != 0);
00679   }
00680 
00681   delete [] seed;
00682 
00683   return 1;
00684 }
00685 
00686 
00687 // which of these are helices?
00688 generic_sstruct_boolean(atomsel_helix, (s == SS_HELIX_ALPHA ||
00689                                         s == SS_HELIX_3_10  ||
00690                                         s == SS_HELIX_PI))
00691 generic_sstruct_boolean(atomsel_alpha_helix, (s == SS_HELIX_ALPHA))
00692 generic_sstruct_boolean(atomsel_3_10_helix, (s == SS_HELIX_3_10))
00693 generic_sstruct_boolean(atomsel_pi_helix, (s == SS_HELIX_PI))
00694 
00695 // Makes the residue into a HELIX_ALPHA
00696 generic_set_sstruct_boolean(atomsel_set_helix, SS_HELIX_ALPHA)
00697 // Makes the residue into a HELIX_3_10
00698 generic_set_sstruct_boolean(atomsel_set_3_10_helix, SS_HELIX_3_10)
00699 // Makes the residue into a HELIX_PI
00700 generic_set_sstruct_boolean(atomsel_set_pi_helix, SS_HELIX_PI)
00701 
00702 // which of these are beta sheets?
00703 generic_sstruct_boolean(atomsel_sheet, (s == SS_BETA ||
00704                                         s == SS_BRIDGE ))
00705 generic_sstruct_boolean(atomsel_extended_sheet, (s == SS_BETA))
00706 generic_sstruct_boolean(atomsel_bridge_sheet, (s == SS_BRIDGE ))
00707 
00708 // Makes the residue into a BETA
00709 generic_set_sstruct_boolean(atomsel_set_sheet, SS_BETA)
00710 generic_set_sstruct_boolean(atomsel_set_bridge_sheet, SS_BRIDGE)
00711 
00712 // which of these are coils?
00713 generic_sstruct_boolean(atomsel_coil, (s == SS_COIL))
00714 
00715 // Makes the residue into COIL
00716 generic_set_sstruct_boolean(atomsel_set_coil, SS_COIL)
00717 
00718 // which of these are TURNS?
00719 generic_sstruct_boolean(atomsel_turn, (s == SS_TURN))
00720 
00721 // Makes the residue into TURN
00722 generic_set_sstruct_boolean(atomsel_set_turn, SS_TURN)
00723 
00724 // return the sstruct information as a 1 character string
00725 static int atomsel_sstruct(void *v, int num, const char **data, int *flgs) {
00726   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;
00727   atom_sel_mol->need_secondary_structure(1);
00728   for (int i=0; i<num; i++) {
00729     if (flgs[i]) {
00730       switch(atom_sel_mol->residue(atom_sel_mol->atom(i)->uniq_resid)->sstruct) {
00731         case SS_HELIX_ALPHA: data[i] = "H"; break;
00732         case SS_HELIX_3_10 : data[i] = "G"; break;
00733         case SS_HELIX_PI   : data[i] = "I"; break;
00734         case SS_BETA       : data[i] = "E"; break;
00735         case SS_BRIDGE     : data[i] = "B"; break;
00736         case SS_TURN       : data[i] = "T"; break;
00737         default:
00738         case SS_COIL       : data[i] = "C"; break;
00739       }
00740     }
00741   }
00742   return 1;
00743 }
00744 
00745 
00746 // set the secondary structure based on a string value
00747 static int atomsel_set_sstruct(void *v, int num, const char **data, int *flgs) {
00748   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;
00749   char c;
00750   // Defining it here so remind myself that I don't need STRIDE (or
00751   // whoever) to do it automatically
00752   atom_sel_mol->need_secondary_structure(0);
00753   for (int i=0; i<num; i++) {
00754     if (flgs[i]) {
00755       if (strlen(data[i]) == 0) {
00756         msgErr << "cannot set a 0 length secondary structure string"
00757                << sendmsg;
00758       } else {
00759         c = ((const char *) data[i])[0];
00760         if (strlen(data[i]) > 1) {
00761           while (1) {
00762  if (!strcasecmp((const char *) data[i], "helix")) { c = 'H'; break;}
00763  if (!strcasecmp((const char *) data[i], "alpha")) { c = 'H'; break;}
00764  if (!strcasecmp((const char *) data[i], "alpha_helix")) { c = 'H'; break;}
00765  if (!strcasecmp((const char *) data[i], "alphahelix"))  { c = 'H'; break;}
00766  if (!strcasecmp((const char *) data[i], "alpha helix")) { c = 'H'; break;}
00767 
00768  if (!strcasecmp((const char *) data[i], "pi"))        { c = 'I'; break;}
00769  if (!strcasecmp((const char *) data[i], "pi_helix"))  { c = 'I'; break;}
00770  if (!strcasecmp((const char *) data[i], "pihelix"))   { c = 'I'; break;}
00771  if (!strcasecmp((const char *) data[i], "pi helix"))  { c = 'I'; break;}
00772 
00773  if (!strcasecmp((const char *) data[i], "310"))       { c = 'G'; break;}
00774  if (!strcasecmp((const char *) data[i], "310_helix")) { c = 'G'; break;}
00775  if (!strcasecmp((const char *) data[i], "3_10"))      { c = 'G'; break;}
00776  if (!strcasecmp((const char *) data[i], "3"))         { c = 'G'; break;}
00777  if (!strcasecmp((const char *) data[i], "310 helix")) { c = 'G'; break;}
00778  if (!strcasecmp((const char *) data[i], "3_10_helix")){ c = 'G'; break;}
00779  if (!strcasecmp((const char *) data[i], "3_10 helix")){ c = 'G'; break;}
00780  if (!strcasecmp((const char *) data[i], "3 10 helix")){ c = 'G'; break;}
00781  if (!strcasecmp((const char *) data[i], "helix_3_10")){ c = 'G'; break;}
00782  if (!strcasecmp((const char *) data[i], "helix 3 10")){ c = 'G'; break;}
00783  if (!strcasecmp((const char *) data[i], "helix3_10")) { c = 'G'; break;}
00784  if (!strcasecmp((const char *) data[i], "helix310"))  { c = 'G'; break;}
00785 
00786  if (!strcasecmp((const char *) data[i], "beta"))      { c = 'E'; break;}
00787  if (!strcasecmp((const char *) data[i], "betasheet")) { c = 'E'; break;}
00788  if (!strcasecmp((const char *) data[i], "beta_sheet")){ c = 'E'; break;}
00789  if (!strcasecmp((const char *) data[i], "beta sheet")){ c = 'E'; break;}
00790  if (!strcasecmp((const char *) data[i], "sheet"))     { c = 'E'; break;}
00791  if (!strcasecmp((const char *) data[i], "strand"))    { c = 'E'; break;}
00792  if (!strcasecmp((const char *) data[i], "beta_strand"))  { c = 'E'; break;}
00793  if (!strcasecmp((const char *) data[i], "beta strand"))  { c = 'E'; break;}
00794 
00795  if (!strcasecmp((const char *) data[i], "turn"))  { c = 'T'; break;}
00796 
00797  if (!strcasecmp((const char *) data[i], "coil"))     { c = 'C'; break;}
00798  if (!strcasecmp((const char *) data[i], "unknown"))  { c = 'C'; break;}
00799  c = 'X';
00800  break;
00801           } // while (1)
00802         }
00803         // and set the value
00804         int s = SS_COIL;
00805         switch ( c ) {
00806         case 'H':
00807         case 'h': s = SS_HELIX_ALPHA; break;
00808         case '3':
00809         case 'G':
00810         case 'g': s = SS_HELIX_3_10; break;
00811         case 'P':  // so you can say 'pi'
00812         case 'p':
00813         case 'I':
00814         case 'i': s = SS_HELIX_PI; break;
00815         case 'S':  // for "sheet"
00816         case 's':
00817         case 'E':
00818         case 'e': s = SS_BETA; break;
00819         case 'B':
00820         case 'b': s = SS_BRIDGE; break;
00821         case 'T':
00822         case 't': s = SS_TURN; break;
00823         case 'L': // L is from PHD and may be an alternate form
00824         case 'l':
00825         case 'C':
00826         case 'c': s = SS_COIL; break;
00827         default: {
00828           msgErr << "Unknown sstruct assignment: '"
00829             << (const char *) data[i] << "'" << sendmsg;
00830           s = SS_COIL; break;
00831         }
00832         }
00833         atom_sel_mol->residue(atom_sel_mol->atom(i)->uniq_resid)->sstruct = s;
00834       }
00835     }
00836   }
00837   return 1;
00838 }
00839 
00840 
00842 //      and leave the rest alone.
00843 // It is slower this way, but easier to understand
00844 static void mark_atoms_given_residue(DrawMolecule *mol, int residue, int *on)
00845 {
00846   ResizeArray<int> *atoms = &(mol->residueList[residue]->atoms);
00847   for (int i= atoms->num()-1; i>=0; i--) {
00848      on[(*atoms)[i]] = TRUE;
00849   }
00850 }
00851 
00852 
00853 // macro for either protein or nucleic fragments
00854 #define fragment_data(fctn, fragtype)                                         \
00855 static int fctn(void *v, int num, int *data, int *)                           \
00856 {                                                                             \
00857   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;                     \
00858    int *tmp = new int[num];                                                   \
00859    int i;                                                                     \
00860    for (i=num-1; i>=0; i--) {  /* clear the arrays */                 \
00861       tmp[i] = 0;                                                             \
00862       data[i] = -1;  /* default is -1 for 'not a [np]frag' */                 \
00863    }                                                                          \
00864    /* for each fragment */                                                    \
00865    for ( i=atom_sel_mol->fragtype.num()-1; i>=0; i--) {                       \
00866       /* for each residues of the fragment */                                 \
00867       int j;                                                                  \
00868       for (j=atom_sel_mol->fragtype[i]->num()-1; j>=0; j--) {                 \
00869          /* mark the atoms in the fragment */                                 \
00870          mark_atoms_given_residue(atom_sel_mol,(*atom_sel_mol->fragtype[i])[j], tmp);      \
00871       }                                                                       \
00872       /* and label them with the appropriate number */                        \
00873       for (j=num-1; j>=0; j--) {                                              \
00874          if (tmp[j]) {                                                        \
00875             data[j] = i;                                                      \
00876             tmp[j] = 0;                                                       \
00877          }                                                                    \
00878       }                                                                       \
00879    }                                                                          \
00880    delete [] tmp;                                                             \
00881    return 1;                                                                  \
00882 }
00883 
00884 fragment_data(atomsel_pfrag, pfragList)
00885 fragment_data(atomsel_nfrag, nfragList)
00886 
00887 static Timestep *selframe(DrawMolecule *atom_sel_mol, int which_frame) {
00888   Timestep *r;
00889   switch (which_frame) {
00890    case AtomSel::TS_LAST: r = atom_sel_mol->get_last_frame(); break;
00891 
00892    case AtomSel::TS_NOW : r = atom_sel_mol->current(); break;
00893    default: {
00894      if (!atom_sel_mol->get_frame(which_frame)) {
00895        r = atom_sel_mol->get_last_frame();
00896 
00897      } else {
00898        r = atom_sel_mol->get_frame(which_frame);
00899      }
00900    }
00901   }
00902   return r;
00903 }
00904 
00905 static int atomsel_user(void *v, int num, double *data, int *flgs) {
00906   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;                     
00907   int which_frame = ((atomsel_ctxt *)v)->which_frame;
00908   Timestep *ts = selframe(atom_sel_mol, which_frame);
00909   if (!ts || !ts->user) {
00910     memset(data, 0, num*sizeof(double));
00911     return 1;                                                           
00912   }
00913   for (int i=0; i<num; i++) {                                         
00914     if (flgs[i]) {                                                            
00915       data[i] = ts->user[i];                                          
00916     }                                                                         
00917   }                                                                           
00918   return 1;                                                                  
00919 }
00920 static int atomsel_set_user(void *v, int num, double *data, int *flgs) {
00921   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;                     
00922   int which_frame = ((atomsel_ctxt *)v)->which_frame;
00923   Timestep *ts = selframe(atom_sel_mol, which_frame);
00924   if (!ts) return 0;
00925   if (!ts->user) {
00926     ts->user= new float[num];
00927     memset(ts->user, 0, num*sizeof(float));
00928   }
00929   for (int i=0; i<num; i++) {                                         
00930     if (flgs[i]) {                                                            
00931       ts->user[i] = (float)data[i];                                           
00932     }                                                                         
00933   }                                                                           
00934   return 1;                                                                  
00935 }
00936 
00937 static int atomsel_user2(void *v, int num, double *data, int *flgs) {
00938   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;                     
00939   int which_frame = ((atomsel_ctxt *)v)->which_frame;
00940   Timestep *ts = selframe(atom_sel_mol, which_frame);
00941   if (!ts || !ts->user2) {
00942     memset(data, 0, num*sizeof(double));
00943     return 1;                                                           
00944   }
00945   for (int i=0; i<num; i++) {                                         
00946     if (flgs[i]) {                                                            
00947       data[i] = ts->user2[i];                                         
00948     }                                                                         
00949   }                                                                           
00950   return 1;                                                                  
00951 }
00952 static int atomsel_set_user2(void *v, int num, double *data, int *flgs) {
00953   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;                     
00954   int which_frame = ((atomsel_ctxt *)v)->which_frame;
00955   Timestep *ts = selframe(atom_sel_mol, which_frame);
00956   if (!ts) return 0;
00957   if (!ts->user2) {
00958     ts->user2= new float[num];
00959     memset(ts->user2, 0, num*sizeof(float));
00960   }
00961   for (int i=0; i<num; i++) {                                         
00962     if (flgs[i]) {                                                            
00963       ts->user2[i] = (float)data[i];                                          
00964     }                                                                         
00965   }                                                                           
00966   return 1;                                                                  
00967 }
00968 
00969 static int atomsel_user3(void *v, int num, double *data, int *flgs) {
00970   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;                     
00971   int which_frame = ((atomsel_ctxt *)v)->which_frame;
00972   Timestep *ts = selframe(atom_sel_mol, which_frame);
00973   if (!ts || !ts->user3) {
00974     memset(data, 0, num*sizeof(double));
00975     return 1;                                                           
00976   }
00977   for (int i=0; i<num; i++) {                                         
00978     if (flgs[i]) {                                                            
00979       data[i] = ts->user3[i];                                         
00980     }                                                                         
00981   }                                                                           
00982   return 1;                                                                  
00983 }
00984 static int atomsel_set_user3(void *v, int num, double *data, int *flgs) {
00985   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;                     
00986   int which_frame = ((atomsel_ctxt *)v)->which_frame;
00987   Timestep *ts = selframe(atom_sel_mol, which_frame);
00988   if (!ts) return 0;
00989   if (!ts->user3) {
00990     ts->user3= new float[num];
00991     memset(ts->user3, 0, num*sizeof(float));
00992   }
00993   for (int i=0; i<num; i++) {                                         
00994     if (flgs[i]) {                                                            
00995       ts->user3[i] = (float)data[i];                                          
00996     }                                                                         
00997   }                                                                           
00998   return 1;                                                                  
00999 }
01000 
01001 static int atomsel_user4(void *v, int num, double *data, int *flgs) {
01002   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;                     
01003   int which_frame = ((atomsel_ctxt *)v)->which_frame;
01004   Timestep *ts = selframe(atom_sel_mol, which_frame);
01005   if (!ts || !ts->user4) {
01006     memset(data, 0, num*sizeof(double));
01007     return 1;                                                           
01008   }
01009   for (int i=0; i<num; i++) {                                         
01010     if (flgs[i]) {                                                            
01011       data[i] = ts->user4[i];                                         
01012     }                                                                         
01013   }                                                                           
01014   return 1;                                                                  
01015 }
01016 static int atomsel_set_user4(void *v, int num, double *data, int *flgs) {
01017   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;                     
01018   int which_frame = ((atomsel_ctxt *)v)->which_frame;
01019   Timestep *ts = selframe(atom_sel_mol, which_frame);
01020   if (!ts) return 0;
01021   if (!ts->user4) {
01022     ts->user4= new float[num];
01023     memset(ts->user4, 0, num*sizeof(float));
01024   }
01025   for (int i=0; i<num; i++) {                                         
01026     if (flgs[i]) {                                                            
01027       ts->user4[i] = (float)data[i];                                          
01028     }                                                                         
01029   }                                                                           
01030   return 1;                                                                  
01031 }
01032 
01033 
01034 
01035 static int atomsel_xpos(void *v, int num, double *data, int *flgs) {
01036   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;                     
01037   int which_frame = ((atomsel_ctxt *)v)->which_frame;
01038   Timestep *ts = selframe(atom_sel_mol, which_frame);
01039   int i;
01040   if (!ts) {
01041     for (i=0; i<num; i++) 
01042       if (flgs[i]) data[i] = 0.0;
01043     return 0;                                                           
01044   }
01045   for (i=0; i<num; i++) {                                             
01046     if (flgs[i]) {                                                            
01047       data[i] = ts->pos[3*i + 0];                                             
01048     }                                                                         
01049   }                                                                           
01050   return 1;                                                                  
01051 }
01052 
01053 static int atomsel_ypos(void *v, int num, double *data, int *flgs) {
01054   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;                     
01055   int which_frame = ((atomsel_ctxt *)v)->which_frame;
01056   Timestep *ts = selframe(atom_sel_mol, which_frame);
01057   int i;
01058   if (!ts) {
01059     for (i=0; i<num; i++) 
01060       if (flgs[i]) data[i] = 0.0;
01061     return 0;                                                           
01062   }
01063   for (i=0; i<num; i++) {                                             
01064     if (flgs[i]) {                                                            
01065       data[i] = ts->pos[3*i + 1];                                             
01066     }                                                                         
01067   }                                                                           
01068   return 1;                                                                  
01069 }
01070 
01071 static int atomsel_zpos(void *v, int num, double *data, int *flgs) {
01072   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;                     
01073   int which_frame = ((atomsel_ctxt *)v)->which_frame;
01074   Timestep *ts = selframe(atom_sel_mol, which_frame);
01075   int i;
01076   if (!ts) {
01077     for (i=0; i<num; i++) 
01078       if (flgs[i]) data[i] = 0.0;
01079     return 0;                                                           
01080   }
01081   for (i=0; i<num; i++) {                                             
01082     if (flgs[i]) {                                                            
01083       data[i] = ts->pos[3*i + 2];                                             
01084     }                                                                         
01085   }                                                                           
01086   return 1;                                                                  
01087 }
01088 
01089 static int atomsel_ufx(void *v, int num, double *data, int *flgs) {
01090   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;                     
01091   int which_frame = ((atomsel_ctxt *)v)->which_frame;
01092   Timestep *ts = selframe(atom_sel_mol, which_frame);
01093   int i;
01094   if (!ts || !ts->force) {
01095     for (i=0; i<num; i++) 
01096       if (flgs[i]) data[i] = 0.0;
01097     return 0;                                                           
01098   }
01099   for (i=0; i<num; i++) {                                             
01100     if (flgs[i]) {                                                            
01101       data[i] = ts->force[3*i + 0];                                           
01102     }                                                                         
01103   }                                                                           
01104   return 1;                                                                  
01105 }
01106 
01107 static int atomsel_ufy(void *v, int num, double *data, int *flgs) {
01108   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;                     
01109   int which_frame = ((atomsel_ctxt *)v)->which_frame;
01110   Timestep *ts = selframe(atom_sel_mol, which_frame);
01111   int i;
01112   if (!ts || !ts->force) {
01113     for (i=0; i<num; i++) 
01114       if (flgs[i]) data[i] = 0.0;
01115     return 0;                                                           
01116   }
01117   for (i=0; i<num; i++) {                                             
01118     if (flgs[i]) {                                                            
01119       data[i] = ts->force[3*i + 1];                                           
01120     }                                                                         
01121   }                                                                           
01122   return 1;                                                                  
01123 }
01124 
01125 static int atomsel_ufz(void *v, int num, double *data, int *flgs) {
01126   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;                     
01127   int which_frame = ((atomsel_ctxt *)v)->which_frame;
01128   Timestep *ts = selframe(atom_sel_mol, which_frame);
01129   int i;
01130   if (!ts || !ts->force) {
01131     for (i=0; i<num; i++) 
01132       if (flgs[i]) data[i] = 0.0;
01133     return 0;                                                           
01134   }
01135   for (i=0; i<num; i++) {                                             
01136     if (flgs[i]) {                                                            
01137       data[i] = ts->force[3*i + 2];                                           
01138     }                                                                         
01139   }                                                                           
01140   return 1;                                                                  
01141 }
01142 
01143 #define atomsel_get_vel(name, offset) \
01144 static int atomsel_##name(void *v, int num, double *data, int *flgs) {  \
01145   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;       \
01146   int which_frame = ((atomsel_ctxt *)v)->which_frame;  \
01147   Timestep *ts = selframe(atom_sel_mol, which_frame);  \
01148   int i;                                               \
01149   if (!ts || !ts->vel) {                               \
01150     for (i=0; i<num; i++)                              \
01151       if (flgs[i]) data[i] = 0.0;                      \
01152     return 0;                                          \
01153   }                                                    \
01154   for (i=0; i<num; i++) {                              \
01155     if (flgs[i]) {                                     \
01156       data[i] = ts->vel[3*i + (offset)];               \
01157     }                                                  \
01158   }                                                    \
01159   return 1;                                            \
01160 }                                                      
01161 
01162 atomsel_get_vel(vx, 0)
01163 atomsel_get_vel(vy, 1)
01164 atomsel_get_vel(vz, 2)
01165 
01166 static int atomsel_phi(void *v, int num, double *data, int *flgs) {
01167   DrawMolecule *atom_sel_mol = ((atomsel_ctxt *)v)->atom_sel_mol;                     
01168   int which_frame = ((atomsel_ctxt *)v)->which_frame;
01169   Timestep *ts =