00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <math.h>
00024 #include <stdlib.h>
00025 #include <tcl.h>
00026 #include "TclCommands.h"
00027 #include "AtomSel.h"
00028 #include "VMDApp.h"
00029 #include "MoleculeList.h"
00030 #include "config.h"
00031 #include "Measure.h"
00032 #include "VolumetricData.h"
00033 #include "VolMapCreate.h"
00034 #include "Inform.h"
00035 #include "MeasureSymmetry.h"
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052 static int parse_minmax_args(Tcl_Interp *interp, int arg_minmax,
00053 Tcl_Obj * const objv[], double *minmax) {
00054 int num, i;
00055 Tcl_Obj **data, **vecmin, **vecmax;
00056
00057
00058 if (Tcl_ListObjGetElements(interp, objv[arg_minmax], &num, &data) != TCL_OK) {
00059 Tcl_SetResult(interp, (char *)"volmap: could not read parameter (-minmax)", TCL_STATIC);
00060 return TCL_ERROR;
00061 }
00062 if (num != 2) {
00063 Tcl_SetResult(interp, (char *)"volmap: minmax requires a list with two vectors (-minmax)", TCL_STATIC);
00064 return TCL_ERROR;
00065 }
00066
00067 if (Tcl_ListObjGetElements(interp, data[0], &num, &vecmin) != TCL_OK) {
00068 return TCL_ERROR;
00069 }
00070 if (num != 3) {
00071 Tcl_SetResult(interp, (char *)"volmap: the first vector does not contain 3 elements (-minmax)", TCL_STATIC);
00072 return TCL_ERROR;
00073 }
00074
00075 if (Tcl_ListObjGetElements(interp, data[1], &num, &vecmax) != TCL_OK) {
00076 return TCL_ERROR;
00077 }
00078 if (num != 3) {
00079 Tcl_SetResult(interp, (char *)"volmap: the second vector does not contain 3 elements (-minmax)", TCL_STATIC);
00080 return TCL_ERROR;
00081 }
00082
00083
00084 for (i=0; i<3; i++)
00085 if (Tcl_GetDoubleFromObj(interp, vecmin[i], minmax+i) != TCL_OK)
00086 return TCL_ERROR;
00087
00088
00089 for (i=0; i<3; i++)
00090 if (Tcl_GetDoubleFromObj(interp, vecmax[i], minmax+i+3) != TCL_OK)
00091 return TCL_ERROR;
00092
00093
00094 if (minmax[0] >= minmax[3] || minmax[1] >= minmax[4] || minmax[2] >= minmax[5]) {
00095 Tcl_SetResult(interp, (char *)"volmap: invalid minmax range (-minmax)", TCL_STATIC);
00096 return TCL_ERROR;
00097 }
00098
00099 return TCL_OK;
00100 }
00101
00102
00103 static int vmd_volmap_ils(VMDApp *app, int argc, Tcl_Obj * const objv[], Tcl_Interp *interp) {
00104 bool bad_usage = false;
00105 bool bailout = false;
00106 double cutoff = 10.;
00107 double resolution = 1.;
00108 double minmax[6];
00109 bool pbc = false;
00110 bool pbcbox = false;
00111 float *pbccenter = NULL;
00112
00113 int maskonly = 0;
00114 bool export_to_file = false;
00115 int molid = -1;
00116 char *filebase = NULL;
00117 char *filename = NULL;
00118
00119 int nprobecoor = 0;
00120 int nprobevdw = 0;
00121 int nprobecharge = 0;
00122 float *probe_vdwrmin = NULL;
00123 float *probe_vdweps = NULL;
00124 float *probe_coords = NULL;
00125 float *probe_charge = NULL;
00126 double temperature = 300.0;
00127 double maxenergy = 150.0;
00128 int subres = 3;
00129 int num_conf = 0;
00130 AtomSel *probesel = NULL;
00131 AtomSel *alignsel = NULL;
00132 Matrix4 *transform = NULL;
00133
00134 if (argc<3) {
00135 Tcl_WrongNumArgs(interp, 2, objv-1, (char *)"<molid> <minmax> [options...]");
00136 return TCL_ERROR;
00137 }
00138
00139
00140 if (!strcmp(Tcl_GetStringFromObj(objv[1], NULL), "top"))
00141 molid = app->molecule_top();
00142 else
00143 Tcl_GetIntFromObj(interp, objv[1], &molid);
00144
00145 if (!app->molecule_valid_id(molid)) {
00146 Tcl_AppendResult(interp, "volmap: molecule specified for ouput is invalid. (-mol)", NULL);
00147 return TCL_ERROR;
00148 }
00149
00150
00151 if (!strcmp(Tcl_GetStringFromObj(objv[2], NULL), "pbcbox")) {
00152 pbcbox = true;
00153 }
00154 else if (parse_minmax_args(interp, 2, objv, minmax)!=TCL_OK) {
00155 Tcl_AppendResult(interp, "volmap: no atoms selected.", NULL);
00156 }
00157
00158 int first = 0;
00159 int nframes = app->molecule_numframes(molid);
00160 int last = nframes-1;
00161
00162
00163 int arg;
00164 for (arg=3; arg<argc && !bad_usage && !bailout; arg++) {
00165
00166 if (!strcmp(Tcl_GetStringFromObj(objv[arg], NULL), "-res")) {
00167 if (arg+1>=argc) { bad_usage=true; break; }
00168 Tcl_GetDoubleFromObj(interp, objv[arg+1], &resolution);
00169 if (resolution <= 0.f) {
00170 Tcl_AppendResult(interp, "volmap ils: resolution must be positive. (-res)", NULL);
00171 bailout = true; break;
00172 }
00173 arg++;
00174 }
00175 else if (!strcmp(Tcl_GetStringFromObj(objv[arg], NULL), "-probesel")) {
00176 if (arg+1>=argc) { bad_usage=true; break; }
00177
00178 probesel = tcl_commands_get_sel(interp, Tcl_GetStringFromObj(objv[arg+1],NULL));
00179 if (!probesel) {
00180 Tcl_AppendResult(interp, "volmap ils -probesel: no atom selection.", NULL);
00181 bailout = true; break;
00182 }
00183 if (!probesel->selected) {
00184 Tcl_AppendResult(interp, "volmap ils -probesel: no atoms selected.", NULL);
00185 bailout = true; break;
00186 }
00187 if (!app->molecule_valid_id(probesel->molid())) {
00188 Tcl_AppendResult(interp, "volmap ils -probesel: ",
00189 measure_error(MEASURE_ERR_NOMOLECULE), NULL);
00190 bailout = true; break;
00191 }
00192 arg++;
00193 }
00194
00195 else if (!strcmp(Tcl_GetStringFromObj(objv[arg], NULL), "-first")) {
00196 if (arg+1>=argc) { bad_usage=true; break; }
00197 Tcl_GetIntFromObj(interp, objv[arg+1], &first);
00198 if (first < 0) {
00199 Tcl_AppendResult(interp, "volmap ils: Frame specified with -first must be positive.", NULL);
00200 bailout = true; break;
00201 }
00202 if (first >= nframes) {
00203 Tcl_AppendResult(interp, "volmap ils: Frame specified with -first exceeds number of existing frames.", NULL);
00204 bailout = true; break;
00205 }
00206 arg++;
00207 }
00208 else if (!strcmp(Tcl_GetStringFromObj(objv[arg], NULL), "-last")) {
00209 if (arg+1>=argc) { bad_usage=true; break; }
00210 Tcl_GetIntFromObj(interp, objv[arg+1], &last);
00211 if (last < 0) {
00212 Tcl_AppendResult(interp, "volmap ils: Frame specified with -last must be positive.", NULL);
00213 bailout = true; break;
00214 }
00215 if (last >= nframes) {
00216 Tcl_AppendResult(interp, "volmap ils: Frame specified with -last exceeds number of existing frames.", NULL);
00217 bailout = true; break;
00218 }
00219 arg++;
00220 }
00221 else if (!strcmp(Tcl_GetStringFromObj(objv[arg], NULL), "-cutoff")) {
00222 if (arg+1 >= argc) { bad_usage=true; break; }
00223 Tcl_GetDoubleFromObj(interp, objv[arg+1], &cutoff);
00224 if (cutoff <= 0.) {
00225 Tcl_AppendResult(interp, "volmap ils: cutoff must be positive. (-cutoff)", NULL);
00226 bailout = true; break;
00227 }
00228 arg++;
00229 }
00230 else if (!strcmp(Tcl_GetStringFromObj(objv[arg], NULL), "-dx") ||
00231 !strcmp(Tcl_GetStringFromObj(objv[arg], NULL), "-o")) {
00232 if (arg+1>=argc) { bad_usage=true; break; }
00233 const char* outputfilename = Tcl_GetString(objv[arg+1]);
00234 if (outputfilename) {
00235 filebase = new char[strlen(outputfilename)+1];
00236 strcpy(filebase, outputfilename);
00237 export_to_file = true;
00238 }
00239 arg++;
00240 }
00241
00242 else if (!strcmp(Tcl_GetStringFromObj(objv[arg], NULL), "-probecoor")) {
00243 if (arg+1>=argc) { bad_usage=true; break; }
00244 int i;
00245 double tmp;
00246 Tcl_Obj **listObj;
00247 if (Tcl_ListObjGetElements(interp, objv[arg+1], &nprobecoor, &listObj) != TCL_OK) {
00248 Tcl_AppendResult(interp, " volmap ils: bad syntax in probecoor!", NULL);
00249 bailout = true; break;
00250 }
00251 if (!nprobecoor) {
00252 Tcl_AppendResult(interp, " volmap ils: Empty probecoor list!", NULL);
00253 bailout = true; break;
00254 }
00255
00256 probe_coords = new float[3*nprobecoor];
00257
00258 for (i=0; i<nprobecoor; i++) {
00259 Tcl_Obj **coorObj;
00260 int j, ndim = 0;
00261 if (Tcl_ListObjGetElements(interp, listObj[i], &ndim, &coorObj) != TCL_OK) {
00262 Tcl_AppendResult(interp, " volmap ils: bad syntax in probecoor!", NULL);
00263 bailout = true; break;
00264 }
00265
00266 if (ndim!=3) {
00267 Tcl_AppendResult(interp, " volmap ils: need three values for each probecoor vector", NULL);
00268 bailout = true; break;
00269 }
00270
00271 for (j=0; j<3; j++) {
00272 if (Tcl_GetDoubleFromObj(interp, coorObj[j], &tmp) != TCL_OK) {
00273 Tcl_AppendResult(interp, " volmap ils: non-numeric in probecoor", NULL);
00274 bailout = true; break;
00275 }
00276 probe_coords[3*i+j] = (float)tmp;
00277 }
00278 }
00279 arg++;
00280 }
00281 else if (!strcmp(Tcl_GetStringFromObj(objv[arg], NULL), "-probevdw")) {
00282 if (arg+1>=argc) { bad_usage=true; break; }
00283 double tmp;
00284 Tcl_Obj **listObj;
00285 if (Tcl_ListObjGetElements(interp, objv[arg+1], &nprobevdw, &listObj) != TCL_OK) {
00286 Tcl_AppendResult(interp, " volmap ils: bad syntax in probevdw", NULL);
00287 bailout = true; break;
00288 }
00289
00290 probe_vdweps = new float[nprobevdw];
00291 probe_vdwrmin = new float[nprobevdw];
00292
00293 int i;
00294 for (i=0; i<nprobevdw; i++) {
00295 Tcl_Obj **vdwObj;
00296 int ndim = 0;
00297 if (Tcl_ListObjGetElements(interp, listObj[i], &ndim, &vdwObj) != TCL_OK) {
00298 Tcl_AppendResult(interp, " volmap ils: bad syntax in probevdw", NULL);
00299 bailout = true; break;
00300 }
00301
00302 if (ndim!=2) {
00303 Tcl_AppendResult(interp, " volmap ils: Need two probevdw values (eps, rmin) for each atom", NULL);
00304 bailout = true; break;
00305 }
00306
00307 if (Tcl_GetDoubleFromObj(interp, vdwObj[0], &tmp) != TCL_OK) {
00308 Tcl_AppendResult(interp, " volmap ils: Non-numeric in probevdw (eps)", NULL);
00309 bailout = true; break;
00310 }
00311 probe_vdweps[i] = (float)tmp;
00312
00313 if (Tcl_GetDoubleFromObj(interp, vdwObj[1], &tmp) != TCL_OK) {
00314 Tcl_AppendResult(interp, " volmap ils: Non-numeric in probevdw (rmin)", NULL);
00315 bailout = true; break;
00316 }
00317 probe_vdwrmin[i] = (float)tmp;
00318 }
00319 arg++;
00320 }
00321
00322 else if (!strcmp(Tcl_GetStringFromObj(objv[arg], NULL), "-probecharge")) {
00323 if (arg+1>=argc) { bad_usage=true; break; }
00324 int i;
00325 double tmp;
00326 Tcl_Obj **listObj;
00327 if (Tcl_ListObjGetElements(interp, objv[arg+1], &nprobecharge, &listObj) != TCL_OK) {
00328 Tcl_AppendResult(interp, " volmap ils: bad syntax in probecharge", NULL);
00329 bailout = true; break;
00330 }
00331
00332 probe_charge = new float[nprobecharge];
00333
00334 for (i=0; i<nprobecharge; i++) {
00335 if (Tcl_GetDoubleFromObj(interp, listObj[0], &tmp) != TCL_OK) {
00336 Tcl_AppendResult(interp, " volmap ils: non-numeric in probecharge", NULL);
00337 bailout = true; break;
00338 }
00339 probe_charge[i] = (float)tmp;
00340 }
00341 arg++;
00342 }
00343
00344 else if (!strcmp(Tcl_GetStringFromObj(objv[arg], NULL), "-orient") ||
00345 !strcmp(Tcl_GetStringFromObj(objv[arg], NULL), "-conf")) {
00346 if (arg+1>=argc) { bad_usage=true; break; }
00347 Tcl_GetIntFromObj(interp, objv[arg+1], &num_conf);
00348 if (num_conf < 0) {
00349 Tcl_AppendResult(interp, "volmap ils: invalid -orient parameter", NULL);
00350 bailout = true; break;
00351 }
00352 arg++;
00353 }
00354 else if (!strcmp(Tcl_GetStringFromObj(objv[arg], NULL), "-subres")) {
00355 if (arg+1>=argc) { bad_usage=true; break; }
00356 Tcl_GetIntFromObj(interp, objv[arg+1], &subres);
00357 if (subres < 1) {
00358 Tcl_AppendResult(interp, "volmap ils: invalid -subres parameter", NULL);
00359 bailout = true; break;
00360 }
00361 arg++;
00362 }
00363 else if (!strcmp(Tcl_GetStringFromObj(objv[arg], NULL), "-T")) {
00364 if (arg+1>=argc) { bad_usage=true; break; }
00365 Tcl_GetDoubleFromObj(interp, objv[arg+1], &temperature);
00366 arg++;
00367 }
00368 else if (!strcmp(Tcl_GetStringFromObj(objv[arg], NULL), "-maxenergy")) {
00369 if (arg+1>=argc) { bad_usage=true; break; }
00370 if (Tcl_GetDoubleFromObj(interp, objv[arg+1], &maxenergy) != TCL_OK) {
00371 Tcl_AppendResult(interp, "volmap ils: invalid -maxenergy parameter", NULL);
00372 bailout = true; break;
00373 }
00374 arg++;
00375 }
00376 else if (!strcmp(Tcl_GetStringFromObj(objv[arg], NULL), "-alignsel")) {
00377 if (arg+1>=argc) { bad_usage=true; break; }
00378 alignsel = tcl_commands_get_sel(interp, Tcl_GetStringFromObj(objv[arg+1],NULL));
00379 if (!alignsel) {
00380 Tcl_AppendResult(interp, "volmap ils: no atom selection for alignment.", NULL);
00381 bailout = true; break;
00382 }
00383 if (!alignsel->selected) {
00384 Tcl_AppendResult(interp, "volmap ils: no atoms selected for alignment.", NULL);
00385 bailout = true; break;
00386 }
00387 arg++;
00388 }
00389 else if (!strcmp(Tcl_GetStringFromObj(objv[arg], NULL), "-transform")) {
00390 if (arg+1>=argc) { bad_usage=true; break; }
00391 transform = new Matrix4;
00392 tcl_get_matrix("volmap ils: ", interp, objv[arg+1], transform->mat);
00393 arg++;
00394 }
00395
00396 else if (!strcmp(Tcl_GetStringFromObj(objv[arg], NULL), "-pbc")) {
00397 pbc = true;
00398 }
00399
00400 else if (!strcmp(Tcl_GetStringFromObj(objv[arg], NULL), "-pbccenter")) {
00401 if (arg+1>=argc) { bad_usage=true; break; }
00402 int i, ndim = 0;
00403 double tmp;
00404 Tcl_Obj **centerObj;
00405 if (Tcl_ListObjGetElements(interp, objv[arg+1], &ndim, ¢erObj) != TCL_OK) {
00406 Tcl_AppendResult(interp, " volmap ils: bad syntax in pbccenter", NULL);
00407 bailout = true; break;
00408 }
00409
00410 if (ndim!=3) {
00411 Tcl_AppendResult(interp, " volmap ils: need three values for vector pbccenter", NULL);
00412 bailout = true; break;
00413 }
00414
00415 pbccenter = new float[3];
00416 for (i=0; i<3; i++) {
00417 if (Tcl_GetDoubleFromObj(interp, centerObj[i], &tmp) != TCL_OK) {
00418 Tcl_AppendResult(interp, " volmap ils: non-numeric in pbccenter", NULL);
00419 bailout = true; break;
00420 }
00421 pbccenter[i] = (float)tmp;
00422 }
00423 arg++;
00424 pbc = true;
00425 }
00426
00427 else if (!strcmp(Tcl_GetStringFromObj(objv[arg], NULL), "-maskonly")) {
00428 maskonly = 1;
00429 }
00430
00431 else {
00432
00433 Tcl_AppendResult(interp, " volmap ils: unknown argument ",
00434 Tcl_GetStringFromObj(objv[arg], NULL), NULL);
00435 bailout = true;
00436 }
00437
00438 }
00439
00440 if (bad_usage) {
00441 Tcl_WrongNumArgs(interp, 2, objv-1, (char *)"<molid> <minmax> [options...]");
00442 bailout = true;
00443 }
00444
00445 int num_probe_atoms = 0;
00446 if (!bailout) {
00447 if (probesel) {
00448 if (nprobecoor) {
00449 Tcl_AppendResult(interp, "volmap ils: Must specify either -probesel or -probecoor not both.",
00450 NULL);
00451 bailout = true;
00452 }
00453
00454
00455 Molecule *probemol = app->moleculeList->mol_from_id(probesel->molid());
00456 const float *radius = probemol->extraflt.data("radius");
00457 if (!radius) {
00458 Tcl_AppendResult(interp, "volmap ils: probe selection contains no VDW radii", NULL);
00459 bailout = true;
00460 }
00461
00462 const float *occupancy = probemol->extraflt.data("occupancy");
00463 if (!occupancy) {
00464 Tcl_AppendResult(interp, "volmap ils: probe selection contains no VDW epsilon values (in occupancy field)", NULL);
00465 bailout = true;
00466 }
00467
00468 if (!bailout) {
00469 const float *charge = probemol->extraflt.data("charge");
00470
00471 num_probe_atoms = probesel->selected;
00472 if (!nprobevdw) {
00473 probe_vdwrmin = new float[num_probe_atoms];
00474 probe_vdweps = new float[num_probe_atoms];
00475 }
00476 probe_charge = new float[num_probe_atoms];
00477 probe_coords = new float[3*num_probe_atoms];
00478 const float *coords = probesel->coordinates(app->moleculeList);
00479 int i, j=0;
00480 for (i=0; i<probesel->num_atoms; i++) {
00481 if (probesel->on[i]) {
00482 vec_copy(&probe_coords[3*j], &coords[3*i]);
00483
00484 if (!nprobevdw) {
00485 probe_vdweps[j] = -fabsf(occupancy[i]);
00486 probe_vdwrmin[j] = radius[i];
00487 }
00488 if (!nprobecharge) {
00489 if (charge) probe_charge[j] = charge[i];
00490 else probe_charge[j] = 0.f;
00491 }
00492 j++;
00493 }
00494 }
00495 }
00496
00497 } else {
00498
00499 if (nprobecoor==0 && nprobevdw==1) {
00500
00501 num_probe_atoms = 1;
00502 probe_coords = new float[3];
00503 probe_coords[0] = probe_coords[1] = probe_coords[2] = 0.f;
00504 } else {
00505 num_probe_atoms = nprobecoor;
00506 }
00507
00508 if (!nprobevdw) {
00509 Tcl_AppendResult(interp, "volmap ils: No probe VDW parameters specified.", NULL);
00510 bailout = true;
00511 }
00512
00513 if (nprobecharge && nprobecharge!=num_probe_atoms && !bailout) {
00514 Tcl_AppendResult(interp, "volmap ils: # probe charges doesn't match # probe atoms", NULL);
00515 bailout = true;
00516 }
00517 }
00518
00519 if (num_probe_atoms==0 && !bailout) {
00520 Tcl_AppendResult(interp, "volmap: No probe coordinates specified.", NULL);
00521 bailout = true;
00522 }
00523
00524 if (nprobevdw && nprobevdw!=num_probe_atoms && !bailout) {
00525 Tcl_AppendResult(interp, "volmap ils: # probe VDW params doesn't match # probe atoms", NULL);
00526 bailout = true;
00527 }
00528
00529 if (pbc && !alignsel) {
00530 Tcl_AppendResult(interp, "volmap ils: You cannot use -pbc without also "
00531 " providing -alignsel.", NULL);
00532 bailout = true;
00533 }
00534
00535
00536
00537
00538
00539 }
00540
00541 if (bailout) {
00542 if (transform) delete transform;
00543 if (pbccenter) delete [] pbccenter;
00544 if (filebase) delete [] filebase;
00545 if (probe_vdwrmin) delete [] probe_vdwrmin;
00546 if (probe_vdweps) delete [] probe_vdweps;
00547 if (probe_charge) delete [] probe_charge;
00548 if (probe_coords) delete [] probe_coords;
00549 return TCL_ERROR;
00550 }
00551
00552
00553
00554
00555
00556
00557
00558
00559 int tetrahedral_symm = 0;
00560 int order1=0, order2=0;
00561 float symmaxis1[3];
00562 float symmaxis2[3];
00563 if (probesel) {
00564 msgInfo << "Determining probe symmetry:" << sendmsg;
00565
00566
00567 Symmetry sym = Symmetry(probesel, app->moleculeList, 1);
00568
00569
00570 sym.set_overlaptol(0.05f);
00571
00572
00573 sym.set_checkbonds(1);
00574
00575
00576 int ret_val = sym.guess(0.05f);
00577 if (ret_val < 0) {
00578 Tcl_AppendResult(interp, "measure symmetry: ", measure_error(ret_val), NULL);
00579 return TCL_ERROR;
00580 }
00581 int pgorder;
00582 char pointgroup[6];
00583 sym.get_pointgroup(pointgroup, &pgorder);
00584
00585 if (pointgroup[0]=='T') tetrahedral_symm = 1;
00586
00587 if (sym.numaxes()) {
00588
00589 vec_copy(symmaxis1, sym.axis(0));
00590 order1 = sym.get_axisorder(0);
00591
00592 int i;
00593 for (i=1; i<sym.numaxes(); i++) {
00594 vec_copy(symmaxis2, sym.axis(i));
00595 if (fabs(dot_prod(symmaxis1, symmaxis2)) < DEGTORAD(1.f)) {
00596
00597 order2 = sym.get_axisorder(i);
00598 break;
00599 }
00600 }
00601 }
00602 }
00603
00604
00605 VolMapCreateILS vol(app, molid, first, last, (float)temperature,
00606 (float)resolution, subres, (float)cutoff,
00607 maskonly);
00608
00609 vol.set_probe(num_probe_atoms, num_conf, probe_coords,
00610 probe_vdwrmin, probe_vdweps, probe_charge);
00611 vol.set_maxenergy(float(maxenergy));
00612
00613 if (pbc) vol.set_pbc(pbccenter, pbcbox);
00614 if (transform) vol.set_transform(transform);
00615 if (alignsel) vol.set_alignsel(alignsel);
00616 if (!pbcbox) {
00617 vol.set_minmax(float(minmax[0]), float(minmax[1]), float(minmax[2]),
00618 float(minmax[3]), float(minmax[4]), float(minmax[5]));
00619 }
00620
00621 if (tetrahedral_symm || order1 || order2) {
00622
00623 vol.set_probe_symmetry(order1, symmaxis1, order2, symmaxis2, tetrahedral_symm);
00624 }
00625
00626
00627 int ret_val = vol.compute();
00628
00629 if (ret_val < 0) {
00630 Tcl_AppendResult(interp, "\nvolmap: ERROR ", measure_error(ret_val), NULL);
00631
00632 if (transform) delete transform;
00633 if (pbccenter) delete [] pbccenter;
00634 if (filebase) delete [] filebase;
00635 if (probe_vdwrmin) delete [] probe_vdwrmin;
00636 if (probe_vdweps) delete [] probe_vdweps;
00637 if (probe_charge) delete [] probe_charge;
00638 if (probe_coords) delete [] probe_coords;
00639 return TCL_ERROR;
00640 }
00641
00642 int numconf, numorient, numrot;
00643 vol.get_statistics(numconf, numorient, numrot);
00644
00645
00646
00647
00648 if (probesel && probesel->molid()!=molid) {
00649 float *conformers = NULL;
00650 int numconf = vol.get_conformers(conformers);
00651 Molecule *pmol = app->moleculeList->mol_from_id(probesel->molid());
00652 int i, j;
00653 for (i=0; i<numconf; i++) {
00654 if (i>0) {
00655 pmol->duplicate_frame(pmol->current());
00656 }
00657 float *coor = pmol->get_frame(i)->pos;
00658 int k=0;
00659 for (j=0; j<probesel->num_atoms; j++) {
00660 if (!probesel->on[j]) continue;
00661
00662 vec_copy(&coor[3*j], &conformers[i*3*num_probe_atoms+3*k]);
00663 k++;
00664 }
00665 }
00666 }
00667
00668
00669 if (export_to_file) {
00670
00671 filename = new char[strlen(filebase)+16];
00672 strcpy(filename, filebase);
00673 char *suffix = strrchr(filename, '.');
00674 if (strcmp(suffix, ".dx")) strcat(filename, ".dx");
00675
00676
00677 if (!vol.write_map(filename)) {
00678 Tcl_AppendResult(interp, "\nvolmap: ERROR Could not write ils map to file", NULL);
00679 }
00680
00681 delete[] filename;
00682
00683 } else {
00684 if (!vol.add_map_to_molecule()) {
00685 Tcl_AppendResult(interp, "\nvolmap: ERROR Could not add ils map to molecule", NULL);
00686 }
00687 }
00688
00689 Tcl_Obj *tcl_result = Tcl_NewListObj(0, NULL);
00690 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewStringObj("numconf", -1));
00691 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewDoubleObj(numconf));
00692 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewStringObj("numorient", -1));
00693 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewDoubleObj(numorient));
00694 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewStringObj("numrot", -1));
00695 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewDoubleObj(numrot));
00696 Tcl_SetObjResult(interp, tcl_result);
00697
00698 if (transform) delete transform;
00699 if (pbccenter) delete [] pbccenter;
00700 if (filebase) delete [] filebase;
00701 if (probe_vdwrmin) delete [] probe_vdwrmin;
00702 if (probe_vdweps) delete [] probe_vdweps;
00703 if (probe_charge) delete [] probe_charge;
00704 if (probe_coords) delete [] probe_coords;
00705
00706 return TCL_OK;
00707 }
00708
00709
00710 static int vmd_volmap_new_fromtype(VMDApp *app, int argc, Tcl_Obj * const objv[], Tcl_Interp *interp) {
00711
00712
00713 enum {UNDEF_MAP, DENS_MAP, INTERP_MAP, DIST_MAP, OCCUP_MAP, MASK_MAP,
00714 CPOTENTIAL_MAP, CPOTENTIALMSM_MAP } maptype=UNDEF_MAP;
00715
00716 char *maptype_string=Tcl_GetString(objv[0]);
00717
00718 if (!strcmp(maptype_string, "density")) maptype=DENS_MAP;
00719 else if (!strcmp(maptype_string, "interp")) maptype=INTERP_MAP;
00720 else if (!strcmp(maptype_string, "distance")) maptype=DIST_MAP;
00721 else if (!strcmp(maptype_string, "occupancy")) maptype=OCCUP_MAP;
00722 else if (!strcmp(maptype_string, "mask")) maptype=MASK_MAP;
00723 else if (!strcmp(maptype_string, "coulomb")) maptype=CPOTENTIAL_MAP;
00724 else if (!strcmp(maptype_string, "coulombpotential")) maptype=CPOTENTIAL_MAP;
00725 else if (!strcmp(maptype_string, "coulombmsm")) maptype=CPOTENTIALMSM_MAP;
00726
00727
00728 if (argc < 2) {
00729 Tcl_AppendResult(interp, "volmap: no atom selection.", NULL);
00730 return TCL_ERROR;
00731 }
00732
00733 AtomSel *sel = NULL;
00734 sel = tcl_commands_get_sel(interp, Tcl_GetStringFromObj(objv[1],NULL));
00735 if (!sel) {
00736 Tcl_AppendResult(interp, "volmap: no atom selection.", NULL);
00737 return TCL_ERROR;
00738 }
00739 if (!sel->selected) {
00740 Tcl_AppendResult(interp, "volmap: no atoms selected.", NULL);
00741 return TCL_ERROR;
00742 }
00743 if (!app->molecule_valid_id(sel->molid())) {
00744 Tcl_AppendResult(interp, "volmap: ",
00745 measure_error(MEASURE_ERR_NOMOLECULE), NULL);
00746 return TCL_ERROR;
00747 }
00748
00749
00750
00751 bool accept_weight = false;
00752 bool accept_cutoff = false;
00753 bool accept_radius = false;
00754 bool accept_usepoints = false;
00755
00756 bool use_point_particles = false;
00757 bool export_to_file = false;
00758 bool use_all_frames = false;
00759 bool bad_usage = false;
00760
00761 int export_molecule = -1;
00762 double cutoff = 5.;
00763 double radius_factor = 1.;
00764 double resolution = 1.;
00765 double minmax[6];
00766
00767 char *filebase = NULL;
00768 char *filename = NULL;
00769
00770
00771
00772 int checkpoint_freq = 500;
00773
00774
00775
00776 switch(maptype) {
00777 case DENS_MAP:
00778 accept_weight = true;
00779 accept_radius = true;
00780 break;
00781 case INTERP_MAP:
00782 accept_weight = true;
00783 break;
00784 case DIST_MAP:
00785 accept_cutoff = true;
00786 cutoff = 3.;
00787 break;
00788 case OCCUP_MAP:
00789 accept_usepoints = true;
00790 break;
00791 case MASK_MAP:
00792 accept_cutoff = true;
00793 cutoff = 4.;
00794 break;
00795 case CPOTENTIAL_MAP:
00796 case CPOTENTIALMSM_MAP:
00797 break;
00798 case UNDEF_MAP:
00799 bad_usage = true;
00800 break;
00801 }
00802
00803
00804
00805 int arg_weight=0, arg_combine=0, arg_minmax=0;
00806
00807
00808 for (int arg=2; arg<argc && !bad_usage; arg++) {
00809 if (!strcmp(Tcl_GetStringFromObj(objv[arg], NULL), "-res")) {
00810 if (arg+1>=argc) bad_usage=true;
00811 Tcl_GetDoubleFromObj(interp, objv[arg+1], &resolution);
00812 if (resolution <= 0.f) {
00813 Tcl_AppendResult(interp, "volmap: resolution must be positive. (-res)", NULL);
00814 return TCL_ERROR;
00815 }
00816 arg++;
00817 }
00818 else if (!strcmp(Tcl_GetStringFromObj(objv[arg], NULL), "-mol")) {
00819 if (arg+1 >= argc) bad_usage=true;
00820 if (!strcmp(Tcl_GetStringFromObj(objv[arg+1], NULL), "top"))
00821 export_molecule = app->molecule_top();
00822 else
00823 Tcl_GetIntFromObj(interp, objv[arg+1], &export_molecule);
00824
00825 if (!app->molecule_valid_id(export_molecule)) {
00826 Tcl_AppendResult(interp, "volmap: molecule specified for ouput is invalid. (-mol)", NULL);
00827 return TCL_ERROR;
00828 }
00829 arg++;
00830 }
00831 else if (!strcmp(Tcl_GetStringFromObj(objv[arg], NULL), "-minmax")) {
00832 arg_minmax=arg+1;
00833 arg++;
00834 if (arg_minmax>=argc) bad_usage=true;
00835 if (parse_minmax_args(interp, arg_minmax, objv, minmax)!=TCL_OK) {
00836 return TCL_ERROR;
00837 }
00838 }
00839 else if (!strcmp(Tcl_GetStringFromObj(objv[arg], NULL), "-checkpoint")) {
00840 if (arg+1 >= argc) bad_usage=true;
00841 Tcl_GetIntFromObj(interp, objv[arg+1], &checkpoint_freq);
00842 if (checkpoint_freq < 0) {
00843 Tcl_AppendResult(interp, "volmap: invalid -checkpoint parameter", NULL);
00844 return TCL_ERROR;
00845 }
00846 arg++;
00847 }
00848 else if (!strcmp(Tcl_GetStringFromObj(objv[arg], NULL), "-allframes")) {
00849 use_all_frames=true;
00850 }
00851 else if (!strcmp(Tcl_GetStringFromObj(objv[arg], NULL), "-dx") ||
00852 !strcmp(Tcl_GetStringFromObj(objv[arg], NULL), "-o")) {
00853 if (arg+1>=argc) {bad_usage=true; break;}
00854 const char* outputfilename = Tcl_GetString(objv[arg+1]);
00855 if (outputfilename) {
00856 filebase = new char[strlen(outputfilename)+1];
00857 strcpy(filebase, outputfilename);
00858 export_to_file = true;
00859 }
00860 arg++;
00861 }
00862 else if (!strcmp(Tcl_GetStringFromObj(objv[arg], NULL), "-combine")) {
00863 arg_combine=arg+1;
00864 arg++;
00865 if (arg_combine>=argc) bad_usage=true;
00866 }
00867 else if (accept_usepoints && !strcmp(Tcl_GetStringFromObj(objv[arg], NULL), "-points")) {
00868 use_point_particles=true;
00869 }
00870 else if (accept_cutoff && !strcmp(Tcl_GetStringFromObj(objv[arg], NULL), "-cutoff")) {
00871 if (arg+1 >= argc) bad_usage=true;
00872 Tcl_GetDoubleFromObj(interp, objv[arg+1], &cutoff);
00873 if (cutoff <= 0.) {
00874 Tcl_AppendResult(interp, "volmap: cutoff must be positive. (-cutoff)", NULL);
00875 return TCL_ERROR;
00876 }
00877 arg++;
00878 }
00879 else if (accept_radius && !strcmp(Tcl_GetStringFromObj(objv[arg], NULL), "-radscale")) {
00880 if (arg+1 >= argc) bad_usage=true;
00881 Tcl_GetDoubleFromObj(interp, objv[arg+1], &radius_factor);
00882 if (radius_factor < 0.f) {
00883 Tcl_AppendResult(interp, "volmap: radscale must be positive. (-radscale)", NULL);
00884 return TCL_ERROR;
00885 }
00886 arg++;
00887 }
00888 else if (accept_weight && !strcmp(Tcl_GetStringFromObj(objv[arg], NULL), "-weight")) {
00889 if (arg+1>=argc) bad_usage=true;
00890 arg_weight = arg+1;
00891 arg++;
00892 }
00893
00894 else
00895 bad_usage=true;
00896 }
00897
00898
00899 if (bad_usage) {
00900 if (maptype == UNDEF_MAP)
00901 Tcl_AppendResult(interp, "volmap: unknown map type.", NULL);
00902 else
00903 Tcl_WrongNumArgs(interp, 2, objv-1, (char *)"<selection> [options...]");
00904
00905 return TCL_ERROR;
00906 }
00907
00908
00909
00910
00911
00912 VolMapCreate::CombineType combine_type=VolMapCreate::COMBINE_AVG;
00913 if (arg_combine) {
00914 char *combine_str=Tcl_GetString(objv[arg_combine]);
00915 if (!strcmp(combine_str, "avg") || !strcmp(combine_str, "average"))
00916 combine_type=VolMapCreate::COMBINE_AVG;
00917 else if (!strcmp(combine_str, "max") || !strcmp(combine_str, "maximum"))
00918 combine_type=VolMapCreate::COMBINE_MAX;
00919 else if (!strcmp(combine_str, "min") || !strcmp(combine_str, "minimum"))
00920 combine_type=VolMapCreate::COMBINE_MIN;
00921 else if (!strcmp(combine_str, "stdev"))
00922 combine_type=VolMapCreate::COMBINE_STDEV;
00923 else if (!strcmp(combine_str, "pmf"))
00924 combine_type=VolMapCreate::COMBINE_PMF;
00925 else {
00926 Tcl_AppendResult(interp, "volmap: -combine argument must be: avg, min, \
00927 max, stdev, pmf", NULL);
00928 return TCL_ERROR;
00929 }
00930 }
00931
00932
00933 int ret_val=0;
00934 float *weights = NULL;
00935 if (accept_weight) {
00936 weights = new float[sel->selected];
00937
00938 if (arg_weight)
00939 ret_val = tcl_get_weights(interp, app, sel, objv[arg_weight], weights);
00940 else
00941 ret_val = tcl_get_weights(interp, app, sel, NULL, weights);
00942
00943 if (ret_val < 0) {
00944 Tcl_AppendResult(interp, "volmap: ", measure_error(ret_val), NULL);
00945 delete [] weights;
00946 return TCL_ERROR;
00947 }
00948 }
00949
00950
00951
00952
00953 VolMapCreate *volcreate = NULL;
00954
00955
00956 switch(maptype) {
00957 case DENS_MAP:
00958 volcreate = new VolMapCreateDensity(app, sel, (float)resolution, weights, (float)radius_factor);
00959 if (!filebase) {
00960 filebase = new char[strlen("density_out.dx")+1];
00961 strcpy(filebase, "density_out.dx");
00962 }
00963 break;
00964
00965 case INTERP_MAP:
00966 volcreate = new VolMapCreateInterp(app, sel, (float)resolution, weights);
00967 if (!filebase) {
00968 filebase = new char[strlen("interp_out.dx")+1];
00969 strcpy(filebase, "interp_out.dx");
00970 }
00971 break;
00972
00973 case DIST_MAP:
00974 volcreate = new VolMapCreateDistance(app, sel, (float)resolution, (float)cutoff);
00975 if (!filebase) {
00976 filebase = new char[strlen("distance_out.dx")+1];
00977 strcpy(filebase, "distance_out.dx");
00978 }
00979 break;
00980
00981 case OCCUP_MAP:
00982 volcreate = new VolMapCreateOccupancy(app, sel, (float)resolution, use_point_particles);
00983 if (!filebase) {
00984 filebase = new char[strlen("occupancy_out.dx")+1];
00985 strcpy(filebase, "occupancy_out.dx");
00986 }
00987 break;
00988
00989 case MASK_MAP:
00990 volcreate = new VolMapCreateMask(app, sel, (float)resolution, (float)cutoff);
00991 if (!filebase) {
00992 filebase = new char[strlen("mask_out.dx")+1];
00993 strcpy(filebase, "mask_out.dx");
00994 }
00995 break;
00996
00997 case CPOTENTIAL_MAP:
00998 volcreate = new VolMapCreateCoulombPotential(app, sel, (float)resolution);
00999 if (!filebase) {
01000 filebase = new char[strlen("coulomb_out.dx")+1];
01001 strcpy(filebase, "coulomb_out.dx");
01002 }
01003 break;
01004
01005 case CPOTENTIALMSM_MAP:
01006 volcreate = new VolMapCreateCoulombPotentialMSM(app, sel, (float)resolution);
01007 if (!filebase) {
01008 filebase = new char[strlen("coulombmsm_out.dx")+1];
01009 strcpy(filebase, "coulombmsm_out.dx");
01010 }
01011 break;
01012
01013
01014 default:
01015 break;
01016 }
01017
01018
01019 if (volcreate) {
01020
01021 if (arg_minmax)
01022 volcreate->set_minmax(float(minmax[0]), float(minmax[1]),
01023 float(minmax[2]), float(minmax[3]),
01024 float(minmax[4]), float(minmax[5]));
01025
01026
01027 if (checkpoint_freq) {
01028 char *checkpointname = new char[32+strlen(filebase)+1];
01029 #if defined(_MSC_VER)
01030 char slash = '\\';
01031 #else
01032 char slash = '/';
01033 #endif
01034 char *tailname = strrchr(filebase, slash);
01035 if (!tailname) tailname = filebase;
01036 else tailname = tailname+1;
01037 char *dirname = new char[strlen(filebase)+1];
01038 strcpy(dirname, filebase);
01039 char *sep = strrchr(dirname, slash);
01040
01041 if (sep) {
01042 *sep = '\0';
01043 sprintf(checkpointname, "%s%ccheckpoint:%s", dirname, slash, tailname);
01044 }
01045 else {
01046 *dirname = '\0';
01047 sprintf(checkpointname, "checkpoint:%s", tailname);
01048 }
01049 delete[] dirname;
01050
01051 Tcl_AppendResult(interp, "CHECKPOINTNAME = ", checkpointname, NULL);
01052 volcreate->set_checkpoint(checkpoint_freq, checkpointname);
01053 delete[] checkpointname;
01054 }
01055
01056
01057 ret_val = volcreate->compute_all(use_all_frames, combine_type, NULL);
01058 if (ret_val < 0) {
01059 delete volcreate;
01060 if (weights) delete [] weights;
01061 if (filebase) delete [] filebase;
01062
01063 Tcl_AppendResult(interp, "\nvolmap: ERROR ", measure_error(ret_val), NULL);
01064 return TCL_ERROR;
01065 }
01066
01067
01068 if (export_to_file || export_molecule < 0) {
01069
01070 filename = new char[strlen(filebase)+16];
01071 strcpy(filename,filebase);
01072 char *suffix = strrchr(filename, '.');
01073 if (!strcmp(suffix,".dx")) *suffix = '\0';
01074 strcat(filename, ".dx");
01075 volcreate->write_map(filename);
01076 delete[] filename;
01077 }
01078
01079
01080 if (export_molecule >= 0) {
01081 VolumetricData *volmap = volcreate->volmap;
01082 float origin[3], xaxis[3], yaxis[3], zaxis[3];
01083 int i;
01084 for (i=0; i<3; i++) {
01085 origin[i] = (float) volmap->origin[i];
01086 xaxis[i] = (float) volmap->xaxis[i];
01087 yaxis[i] = (float) volmap->yaxis[i];
01088 zaxis[i] = (float) volmap->zaxis[i];
01089 }
01090 int err = app->molecule_add_volumetric(export_molecule,
01091 (volmap->name) ? volmap->name : "(no name)",
01092 origin, xaxis, yaxis, zaxis,
01093 volmap->xsize, volmap->ysize, volmap->zsize, volmap->data);
01094 if (err != 1) {
01095 Tcl_AppendResult(interp, "ERROR: export of volmap into molecule was unsuccessful!", NULL);
01096 }
01097 else volmap->data=NULL;
01098 }
01099
01100 delete volcreate;
01101 }
01102
01103 if (weights) delete [] weights;
01104 if (filebase) delete [] filebase;
01105
01106 return TCL_OK;
01107 }
01108
01109
01110
01111
01112 #define DOUBLE_VSUB(D, X, Y) \
01113 D[0] = float(X[0]-Y[0]); \
01114 D[1] = float(X[1]-Y[1]); \
01115 D[2] = float(X[2]-Y[2]);
01116
01117
01118
01119
01120
01121
01122
01123
01124
01125 static int vmd_volmap_compare(VMDApp *app, int argc, Tcl_Obj * const objv[], Tcl_Interp *interp)
01126 {
01127 int molid1 = -1;
01128 int molid2 = -1;
01129 int mapid1 = -1;
01130 int mapid2 = -1;
01131
01132
01133 if (!strcmp(Tcl_GetStringFromObj(objv[1], NULL), "top"))
01134 molid1 = app->molecule_top();
01135 else
01136 Tcl_GetIntFromObj(interp, objv[1], &molid1);
01137
01138 if (!strcmp(Tcl_GetStringFromObj(objv[3], NULL), "top"))
01139 molid2 = app->molecule_top();
01140 else
01141 Tcl_GetIntFromObj(interp, objv[3], &molid2);
01142
01143 if (!app->molecule_valid_id(molid1) || !app->molecule_valid_id(molid2)) {
01144 Tcl_AppendResult(interp, "volmap compare: molecule specified for ouput is invalid. (-mol)", NULL);
01145 return TCL_ERROR;
01146 }
01147
01148 Molecule *mol1 = app->moleculeList->mol_from_id(molid1);
01149 Molecule *mol2 = app->moleculeList->mol_from_id(molid2);
01150
01151
01152 Tcl_GetIntFromObj(interp, objv[2], &mapid1);
01153 Tcl_GetIntFromObj(interp, objv[4], &mapid2);
01154
01155 if (mapid1<0 || mapid2<0) {
01156 Tcl_AppendResult(interp, "volmap compare: Volmap ID must be positive.", NULL);
01157 return TCL_ERROR;
01158 }
01159 if (mapid1 >= mol1->num_volume_data() ||
01160 mapid2 >= mol2->num_volume_data()) {
01161 Tcl_AppendResult(interp, "volmap compare: Volmap ID does not exist.", NULL);
01162 return TCL_ERROR;
01163 }
01164
01165
01166 bool bad_usage = false;
01167 double histinterval = 2.5;
01168 int numbins = 9;
01169 int arg;
01170 for (arg=5; arg<argc && !bad_usage; arg++) {
01171 if (!strcmp(Tcl_GetStringFromObj(objv[arg], NULL), "-interval")) {
01172 if (arg+1>=argc) { bad_usage=true; break; }
01173 Tcl_GetDoubleFromObj(interp, objv[arg+1], &histinterval);
01174 if (histinterval <= 0.f) {
01175 Tcl_AppendResult(interp, "volmap compare: histogram interval must be positive. (-interval)", NULL);
01176 return TCL_ERROR;
01177 }
01178 arg++;
01179 }
01180 else if (!strcmp(Tcl_GetStringFromObj(objv[arg], NULL), "-numbins")) {
01181 if (arg+1>=argc) { bad_usage=true; break; }
01182 Tcl_GetIntFromObj(interp, objv[arg+1], &numbins);
01183 if (numbins <= 0) {
01184 Tcl_AppendResult(interp, "volmap compare: histogram bin size must be positive. (-interval)", NULL);
01185 return TCL_ERROR;
01186 }
01187 arg++;
01188 }
01189 else {
01190
01191 Tcl_AppendResult(interp, " volmap compare: unknown argument ",
01192 Tcl_GetStringFromObj(objv[arg], NULL), NULL);
01193 return TCL_ERROR;
01194 }
01195
01196 }
01197 if (bad_usage) {
01198 Tcl_WrongNumArgs(interp, 2, objv-1, (char *)"<molid> <minmax> [options...]");
01199 return TCL_ERROR;
01200 }
01201
01202 const VolumetricData *vol1 = mol1->get_volume_data(mapid1);
01203 const VolumetricData *vol2 = mol2->get_volume_data(mapid2);
01204
01205 if (vol1->xsize != vol2->xsize ||
01206 vol1->ysize != vol2->ysize ||
01207 vol1->zsize != vol2->zsize) {
01208 Tcl_AppendResult(interp, "volmap compare: maps have different dimensions.", NULL);
01209 return TCL_ERROR;
01210 }
01211
01212 float vdiff[3];
01213 DOUBLE_VSUB(vdiff, vol1->origin, vol2->origin);
01214 if (norm(vdiff)>1e-6) {
01215 Tcl_AppendResult(interp, "volmap compare: maps have different origin.", NULL);
01216 }
01217
01218 DOUBLE_VSUB(vdiff, vol1->xaxis, vol2->xaxis);
01219 if (norm(vdiff)>1e-6) {
01220 Tcl_AppendResult(interp, "volmap compare: maps have different x-axis.", NULL);
01221 }
01222 DOUBLE_VSUB(vdiff, vol1->yaxis, vol2->yaxis);
01223 if (norm(vdiff)>1e-6) {
01224 Tcl_AppendResult(interp, "volmap compare: maps have different y-axis.", NULL);
01225 }
01226 DOUBLE_VSUB(vdiff, vol1->zaxis, vol2->zaxis);
01227 if (norm(vdiff)>1e-6) {
01228 Tcl_AppendResult(interp, "volmap compare: maps have different z-axis.", NULL);
01229 }
01230
01231 int i;
01232 int numdiff = 0;
01233 float sqsum = 0.f;
01234 float sqsumd = 0.f;
01235 float min1 = 0.f, min2 = 0.f;
01236 float max1 = 0.f, max2 = 0.f;
01237 float maxdiff = 0.f;
01238 int indexmaxdiff = 0;
01239
01240 for (i=0; i<vol1->gridsize(); i++) {
01241 float v1 = vol1->data[i];
01242 float v2 = vol2->data[i];
01243 float diff = v1-v2;
01244 sqsum += diff*diff;
01245 if (v1<min1) min1 = v1;
01246 if (v2<min2) min2 = v2;
01247 if (v1>max1) max1 = v1;
01248 if (v2>max2) max2 = v2;
01249 if (fabsf(diff)>maxdiff) {
01250 maxdiff = fabsf(diff);
01251 indexmaxdiff = i;
01252 }
01253 if (diff) {
01254
01255 sqsumd += diff*diff;
01256 numdiff++;
01257 }
01258 }
01259 float rmsd = 0.f;
01260 float diffrmsd = 0.f;
01261 if (sqsum) rmsd = sqrtf(sqsum/vol1->gridsize());
01262 if (sqsumd) diffrmsd = sqrtf(sqsumd/numdiff);
01263
01264 char tmpstr[128];
01265 msgInfo << "volmap compare" << sendmsg;
01266 msgInfo << "--------------" << sendmsg;
01267 msgInfo << "Comparing mol "<<molid1<<" -> map "<<mapid1<<"/"<<mol1->num_volume_data()<<sendmsg;
01268 msgInfo << " to mol "<<molid2<<" -> map "<<mapid2<<"/"<<mol2->num_volume_data()<<sendmsg;
01269 msgInfo << "Statistics:" << sendmsg;
01270 sprintf(tmpstr, " %12s | %12s", "MAP 1", "MAP 2");
01271 msgInfo << tmpstr << sendmsg;
01272 sprintf(tmpstr, "min value = %12g | %12g", min1, min2);
01273 msgInfo << tmpstr << sendmsg;
01274 sprintf(tmpstr, "max value = %12g | %12g", max1, max2);
01275 msgInfo << tmpstr << sendmsg;
01276 msgInfo << sendmsg;
01277 sprintf(tmpstr, "# differing elements = %d/%d", numdiff, vol1->gridsize());
01278 msgInfo << tmpstr << sendmsg;
01279 msgInfo << "max difference:" << sendmsg;
01280 sprintf(tmpstr, " map1[%d] = %g map2[%d] = %g diff = %g",
01281 indexmaxdiff, vol1->data[indexmaxdiff],
01282 indexmaxdiff, vol2->data[indexmaxdiff], maxdiff);
01283 msgInfo << tmpstr << sendmsg;
01284
01285
01286 msgInfo << sendmsg;
01287 sprintf(tmpstr, " RMSD = %12.6f", rmsd);
01288 msgInfo << tmpstr << sendmsg;
01289 sprintf(tmpstr, " diffRMSD = %12.6f (for the set of differing elements)", diffrmsd);
01290 msgInfo << tmpstr << sendmsg;
01291
01292
01293
01294
01295 float wsum = 0.f;
01296 float range = max2-min2;
01297 float wdiffrmsd = 0.f;
01298 if (range) {
01299 sqsum = 0.f;
01300 for (i=0; i<vol1->gridsize(); i++) {
01301 float diff = vol1->data[i]-vol2->data[i];
01302 if (diff) {
01303 float weight = 1.f-(vol2->data[i]-min2)/range;
01304 wsum += weight;
01305 sqsum += diff*diff*weight;
01306 }
01307 }
01308 if (sqsum) wdiffrmsd = sqrtf(sqsum/wsum);
01309 }
01310
01311
01312 sprintf(tmpstr, "weighted RMSD = %12.6f (for the set of differing elements)", wdiffrmsd);
01313 msgInfo << tmpstr << sendmsg;
01314 msgInfo << " weight factor w = 1-(E_i-E_min)/(E_max-E_min)" << sendmsg;
01315 msgInfo << sendmsg;
01316
01317
01318
01319
01320
01321
01322
01323
01324
01325
01326
01327
01328
01329
01330
01331 float *histo = new float[numbins*sizeof(float)];
01332
01333 int *num = new int[numbins*sizeof(float)];
01334
01335 float *maxEntry = new float[numbins*sizeof(float)];
01336 float *binrmsd = new float[numbins*sizeof(float)];
01337 memset(histo, 0, numbins*sizeof(float));
01338 memset(num, 0, numbins*sizeof(int));
01339 memset(maxEntry, 0, numbins*sizeof(float));
01340 memset(binrmsd, 0, numbins*sizeof(float));
01341
01342 for (i = 0; i < vol1->gridsize(); i++) {
01343 float e1 = vol1->data[i];
01344 float e2 = vol2->data[i];
01345 float err = fabsf(e1 - e2) / (e2 - min2 + 1);
01346 int index = (int) floorf((e2 - min2) / float(histinterval));
01347 if (index < 0) index = 0;
01348 else if (index >= numbins) index = numbins - 1;
01349
01350
01351 if (err > maxEntry[index]) {
01352 maxEntry[index] = err;
01353 }
01354 histo[index] += err;
01355 num[index]++;
01356 binrmsd[index] += (e2-e1)*(e2-e1);
01357 }
01358 for (i=0; i<numbins; i++) {
01359 if (binrmsd[i]) binrmsd[i] = sqrtf(binrmsd[i]/num[i]);
01360 }
01361
01362
01363 float firstbin = floorf(min2/float(histinterval))*float(histinterval);
01364 Tcl_Obj *caption = Tcl_NewListObj(0, NULL);
01365 Tcl_Obj *numEntries = Tcl_NewListObj(0, NULL);
01366 Tcl_Obj *objHisto = Tcl_NewListObj(0, NULL);
01367 Tcl_Obj *objAverage = Tcl_NewListObj(0, NULL);
01368 Tcl_Obj *objMax = Tcl_NewListObj(0, NULL);
01369 Tcl_Obj *objBinRMSD = Tcl_NewListObj(0, NULL);
01370 char label[64];
01371 msgInfo << "Histogram of error in map 1 relative to map 2 " << sendmsg;
01372 msgInfo << sendmsg;
01373 msgInfo << " interval # samples total error avg error"
01374 << " max error rmsd" << sendmsg;
01375 msgInfo << "---------------------------------------------------------"
01376 << "----------------------------" << sendmsg;
01377
01378 sprintf(label, "[%g,%g)", (double) firstbin, (double) (firstbin+histinterval));
01379 sprintf(tmpstr, "%14s %10d %14.6f %14.6f %14.6f %14.6f", label, num[0],
01380 (double) histo[0], (double) (!num[0]?0:histo[0]/num[0]),
01381 (double) maxEntry[0], (double) binrmsd[0]);
01382 msgInfo << tmpstr << sendmsg;
01383 Tcl_ListObjAppendElement(interp, caption, Tcl_NewStringObj(label, -1));
01384 Tcl_ListObjAppendElement(interp, numEntries, Tcl_NewIntObj(num[0]));
01385 Tcl_ListObjAppendElement(interp, objHisto, Tcl_NewDoubleObj(histo[0]));
01386 Tcl_ListObjAppendElement(interp, objAverage, Tcl_NewDoubleObj(!num[0]?0:histo[0]/num[0]));
01387 Tcl_ListObjAppendElement(interp, objMax, Tcl_NewDoubleObj(maxEntry[0]));
01388 Tcl_ListObjAppendElement(interp, objBinRMSD, Tcl_NewDoubleObj(binrmsd[0]));
01389 for (i = 1; i < numbins-1; i++) {
01390 sprintf(label, "[%g,%g)", (double)(firstbin+i*histinterval), (double)(firstbin+(i+1)*histinterval));
01391 sprintf(tmpstr, "%14s %10d %14.6f %14.6f %14.6f %14.6f", label, num[i],
01392 (double) histo[i], (double) (!num[i]?0:histo[i]/num[i]),
01393 (double) maxEntry[i], (double) binrmsd[i]);
01394 Tcl_ListObjAppendElement(interp, caption, Tcl_NewStringObj(label, -1));
01395 Tcl_ListObjAppendElement(interp, numEntries, Tcl_NewIntObj(num[i]));
01396 Tcl_ListObjAppendElement(interp, objHisto, Tcl_NewDoubleObj(histo[i]));
01397 Tcl_ListObjAppendElement(interp, objAverage, Tcl_NewDoubleObj(!num[i]?0:histo[i]/num[i]));
01398 Tcl_ListObjAppendElement(interp, objMax, Tcl_NewDoubleObj(maxEntry[i]));
01399 Tcl_ListObjAppendElement(interp, objBinRMSD, Tcl_NewDoubleObj(binrmsd[i]));
01400 msgInfo << tmpstr << sendmsg;
01401 }
01402 sprintf(label, "[%g,+infty)", (double)(firstbin+i*histinterval));
01403 sprintf(tmpstr, "%14s %10d %14.6f %14.6f %14.6f %14.6f", label, num[i],
01404 (double) histo[i], (double) (!num[i]?0:histo[i]/num[i]),
01405 (double) maxEntry[i], (double) binrmsd[i]);
01406 Tcl_ListObjAppendElement(interp, caption, Tcl_NewStringObj(label, -1));
01407 Tcl_ListObjAppendElement(interp, numEntries, Tcl_NewIntObj(num[i]));
01408 Tcl_ListObjAppendElement(interp, objHisto, Tcl_NewDoubleObj(histo[i]));
01409 Tcl_ListObjAppendElement(interp, objAverage, Tcl_NewDoubleObj(!num[i]?0:histo[i]/num[i]));
01410 Tcl_ListObjAppendElement(interp, objMax, Tcl_NewDoubleObj(maxEntry[i]));
01411 Tcl_ListObjAppendElement(interp, objBinRMSD, Tcl_NewDoubleObj(binrmsd[i]));
01412 msgInfo << tmpstr << sendmsg;
01413 msgInfo << sendmsg;
01414
01415 Tcl_Obj *tcl_result = Tcl_NewListObj(0, NULL);
01416 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewStringObj("rmsd", -1));
01417 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewDoubleObj(rmsd));
01418 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewStringObj("diffrmsd", -1));
01419 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewDoubleObj(diffrmsd));
01420 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewStringObj("weightedrmsd", -1));
01421 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewDoubleObj(wdiffrmsd));
01422 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewStringObj("maxdiff", -1));
01423 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewDoubleObj(maxdiff));
01424 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewStringObj("numdiff", -1));
01425 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewIntObj(numdiff));
01426 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewStringObj("caption", -1));
01427 Tcl_ListObjAppendElement(interp, tcl_result, caption);
01428 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewStringObj("numEntries", -1));
01429 Tcl_ListObjAppendElement(interp, tcl_result, numEntries);
01430 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewStringObj("histo", -1));
01431 Tcl_ListObjAppendElement(interp, tcl_result, objHisto);
01432 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewStringObj("avgErr", -1));
01433 Tcl_ListObjAppendElement(interp, tcl_result, objAverage);
01434 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewStringObj("maxError", -1));
01435 Tcl_ListObjAppendElement(interp, tcl_result, objMax);
01436 Tcl_ListObjAppendElement(interp, tcl_result, Tcl_NewStringObj("binRMSD", -1));
01437 Tcl_ListObjAppendElement(interp, tcl_result, objBinRMSD);
01438 Tcl_SetObjResult(interp, tcl_result);
01439
01440 delete [] histo;
01441 delete [] num;
01442 delete [] maxEntry;
01443 delete [] binrmsd;
01444 return TCL_OK;
01445 }
01446
01447 int obj_volmap(ClientData cd, Tcl_Interp *interp, int argc, Tcl_Obj * const objv[]) {
01448
01449 if (argc < 2) {
01450 Tcl_SetResult(interp, (char *)
01451 "usage: volmap <command> <args...>\n"
01452 "\nVolmap Creation:\n"
01453 " volmap <maptype> <selection> [opts...] -- create a new volmap file\n"
01454 " maptypes:\n"
01455 " density -- arbitrary-weight density map [atoms/A^3]\n"
01456 " interp -- arbitrary-weight interpolation map [atoms/A^3]\n"
01457 " distance -- distance nearest atom surface [A]\n"
01458 " occupancy -- percent atomic occupancy of gridpoints [%]\n"
01459 " mask -- binary mask by painting spheres around atoms\n"
01460 " coulomb -- Coulomb electrostatic potential [kT/e] (slow)\n"
01461 " coulombmsm -- Coulomb electrostatic potential [kT/e] (fast)\n"
01462 " ils -- free energy map [kT] computed by implicit ligand sampling\n"
01463 " options common to all maptypes:\n"
01464 " -o <filename> -- output DX format file name (use .dx extension)\n"
01465 " -mol <molid> -- export volmap into the specified mol\n"
01466 " -res <float> -- resolution in A of smallest cube\n"
01467 " -allframes -- compute for all frames of the trajectory\n"
01468 " -combine <arg> -- rule for combining the different frames\n"
01469 " <arg> = avg, min, max, stdev or pmf\n"
01470 " -minmax <list of 2 vectors> -- specify boundary of output grid\n"
01471 " options specific to certain maptypes:\n"
01472 " -points -- use point particles for occupancy\n"
01473 " -cutoff <float> -- distance cutoff for calculations [A]\n"
01474 " -radscale <float> -- premultiply all atomic radii by a factor\n"
01475 " -weight <str/list> -- per atom weights for calculation\n"
01476 " options for ils:\n"
01477 " see documentation\n", NULL);
01478 return TCL_ERROR;
01479 }
01480
01481 VMDApp *app = (VMDApp *)cd;
01482 char *arg1 = Tcl_GetStringFromObj(objv[1],NULL);
01483
01484
01485 if (argc > 1 && !strupncmp(arg1, "occupancy", CMDLEN))
01486 return vmd_volmap_new_fromtype(app, argc-1, objv+1, interp);
01487 if (argc > 1 && !strupncmp(arg1, "density", CMDLEN))
01488 return vmd_volmap_new_fromtype(app, argc-1, objv+1, interp);
01489 if (argc > 1 && !strupncmp(arg1, "interp", CMDLEN))
01490 return vmd_volmap_new_fromtype(app, argc-1, objv+1, interp);
01491 if (argc > 1 && !strupncmp(arg1, "distance", CMDLEN))
01492 return vmd_volmap_new_fromtype(app, argc-1, objv+1, interp);
01493 if (argc > 1 && !strupncmp(arg1, "mask", CMDLEN))
01494 return vmd_volmap_new_fromtype(app, argc-1, objv+1, interp);
01495 if (argc > 1 && (!strupncmp(arg1, "coulombpotential", CMDLEN) ||
01496 !strupncmp(arg1, "coulomb", CMDLEN) ||
01497 !strupncmp(arg1, "coulombmsm", CMDLEN)))
01498 return vmd_volmap_new_fromtype(app, argc-1, objv+1, interp);
01499
01500 if (argc > 1 && !strupncmp(arg1, "compare", CMDLEN))
01501 return vmd_volmap_compare(app, argc-1, objv+1, interp);
01502
01503 if (argc > 1 && !strupncmp(arg1, "ils", CMDLEN))
01504 return vmd_volmap_ils(app, argc-1, objv+1, interp);
01505 if (argc > 1 && !strupncmp(arg1, "ligand", CMDLEN))
01506 return vmd_volmap_ils(app, argc-1, objv+1, interp);
01507
01508 Tcl_SetResult(interp, (char *)"Type 'volmap' for summary of usage\n",NULL);
01509 return TCL_ERROR;
01510 }