Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members   Related Pages  

VolMapCreate.C

Go to the documentation of this file.
00001 /***************************************************************************
00002  *cr
00003  *cr            (C) Copyright 1995-2011 The Board of Trustees of the
00004  *cr                        University of Illinois
00005  *cr                         All Rights Reserved
00006  *cr
00007  ***************************************************************************/
00008 /***************************************************************************
00009  * RCS INFORMATION:
00010  *
00011  *      $RCSfile: VolMapCreate.C,v $
00012  *      $Author: johns $        $Locker:  $             $State: Exp $
00013  *      $Revision: 1.119 $      $Date: 2011/06/15 05:42:27 $
00014  *
00015  ***************************************************************************/
00016 
00017 /* Functions for creating useful volumetric maps based on the 3-D molecular structure */
00018 
00019 // Todo List: 
00020 // - Document!
00021 // - Don't just output to a DX file... give user more control (use plugins)
00022 // - Allow a framerange param, don't just use all available frames (and get rid
00023 // of the VMDApp dependency). Also, VMD needs a general FrameRange object...
00024 
00025 // Note:
00026 // All functions in here loop over x fastest and z slowest and also create
00027 // maps with that order of data. This matches the order used in
00028 // VolumetricData which is ultimately dictated by the way graphics hardware 
00029 // works.
00030 
00031 // XXX VolMapCreate provides its own dx file writer.
00032 // Actualy the maps should be generated in memory only and only dumped
00033 // to files using the molfile_plugin interface. This is currently
00034 // not yet possible but will hopefully be enabled soon.
00035 
00036 #include <math.h>
00037 #include <stdlib.h>
00038 #include <stdio.h>
00039 #include <string.h>
00040 #include <errno.h> // only for write_dx_file()
00041 
00042 #include "VMDApp.h"
00043 #include "MoleculeList.h"
00044 #include "Molecule.h"
00045 #include "Timestep.h"
00046 #include "Measure.h"
00047 #include "SpatialSearch.h"
00048 #include "VolCPotential.h"
00049 #include "VolumetricData.h"
00050 #include "VolMapCreate.h"
00051 #include "utilities.h"
00052 #include "ResizeArray.h"
00053 #include "Inform.h"
00054 #include "WKFUtils.h"
00055 
00056 #if defined(VMDUSEMSMPOT)
00057 #include "msmpot.h"
00058 #endif
00059 
00060 // Conversion factor between raw units (e^2 / A) and kT/e
00061 #define POT_CONV 560.47254
00062 
00063 #define MIN(X,Y) (((X)<(Y))? (X) : (Y))
00064 #define MAX(X,Y) (((X)>(Y))? (X) : (Y))
00065 
00068 static const float MAX_ENERGY = 150.f; 
00069 
00070 
00071 
00073 
00074 VolMapCreate::VolMapCreate(VMDApp *the_app, AtomSel *the_sel, float resolution) {
00075   volmap = NULL;
00076   app = the_app;
00077   sel = the_sel;
00078   delta = resolution;
00079   computed_frames = 0;
00080   checkpoint_freq = 0;
00081   checkpoint_name = NULL;
00082 
00083   char dataname[1];
00084   strcpy(dataname, ""); // null-terminated empty string
00085   float zerovec[3];
00086   memset(zerovec, 0, 3*sizeof(float));
00087   volmap = new VolumetricData(dataname, zerovec,
00088                               zerovec, zerovec, zerovec, 0, 0, 0, NULL);
00089   user_minmax = false;
00090 }
00091 
00092 
00093 VolMapCreate::~VolMapCreate() {
00094   if (volmap) delete volmap;
00095   if (checkpoint_name) delete[] checkpoint_name;
00096 }
00097 
00098 
00099 void VolMapCreate::set_minmax (float minx, float miny, float minz, float maxx, float maxy, float maxz) {
00100   user_minmax = true;
00101   min_coord[0] = minx;
00102   min_coord[1] = miny;
00103   min_coord[2] = minz;
00104   max_coord[0] = maxx;
00105   max_coord[1] = maxy;
00106   max_coord[2] = maxz;
00107 }
00108 
00109 
00110 void VolMapCreate::set_checkpoint (int checkpointfreq_tmp, char *checkpointname_tmp) {
00111   if (checkpointfreq_tmp > -1) checkpoint_freq = checkpointfreq_tmp;
00112   if (!checkpointname_tmp) return;
00113   
00114   if (checkpoint_name) delete[] checkpoint_name;
00115   checkpoint_name = new char[strlen(checkpointname_tmp)+1];
00116   strcpy(checkpoint_name, checkpointname_tmp);
00117 }
00118 
00119 
00122 int VolMapCreate::calculate_minmax (float *my_min_coord, float *my_max_coord) {
00123   DrawMolecule *mol = app->moleculeList->mol_from_id(sel->molid());
00124   int numframes = app->molecule_numframes(sel->molid()); // XXX need a frame selection object
00125   
00126   float frame_min_coord[3], frame_max_coord[3], *coords;
00127   
00128   msgInfo << "volmap: Computing bounding box coordinates" << sendmsg;
00129 
00130   int save_frame = sel->which_frame;
00131   int frame;
00132   for (frame=0; frame<numframes; frame++) {
00133     sel->which_frame=frame;
00134     sel->change(NULL,mol);
00135     coords = sel->coordinates(app->moleculeList);
00136     if (!coords) continue;
00137 
00138     int err = measure_minmax(sel->num_atoms, sel->on, coords, NULL, 
00139                              frame_min_coord, frame_max_coord);
00140     if (err != MEASURE_NOERR) {
00141       sel->which_frame = save_frame;
00142       return err;
00143     }
00144     
00145     int i;
00146     for (i=0; i<3; i++) {
00147       if (!frame || frame_min_coord[i] < my_min_coord[i]) my_min_coord[i] = frame_min_coord[i];
00148       if (!frame || frame_max_coord[i] > my_max_coord[i]) my_max_coord[i] = frame_max_coord[i];
00149     }
00150   }
00151   sel->which_frame = save_frame;
00152   
00153   return 0;
00154 }
00155 
00156 
00158 int VolMapCreate::calculate_max_radius (float &max_rad) {
00159   DrawMolecule *mol = app->moleculeList->mol_from_id(sel->molid());
00160   if (!mol) return -1;
00161   const float *radius = mol->extraflt.data("radius");
00162   if (!radius) return MEASURE_ERR_NORADII;
00163   
00164   max_rad = 0.f;
00165   int i;
00166   for (i=sel->firstsel; i<=sel->lastsel; i++) 
00167     if (sel->on[i] && radius[i] > max_rad) max_rad = radius[i];
00168   
00169   return 0;
00170 }
00171 
00172 // Combo routines are used to combine the different frame maps together into a
00173 // final entity
00174 
00175 // Initialize the frame combination buffer
00176 void VolMapCreate::combo_begin(CombineType method, void **customptr, void *params) {
00177   int gridsize = volmap->xsize*volmap->ysize*volmap->zsize;
00178   
00179   *customptr = NULL;
00180   memset(volmap->data, 0, sizeof(float)*gridsize);
00181   computed_frames = 0;
00182   
00183   // these combine types need additional storage
00184   if (method == COMBINE_STDEV) {
00185     float *voldata2 = new float[gridsize];
00186     memset(voldata2, 0, gridsize*sizeof(float));
00187     *customptr = (void*) voldata2;
00188   }
00189 }
00190 
00191 // Add a frame to the combination buffer
00192 void VolMapCreate::combo_addframe(CombineType method, float *voldata, void *customptr, float *frame_voldata) {
00193   float *voldata2 = (float*) customptr;
00194   int gridsize = volmap->xsize*volmap->ysize*volmap->zsize;
00195   int n;
00196   
00197   computed_frames++;
00198      
00199   if (computed_frames == 1) { // FIRST FRAME
00200     switch (method) {
00201     case COMBINE_AVG:
00202     case COMBINE_MAX:    
00203     case COMBINE_MIN:    
00204       memcpy(voldata, frame_voldata, gridsize*sizeof(float));
00205       break;
00206     case COMBINE_PMF:
00207       memcpy(voldata, frame_voldata, gridsize*sizeof(float));
00208       break;
00209     case COMBINE_STDEV:    
00210       memcpy(voldata, frame_voldata, gridsize*sizeof(float));
00211       for (n=0; n<gridsize; n++) voldata2[n] = frame_voldata[n]*frame_voldata[n];
00212       break;
00213     }
00214     
00215     return;
00216   }
00217 
00218   // THE FOLLOWING ONLY APPLIES TO OTHER FRAMES THAN FIRST
00219   switch (method) {
00220     case COMBINE_AVG:
00221       for (n=0; n<gridsize; n++) voldata[n] += frame_voldata[n];
00222       break;
00223     case COMBINE_PMF:
00224       for (n=0; n<gridsize; n++) voldata[n] = (float) -log(exp(-voldata[n]) + exp(-frame_voldata[n]));
00225       break;
00226     case COMBINE_MAX:    
00227       for (n=0; n<gridsize; n++) voldata[n] = MAX(voldata[n], frame_voldata[n]);
00228       break;
00229     case COMBINE_MIN:    
00230       for (n=0; n<gridsize; n++) voldata[n] = MIN(voldata[n], frame_voldata[n]);
00231       break;
00232     case COMBINE_STDEV:    
00233       for (n=0; n<gridsize; n++) voldata[n] += frame_voldata[n];
00234       for (n=0; n<gridsize; n++) voldata2[n] += frame_voldata[n]*frame_voldata[n];
00235       break;
00236   }
00237 }
00238 
00239 
00244 void VolMapCreate::combo_export(CombineType method, float *voldata, void *customptr) {
00245   float *voldata2 = (float*) customptr;
00246   int gridsize = volmap->xsize*volmap->ysize*volmap->zsize;
00247   int n;
00248   
00249   switch (method) {
00250   case COMBINE_AVG:
00251     for (n=0; n<gridsize; n++)
00252       volmap->data[n] = voldata[n]/computed_frames;
00253     break;
00254   case COMBINE_PMF:
00255     for (n=0; n<gridsize; n++) {
00256       float val = voldata[n] + logf((float) computed_frames);
00257       if (val > MAX_ENERGY) val = MAX_ENERGY;  // weed out outlying data
00258       volmap->data[n] = val;
00259     }
00260     break;
00261   case COMBINE_MAX:
00262   case COMBINE_MIN:    
00263     memcpy(volmap->data, voldata, gridsize*sizeof(float));    
00264     break;
00265   case COMBINE_STDEV:    
00266     for (n=0; n<gridsize; n++) {
00267       volmap->data[n] = voldata[n]/computed_frames;
00268       volmap->data[n] = sqrtf(voldata2[n]/computed_frames - volmap->data[n]*volmap->data[n]); 
00269     }
00270     break;
00271   }
00272 }
00273 
00274 
00276 void VolMapCreate::combo_end(CombineType method, void *customptr) {
00277   if (method == COMBINE_STDEV) {
00278     float *voldata2 = (float*) customptr;
00279     delete[] voldata2;
00280   }
00281 }
00282 
00283 
00288 int VolMapCreate::compute_all (bool allframes, CombineType method, void *params) {
00289   int err = this->compute_init();
00290   if (err) return err;
00291   
00292   int gridsize = volmap->xsize*volmap->ysize*volmap->zsize;
00293 
00294   // Special case: if only have one frame do it here the fast way
00295   if (!allframes) {
00296     if (volmap->data) delete[] volmap->data;
00297     volmap->data = new float[gridsize];         // final exported voldata
00298   
00299     msgInfo << "volmap: grid size = " << volmap->xsize
00300             <<"x"<< volmap->ysize <<"x"<< volmap->zsize;
00301     char tmp[64];
00302     sprintf(tmp, " (%.1f MB)", sizeof(float)*gridsize/(1024.*1024.));
00303     msgInfo << tmp << sendmsg;
00304 
00305     // only compute the current frame of the given selection
00306     this->compute_frame(sel->which_frame, volmap->data); 
00307     
00308     //err = this->compute_end();
00309     //if (err) return err;
00310     return 0; // no error
00311   }
00312   
00313   
00314   msgInfo << "volmap: grid size    = " << volmap->xsize
00315           <<"x"<< volmap->ysize <<"x"<< volmap->zsize;
00316   char tmp[64];
00317   sprintf(tmp, " (%.1f MB)", sizeof(float)*gridsize/(1024.*1024.));
00318   msgInfo << tmp << sendmsg;
00319 
00320   int numframes = app->molecule_numframes(sel->molid());
00321   msgInfo << "volmap: Computing " << numframes << " frames in total..." << sendmsg;
00322 
00323   if (volmap->data) delete[] volmap->data;
00324   volmap->data = new float[gridsize];         // final exported voldata
00325   float *frame_voldata = new float[gridsize]; // individual frame voldata
00326   float *voldata = new float[gridsize];       // combo cache voldata
00327   
00328   void *customptr = NULL;
00329   combo_begin(method, &customptr, params);
00330   wkf_timerhandle timer = wkf_timer_create();
00331 
00332   // Combine frame_voldata into voldata, one frame at a time, starting with 1st frame
00333   int frame;
00334   for (frame=0; frame<numframes; frame++) { 
00335     // XXX to-do, only take frames from a frame selection
00336     msgInfo << "volmap: frame " << frame << "/" << numframes;
00337 #ifdef TIMING
00338     msgInfo << sendmsg;
00339 #else
00340     msgInfo << "   ";
00341 #endif
00342 
00343     wkf_timer_start(timer);
00344 
00345     this->compute_frame(frame, frame_voldata);
00346     wkf_timer_stop(timer);
00347     msgInfo << "Total time = " << wkf_timer_time(timer) << " s" << sendmsg;
00348 
00349     combo_addframe(method, voldata, customptr, frame_voldata);
00350     if (checkpoint_freq && computed_frames && !(computed_frames%checkpoint_freq)) {
00351       combo_export(method, voldata, customptr);
00352       const char *filename;
00353       if (checkpoint_name) filename=checkpoint_name;
00354       else filename = "checkpoint.dx";
00355       write_map(filename);
00356     }
00357   }
00358     
00359   wkf_timer_destroy(timer);
00360 
00361   delete[] frame_voldata;
00362   
00363   // All frames have been combined, perform finishing steps here
00364   combo_export(method, voldata, customptr);
00365   combo_end (method, customptr);
00366   delete[] voldata;
00367        
00368   return 0; // no error
00369 }
00370 
00371 
00372 
00373 // compute_init() sets up the grid coordinate system and dimensions
00374 // If the user did not specify the grid's minmax boundary, it is
00375 // defaulted to the trajectory's minmax coordinates, to which "padding"
00376 // is added in all dimensions. 
00377 int VolMapCreate::compute_init (float padding) {
00378   if (!sel) return MEASURE_ERR_NOSEL;
00379   if (sel->num_atoms == 0) return MEASURE_ERR_NOATOMS;
00380   
00381   int err, i;
00382   
00383   if (!volmap) return -1;
00384   
00385   if (user_minmax)
00386     padding = 0.;  // don't want to pad user's defaults
00387   else {
00388     // The minmax coordinates over all frames
00389     err = calculate_minmax(min_coord, max_coord);
00390     if (err) return err;
00391   }
00392   
00393   // Depending on the volmap type we are computing we add some padding
00394   // to the dimensions of the grid. This function is called by the 
00395   // compute_init() methods of the VolMapCreate<type> subclasses. 
00396   // The caller provides a reasonable map type specific padding value.
00397   // The padding can for example be the radius of the largest atom or
00398   // an interaction distance cutoff.
00399   // After padding we align the grid with integer coordinates.
00400   for (i=0; i<3; i++) {
00401     //adjust padding and ensure that different maps are properly aligned
00402     min_coord[i] = (float) floor((min_coord[i] - padding)/delta)*delta;    
00403     max_coord[i] = (float)  ceil((max_coord[i] + padding)/delta)*delta;
00404   }
00405   
00406   volmap->xsize = MAX((int)((max_coord[0] - min_coord[0])/delta), 0);
00407   volmap->ysize = MAX((int)((max_coord[1] - min_coord[1])/delta), 0);
00408   volmap->zsize = MAX((int)((max_coord[2] - min_coord[2])/delta), 0);
00409 
00410   char tmpstr[256];
00411   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]);
00412   msgInfo << "volmap: grid minmax = " << tmpstr << sendmsg; 
00413   
00414   float cellx[3], celly[3], cellz[3];
00415   cellx[0] = delta;
00416   cellx[1] = 0.f;
00417   cellx[2] = 0.f;
00418   celly[0] = 0.f;
00419   celly[1] = delta;
00420   celly[2] = 0.f;
00421   cellz[0] = 0.f;
00422   cellz[1] = 0.f;
00423   cellz[2] = delta;
00424 
00425   // define origin by shifting to middle of each cell,
00426   // compute_frame() needs to take this into account
00427   for (i=0; i<3; i++) 
00428     volmap->origin[i] = min_coord[i] + \
00429                  0.5f*(cellx[i] + celly[i] + cellz[i]);
00430   int d;
00431   for (d=0; d<3; d++) {
00432     volmap->xaxis[d] = cellx[d]*(volmap->xsize-1);
00433     volmap->yaxis[d] = celly[d]*(volmap->ysize-1);
00434     volmap->zaxis[d] = cellz[d]*(volmap->zsize-1);
00435   }
00436   
00437   if (!volmap->xsize*volmap->ysize*volmap->zsize)
00438     return MEASURE_ERR_ZEROGRIDSIZE;
00439 
00440   return 0; // no error
00441 }
00442 
00443 
00444 
00446 
00451 
00452 int VolMapCreateMask::compute_init() {
00453   char tmpstr[255];
00454   sprintf(tmpstr, "mask (%s.200)", sel->cmdStr);
00455   volmap->set_name(tmpstr);
00456     
00457   return VolMapCreate::compute_init(atomradius+0.5f);
00458 }
00459 
00460 
00461 int VolMapCreateMask::compute_frame (int frame, float *voldata) {
00462   DrawMolecule *mol = app->moleculeList->mol_from_id(sel->molid());
00463   if (!mol) return -1;
00464   
00465   int i;
00466   int GRIDSIZEX = volmap->xsize;
00467   int GRIDSIZEY = volmap->ysize;
00468   int GRIDSIZEZ = volmap->zsize;
00469   int gridsize = volmap->xsize*volmap->ysize*volmap->zsize;
00470   
00471   //create volumetric density grid
00472   memset(voldata, 0, gridsize*sizeof(float));
00473   int save_frame = sel->which_frame;
00474   sel->which_frame=frame;
00475   sel->change(NULL,mol);
00476   
00477   const float *coords = sel->coordinates(app->moleculeList);
00478   if (!coords) {
00479     sel->which_frame = save_frame;
00480     return -1;
00481   }
00482   
00483   float cellx[3], celly[3], cellz[3];
00484   volmap->cell_axes(cellx, celly, cellz);
00485 
00486   float min_coords[3];
00487   for (i=0; i<3; i++)
00488     min_coords[i] = float(volmap->origin[i] - 0.5f*(cellx[i] + celly[i] + cellz[i]));
00489   
00490   // paint atomic spheres on map
00491   int gx, gy, gz;
00492   for (i=sel->firstsel; i<=sel->lastsel; i++) { 
00493     if (!sel->on[i]) continue; //atom is not selected
00494 
00495     gx = (int) ((coords[3*i  ] - min_coords[0])/delta);
00496     gy = (int) ((coords[3*i+1] - min_coords[1])/delta);
00497     gz = (int) ((coords[3*i+2] - min_coords[2])/delta);
00498       
00499     int steps = (int)(atomradius/delta)+1;
00500     int iz, iy, ix;
00501     for (iz=MAX(gz-steps,0); iz<=MIN(gz+steps,GRIDSIZEZ-1); iz++)
00502     for (iy=MAX(gy-steps,0); iy<=MIN(gy+steps,GRIDSIZEY-1); iy++)
00503     for (ix=MAX(gx-steps,0); ix<=MIN(gx+steps,GRIDSIZEX-1); ix++) {
00504       int n = ix + iy*GRIDSIZEX + iz*GRIDSIZEY*GRIDSIZEX;
00505       float dx = float(coords[3*i  ] - volmap->origin[0] - ix*delta);
00506       float dy = float(coords[3*i+1] - volmap->origin[1] - iy*delta);
00507       float dz = float(coords[3*i+2] - volmap->origin[2] - iz*delta);
00508       float dist2 = dx*dx+dy*dy+dz*dz;
00509       if (dist2 <= atomradius*atomradius) voldata[n] = 1.f;
00510     }
00511   }
00512   
00513   sel->which_frame = save_frame;
00514   
00515   return 0;
00516 }  
00517 
00518 
00519 
00521 
00529 
00530 int VolMapCreateDensity::compute_init () {
00531   char tmpstr[255];
00532   sprintf(tmpstr, "density (%.200s) [A^-3]", sel->cmdStr);
00533   volmap->set_name(tmpstr);
00534   
00535   float max_rad=0.f;
00536   calculate_max_radius(max_rad);
00537     
00538   return VolMapCreate::compute_init(MAX(3.f*radius_scale*max_rad,10.f));
00539 }
00540 
00541 
00542 int VolMapCreateDensity::compute_frame (int frame, float *voldata) {
00543   if (!weight) return MEASURE_ERR_NOWEIGHT;
00544     
00545   DrawMolecule *mol = app->moleculeList->mol_from_id(sel->molid());
00546   if (!mol) return -1;
00547     int i;
00548     
00549   const float *radius = mol->extraflt.data("radius");
00550   if (!radius) return MEASURE_ERR_NORADII;
00551   
00552   int GRIDSIZEX = volmap->xsize;
00553   int GRIDSIZEY = volmap->ysize;
00554   int GRIDSIZEZ = volmap->zsize;
00555   int gridsize = volmap->xsize*volmap->ysize*volmap->zsize;
00556 
00557   //create volumetric density grid
00558   memset(voldata, 0, gridsize*sizeof(float));
00559   int save_frame = sel->which_frame;
00560   sel->which_frame = frame;
00561   sel->change(NULL,mol);
00562   const float *coords = sel->coordinates(app->moleculeList);
00563   if (!coords) {
00564     sel->which_frame = save_frame;
00565     return -1;
00566   }
00567   
00568   float cellx[3], celly[3], cellz[3];
00569   volmap->cell_axes(cellx, celly, cellz);
00570 
00571   float min_coords[3];
00572   for (i=0; i<3; i++) 
00573     min_coords[i] = float(volmap->origin[i] - 0.5f*(cellx[i] + celly[i] + cellz[i]));
00574   
00575   int w_index=0;
00576   int gx, gy, gz;   // grid coord indices
00577   for (i=sel->firstsel; i<=sel->lastsel; i++) { 
00578     if (!sel->on[i]) continue; //atom is not selected
00579 
00580     gx = (int) ((coords[3*i  ] - min_coords[0])/delta);
00581     gy = (int) ((coords[3*i+1] - min_coords[1])/delta);
00582     gz = (int) ((coords[3*i+2] - min_coords[2])/delta);
00583       
00584     float scaled_radius = 0.5f*radius_scale*radius[i];
00585     float exp_factor = 1.0f/(2.0f*scaled_radius*scaled_radius);
00586     float norm = weight[w_index++]/(sqrtf((float) (8.0f*VMD_PI*VMD_PI*VMD_PI))*scaled_radius*scaled_radius*scaled_radius);
00587                   
00588     int steps = (int)(4.1f*scaled_radius/delta);
00589     int iz, iy, ix;
00590     for (iz=MAX(gz-steps,0); iz<=MIN(gz+steps,GRIDSIZEZ-1); iz++)
00591     for (iy=MAX(gy-steps,0); iy<=MIN(gy+steps,GRIDSIZEY-1); iy++)
00592     for (ix=MAX(gx-steps,0); ix<=MIN(gx+steps,GRIDSIZEX-1); ix++) {
00593       int n = ix + iy*GRIDSIZEX + iz*GRIDSIZEY*GRIDSIZEX;
00594       float dx = float(coords[3*i  ] - volmap->origin[0] - ix*delta);
00595       float dy = float(coords[3*i+1] - volmap->origin[1] - iy*delta);
00596       float dz = float(coords[3*i+2] - volmap->origin[2] - iz*delta);
00597       float dist2 = dx*dx+dy*dy+dz*dz;
00598       voldata[n] += norm * expf(-dist2*exp_factor);
00599       // Uncomment the following line for a much faster implementation
00600       // This is useful is all you care about is the smooth visual appearance
00601       // voldata[n] += exp_factor/(dist2+10.f);
00602     }
00603   }
00604 
00605   sel->which_frame = save_frame;
00606     
00607   return 0;
00608 }  
00609 
00610 
00611 
00612 
00614   
00618   
00619 int VolMapCreateInterp::compute_init () {
00620   char tmpstr[255];
00621   sprintf(tmpstr, "interp (%.200s) [A^-3]", sel->cmdStr);
00622   volmap->set_name(tmpstr);
00623   
00624   return VolMapCreate::compute_init(delta+0.5f);
00625 }
00626 
00627 
00628 int VolMapCreateInterp::compute_frame (int frame, float *voldata) {
00629   if (!weight) return MEASURE_ERR_NOWEIGHT;
00630     
00631   DrawMolecule *mol = app->moleculeList->mol_from_id(sel->molid());
00632   if (!mol) return -1;
00633     int i;
00634     
00635   int GRIDSIZEX = volmap->xsize;
00636   int GRIDSIZEY = volmap->ysize;
00637   int GRIDSIZEXY = GRIDSIZEX * GRIDSIZEY;
00638   int gridsize = volmap->xsize*volmap->ysize*volmap->zsize;
00639 
00640   // create volumetric density grid
00641   memset(voldata, 0, gridsize*sizeof(float));
00642   int save_frame = sel->which_frame;
00643   sel->which_frame = frame;
00644   sel->change(NULL,mol);
00645   const float *coords = sel->coordinates(app->moleculeList);
00646   if (!coords) {
00647     sel->which_frame = save_frame;
00648     return -1;
00649   }
00650   
00651   int w_index=0;
00652   int gx, gy, gz;      // grid coord indices
00653   float fgx, fgy, fgz; // fractional grid coord indices
00654   float dx, dy, dz;    // to measure distances
00655   for (i=sel->firstsel; i<=sel->lastsel; i++) { 
00656     if (!sel->on[i]) continue; //atom is not selected
00657 
00658     // Find position of the atom within the map ("fractional indices")
00659     fgx = float(coords[3*i  ] - volmap->origin[0])/delta;
00660     fgy = float(coords[3*i+1] - volmap->origin[1])/delta;
00661     fgz = float(coords[3*i+2] - volmap->origin[2])/delta;
00662 
00663     // Find nearest voxel with lowest indices
00664     gx = (int) fgx;
00665     gy = (int) fgy;
00666     gz = (int) fgz;
00667 
00668     // Calculate distance between atom and each voxel
00669     dx = fgx - gx;
00670     dy = fgy - gy;
00671     dz = fgz - gz;
00672 
00673     // Perform trilinear interpolation
00674 
00675     voldata[ gx + gy*GRIDSIZEX + gz*GRIDSIZEXY ] \
00676       += (1.0f - dx) * (1.0f - dy) * (1.0f - dz) * weight[w_index];
00677 
00678     voldata[ (gx+1) + (gy+1)*GRIDSIZEX + (gz+1)*GRIDSIZEXY ] \
00679       += dx * dy * dz * weight[w_index];
00680 
00681     voldata[ (gx+1) + (gy+1)*GRIDSIZEX + gz*GRIDSIZEXY ] \
00682       += dx * dy * (1.0f - dz) * weight[w_index];
00683 
00684     voldata[ gx + gy*GRIDSIZEX + (gz+1)*GRIDSIZEXY ] \
00685       += (1.0f - dx) * (1.0f - dy) * dz * weight[w_index];
00686 
00687     voldata[ (gx+1) + gy*GRIDSIZEX + gz*GRIDSIZEXY ] \
00688       += dx * (1.0f - dy) * (1.0f - dz) * weight[w_index];
00689 
00690     voldata[ gx + (gy+1)*GRIDSIZEX + (gz+1)*GRIDSIZEXY ] \
00691       += (1.0f - dx) * dy * dz * weight[w_index];
00692 
00693     voldata[ gx + (gy+1)*GRIDSIZEX + gz*GRIDSIZEXY ] \
00694       += (1.0f - dx) * dy * (1.0f - dz) * weight[w_index];
00695 
00696     voldata[ (gx+1) + gy*GRIDSIZEX + (gz+1)*GRIDSIZEXY ] \
00697       += dx * (1.0f - dy) + dz * weight[w_index++];
00698   }
00699 
00700   sel->which_frame = save_frame;
00701       
00702   return 0;
00703 }  
00704 
00705 
00706 
00707 
00708   
00710 
00716 
00717 int VolMapCreateOccupancy::compute_init () {
00718   char tmpstr[255];
00719   sprintf(tmpstr, "occupancy (%.200s)", sel->cmdStr);
00720   volmap->set_name(tmpstr);
00721   
00722   float max_rad=0.f;  
00723   if (use_points)
00724     max_rad = 1.f;
00725   else
00726     calculate_max_radius(max_rad);
00727   
00728   return VolMapCreate::compute_init(max_rad);
00729 }
00730 
00731 
00732 int VolMapCreateOccupancy::compute_frame(int frame, float *voldata) { 
00733   DrawMolecule *mol = app->moleculeList->mol_from_id(sel->molid());
00734   if (!mol) return -1;
00735   
00736   int GRIDSIZEX = volmap->xsize;
00737   int GRIDSIZEY = volmap->ysize;
00738   int GRIDSIZEZ = volmap->zsize;
00739   int gridsize = volmap->xsize*volmap->ysize*volmap->zsize;
00740   int i;
00741   
00742   //create volumetric density grid
00743   memset(voldata, 0, gridsize*sizeof(float));
00744   int save_frame = sel->which_frame;
00745   sel->which_frame=frame;
00746   sel->change(NULL,mol);
00747   const float *coords = sel->coordinates(app->moleculeList);
00748 
00749   if (!coords) {
00750     sel->which_frame = save_frame;
00751     return -1;
00752   }
00753 
00754   float cellx[3], celly[3], cellz[3];
00755   volmap->cell_axes(cellx, celly, cellz);
00756 
00757   float min_coords[3];
00758   for (i=0; i<3; i++) 
00759     min_coords[i] = float(volmap->origin[i] - 0.5f*(cellx[i] + celly[i] + cellz[i]));
00760 
00761   int gx, gy, gz;
00762   
00763   if (use_points) { // draw single points
00764     for (i=sel->firstsel; i<=sel->lastsel; i++) { 
00765       if (!sel->on[i]) continue; //atom is not selected
00766 
00767       gx = (int) ((coords[3*i  ] - min_coords[0])/delta);
00768       if (gx<0 || gx>=GRIDSIZEX) continue;
00769       gy = (int) ((coords[3*i+1] - min_coords[1])/delta);
00770       if (gy<0 || gy>=GRIDSIZEY) continue;
00771       gz = (int) ((coords[3*i+2] - min_coords[2])/delta);
00772       if (gz<0 || gz>=GRIDSIZEZ) continue;
00773 
00774       voldata[gx+GRIDSIZEX*gy+GRIDSIZEX*GRIDSIZEY*gz] = 1.f; 
00775     }
00776   }
00777   else { // paint atomic spheres on map
00778     const float *radius = mol->extraflt.data("radius");
00779     if (!radius) {
00780       sel->which_frame = save_frame;
00781       return MEASURE_ERR_NORADII;
00782     }
00783   
00784     for (i=sel->firstsel; i<=sel->lastsel; i++) { 
00785       if (!sel->on[i]) continue; //atom is not selected
00786 
00787       gx = (int) ((coords[3*i  ] - min_coords[0])/delta);
00788       gy = (int) ((coords[3*i+1] - min_coords[1])/delta);
00789       gz = (int) ((coords[3*i+2] - min_coords[2])/delta);
00790       
00791       int steps = (int)(radius[i]/delta)+1;
00792       int iz, iy, ix;
00793       for (iz=MAX(gz-steps,0); iz<=MIN(gz+steps,GRIDSIZEZ-1); iz++)
00794       for (iy=MAX(gy-steps,0); iy<=MIN(gy+steps,GRIDSIZEY-1); iy++)
00795       for (ix=MAX(gx-steps,0); ix<=MIN(gx+steps,GRIDSIZEX-1); ix++) {
00796         int n = ix + iy*GRIDSIZEX + iz*GRIDSIZEY*GRIDSIZEX;
00797         float dx = float(coords[3*i  ] - volmap->origin[0] - ix*delta);
00798         float dy = float(coords[3*i+1] - volmap->origin[1] - iy*delta);
00799         float dz = float(coords[3*i+2] - volmap->origin[2] - iz*delta);
00800         float dist2 = dx*dx+dy*dy+dz*dz;
00801         if (dist2 <= radius[i]*radius[i]) voldata[n] = 1.f;
00802       }
00803     }
00804   }
00805   
00806   sel->which_frame = save_frame;
00807     
00808   return 0;
00809 }
00810 
00811 
00812 
00814 
00820 
00821 int VolMapCreateDistance::compute_init () {
00822   char tmpstr[255];
00823   sprintf(tmpstr, "distance (%.200s) [A]", sel->cmdStr);
00824   volmap->set_name(tmpstr);
00825   
00826   float max_rad=0.f;
00827   calculate_max_radius(max_rad);
00828   
00829   return VolMapCreate::compute_init(max_rad+max_dist);
00830 }
00831  
00832 
00835 int VolMapCreateDistance::compute_frame(int frame, float *voldata) { 
00836   int i, n;  
00837   DrawMolecule *mol = app->moleculeList->mol_from_id(sel->molid());
00838   if (!mol) return -1;
00839   const float *radius = mol->extraflt.data("radius");
00840   if (!radius) return MEASURE_ERR_NORADII;
00841   
00842   int GRIDSIZEX = volmap->xsize;
00843   int GRIDSIZEY = volmap->ysize;
00844   int gridsize = volmap->xsize*volmap->ysize*volmap->zsize;
00845 
00846   float dx, dy, dz;
00847   float dist, mindist, r;
00848   
00849   float max_rad=0.f;
00850   calculate_max_radius(max_rad);
00851   
00852   // 1. Create a fake "molecule" containing all of the grid points
00853   //    this is quite memory intensive but _MUCH_ faster doing it point-by point!
00854   
00855   float *gridpos = new float[3*gridsize]; 
00856   int *gridon = new int[gridsize]; 
00857   for (n=0; n<gridsize; n++) {
00858     gridpos[3*n  ] = float((n%GRIDSIZEX)*delta + volmap->origin[0]); //position of grid cell's center
00859     gridpos[3*n+1] = float(((n/GRIDSIZEX)%GRIDSIZEY)*delta + volmap->origin[1]);
00860     gridpos[3*n+2] = float((n/(GRIDSIZEX*GRIDSIZEY))*delta + volmap->origin[2]); 
00861     gridon[n] = 1;
00862   }
00863 
00864   GridSearchPair *pairlist, *p;
00865 
00866   int save_frame = sel->which_frame;
00867   sel->which_frame = frame;
00868   sel->change(NULL,mol);
00869   const float *coords = sel->coordinates(app->moleculeList);
00870   if (!coords) {
00871     sel->which_frame = save_frame;
00872     return -1;
00873   }
00874   
00875   // initialize all grid points to be the maximal allowed distance = cutoff
00876   for (n=0; n<gridsize; n++) voldata[n] = max_dist;
00877   
00878   // 2. Create a list of all bonds between the grid and the real molecule
00879   //    which are within the user-set cutoff distance 
00880   //    (the use of a cutoff is purely to speed this up tremendously)
00881   
00882   pairlist = vmd_gridsearch3(gridpos, gridsize, gridon, coords,
00883                              sel->num_atoms, sel->on, max_dist+max_rad, true, -1);
00884   for (p=pairlist; p; p=p->next) {
00885     n = p->ind1;
00886     // if a grid point is already known to be inside an atom, skip it and save some time
00887     if ((mindist = voldata[n]) == 0.f) continue;
00888     i = p->ind2;
00889     r = radius[i];
00890     dx = gridpos[3*n  ] - coords[3*i];
00891     dy = gridpos[3*n+1] - coords[3*i+1];
00892     dz = gridpos[3*n+2] - coords[3*i+2];
00893     
00894     // 3. At each grid point, store the _smallest_ recorded distance
00895     //    to a nearby atomic surface
00896       
00897     dist = sqrtf(dx*dx+dy*dy+dz*dz) - r;
00898     if (dist < 0) dist = 0.f;
00899     if (dist < mindist) voldata[n] = dist;
00900   }
00901   
00902   // delete pairlist
00903   for (p=pairlist; p;) {
00904     GridSearchPair *tmp = p;
00905     p = p->next;
00906     free(tmp);
00907   }  
00908 
00909   delete [] gridpos; 
00910   delete [] gridon; 
00911 
00912   sel->which_frame = save_frame;
00913 
00914   return MEASURE_NOERR; 
00915 }
00916 
00917 
00918 
00919 
00921   
00922 int VolMapCreateCoulombPotential::compute_init () {
00923   char tmpstr[255];
00924   sprintf(tmpstr, "Potential (kT/e at 298.15K) (%.200s)", sel->cmdStr);
00925   volmap->set_name(tmpstr);
00926   
00927   float max_rad;
00928   calculate_max_radius(max_rad);
00929     
00930   // init object, no extra padding by default  
00931   return VolMapCreate::compute_init(0.f);
00932 }
00933 
00934 
00935 int VolMapCreateCoulombPotential::compute_frame(int frame, float *voldata) {
00936   DrawMolecule *mol = app->moleculeList->mol_from_id(sel->molid());
00937   if (!mol) return -1;
00938     int i;
00939     
00940   const float *charge = mol->extraflt.data("charge");
00941   if (!charge) return MEASURE_ERR_NORADII; // XXX fix this later
00942 
00943   int gridsize=volmap->xsize*volmap->ysize*volmap->zsize;
00944 
00945   // create volumetric density grid
00946   memset(voldata, 0, gridsize*sizeof(float));
00947   int save_frame = sel->which_frame;
00948   sel->which_frame=frame;
00949   sel->change(NULL,mol);
00950   const float *coords = sel->coordinates(app->moleculeList);
00951   if (!coords) {
00952     sel->which_frame = save_frame;
00953     return -1;
00954   }
00955  
00956   float cellx[3], celly[3], cellz[3];
00957   volmap->cell_axes(cellx, celly, cellz);
00958 
00959   float min_coords[3];
00960   for (i=0; i<3; i++) 
00961     min_coords[i] = float(volmap->origin[i] - 0.5f*(cellx[i] + celly[i] + cellz[i]));
00962 
00963   // copy selected atom coordinates and charges to a contiguous memory
00964   // buffer and translate them to the starting corner of the map.
00965   float *xyzq = (float *) malloc(sel->selected * 4 * sizeof(float));
00966   float *curatom = xyzq;
00967   for (i=sel->firstsel; i<=sel->lastsel; i++) { 
00968     if (sel->on[i]) {
00969       curatom[0] = coords[3*i  ] - min_coords[0];
00970       curatom[1] = coords[3*i+1] - min_coords[1];
00971       curatom[2] = coords[3*i+2] - min_coords[2];
00972       curatom[3] = charge[i] * float(POT_CONV);
00973       curatom += 4;
00974     }
00975   }
00976 
00977   vol_cpotential(sel->selected, xyzq, voldata, 
00978                  volmap->zsize, volmap->ysize, volmap->xsize, delta);
00979 
00980   free(xyzq);
00981 
00982   sel->which_frame = save_frame;
00983  
00984   return 0;
00985 }  
00986 
00988 
00989 #if defined(VMDUSEMSMPOT)
00990 int VolMapCreateCoulombPotentialMSM::compute_init () {
00991   char tmpstr[255];
00992   sprintf(tmpstr, "Potential (kT/e at 298.15K) (%.200s)", sel->cmdStr);
00993   volmap->set_name(tmpstr);
00994   
00995   float max_rad;
00996   calculate_max_radius(max_rad);
00997   
00998   // init object, no extra padding by default
00999   // Note: padding would create serious problems for the periodic case 
01000   return VolMapCreate::compute_init(0.f);
01001 }
01002 
01003 
01004 int VolMapCreateCoulombPotentialMSM::compute_frame(int frame, float *voldata) {
01005   DrawMolecule *mol = app->moleculeList->mol_from_id(sel->molid());
01006   if (!mol) return -1;
01007     int i;
01008 
01009   int usepbc = 0;
01010     
01011   const float *charge = mol->extraflt.data("charge");
01012   if (!charge) return MEASURE_ERR_NORADII; // XXX fix this later
01013 
01014   int gridsize=volmap->xsize*volmap->ysize*volmap->zsize;
01015 
01016   // create volumetric density grid
01017   memset(voldata, 0, gridsize*sizeof(float));
01018   int save_frame = sel->which_frame;
01019   sel->which_frame=frame;
01020   sel->change(NULL,mol);
01021   const float *coords = sel->coordinates(app->moleculeList);
01022   const Timestep *ts = sel->timestep(app->moleculeList); 
01023   if (!coords) {
01024     sel->which_frame = save_frame;
01025     return -1;
01026   }
01027   if (!ts) {
01028     return -1;
01029   }
01030  
01031   float cellx[3], celly[3], cellz[3];
01032   volmap->cell_axes(cellx, celly, cellz);
01033 
01034   float min_coords[3];
01035   for (i=0; i<3; i++) 
01036     min_coords[i] = float(volmap->origin[i] - 0.5f*(cellx[i] + celly[i] + cellz[i]));
01037 
01038   // copy selected atom coordinates and charges to a contiguous memory
01039   // buffer and translate them to the starting corner of the map.
01040   float *xyzq = (float *) malloc(sel->selected * 4 * sizeof(float));
01041   float *curatom = xyzq;
01042   for (i=sel->firstsel; i<=sel->lastsel; i++) { 
01043     if (sel->on[i]) {
01044       curatom[0] = coords[3*i  ] - min_coords[0];
01045       curatom[1] = coords[3*i+1] - min_coords[1];
01046       curatom[2] = coords[3*i+2] - min_coords[2];
01047       curatom[3] = charge[i] * float(POT_CONV);
01048       curatom += 4;
01049     }
01050   }
01051 
01052   Msmpot *msm = Msmpot_create(); // create a multilevel summation object
01053 #if 0
01054   int msmrc;
01055   int mx = volmap->xsize;  /* map lattice dimensions */
01056   int my = volmap->ysize;
01057   int mz = volmap->zsize;
01058   float lx = delta*mx;     /* map lattice lengths */
01059   float ly = delta*my;
01060   float lz = delta*mz;
01061   float x0=0, y0=0, z0=0;  /* map origin */
01062   float vx=0, vy=0, vz=0;  /* periodic domain lengths (0 for nonperiodic) */
01063 
01064   if (getenv("MSMPOT_NOCUDA")) {
01065     /* turn off use of CUDA (with 0 in last parameter) */
01066     Msmpot_configure(msm, 0, 0, 0, 0, 0, 0, 0, 0, 0);
01067   }
01068 
01069   if (getenv("MSMPOT_PBCON")) {
01070     vx = lx, vy = ly, vz = lz;  /* use periodic boundary conditions */
01071   }
01072 
01073   if (getenv("MSMPOT_EXACT")) { 
01074     msmrc = Msmpot_compute_exact(msm, voldata, 
01075         mx, my, mz, lx, ly, lz, x0, y0, z0, vx, vy, vz,
01076         xyzq, sel->selected);
01077   }
01078   else {
01079     msmrc = Msmpot_compute(msm, voldata, 
01080         mx, my, mz, lx, ly, lz, x0, y0, z0, vx, vy, vz,
01081         xyzq, sel->selected);
01082   }
01083   if (msmrc != MSMPOT_SUCCESS) {
01084     printf("MSM return code: %d\n", msmrc);
01085     printf("MSM error string: '%s'\n", Msmpot_error_string(msmrc));
01086   } 
01087 #endif
01088 #if 1
01089   // New MSM API: both non-periodic and periodic MSM calcs
01090   int msmrc;
01091 
01092   // XXX hack for ease of initial testing
01093   if (getenv("VMDMSMUSEPBC"))
01094     usepbc = 1;
01095 
01096   if (usepbc) {
01097     // get periodic cell information for current frame
01098     float a, b, c, alpha, beta, gamma;
01099     a = ts->a_length;
01100     b = ts->b_length;
01101     c = ts->c_length;
01102     alpha = ts->alpha;
01103     beta = ts->beta;
01104     gamma = ts->gamma;
01105 
01106     // check validity of PBC cell side lengths
01107     if (fabsf(a*b*c) < 0.0001) {
01108       msgErr << "volmap coulombmsm: unit cell volume is zero." << sendmsg;
01109       return -1;
01110     }
01111 
01112     // check PBC unit cell shape to select proper low level algorithm.
01113     if ((alpha != 90.0) || (beta != 90.0) || (gamma != 90.0)) {
01114       msgErr << "volmap coulombmsm: unit cell is non-orthogonal." << sendmsg;
01115       return -1;
01116     }
01117 
01118 #ifdef MSMPOT_COMPUTE_EXACT
01119   if (getenv("MSMPOT_EXACT")) {
01120     // XXX the current PBC code will currently use the initially specified 
01121     //     map dimensions and coordinates for all frames in a time-averaged
01122     //     calculation.  In the case that one would prefer the map to cover
01123     //     a fixed region of the unit cell in reciprocal space, we will need
01124     //     to change this code to update the effective map geometry on-the-fly.
01125     msgInfo << "Running EXACT periodic MSM calculation..." << sendmsg;
01126     msmrc = Msmpot_compute_exact(msm, voldata, 
01127                            volmap->xsize, volmap->ysize, volmap->zsize,
01128                            volmap->xsize * delta, 
01129                            volmap->ysize * delta, 
01130                            volmap->zsize * delta, 
01131                            0, 0, 0, // origin, already translated to min 
01132                            a, b, c, // pbc cell length 0 == nonperiodic calc
01133                            xyzq, sel->selected);
01134   } else {
01135 #endif
01136     // XXX the current PBC code will currently use the initially specified 
01137     //     map dimensions and coordinates for all frames in a time-averaged
01138     //     calculation.  In the case that one would prefer the map to cover
01139     //     a fixed region of the unit cell in reciprocal space, we will need
01140     //     to change this code to update the effective map geometry on-the-fly.
01141     msgInfo << "Running periodic MSM calculation..." << sendmsg;
01142     msmrc = Msmpot_compute(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, // origin, already translated to min 
01148                            a, b, c, // pbc cell length 0 == nonperiodic calc
01149                            xyzq, sel->selected);
01150 #ifdef MSMPOT_COMPUTE_EXACT
01151   }
01152 #endif
01153 
01154   } else {
01155 
01156 #ifdef MSMPOT_COMPUTE_EXACT
01157   if (getenv("MSMPOT_EXACT")) {
01158     msgInfo << "Running EXACT non-periodic MSM calculation..." << sendmsg;
01159     msmrc = Msmpot_compute_exact(msm, voldata, 
01160                            volmap->xsize, volmap->ysize, volmap->zsize,
01161                            volmap->xsize * delta, 
01162                            volmap->ysize * delta, 
01163                            volmap->zsize * delta, 
01164                            0, 0, 0, // origin, already translated to min 
01165                            0, 0, 0, // pbc cell length 0 == nonperiodic calc
01166                            xyzq, sel->selected);
01167   } else {
01168 #endif
01169     msgInfo << "Running non-periodic MSM calculation..." << sendmsg;
01170     msmrc = Msmpot_compute(msm, voldata, 
01171                            volmap->xsize, volmap->ysize, volmap->zsize,
01172                            volmap->xsize * delta, 
01173                            volmap->ysize * delta, 
01174                            volmap->zsize * delta, 
01175                            0, 0, 0, // origin, already translated to min 
01176                            0, 0, 0, // pbc cell length 0 == nonperiodic calc
01177                            xyzq, sel->selected);
01178 #ifdef MSMPOT_COMPUTE_EXACT
01179   }
01180 #endif
01181 
01182   }
01183 
01184   if (msmrc != MSMPOT_SUCCESS) {
01185     printf("MSM return code: %d\n", msmrc);
01186     printf("MSM error string: '%s'\n", Msmpot_error_string(msmrc));
01187   } 
01188 #else
01189   // old MSM API: non-periodic MSM calcs only
01190   int msmrc = Msmpot_compute(msm, voldata, 
01191                              volmap->xsize, volmap->ysize, volmap->zsize,
01192                              delta, delta, delta, 
01193                              0, 0, 0,
01194                              0, 0, 0, // origin, already translated to min 
01195                              xyzq, sel->selected);
01196   if (msmrc != MSMPOT_ERROR_NONE) {
01197     printf("MSM return code: %d\n", msmrc);
01198     printf("MSM error string: '%s'\n", Msmpot_error_string(msmrc));
01199   } 
01200 #endif
01201   Msmpot_destroy(msm);
01202 
01203   free(xyzq);
01204 
01205   sel->which_frame = save_frame;
01206  
01207   return 0;
01208 }  
01209 
01210 #endif
01211 
01212 
01213 
01214 
01215 
01216 // Write the map as a DX file.
01217 // This is the default base class function which can be
01218 // overridden by the derived classes. 
01219 // E.g. VolMapCreateFastEnergy defines its own write_map().
01220 void VolMapCreate::write_map(const char *filename) {
01221   volmap_write_dx_file(volmap, filename);
01222 }
01223 
01224 
01225 int volmap_write_dx_file (VolumetricData *volmap, const char *filename) {
01226   if (!volmap->data) return -1; // XXX is this a good random error code?
01227   int i;
01228   int xsize = volmap->xsize;
01229   int ysize = volmap->ysize;
01230   int zsize = volmap->zsize;
01231   int gridsize = xsize*ysize*zsize;
01232 
01233   float cellx[3], celly[3], cellz[3];
01234   volmap->cell_axes(cellx, celly, cellz);
01235 
01236   
01237   msgInfo << "volmap: writing file \"" << filename << "\"." << sendmsg;
01238   
01239   FILE *fout = fopen(filename, "w");
01240   if (!fout) {
01241     msgErr << "volmap: Cannot open file \"" << filename
01242            << "\" for writing." << sendmsg;
01243     return errno;
01244   };
01245     
01246   fprintf(fout, "# Data calculated by the VMD volmap function\n");
01247 
01248   // Since the data origin and the grid origin are aligned we have
01249   // grid centered data, even though we were thinking in terms of
01250   // voxels centered in datapoints. VMD treats all dx file maps as
01251   // grid centered data, so this is right.
01252   fprintf(fout, "object 1 class gridpositions counts %d %d %d\n", xsize, ysize, zsize);
01253   fprintf(fout, "origin %g %g %g\n", volmap->origin[0], volmap->origin[1], volmap->origin[2]);
01254   fprintf(fout, "delta %g %g %g\n", cellx[0], cellx[1], cellx[2]);
01255   fprintf(fout, "delta %g %g %g\n", celly[0], celly[1], celly[2]);
01256   fprintf(fout, "delta %g %g %g\n", cellz[0], cellz[1], cellz[2]);
01257   fprintf(fout, "object 2 class gridconnections counts %d %d %d\n", xsize, ysize, zsize);
01258   fprintf(fout, "object 3 class array type double rank 0 items %d data follows\n", gridsize);
01259   
01260   // This reverses the ordering from x fastest to z fastest changing variable
01261   float val1,val2,val3;
01262   int gx=0, gy=0, gz=-1;
01263   for (i=0; i < (gridsize/3)*3; i+=3)  {
01264     if (++gz >= zsize) {
01265       gz=0;
01266       if (++gy >= ysize) {gy=0; gx++;}
01267     }
01268     val1 = volmap->voxel_value(gx,gy,gz);
01269     if (++gz >= zsize) {
01270       gz=0;
01271       if (++gy >= ysize) {gy=0; gx++;}
01272     }
01273     val2 = volmap->voxel_value(gx,gy,gz);
01274     if (++gz >= zsize) {
01275       gz=0;
01276       if (++gy >= ysize) {gy=0; gx++;}
01277     }
01278     val3 = volmap->voxel_value(gx,gy,gz);    
01279     fprintf(fout, "%g %g %g\n", val1, val2, val3);
01280   }
01281   for (i=(gridsize/3)*3; i < gridsize; i++) {
01282     if (++gz >= zsize) {
01283       gz=0;
01284       if (++gy >= ysize) {gy=0; gx++;}
01285     }
01286     fprintf(fout, "%g ", volmap->voxel_value(gx,gy,gz));
01287   }
01288   if (gridsize%3) fprintf(fout, "\n");
01289   fprintf(fout, "\n");
01290   
01291   // Replace any double quotes (") by single quotes (') in the 
01292   // dataname string to make sure that we don't prematurely
01293   // terminate the string in the dx file.
01294   char *squotes = new char[strlen(volmap->name)+1];
01295   strcpy(squotes, volmap->name);
01296   char *s = squotes;
01297   while((s=strchr(s, '"'))) *s = '\'';
01298 
01299   if (volmap->name) {
01300     fprintf(fout, "object \"%s\" class field\n", squotes);
01301   } else {
01302     char dataname[10];
01303     strcpy(dataname, "(no name)");
01304     fprintf(fout, "object \"%s\" class field\n", dataname);
01305   }
01306 
01307   delete [] squotes;
01308 
01309   fclose(fout);
01310   return 0;
01311 }

Generated on Sat May 26 01:48:36 2012 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002