00001
00054 #include "apbscfg.h"
00055 #include "apbs/apbs.h"
00056
00057 #define IJK(i,j,k) (((k)*(nx)*(ny))+((j)*(nx))+(i))
00058 #define INTERVAL(x,a,b) (((x) >= (a)) && ((x) <= (b)))
00059
00060 VEMBED(rcsid="$Id: mergedx2.c 1554 2010-02-11 22:24:51Z sdg0919 $")
00061
00062 VPRIVATE int Vgrid_readDXhead(Vgrid *thee,
00063 const char *iodev, const char *iofmt, const char *thost, const char *fname);
00064 VPRIVATE int Vgrid_value2(Vgrid *thee, double pt[3], double *value);
00065
00066 VPRIVATE char *MCwhiteChars = " =,;\t\n";
00067 VPRIVATE char *MCcommChars = "#%";
00068
00069 void usage(){
00070
00071 Vnm_print(1,"mergedx2 [FLAGS] file1.dx [file2.dx ...]\n"
00072 "\n"
00073 "ARGUMENTS:\n"
00074 " file1.dx [file2.dx ...]\n"
00075 " The OpenDX files to be merged\n"
00076 "FLAGS:\n"
00077 " -o Output OpenDX file (default: gridmerged.dx)\n"
00078 " -r Resolution of gridpoints (default: 1.0 Angstroms)\n"
00079 " -b Bounds of output map as: xmin ymin zmin xmax ymax zmax\n"
00080 " (default: calculates full map)\n"
00081 " -s Print bounds of merged input dx files. Doesn't generate a merged map.\n"
00082 " (-s is exclusive of the other FLAGS)\n"
00083 " -h Print this message\n"
00084 "\n"
00085 "All FLAGS are optional. Flags must be set prior to listing input files. You must provide at least one\n"
00086 "OpenDX file. Subsequent files can be listed as a series of names on the command line.\n"
00087 "\n"
00088 "Specifying -s with all of the input files listed will run a calculation that will print the current minimum\n"
00089 "and maximum bounds for all user supplied input files. No output (merged) OpenDX file is produced. The -s\n"
00090 "flag will cause all other options to be ignored.\n"
00091 "\n"
00092 "Specifying -r will allow the user to supply a spacing of grid points in the output OpenDX map. If the\n"
00093 "specified resolution is smaller than the actual resolution in the input files, upsampling will occur and a\n"
00094 "message printed to stdout will be passed. The default value is 1.0.\n"
00095 "\n"
00096 "The -b flag allows the user to specify a subvolume of the volume occupied by all input OpenDX files. Ranges\n"
00097 "provided that fall outside the available bounds will cause the program to terminate. To determine the bounds\n"
00098 "of all input files use the -s option. The order for specifying bounds is:\n"
00099 "\n"
00100 " -b xmin ymin zmin xmax ymax zmax\n"
00101 "\n"
00102 "The default values are the full bounds of all input files.\n"
00103 "\n"
00104 "Specifying -o will assign an output name to the merged OpenDX file. The default file name is gridmerged.dx.\n"
00105 "\n"
00106 "Examples:\n"
00107 "\n"
00108 " ./mergedx2 -r 0.5 file1.dx file2.dx\n"
00109 "\n"
00110 " ./mergedx2 -b -3.13 -2.0 -2.14 31.0 25.4 22.1 file1.dx file2.dx file3.dx\n"
00111 "\n"
00112 " ./mergedx2 -o myfile.dx -r 0.5 -b -3.13 -2.0 -2.14 31.0 25.4 22.1 file1.dx file2.dx\n"
00113 "\n"
00114 " ./mergedx2 -s\n"
00115 "\n"
00116 );
00117
00118 }
00119
00120 int main(int argc, char **argv) {
00121
00122
00123 int i, j, k,spec,warn;
00124 int nx, ny, nz, count, numfnams;
00125
00126 double pt[3],value, res1, res2, res3, resx, resy, resz;
00127
00128 double xmin, ymin, zmin;
00129 double xmax, ymax, zmax;
00130
00131 double xminb, yminb, zminb;
00132 double xmaxb, ymaxb, zmaxb;
00133
00134 char fnams[80][1024];
00135 short *carray = VNULL;
00136
00137 char *snam = "# main: ";
00138 char outname[80];
00139
00140 int ch, ind;
00141 extern char *optarg;
00142 extern int optind, opterr, optopt;
00143
00144
00145 Vgrid *grid, *mgrid;
00146
00147
00148 spec = 0;
00149 warn = 0;
00150 res1 = 1.0;
00151 res2 = 1.0;
00152 res3 = 1.0;
00153 xmin = ymin = zmin = 0.0;
00154 xmax = ymax = zmax = 0.0;
00155 sprintf(outname,"gridmerged.dx");
00156
00157
00158
00159
00160 if(argc <= 1){ usage(); return 1; }
00161
00162 while ((ch = getopt(argc, argv, "r:b:o:s:h")) != -1) {
00163 switch (ch) {
00164 case 'r':
00165 ind = optind - 1;
00166 res1 = atof(argv[ind++]);
00167 res2 = atof(argv[ind++]);
00168 res3 = atof(argv[ind++]);
00169 optind = ind;
00170 break;
00171 case 'b':
00172 ind = optind - 1;
00173 xmin = atof(argv[ind++]);
00174 ymin = atof(argv[ind++]);
00175 zmin = atof(argv[ind++]);
00176
00177 xmax = atof(argv[ind++]);
00178 ymax = atof(argv[ind++]);
00179 zmax = atof(argv[ind++]);
00180
00181 optind = ind;
00182 break;
00183 case 'o':
00184 strcpy(outname,optarg);
00185 break;
00186 case 's':
00187 spec = 1;
00188 break;
00189 case 'h':
00190 usage();
00191 return 0;
00192 break;
00193 default:
00194 break;
00195 }
00196 }
00197
00198 numfnams = 0;
00199 if (optind < argc) {
00200 while (optind < argc){
00201 strcpy(fnams[numfnams],argv[optind++]);
00202 numfnams += 1;
00203 }
00204 }
00205
00206
00207 Vio_start();
00208
00209
00210 resx = res1;
00211 resy = res2;
00212 resz = res3;
00213
00214
00215 mgrid = Vgrid_ctor(0, 0, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, VNULL);
00216 mgrid->xmin = VLARGE; mgrid->xmax = -VLARGE;
00217 mgrid->ymin = VLARGE; mgrid->ymax = -VLARGE;
00218 mgrid->zmin = VLARGE; mgrid->zmax = -VLARGE;
00219
00220
00221 Vnm_print(1, "%s Reading Headers...\n",snam);
00222 grid = Vgrid_ctor(0, 0, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, VNULL);
00223 for(count=0; count<numfnams; count++) {
00224 Vnm_print(0, "%s Reading header from %s...\n",snam, fnams[count]);
00225 Vgrid_readDXhead(grid, "FILE", "ASC", VNULL, fnams[count]);
00226
00227
00228 if( grid->xmin < mgrid->xmin ) mgrid->xmin = grid->xmin;
00229 if( grid->xmax > mgrid->xmax ) mgrid->xmax = grid->xmax;
00230 if( grid->ymin < mgrid->ymin ) mgrid->ymin = grid->ymin;
00231 if( grid->ymax > mgrid->ymax ) mgrid->ymax = grid->ymax;
00232 if( grid->zmin < mgrid->zmin ) mgrid->zmin = grid->zmin;
00233 if( grid->zmax > mgrid->zmax ) mgrid->zmax = grid->zmax;
00234
00235 if( grid->hx > res1 || grid->hy > res2 || grid->hzed > res3 ) warn = 1;
00236 }
00237
00238 if(warn){
00239 Vnm_print(1,"WARNING: The specified output resolution is greater than the\n"
00240 " resolution of the input DX files. Upsampling.......\n");
00241 }
00242
00243
00244 xminb = mgrid->xmin; yminb = mgrid->ymin; zminb = mgrid->zmin;
00245 xmaxb = mgrid->xmax; ymaxb = mgrid->ymax; zmaxb = mgrid->zmax;
00246
00247
00248 if(xmin != 0.0) mgrid->xmin = xmin;
00249 if(ymin != 0.0) mgrid->ymin = ymin;
00250 if(zmin != 0.0) mgrid->zmin = zmin;
00251
00252 if(xmax != 0.0) mgrid->xmax = xmax;
00253 if(ymax != 0.0) mgrid->ymax = ymax;
00254 if(zmax != 0.0) mgrid->zmax = zmax;
00255
00256
00257
00258
00259 if((mgrid->xmin < xminb) ||
00260 (mgrid->ymin < yminb) ||
00261 (mgrid->zmin < zminb) ||
00262 (mgrid->xmax > xmaxb) ||
00263 (mgrid->ymax > ymaxb) ||
00264 (mgrid->zmax > zmaxb))
00265 {
00266 Vnm_print(1,"\nError: The bounds requested do not fall within the bounds of the specified grid\n"
00267 "You specified <xmin> <ymin> <zmin> <xmax> <ymax> <zmax>: %lf\t%lf\t%lf\t%lf\t%lf\t%lf\n"
00268 "The input DX files provided : %lf\t%lf\t%lf\t%lf\t%lf\t%lf\n",
00269 mgrid->xmin,mgrid->ymin,mgrid->zmin,mgrid->xmax,mgrid->ymax,mgrid->zmax,
00270 xminb,yminb,zminb,xmaxb,ymaxb,zmaxb
00271 );
00272 return 1;
00273 }
00274
00275
00276 mgrid->nx = VFLOOR(((mgrid->xmax - mgrid->xmin) / resx) + 1.5);
00277 mgrid->ny = VFLOOR(((mgrid->ymax - mgrid->ymin) / resy) + 1.5);
00278 mgrid->nz = VFLOOR(((mgrid->zmax - mgrid->zmin) / resz) + 1.5);
00279
00280 mgrid->hx = (mgrid->xmax - mgrid->xmin) / (mgrid->nx-1);
00281 mgrid->hy = (mgrid->ymax - mgrid->ymin) / (mgrid->ny-1);
00282 mgrid->hzed = (mgrid->zmax - mgrid->zmin) / (mgrid->nz-1);
00283
00284
00285 Vnm_print(1, "%s Dimensions of the merged grid\n",snam);
00286 Vnm_print(1, "%s nx = %d, ny = %d, nz = %d\n",snam,
00287 mgrid->nx, mgrid->ny, mgrid->nz);
00288 Vnm_print(1, "%s hx = %lf, hy = %lf, hz = %lf\n",snam,
00289 mgrid->hx, mgrid->hy, mgrid->hzed);
00290 Vnm_print(1, "%s xmin = %lf, ymin = %lf, zmin = %lf\n",snam,
00291 mgrid->xmin, mgrid-> ymin, mgrid->zmin);
00292 Vnm_print(1, "%s xmax = %lf, ymax = %lf, zmax = %lf\n",snam,
00293 mgrid->xmax, mgrid-> ymax, mgrid->zmax);
00294
00295 if(spec) return 0;
00296
00297 mgrid->data = (double *)
00298 Vmem_malloc(mgrid->mem,(mgrid->nx*mgrid->ny*mgrid->nz),sizeof(double));
00299 mgrid->ctordata = 1;
00300
00301 carray = (short *)
00302 Vmem_malloc(VNULL, (mgrid->nx*mgrid->ny*mgrid->nz), sizeof(short) );
00303
00304
00305 nx = mgrid->nx;
00306 ny = mgrid->ny;
00307 nz = mgrid->nz;
00308 for (i=0; i<nx; i++) {
00309 for (j=0; j<ny; j++) {
00310 for (k=0; k<nz; k++) {
00311 (mgrid->data)[IJK(i,j,k)] = 0.0;
00312 carray[IJK(i,j,k)] = 0;
00313 }
00314 }
00315 }
00316
00317
00318 Vnm_print(1, "%s Reading and Merging...\n",snam);
00319 for (count=0; count<numfnams; count++) {
00320 Vgrid_readDX(grid, "FILE", "ASC", VNULL, fnams[count]);
00321 xmin = grid->xmin - grid->hx - VSMALL;
00322 ymin = grid->ymin - grid->hy - VSMALL;
00323 zmin = grid->zmin - grid->hzed - VSMALL;
00324 xmax = grid->xmax + grid->hx + VSMALL;
00325 ymax = grid->ymax + grid->hy + VSMALL;
00326 zmax = grid->zmax + grid->hzed + VSMALL;
00327 for (i=0; i<nx; i++) {
00328 pt[0] = mgrid->xmin + i*mgrid->hx;
00329 if(INTERVAL(pt[0],xmin,xmax)) {
00330 for (j=0; j<ny; j++) {
00331 pt[1] = mgrid->ymin + j*mgrid->hy;
00332 if(INTERVAL(pt[1],ymin,ymax)) {
00333 for (k=0; k<nz; k++) {
00334 pt[2] = mgrid->zmin + k*mgrid->hzed;
00335 if(INTERVAL(pt[2],zmin,zmax)) {
00336 if (Vgrid_value2(grid, pt, &value)) {
00337 (mgrid->data)[IJK(i,j,k)] += value;
00338 carray[IJK(i,j,k)] += 1;
00339 }
00340 }
00341 }
00342 }
00343 }
00344 }
00345 }
00346 Vmem_free(grid->mem,(grid->nx*grid->ny*grid->nz), sizeof(double),
00347 (void **)&(grid->data));
00348 grid->readdata = 0;
00349 grid->ctordata = 0;
00350 }
00351 Vgrid_dtor( &grid );
00352
00353 mgrid->readdata = 1;
00354
00355
00356 nx = mgrid->nx;
00357 ny = mgrid->ny;
00358 nz = mgrid->nz;
00359 for (i=0; i<nx; i++) {
00360 for (j=0; j<ny; j++) {
00361 for (k=0; k<nz; k++) {
00362 if ( carray[IJK(i,j,k)] >= 1 ) {
00363 (mgrid->data)[IJK(i,j,k)] /= carray[IJK(i,j,k)];
00364 } else {
00365 Vnm_print(2,"%s Warning: Gap in subgrids at point (%g,%g,%g)\n",
00366 snam,
00367 mgrid->xmin + i*mgrid->hx,
00368 mgrid->ymin + j*mgrid->hy,
00369 mgrid->zmin + k*mgrid->hzed );
00370 }
00371 }
00372 }
00373 }
00374
00375
00376 Vnm_print(1, "%s Writing...\n",snam);
00377 Vnm_print(0, "%s Writing merged data to %s...\n",snam,outname);
00378 Vgrid_writeDX(mgrid, "FILE", "ASC", VNULL, outname,"mergedx",VNULL);
00379
00380 Vmem_free(VNULL,(mgrid->nx*mgrid->ny*mgrid->nz), sizeof(short),
00381 (void **)&(carray));
00382 Vgrid_dtor( &mgrid );
00383
00384 return 0;
00385 }
00386
00387
00388
00389
00390
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424 if ( ilo < 0 ) {
00425 ilo = 0;
00426 ihi = ilo + 1;
00427 ifloat = (double)(ilo);
00428 } else if ( ihi >= nx ) {
00429 ihi = nx - 1;
00430 ilo = ihi - 1;
00431 ifloat = (double)(ihi);
00432 }
00433 if ( jlo < 0 ) {
00434 jlo = 0;
00435 jhi = jlo + 1;
00436 jfloat = (double)(jlo);
00437 } else if ( jhi >= ny ) {
00438 jhi = ny - 1;
00439 jlo = jhi - 1;
00440 jfloat = (double)(jhi);
00441 }
00442 if ( klo < 0 ) {
00443 klo = 0;
00444 khi = klo + 1;
00445 kfloat = (double)(klo);
00446 } else if ( khi >= nz ) {
00447 khi = nz - 1;
00448 klo = khi - 1;
00449 kfloat = (double)(khi);
00450 }
00451
00452
00453 if ((ihi<nx) && (jhi<ny) && (khi<nz) &&
00454 (ilo>=0) && (jlo>=0) && (klo>=0)) {
00455 dx = ifloat - (double)(ilo);
00456 dy = jfloat - (double)(jlo);
00457 dz = kfloat - (double)(klo);
00458 u = dx *dy *dz *(thee->data[IJK(ihi,jhi,khi)])
00459 + dx *(1.0-dy)*dz *(thee->data[IJK(ihi,jlo,khi)])
00460 + dx *dy *(1.0-dz)*(thee->data[IJK(ihi,jhi,klo)])
00461 + dx *(1.0-dy)*(1.0-dz)*(thee->data[IJK(ihi,jlo,klo)])
00462 + (1.0-dx)*dy *dz *(thee->data[IJK(ilo,jhi,khi)])
00463 + (1.0-dx)*(1.0-dy)*dz *(thee->data[IJK(ilo,jlo,khi)])
00464 + (1.0-dx)*dy *(1.0-dz)*(thee->data[IJK(ilo,jhi,klo)])
00465 + (1.0-dx)*(1.0-dy)*(1.0-dz)*(thee->data[IJK(ilo,jlo,klo)]);
00466
00467 *value = u;
00468 return 1;
00469
00470 }
00471
00472 *value = 0.0;
00473 return 0;
00474 }
00475
00476
00477
00478
00479
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491 if (thee->data != VNULL) {
00492 Vnm_print(1, "%s destroying existing data!\n",snam);
00493 Vmem_free(thee->mem, (thee->nx*thee->ny*thee->nz), sizeof(double),
00494 (void **)&(thee->data)); }
00495 thee->readdata = 0;
00496 thee->ctordata = 0;
00497
00498
00499 sock = Vio_ctor(iodev,iofmt,thost,fname,"r");
00500 if (sock == VNULL) {
00501 Vnm_print(2, "%s Problem opening virtual socket %s\n",snam,fname);
00502 return 0;
00503 }
00504 if (Vio_accept(sock, 0) < 0) {
00505 Vnm_print(2, "%s Problem accepting virtual socket %s\n",snam,fname);
00506 return 0;
00507 }
00508
00509 Vio_setWhiteChars(sock, MCwhiteChars);
00510 Vio_setCommChars(sock, MCcommChars);
00511
00512
00513
00514 VJMPERR2(1 == Vio_scanf(sock, "%s", tok));
00515 VJMPERR1(!strcmp(tok, "object"));
00516
00517 VJMPERR2(1 == Vio_scanf(sock, "%d", &itmp));
00518
00519 VJMPERR2(1 == Vio_scanf(sock, "%s", tok));
00520 VJMPERR1(!strcmp(tok, "class"));
00521
00522 VJMPERR2(1 == Vio_scanf(sock, "%s", tok));
00523 VJMPERR1(!strcmp(tok, "gridpositions"));
00524
00525 VJMPERR2(1 == Vio_scanf(sock, "%s", tok));
00526 VJMPERR1(!strcmp(tok, "counts"));
00527
00528 VJMPERR2(1 == Vio_scanf(sock, "%s", tok));
00529 VJMPERR1(1 == sscanf(tok, "%d", &(thee->nx)));
00530
00531 VJMPERR2(1 == Vio_scanf(sock, "%s", tok));
00532 VJMPERR1(1 == sscanf(tok, "%d", &(thee->ny)));
00533
00534 VJMPERR2(1 == Vio_scanf(sock, "%s", tok));
00535 VJMPERR1(1 == sscanf(tok, "%d", &(thee->nz)));
00536 Vnm_print(0, "%s Grid dimensions %d x %d x %d grid\n",snam,
00537 thee->nx, thee->ny, thee->nz);
00538
00539 VJMPERR2(1 == Vio_scanf(sock, "%s", tok));
00540 VJMPERR1(!strcmp(tok, "origin"));
00541
00542 VJMPERR2(1 == Vio_scanf(sock, "%s", tok));
00543 VJMPERR1(1 == sscanf(tok, "%lf", &(thee->xmin)));
00544
00545 VJMPERR2(1 == Vio_scanf(sock, "%s", tok));
00546 VJMPERR1(1 == sscanf(tok, "%lf", &(thee->ymin)));
00547
00548 VJMPERR2(1 == Vio_scanf(sock, "%s", tok));
00549 VJMPERR1(1 == sscanf(tok, "%lf", &(thee->zmin)));
00550 Vnm_print(0, "%s Grid origin = (%g, %g, %g)\n",snam,
00551 thee->xmin, thee->ymin, thee->zmin);
00552
00553 VJMPERR2(1 == Vio_scanf(sock, "%s", tok));
00554 VJMPERR1(!strcmp(tok, "delta"));
00555
00556 VJMPERR2(1 == Vio_scanf(sock, "%s", tok));
00557 VJMPERR1(1 == sscanf(tok, "%lf", &(thee->hx)));
00558
00559 VJMPERR2(1 == Vio_scanf(sock, "%s", tok));
00560 VJMPERR1(1 == sscanf(tok, "%lf", &dtmp));
00561 VJMPERR1(dtmp == 0.0);
00562
00563 VJMPERR2(1 == Vio_scanf(sock, "%s", tok));
00564 VJMPERR1(1 == sscanf(tok, "%lf", &dtmp));
00565 VJMPERR1(dtmp == 0.0);
00566
00567 VJMPERR2(1 == Vio_scanf(sock, "%s", tok));
00568 VJMPERR1(!strcmp(tok, "delta"));
00569
00570 VJMPERR2(1 == Vio_scanf(sock, "%s", tok));
00571 VJMPERR1(1 == sscanf(tok, "%lf", &dtmp));
00572 VJMPERR1(dtmp == 0.0);
00573
00574 VJMPERR2(1 == Vio_scanf(sock, "%s", tok));
00575 VJMPERR1(1 == sscanf(tok, "%lf", &(thee->hy)));
00576
00577 VJMPERR2(1 == Vio_scanf(sock, "%s", tok));
00578 VJMPERR1(1 == sscanf(tok, "%lf", &dtmp));
00579 VJMPERR1(dtmp == 0.0);
00580
00581 VJMPERR2(1 == Vio_scanf(sock, "%s", tok));
00582 VJMPERR1(!strcmp(tok, "delta"));
00583
00584 VJMPERR2(1 == Vio_scanf(sock, "%s", tok));
00585 VJMPERR1(1 == sscanf(tok, "%lf", &dtmp));
00586 VJMPERR1(dtmp == 0.0);
00587
00588 VJMPERR2(1 == Vio_scanf(sock, "%s", tok));
00589 VJMPERR1(1 == sscanf(tok, "%lf", &dtmp));
00590 VJMPERR1(dtmp == 0.0);
00591
00592 VJMPERR2(1 == Vio_scanf(sock, "%s", tok));
00593 VJMPERR1(1 == sscanf(tok, "%lf", &(thee->hzed)));
00594 Vnm_print(0, "%s Grid spacings = (%g, %g, %g)\n",snam,
00595 thee->hx, thee->hy, thee->hzed);
00596
00597 thee->xmax = thee->xmin + (thee->nx-1)*thee->hx;
00598 thee->ymax = thee->ymin + (thee->ny-1)*thee->hy;
00599 thee->zmax = thee->zmin + (thee->nz-1)*thee->hzed;
00600
00601
00602 Vio_acceptFree(sock);
00603 Vio_dtor(&sock);
00604
00605 return 1;
00606
00607 VERROR1:
00608 Vio_dtor(&sock);
00609 Vnm_print(2, "%s Format problem with input file <%s>\n",snam,fname);
00610 return 0;
00611
00612 VERROR2:
00613 Vio_dtor(&sock);
00614 Vnm_print(2, "%s I/O problem with input file <%s>\n",snam,fname);
00615 return 0;
00616 }