FOX/ObjCryst++  2022
wxMolecule.cpp
1 /* ObjCryst++ Object-Oriented Crystallographic Library
2  (c) 2000-2002 Vincent Favre-Nicolin vincefn@users.sourceforge.net
3  2000-2001 University of Geneva (Switzerland)
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program; if not, write to the Free Software
17  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19 
20 // wx headers, with or without precompilation
21 #include "wx/wxprec.h"
22 #ifdef __BORLANDC__
23  #pragma hdrstop
24 #endif
25 #ifndef WX_PRECOMP
26  #include "wx/wx.h"
27 #endif
28 #include "wx/notebook.h"
29 #include "wx/minifram.h"
30 #include <wx/wfstream.h>
31 #include "wx/progdlg.h"
32 
33 #include <sstream>
34 #include <fstream>
35 #include <algorithm>
36 #include "ObjCryst/wxCryst/wxMolecule.h"
37 #include "ObjCryst/RefinableObj/LSQNumObj.h"
38 #include "ObjCryst/Quirks/Chronometer.h"
39 #include "ObjCryst/Quirks/VFNStreamFormat.h"
40 
41 namespace ObjCryst
42 {
43 
44 //:TODO: Move this to wxCryst.h
45 template<class T> T const* WXDialogChooseFromVector(const vector<T*> &reg,wxWindow*parent,
46  const string &message,int &choice)
47 {
48  wxString *choices = new wxString[reg.size()];
49  for(unsigned int i=0;i<reg.size();i++)
50  choices[i]= wxString::FromAscii((reg[i]->GetName()).c_str());
51  wxSingleChoiceDialog dialog
52  (parent,message.c_str(),"Choose",reg.size(),choices,NULL,wxOK | wxCANCEL);
53  dialog.SetSize(300,300);
54  if(wxID_OK!=dialog.ShowModal()) return 0;
55  choice=dialog.GetSelection();
56  delete[] choices;
57  return reg[choice];
58 }
59 
60 template<class T> T * WXDialogChooseFromVector(vector<T*> &reg,wxWindow*parent,
61  const string &message,int &choice)
62 {
63  wxString *choices = new wxString[reg.size()];
64  for(unsigned int i=0;i<reg.size();i++)
65  choices[i]= wxString::FromAscii((reg[i]->GetName()).c_str());
66  #if wxCHECK_VERSION( 2, 9, 4 )
67  wxSingleChoiceDialog dialog
68  (parent, wxString::FromAscii(message.c_str()),_T("Choose"),reg.size(),choices,(void**)NULL,wxOK | wxCANCEL);
69  #else
70  wxSingleChoiceDialog dialog
71  (parent, wxString::FromAscii(message.c_str()),_T("Choose"),reg.size(),choices,NULL,wxOK | wxCANCEL);
72  #endif
73  dialog.SetSize(300,300);
74  if(wxID_OK!=dialog.ShowModal()) return 0;
75  choice=dialog.GetSelection();
76  delete[] choices;
77  return reg[choice];
78 }
79 
80 template<class T> list<T *> WXDialogChooseMultipleFromVector(vector<T*> &reg,wxWindow*parent,
81  const string &message)
82 {
83  wxString *choices = new wxString[reg.size()];
84  for(unsigned int i=0;i<reg.size();i++)
85  choices[i]= wxString::FromAscii((reg[i]->GetName()).c_str());
86  wxMultiChoiceDialog_ListBox dialog
87  (parent, wxString::FromAscii(message.c_str()),_T("Choose"),reg.size(),choices);
88  dialog.ShowModal();
89  wxArrayInt choice=dialog.GetSelections();
90  list<T*> vChoice;
91  for(unsigned int i=0;i<choice.GetCount();++i) vChoice.push_back(reg[choice.Item(i)]);
92  delete[] choices;
93  return vChoice;
94 }
95 template<class T> list<T const*> WXDialogChooseMultipleFromVector(const vector<T*> &reg,wxWindow*parent,
96  const string &message)
97 {
98  wxString *choices = new wxString[reg.size()];
99  for(unsigned int i=0;i<reg.size();i++)
100  choices[i]= wxString::FromAscii((reg[i]->GetName()).c_str());
101  wxMultiChoiceDialog_ListBox dialog
102  (parent, wxString::FromAscii(message.c_str()),_T("Choose"),reg.size(),choices);
103  dialog.ShowModal();
104  wxArrayInt choice=dialog.GetSelections();
105  list<T const*> vChoice;
106  for(unsigned int i=0;i<choice.GetCount();++i) vChoice.push_back(reg[choice.Item(i)]);
107  delete[] choices;
108  return vChoice;
109 }
110 
111 // Compress a string by removing a given character
112 string CompressString(const string &s,const string &c)
113 {
114  string sc=s;
115  string::size_type idx=0;
116  while(idx!=string::npos)
117  {
118  idx=sc.find(c);
119  if(idx!=string::npos) sc.erase(idx,c.size());
120  }
121  return sc;
122 }
123 // Split
124 list<string> SplitString(const string &str, const string &separator)
125 {
126  string::size_type idx0=(string::size_type) 0;
127  string::size_type idx1=(string::size_type) 0;
128  list<string> l;
129  while((idx1!=string::npos)&&(idx0<str.size()))
130  {
131  idx1=str.find(separator,idx0);
132  if(idx1==string::npos) l.push_back(str.substr(idx0,idx1));
133  if(idx1>idx0) l.push_back(str.substr(idx0,idx1-idx0));
134  idx0=idx1+1;
135  }
136  //for(list<string>::const_iterator pos=l.begin();pos!=l.end();++pos) cout <<*pos<<" / ";
137  //cout<<endl;
138  return l;
139 }
140 
142 //
143 // WXMolScrolledWindow
144 //
146 WXMolScrolledWindow::WXMolScrolledWindow(wxWindow* parent, WXMolecule* pWXMol, long id):
147 wxGrid(parent,id),mpWXMolecule(pWXMol)
148 {}
149 WXMolScrolledWindow::~WXMolScrolledWindow()
150 {
151  mpWXMolecule->NotifyDeleteListWin(this);
152 }
154 //
155 // WXMolAtom
156 //
158 static const long ID_MOLATOM_SCATTPOW=WXCRYST_ID();
159 static const long ID_MOLATOM_NAME=WXCRYST_ID();
160 
161 BEGIN_EVENT_TABLE(WXMolAtom,wxWindow)
162  EVT_BUTTON(ID_MOLATOM_SCATTPOW, WXMolAtom::OnChangeScattPow)
163 END_EVENT_TABLE()
164 
165 WXMolAtom::WXMolAtom(wxWindow *parent, MolAtom*obj):
166 WXCrystObjBasic(parent),mpMolAtom(obj)
167 {
168  VFN_DEBUG_ENTRY("WXMolAtom::WXMolAtom():"<<obj->GetName(),6)
169  mpSizer=new wxBoxSizer(wxHORIZONTAL);
170  wxStaticText* label=new wxStaticText(this,-1,_T("Atom"));
171  mpSizer->Add(label);
172  {
173  mpFieldName=new WXFieldString(this, mpMolAtom->GetName(),ID_MOLATOM_NAME,80,true);
174  mpSizer->Add(mpFieldName,0,wxALIGN_CENTER);
175  mpFieldScattPower=new WXFieldChoice(this,ID_MOLATOM_SCATTPOW,"Type:",60);
176  mpSizer->Add(mpFieldScattPower,0,wxALIGN_CENTER);
177  mList.Add(mpFieldScattPower);
178  if(mpMolAtom->IsDummy())
179  mpFieldScattPower->SetValue("Dummy");
180  else
181  mpFieldScattPower->SetValue(mpMolAtom->GetScatteringPower().GetName());
182  }
183  {
184  WXCrystObjBasic* pFieldX=mpMolAtom->GetMolecule().GetPar(&(mpMolAtom->X())).WXCreate(this);
185  mpSizer->Add(pFieldX,0,wxALIGN_CENTER);
186  mList.Add(pFieldX);
187  }
188  {
189  WXCrystObjBasic* pFieldY=mpMolAtom->GetMolecule().GetPar(&(mpMolAtom->Y())).WXCreate(this);
190  mpSizer->Add(pFieldY,0,wxALIGN_CENTER);
191  mList.Add(pFieldY);
192  }
193  {
194  WXCrystObjBasic* pFieldZ=mpMolAtom->GetMolecule().GetPar(&(mpMolAtom->Z())).WXCreate(this);
195  mpSizer->Add(pFieldZ,0,wxALIGN_CENTER);
196  mList.Add(pFieldZ);
197  }
198 
199  this->SetSizer(mpSizer);
200  this->Layout();
201  this->CrystUpdate(true);
202  VFN_DEBUG_EXIT("WXMolAtom::WXMolAtom():"<<obj->GetName(),6)
203 }
204 
205 WXMolAtom::~WXMolAtom()
206 {
207  mpMolAtom->WXNotifyDelete();
208 }
209 
210 void WXMolAtom::CrystUpdate(const bool uui,const bool lock)
211 {
212  VFN_DEBUG_ENTRY("WXMolAtom::CrystUpdate()",5)
213  if(lock) mMutex.Lock();
214  mList.CrystUpdate(uui,false);
215  if(lock) mMutex.Unlock();
216  VFN_DEBUG_EXIT("WXMolAtom::CrystUpdate()",5)
217 }
218 
219 void WXMolAtom::UpdateUI(const bool lock)
220 {
221  VFN_DEBUG_ENTRY("WXMolAtom::UpdateUI()",5)
222  if(lock) mMutex.Lock();
223  mList.UpdateUI(false);
224  mpFieldName->SetValue(mpMolAtom->GetName().c_str());
225  if(mpMolAtom->IsDummy())
226  mpFieldScattPower->SetValue("Dummy");
227  else
228  mpFieldScattPower->SetValue(mpMolAtom->GetScatteringPower().GetName());
229  if(lock) mMutex.Unlock();
230  VFN_DEBUG_EXIT("WXMolAtom::UpdateUI()",5)
231 }
232 
233 void WXMolAtom::OnChangeScattPow(wxCommandEvent & WXUNUSED(event))
234 {
235  VFN_DEBUG_ENTRY("WXMolAtom::OnChangeScattPow()",6)
236  WXCrystValidateAllUserInput();
237  int choice;
238  const ScatteringPower *scatt=WXDialogChooseFromRegistry(
239  mpMolAtom->GetMolecule().GetCrystal().GetScatteringPowerRegistry(),
240  (wxWindow*)this,"Choose a new Scattering Power",choice);
241  if(0==scatt) return;
242  mpMolAtom->SetScatteringPower(*scatt);
243  this->CrystUpdate(true);
244  this->UpdateUI(true);
245  VFN_DEBUG_EXIT("WXMolAtom::OnChangeScattPow()",6)
246 }
248 //
249 // WXMolBond
250 //
252 WXCRYST_ID ID_MOLBOND_ATOM1;
253 WXCRYST_ID ID_MOLBOND_ATOM2;
254 WXCRYST_ID ID_MOLBOND_FREEBUTTON;
255 
256 BEGIN_EVENT_TABLE(WXMolBond,wxWindow)
257  EVT_BUTTON(ID_MOLBOND_ATOM1, WXMolBond::OnChangeAtom)
258  EVT_BUTTON(ID_MOLBOND_ATOM2, WXMolBond::OnChangeAtom)
259  EVT_CHECKBOX(ID_MOLBOND_FREEBUTTON, WXMolBond::OnToggleFree)
260 END_EVENT_TABLE()
261 
262 WXMolBond::WXMolBond(wxWindow *parent, MolBond*obj):
263 WXCrystObjBasic(parent),mpMolBond(obj),mpButtonFree(0)
264 {
265  VFN_DEBUG_ENTRY("WXMolBond::WXMolBond():"<<obj->GetName(),6)
266  mpSizer=new wxBoxSizer(wxHORIZONTAL);
267  #if 1
268  mpButtonFree=new wxCheckBox(this,ID_MOLBOND_FREEBUTTON,_T(""),wxDefaultPosition, wxDefaultSize);
269  mpButtonFree->Fit();
270  mpSizer->Add(mpButtonFree,0,wxALIGN_CENTER);
271  #endif
272  mpFieldAtom1=new WXFieldChoice(this,ID_MOLBOND_ATOM1,"Bond:",60);
273  mpFieldAtom1->SetValue(mpMolBond->GetAtom1().GetName());
274  mpSizer->Add(mpFieldAtom1,0,wxALIGN_CENTER);
275  mList.Add(mpFieldAtom1);
276 
277  mpFieldAtom2=new WXFieldChoice(this,ID_MOLBOND_ATOM2,"-",60);
278  mpFieldAtom2->SetValue(mpMolBond->GetAtom2().GetName());
279  mpSizer->Add(mpFieldAtom2,0,wxALIGN_CENTER);
280  mList.Add(mpFieldAtom2);
281 
282  WXFieldPar<REAL> *value=
283  new WXFieldPar<REAL>(this,"Length=",-1,&mValue);
284  mpSizer->Add(value,0,wxALIGN_CENTER);
285  mList.Add(value);
286 
287  WXFieldPar<REAL> *length=
288  new WXFieldPar<REAL>(this,",Restraint=",-1,&(mpMolBond->Length0()));
289  mpSizer->Add(length,0,wxALIGN_CENTER);
290  mList.Add(length);
291 
292  WXFieldPar<REAL> *delta=
293  new WXFieldPar<REAL>(this,",delta=",-1,&(mpMolBond->LengthDelta()));
294  mpSizer->Add(delta,0,wxALIGN_CENTER);
295  mList.Add(delta);
296 
297  WXFieldPar<REAL> *sigma=
298  new WXFieldPar<REAL>(this,",sigma=",-1,&(mpMolBond->LengthSigma()));
299  mpSizer->Add(sigma,0,wxALIGN_CENTER);
300  mList.Add(sigma);
301 
302  this->SetSizer(mpSizer);
303  this->Layout();
304  this->CrystUpdate(true,true);
305  VFN_DEBUG_EXIT("WXMolBond::WXMolBond():"<<obj->GetName(),6)
306 }
307 WXMolBond::~WXMolBond()
308 {
309  mpMolBond->WXNotifyDelete();
310 }
311 
312 void WXMolBond::CrystUpdate(const bool uui,const bool lock)
313 {
314  VFN_DEBUG_ENTRY("WXMolBond::CrystUpdate()",5)
315  if(lock) mMutex.Lock();
316  mValue=mpMolBond->GetLength();
317  mList.CrystUpdate(uui,false);
318  if(lock) mMutex.Unlock();
319  VFN_DEBUG_EXIT("WXMolBond::CrystUpdate()",5)
320 }
321 
322 void WXMolBond::UpdateUI(const bool lock)
323 {
324  VFN_DEBUG_ENTRY("WXMolBond::UpdateUI()",5)
325  if(lock) mMutex.Lock();
326  if(0!=mpButtonFree) mpButtonFree->SetValue(mpMolBond->IsFreeTorsion());
327  mList.UpdateUI(false);
328  mpFieldAtom1->SetValue(mpMolBond->GetAtom1().GetName().c_str());
329  mpFieldAtom2->SetValue(mpMolBond->GetAtom2().GetName().c_str());
330  if(lock) mMutex.Unlock();
331  VFN_DEBUG_EXIT("WXMolBond::UpdateUI()",5)
332 }
333 
334 void WXMolBond::OnChangeAtom(wxCommandEvent &event)
335 {
336  VFN_DEBUG_ENTRY("WXMolBond::OnChangeAtom()",6)
337  WXCrystValidateAllUserInput();
338  int choice;
339  MolAtom *const at=WXDialogChooseFromVector(mpMolBond->GetMolecule().GetAtomList(),
340  (wxWindow*)this,"Choose a new Atom",choice);
341  if(0==at) return;
342  if((long)ID_MOLBOND_ATOM1==event.GetId())
343  {
344  if(at==&(mpMolBond->GetAtom2()))
345  {
346  wxMessageDialog dumbUser(this,_T("The two atoms must be different !"),
347  _T("Whooops"),wxOK|wxICON_EXCLAMATION);
348  dumbUser.ShowModal();
349  return;
350  }
351  mpMolBond->SetAtom1(*at);
352  }
353  if((long)ID_MOLBOND_ATOM2==event.GetId())
354  {
355  if(at==&(mpMolBond->GetAtom1()))
356  {
357  wxMessageDialog dumbUser(this,_T("The two atoms must be different !"),
358  _T("Whooops"),wxOK|wxICON_EXCLAMATION);
359  dumbUser.ShowModal();
360  return;
361  }
362  mpMolBond->SetAtom2(*at);
363  }
364 
365  this->CrystUpdate(true);
366  this->UpdateUI(true);
367  VFN_DEBUG_EXIT("WXMolBond::OnChangeScattPow()",6)
368 }
369 
370 void WXMolBond::OnToggleFree(wxCommandEvent & WXUNUSED(event))
371 {
372  VFN_DEBUG_MESSAGE("WXMolBond::OnToggleFree()",6)
373  if(0!=mpButtonFree) mpMolBond->SetFreeTorsion(mpButtonFree->GetValue());
374 }
375 
377 //
378 // WXMolBondAngle
379 //
381 WXCRYST_ID ID_MOLBONDANGLE_ATOM1;
382 WXCRYST_ID ID_MOLBONDANGLE_ATOM2;
383 WXCRYST_ID ID_MOLBONDANGLE_ATOM3;
384 
385 BEGIN_EVENT_TABLE(WXMolBondAngle,wxWindow)
386  EVT_BUTTON(ID_MOLBONDANGLE_ATOM1, WXMolBondAngle::OnChangeAtom)
387  EVT_BUTTON(ID_MOLBONDANGLE_ATOM2, WXMolBondAngle::OnChangeAtom)
388  EVT_BUTTON(ID_MOLBONDANGLE_ATOM3, WXMolBondAngle::OnChangeAtom)
389 END_EVENT_TABLE()
390 
391 WXMolBondAngle::WXMolBondAngle(wxWindow *parent, MolBondAngle*obj):
392 WXCrystObjBasic(parent),mpMolBondAngle(obj)
393 {
394  VFN_DEBUG_ENTRY("WXMolBondAngle::WXMolBond():"<<obj->GetName(),6)
395  mpSizer=new wxBoxSizer(wxHORIZONTAL);
396 
397  mpFieldAtom1=new WXFieldChoice(this,ID_MOLBONDANGLE_ATOM1,"Bond Angle:",60);
398  mpFieldAtom1->SetValue(mpMolBondAngle->GetAtom1().GetName());
399  mpSizer->Add(mpFieldAtom1,0,wxALIGN_CENTER);
400  mList.Add(mpFieldAtom1);
401 
402  mpFieldAtom2=new WXFieldChoice(this,ID_MOLBONDANGLE_ATOM2,"-",60);
403  mpFieldAtom2->SetValue(mpMolBondAngle->GetAtom2().GetName());
404  mpSizer->Add(mpFieldAtom2,0,wxALIGN_CENTER);
405  mList.Add(mpFieldAtom2);
406 
407  mpFieldAtom3=new WXFieldChoice(this,ID_MOLBONDANGLE_ATOM3,"-",60);
408  mpFieldAtom3->SetValue(mpMolBondAngle->GetAtom3().GetName());
409  mpSizer->Add(mpFieldAtom3,0,wxALIGN_CENTER);
410  mList.Add(mpFieldAtom3);
411 
412  WXFieldPar<REAL> *value=
413  new WXFieldPar<REAL>(this,"Angle=",-1,&mValue);
414  value->SetHumanValueScale(RAD2DEG);
415  mpSizer->Add(value,0,wxALIGN_CENTER);
416  mList.Add(value);
417 
418  WXFieldPar<REAL> *angle=
419  new WXFieldPar<REAL>(this,",Restraint=",WXCRYST_ID(),&(mpMolBondAngle->Angle0()));
420  angle->SetHumanValueScale(RAD2DEG);
421  mpSizer->Add(angle,0,wxALIGN_CENTER);
422  mList.Add(angle);
423 
424  WXFieldPar<REAL> *delta=
425  new WXFieldPar<REAL>(this,",delta=",WXCRYST_ID(),&(mpMolBondAngle->AngleDelta()));
426  delta->SetHumanValueScale(RAD2DEG);
427  mpSizer->Add(delta,0,wxALIGN_CENTER);
428  mList.Add(delta);
429 
430  WXFieldPar<REAL> *sigma=
431  new WXFieldPar<REAL>(this,",sigma=",WXCRYST_ID(),&(mpMolBondAngle->AngleSigma()));
432  sigma->SetHumanValueScale(RAD2DEG);
433  mpSizer->Add(sigma,0,wxALIGN_CENTER);
434  mList.Add(sigma);
435 
436  this->SetSizer(mpSizer);
437  this->Layout();
438  this->CrystUpdate(true,true);
439  VFN_DEBUG_EXIT("WXMolBondAngle::WXMolBond():"<<obj->GetName(),6)
440 }
441 
443 {
444  mpMolBondAngle->WXNotifyDelete();
445 }
446 
447 void WXMolBondAngle::CrystUpdate(const bool uui,const bool lock)
448 {
449  VFN_DEBUG_ENTRY("WXMolBondAngle::CrystUpdate()",5)
450  if(lock) mMutex.Lock();
451  mValue=mpMolBondAngle->GetAngle();
452  mList.CrystUpdate(uui,false);
453  if(lock) mMutex.Unlock();
454  VFN_DEBUG_EXIT("WXMolBondAngle::CrystUpdate()",5)
455 }
456 
457 void WXMolBondAngle::UpdateUI(const bool lock)
458 {
459  VFN_DEBUG_ENTRY("WXMolBondAngle::UpdateUI()",5)
460  if(lock) mMutex.Lock();
461  mList.UpdateUI(false);
462  mpFieldAtom1->SetValue(mpMolBondAngle->GetAtom1().GetName().c_str());
463  mpFieldAtom2->SetValue(mpMolBondAngle->GetAtom2().GetName().c_str());
464  mpFieldAtom3->SetValue(mpMolBondAngle->GetAtom3().GetName().c_str());
465  if(lock) mMutex.Unlock();
466  VFN_DEBUG_EXIT("WXMolBondAngle::UpdateUI()",5)
467 }
468 
469 void WXMolBondAngle::OnChangeAtom(wxCommandEvent &event)
470 {
471  VFN_DEBUG_ENTRY("WXMolBondAngle::OnChangeAtom()",6)
472  WXCrystValidateAllUserInput();
473  int choice;
474  MolAtom *const at=WXDialogChooseFromVector(mpMolBondAngle->GetMolecule().GetAtomList(),
475  (wxWindow*)this,"Choose a new Atom",choice);
476  if(0==at) return;
477  if((long)ID_MOLBONDANGLE_ATOM1==event.GetId())
478  {
479  if((at==&(mpMolBondAngle->GetAtom2()) )||(at==&(mpMolBondAngle->GetAtom3())) )
480  {
481  wxMessageDialog dumbUser(this,_T("The three atoms must be different !"),
482  _T("Whooops"),wxOK|wxICON_EXCLAMATION);
483  dumbUser.ShowModal();
484  return;
485  }
486  mpMolBondAngle->SetAtom1(*at);
487  }
488  if((long)ID_MOLBONDANGLE_ATOM2==event.GetId())
489  {
490  if((at==&(mpMolBondAngle->GetAtom1()) )||(at==&(mpMolBondAngle->GetAtom3())) )
491  {
492  wxMessageDialog dumbUser(this,_T("The three atoms must be different !"),
493  _T("Whooops"),wxOK|wxICON_EXCLAMATION);
494  dumbUser.ShowModal();
495  return;
496  }
497  mpMolBondAngle->SetAtom2(*at);
498  }
499  if((long)ID_MOLBONDANGLE_ATOM3==event.GetId())
500  {
501  if((at==&(mpMolBondAngle->GetAtom1()) )||(at==&(mpMolBondAngle->GetAtom2())) )
502  {
503  wxMessageDialog dumbUser(this,_T("The three atoms must be different !"),
504  _T("Whooops"),wxOK|wxICON_EXCLAMATION);
505  dumbUser.ShowModal();
506  return;
507  }
508  mpMolBondAngle->SetAtom3(*at);
509  }
510 
511  this->CrystUpdate(true);
512  this->UpdateUI(true);
513  VFN_DEBUG_EXIT("WXMolBondAngle::OnChangeScattPow()",6)
514 }
516 //
517 // WXMolDihedralAngle
518 //
520 WXCRYST_ID ID_MOLDIHEDRALANGLE_ATOM1;
521 WXCRYST_ID ID_MOLDIHEDRALANGLE_ATOM2;
522 WXCRYST_ID ID_MOLDIHEDRALANGLE_ATOM3;
523 WXCRYST_ID ID_MOLDIHEDRALANGLE_ATOM4;
524 
525 BEGIN_EVENT_TABLE(WXMolDihedralAngle,wxWindow)
526  EVT_BUTTON(ID_MOLDIHEDRALANGLE_ATOM1, WXMolDihedralAngle::OnChangeAtom)
527  EVT_BUTTON(ID_MOLDIHEDRALANGLE_ATOM2, WXMolDihedralAngle::OnChangeAtom)
528  EVT_BUTTON(ID_MOLDIHEDRALANGLE_ATOM3, WXMolDihedralAngle::OnChangeAtom)
529  EVT_BUTTON(ID_MOLDIHEDRALANGLE_ATOM4, WXMolDihedralAngle::OnChangeAtom)
530 END_EVENT_TABLE()
531 
532 WXMolDihedralAngle::WXMolDihedralAngle(wxWindow *parent, MolDihedralAngle*obj):
533 WXCrystObjBasic(parent),mpMolDihedralAngle(obj)
534 {
535  VFN_DEBUG_ENTRY("WXMolDihedralAngle::WXMolBond()",6)
536  mpSizer=new wxBoxSizer(wxHORIZONTAL);
537 
538  mpFieldAtom1=new WXFieldChoice(this,ID_MOLDIHEDRALANGLE_ATOM1,"Dihedral Angle:",60);
539  mpFieldAtom1->SetValue(mpMolDihedralAngle->GetAtom1().GetName());
540  mpSizer->Add(mpFieldAtom1,0,wxALIGN_CENTER);
541  mList.Add(mpFieldAtom1);
542 
543  mpFieldAtom2=new WXFieldChoice(this,ID_MOLDIHEDRALANGLE_ATOM2,"-",60);
544  mpFieldAtom2->SetValue(mpMolDihedralAngle->GetAtom2().GetName());
545  mpSizer->Add(mpFieldAtom2,0,wxALIGN_CENTER);
546  mList.Add(mpFieldAtom2);
547 
548  mpFieldAtom3=new WXFieldChoice(this,ID_MOLDIHEDRALANGLE_ATOM3,"-",60);
549  mpFieldAtom3->SetValue(mpMolDihedralAngle->GetAtom3().GetName());
550  mpSizer->Add(mpFieldAtom3,0,wxALIGN_CENTER);
551  mList.Add(mpFieldAtom3);
552 
553  mpFieldAtom4=new WXFieldChoice(this,ID_MOLDIHEDRALANGLE_ATOM4,"-",60);
554  mpFieldAtom4->SetValue(mpMolDihedralAngle->GetAtom4().GetName());
555  mpSizer->Add(mpFieldAtom4,0,wxALIGN_CENTER);
556  mList.Add(mpFieldAtom4);
557 
558  WXFieldPar<REAL> *value=
559  new WXFieldPar<REAL>(this,"Angle=",-1,&mValue);
560  value->SetHumanValueScale(RAD2DEG);
561  mpSizer->Add(value,0,wxALIGN_CENTER);
562  mList.Add(value);
563 
564  WXFieldPar<REAL> *angle=
565  new WXFieldPar<REAL>(this,"Restraint:",-1,&(mpMolDihedralAngle->Angle0()));
566  angle->SetHumanValueScale(RAD2DEG);
567  mpSizer->Add(angle,0,wxALIGN_CENTER);
568  mList.Add(angle);
569 
570  WXFieldPar<REAL> *delta=
571  new WXFieldPar<REAL>(this,",delta=",-1,&(mpMolDihedralAngle->AngleDelta()));
572  delta->SetHumanValueScale(RAD2DEG);
573  mpSizer->Add(delta,0,wxALIGN_CENTER);
574  mList.Add(delta);
575 
576  WXFieldPar<REAL> *sigma=
577  new WXFieldPar<REAL>(this,",sigma=",-1,&(mpMolDihedralAngle->AngleSigma()));
578  sigma->SetHumanValueScale(RAD2DEG);
579  mpSizer->Add(sigma,0,wxALIGN_CENTER);
580  mList.Add(sigma);
581 
582  this->SetSizer(mpSizer);
583  this->Layout();
584  this->CrystUpdate(true);
585  VFN_DEBUG_EXIT("WXMolDihedralAngle::WXMolBond():"<<obj->GetName(),6)
586 }
587 
588 WXMolDihedralAngle::~WXMolDihedralAngle()
589 {
590  mpMolDihedralAngle->WXNotifyDelete();
591 }
592 
593 void WXMolDihedralAngle::CrystUpdate(const bool uui,const bool lock)
594 {
595  VFN_DEBUG_ENTRY("WXMolDihedralAngle::CrystUpdate()",5)
596  if(lock) mMutex.Lock();
597  mValue=mpMolDihedralAngle->GetAngle();
598  mList.CrystUpdate(uui,false);
599  if(lock) mMutex.Unlock();
600  VFN_DEBUG_EXIT("WXMolDihedralAngle::CrystUpdate()",5)
601 }
602 
603 void WXMolDihedralAngle::UpdateUI(const bool lock)
604 {
605  VFN_DEBUG_ENTRY("WXMolDihedralAngle::UpdateUI()",5)
606  if(lock) mMutex.Lock();
607  mList.UpdateUI(false);
608  mpFieldAtom1->SetValue(mpMolDihedralAngle->GetAtom1().GetName().c_str());
609  mpFieldAtom2->SetValue(mpMolDihedralAngle->GetAtom2().GetName().c_str());
610  mpFieldAtom3->SetValue(mpMolDihedralAngle->GetAtom3().GetName().c_str());
611  if(lock) mMutex.Unlock();
612  VFN_DEBUG_EXIT("WXMolDihedralAngle::UpdateUI()",5)
613 }
614 
615 void WXMolDihedralAngle::OnChangeAtom(wxCommandEvent &event)
616 {
617  VFN_DEBUG_ENTRY("WXMolDihedralAngle::OnChangeAtom()",6)
618  WXCrystValidateAllUserInput();
619  int choice;
620  MolAtom *const at=WXDialogChooseFromVector(mpMolDihedralAngle->GetMolecule().GetAtomList(),
621  (wxWindow*)this,"Choose a new Atom",choice);
622  if(0==at) return;
623  if((long)ID_MOLDIHEDRALANGLE_ATOM1==event.GetId())
624  {
625  if( (at==&(mpMolDihedralAngle->GetAtom2()))
626  ||(at==&(mpMolDihedralAngle->GetAtom3()))
627  ||(at==&(mpMolDihedralAngle->GetAtom4())) )
628  {
629  wxMessageDialog dumbUser(this,_T("The four atoms must be different !"),
630  _T("Whooops"),wxOK|wxICON_EXCLAMATION);
631  dumbUser.ShowModal();
632  return;
633  }
634  mpMolDihedralAngle->SetAtom1(*at);
635  }
636  if((long)ID_MOLDIHEDRALANGLE_ATOM2==event.GetId())
637  {
638  if( (at==&(mpMolDihedralAngle->GetAtom1()))
639  ||(at==&(mpMolDihedralAngle->GetAtom3()))
640  ||(at==&(mpMolDihedralAngle->GetAtom4())) )
641  {
642  wxMessageDialog dumbUser(this,_T("The four atoms must be different !"),
643  _T("Whooops"),wxOK|wxICON_EXCLAMATION);
644  dumbUser.ShowModal();
645  return;
646  }
647  mpMolDihedralAngle->SetAtom2(*at);
648  }
649  if((long)ID_MOLDIHEDRALANGLE_ATOM3==event.GetId())
650  {
651  if( (at==&(mpMolDihedralAngle->GetAtom1()))
652  ||(at==&(mpMolDihedralAngle->GetAtom2()))
653  ||(at==&(mpMolDihedralAngle->GetAtom4())) )
654  {
655  wxMessageDialog dumbUser(this,_T("The four atoms must be different !"),
656  _T("Whooops"),wxOK|wxICON_EXCLAMATION);
657  dumbUser.ShowModal();
658  return;
659  }
660  mpMolDihedralAngle->SetAtom3(*at);
661  }
662  if((long)ID_MOLDIHEDRALANGLE_ATOM4==event.GetId())
663  {
664  if( (at==&(mpMolDihedralAngle->GetAtom1()))
665  ||(at==&(mpMolDihedralAngle->GetAtom2()))
666  ||(at==&(mpMolDihedralAngle->GetAtom3())) )
667  {
668  wxMessageDialog dumbUser(this,_T("The four atoms must be different !"),
669  _T("Whooops"),wxOK|wxICON_EXCLAMATION);
670  dumbUser.ShowModal();
671  return;
672  }
673  mpMolDihedralAngle->SetAtom4(*at);
674  }
675 
676  this->CrystUpdate(true);
677  this->UpdateUI(true);
678  VFN_DEBUG_EXIT("WXMolDihedralAngle::OnChangeScattPow()",6)
679 }
680 
682 //
683 // WXMolecule Grid objects
684 //
686 WXMolecule::CellAtom::CellAtom():
687 mpAtom(0),mName(""),mpScatteringPower(0),mX(0),mY(0),mZ(0),mNeedUpdateUI(true)
688 {}
689 
690 WXMolecule::CellBond::CellBond():
691 mpBond(0),mAtom1(""),mAtom2(""),
692 mLength(0),mLength0(0),mSigma(0),mDelta(0),mNeedUpdateUI(true)
693 {}
694 
695 WXMolecule::CellBondAngle::CellBondAngle():
696 mpBondAngle(0),mAtom1(""),mAtom2(""),mAtom3(""),
697 mAngle(0),mAngle0(0),mSigma(0),mDelta(0),mNeedUpdateUI(true)
698 {}
699 
700 WXMolecule::CellDihedralAngle::CellDihedralAngle():
701 mpDihedralAngle(0),mAtom1(""),mAtom2(""),mAtom3(""),mAtom4(""),
702 mAngle(0),mAngle0(0),mSigma(0),mDelta(0),mNeedUpdateUI(true)
703 {}
704 
705 WXMolecule::CellRigidGroup::CellRigidGroup():
706 mpGroup(0),mNeedUpdateUI(false)
707 {}
708 
709 
711 //
712 // WXMolecule
713 //
715 
716 WXCRYST_ID ID_MENU_OPTIMIZECONFORMATION;
717 WXCRYST_ID ID_MENU_SETLIMITS;
718 WXCRYST_ID ID_MOLECULE_MENU_FILE;
719 WXCRYST_ID ID_MOLECULE_MENU_FILE_2ZMATRIX;
720 WXCRYST_ID ID_MOLECULE_MENU_FILE_2ZMATRIXNAMED;
721 WXCRYST_ID ID_MOLECULE_MENU_PAR_MDTEST;
722 WXCRYST_ID ID_MOLECULE_MENU_FORMULA;
723 WXCRYST_ID ID_MOLECULE_MENU_FORMULA_OPTIMIZECONFORMATION;
724 WXCRYST_ID ID_MOLECULE_MENU_FORMULA_STATUS;
725 WXCRYST_ID ID_MOLECULE_MENU_EXPORT_RESTRAINTS;
726 WXCRYST_ID ID_MOLECULE_MENU_FORMULA_ADD_ATOM;
727 WXCRYST_ID ID_MOLECULE_MENU_FORMULA_ADD_BOND;
728 WXCRYST_ID ID_MOLECULE_MENU_FORMULA_ADD_ANGLE;
729 WXCRYST_ID ID_MOLECULE_MENU_FORMULA_ADD_DIHEDRAL;
730 WXCRYST_ID ID_MOLECULE_MENU_FORMULA_ADD_RIGID_GROUP;
731 WXCRYST_ID ID_MOLECULE_MENU_FORMULA_ADD_NONFLIP_ATOM;
732 WXCRYST_ID ID_MOLECULE_MENU_FORMULA_RIGIDIFY_WITH_DIHEDRALANGLES;
733 WXCRYST_ID ID_MOLECULE_MENU_FORMULA_TEST;
734 WXCRYST_ID ID_MOLECULE_MENU_FORMULA_REMOVE_ATOM;
735 WXCRYST_ID ID_MOLECULE_MENU_FORMULA_REMOVE_BOND;
736 WXCRYST_ID ID_MOLECULE_MENU_FORMULA_REMOVE_ANGLE;
737 WXCRYST_ID ID_MOLECULE_MENU_FORMULA_REMOVE_DIHEDRAL;
738 WXCRYST_ID ID_MOLECULE_MENU_FORMULA_REMOVE_RIGID_GROUP;
739 WXCRYST_ID ID_MOLECULE_MENU_FORMULA_REMOVE_NONFLIPATOM;
740 WXCRYST_ID ID_MOLECULE_MENU_FORMULA_SHOW_RESTRAINT;
741 WXCRYST_ID ID_MOLECULE_MENU_FORMULA_SET_DELTA_SIGMA;
742 WXCRYST_ID ID_MOLECULE_MENU_GEOMETRY;
743 WXCRYST_ID ID_MOLECULE_MENU_GEOMETRY_ROTATE_BOND;
744 WXCRYST_ID ID_MOLECULE_MENU_GEOMETRY_ROTATE_DIHED;
745 
746 WXCRYST_ID ID_MOLECULE_CHANGE_CENTER_ATOM;
747 
748 
749 WXCRYST_ID ID_WINDOW_ATOM;
750 WXCRYST_ID ID_WINDOW_BONDLENGTH;
751 WXCRYST_ID ID_WINDOW_BONDANGLE;
752 WXCRYST_ID ID_WINDOW_DIHEDRALANGLE;
753 WXCRYST_ID ID_WINDOW_RIGIDGROUP;
754 WXCRYST_ID ID_WINDOW_NONFLIPATOM;
755 
756 BEGIN_EVENT_TABLE(WXMolecule,wxWindow)
757  EVT_BUTTON(ID_WXOBJ_COLLAPSE, WXCrystObj::OnToggleCollapse)
758  EVT_MENU(ID_REFOBJ_MENU_PAR_FIXALL, WXRefinableObj::OnMenuFixAllPar)
759  EVT_MENU(ID_REFOBJ_MENU_PAR_UNFIXALL, WXRefinableObj::OnMenuUnFixAllPar)
760  EVT_MENU(ID_REFOBJ_MENU_PAR_RANDOMIZE, WXRefinableObj::OnMenuParRandomize)
761  EVT_MENU(ID_MOLECULE_MENU_PAR_MDTEST, WXMolecule::OnMenuMDTest)
762  EVT_MENU(ID_MOLECULE_MENU_FORMULA_OPTIMIZECONFORMATION,WXMolecule::OnMenuOptimizeConformation)
763  EVT_MENU(ID_MOLECULE_MENU_FORMULA_STATUS, WXMolecule::OnMenuPrintRestraintStatus)
764  EVT_MENU(ID_MOLECULE_MENU_EXPORT_RESTRAINTS, WXMolecule::OnMenuExportRestraints)
765  EVT_MENU(ID_MOLECULE_MENU_FORMULA_ADD_ATOM, WXMolecule::OnMenuAddAtom)
766  EVT_MENU(ID_MOLECULE_MENU_FORMULA_ADD_BOND, WXMolecule::OnMenuAddBond)
767  EVT_MENU(ID_MOLECULE_MENU_FORMULA_ADD_ANGLE, WXMolecule::OnMenuAddAngle)
768  EVT_MENU(ID_MOLECULE_MENU_FORMULA_ADD_DIHEDRAL, WXMolecule::OnMenuAddDihedralAngle)
769  EVT_MENU(ID_MOLECULE_MENU_FORMULA_ADD_RIGID_GROUP, WXMolecule::OnMenuAddRigidGroup)
770  EVT_MENU(ID_MOLECULE_MENU_FORMULA_ADD_NONFLIP_ATOM, WXMolecule::OnMenuAddNonFlipAtom)
771  EVT_MENU(ID_MOLECULE_MENU_FORMULA_RIGIDIFY_WITH_DIHEDRALANGLES,WXMolecule::OnMenuRigidfyWithDihedralAngles)
772  EVT_MENU(ID_MOLECULE_MENU_FORMULA_REMOVE_ATOM, WXMolecule::OnMenuRemoveAtom)
773  EVT_MENU(ID_MOLECULE_MENU_FORMULA_REMOVE_BOND, WXMolecule::OnMenuRemoveBond)
774  EVT_MENU(ID_MOLECULE_MENU_FORMULA_REMOVE_ANGLE, WXMolecule::OnMenuRemoveAngle)
775  EVT_MENU(ID_MOLECULE_MENU_FORMULA_REMOVE_DIHEDRAL, WXMolecule::OnMenuRemoveDihedralAngle)
776  EVT_MENU(ID_MOLECULE_MENU_FORMULA_REMOVE_RIGID_GROUP, WXMolecule::OnMenuRemoveRigidGroup)
777  EVT_MENU(ID_MOLECULE_MENU_FORMULA_REMOVE_NONFLIPATOM, WXMolecule::OnMenuRemoveNonFlipAtom)
778  EVT_MENU(ID_MOLECULE_MENU_FORMULA_TEST , WXMolecule::OnMenuTest)
779  EVT_MENU(ID_MENU_SETLIMITS, WXMolecule::OnMenuSetLimits)
780  EVT_MENU(ID_MOLECULE_MENU_FORMULA_SHOW_RESTRAINT, WXMolecule::OnMenuShowRestraintWindow)
781  EVT_MENU(ID_MOLECULE_MENU_FORMULA_SET_DELTA_SIGMA ,WXMolecule::OnMenuSetDeltaSigma)
782  EVT_MENU(ID_MOLECULE_MENU_FILE_2ZMATRIX, WXMolecule::OnMenuExport2ZMatrix)
783  EVT_MENU(ID_MOLECULE_MENU_FILE_2ZMATRIXNAMED, WXMolecule::OnMenuExport2ZMatrix)
784  EVT_MENU(ID_MOLECULE_MENU_GEOMETRY_ROTATE_BOND, WXMolecule::OnMenuRotate)
785  EVT_MENU(ID_MOLECULE_MENU_GEOMETRY_ROTATE_DIHED, WXMolecule::OnMenuRotate)
786  EVT_GRID_CMD_CELL_CHANGED(ID_WINDOW_ATOM, WXMolecule::OnEditGridAtom)
787  EVT_GRID_CMD_CELL_CHANGED(ID_WINDOW_BONDLENGTH, WXMolecule::OnEditGridBondLength)
788  EVT_GRID_CMD_CELL_CHANGED(ID_WINDOW_BONDANGLE, WXMolecule::OnEditGridBondAngle)
789  EVT_GRID_CMD_CELL_CHANGED(ID_WINDOW_DIHEDRALANGLE, WXMolecule::OnEditGridDihedralAngle)
790  EVT_GRID_CMD_CELL_CHANGED(ID_WINDOW_RIGIDGROUP, WXMolecule::OnEditGridRigidGroup)
791  EVT_BUTTON(ID_MOLECULE_CHANGE_CENTER_ATOM, WXMolecule::OnChangeCenterAtom)
792 END_EVENT_TABLE()
793 
794 WXMolecule::WXMolecule(wxWindow *parent, Molecule *mol):
795 WXScatterer(parent,mol),mpMolecule(mol),
796 mpBondWin(0),mpAngleWin(0),mpDihedralAngleWin(0),mpRigidGroupWin(0),mpNonFlipAtomWin(0),mIsSelfUpdating(false)
797 {
798  VFN_DEBUG_ENTRY("WXMolecule::WXMolecule():"<<mol->GetName(),6)
799  //Menus
800  mpMenuBar->AddMenu("File",ID_MOLECULE_MENU_FILE);
801  mpMenuBar->AddMenuItem(ID_MOLECULE_MENU_FILE,ID_MOLECULE_MENU_FILE_2ZMATRIX,"Export to Fenske-Hall Z-Matrix");
802  mpMenuBar->AddMenuItem(ID_MOLECULE_MENU_FILE,ID_MOLECULE_MENU_FILE_2ZMATRIXNAMED,"Export to Z-Matrix with atom names");
803  mpMenuBar->AddMenu("Parameters",ID_REFOBJ_MENU_PAR);
804  mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_PAR,ID_REFOBJ_MENU_PAR_FIXALL,"Fix all");
805  mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_PAR,ID_REFOBJ_MENU_PAR_UNFIXALL,"Unfix all");
806  mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_PAR,ID_REFOBJ_MENU_PAR_RANDOMIZE,
807  "Randomize Configuration");
808  mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_PAR,ID_MOLECULE_MENU_PAR_MDTEST,
809  "Test Molecular Dynamics moves for 30s");
810  mpMenuBar->AddMenu("Formula && Restraints",ID_MOLECULE_MENU_FORMULA);
811  mpMenuBar->AddMenuItem(ID_MOLECULE_MENU_FORMULA,ID_MOLECULE_MENU_FORMULA_OPTIMIZECONFORMATION,
812  "Optimize Starting Conformation");
813  mpMenuBar->AddMenuItem(ID_MOLECULE_MENU_FORMULA,ID_MOLECULE_MENU_FORMULA_SET_DELTA_SIGMA,
814  "Set Restraints delta && sigma for all bonds && angles");
815  mpMenuBar->AddMenuItem(ID_MOLECULE_MENU_FORMULA,ID_MOLECULE_MENU_FORMULA_STATUS,
816  "Print Detailed Restraint Values");
817  mpMenuBar->AddMenuItem(ID_MOLECULE_MENU_FORMULA,ID_MOLECULE_MENU_EXPORT_RESTRAINTS,
818  "Export Restraints in CVS File format");
819  mpMenuBar->GetMenu(ID_MOLECULE_MENU_FORMULA).AppendSeparator();
820  mpMenuBar->AddMenuItem(ID_MOLECULE_MENU_FORMULA,ID_MOLECULE_MENU_FORMULA_ADD_ATOM,
821  "Add an Atom");
822  mpMenuBar->AddMenuItem(ID_MOLECULE_MENU_FORMULA,ID_MOLECULE_MENU_FORMULA_ADD_BOND,
823  "Add Bond Restraint");
824  mpMenuBar->AddMenuItem(ID_MOLECULE_MENU_FORMULA,ID_MOLECULE_MENU_FORMULA_ADD_ANGLE,
825  "Add Bond Angle Restraint");
826  mpMenuBar->AddMenuItem(ID_MOLECULE_MENU_FORMULA,ID_MOLECULE_MENU_FORMULA_ADD_DIHEDRAL,
827  "Add Dihedral Angle Restraint");
828  mpMenuBar->AddMenuItem(ID_MOLECULE_MENU_FORMULA,ID_MOLECULE_MENU_FORMULA_ADD_RIGID_GROUP,
829  "Add Rigid Group");
830  mpMenuBar->AddMenuItem(ID_MOLECULE_MENU_FORMULA,ID_MOLECULE_MENU_FORMULA_ADD_NONFLIP_ATOM,
831  "Add Non-Flip (optically active) Atom");
832  mpMenuBar->AddMenuItem(ID_MOLECULE_MENU_FORMULA,ID_MOLECULE_MENU_FORMULA_RIGIDIFY_WITH_DIHEDRALANGLES,
833  "Rigidify with Dihedral Angles");
834  mpMenuBar->GetMenu(ID_MOLECULE_MENU_FORMULA).AppendSeparator();
835  mpMenuBar->AddMenuItem(ID_MOLECULE_MENU_FORMULA,ID_MOLECULE_MENU_FORMULA_REMOVE_ATOM,
836  "Remove an Atom");
837  mpMenuBar->AddMenuItem(ID_MOLECULE_MENU_FORMULA,ID_MOLECULE_MENU_FORMULA_REMOVE_BOND,
838  "Remove a Bond Restraint");
839  mpMenuBar->AddMenuItem(ID_MOLECULE_MENU_FORMULA,ID_MOLECULE_MENU_FORMULA_REMOVE_ANGLE,
840  "Remove a Bond Angle Restraint");
841  mpMenuBar->AddMenuItem(ID_MOLECULE_MENU_FORMULA,ID_MOLECULE_MENU_FORMULA_REMOVE_DIHEDRAL,
842  "Remove a Dihedral Angle Restraint");
843  mpMenuBar->AddMenuItem(ID_MOLECULE_MENU_FORMULA,ID_MOLECULE_MENU_FORMULA_REMOVE_RIGID_GROUP,
844  "Remove Rigid Group");
845  mpMenuBar->AddMenuItem(ID_MOLECULE_MENU_FORMULA,ID_MOLECULE_MENU_FORMULA_REMOVE_NONFLIPATOM,
846  "Remove Non-Flip (optically active) Atom");
847 
848  mpMenuBar->GetMenu(ID_MOLECULE_MENU_FORMULA).AppendSeparator();
849  mpMenuBar->AddMenuItem(ID_MOLECULE_MENU_FORMULA,ID_MOLECULE_MENU_FORMULA_SHOW_RESTRAINT,
850  "Show Restraint Window");
851  //#ifdef __DEBUG__
852  mpMenuBar->AddMenuItem(ID_MOLECULE_MENU_FORMULA,ID_MOLECULE_MENU_FORMULA_TEST,"Debug Test");
853  //#endif
854  mpMenuBar->AddMenu("Manipulate Geometry",ID_MOLECULE_MENU_GEOMETRY);
855  mpMenuBar->AddMenuItem(ID_MOLECULE_MENU_GEOMETRY,ID_MOLECULE_MENU_GEOMETRY_ROTATE_BOND,
856  "Rotate around bond");
857  mpMenuBar->AddMenuItem(ID_MOLECULE_MENU_GEOMETRY,ID_MOLECULE_MENU_GEOMETRY_ROTATE_DIHED,
858  "Set dihedral angle");
859  //mpSizer->SetItemMinSize(mpMenuBar,
860  // mpMenuBar->GetSize().GetWidth(),
861  // mpMenuBar->GetSize().GetHeight());
862  WXFieldPar<REAL> *pLLKScale= new WXFieldPar<REAL>(this,"Log(likelihood) scale",-1,&(mpMolecule->mLogLikelihoodScale));
863  mList.Add(pLLKScale);
864  mpSizer->Add(pLLKScale,0,wxALIGN_LEFT);
865  pLLKScale->SetToolTip(_T("The log(likelihood) of the molecule, i.e. the sum\n")
866  _T("of the restraints costs for all bonds and angles \n")
867  _T("are multiplied by this scale.\n\n")
868  _T("The default value is 1.\n\n")
869  _T("Multiplying this value by 4 is equivalent to dividing the\n")
870  _T("sigma of all bonds and angles by a factor 2.\n")
871  _T("This can be increased if the molecule presents too\n")
872  _T("much distortion.\n\n")
873  _T("Note that a too large value (e.g.>100) will decrease the\n")
874  _T("convergence speed of the algorithm, as distortion of the\n")
875  _T("structure is necessary for an efficient minimisation."));
876 
877  // Molecular Dynamics move parameters
878  wxBoxSizer* pMDSizer=new wxBoxSizer(wxHORIZONTAL);
879  WXFieldPar<REAL> *pWXFieldMDEnergy=
880  new WXFieldPar<REAL>(this,"MD moves Energy",-1,&(mpMolecule->mMDMoveEnergy));
881  WXFieldPar<REAL> *pWXFieldMDFrequency=
882  new WXFieldPar<REAL>(this,"MD moves frequency",-1,&(mpMolecule->mMDMoveFreq));
883  pMDSizer->Add(pWXFieldMDFrequency);
884  pMDSizer->Add(pWXFieldMDEnergy);
885  mpSizer->Add(pMDSizer,0,wxALIGN_LEFT);
886  mList.Add(pWXFieldMDEnergy);
887  mList.Add(pWXFieldMDFrequency);
888 
889  pWXFieldMDFrequency->SetToolTip(_T("Frequency of Molecular Dynamics Moves (0.0-1.0)\n\n")
890  _T("MD moves are used to alter the conformation of atom groups \n")
891  _T("which cannot be changed by simple bond distance\n")
892  _T("or bond angle changes.\n\n")
893  _T("MD moves are CPU intensive, so a slow value (0.05) is recommended\n")
894  _T("Larger frequencies can be used for constrained molecules,\n")
895  _T("e.g. with large, flexible cycles."));
896  pWXFieldMDEnergy->SetToolTip(_T("Energy of Molecule for Molecular Dynamics Moves\n\n")
897  _T("Standard amplitude=40. \n")
898  _T("Small amplitude=10. (small distortion of the Molecule)\n")
899  _T("Large amplitude=400. (large distortion of the Molecule)"));
900  //Center atom
901  mpFieldCenterAtom=new WXFieldChoice(this,ID_MOLECULE_CHANGE_CENTER_ATOM,"Center Atom:",240);
902  if(mpMolecule->GetCenterAtom()!=0)
903  mpFieldCenterAtom->SetValue(mpMolecule->GetCenterAtom()->GetName());
904  else mpFieldCenterAtom->SetValue("Click to choose an atom !");
905  mpSizer->Add(mpFieldCenterAtom,0,wxALIGN_LEFT);
906  mList.Add(mpFieldCenterAtom);
907  // Atom list
908  wxGridCellAttr* cellAttrName = new wxGridCellAttr;
909  cellAttrName->SetRenderer(new wxGridCellStringRenderer);
910  cellAttrName->SetEditor(new wxGridCellTextEditor);
911  wxGridCellAttr* cellAttrFloat = new wxGridCellAttr;
912  cellAttrFloat->SetRenderer(new wxGridCellFloatRenderer(6,3));
913  cellAttrFloat->SetEditor(new wxGridCellFloatEditor(6,3));
914 
915  mpAtomWin= new WXMolScrolledWindow(this,this,ID_WINDOW_ATOM);
916  //mpAtomWin->SetSize(800,300);
917  mpAtomWin->EnableScrolling(true,true);
918  //mpAtomWin->SetSizeHints(-1,300,-1,300);
919  mpAtomWin->CreateGrid(0,6);
920  mpAtomWin->SetRowLabelSize(40);
921  mpAtomWin->SetDefaultColSize(60);
922  mpAtomWin->SetColAttr(0,cellAttrName);
923  mpAtomWin->SetColAttr(1,cellAttrName->Clone());
924  mpAtomWin->SetColAttr(2,cellAttrFloat);
925  mpAtomWin->SetColAttr(3,cellAttrFloat->Clone());
926  mpAtomWin->SetColAttr(4,cellAttrFloat->Clone());
927  mpAtomWin->SetColAttr(5,cellAttrFloat->Clone());
928  mpAtomWin->SetColLabelValue(0,_T("Name"));
929  mpAtomWin->SetColLabelValue(1,_T("Type"));
930  mpAtomWin->SetColLabelValue(2,_T("X"));
931  mpAtomWin->SetColLabelValue(3,_T("Y"));
932  mpAtomWin->SetColLabelValue(4,_T("Z"));
933  mpAtomWin->SetColLabelValue(5,_T("Occup"));
934  mpAtomWin->AutoSizeRows();
935  mpSizer->Add(mpAtomWin,0,wxALIGN_LEFT);
936  this->CrystUpdate(true);
937  VFN_DEBUG_EXIT("WXMolecule::WXMolecule():"<<mol->GetName(),6)
938 }
939 
940 WXMolecule::~WXMolecule()
941 {
942  VFN_DEBUG_ENTRY("WXMolecule::~WXMolecule()",10)
943  if(0!=mpBondWin) mpBondWin->GetParent()->Destroy();
944  VFN_DEBUG_EXIT("WXMolecule::~WXMolecule()",10)
945 }
946 
947 void WXMolecule::OnMenuOptimizeConformation(wxCommandEvent & WXUNUSED(event))
948 {
949  VFN_DEBUG_ENTRY("WXMolecule::OnMenuOptimizeConformation()",5)
951  mpMolecule->OptimizeConformation(20000,mpMolecule->GetAtomList().size());
952  mpMolecule->OptimizeConformationSteepestDescent(0.01,100);
953  mpMolecule->RestraintStatus(cout);
954 
955  LSQNumObj lsq;
956  lsq.SetRefinedObj(*mpMolecule);
957  lsq.PrepareRefParList(true);
958  lsq.SetParIsUsed(gpRefParTypeObjCryst,false);
959  lsq.SetParIsUsed(gpRefParTypeScattConform,true);
960  try {lsq.Refine(10,true,false);}
961  catch(const ObjCrystException &except){}
962  mpMolecule->GetCrystal().UpdateDisplay();
963  mpMolecule->RestraintStatus(cout);
964 
965  mpMolecule->GetCrystal().UpdateDisplay();
966 
967  VFN_DEBUG_EXIT("WXMolecule::OnMenuOptimizeConformation()",5)
968 }
969 void WXMolecule::OnMenuExportRestraints(wxCommandEvent & WXUNUSED(event))
970 {
971  VFN_DEBUG_ENTRY("WXMolecule::OnMenuExportRestraints()",5)
973 
974  stringstream ss;
975  mpMolecule->RestraintExport(ss);
976 
977  wxFileDialog open(this,_T("Choose File to save restraints:"),
978  _T(""),_T(""),_T("*.csv"), wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
979  if(open.ShowModal() != wxID_OK) return;
980  wxString name=open.GetPath();
981  if(name.substr(name.size()-4,4)!=_T(".csv"))
982  {
983  cout<<name<<" -> "<<name+_T(".csv")<<endl;
984  name=name+_T(".csv");
985  }
986 
987  wxFileOutputStream ostream(name.c_str());
988  ostream.Write(ss.str().c_str(),ss.str().size());
989 
990  VFN_DEBUG_EXIT("WXMolecule::OnMenuExportRestraints()",5)
991 }
992 void WXMolecule::OnMenuPrintRestraintStatus(wxCommandEvent & WXUNUSED(event))
993 {
994  VFN_DEBUG_ENTRY("WXMolecule::OnMenuPrintRestraintStatus()",5)
996  mpMolecule->RestraintStatus(cout);
997  VFN_DEBUG_EXIT("WXMolecule::OnMenuPrintRestraintStatus()",5)
998 }
999 
1000 void WXMolecule::OnMenuAddAtom(wxCommandEvent & WXUNUSED(event))
1001 {
1002  VFN_DEBUG_ENTRY("WXMolecule::OnMenuAddAtom()",6)
1004  int choice;
1005  const ScatteringPower *scatt=WXDialogChooseFromRegistry(
1006  mpMolecule->GetCrystal().GetScatteringPowerRegistry(),
1007  (wxWindow*)this,"Choose a new Scattering Power",choice);
1008  if(0==scatt) return;
1009  long num=mpMolecule->GetAtomList().size();
1010  if(num>0)
1011  {
1012  wxString lastAtom=wxString::FromAscii(mpMolecule->GetAtom(num-1).GetName().c_str());
1013  for(;;)
1014  {
1015  if(lastAtom.size()==0) break;
1016  if(lastAtom.IsNumber())
1017  {
1018  lastAtom.ToLong(&num);
1019  break;
1020  }
1021  lastAtom.erase(0,1);
1022  }
1023  }
1024  stringstream st;
1025  st<<num+1;
1026  mpMolecule->AddAtom(0.,0.,0.,scatt,scatt->GetName()+st.str());
1027  VFN_DEBUG_EXIT("WXMolecule::OnMenuAddAtom()",6)
1028 }
1029 
1030 void WXMolecule::OnMenuAddBond(wxCommandEvent & WXUNUSED(event))
1031 {
1032  VFN_DEBUG_ENTRY("WXMolecule::OnMenuAddBond()",6)
1034  int choice;
1035  vector<MolAtom*> v=mpMolecule->GetAtomList();
1036  MolAtom *at1=WXDialogChooseFromVector(v,
1037  (wxWindow*)this,"Choose the first Atom",choice);
1038  if(0==at1) return;
1039  MolAtom *at2=WXDialogChooseFromVector(v,
1040  (wxWindow*)this,"Choose the second Atom",choice);
1041  if(0==at2) return;
1042 
1043  if(at1==at2)
1044  {
1045  wxMessageDialog dumbUser(this,_T("The two atoms must be different !"),
1046  _T("Whooops"),wxOK|wxICON_EXCLAMATION);
1047  dumbUser.ShowModal();
1048  return;
1049  }
1050  static double d=1.5;//static so that last entered value will be used next time
1051  wxString s;
1052  s.Printf(_T("%6.3f"),d);
1053  // if((at1->IsDummy())||(at2->IsDummy())) d=1.5;
1054  // else d= (at1->GetScatteringPower().GetRadius()+at2->GetScatteringPower().GetRadius())*0.9;
1055  string mes="Enter bond distance (Angstroems) for "+at1->GetName()+"-"+at2->GetName();
1056  wxTextEntryDialog dialog(this,wxString::FromAscii(mes.c_str()),
1057  _T("Bond distance"),s,wxOK | wxCANCEL);
1058  dialog.SetTextValidator(wxTextValidator(wxFILTER_NUMERIC));
1059  if(wxID_OK!=dialog.ShowModal())
1060  {
1061  VFN_DEBUG_EXIT("WXMolecule::OnMenuAddBond():Canceled",6)
1062  return;
1063  }
1064  dialog.GetValue().ToDouble(&d);
1065 
1066  mpMolecule->AddBond(*at1,*at2,d,.01,.02,1.);
1067  VFN_DEBUG_EXIT("WXMolecule::OnMenuAddBond()",6)
1068 }
1069 
1070 void WXMolecule::OnMenuAddAngle(wxCommandEvent & WXUNUSED(event))
1071 {
1072  VFN_DEBUG_ENTRY("WXMolecule::OnMenuAddBond()",6)
1074  int choice;
1075  vector<MolAtom*> v=mpMolecule->GetAtomList();
1076  MolAtom *at1=WXDialogChooseFromVector(v,
1077  (wxWindow*)this,"Choose the first Atom",choice);
1078  if(0==at1) return;
1079  MolAtom *at2=WXDialogChooseFromVector(v,
1080  (wxWindow*)this,"Choose the second Atom",choice);
1081  if(0==at2) return;
1082 
1083  MolAtom *at3=WXDialogChooseFromVector(v,
1084  (wxWindow*)this,"Choose the third Atom",choice);
1085  if(0==at2) return;
1086 
1087  if( (at1==at2) || (at1==at3) ||(at2==at3))
1088  {
1089  wxMessageDialog dumbUser(this,_T("The three atoms must be different !"),
1090  _T("Whooops"),wxOK|wxICON_EXCLAMATION);
1091  dumbUser.ShowModal();
1092  return;
1093  }
1094 
1095  static double a=109.5;//static so that last entered value will be used next time
1096  wxString s;
1097  s.Printf(_T("%6.2f"),a);
1098  string mes="Enter bond angle (degrees) for "+at1->GetName()
1099  +"-"+at2->GetName()
1100  +"-"+at3->GetName();
1101  wxTextEntryDialog dialog(this,wxString::FromAscii(mes.c_str()),
1102  _T("Bond angle"),s,wxOK | wxCANCEL);
1103  dialog.SetTextValidator(wxTextValidator(wxFILTER_NUMERIC));
1104  if(wxID_OK!=dialog.ShowModal())
1105  {
1106  VFN_DEBUG_EXIT("WXMolecule::OnMenuAddAngle():Canceled",6)
1107  return;
1108  }
1109  dialog.GetValue().ToDouble(&a);
1110 
1111  mpMolecule->AddBondAngle(*at1,*at2,*at3,a*DEG2RAD,.01,0.02);
1112  VFN_DEBUG_EXIT("WXMolecule::OnMenuAddBond()",6)
1113 }
1114 
1115 void WXMolecule::OnMenuAddDihedralAngle(wxCommandEvent & WXUNUSED(event))
1116 {
1117  VFN_DEBUG_ENTRY("WXMolecule::OnMenuAddDihedralAngle()",6)
1119  int choice;
1120  vector<MolAtom*> v=mpMolecule->GetAtomList();
1121  MolAtom *at1=WXDialogChooseFromVector(v,
1122  (wxWindow*)this,"Choose the first Atom",choice);
1123  if(0==at1) return;
1124  MolAtom *at2=WXDialogChooseFromVector(v,
1125  (wxWindow*)this,"Choose the second Atom",choice);
1126  if(0==at2) return;
1127 
1128  MolAtom *at3=WXDialogChooseFromVector(v,
1129  (wxWindow*)this,"Choose the third Atom",choice);
1130  if(0==at3) return;
1131 
1132  MolAtom *at4=WXDialogChooseFromVector(v,
1133  (wxWindow*)this,"Choose the fourth Atom",choice);
1134  if(0==at4) return;
1135 
1136  if( (at1==at2) || (at1==at3) || (at1==at4) || (at2==at3) || (at2==at4) || (at3==at4))
1137  {
1138  wxMessageDialog dumbUser(this,_T("The atoms must be different !"),
1139  _T("Whooops"),wxOK|wxICON_EXCLAMATION);
1140  dumbUser.ShowModal();
1141  return;
1142  }
1143 
1144  static double a=180;
1145  wxString s;
1146  s.Printf(_T("%6.2f"),a);
1147  string mes="Enter dihedral angle (degrees) for "+at1->GetName()
1148  +"-"+at2->GetName()
1149  +"-"+at3->GetName()
1150  +"-"+at4->GetName();
1151  wxTextEntryDialog dialog(this,_T("Enter dihedral angle (degrees)"),
1152  _T("Bond angle"),s,wxOK | wxCANCEL);
1153  dialog.SetTextValidator(wxTextValidator(wxFILTER_NUMERIC));
1154  if(wxID_OK!=dialog.ShowModal())
1155  {
1156  VFN_DEBUG_EXIT("WXMolecule::OnMenuAddDihedralAngle():Canceled",6)
1157  return;
1158  }
1159  dialog.GetValue().ToDouble(&a);
1160 
1161  mpMolecule->AddDihedralAngle(*at1,*at2,*at3,*at4,a*DEG2RAD,.01,.02);
1162  VFN_DEBUG_EXIT("WXMolecule::OnMenuAddDihedralAngle()",6)
1163 }
1164 
1165 void WXMolecule::OnMenuAddRigidGroup(wxCommandEvent & WXUNUSED(event))
1166 {
1167  VFN_DEBUG_ENTRY("WXMolecule::OnMenuAddRigidGroup()",6)
1169  list<MolAtom*> l=WXDialogChooseMultipleFromVector(mpMolecule->GetAtomList(),this,
1170  "Choose atoms in the rigid group");
1171  RigidGroup s;
1172  for(list<MolAtom*>::const_iterator pos=l.begin();pos!=l.end();++pos) s.insert(*pos);
1173  mpMolecule->AddRigidGroup(s);
1174  VFN_DEBUG_EXIT("WXMolecule::OnMenuAddRigidGroup()",6)
1175 }
1176 
1177 void WXMolecule::OnMenuAddNonFlipAtom(wxCommandEvent & WXUNUSED(event))
1178 {
1179  VFN_DEBUG_ENTRY("WXMolecule::OnMenuAddNonFlipAtom()",6)
1181  int choice;
1182  vector<MolAtom*> v;
1183  for(vector<MolAtom*>::const_iterator pos=mpMolecule->GetAtomList().begin();pos!=mpMolecule->GetAtomList().end();++pos)
1184  {
1185  if((*pos)->IsNonFlipAtom()==false) v.push_back(*pos);
1186  }
1187 
1188  MolAtom *at1=WXDialogChooseFromVector(v,
1189  (wxWindow*)this,"Choose the Optically active Atom",choice);
1190 
1191  if(0==at1) {
1192  wxMessageDialog dumbUser(this,_T("No atom selected !"),
1193  _T("Whooops"),wxOK|wxICON_EXCLAMATION);
1194  dumbUser.ShowModal();
1195  return;
1196  }
1197 
1198  at1->SetNonFlipAtom(true);
1199  this->CrystUpdate(true);
1200  VFN_DEBUG_EXIT("WXMolecule::OnMenuAddNonFlipAtom()",6)
1201 }
1202 
1203 void WXMolecule::OnMenuRemoveAtom(wxCommandEvent & WXUNUSED(event))
1204 {
1205  VFN_DEBUG_ENTRY("WXMolecule::OnMenuRemoveAtom()",6)
1207  vector<MolAtom*> v=mpMolecule->GetAtomList();
1208  list<MolAtom*> vAt=WXDialogChooseMultipleFromVector(v,(wxWindow*)this,
1209  "Choose the Atom(s) to be removed");
1210  if(0==vAt.size()) return;
1211  for(list<MolAtom*>::iterator pos=vAt.begin();pos!=vAt.end();++pos) mpMolecule->RemoveAtom(**pos);
1212  this->CrystUpdate(true);
1213  VFN_DEBUG_EXIT("WXMolecule::OnMenuRemoveAtom()",6)
1214 }
1215 
1216 void WXMolecule::OnMenuRemoveBond(wxCommandEvent & WXUNUSED(event))
1217 {
1218  VFN_DEBUG_ENTRY("WXMolecule::OnMenuRemoveBond()",6)
1220  vector<MolBond*> v=mpMolecule->GetBondList();
1221  list<MolBond*> vBond=WXDialogChooseMultipleFromVector(v,(wxWindow*)this,
1222  "Choose the Bond(s) to be removed");
1223  if(0==vBond.size()) return;
1224  const int answer =wxMessageBox
1225  (_T("Remove Bond and Dihedral Angles involving the deleted Bond(s) (if any) ?"),
1226  _T("Delete related Restraints ?"),wxYES_NO, this);
1227  for(list<MolBond*>::iterator pos=vBond.begin();pos!=vBond.end();++pos)
1228  {
1229  if(answer==wxYES)
1230  {
1231  const MolAtom *pAtom1= &((*pos)->GetAtom1());
1232  const MolAtom *pAtom2= &((*pos)->GetAtom2());
1233  for(vector<MolBondAngle*>::iterator posb=mpMolecule->GetBondAngleList().begin();
1234  posb!=mpMolecule->GetBondAngleList().end();)
1235  {
1236  if( ( (pAtom1==&((*posb)->GetAtom1())) && (pAtom2==&((*posb)->GetAtom2())) )
1237  ||( (pAtom1==&((*posb)->GetAtom2())) && (pAtom2==&((*posb)->GetAtom1())) )
1238  ||( (pAtom1==&((*posb)->GetAtom2())) && (pAtom2==&((*posb)->GetAtom3())) )
1239  ||( (pAtom1==&((*posb)->GetAtom3())) && (pAtom2==&((*posb)->GetAtom2())) ))
1240  posb=mpMolecule->RemoveBondAngle(**posb);
1241  else ++posb;
1242  }
1243  for(vector<MolDihedralAngle*>::iterator posb=mpMolecule->GetDihedralAngleList().begin();
1244  posb!=mpMolecule->GetDihedralAngleList().end();)
1245  {
1246  if( ( (pAtom1==&((*posb)->GetAtom1())) && (pAtom2==&((*posb)->GetAtom2())) )
1247  ||( (pAtom1==&((*posb)->GetAtom2())) && (pAtom2==&((*posb)->GetAtom1())) )
1248  ||( (pAtom1==&((*posb)->GetAtom2())) && (pAtom2==&((*posb)->GetAtom3())) )
1249  ||( (pAtom1==&((*posb)->GetAtom3())) && (pAtom2==&((*posb)->GetAtom2())) )
1250  ||( (pAtom1==&((*posb)->GetAtom3())) && (pAtom2==&((*posb)->GetAtom4())) )
1251  ||( (pAtom1==&((*posb)->GetAtom4())) && (pAtom2==&((*posb)->GetAtom3())) ))
1252  posb=mpMolecule->RemoveDihedralAngle(**posb);
1253  else ++posb;
1254  }
1255  }
1256  mpMolecule->RemoveBond(**pos);
1257  }
1258  this->CrystUpdate(true);
1259  VFN_DEBUG_EXIT("WXMolecule::OnMenuRemoveBond()",6)
1260 }
1261 
1262 void WXMolecule::OnMenuRemoveAngle(wxCommandEvent & WXUNUSED(event))
1263 {
1264  VFN_DEBUG_ENTRY("WXMolecule::OnMenuRemoveAngle()",6)
1266  vector<MolBondAngle*> v=mpMolecule->GetBondAngleList();
1267  list<MolBondAngle*> vAngle=WXDialogChooseMultipleFromVector(v,(wxWindow*)this,
1268  "Choose the Bond Angle(s) to be removed");
1269  if(0==vAngle.size()) return;
1270  for(list<MolBondAngle*>::iterator pos=vAngle.begin();pos!=vAngle.end();++pos)
1271  mpMolecule->RemoveBondAngle(**pos);
1272  this->CrystUpdate(true);
1273  VFN_DEBUG_EXIT("WXMolecule::OnMenuRemoveAngle()",6)
1274 }
1275 
1276 void WXMolecule::OnMenuRemoveDihedralAngle(wxCommandEvent & WXUNUSED(event))
1277 {
1278  VFN_DEBUG_ENTRY("WXMolecule::OnMenuRemoveDihedralAngle()",6)
1280  vector<MolDihedralAngle*> v=mpMolecule->GetDihedralAngleList();
1281  list<MolDihedralAngle*> vAngle=WXDialogChooseMultipleFromVector(v,(wxWindow*)this,
1282  "Choose the Dihedral Angle(s) to be removed");
1283  if(0==vAngle.size()) return;
1284  for(list<MolDihedralAngle*>::iterator pos=vAngle.begin();pos!=vAngle.end();++pos)
1285  mpMolecule->RemoveDihedralAngle(**pos);
1286  this->CrystUpdate(true);
1287  VFN_DEBUG_EXIT("WXMolecule::OnMenuRemoveDihedralAngle()",6)
1288 }
1289 
1290 void WXMolecule::OnMenuRemoveNonFlipAtom(wxCommandEvent & WXUNUSED(event))
1291 {
1292  VFN_DEBUG_ENTRY("WXMolecule::OnMenuRemoveNonFlipAtom()",6)
1294  int choice;
1295  vector<MolAtom*> v;
1296  for(vector<MolAtom*>::const_iterator pos=mpMolecule->GetAtomList().begin();pos!=mpMolecule->GetAtomList().end();++pos)
1297  {
1298  if((*pos)->IsNonFlipAtom()) v.push_back(*pos);
1299  }
1300 
1301  if(v.size()==0) {
1302  wxMessageDialog dumbUser(this,_T("The list of optically active atoms is empty !"),
1303  _T("Whooops"),wxOK|wxICON_EXCLAMATION);
1304  dumbUser.ShowModal();
1305  return;
1306  }
1307  MolAtom *at1=WXDialogChooseFromVector(v, (wxWindow*)this,"Choose the Optically active Atom to be removed",choice);
1308  if(0==at1) {
1309  wxMessageDialog dumbUser(this,_T("No atom selected !"),
1310  _T("Whooops"),wxOK|wxICON_EXCLAMATION);
1311  dumbUser.ShowModal();
1312  return;
1313  }
1314 
1315  at1->SetNonFlipAtom(false);
1316  this->CrystUpdate(true);
1317  VFN_DEBUG_EXIT("WXMolecule::OnMenuRemoveNonFlipAtom()",6)
1318 }
1319 
1320 void WXMolecule::OnMenuRemoveRigidGroup(wxCommandEvent & WXUNUSED(event))
1321 {
1322  VFN_DEBUG_ENTRY("WXMolecule::OnMenuRemoveRigidGroup()",6)
1324  vector<RigidGroup*> v=mpMolecule->GetRigidGroupList();
1325  list<RigidGroup*> vGroup=WXDialogChooseMultipleFromVector(v,(wxWindow*)this,
1326  "Choose the Rigid Group(s) to be removed");
1327  if(0==vGroup.size()) return;
1328  for(list<RigidGroup*>::iterator pos=vGroup.begin();pos!=vGroup.end();++pos)
1329  mpMolecule->RemoveRigidGroup(**pos);
1330  this->CrystUpdate(true);
1331  VFN_DEBUG_EXIT("WXMolecule::OnMenuRemoveRigidGroup()",6)
1332 }
1333 /*
1334 void WXMolecule::OnMenuRemoveFlipGroup(wxCommandEvent & WXUNUSED(event))
1335 {
1336  VFN_DEBUG_ENTRY("WXMolecule::OnMenuRemoveFlipGroup()",6)
1337  WXCrystValidateAllUserInput();
1338  mpMolecule->BuildFlipGroup();
1339  list<Molecule::FlipGroup> v = mpMolecule->GetFlipGroupList();
1340 
1341  wxString *choices = new wxString[v.size()];
1342  int i=0;
1343  for(list<Molecule::FlipGroup>::iterator pos=v.begin();pos!=v.end();++pos) {
1344  if(pos->mvRotatedChainList.begin()->first==pos->mpAtom0) {
1345  choices[i] = pos->mpAtom0->GetName();
1346  choices[i] += ": ";
1347  choices[i] += pos->mpAtom1->GetName();
1348  choices[i] += " <-> ";
1349  choices[i] += pos->mpAtom2->GetName();
1350  } else {
1351  choices[i] = pos->mpAtom0->GetName();
1352  for(list<pair<const MolAtom *,set<MolAtom*> > >::const_iterator chain=pos->mvRotatedChainList.begin(); chain!=pos->mvRotatedChainList.end();++chain) {
1353  choices[i] += chain->first->GetName();
1354  choices[i] += " <-> ";
1355  }
1356  choices[i].Remove(choices[i].size()-5, choices[i].size());
1357  }
1358  i++;
1359  }
1360 
1361  wxMultiChoiceDialog_ListBox dialog ((wxWindow*)this, "Choose the Flip Group(s) to be removed",_T("Choose"),v.size(),choices);
1362  dialog.ShowModal();
1363  wxArrayInt choice=dialog.GetSelections();
1364 
1365  delete[] choices;
1366 
1367  this->CrystUpdate(true);
1368  VFN_DEBUG_EXIT("WXMolecule::OnMenuRemoveFlipGroup()",6)
1369 }
1370 */
1371 void WXMolecule::OnEditGridAtom(wxGridEvent &e)
1372 {
1373  if(mIsSelfUpdating) return;
1374  VFN_DEBUG_ENTRY("WXMolecule::OnEditGridAtom():"<<e.GetRow()<<","<<e.GetCol(),10)
1376  const long r=e.GetRow();
1377  const long c=e.GetCol();
1378  if(c==0)
1379  {
1380  wxString s=mpAtomWin->GetCellValue(r,c);
1381  if(s!=_T(""))
1382  mpMolecule->GetAtomList()[r]->SetName(string(s.ToAscii()));
1383  }
1384  if(c==1)
1385  {
1386  wxString s=mpAtomWin->GetCellValue(r,c);
1387  if(s!=_T(""))
1388  {
1389  try
1390  {
1391  long p=mpMolecule->GetCrystal().GetScatteringPowerRegistry().Find(string(s.ToAscii()));
1392  if(p>=0) mpMolecule->GetAtomList()[r]->SetScatteringPower(
1393  mpMolecule->GetCrystal().GetScatteringPowerRegistry().GetObj(p));
1394  }
1395  catch(ObjCrystException){};
1396  }
1397  }
1398  if(c==2)
1399  {
1400  wxString s=mpAtomWin->GetCellValue(r,c);
1401  if(s!=_T(""))
1402  {
1403  double d;
1404  if(s.ToDouble(&d))
1405  mpMolecule->GetAtomList()[r]->SetX(d);
1406  }
1407  }
1408  if(c==3)
1409  {
1410  wxString s=mpAtomWin->GetCellValue(r,c);
1411  if(s!=_T(""))
1412  {
1413  double d;
1414  if(s.ToDouble(&d))
1415  mpMolecule->GetAtomList()[r]->SetY(d);
1416  }
1417  }
1418  if(c==4)
1419  {
1420  wxString s=mpAtomWin->GetCellValue(r,c);
1421  if(s!=_T(""))
1422  {
1423  double d;
1424  if(s.ToDouble(&d))
1425  mpMolecule->GetAtomList()[r]->SetZ(d);
1426  }
1427  }
1428  if(c==5)
1429  {
1430  wxString s=mpAtomWin->GetCellValue(r,c);
1431  if(s!=_T(""))
1432  {
1433  double d;
1434  if(s.ToDouble(&d))
1435  {
1436  if(d>1)d=1;
1437  else if(d<0)d=0;
1438  mpMolecule->GetAtomList()[r]->SetOccupancy(d);
1439  }
1440  }
1441  }
1442  mpMolecule->GetCrystal().UpdateDisplay();
1443  VFN_DEBUG_EXIT("WXMolecule::OnEditGridAtom():"<<e.GetRow()<<","<<e.GetCol(),10)
1444 }
1445 
1446 void WXMolecule::OnEditGridBondLength(wxGridEvent &e)
1447 {
1448  if(mIsSelfUpdating) return;
1449  VFN_DEBUG_ENTRY("WXMolecule::OnEditGridBondLength():"<<e.GetRow()<<","<<e.GetCol(),10)
1451  const long r=e.GetRow();
1452  const long c=e.GetCol();
1453  if(c==0)
1454  {
1455  wxString s=mpBondWin->GetCellValue(r,c);
1456  vector<MolAtom*>::reverse_iterator at=mpMolecule->FindAtom(string(s.ToAscii()));
1457  if(at!=mpMolecule->GetAtomList().rend())
1458  {
1459  if(*at!=&(mpMolecule->GetBondList()[r]->GetAtom2()))
1460  mpMolecule->GetBondList()[r]->SetAtom1(**at);
1461  else
1462  mpBondWin->SetCellValue(r,c,wxString::FromAscii(mpMolecule->GetBondList()[r]->GetAtom1().GetName().c_str()));
1463  }
1464  else
1465  mpBondWin->SetCellValue(r,c,wxString::FromAscii(mpMolecule->GetBondList()[r]->GetAtom1().GetName().c_str()));
1466  }
1467  if(c==1)
1468  {
1469  wxString s=mpBondWin->GetCellValue(r,c);
1470  vector<MolAtom*>::reverse_iterator at=mpMolecule->FindAtom(string(s.ToAscii()));
1471  if(at!=mpMolecule->GetAtomList().rend())
1472  {
1473  if(*at!=&(mpMolecule->GetBondList()[r]->GetAtom1()))
1474  mpMolecule->GetBondList()[r]->SetAtom2(**at);
1475  else
1476  mpBondWin->SetCellValue(r,c,wxString::FromAscii(mpMolecule->GetBondList()[r]->GetAtom2().GetName().c_str()));
1477  }
1478  else
1479  mpBondWin->SetCellValue(r,c,wxString::FromAscii(mpMolecule->GetBondList()[r]->GetAtom2().GetName().c_str()));
1480  }
1481  if(c==3)
1482  {
1483  wxString s=mpBondWin->GetCellValue(r,c);
1484  if(s!=_T(""))
1485  {
1486  double d;
1487  if(s.ToDouble(&d))
1488  if(d>0) mpMolecule->GetBondList()[r]->SetLength0(d);
1489  }
1490  }
1491  if(c==4)
1492  {
1493  wxString s=mpBondWin->GetCellValue(r,c);
1494  if(s!=_T(""))
1495  {
1496  double d;
1497  if(s.ToDouble(&d))
1498  if(d>0) mpMolecule->GetBondList()[r]->SetLengthSigma(d);
1499  }
1500  }
1501  if(c==5)
1502  {
1503  wxString s=mpBondWin->GetCellValue(r,c);
1504  if(s!=_T(""))
1505  {
1506  double d;
1507  if(s.ToDouble(&d))
1508  if(d>0) mpMolecule->GetBondList()[r]->SetLengthDelta(d);
1509  }
1510  }
1511  this->CrystUpdate(true);
1512  VFN_DEBUG_EXIT("WXMolecule::OnEditGridBondLength():"<<e.GetRow()<<","<<e.GetCol(),10)
1513 }
1514 
1515 void WXMolecule::OnEditGridBondAngle(wxGridEvent &e)
1516 {
1517  if(mIsSelfUpdating) return;
1518  VFN_DEBUG_ENTRY("WXMolecule::OnEditGridBondAngle():"<<e.GetRow()<<","<<e.GetCol(),10)
1520  const long r=e.GetRow();
1521  const long c=e.GetCol();
1522  if(c==0)
1523  {
1524  wxString s=mpAngleWin->GetCellValue(r,c);
1525  vector<MolAtom*>::reverse_iterator at=mpMolecule->FindAtom(string(s.ToAscii()));
1526  if(at!=mpMolecule->GetAtomList().rend())
1527  {
1528  if( (*at!=&(mpMolecule->GetBondAngleList()[r]->GetAtom2()))
1529  &&(*at!=&(mpMolecule->GetBondAngleList()[r]->GetAtom3())))
1530  mpMolecule->GetBondAngleList()[r]->SetAtom1(**at);
1531  else
1532  mpAngleWin->SetCellValue(r,c,wxString::FromAscii(mpMolecule->GetBondAngleList()[r]->GetAtom1().GetName().c_str()));
1533  }
1534  else
1535  mpAngleWin->SetCellValue(r,c,wxString::FromAscii(mpMolecule->GetBondAngleList()[r]->GetAtom1().GetName().c_str()));
1536  }
1537  if(c==1)
1538  {
1539  wxString s=mpAngleWin->GetCellValue(r,c);
1540  vector<MolAtom*>::reverse_iterator at=mpMolecule->FindAtom(string(s.ToAscii()));
1541  if(at!=mpMolecule->GetAtomList().rend())
1542  {
1543  if( (*at!=&(mpMolecule->GetBondAngleList()[r]->GetAtom1()))
1544  &&(*at!=&(mpMolecule->GetBondAngleList()[r]->GetAtom3())))
1545  mpMolecule->GetBondAngleList()[r]->SetAtom2(**at);
1546  else
1547  mpAngleWin->SetCellValue(r,c,wxString::FromAscii(mpMolecule->GetBondAngleList()[r]->GetAtom2().GetName().c_str()));
1548  }
1549  else
1550  mpAngleWin->SetCellValue(r,c,wxString::FromAscii(mpMolecule->GetBondAngleList()[r]->GetAtom2().GetName().c_str()));
1551  }
1552  if(c==2)
1553  {
1554  wxString s=mpAngleWin->GetCellValue(r,c);
1555  vector<MolAtom*>::reverse_iterator at=mpMolecule->FindAtom(string(s.ToAscii()));
1556  if(at!=mpMolecule->GetAtomList().rend())
1557  {
1558  if( (*at!=&(mpMolecule->GetBondAngleList()[r]->GetAtom1()))
1559  &&(*at!=&(mpMolecule->GetBondAngleList()[r]->GetAtom2())))
1560  mpMolecule->GetBondAngleList()[r]->SetAtom3(**at);
1561  else
1562  mpAngleWin->SetCellValue(r,c,wxString::FromAscii(mpMolecule->GetBondAngleList()[r]->GetAtom3().GetName().c_str()));
1563  }
1564  else
1565  mpAngleWin->SetCellValue(r,c,wxString::FromAscii(mpMolecule->GetBondAngleList()[r]->GetAtom2().GetName().c_str()));
1566  }
1567  if(c==4)
1568  {
1569  wxString s=mpAngleWin->GetCellValue(r,c);
1570  if(s!=_T(""))
1571  {
1572  double d;
1573  if(s.ToDouble(&d))
1574  if(d>0) mpMolecule->GetBondAngleList()[r]->SetAngle0(d*DEG2RAD);
1575  }
1576  }
1577  if(c==5)
1578  {
1579  wxString s=mpAngleWin->GetCellValue(r,c);
1580  if(s!=_T(""))
1581  {
1582  double d;
1583  if(s.ToDouble(&d))
1584  if(d>0) mpMolecule->GetBondAngleList()[r]->SetAngleSigma(d*DEG2RAD);
1585  }
1586  }
1587  if(c==6)
1588  {
1589  wxString s=mpAngleWin->GetCellValue(r,c);
1590  if(s!=_T(""))
1591  {
1592  double d;
1593  if(s.ToDouble(&d))
1594  if(d>0) mpMolecule->GetBondAngleList()[r]->SetAngleDelta(d*DEG2RAD);
1595  }
1596  }
1597  this->CrystUpdate(true);
1598  VFN_DEBUG_EXIT("WXMolecule::OnEditGridBondAngle():"<<e.GetRow()<<","<<e.GetCol(),10)
1599 }
1600 
1601 void WXMolecule::OnEditGridDihedralAngle(wxGridEvent &e)
1602 {
1603  if(mIsSelfUpdating) return;
1604  VFN_DEBUG_ENTRY("WXMolecule::OnEditGridDihedralAngle():"<<e.GetRow()<<","<<e.GetCol(),10)
1606  const long r=e.GetRow();
1607  const long c=e.GetCol();
1608  if(c==0)
1609  {
1610  wxString s=mpDihedralAngleWin->GetCellValue(r,c);
1611  vector<MolAtom*>::reverse_iterator at=mpMolecule->FindAtom(string(s.ToAscii()));
1612  if(at!=mpMolecule->GetAtomList().rend())
1613  {
1614  if( (*at!=&(mpMolecule->GetDihedralAngleList()[r]->GetAtom2()))
1615  &&(*at!=&(mpMolecule->GetDihedralAngleList()[r]->GetAtom3())))
1616  mpMolecule->GetDihedralAngleList()[r]->SetAtom1(**at);
1617  else
1618  mpDihedralAngleWin->SetCellValue(r,c,wxString::FromAscii(mpMolecule->GetDihedralAngleList()[r]->GetAtom1().GetName().c_str()));
1619  }
1620  else
1621  mpDihedralAngleWin->SetCellValue(r,c,wxString::FromAscii(mpMolecule->GetDihedralAngleList()[r]->GetAtom1().GetName().c_str()));
1622  }
1623  if(c==1)
1624  {
1625  wxString s=mpDihedralAngleWin->GetCellValue(r,c);
1626  vector<MolAtom*>::reverse_iterator at=mpMolecule->FindAtom(string(s.ToAscii()));
1627  if(at!=mpMolecule->GetAtomList().rend())
1628  {
1629  if( (*at!=&(mpMolecule->GetDihedralAngleList()[r]->GetAtom1()))
1630  &&(*at!=&(mpMolecule->GetDihedralAngleList()[r]->GetAtom3())))
1631  mpMolecule->GetDihedralAngleList()[r]->SetAtom2(**at);
1632  else
1633  mpDihedralAngleWin->SetCellValue(r,c,wxString::FromAscii(mpMolecule->GetDihedralAngleList()[r]->GetAtom2().GetName().c_str()));
1634  }
1635  else
1636  mpDihedralAngleWin->SetCellValue(r,c,wxString::FromAscii(mpMolecule->GetDihedralAngleList()[r]->GetAtom2().GetName().c_str()));
1637  }
1638  if(c==2)
1639  {
1640  wxString s=mpDihedralAngleWin->GetCellValue(r,c);
1641  vector<MolAtom*>::reverse_iterator at=mpMolecule->FindAtom(string(s.ToAscii()));
1642  if(at!=mpMolecule->GetAtomList().rend())
1643  {
1644  if( (*at!=&(mpMolecule->GetDihedralAngleList()[r]->GetAtom1()))
1645  &&(*at!=&(mpMolecule->GetDihedralAngleList()[r]->GetAtom2())))
1646  mpMolecule->GetDihedralAngleList()[r]->SetAtom3(**at);
1647  else
1648  mpDihedralAngleWin->SetCellValue(r,c,wxString::FromAscii(mpMolecule->GetDihedralAngleList()[r]->GetAtom3().GetName().c_str()));
1649  }
1650  else
1651  mpDihedralAngleWin->SetCellValue(r,c,wxString::FromAscii(mpMolecule->GetDihedralAngleList()[r]->GetAtom3().GetName().c_str()));
1652  }
1653  if(c==3)
1654  {
1655  wxString s=mpDihedralAngleWin->GetCellValue(r,c);
1656  vector<MolAtom*>::reverse_iterator at=mpMolecule->FindAtom(string(s.ToAscii()));
1657  if(at!=mpMolecule->GetAtomList().rend())
1658  {
1659  if( (*at!=&(mpMolecule->GetDihedralAngleList()[r]->GetAtom1()))
1660  &&(*at!=&(mpMolecule->GetDihedralAngleList()[r]->GetAtom2())))
1661  mpMolecule->GetDihedralAngleList()[r]->SetAtom4(**at);
1662  else
1663  mpDihedralAngleWin->SetCellValue(r,c,wxString::FromAscii(mpMolecule->GetDihedralAngleList()[r]->GetAtom4().GetName().c_str()));
1664  }
1665  else
1666  mpDihedralAngleWin->SetCellValue(r,c,wxString::FromAscii(mpMolecule->GetDihedralAngleList()[r]->GetAtom4().GetName().c_str()));
1667  }
1668  if(c==5)
1669  {
1670  wxString s=mpDihedralAngleWin->GetCellValue(r,c);
1671  if(s!=_T(""))
1672  {
1673  double d;
1674  if(s.ToDouble(&d))
1675  mpMolecule->GetDihedralAngleList()[r]->SetAngle0(d*DEG2RAD);
1676  }
1677  }
1678  if(c==6)
1679  {
1680  wxString s=mpDihedralAngleWin->GetCellValue(r,c);
1681  if(s!=_T(""))
1682  {
1683  double d;
1684  if(s.ToDouble(&d))
1685  if(d>0) mpMolecule->GetDihedralAngleList()[r]->SetAngleSigma(d*DEG2RAD);
1686  }
1687  }
1688  if(c==7)
1689  {
1690  wxString s=mpDihedralAngleWin->GetCellValue(r,c);
1691  if(s!=_T(""))
1692  {
1693  double d;
1694  if(s.ToDouble(&d))
1695  if(d>0) mpMolecule->GetDihedralAngleList()[r]->SetAngleDelta(d*DEG2RAD);
1696  }
1697  }
1698  this->CrystUpdate(true);
1699  VFN_DEBUG_EXIT("WXMolecule::OnEditGridDihedralAngle():"<<e.GetRow()<<","<<e.GetCol(),10)
1700 }
1701 
1702 void WXMolecule::OnEditGridRigidGroup(wxGridEvent &e)
1703 {
1704  if(mIsSelfUpdating) return;
1705  VFN_DEBUG_ENTRY("WXMolecule::OnEditGridRigidGroup():"<<e.GetRow()<<","<<e.GetCol(),10)
1707 
1708  const long r=e.GetRow();
1709  const long c=e.GetCol();
1710  wxString s=mpRigidGroupWin->GetCellValue(r,c);
1711  list<string> l=SplitString(CompressString(string(s.ToAscii())," "),",");
1712  RigidGroup rg;
1713  for(list<string>::const_iterator pos=l.begin();pos!=l.end();++pos)
1714  {
1715  vector<MolAtom*>::reverse_iterator rpos=mpMolecule->FindAtom(*pos);
1716  if(rpos!=mpMolecule->GetAtomList().rend()) rg.insert(*rpos);
1717  else cout<<*pos<<" : NOT FOUND"<<endl;;
1718  }
1719  set<MolAtom *> *pold=(set<MolAtom *>*) mpMolecule->GetRigidGroupList()[r];
1720  set<MolAtom *> *pnew=(set<MolAtom *>*) &rg;
1721 
1722  if( *pold != *pnew)
1723  {
1724  *pold = *pnew;
1725  mpMolecule->GetRigidGroupClock().Click();
1726  }
1727  this->CrystUpdate(true);
1728  VFN_DEBUG_EXIT("WXMolecule::OnEditGridRigidGroup():"<<e.GetRow()<<","<<e.GetCol(),10)
1729 }
1730 
1731 void WXMolecule::OnMenuExport2ZMatrix(wxCommandEvent &event)
1732 {
1733  VFN_DEBUG_MESSAGE("WXMolecule::OnMenuExport2ZMatrix()",6)
1734  const vector<MolZAtom> *pz=&(mpMolecule->AsZMatrix(true));
1735 
1736  if(event.GetId()==ID_MOLECULE_MENU_FILE_2ZMATRIX)
1737  {
1738  wxFileDialog open(this,_T("Choose a file to save the Z-matrix to"),_T(""),_T(""),_T("*.fhz"),
1739  wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
1740  if(open.ShowModal() != wxID_OK) return;
1741  ofstream fout (open.GetPath().ToAscii());
1742  fout.imbue(std::locale::classic());
1743  if(fout)
1744  {
1745  wxString tmp;
1746 
1747  fout<<mpMolecule->GetName()<<endl<<pz->size()<<endl;
1748  long i=0;
1749  for(vector<MolZAtom>::const_iterator pos=pz->begin();pos!=pz->end();++pos)
1750  {
1751  tmp.Printf(_T("%-2s %2lu"),pos->mpPow->GetSymbol().c_str(),pos->mBondAtom+1);
1752  fout<<tmp;
1753  if(i>0)
1754  {
1755  fout<<FormatFloat(pos->mBondLength,6,3);;
1756  if(i>1)
1757  {
1758  tmp.Printf(_T(" %2lu"),pos->mBondAngleAtom+1);
1759  fout<<tmp<<FormatFloat(pos->mBondAngle*RAD2DEG,8,3);;
1760  if(i>2)
1761  {
1762  fout<<" "<<FormatInt(pos->mDihedralAtom+1,2)<<FormatFloat(pos->mDihedralAngle*RAD2DEG,8,3);
1763  }
1764  }
1765  }
1766  fout<<endl;
1767  i++;
1768  }
1769  }
1770  fout.close();
1771  }
1772  else
1773  {
1774  wxFileDialog open(this,_T("Choose a file to save the (named) Z-matrix to"),_T(""),_T(""),_T("*.zmat"),
1775  wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
1776 
1777  if(open.ShowModal() != wxID_OK) return;
1778 
1779  unsigned long nbchar=0;
1780  for(vector<MolAtom*>::const_iterator pos=mpMolecule->GetAtomList().begin();
1781  pos!=mpMolecule->GetAtomList().end();++pos)
1782  if(nbchar<(*pos)->GetName().size()) nbchar=(*pos)->GetName().size();
1783 
1784  ofstream fout (open.GetPath().ToAscii());
1785  fout.imbue(std::locale::classic());
1786  if(fout)
1787  {
1788  wxString tmp;
1789 
1790  fout<<mpMolecule->GetName()<<endl<<pz->size()<<endl;
1791  long i=0;
1792  for(vector<MolZAtom>::const_iterator pos=pz->begin();pos!=pz->end();++pos)
1793  {
1794  fout.width(nbchar);
1795  fout<<mpMolecule->GetAtomList()[i]->GetName();
1796  tmp.Printf(_T(" %2s "),pos->mpPow->GetSymbol().c_str());
1797  fout<<tmp;
1798  fout.width(nbchar);
1799  fout<<mpMolecule->GetAtomList()[pos->mBondAtom]->GetName()<<" ";
1800  if(i>0)
1801  {
1802  fout<<FormatFloat(pos->mBondLength,6,3)<<" ";
1803  if(i>1)
1804  {
1805  fout.width(nbchar);
1806  fout<<mpMolecule->GetAtomList()[pos->mBondAngleAtom]->GetName();
1807  fout<<" "<<FormatFloat(pos->mBondAngle*RAD2DEG,8,3)<<" ";
1808  if(i>2)
1809  {
1810  fout.width(nbchar);
1811  fout<<mpMolecule->GetAtomList()[pos->mDihedralAtom]->GetName();
1812  fout<<" "<<FormatFloat(pos->mDihedralAngle*RAD2DEG,8,3)<<" ";
1813  }
1814  }
1815  }
1816  fout<<endl;
1817  i++;
1818  }
1819  }
1820  fout.close();
1821  }
1822 }
1823 
1824 void WXMolecule::OnMenuTest(wxCommandEvent & WXUNUSED(event))
1825 {
1826  VFN_DEBUG_ENTRY("WXMolecule::OnMenuTest()",6)
1828  #if 1
1829  mpMolecule->BuildRingList();
1830  mpMolecule->BuildStretchModeBondLength();
1831  mpMolecule->BuildStretchModeBondAngle();
1832  mpMolecule->BuildStretchModeTorsion();
1833  mpMolecule->BuildStretchModeTwist();
1834 
1835  //mpMolecule->BuildRotorGroup();
1836  mpMolecule->BuildFlipGroup();
1837  mpMolecule->TuneGlobalOptimRotationAmplitude();
1838  //mpMolecule->FlipAtomGroup(*(mpMolecule->mvFlipGroup.begin()));
1839  //mpMolecule->GlobalOptRandomMove(0.1,gpRefParTypeObjCryst);
1840  mpMolecule->BuildStretchModeGroups();
1841  #else
1842  for(list<StretchModeTorsion>::iterator pos=mpMolecule->GetStretchModeTorsionList().begin();
1843  pos!=mpMolecule->GetStretchModeTorsionList().end();++pos)
1844  {
1845  if((pos->mpAtom1->GetName()=="C12")&&(pos->mpAtom2->GetName()=="N13"))
1846  {
1847  //mpMolecule->DihedralAngleRandomChange(*pos,0.01,true);
1848  cout<<pos->mpDihedralAngle->GetAngle()*RAD2DEG;
1849  mpMolecule->RotateAtomGroup(*(pos->mpAtom1),*(pos->mpAtom2),pos->mvRotatedAtomList,2*M_PI/10,true);
1850  cout<<" -> "<<pos->mpDihedralAngle->GetAngle()*RAD2DEG
1851  <<", llk="<<pos->mpDihedralAngle->GetLogLikelihood()<<endl;
1852  }
1853  }
1854  mpMolecule->GetCrystal().UpdateDisplay();
1855  #endif
1856  #if 0
1857  mpMolecule->BeginOptimization(true);
1858  for(REAL amplitude=0.1;amplitude<10;amplitude*=1.5)
1859  {
1860  REAL maxLLK=0,llk,ave=0.0;
1861  for(unsigned long i=0;i<1000;i++)
1862  {
1863  mpMolecule->BeginGlobalOptRandomMove();
1864  mpMolecule->GlobalOptRandomMove(amplitude,gpRefParTypeObjCryst);
1865  llk=mpMolecule->GetLogLikelihood();
1866  //cout<<" "<<llk<<endl;
1867  if(llk>maxLLK) maxLLK=llk;
1868  ave+=llk;
1869  mpMolecule->GetCrystal().UpdateDisplay();
1870  }
1871  cout<<"Amplitude="<<amplitude<<", <LLK>= "<<ave/1000<<", Max LLK= "<<maxLLK<<endl;
1872  }
1873  mpMolecule->EndOptimization();
1874  #endif
1875  VFN_DEBUG_EXIT("WXMolecule::OnMenuTest()",6)
1876 }
1877 
1878 class MoleculeMDTestThread: public wxThread
1879 {
1880 public:
1881  MoleculeMDTestThread(Molecule &mol,float seconds):
1882  wxThread(wxTHREAD_DETACHED),mpMolecule(&mol),mSeconds(seconds){};
1883  virtual void *Entry()
1884  {
1885  cout<<endl<<"Entering refinement thread "<<endl<<endl;
1886  const map<MolAtom *,set<MolAtom *> > *pConnect=&(mpMolecule-> GetConnectivityTable());
1887  Chronometer chrono;
1888  float dt0=chrono.seconds();
1889  unsigned long ct=0;
1890  while(chrono.seconds()<30)
1891  {
1892  cout<<"MD Test, cycle #"<<ct++<<endl;
1893  // Use Same procedure as in Molecule::GLobalOptRandomMove
1894  #if 0
1895  // Use one center for the position of an impulsion, applied to all atoms with an exponential decrease
1896  REAL xmin=(*mpMolecule->mvMDFullAtomGroup.begin())->GetX();
1897  REAL xmax=(*mpMolecule->mvMDFullAtomGroup.begin())->GetX();
1898  REAL ymin=(*mpMolecule->mvMDFullAtomGroup.begin())->GetY();
1899  REAL ymax=(*mpMolecule->mvMDFullAtomGroup.begin())->GetY();
1900  REAL zmin=(*mpMolecule->mvMDFullAtomGroup.begin())->GetZ();
1901  REAL zmax=(*mpMolecule->mvMDFullAtomGroup.begin())->GetZ();
1902  for(set<MolAtom*>::iterator at=mpMolecule->mvMDFullAtomGroup.begin();at!=mpMolecule->mvMDFullAtomGroup.end();++at)
1903  {
1904  if((*at)->GetX()<xmin) xmin=(*at)->GetX();
1905  if((*at)->GetX()>xmax) xmax=(*at)->GetX();
1906  if((*at)->GetY()<ymin) ymin=(*at)->GetY();
1907  if((*at)->GetY()>ymax) ymax=(*at)->GetY();
1908  if((*at)->GetZ()<zmin) zmin=(*at)->GetZ();
1909  if((*at)->GetZ()>zmax) zmax=(*at)->GetZ();
1910  }
1911  // Apply a gaussian impulsion to part of the atom group (FWHM=1/5 of group size)
1912  REAL dx=(xmax-xmin)/5.,dy=(ymax-ymin)/5.,dz=(zmax-zmin)/5.;
1913  if(dx<2) dx=2;
1914  if(dy<2) dy=2;
1915  if(dz<2) dz=2;
1916  const REAL xc=xmin+rand()/(REAL)RAND_MAX*(xmax-xmin);
1917  const REAL yc=ymin+rand()/(REAL)RAND_MAX*(ymax-ymin);
1918  const REAL zc=zmin+rand()/(REAL)RAND_MAX*(zmax-zmin);
1919  map<MolAtom*,XYZ> v0;
1920  const REAL ax=-4.*log(2.)/(dx*dx);
1921  const REAL ay=-4.*log(2.)/(dy*dy);
1922  const REAL az=-4.*log(2.)/(dz*dz);
1923  REAL ux,uy,uz,n=0;
1924  while(n<1)
1925  {
1926  ux=REAL(rand()-RAND_MAX/2);
1927  uy=REAL(rand()-RAND_MAX/2);
1928  uz=REAL(rand()-RAND_MAX/2);
1929  n=sqrt(ux*ux+uy*uy+uz*uz);
1930  }
1931  ux=ux/n;uy=uy/n;uz=uz/n;
1932  if(rand()%2==0)
1933  for(set<MolAtom*>::iterator at=mpMolecule->mvMDFullAtomGroup.begin();at!=mpMolecule->mvMDFullAtomGroup.end();++at)
1934  v0[*at]=XYZ(ux*exp(ax*((*at)->GetX()-xc)*((*at)->GetX()-xc)),
1935  uy*exp(ay*((*at)->GetY()-yc)*((*at)->GetY()-yc)),
1936  uz*exp(az*((*at)->GetZ()-zc)*((*at)->GetZ()-zc)));
1937  else
1938  for(set<MolAtom*>::iterator at=mpMolecule->mvMDFullAtomGroup.begin();at!=mpMolecule->mvMDFullAtomGroup.end();++at)
1939  v0[*at]=XYZ(((*at)->GetX()-xc)*ux*exp(ax*((*at)->GetX()-xc)*((*at)->GetX()-xc)),
1940  ((*at)->GetY()-yc)*uy*exp(ay*((*at)->GetY()-yc)*((*at)->GetY()-yc)),
1941  ((*at)->GetZ()-zc)*uz*exp(az*((*at)->GetZ()-zc)*((*at)->GetZ()-zc)));
1942  #else
1943  map<MolAtom*,XYZ> v0;
1944  // Use one atom for the center of the impulsion, 'push' atoms depending on distance & connectivity table
1945  for(set<MolAtom*>::iterator at=mpMolecule->mvMDFullAtomGroup.begin();at!=mpMolecule->mvMDFullAtomGroup.end();++at)
1946  v0[*at]=XYZ(0,0,0);
1947  map<MolAtom*,unsigned long> pushedAtoms;
1948  unsigned long idx=rand()%v0.size();
1949  set<MolAtom*>::iterator at0=mpMolecule->mvMDFullAtomGroup.begin();
1950  for(unsigned int i=0;i<idx;i++) at0++;
1951  const REAL xc=(*at0)->GetX();
1952  const REAL yc=(*at0)->GetY();
1953  const REAL zc=(*at0)->GetZ();
1954  ExpandAtomGroupRecursive(*at0,*pConnect,pushedAtoms,3);
1955  REAL ux,uy,uz,n=0;
1956  while(n<1)
1957  {
1958  ux=REAL(rand()-RAND_MAX/2);
1959  uy=REAL(rand()-RAND_MAX/2);
1960  uz=REAL(rand()-RAND_MAX/2);
1961  n=sqrt(ux*ux+uy*uy+uz*uz);
1962  }
1963  ux=ux/n;uy=uy/n;uz=uz/n;
1964  const REAL a=-4.*log(2.)/(2*2);//FWHM=2 Angstroems
1965  if(rand()%2==0)
1966  for(map<MolAtom*,unsigned long>::iterator at=pushedAtoms.begin() ;at!=pushedAtoms.end();++at)
1967  v0[at->first]=XYZ(ux*exp(a*(at->first->GetX()-xc)*(at->first->GetX()-xc)),
1968  uy*exp(a*(at->first->GetY()-yc)*(at->first->GetY()-yc)),
1969  uz*exp(a*(at->first->GetZ()-zc)*(at->first->GetZ()-zc)));
1970  else
1971  for(map<MolAtom*,unsigned long>::iterator at=pushedAtoms.begin() ;at!=pushedAtoms.end();++at)
1972  v0[at->first]=XYZ((at->first->GetX()-xc)*ux*exp(a*(at->first->GetX()-xc)*(at->first->GetX()-xc)),
1973  (at->first->GetY()-yc)*uy*exp(a*(at->first->GetY()-yc)*(at->first->GetY()-yc)),
1974  (at->first->GetZ()-zc)*uz*exp(a*(at->first->GetZ()-zc)*(at->first->GetZ()-zc)));
1975 
1976  #endif
1977  const REAL nrj0=40*( mpMolecule->GetBondList().size()
1978  +mpMolecule->GetBondAngleList().size()
1979  +mpMolecule->GetDihedralAngleList().size());
1980  map<RigidGroup*,std::pair<XYZ,XYZ> > vr;
1981  mpMolecule->MolecularDynamicsEvolve(v0, 200,0.004,
1982  mpMolecule->GetBondList(),
1983  mpMolecule->GetBondAngleList(),
1984  mpMolecule->GetDihedralAngleList(),
1985  vr,nrj0);
1986 
1987  // Display
1988  wxMilliSleep(1);// Slow down display for simple structures
1989  if((chrono.seconds()-dt0)>0.05) {mpMolecule->GetCrystal().UpdateDisplay();dt0=chrono.seconds();}
1990  }
1991  return NULL;
1992  };
1993  virtual void OnExit()
1994  {
1995  cout <<endl<<"Exiting refinement thread "<<endl<<endl;
1996  };
1997 private:
1999  Molecule *mpMolecule;
2001  float mSeconds;
2002 };
2003 
2004 void WXMolecule::OnMenuMDTest(wxCommandEvent & WXUNUSED(event))
2005 {
2006  VFN_DEBUG_ENTRY("WXMolecule::OnMenuMDTest()",6)
2008  {
2009  wxProgressDialog dlgProgress(_T("Beginning MD Test..."),_T("Building Flip Groups"),
2010  7,this,wxPD_AUTO_HIDE|wxPD_ELAPSED_TIME);//|wxPD_CAN_ABORT
2011  mpMolecule->BuildFlipGroup();
2012  dlgProgress.Update(0,_T("Build Ring List")) ;
2013  mpMolecule->BuildRingList();
2014  dlgProgress.Update(1,_T("Build Stretch Modes: Bond Length")) ;
2015  mpMolecule->BuildStretchModeBondLength();
2016  dlgProgress.Update(2,_T("Build Stretch Modes: Bond Angle")) ;
2017  mpMolecule->BuildStretchModeBondAngle();
2018  dlgProgress.Update(3,_T("Build Stretch Modes: Torsion")) ;
2019  mpMolecule->BuildStretchModeTorsion();
2020  //mpMolecule->BuildStretchModeTwist();
2021  dlgProgress.Update(4,_T("Build Stretch Modes: Optimize Rotation Amplitudes")) ;
2022  mpMolecule->TuneGlobalOptimRotationAmplitude();
2023  dlgProgress.Update(5,_T("Build Stretch Modes Groups")) ;
2024  mpMolecule->BuildStretchModeGroups();
2025  dlgProgress.Update(6,_T("Build MD Atom Groups")) ;
2026  mpMolecule->BuildMDAtomGroups();
2027  }
2028 
2029  MoleculeMDTestThread *pTest = new MoleculeMDTestThread(*mpMolecule,30);
2030  if(pTest->Create() != wxTHREAD_NO_ERROR)
2031  wxLogError(_T("Can't create test optimization thread"));
2032  else pTest->Run();
2033  VFN_DEBUG_EXIT("WXMolecule::OnMenuMDTest()",6)
2034 }
2035 
2036 static const long ID_MOLECULE_ROTATE_BOND_GO =WXCRYST_ID();
2037 static const long ID_MOLECULE_ROTATE_BOND_ATOMS=WXCRYST_ID();
2038 
2039 class WXMoleculeRotation:public wxWindow
2040 {
2041  public:
2042  WXMoleculeRotation(wxWindow *parent, Molecule &mol):
2043  wxWindow(parent,-1),mBondListClock(mol.GetBondListClock()),mpMol(&mol)
2044  {
2045  VFN_DEBUG_ENTRY("WXMoleculeRotation::WXMoleculeRotation()",10)
2046  this->SetFont(wxFont(8,wxTELETYPE,wxFONTSTYLE_NORMAL,wxFONTWEIGHT_NORMAL));
2047 
2048  wxArrayString choices;
2049  for(vector<MolBond*>::const_iterator pos=mol.GetBondList().begin();pos!=mol.GetBondList().end();++pos)
2050  choices.Add(wxString::FromAscii((*pos)->GetName().c_str()));
2051 
2052  wxBoxSizer* pSizer=new wxBoxSizer(wxHORIZONTAL);
2053 
2054  wxBoxSizer* pSizer1=new wxBoxSizer(wxVERTICAL);
2055  pSizer1->Add(new wxStaticText(this,-1,_T("Select bond:")),0,wxALIGN_CENTER);
2056  mpBond= new wxChoice(this,ID_MOLECULE_ROTATE_BOND_ATOMS,wxDefaultPosition,wxDefaultSize,choices);
2057  mpBond->SetSelection(0);
2058  pSizer1->Add(mpBond,0,wxALIGN_CENTER);
2059  pSizer->Add(pSizer1,0,wxALIGN_CENTER);
2060 
2061  wxBoxSizer* pSizer2=new wxBoxSizer(wxVERTICAL);
2062  pSizer2->Add(new wxStaticText(this,-1,_T("Atoms to rotate:")),0,wxALIGN_CENTER);
2063  mpRotatedAtoms= new wxListBox(this,-1,wxDefaultPosition,wxSize(150,60));
2064  pSizer2->Add(mpRotatedAtoms,0,wxALIGN_CENTER);
2065  pSizer->Add(pSizer2,0,wxALIGN_CENTER);
2066 
2067  wxBoxSizer* pSizer3=new wxBoxSizer(wxVERTICAL);
2068  pSizer3->Add(new wxStaticText(this,-1,_T("Amplitude:")),0,wxALIGN_CENTER);
2069  mpAngle=new wxTextCtrl(this,-1,_T("10"), wxDefaultPosition,
2070  wxDefaultSize, 0, wxTextValidator(wxFILTER_NUMERIC));
2071  pSizer3->Add(mpAngle,0,wxALIGN_CENTER);
2072  pSizer->Add(pSizer3,0,wxALIGN_CENTER);
2073 
2074  wxButton *pButtonRotate=new wxButton(this,ID_MOLECULE_ROTATE_BOND_GO,_T("Rotate !"));
2075  pSizer->Add(pButtonRotate,0,wxALIGN_CENTER);
2076 
2077  this->SetSizer(pSizer);
2078  this->SetAutoLayout(true);
2079  pSizer->SetSizeHints(this);
2080  pSizer->SetSizeHints(parent);
2081  this->Layout();
2082  wxCommandEvent ev(wxEVT_COMMAND_CHOICE_SELECTED,ID_MOLECULE_ROTATE_BOND_ATOMS);
2083  wxPostEvent(this,ev);
2084  VFN_DEBUG_EXIT("WXMoleculeRotation::WXMoleculeRotation()",10)
2085  }
2086 
2087  void OnRotate(wxCommandEvent &event)
2088  {
2089  if(mBondListClock<mpMol->GetBondListClock())
2090  {
2091  cout<<" The bond list has changed !"<<endl;
2092  this->GetParent()->Destroy();
2093  return;
2094  }
2095  VFN_DEBUG_MESSAGE("WXMoleculeRotation::OnRotate()",10)
2097  unsigned int bond=mpBond->GetSelection();
2098  unsigned int choice=mpRotatedAtoms->GetSelection();
2099  double angle;
2100  mpAngle->GetValue().ToDouble(&angle);
2101  mpMol->RotateAtomGroup(mpMol->GetBondList()[bond]->GetAtom1(),
2102  mpMol->GetBondList()[bond]->GetAtom2(),
2103  mvpRotatedAtoms[choice], angle*DEG2RAD, true);
2104  mpMol->GetCrystal().UpdateDisplay();
2105  }
2106  void OnSelectBond(wxCommandEvent &event)
2107  {
2108  if(mBondListClock<mpMol->GetBondListClock())
2109  {
2110  cout<<" The bond list has changed !"<<endl;
2111  this->GetParent()->Destroy();
2112  return;
2113  }
2114  VFN_DEBUG_MESSAGE("WXMoleculeRotation::OnSelectBond()",10)
2116  const unsigned int choice=mpBond->GetSelection();
2117  MolAtom *pAt1=&(mpMol->GetBondList()[choice]->GetAtom1());
2118  MolAtom *pAt2=&(mpMol->GetBondList()[choice]->GetAtom2());
2119  mpMol->BuildConnectivityTable();
2120 
2121  mvpRotatedAtoms.clear();
2122  mvpRotatedAtoms.resize(2);
2123  mvpRotatedAtoms[0].insert(pAt1);
2124  ExpandAtomGroupRecursive(pAt2,mpMol->GetConnectivityTable(),mvpRotatedAtoms[0]);
2125 
2126  mvpRotatedAtoms[1].insert(pAt2);
2127  ExpandAtomGroupRecursive(pAt1,mpMol->GetConnectivityTable(),mvpRotatedAtoms[1]);
2128 
2129  wxArrayString choices;
2130 
2131  set<MolAtom *>::const_iterator pos=mvpRotatedAtoms[0].begin();
2132  wxString choice1(wxString::FromAscii((*pos++)->GetName().c_str()));
2133  for(;pos!=mvpRotatedAtoms[0].end();++pos)
2134  choice1 +=_T("-")+wxString::FromAscii((*pos)->GetName().c_str());
2135  choices.Add(choice1);
2136 
2137  pos=mvpRotatedAtoms[1].begin();
2138  wxString choice2(wxString::FromAscii((*pos++)->GetName().c_str()));
2139  for(;pos!=mvpRotatedAtoms[1].end();++pos)
2140  choice2 +=_T("-")+wxString::FromAscii((*pos)->GetName().c_str());
2141  choices.Add(choice2);
2142 
2143  mpRotatedAtoms->Set(choices);
2144  mpRotatedAtoms->SetSelection(0);
2145  }
2146  private:
2148  const RefinableObjClock& mBondListClock;
2149  Molecule *mpMol;
2150  wxChoice *mpBond;
2151  wxListBox *mpRotatedAtoms;
2152  vector<set<MolAtom *> > mvpRotatedAtoms;
2153  wxTextCtrl *mpAngle;
2154  DECLARE_EVENT_TABLE()
2155 };
2156 BEGIN_EVENT_TABLE(WXMoleculeRotation,wxWindow)
2157  EVT_BUTTON(ID_MOLECULE_ROTATE_BOND_GO, WXMoleculeRotation::OnRotate)
2158  EVT_CHOICE(ID_MOLECULE_ROTATE_BOND_ATOMS, WXMoleculeRotation::OnSelectBond)
2159 END_EVENT_TABLE()
2160 
2161 static const long ID_MOLECULE_ROTATE_DIHED_GO =WXCRYST_ID();
2162 static const long ID_MOLECULE_ROTATE_DIHED_ATOMS=WXCRYST_ID();
2163 
2164 class WXMoleculeRotationDihed:public wxWindow
2165 {
2166  public:
2167  WXMoleculeRotationDihed(wxWindow *parent, Molecule &mol):
2168  wxWindow(parent,-1),mBondListClock(mol.GetBondListClock()),mpMol(&mol)
2169  {
2170  VFN_DEBUG_ENTRY("WXMoleculeRotationDihed::WXMoleculeRotationDihed()",10)
2171  this->SetFont(wxFont(8,wxTELETYPE,wxFONTSTYLE_NORMAL,wxFONTWEIGHT_NORMAL));
2172 
2173  wxArrayString choices;
2174  // Use existing angle restraints to generate dihedral angles
2175  for(vector<MolBondAngle*>::const_iterator pos=mol.GetBondAngleList().begin();pos!=mol.GetBondAngleList().end();++pos)
2176  {
2177  MolAtom *pAt1=&((*pos)->GetAtom1());
2178  MolAtom *pAt2=&((*pos)->GetAtom2());
2179  MolAtom *pAt3=&((*pos)->GetAtom3());
2180  const set<MolAtom * > *pConn=&(mpMol->GetConnectivityTable().find(pAt3)->second);
2181  for(set<MolAtom * >::const_iterator neigh=pConn->begin();neigh!=pConn->end();++neigh)
2182  {
2183  if( (*neigh==pAt1) || (*neigh==pAt2) ) continue;
2184  mvDihed.push_back(MolDihedralAngle(*pAt1,*pAt2,*pAt3,**neigh,0,.001,.001,*mpMol));
2185  choices.Add(wxString::FromAscii(mvDihed.back().GetName().c_str()));
2186  }
2187  }
2188 
2189  wxBoxSizer* pSizer=new wxBoxSizer(wxHORIZONTAL);
2190 
2191  wxBoxSizer* pSizer1=new wxBoxSizer(wxVERTICAL);
2192  pSizer1->Add(new wxStaticText(this,-1,_T("Dihedral Angle:")),0,wxALIGN_CENTER);
2193  mpDihed= new wxChoice(this,ID_MOLECULE_ROTATE_DIHED_ATOMS,wxDefaultPosition,wxDefaultSize,choices);
2194  mpDihed->SetSelection(0);
2195  pSizer1->Add(mpDihed,0,wxALIGN_CENTER);
2196  pSizer->Add(pSizer1,0,wxALIGN_CENTER);
2197 
2198  wxBoxSizer* pSizer2=new wxBoxSizer(wxVERTICAL);
2199  pSizer2->Add(new wxStaticText(this,-1,_T("Atoms to rotate:")),0,wxALIGN_CENTER);
2200  mpRotatedAtoms= new wxListBox(this,-1,wxDefaultPosition,wxSize(150,60));
2201  pSizer2->Add(mpRotatedAtoms,0,wxALIGN_CENTER);
2202  pSizer->Add(pSizer2,0,wxALIGN_CENTER);
2203 
2204  wxBoxSizer* pSizer3=new wxBoxSizer(wxVERTICAL);
2205  pSizer3->Add(new wxStaticText(this,-1,_T("Angle:")),0,wxALIGN_CENTER);
2206  mpAngle=new wxTextCtrl(this,-1,_T("10"), wxDefaultPosition,
2207  wxDefaultSize, 0, wxTextValidator(wxFILTER_NUMERIC));
2208  pSizer3->Add(mpAngle,0,wxALIGN_CENTER);
2209  pSizer->Add(pSizer3,0,wxALIGN_CENTER);
2210 
2211  wxButton *pButtonRotate=new wxButton(this,ID_MOLECULE_ROTATE_DIHED_GO,_T("Set angle !"));
2212  pSizer->Add(pButtonRotate,0,wxALIGN_CENTER);
2213 
2214  this->SetSizer(pSizer);
2215  this->SetAutoLayout(true);
2216  pSizer->SetSizeHints(this);
2217  pSizer->SetSizeHints(parent);
2218  this->Layout();
2219  wxCommandEvent ev(wxEVT_COMMAND_CHOICE_SELECTED,ID_MOLECULE_ROTATE_DIHED_ATOMS);
2220  wxPostEvent(this,ev);
2221  VFN_DEBUG_EXIT("WXMoleculeRotationDihed::WXMoleculeRotationDihed()",10)
2222  }
2223 
2224  void OnRotate(wxCommandEvent &event)
2225  {
2226  if(mBondListClock<mpMol->GetBondListClock())
2227  {
2228  cout<<" The bond list has changed !"<<endl;
2229  this->GetParent()->Destroy();
2230  return;
2231  }
2232  VFN_DEBUG_MESSAGE("WXMoleculeRotationDihed::OnRotate()",10)
2234  MolDihedralAngle *pDihed=&mvDihed[mpDihed->GetSelection()];
2235  unsigned int choice=mpRotatedAtoms->GetSelection();
2236  double angle;
2237  mpAngle->GetValue().ToDouble(&angle);
2238  angle*=DEG2RAD;
2239  angle-=pDihed->GetAngle();
2240 
2241  if(mvpRotatedAtoms[choice].find(&(pDihed->GetAtom1()))!=mvpRotatedAtoms[choice].end()) angle*=-1;
2242 
2243  mpMol->RotateAtomGroup(pDihed->GetAtom2(),
2244  pDihed->GetAtom3(),
2245  mvpRotatedAtoms[choice], angle, true);
2246  mpMol->GetCrystal().UpdateDisplay();
2247  }
2248  void OnSelectDihed(wxCommandEvent &event)
2249  {
2250  if(mBondListClock<mpMol->GetBondListClock())
2251  {
2252  cout<<" The bond list has changed !"<<endl;
2253  this->GetParent()->Destroy();
2254  return;
2255  }
2256  VFN_DEBUG_MESSAGE("WXMoleculeRotationDihed::OnSelectBond()",10)
2258  MolDihedralAngle *pDihed=&mvDihed[mpDihed->GetSelection()];
2259  MolAtom *pAt1=&(pDihed->GetAtom1());
2260  MolAtom *pAt2=&(pDihed->GetAtom2());
2261  MolAtom *pAt3=&(pDihed->GetAtom3());
2262  MolAtom *pAt4=&(pDihed->GetAtom4());
2263  mpMol->BuildConnectivityTable();
2264 
2265  mvpRotatedAtoms.clear();
2266  mvpRotatedAtoms.resize(2);
2267 
2268  mvpRotatedAtoms[0].insert(pAt1);
2269  mvpRotatedAtoms[0].insert(pAt2);
2270  ExpandAtomGroupRecursive(pAt3,mpMol->GetConnectivityTable(),mvpRotatedAtoms[0]);
2271  mvpRotatedAtoms[0].erase(pAt1);
2272  mvpRotatedAtoms[0].erase(pAt2);
2273 
2274  mvpRotatedAtoms[1].insert(pAt4);
2275  mvpRotatedAtoms[1].insert(pAt3);
2276  ExpandAtomGroupRecursive(pAt2,mpMol->GetConnectivityTable(),mvpRotatedAtoms[1]);
2277  mvpRotatedAtoms[1].erase(pAt4);
2278  mvpRotatedAtoms[1].erase(pAt3);
2279 
2280  wxArrayString choices;
2281 
2282  set<MolAtom *>::const_iterator pos=mvpRotatedAtoms[0].begin();
2283  wxString choice1(wxString::FromAscii((*pos++)->GetName().c_str()));
2284  for(;pos!=mvpRotatedAtoms[0].end();++pos)
2285  choice1 +=_T("-")+wxString::FromAscii((*pos)->GetName().c_str());
2286  choices.Add(choice1);
2287 
2288  pos=mvpRotatedAtoms[1].begin();
2289  wxString choice2(wxString::FromAscii((*pos++)->GetName().c_str()));
2290  for(;pos!=mvpRotatedAtoms[1].end();++pos)
2291  choice2 +=_T("-")+wxString::FromAscii((*pos)->GetName().c_str());
2292  choices.Add(choice2);
2293 
2294  mpRotatedAtoms->Set(choices);
2295  mpRotatedAtoms->SetSelection(0);
2296  mpAngle->SetValue(wxString::Format(_T("%6.2f"),pDihed->GetAngle()*RAD2DEG));
2297  }
2298  private:
2300  const RefinableObjClock& mBondListClock;
2301  Molecule *mpMol;
2302  vector<MolDihedralAngle > mvDihed;
2303  wxChoice *mpDihed;
2304  wxListBox *mpRotatedAtoms;
2305  vector<set<MolAtom *> > mvpRotatedAtoms;
2306  wxTextCtrl *mpAngle;
2307  DECLARE_EVENT_TABLE()
2308 };
2309 BEGIN_EVENT_TABLE(WXMoleculeRotationDihed,wxWindow)
2310  EVT_BUTTON(ID_MOLECULE_ROTATE_DIHED_GO, WXMoleculeRotationDihed::OnRotate)
2311  EVT_CHOICE(ID_MOLECULE_ROTATE_DIHED_ATOMS, WXMoleculeRotationDihed::OnSelectDihed)
2312 END_EVENT_TABLE()
2313 
2314 void WXMolecule::OnMenuRotate(wxCommandEvent &event)
2315 {
2316  VFN_DEBUG_ENTRY("WXMolecule::OnMenuRotate()",10)
2318  if(event.GetId()==ID_MOLECULE_MENU_GEOMETRY_ROTATE_BOND)
2319  {
2320  #ifdef __WXGTK__
2321  wxFrame *frame= new wxMiniFrame(this,-1,_T("Rotate around bond"),wxDefaultPosition,
2322  wxDefaultSize,wxCLOSE_BOX|wxSTAY_ON_TOP|wxCAPTION);
2323  #else
2324  wxFrame *frame= new wxFrame(this,-1,_T("Rotate around bond"),wxDefaultPosition,
2325  wxDefaultSize);
2326  #endif
2327  WXMoleculeRotation * wxMolRot;
2328  wxMolRot=new WXMoleculeRotation(frame,*mpMolecule);
2329  frame->Show(true);
2330  }
2331  if(event.GetId()==ID_MOLECULE_MENU_GEOMETRY_ROTATE_DIHED)
2332  {
2333  #ifdef __WXGTK__
2334  wxFrame *frame= new wxMiniFrame(this,-1,_T("Change dihedral angle"),wxDefaultPosition,
2335  wxDefaultSize,wxCLOSE_BOX|wxSTAY_ON_TOP|wxCAPTION);
2336  #else
2337  wxFrame *frame= new wxFrame(this,-1,_T("Change dihedral angle"),wxDefaultPosition,
2338  wxDefaultSize);
2339  #endif
2340  WXMoleculeRotationDihed * wxMolRot;
2341  wxMolRot=new WXMoleculeRotationDihed(frame,*mpMolecule);
2342  frame->Show(true);
2343  }
2344  VFN_DEBUG_EXIT("WXMolecule::OnMenuRotate()",10)
2345 }
2346 
2347 
2348 void WXMolecule::OnMenuSetLimits(wxCommandEvent &event)
2349 {
2350 }
2351 
2352 void WXMolecule::CrystUpdate(const bool uui,const bool lock)
2353 {
2354  VFN_DEBUG_ENTRY("WXMolecule::CrystUpdate()",6)
2355  if(lock) mMutex.Lock();
2356  if(false==mpMolecule->IsBeingRefined())
2357  {
2358  //Remove any atom, bond, bond angle or dihedral angle that could have been removed
2359  {
2360  unsigned long i=0;
2361  for(list<CellAtom>::iterator pos=mvpAtom.begin();pos!=mvpAtom.end();)
2362  {
2363  if(i>=mpMolecule->GetAtomList().size())
2364  {
2365  pos=mvpAtom.erase(pos);
2366  mpAtomWin->DeleteRows(i);
2367  }
2368  else
2369  {
2370  if(pos->mpAtom!=mpMolecule->GetAtomList()[i])
2371  {
2372  pos=mvpAtom.erase(pos);
2373  mpAtomWin->DeleteRows(i);
2374  }
2375  else
2376  {
2377  ++pos;
2378  ++i;
2379  }
2380  }
2381  }
2382  }
2383  if(0!=mpBondWin)
2384  {
2385  unsigned long i=0;
2386  for(list<CellBond>::iterator pos=mvpBond.begin();pos!=mvpBond.end();)
2387  {
2388  if(i>=mpMolecule->GetBondList().size())
2389  {
2390  pos=mvpBond.erase(pos);
2391  mpBondWin->DeleteRows(i);
2392  }
2393  else
2394  {
2395  if(pos->mpBond!=mpMolecule->GetBondList()[i])
2396  {
2397  pos=mvpBond.erase(pos);
2398  mpBondWin->DeleteRows(i);
2399  }
2400  else
2401  {
2402  ++pos;
2403  ++i;
2404  }
2405  }
2406  }
2407  }
2408  if(0!=mpAngleWin)
2409  {
2410  unsigned long i=0;
2411  for(list<CellBondAngle>::iterator pos=mvpBondAngle.begin();pos!=mvpBondAngle.end();)
2412  {
2413  if(i>=mpMolecule->GetBondAngleList().size())
2414  {
2415  pos=mvpBondAngle.erase(pos);
2416  mpAngleWin->DeleteRows(i);
2417  }
2418  else
2419  {
2420  if(pos->mpBondAngle!=mpMolecule->GetBondAngleList()[i])
2421  {
2422  pos=mvpBondAngle.erase(pos);
2423  mpAngleWin->DeleteRows(i);
2424  }
2425  else
2426  {
2427  ++pos;
2428  ++i;
2429  }
2430  }
2431  }
2432  }
2433  if(0!=mpDihedralAngleWin)
2434  {
2435  unsigned long i=0;
2436  for(list<CellDihedralAngle>::iterator pos=mvpDihedralAngle.begin();pos!=mvpDihedralAngle.end();)
2437  {
2438  if(i>=mpMolecule->GetDihedralAngleList().size())
2439  {
2440  pos=mvpDihedralAngle.erase(pos);
2441  mpDihedralAngleWin->DeleteRows(i);
2442  }
2443  else
2444  {
2445  if(pos->mpDihedralAngle!=mpMolecule->GetDihedralAngleList()[i])
2446  {
2447  pos=mvpDihedralAngle.erase(pos);
2448  mpDihedralAngleWin->DeleteRows(i);
2449  }
2450  else
2451  {
2452  ++pos;
2453  ++i;
2454  }
2455  }
2456  }
2457  }
2458  if(0!=mpRigidGroupWin)
2459  {
2460  unsigned long i=0;
2461  for(list<CellRigidGroup>::iterator pos=mvpRigidGroup.begin();pos!=mvpRigidGroup.end();)
2462  {
2463  if(i>=mpMolecule->GetRigidGroupList().size())
2464  {
2465  pos=mvpRigidGroup.erase(pos);
2466  mpRigidGroupWin->DeleteRows(i);
2467  }
2468  else
2469  {
2470  if(pos->mpGroup!=mpMolecule->GetRigidGroupList()[i])
2471  {
2472  pos=mvpRigidGroup.erase(pos);
2473  mpRigidGroupWin->DeleteRows(i);
2474  }
2475  else
2476  {
2477  ++pos;
2478  ++i;
2479  }
2480  }
2481  }
2482  }
2483  if(0!=mpNonFlipAtomWin)
2484  {
2485  if(mpNonFlipAtomWin->GetNumberRows()>0)
2486  mpNonFlipAtomWin->DeleteRows(0, mpNonFlipAtomWin->GetNumberRows(), true);
2487  }
2488  //Add any atom, bond, bond angle or dihedral angle that could have been added
2489  {
2490  bool needLayout=false;
2491  for(unsigned long i=mvpAtom.size();i<mpMolecule->GetAtomList().size();++i)
2492  {
2493  VFN_DEBUG_MESSAGE("WXMolecule::CrystUpdate():Atom not found",5)
2494  mpAtomWin->AppendRows();
2495  mvpAtom.push_back(CellAtom());
2496  mvpAtom.back().mpAtom=mpMolecule->GetAtomList()[i];
2497  needLayout=true;
2498  }
2499  if(needLayout)
2500  {
2501  //mpAtomWin->Layout();
2502  //mpAtomWin->SetScrollRate(20,20);
2503  mpAtomWin->FitInside();
2504  //mpAtomWin->EnableScrolling(true,true);
2505  }
2506  }
2507  if(0!=mpBondWin)
2508  {
2509  for(unsigned long i=mvpBond.size();i<mpMolecule->GetBondList().size();++i)
2510  {
2511  VFN_DEBUG_MESSAGE("WXMolecule::CrystUpdate():Bond not found",5)
2512  mpBondWin->AppendRows();
2513  mvpBond.push_back(CellBond());
2514  mvpBond.back().mpBond=mpMolecule->GetBondList()[i];
2515  }
2516  }
2517  if(0!=mpAngleWin)
2518  {
2519  for(unsigned long i=mvpBondAngle.size();i<mpMolecule->GetBondAngleList().size();++i)
2520  {
2521  VFN_DEBUG_MESSAGE("WXMolecule::CrystUpdate():Bond Angle not found",5)
2522  mpAngleWin->AppendRows();
2523  mvpBondAngle.push_back(CellBondAngle());
2524  mvpBondAngle.back().mpBondAngle=mpMolecule->GetBondAngleList()[i];
2525  }
2526  }
2527  if(0!=mpDihedralAngleWin)
2528  {
2529  for(unsigned long i=mvpDihedralAngle.size();i<mpMolecule->GetDihedralAngleList().size();++i)
2530  {
2531  VFN_DEBUG_MESSAGE("WXMolecule::CrystUpdate():Dihedral Angle not found",5)
2532  mpDihedralAngleWin->AppendRows();
2533  mvpDihedralAngle.push_back(CellDihedralAngle());
2534  mvpDihedralAngle.back().mpDihedralAngle=mpMolecule->GetDihedralAngleList()[i];
2535  }
2536  }
2537  if(0!=mpRigidGroupWin)
2538  {
2539  for(unsigned long i=mvpRigidGroup.size();i<mpMolecule->GetRigidGroupList().size();++i)
2540  {
2541  VFN_DEBUG_MESSAGE("WXMolecule::CrystUpdate():Rigid Group not found",5)
2542  mpRigidGroupWin->AppendRows();
2543  mvpRigidGroup.push_back(CellRigidGroup());
2544  mvpRigidGroup.back().mpGroup=mpMolecule->GetRigidGroupList()[i];
2545  }
2546  // Update list of atoms, if necessary
2547  for(list<CellRigidGroup>::iterator pos=mvpRigidGroup.begin();pos!=mvpRigidGroup.end();++pos)
2548  {
2549  if(*(pos->mpGroup) != pos->mGroupCopy)
2550  {
2551  pos->mGroupCopy=*(pos->mpGroup);
2552  pos->mNeedUpdateUI=true;
2553  }
2554  }
2555  }
2556  if(0!=mpNonFlipAtomWin)
2557  {
2558  vector<MolAtom*> v = mpMolecule->GetAtomList();
2559  unsigned int i=0;
2560  for(std::vector<MolAtom*>::const_iterator pos=mpMolecule->GetAtomList().begin();pos!=mpMolecule->GetAtomList().end();++pos)
2561  {
2562  if((*pos)->IsNonFlipAtom())
2563  {
2564  mpNonFlipAtomWin->AppendRows(1, true);
2565  mpNonFlipAtomWin->SetCellValue(i, 0, (*pos)->GetName());
2566  i++;
2567  }
2568  }
2569  }
2570  }
2571  // Update values
2572  {
2573  for(list<CellAtom>::iterator pos=mvpAtom.begin();pos!=mvpAtom.end();++pos)
2574  {
2575  const string name=pos->mpAtom->GetName();
2576  const ScatteringPower* pow=&(pos->mpAtom->GetScatteringPower());
2577  const REAL x=pos->mpAtom->X();
2578  const REAL y=pos->mpAtom->Y();
2579  const REAL z=pos->mpAtom->Z();
2580  const REAL occ=pos->mpAtom->GetOccupancy();
2581  if( (name !=pos->mName)
2582  ||(pow !=pos->mpScatteringPower)
2583  ||(x !=pos->mX)
2584  ||(y !=pos->mY)
2585  ||(z !=pos->mZ)
2586  ||(occ !=pos->mOcc))
2587  {
2588  pos->mName =name;
2589  pos->mpScatteringPower =pow;
2590  pos->mX =x;
2591  pos->mY =y;
2592  pos->mZ =z;
2593  pos->mOcc =occ;
2594  pos->mNeedUpdateUI=true;
2595  }
2596  }
2597  }
2598  if(0!=mpBondWin)
2599  {
2600  for(list<CellBond>::iterator pos=mvpBond.begin();pos!=mvpBond.end();++pos)
2601  {
2602  const string atom1=pos->mpBond->GetAtom1().GetName();
2603  const string atom2=pos->mpBond->GetAtom2().GetName();
2604  const REAL length =pos->mpBond->GetLength();
2605  const REAL length0 =pos->mpBond->GetLength0();
2606  const REAL sigma =pos->mpBond->GetLengthSigma();
2607  const REAL delta =pos->mpBond->GetLengthDelta();
2608  if( (atom1 !=pos->mAtom1)
2609  ||(atom2 !=pos->mAtom2)
2610  ||(length !=pos->mLength)
2611  ||(length0!=pos->mLength0)
2612  ||(sigma !=pos->mSigma)
2613  ||(delta !=pos->mDelta))
2614  {
2615  VFN_DEBUG_MESSAGE("WXMolecule::CrystUpdate():"<<atom1<<"-"<<atom2<<":"<<length,4)
2616  pos->mAtom1 =atom1;
2617  pos->mAtom2 =atom2;
2618  pos->mLength =length;
2619  pos->mLength0=length0;
2620  pos->mSigma =sigma;
2621  pos->mDelta =delta;
2622  pos->mNeedUpdateUI=true;
2623  }
2624  }
2625  }
2626  if(0!=mpAngleWin)
2627  {
2628  for(list<CellBondAngle>::iterator pos=mvpBondAngle.begin();pos!=mvpBondAngle.end();++pos)
2629  {
2630  const string atom1=pos->mpBondAngle->GetAtom1().GetName();
2631  const string atom2=pos->mpBondAngle->GetAtom2().GetName();
2632  const string atom3=pos->mpBondAngle->GetAtom3().GetName();
2633  const REAL angle =pos->mpBondAngle->GetAngle();
2634  const REAL angle0 =pos->mpBondAngle->GetAngle0();
2635  const REAL sigma =pos->mpBondAngle->GetAngleSigma();
2636  const REAL delta =pos->mpBondAngle->GetAngleDelta();
2637  if( (atom1 !=pos->mAtom1)
2638  ||(atom2 !=pos->mAtom2)
2639  ||(atom3 !=pos->mAtom3)
2640  ||(angle !=pos->mAngle)
2641  ||(angle0!=pos->mAngle0)
2642  ||(sigma !=pos->mSigma)
2643  ||(delta !=pos->mDelta))
2644  {
2645  pos->mAtom1 =atom1;
2646  pos->mAtom2 =atom2;
2647  pos->mAtom3 =atom3;
2648  pos->mAngle =angle;
2649  pos->mAngle0=angle0;
2650  pos->mSigma =sigma;
2651  pos->mDelta =delta;
2652  pos->mNeedUpdateUI=true;
2653  }
2654  }
2655  }
2656  if(0!=mpDihedralAngleWin)
2657  {
2658  for(list<CellDihedralAngle>::iterator pos=mvpDihedralAngle.begin();pos!=mvpDihedralAngle.end();++pos)
2659  {
2660  const string atom1=pos->mpDihedralAngle->GetAtom1().GetName();
2661  const string atom2=pos->mpDihedralAngle->GetAtom2().GetName();
2662  const string atom3=pos->mpDihedralAngle->GetAtom3().GetName();
2663  const string atom4=pos->mpDihedralAngle->GetAtom4().GetName();
2664  const REAL angle =pos->mpDihedralAngle->GetAngle();
2665  const REAL angle0 =pos->mpDihedralAngle->GetAngle0();
2666  const REAL sigma =pos->mpDihedralAngle->GetAngleSigma();
2667  const REAL delta =pos->mpDihedralAngle->GetAngleDelta();
2668  if( (atom1 !=pos->mAtom1)
2669  ||(atom2 !=pos->mAtom2)
2670  ||(atom3 !=pos->mAtom3)
2671  ||(atom4 !=pos->mAtom4)
2672  ||(angle !=pos->mAngle)
2673  ||(angle0!=pos->mAngle0)
2674  ||(sigma !=pos->mSigma)
2675  ||(delta !=pos->mDelta))
2676  {
2677  pos->mAtom1 =atom1;
2678  pos->mAtom2 =atom2;
2679  pos->mAtom3 =atom3;
2680  pos->mAtom4 =atom4;
2681  pos->mAngle =angle;
2682  pos->mAngle0=angle0;
2683  pos->mSigma =sigma;
2684  pos->mDelta =delta;
2685  pos->mNeedUpdateUI=true;
2686  }
2687  }
2688  }
2689  if(0!=mpNonFlipAtomWin)
2690  {
2691 
2692  }
2693  this->WXRefinableObj::CrystUpdate(uui,false);
2694  if(lock) mMutex.Unlock();
2695  VFN_DEBUG_EXIT("WXMolecule::CrystUpdate()",6)
2696 }
2697 
2698 void WXMolecule::OnMenuShowRestraintWindow(wxCommandEvent &event)
2699 {
2700  if(0!=mpBondWin) return;
2701 
2702  // Frame with notebook
2703  wxFrame *frame= new wxFrame(this,-1,_T("Restraints for: ")+wxString::FromAscii(mpMolecule->GetName().c_str()),
2704  wxDefaultPosition,wxSize(800,300));
2705 
2706  wxNotebook *notebook = new wxNotebook(frame, -1);
2707  // Bond lengths
2708  {
2709  wxGridCellAttr* cellAttrName = new wxGridCellAttr;
2710  cellAttrName->SetRenderer(new wxGridCellStringRenderer);
2711  cellAttrName->SetEditor(new wxGridCellTextEditor);
2712  wxGridCellAttr* cellAttrFloat = new wxGridCellAttr;
2713  cellAttrFloat->SetRenderer(new wxGridCellFloatRenderer(-1,3));
2714  cellAttrFloat->SetEditor(new wxGridCellFloatEditor);
2715  wxGridCellAttr* cellAttrFloatReadOnly = new wxGridCellAttr;
2716  cellAttrFloatReadOnly->SetRenderer(new wxGridCellFloatRenderer(-1,3));
2717  cellAttrFloatReadOnly->SetEditor(new wxGridCellFloatEditor);
2718  cellAttrFloatReadOnly->SetReadOnly();
2719 
2720  mpBondWin = new WXMolScrolledWindow(notebook,this,ID_WINDOW_BONDLENGTH);
2721  notebook->AddPage(mpBondWin, _T("Bond Lengths"), true);
2722  mpBondWin->CreateGrid(0,6);
2723  mpBondWin->SetColSize(0,80);
2724  mpBondWin->SetColAttr(0,cellAttrName);
2725  mpBondWin->SetColAttr(1,cellAttrName->Clone());
2726  mpBondWin->SetColAttr(2,cellAttrFloatReadOnly);
2727  mpBondWin->SetColAttr(3,cellAttrFloat);
2728  mpBondWin->SetColAttr(4,cellAttrFloat->Clone());
2729  mpBondWin->SetColAttr(5,cellAttrFloat->Clone());
2730  mpBondWin->SetColLabelValue(0,_T("Atom1"));
2731  mpBondWin->SetColLabelValue(1,_T("Atom2"));
2732  mpBondWin->SetColLabelValue(2,_T("Length"));
2733  mpBondWin->SetColLabelValue(3,_T("Restraint"));
2734  mpBondWin->SetColLabelValue(4,_T("Sigma"));
2735  mpBondWin->SetColLabelValue(5,_T("Delta"));
2736  mpBondWin->AutoSizeRows();
2737  }
2738  // Bond angles
2739  {
2740  wxGridCellAttr* cellAttrName = new wxGridCellAttr;
2741  cellAttrName->SetRenderer(new wxGridCellStringRenderer);
2742  cellAttrName->SetEditor(new wxGridCellTextEditor);
2743  wxGridCellAttr* cellAttrFloat = new wxGridCellAttr;
2744  cellAttrFloat->SetRenderer(new wxGridCellFloatRenderer(-1,3));
2745  cellAttrFloat->SetEditor(new wxGridCellFloatEditor);
2746  wxGridCellAttr* cellAttrFloatReadOnly = new wxGridCellAttr;
2747  cellAttrFloatReadOnly->SetRenderer(new wxGridCellFloatRenderer(-1,3));
2748  cellAttrFloatReadOnly->SetEditor(new wxGridCellFloatEditor);
2749  cellAttrFloatReadOnly->SetReadOnly();
2750 
2751  mpAngleWin = new WXMolScrolledWindow(notebook,this,ID_WINDOW_BONDANGLE);
2752  notebook->AddPage(mpAngleWin, _T("Bond Angles"), true);
2753  mpAngleWin->CreateGrid(0,7);
2754  mpAngleWin->SetColSize(0,80);
2755  mpAngleWin->SetColAttr(0,cellAttrName);
2756  mpAngleWin->SetColAttr(1,cellAttrName->Clone());
2757  mpAngleWin->SetColAttr(2,cellAttrName->Clone());
2758  mpAngleWin->SetColAttr(3,cellAttrFloatReadOnly);
2759  mpAngleWin->SetColAttr(4,cellAttrFloat);
2760  mpAngleWin->SetColAttr(5,cellAttrFloat->Clone());
2761  mpAngleWin->SetColAttr(6,cellAttrFloat->Clone());
2762  mpAngleWin->SetColLabelValue(0,_T("Atom1"));
2763  mpAngleWin->SetColLabelValue(1,_T("Atom2"));
2764  mpAngleWin->SetColLabelValue(2,_T("Atom3"));
2765  mpAngleWin->SetColLabelValue(3,_T("Angle"));
2766  mpAngleWin->SetColLabelValue(4,_T("Restraint"));
2767  mpAngleWin->SetColLabelValue(5,_T("Sigma"));
2768  mpAngleWin->SetColLabelValue(6,_T("Delta"));
2769  mpAngleWin->AutoSizeRows();
2770  }
2771  // Dihedral angles
2772  {
2773  wxGridCellAttr* cellAttrName = new wxGridCellAttr;
2774  cellAttrName->SetRenderer(new wxGridCellStringRenderer);
2775  cellAttrName->SetEditor(new wxGridCellTextEditor);
2776  wxGridCellAttr* cellAttrFloat = new wxGridCellAttr;
2777  cellAttrFloat->SetRenderer(new wxGridCellFloatRenderer(-1,3));
2778  cellAttrFloat->SetEditor(new wxGridCellFloatEditor);
2779  wxGridCellAttr* cellAttrFloatReadOnly = new wxGridCellAttr;
2780  cellAttrFloatReadOnly->SetRenderer(new wxGridCellFloatRenderer(-1,3));
2781  cellAttrFloatReadOnly->SetEditor(new wxGridCellFloatEditor);
2782  cellAttrFloatReadOnly->SetReadOnly();
2783 
2784  mpDihedralAngleWin = new WXMolScrolledWindow(notebook,this,ID_WINDOW_DIHEDRALANGLE);
2785  notebook->AddPage(mpDihedralAngleWin, _T("Dihedral Angles"), true);
2786  mpDihedralAngleWin->CreateGrid(0,8);
2787  mpDihedralAngleWin->SetColSize(0,80);
2788  mpDihedralAngleWin->SetColAttr(0,cellAttrName);
2789  mpDihedralAngleWin->SetColAttr(1,cellAttrName->Clone());
2790  mpDihedralAngleWin->SetColAttr(2,cellAttrName->Clone());
2791  mpDihedralAngleWin->SetColAttr(3,cellAttrName->Clone());
2792  mpDihedralAngleWin->SetColAttr(4,cellAttrFloatReadOnly);
2793  mpDihedralAngleWin->SetColAttr(5,cellAttrFloat);
2794  mpDihedralAngleWin->SetColAttr(6,cellAttrFloat->Clone());
2795  mpDihedralAngleWin->SetColAttr(7,cellAttrFloat->Clone());
2796  mpDihedralAngleWin->SetColLabelValue(0,_T("Atom1"));
2797  mpDihedralAngleWin->SetColLabelValue(1,_T("Atom2"));
2798  mpDihedralAngleWin->SetColLabelValue(2,_T("Atom3"));
2799  mpDihedralAngleWin->SetColLabelValue(3,_T("Atom4"));
2800  mpDihedralAngleWin->SetColLabelValue(4,_T("Angle"));
2801  mpDihedralAngleWin->SetColLabelValue(5,_T("Restraint"));
2802  mpDihedralAngleWin->SetColLabelValue(6,_T("Sigma"));
2803  mpDihedralAngleWin->SetColLabelValue(7,_T("Delta"));
2804  mpDihedralAngleWin->AutoSizeRows();
2805  }
2806  // Rigid groups
2807  {
2808  wxGridCellAttr* cellAttrName = new wxGridCellAttr;
2809  cellAttrName->SetRenderer(new wxGridCellStringRenderer);
2810  cellAttrName->SetEditor(new wxGridCellTextEditor);
2811 
2812  mpRigidGroupWin = new WXMolScrolledWindow(notebook,this,ID_WINDOW_RIGIDGROUP);
2813  notebook->AddPage(mpRigidGroupWin, _T("Rigid Groups"), true);
2814  mpRigidGroupWin->CreateGrid(0,1);
2815  mpRigidGroupWin->SetColMinimalWidth(0,600);
2816  mpRigidGroupWin->SetColSize(0,600);
2817  mpRigidGroupWin->SetColAttr(0,cellAttrName);
2818  mpRigidGroupWin->SetColLabelValue(0,_T("Atoms in Rigid Group"));
2819  //mpRigidGroupWin->ForceRefresh();
2820  //mpRigidGroupWin->AutoSizeRows();
2821  }
2822 
2823  //non-flip atoms
2824  {
2825  wxGridCellAttr* cellAttrName = new wxGridCellAttr;
2826  cellAttrName->SetReadOnly();
2827  cellAttrName->SetRenderer(new wxGridCellStringRenderer);
2828  cellAttrName->SetEditor(new wxGridCellTextEditor);
2829 
2830  mpNonFlipAtomWin = new WXMolScrolledWindow(notebook,this,ID_WINDOW_NONFLIPATOM);
2831  notebook->AddPage(mpNonFlipAtomWin, _T("Optically active atoms"), true);
2832  mpNonFlipAtomWin->CreateGrid(0,1);
2833  mpNonFlipAtomWin->SetColMinimalWidth(0,600);
2834  mpNonFlipAtomWin->SetColSize(0,600);
2835  mpNonFlipAtomWin->SetColAttr(0,cellAttrName);
2836  mpNonFlipAtomWin->SetColLabelValue(0,_T("Optically active atom"));
2837  }
2838  notebook->SetSelection(0);
2839  this->CrystUpdate(true);
2840  frame->Show(true);
2841  frame->Layout();
2842 }
2843 
2844 void WXMolecule::OnMenuRigidfyWithDihedralAngles(wxCommandEvent & WXUNUSED(event))
2845 {
2846  VFN_DEBUG_ENTRY("WXMolecule::OnMenuRigidfyWithDihedralAngles()",6)
2848  wxString msg;
2849  msg.Printf( _T("This will add all possible dihedral angles,\n")
2850  _T("in practice making the Molecule rigid\n\n")
2851  _T("Are you sure you want to proceed ?")
2852  );
2853 
2854  wxMessageDialog w(this,msg,_T("Warning !"),wxYES_NO|wxNO_DEFAULT|wxICON_EXCLAMATION);
2855  int result=w.ShowModal();
2856  if(wxID_YES==result) mpMolecule->RigidifyWithDihedralAngles();
2857 
2858  VFN_DEBUG_EXIT("WXMolecule::OnMenuRigidfyWithDihedralAngles()",6)
2859 }
2860 
2861 void WXMolecule::OnMenuSetDeltaSigma(wxCommandEvent &event)
2862 {
2863  VFN_DEBUG_ENTRY("WXMolecule::OnMenuSetDeltaSigma()",6)
2865  double sigma=0.01,delta=0.02;
2866  {
2867  wxString s;
2868  s.Printf(_T("%f"),delta);
2869  wxString title=_T("Choose 'delta' value");
2870  wxString info;
2871  info.Printf(_T("The 'delta' value is the allowed range \n")
2872  _T("(without penalty) around the expected value.\n\n")
2873  _T("It is by default equal to 0.02, in Angstroems for bond lengths,\n")
2874  _T("and in radians for angles (0.02rad = 1.15deg)\n\n")
2875  _T("DO NOT TRY TO CHANGE THE DEFAULT VALUE\n")
2876  _T("UNLESS YOU REALLY KNOW WHAT YOU ARE DOING\n")
2877  _T("Fox has been optimized with the default values...")
2878  );
2879  wxTextEntryDialog dialog(this,info,title,s,wxOK|wxCANCEL);
2880  dialog.SetTextValidator(wxTextValidator(wxFILTER_NUMERIC));
2881  if(wxID_OK!=dialog.ShowModal())
2882  {
2883  VFN_DEBUG_EXIT("WXMolecule::OnMenuSetDeltaSigma():Canceled",6)
2884  return;
2885  }
2886  dialog.GetValue().ToDouble(&delta);
2887  }
2888  {
2889  wxString s;
2890  s.Printf(_T("%f"),sigma);
2891  wxString title=_T("Choose 'sigma' value");
2892  wxString info;
2893  info.Printf(_T("The 'sigma' value is used to compute \n")
2894  _T("penalty)around the expected value\n\n")
2895  _T("It is by default equal to 0.01, in Angstroems for bond angles,\n")
2896  _T("and in radians for angles (0.01rad = 0.57deg)\n\n")
2897  _T("DO NOT TRY TO CHANGE THE DEFAULT VALUE\n")
2898  _T("UNLESS YOU REALLY KNOW WHAT YOU ARE DOING\n")
2899  _T("Fox has been optimized with the default values...")
2900  );
2901  wxTextEntryDialog dialog(this,info,title.c_str(),s,wxOK|wxCANCEL);
2902  dialog.SetTextValidator(wxTextValidator(wxFILTER_NUMERIC));
2903  if(wxID_OK!=dialog.ShowModal())
2904  {
2905  VFN_DEBUG_EXIT("WXMolecule::OnMenuSetDeltaSigma():Canceled",6)
2906  return;
2907  }
2908  dialog.GetValue().ToDouble(&sigma);
2909  }
2910  for(vector<MolBond*>::iterator pos=mpMolecule->GetBondList().begin();
2911  pos != mpMolecule->GetBondList().end();++pos)
2912  {
2913  (*pos)->SetLengthDelta(delta);
2914  (*pos)->SetLengthSigma(sigma);
2915  }
2916  for(vector<MolBondAngle*>::iterator pos=mpMolecule->GetBondAngleList().begin();
2917  pos != mpMolecule->GetBondAngleList().end();++pos)
2918  {
2919  (*pos)->SetAngleDelta(delta*DEG2RAD);
2920  (*pos)->SetAngleSigma(sigma*DEG2RAD);
2921  }
2922  for(vector<MolDihedralAngle*>::iterator pos=mpMolecule->GetDihedralAngleList().begin();
2923  pos != mpMolecule->GetDihedralAngleList().end();++pos)
2924  {
2925  //(*pos)->AngleDelta()=delta;
2926  //(*pos)->AngleSigma()=sigma;
2927  }
2928  mpMolecule->GetBondListClock().Click();
2929  this->CrystUpdate(true);
2930  VFN_DEBUG_EXIT("WXMolecule::OnMenuSetDeltaSigma()",6)
2931 }
2932 
2933 void WXMolecule::OnChangeCenterAtom(wxCommandEvent &event)
2934 {
2936  int choice;
2937  MolAtom *const at=WXDialogChooseFromVector(mpMolecule->GetAtomList(),
2938  (wxWindow*)this,"Choose a new Atom",choice);
2939  if(0==at) return;
2940  mpMolecule->SetCenterAtom(*at);
2941 }
2942 
2944 {
2945  VFN_DEBUG_ENTRY("WXMolecule::NotifyDeleteListWin()",6)
2946  if(win==mpBondWin)
2947  {
2948  VFN_DEBUG_MESSAGE("WXMolecule::NotifyDeleteListWin(): Bond List window",5)
2949  mpBondWin=0;
2950  mvpBond.clear();
2951  }
2952  if(win==mpAngleWin)
2953  {
2954  VFN_DEBUG_MESSAGE("WXMolecule::NotifyDeleteListWin(): Angle List window",5)
2955  mpAngleWin=0;
2956  mvpBondAngle.clear();
2957  }
2958  if(win==mpDihedralAngleWin)
2959  {
2960  VFN_DEBUG_MESSAGE("WXMolecule::NotifyDeleteListWin(): Dihedral Angle List window",5)
2961  mpDihedralAngleWin=0;
2962  mvpDihedralAngle.clear();
2963  }
2964  if(win==mpRigidGroupWin)
2965  {
2966  VFN_DEBUG_MESSAGE("WXMolecule::NotifyDeleteListWin(): Dihedral Angle List window",5)
2967  mpRigidGroupWin=0;
2968  mvpRigidGroup.clear();
2969  }
2970  if(win==mpNonFlipAtomWin)
2971  {
2972  VFN_DEBUG_MESSAGE("WXMolecule::NotifyDeleteListWin(): non-flip atom list window",5)
2973  mpNonFlipAtomWin=0;
2974  }
2975  VFN_DEBUG_EXIT("WXMolecule::NotifyDeleteListWin()",6)
2976 }
2977 void WXMolecule::UpdateUI(const bool lock)
2978 {
2979  if(lock) mMutex.Lock();
2980  VFN_DEBUG_ENTRY("WXMolecule::UpdateUI()",5)
2981  {
2982  unsigned long i=0;
2983  for(list<CellAtom>::iterator pos=mvpAtom.begin();pos!=mvpAtom.end();++pos)
2984  {
2985  if(pos->mNeedUpdateUI==true)
2986  {
2987  mIsSelfUpdating=true;
2988  mpAtomWin->SetCellValue(i, 0, wxString::FromAscii(pos->mName.c_str()));
2989  mpAtomWin->SetCellValue(i, 1, wxString::FromAscii(pos->mpScatteringPower->GetName().c_str()));
2990  wxString tmp;
2991  tmp.Printf(_T("%.3f"),pos->mX);
2992  mpAtomWin->SetCellValue(i, 2, tmp);
2993  tmp.Printf(_T("%.3f"),pos->mY);
2994  mpAtomWin->SetCellValue(i, 3, tmp);
2995  tmp.Printf(_T("%.3f"),pos->mZ);
2996  mpAtomWin->SetCellValue(i, 4, tmp);
2997  tmp.Printf(_T("%.3f"),pos->mOcc);
2998  mpAtomWin->SetCellValue(i, 5, tmp);
2999  mIsSelfUpdating=false;
3000  }
3001  ++i;
3002  }
3003  }
3004  if(0!=mpBondWin)
3005  {
3006  unsigned long i=0;
3007  for(list<CellBond>::iterator pos=mvpBond.begin();pos!=mvpBond.end();++pos)
3008  {
3009  if(pos->mNeedUpdateUI==true)
3010  {
3011  mIsSelfUpdating=true;
3012  mpBondWin->SetCellValue(i, 0, wxString::FromAscii(pos->mAtom1.c_str()));
3013  mpBondWin->SetCellValue(i, 1, wxString::FromAscii(pos->mAtom2.c_str()));
3014  wxString tmp;
3015  tmp.Printf(_T("%f"),pos->mLength);
3016  mpBondWin->SetCellValue(i, 2, tmp);
3017  tmp.Printf(_T("%f"),pos->mLength0);
3018  mpBondWin->SetCellValue(i, 3, tmp);
3019  tmp.Printf(_T("%f"),pos->mSigma);
3020  mpBondWin->SetCellValue(i, 4, tmp);
3021  tmp.Printf(_T("%f"),pos->mDelta);
3022  mpBondWin->SetCellValue(i, 5, tmp);
3023  mIsSelfUpdating=false;
3024  }
3025  ++i;
3026  }
3027  }
3028  if(0!=mpAngleWin)
3029  {
3030  unsigned long i=0;
3031  for(list<CellBondAngle>::iterator pos=mvpBondAngle.begin();pos!=mvpBondAngle.end();++pos)
3032  {
3033  if(pos->mNeedUpdateUI==true)
3034  {
3035  mIsSelfUpdating=true;
3036  mpAngleWin->SetCellValue(i, 0, wxString::FromAscii(pos->mAtom1.c_str()));
3037  mpAngleWin->SetCellValue(i, 1, wxString::FromAscii(pos->mAtom2.c_str()));
3038  mpAngleWin->SetCellValue(i, 2, wxString::FromAscii(pos->mAtom3.c_str()));
3039  wxString tmp;
3040  tmp.Printf(_T("%f"),pos->mAngle*RAD2DEG);
3041  mpAngleWin->SetCellValue(i, 3, tmp);
3042  tmp.Printf(_T("%f"),pos->mAngle0*RAD2DEG);
3043  mpAngleWin->SetCellValue(i, 4, tmp);
3044  tmp.Printf(_T("%f"),pos->mSigma*RAD2DEG);
3045  mpAngleWin->SetCellValue(i, 5, tmp);
3046  tmp.Printf(_T("%f"),pos->mDelta*RAD2DEG);
3047  mpAngleWin->SetCellValue(i, 6, tmp);
3048  mIsSelfUpdating=false;
3049  }
3050  ++i;
3051  }
3052  }
3053  if(0!=mpDihedralAngleWin)
3054  {
3055  unsigned long i=0;
3056  for(list<CellDihedralAngle>::iterator pos=mvpDihedralAngle.begin();pos!=mvpDihedralAngle.end();++pos)
3057  {
3058  if(pos->mNeedUpdateUI==true)
3059  {
3060  mIsSelfUpdating=true;
3061  mpDihedralAngleWin->SetCellValue(i, 0, wxString::FromAscii(pos->mAtom1.c_str()));
3062  mpDihedralAngleWin->SetCellValue(i, 1, wxString::FromAscii(pos->mAtom2.c_str()));
3063  mpDihedralAngleWin->SetCellValue(i, 2, wxString::FromAscii(pos->mAtom3.c_str()));
3064  mpDihedralAngleWin->SetCellValue(i, 3, wxString::FromAscii(pos->mAtom4.c_str()));
3065  wxString tmp;
3066  tmp.Printf(_T("%f"),pos->mAngle*RAD2DEG);
3067  mpDihedralAngleWin->SetCellValue(i, 4, tmp);
3068  tmp.Printf(_T("%f"),pos->mAngle0*RAD2DEG);
3069  mpDihedralAngleWin->SetCellValue(i, 5, tmp);
3070  tmp.Printf(_T("%f"),pos->mSigma*RAD2DEG);
3071  mpDihedralAngleWin->SetCellValue(i, 6, tmp);
3072  tmp.Printf(_T("%f"),pos->mDelta*RAD2DEG);
3073  mpDihedralAngleWin->SetCellValue(i, 7, tmp);
3074  mIsSelfUpdating=false;
3075  }
3076  ++i;
3077  }
3078  }
3079  if(0!=mpRigidGroupWin)
3080  {
3081  unsigned long i=0;
3082  for(list<CellRigidGroup>::iterator pos=mvpRigidGroup.begin();pos!=mvpRigidGroup.end();++pos)
3083  {
3084  if(pos->mNeedUpdateUI==true)
3085  {
3086  mIsSelfUpdating=true;
3087  mpRigidGroupWin->SetCellValue(i, 0, wxString::FromAscii(pos->mpGroup->GetName().c_str()));
3088  mIsSelfUpdating=false;
3089  }
3090  ++i;
3091  }
3092  }
3093  if(0!=mpNonFlipAtomWin)
3094  {
3095  //for(unsigned long i=0;i<
3096  // mpNonFlipAtomWin->SetCellValue(v[i]->GetName(), i, 1);
3097  }
3098  if(mpMolecule->GetCenterAtom()!=0)
3099  mpFieldCenterAtom->SetValue(mpMolecule->GetCenterAtom()->GetName());
3100  else mpFieldCenterAtom->SetValue("No atom !");
3101 
3102  //if(mpMolecule->GetOption(3).GetChoice()==0) mpFieldCenterAtom->Enable(false);
3103  //else mpFieldCenterAtom->Enable(true);
3104 
3105  if(lock) mMutex.Unlock();
3106  this->WXRefinableObj::UpdateUI(lock);
3107  VFN_DEBUG_EXIT("WXMolecule::UpdateUI()",5)
3108 }
3109 
3110 bool WXMolecule::Enable(bool e)
3111 {
3112  if(0!=mpAtomWin) mpAtomWin ->Enable(e);
3113  if(0!=mpBondWin) mpBondWin ->Enable(e);
3114  if(0!=mpAngleWin) mpAngleWin ->Enable(e);
3115  if(0!=mpDihedralAngleWin)mpDihedralAngleWin->Enable(e);
3116  if(0!=mpRigidGroupWin) mpRigidGroupWin ->Enable(e);
3117  return this->::wxWindow::Enable(e);
3118 }
3119 } //namespace
The namespace which includes all objects (crystallographic and algorithmic) in ObjCryst++.
Definition: doc-main.h:25
void WXCrystValidateAllUserInput()
This function validates all user input (in a WXField) not yet taken into account, if needs be.
Definition: wxCryst.cpp:258
const RefParType * gpRefParTypeObjCryst
Top RefParType for the ObjCryst++ library.
void ExpandAtomGroupRecursive(MolAtom *atom, const map< MolAtom *, set< MolAtom * > > &connect, set< MolAtom * > &atomlist, const MolAtom *finalAtom)
Build recursively a list of atoms, starting from a one atom, and given a connectivity table.
Definition: Molecule.cpp:154
T * WXDialogChooseFromRegistry(ObjRegistry< T > &reg, wxWindow *parent, const string &message, int &choice)
This function allows to pick up one object in a registry.
The basic atom scatterer, in a crystal.
Definition: Atom.h:58
MolAtom : atom inside a Molecule.
Definition: Molecule.h:59
Bond between two atoms, also a restraint on the associated bond length.
Definition: Molecule.h:165
Bond angle restraint between 3 atoms.
Definition: Molecule.h:271
Abstract Base Class to describe the scattering power of any Scatterer component in a crystal.
Restraint: generic class for a restraint of a given model.
Definition: RefinableObj.h:201
virtual const string & GetName() const
Name of the object.
Simple chronometer class, with microsecond precision.
Definition: Chronometer.h:35
output a number as a formatted integer:
output a number as a formatted float:
Class to automatically assign a unique wxID to each window.
Definition: wxCryst.h:75
Abstract base class for all objects in wxCryst.
Definition: wxCryst.h:128
CrystMutex mMutex
Mutex used to lock data when preparing to update the UI in non-main thread.
Definition: wxCryst.h:189
void OnToggleCollapse(wxCommandEvent &WXUNUSED(event))
Only display the title, and collapse everything else.
Definition: wxCryst.cpp:818
A field for a parameter.
Definition: wxCryst.h:453
Class to pick one choice...
Definition: wxCryst.h:483
void SetValue(const string &)
Used by the owner to change the name of the choice.
Definition: wxCryst.cpp:764
wx class for MolAtom objects
Definition: wxMolecule.h:44
wx class for MolBond objects
Definition: wxMolecule.h:62
wx class for MolBondAngle objects
Definition: wxMolecule.h:85
std::list< CellRigidGroup > mvpRigidGroup
Displayed list of Dihedral angles.
Definition: wxMolecule.h:256
void NotifyDeleteListWin(WXMolScrolledWindow *win)
Notify that either the bond, bond angle or dihedral angle list window has been destroyed.
std::list< CellDihedralAngle > mvpDihedralAngle
Displayed list of Dihedral angles.
Definition: wxMolecule.h:243
virtual void CrystUpdate(const bool updateUI=false, const bool mutexlock=false)
Get new values to be displayed from the underlying object, and raise flag if an UI update is necessar...
WXFieldChoice * mpFieldCenterAtom
Center atom.
Definition: wxMolecule.h:261
std::list< CellAtom > mvpAtom
Displayed list of atoms.
Definition: wxMolecule.h:188
std::list< CellBondAngle > mvpBondAngle
Displayed list of bond angle.
Definition: wxMolecule.h:224
std::list< CellBond > mvpBond
Displayed list of bonds, in the order they appear.
Definition: wxMolecule.h:206
virtual void UpdateUI(const bool mutexlock=false)
Update the User Interface, if necessary.
bool mIsSelfUpdating
Flag to indicate whether we are updating values in the wxGrid data.
Definition: wxMolecule.h:259
Structure to store the Atom parameters.
Definition: wxMolecule.h:177
Structure to store the bond current values.
Definition: wxMolecule.h:192
Structure to store the bond angles current values.
Definition: wxMolecule.h:209
Structure to store the dihedral angles current values.
Definition: wxMolecule.h:227
virtual void CrystUpdate(const bool updateUI=false, const bool mutexlock=false)
Get new values to be displayed from the underlying object, and raise flag if an UI update is necessar...
virtual void UpdateUI(const bool mutexlock=false)
Update the User Interface, if necessary.