00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00028 #include <ctype.h>
00029 #include <stdio.h>
00030 #include <stdlib.h>
00031 #include <math.h>
00032 #include "Inform.h"
00033 #include "utilities.h"
00034 #include "intstack.h"
00035 #include "WKFUtils.h"
00036
00037 #include "BaseMolecule.h"
00038 #include "VolumetricData.h"
00039 #include "QMData.h"
00040 #include "QMTimestep.h"
00041
00042 #ifdef VMDWITHCARBS
00043 #include <vector>
00044 #endif
00045
00046 #define MAXBONDERRORS 25
00047
00049
00050 BaseMolecule::BaseMolecule(int myID) : residueList(10) , fragList(1),
00051 #if defined(VMDWITHCARBS)
00052 pfragList(1), nfragList(1), smallringList(), smallringLinkages(), currentMaxRingSize(-1), currentMaxPathLength(-1), ID(myID) {
00053 #else
00054 pfragList(1), nfragList(1), ID(myID) {
00055 #endif
00056
00057
00058 nAtoms = 0;
00059 nResidues = 0;
00060 nWaters = 0;
00061 nSegments = 0;
00062 nFragments = 0;
00063 nProteinFragments = 0;
00064 nNucleicFragments = 0;
00065
00066 cur_atom = 0;
00067 atomList = NULL;
00068 moleculename = NULL;
00069 lastbonderratomid=-1;
00070 bonderrorcount=0;
00071 datasetflags=NODATA;
00072 qm_data = NULL;
00073
00074 radii_minmax_need_update = 1;
00075 radii_min = 0.0f;
00076 radii_max = 0.0f;
00077
00078 need_find_bonds = 0;
00079 }
00080
00081
00083
00084 BaseMolecule::~BaseMolecule(void) {
00085 int i;
00086
00087 #if 0
00088
00089
00090 smallringList.clear();
00091 smallringLinkages.clear();
00092 #endif
00093
00094
00095 delete [] atomList;
00096 for (i=0; i<residueList.num(); i++) {
00097 delete residueList[i];
00098 }
00099 for (i=0; i<nfragList.num(); i++) {
00100 delete nfragList[i];
00101 }
00102 #if defined(VMDFASTRIBBONS)
00103 for (i=0; i<nfragCPList.num(); i++) {
00104 delete [] nfragCPList[i];
00105 }
00106 #endif
00107 for (i=0; i<pfragList.num(); i++) {
00108 delete pfragList[i];
00109 }
00110 #if defined(VMDFASTRIBBONS)
00111 for (i=0; i<pfragCPList.num(); i++) {
00112 delete [] pfragCPList[i];
00113 }
00114 #endif
00115 for (i=0; i<fragList.num(); i++) {
00116 delete fragList[i];
00117 }
00118 for (i=0; i<volumeList.num(); i++) {
00119 delete volumeList[i];
00120 }
00121
00122
00123 for (i=0; i<extraflt.num(); i++) {
00124 delete [] extraflt.data(i);
00125 }
00126 for (i=0; i<extraint.num(); i++) {
00127 delete [] extraint.data(i);
00128 }
00129 for (i=0; i<extraflg.num(); i++) {
00130 delete [] extraflg.data(i);
00131 }
00132
00133 if (qm_data)
00134 delete qm_data;
00135 }
00136
00137
00139
00140
00141 int BaseMolecule::init_atoms(int n) {
00142 if (n <= 0) {
00143 msgErr << "BaseMolecule: init_atoms called with invalid number of atoms: "
00144 << n << sendmsg;
00145 return FALSE;
00146 }
00147 if (cur_atom != 0 && nAtoms != n) {
00148 msgErr << "BaseMolecule: attempt to init atoms while structure building in progress!" << sendmsg;
00149 return FALSE;
00150 }
00151
00152 if (!atomList) {
00153 int i;
00154
00155 nAtoms = n;
00156 atomList = new MolAtom[nAtoms];
00157 memset(atomList, 0, long(nAtoms)*sizeof(MolAtom));
00158
00159
00160
00161 extraflt.add_name("NULL", NULL);
00162 extraint.add_name("NULL", NULL);
00163 extraflg.add_name("NULL", NULL);
00164
00165
00166 extraflt.add_name("beta", new float[nAtoms]);
00167 extraflt.add_name("occupancy", new float[nAtoms]);
00168 extraflt.add_name("charge", new float[nAtoms]);
00169 extraflt.add_name("mass", new float[nAtoms]);
00170 extraflt.add_name("radius", new float[nAtoms]);
00171
00172
00173 extraflg.add_name("flags", new unsigned char[nAtoms]);
00174
00175
00176 for (i=0; i<extraflt.num(); i++) {
00177 void *data = extraflt.data(i);
00178 if (data != NULL)
00179 memset(data, 0, long(nAtoms)*sizeof(float));
00180 }
00181
00182
00183 for (i=0; i<extraint.num(); i++) {
00184 void *data = extraint.data(i);
00185 if (data != NULL)
00186 memset(data, 0, long(nAtoms)*sizeof(int));
00187 }
00188
00189
00190 for (i=0; i<extraflg.num(); i++) {
00191 void *data = extraflg.data(i);
00192
00193
00194 if (data != NULL)
00195 memset(data, 0, long(nAtoms)*sizeof(unsigned char));
00196 }
00197
00198 return TRUE;
00199 }
00200 if (n != nAtoms) {
00201 msgErr << "The number of atoms in this molecule has already been assigned."
00202 << sendmsg;
00203 return FALSE;
00204 }
00205 return TRUE;
00206 }
00207
00208
00209
00210 int BaseMolecule::add_atoms(int addatomcount,
00211 const char *name, const char *atomtype,
00212 int atomicnumber, const char *resname, int resid,
00213 const char *chain, const char *segname,
00214 const char *insertion, const char *altloc) {
00215 if (addatomcount < 1) {
00216 msgErr << "BaseMolecule: Cannot add negative atom count!" << sendmsg;
00217 return -1;
00218 }
00219
00220 int newtotalcount = cur_atom + addatomcount;
00221 if (newtotalcount > nAtoms) {
00222 msgErr << "BaseMolecule: Cannot add more atoms to molecule!" << sendmsg;
00223 return -1;
00224 }
00225
00226 if (!atomList || cur_atom >= nAtoms) {
00227 msgErr << "BaseMolecule: Cannot add new atom; currently " << nAtoms;
00228 msgErr << " atoms in structure." << sendmsg;
00229 return -1;
00230 }
00231
00232
00233 int nameindex = atomNames.add_name(name, atomNames.num());
00234 int typeindex = atomTypes.add_name(atomtype, atomTypes.num());
00235 int resnameindex = resNames.add_name(resname, resNames.num());
00236 int segnameindex = segNames.add_name(segname, segNames.num());
00237 int altlocindex = altlocNames.add_name(altloc, altlocNames.num());
00238
00239
00240 int chainindex = -1;
00241 if (!chain || ! (*chain) || *chain == ' ')
00242 chainindex = chainNames.add_name("X", chainNames.num());
00243 else
00244 chainindex = chainNames.add_name(chain, chainNames.num());
00245
00246
00247 MolAtom *newatom = atom(cur_atom);
00248 newatom->init(cur_atom, resid, insertion);
00249
00250
00251 newatom->nameindex = nameindex;
00252 newatom->typeindex = typeindex;
00253 newatom->atomicnumber = atomicnumber;
00254 newatom->resnameindex = resnameindex;
00255 newatom->segnameindex = segnameindex;
00256 newatom->altlocindex = altlocindex;
00257 newatom->chainindex = chainindex;
00258
00259
00260
00261 if (newatom->nameindex != nameindex ||
00262 newatom->typeindex != typeindex ||
00263 newatom->atomicnumber != atomicnumber ||
00264 newatom->resnameindex != resnameindex ||
00265 newatom->segnameindex != segnameindex ||
00266 newatom->altlocindex != altlocindex ||
00267 newatom->chainindex != chainindex) {
00268 msgErr << "BaseMolecule: Cannot add atom; namelist index value too large." << sendmsg;
00269 msgErr << "Recompile VMD with larger index types." << sendmsg;
00270 msgErr << "Atom namelist index values at time of overflow:" << sendmsg;
00271 msgErr << " nameindex: " << nameindex << sendmsg;;
00272 msgErr << " typeindex: " << typeindex << sendmsg;;
00273 msgErr << " resnameindex: " << resnameindex << sendmsg;;
00274 msgErr << " segnameindex: " << segnameindex << sendmsg;;
00275 msgErr << " altlocindex: " << altlocindex << sendmsg;;
00276 msgErr << " chainindex: " << chainindex << sendmsg;
00277 return -1;
00278 }
00279
00280 cur_atom++;
00281
00282
00283
00284
00285 while (cur_atom < newtotalcount) {
00286 newatom = atom(cur_atom);
00287 newatom->init(cur_atom, resid, insertion);
00288
00289 newatom->nameindex = nameindex;
00290 newatom->typeindex = typeindex;
00291 newatom->atomicnumber = atomicnumber;
00292 newatom->resnameindex = resnameindex;
00293 newatom->segnameindex = segnameindex;
00294 newatom->altlocindex = altlocindex;
00295 newatom->chainindex = chainindex;
00296
00297 cur_atom++;
00298 }
00299
00300 return cur_atom;
00301 }
00302
00303
00304
00305 int BaseMolecule::add_bond(int a, int b, float bondorder,
00306 int bondtype, int backbonetype) {
00307 if (!nAtoms || a >= nAtoms || b >= nAtoms) {
00308 msgErr << "BaseMolecule: Atoms must be added before bonds." << sendmsg;
00309 return (-1);
00310 }
00311
00312 if (a == b) {
00313 msgErr << "BaseMolecule: Cannot bond atom " <<a<< " to itself." << sendmsg;
00314 return (-1);
00315 }
00316
00317
00318 if (atom(a)->add_bond(b, backbonetype)) {
00319 if (bonderrorcount < MAXBONDERRORS) {
00320 if (lastbonderratomid != a) {
00321 msgErr << "MolAtom " << a << ": Exceeded maximum number of bonds ("
00322 << atom(a)->bonds << ")." << sendmsg;
00323 lastbonderratomid=a;
00324 bonderrorcount++;
00325 }
00326 } else if (bonderrorcount == MAXBONDERRORS) {
00327 msgErr << "BaseMolecule: Excessive bonding errors encountered, perhaps atom coordinates are in the wrong units?" << sendmsg;
00328 msgErr << "BaseMolecule: Silencing bonding error messages." << sendmsg;
00329 bonderrorcount++;
00330 }
00331 return (-1);
00332 }
00333
00334 if (atom(b)->add_bond(a, backbonetype)) {
00335 if (bonderrorcount < MAXBONDERRORS) {
00336 if (lastbonderratomid != b) {
00337 msgErr << "MolAtom " << b << ": Exceeded maximum number of bonds ("
00338 << atom(b)->bonds << ")." << sendmsg;
00339 lastbonderratomid=b;
00340 bonderrorcount++;
00341 }
00342 } else if (bonderrorcount == MAXBONDERRORS) {
00343 msgErr << "BaseMolecule: Excessive bonding errors encountered, perhaps atom coordinates are in the wrong units?" << sendmsg;
00344 msgErr << "BaseMolecule: Silencing bonding error messages." << sendmsg;
00345 bonderrorcount++;
00346 }
00347 return (-1);
00348 }
00349
00350
00351 setbondorder(a, atom(a)->bonds-1, bondorder);
00352 setbondorder(b, atom(b)->bonds-1, bondorder);
00353
00354 setbondtype(a, atom(a)->bonds-1, bondtype);
00355 setbondtype(b, atom(b)->bonds-1, bondtype);
00356
00357 return 0;
00358 }
00359
00360
00361
00362
00363 int BaseMolecule::add_bond_dupcheck(int a, int b, float bondorder, int bondtype) {
00364 int i;
00365
00366 if (!nAtoms || a >= nAtoms || b >= nAtoms) {
00367 msgErr << "BaseMolecule: Atoms must be added before bonds." << sendmsg;
00368 return (-1);
00369 }
00370
00371 MolAtom *atm = atom(a);
00372 int nbonds = atm->bonds;
00373 const int *bonds = &atm->bondTo[0];
00374 for (i=0; i<nbonds; i++) {
00375 if (bonds[i] == b) {
00376 return 0;
00377 }
00378 }
00379 add_bond(a, b, bondorder, bondtype);
00380
00381 return 0;
00382 }
00383
00384 int BaseMolecule::add_angle(int a, int b, int c, int type) {
00385 int i,n;
00386
00387 if (a > c) { i = a; a = c; c = i; }
00388
00389 angles.append3(a, b, c);
00390
00391 n = num_angles()-1;
00392 set_angletype(n, type);
00393 return n;
00394 }
00395
00396
00397 int BaseMolecule::set_angletype(int nangle, int type) {
00398
00399
00400 if ((type < 0) || (nangle >= num_angles()))
00401 return -1;
00402
00403
00404 if (angleTypes.num() <= nangle) {
00405 set_dataset_flag(BaseMolecule::ANGLETYPES);
00406 int addcnt = num_angles() - angleTypes.num();
00407 if (addcnt > 0)
00408 angleTypes.appendN(-1, addcnt);
00409 }
00410
00411 angleTypes[nangle] = type;
00412 return type;
00413 }
00414
00415 int BaseMolecule::get_angletype(int nangle) {
00416 if ((nangle < 0) || (nangle >= angleTypes.num()))
00417 return -1;
00418
00419 return angleTypes[nangle];
00420 }
00421
00422
00423 int BaseMolecule::add_dihedral(int a, int b, int c, int d, int type) {
00424 int i, j, n;
00425
00426 if (b > c) { i = a; j = b ; a = d ; b = c; d = i; c = j; }
00427
00428 dihedrals.append4(a, b, c, d);
00429
00430 n = num_dihedrals()-1;
00431 set_dihedraltype(n, type);
00432 return n;
00433 }
00434
00435
00436 int BaseMolecule::set_dihedraltype(int ndihedral, int type) {
00437
00438
00439 if ((type < 0) || (ndihedral >= num_dihedrals()))
00440 return -1;
00441
00442
00443 if (dihedralTypes.num() <= ndihedral) {
00444 set_dataset_flag(BaseMolecule::ANGLETYPES);
00445 int addcnt = num_dihedrals() - dihedralTypes.num();
00446 if (addcnt > 0)
00447 dihedralTypes.appendN(-1, addcnt);
00448 }
00449
00450 dihedralTypes[ndihedral] = type;
00451 return type;
00452 }
00453
00454 int BaseMolecule::get_dihedraltype(int ndihedral) {
00455 if ((ndihedral < 0) || (ndihedral >= dihedralTypes.num()))
00456 return -1;
00457
00458 return dihedralTypes[ndihedral];
00459 }
00460
00461 int BaseMolecule::add_improper(int a, int b, int c, int d, int type) {
00462 int i, j, n;
00463
00464 if (b > c) { i = a; j = b ; a = d ; b = c; d = i; c = j; }
00465
00466 impropers.append4(a, b, c, d);
00467
00468 n = num_impropers()-1;
00469 set_impropertype(n, type);
00470 return n;
00471 }
00472
00473
00474 int BaseMolecule::set_impropertype(int nimproper, int type) {
00475
00476
00477 if ((type < 0) || (nimproper >= num_impropers()))
00478 return -1;
00479
00480
00481 if (improperTypes.num() <= nimproper) {
00482 set_dataset_flag(BaseMolecule::ANGLETYPES);
00483 int addcnt = num_impropers() - improperTypes.num();
00484 if (addcnt > 0)
00485 improperTypes.appendN(-1, addcnt);
00486 }
00487
00488 improperTypes[nimproper] = type;
00489 return type;
00490 }
00491
00492 int BaseMolecule::get_impropertype(int nimproper) {
00493 if ((nimproper < 0) || (nimproper >= improperTypes.num()))
00494 return -1;
00495
00496 return improperTypes[nimproper];
00497 }
00498
00500
00501 void BaseMolecule::setbondorder(int atom, int bond, float order) {
00502 float *bondOrders = extraflt.data("bondorders");
00503
00504
00505 if (bondOrders == NULL) {
00506 if (order != 1) {
00507 int i;
00508 extraflt.add_name("bondorders", new float[nAtoms*MAXATOMBONDS]);
00509 bondOrders = extraflt.data("bondorders");
00510 for (i=0; i<nAtoms*MAXATOMBONDS; i++)
00511 bondOrders[i] = 1.0f;
00512
00513 bondOrders[atom * MAXATOMBONDS + bond] = order;
00514 }
00515 return;
00516 }
00517
00518 bondOrders[atom * MAXATOMBONDS + bond] = order;
00519 }
00520
00521 float BaseMolecule::getbondorder(int atom, int bond) {
00522 float *bondOrders = extraflt.data("bondorders");
00523
00524
00525 if (bondOrders == NULL) {
00526 return 1;
00527 }
00528
00529 return bondOrders[atom * MAXATOMBONDS + bond];
00530 }
00531
00532
00533 void BaseMolecule::setbondtype(int atom, int bond, int type) {
00534 int *bondTypes = extraint.data("bondtypes");
00535
00536
00537 if (bondTypes == NULL) {
00538 if (type != -1) {
00539 int i;
00540 extraint.add_name("bondtypes", new int[nAtoms*MAXATOMBONDS]);
00541 bondTypes = extraint.data("bondtypes");
00542 for (i=0; i<nAtoms*MAXATOMBONDS; i++)
00543 bondTypes[i] = -1;
00544
00545 bondTypes[atom * MAXATOMBONDS + bond] = type;
00546 }
00547 return;
00548 }
00549
00550 bondTypes[atom * MAXATOMBONDS + bond] = type;
00551 }
00552
00553 int BaseMolecule::getbondtype(int atom, int bond) {
00554 int *bondTypes = extraint.data("bondtypes");
00555
00556
00557 if (bondTypes == NULL) {
00558 return -1;
00559 }
00560
00561 return bondTypes[atom * MAXATOMBONDS + bond];
00562 }
00563
00564
00565
00566 Residue *BaseMolecule::residue(int n) {
00567 return residueList[n];
00568 }
00569
00570
00571
00572 Fragment *BaseMolecule::fragment(int n) {
00573 return fragList[n];
00574 }
00575
00576
00577
00578
00579 Residue *BaseMolecule::atom_residue(int n) {
00580 MolAtom *atm = atom(n);
00581 if(atm->uniq_resid < 0)
00582 return NULL;
00583 else
00584 return residue(atm->uniq_resid);
00585 }
00586
00587
00588
00589
00590 Fragment *BaseMolecule::atom_fragment(int n) {
00591 MolAtom *atm = atom(n);
00592 int frag = residue(atm->uniq_resid)->fragment;
00593 if(frag < 0)
00594 return NULL;
00595 else
00596 return fragment(frag);
00597 }
00598
00599
00600 float BaseMolecule::default_radius(const char *nm) {
00601 float val = 1.5;
00602
00603
00604 while (*nm && isdigit(*nm))
00605 nm++;
00606
00607 if (*nm != '\0') {
00608 switch(toupper(nm[0])) {
00609
00610
00611 case 'H': val = 1.00f; break;
00612 case 'C': val = 1.50f; break;
00613 case 'N': val = 1.40f; break;
00614 case 'O': val = 1.30f; break;
00615 case 'F': val = 1.20f; break;
00616 case 'S': val = 1.90f; break;
00617 }
00618 }
00619
00620 return val;
00621 }
00622
00623
00624
00625 float BaseMolecule::default_mass(const char *nm) {
00626 float val = 12.0;
00627
00628
00629 while (*nm && isdigit(*nm))
00630 nm++;
00631
00632 if (*nm != '\0') {
00633 char c0 = toupper(nm[0]);
00634 char c1 = toupper(nm[1]);
00635 switch(c0) {
00636 case 'H': val = 1.00800f; break;
00637
00638 case 'C':
00639 if (c1 == 'L')
00640 val = 35.453f;
00641 else
00642 val = 12.011f;
00643 break;
00644
00645 case 'M':
00646 if (c1 == 'G')
00647 val = 24.3050f;
00648 break;
00649
00650 case 'N':
00651 if (c1 == 'A')
00652 val = 22.98977f;
00653 else
00654 val = 14.00700f;
00655 break;
00656
00657 case 'O': val = 15.99900f; break;
00658
00659 case 'F':
00660 if (c1 == 'E')
00661 val = 55.84700f;
00662 else
00663 val = 18.998f;
00664 break;
00665
00666 case 'B':
00667 if (c1 == 'R')
00668 val = 79.9040f;
00669 break;
00670
00671 case 'Z':
00672 if (c1 == 'N')
00673 val = 65.3700f;
00674 break;
00675
00676 case 'I': val = 126.90447f; break;
00677 case 'K': val = 39.09830f; break;
00678 case 'P': val = 30.97376f; break;
00679 case 'S': val = 32.06000f; break;
00680 }
00681 }
00682
00683 return val;
00684 }
00685
00686
00687 float BaseMolecule::default_charge(const char *) {
00688
00689
00690
00691 return 0.0f;
00692 }
00693
00694
00695
00696 int BaseMolecule::count_bonds(void) {
00697 int i, j;
00698 int count=0;
00699
00700 for (i=0; i<nAtoms; i++) {
00701 int nbonds = atomList[i].bonds;
00702 const int *bonds = &atomList[i].bondTo[0];
00703
00704 for (j=0; j<nbonds; j++) {
00705 if (bonds[j] > i)
00706 count++;
00707 }
00708 }
00709
00710 return count;
00711 }
00712
00713
00714 void BaseMolecule::clear_bonds(void) {
00715 int i;
00716 for (i=0; i<nAtoms; i++)
00717 atomList[i].bonds = 0;
00718 }
00719
00720
00721
00722
00723
00724
00725
00726 void BaseMolecule::analyze(void) {
00727 need_find_bonds = 0;
00728
00729
00730
00731
00732
00733 if (nAtoms < 1)
00734 return;
00735
00736 wkf_timerhandle tm = wkf_timer_create();
00737 wkf_timer_start(tm);
00738
00739
00740 msgInfo << "Analyzing structure ..." << sendmsg;
00741 msgInfo << " Atoms: " << nAtoms << sendmsg;
00742
00743
00744 int total_bondcount = count_bonds();
00745 double bondtime = wkf_timer_timenow(tm);
00746
00747 msgInfo << " Bonds: " << total_bondcount << sendmsg;
00748 msgInfo << " Angles: " << num_angles()
00749 << " Dihedrals: " << num_dihedrals()
00750 << " Impropers: " << num_impropers()
00751 << " Cross-terms: " << num_cterms()
00752 << sendmsg;
00753
00754 msgInfo << " Bondtypes: " << bondTypeNames.num()
00755 << " Angletypes: " << angleTypeNames.num()
00756 << " Dihedraltypes: " << dihedralTypeNames.num()
00757 << " Impropertypes: " << improperTypeNames.num()
00758 << sendmsg;
00759
00760
00761 residueList.clear();
00762 fragList.clear();
00763 pfragList.clear();
00764 pfragCyclic.clear();
00765 #if defined(VMDFASTRIBBONS)
00766 pfragCPList.clear();
00767 #endif
00768 nfragList.clear();
00769 nfragCyclic.clear();
00770 #if defined(VMDFASTRIBBONS)
00771 nfragCPList.clear();
00772 #endif
00773
00774
00775 find_backbone();
00776 double backbonetime = wkf_timer_timenow(tm);
00777
00778
00779
00780 nResidues = find_residues();
00781 double findrestime = wkf_timer_timenow(tm);
00782 msgInfo << " Residues: " << nResidues << sendmsg;
00783
00784 nWaters = find_waters();
00785 double findwattime = wkf_timer_timenow(tm);
00786 msgInfo << " Waters: " << nWaters << sendmsg;
00787
00788
00789 bonderrorcount=0;
00790 find_connected_residues(nResidues);
00791 double findconrestime = wkf_timer_timenow(tm);
00792
00793 nSegments = find_segments();
00794 msgInfo << " Segments: " << nSegments << sendmsg;
00795
00796 nFragments = find_fragments();
00797 msgInfo << " Fragments: " << nFragments;
00798
00799 nProteinFragments = pfragList.num();
00800 msgInfo << " Protein: " << nProteinFragments;
00801
00802 nNucleicFragments = nfragList.num();
00803 msgInfo << " Nucleic: " << nNucleicFragments << sendmsg;
00804 double findfragstime = wkf_timer_timenow(tm);
00805
00806
00807
00808
00809
00810
00811 int i;
00812 for (i=0; i<nAtoms; i++) {
00813 MolAtom *a = atom(i);
00814 if ((a->residueType != RESNUCLEIC) && (a->residueType != RESPROTEIN))
00815 a->atomType = ATOMNORMAL;
00816 }
00817 double fixlipidtime = wkf_timer_timenow(tm);
00818
00819
00820
00821
00822
00823
00824 for (i=0; i<nAtoms; i++) {
00825 MolAtom *a = atom(i);
00826 const char *aname = atomNames.name(a->nameindex);
00827 if (aname != NULL && IS_HYDROGEN(aname))
00828 a->atomType = ATOMHYDROGEN;
00829 }
00830 double findhydrogentime = wkf_timer_timenow(tm);
00831
00832 #if defined(VMDFASTRIBBONS)
00833 calculate_ribbon_controlpoints();
00834 #endif
00835 double calcribbontime = wkf_timer_timenow(tm);
00836
00837 #if 1
00838 if (getenv("VMDBASEMOLECULETIMING") != NULL) {
00839 printf("BaseMolecule::analyze() runtime breakdown:\n");
00840 printf(" %.2f bonds\n", bondtime);
00841 printf(" %.2f backbone\n", backbonetime - bondtime);
00842 printf(" %.2f findres\n", findrestime - backbonetime);
00843 printf(" %.2f findwat\n", findwattime - findrestime);
00844 printf(" %.2f findconres\n", findconrestime - findwattime);
00845 printf(" %.2f findfrags\n", findfragstime - findconrestime);
00846 printf(" %.2f fixlipds\n", fixlipidtime - findfragstime);
00847 printf(" %.2f findH\n", findhydrogentime - fixlipidtime);
00848 printf(" %.2f calcribbons\n", calcribbontime - findhydrogentime);
00849 }
00850 #endif
00851
00852 wkf_timer_destroy(tm);
00853 }
00854
00855
00857 int BaseMolecule::find_backbone(void) {
00858 #if 1
00859 const char * protnames[] = { "CA", "C", "O", "N", NULL };
00860 const char * prottermnames[] = { "OT1", "OT2", "OXT", "O1", "O2", NULL };
00861 const char * nucnames[] = { "P", "O1P", "O2P", "OP1", "OP2",
00862 "C3*", "C3'", "O3*", "O3'", "C4*", "C4'",
00863 "C5*", "C5'", "O5*", "O5'", NULL };
00864 #if 0
00865
00866 const char * nucnames2[] = { "C1*", "C1'", "C2*", "C2'",
00867 "O2*", "O2'", "O4*", "O4'", NULL };
00868 #endif
00869 const char *nuctermnames[] = { "H5T", "H3T", NULL };
00870
00871 ResizeArray<int> prottypecodes;
00872 ResizeArray<int> prottermtypecodes;
00873 ResizeArray<int> nuctypecodes;
00874 ResizeArray<int> nuctermtypecodes;
00875 const char ** str;
00876 int tc, i, j, k;
00877
00878
00879 for (str=protnames; *str!=NULL; str++) {
00880 if ((tc = atomNames.typecode((char *) *str)) >= 0)
00881 prottypecodes.append(tc);
00882 }
00883 for (str=prottermnames; *str!=NULL; str++) {
00884 if ((tc = atomNames.typecode((char *) *str)) >= 0)
00885 prottermtypecodes.append(tc);
00886 }
00887
00888
00889 for (str=nucnames; *str!=NULL; str++) {
00890 if ((tc = atomNames.typecode((char *) *str)) >= 0)
00891 nuctypecodes.append(tc);
00892 }
00893 for (str=nuctermnames; *str!=NULL; str++) {
00894 if ((tc = atomNames.typecode((char *) *str)) >= 0)
00895 nuctermtypecodes.append(tc);
00896 }
00897
00898 int numprotcodes = prottypecodes.num();
00899 int numprottermcodes = prottermtypecodes.num();
00900 int numnuccodes = nuctypecodes.num();
00901 int numnuctermcodes = nuctermtypecodes.num();
00902
00903 int *protcodes = &prottypecodes[0];
00904 int *prottermcodes = &prottermtypecodes[0];
00905 int *nuccodes = &nuctypecodes[0];
00906 int *nuctermcodes = &nuctermtypecodes[0];
00907
00908
00909
00910 if ((numprotcodes + numprottermcodes +
00911 numnuccodes + numnuctermcodes) == 0) {
00912
00913 for (i=0; i<nAtoms; i++) {
00914 MolAtom *a = atom(i);
00915 a->atomType = ATOMNORMAL;
00916 }
00917 } else {
00918
00919 for (i=0; i<nAtoms; i++) {
00920 MolAtom *a = atom(i);
00921
00922
00923 a->atomType = ATOMNORMAL;
00924
00925
00926 for (j=0; j < numprotcodes; j++) {
00927 if (a->nameindex == protcodes[j]) {
00928 a->atomType = ATOMPROTEINBACK;
00929 break;
00930 }
00931 }
00932
00933
00934 for (j=0; j < numprottermcodes; j++) {
00935 if (a->nameindex == prottermcodes[j]) {
00936 for (k=0; k < a->bonds; k++) {
00937 if (atom(a->bondTo[k])->atomType == ATOMPROTEINBACK) {
00938 a->atomType = ATOMPROTEINBACK;
00939 break;
00940 }
00941 }
00942 }
00943 }
00944
00945
00946 if (!(a->atomType)) {
00947 for (j=0; j < numnuccodes; j++) {
00948 if (a->nameindex == nuccodes[j]) {
00949 a->atomType = ATOMNUCLEICBACK;
00950 break;
00951 }
00952 }
00953 }
00954
00955
00956 for (j=0; j < numnuctermcodes; j++) {
00957 if (a->nameindex == nuctermcodes[j]) {
00958 for (k=0; k < a->bonds; k++) {
00959 if (atom(a->bondTo[k])->atomType == ATOMNUCLEICBACK) {
00960 a->atomType = ATOMNUCLEICBACK;
00961 break;
00962 }
00963 }
00964 }
00965 }
00966 }
00967 }
00968 #else
00969 int i, j, k;
00970
00971
00972 int protypes[4];
00973 protypes[0] = atomNames.typecode((char *) "CA");
00974 protypes[1] = atomNames.typecode((char *) "C");
00975 protypes[2] = atomNames.typecode((char *) "O");
00976 protypes[3] = atomNames.typecode((char *) "N");
00977
00978
00979
00980 int termtypes[5];
00981 termtypes[0] = atomNames.typecode((char *) "OT1");
00982 termtypes[1] = atomNames.typecode((char *) "OT2");
00983 termtypes[2] = atomNames.typecode((char *) "OXT");
00984 termtypes[3] = atomNames.typecode((char *) "O1");
00985 termtypes[4] = atomNames.typecode((char *) "O2");
00986
00987
00988
00989
00990
00991 int nuctypes[15];
00992 nuctypes[ 0] = atomNames.typecode((char *) "P");
00993 nuctypes[ 1] = atomNames.typecode((char *) "O1P");
00994 nuctypes[ 2] = atomNames.typecode((char *) "O2P");
00995 nuctypes[ 3] = atomNames.typecode((char *) "OP1");
00996 nuctypes[ 4] = atomNames.typecode((char *) "OP2");
00997 nuctypes[ 5] = atomNames.typecode((char *) "C3*");
00998 nuctypes[ 6] = atomNames.typecode((char *) "C3'");
00999 nuctypes[ 7] = atomNames.typecode((char *) "O3*");
01000 nuctypes[ 8] = atomNames.typecode((char *) "O3'");
01001 nuctypes[ 9] = atomNames.typecode((char *) "C4*");
01002 nuctypes[10] = atomNames.typecode((char *) "C4'");
01003 nuctypes[11] = atomNames.typecode((char *) "C5*");
01004 nuctypes[12] = atomNames.typecode((char *) "C5'");
01005 nuctypes[13] = atomNames.typecode((char *) "O5*");
01006 nuctypes[14] = atomNames.typecode((char *) "O5'");
01007
01008 #if 0
01009
01010 nuctypes[ ] = atomNames.typecode((char *) "C1*");
01011 nuctypes[ ] = atomNames.typecode((char *) "C1'");
01012 nuctypes[ ] = atomNames.typecode((char *) "C2*");
01013 nuctypes[ ] = atomNames.typecode((char *) "C2'");
01014 nuctypes[ ] = atomNames.typecode((char *) "O2*");
01015 nuctypes[ ] = atomNames.typecode((char *) "O2'");
01016 nuctypes[ ] = atomNames.typecode((char *) "O4*");
01017 nuctypes[ ] = atomNames.typecode((char *) "O4'");
01018 #endif
01019
01020
01021 int nuctermtypes[2];
01022 nuctermtypes[0] = atomNames.typecode((char *) "H5T");
01023 nuctermtypes[1] = atomNames.typecode((char *) "H3T");
01024
01025
01026
01027 for (i=0; i<nAtoms; i++) {
01028 MolAtom *a = atom(i);
01029
01030
01031 a->atomType = ATOMNORMAL;
01032
01033
01034 for (j=0; j < 4; j++) {
01035 if (a->nameindex == protypes[j]) {
01036 a->atomType = ATOMPROTEINBACK;
01037 break;
01038 }
01039 }
01040
01041
01042 for (j=0; j < 4; j++) {
01043 if (a->nameindex == termtypes[j]) {
01044 for (k=0; k < a->bonds; k++) {
01045 if (atom(a->bondTo[k])->atomType == ATOMPROTEINBACK) {
01046 a->atomType = ATOMPROTEINBACK;
01047 break;
01048 }
01049 }
01050 }
01051 }
01052
01053
01054 if (!(a->atomType)) {
01055 for (j=0; j < 15; j++) {
01056 if (a->nameindex == nuctypes[j]) {
01057 a->atomType = ATOMNUCLEICBACK;
01058 break;
01059 }
01060 }
01061 }
01062
01063
01064 for (j=0; j < 2; j++) {
01065 if (a->nameindex == nuctermtypes[j]) {
01066 for (k=0; k < a->bonds; k++) {
01067 if (atom(a->bondTo[k])->atomType == ATOMNUCLEICBACK) {
01068 a->atomType = ATOMNUCLEICBACK;
01069 break;
01070 }
01071 }
01072 }
01073 }
01074 }
01075 #endif
01076
01077 return 0;
01078 }
01079
01080
01081
01082
01083
01084
01085
01086
01087
01088 int BaseMolecule::find_waters(void) {
01089 #if 1
01090 const char *watresnames[] = { "H2O", "HHO", "OHH", "HOH", "OH2",
01091 "SOL", "WAT",
01092 "TIP", "TIP2", "TIP3", "TIP4",
01093 "SPC", NULL };
01094
01095
01096
01097
01098
01099
01100
01101
01102
01103
01104
01105 ResizeArray<int> watrestypecodes;
01106 const char ** str;
01107 int tc, i, j;
01108
01109 for (str=watresnames; *str!=NULL; str++) {
01110 if ((tc = resNames.typecode((char *) *str)) >= 0)
01111 watrestypecodes.append(tc);
01112 }
01113 int numwatrescodes = watrestypecodes.num();
01114 int *watrescodes = &watrestypecodes[0];
01115
01116
01117 if (numwatrescodes == 0) {
01118 return 0;
01119 } else {
01120 for (i=0; i<nAtoms; i++) {
01121 MolAtom *a = atom(i);
01122 if (a->residueType == RESNOTHING) {
01123 for (j=0; j<numwatrescodes; j++) {
01124 if (a->resnameindex == watrescodes[j]) {
01125 a->residueType = RESWATERS;
01126 break;
01127 }
01128 }
01129 }
01130 }
01131 }
01132 #else
01133 int i, j;
01134 int watertypes[12];
01135 watertypes[0] = resNames.typecode((char *) "H2O");
01136 watertypes[1] = resNames.typecode((char *) "HH0");
01137 watertypes[2] = resNames.typecode((char *) "OHH");
01138 watertypes[3] = resNames.typecode((char *) "HOH");
01139 watertypes[4] = resNames.typecode((char *) "OH2");
01140 watertypes[5] = resNames.typecode((char *) "SOL");
01141 watertypes[6] = resNames.typecode((char *) "WAT");
01142 watertypes[7] = resNames.typecode((char *) "TIP");
01143 watertypes[8] = resNames.typecode((char *) "TIP2");
01144 watertypes[9] = resNames.typecode((char *) "TIP3");
01145 watertypes[10] = resNames.typecode((char *) "TIP4");
01146
01147
01148
01149
01150
01151
01152
01153
01154
01155
01156 watertypes[11] = resNames.typecode((char *) "SPC");
01157
01158
01159
01160
01161
01162 int waterresnameexists=0;
01163 for (j=0; j<12; j++) {
01164 if (watertypes[j] != -1) {
01165 waterresnameexists=1;
01166 }
01167 }
01168 if (!waterresnameexists) {
01169 return 0;
01170 }
01171
01172 for (i=0; i<nAtoms; i++) {
01173 MolAtom *a = atom(i);
01174 if (a->residueType == RESNOTHING) {
01175 for (j=0; j<12; j++) {
01176 if (watertypes[j] == a->resnameindex) {
01177 a->residueType = RESWATERS;
01178 break;
01179 }
01180 }
01181 }
01182 }
01183 #endif
01184
01185 int count = find_connected_waters2();
01186
01187 return count;
01188 }
01189
01190
01191
01192
01193
01194 void BaseMolecule::find_connected_waters(int i, char *tmp) {
01195 MolAtom *a = atom(i);
01196 int j;
01197 if (a->residueType == RESWATERS && !tmp[i]) {
01198 tmp[i] = TRUE;
01199 for (j=0; j<a->bonds; j++) {
01200 find_connected_waters(a->bondTo[j], tmp);
01201 }
01202 }
01203 }
01204
01205
01206
01207
01208 int BaseMolecule::find_connected_waters2(void) {
01209 MolAtom *a;
01210 int count, i;
01211 IntStackHandle s;
01212
01213
01214 char *tmp = (char *) calloc(1, nAtoms * sizeof(char));
01215
01216 s = intstack_create(nAtoms);
01217
01218 for (count=0, i=0; i<nAtoms; i++) {
01219 if (atom(i)->residueType == RESWATERS && !tmp[i]) {
01220 int nextatom;
01221
01222 count++;
01223 intstack_push(s, i);
01224
01225
01226 while (!intstack_pop(s, &nextatom)) {
01227 int j;
01228
01229 a = atom(nextatom);
01230 tmp[nextatom] = TRUE;
01231
01232 for (j=a->bonds - 1; j>=0; j--) {
01233 int bi = a->bondTo[j];
01234 MolAtom *b = atom(bi);
01235 if (b->residueType == RESWATERS && !tmp[bi])
01236 intstack_push(s, bi);
01237 }
01238 }
01239 }
01240 }
01241
01242 intstack_destroy(s);
01243 free(tmp);
01244
01245 return count;
01246 }
01247
01248
01249
01250
01251
01252
01253
01254 int BaseMolecule::make_uniq_resids(int *flgs) {
01255 int i;
01256 int num_residues = 0;
01257 IntStackHandle s = intstack_create(nAtoms);
01258
01259 for (i=0; i<nAtoms; i++) {
01260 if (!flgs[i]) {
01261
01262
01263 MolAtom *a = atom(i);
01264 int resid = a->resid;
01265
01266 char insertioncode = a->insertionstr[0];
01267
01268 intstack_push(s, i);
01269 int nextatom;
01270
01271
01272 while (!intstack_pop(s, &nextatom)) {
01273 MolAtom *a = atom(nextatom);
01274 a->uniq_resid = num_residues;
01275 flgs[nextatom] = TRUE;
01276
01277 int j;
01278 for (j=a->bonds - 1; j>=0; j--) {
01279 int bi = a->bondTo[j];
01280 if (flgs[bi] == 0) {
01281 MolAtom *b = atom(bi);
01282 if (a->chainindex == b->chainindex &&
01283 a->segnameindex == b->segnameindex &&
01284 b->resid == resid && b->insertionstr[0] == insertioncode)
01285
01286 intstack_push(s, bi);
01287 }
01288 }
01289 }
01290
01291 num_residues++;
01292 }
01293 }
01294
01295 intstack_destroy(s);
01296
01297 return num_residues;
01298 }
01299
01300
01301
01302
01303
01304 int BaseMolecule::find_connected_backbone(IntStackHandle s, int backbone,
01305 int atomidx, int residueid, int tmpid, int *flgs) {
01306 if (flgs[atomidx] != 0)
01307 return 0;
01308
01309 MolAtom *x = atom(atomidx);
01310 if (x->atomType != backbone || x->resid != residueid)
01311 return 0;
01312
01313 intstack_popall(s);
01314 intstack_push(s, atomidx);
01315 int nextatom;
01316 int count = 0;
01317
01318
01319 while (!intstack_pop(s, &nextatom)) {
01320 MolAtom *a = atom(nextatom);
01321 flgs[nextatom] = tmpid;
01322 count++;
01323
01324 int j;
01325 for (j=a->bonds - 1; j>=0; j--) {
01326 int bi = a->bondTo[j];
01327 if (flgs[bi] == 0) {
01328 MolAtom *b = atom(bi);
01329
01330
01331 if (a->chainindex != b->chainindex ||
01332 a->segnameindex != b->segnameindex)
01333 continue;
01334
01335 if (b->atomType == backbone && b->resid == residueid)
01336 intstack_push(s, bi);
01337 }
01338 }
01339 }
01340
01341 return count;
01342 }
01343
01344
01345
01346 void BaseMolecule::clean_up_connection(IntStackHandle s, int i, int tmpid, int *flgs) {
01347 if (flgs[i] != tmpid)
01348 return;
01349
01350 intstack_popall(s);
01351 intstack_push(s, i);
01352 int nextatom;
01353
01354
01355 while (!intstack_pop(s, &nextatom)) {
01356 flgs[nextatom] = 0;
01357 MolAtom *a = atom(nextatom);
01358 int j;
01359 for (j=a->bonds - 1; j>=0; j--) {
01360 int bi = a->bondTo[j];
01361 if (flgs[bi] == tmpid) {
01362 intstack_push(s, bi);
01363 }
01364 }
01365 }
01366 }
01367
01368
01369
01370
01371
01372
01373 void BaseMolecule::find_and_mark(IntStackHandle s, int n, int backbone,
01374 int restype, int *tmpid, int *flgs) {
01375 int i;
01376 int residueid;
01377
01378 intstack_popall(s);
01379 for (i=0; i<nAtoms; i++) {
01380 MolAtom *a = atom(i);
01381 if (a->atomType == backbone && flgs[i] == 0) {
01382 residueid = a->resid;
01383 if (find_connected_backbone(s, backbone, i, residueid, *tmpid, flgs) >= n) {
01384
01385 clean_up_connection(s, i, *tmpid, flgs);
01386
01387 find_connected_atoms_in_resid(s, restype, i, residueid, *tmpid, flgs);
01388
01389 (*tmpid)++;
01390 } else {
01391
01392 clean_up_connection(s, i, *tmpid, flgs);
01393 }
01394 }
01395 }
01396 }
01397
01398
01399
01400 void BaseMolecule::find_connected_atoms_in_resid(IntStackHandle s,
01401 int restype, int i, int residueid, int tmpid, int *flgs)
01402 {
01403 if (flgs[i] != 0 || atom(i)->resid != residueid)
01404 return;
01405
01406 intstack_popall(s);
01407 intstack_push(s, i);
01408 int nextatom;
01409
01410
01411 while (!intstack_pop(s, &nextatom)) {
01412 flgs[nextatom] = tmpid;
01413 MolAtom *a = atom(nextatom);
01414 a->residueType = restype;
01415
01416 int j;
01417 for (j=a->bonds - 1; j>=0; j--) {
01418 int bi = a->bondTo[j];
01419 MolAtom *b = atom(bi);
01420 if (flgs[bi] == 0 &&
01421 a->chainindex == b->chainindex &&
01422 a->segnameindex == b->segnameindex &&
01423 b->resid == residueid) {
01424 intstack_push(s, bi);
01425 }
01426 }
01427 }
01428 }
01429
01430
01431 int BaseMolecule::find_residues(void) {
01432
01433
01434 int *flgs = (int *) calloc(1, nAtoms * sizeof(int));
01435
01436
01437
01438
01439
01440 int num_residues = make_uniq_resids(flgs);
01441
01442 int back_res_count = 1;
01443 memset(flgs, 0, nAtoms * sizeof(int));
01444
01445 IntStackHandle s = intstack_create(nAtoms);
01446
01447
01448
01449
01450
01451 find_and_mark(s, 4, ATOMPROTEINBACK, RESPROTEIN, &back_res_count, flgs);
01452
01453
01454
01455
01456
01457 find_and_mark(s, 4, ATOMNUCLEICBACK, RESNUCLEIC, &back_res_count, flgs);
01458
01459 intstack_destroy(s);
01460
01461 free(flgs);
01462 return num_residues;
01463 }
01464
01465 int BaseMolecule::find_atom_in_residue(const char *name, int residue) {
01466 int nametype = atomNames.typecode(name);
01467 if (nametype < 0)
01468 return -2;
01469
01470 return find_atom_in_residue(nametype, residue);
01471 }
01472
01473
01474
01475
01476 void BaseMolecule::find_connected_residues(int num_residues) {
01477 int i, j;
01478 residueList.appendN(NULL, num_residues);
01479
01480 for (i=nAtoms-1; i>=0; i--) {
01481 MolAtom *a = atom(i);
01482 j = a->uniq_resid;
01483 if (residueList[j] == NULL) {
01484 residueList[j] = new Residue(a->resid, a->residueType);
01485 }
01486
01487 residueList[j]->add_atom(i);
01488 }
01489
01490
01491
01492
01493 int resmissingatomflag=0;
01494
01495
01496 if (num_residues > 10000000) {
01497 for (i=0; i<num_residues; i++) {
01498 Residue *res = residueList[i];
01499
01500
01501 if (res == NULL) {
01502
01503 resmissingatomflag=1;
01504 res = new Residue((int) -1, RESNOTHING);
01505 residueList[i] = res;
01506 }
01507 }
01508 } else {
01509 for (i=0; i<num_residues; i++) {
01510 Residue *res = residueList[i];
01511
01512
01513 if (res == NULL) {
01514
01515 resmissingatomflag=1;
01516 res = new Residue((int) -1, RESNOTHING);
01517 residueList[i] = res;
01518 }
01519
01520 int bondfromtype = res->residueType;
01521 int numatoms = res->atoms.num();
01522 for (j=0; j<numatoms; j++) {
01523 MolAtom *a = atom(res->atoms[j]);
01524
01525
01526 int k;
01527 for (k=0; k<a->bonds; k++) {
01528 MolAtom *b = atom(a->bondTo[k]);
01529
01530
01531 if (a->chainindex != b->chainindex ||
01532 a->segnameindex != b->segnameindex)
01533 continue;
01534
01535 if (b->uniq_resid != i) {
01536 int bondtotype = residueList[b->uniq_resid]->residueType;
01537
01538 if (bondfromtype != bondtotype) {
01539 if (i < b->uniq_resid) {
01540 msgWarn << "Unusual bond between residues: ";
01541 msgWarn << residueList[i]->resid;
01542 switch (bondfromtype) {
01543 case RESPROTEIN: msgWarn << " (protein)"; break;
01544 case RESNUCLEIC: msgWarn << " (nucleic)"; break;
01545 case RESWATERS: msgWarn << " (waters)"; break;
01546 default:
01547 case RESNOTHING: msgWarn << " (none)"; break;
01548 }
01549 msgWarn << " and ";
01550 msgWarn << residueList[b->uniq_resid]->resid;
01551 switch (bondtotype) {
01552 case RESPROTEIN: msgWarn << " (protein)"; break;
01553 case RESNUCLEIC: msgWarn << " (nucleic)"; break;
01554 case RESWATERS: msgWarn << " (waters)"; break;
01555 default:
01556 case RESNOTHING: msgWarn << " (none)"; break;
01557 }
01558 msgWarn << sendmsg;
01559 }
01560 }
01561 }
01562 }
01563 }
01564 }
01565 }
01566
01567
01568 if (resmissingatomflag) {
01569 msgErr << "Mysterious residue creation in "
01570 << "BaseMolecule::find_connected_residues." << sendmsg;
01571 }
01572 }
01573
01574
01575
01576 int BaseMolecule::find_connected_fragments(void) {
01577 int i;
01578 int count = 0;
01579
01580 char *flgs = (char *) calloc(1, residueList.num() * sizeof(char));
01581 IntStackHandle s = intstack_create(residueList.num());
01582
01583 int atomsg = atomNames.typecode((char *) "SG");
01584
01585 int nextres;
01586 for (i=0; i<residueList.num(); i++) {
01587 if (!flgs[i]) {
01588 fragList.append(new Fragment);
01589 intstack_push(s, i);
01590
01591
01592 while (!intstack_pop(s, &nextres)) {
01593 fragList[count]->append(nextres);
01594 Residue *res = residueList[nextres];
01595 res->fragment = count;
01596
01597 int numatoms = res->atoms.num();
01598 int j;
01599 for (j=0; j<numatoms; j++) {
01600 MolAtom *a = atom(res->atoms[j]);
01601
01602
01603 int k;
01604 for (k=0; k<a->bonds; k++) {
01605 MolAtom *b = atom(a->bondTo[k]);
01606 int ri = b->uniq_resid;
01607
01608
01609
01610
01611
01612 if ((ri != i) &&
01613 (flgs[ri] == 0) &&
01614 (a->chainindex == b->chainindex) &&
01615 (a->segnameindex == b->segnameindex) &&
01616 ((a->nameindex != atomsg) || (b->nameindex != atomsg))) {
01617 flgs[ri] = TRUE;
01618 intstack_push(s, ri);
01619 }
01620 }
01621 }
01622 }
01623
01624 count++;
01625 }
01626 }
01627
01628 intstack_destroy(s);
01629 free(flgs);
01630
01631 return count;
01632 }
01633
01634
01635
01636 int BaseMolecule::find_fragments(void) {
01637 int count = find_connected_fragments();
01638
01639 #if 1
01640
01641 find_subfragments(atomNames.typecode((char *) "N"),
01642 -1,
01643 -1,
01644 atomNames.typecode((char *) "C"),
01645 -1,
01646 -1,
01647 -1,
01648 RESPROTEIN, &pfragList);
01649
01650 #if 0
01651
01652 find_subfragments(atomNames.typecode((char *) "P"),
01653 atomNames.typecode((char *) "H5T"),
01654 -1,
01655 atomNames.typecode((char *) "O3'"),
01656 atomNames.typecode((char *) "O3*"),
01657 atomNames.typecode((char *) "H3T"),
01658 -1,
01659 RESNUCLEIC, &nfragList);
01660 #else
01661
01662 find_subfragments_topologically(
01663 RESNUCLEIC, &nfragList,
01664 atomNames.typecode((char *) "O3'"),
01665 atomNames.typecode((char *) "O3*"),
01666 atomNames.typecode((char *) "H3T"),
01667 -1);
01668 #endif
01669 #else
01670 find_subfragments_cyclic(&pfragList, RESPROTEIN);
01671 find_subfragments_cyclic(&nfragList, RESNUCLEIC);
01672 #endif
01673
01674
01675 find_cyclic_subfragments(&pfragList, &pfragCyclic);
01676 find_cyclic_subfragments(&nfragList, &nfragCyclic);
01677
01678 return count;
01679 }
01680
01681
01682 void BaseMolecule::find_subfragments_cyclic(ResizeArray<Fragment *> *subfragList, int restype) {
01683 int numfrags = fragList.num();
01684 int i, frag;
01685
01686
01687 for (frag=0; frag<numfrags; frag++) {
01688 int numres = fragList[frag]->num();
01689 int match=1;
01690
01691
01692 for (i=0; i<numres; i++) {
01693 int resid = (*fragList[frag])[i];
01694 if (residueList[resid]->residueType != restype) {
01695 match=0;
01696 break;
01697 }
01698 }
01699
01700
01701 if (match) {
01702 Fragment *frg = new Fragment;
01703
01704
01705 for (i=0; i<numres; i++) {
01706 int resid = (*fragList[frag])[i];
01707 frg->append(resid);
01708 }
01709
01710 subfragList->append(frg);
01711 }
01712 }
01713 }
01714
01715
01716
01717 void BaseMolecule::find_cyclic_subfragments(ResizeArray<Fragment *> *subfragList, ResizeArray<int> *subfragCyclic) {
01718 int i, j, frag;
01719 int numfrags = subfragList->num();
01720
01721
01722 for (frag=0; frag<numfrags; frag++) {
01723 int numres = (*subfragList)[frag]->num();
01724
01725
01726 if (numres < 1) {
01727
01728 subfragCyclic->append(0);
01729 continue;
01730 }
01731
01732 int startres = (*(*subfragList)[frag])[0];
01733 int endres = (*(*subfragList)[frag])[numres-1];
01734 int cyclic = 0;
01735
01736
01737 int numatoms = residueList[endres]->atoms.num();
01738 int done = 0;
01739 for (i=0; (i < numatoms) && (!done); i++) {
01740 MolAtom *a = atom(residueList[endres]->atoms[i]);
01741 int nbonds = a->bonds;
01742 for (j=0; j < nbonds; j++) {
01743 MolAtom *b = atom(a->bondTo[j]);
01744
01745 if (b->uniq_resid == startres) {
01746 cyclic=1;
01747 done=1;
01748 break;
01749 }
01750 }
01751 }
01752
01753
01754 subfragCyclic->append(cyclic);
01755 }
01756 }
01757
01758
01759
01760
01761
01762
01763 void BaseMolecule::find_connected_subfragment(int resnum, int fragnum,
01764 char *flgs, int endatom, int altendatom,
01765 int alt2endatom, int alt3endatom,
01766 int restype,
01767 ResizeArray<Fragment *> *subfragList)
01768 {
01769 if (flgs[resnum] || residueList[resnum]->residueType != restype)
01770 return;
01771 (*subfragList)[fragnum]->append(resnum);
01772 flgs[resnum] = TRUE;
01773
01774
01775 int i, j, nextres;
01776 MolAtom *a;
01777 for (i=residueList[resnum]->atoms.num() - 1; i>=0; i--) {
01778 a = atom(residueList[resnum]->atoms[i]);
01779 if (a->nameindex == endatom ||
01780 a->nameindex == altendatom ||
01781 a->nameindex == alt2endatom ||
01782 a->nameindex == alt3endatom) {
01783 for (j=a->bonds-1; j>=0; j--) {
01784
01785
01786
01787
01788
01789 if ((!(a->atomType == ATOMNORMAL && atom(a->bondTo[j])->atomType == ATOMNORMAL)) &&
01790 (nextres = atom(a->bondTo[j])->uniq_resid) != resnum &&
01791 !flgs[nextres] ) {
01792 find_connected_subfragment(nextres, fragnum, flgs, endatom,
01793 altendatom, alt2endatom, alt3endatom, restype, subfragList);
01794 return;
01795 }
01796 }
01797 }
01798 }
01799 }
01800
01801
01802
01803 void BaseMolecule::find_subfragments(int startatom,
01804 int altstartatom, int alt2startatom,
01805 int endatom, int altendatom, int alt2endatom, int alt3endatom,
01806 int restype, ResizeArray<Fragment *> *subfragList)
01807 {
01808
01809 if (startatom==-1 && altstartatom==-1 && alt2startatom==-1 &&
01810 endatom==-1 && altendatom==-1 && alt2endatom==-1 && alt3endatom==-1) {
01811 return;
01812 }
01813
01814 int i, j, k;
01815 MolAtom *a;
01816 char *flgs = new char[residueList.num()];
01817 memset(flgs, 0, residueList.num() * sizeof(char));
01818
01819
01820
01821
01822
01823 for (i=residueList.num()-1; i>=0; i--) {
01824
01825 if (!flgs[i] && residueList[i]->residueType == restype) {
01826
01827 for (j=residueList[i]->atoms.num()-1; j>=0; j--) {
01828 int satom = (a=atom(residueList[i]->atoms[j]))->nameindex;
01829 if (satom == startatom ||
01830 satom == altstartatom ||
01831 satom == alt2startatom){
01832 for (k=a->bonds-1; k>=0; k--) {
01833 MolAtom *bondto = atom(a->bondTo[k]);
01834
01835 if (bondto->uniq_resid != i && bondto->residueType == restype) {
01836 break;
01837 }
01838 }
01839
01840
01841 if (k<0) {
01842 subfragList->append(new Fragment);
01843 find_connected_subfragment(i, subfragList->num()-1, flgs,
01844 endatom, altendatom, alt2endatom, alt3endatom,
01845 restype, subfragList);
01846 }
01847 }
01848 }
01849 }
01850 }
01851
01852
01853 delete [] flgs;
01854 }
01855
01856
01857
01858 void BaseMolecule::find_subfragments_topologically(int restype,
01859 ResizeArray<Fragment *> *subfragList,
01860 int endatom, int altendatom, int alt2endatom, int alt3endatom) {
01861
01862
01863 if (endatom==-1 && altendatom==-1 && alt2endatom==-1 && alt3endatom==-1) {
01864 return;
01865 }
01866
01867 int i;
01868 char *flgs = new char[residueList.num()];
01869 memset(flgs, 0, residueList.num() * sizeof(char));
01870 int numres = residueList.num();
01871
01872
01873
01874
01875
01876 for (i=0; i<numres; i++) {
01877 Residue *res = residueList[i];
01878
01879
01880 if (!flgs[i] && res->residueType == restype) {
01881
01882
01883 int offresbondcount = 0;
01884 int j, k;
01885 int numatoms = res->atoms.num();
01886 for (j=0; j<numatoms; j++) {
01887 MolAtom *a = atom(res->atoms[j]);
01888
01889
01890 for (k=0; k<a->bonds; k++) {
01891 MolAtom *b = atom(a->bondTo[k]);
01892 if (b->uniq_resid != i &&
01893 residueList[b->uniq_resid]->residueType == restype) {
01894 offresbondcount++;
01895 }
01896 }
01897 }
01898
01899
01900 if (offresbondcount == 1) {
01901 subfragList->append(new Fragment);
01902 find_connected_subfragment(i, subfragList->num()-1, flgs,
01903 endatom, altendatom, alt2endatom, alt3endatom,
01904 restype, subfragList);
01905 }
01906 }
01907 }
01908
01909
01910 delete [] flgs;
01911 }
01912
01913
01914 #if defined(VMDFASTRIBBONS)
01915
01916
01917 void BaseMolecule::calculate_ribbon_controlpoints() {
01918 int onum, canum, frag, num, res;
01919
01920 wkf_timerhandle tm = wkf_timer_create();
01921
01922 msgInfo << "XXX Building pre-computed control point lists" << sendmsg;
01923
01924 wkf_timer_start(tm);
01925
01926
01927
01928
01929 int CAtypecode = atomNames.typecode("CA");
01930 int Otypecode = atomNames.typecode("O");
01931 int OT1typecode = atomNames.typecode("OT1");
01932
01933
01934 if (CAtypecode < 0) {
01935 msgErr << "This structure has no identifiable CA atoms,"
01936 << "ribbon and cartoon representations will not be usable."
01937 << sendmsg;
01938 return;
01939 }
01940 if ((Otypecode < 0) && (OT1typecode < 0)) {
01941 msgErr << "This structure has no identifiable Oxygen atoms,"
01942 << "ribbon and cartoon representations will not be usable."
01943 << sendmsg;
01944 return;
01945 }
01946
01947
01948
01949
01950
01951 msgInfo << "XXX Building protein control point lists" << sendmsg;
01952
01953
01954
01955 ResizeArray<int> cpind;
01956 for (frag=0; frag<pfragList.num(); frag++) {
01957 num = pfragList[frag]->num();
01958 if (num < 2) {
01959
01960 nfragCPList.append(NULL);
01961 continue;
01962 }
01963
01964
01965 res = (*pfragList[frag])[0];
01966 canum = find_atom_in_residue(CAtypecode, res);
01967 onum = find_atom_in_residue(Otypecode, res);
01968
01969 if (onum < 0 && OT1typecode >= 0) {
01970 onum = find_atom_in_residue(OT1typecode, res);
01971 }
01972 if (canum < 0 || onum < 0) {
01973
01974 msgErr << "Fragment control point calc unable to identify target atoms" << sendmsg;
01975 nfragCPList.append(NULL);
01976 continue;
01977 }
01978
01979
01980 cpind.clear();
01981
01982 int loop;
01983 for (loop=0; loop<num; loop++) {
01984 res = (*pfragList[frag])[loop];
01985
01986
01987 canum = find_atom_in_residue(CAtypecode, res);
01988
01989
01990 onum = find_atom_in_residue(Otypecode, res);
01991 if (onum < 0 && OT1typecode >= 0) {
01992 onum = find_atom_in_residue(OT1typecode, res);
01993 }
01994
01995
01996 cpind.append(canum);
01997 cpind.append(onum);
01998 }
01999
02000
02001 if (cpind.num() == 2L*num) {
02002 int *cpindices = new int[cpind.num()];
02003 memcpy(cpindices, &cpind[0], long(cpind.num()) * sizeof(int));
02004
02005
02006 nfragCPList.append(cpindices);
02007 } else {
02008 msgErr << "Unexpected failure in control point calculation" << sendmsg;
02009 nfragCPList.append(NULL);
02010 }
02011 }
02012
02013 wkf_timer_stop(tm);
02014
02015 msgInfo << "XXX Calc time for protein cplist: "
02016 << wkf_timer_time(tm) << sendmsg;
02017 msgInfo << "XXX done building protein control point lists" << sendmsg;
02018
02019
02020
02021
02022
02023 wkf_timer_destroy(tm);
02024 }
02025 #endif
02026
02027 #if defined(VMDWITHCARBS)
02028
02029
02030
02031
02032
02033
02034
02035
02036 void BaseMolecule::find_small_rings_and_links(int maxpathlength, int maxringsize) {
02037
02038 if (maxpathlength == currentMaxPathLength && maxringsize == currentMaxRingSize)
02039 return;
02040 currentMaxPathLength = maxpathlength;
02041 currentMaxRingSize = maxringsize;
02042
02043
02044 smallringList.clear();
02045 smallringLinkages.clear();
02046
02047
02048 find_small_rings(maxringsize);
02049 #if 0
02050 msgInfo << " Rings: " << smallringList.num() << sendmsg;
02051 #endif
02052
02053
02054 orientate_small_rings(maxringsize);
02055 int nOrientatedRings = 0;
02056 for (int i=0; i<smallringList.num(); i++) {
02057 if (smallringList[i]->orientated)
02058 nOrientatedRings++;
02059 }
02060 #if 0
02061 msgInfo << " Rings orientated: " << nOrientatedRings << sendmsg;
02062 #endif
02063
02064 find_orientated_small_ring_linkages(maxpathlength, maxringsize);
02065 #if 0
02066 msgInfo << " Ring Paths: " << smallringLinkages.paths.num() << sendmsg;
02067 #endif
02068 }
02069
02070
02071 int BaseMolecule::find_small_rings(int maxringsize) {
02072 int n_back_edges, n_rings;
02073 ResizeArray<int> back_edge_src, back_edge_dest;
02074
02075 n_back_edges = find_back_edges(back_edge_src, back_edge_dest);
02076 n_rings = find_small_rings_from_back_edges(maxringsize, back_edge_src, back_edge_dest);
02077
02078 #if 1
02079 if (getenv("VMDFINDSMALLRINGSDEBUG") != NULL) {
02080 int i;
02081
02082 msgInfo << " BACK EDGES: " << n_back_edges << sendmsg;
02083 for (i=0; i < n_back_edges; i++) {
02084 msgInfo << " SRC:" << back_edge_src[i] << ", DST:" << back_edge_dest[i] << sendmsg;
02085 }
02086
02087 msgInfo << " SMALL RINGS: " << n_rings << sendmsg;
02088 for (i=0; i < n_rings; i++) {
02089 msgInfo << " RING: " << *(smallringList[i]) << sendmsg;
02090 }
02091 }
02092 #endif
02093
02094 return n_rings;
02095 }
02096
02097
02098 #define INTREE_NOT -1 // not in tree
02099 #define INTREE_NOPARENT -2 // no parent
02100
02101
02102 int BaseMolecule::find_back_edges(ResizeArray<int> &back_edge_src, ResizeArray<int> &back_edge_dest) {
02103 int i;
02104 int n_back_edges = 0;
02105 int *intree_parents = new int[nAtoms];
02106 memset(intree_parents, INTREE_NOT, nAtoms * sizeof(int));
02107
02108 for (i=0; i<nAtoms; i++) {
02109 if (intree_parents[i] == INTREE_NOT) {
02110 n_back_edges += find_connected_subgraph_back_edges(i,back_edge_src,back_edge_dest,intree_parents);
02111 }
02112 }
02113
02114 delete [] intree_parents;
02115
02116 return n_back_edges;
02117 }
02118
02119
02120
02121 int BaseMolecule::find_connected_subgraph_back_edges(int atomid, ResizeArray<int> &back_edge_src, ResizeArray<int> &back_edge_dest,
02122 int *intree_parents) {
02123 int i, n_new_back_edges, cur_atom_id, child_atom_id, parent_atom_id;
02124 MolAtom *curatom;
02125 ResizeArray<int> node_stack;
02126
02127 node_stack.append(atomid);
02128 intree_parents[atomid] = INTREE_NOPARENT;
02129 n_new_back_edges = 0;
02130
02131 while (node_stack.num() > 0) {
02132 #if 1
02133 cur_atom_id = node_stack.pop();
02134 #else
02135 cur_atom_id = node_stack[node_stack.num()-1];
02136 node_stack.remove(node_stack.num()-1);
02137 #endif
02138
02139 curatom = atom(cur_atom_id);
02140 parent_atom_id = intree_parents[cur_atom_id];
02141
02142 for(i=0;i<curatom->bonds;i++) {
02143 child_atom_id = curatom->bondTo[i];
02144 if (intree_parents[child_atom_id] != INTREE_NOT) {
02145
02146 if ((child_atom_id != parent_atom_id) && (child_atom_id > cur_atom_id)) {
02147
02148
02149
02150 back_edge_src.append(cur_atom_id);
02151 back_edge_dest.append(child_atom_id);
02152 n_new_back_edges++;
02153 }
02154 } else {
02155
02156 intree_parents[child_atom_id] = cur_atom_id;
02157 node_stack.append(child_atom_id);
02158 }
02159 }
02160 }
02161
02162 return n_new_back_edges;
02163 }
02164
02165
02166 int BaseMolecule::find_small_rings_from_back_edges(int maxringsize, ResizeArray<int> &back_edge_src, ResizeArray<int> &back_edge_dest) {
02167 int i, key, max_rings;
02168 int n_rings = 0;
02169 int n_back_edges = back_edge_src.num();
02170 SmallRing *ring;
02171 inthash_t *used_edges = new inthash_t;
02172 inthash_t *used_atoms = new inthash_t;
02173 inthash_init(used_edges,n_back_edges);
02174 inthash_init(used_atoms,maxringsize);
02175
02176
02177
02178
02179
02180 max_rings = 2000 + (int) (100.0*sqrt((double) nAtoms));
02181
02182 for(i=0;i<n_back_edges;i++) {
02183 ring = new SmallRing();
02184 ring->append(back_edge_src[i]);
02185 ring->append(back_edge_dest[i]);
02186
02187
02188 inthash_insert(used_atoms,back_edge_dest[i],1);
02189
02190 n_rings += find_small_rings_from_partial(ring,maxringsize,used_edges,used_atoms);
02191 delete ring;
02192
02193
02194 if (n_rings > max_rings) {
02195 msgWarn << "Maximum number of rings (" << max_rings << ") exceed."
02196 << " Stopped looking for rings after " << n_rings << " rings found." << sendmsg;
02197 break;
02198 }
02199
02200 key = get_edge_key(back_edge_src[i],back_edge_dest[i]);
02201 inthash_insert(used_edges,key,1);
02202
02203
02204 inthash_delete(used_atoms,back_edge_dest[i]);
02205 }
02206
02207 inthash_destroy(used_edges);
02208 delete used_edges;
02209 inthash_destroy(used_atoms);
02210 delete used_atoms;
02211
02212 return n_rings;
02213 }
02214
02215
02216
02217 int BaseMolecule::find_small_rings_from_partial(SmallRing *ring, int maxringsize, inthash_t *used_edges, inthash_t *used_atoms) {
02218 int i, next_bond_pos, cur_atom_id, child_atom_id, bond_key, barred, closes, do_pop;
02219 int n_rings = 0;
02220 MolAtom *curatom;
02221
02222 IntStackHandle atom_id_stack = intstack_create(maxringsize);
02223 IntStackHandle bond_pos_stack = intstack_create(maxringsize);
02224 intstack_push(atom_id_stack,ring->last_atom());
02225 intstack_push(bond_pos_stack,0);
02226
02227 while (!intstack_pop(atom_id_stack,&cur_atom_id)) {
02228 intstack_pop(bond_pos_stack,&next_bond_pos);
02229 curatom = atom(cur_atom_id);
02230 do_pop = 0;
02231
02232
02233 if (ring->num() > maxringsize)
02234 do_pop = 1;
02235
02236 if (next_bond_pos == 0 && !do_pop) {
02237
02238
02239 barred = closes = 0;
02240 for(i=0;i<curatom->bonds;i++) {
02241 child_atom_id = curatom->bondTo[i];
02242
02243
02244 if (child_atom_id == ring->atoms[ring->atoms.num()-2]) continue;
02245
02246
02247
02248 if (inthash_lookup(used_atoms, child_atom_id) != HASH_FAIL) {
02249 barred = 1;
02250 continue;
02251 }
02252
02253
02254 bond_key = get_edge_key(cur_atom_id,child_atom_id);
02255 if (inthash_lookup(used_edges, bond_key) != HASH_FAIL) {
02256 if (child_atom_id == ring->first_atom())
02257 barred = 1;
02258 continue;
02259 }
02260
02261
02262 if (child_atom_id == ring->first_atom()) {
02263 closes = 1;
02264 continue;
02265 }
02266 }
02267
02268 if (closes && !barred) {
02269 smallringList.append(ring->copy());
02270 n_rings += 1;
02271 }
02272 if (closes || barred) {
02273
02274 do_pop = 1;
02275 }
02276 }
02277
02278 if (!do_pop) {
02279 for(i=next_bond_pos;i<curatom->bonds;i++) {
02280 child_atom_id = curatom->bondTo[i];
02281
02282
02283 if (child_atom_id == ring->atoms[ring->atoms.num()-2]) continue;
02284
02285
02286 bond_key = get_edge_key(cur_atom_id,child_atom_id);
02287 if (inthash_lookup(used_edges, bond_key) != HASH_FAIL) continue;
02288
02289
02290 ring->append(child_atom_id);
02291 inthash_insert(used_atoms,child_atom_id,1);
02292
02293
02294 intstack_push(atom_id_stack,cur_atom_id);
02295 intstack_push(bond_pos_stack,i+1);
02296 intstack_push(atom_id_stack,child_atom_id);
02297 intstack_push(bond_pos_stack,0);
02298 break;
02299 }
02300
02301
02302 if(i>=curatom->bonds)
02303 do_pop = 1;
02304 }
02305
02306 if (do_pop && !intstack_empty(atom_id_stack)) {
02307
02308
02309 ring->remove_last();
02310 inthash_delete(used_atoms,cur_atom_id);
02311 }
02312 }
02313
02314 intstack_destroy(atom_id_stack);
02315 intstack_destroy(bond_pos_stack);
02316 return n_rings;
02317 }
02318
02319
02320
02321 int BaseMolecule::get_edge_key(int edge_src, int edge_dest) {
02322 int t;
02323 if (edge_dest > edge_src) {
02324 t = edge_src;
02325 edge_src = edge_dest;
02326 edge_dest = t;
02327 }
02328 return edge_src * nAtoms + edge_dest;
02329 }
02330
02331
02332
02333
02334 void BaseMolecule::orientate_small_rings(int maxringsize) {
02335 for (int i=0;i<smallringList.num();i++)
02336 orientate_small_ring(*smallringList[i],maxringsize);
02337 }
02338
02339 void BaseMolecule::orientate_small_ring(SmallRing &ring,int maxringsize) {
02340 short int oxygen = -1;
02341 int oxygen_typeindex, c1_nameindex, c1p_nameindex, cu1_nameindex;
02342 int c2_nameindex, c2p_nameindex, cu2_nameindex;
02343 MolAtom *curatom, *atom_before_O, *atom_after_O;
02344
02345
02346 oxygen_typeindex = atomTypes.typecode("O");
02347 c1_nameindex = atomNames.typecode("C1");
02348 c1p_nameindex = atomNames.typecode("C1'");
02349 cu1_nameindex = atomNames.typecode("C_1");
02350 c2_nameindex = atomNames.typecode("C2");
02351 c2p_nameindex = atomNames.typecode("C2'");
02352 cu2_nameindex = atomNames.typecode("C_2");
02353
02354
02355 for (int i=0; i<ring.num(); i++) {
02356 curatom = atom(ring[i]);
02357 if (curatom->atomicnumber == 8 || curatom->typeindex == oxygen_typeindex || curatom->bonds == 2) {
02358 oxygen = i;
02359 break;
02360 }
02361 }
02362
02363
02364 if (oxygen == -1) return;
02365
02366
02367 if (oxygen == 0) atom_before_O = atom(ring.last_atom());
02368 else atom_before_O = atom(ring[oxygen-1]);
02369
02370 if (oxygen == ring.num()-1) atom_after_O = atom(ring.first_atom());
02371 else atom_after_O = atom(ring[oxygen+1]);
02372
02373
02374
02375 if (atom_before_O->nameindex == c1_nameindex || atom_before_O->nameindex == c1p_nameindex
02376 || atom_before_O->nameindex == cu1_nameindex
02377 || atom_before_O->nameindex == c2_nameindex || atom_before_O->nameindex == c2p_nameindex
02378 || atom_before_O->nameindex == cu2_nameindex) {
02379 ring.reverse();
02380 ring.orientated = 1;
02381 }
02382 else if (atom_after_O->nameindex == c1_nameindex || atom_after_O->nameindex == c1p_nameindex
02383 || atom_after_O->nameindex == cu1_nameindex
02384 || atom_after_O->nameindex == c2_nameindex || atom_after_O->nameindex == c2p_nameindex
02385 || atom_after_O->nameindex == cu2_nameindex) {
02386 ring.orientated = 1;
02387 }
02388 }
02389
02390
02391
02392
02393
02394
02395
02396 int BaseMolecule::find_orientated_small_ring_linkages(int maxpathlength, int maxringsize) {
02397 SmallRing *sr;
02398 LinkagePath *lp;
02399 int i, j, atom_id;
02400 int n_paths = 0;
02401 inthash_t *atom_to_ring = new inthash_t;
02402 inthash_t *multi_ring_atoms = new inthash_t;
02403 inthash_t *used_atoms = new inthash_t;
02404 inthash_init(atom_to_ring,smallringList.num()*maxringsize/2);
02405 inthash_init(multi_ring_atoms,smallringList.num());
02406 inthash_init(used_atoms,maxpathlength);
02407
02408
02409 for (i=0;i<smallringList.num();i++) {
02410 sr = smallringList[i];
02411
02412
02413
02414 for (j=0;j<sr->num();j++) {
02415 atom_id = (*sr)[j];
02416 if (inthash_lookup(atom_to_ring,atom_id) == HASH_FAIL)
02417 inthash_insert(atom_to_ring,atom_id,i);
02418 else
02419 inthash_insert(multi_ring_atoms,atom_id,1);
02420 }
02421 }
02422
02423
02424
02425 for (i=0;i<smallringList.num();i++) {
02426 sr = smallringList[i];
02427 if (!sr->orientated) continue;
02428 for (j=0;j<sr->num();j++) {
02429 if (inthash_lookup(multi_ring_atoms,(*sr)[j]) != HASH_FAIL) continue;
02430 lp = new LinkagePath();
02431 lp->start_ring = i;
02432 lp->path.append((*sr)[j]);
02433 n_paths += find_linkages_for_ring_from_partial(*lp,maxpathlength,atom_to_ring,multi_ring_atoms,used_atoms);
02434 delete lp;
02435 }
02436 }
02437
02438 inthash_destroy(atom_to_ring);
02439 delete atom_to_ring;
02440 inthash_destroy(multi_ring_atoms);
02441 delete multi_ring_atoms;
02442 inthash_destroy(used_atoms);
02443 delete used_atoms;
02444
02445 #if 0
02446 msgInfo << smallringLinkages << sendmsg;
02447 #endif
02448
02449 return n_paths;
02450 }
02451
02452 int BaseMolecule::find_linkages_for_ring_from_partial(LinkagePath &lp, int maxpathlength, inthash_t *atom_to_ring, inthash_t *multi_ring_atoms, inthash_t *used_atoms) {
02453 int i, cur_atom_id, next_bond_pos, child_atom_id, ringidx;
02454 int n_paths = 0;
02455 MolAtom *curatom;
02456
02457 IntStackHandle atom_id_stack = intstack_create(maxpathlength);
02458 IntStackHandle bond_pos_stack = intstack_create(maxpathlength);
02459 intstack_push(atom_id_stack,lp.path.last_atom());
02460 intstack_push(bond_pos_stack,0);
02461
02462 while (!intstack_pop(atom_id_stack,&cur_atom_id)) {
02463 intstack_pop(bond_pos_stack,&next_bond_pos);
02464 curatom = atom(cur_atom_id);
02465
02466 if (next_bond_pos == 0)
02467 inthash_insert(used_atoms, cur_atom_id, 1);
02468
02469 for(i=next_bond_pos;i<curatom->bonds;i++) {
02470 child_atom_id = curatom->bondTo[i];
02471
02472
02473 if (inthash_lookup(multi_ring_atoms,child_atom_id) != HASH_FAIL) continue;
02474
02475
02476
02477 if (lp.num() > 1 && child_atom_id == lp[lp.num()-2]) continue;
02478
02479
02480 ringidx = inthash_lookup(atom_to_ring, child_atom_id);
02481 if (ringidx != HASH_FAIL && !smallringList[ringidx]->orientated) continue;
02482
02483
02484
02485
02486 if (ringidx != HASH_FAIL && ringidx <= lp.start_ring) continue;
02487
02488
02489 if (ringidx != HASH_FAIL && (ringidx > lp.start_ring)) {
02490 lp.append(child_atom_id);
02491 lp.end_ring = ringidx;
02492 smallringLinkages.addLinkagePath(*lp.copy());
02493 n_paths++;
02494 lp.end_ring = -1;
02495 lp.remove_last();
02496 continue;
02497 }
02498
02499
02500
02501 if (inthash_lookup(used_atoms, child_atom_id) != HASH_FAIL) continue;
02502
02503 if (lp.num() < maxpathlength) {
02504 lp.append(child_atom_id);
02505
02506
02507 intstack_push(atom_id_stack,cur_atom_id);
02508 intstack_push(bond_pos_stack,i+1);
02509 intstack_push(atom_id_stack,child_atom_id);
02510 intstack_push(bond_pos_stack,0);
02511 break;
02512 }
02513 }
02514
02515 if ((i>=curatom->bonds)&&(!intstack_empty(atom_id_stack))) {
02516
02517 lp.remove_last();
02518 inthash_delete(used_atoms,cur_atom_id);
02519 }
02520 }
02521
02522 intstack_destroy(atom_id_stack);
02523 intstack_destroy(bond_pos_stack);
02524 return n_paths;
02525 }
02526
02527 #endif // end of carbohydrate related stuff
02528
02529
02530
02531 void BaseMolecule::add_volume_data(const char *name, const float *o,
02532 const float *xa, const float *ya, const float *za, int x, int y, int z,
02533 float *scalar, float *grad, float *variance) {
02534 msgInfo << "Analyzing Volume..." << sendmsg;
02535
02536 VolumetricData *vdata = new VolumetricData(name, o, xa, ya, za,
02537 x, y, z, scalar);
02538
02539
02540
02541
02542 msgInfo << " Grid size: " << x << "x" << y << "x" << z << " ("
02543 << (int) (1.0 * (vdata->gridsize() * sizeof(float)) / (1024.0 * 1024.0)) << " MB)"
02544 << sendmsg;
02545
02546 msgInfo << " Total voxels: " << vdata->gridsize() << sendmsg;
02547
02548 float datamin, datamax;
02549 vdata->datarange(datamin, datamax);
02550 #if 1
02551 char minstr[1024];
02552 char maxstr[1024];
02553 char rangestr[1024];
02554 sprintf(minstr, "%g", datamin);
02555 sprintf(maxstr, "%g", datamax);
02556 sprintf(rangestr, "%g", (datamax - datamin));
02557 msgInfo << " Min: " << minstr << " Max: " << maxstr
02558 << " Range: " << rangestr << sendmsg;
02559 #else
02560 msgInfo << " Min: " << datamin << " Max: " << datamax
02561 << " Range: " << (datamax - datamin) << sendmsg;
02562 #endif
02563
02564 int gmapmb = int((3.0 * (vdata->gridsize() * sizeof(float)) / (1024.0 * 1024.0)));
02565 if (grad) {
02566
02567 msgInfo << " Assigning volume gradient map"
02568 << " (" << gmapmb << " MB)" << sendmsg;
02569 vdata->set_volume_gradient(grad);
02570 } else {
02571 if (gmapmb <= 3072) {
02572
02573 msgInfo << " Computing volume gradient map "
02574 << " (" << gmapmb << " MB)" << sendmsg;
02575 vdata->compute_volume_gradient();
02576 } else {
02577 msgInfo << " Volume gradient map calculations deferred to on-demand"
02578 << sendmsg;
02579 }
02580 }
02581
02582 volumeList.append(vdata);
02583
02584 msgInfo << "Added volume data, name=" << vdata->name << sendmsg;
02585 }
02586
02587
02588 void BaseMolecule::add_volume_data(const char *name, const double *o,
02589 const double *xa, const double *ya, const double *za, int x, int y, int z,
02590 float *scalar) {
02591 msgInfo << "Analyzing Volume..." << sendmsg;
02592
02593 VolumetricData *vdata = new VolumetricData(name, o, xa, ya, za,
02594 x, y, z, scalar);
02595
02596
02597
02598
02599 msgInfo << " Grid size: " << x << "x" << y << "x" << z << " ("
02600 << (int) (4.0 * (vdata->gridsize() * sizeof(float)) / (1024.0 * 1024.0)) << " MB)"
02601 << sendmsg;
02602
02603 msgInfo << " Total voxels: " << vdata->gridsize() << sendmsg;
02604
02605 float datamin, datamax;
02606 vdata->datarange(datamin, datamax);
02607 msgInfo << " Min: " << datamin << " Max: " << datamax
02608 << " Range: " << (datamax - datamin) << sendmsg;
02609
02610 msgInfo << " Computing volume gradient map for smooth shading" << sendmsg;
02611 vdata->compute_volume_gradient();
02612
02613 volumeList.append(vdata);
02614
02615 msgInfo << "Added volume data, name=" << vdata->name << sendmsg;
02616 }
02617
02618
02619 void BaseMolecule::remove_volume_data(int idx) {
02620 if (idx >= 0 && idx < volumeList.num()) {
02621 delete volumeList[idx];
02622 volumeList.remove(idx);
02623 }
02624 }
02625
02626
02627 int BaseMolecule::num_volume_data() {
02628 return volumeList.num();
02629 }
02630
02631 VolumetricData *BaseMolecule::modify_volume_data(int id) {
02632 if (id >= 0 && id < volumeList.num())
02633 return volumeList[id];
02634 return NULL;
02635 }
02636
02637 const VolumetricData *BaseMolecule::get_volume_data(int id) {
02638 return modify_volume_data(id);
02639 }
02640