00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <math.h>
00022 #include <stdlib.h>
00023 #include <stdio.h>
00024 #include "Measure.h"
00025
00026 class Vector3D;
00027 class IndexList;
00028 class AtomData;
00029 class MolData;
00030 class AtomList;
00031 class AtomGrid;
00032 class GridList;
00033 class AtomGridCell;
00034
00035
00036
00037
00038 class Vector3D {
00039 public:
00040 const Vector3D operator+(const Vector3D w ) const {
00041 Vector3D v;
00042 v.x = x + w.x;
00043 v.y = y + w.y;
00044 v.z = z + w.z;
00045 return v;
00046 }
00047
00048 const Vector3D operator-(const Vector3D w ) const {
00049 Vector3D v;
00050 v.x = x - w.x;
00051 v.y = y - w.y;
00052 v.z = z - w.z;
00053 return v;
00054 }
00055
00056 const Vector3D operator*(double s) const {
00057 Vector3D v;
00058 v.x = s*x;
00059 v.y = s*y;
00060 v.z = s*z;
00061 return v;
00062 }
00063
00064 double length() const { return sqrt(x*x + y*y + z*z); }
00065 double length2() const { return x*x + y*y + z*z; }
00066 double x,y,z;
00067 };
00068
00069 Vector3D operator*(double s, Vector3D v) {
00070 v.x *= s;
00071 v.y *= s;
00072 v.z *= s;
00073 return v;
00074 }
00075
00076 Vector3D operator/(Vector3D v, double s) {
00077 v.x /= s;
00078 v.y /= s;
00079 v.z /= s;
00080 return v;
00081 }
00082
00083
00084
00085
00086 class IndexList {
00087 public:
00088 IndexList() {
00089 num=0;
00090 maxnum=16;
00091 list = new int[16];
00092 }
00093
00094 ~IndexList() {
00095 if (list != 0)
00096 delete [] list;
00097 }
00098
00099 void add(const int val) {
00100
00101
00102 if (num == maxnum) {
00103 maxnum = (int)(maxnum * 1.5 + 1);
00104 int* oldlist = list;
00105 list = new int[maxnum];
00106 int i;
00107 for(i=0;i<num;i++) {
00108 list[i] = oldlist[i];
00109 }
00110 delete [] oldlist;
00111 }
00112
00113
00114 list[num] = val;
00115 num++;
00116 }
00117
00118 int size() {
00119 return num;
00120 }
00121
00122 int get(const int i) const { return list[i]; }
00123
00124 private:
00125 int num;
00126 int maxnum;
00127 int* list;
00128 };
00129
00130
00131
00132
00133 class AtomData {
00134 public:
00135 int index;
00136 Vector3D coord;
00137 };
00138
00139
00140
00141
00142
00143
00144 class MolData {
00145 public:
00146 MolData() {
00147 coords = 0;
00148 }
00149
00150 ~MolData() {
00151 if ( coords != 0) {
00152 delete [] coords;
00153 }
00154 }
00155
00156 static MolData* readFile(const char* fname,
00157 double gridspacing, double radius, double threshold);
00158
00159 static MolData* readData(const int *indx, const float *coords, const int count,
00160 const Vector3D o,
00161 const Vector3D a, const Vector3D b, const Vector3D c,
00162 const double gridspacing, const double radius,
00163 const double threshold,
00164 const bool periodic);
00165
00166 void wrapCoords(const AtomGrid* grid);
00167
00168 AtomList* findAtomsGrid(const AtomGrid* grid);
00169 double getRadius() const { return radius; }
00170 double getActualRadius() const { return actual_radius; }
00171
00172 double gridspacing;
00173 double radius;
00174 double threshold;
00175 double actual_radius;
00176 Vector3D origin;
00177 Vector3D basisa;
00178 Vector3D basisb;
00179 Vector3D basisc;
00180 int count;
00181 AtomData* coords;
00182 bool periodic;
00183 };
00184
00185
00186
00187
00188
00189 class AtomList {
00190 public:
00191 AtomList(const int sz) {
00192 size = sz;
00193 index_list = new int[sz];
00194 count = 0;
00195 }
00196
00197 ~AtomList() {
00198 if (index_list != 0) {
00199 delete [] index_list;
00200 }
00201 }
00202
00203 void add(const int index) { index_list[count] = index; count++; }
00204
00205 void storeFile(const char* fname) const
00206 {
00207 FILE* outf = fopen(fname,"w");
00208 if (outf == NULL) {
00209 printf("Couldn't open file %s\n",fname);
00210 exit(-1);
00211 }
00212
00213 int i;
00214 for(i=0; i < count; i++) {
00215 if (fprintf(outf,"%d\n",index_list[i]) < 0) {
00216 printf("Store file error %d %s\n",i,fname);
00217 exit(-2);
00218 }
00219 }
00220
00221 fclose(outf);
00222 return;
00223 }
00224
00225 void storeData(int **surf, int *surf_count) const
00226 {
00227 *surf_count = count;
00228 *surf = new int[count];
00229 int i;
00230 for(i=0; i < count; i++) {
00231 (*surf)[i] = index_list[i];
00232 }
00233
00234 return;
00235 }
00236
00237 private:
00238 int* index_list;
00239 int count;
00240 int size;
00241 };
00242
00243
00244
00245
00246
00247 class GridList {
00248 public:
00249 GridList(AtomGrid* thegrid, const int gridn)
00250 {
00251 n = gridn;
00252 if (n != 0)
00253 items = new Vector3D[n];
00254 else
00255 items = 0;
00256
00257 indx = 0;
00258 grid = thegrid;
00259 shuffle_vec = scramble_array(n);
00260 }
00261
00262 ~GridList() {
00263 if (items != 0)
00264 delete [] items;
00265 if (shuffle_vec != 0)
00266 delete [] shuffle_vec;
00267 }
00268
00269 int add(const int i, const int j, const int k);
00270
00271 Vector3D get(const int i) const {
00272 if (i < 0 || i >= n)
00273 throw -1;
00274
00275 return items[i];
00276 }
00277
00278 int getNum() const { return indx; }
00279
00280 private:
00281 int n;
00282 int indx;
00283 AtomGrid* grid;
00284 int* shuffle_vec;
00285 Vector3D* items;
00286 static int* scramble_array(const int n);
00287 };
00288
00289
00290
00291
00292
00293
00294 class AtomGridCell {
00295 public:
00296 AtomGridCell(AtomGrid* in_ag, int in_mina, int in_maxa, int in_minb,
00297 int in_maxb, int in_minc, int in_maxc)
00298 {
00299
00300
00301
00302
00303
00304 ag = in_ag;
00305 mina = in_mina;
00306 maxa = in_maxa;
00307 minb = in_minb;
00308 maxb = in_maxb;
00309 minc = in_minc;
00310 maxc = in_maxc;
00311
00312 na = maxa-mina+1;
00313 nb = maxb-minb+1;
00314 nc = maxc-minc+1;
00315
00316 noneset = true;
00317 getlistcalled = false;
00318 cellmap = 0;
00319 count=0;
00320 gridlist=0;
00321 }
00322
00323 ~AtomGridCell()
00324 {
00325 if (cellmap != 0)
00326 delete [] cellmap;
00327 }
00328
00329 int set(const int i, const int j, const int k);
00330 bool get(const int i, const int j, const int k) const;
00331 const GridList* get_list();
00332
00333 private:
00334 void build_list();
00335 AtomGrid* ag;
00336 int mina;
00337 int maxa;
00338 int minb;
00339 int maxb;
00340 int minc;
00341 int maxc;
00342 int na;
00343 int nb;
00344 int nc;
00345 bool noneset;
00346 bool getlistcalled;
00347 bool* cellmap;
00348 int count;
00349 GridList* gridlist;
00350 };
00351
00352
00353
00354
00355 class AtomGrid {
00356 public:
00357 AtomGrid(const MolData* mdata);
00358
00359 ~AtomGrid() {
00360 int i,j,k;
00361 for(i=0; i < cna; i++)
00362 for(j=0; j < cnb; j++)
00363 for(k=0; k < cnc; k++) {
00364 delete cellgrid[((i*cnb)+j)*cnc+k];
00365 }
00366 delete [] cellgrid;
00367 delete [] celli;
00368 delete [] cellj;
00369 delete [] cellk;
00370 }
00371
00372
00373
00374
00375 bool get(const int i, const int j, const int k) const
00376 {
00377
00378 bool ret;
00379 if (i >= 0 && i < na && j >= 0 && j < nb && k >= 0 && k < nc) {
00380 const int ii = celli[i];
00381 const int jj = cellj[j];
00382 const int kk = cellk[k];
00383 const int indx = ((ii*cnb)+jj)*cnc+kk;
00384 ret = cellgrid[indx]->get(i,j,k);
00385 } else {
00386 ret = false;
00387 }
00388 return ret;
00389 }
00390
00391
00392
00393
00394 int set(const int i, const int j, const int k) {
00395
00396 if ( i < 0 || i >= na || j < 0 || j >= nb || k < 0 || k >= nc )
00397 return -1;
00398
00399 const int ii = celli[i];
00400 const int jj = cellj[j];
00401 const int kk = cellk[k];
00402 return cellgrid[((ii*cnb)+jj)*cnc+kk]->set(i,j,k);
00403 }
00404
00405
00406
00407
00408
00409
00410 Vector3D get_ijk(const Vector3D vv) const
00411 {
00412 Vector3D ijk;
00413 const Vector3D v = vv - origin;
00414
00415
00416
00417 ijk.x = (inv_abc[0][0] * v.x + inv_abc[0][1] * v.y + inv_abc[0][2] * v.z)
00418 * na;
00419 ijk.y = (inv_abc[1][0] * v.x + inv_abc[1][1] * v.y + inv_abc[1][2] * v.z)
00420 * nb;
00421 ijk.z = (inv_abc[2][0] * v.x + inv_abc[2][1] * v.y + inv_abc[2][2] * v.z)
00422 * nc;
00423
00424 return ijk;
00425 }
00426
00427
00428
00429
00430
00431
00432 void get_cijk(const Vector3D vv, int& i, int& j, int& k) const
00433 {
00434 Vector3D ijk = get_ijk(vv);
00435
00436 ijk.x = fmod(ijk.x,na);
00437 if (ijk.x < 0)
00438 ijk.x += na;
00439 ijk.y = fmod(ijk.y,nb);
00440 if (ijk.y < 0)
00441 ijk.y += nb;
00442 ijk.z = fmod(ijk.z,nc);
00443 if (ijk.z < 0)
00444 ijk.z += nc;
00445
00446 i = celli[(int)(floor(ijk.x))];
00447 j = cellj[(int)(floor(ijk.y))];
00448 k = cellk[(int)(floor(ijk.z))];
00449 return;
00450 }
00451
00452
00453
00454
00455
00456
00457 Vector3D get_xyz(const Vector3D ijk) const
00458 {
00459 Vector3D v = grida * ijk.x / na + gridb * ijk.y / nb + gridc * ijk.z / nc
00460 + origin;
00461 return v;
00462 }
00463
00464
00465
00466
00467
00468 Vector3D get_xyz(const int i, const int j, const int k) const
00469 {
00470 const double id = (i+0.5) / na;
00471 const double jd = (j+0.5) / nb;
00472 const double kd = (k+0.5) / nc;
00473
00474 Vector3D v = grida * id + gridb * jd + gridc * kd + origin;
00475 return v;
00476 }
00477
00478
00479
00480
00481
00482 const GridList* get_cell(const int i, const int j, const int k) const
00483 {
00484 if (i>=0 && i<cna && j>=0 && j<cnb && k>=0 && k<cnc) {
00485 return cellgrid[((i*cnb)+j)*cnc+k]->get_list();
00486 }
00487 return 0;
00488 }
00489
00490 Vector3D wrap_xyz(const Vector3D xyz) const
00491 {
00492 Vector3D gridcoord = get_ijk(xyz);
00493 gridcoord.x = fmod(gridcoord.x,na);
00494 if (gridcoord.x < 0)
00495 gridcoord.x += na;
00496 gridcoord.y = fmod(gridcoord.y,nb);
00497 if (gridcoord.y < 0)
00498 gridcoord.y += nb;
00499 gridcoord.z = fmod(gridcoord.z,nc);
00500 if (gridcoord.z < 0)
00501 gridcoord.z += nc;
00502
00503 const Vector3D ret = get_xyz(gridcoord);
00504
00505
00506
00507
00508
00509 return ret;
00510 }
00511
00512 int get_na() const { return na; }
00513 int get_nb() const { return nb; }
00514 int get_nc() const { return nc; }
00515
00516 int get_cna() const { return cna; }
00517 int get_cnb() const { return cnb; }
00518 int get_cnc() const { return cnc; }
00519
00520 Vector3D findAtomBox(const double radius) const;
00521 void build(const MolData* mol_data);
00522 void store(char* fname);
00523 void print();
00524 static int* scramble_array(const int n);
00525
00526 private:
00527 void Inverse3(const double m[3][3], double inv[3][3]) const;
00528 double Cofactor3(const double mat[3][3],const int i, const int j) const;
00529
00530
00531 Vector3D origin;
00532 Vector3D grida;
00533 Vector3D gridb;
00534 Vector3D gridc;
00535 double inv_abc[3][3];
00536 int na;
00537 int nb;
00538 int nc;
00539
00540 int cna;
00541 int cnb;
00542 int cnc;
00543 AtomGridCell** cellgrid;
00544 int* celli;
00545 int* cellj;
00546 int* cellk;
00547 bool periodic;
00548 };
00549
00550 MolData* MolData::readFile(const char* fname,
00551 double gridspacing, double radius, double threshold)
00552 {
00553 MolData *data = new MolData;
00554 data->gridspacing = gridspacing;
00555 data->radius = radius;
00556 data->threshold = threshold;
00557 data->actual_radius = radius+threshold;
00558
00559
00560 FILE* inpf = fopen(fname,"r");
00561 if (inpf == NULL) {
00562 printf("Couldn't open file %s\n",fname);
00563 exit(-1);
00564 }
00565
00566 int n_read=0;
00567 n_read += fscanf(inpf,"%lf %lf %lf",
00568 &(data->origin.x),&(data->origin.y),&(data->origin.z));
00569 n_read += fscanf(inpf,"%lf %lf %lf",
00570 &(data->basisa.x),&(data->basisa.y),&(data->basisa.z));
00571 n_read += fscanf(inpf,"%lf %lf %lf",
00572 &(data->basisb.x),&(data->basisb.y),&(data->basisb.z));
00573 n_read += fscanf(inpf,"%lf %lf %lf",
00574 &(data->basisc.x),&(data->basisc.y),&(data->basisc.z));
00575 n_read += fscanf(inpf,"%d",&(data->count));
00576
00577 if (n_read != 13) {
00578 printf("Error reading header (%d)",n_read);
00579 exit(-2);
00580 }
00581
00582 data->coords = new AtomData[data->count];
00583 int i;
00584 for(i=0; i<data->count; i++) {
00585 n_read = fscanf(inpf,"%d %lf %lf %lf",
00586 &(data->coords[i].index),
00587 &(data->coords[i].coord.x),
00588 &(data->coords[i].coord.y),
00589 &(data->coords[i].coord.z));
00590 if (n_read != 4) {
00591 printf("Error reading atom %d (%d)",i,n_read);
00592 exit(-2);
00593 }
00594 }
00595 fclose(inpf);
00596 return data;
00597 }
00598
00599 MolData* MolData::readData(const int *indx, const float *coords,
00600 const int count,
00601 const Vector3D o,
00602 const Vector3D a,
00603 const Vector3D b,
00604 const Vector3D c,
00605 const double gridspacing,
00606 const double radius,
00607 const double threshold,
00608 const bool periodic)
00609 {
00610 MolData *data = new MolData;
00611 data->gridspacing = gridspacing;
00612 data->radius = radius;
00613 data->threshold = threshold;
00614 data->actual_radius = radius+threshold;
00615 data->periodic = periodic;
00616
00617 data->origin=o;
00618 data->basisa = a;
00619 data->basisb = b;
00620 data->basisc = c;
00621 data->count = count;
00622
00623 data->coords = new AtomData[data->count];
00624 int i;
00625 int ind=0;
00626 for(i=0; i<data->count; i++) {
00627 data->coords[i].index = indx[i];
00628 data->coords[i].coord.x = coords[ind];
00629 data->coords[i].coord.y = coords[ind+1];
00630 data->coords[i].coord.z = coords[ind+2];
00631 ind += 3;
00632 }
00633 return data;
00634 }
00635
00636
00637 void MolData::wrapCoords(const AtomGrid* grid)
00638 {
00639 int i;
00640 for(i=0; i < count; i++) {
00641 coords[i].coord = grid->wrap_xyz(coords[i].coord);
00642 }
00643 }
00644
00645 int GridList::add(const int i, const int j, const int k)
00646 {
00647 if (indx >= n)
00648 return -1;
00649
00650 const int i2 = shuffle_vec[indx];
00651 items[i2].x = i;
00652 items[i2].y = j;
00653 items[i2].z = k;
00654 indx++;
00655 return indx-1;
00656 }
00657
00658 int AtomGridCell::set(const int i, const int j, const int k)
00659 {
00660 if (i<mina || i>maxa || j<minb || j>maxb || k<minc || k>maxc ) {
00661 return -1;
00662 }
00663 if (getlistcalled) {
00664 return -2;
00665 }
00666
00667 if (noneset) {
00668 cellmap = new bool[na*nb*nc];
00669 int m;
00670 for(m=na*nb*nc-1; m >= 0; m--)
00671 cellmap[m] = false;
00672 noneset = false;
00673
00674 }
00675
00676 const int ii = i - mina;
00677 const int jj = j - minb;
00678 const int kk = k - minc;
00679 const int indx = ((ii*nb)+jj)*nc+kk;
00680 if (!cellmap[indx]) {
00681 count++;
00682 }
00683 cellmap[indx] = true;
00684
00685 return 0;
00686 }
00687
00688
00689 bool AtomGridCell::get(const int i, const int j, const int k) const
00690 {
00691
00692
00693
00694 if (i<mina || i>maxa || j<minb || j>maxb || k<minc || k>maxc )
00695 return false;
00696
00697 if (noneset)
00698 return false;
00699
00700 const int ii = i - mina;
00701 const int jj = j - minb;
00702 const int kk = k - minc;
00703 return cellmap[((ii*nb)+jj)*nc+kk];
00704 }
00705
00706 const GridList* AtomGridCell::get_list()
00707 {
00708 if (!getlistcalled) {
00709 build_list();
00710 }
00711 return gridlist;
00712 }
00713
00714 void AtomGridCell::build_list()
00715 {
00716
00717 getlistcalled = true;
00718 int sz = na*nb*nc;
00719 bool* vac = new bool[sz];
00720 int i;
00721 for (i=0; i < sz; i++)
00722 vac[i] = false;
00723
00724 int tot=0;
00725 int grid_idx = 0;
00726 for(i=mina; i <= maxa; i++) {
00727
00728 int j;
00729 for(j=minb; j <= maxb; j++) {
00730
00731 int k;
00732 for(k=minc; k <= maxc; grid_idx++, k++) {
00733 if (!get(i,j,k)) {
00734
00735
00736
00737 bool all_vac = true;
00738 if (i > mina && i < maxa
00739 && j > minb && j < maxb
00740 && k > minc && k < maxc) {
00741 int ii;
00742 for(ii=-1; ii <= 1; ii++) {
00743 int jj;
00744 for(jj=-1; jj <= 1; jj++) {
00745 int kk;
00746 for(kk=-1; kk <= 1; kk++) {
00747 if (get(i+ii,j+jj,k+kk)) {
00748
00749
00750 all_vac = false;
00751 break;
00752 }
00753 }
00754 if (!all_vac)
00755 break;
00756 }
00757 if (!all_vac)
00758 break;
00759 }
00760 } else {
00761 all_vac = false;
00762 }
00763 if (!all_vac) {
00764
00765 vac[grid_idx] = true;
00766 tot++;
00767
00768 }
00769 }
00770 }
00771
00772 }
00773 }
00774 gridlist = new GridList(ag,tot);
00775 grid_idx = 0;
00776 int gi;
00777 for(gi=mina; gi <= maxa; gi++) {
00778 int gj;
00779 for(gj=minb; gj <= maxb; gj++) {
00780 int gk;
00781 for(gk=minc; gk <= maxc; grid_idx++, gk++) {
00782 if (vac[grid_idx]) {
00783
00784 gridlist->add(gi,gj,gk);
00785 }
00786 }
00787 }
00788 }
00789
00790
00791 delete [] vac;
00792 }
00793
00794 AtomGrid::AtomGrid(const MolData* mdata)
00795 {
00796
00797
00798
00799 origin = mdata->origin;
00800 grida = mdata->basisa;
00801 gridb = mdata->basisb;
00802 gridc = mdata->basisc;
00803 na = (int)ceil(mdata->basisa.length() / mdata->gridspacing);
00804 nb = (int)ceil(mdata->basisb.length() / mdata->gridspacing);
00805 nc = (int)ceil(mdata->basisc.length() / mdata->gridspacing);
00806 periodic = mdata->periodic;
00807
00808
00809
00810
00811 printf("Grid %d %d %d\n",na,nb,nc);
00812 printf("Origin %f %f %f\n",origin.x,origin.y,origin.z);
00813
00814 double a[3][3];
00815
00816 a[0][0] = grida.x;
00817 a[0][1] = gridb.x;
00818 a[0][2] = gridc.x;
00819 a[1][0] = grida.y;
00820 a[1][1] = gridb.y;
00821 a[1][2] = gridc.y;
00822 a[2][0] = grida.z;
00823 a[2][1] = gridb.z;
00824 a[2][2] = gridc.z;
00825 Inverse3(a,this->inv_abc);
00826
00827 printf("a...\n");
00828 printf("%f %f %f\n",a[0][0],a[0][1],a[0][2]);
00829 printf("%f %f %f\n",a[1][0],a[1][1],a[1][2]);
00830 printf("%f %f %f\n",a[2][0],a[2][1],a[2][2]);
00831
00832 printf("inv a...\n");
00833 printf("%f %f %f\n",inv_abc[0][0],inv_abc[0][1],inv_abc[0][2]);
00834 printf("%f %f %f\n",inv_abc[1][0],inv_abc[1][1],inv_abc[1][2]);
00835 printf("%f %f %f\n",inv_abc[2][0],inv_abc[2][1],inv_abc[2][2]);
00836
00837
00838 Vector3D cellsz = findAtomBox(mdata->getActualRadius());
00839 printf("cellsz=%f, %f, %f\n",cellsz.x,cellsz.y,cellsz.z);
00840
00841 cna = (int)(floor(na/cellsz.x));
00842 cnb = (int)(floor(nb/cellsz.y));
00843 cnc = (int)(floor(nc/cellsz.z));
00844 if (cna==0) {
00845 cna = 1;
00846 }
00847 if (cnb==0) {
00848 cnb = 1;
00849 }
00850 if (cnc==0) {
00851 cnc = 1;
00852 }
00853
00854 printf("na=%d, %d, %d\n",na,nb,nc);
00855 printf("cna=%d, %d, %d\n",cna,cnb,cnc);
00856
00857
00858 cellgrid = new AtomGridCell*[cna*cnb*cnc];
00859
00860 celli = new int[na+1];
00861 celli[na] = cna;
00862 cellj = new int[nb+1];
00863 cellj[nb] = cnb;
00864 cellk = new int[nc+1];
00865 cellk[nc] = cnc;
00866
00867 int* gridi = new int[cna+1];
00868 gridi[cna] = na;
00869 int* gridj = new int[cnb+1];
00870 gridj[cnb] = nb;
00871 int* gridk = new int[cnc+1];
00872 gridk[cnc] = nc;
00873
00874
00875 int mina = 0;
00876 int maxa;
00877 int i;
00878 for(i=0; i < cna; i++) {
00879 maxa = ((i+1) * na) / cna - 1;
00880
00881 int ii;
00882 for(ii=mina; ii<= maxa; ii++) {
00883 celli[ii] = i;
00884
00885 }
00886 gridi[i] = mina;
00887 int minb = 0;
00888 int maxb;
00889 int j;
00890 for(j=0; j < cnb; j++) {
00891 maxb = ((j+1) * nb) / cnb - 1;
00892 if (i==0) {
00893 for(int jj=minb; jj<= maxb; jj++)
00894 cellj[jj] = j;
00895 }
00896 gridj[j] = minb;
00897 int minc = 0;
00898 int maxc;
00899 int k;
00900 for(k=0; k < cnc; k++) {
00901 maxc = ((k+1) * nc) / cnc - 1;
00902 if (i==0 && j==0) {
00903 for(int kk=minc; kk<= maxc; kk++)
00904 cellk[kk] = k;
00905 }
00906 gridk[k] = minc;
00907 minc = maxc+1;
00908 }
00909 minb = maxb+1;
00910 }
00911 mina = maxa+1;
00912 }
00913
00914
00915 int ci;
00916 for(ci=0; ci < cna; ci++) {
00917 int cj;
00918 for(cj=0; cj < cnb; cj++) {
00919 int ck;
00920 for(ck=0; ck < cnc; ck++) {
00921
00922 cellgrid[((ci*cnb)+cj) * cnc + ck]
00923 = new AtomGridCell(this,gridi[ci],gridi[ci+1]-1,
00924 gridj[cj],gridj[cj+1]-1,
00925 gridk[ck],gridk[ck+1]-1);
00926 }
00927 }
00928 }
00929 delete[] gridi;
00930 delete[] gridj;
00931 delete[] gridk;
00932 }
00933
00934 int* GridList::scramble_array(const int n) {
00935 return AtomGrid::scramble_array(n);
00936 }
00937
00938 int* AtomGrid::scramble_array(const int n)
00939 {
00940 if (n < 1) return 0;
00941
00942 int* a = new int[n];
00943 a[0]=n-1;
00944 if (n == 1) return a;
00945 a[1] = 0;
00946 if (n == 2) return a;
00947
00948 bool* b = new bool[n];
00949 int i;
00950 for(i=0; i<n; i++)
00951 b[i] = true;
00952
00953 int howmany = 1;
00954 int incr = (n >> 1);
00955
00956
00957 int nxt=2;
00958 while (nxt < n) {
00959 int i;
00960 for (i=0; i < howmany; i++) {
00961
00962 int nxtval = a[i+1] + incr;
00963
00964 if (b[nxtval]) {
00965 a[nxt++] = nxtval;
00966
00967 b[nxtval] = false;
00968 }
00969
00970 if (nxt > n-1)
00971 break;
00972 }
00973 howmany <<= 1;
00974 incr >>= 1;
00975 if (incr == 0)
00976 break;
00977 }
00978 for(i=1; i < n; i++) {
00979 if (nxt >= n) break;
00980 if (b[i])
00981 a[nxt++] = i;
00982 }
00983 delete [] b;
00984
00985 return a;
00986 }
00987
00988 Vector3D AtomGrid::findAtomBox(const double radius) const
00989 {
00990
00991 Vector3D cornerx[8];
00992 Vector3D dx, dy, dz;
00993
00994 const Vector3D o = origin;
00995 dx.y = dx.z = dy.x = dy.z = dz.x = dz.y = 0;
00996 dx.x = dy.y = dz.z = radius;
00997 cornerx[0] = o;
00998 cornerx[1] = o + dx;
00999 cornerx[2] = o + dy;
01000 cornerx[3] = o + dz;
01001 cornerx[4] = cornerx[1] + dy;
01002 cornerx[5] = cornerx[1] + dz;
01003 cornerx[6] = cornerx[2] + dz;
01004 cornerx[7] = cornerx[4] + dz;
01005
01006
01007 Vector3D ijk = get_ijk(cornerx[0]);
01008 double dimax = ijk.x;
01009 double djmax = ijk.y;
01010 double dkmax = ijk.z;
01011
01012 int i;
01013 for(i=1; i < 8; i++) {
01014 ijk = get_ijk(cornerx[i]);
01015 if (ijk.x > dimax)
01016 dimax = ijk.x;
01017 if (ijk.y > djmax)
01018 djmax = ijk.y;
01019 if (ijk.z > dkmax)
01020 dkmax = ijk.z;
01021 }
01022 Vector3D vec;
01023
01024 vec.x = dimax;
01025 vec.y = djmax;
01026 vec.z = dkmax;
01027
01028 return vec;
01029 }
01030
01031 void AtomGrid::build(const MolData* mdata)
01032 {
01033
01034
01035 Vector3D bb = findAtomBox(mdata->getRadius());
01036
01037 const int imax = (int)ceil(bb.x);
01038 const int jmax = (int)ceil(bb.y);
01039 const int kmax = (int)ceil(bb.z);
01040
01041 printf("Box=%d, %d, %d\n",imax,jmax,kmax);
01042 const double rsq = mdata->getRadius() * mdata->getRadius();
01043 int atomi;
01044 for(atomi=0; atomi<mdata->count; atomi++) {
01045 Vector3D atom = mdata->coords[atomi].coord;
01046
01047 Vector3D atomijk = get_ijk(atom);
01048 const int ai = (int)atomijk.x;
01049 const int aj = (int)atomijk.y;
01050 const int ak = (int)atomijk.z;
01051 int i;
01052 for(i=ai-imax; i <= ai+imax; i++) {
01053 int ii = i;
01054 if (i < 0) {
01055 if (periodic) {
01056 ii += na;
01057 } else continue;
01058 } else if (i >= na) {
01059 if (periodic) {
01060 ii -= na;
01061 } else continue;
01062 }
01063 int j;
01064 for(j=aj-jmax; j <= aj+jmax; j++) {
01065 int jj = j;
01066 if (j < 0) {
01067 if (periodic) {
01068 jj += nb;
01069 } else continue;
01070 } else if (j >= nb) {
01071 if (periodic) {
01072 jj -= nb;
01073 } else continue;
01074 }
01075
01076
01077 int k;
01078 for(k=0; k <= kmax; k++) {
01079 int k_no_wrap = ak+k;
01080 int kk = k_no_wrap;
01081 if (k_no_wrap < 0) {
01082 if (periodic) {
01083 kk += nc;
01084 } else continue;
01085 } else if (k_no_wrap >= nc) {
01086 if (periodic) {
01087 kk -= nc;
01088 } else continue;
01089 }
01090
01091
01092 if (get(ii,jj,kk))
01093 continue;
01094
01095 const Vector3D v = get_xyz(i,j,k_no_wrap);
01096 const Vector3D dv = v - atom;
01097 if (dv.length2() <= rsq) {
01098 set(ii,jj,kk);
01099 } else {
01100 break;
01101 }
01102 }
01103 for(k=1; k <= kmax; k++) {
01104 int k_no_wrap = ak-k;
01105 int kk = k_no_wrap;
01106 if (k_no_wrap < 0) {
01107 if (periodic) {
01108 kk += nc;
01109 } else continue;
01110 } else if (k_no_wrap >= nc) {
01111 if (periodic) {
01112 kk -= nc;
01113 } else continue;
01114 }
01115
01116
01117 if (get(ii,jj,kk))
01118 continue;
01119
01120 const Vector3D v = get_xyz(i,j,k_no_wrap);
01121 const Vector3D dv = v - atom;
01122 if (dv.length2() <= rsq) {
01123 set(ii,jj,kk);
01124 } else {
01125 break;
01126 }
01127 }
01128 }
01129 }
01130 }
01131 return;
01132 }
01133
01134 void AtomGrid::print()
01135 {
01136 int k;
01137 for(k=0;k < nc; k++) {
01138 int i;
01139 for(i=0; i < na; i++) {
01140 printf("%d:",i);
01141 int j;
01142 for(j=0; j < nb; j++) {
01143 if (get(i,j,k))
01144 printf("1");
01145 else printf("0");
01146 }
01147 printf("\n");
01148 }
01149 printf("%d:-------------------------------------------------------\n",k);
01150 }
01151 }
01152
01153 void AtomGrid::store(char* fname)
01154 {
01155 FILE* outf = fopen(fname,"w");
01156 if (outf == NULL) {
01157 printf("Couldn't open file %s\n",fname);
01158 exit(-1);
01159 }
01160
01161 int k;
01162 for(k=0;k < nc; k++) {
01163 int i;
01164 for(i=0; i < na; i++) {
01165 int j;
01166 for(j=0; j < nb; j++) {
01167 if (!get(i,j,k)) {
01168 Vector3D v = get_xyz(i,j,k);
01169 if (fprintf(outf,"%f %f %f\n",v.x,v.y,v.z) < 0) {
01170 printf("Store grid error %s\n",fname);
01171 exit(-2);
01172 }
01173 }
01174 }
01175 }
01176 }
01177
01178 fclose(outf);
01179 return;
01180 }
01181
01182 void AtomGrid::Inverse3(const double m[3][3], double inv[3][3]) const
01183 {
01184
01185 int i,j;
01186 for(i=0; i < 3; i++)
01187 for(j=0; j < 3; j++)
01188 inv[i][j] = Cofactor3(m,i,j);
01189
01190
01191 const double det = m[0][0] * inv[0][0]
01192 + m[0][1] * inv[1][0]
01193 + m[0][2] * inv[2][0];
01194
01195
01196
01197
01198
01199 for(i=0; i < 3; i++)
01200 for(j=0; j < 3; j++)
01201 inv[i][j] /= det;
01202
01203 return;
01204 }
01205
01206 double AtomGrid::Cofactor3(const double mat[3][3],
01207 const int i, const int j) const {
01208 int cols[3][2] = { {1,2}, {0,2}, {0,1}};
01209
01210 const int row1 = cols[j][0];
01211 const int row2 = cols[j][1];
01212
01213 const int col1 = cols[i][0];
01214 const int col2 = cols[i][1];
01215
01216 const double a = mat[row1][col1];
01217 const double b = mat[row1][col2];
01218 const double c = mat[row2][col1];
01219 const double d = mat[row2][col2];
01220
01221 const double det = a*d-b*c;
01222 if (((i+j) % 2) != 0)
01223 return -det;
01224 else
01225 return det;
01226 }
01227
01228 AtomList* MolData::findAtomsGrid(const AtomGrid* grid)
01229 {
01230
01231 AtomList *al = new AtomList(count);
01232 const double r = getActualRadius();
01233 const double rsq = r*r;
01234 const Vector3D atom_box = grid->findAtomBox(radius);
01235 int atomi;
01236 for(atomi=0; atomi<count; atomi++) {
01237 Vector3D atom = coords[atomi].coord;
01238
01239 int i0, j0, k0;
01240 bool found = false;
01241
01242 grid->get_cijk(atom,i0,j0,k0);
01243 int di;
01244 bool cell_outside = false;
01245 for(di=-1; !found && di <= 1; di++) {
01246 int ci = i0 + di;
01247 int cna = grid->get_cna();
01248 int wrapi = 0;
01249 if (ci<0) {
01250 ci += cna;
01251 wrapi = grid->get_na();
01252 if (!periodic)
01253 cell_outside = true;
01254 } else if (ci >= cna) {
01255 ci -= cna;
01256 wrapi = -grid->get_na();
01257 if (!periodic)
01258 cell_outside = true;
01259 }
01260 int dj;
01261 for(dj=-1; !found && dj <= 1; dj++) {
01262 int cj = j0 + dj;
01263 int cnb = grid->get_cnb();
01264 int wrapj = 0;
01265 if (cj<0) {
01266 cj += cnb;
01267 wrapj = grid->get_nb();
01268 if (!periodic)
01269 cell_outside = true;
01270 } else if (cj >= cnb) {
01271 cj -= cnb;
01272 wrapj = grid->get_nb();
01273 if (!periodic)
01274 cell_outside = true;
01275 }
01276 int dk;
01277 for(dk=-1; !found && dk <= 1; dk++) {
01278 int ck = k0 + dk;
01279 int cnc = grid->get_cnc();
01280 int wrapk = 0;
01281 if (ck<0) {
01282 ck += cnc;
01283 wrapk = grid->get_nc();
01284 if (!periodic)
01285 cell_outside = true;
01286 } else if (ck >= cnc) {
01287 ck -= cnc;
01288 wrapk = -grid->get_nc();
01289 if (!periodic)
01290 cell_outside = true;
01291 }
01292
01293
01294 if (!periodic && cell_outside) {
01295 const Vector3D atom_grid = grid->get_ijk(atom);
01296 const Vector3D corner0 = atom_grid - atom_box;
01297 bool addit = false;
01298 if (corner0.x < 0 || corner0.y < 0 || corner0.z < 0) {
01299 addit = true;
01300 } else {
01301 const Vector3D corner1 = atom_grid + atom_box;
01302 if (corner1.x >= grid->get_na()
01303 || corner1.y >= grid->get_nb()
01304 || corner1.z >= grid->get_nc() )
01305 addit = true;
01306 }
01307 if (addit) {
01308 al->add(coords[atomi].index);
01309 found = true;
01310 }
01311 cell_outside = false;
01312 }
01313 const GridList* list = grid->get_cell(ci,cj,ck);
01314
01315
01316
01317 int gli;
01318 for(gli=0; !found && gli < list->getNum(); gli++) {
01319 Vector3D gridpt = list->get(gli);
01320 gridpt.x += wrapi;
01321 gridpt.y += wrapj;
01322 gridpt.z += wrapk;
01323 const Vector3D v = grid->get_xyz(gridpt);
01324 const Vector3D dv = v - atom;
01325 if (dv.length2() <= rsq) {
01326 al->add(coords[atomi].index);
01327 found = true;
01328
01329 }
01330 }
01331 }
01332 }
01333 }
01334 }
01335 return al;
01336 }
01337
01338 int msmain(int argc,char *argv[])
01339 {
01340 if ( argc != 6 ) {
01341 printf(
01342 "Usage: %s grid-res vac-radius selection-dist coord-file index-file\n",
01343 argv[0]);
01344 return 0;
01345 }
01346
01347 double res = strtod(argv[1],NULL);
01348 double radius = strtod(argv[2],NULL);
01349 double select_dist = strtod(argv[3],NULL);
01350
01351 printf("Reading\n");
01352 MolData* mol_data = MolData::readFile(argv[4],res,radius,select_dist);
01353 printf("Building grid\n");
01354 AtomGrid* atom_grid = new AtomGrid(mol_data);
01355 mol_data->wrapCoords(atom_grid);
01356 atom_grid->build(mol_data);
01357
01358
01359
01360
01361 printf("Searching grid\n");
01362 AtomList* atom_list = mol_data->findAtomsGrid(atom_grid);
01363 printf("Storing\n");
01364 atom_list->storeFile(argv[5]);
01365
01366 delete atom_list;
01367 delete atom_grid;
01368 delete mol_data;
01369
01370 return 0;
01371 }
01372
01373 void measure_surface_int(const double res, const double radius,
01374 const double select_dist,
01375 const bool periodic,
01376 const double a, const double b, const double c,
01377 const double alpha, const double beta, const double gamma,
01378 int *indices, float *coords, int count,
01379 int **surf, int *n_surf
01380 )
01381 {
01382 if (periodic)
01383 printf("System periodic\n");
01384 else printf("System not periodic\n");
01385
01386 printf("Reading\n");
01387 Vector3D uo;
01388 Vector3D ua;
01389 Vector3D ub;
01390 Vector3D uc;
01391
01392
01393 double xmin = coords[0];
01394 double xmax = coords[0];
01395 double ymin = coords[1];
01396 double ymax = coords[1];
01397 double zmin = coords[2];
01398 double zmax = coords[2];
01399 int ind;
01400 int i;
01401 for(i=1, ind=3; i < count; i++, ind += 3) {
01402 if (coords[ind] < xmin)
01403 xmin = coords[ind];
01404 if (coords[ind] > xmax)
01405 xmax = coords[ind];
01406 if (coords[ind+1] < ymin)
01407 ymin = coords[ind+1];
01408 if (coords[ind+1] > ymax)
01409 ymax = coords[ind+1];
01410 if (coords[ind+2] < zmin)
01411 zmin = coords[ind+2];
01412 if (coords[ind+2] > zmax)
01413 zmax = coords[ind+2];
01414 }
01415 uo.x = 0.5*(xmin+xmax);
01416 uo.y = 0.5*(ymin+ymax);
01417 uo.z = 0.5*(zmin+zmax);
01418
01419 double cosbc = cos(DEGTORAD(alpha));
01420 double cosac = cos(DEGTORAD(beta));
01421 double cosab = cos(DEGTORAD(gamma));
01422 double sinab = sin(DEGTORAD(gamma));
01423 ua.x = a; ua.y = 0; ua.z = 0;
01424 ub.x = b * cosab;
01425 ub.y = b * sinab;
01426 ub.z = 0;
01427
01428
01429 if (sinab > 0) {
01430 uc.x = cosac;
01431 uc.y = (cosbc - cosac * cosab) / sinab;
01432 uc.z = sqrt(1.0 - uc.x*uc.x - uc.y*uc.y);
01433 }
01434 uc = c * uc;
01435
01436 uo = uo - (0.5 * (ua + ub + uc));
01437
01438 MolData* mol_data = MolData::readData(indices, coords, count,
01439 uo, ua, ub, uc,
01440 res,radius,select_dist,periodic);
01441 printf("Building grid\n");
01442 AtomGrid* atom_grid = new AtomGrid(mol_data);
01443 mol_data->wrapCoords(atom_grid);
01444 atom_grid->build(mol_data);
01445
01446
01447
01448
01449 printf("Searching grid\n");
01450 AtomList* atom_list = mol_data->findAtomsGrid(atom_grid);
01451 printf("Storing\n");
01452 atom_list->storeData(surf,n_surf);
01453
01454 delete atom_list;
01455 delete atom_grid;
01456 delete mol_data;
01457
01458 return;
01459 }
01460
01461 int measure_surface(AtomSel *sel, MoleculeList *mlist,
01462 const float *framepos,
01463 const double gridsz,
01464 const double radius,
01465 const double depth,
01466 int **surface, int *n_surf ) {
01467 int i;
01468
01469 if (!sel) return MEASURE_ERR_NOSEL;
01470 if (sel->num_atoms == 0) return MEASURE_ERR_NOATOMS;
01471
01472
01473 int sel_count = 0;
01474 for(i=0; i < sel->num_atoms; i++) {
01475 if (sel->on[i]) {
01476 sel_count++;
01477 }
01478 }
01479 int *sel_ind = new int[sel_count];
01480 float *coords = new float[sel_count*3];
01481 int j=0;
01482 int k=0;
01483 int ind=0;
01484 for(i=0; i < sel->num_atoms; i++) {
01485 if (sel->on[i]) {
01486 sel_ind[j++] = i;
01487 coords[k++] = framepos[ind];
01488 coords[k++] = framepos[ind+1];
01489 coords[k++] = framepos[ind+2];
01490 }
01491 ind += 3;
01492 }
01493
01494 Timestep *ts = sel->timestep(mlist);
01495 double a = ts->a_length;
01496 double b = ts->b_length;
01497 double c = ts->c_length;
01498 double alpha = ts->alpha;
01499 double beta = ts->beta;
01500 double gamma = ts->gamma;
01501 bool periodic = true;
01502 if (a == 0 || b == 0 || c == 0
01503 || alpha == 0 || beta == 0 || gamma == 0) {
01504 periodic = false;
01505 float min_coord[3];
01506 float max_coord[3];
01507 measure_minmax(sel->num_atoms, sel->on, framepos, NULL, min_coord, max_coord);
01508 a = max_coord[0] - min_coord[0];
01509 b = max_coord[1] - min_coord[1];
01510 c = max_coord[2] - min_coord[2];
01511 alpha = beta = gamma = 90;
01512 }
01513
01514 printf("Periodic: %f %f %f %f %f %f\n",a,b,c,alpha,beta,gamma);
01515
01516 measure_surface_int(gridsz, radius, depth, periodic,
01517 a,b,c,alpha,beta,gamma,
01518 sel_ind,coords,sel_count,
01519 surface, n_surf);
01520
01521 printf("Done!\n");
01522
01523 return MEASURE_NOERR;
01524 }