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

VolMapCreate.C

Go to the documentation of this file.
00001 /***************************************************************************
00002 *cr
00003 *cr (C) Copyright 1995-2019 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.127 $ $Date: 2024年03月01日 02:39:38 $
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 #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 // Conversion factor between raw units (e^2 / A) and kT/e
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, ""); // null-terminated empty string
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()); // XXX need a frame selection object
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 // Combo routines are used to combine the different frame maps together into a
00175 // final entity
00176 
00177 // Initialize the frame combination buffer
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 // these combine types need additional storage
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 // Add a frame to the combination buffer
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) { // FIRST FRAME
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 // THE FOLLOWING ONLY APPLIES TO OTHER FRAMES THAN FIRST
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; // weed out outlying data
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 // Special case: if only have one frame do it here the fast way
00297 if (!allframes) {
00298 if (volmap->data) delete[] volmap->data;
00299 volmap->data = new float[gridsize]; // final exported voldata
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 // only compute the current frame of the given selection
00308 this->compute_frame(sel->which_frame, volmap->data); 
00309 
00310 //err = this->compute_end();
00311 //if (err) return err;
00312 return 0; // no error
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]; // final exported voldata
00327 float *frame_voldata = new float[gridsize]; // individual frame voldata
00328 float *voldata = new float[gridsize]; // combo cache voldata
00329 
00330 void *customptr = NULL;
00331 combo_begin(method, &customptr, params);
00332 wkf_timerhandle timer = wkf_timer_create();
00333 
00334 // Combine frame_voldata into voldata, one frame at a time, starting with 1st frame
00335 int frame;
00336 for (frame=0; frame<numframes; frame++) { 
00337 // XXX to-do, only take frames from a frame selection
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 // All frames have been combined, perform finishing steps here
00366 combo_export(method, voldata, customptr);
00367 combo_end (method, customptr);
00368 delete[] voldata;
00369 
00370 return 0; // no error
00371 }
00372 
00373 
00374 
00375 // compute_init() sets up the grid coordinate system and dimensions
00376 // If the user did not specify the grid's minmax boundary, it is
00377 // defaulted to the trajectory's minmax coordinates, to which "padding"
00378 // is added in all dimensions. 
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.; // don't want to pad user's defaults
00389 else {
00390 // The minmax coordinates over all frames
00391 err = calculate_minmax(min_coord, max_coord);
00392 if (err) return err;
00393 }
00394 
00395 // Depending on the volmap type we are computing we add some padding
00396 // to the dimensions of the grid. This function is called by the 
00397 // compute_init() methods of the VolMapCreate<type> subclasses. 
00398 // The caller provides a reasonable map type specific padding value.
00399 // The padding can for example be the radius of the largest atom or
00400 // an interaction distance cutoff.
00401 // After padding we align the grid with integer coordinates.
00402 for (i=0; i<3; i++) {
00403 //adjust padding and ensure that different maps are properly aligned
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 // define origin by shifting to middle of each cell,
00428 // compute_frame() needs to take this into account
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; // no error
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 //create volumetric mask grid
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 // paint atomic spheres on map
00493 int gx, gy, gz;
00494 for (i=sel->firstsel; i<=sel->lastsel; i++) { 
00495 if (!sel->on[i]) continue; //atom is not selected
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 //create volumetric density grid
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; // grid coord indices
00586 for (i=sel->firstsel; i<=sel->lastsel; i++) { 
00587 if (!sel->on[i]) continue; //atom is not selected
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 // Uncomment the following line for a much faster implementation
00609 // This is useful is all you care about is the smooth visual appearance
00610 // voldata[n] += exp_factor/(dist2+10.f);
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 // create volumetric density grid
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; // grid coord indices
00669 float fgx, fgy, fgz; // fractional grid coord indices
00670 float dx, dy, dz; // to measure distances
00671 for (i=sel->firstsel; i<=sel->lastsel; i++) { 
00672 if (!sel->on[i]) continue; //atom is not selected
00673 
00674 // Find position of the atom within the map ("fractional indices")
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 // Find nearest voxel with lowest indices
00680 gx = (int) fgx;
00681 gy = (int) fgy;
00682 gz = (int) fgz;
00683 
00684 // Calculate distance between atom and each voxel
00685 dx = fgx - gx;
00686 dy = fgy - gy;
00687 dz = fgz - gz;
00688 
00689 // Perform trilinear interpolation
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 //create volumetric density grid
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) { // draw single points
00780 for (i=sel->firstsel; i<=sel->lastsel; i++) { 
00781 if (!sel->on[i]) continue; //atom is not selected
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 { // paint atomic spheres on map
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; //atom is not selected
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 // 1. Create a fake "molecule" containing all of the grid points
00869 // this is quite memory intensive but _MUCH_ faster doing it point-by point!
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]); //position of grid cell's center
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 // initialize all grid points to be the maximal allowed distance = cutoff
00892 for (n=0; n<gridsize; n++) voldata[n] = max_dist;
00893 
00894 // 2. Create a list of all bonds between the grid and the real molecule
00895 // which are within the user-set cutoff distance 
00896 // (the use of a cutoff is purely to speed this up tremendously)
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 // if a grid point is already known to be inside an atom, skip it and save some time
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 // 3. At each grid point, store the _smallest_ recorded distance
00911 // to a nearby atomic surface
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 // delete pairlist
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 // init object, no extra padding by default 
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; // XXX fix this later
00958 
00959 int gridsize=volmap->xsize*volmap->ysize*volmap->zsize;
00960 
00961 // create volumetric density grid
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 // copy selected atom coordinates and charges to a contiguous memory
00980 // buffer and translate them to the starting corner of the map.
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 // init object, no extra padding by default
01015 // Note: padding would create serious problems for the periodic case 
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; // XXX fix this later
01029 
01030 int gridsize=volmap->xsize*volmap->ysize*volmap->zsize;
01031 
01032 // create volumetric density grid
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 // copy selected atom coordinates and charges to a contiguous memory
01055 // buffer and translate them to the starting corner of the map.
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(); // create a multilevel summation object
01069 #if 0
01070 int msmrc;
01071 int mx = volmap->xsize; /* map lattice dimensions */
01072 int my = volmap->ysize;
01073 int mz = volmap->zsize;
01074 float lx = delta*mx; /* map lattice lengths */
01075 float ly = delta*my;
01076 float lz = delta*mz;
01077 float x0=0, y0=0, z0=0; /* map origin */
01078 float vx=0, vy=0, vz=0; /* periodic domain lengths (0 for nonperiodic) */
01079 
01080 if (getenv("MSMPOT_NOCUDA")) {
01081 /* turn off use of CUDA (with 0 in last parameter) */
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; /* use periodic boundary conditions */
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 // New MSM API: both non-periodic and periodic MSM calcs
01106 int msmrc;
01107 
01108 // XXX hack for ease of initial testing
01109 if (getenv("VMDMSMUSEPBC"))
01110 usepbc = 1;
01111 
01112 if (usepbc) {
01113 // get periodic cell information for current frame
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 // check validity of PBC cell side lengths
01123 if (fabsf(a*b*c) < 0.0001) {
01124 msgErr << "volmap coulombmsm: unit cell volume is zero." << sendmsg;
01125 return -1;
01126 }
01127 
01128 // check PBC unit cell shape to select proper low level algorithm.
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 // 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 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, // origin, already translated to min 
01148 a, b, c, // pbc cell length 0 == nonperiodic calc
01149 xyzq, sel->selected);
01150 } else {
01151 #endif
01152 // XXX the current PBC code will currently use the initially specified 
01153 // map dimensions and coordinates for all frames in a time-averaged
01154 // calculation. In the case that one would prefer the map to cover
01155 // a fixed region of the unit cell in reciprocal space, we will need
01156 // to change this code to update the effective map geometry on-the-fly.
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, // origin, already translated to min 
01164 a, b, c, // pbc cell length 0 == nonperiodic calc
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, // origin, already translated to min 
01181 0, 0, 0, // pbc cell length 0 == nonperiodic calc
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, // origin, already translated to min 
01192 0, 0, 0, // pbc cell length 0 == nonperiodic calc
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 // old MSM API: non-periodic MSM calcs only
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, // origin, already translated to min 
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 // Write the map as a DX file.
01233 // This is the default base class function which can be
01234 // overridden by the derived classes. 
01235 // E.g. VolMapCreateFastEnergy defines its own write_map().
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; // XXX is this a good random error code?
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 // Since the data origin and the grid origin are aligned we have
01265 // grid centered data, even though we were thinking in terms of
01266 // voxels centered in datapoints. VMD treats all dx file maps as
01267 // grid centered data, so this is right.
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 // This reverses the ordering from x fastest to z fastest changing variable
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 // Replace any double quotes (") by single quotes (') in the 
01308 // dataname string to make sure that we don't prematurely
01309 // terminate the string in the dx file.
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 }

Generated on Mon Nov 17 02:47:24 2025 for VMD (current) by doxygen1.2.14 written by Dimitri van Heesch, © 1997-2002

AltStyle によって変換されたページ (->オリジナル) /