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