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