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 #include "DrawMolecule.h"
00026 #include "AtomColor.h"
00027 #include "AtomRep.h"
00028 #include "AtomSel.h"
00029 #include "utilities.h"
00030 #include "VMDApp.h"
00031 #include "MoleculeList.h"
00032 #include "CommandQueue.h"
00033 #include "CmdAnimate.h"
00034 #include "Stride.h"
00035 #include "PickList.h"
00036 #include "MaterialList.h"
00037 #include "Inform.h"
00038 #include "TextEvent.h"
00039 #include "DisplayDevice.h"
00040 #include "MoleculeGraphics.h"
00041 #include "BondSearch.h"
00042 #include "DrawForce.h"
00043 #include "VolumetricData.h"
00044 #include "CUDAAccel.h"
00045
00047
00048 DrawMolecule::DrawMolecule(VMDApp *vmdapp, Displayable *par)
00049 : BaseMolecule(vmdapp->next_molid()),
00050 Displayable(par), app(vmdapp), repList(8) {
00051 repcounter = 0;
00052 curframe = -1;
00053 active = TRUE;
00054 did_secondary_structure = 0;
00055 molgraphics = new MoleculeGraphics(this);
00056 vmdapp->pickList->add_pickable(molgraphics);
00057 drawForce = new DrawForce(this);
00058
00059 invalidate_cov_scale();
00060 center[0] = center[1] = center[2] = 0.0f;
00061
00062 need_find_bonds = 0;
00063 }
00064
00065
00066
00067 DrawMolecule::~DrawMolecule() {
00068 int i;
00069
00070
00071 for(i=0; i < components(); i++) {
00072 app->pickList->remove_pickable(component(i));
00073 delete component(i);
00074 }
00075
00076 app->pickList->remove_pickable(molgraphics);
00077
00078
00079 for (i=timesteps.num()-1; i>=0; i--) {
00080 delete timesteps[i];
00081 timesteps.remove(i);
00082 }
00083
00084 delete molgraphics;
00085 }
00086
00088
00089
00090 DrawMolItem *DrawMolecule::component(int n) {
00091 if(n >= 0 && n < components())
00092 return repList[n];
00093 else
00094 return NULL;
00095 }
00096
00097
00098
00099 DrawMolItem *DrawMolecule::component_from_pickable(const Pickable *p) {
00100 for (int i=0; i<components(); i++)
00101 if (repList[i] == p) return repList[i];
00102 return NULL;
00103 }
00104
00105
00106 wkf_threadpool_t * DrawMolecule::cpu_threadpool(void) {
00107 return (wkf_threadpool_t *) app->thrpool;
00108 }
00109
00110
00111 wkf_threadpool_t * DrawMolecule::cuda_devpool(void) {
00112 return (app->cuda != NULL) ? app->cuda->get_cuda_devpool() : NULL;
00113 }
00114
00115
00116
00117 int DrawMolecule::atom_displayed(int n) {
00118 if (displayed() && n >= 0 && n < nAtoms) {
00119 for (int i=(components() - 1); i >= 0; i--) {
00120 if ((repList[i])->atom_displayed(n))
00121 return TRUE;
00122 }
00123 }
00124 return FALSE;
00125 }
00126
00127
00128
00129 int DrawMolecule::del_rep(int n) {
00130 DrawMolItem *rep = component(n);
00131 if (rep) {
00132 app->pickList->remove_pickable(rep);
00133 delete rep;
00134 repList.remove(n);
00135 invalidate_cov_scale();
00136 }
00137
00138 return (rep != NULL);
00139 }
00140
00141
00142 void DrawMolecule::add_rep(AtomColor *ac, AtomRep *ar, AtomSel *as,
00143 const Material *am) {
00144
00145 char buf[50];
00146 sprintf(buf, "rep%d", repcounter++);
00147 DrawMolItem *rep = new DrawMolItem(buf, this, ac, ar, as);
00148 app->pickList->add_pickable(rep);
00149 rep->change_material(am);
00150 repList.append(rep);
00151 invalidate_cov_scale();
00152 }
00153
00154 int DrawMolecule::show_rep(int repid, int onoff) {
00155 DrawMolItem *rep = component(repid);
00156 if (rep) {
00157 if (onoff) rep->on();
00158 else rep->off();
00159 invalidate_cov_scale();
00160 return TRUE;
00161 }
00162 return FALSE;
00163 }
00164
00165
00166
00167 int DrawMolecule::change_rep(int n, AtomColor *ac, AtomRep *ar, const char *sel) {
00168 DrawMolItem *rep = component(n);
00169 if (rep) {
00170 rep->change_color(ac);
00171 rep->change_rep(ar);
00172 rep->change_sel(sel);
00173
00174 invalidate_cov_scale();
00175 return TRUE;
00176 }
00177
00178 return FALSE;
00179 }
00180
00181
00182
00183 void DrawMolecule::force_recalc(int reason) {
00184 int numcomp = components();
00185 for (int i=0; i<numcomp; i++) {
00186 component(i)->force_recalc(reason);
00187 }
00188
00189
00190
00191 need_matrix_recalc();
00192 app->commandQueue->runcommand(new CmdAnimNewFrame);
00193
00194
00195 if (reason & (DrawMolItem::MOL_REGEN | DrawMolItem::SEL_REGEN))
00196 invalidate_cov_scale();
00197 }
00198
00199
00200
00201 void DrawMolecule::change_pbc() {
00202 int numcomp = components();
00203 for (int i=0; i<numcomp; i++)
00204 component(i)->change_pbc();
00205
00206
00207
00208 notify();
00209 }
00210
00211
00212
00213 void DrawMolecule::change_ts() {
00214 int numcomp = components();
00215 for (int i=0; i<numcomp; i++)
00216 component(i)->change_ts();
00217
00218 molgraphics->prepare();
00219 drawForce->prepare();
00220
00221 notify();
00222
00223
00224 app->commandQueue->runcommand(new FrameEvent(id(), curframe));
00225 }
00226
00227
00228
00229 int DrawMolecule::highlighted_rep() const {
00230 if (app->highlighted_molid != id())
00231 return -1;
00232 return app->highlighted_rep;
00233 }
00234
00235
00236
00237 int DrawMolecule::get_component_by_name(const char *nm) {
00238
00239 int numreps = repList.num();
00240 for (int i=0; i<numreps; i++) {
00241 if (!strcmp(repList[i]->name, nm))
00242 return i;
00243 }
00244 return -1;
00245 }
00246
00247
00248
00249 const char *DrawMolecule::get_component_name(int ind) {
00250 DrawMolItem *rep = component(ind);
00251 if (!rep)
00252 return FALSE;
00253 return rep->name;
00254 }
00255
00256 void DrawMolecule::prepare() {
00257 if (needUpdate()) {
00258 notify();
00259 }
00260 }
00261
00262 void DrawMolecule::override_current_frame(int n) {
00263 if (n == curframe) return;
00264 int num = timesteps.num();
00265 if ( num==0 ) return;
00266 if ( n<0 ) curframe = 0;
00267 else if ( n>=num ) curframe = num-1;
00268 else curframe = n;
00269 invalidate_cov_scale();
00270 }
00271
00272
00273 void DrawMolecule::notify() {
00274 int monnum = monitorlist.num();
00275 int nid = id();
00276 for (int i=0; i<monnum; i++)
00277 monitorlist[i]->notify(nid);
00278 }
00279
00280
00281
00282 void DrawMolecule::append_frame(Timestep *ts) {
00283 timesteps.append(ts);
00284
00285
00286
00287 override_current_frame(timesteps.num() - 1);
00288
00289
00290
00291
00292
00293 change_ts();
00294
00295
00296 if (timesteps.num() == 1) {
00297 #if 0
00298
00299
00300 if (getenv("VMDNOCOVCALC") == NULL)
00301 #endif
00302 app->scene_resetview_newmoldata();
00303 }
00304
00305
00306 if (timesteps.num() >= 1) {
00307
00308 if (need_find_bonds == 1) {
00309 need_find_bonds = 0;
00310 vmd_bond_search(this, ts, -1, 0);
00311 } else if (need_find_bonds == 2) {
00312 need_find_bonds = 0;
00313 vmd_bond_search(this, ts, -1, 1);
00314 }
00315 }
00316
00317 addremove_ts();
00318 app->commandQueue->runcommand(new CmdAnimNewNumFrames);
00319 }
00320
00321
00322
00323 void DrawMolecule::duplicate_frame(const Timestep *ts) {
00324 Timestep *newts;
00325 if (ts == NULL) {
00326 newts = new Timestep(nAtoms);
00327 newts->zero_values();
00328 } else {
00329 newts = new Timestep(*ts);
00330 }
00331 append_frame(newts);
00332 }
00333
00334
00335
00336 void DrawMolecule::delete_frame(int n) {
00337 if (n<0 || n>=timesteps.num()) return;
00338 delete timesteps[n];
00339 timesteps.remove(n);
00340
00341
00342 addremove_ts();
00343 app->commandQueue->runcommand(new CmdAnimNewNumFrames);
00344
00345
00346 if (curframe >= timesteps.num()) {
00347 curframe = timesteps.num()-1;
00348 change_ts();
00349 }
00350 }
00351
00352
00353
00354 void DrawMolecule::addremove_ts() {
00355 int numcomp = components();
00356 for (int i=0; i<numcomp; i++)
00357 component(i)->change_traj();
00358 }
00359
00360
00361
00362 static float dnorm(const double *v) {
00363 return (float)sqrt(v[0]*v[0] + v[1]*v[1] + v[2]*v[2]);
00364 }
00365
00366 void DrawMolecule::invalidate_cov_scale() {
00367 scalefactor = -1;
00368 }
00369
00370
00371 float DrawMolecule::scale_factor() {
00372 if (scalefactor < 0) update_cov_scale();
00373 if (scalefactor > 0) {
00374 return scalefactor;
00375
00376 } else if (molgraphics->num_elements() > 0) {
00377 return molgraphics->scale_factor();
00378
00379 } else if (volumeList.num() > 0) {
00380
00381
00382
00383
00384 const VolumetricData *data = volumeList[0];
00385 float x=dnorm(data->xaxis), y=dnorm(data->yaxis), z=dnorm(data->zaxis);
00386 float scale_factor = x > y ? x : y;
00387 scale_factor = scale_factor > z ? scale_factor : z;
00388 if (scale_factor > 0) return 1.5f/scale_factor;
00389 }
00390 return 1.0f;
00391 }
00392
00393
00394
00395 int DrawMolecule::cov(float& x, float& y, float& z) {
00396 if (scalefactor < 0) update_cov_scale();
00397
00398 if (scalefactor > 0) {
00399
00400 x = center[0]; y = center[1]; z = center[2];
00401
00402 } else if (molgraphics->num_elements() > 0) {
00403
00404 molgraphics->cov(x, y, z);
00405
00406 } else if (volumeList.num() > 0) {
00407
00408 const VolumetricData *data = volumeList[0];
00409 x = (float) (data->origin[0] +
00410 0.5*(data->xaxis[0] + data->yaxis[0] + data->zaxis[0]));
00411 y = (float) (data->origin[1] +
00412 0.5*(data->xaxis[1] + data->yaxis[1] + data->zaxis[1]));
00413 z = (float) (data->origin[2] +
00414 0.5*(data->xaxis[2] + data->yaxis[2] + data->zaxis[2]));
00415 } else {
00416 return FALSE;
00417 }
00418 return TRUE;
00419 }
00420
00421
00423 int DrawMolecule::recalc_bonds() {
00424 Timestep *ts = current();
00425
00426 if (ts) {
00427 clear_bonds();
00428 vmd_bond_search(this, ts, -1, 0);
00429 msgInfo << "Bond count: " << count_bonds() << sendmsg;
00430 return 0;
00431 }
00432
00433 msgInfo << "No coordinates" << sendmsg;
00434 return -1;
00435 }
00436
00437 int DrawMolecule::need_secondary_structure(int calc_if_not_yet_done) {
00438 if (did_secondary_structure) return TRUE;
00439
00440 if (calc_if_not_yet_done) {
00441 if (!current()) return FALSE;
00442 did_secondary_structure = TRUE;
00443 app->show_stride_message();
00444 int usestride=1;
00445 if (getenv("VMDUSEDSSP") != NULL) {
00446 usestride=0;
00447 }
00448
00449 if (!usestride) {
00450 msgInfo << "User override of STRIDE, using DSSP for secondary structure"
00451 << sendmsg;
00452 if (ss_from_dssp(this)) {
00453 msgErr << "Call to DSSP program failed." << sendmsg;
00454 return FALSE;
00455 }
00456 return TRUE;
00457 }
00458 if (ss_from_stride(this)) {
00459 msgErr << "Call to Stride program failed." << sendmsg;
00460 return FALSE;
00461 }
00462 return TRUE;
00463 }
00464
00465 did_secondary_structure = TRUE;
00466 return TRUE;
00467 }
00468
00469 void DrawMolecule::invalidate_ss() {
00470 did_secondary_structure = 0;
00471 }
00472
00473 int DrawMolecule::recalc_ss() {
00474 did_secondary_structure = 0;
00475 int success = need_secondary_structure(1);
00476 did_secondary_structure = 1;
00477
00478 if (success) for (int i=0; i<components(); i++) component(i)->change_ss();
00479 return success;
00480 }
00481
00482 void DrawMolecule::register_monitor(DrawMoleculeMonitor *mon) {
00483 monitorlist.append(mon);
00484 }
00485 void DrawMolecule::unregister_monitor(DrawMoleculeMonitor *mon) {
00486 monitorlist.remove(monitorlist.find(mon));
00487 }
00488
00489 void DrawMolecule::update_cov_scale() {
00490 const Timestep *ts = current();
00491 if (!ts) return;
00492 int i, n = ts->num;
00493
00494 if (!n) return;
00495
00496 float covx, covy, covz;
00497 float minposx, minposy, minposz;
00498 float maxposx, maxposy, maxposz;
00499
00500
00501 ResizeArray<int> tmp_(n);
00502 int *on = &tmp_[0];
00503 for (i=0; i<n; i++) on[i] = 0;
00504
00505 int istart=n;
00506
00507
00508
00509
00510 for (int j=0; j<repList.num(); j++) {
00511 const DrawMolItem *rep = repList[j];
00512 if (!rep->displayed())
00513 continue;
00514
00515 if (rep->atomSel->selected > 0) {
00516 const int first = rep->atomSel->firstsel;
00517 const int last = rep->atomSel->lastsel;
00518 if (first < istart)
00519 istart=first;
00520
00521 const int *flgs = rep->atomSel->on;
00522 for (i=first; i<=last; i++)
00523 on[i] |= flgs[i];
00524 }
00525 }
00526
00527
00528 if (istart < 0 || istart >= n) {
00529 istart = 0;
00530 for (i=0; i<n; i++) on[i] = 1;
00531 }
00532
00533
00534 const float *mpos = ts->pos + 3L*istart;
00535 minposx = maxposx = mpos[0];
00536 minposy = maxposy = mpos[1];
00537 minposz = maxposz = mpos[2];
00538 covx = covy = covz = 0.0;
00539
00540 int icount = 0;
00541 for (i=istart; i<n; ++i, mpos += 3) {
00542 if (!on[i]) continue;
00543 ++icount;
00544
00545 const float xpos = mpos[0];
00546 const float ypos = mpos[1];
00547 const float zpos = mpos[2];
00548
00549 covx += xpos;
00550 covy += ypos;
00551 covz += zpos;
00552
00553 if (xpos < minposx) minposx = xpos;
00554 if (xpos > maxposx) maxposx = xpos;
00555
00556 if (ypos < minposy) minposy = ypos;
00557 if (ypos > maxposy) maxposy = ypos;
00558
00559 if (zpos < minposz) minposz = zpos;
00560 if (zpos > maxposz) maxposz = zpos;
00561 }
00562
00563
00564 center[0] = covx;
00565 center[1] = covy;
00566 center[2] = covz;
00567 vec_scale(center, 1.0f / icount, center);
00568
00569
00570 scalefactor = maxposx - minposx;
00571
00572
00573 if (scalefactor == 0.0) {
00574 scalefactor = 3.0;
00575 }
00576
00577 if ((maxposx - minposx) > scalefactor)
00578 scalefactor = maxposx - minposx;
00579 if ((maxposy - minposy) > scalefactor)
00580 scalefactor = maxposy - minposy;
00581 if ((maxposz - minposz) > scalefactor)
00582 scalefactor = maxposz - minposz;
00583
00584 scalefactor = 1.5f / scalefactor;
00585 }
00586