• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Data Structures
  • Files
  • File List
  • Globals

tools/mesh/smooth.c

Go to the documentation of this file.
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 ERRRC 2
00059 
00060 typedef enum Smooth_Filter {
00061     SM_GAUSSIAN  
00062 } Smooth_Filter;
00063 
00064 
00065 VEMBED(rcsid="$Id: smooth.c 1552 2010-02-10 17:46:27Z yhuang01 $")
00066 
00067 int gaussian(Vgrid *grid, double stddev, double bandwidth);
00068 
00069 int usage(int rc) {
00070 
00071     char *usage = "\n\n\
00072     ----------------------------------------------------------------------\n\
00073     This driver program convolves grid data with various filters.  It is\n\
00074     invoked as:\n\
00075       smooth <args>\n\n\
00076     where <args> is a list of the following arguments:\n\
00077       REQUIRED GENERAL ARGUMENTS:\n\
00078       --format=<format>  where <format> specifies the data format and is one\n\
00079                           of the following: dx (OpenDX)\n\
00080       --input=<file>     where <file> is the input mesh data in the\n\
00081                          specified format\n\
00082       --output=<file>    where <file> is the output mesh data in the\n\
00083                          specified format\n\
00084       --filter=<filter>  where <filter> is the filter with which the data\n\
00085                          will be convolved and is one of the following:\n\
00086                          gaussian (Gaussian filter)\n\
00087       REQUIRED FILTER-SPECIFIC ARGUMENTS:\n\
00088         Gaussian filter:\n\
00089         --stddev=<n>     the standard deviation of the filter (in A)\n\
00090         --bandwidth=<n>  the bandwith of the filter (in units of stddev)\n\
00091     ----------------------------------------------------------------------\n\n";
00092 
00093     Vnm_print(2, usage);
00094 
00095     exit(rc);
00096  
00097     return 0;
00098 }
00099 
00100 int main(int argc, char **argv) {
00101 
00102     /* *************** VARIABLES ******************* */
00103     int i;
00104     Vgrid *grid = VNULL;
00105     /* Input parameters */
00106     Vdata_Format format; int gotFormat = 0;
00107     char inPath[VMAX_BUFSIZE]; int gotInPath = 0;
00108     char outPath[VMAX_BUFSIZE]; int gotOutPath = 0;
00109     Smooth_Filter filter; int gotFilter = 0;
00110     double stddev; int gotStddev = 0;
00111     double bandwidth; int gotBandwidth = 0;
00112 
00113     char *header = "\n\n\
00114     ----------------------------------------------------------------------\n\
00115     ----------------------------------------------------------------------\n\
00116     \n\n";
00117 
00118     /* *************** CHECK INVOCATION ******************* */
00119     Vio_start();
00120     Vnm_redirect(1);
00121     Vnm_print(1, "%s", header);
00122     for (i=1; i<argc; i++) {
00123         Vnm_print(1, "Parsing: %s...\n", argv[i]);
00124         if (strstr(argv[i], "--format") != NULL) {
00125             if (strstr(argv[i], "dx") != NULL) {
00126                 gotFormat = 1;
00127                 format = VDF_DX;
00128             } else {
00129                 Vnm_print(2, "Error:  %s\n", argv[i]);
00130                 usage(2);
00131             }
00132         } else if (strstr(argv[i], "--input") != NULL) {
00133             if (sscanf(argv[i], "--input=%s", inPath) == 1) gotInPath = 1;
00134             else {
00135                 Vnm_print(2, "Error:  %s\n", argv[i]);
00136                 usage(2);
00137             }
00138         } else if (strstr(argv[i], "--output") != NULL) {
00139             if (sscanf(argv[i], "--output=%s", outPath) == 1) gotOutPath = 1;
00140             else {
00141                 Vnm_print(2, "Error:  %s\n", argv[i]);
00142                 usage(2);
00143             }
00144         } else if (strstr(argv[i], "--filter") != NULL) {
00145             if (strstr(argv[i], "gaussian") != NULL) {
00146                 gotFilter = 1;
00147                 filter = SM_GAUSSIAN;
00148             } else {
00149                 Vnm_print(2, "Error:  %s\n", argv[i]);
00150                 usage(2);
00151             }
00152         } else if (strstr(argv[i], "--stddev") != NULL) {
00153             if (sscanf(argv[i], "--stddev=%lf", &stddev) == 1) gotStddev = 1;
00154             else {
00155                 Vnm_print(2, "Error:  %s\n", argv[i]);
00156                 usage(2);
00157             }
00158         } else if (strstr(argv[i], "--bandwidth") != NULL) {
00159             if (sscanf(argv[i], "--bandwidth=%lf", &bandwidth) == 1) 
00160                 gotBandwidth = 1;
00161             else {
00162                 Vnm_print(2, "Error:  %s\n", argv[i]);
00163                 usage(2);
00164             }
00165         } else {
00166             Vnm_print(2, "Error:  %s\n", argv[i]);
00167             usage(2);
00168         }
00169     }
00170     if (!gotFormat) {
00171         Vnm_print(2, "Error:  --format not specified!\n");
00172         usage(2);
00173     } 
00174     if (!gotInPath) {
00175         Vnm_print(2, "Error:  --input not specified!\n");
00176         usage(2);
00177     }
00178     if (!gotOutPath) {
00179         Vnm_print(2, "Error:  --output not specified!\n");
00180         usage(2);
00181     }
00182     if (!gotFilter) {
00183         Vnm_print(2, "Error:  --filter not specified!\n");
00184         usage(2);
00185     }
00186     if (filter == SM_GAUSSIAN) {
00187         if (!gotStddev) {
00188             Vnm_print(2, "Error:  --stddev not specified!\n");
00189             usage(2);
00190         }
00191         if (!gotBandwidth) {
00192             Vnm_print(2, "Error:  --bandwidth not specified!\n");
00193             usage(2);
00194         }
00195     }
00196 
00197     /* *************** READ DATA ******************* */
00198     Vnm_print(1, "main:  Reading data from %s...\n", inPath);
00199     grid = Vgrid_ctor(0, 0, 0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, VNULL);
00200     if (format == VDF_DX) {
00201         if (!Vgrid_readDX(grid, "FILE", "ASC", VNULL, inPath)) {
00202             Vnm_print(2, "main:  Problem reading OpenDX-format grid from %s\n",
00203               inPath);
00204             return ERRRC;
00205         }
00206     }
00207 
00208     /* *************** SMOOTH ******************* */
00209     switch(filter) {
00210         case SM_GAUSSIAN:
00211            Vnm_print(1, "Smoothing data with Gaussian filter...\n");
00212            gaussian(grid, stddev, bandwidth);
00213            break;
00214         default:
00215            Vnm_print(2, "Invalid format (%d)!\n", format);
00216            usage(2);
00217     }
00218 
00219     /* *************** READ DATA ******************* */
00220     Vnm_print(1, "main:  Writing data to %s...\n", outPath);
00221     if (format == VDF_DX) 
00222       Vgrid_writeDX(grid, "FILE", "ASC", VNULL, outPath, "Smoothed data",
00223         VNULL);
00224 
00225     return 0;
00226 }
00227 
00228 int gaussian(Vgrid *grid, double stddev, double bandwidth) {
00229 
00230     int nx, ny, nz, iband, jband, kband, i, j, k, ii, jj, kk;
00231     int kkmin, jjmin, iimin, kkmax, jjmax, iimax;
00232     double hx, hy, hzed, xmin, ymin, zmin, *newData, *oldData, scal, norm;
00233     double u, ga, dist2;
00234 
00235     Vnm_print(1, "Gaussian filter:  std. dev. = %g A, bandwidth = %g A.\n",
00236       stddev, bandwidth*stddev);
00237 
00238     nx = grid->nx; ny = grid->ny; nz = grid->nz;
00239     hx = grid->hx; hy = grid->hy; hzed = grid->hzed;
00240     xmin = grid->xmin; ymin = grid->ymin; zmin = grid->zmin;
00241     Vnm_print(1, "Grid:  %d x %d x %d points\n", nx, ny, nz);
00242     Vnm_print(1, "Grid:  %g, %g, %g A spacing\n", hx, hy, hzed);
00243     Vnm_print(1, "Grid:  (%g, %g, %g) A origin\n", xmin, ymin, zmin);
00244 
00245     /* Convert HALF bandwidth to grid units */
00246     iband = (int)(stddev*bandwidth/hx);
00247     jband = (int)(stddev*bandwidth/hy);
00248     kband = (int)(stddev*bandwidth/hzed);
00249     /* Special handling for iband, jband and kband, they are non-zero positive integers */
00250     if (iband == 0) iband = 1;
00251     if (jband == 0) jband = 1;
00252     if (kband == 0) kband = 1;
00253     Vnm_print(1, "Bandwidth converted to %d x %d x %d grid units.\n",
00254       iband, jband, kband);
00255     Vnm_print(1, "This means any non-zero data within (%g, %g, %g) of the\n", 
00256       (iband+1)*hx, (jband+1)*hy, (kband+1)*hzed);
00257     Vnm_print(1, "domain boundary will be convolved differently.\n");
00258 
00259     /* Get exponent scaling factor */
00260     scal = 2.0 * stddev * stddev;
00261     VASSERT(scal > 0);
00262     scal = 1.0/scal;
00263 
00264     /* Get data */
00265     oldData = grid->data;
00266     newData = Vmem_malloc(VNULL, (nx*ny*nz), sizeof(double));
00267 
00268            /* Copy over old data.  All but the boundary values will be replaced in the next step so this is more copying than is strictly
00269               necessary... */
00270            for (i=0; i<(nx*ny*nz); i++) newData[i] = oldData[i];
00271 
00272     /* Apply filter */
00273     for (k=1; k<(nz-1); k++) {
00274         kkmin = VMAX2(1, (k - kband));
00275         kkmax = VMIN2((nz-1), (k + kband));
00276         for (j=1; j<(ny-1); j++) {
00277             jjmin = VMAX2(1, (j - jband));
00278             jjmax = VMIN2((ny-1), (j + jband));
00279             for (i=1; i<(nx-1); i++) {
00280                 iimin = VMAX2(1, (i - iband));
00281                 iimax = VMIN2((nx-1), (i + iband));
00282                 u = 0;
00283                 /* We normalize within the loop to conserve densities */
00284                 norm = 0;
00285                 for (kk=kkmin; kk<kkmax; kk++) {
00286                     for (jj=jjmin; jj<jjmax; jj++) {
00287                         for (ii=iimin; ii<iimax; ii++) {
00288                             dist2 = VSQR(hx*(i-ii)) + VSQR(hy*(j-jj)) +
00289                               VSQR(hzed*(k-kk));
00290                             ga = VEXP(-dist2*scal);
00291                             u += (ga*oldData[IJK(ii,jj,kk)]);
00292                             norm += ga;
00293                         } /* ii loop */
00294                     } /* jj loop */
00295                 } /* kk loop */
00296                 if (norm > 0) newData[IJK(i,j,k)] = u/norm;
00297                 else newData[IJK(i,j,k)] = 0;
00298             } /* i loop */
00299         } /* j loop */
00300     } /* k loop */
00301 
00302     /* Replace data */
00303     for (i=0; i<(nx*ny*nz); i++) grid->data[i] = newData[i];
00304     Vmem_free(VNULL, (nx*ny*nz), sizeof(double), (void **)&newData);
00305 
00306     return 0;
00307 }

Generated on Wed Oct 20 2010 11:12:20 for APBS by  doxygen 1.7.2