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
00103 int i;
00104 Vgrid *grid = VNULL;
00105
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
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
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
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
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
00246 iband = (int)(stddev*bandwidth/hx);
00247 jband = (int)(stddev*bandwidth/hy);
00248 kband = (int)(stddev*bandwidth/hzed);
00249
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
00260 scal = 2.0 * stddev * stddev;
00261 VASSERT(scal > 0);
00262 scal = 1.0/scal;
00263
00264
00265 oldData = grid->data;
00266 newData = Vmem_malloc(VNULL, (nx*ny*nz), sizeof(double));
00267
00268
00269
00270 for (i=0; i<(nx*ny*nz); i++) newData[i] = oldData[i];
00271
00272
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
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 }
00294 }
00295 }
00296 if (norm > 0) newData[IJK(i,j,k)] = u/norm;
00297 else newData[IJK(i,j,k)] = 0;
00298 }
00299 }
00300 }
00301
00302
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 }