00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025 #include <stdio.h>
00026 #include <stdlib.h>
00027 #include <math.h>
00028 #include "Measure.h"
00029 #include "AtomSel.h"
00030 #include "utilities.h"
00031 #include "ResizeArray.h"
00032 #include "MoleculeList.h"
00033 #include "Inform.h"
00034 #include "Timestep.h"
00035 #include "VMDApp.h"
00036 #include "WKFThreads.h"
00037 #include "WKFUtils.h"
00038 #include "SpatialSearch.h"
00039
00040 class AtomSelThr : public AtomSel
00041 {
00042 public:
00043 AtomSelThr(VMDApp *vmdapp, AtomSel *osel, wkf_mutex_t *olock)
00044 : AtomSel(vmdapp, NULL, osel->molid()),
00045 sel(osel), lock(olock) {
00046 if (sel) {
00047 selected=sel->selected;
00048 num_atoms=sel->num_atoms;
00049 which_frame=sel->which_frame;
00050 if (sel->on) {
00051 on = new int[num_atoms];
00052 memcpy(on,sel->on,num_atoms*sizeof(int));
00053 }
00054 } else {
00055 selected=-1;
00056 num_atoms=-1;
00057 which_frame=-1;
00058 }
00059 }
00060
00061 ~AtomSelThr() {
00062 sel=NULL;
00063 }
00064
00065
00066 private:
00067
00068 AtomSelThr& operator=(const AtomSelThr &) { return *this; };
00069
00070 int change(const char *newcmd, DrawMolecule *mol) { return NO_PARSE; }
00071
00072 public:
00073
00074
00075 void update( DrawMolecule *mol, const int frame) {
00076 if (!sel) return;
00077
00078 wkf_mutex_lock(lock);
00079
00080 sel->which_frame=frame;
00081 which_frame=frame;
00082
00083 if (sel->change(NULL, mol) != AtomSel::PARSE_SUCCESS)
00084 msgErr << "AtomSelThr::update(): failed to evaluate atom selection update";
00085
00086 num_atoms=sel->num_atoms;
00087 selected=sel->selected;
00088 if (!on) on = new int[num_atoms];
00089 memcpy(on,sel->on,num_atoms*sizeof(int));
00090
00091 wkf_mutex_unlock(lock);
00092 }
00093
00094 protected:
00095 AtomSel *sel;
00096 wkf_mutex_t *lock;
00097 };
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175 #ifdef __cplusplus
00176 extern "C" {
00177 #endif
00178
00179 #ifdef R_SMALL
00180 #undef R_SMALL
00181 #endif
00182 #define R_SMALL 0.000000001
00183
00184 static void normalize3d(double *v) {
00185 double vlen;
00186 vlen = sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
00187 if (vlen > R_SMALL) {
00188 v[0] /= vlen;
00189 v[1] /= vlen;
00190 v[2] /= vlen;
00191 } else {
00192 v[0] = 0;
00193 v[1] = 0;
00194 v[2] = 0;
00195 }
00196 }
00197
00198
00199 static float MyMatrixFitRMS(int n, float *v1, float *v2, const float *wt, const double tol)
00200 {
00201
00202
00203
00204
00205
00206
00207
00208
00209 float *vv1,*vv2;
00210 double m[3][3],aa[3][3];
00211 double sumwt, sig, gam;
00212 double sg, bb, cc, tmp, err, etmp;
00213 int a, b, c, maxiter, iters, iy, iz;
00214 double t1[3],t2[3];
00215 double aatmp[9];
00216
00217
00218
00219 for(a=0;a<3;a++) {
00220 for(b=0;b<3;b++) {
00221 m[a][b] = 0.0;
00222 aa[a][b] = 0.0;
00223 aatmp[3*a+b] = 0;
00224 }
00225 m[a][a] = 1.0;
00226 t1[a]=0.0;
00227 t2[a]=0.0;
00228 }
00229
00230
00231 maxiter = 1000;
00232
00233
00234
00235 vv1=v1;
00236 vv2=v2;
00237 sumwt = 0.0;
00238
00239 for(c=0;c<n;c++) {
00240 double w = wt ? wt[c] : 1;
00241 t1[0] += w * vv1[0];
00242 t1[1] += w * vv1[1];
00243 t1[2] += w * vv1[2];
00244 t2[0] += w * vv2[0];
00245 t2[1] += w * vv2[1];
00246 t2[2] += w * vv2[2];
00247 sumwt += w;
00248 vv1+=3;
00249 vv2+=3;
00250 }
00251 for(a=0;a<3;a++) {
00252 t1[a] /= sumwt;
00253 t2[a] /= sumwt;
00254 }
00255
00256
00257 vv1=v1;
00258 vv2=v2;
00259 for(c=0;c<n;c++) {
00260 double w = wt ? wt[c] : 1;
00261 double x1 = w * (vv1[0] - t1[0]);
00262 double y1 = w * (vv1[1] - t1[1]);
00263 double z1 = w * (vv1[2] - t1[2]);
00264
00265
00266 double x2 = (vv2[0] - t2[0]);
00267 double y2 = (vv2[1] - t2[1]);
00268 double z2 = (vv2[2] - t2[2]);
00269 aatmp[0] += x2 * x1;
00270 aatmp[1] += x2 * y1;
00271 aatmp[2] += x2 * z1;
00272 aatmp[3] += y2 * x1;
00273 aatmp[4] += y2 * y1;
00274 aatmp[5] += y2 * z1;
00275 aatmp[6] += z2 * x1;
00276 aatmp[7] += z2 * y1;
00277 aatmp[8] += z2 * z1;
00278 vv1+=3;
00279 vv2+=3;
00280 }
00281
00282 for (a=0; a<3; a++)
00283 for (b=0; b<3; b++)
00284 aa[a][b] = aatmp[3*a+b];
00285
00286 if(n>1) {
00287
00288 iters = 0;
00289 while(1) {
00290
00291 iz = (iters+1) % 3;
00292 iy = (iz+1) % 3;
00293
00294
00295 sig = aa[iz][iy] - aa[iy][iz];
00296 gam = aa[iy][iy] + aa[iz][iz];
00297
00298 if(iters>=maxiter) {
00299 fprintf(stderr,
00300 " Matrix: Warning: no convergence (%.15f>%.15f after %d iterations).\n",
00301 fabs(sig),tol*fabs(gam),iters);
00302 break;
00303 }
00304
00305
00306
00307 tmp = sig*sig + gam*gam;
00308 sg = sqrt(tmp);
00309 if( (sg > 0.0) && (fabs(sig)>(tol*fabs(gam))) ) {
00310 sg = 1.0 / sg;
00311 for(a=0;a<3;a++) {
00312 bb = gam*aa[iy][a] + sig*aa[iz][a];
00313 cc = gam*aa[iz][a] - sig*aa[iy][a];
00314 aa[iy][a] = bb*sg;
00315 aa[iz][a] = cc*sg;
00316
00317 bb = gam*m[iy][a] + sig*m[iz][a];
00318 cc = gam*m[iz][a] - sig*m[iy][a];
00319 m[iy][a] = bb*sg;
00320 m[iz][a] = cc*sg;
00321 }
00322 } else {
00323 break;
00324 }
00325 iters++;
00326 }
00327 }
00328
00329
00330 err=0.0;
00331 vv1=v1;
00332 vv2=v2;
00333
00334 normalize3d(m[0]);
00335 normalize3d(m[1]);
00336 normalize3d(m[2]);
00337
00338 for(c=0;c<n;c++) {
00339 etmp = 0.0;
00340 for(a=0;a<3;a++) {
00341 tmp = m[a][0]*(vv2[0]-t2[0])
00342 + m[a][1]*(vv2[1]-t2[1])
00343 + m[a][2]*(vv2[2]-t2[2]);
00344 tmp = (vv1[a]-t1[a])-tmp;
00345 etmp += tmp*tmp;
00346 }
00347
00348 if(wt)
00349 err += wt[c] * etmp;
00350 else
00351 err += etmp;
00352
00353 vv1+=3;
00354 vv2+=3;
00355 }
00356
00357 err=err/sumwt;
00358 err=sqrt(err);
00359 return (float)err;
00360 }
00361
00362 #ifdef __cplusplus
00363 }
00364 #endif
00365
00366
00367
00368
00369
00370
00371 static float cluster_get_rmsd(const float *Frame1Pos, const float *Frame2Pos,
00372 AtomSel *sel, float *weights) {
00373 float distance = 0.0f;
00374 measure_rmsd(sel, sel, sel->num_atoms, Frame1Pos, Frame2Pos, weights, &distance);
00375 return distance;
00376 }
00377
00378
00379
00380
00381 static float cluster_get_rgyrd(const float *Frame1Pos, const float *Frame2Pos,
00382 AtomSel *sel, float *weights) {
00383
00384 float distance = 10000000.0f;
00385
00386
00387 float com1[3], com2[3];
00388 int ret_val;
00389
00390 ret_val = measure_center(sel, Frame1Pos, weights, com1);
00391 if (ret_val < 0)
00392 return distance;
00393
00394 ret_val = measure_center(sel, Frame2Pos, weights, com2);
00395 if (ret_val < 0)
00396 return distance;
00397
00398
00399 int i, j;
00400 float total_w, w, sum1, sum2;
00401 total_w=sum1=sum2=0.0f;
00402 for (j=0,i=sel->firstsel; i<=sel->lastsel; i++) {
00403 if (sel->on[i]) {
00404 w = weights[j];
00405 total_w += w;
00406 sum1 += w * distance2(Frame1Pos + 3*i, com1);
00407 sum2 += w * distance2(Frame2Pos + 3*i, com2);
00408 j++;
00409 }
00410 }
00411
00412 if (total_w == 0.0f)
00413 return distance;
00414
00415
00416 distance = sqrtf(sum1/total_w) - sqrtf(sum2/total_w);
00417 return fabsf(distance);
00418 }
00419
00420
00421
00422
00423
00424
00425 static float cluster_get_fitrmsd(const float *Frame1Pos, const float *Frame2Pos,
00426 AtomSel *sel, float *weights, const double tol) {
00427
00428 int num = sel->selected;
00429
00430
00431 float distance = 10000000.0f;
00432
00433
00434
00435
00436
00437
00438
00439 if (sel->selected < 4)
00440 return distance;
00441
00442 int i, j, k;
00443 float *v1, *v2, *wt;
00444 v1 = new float[3*num];
00445 v2 = new float[3*num];
00446 wt = new float[num];
00447 for (j=0,k=0,i=sel->firstsel; i<=sel->lastsel; i++) {
00448 if (sel->on[i]) {
00449 int ind = 3 * i;
00450 wt[j] = weights[i];
00451 ++j;
00452 v1[k] = Frame1Pos[ind];
00453 v2[k] = Frame2Pos[ind];
00454 v1[k+1] = Frame1Pos[ind+1];
00455 v2[k+1] = Frame2Pos[ind+1];
00456 v1[k+2] = Frame1Pos[ind+2];
00457 v2[k+2] = Frame2Pos[ind+2];
00458 k+=3;
00459 }
00460 }
00461 distance = MyMatrixFitRMS(num, v1, v2, wt, tol);
00462
00463 delete [] v1;
00464 delete [] v2;
00465 delete [] wt;
00466
00467 return distance;
00468 }
00469
00470
00471
00472
00473 typedef struct {
00474 int threadid;
00475 int threadcount;
00476
00477 int max_cluster_size;
00478 const int *skip_list;
00479 int *new_skip_list;
00480 int *max_cluster;
00481
00482 int istart;
00483 int iend;
00484 int *frames_list;
00485 int numframes;
00486
00487 AtomSelThr *sel;
00488 Molecule *mol;
00489 int selupdate;
00490 float cutoff;
00491 int likeness;
00492 float *weights;
00493 } clusterparms_t;
00494
00495
00496
00497 extern "C" void * find_cluster_thr(void *voidparms)
00498 {
00499
00500 clusterparms_t *parms = (clusterparms_t *)voidparms;
00501 const int istart = parms->istart;
00502 const int iend = parms->iend;
00503 int *framesList = parms->frames_list;
00504 const int numframes = parms->numframes;
00505
00506 const int selupdate = parms->selupdate;
00507 const int likeness = parms->likeness;
00508 float cutoff = parms->cutoff;
00509 float *weights = parms->weights;
00510
00511 AtomSelThr *sel = parms->sel;
00512 Molecule *mymol = parms->mol;
00513 const int *skipList = parms->skip_list;
00514
00515 int *maxCluster = parms->max_cluster;
00516 memset(maxCluster, 0, numframes*sizeof(int));
00517 int *newSkipList = parms->new_skip_list;
00518 memset(newSkipList, 0, numframes*sizeof(int));
00519
00520 int maxClusterSize = 0, tempClusterSize = 0;
00521 int *tempCluster = new int[numframes];
00522 int *tempSkipList = new int[numframes];
00523
00524
00525
00526
00527 double tol = 1e-15;
00528 const char *TOL = getenv( "VMDFITRMSTOLERANCE" );
00529 if (TOL)
00530 tol = atof(TOL);
00531
00532
00533 int i,j;
00534 for (i = istart; i < iend; i++) {
00535 memset(tempSkipList, 0, numframes*sizeof(int));
00536 memset(tempCluster, 0, numframes*sizeof(int));
00537
00538 if (skipList[i]==0) {
00539 if (selupdate)
00540 sel->update(mymol,framesList[i]);
00541
00542 const Timestep *tsMain = mymol->get_frame(framesList[i]);
00543 const float *framePos = tsMain->pos;
00544
00545 tempCluster[0] = i;
00546 tempSkipList[i] = 1;
00547 tempClusterSize = 1;
00548
00549
00550 for (j = 0; j < numframes; j++) {
00551 if (skipList[j]==0 && j != i) {
00552 const Timestep *ts2;
00553 ts2 = mymol->get_frame(framesList[j]);
00554 float distance;
00555
00556
00557 switch(likeness) {
00558 case MEASURE_DIST_RMSD:
00559 distance = cluster_get_rmsd(framePos, ts2->pos, sel, weights);
00560 break;
00561
00562 case MEASURE_DIST_FITRMSD:
00563 distance = cluster_get_fitrmsd(framePos, ts2->pos, sel, weights, tol);
00564 break;
00565
00566 case MEASURE_DIST_RGYRD:
00567 distance = cluster_get_rgyrd(framePos, ts2->pos, sel, weights);
00568 break;
00569
00570 default:
00571 distance = 10000000.0f;
00572 }
00573
00574 if (distance <= cutoff) {
00575 tempCluster[tempClusterSize] = j;
00576 ++tempClusterSize;
00577 tempSkipList[j] = 1;
00578 }
00579 }
00580 }
00581
00582
00583 if (tempClusterSize > maxClusterSize) {
00584 int *temp;
00585 maxClusterSize = tempClusterSize;
00586
00587 temp = maxCluster;
00588 maxCluster = tempCluster;
00589 tempCluster = temp;
00590
00591 temp = newSkipList;
00592 newSkipList = tempSkipList;
00593 tempSkipList = temp;
00594 }
00595 }
00596 }
00597
00598
00599 parms->max_cluster_size = maxClusterSize;
00600 parms->max_cluster = maxCluster;
00601 parms->new_skip_list = newSkipList;
00602
00603
00604 delete[] tempCluster;
00605 delete[] tempSkipList;
00606
00607 return MEASURE_NOERR;
00608 }
00609
00610
00612 static int *find_next_cluster(Molecule *mymol, int *framesList, const int numframes,
00613 const int remframes, const int *skipList, int **newSkipList,
00614 const int likeness, AtomSel *sel, const int selupdate,
00615 const double cutoff, float *weights)
00616 {
00617 int i,j;
00618
00619
00620 wkf_thread_t *threads;
00621 clusterparms_t *parms;
00622
00623 #if defined(VMDTHREADS)
00624 int numprocs = wkf_thread_numprocessors();
00625 #else
00626 int numprocs = 1;
00627 #endif
00628
00629 int delta = remframes / numprocs;
00630 int istart = 0;
00631 int iend = 0;
00632
00633
00634 if (delta < 1) {
00635 numprocs=1;
00636 delta=numframes;
00637 }
00638
00639 threads = new wkf_thread_t[numprocs];
00640 memset(threads, 0, numprocs * sizeof(wkf_thread_t));
00641 wkf_mutex_t *atomsel_lock = new wkf_mutex_t;
00642 wkf_mutex_init(atomsel_lock);
00643
00644
00645 parms = new clusterparms_t[numprocs];
00646 for (i=0; i<numprocs; ++i) {
00647 parms[i].threadid = i;
00648 parms[i].threadcount = numprocs;
00649
00650 parms[i].max_cluster_size = 1;
00651 parms[i].skip_list = skipList;
00652 parms[i].new_skip_list = new int[numframes];
00653 parms[i].max_cluster = new int[numframes];
00654
00655
00656
00657
00658
00659
00660 parms[i].sel = new AtomSelThr(mymol->app, sel, atomsel_lock);
00661 parms[i].mol = mymol;
00662
00663
00664
00665 parms[i].istart = istart;
00666 int nframe=0;
00667 for (j=istart; (j < numframes) && (nframe < delta); ++j) {
00668 if (skipList[framesList[j]]==0)
00669 ++nframe;
00670 iend=j;
00671 }
00672 parms[i].iend = iend;
00673 istart=iend;
00674
00675 parms[i].frames_list = framesList;
00676 parms[i].numframes = numframes;
00677 parms[i].selupdate = selupdate;
00678 parms[i].likeness = likeness;
00679 parms[i].cutoff = (float) cutoff;
00680 parms[i].weights = weights;
00681 }
00682 parms[numprocs-1].iend=numframes;
00683
00684
00685 #if defined(VMDTHREADS)
00686 if (numprocs > 1) {
00687 for (i=0; i<numprocs; ++i) {
00688 wkf_thread_create(&threads[i], find_cluster_thr, &parms[i]);
00689 }
00690 for (i=0; i<numprocs; ++i) {
00691 wkf_thread_join(threads[i], NULL);
00692 }
00693 } else
00694 #endif
00695 find_cluster_thr(&parms[0]);
00696
00697 int maxClusterSize = parms[0].max_cluster_size;
00698 int *maxCluster = parms[0].max_cluster;
00699 delete[] *newSkipList;
00700 *newSkipList= parms[0].new_skip_list;
00701
00702
00703
00704 if (numprocs > 1) {
00705 for (i = 1; i < numprocs; i++) {
00706 if (parms[i].max_cluster_size > maxClusterSize) {
00707 maxClusterSize = parms[i].max_cluster_size;
00708 delete[] maxCluster;
00709 maxCluster = parms[i].max_cluster;
00710 delete[] *newSkipList;
00711 *newSkipList = parms[i].new_skip_list;
00712 } else {
00713 delete[] parms[i].max_cluster;
00714 delete[] parms[i].new_skip_list;
00715 }
00716 }
00717 }
00718
00719
00720 for (i = 0; i < numframes; i++) {
00721 maxCluster[i] = framesList[maxCluster[i]];
00722 }
00723
00724
00725 wkf_mutex_destroy(atomsel_lock);
00726 delete atomsel_lock;
00727
00728 if (selupdate) {
00729 for (i=0; i<numprocs; ++i)
00730 delete parms[i].sel;
00731 }
00732 delete[] threads;
00733 delete[] parms;
00734
00735 return maxCluster;
00736 }
00737
00738 int measure_cluster(AtomSel *sel, MoleculeList *mlist,
00739 const int numcluster, const int algorithm,
00740 const int likeness, const double cutoff,
00741 int *clustersize, int **clusterlist,
00742 int first, int last, int step, int selupdate,
00743 float *weights)
00744 {
00745 Molecule *mymol = mlist->mol_from_id(sel->molid());
00746 int maxframe = mymol->numframes()-1;
00747
00748 if (last == -1) last = maxframe;
00749
00750 if ((last < first) || (last < 0) || (step <=0) || (first < 0)
00751 || (last > maxframe)) {
00752 msgErr << "measure cluster: bad frame range given."
00753 << " max. allowed frame#: " << maxframe << sendmsg;
00754 return MEASURE_ERR_BADFRAMERANGE;
00755 }
00756
00757 int numframes = (last-first+1)/step;
00758 int remframes = numframes;
00759
00760
00761 int *framesList = new int[numframes];
00762 int frame_count = 0;
00763 int n;
00764
00765 for(n = first; n <= last; n += step)
00766 framesList[frame_count++] = n;
00767
00768
00769 int *skipList = new int[numframes];
00770
00771 int *newSkipList = new int[numframes];
00772
00773 memset(skipList, 0, numframes*sizeof(int));
00774
00775 wkfmsgtimer *msgtp = wkf_msg_timer_create(5);
00776
00777
00778 for(n = 0; n < numcluster; ++n){
00779
00780
00781 memset(newSkipList, 0, numframes*sizeof(int));
00782 clusterlist[n] = find_next_cluster(mymol, framesList, numframes, remframes,
00783 skipList, &newSkipList, likeness,
00784 sel, selupdate, cutoff, weights);
00785 int n_cluster=0;
00786 for(int i = 0; i < numframes; ++i){
00787 if (newSkipList[i] == 1) {
00788 skipList[i] = 1;
00789 n_cluster++;
00790 }
00791 }
00792 clustersize[n]=n_cluster;
00793 remframes -= n_cluster;
00794
00795
00796 if (msgtp && wkf_msg_timer_timeout(msgtp)) {
00797 char tmpbuf[1024];
00798 sprintf(tmpbuf, "cluster %d of %d: (%6.2f%% complete). %d frames of %d left.",
00799 n+1, numcluster, 100.0f*(n+1)/((float) numcluster), remframes, numframes);
00800 msgInfo << "measure cluster: " << tmpbuf << sendmsg;
00801 }
00802 }
00803
00804
00805 int *unclustered = new int[numframes];
00806 int numunclustered = 0;
00807 for (n = 0; n < numframes; ++n) {
00808 if (skipList[n] == 0) {
00809 unclustered[numunclustered] = framesList[n];
00810 ++numunclustered;
00811 }
00812 }
00813
00814
00815 clusterlist[numcluster] = unclustered;
00816 clustersize[numcluster] = numunclustered;
00817
00818
00819 delete[] newSkipList;
00820 delete[] skipList;
00821 wkf_msg_timer_destroy(msgtp);
00822
00823 return MEASURE_NOERR;
00824 }
00825
00826
00827
00828
00829 typedef ResizeArray<int> intlist;
00830
00831
00832
00833 static void assemble_cluster(intlist &cluster_list, intlist &candidate_list,
00834 intlist **neighbor_grid, int atom, int numshared, int *idxmap) {
00835 int idx, nn, i,j;
00836
00837
00838 candidate_list.clear();
00839 cluster_list.clear();
00840
00841 idx = idxmap[atom];
00842 nn = neighbor_grid[idx]->num();
00843 for (i = 0; i < nn; i++) {
00844 int bn = (*neighbor_grid[idx])[i];
00845 if (neighbor_grid[idxmap[bn]]) {
00846 candidate_list.append(atom);
00847 candidate_list.append(bn);
00848 }
00849 }
00850
00851
00852 int curidx=0;
00853
00854 while (curidx < candidate_list.num()) {
00855
00856
00857
00858
00859 int count = 0;
00860
00861 if (numshared > 0) {
00862 int ida = idxmap[candidate_list[curidx]];
00863 int idb = idxmap[candidate_list[curidx+1]];
00864 int nna = neighbor_grid[ida]->num();
00865 int nnb = neighbor_grid[idb]->num();
00866
00867 for (i = 0; i < nna; i++) {
00868 if (neighbor_grid[ida]) {
00869 for (j = 0; j < nnb; j++) {
00870 if (neighbor_grid[idb]) {
00871 if ( (*neighbor_grid[ida])[i] == (*neighbor_grid[idb])[j] ) {
00872 ++count;
00873 if (count == numshared)
00874 goto exit;
00875 }
00876 }
00877 }
00878 }
00879 }
00880 }
00881 exit:
00882
00883 if (count == numshared) {
00884
00885
00886
00887
00888 int atma = candidate_list[curidx];
00889 if (cluster_list.find(atma) < 0)
00890 cluster_list.append(atma);
00891
00892
00893
00894
00895 int atmb = candidate_list[curidx+1];
00896 idx = idxmap[atmb];
00897
00898 if (cluster_list.find(atmb) < 0) {
00899 cluster_list.append(atmb);
00900
00901 int nnb = neighbor_grid[idx]->num();
00902 for (i = 0; i < nnb; i++) {
00903 int bn = (*neighbor_grid[idx])[i];
00904 if ((neighbor_grid[idxmap[bn]]) && (cluster_list.find(bn) < 0)) {
00905 candidate_list.append(atmb);
00906 candidate_list.append(bn);
00907 }
00908 }
00909 }
00910 }
00911
00912 ++curidx;++curidx;
00913 }
00914
00915 return;
00916 }
00917
00918
00919 int measure_clustsize(const AtomSel *sel, MoleculeList *mlist,
00920 const double cutoff, int *clustersize,
00921 int *clusternum, int *clusteridx,
00922 int minsize, int numshared, int usepbc) {
00923 int i,j;
00924
00925 const float *framepos = sel->coordinates(mlist);
00926 const int num_selected = sel->selected;
00927 const int num_atoms = sel->num_atoms;
00928 const int *selected = sel->on;
00929
00930
00931
00932 int *idxmap = new int[num_atoms];
00933 int *idxrev = new int[num_selected];
00934
00935 for (i=0; i<sel->firstsel; i++)
00936 idxmap[i]=-1;
00937
00938 for(j=0,i=sel->firstsel; i<=sel->lastsel; i++) {
00939 if (sel->on[i]) {
00940 idxrev[j]=i;
00941 idxmap[i]=j++;
00942 } else {
00943 idxmap[i]=-1;
00944 }
00945 }
00946
00947 for (i=sel->lastsel+1; i<sel->num_atoms; i++)
00948 idxmap[i]=-1;
00949
00950
00951 intlist **neighbor_grid;
00952 neighbor_grid = new intlist *[num_selected];
00953 for (i = 0; i < num_selected; i++)
00954 neighbor_grid[i] = new intlist;
00955
00956
00957 GridSearchPair *pairlist, *currentPair, *nextPair;
00958 pairlist = vmd_gridsearch1(framepos, num_atoms, selected, (float)cutoff, 0, -1);
00959
00960
00961 for (currentPair = pairlist; currentPair != NULL; currentPair = nextPair) {
00962 neighbor_grid[idxmap[currentPair->ind1]]->append(currentPair->ind2);
00963 neighbor_grid[idxmap[currentPair->ind2]]->append(currentPair->ind1);
00964 nextPair = currentPair->next;
00965 free(currentPair);
00966 }
00967
00968
00969 int currentClusterNum = 0;
00970 int currentPosition = 0;
00971 intlist cluster_list(64);
00972 intlist candidate_list(128);
00973
00974 while (currentPosition < num_selected) {
00975 if (neighbor_grid[currentPosition]) {
00976
00977
00978
00979
00980
00981
00982 if (neighbor_grid[currentPosition]->num() > numshared) {
00983 assemble_cluster(cluster_list, candidate_list, neighbor_grid,
00984 idxrev[currentPosition], numshared, idxmap);
00985
00986 if (minsize <= cluster_list.num()) {
00987
00988 for (i = 0; i < cluster_list.num(); i++) {
00989 int idx = idxmap[cluster_list[i]];
00990 delete neighbor_grid[idx];
00991 neighbor_grid[idx] = 0;
00992 }
00993
00994
00995
00996 for (i = 0; i < cluster_list.num(); i++) {
00997 int atom = idxmap[cluster_list[i]];
00998 clusteridx[atom] = cluster_list[i];
00999 clusternum[atom] = currentClusterNum;
01000 clustersize[atom] = cluster_list.num();
01001 }
01002 currentClusterNum++;
01003 }
01004 }
01005 }
01006 ++currentPosition;
01007 }
01008
01009 for(i=0; i < num_selected; ++i) {
01010 if (neighbor_grid[i])
01011 delete neighbor_grid[i];
01012 }
01013 delete[] neighbor_grid;
01014
01015 return MEASURE_NOERR;
01016 }