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 }