00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00032 
00033 
00034 
00035 
00036 #include <math.h>
00037 #include <stdlib.h>
00038 #include <stdio.h>
00039 #include <string.h>
00040 #include <errno.h> 
00041 #include <tcl.h>
00042 
00043 #include "VMDApp.h"
00044 #include "MoleculeList.h"
00045 #include "Molecule.h"
00046 #include "Timestep.h"
00047 #include "Measure.h"
00048 #include "SpatialSearch.h"
00049 #include "VolCPotential.h"
00050 #include "VolumetricData.h"
00051 #include "VolMapCreate.h"
00052 #include "utilities.h"
00053 #include "ResizeArray.h"
00054 #include "Inform.h"
00055 #include "WKFUtils.h"
00056 #include "TclCommands.h"
00057 
00058 #if defined(VMDUSEMSMPOT)
00059 #include "msmpot.h"
00060 #endif
00061 
00062 
00063 #define POT_CONV 560.47254
00064 
00065 #define MIN(X,Y) (((X)<(Y))? (X) : (Y))
00066 #define MAX(X,Y) (((X)>(Y))? (X) : (Y))
00067 
00070 static const float MAX_ENERGY = 150.f; 
00071 
00072 
00073 
00075 
00076 VolMapCreate::VolMapCreate(VMDApp *the_app, AtomSel *the_sel, float resolution) {
00077   volmap = NULL;
00078   app = the_app;
00079   sel = the_sel;
00080   delta = resolution;
00081   computed_frames = 0;
00082   checkpoint_freq = 0;
00083   checkpoint_name = NULL;
00084 
00085   char dataname[1];
00086   strcpy(dataname, ""); 
00087   float zerovec[3];
00088   memset(zerovec, 0, 3L*sizeof(float));
00089   volmap = new VolumetricData(dataname, zerovec,
00090                               zerovec, zerovec, zerovec, 0, 0, 0, NULL);
00091   user_minmax = false;
00092 }
00093 
00094 
00095 VolMapCreate::~VolMapCreate() {
00096   if (volmap) delete volmap;
00097   if (checkpoint_name) delete[] checkpoint_name;
00098 }
00099 
00100 
00101 void VolMapCreate::set_minmax (float minx, float miny, float minz, float maxx, float maxy, float maxz) {
00102   user_minmax = true;
00103   min_coord[0] = minx;
00104   min_coord[1] = miny;
00105   min_coord[2] = minz;
00106   max_coord[0] = maxx;
00107   max_coord[1] = maxy;
00108   max_coord[2] = maxz;
00109 }
00110 
00111 
00112 void VolMapCreate::set_checkpoint (int checkpointfreq_tmp, char *checkpointname_tmp) {
00113   if (checkpointfreq_tmp > -1) checkpoint_freq = checkpointfreq_tmp;
00114   if (!checkpointname_tmp) return;
00115   
00116   if (checkpoint_name) delete[] checkpoint_name;
00117   checkpoint_name = new char[strlen(checkpointname_tmp)+1];
00118   strcpy(checkpoint_name, checkpointname_tmp);
00119 }
00120 
00121 
00124 int VolMapCreate::calculate_minmax (float *my_min_coord, float *my_max_coord) {
00125   DrawMolecule *mol = app->moleculeList->mol_from_id(sel->molid());
00126   int numframes = app->molecule_numframes(sel->molid()); 
00127   
00128   float frame_min_coord[3], frame_max_coord[3], *coords;
00129   
00130   msgInfo << "volmap: Computing bounding box coordinates" << sendmsg;
00131 
00132   int save_frame = sel->which_frame;
00133   int frame;
00134   for (frame=0; frame<numframes; frame++) {
00135     sel->which_frame=frame;
00136     sel->change(NULL,mol);
00137     coords = sel->coordinates(app->moleculeList);
00138     if (!coords) continue;
00139 
00140     int err = measure_minmax(sel->num_atoms, sel->on, coords, NULL, 
00141                              frame_min_coord, frame_max_coord);
00142     if (err != MEASURE_NOERR) {
00143       sel->which_frame = save_frame;
00144       return err;
00145     }
00146     
00147     int i;
00148     for (i=0; i<3; i++) {
00149       if (!frame || frame_min_coord[i] < my_min_coord[i]) my_min_coord[i] = frame_min_coord[i];
00150       if (!frame || frame_max_coord[i] > my_max_coord[i]) my_max_coord[i] = frame_max_coord[i];
00151     }
00152   }
00153   sel->which_frame = save_frame;
00154   
00155   return 0;
00156 }
00157 
00158 
00160 int VolMapCreate::calculate_max_radius (float &max_rad) {
00161   DrawMolecule *mol = app->moleculeList->mol_from_id(sel->molid());
00162   if (!mol) return -1;
00163   const float *radius = mol->extraflt.data("radius");
00164   if (!radius) return MEASURE_ERR_NORADII;
00165   
00166   max_rad = 0.f;
00167   int i;
00168   for (i=sel->firstsel; i<=sel->lastsel; i++) 
00169     if (sel->on[i] && radius[i] > max_rad) max_rad = radius[i];
00170   
00171   return 0;
00172 }
00173 
00174 
00175 
00176 
00177 
00178 void VolMapCreate::combo_begin(CombineType method, void **customptr, void *params) {
00179   int gridsize = volmap->xsize*volmap->ysize*volmap->zsize;
00180   
00181   *customptr = NULL;
00182   memset(volmap->data, 0, sizeof(float)*gridsize);
00183   computed_frames = 0;
00184   
00185   
00186   if (method == COMBINE_STDEV) {
00187     float *voldata2 = new float[gridsize];
00188     memset(voldata2, 0, gridsize*sizeof(float));
00189     *customptr = (void*) voldata2;
00190   }
00191 }
00192 
00193 
00194 void VolMapCreate::combo_addframe(CombineType method, float *voldata, void *customptr, float *frame_voldata) {
00195   float *voldata2 = (float*) customptr;
00196   int gridsize = volmap->xsize*volmap->ysize*volmap->zsize;
00197   int n;
00198   
00199   computed_frames++;
00200      
00201   if (computed_frames == 1) { 
00202     switch (method) {
00203     case COMBINE_AVG:
00204     case COMBINE_MAX:    
00205     case COMBINE_MIN:    
00206       memcpy(voldata, frame_voldata, gridsize*sizeof(float));
00207       break;
00208     case COMBINE_PMF:
00209       memcpy(voldata, frame_voldata, gridsize*sizeof(float));
00210       break;
00211     case COMBINE_STDEV:    
00212       memcpy(voldata, frame_voldata, gridsize*sizeof(float));
00213       for (n=0; n<gridsize; n++) voldata2[n] = frame_voldata[n]*frame_voldata[n];
00214       break;
00215     }
00216     
00217     return;
00218   }
00219 
00220   
00221   switch (method) {
00222     case COMBINE_AVG:
00223       for (n=0; n<gridsize; n++) voldata[n] += frame_voldata[n];
00224       break;
00225     case COMBINE_PMF:
00226       for (n=0; n<gridsize; n++) voldata[n] = (float) -log(exp(-voldata[n]) + exp(-frame_voldata[n]));
00227       break;
00228     case COMBINE_MAX:    
00229       for (n=0; n<gridsize; n++) voldata[n] = MAX(voldata[n], frame_voldata[n]);
00230       break;
00231     case COMBINE_MIN:    
00232       for (n=0; n<gridsize; n++) voldata[n] = MIN(voldata[n], frame_voldata[n]);
00233       break;
00234     case COMBINE_STDEV:    
00235       for (n=0; n<gridsize; n++) voldata[n] += frame_voldata[n];
00236       for (n=0; n<gridsize; n++) voldata2[n] += frame_voldata[n]*frame_voldata[n];
00237       break;
00238   }
00239 }
00240 
00241 
00246 void VolMapCreate::combo_export(CombineType method, float *voldata, void *customptr) {
00247   float *voldata2 = (float*) customptr;
00248   int gridsize = volmap->xsize*volmap->ysize*volmap->zsize;
00249   int n;
00250   
00251   switch (method) {
00252   case COMBINE_AVG:
00253     for (n=0; n<gridsize; n++)
00254       volmap->data[n] = voldata[n]/computed_frames;
00255     break;
00256   case COMBINE_PMF:
00257     for (n=0; n<gridsize; n++) {
00258       float val = voldata[n] + logf((float) computed_frames);
00259       if (val > MAX_ENERGY) val = MAX_ENERGY;  
00260       volmap->data[n] = val;
00261     }
00262     break;
00263   case COMBINE_MAX:
00264   case COMBINE_MIN:    
00265     memcpy(volmap->data, voldata, gridsize*sizeof(float));    
00266     break;
00267   case COMBINE_STDEV:    
00268     for (n=0; n<gridsize; n++) {
00269       volmap->data[n] = voldata[n]/computed_frames;
00270       volmap->data[n] = sqrtf(voldata2[n]/computed_frames - volmap->data[n]*volmap->data[n]); 
00271     }
00272     break;
00273   }
00274 }
00275 
00276 
00278 void VolMapCreate::combo_end(CombineType method, void *customptr) {
00279   if (method == COMBINE_STDEV) {
00280     float *voldata2 = (float*) customptr;
00281     delete[] voldata2;
00282   }
00283 }
00284 
00285 
00290 int VolMapCreate::compute_all (bool allframes, CombineType method, void *params) {
00291   int err = this->compute_init();
00292   if (err) return err;
00293   
00294   int gridsize = volmap->xsize*volmap->ysize*volmap->zsize;
00295 
00296   
00297   if (!allframes) {
00298     if (volmap->data) delete[] volmap->data;
00299     volmap->data = new float[gridsize];         
00300   
00301     msgInfo << "volmap: grid size = " << volmap->xsize
00302             <<"x"<< volmap->ysize <<"x"<< volmap->zsize;
00303     char tmp[64];
00304     sprintf(tmp, " (%.1f MB)", sizeof(float)*gridsize/(1024.*1024.));
00305     msgInfo << tmp << sendmsg;
00306 
00307     
00308     this->compute_frame(sel->which_frame, volmap->data); 
00309     
00310     
00311     
00312     return 0; 
00313   }
00314   
00315   
00316   msgInfo << "volmap: grid size    = " << volmap->xsize
00317           <<"x"<< volmap->ysize <<"x"<< volmap->zsize;
00318   char tmp[64];
00319   sprintf(tmp, " (%.1f MB)", sizeof(float)*gridsize/(1024.*1024.));
00320   msgInfo << tmp << sendmsg;
00321 
00322   int numframes = app->molecule_numframes(sel->molid());
00323   msgInfo << "volmap: Computing " << numframes << " frames in total..." << sendmsg;
00324 
00325   if (volmap->data) delete[] volmap->data;
00326   volmap->data = new float[gridsize];         
00327   float *frame_voldata = new float[gridsize]; 
00328   float *voldata = new float[gridsize];       
00329   
00330   void *customptr = NULL;
00331   combo_begin(method, &customptr, params);
00332   wkf_timerhandle timer = wkf_timer_create();
00333 
00334   
00335   int frame;
00336   for (frame=0; frame<numframes; frame++) { 
00337     
00338     msgInfo << "volmap: frame " << frame << "/" << numframes;
00339 #ifdef TIMING
00340     msgInfo << sendmsg;
00341 #else
00342     msgInfo << "   ";
00343 #endif
00344 
00345     wkf_timer_start(timer);
00346 
00347     this->compute_frame(frame, frame_voldata);
00348     wkf_timer_stop(timer);
00349     msgInfo << "Total time = " << wkf_timer_time(timer) << " s" << sendmsg;
00350 
00351     combo_addframe(method, voldata, customptr, frame_voldata);
00352     if (checkpoint_freq && computed_frames && !(computed_frames%checkpoint_freq)) {
00353       combo_export(method, voldata, customptr);
00354       const char *filename;
00355       if (checkpoint_name) filename=checkpoint_name;
00356       else filename = "checkpoint.dx";
00357       write_map(filename);
00358     }
00359   }
00360     
00361   wkf_timer_destroy(timer);
00362 
00363   delete[] frame_voldata;
00364   
00365   
00366   combo_export(method, voldata, customptr);
00367   combo_end (method, customptr);
00368   delete[] voldata;
00369        
00370   return 0; 
00371 }
00372 
00373 
00374 
00375 
00376 
00377 
00378 
00379 int VolMapCreate::compute_init (float padding) {
00380   if (!sel) return MEASURE_ERR_NOSEL;
00381   if (sel->num_atoms == 0) return MEASURE_ERR_NOATOMS;
00382   
00383   int err, i;
00384   
00385   if (!volmap) return -1;
00386   
00387   if (user_minmax)
00388     padding = 0.;  
00389   else {
00390     
00391     err = calculate_minmax(min_coord, max_coord);
00392     if (err) return err;
00393   }
00394   
00395   
00396   
00397   
00398   
00399   
00400   
00401   
00402   for (i=0; i<3; i++) {
00403     
00404     min_coord[i] = (float) floor((min_coord[i] - padding)/delta)*delta;    
00405     max_coord[i] = (float)  ceil((max_coord[i] + padding)/delta)*delta;
00406   }
00407   
00408   volmap->xsize = MAX((int)((max_coord[0] - min_coord[0])/delta), 0);
00409   volmap->ysize = MAX((int)((max_coord[1] - min_coord[1])/delta), 0);
00410   volmap->zsize = MAX((int)((max_coord[2] - min_coord[2])/delta), 0);
00411 
00412   char tmpstr[256] = { 0 };
00413   sprintf(tmpstr, "{%g %g %g} {%g %g %g}\n", min_coord[0], min_coord[1], min_coord[2], max_coord[0], max_coord[1], max_coord[2]);
00414   msgInfo << "volmap: grid minmax = " << tmpstr << sendmsg; 
00415   
00416   float cellx[3], celly[3], cellz[3];
00417   cellx[0] = delta;
00418   cellx[1] = 0.f;
00419   cellx[2] = 0.f;
00420   celly[0] = 0.f;
00421   celly[1] = delta;
00422   celly[2] = 0.f;
00423   cellz[0] = 0.f;
00424   cellz[1] = 0.f;
00425   cellz[2] = delta;
00426 
00427   
00428   
00429   for (i=0; i<3; i++) 
00430     volmap->origin[i] = min_coord[i] + \
00431                  0.5f*(cellx[i] + celly[i] + cellz[i]);
00432   int d;
00433   for (d=0; d<3; d++) {
00434     volmap->xaxis[d] = cellx[d]*(volmap->xsize-1);
00435     volmap->yaxis[d] = celly[d]*(volmap->ysize-1);
00436     volmap->zaxis[d] = cellz[d]*(volmap->zsize-1);
00437   }
00438   
00439   if ((volmap->xsize*volmap->ysize*volmap->zsize) == 0)
00440     return MEASURE_ERR_ZEROGRIDSIZE;
00441 
00442   return 0; 
00443 }
00444 
00445 
00446 
00448 
00453 
00454 int VolMapCreateMask::compute_init() {
00455   char tmpstr[255] = { 0 };
00456   sprintf(tmpstr, "mask (%s.200)", sel->cmdStr);
00457   volmap->set_name(tmpstr);
00458     
00459   return VolMapCreate::compute_init(atomradius+0.5f);
00460 }
00461 
00462 
00463 int VolMapCreateMask::compute_frame (int frame, float *voldata) {
00464   DrawMolecule *mol = app->moleculeList->mol_from_id(sel->molid());
00465   if (!mol) return -1;
00466   
00467   int i;
00468   int GRIDSIZEX = volmap->xsize;
00469   int GRIDSIZEY = volmap->ysize;
00470   int GRIDSIZEZ = volmap->zsize;
00471   int gridsize = volmap->xsize*volmap->ysize*volmap->zsize;
00472   
00473   
00474   memset(voldata, 0, gridsize*sizeof(float));
00475   int save_frame = sel->which_frame;
00476   sel->which_frame=frame;
00477   sel->change(NULL,mol);
00478   
00479   const float *coords = sel->coordinates(app->moleculeList);
00480   if (!coords) {
00481     sel->which_frame = save_frame;
00482     return -1;
00483   }
00484   
00485   float cellx[3], celly[3], cellz[3];
00486   volmap->cell_axes(cellx, celly, cellz);
00487 
00488   float min_coords[3];
00489   for (i=0; i<3; i++)
00490     min_coords[i] = float(volmap->origin[i] - 0.5f*(cellx[i] + celly[i] + cellz[i]));
00491   
00492   
00493   int gx, gy, gz;
00494   for (i=sel->firstsel; i<=sel->lastsel; i++) { 
00495     if (!sel->on[i]) continue; 
00496 
00497     gx = (int) ((coords[3L*i  ] - min_coords[0])/delta);
00498     gy = (int) ((coords[3L*i+1] - min_coords[1])/delta);
00499     gz = (int) ((coords[3L*i+2] - min_coords[2])/delta);
00500       
00501     int steps = (int)(atomradius/delta)+1;
00502     int iz, iy, ix;
00503     for (iz=MAX(gz-steps,0); iz<=MIN(gz+steps,GRIDSIZEZ-1); iz++)
00504     for (iy=MAX(gy-steps,0); iy<=MIN(gy+steps,GRIDSIZEY-1); iy++)
00505     for (ix=MAX(gx-steps,0); ix<=MIN(gx+steps,GRIDSIZEX-1); ix++) {
00506       int n = ix + iy*GRIDSIZEX + iz*GRIDSIZEY*GRIDSIZEX;
00507       float dx = float(coords[3L*i  ] - volmap->origin[0] - ix*delta);
00508       float dy = float(coords[3L*i+1] - volmap->origin[1] - iy*delta);
00509       float dz = float(coords[3L*i+2] - volmap->origin[2] - iz*delta);
00510       float dist2 = dx*dx+dy*dy+dz*dz;
00511       if (dist2 <= atomradius*atomradius) voldata[n] = 1.f;
00512     }
00513   }
00514   
00515   sel->which_frame = save_frame;
00516   
00517   return 0;
00518 }  
00519 
00520 
00521 
00523 
00531 
00532 int VolMapCreateDensity::compute_init () {
00533   char tmpstr[255] = { 0 };
00534   sprintf(tmpstr, "density (%.200s) [A^-3]", sel->cmdStr);
00535   volmap->set_name(tmpstr);
00536   
00537   float max_rad=0.f;
00538   calculate_max_radius(max_rad);
00539     
00540   return VolMapCreate::compute_init(MAX(3.f*radius_scale*max_rad,10.f));
00541 }
00542 
00543 
00544 int VolMapCreateDensity::compute_frame (int frame, float *voldata) {
00545   if (!weight) return MEASURE_ERR_NOWEIGHT;
00546     
00547   DrawMolecule *mol = app->moleculeList->mol_from_id(sel->molid());
00548   if (!mol) return -1;
00549     int i;
00550     
00551   const float *radius = mol->extraflt.data("radius");
00552   if (!radius) return MEASURE_ERR_NORADII;
00553   
00554   int GRIDSIZEX = volmap->xsize;
00555   int GRIDSIZEY = volmap->ysize;
00556   int GRIDSIZEZ = volmap->zsize;
00557   int gridsize = volmap->xsize*volmap->ysize*volmap->zsize;
00558 
00559   
00560   memset(voldata, 0, gridsize*sizeof(float));
00561   int save_frame = sel->which_frame;
00562   sel->which_frame = frame;
00563   sel->change(NULL,mol);
00564   const float *coords = sel->coordinates(app->moleculeList);
00565   if (!coords) {
00566     sel->which_frame = save_frame;
00567     return -1;
00568   }
00569 
00570   if (weight_mutable) {
00571     if (weight_string) {
00572       get_weights_from_attribute(app, sel, weight_string, weight);
00573     } else {
00574       atomsel_default_weights(sel, weight);
00575     }
00576   }
00577   
00578   float cellx[3], celly[3], cellz[3];
00579   volmap->cell_axes(cellx, celly, cellz);
00580 
00581   float min_coords[3];
00582   for (i=0; i<3; i++) 
00583     min_coords[i] = float(volmap->origin[i] - 0.5f*(cellx[i] + celly[i] + cellz[i]));
00584   
00585   int gx, gy, gz;   
00586   for (i=sel->firstsel; i<=sel->lastsel; i++) { 
00587     if (!sel->on[i]) continue; 
00588 
00589     gx = (int) ((coords[3L*i  ] - min_coords[0])/delta);
00590     gy = (int) ((coords[3L*i+1] - min_coords[1])/delta);
00591     gz = (int) ((coords[3L*i+2] - min_coords[2])/delta);
00592       
00593     float scaled_radius = 0.5f*radius_scale*radius[i];
00594     float exp_factor = 1.0f/(2.0f*scaled_radius*scaled_radius);
00595     float norm = weight[i]/(sqrtf((float) (8.0f*VMD_PI*VMD_PI*VMD_PI))*scaled_radius*scaled_radius*scaled_radius);
00596                   
00597     int steps = (int)(4.1f*scaled_radius/delta);
00598     int iz, iy, ix;
00599     for (iz=MAX(gz-steps,0); iz<=MIN(gz+steps,GRIDSIZEZ-1); iz++)
00600     for (iy=MAX(gy-steps,0); iy<=MIN(gy+steps,GRIDSIZEY-1); iy++)
00601     for (ix=MAX(gx-steps,0); ix<=MIN(gx+steps,GRIDSIZEX-1); ix++) {
00602       int n = ix + iy*GRIDSIZEX + iz*GRIDSIZEY*GRIDSIZEX;
00603       float dx = float(coords[3L*i  ] - volmap->origin[0] - ix*delta);
00604       float dy = float(coords[3L*i+1] - volmap->origin[1] - iy*delta);
00605       float dz = float(coords[3L*i+2] - volmap->origin[2] - iz*delta);
00606       float dist2 = dx*dx+dy*dy+dz*dz;
00607       voldata[n] += norm * expf(-dist2*exp_factor);
00608       
00609       
00610       
00611     }
00612   }
00613 
00614   sel->which_frame = save_frame;
00615     
00616   return 0;
00617 }  
00618 
00619 
00620 
00621 
00623   
00627   
00628 int VolMapCreateInterp::compute_init () {
00629   char tmpstr[255] = { 0 };
00630   sprintf(tmpstr, "interp (%.200s) [A^-3]", sel->cmdStr);
00631   volmap->set_name(tmpstr);
00632   
00633   return VolMapCreate::compute_init(delta+0.5f);
00634 }
00635 
00636 
00637 int VolMapCreateInterp::compute_frame (int frame, float *voldata) {
00638   if (!weight) return MEASURE_ERR_NOWEIGHT;
00639     
00640   DrawMolecule *mol = app->moleculeList->mol_from_id(sel->molid());
00641   if (!mol) return -1;
00642     int i;
00643     
00644   int GRIDSIZEX = volmap->xsize;
00645   int GRIDSIZEY = volmap->ysize;
00646   int GRIDSIZEXY = GRIDSIZEX * GRIDSIZEY;
00647   int gridsize = volmap->xsize*volmap->ysize*volmap->zsize;
00648 
00649   
00650   memset(voldata, 0, gridsize*sizeof(float));
00651   int save_frame = sel->which_frame;
00652   sel->which_frame = frame;
00653   sel->change(NULL,mol);
00654   const float *coords = sel->coordinates(app->moleculeList);
00655   if (!coords) {
00656     sel->which_frame = save_frame;
00657     return -1;
00658   }
00659 
00660   if (weight_mutable) {
00661     if (weight_string) {
00662       get_weights_from_attribute(app, sel, weight_string, weight);
00663     } else {
00664       atomsel_default_weights(sel, weight);
00665     }
00666   }
00667   
00668   int gx, gy, gz;      
00669   float fgx, fgy, fgz; 
00670   float dx, dy, dz;    
00671   for (i=sel->firstsel; i<=sel->lastsel; i++) { 
00672     if (!sel->on[i]) continue; 
00673 
00674     
00675     fgx = float(coords[3L*i  ] - volmap->origin[0])/delta;
00676     fgy = float(coords[3L*i+1] - volmap->origin[1])/delta;
00677     fgz = float(coords[3L*i+2] - volmap->origin[2])/delta;
00678 
00679     
00680     gx = (int) fgx;
00681     gy = (int) fgy;
00682     gz = (int) fgz;
00683 
00684     
00685     dx = fgx - gx;
00686     dy = fgy - gy;
00687     dz = fgz - gz;
00688 
00689     
00690 
00691     voldata[ gx + gy*GRIDSIZEX + gz*GRIDSIZEXY ] \
00692       += (1.0f - dx) * (1.0f - dy) * (1.0f - dz) * weight[i];
00693 
00694     voldata[ (gx+1) + (gy+1)*GRIDSIZEX + (gz+1)*GRIDSIZEXY ] \
00695       += dx * dy * dz * weight[i];
00696 
00697     voldata[ (gx+1) + (gy+1)*GRIDSIZEX + gz*GRIDSIZEXY ] \
00698       += dx * dy * (1.0f - dz) * weight[i];
00699 
00700     voldata[ gx + gy*GRIDSIZEX + (gz+1)*GRIDSIZEXY ] \
00701       += (1.0f - dx) * (1.0f - dy) * dz * weight[i];
00702 
00703     voldata[ (gx+1) + gy*GRIDSIZEX + gz*GRIDSIZEXY ] \
00704       += dx * (1.0f - dy) * (1.0f - dz) * weight[i];
00705 
00706     voldata[ gx + (gy+1)*GRIDSIZEX + (gz+1)*GRIDSIZEXY ] \
00707       += (1.0f - dx) * dy * dz * weight[i];
00708 
00709     voldata[ gx + (gy+1)*GRIDSIZEX + gz*GRIDSIZEXY ] \
00710       += (1.0f - dx) * dy * (1.0f - dz) * weight[i];
00711 
00712     voldata[ (gx+1) + gy*GRIDSIZEX + (gz+1)*GRIDSIZEXY ] \
00713       += dx * (1.0f - dy) * dz * weight[i];
00714   }
00715 
00716   sel->which_frame = save_frame;
00717       
00718   return 0;
00719 }  
00720 
00721 
00722 
00723 
00724   
00726 
00732 
00733 int VolMapCreateOccupancy::compute_init () {
00734   char tmpstr[255] = { 0 };
00735   sprintf(tmpstr, "occupancy (%.200s)", sel->cmdStr);
00736   volmap->set_name(tmpstr);
00737   
00738   float max_rad=0.f;  
00739   if (use_points)
00740     max_rad = 1.f;
00741   else
00742     calculate_max_radius(max_rad);
00743   
00744   return VolMapCreate::compute_init(max_rad);
00745 }
00746 
00747 
00748 int VolMapCreateOccupancy::compute_frame(int frame, float *voldata) { 
00749   DrawMolecule *mol = app->moleculeList->mol_from_id(sel->molid());
00750   if (!mol) return -1;
00751   
00752   int GRIDSIZEX = volmap->xsize;
00753   int GRIDSIZEY = volmap->ysize;
00754   int GRIDSIZEZ = volmap->zsize;
00755   int gridsize = volmap->xsize*volmap->ysize*volmap->zsize;
00756   int i;
00757   
00758   
00759   memset(voldata, 0, gridsize*sizeof(float));
00760   int save_frame = sel->which_frame;
00761   sel->which_frame=frame;
00762   sel->change(NULL,mol);
00763   const float *coords = sel->coordinates(app->moleculeList);
00764 
00765   if (!coords) {
00766     sel->which_frame = save_frame;
00767     return -1;
00768   }
00769 
00770   float cellx[3], celly[3], cellz[3];
00771   volmap->cell_axes(cellx, celly, cellz);
00772 
00773   float min_coords[3];
00774   for (i=0; i<3; i++) 
00775     min_coords[i] = float(volmap->origin[i] - 0.5f*(cellx[i] + celly[i] + cellz[i]));
00776 
00777   int gx, gy, gz;
00778   
00779   if (use_points) { 
00780     for (i=sel->firstsel; i<=sel->lastsel; i++) { 
00781       if (!sel->on[i]) continue; 
00782 
00783       gx = (int) ((coords[3L*i  ] - min_coords[0])/delta);
00784       if (gx<0 || gx>=GRIDSIZEX) continue;
00785       gy = (int) ((coords[3L*i+1] - min_coords[1])/delta);
00786       if (gy<0 || gy>=GRIDSIZEY) continue;
00787       gz = (int) ((coords[3L*i+2] - min_coords[2])/delta);
00788       if (gz<0 || gz>=GRIDSIZEZ) continue;
00789 
00790       voldata[gx+GRIDSIZEX*gy+GRIDSIZEX*GRIDSIZEY*gz] = 1.f; 
00791     }
00792   }
00793   else { 
00794     const float *radius = mol->extraflt.data("radius");
00795     if (!radius) {
00796       sel->which_frame = save_frame;
00797       return MEASURE_ERR_NORADII;
00798     }
00799   
00800     for (i=sel->firstsel; i<=sel->lastsel; i++) { 
00801       if (!sel->on[i]) continue; 
00802 
00803       gx = (int) ((coords[3L*i  ] - min_coords[0])/delta);
00804       gy = (int) ((coords[3L*i+1] - min_coords[1])/delta);
00805       gz = (int) ((coords[3L*i+2] - min_coords[2])/delta);
00806       
00807       int steps = (int)(radius[i]/delta)+1;
00808       int iz, iy, ix;
00809       for (iz=MAX(gz-steps,0); iz<=MIN(gz+steps,GRIDSIZEZ-1); iz++)
00810       for (iy=MAX(gy-steps,0); iy<=MIN(gy+steps,GRIDSIZEY-1); iy++)
00811       for (ix=MAX(gx-steps,0); ix<=MIN(gx+steps,GRIDSIZEX-1); ix++) {
00812         int n = ix + iy*GRIDSIZEX + iz*GRIDSIZEY*GRIDSIZEX;
00813         float dx = float(coords[3L*i  ] - volmap->origin[0] - ix*delta);
00814         float dy = float(coords[3L*i+1] - volmap->origin[1] - iy*delta);
00815         float dz = float(coords[3L*i+2] - volmap->origin[2] - iz*delta);
00816         float dist2 = dx*dx+dy*dy+dz*dz;
00817         if (dist2 <= radius[i]*radius[i]) voldata[n] = 1.f;
00818       }
00819     }
00820   }
00821   
00822   sel->which_frame = save_frame;
00823     
00824   return 0;
00825 }
00826 
00827 
00828 
00830 
00836 
00837 int VolMapCreateDistance::compute_init () {
00838   char tmpstr[255] = { 0 };
00839   sprintf(tmpstr, "distance (%.200s) [A]", sel->cmdStr);
00840   volmap->set_name(tmpstr);
00841   
00842   float max_rad=0.f;
00843   calculate_max_radius(max_rad);
00844   
00845   return VolMapCreate::compute_init(max_rad+max_dist);
00846 }
00847  
00848 
00851 int VolMapCreateDistance::compute_frame(int frame, float *voldata) { 
00852   int i, n;  
00853   DrawMolecule *mol = app->moleculeList->mol_from_id(sel->molid());
00854   if (!mol) return -1;
00855   const float *radius = mol->extraflt.data("radius");
00856   if (!radius) return MEASURE_ERR_NORADII;
00857   
00858   int GRIDSIZEX = volmap->xsize;
00859   int GRIDSIZEY = volmap->ysize;
00860   int gridsize = volmap->xsize*volmap->ysize*volmap->zsize;
00861 
00862   float dx, dy, dz;
00863   float dist, mindist, r;
00864   
00865   float max_rad=0.f;
00866   calculate_max_radius(max_rad);
00867   
00868   
00869   
00870   
00871   float *gridpos = new float[3L*gridsize]; 
00872   int *gridon = new int[gridsize]; 
00873   for (n=0; n<gridsize; n++) {
00874     gridpos[3L*n  ] = float((n%GRIDSIZEX)*delta + volmap->origin[0]); 
00875     gridpos[3L*n+1] = float(((n/GRIDSIZEX)%GRIDSIZEY)*delta + volmap->origin[1]);
00876     gridpos[3L*n+2] = float((n/(GRIDSIZEX*GRIDSIZEY))*delta + volmap->origin[2]); 
00877     gridon[n] = 1;
00878   }
00879 
00880   GridSearchPair *pairlist, *p;
00881 
00882   int save_frame = sel->which_frame;
00883   sel->which_frame = frame;
00884   sel->change(NULL,mol);
00885   const float *coords = sel->coordinates(app->moleculeList);
00886   if (!coords) {
00887     sel->which_frame = save_frame;
00888     return -1;
00889   }
00890   
00891   
00892   for (n=0; n<gridsize; n++) voldata[n] = max_dist;
00893   
00894   
00895   
00896   
00897   
00898   pairlist = vmd_gridsearch3(gridpos, gridsize, gridon, coords,
00899                              sel->num_atoms, sel->on, max_dist+max_rad, true, -1);
00900   for (p=pairlist; p; p=p->next) {
00901     n = p->ind1;
00902     
00903     if ((mindist = voldata[n]) == 0.f) continue;
00904     i = p->ind2;
00905     r = radius[i];
00906     dx = gridpos[3L*n  ] - coords[3L*i];
00907     dy = gridpos[3L*n+1] - coords[3L*i+1];
00908     dz = gridpos[3L*n+2] - coords[3L*i+2];
00909     
00910     
00911     
00912       
00913     dist = sqrtf(dx*dx+dy*dy+dz*dz) - r;
00914     if (dist < 0) dist = 0.f;
00915     if (dist < mindist) voldata[n] = dist;
00916   }
00917   
00918   
00919   for (p=pairlist; p;) {
00920     GridSearchPair *tmp = p;
00921     p = p->next;
00922     free(tmp);
00923   }  
00924 
00925   delete [] gridpos; 
00926   delete [] gridon; 
00927 
00928   sel->which_frame = save_frame;
00929 
00930   return MEASURE_NOERR; 
00931 }
00932 
00933 
00934 
00935 
00937   
00938 int VolMapCreateCoulombPotential::compute_init () {
00939   char tmpstr[255] = { 0 };
00940   sprintf(tmpstr, "Potential (kT/e at 298.15K) (%.200s)", sel->cmdStr);
00941   volmap->set_name(tmpstr);
00942   
00943   float max_rad;
00944   calculate_max_radius(max_rad);
00945     
00946   
00947   return VolMapCreate::compute_init(0.f);
00948 }
00949 
00950 
00951 int VolMapCreateCoulombPotential::compute_frame(int frame, float *voldata) {
00952   DrawMolecule *mol = app->moleculeList->mol_from_id(sel->molid());
00953   if (!mol) return -1;
00954     int i;
00955     
00956   const float *charge = mol->extraflt.data("charge");
00957   if (!charge) return MEASURE_ERR_NORADII; 
00958 
00959   int gridsize=volmap->xsize*volmap->ysize*volmap->zsize;
00960 
00961   
00962   memset(voldata, 0, gridsize*sizeof(float));
00963   int save_frame = sel->which_frame;
00964   sel->which_frame=frame;
00965   sel->change(NULL,mol);
00966   const float *coords = sel->coordinates(app->moleculeList);
00967   if (!coords) {
00968     sel->which_frame = save_frame;
00969     return -1;
00970   }
00971  
00972   float cellx[3], celly[3], cellz[3];
00973   volmap->cell_axes(cellx, celly, cellz);
00974 
00975   float min_coords[3];
00976   for (i=0; i<3; i++) 
00977     min_coords[i] = float(volmap->origin[i] - 0.5f*(cellx[i] + celly[i] + cellz[i]));
00978 
00979   
00980   
00981   float *xyzq = (float *) malloc(sel->selected * 4L * sizeof(float));
00982   float *curatom = xyzq;
00983   for (i=sel->firstsel; i<=sel->lastsel; i++) { 
00984     if (sel->on[i]) {
00985       curatom[0] = coords[3L*i  ] - min_coords[0];
00986       curatom[1] = coords[3L*i+1] - min_coords[1];
00987       curatom[2] = coords[3L*i+2] - min_coords[2];
00988       curatom[3] = charge[i] * float(POT_CONV);
00989       curatom += 4;
00990     }
00991   }
00992 
00993   vol_cpotential(sel->selected, xyzq, voldata, 
00994                  volmap->zsize, volmap->ysize, volmap->xsize, delta);
00995 
00996   free(xyzq);
00997 
00998   sel->which_frame = save_frame;
00999  
01000   return 0;
01001 }  
01002 
01004 
01005 #if defined(VMDUSEMSMPOT)
01006 int VolMapCreateCoulombPotentialMSM::compute_init () {
01007   char tmpstr[255] = { 0 };
01008   sprintf(tmpstr, "Potential (kT/e at 298.15K) (%.200s)", sel->cmdStr);
01009   volmap->set_name(tmpstr);
01010   
01011   float max_rad;
01012   calculate_max_radius(max_rad);
01013   
01014   
01015   
01016   return VolMapCreate::compute_init(0.f);
01017 }
01018 
01019 
01020 int VolMapCreateCoulombPotentialMSM::compute_frame(int frame, float *voldata) {
01021   DrawMolecule *mol = app->moleculeList->mol_from_id(sel->molid());
01022   if (!mol) return -1;
01023     int i;
01024 
01025   int usepbc = 0;
01026     
01027   const float *charge = mol->extraflt.data("charge");
01028   if (!charge) return MEASURE_ERR_NORADII; 
01029 
01030   int gridsize=volmap->xsize*volmap->ysize*volmap->zsize;
01031 
01032   
01033   memset(voldata, 0, gridsize*sizeof(float));
01034   int save_frame = sel->which_frame;
01035   sel->which_frame=frame;
01036   sel->change(NULL,mol);
01037   const float *coords = sel->coordinates(app->moleculeList);
01038   const Timestep *ts = sel->timestep(app->moleculeList); 
01039   if (!coords) {
01040     sel->which_frame = save_frame;
01041     return -1;
01042   }
01043   if (!ts) {
01044     return -1;
01045   }
01046  
01047   float cellx[3], celly[3], cellz[3];
01048   volmap->cell_axes(cellx, celly, cellz);
01049 
01050   float min_coords[3];
01051   for (i=0; i<3; i++) 
01052     min_coords[i] = float(volmap->origin[i] - 0.5f*(cellx[i] + celly[i] + cellz[i]));
01053 
01054   
01055   
01056   float *xyzq = (float *) malloc(sel->selected * 4L * sizeof(float));
01057   float *curatom = xyzq;
01058   for (i=sel->firstsel; i<=sel->lastsel; i++) { 
01059     if (sel->on[i]) {
01060       curatom[0] = coords[3L*i  ] - min_coords[0];
01061       curatom[1] = coords[3L*i+1] - min_coords[1];
01062       curatom[2] = coords[3L*i+2] - min_coords[2];
01063       curatom[3] = charge[i] * float(POT_CONV);
01064       curatom += 4;
01065     }
01066   }
01067 
01068   Msmpot *msm = Msmpot_create(); 
01069 #if 0
01070   int msmrc;
01071   int mx = volmap->xsize;  
01072   int my = volmap->ysize;
01073   int mz = volmap->zsize;
01074   float lx = delta*mx;     
01075   float ly = delta*my;
01076   float lz = delta*mz;
01077   float x0=0, y0=0, z0=0;  
01078   float vx=0, vy=0, vz=0;  
01079 
01080   if (getenv("MSMPOT_NOCUDA")) {
01081     
01082     Msmpot_configure(msm, 0, 0, 0, 0, 0, 0, 0, 0, 0);
01083   }
01084 
01085   if (getenv("MSMPOT_PBCON")) {
01086     vx = lx, vy = ly, vz = lz;  
01087   }
01088 
01089   if (getenv("MSMPOT_EXACT")) { 
01090     msmrc = Msmpot_compute_exact(msm, voldata, 
01091         mx, my, mz, lx, ly, lz, x0, y0, z0, vx, vy, vz,
01092         xyzq, sel->selected);
01093   }
01094   else {
01095     msmrc = Msmpot_compute(msm, voldata, 
01096         mx, my, mz, lx, ly, lz, x0, y0, z0, vx, vy, vz,
01097         xyzq, sel->selected);
01098   }
01099   if (msmrc != MSMPOT_SUCCESS) {
01100     printf("MSM return code: %d\n", msmrc);
01101     printf("MSM error string: '%s'\n", Msmpot_error_string(msmrc));
01102   } 
01103 #endif
01104 #if 1
01105   
01106   int msmrc;
01107 
01108   
01109   if (getenv("VMDMSMUSEPBC"))
01110     usepbc = 1;
01111 
01112   if (usepbc) {
01113     
01114     float a, b, c, alpha, beta, gamma;
01115     a = ts->a_length;
01116     b = ts->b_length;
01117     c = ts->c_length;
01118     alpha = ts->alpha;
01119     beta = ts->beta;
01120     gamma = ts->gamma;
01121 
01122     
01123     if (fabsf(a*b*c) < 0.0001) {
01124       msgErr << "volmap coulombmsm: unit cell volume is zero." << sendmsg;
01125       return -1;
01126     }
01127 
01128     
01129     if ((alpha != 90.0) || (beta != 90.0) || (gamma != 90.0)) {
01130       msgErr << "volmap coulombmsm: unit cell is non-orthogonal." << sendmsg;
01131       return -1;
01132     }
01133 
01134 #ifdef MSMPOT_COMPUTE_EXACT
01135   if (getenv("MSMPOT_EXACT")) {
01136     
01137     
01138     
01139     
01140     
01141     msgInfo << "Running EXACT periodic MSM calculation..." << sendmsg;
01142     msmrc = Msmpot_compute_exact(msm, voldata, 
01143                            volmap->xsize, volmap->ysize, volmap->zsize,
01144                            volmap->xsize * delta, 
01145                            volmap->ysize * delta, 
01146                            volmap->zsize * delta, 
01147                            0, 0, 0, 
01148                            a, b, c, 
01149                            xyzq, sel->selected);
01150   } else {
01151 #endif
01152     
01153     
01154     
01155     
01156     
01157     msgInfo << "Running periodic MSM calculation..." << sendmsg;
01158     msmrc = Msmpot_compute(msm, voldata, 
01159                            volmap->xsize, volmap->ysize, volmap->zsize,
01160                            volmap->xsize * delta, 
01161                            volmap->ysize * delta, 
01162                            volmap->zsize * delta, 
01163                            0, 0, 0, 
01164                            a, b, c, 
01165                            xyzq, sel->selected);
01166 #ifdef MSMPOT_COMPUTE_EXACT
01167   }
01168 #endif
01169 
01170   } else {
01171 
01172 #ifdef MSMPOT_COMPUTE_EXACT
01173   if (getenv("MSMPOT_EXACT")) {
01174     msgInfo << "Running EXACT non-periodic MSM calculation..." << sendmsg;
01175     msmrc = Msmpot_compute_exact(msm, voldata, 
01176                            volmap->xsize, volmap->ysize, volmap->zsize,
01177                            volmap->xsize * delta, 
01178                            volmap->ysize * delta, 
01179                            volmap->zsize * delta, 
01180                            0, 0, 0, 
01181                            0, 0, 0, 
01182                            xyzq, sel->selected);
01183   } else {
01184 #endif
01185     msgInfo << "Running non-periodic MSM calculation..." << sendmsg;
01186     msmrc = Msmpot_compute(msm, voldata, 
01187                            volmap->xsize, volmap->ysize, volmap->zsize,
01188                            volmap->xsize * delta, 
01189                            volmap->ysize * delta, 
01190                            volmap->zsize * delta, 
01191                            0, 0, 0, 
01192                            0, 0, 0, 
01193                            xyzq, sel->selected);
01194 #ifdef MSMPOT_COMPUTE_EXACT
01195   }
01196 #endif
01197 
01198   }
01199 
01200   if (msmrc != MSMPOT_SUCCESS) {
01201     printf("MSM return code: %d\n", msmrc);
01202     printf("MSM error string: '%s'\n", Msmpot_error_string(msmrc));
01203   } 
01204 #else
01205   
01206   int msmrc = Msmpot_compute(msm, voldata, 
01207                              volmap->xsize, volmap->ysize, volmap->zsize,
01208                              delta, delta, delta, 
01209                              0, 0, 0,
01210                              0, 0, 0, 
01211                              xyzq, sel->selected);
01212   if (msmrc != MSMPOT_ERROR_NONE) {
01213     printf("MSM return code: %d\n", msmrc);
01214     printf("MSM error string: '%s'\n", Msmpot_error_string(msmrc));
01215   } 
01216 #endif
01217   Msmpot_destroy(msm);
01218 
01219   free(xyzq);
01220 
01221   sel->which_frame = save_frame;
01222  
01223   return 0;
01224 }  
01225 
01226 #endif
01227 
01228 
01229 
01230 
01231 
01232 
01233 
01234 
01235 
01236 void VolMapCreate::write_map(const char *filename) {
01237   volmap_write_dx_file(volmap, filename);
01238 }
01239 
01240 
01241 int volmap_write_dx_file (VolumetricData *volmap, const char *filename) {
01242   if (!volmap->data) return -1; 
01243   int i;
01244   int xsize = volmap->xsize;
01245   int ysize = volmap->ysize;
01246   int zsize = volmap->zsize;
01247   int gridsize = xsize*ysize*zsize;
01248 
01249   float cellx[3], celly[3], cellz[3];
01250   volmap->cell_axes(cellx, celly, cellz);
01251 
01252   
01253   msgInfo << "volmap: writing file \"" << filename << "\"." << sendmsg;
01254   
01255   FILE *fout = fopen(filename, "w");
01256   if (!fout) {
01257     msgErr << "volmap: Cannot open file \"" << filename
01258            << "\" for writing." << sendmsg;
01259     return errno;
01260   };
01261     
01262   fprintf(fout, "# Data calculated by the VMD volmap function\n");
01263 
01264   
01265   
01266   
01267   
01268   fprintf(fout, "object 1 class gridpositions counts %d %d %d\n", xsize, ysize, zsize);
01269   fprintf(fout, "origin %g %g %g\n", volmap->origin[0], volmap->origin[1], volmap->origin[2]);
01270   fprintf(fout, "delta %g %g %g\n", cellx[0], cellx[1], cellx[2]);
01271   fprintf(fout, "delta %g %g %g\n", celly[0], celly[1], celly[2]);
01272   fprintf(fout, "delta %g %g %g\n", cellz[0], cellz[1], cellz[2]);
01273   fprintf(fout, "object 2 class gridconnections counts %d %d %d\n", xsize, ysize, zsize);
01274   fprintf(fout, "object 3 class array type double rank 0 items %d data follows\n", gridsize);
01275   
01276   
01277   float val1,val2,val3;
01278   int gx=0, gy=0, gz=-1;
01279   for (i=0; i < (gridsize/3)*3; i+=3)  {
01280     if (++gz >= zsize) {
01281       gz=0;
01282       if (++gy >= ysize) {gy=0; gx++;}
01283     }
01284     val1 = volmap->voxel_value(gx,gy,gz);
01285     if (++gz >= zsize) {
01286       gz=0;
01287       if (++gy >= ysize) {gy=0; gx++;}
01288     }
01289     val2 = volmap->voxel_value(gx,gy,gz);
01290     if (++gz >= zsize) {
01291       gz=0;
01292       if (++gy >= ysize) {gy=0; gx++;}
01293     }
01294     val3 = volmap->voxel_value(gx,gy,gz);    
01295     fprintf(fout, "%g %g %g\n", val1, val2, val3);
01296   }
01297   for (i=(gridsize/3)*3; i < gridsize; i++) {
01298     if (++gz >= zsize) {
01299       gz=0;
01300       if (++gy >= ysize) {gy=0; gx++;}
01301     }
01302     fprintf(fout, "%g ", volmap->voxel_value(gx,gy,gz));
01303   }
01304   if (gridsize%3) fprintf(fout, "\n");
01305   fprintf(fout, "\n");
01306   
01307   
01308   
01309   
01310   char *squotes = new char[strlen(volmap->name)+1];
01311   strcpy(squotes, volmap->name);
01312   char *s = squotes;
01313   while((s=strchr(s, '"'))) *s = '\'';
01314 
01315   if (volmap->name) {
01316     fprintf(fout, "object \"%s\" class field\n", squotes);
01317   } else {
01318     char dataname[10];
01319     strcpy(dataname, "(no name)");
01320     fprintf(fout, "object \"%s\" class field\n", dataname);
01321   }
01322 
01323   delete [] squotes;
01324 
01325   fclose(fout);
01326   return 0;
01327 }