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
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
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, "");
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());
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
00173
00174
00175
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
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
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) {
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
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;
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
00295 if (!allframes) {
00296 if (volmap->data) delete[] volmap->data;
00297 volmap->data = new float[gridsize];
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
00306 this->compute_frame(sel->which_frame, volmap->data);
00307
00308
00309
00310 return 0;
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];
00325 float *frame_voldata = new float[gridsize];
00326 float *voldata = new float[gridsize];
00327
00328 void *customptr = NULL;
00329 combo_begin(method, &customptr, params);
00330 wkf_timerhandle timer = wkf_timer_create();
00331
00332
00333 int frame;
00334 for (frame=0; frame<numframes; frame++) {
00335
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
00364 combo_export(method, voldata, customptr);
00365 combo_end (method, customptr);
00366 delete[] voldata;
00367
00368 return 0;
00369 }
00370
00371
00372
00373
00374
00375
00376
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.;
00387 else {
00388
00389 err = calculate_minmax(min_coord, max_coord);
00390 if (err) return err;
00391 }
00392
00393
00394
00395
00396
00397
00398
00399
00400 for (i=0; i<3; i++) {
00401
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
00426
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;
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
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
00491 int gx, gy, gz;
00492 for (i=sel->firstsel; i<=sel->lastsel; i++) {
00493 if (!sel->on[i]) continue;
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
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;
00577 for (i=sel->firstsel; i<=sel->lastsel; i++) {
00578 if (!sel->on[i]) continue;
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
00600
00601
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
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;
00653 float fgx, fgy, fgz;
00654 float dx, dy, dz;
00655 for (i=sel->firstsel; i<=sel->lastsel; i++) {
00656 if (!sel->on[i]) continue;
00657
00658
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
00664 gx = (int) fgx;
00665 gy = (int) fgy;
00666 gz = (int) fgz;
00667
00668
00669 dx = fgx - gx;
00670 dy = fgy - gy;
00671 dz = fgz - gz;
00672
00673
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
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) {
00764 for (i=sel->firstsel; i<=sel->lastsel; i++) {
00765 if (!sel->on[i]) continue;
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 {
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;
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
00853
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]);
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
00876 for (n=0; n<gridsize; n++) voldata[n] = max_dist;
00877
00878
00879
00880
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
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
00895
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
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
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;
00942
00943 int gridsize=volmap->xsize*volmap->ysize*volmap->zsize;
00944
00945
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
00964
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
00999
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;
01013
01014 int gridsize=volmap->xsize*volmap->ysize*volmap->zsize;
01015
01016
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
01039
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();
01053 #if 0
01054 int msmrc;
01055 int mx = volmap->xsize;
01056 int my = volmap->ysize;
01057 int mz = volmap->zsize;
01058 float lx = delta*mx;
01059 float ly = delta*my;
01060 float lz = delta*mz;
01061 float x0=0, y0=0, z0=0;
01062 float vx=0, vy=0, vz=0;
01063
01064 if (getenv("MSMPOT_NOCUDA")) {
01065
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;
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
01090 int msmrc;
01091
01092
01093 if (getenv("VMDMSMUSEPBC"))
01094 usepbc = 1;
01095
01096 if (usepbc) {
01097
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
01107 if (fabsf(a*b*c) < 0.0001) {
01108 msgErr << "volmap coulombmsm: unit cell volume is zero." << sendmsg;
01109 return -1;
01110 }
01111
01112
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
01121
01122
01123
01124
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,
01132 a, b, c,
01133 xyzq, sel->selected);
01134 } else {
01135 #endif
01136
01137
01138
01139
01140
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,
01148 a, b, c,
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,
01165 0, 0, 0,
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,
01176 0, 0, 0,
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
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,
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
01217
01218
01219
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;
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
01249
01250
01251
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
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
01292
01293
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 }