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 Vector3D get(const int i) const {
00271 if (i < 0 || i >= n)
00272 return Vector3D();
00273
00274 return items[i];
00275 }
00276
00277 int getNum() const { return indx; }
00278
00279 private:
00280 int n;
00281 int indx;
00282 AtomGrid* grid;
00283 int* shuffle_vec;
00284 Vector3D* items;
00285 static int* scramble_array(const int n);
00286 };
00287
00288
00289
00290
00291
00292
00293 class AtomGridCell {
00294 public:
00295 AtomGridCell(AtomGrid* in_ag, int in_mina, int in_maxa, int in_minb,
00296 int in_maxb, int in_minc, int in_maxc)
00297 {
00298
00299
00300
00301
00302
00303 ag = in_ag;
00304 mina = in_mina;
00305 maxa = in_maxa;
00306 minb = in_minb;
00307 maxb = in_maxb;
00308 minc = in_minc;
00309 maxc = in_maxc;
00310
00311 na = maxa-mina+1;
00312 nb = maxb-minb+1;
00313 nc = maxc-minc+1;
00314
00315 noneset = true;
00316 getlistcalled = false;
00317 cellmap = 0;
00318 count=0;
00319 gridlist=0;
00320 }
00321
00322 ~AtomGridCell()
00323 {
00324 if (cellmap != 0)
00325 delete [] cellmap;
00326 }
00327
00328 int set(const int i, const int j, const int k);
00329 bool get(const int i, const int j, const int k) const;
00330 const GridList* get_list();
00331
00332 private:
00333 void build_list();
00334 AtomGrid* ag;
00335 int mina;
00336 int maxa;
00337 int minb;
00338 int maxb;
00339 int minc;
00340 int maxc;
00341 int na;
00342 int nb;
00343 int nc;
00344 bool noneset;
00345 bool getlistcalled;
00346 bool* cellmap;
00347 int count;
00348 GridList* gridlist;
00349 };
00350
00351
00352
00353
00354 class AtomGrid {
00355 public:
00356 AtomGrid(const MolData* mdata);
00357
00358 ~AtomGrid() {
00359 int i,j,k;
00360 for(i=0; i < cna; i++)
00361 for(j=0; j < cnb; j++)
00362 for(k=0; k < cnc; k++) {
00363 delete cellgrid[((i*cnb)+j)*cnc+k];
00364 }
00365 delete [] cellgrid;
00366 delete [] celli;
00367 delete [] cellj;
00368 delete [] cellk;
00369 }
00370
00371
00372
00373
00374 bool get(const int i, const int j, const int k) const
00375 {
00376
00377 bool ret;
00378 if (i >= 0 && i < na && j >= 0 && j < nb && k >= 0 && k < nc) {
00379 const int ii = celli[i];
00380 const int jj = cellj[j];
00381 const int kk = cellk[k];
00382 const int indx = ((ii*cnb)+jj)*cnc+kk;
00383 ret = cellgrid[indx]->get(i,j,k);
00384 } else {
00385 ret = false;
00386 }
00387 return ret;
00388 }
00389
00390
00391
00392
00393 int set(const int i, const int j, const int k) {
00394
00395 if ( i < 0 || i >= na || j < 0 || j >= nb || k < 0 || k >= nc )
00396 return -1;
00397
00398 const int ii = celli[i];
00399 const int jj = cellj[j];
00400 const int kk = cellk[k];
00401 return cellgrid[((ii*cnb)+jj)*cnc+kk]->set(i,j,k);
00402 }
00403
00404
00405
00406
00407
00408
00409 Vector3D get_ijk(const Vector3D vv) const
00410 {
00411 Vector3D ijk;
00412 const Vector3D v = vv - origin;
00413
00414
00415
00416 ijk.x = (inv_abc[0][0] * v.x + inv_abc[0][1] * v.y + inv_abc[0][2] * v.z)
00417 * na;
00418 ijk.y = (inv_abc[1][0] * v.x + inv_abc[1][1] * v.y + inv_abc[1][2] * v.z)
00419 * nb;
00420 ijk.z = (inv_abc[2][0] * v.x + inv_abc[2][1] * v.y + inv_abc[2][2] * v.z)
00421 * nc;
00422
00423 return ijk;
00424 }
00425
00426
00427
00428
00429
00430
00431 void get_cijk(const Vector3D vv, int& i, int& j, int& k) const
00432 {
00433 Vector3D ijk = get_ijk(vv);
00434
00435 ijk.x = fmod(ijk.x,na);
00436 if (ijk.x < 0)
00437 ijk.x += na;
00438 ijk.y = fmod(ijk.y,nb);
00439 if (ijk.y < 0)
00440 ijk.y += nb;
00441 ijk.z = fmod(ijk.z,nc);
00442 if (ijk.z < 0)
00443 ijk.z += nc;
00444
00445 i = celli[(int)(floor(ijk.x))];
00446 j = cellj[(int)(floor(ijk.y))];
00447 k = cellk[(int)(floor(ijk.z))];
00448 return;
00449 }
00450
00451
00452
00453
00454
00455
00456 Vector3D get_xyz(const Vector3D ijk) const
00457 {
00458 Vector3D v = grida * ijk.x / na + gridb * ijk.y / nb + gridc * ijk.z / nc
00459 + origin;
00460 return v;
00461 }
00462
00463
00464
00465
00466
00467 Vector3D get_xyz(const int i, const int j, const int k) const
00468 {
00469 const double id = (i+0.5) / na;
00470 const double jd = (j+0.5) / nb;
00471 const double kd = (k+0.5) / nc;
00472
00473 Vector3D v = grida * id + gridb * jd + gridc * kd + origin;
00474 return v;
00475 }
00476
00477
00478
00479
00480
00481 const GridList* get_cell(const int i, const int j, const int k) const
00482 {
00483 if (i>=0 && i<cna && j>=0 && j<cnb && k>=0 && k<cnc) {
00484 return cellgrid[((i*cnb)+j)*cnc+k]->get_list();
00485 }
00486 return 0;
00487 }
00488
00489 Vector3D wrap_xyz(const Vector3D xyz) const
00490 {
00491 Vector3D gridcoord = get_ijk(xyz);
00492 gridcoord.x = fmod(gridcoord.x,na);
00493 if (gridcoord.x < 0)
00494 gridcoord.x += na;
00495 gridcoord.y = fmod(gridcoord.y,nb);
00496 if (gridcoord.y < 0)
00497 gridcoord.y += nb;
00498 gridcoord.z = fmod(gridcoord.z,nc);
00499 if (gridcoord.z < 0)
00500 gridcoord.z += nc;
00501
00502 const Vector3D ret = get_xyz(gridcoord);
00503
00504
00505
00506
00507
00508 return ret;
00509 }
00510
00511 int get_na() const { return na; }
00512 int get_nb() const { return nb; }
00513 int get_nc() const { return nc; }
00514
00515 int get_cna() const { return cna; }
00516 int get_cnb() const { return cnb; }
00517 int get_cnc() const { return cnc; }
00518
00519 Vector3D findAtomBox(const double radius) const;
00520 void build(const MolData* mol_data);
00521 void store(char* fname);
00522 void print();
00523 static int* scramble_array(const int n);
00524
00525 private:
00526 void Inverse3(const double m[3][3], double inv[3][3]) const;
00527 double Cofactor3(const double mat[3][3],const int i, const int j) const;
00528
00529
00530 Vector3D origin;
00531 Vector3D grida;
00532 Vector3D gridb;
00533 Vector3D gridc;
00534 double inv_abc[3][3];
00535 int na;
00536 int nb;
00537 int nc;
00538
00539 int cna;
00540 int cnb;
00541 int cnc;
00542 AtomGridCell** cellgrid;
00543 int* celli;
00544 int* cellj;
00545 int* cellk;
00546 bool periodic;
00547 };
00548
00549
00550 MolData* MolData::readFile(const char* fname, double gridspacing,
00551 double radius, double threshold) {
00552 MolData *data = new MolData;
00553 data->gridspacing = gridspacing;
00554 data->radius = radius;
00555 data->threshold = threshold;
00556 data->actual_radius = radius+threshold;
00557
00558
00559 FILE* inpf = fopen(fname,"r");
00560 if (inpf == NULL) {
00561 printf("Couldn't open file %s\n",fname);
00562 exit(-1);
00563 }
00564
00565 int n_read=0;
00566 n_read += fscanf(inpf,"%lf %lf %lf",
00567 &(data->origin.x),&(data->origin.y),&(data->origin.z));
00568 n_read += fscanf(inpf,"%lf %lf %lf",
00569 &(data->basisa.x),&(data->basisa.y),&(data->basisa.z));
00570 n_read += fscanf(inpf,"%lf %lf %lf",
00571 &(data->basisb.x),&(data->basisb.y),&(data->basisb.z));
00572 n_read += fscanf(inpf,"%lf %lf %lf",
00573 &(data->basisc.x),&(data->basisc.y),&(data->basisc.z));
00574 n_read += fscanf(inpf,"%d",&(data->count));
00575
00576 if (n_read != 13) {
00577 printf("Error reading header (%d)",n_read);
00578 exit(-2);
00579 }
00580
00581 data->coords = new AtomData[data->count];
00582 int i;
00583 for (i=0; i<data->count; i++) {
00584 n_read = fscanf(inpf,"%d %lf %lf %lf",
00585 &(data->coords[i].index),
00586 &(data->coords[i].coord.x),
00587 &(data->coords[i].coord.y),
00588 &(data->coords[i].coord.z));
00589 if (n_read != 4) {
00590 printf("Error reading atom %d (%d)",i,n_read);
00591 exit(-2);
00592 }
00593 }
00594 fclose(inpf);
00595 return data;
00596 }
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 int i;
00639 for(i=0; i < count; i++) {
00640 coords[i].coord = grid->wrap_xyz(coords[i].coord);
00641 }
00642 }
00643
00644
00645 int GridList::add(const int i, const int j, const int k) {
00646 if (indx >= n)
00647 return -1;
00648
00649 const int i2 = shuffle_vec[indx];
00650 items[i2].x = i;
00651 items[i2].y = j;
00652 items[i2].z = k;
00653 indx++;
00654 return indx-1;
00655 }
00656
00657
00658 int AtomGridCell::set(const int i, const int j, const int k) {
00659 if (i<mina || i>maxa || j<minb || j>maxb || k<minc || k>maxc ) {
00660 return -1;
00661 }
00662 if (getlistcalled) {
00663 return -2;
00664 }
00665
00666 if (noneset) {
00667 cellmap = new bool[na*nb*nc];
00668 int m;
00669 for (m=na*nb*nc-1; m >= 0; m--)
00670 cellmap[m] = false;
00671 noneset = false;
00672
00673 }
00674
00675 const int ii = i - mina;
00676 const int jj = j - minb;
00677 const int kk = k - minc;
00678 const int indx = ((ii*nb)+jj)*nc+kk;
00679 if (!cellmap[indx]) {
00680 count++;
00681 }
00682 cellmap[indx] = true;
00683
00684 return 0;
00685 }
00686
00687
00688 bool AtomGridCell::get(const int i, const int j, const int k) const {
00689
00690
00691
00692 if (i<mina || i>maxa || j<minb || j>maxb || k<minc || k>maxc )
00693 return false;
00694
00695 if (noneset)
00696 return false;
00697
00698 const int ii = i - mina;
00699 const int jj = j - minb;
00700 const int kk = k - minc;
00701 return cellmap[((ii*nb)+jj)*nc+kk];
00702 }
00703
00704
00705 const GridList* AtomGridCell::get_list() {
00706 if (!getlistcalled) {
00707 build_list();
00708 }
00709 return gridlist;
00710 }
00711
00712
00713 void AtomGridCell::build_list() {
00714
00715 getlistcalled = true;
00716 int sz = na*nb*nc;
00717 bool* vac = new bool[sz];
00718 int i;
00719 for (i=0; i < sz; i++)
00720 vac[i] = false;
00721
00722 int tot=0;
00723 int grid_idx = 0;
00724 for(i=mina; i <= maxa; i++) {
00725
00726 int j;
00727 for (j=minb; j <= maxb; j++) {
00728
00729 int k;
00730 for (k=minc; k <= maxc; grid_idx++, k++) {
00731 if (!get(i,j,k)) {
00732
00733
00734
00735 bool all_vac = true;
00736 if (i > mina && i < maxa
00737 && j > minb && j < maxb
00738 && k > minc && k < maxc) {
00739 int ii;
00740 for (ii=-1; ii <= 1; ii++) {
00741 int jj;
00742 for (jj=-1; jj <= 1; jj++) {
00743 int kk;
00744 for (kk=-1; kk <= 1; kk++) {
00745 if (get(i+ii,j+jj,k+kk)) {
00746
00747
00748 all_vac = false;
00749 break;
00750 }
00751 }
00752 if (!all_vac)
00753 break;
00754 }
00755 if (!all_vac)
00756 break;
00757 }
00758 } else {
00759 all_vac = false;
00760 }
00761 if (!all_vac) {
00762
00763 vac[grid_idx] = true;
00764 tot++;
00765
00766 }
00767 }
00768 }
00769
00770 }
00771 }
00772 gridlist = new GridList(ag,tot);
00773 grid_idx = 0;
00774 int gi;
00775 for (gi=mina; gi <= maxa; gi++) {
00776 int gj;
00777 for (gj=minb; gj <= maxb; gj++) {
00778 int gk;
00779 for (gk=minc; gk <= maxc; grid_idx++, gk++) {
00780 if (vac[grid_idx]) {
00781
00782 gridlist->add(gi,gj,gk);
00783 }
00784 }
00785 }
00786 }
00787
00788
00789
00790
00791 delete [] vac;
00792 }
00793
00794
00795 AtomGrid::AtomGrid(const MolData* mdata) {
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
00930 delete[] gridi;
00931 delete[] gridj;
00932 delete[] gridk;
00933 }
00934
00935
00936 int* GridList::scramble_array(const int n) {
00937 return AtomGrid::scramble_array(n);
00938 }
00939
00940
00941 int* AtomGrid::scramble_array(const int n) {
00942 if (n < 1) return 0;
00943
00944 int* a = new int[n];
00945 a[0]=n-1;
00946 if (n == 1) return a;
00947 a[1] = 0;
00948 if (n == 2) return a;
00949
00950 bool* b = new bool[n];
00951 int i;
00952 for (i=0; i<n; i++)
00953 b[i] = true;
00954
00955 int howmany = 1;
00956 int incr = (n >> 1);
00957
00958
00959 int nxt=2;
00960 while (nxt < n) {
00961 int i;
00962 for (i=0; i < howmany; i++) {
00963
00964 int nxtval = a[i+1] + incr;
00965
00966 if (b[nxtval]) {
00967 a[nxt++] = nxtval;
00968
00969 b[nxtval] = false;
00970 }
00971
00972 if (nxt > n-1)
00973 break;
00974 }
00975 howmany <<= 1;
00976 incr >>= 1;
00977 if (incr == 0)
00978 break;
00979 }
00980
00981 for (i=1; i < n; i++) {
00982 if (nxt >= n) break;
00983 if (b[i])
00984 a[nxt++] = i;
00985 }
00986
00987 delete [] b;
00988 return a;
00989 }
00990
00991
00992 Vector3D AtomGrid::findAtomBox(const double radius) const {
00993
00994 Vector3D cornerx[8];
00995 Vector3D dx, dy, dz;
00996
00997 const Vector3D o = origin;
00998 dx.y = dx.z = dy.x = dy.z = dz.x = dz.y = 0;
00999 dx.x = dy.y = dz.z = radius;
01000 cornerx[0] = o;
01001 cornerx[1] = o + dx;
01002 cornerx[2] = o + dy;
01003 cornerx[3] = o + dz;
01004 cornerx[4] = cornerx[1] + dy;
01005 cornerx[5] = cornerx[1] + dz;
01006 cornerx[6] = cornerx[2] + dz;
01007 cornerx[7] = cornerx[4] + dz;
01008
01009
01010 Vector3D ijk = get_ijk(cornerx[0]);
01011 double dimax = ijk.x;
01012 double djmax = ijk.y;
01013 double dkmax = ijk.z;
01014
01015 int i;
01016 for (i=1; i<8; i++) {
01017 ijk = get_ijk(cornerx[i]);
01018 if (ijk.x > dimax)
01019 dimax = ijk.x;
01020 if (ijk.y > djmax)
01021 djmax = ijk.y;
01022 if (ijk.z > dkmax)
01023 dkmax = ijk.z;
01024 }
01025 Vector3D vec;
01026
01027 vec.x = dimax;
01028 vec.y = djmax;
01029 vec.z = dkmax;
01030
01031 return vec;
01032 }
01033
01034
01035 void AtomGrid::build(const MolData* mdata) {
01036
01037
01038 Vector3D bb = findAtomBox(mdata->getRadius());
01039
01040 const int imax = (int)ceil(bb.x);
01041 const int jmax = (int)ceil(bb.y);
01042 const int kmax = (int)ceil(bb.z);
01043
01044 printf("Box=%d, %d, %d\n",imax,jmax,kmax);
01045 const double rsq = mdata->getRadius() * mdata->getRadius();
01046 int atomi;
01047 for (atomi=0; atomi<mdata->count; atomi++) {
01048 Vector3D atom = mdata->coords[atomi].coord;
01049
01050
01051 Vector3D atomijk = get_ijk(atom);
01052 const int ai = (int)atomijk.x;
01053 const int aj = (int)atomijk.y;
01054 const int ak = (int)atomijk.z;
01055 int i;
01056 for (i=ai-imax; i <= ai+imax; i++) {
01057 int ii = i;
01058 if (i < 0) {
01059 if (periodic) {
01060 ii += na;
01061 } else continue;
01062 } else if (i >= na) {
01063 if (periodic) {
01064 ii -= na;
01065 } else continue;
01066 }
01067
01068 int j;
01069 for(j=aj-jmax; j <= aj+jmax; j++) {
01070 int jj = j;
01071 if (j < 0) {
01072 if (periodic) {
01073 jj += nb;
01074 } else continue;
01075 } else if (j >= nb) {
01076 if (periodic) {
01077 jj -= nb;
01078 } else continue;
01079 }
01080
01081
01082
01083 int k;
01084 for (k=0; k <= kmax; k++) {
01085 int k_no_wrap = ak+k;
01086 int kk = k_no_wrap;
01087 if (k_no_wrap < 0) {
01088 if (periodic) {
01089 kk += nc;
01090 } else continue;
01091 } else if (k_no_wrap >= nc) {
01092 if (periodic) {
01093 kk -= nc;
01094 } else continue;
01095 }
01096
01097
01098 if (get(ii,jj,kk))
01099 continue;
01100
01101 const Vector3D v = get_xyz(i,j,k_no_wrap);
01102 const Vector3D dv = v - atom;
01103 if (dv.length2() <= rsq) {
01104 set(ii,jj,kk);
01105 } else {
01106 break;
01107 }
01108 }
01109
01110 for (k=1; k <= kmax; k++) {
01111 int k_no_wrap = ak-k;
01112 int kk = k_no_wrap;
01113 if (k_no_wrap < 0) {
01114 if (periodic) {
01115 kk += nc;
01116 } else continue;
01117 } else if (k_no_wrap >= nc) {
01118 if (periodic) {
01119 kk -= nc;
01120 } else continue;
01121 }
01122
01123
01124 if (get(ii,jj,kk))
01125 continue;
01126
01127 const Vector3D v = get_xyz(i,j,k_no_wrap);
01128 const Vector3D dv = v - atom;
01129 if (dv.length2() <= rsq) {
01130 set(ii,jj,kk);
01131 } else {
01132 break;
01133 }
01134 }
01135 }
01136 }
01137 }
01138 return;
01139 }
01140
01141
01142 void AtomGrid::print() {
01143 int k;
01144 for (k=0; k<nc; k++) {
01145 int i;
01146 for (i=0; i<na; i++) {
01147 printf("%d:",i);
01148 int j;
01149 for (j=0; j<nb; j++) {
01150 if (get(i,j,k))
01151 printf("1");
01152 else printf("0");
01153 }
01154 printf("\n");
01155 }
01156 printf("%d:-------------------------------------------------------\n",k);
01157 }
01158 }
01159
01160
01161 void AtomGrid::store(char* fname) {
01162 FILE* outf = fopen(fname,"w");
01163 if (outf == NULL) {
01164 printf("Couldn't open file %s\n",fname);
01165 exit(-1);
01166 }
01167
01168 int k;
01169 for (k=0; k<nc; k++) {
01170 int i;
01171 for (i=0; i<na; i++) {
01172 int j;
01173 for (j=0; j<nb; j++) {
01174 if (!get(i,j,k)) {
01175 Vector3D v = get_xyz(i,j,k);
01176 if (fprintf(outf,"%f %f %f\n",v.x,v.y,v.z) < 0) {
01177 printf("Store grid error %s\n",fname);
01178 exit(-2);
01179 }
01180 }
01181 }
01182 }
01183 }
01184
01185 fclose(outf);
01186 return;
01187 }
01188
01189
01190 void AtomGrid::Inverse3(const double m[3][3], double inv[3][3]) const {
01191
01192 int i,j;
01193 for (i=0; i<3; i++)
01194 for (j=0; j<3; j++)
01195 inv[i][j] = Cofactor3(m,i,j);
01196
01197
01198 const double det = m[0][0] * inv[0][0]
01199 + m[0][1] * inv[1][0]
01200 + m[0][2] * inv[2][0];
01201
01202
01203
01204
01205
01206 for (i=0; i<3; i++)
01207 for (j=0; j<3; j++)
01208 inv[i][j] /= det;
01209
01210 return;
01211 }
01212
01213
01214 double AtomGrid::Cofactor3(const double mat[3][3],
01215 const int i, const int j) const {
01216 int cols[3][2] = { {1,2}, {0,2}, {0,1}};
01217
01218 const int row1 = cols[j][0];
01219 const int row2 = cols[j][1];
01220
01221 const int col1 = cols[i][0];
01222 const int col2 = cols[i][1];
01223
01224 const double a = mat[row1][col1];
01225 const double b = mat[row1][col2];
01226 const double c = mat[row2][col1];
01227 const double d = mat[row2][col2];
01228
01229 const double det = a*d-b*c;
01230 if (((i+j) % 2) != 0)
01231 return -det;
01232 else
01233 return det;
01234 }
01235
01236
01237 AtomList* MolData::findAtomsGrid(const AtomGrid* grid) {
01238
01239 AtomList *al = new AtomList(count);
01240 const double r = getActualRadius();
01241 const double rsq = r*r;
01242 const Vector3D atom_box = grid->findAtomBox(radius);
01243
01244 int atomi;
01245 for (atomi=0; atomi<count; atomi++) {
01246 Vector3D atom = coords[atomi].coord;
01247
01248
01249 int i0, j0, k0;
01250 bool found = false;
01251
01252 grid->get_cijk(atom,i0,j0,k0);
01253 bool cell_outside = false;
01254
01255 int di;
01256 for (di=-1; !found && di <= 1; di++) {
01257 int ci = i0 + di;
01258 int cna = grid->get_cna();
01259 int wrapi = 0;
01260 if (ci<0) {
01261 ci += cna;
01262 wrapi = grid->get_na();
01263 if (!periodic)
01264 cell_outside = true;
01265 } else if (ci >= cna) {
01266 ci -= cna;
01267 wrapi = -grid->get_na();
01268 if (!periodic)
01269 cell_outside = true;
01270 }
01271
01272 int dj;
01273 for (dj=-1; !found && dj <= 1; dj++) {
01274 int cj = j0 + dj;
01275 int cnb = grid->get_cnb();
01276 int wrapj = 0;
01277 if (cj<0) {
01278 cj += cnb;
01279 wrapj = grid->get_nb();
01280 if (!periodic)
01281 cell_outside = true;
01282 } else if (cj >= cnb) {
01283 cj -= cnb;
01284 wrapj = grid->get_nb();
01285 if (!periodic)
01286 cell_outside = true;
01287 }
01288
01289 int dk;
01290 for (dk=-1; !found && dk <= 1; dk++) {
01291 int ck = k0 + dk;
01292 int cnc = grid->get_cnc();
01293 int wrapk = 0;
01294 if (ck<0) {
01295 ck += cnc;
01296 wrapk = grid->get_nc();
01297 if (!periodic)
01298 cell_outside = true;
01299 } else if (ck >= cnc) {
01300 ck -= cnc;
01301 wrapk = -grid->get_nc();
01302 if (!periodic)
01303 cell_outside = true;
01304 }
01305
01306
01307
01308 if (!periodic && cell_outside) {
01309 const Vector3D atom_grid = grid->get_ijk(atom);
01310 const Vector3D corner0 = atom_grid - atom_box;
01311 bool addit = false;
01312 if (corner0.x < 0 || corner0.y < 0 || corner0.z < 0) {
01313 addit = true;
01314 } else {
01315 const Vector3D corner1 = atom_grid + atom_box;
01316 if (corner1.x >= grid->get_na()
01317 || corner1.y >= grid->get_nb()
01318 || corner1.z >= grid->get_nc() )
01319 addit = true;
01320 }
01321 if (addit) {
01322 al->add(coords[atomi].index);
01323 found = true;
01324 }
01325 cell_outside = false;
01326 }
01327
01328 const GridList* list = grid->get_cell(ci,cj,ck);
01329
01330
01331
01332 int gli;
01333 for (gli=0; !found && gli < list->getNum(); gli++) {
01334
01335 Vector3D gridpt = list->get(gli);
01336 gridpt.x += wrapi;
01337 gridpt.y += wrapj;
01338 gridpt.z += wrapk;
01339 const Vector3D v = grid->get_xyz(gridpt);
01340 const Vector3D dv = v - atom;
01341 if (dv.length2() <= rsq) {
01342 al->add(coords[atomi].index);
01343 found = true;
01344
01345 }
01346 }
01347 }
01348 }
01349 }
01350 }
01351
01352 return al;
01353 }
01354
01355
01356 int msmain(int argc,char *argv[]) {
01357 if (argc != 6) {
01358 printf("Usage: %s grid-res vac-radius selection-dist coord-file index-file\n", argv[0]);
01359 return 0;
01360 }
01361
01362 double res = strtod(argv[1],NULL);
01363 double radius = strtod(argv[2],NULL);
01364 double select_dist = strtod(argv[3],NULL);
01365
01366 printf("Reading\n");
01367 MolData* mol_data = MolData::readFile(argv[4],res,radius,select_dist);
01368 printf("Building grid\n");
01369 AtomGrid* atom_grid = new AtomGrid(mol_data);
01370 mol_data->wrapCoords(atom_grid);
01371 atom_grid->build(mol_data);
01372
01373
01374
01375
01376 printf("Searching grid\n");
01377 AtomList* atom_list = mol_data->findAtomsGrid(atom_grid);
01378 printf("Storing\n");
01379 atom_list->storeFile(argv[5]);
01380
01381 delete atom_list;
01382 delete atom_grid;
01383 delete mol_data;
01384
01385 return 0;
01386 }
01387
01388
01389 void measure_surface_int(const double res, const double radius,
01390 const double select_dist,
01391 const bool periodic,
01392 const double a, const double b, const double c,
01393 const double alpha, const double beta, const double gamma,
01394 int *indices, float *coords, int count,
01395 int **surf, int *n_surf
01396 )
01397 {
01398 if (periodic)
01399 printf("System periodic\n");
01400 else
01401 printf("System not periodic\n");
01402
01403 printf("Reading\n");
01404 Vector3D uo;
01405 Vector3D ua;
01406 Vector3D ub;
01407 Vector3D uc;
01408
01409
01410 double xmin = coords[0];
01411 double xmax = coords[0];
01412 double ymin = coords[1];
01413 double ymax = coords[1];
01414 double zmin = coords[2];
01415 double zmax = coords[2];
01416 int ind;
01417 int i;
01418 for(i=1, ind=3; i < count; i++, ind += 3) {
01419 if (coords[ind] < xmin)
01420 xmin = coords[ind];
01421 if (coords[ind] > xmax)
01422 xmax = coords[ind];
01423 if (coords[ind+1] < ymin)
01424 ymin = coords[ind+1];
01425 if (coords[ind+1] > ymax)
01426 ymax = coords[ind+1];
01427 if (coords[ind+2] < zmin)
01428 zmin = coords[ind+2];
01429 if (coords[ind+2] > zmax)
01430 zmax = coords[ind+2];
01431 }
01432 uo.x = 0.5*(xmin+xmax);
01433 uo.y = 0.5*(ymin+ymax);
01434 uo.z = 0.5*(zmin+zmax);
01435
01436 double cosbc = cos(DEGTORAD(alpha));
01437 double cosac = cos(DEGTORAD(beta));
01438 double sinab, cosab;
01439 sincos(DEGTORAD(gamma), &sinab, &cosab);
01440
01441 ua.x = a; ua.y = 0; ua.z = 0;
01442 ub.x = b * cosab;
01443 ub.y = b * sinab;
01444 ub.z = 0;
01445
01446
01447
01448 if (sinab > 0) {
01449 uc.x = cosac;
01450 uc.y = (cosbc - cosac * cosab) / sinab;
01451 uc.z = sqrt(1.0 - uc.x*uc.x - uc.y*uc.y);
01452 }
01453 uc = c * uc;
01454
01455 uo = uo - (0.5 * (ua + ub + uc));
01456
01457 MolData* mol_data = MolData::readData(indices, coords, count,
01458 uo, ua, ub, uc,
01459 res,radius,select_dist,periodic);
01460 printf("Building grid\n");
01461 AtomGrid* atom_grid = new AtomGrid(mol_data);
01462 mol_data->wrapCoords(atom_grid);
01463 atom_grid->build(mol_data);
01464
01465
01466
01467
01468 printf("Searching grid\n");
01469 AtomList* atom_list = mol_data->findAtomsGrid(atom_grid);
01470 printf("Storing\n");
01471 atom_list->storeData(surf,n_surf);
01472
01473 delete atom_list;
01474 delete atom_grid;
01475 delete mol_data;
01476
01477 return;
01478 }
01479
01480
01481 int measure_surface(AtomSel *sel, MoleculeList *mlist,
01482 const float *framepos,
01483 const double gridsz,
01484 const double radius,
01485 const double depth,
01486 int **surface, int *n_surf ) {
01487 int i;
01488
01489 if (!sel) return MEASURE_ERR_NOSEL;
01490 if (sel->num_atoms == 0) return MEASURE_ERR_NOATOMS;
01491
01492
01493 int *sel_ind = new int[sel->selected];
01494 float *coords = new float[sel->selected*3];
01495 int j=0;
01496 int k=0;
01497 int ind=sel->firstsel*3;
01498 for(i=sel->firstsel; i<=sel->lastsel; i++) {
01499 if (sel->on[i]) {
01500 sel_ind[j++] = i;
01501 coords[k++] = framepos[ind];
01502 coords[k++] = framepos[ind+1];
01503 coords[k++] = framepos[ind+2];
01504 }
01505 ind += 3;
01506 }
01507
01508 Timestep *ts = sel->timestep(mlist);
01509 double a = ts->a_length;
01510 double b = ts->b_length;
01511 double c = ts->c_length;
01512 double alpha = ts->alpha;
01513 double beta = ts->beta;
01514 double gamma = ts->gamma;
01515 bool periodic = true;
01516 if (a == 0 || b == 0 || c == 0 || alpha == 0 || beta == 0 || gamma == 0) {
01517 periodic = false;
01518 float min_coord[3];
01519 float max_coord[3];
01520 measure_minmax(sel->num_atoms, sel->on, framepos, NULL, min_coord, max_coord);
01521 a = max_coord[0] - min_coord[0];
01522 b = max_coord[1] - min_coord[1];
01523 c = max_coord[2] - min_coord[2];
01524 alpha = beta = gamma = 90;
01525 }
01526
01527 printf("Periodic: %f %f %f %f %f %f\n",a,b,c,alpha,beta,gamma);
01528
01529 measure_surface_int(gridsz, radius, depth, periodic,
01530 a,b,c,alpha,beta,gamma,
01531 sel_ind,coords,sel->selected,
01532 surface, n_surf);
01533
01534 printf("Done!\n");
01535
01536 return MEASURE_NOERR;
01537 }