23 #include "cctbx/sgtbx/space_group.h"
24 #include <boost/format.hpp>
27 #include "wx/wxprec.h"
34 #include "wx/dcbuffer.h"
35 #include "wx/config.h"
36 #include "wx/notebook.h"
37 #include "wx/progdlg.h"
38 #include "wx/filename.h"
40 #include "ObjCryst/wxCryst/wxPowderPattern.h"
41 #include "ObjCryst/wxCryst/wxRadiation.h"
42 #include "ObjCryst/RefinableObj/Simplex.h"
43 #include "ObjCryst/RefinableObj/LSQNumObj.h"
44 #include "ObjCryst/ObjCryst/PowderPatternBackgroundBayesianMinimiser.h"
45 #include "ObjCryst/Quirks/VFNStreamFormat.h"
46 #include "ObjCryst/Quirks/Chronometer.h"
68 BEGIN_EVENT_TABLE(WXRadiation, wxWindow)
69 EVT_UPDATE_UI(ID_CRYST_UPDATEUI, WXRadiation::OnUpdateUI)
72 WXRadiation::WXRadiation(wxWindow *parent, Radiation* rad):
73 WXCrystObjBasic(parent),mpRadiation(rad)
75 VFN_DEBUG_ENTRY(
"WXRadiation::WXRadiation()",6)
78 mpSizer=new wxBoxSizer(wxVERTICAL);
79 wxSizer *pSizer1=new wxBoxSizer(wxHORIZONTAL);
80 wxSizer *pSizer2=new wxBoxSizer(wxHORIZONTAL);
82 mpFieldRadType= new WXFieldOption(this,-1,&(mpRadiation->mRadiationType));
83 pSizer1->Add(mpFieldRadType,0);
84 mList.Add(mpFieldRadType);
86 mpFieldWavelengthType= new WXFieldOption(this,-1,&(mpRadiation->mWavelengthType));
87 pSizer1->Add(mpFieldWavelengthType,0);
88 mList.Add(mpFieldWavelengthType);
90 WXCrystObjBasic* pFieldWavelength
91 =mpRadiation->GetPar(mpRadiation->mWavelength.data()).WXCreate(this);
92 pSizer1->Add(pFieldWavelength,0);
93 mList.Add(pFieldWavelength);
95 WXFieldPar<REAL> *polarRate=new WXFieldPar<REAL>(this,"Linear Polar Rate:",-1,
96 &(mpRadiation->mLinearPolarRate));
97 pSizer2->Add(polarRate,0,wxALIGN_LEFT);
100 WXCrystObjBasic* pFieldXRayTubeDlambda=mpRadiation->GetPar("XRayTubeDeltaLambda").WXCreate(this);
102 pSizer2->Add(pFieldXRayTubeDlambda,0,wxALIGN_LEFT|wxRESERVE_SPACE_EVEN_IF_HIDDEN);
103 mList.Add(pFieldXRayTubeDlambda);
105 WXCrystObjBasic* pFieldXRayTubeAlpha2Alpha1=mpRadiation->GetPar("XRayTubeAlpha2Alpha1Ratio").WXCreate(this);
106 pSizer2->Add(pFieldXRayTubeAlpha2Alpha1,0,wxALIGN_LEFT|wxRESERVE_SPACE_EVEN_IF_HIDDEN);
107 mList.Add(pFieldXRayTubeAlpha2Alpha1);
109 mpSizer->Add(pSizer1,0);
110 mpSizer->Add(pSizer2,0);
112 this->CrystUpdate(true);
113 this->SetSizer(mpSizer);
114 mpSizer->SetSizeHints(this);
116 VFN_DEBUG_EXIT("WXRadiation::WXRadiation()",6)
118 WXRadiation::~WXRadiation()
120 mpRadiation->WXNotifyDelete();
130 if(
true==wxThread::IsMain()) this->
UpdateUI(lock);
133 wxUpdateUIEvent event(ID_CRYST_UPDATEUI);
134 wxPostEvent(
this,event);
144 void WXRadiation::OnUpdateUI(wxUpdateUIEvent& event)
152 class WXProfileFitting:
public wxWindow
155 WXProfileFitting(wxWindow *parent,PowderPattern *pPattern,PowderPatternDiffraction *pDiff=0);
158 void OnFit(wxCommandEvent &event);
159 void OnExploreSpacegroups(wxCommandEvent &event);
161 PowderPattern *mpPattern;
162 PowderPatternDiffraction *mpDiff;
163 wxCheckListBox *mpFitCheckList;
167 DECLARE_EVENT_TABLE()
175 static const long ID_POWDER_MENU_COMP_ADDBACKGD_BAYESIAN= WXCRYST_ID();
176 static const long ID_POWDER_MENU_COMP_ADDBACKGD= WXCRYST_ID();
177 static const long ID_POWDER_MENU_COMP_ADDCRYST= WXCRYST_ID();
178 static const long ID_POWDER_MENU_COMP_REMOVE= WXCRYST_ID();
179 static const long ID_POWDER_MENU_GRAPH= WXCRYST_ID();
180 static const long ID_POWDER_MENU_SAVETEXT= WXCRYST_ID();
181 static const long ID_POWDER_MENU_SIMULATE= WXCRYST_ID();
182 static const long ID_POWDER_MENU_EXPORT= WXCRYST_ID();
183 static const long ID_POWDER_MENU_EXPORT_FULLPROF= WXCRYST_ID();
184 static const long ID_POWDER_MENU_IMPORT_FULLPROF= WXCRYST_ID();
185 static const long ID_POWDER_MENU_IMPORT_PSI_DMC= WXCRYST_ID();
186 static const long ID_POWDER_MENU_IMPORT_ILL_D1A5= WXCRYST_ID();
187 static const long ID_POWDER_MENU_IMPORT_XDD= WXCRYST_ID();
188 static const long ID_POWDER_MENU_IMPORT_CPI= WXCRYST_ID();
189 static const long ID_POWDER_MENU_IMPORT_FULLPROF4= WXCRYST_ID();
190 static const long ID_POWDER_MENU_IMPORT_MULTIDETECTORLLBG42=WXCRYST_ID();
191 static const long ID_POWDER_MENU_IMPORT_2THETAOBSSIGMA= WXCRYST_ID();
192 static const long ID_POWDER_MENU_IMPORT_2THETAOBS= WXCRYST_ID();
193 static const long ID_POWDER_MENU_IMPORT_TOFISISXYSIGMA= WXCRYST_ID();
194 static const long ID_POWDER_MENU_IMPORT_GSAS= WXCRYST_ID();
195 static const long ID_POWDER_MENU_IMPORT_CIF= WXCRYST_ID();
196 static const long ID_POWDER_MENU_FITSCALE_R= WXCRYST_ID();
197 static const long ID_POWDER_MENU_FITSCALE_RW= WXCRYST_ID();
198 static const long ID_POWDER_MENU_WAVELENGTH= WXCRYST_ID();
199 static const long ID_POWDER_MENU_WAVELENGTH_XRAY= WXCRYST_ID();
200 static const long ID_POWDER_MENU_WAVELENGTH_NEUTRON= WXCRYST_ID();
201 static const long ID_POWDER_MENU_WAVELENGTH_NEUTRON_TOF= WXCRYST_ID();
202 static const long ID_POWDER_MENU_WAVELENGTH_SET= WXCRYST_ID();
203 static const long ID_POWDER_MENU_WAVELENGTH_SET_AG= WXCRYST_ID();
204 static const long ID_POWDER_MENU_WAVELENGTH_SET_MO= WXCRYST_ID();
205 static const long ID_POWDER_MENU_WAVELENGTH_SET_CU= WXCRYST_ID();
206 static const long ID_POWDER_MENU_WAVELENGTH_SET_FE= WXCRYST_ID();
207 static const long ID_POWDER_MENU_WAVELENGTH_SET_CO= WXCRYST_ID();
208 static const long ID_POWDER_MENU_WAVELENGTH_SET_CR= WXCRYST_ID();
209 static const long ID_POWDER_MENU_WAVELENGTH_SET_AGA1= WXCRYST_ID();
210 static const long ID_POWDER_MENU_WAVELENGTH_SET_MOA1= WXCRYST_ID();
211 static const long ID_POWDER_MENU_WAVELENGTH_SET_CUA1= WXCRYST_ID();
212 static const long ID_POWDER_MENU_WAVELENGTH_SET_FEA1= WXCRYST_ID();
213 static const long ID_POWDER_MENU_WAVELENGTH_SET_COA1= WXCRYST_ID();
214 static const long ID_POWDER_MENU_WAVELENGTH_SET_CRA1= WXCRYST_ID();
215 static const long ID_POWDER_MENU_ADD_2THETA_EXCLUDE= WXCRYST_ID();
216 static const long ID_POWDER_MENU_LEBAIL= WXCRYST_ID();
217 static const long ID_POWDERBACKGROUND_IMPORT= WXCRYST_ID();
218 static const long ID_POWDERBACKGROUND_OPTIMIZEBAYESIAN= WXCRYST_ID();
219 static const long ID_POWDERDIFF_CRYSTAL= WXCRYST_ID();
220 static const long ID_POWDERDIFF_SAVEHKLFCALC= WXCRYST_ID();
221 static const long ID_POWDER_GRAPH_NEW_PATTERN= WXCRYST_ID();
222 static const long ID_POWDERTEXTURE_MENU_ADDPHASE= WXCRYST_ID();
223 static const long ID_POWDERTEXTURE_MENU_DELETEPHASE= WXCRYST_ID();
224 static const long ID_POWDERPATTERN_MENU_COMPONENTS= WXCRYST_ID();
225 static const long ID_POWDERPATTERN_MENU_PATTERN= WXCRYST_ID();
226 static const long ID_POWDERDIFF_PROFILE_DEPV= WXCRYST_ID();
227 static const long ID_POWDER_GRAPH_WIN= WXCRYST_ID();
230 BEGIN_EVENT_TABLE(WXPowderPattern, wxWindow)
232 EVT_MENU(ID_POWDER_MENU_EXPORT_FULLPROF, WXPowderPattern::OnMenuExport)
233 EVT_MENU(ID_REFOBJ_MENU_OBJ_SAVE, WXRefinableObj::OnMenuSave)
234 EVT_MENU(ID_REFOBJ_MENU_OBJ_LOAD, WXRefinableObj::OnMenuLoad)
235 EVT_MENU(ID_REFOBJ_MENU_PAR_FIXALL, WXRefinableObj::OnMenuFixAllPar)
236 EVT_MENU(ID_REFOBJ_MENU_PAR_UNFIXALL, WXRefinableObj::OnMenuUnFixAllPar)
237 EVT_MENU(ID_POWDER_MENU_COMP_ADDBACKGD, WXPowderPattern::OnMenuAddCompBackgd)
238 EVT_MENU(ID_POWDER_MENU_COMP_ADDBACKGD_BAYESIAN, WXPowderPattern::OnMenuAddCompBackgdBayesian)
239 EVT_MENU(ID_POWDER_MENU_COMP_ADDCRYST, WXPowderPattern::OnMenuAddCompCryst)
240 EVT_MENU(ID_POWDER_MENU_COMP_REMOVE, WXPowderPattern::OnMenuRemoveComp)
241 EVT_MENU(ID_POWDER_MENU_SAVETEXT, WXPowderPattern::OnMenuSaveText)
242 EVT_MENU(ID_POWDER_MENU_SIMULATE, WXPowderPattern::OnMenuSimulate)
243 EVT_MENU(ID_POWDER_MENU_IMPORT_FULLPROF, WXPowderPattern::OnMenuImportPattern)
244 EVT_MENU(ID_POWDER_MENU_IMPORT_PSI_DMC, WXPowderPattern::OnMenuImportPattern)
245 EVT_MENU(ID_POWDER_MENU_IMPORT_ILL_D1A5, WXPowderPattern::OnMenuImportPattern)
246 EVT_MENU(ID_POWDER_MENU_IMPORT_XDD, WXPowderPattern::OnMenuImportPattern)
247 EVT_MENU(ID_POWDER_MENU_IMPORT_CPI, WXPowderPattern::OnMenuImportPattern)
248 EVT_MENU(ID_POWDER_MENU_IMPORT_FULLPROF4, WXPowderPattern::OnMenuImportPattern)
249 EVT_MENU(ID_POWDER_MENU_IMPORT_MULTIDETECTORLLBG42,WXPowderPattern::OnMenuImportPattern)
250 EVT_MENU(ID_POWDER_MENU_IMPORT_2THETAOBSSIGMA, WXPowderPattern::OnMenuImportPattern)
251 EVT_MENU(ID_POWDER_MENU_IMPORT_2THETAOBS, WXPowderPattern::OnMenuImportPattern)
252 EVT_MENU(ID_POWDER_MENU_IMPORT_TOFISISXYSIGMA, WXPowderPattern::OnMenuImportPattern)
253 EVT_MENU(ID_POWDER_MENU_IMPORT_GSAS, WXPowderPattern::OnMenuImportPattern)
254 EVT_MENU(ID_POWDER_MENU_IMPORT_CIF, WXPowderPattern::OnMenuImportPattern)
255 EVT_MENU(ID_POWDER_MENU_WAVELENGTH_SET, WXPowderPattern::OnMenuSetWavelength)
256 EVT_MENU(ID_POWDER_MENU_WAVELENGTH_XRAY, WXPowderPattern::OnMenuSetWavelength)
257 EVT_MENU(ID_POWDER_MENU_WAVELENGTH_NEUTRON, WXPowderPattern::OnMenuSetWavelength)
258 EVT_MENU(ID_POWDER_MENU_WAVELENGTH_NEUTRON_TOF, WXPowderPattern::OnMenuSetWavelength)
259 EVT_MENU(ID_POWDER_MENU_WAVELENGTH_SET_AG, WXPowderPattern::OnMenuSetWavelength)
260 EVT_MENU(ID_POWDER_MENU_WAVELENGTH_SET_MO, WXPowderPattern::OnMenuSetWavelength)
261 EVT_MENU(ID_POWDER_MENU_WAVELENGTH_SET_CU, WXPowderPattern::OnMenuSetWavelength)
262 EVT_MENU(ID_POWDER_MENU_WAVELENGTH_SET_FE, WXPowderPattern::OnMenuSetWavelength)
263 EVT_MENU(ID_POWDER_MENU_WAVELENGTH_SET_CO, WXPowderPattern::OnMenuSetWavelength)
264 EVT_MENU(ID_POWDER_MENU_WAVELENGTH_SET_CR, WXPowderPattern::OnMenuSetWavelength)
265 EVT_MENU(ID_POWDER_MENU_WAVELENGTH_SET_AGA1, WXPowderPattern::OnMenuSetWavelength)
266 EVT_MENU(ID_POWDER_MENU_WAVELENGTH_SET_MOA1, WXPowderPattern::OnMenuSetWavelength)
267 EVT_MENU(ID_POWDER_MENU_WAVELENGTH_SET_CUA1, WXPowderPattern::OnMenuSetWavelength)
268 EVT_MENU(ID_POWDER_MENU_WAVELENGTH_SET_FEA1, WXPowderPattern::OnMenuSetWavelength)
269 EVT_MENU(ID_POWDER_MENU_WAVELENGTH_SET_COA1, WXPowderPattern::OnMenuSetWavelength)
270 EVT_MENU(ID_POWDER_MENU_WAVELENGTH_SET_CRA1, WXPowderPattern::OnMenuSetWavelength)
271 EVT_MENU(ID_POWDER_MENU_GRAPH, WXPowderPattern::OnMenuShowGraph)
272 EVT_MENU(ID_POWDER_MENU_FITSCALE_R, WXPowderPattern::OnMenuFitScaleForR)
273 EVT_MENU(ID_POWDER_MENU_FITSCALE_RW, WXPowderPattern::OnMenuFitScaleForRw)
274 EVT_MENU(ID_POWDER_MENU_ADD_2THETA_EXCLUDE, WXPowderPattern::OnMenuAddExclude)
276 EVT_UPDATE_UI(ID_CRYST_UPDATEUI, WXRefinableObj::OnUpdateUI)
279 WXPowderPattern::WXPowderPattern(wxWindow *parent, PowderPattern* pow):
280 WXRefinableObj(parent,pow),mpPowderPattern(pow),mpGraph(0),
281 mChi2(0.0),mGoF(0.0),mRwp(0.0),mRp(0.0)
283 VFN_DEBUG_MESSAGE(
"WXPowderPattern::WXPowderPattern()",6)
284 mpWXTitle->SetForegroundColour(wxColour(255,0,0));
285 mpWXTitle->SetSize(400,-1);
287 mpMenuBar->AddMenu("Data",ID_REFOBJ_MENU_OBJ);
291 mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_OBJ,ID_POWDER_MENU_SAVETEXT,
292 "Save pattern (text)");
293 mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_OBJ,ID_POWDER_MENU_SIMULATE,
294 "Simulation mode (no obs. pattern)");
295 mpMenuBar->GetMenu(ID_REFOBJ_MENU_OBJ).AppendSeparator();
296 mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_OBJ,ID_POWDER_MENU_IMPORT_CIF,
297 "Import CIF Powder Data");
298 mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_OBJ,ID_POWDER_MENU_IMPORT_GSAS,
299 "Import GSAS Data(CONS-ESD,CONS6STD,RALF-ALT)");
300 mpMenuBar->GetMenu(ID_REFOBJ_MENU_OBJ).AppendSeparator();
301 mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_OBJ,ID_POWDER_MENU_IMPORT_2THETAOBSSIGMA,
302 "Import 2Theta-Obs-Sigma Pattern");
303 mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_OBJ,ID_POWDER_MENU_IMPORT_2THETAOBS,
304 "Import 2Theta-Obs Pattern");
305 mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_OBJ,ID_POWDER_MENU_IMPORT_FULLPROF,
306 "Import Fullprof Pattern");
307 mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_OBJ,ID_POWDER_MENU_IMPORT_FULLPROF4,
308 "Import FullProf format
#4");
309 mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_OBJ,ID_POWDER_MENU_IMPORT_XDD,
310 "Import Xdd Pattern");
311 mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_OBJ,ID_POWDER_MENU_IMPORT_CPI,
312 "Import Sietronics CPI Pattern");
313 mpMenuBar->GetMenu(ID_REFOBJ_MENU_OBJ).AppendSeparator();
314 mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_OBJ,ID_POWDER_MENU_IMPORT_ILL_D1A5,
315 "Import Neutron ILL(D1A-D1B) Pattern (D1A5)");
316 mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_OBJ,ID_POWDER_MENU_IMPORT_PSI_DMC,
317 "Import PSI(DMC) Pattern");
318 mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_OBJ,ID_POWDER_MENU_IMPORT_MULTIDETECTORLLBG42,
319 "Import Neutron Multi-Detector Format (LLB G42)");
320 mpMenuBar->GetMenu(ID_REFOBJ_MENU_OBJ).AppendSeparator();
321 mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_OBJ,ID_POWDER_MENU_IMPORT_TOFISISXYSIGMA,
322 "Import Neutron TOF ISIS X Y Sigma");
323 mpMenuBar->AddMenu("Export",ID_POWDER_MENU_EXPORT);
324 mpMenuBar->AddMenuItem(ID_POWDER_MENU_EXPORT,ID_POWDER_MENU_EXPORT_FULLPROF,
325 "Export to Fullprof");
326 mpMenuBar->AddMenu("Parameters",ID_REFOBJ_MENU_PAR);
327 mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_PAR,ID_REFOBJ_MENU_PAR_FIXALL,"Fix all");
328 //mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_PAR,ID_REFOBJ_MENU_PAR_UNFIXALL,"Unfix all");
329 mpMenuBar->AddMenu("Phases",ID_POWDERPATTERN_MENU_COMPONENTS);
330 mpMenuBar->AddMenuItem(ID_POWDERPATTERN_MENU_COMPONENTS,
331 ID_POWDER_MENU_COMP_ADDBACKGD_BAYESIAN,
332 "Add Background (Bayesian, automatic)");
333 mpMenuBar->AddMenuItem(ID_POWDERPATTERN_MENU_COMPONENTS,
334 ID_POWDER_MENU_COMP_ADDBACKGD,
335 "Add user-supplied Background ");
336 mpMenuBar->AddMenuItem(ID_POWDERPATTERN_MENU_COMPONENTS,ID_POWDER_MENU_COMP_ADDCRYST,
337 "Add Crystalline Phase");
338 mpMenuBar->AddMenuItem(ID_POWDERPATTERN_MENU_COMPONENTS,ID_POWDER_MENU_COMP_REMOVE,
339 "Remove background or crystalline phase");
340 mpMenuBar->AddMenu("Radiation",ID_POWDER_MENU_WAVELENGTH);
341 mpMenuBar->AddMenuItem(ID_POWDER_MENU_WAVELENGTH,
342 ID_POWDER_MENU_WAVELENGTH_NEUTRON,
344 mpMenuBar->AddMenuItem(ID_POWDER_MENU_WAVELENGTH,
345 ID_POWDER_MENU_WAVELENGTH_NEUTRON_TOF,
346 "Neutron Time Of Flight");
347 mpMenuBar->AddMenuItem(ID_POWDER_MENU_WAVELENGTH,
348 ID_POWDER_MENU_WAVELENGTH_XRAY,
350 mpMenuBar->AddMenuItem(ID_POWDER_MENU_WAVELENGTH,
351 ID_POWDER_MENU_WAVELENGTH_SET,
352 "Monochromatic Wavelength");
353 mpMenuBar->AddMenuItem(ID_POWDER_MENU_WAVELENGTH,
354 ID_POWDER_MENU_WAVELENGTH_SET_AG,
355 "X-Ray Tube Ag Ka12");
356 mpMenuBar->AddMenuItem(ID_POWDER_MENU_WAVELENGTH,
357 ID_POWDER_MENU_WAVELENGTH_SET_AGA1,
358 "X-Ray Tube Ag Ka1");
359 mpMenuBar->AddMenuItem(ID_POWDER_MENU_WAVELENGTH,
360 ID_POWDER_MENU_WAVELENGTH_SET_MO,
361 "X-Ray Tube Mo Ka12");
362 mpMenuBar->AddMenuItem(ID_POWDER_MENU_WAVELENGTH,
363 ID_POWDER_MENU_WAVELENGTH_SET_MOA1,
364 "X-Ray Tube Mo Ka1");
365 mpMenuBar->AddMenuItem(ID_POWDER_MENU_WAVELENGTH,
366 ID_POWDER_MENU_WAVELENGTH_SET_CU,
367 "X-Ray Tube Cu Ka12");
368 mpMenuBar->AddMenuItem(ID_POWDER_MENU_WAVELENGTH,
369 ID_POWDER_MENU_WAVELENGTH_SET_CUA1,
370 "X-Ray Tube Cu Ka1");
371 mpMenuBar->AddMenuItem(ID_POWDER_MENU_WAVELENGTH,
372 ID_POWDER_MENU_WAVELENGTH_SET_FE,
373 "X-Ray Tube Fe Ka12");
374 mpMenuBar->AddMenuItem(ID_POWDER_MENU_WAVELENGTH,
375 ID_POWDER_MENU_WAVELENGTH_SET_FEA1,
376 "X-Ray Tube Fe Ka1");
377 mpMenuBar->AddMenuItem(ID_POWDER_MENU_WAVELENGTH,
378 ID_POWDER_MENU_WAVELENGTH_SET_CO,
379 "X-Ray Tube Co Ka12");
380 mpMenuBar->AddMenuItem(ID_POWDER_MENU_WAVELENGTH,
381 ID_POWDER_MENU_WAVELENGTH_SET_COA1,
382 "X-Ray Tube Co Ka1");
383 mpMenuBar->AddMenuItem(ID_POWDER_MENU_WAVELENGTH,
384 ID_POWDER_MENU_WAVELENGTH_SET_CR,
385 "X-Ray Tube Cr Ka12");
386 mpMenuBar->AddMenuItem(ID_POWDER_MENU_WAVELENGTH,
387 ID_POWDER_MENU_WAVELENGTH_SET_CRA1,
388 "X-Ray Tube Cr Ka1");
389 mpMenuBar->AddMenu("Pattern",ID_POWDERPATTERN_MENU_PATTERN);
390 mpMenuBar->AddMenuItem(ID_POWDERPATTERN_MENU_PATTERN,ID_POWDER_MENU_GRAPH,
392 mpMenuBar->AddMenuItem(ID_POWDERPATTERN_MENU_PATTERN,ID_POWDER_MENU_FITSCALE_R,
394 mpMenuBar->AddMenuItem(ID_POWDERPATTERN_MENU_PATTERN,ID_POWDER_MENU_FITSCALE_RW,
396 mpMenuBar->AddMenuItem(ID_POWDERPATTERN_MENU_PATTERN,
397 ID_POWDER_MENU_ADD_2THETA_EXCLUDE,
398 "Add excluded region");
399 mpMenuBar->GetMenu(ID_POWDERPATTERN_MENU_PATTERN).AppendSeparator();
400 mpMenuBar->AddMenuItem(ID_POWDERPATTERN_MENU_PATTERN,
401 ID_POWDER_MENU_LEBAIL,
402 "Fit profile + Le Bail extract");
403 //mpSizer->SetItemMinSize(mpMenuBar,
404 // mpMenuBar->GetSize().GetWidth(),
405 // mpMenuBar->GetSize().GetHeight());
407 mpSizer->Add(mpPowderPattern->mRadiation.WXCreate(this),0);
408 mList.Add(mpPowderPattern->mRadiation.WXGet());
409 // Correction to 2Theta
410 wxBoxSizer* thetaCorrSizer=new wxBoxSizer(wxHORIZONTAL);
412 WXCrystObjBasic* fieldZero
413 =mpPowderPattern->GetPar(&(mpPowderPattern->mXZero)).WXCreate(this);
414 fieldZero->SetToolTip(_T("Zero shift of peaks\n")
415 _T("2Theta = 2Theta_Bragg + Zero\n"));
416 WXCrystObjBasic* fieldThetaDispl
417 =mpPowderPattern->GetPar(&(mpPowderPattern->m2ThetaDisplacement)).WXCreate(this);
418 fieldThetaDispl->SetToolTip(_T("Peak shift due to sample displacement:\n")
419 _T("2Theta = 2Theta_Bragg + Displacement/cos(Theta)"));
420 WXCrystObjBasic* fieldThetaTransp
421 =mpPowderPattern->GetPar(&(mpPowderPattern->m2ThetaTransparency)).WXCreate(this);
422 fieldThetaTransp->SetToolTip(_T("Zero shift of the peak 2theta positions\n")
423 _T("2Theta = 2Theta_Bragg + Transparency*sin(Theta)"));
425 thetaCorrSizer->Add(fieldZero,0);
426 thetaCorrSizer->Add(fieldThetaDispl,0);
427 thetaCorrSizer->Add(fieldThetaTransp,0);
428 mList.Add(fieldZero);
429 mList.Add(fieldThetaDispl);
430 mList.Add(fieldThetaTransp);
431 mpSizer->Add(thetaCorrSizer);
432 // Time of Flight parameters
433 wxBoxSizer* tofSizer=new wxBoxSizer(wxHORIZONTAL);
434 WXCrystObjBasic* fieldDIFC=mpPowderPattern->GetPar(&(mpPowderPattern->mDIFC)).WXCreate(this);
435 WXCrystObjBasic* fieldDIFA=mpPowderPattern->GetPar(&(mpPowderPattern->mDIFA)).WXCreate(this);
436 fieldDIFA->SetToolTip(_T("Peak position (time, in microseconds):\n")
437 _T("t = DIFA * d_hkl + DIFC * d_hkl^2 + ZERO"));
438 fieldDIFC->SetToolTip(_T("Peak position (time, in microseconds):\n")
439 _T("t = DIFA * d_hkl + DIFC * d_hkl^2 + ZERO"));
440 tofSizer->Add(fieldDIFC,0);
441 tofSizer->Add(fieldDIFA,0);
442 mList.Add(fieldDIFC);
443 mList.Add(fieldDIFA);
444 mpSizer->Add(tofSizer);
445 // Cylindrical absorption correction
446 WXCrystObjBasic* fieldMuR=mpPowderPattern->GetPar(&(mpPowderPattern->mMuR)).WXCreate(this);
447 fieldMuR->SetToolTip(_T("Cylindrical absorption correction parameter (muR)"));
449 mpSizer->Add(fieldMuR);
451 // Max Sin(theta/Lambda)
452 WXFieldPar<REAL> *maxSiThOvLa=
453 new WXFieldPar<REAL>(this,"Max Sin(theta)/lambda:",-1,
454 &(mpPowderPattern->mMaxSinThetaOvLambda));
455 mpSizer->Add(maxSiThOvLa,0,wxALIGN_LEFT);
456 mList.Add(maxSiThOvLa);
457 maxSiThOvLa->SetToolTip(_T("Maximum sin(theta)/lambda=1/2d\n")
458 _T("For global optimization, the default value of ")
459 _T("0.25 (2A resolution) should be sufficient.\n")
460 _T("Use larger values if necessary (0.4(1.25A), 0.5(1A))")
461 _T("but keep in mind that the number of reflections (and")
462 _T("therefore the computing time) varies as [sin(theta/lambda)]^3..."));
464 wxBoxSizer* pStats=new wxBoxSizer(wxHORIZONTAL);
466 WXFieldPar<REAL> *pWXFieldChi2=new WXFieldPar<REAL>(this,"Chi^2",-1,&mChi2,140);
467 pStats->Add(pWXFieldChi2 ,0,wxALIGN_CENTER);
468 mList.Add(pWXFieldChi2);
469 pWXFieldChi2->SetToolTip(_T("Chi^2=SUM[(Obs_i-Calc_i)^2/Sigma_i^2]"));
470 dynamic_cast<WXFieldParBase *>(pWXFieldChi2)->SetFormat(_T("%10.2f"));
472 WXFieldPar<REAL> *pWXFieldGof=new WXFieldPar<REAL>(this,"GoF",-1,&mGoF,90);
473 pStats->Add(pWXFieldGof ,0,wxALIGN_CENTER);
474 mList.Add(pWXFieldGof);
475 pWXFieldGof->SetToolTip(_T("GoF=Chi^2/NbPoints"));
476 dynamic_cast<WXFieldParBase *>(pWXFieldGof)->SetFormat(_T("%8.3f"));
478 WXFieldPar<REAL> *pWXFieldRwp=new WXFieldPar<REAL>(this,"Rwp",-1,&mRwp,70);
479 pStats->Add(pWXFieldRwp ,0,wxALIGN_CENTER);
480 mList.Add(pWXFieldRwp);
481 pWXFieldRwp->SetToolTip(_T("Full profile R-factor (weighted)\n")
482 _T("Will use integrated profiles if option is set."));
483 dynamic_cast<WXFieldParBase *>(pWXFieldRwp)->SetFormat(_T("%8.4f"));
485 WXFieldPar<REAL> *pWXFieldRp=new WXFieldPar<REAL>(this,"Rp",-1,&mRp,70);
486 pStats->Add(pWXFieldRp ,0,wxALIGN_CENTER);
487 mList.Add(pWXFieldRp);
488 pWXFieldRp->SetToolTip(_T("Full profile R-factor (unweighted)\n")
489 _T("Will use integrated profiles if option is set."));
490 dynamic_cast<WXFieldParBase *>(pWXFieldRp)->SetFormat(_T("%8.4f"));
491 //pStats->SetSizeHints(this);
494 mpSizer->Add(pStats);
496 mpWXComponent=mpPowderPattern
497 ->mPowderPatternComponentRegistry.WXCreate(this);
498 mpSizer->Add(mpWXComponent,0,wxALIGN_LEFT);
499 mList.Add(mpWXComponent);
501 VFN_DEBUG_MESSAGE("WXPowderPattern::WXPowderPattern():1",6)
502 this->CrystUpdate(true);
504 mPowderPatternWasPreviouslyEmpty = true;
505 if(!wxConfigBase::Get()->HasEntry(_T("PowderPattern/BOOL/Automatically open powder pattern graph")))
506 wxConfigBase::Get()->Write(_T("PowderPattern/BOOL/Automatically open powder pattern graph"), false);
510 wxConfigBase::Get()->Read(_T("PowderPattern/BOOL/Automatically open powder pattern graph"), &val);
513 wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED,ID_POWDER_MENU_GRAPH);
514 wxPostEvent(this,event);
518 mPowderPatternWasPreviouslyEmpty=false;
522 VFN_DEBUG_MESSAGE("WXPowderPattern::WXPowderPattern():End",6)
525 void WXPowderPattern::CrystUpdate(const bool uui,const bool lock)
527 VFN_DEBUG_ENTRY("WXPowderPattern::CrystUpdate()",7)
529 WXCrystValidateAllUserInput();
530 if(lock) mMutex.Lock();
532 if(mpPowderPattern->GetNbPoint()<=0)
534 if(lock) mMutex.Unlock();
535 this->WXRefinableObj::CrystUpdate(uui,lock);
536 return;// nothing to display yet
541 if(mPowderPatternWasPreviouslyEmpty)
543 wxConfigBase::Get()->Read(_T("PowderPattern/BOOL/Automatically open powder pattern graph"), &val);
545 if(mPowderPatternWasPreviouslyEmpty && val)
547 // We are supposed to automatically open powder pattern graph, but this could not be done
548 // when initializing this window because there were no points.
549 // WXPowderPattern::CrystUpdate() will be called again from WXPowderPattern::OnMenuShowGraph()
550 mPowderPatternWasPreviouslyEmpty = false;
551 wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED,ID_POWDER_MENU_GRAPH);
552 wxPostEvent(this,event);
553 if(lock) mMutex.Unlock();
557 // Will force re-generating reflection list if the wavelength,
558 // or lattice par, or the spacegroup has changed.
559 VFN_DEBUG_MESSAGE("WXPowderPattern::CrystUpdate()",7)
560 mpPowderPattern->Prepare();
561 VFN_DEBUG_MESSAGE("WXPowderPattern::CrystUpdate()",7)
563 mChi2=mpPowderPattern->GetChi2_Option();
564 if(mpPowderPattern->mNbPointUsed>0)
565 mGoF=mpPowderPattern->GetChi2()/mpPowderPattern->mNbPointUsed;
567 //cout<<"WXPowderPattern::CrystUpdate():"<<mpPowderPattern->GetChi2()<<"/"<<mpPowderPattern->mNbPointUsed<<"="<<mGoF<<endl;
568 mRwp=mpPowderPattern->GetRw();
569 mRp=mpPowderPattern->GetR();
573 CrystVector_REAL tmp;
574 mpPowderPattern->CalcPowderPattern();
575 tmp=mpPowderPattern->GetPowderPatternVariance();
576 for(long i=0;i<tmp.numElements();i++)
578 if(tmp(i)<0) tmp(i)=0;
579 else tmp(i)=sqrt(tmp(i));
581 mpGraph->SetPattern( mpPowderPattern->GetPowderPatternX(),
582 mpPowderPattern->GetPowderPatternObs(),
583 mpPowderPattern->GetPowderPatternCalc(),
585 mpPowderPattern->GetChi2Cumul(1));
587 if(lock) mMutex.Unlock();
588 this->WXRefinableObj::CrystUpdate(uui,lock);
591 VFN_DEBUG_EXIT("WXPowderPattern::CrystUpdate()",7)
594 void WXPowderPattern::OnMenuAddCompBackgd(wxCommandEvent & WXUNUSED(event))
596 VFN_DEBUG_MESSAGE("WXPowderPattern::OnMenuAddCompBackgd()",6)
597 WXCrystValidateAllUserInput();
598 const unsigned int nb=mpPowderPattern->GetNbPowderPatternComponent();
600 for(unsigned int i=0;i<nb;i++)
601 if(mpPowderPattern->GetPowderPatternComponent(i).GetClassName()=="PowderPatternBackground")
608 wxMessageDialog dialog(this,_T("You already have one background !\n")
609 _T(" Are you sure you want to add one ?"),
610 _T("Warning : Duplicate Background !"),
611 wxYES_NO|wxICON_HAND|wxNO_DEFAULT);
612 if(wxID_YES!=dialog.ShowModal())
615 PowderPatternBackground *backgdData= new PowderPatternBackground;
616 mpPowderPattern->AddPowderPatternComponent(*backgdData);
617 if(mpGraph!=0) mpPowderPattern->Prepare();//else this will be done when opening the graph
618 wxTheApp->GetTopWindow()->Layout();
619 wxTheApp->GetTopWindow()->SendSizeEvent();
622 void WXPowderPattern::OnMenuAddCompBackgdBayesian(wxCommandEvent & WXUNUSED(event))
624 VFN_DEBUG_ENTRY("WXPowderPattern::OnMenuAddCompBackgdBayesian()",6)
625 WXCrystValidateAllUserInput();
626 const unsigned int nb=mpPowderPattern->GetNbPowderPatternComponent();
628 for(unsigned int i=0;i<nb;i++)
629 if(mpPowderPattern->GetPowderPatternComponent(i).GetClassName()=="PowderPatternBackground")
636 wxMessageDialog dialog(this,_T("You already have one background !\n")
637 _T(" Are you sure you want to add one ?"),
638 _T("Warning : Duplicate Background !"),
639 wxYES_NO|wxICON_HAND|wxNO_DEFAULT);
640 if(wxID_YES!=dialog.ShowModal())
644 long nbPointSpline=20;
645 wxString mes=_T("Number of Interpolation Points");
647 s.Printf(_T("%ld"),nbPointSpline);
648 wxTextEntryDialog dialog(this,mes,_T("Automatic Bayesian (David-Sivia) Background"),
650 dialog.SetTextValidator(wxTextValidator(wxFILTER_DIGITS));
651 if(wxID_OK!=dialog.ShowModal())
653 VFN_DEBUG_EXIT("WXPowderPattern::OnMenuAddCompBackgdBayesian():Canceled",6)
656 dialog.GetValue().ToLong(&nbPointSpline);
657 if(nbPointSpline<=1)nbPointSpline=2;
659 wxProgressDialog dlgProgress(_T("Automatic Bayesian Background"),_T("Automatic Background: Initializing..."),
660 4,this,wxPD_AUTO_HIDE|wxPD_ELAPSED_TIME|wxPD_CAN_ABORT|wxPD_APP_MODAL);
662 PowderPatternBackground *pBckgd= new PowderPatternBackground;
663 VFN_DEBUG_MESSAGE("WXPowderPattern::OnMenuAddCompBackgdBayesian()",6)
664 mpPowderPattern->AddPowderPatternComponent(*pBckgd);
665 VFN_DEBUG_MESSAGE("WXPowderPattern::OnMenuAddCompBackgdBayesian()",6)
667 CrystVector_REAL x(nbPointSpline),backgd(nbPointSpline);
668 const CrystVector_REAL *pObs=&(pBckgd->GetParentPowderPattern().GetPowderPatternObs());
669 const unsigned long nbPoint=pBckgd->GetParentPowderPattern().GetNbPoint();
670 const float xmin=pBckgd->GetParentPowderPattern().GetPowderPatternX()(0),
671 xmax=pBckgd->GetParentPowderPattern().GetPowderPatternX()(nbPoint-1);
672 for(int i=0;i<nbPointSpline;i++)
673 {// xmax is not necessarily > xmin, but in the right order (TOF)
674 x(i)=xmin+(xmax-xmin)/(REAL)(nbPointSpline-1)*REAL(i);
675 REAL x1=xmin+(xmax-xmin)/(REAL)(nbPointSpline-1)*REAL(i-.2);
676 REAL x2=xmin+(xmax-xmin)/(REAL)(nbPointSpline-1)*REAL(i+.2);
677 long n1=(long)(pBckgd->GetParentPowderPattern().X2Pixel(x1));
678 long n2=(long)(pBckgd->GetParentPowderPattern().X2Pixel(x2));
680 if(n2>(long)nbPoint)n2=nbPoint;
681 backgd(i)=(*pObs)(n1);
682 for(long j=n1;j<n2;j++)
683 if((*pObs)(j)<backgd(i))backgd(i)=(*pObs)(j);
685 pBckgd->SetInterpPoints(x,backgd);
687 if(mpGraph!=0) mpPowderPattern->Prepare();//else this will be done when opening the graph
689 pBckgd->UnFixAllPar();
690 pBckgd->GetOption(0).SetChoice(0);//linear
691 if(dlgProgress.Update(1,_T("Automatic Background: Optimizing Linear Model..."))==false) return;
692 pBckgd->OptimizeBayesianBackground();
693 pBckgd->GetOption(0).SetChoice(1);//spline
694 if(dlgProgress.Update(2,_T("Automatic Background: Optimizing Spline Model..."))==false) return;
695 pBckgd->OptimizeBayesianBackground();
698 wxTheApp->GetTopWindow()->Layout();
699 wxTheApp->GetTopWindow()->SendSizeEvent();
700 VFN_DEBUG_EXIT("WXPowderPattern::OnMenuAddCompBackgdBayesian()",6)
703 void WXPowderPattern::OnMenuAddCompCryst(wxCommandEvent & WXUNUSED(event))
705 VFN_DEBUG_ENTRY("WXPowderPattern::OnMenuAddCompCryst()",10)
706 WXCrystValidateAllUserInput();
707 PowderPatternDiffraction * diffData=new PowderPatternDiffraction;
709 Crystal *cryst=dynamic_cast<Crystal*>
710 ( WXDialogChooseFromRegistry(gCrystalRegistry,(wxWindow*)this,
711 "Choose a Crystal Structure:",choice));
712 if(0==cryst) {delete diffData;return;}
713 VFN_DEBUG_MESSAGE("WXPowderPattern::OnMenuAddCompCryst()",10)
714 diffData->SetCrystal(*cryst);
715 VFN_DEBUG_MESSAGE("WXPowderPattern::OnMenuAddCompCryst()",10)
716 mpPowderPattern->AddPowderPatternComponent(*diffData);
717 VFN_DEBUG_MESSAGE("WXPowderPattern::OnMenuAddCompCryst()",10)
718 if(diffData->GetRadiation().GetWavelengthType()==WAVELENGTH_TOF)
720 VFN_DEBUG_MESSAGE("WXPowderPattern::OnMenuAddCompCryst()",10)
721 //wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED,ID_POWDERDIFF_PROFILE_DEPV);
722 //wxPostEvent(diffData->WXGet(),event);
723 ReflectionProfileDoubleExponentialPseudoVoigt *p=
724 new ReflectionProfileDoubleExponentialPseudoVoigt
725 (diffData->GetCrystal());
726 diffData->SetProfile(p);
728 VFN_DEBUG_MESSAGE("WXPowderPattern::OnMenuAddCompCryst()",10)
729 if(mpGraph!=0) mpPowderPattern->Prepare();//else this will be done when opening the graph
730 wxTheApp->GetTopWindow()->Layout();
731 wxTheApp->GetTopWindow()->SendSizeEvent();
733 VFN_DEBUG_EXIT("WXPowderPattern::OnMenuAddCompCryst()",10)
736 void WXPowderPattern::OnMenuRemoveComp(wxCommandEvent & WXUNUSED(event))
738 VFN_DEBUG_ENTRY("WXPowderPattern::OnMenuRemoveComp()",10)
739 WXCrystValidateAllUserInput();
741 for(unsigned int i=0;i<this->GetPowderPattern().GetNbPowderPatternComponent();i++)
743 PowderPatternComponent &comp=this->GetPowderPattern().GetPowderPatternComponent(i);
744 if(comp.GetClassName()=="PowderPatternBackground")
745 comp.SetName("Background");
748 PowderPatternDiffraction* pdiff=dynamic_cast<PowderPatternDiffraction*> (&comp);
749 if(pdiff) comp.SetName("Crystal:" + pdiff->GetCrystal().GetName());
750 else cout<<"WXPowderPattern::OnMenuRemoveComp(): could not recognize:"<<comp.GetClassName()<<":"<<comp.GetName()<<endl;
754 PowderPatternComponent *comp= WXDialogChooseFromRegistry(this->GetPowderPattern().mPowderPatternComponentRegistry,(wxWindow*)this,
755 "Choose a component to remove:",choice);
758 VFN_DEBUG_EXIT("WXPowderPattern::OnMenuRemoveComp(): Canceled",10)
761 VFN_DEBUG_MESSAGE("WXPowderPattern::OnMenuRemoveComp()",10)
762 this->GetPowderPattern().RemovePowderPatternComponent(*comp);
764 VFN_DEBUG_MESSAGE("WXPowderPattern::OnMenuRemoveComp()",10)
765 if(mpGraph!=0) mpPowderPattern->Prepare();//else this will be done when opening the graph
766 wxTheApp->GetTopWindow()->Layout();
767 wxTheApp->GetTopWindow()->SendSizeEvent();
769 VFN_DEBUG_EXIT("WXPowderPattern::OnMenuRemoveComp()",10)
773 class WXPowderPatternGraphFrame :public wxFrame
776 WXPowderPatternGraphFrame(wxWindow *parent, wxWindowID id, const wxString& title, const wxPoint& pos = wxDefaultPosition, const wxSize& size = wxDefaultSize, long style = wxDEFAULT_FRAME_STYLE, const wxString& name = wxFrameNameStr) :
777 wxFrame(parent, id, title, pos, size, style, name)
779 ~WXPowderPatternGraphFrame()
781 gvWindowPosition[ID_POWDER_GRAPH_WIN] = make_pair(this->GetScreenPosition(), this->GetSize());
785 void WXPowderPattern::OnMenuShowGraph(wxCommandEvent & WXUNUSED(event))
787 VFN_DEBUG_MESSAGE("WXPowderPattern::OnMenuShowGraph()"<<mpGraph,6)
788 if(mpGraph!=0) return;
789 if(mpPowderPattern->GetNbPoint()<=0) return;
790 WXCrystValidateAllUserInput();
791 mpPowderPattern->Prepare();
793 if(gvWindowPosition.count(ID_POWDER_GRAPH_WIN))
794 frame = new WXPowderPatternGraphFrame(this, ID_POWDER_GRAPH_WIN, wxString::FromAscii(mpPowderPattern->GetName().c_str()),
795 gvWindowPosition[ID_POWDER_GRAPH_WIN].first,
796 gvWindowPosition[ID_POWDER_GRAPH_WIN].second, wxCLOSE_BOX | wxRESIZE_BORDER | wxCAPTION | wxMINIMIZE_BOX | wxMAXIMIZE_BOX);//wxFRAME_FLOAT_ON_PARENT
798 frame = new WXPowderPatternGraphFrame(this, ID_POWDER_GRAPH_WIN, wxString::FromAscii(mpPowderPattern->GetName().c_str()),
799 wxDefaultPosition, wxSize(500, 300), wxCLOSE_BOX | wxRESIZE_BORDER | wxCAPTION | wxMINIMIZE_BOX | wxMAXIMIZE_BOX);//wxFRAME_FLOAT_ON_PARENT
800 mpGraph = new WXPowderPatternGraph(frame,this);
802 wxSizer *ps=new wxBoxSizer(wxHORIZONTAL);
803 ps->Add(mpGraph,1,wxEXPAND);
805 frame->SetAutoLayout(true);
807 frame->CreateStatusBar(2);
810 this->CrystUpdate(true);
811 //frame->SetStatusText("");
814 void WXPowderPattern::OnMenuSaveText(wxCommandEvent & WXUNUSED(event))
816 VFN_DEBUG_MESSAGE("WXPowderPattern::OnMenuSaveText()",6)
817 WXCrystValidateAllUserInput();
818 wxFileDialog save(this,_T("Choose a file"),_T(""),_T(""),_T("*.txt"),wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
819 if(save.ShowModal() != wxID_OK) return;
821 ofstream out(save.GetPath().ToAscii());
822 if(!out) return;//:TODO:
823 mpPowderPattern->PrintObsCalcData(out);
827 void WXPowderPattern::OnMenuSimulate(wxCommandEvent & WXUNUSED(event))
829 VFN_DEBUG_ENTRY("WXPowderPattern::OnMenuSimulate()",6)
830 WXCrystValidateAllUserInput();
831 double min=0.,max=120.;
834 wxTextEntryDialog dialog(this,_T("2Theta Min"),
835 _T("Enter minimum 2Theta (degrees)"),_T("5"),wxOK | wxCANCEL);
836 dialog.SetTextValidator(wxTextValidator(wxFILTER_NUMERIC));
837 if(wxID_OK!=dialog.ShowModal())
839 VFN_DEBUG_EXIT("WXPowderPattern::OnMenuSimulate():Cancelled",6)
842 dialog.GetValue().ToDouble(&min);
846 wxTextEntryDialog dialog(this,_T("2Theta Max"),
847 _T("Enter maximum 2Theta (degrees)"),_T("100"),wxOK | wxCANCEL);
848 dialog.SetTextValidator(wxTextValidator(wxFILTER_NUMERIC));
849 if(wxID_OK!=dialog.ShowModal())
851 VFN_DEBUG_EXIT("WXPowderPattern::OnMenuSimulate():Cancelled",6)
854 dialog.GetValue().ToDouble(&max);
857 wxTextEntryDialog dialog(this,_T("Number of points"),
858 _T("Enter the number of points"),_T("1000"),wxOK | wxCANCEL);
859 dialog.SetTextValidator(wxTextValidator(wxFILTER_DIGITS));
860 if(wxID_OK!=dialog.ShowModal())
862 VFN_DEBUG_EXIT("WXPowderPattern::OnMenuSimulate():Cancelled",6)
865 dialog.GetValue().ToLong(&nbPoints);
867 CrystVector_REAL newObs(nbPoints);
868 mpPowderPattern->SetPowderPatternPar(min*DEG2RAD,(max-min)/(nbPoints-1)*DEG2RAD,nbPoints);
869 newObs=1;//we must not have 0 in case a scale factor is fitted...
870 newObs(0)=0.01;//Avoid having the same value for ALL points for scaling the graph.
871 if(mpPowderPattern->GetNbPowderPatternComponent()>0)
873 // Use the calculated pattern, for indexing simulation
874 newObs=mpPowderPattern->GetPowderPatternCalc();
876 for(long i=0;i<newObs.numElements();++i)
877 newObs(i) += sqrt(newObs(i))*(2*rand()/(REAL)RAND_MAX-1);
879 mpPowderPattern->SetPowderPatternObs(newObs);
880 VFN_DEBUG_EXIT("WXPowderPattern::OnMenuSimulate()",6)
883 void WXPowderPattern::OnMenuImportPattern(wxCommandEvent &event)
885 VFN_DEBUG_MESSAGE("WXPowderPattern::OnMenuImportPattern()",6)
886 wxFileDialog open(this,_T("Choose a file"),_T(""),_T(""),_T("*.*"),wxFD_OPEN | wxFD_FILE_MUST_EXIST);
887 if(open.ShowModal() != wxID_OK) return;
888 if(event.GetId()==(long)ID_POWDER_MENU_IMPORT_FULLPROF)
889 mpPowderPattern->ImportPowderPatternFullprof(string(open.GetPath().ToAscii()));
890 if(event.GetId()==(long)ID_POWDER_MENU_IMPORT_PSI_DMC)
891 mpPowderPattern->ImportPowderPatternPSI_DMC(string(open.GetPath().ToAscii()));
892 if(event.GetId()==(long)ID_POWDER_MENU_IMPORT_ILL_D1A5)
893 mpPowderPattern->ImportPowderPatternILL_D1A5(string(open.GetPath().ToAscii()));
894 if(event.GetId()==(long)ID_POWDER_MENU_IMPORT_XDD)
895 mpPowderPattern->ImportPowderPatternXdd(string(open.GetPath().ToAscii()));
896 if(event.GetId()==(long)ID_POWDER_MENU_IMPORT_CPI)
897 mpPowderPattern->ImportPowderPatternSietronicsCPI(string(open.GetPath().ToAscii()));
898 if(event.GetId()==(long)ID_POWDER_MENU_IMPORT_FULLPROF4)
899 mpPowderPattern->ImportPowderPatternFullprof4(string(open.GetPath().ToAscii()));
900 if(event.GetId()==(long)ID_POWDER_MENU_IMPORT_MULTIDETECTORLLBG42)
901 mpPowderPattern->ImportPowderPatternMultiDetectorLLBG42(string(open.GetPath().ToAscii()));
902 if(event.GetId()==(long)ID_POWDER_MENU_IMPORT_2THETAOBSSIGMA)
903 mpPowderPattern->ImportPowderPattern2ThetaObsSigma(string(open.GetPath().ToAscii()));
904 if(event.GetId()==(long)ID_POWDER_MENU_IMPORT_2THETAOBS)
905 mpPowderPattern->ImportPowderPattern2ThetaObs(string(open.GetPath().ToAscii()));
906 if(event.GetId()==(long)ID_POWDER_MENU_IMPORT_TOFISISXYSIGMA)
907 mpPowderPattern->ImportPowderPatternTOF_ISIS_XYSigma(string(open.GetPath().ToAscii()));
908 if(event.GetId()==(long)ID_POWDER_MENU_IMPORT_GSAS)
909 mpPowderPattern->ImportPowderPatternGSAS(string(open.GetPath().ToAscii()));
910 if(event.GetId()==(long)ID_POWDER_MENU_IMPORT_CIF)
912 ifstream fin (open.GetPath().ToAscii());
915 throw ObjCrystException("WXPowderPattern::OnMenuImportPattern(): Error opening file for input:"+string(open.GetPath().ToAscii()));
917 ObjCryst::CIF cif(fin,true,true);
918 mpPowderPattern->ImportPowderPatternCIF(cif);
921 wxConfigBase::Get()->Read(_T("PowderPattern/BOOL/Automatically open powder pattern graph"), &val);
924 wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED,ID_POWDER_MENU_GRAPH);
925 wxPostEvent(this,event);
929 void WXPowderPattern::OnMenuFitScaleForR(wxCommandEvent & WXUNUSED(event))
931 if(0==mpGraph) return;
932 WXCrystValidateAllUserInput();
933 mpPowderPattern->FitScaleFactorForR();//FitScaleFactorForIntegratedR
934 this->CrystUpdate(true);
937 void WXPowderPattern::OnMenuFitScaleForRw(wxCommandEvent & WXUNUSED(event))
939 if(0==mpGraph) return;
940 WXCrystValidateAllUserInput();
941 mpPowderPattern->FitScaleFactorForRw();//FitScaleFactorForIntegratedRw
942 this->CrystUpdate(true);
946 void WXPowderPattern::OnMenuSetWavelength(wxCommandEvent & event)
948 WXCrystValidateAllUserInput();
949 // this looks stupid. In fact, if a user changed the wavelength in the
950 // corresponding field, this is (unfortunately) not applied to the
951 // components automagically. So we need this function to do the job...
952 if(event.GetId()== ID_POWDER_MENU_WAVELENGTH_XRAY)
953 mpPowderPattern->SetRadiationType(RAD_XRAY);
954 if(event.GetId()== ID_POWDER_MENU_WAVELENGTH_NEUTRON)
955 mpPowderPattern->SetRadiationType(RAD_NEUTRON);
956 if(event.GetId()== ID_POWDER_MENU_WAVELENGTH_NEUTRON_TOF)
958 mpPowderPattern->SetRadiationType(RAD_NEUTRON);
959 mpPowderPattern->GetRadiation().SetWavelengthType(WAVELENGTH_TOF);
961 if(event.GetId()== ID_POWDER_MENU_WAVELENGTH_SET)
964 wxTextEntryDialog dialog(this,_T("new Wavelength)"),
965 _T("Enter new Wavelength (Angstroems)"),_T("1"),wxOK | wxCANCEL);
966 dialog.SetTextValidator(wxTextValidator(wxFILTER_NUMERIC));
967 if(wxID_OK!=dialog.ShowModal())
969 VFN_DEBUG_EXIT("WXPowderPattern))OnMenuSetWavelength())Monochromatic)Cancelled",6)
972 dialog.GetValue().ToDouble(&lambda);
973 mpPowderPattern->SetWavelength(lambda);
975 if(event.GetId()== ID_POWDER_MENU_WAVELENGTH_SET_AG)
976 mpPowderPattern->SetWavelength("Ag");
977 if(event.GetId()== ID_POWDER_MENU_WAVELENGTH_SET_MO)
978 mpPowderPattern->SetWavelength("Mo");
979 if(event.GetId()== ID_POWDER_MENU_WAVELENGTH_SET_CU)
980 mpPowderPattern->SetWavelength("Cu");
981 if(event.GetId()== ID_POWDER_MENU_WAVELENGTH_SET_FE)
982 mpPowderPattern->SetWavelength("Fe");
983 if(event.GetId()== ID_POWDER_MENU_WAVELENGTH_SET_CO)
984 mpPowderPattern->SetWavelength("Co");
985 if(event.GetId()== ID_POWDER_MENU_WAVELENGTH_SET_CR)
986 mpPowderPattern->SetWavelength("Cr");
987 if(event.GetId()== ID_POWDER_MENU_WAVELENGTH_SET_AGA1)
988 mpPowderPattern->SetWavelength("AgA1");
989 if(event.GetId()== ID_POWDER_MENU_WAVELENGTH_SET_MOA1)
990 mpPowderPattern->SetWavelength("MoA1");
991 if(event.GetId()== ID_POWDER_MENU_WAVELENGTH_SET_CUA1)
992 mpPowderPattern->SetWavelength("CuA1");
993 if(event.GetId()== ID_POWDER_MENU_WAVELENGTH_SET_FEA1)
994 mpPowderPattern->SetWavelength("FeA1");
995 if(event.GetId()== ID_POWDER_MENU_WAVELENGTH_SET_COA1)
996 mpPowderPattern->SetWavelength("CoA1");
997 if(event.GetId()== ID_POWDER_MENU_WAVELENGTH_SET_CRA1)
998 mpPowderPattern->SetWavelength("CrA1");
999 this->CrystUpdate(true);
1002 void WXPowderPattern::OnMenuAddExclude(wxCommandEvent & WXUNUSED(event))
1004 WXCrystValidateAllUserInput();
1008 wxString txt=_T("Enter Min 2theta to exclude (degrees):");
1009 if(mpPowderPattern->GetRadiation().GetWavelengthType()==WAVELENGTH_TOF)
1010 txt=_T("Enter Min 2theta to exclude (microseconds):");
1011 wxTextEntryDialog dialog(this,_T("Min"),txt,_T("0"),wxOK | wxCANCEL);
1012 dialog.SetTextValidator(wxTextValidator(wxFILTER_NUMERIC));
1013 if(wxID_OK!=dialog.ShowModal())
1015 VFN_DEBUG_EXIT("WXPowderPattern::OnMenuAddExclude():Cancelled",6)
1018 dialog.GetValue().ToDouble(&min);
1022 wxString txt=_T("Enter Max 2theta to exclude (degrees):");
1023 if(mpPowderPattern->GetRadiation().GetWavelengthType()==WAVELENGTH_TOF)
1024 txt=_T("Enter Max 2theta to exclude (microseconds):");
1025 wxTextEntryDialog dialog(this,_T("Max"),txt,_T("5"),wxOK | wxCANCEL);
1026 dialog.SetTextValidator(wxTextValidator(wxFILTER_NUMERIC));
1027 if(wxID_OK!=dialog.ShowModal())
1029 VFN_DEBUG_EXIT("WXPowderPattern::OnMenuAddExclude():Cancelled",6)
1032 dialog.GetValue().ToDouble(&max);
1036 VFN_DEBUG_EXIT("WXPowderPattern::OnMenuAddExclude():Stupid user.",6)
1039 if(mpPowderPattern->GetRadiation().GetWavelengthType()==WAVELENGTH_TOF)
1040 mpPowderPattern->AddExcludedRegion(min,max);
1041 else mpPowderPattern->AddExcludedRegion(min*DEG2RAD,max*DEG2RAD);
1044 void WXPowderPattern::OnMenuLeBail(wxCommandEvent& event)
1047 wxFrame *pFrame=new wxFrame(this,-1,_T("Profile Fitting"));
1048 WXProfileFitting *pFit;
1049 pFit=new WXProfileFitting(pFrame,&(this->GetPowderPattern()));
1052 cout<<"Beginning refinement"<<endl;
1054 lsq.SetRefinedObj(this->GetPowderPattern(),0,true,true);
1055 lsq.PrepareRefParList(true);
1056 lsq.SetParIsFixed(gpRefParTypeObjCryst,true);
1057 lsq.SetParIsFixed(gpRefParTypeScatt,false);
1058 lsq.SetParIsFixed(gpRefParTypeScattDataScale,false);
1059 //lsq.SetParIsUsed(gpRefParTypeScattDataProfile,true);
1060 //lsq.SetParIsUsed(gpRefParTypeScattDataCorrPos,true);
1061 //lsq.SetParIsUsed(gpRefParTypeScattDataBackground,true);
1062 //lsq.SetParIsUsed(gpRefParTypeUnitCell,true);
1063 try {lsq.Refine(10,true,false);}
1064 catch(const ObjCrystException &except){};
1065 cout<<"Finishing refinement"<<endl;
1066 this->GetPowderPattern().UpdateDisplay();
1070 void WXPowderPattern::OnMenuExport(wxCommandEvent &event)
1072 WXCrystValidateAllUserInput();
1073 wxFileDialog save(this,_T("Choose a .pcr file"),_T(""),_T(""),_T("*.pcr"),wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
1074 if(save.ShowModal() != wxID_OK) return;
1076 wxString path,name,ext;
1077 wxFileName::SplitPath(save.GetPath(), &path, &name, &ext, wxPATH_NATIVE);
1079 wxString pcr=path+wxFileName::GetPathSeparator()+name+_T(".pcr");
1080 wxString dat=path+wxFileName::GetPathSeparator()+name+_T(".dat");
1081 mes.Printf(_T("This will create the files:\n %s\n %s"),pcr.c_str(),dat.c_str());
1082 wxMessageDialog mesd(this,mes,_T("Files"),wxOK|wxCANCEL|wxICON_INFORMATION);
1083 if(mesd.ShowModal()==wxID_OK)
1084 mpPowderPattern->ExportFullprof(string((path+wxFileName::GetPathSeparator()+name).ToAscii()));
1087 void WXPowderPattern::NotifyDeleteGraph() {mpGraph=0;}
1088 const PowderPattern& WXPowderPattern::GetPowderPattern()const
1089 { return *mpPowderPattern;}
1091 PowderPattern& WXPowderPattern::GetPowderPattern()
1092 { return *mpPowderPattern;}
1094 void WXPowderPattern::UpdateUI(const bool lock)
1096 if(lock)mMutex.Lock();
1099 mpGraph->GetParent()->SetLabel(wxString::FromAscii(mpPowderPattern->GetName().c_str()));
1101 this->WXRefinableObj::UpdateUI(false);
1102 if(lock)mMutex.Unlock();
1106 // WXPowderPatternGraph
1109 static const long ID_POWDERGRAPH_MENU_UPDATE= WXCRYST_ID();
1110 static const long ID_POWDERGRAPH_MENU_TOGGLELABEL= WXCRYST_ID();
1111 static const long ID_POWDERGRAPH_MENU_TOGGPEAK= WXCRYST_ID();
1112 static const long ID_POWDERGRAPH_MENU_FINDPEAKS= WXCRYST_ID();
1113 static const long ID_POWDERGRAPH_MENU_LOADPEAKS= WXCRYST_ID();
1114 static const long ID_POWDERGRAPH_MENU_SAVEPEAKS= WXCRYST_ID();
1115 static const long ID_POWDERGRAPH_MENU_ADDPEAK= WXCRYST_ID();
1116 static const long ID_POWDERGRAPH_MENU_REMOVEPEAK= WXCRYST_ID();
1117 static const long ID_POWDERGRAPH_MENU_INDEX= WXCRYST_ID();
1118 static const long ID_POWDERGRAPH_MENU_XSCALE_DATA= WXCRYST_ID();
1119 static const long ID_POWDERGRAPH_MENU_XSCALE_D= WXCRYST_ID();
1120 static const long ID_POWDERGRAPH_MENU_XSCALE_2PID= WXCRYST_ID();
1121 static const long ID_POWDERGRAPH_MENU_YSCALE_LINEAR= WXCRYST_ID();
1122 static const long ID_POWDERGRAPH_MENU_YSCALE_SQRT= WXCRYST_ID();
1123 static const long ID_POWDERGRAPH_MENU_YSCALE_LOG10= WXCRYST_ID();
1124 static const long ID_POWDERGRAPH_MENU_LEBAIL= WXCRYST_ID();
1126 BEGIN_EVENT_TABLE(WXPowderPatternGraph, wxWindow)
1127 EVT_PAINT( WXPowderPatternGraph::OnPaint)
1128 EVT_MOUSE_EVENTS( WXPowderPatternGraph::OnMouse)
1129 EVT_MENU(ID_POWDERGRAPH_MENU_UPDATE, WXPowderPatternGraph::OnUpdate)
1130 EVT_MENU(ID_POWDERGRAPH_MENU_TOGGLELABEL, WXPowderPatternGraph::OnToggleLabel)
1131 EVT_MENU(ID_POWDERGRAPH_MENU_TOGGPEAK, WXPowderPatternGraph::OnToggleLabel)
1132 EVT_MENU(ID_POWDERGRAPH_MENU_FINDPEAKS, WXPowderPatternGraph::OnFindPeaks)
1133 EVT_MENU(ID_POWDERGRAPH_MENU_LOADPEAKS, WXPowderPatternGraph::OnLoadPeaks)
1134 EVT_MENU(ID_POWDERGRAPH_MENU_SAVEPEAKS, WXPowderPatternGraph::OnSavePeaks)
1135 EVT_MENU(ID_POWDERGRAPH_MENU_ADDPEAK, WXPowderPatternGraph::OnChangePeak)
1136 EVT_MENU(ID_POWDERGRAPH_MENU_REMOVEPEAK, WXPowderPatternGraph::OnChangePeak)
1137 EVT_MENU(ID_POWDERGRAPH_MENU_INDEX, WXPowderPatternGraph::OnIndex)
1138 EVT_MENU(ID_POWDERGRAPH_MENU_XSCALE_DATA, WXPowderPatternGraph::OnChangeScale)
1139 EVT_MENU(ID_POWDERGRAPH_MENU_XSCALE_D, WXPowderPatternGraph::OnChangeScale)
1140 EVT_MENU(ID_POWDERGRAPH_MENU_XSCALE_2PID, WXPowderPatternGraph::OnChangeScale)
1141 EVT_MENU(ID_POWDERGRAPH_MENU_YSCALE_LINEAR, WXPowderPatternGraph::OnChangeScale)
1142 EVT_MENU(ID_POWDERGRAPH_MENU_YSCALE_SQRT, WXPowderPatternGraph::OnChangeScale)
1143 EVT_MENU(ID_POWDERGRAPH_MENU_YSCALE_LOG10, WXPowderPatternGraph::OnChangeScale)
1144 EVT_MENU(ID_POWDERGRAPH_MENU_LEBAIL, WXPowderPatternGraph::OnLeBail)
1145 EVT_UPDATE_UI(ID_POWDER_GRAPH_NEW_PATTERN, WXPowderPatternGraph::OnRedrawNewPattern)
1146 EVT_CHAR( WXPowderPatternGraph::OnKeyDown)
1147 EVT_MOUSEWHEEL( WXPowderPatternGraph::OnMouseWheel)
1148 EVT_SIZE( WXPowderPatternGraph::OnSize)
1151 WXPowderPatternGraph::WXPowderPatternGraph(wxFrame *frame, WXPowderPattern* parent):
1152 wxWindow(frame,-1,wxPoint(-1,-1),wxSize(-1,-1)),
1153 mpPattern(parent),mMargin(20),mDiffPercentShift(.20),
1154 mMaxIntensity(-1),mMinIntensity(-1),mMinX(-1),mMaxX(-1),
1155 mDefaultIntensityScale(true),
1156 mpParentFrame(frame),
1157 mIsDragging(false),mDisplayLabel(true),mDisplayPeak(true)
1159 mpPopUpMenu=new wxMenu(_T("Powder Pattern"));
1160 mpPopUpMenu->Append(ID_POWDERGRAPH_MENU_UPDATE, _T("&Update"));
1161 mpPopUpMenu->Append(ID_POWDERGRAPH_MENU_TOGGLELABEL, _T("&Hide labels"));
1163 mpPopUpMenu->AppendSeparator();
1164 mpPopUpMenu->Append(ID_POWDERGRAPH_MENU_FINDPEAKS, _T("&Find peaks"));
1165 mpPopUpMenu->Append(ID_POWDERGRAPH_MENU_LOADPEAKS, _T("&Load peaks"));
1166 mpPopUpMenu->Append(ID_POWDERGRAPH_MENU_SAVEPEAKS, _T("&Save peaks"));
1167 mpPopUpMenu->Append(ID_POWDERGRAPH_MENU_INDEX, _T("&Index !"));
1168 mpPopUpMenu->Append(ID_POWDERGRAPH_MENU_TOGGPEAK, _T("&Hide peaks"));
1169 mpPopUpMenu->Append(ID_POWDERGRAPH_MENU_ADDPEAK, _T("&Add peak"));
1170 mpPopUpMenu->Append(ID_POWDERGRAPH_MENU_REMOVEPEAK, _T("&Remove peak"));
1171 mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_SAVEPEAKS, FALSE);
1172 mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_TOGGPEAK, FALSE);
1173 mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_ADDPEAK, TRUE);
1174 mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_REMOVEPEAK, FALSE);
1175 mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_INDEX, FALSE);
1177 mpPopUpMenu->AppendSeparator();
1178 mpPopUpMenu->Append(ID_POWDERGRAPH_MENU_LEBAIL, _T("Fit &Profile + Le Bail extraction"));
1179 mpPopUpMenu->AppendSeparator();
1180 mpPopUpMenu->Append(ID_POWDERGRAPH_MENU_XSCALE_DATA, _T("&X scale: 2theta/TOF"));
1181 mpPopUpMenu->Append(ID_POWDERGRAPH_MENU_XSCALE_D, _T("&X scale: Q=1/d"));
1182 mpPopUpMenu->Append(ID_POWDERGRAPH_MENU_XSCALE_2PID, _T("&X scale: Q=2pi/d"));
1183 mpPopUpMenu->Append(ID_POWDERGRAPH_MENU_YSCALE_LINEAR, _T("&Y scale: I"));
1184 mpPopUpMenu->Append(ID_POWDERGRAPH_MENU_YSCALE_SQRT, _T("&Y scale: sqrt(I)"));
1185 mpPopUpMenu->Append(ID_POWDERGRAPH_MENU_YSCALE_LOG10, _T("&Y scale: log10(I)"));
1186 if(!wxConfigBase::Get()->HasEntry(_T("PowderPattern/BOOL/Default-display reflection indices")))
1187 wxConfigBase::Get()->Write(_T("PowderPattern/BOOL/Default-display reflection indices"), mDisplayLabel);
1190 wxConfigBase::Get()->Read(_T("PowderPattern/BOOL/Default-display reflection indices"), &mDisplayLabel);
1191 if(mDisplayLabel) mpPopUpMenu->SetLabel(ID_POWDERGRAPH_MENU_TOGGLELABEL, _T("Hide labels"));
1192 else mpPopUpMenu->SetLabel(ID_POWDERGRAPH_MENU_TOGGLELABEL, _T("Show labels"));
1195 // Scale used to display graph x coordinates : 0 - experimental ; 1 - 1/d ; 2 - 2pi/d
1196 if(!wxConfigBase::Get()->HasEntry(_T("PowderPattern/LONG/graph x scale")))
1197 wxConfigBase::Get()->Write(_T("PowderPattern/LONG/graph x scale"), 0);
1199 // Scale used to display graph y coordinates : 0 - linear ; 1 - square root ; 2 - log10
1200 if(!wxConfigBase::Get()->HasEntry(_T("PowderPattern/LONG/graph y scale")))
1201 wxConfigBase::Get()->Write(_T("PowderPattern/LONG/graph y scale"), 0);
1203 wxConfigBase::Get()->Read(_T("PowderPattern/LONG/graph x scale"), &mXScale);
1204 wxConfigBase::Get()->Read(_T("PowderPattern/LONG/graph y scale"), &mYScale);
1206 mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_XSCALE_DATA, TRUE);
1207 mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_XSCALE_D, TRUE);
1208 mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_XSCALE_2PID, TRUE);
1209 mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_YSCALE_LINEAR, TRUE);
1210 mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_YSCALE_SQRT, TRUE);
1211 mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_YSCALE_LOG10, TRUE);
1213 if(mXScale==0) mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_XSCALE_DATA, FALSE);
1214 if(mXScale==1) mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_XSCALE_D, FALSE);
1215 if(mXScale==2) mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_XSCALE_2PID, FALSE);
1216 if(mYScale==0)mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_YSCALE_LINEAR, FALSE);
1217 if(mYScale==1) mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_YSCALE_SQRT, FALSE);
1218 if(mYScale==2) mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_YSCALE_LOG10, FALSE);
1220 mpPattern->CrystUpdate(true);
1223 WXPowderPatternGraph::~WXPowderPatternGraph()
1225 mpPattern->NotifyDeleteGraph();
1228 void WXPowderPatternGraph::OnPaint(wxPaintEvent& WXUNUSED(event))
1230 if((mObs.numElements()<=0)||(mCalc.numElements()<=0)) return;
1231 VFN_DEBUG_MESSAGE("WXPowderPatternGraph:OnPaint()",5)
1233 while(wxMUTEX_NO_ERROR!=mMutex.TryLock())
1239 wxBufferedPaintDC dc(this);
1241 mpParentFrame->PrepareDC(dc);
1243 dc.DestroyClippingRegion();
1244 dc.SetBackground(wxBrush(_T("white"), wxSOLID));
1247 wxColour blue=wxColour(0,0,255);
1248 wxPen bluePen=wxPen(blue);
1251 dc.SetFont(*wxNORMAL_FONT);
1253 dc.SetFont(*wxSMALL_FONT);
1256 long nbPoint=mX.numElements();
1259 wxCoord width,height;
1260 this->GetSize(&width, &height);
1261 //const int margin=mMargin;
1264 VFN_DEBUG_MESSAGE("WXPowderPatternGraph:OnPaint():1",5)
1266 //Check pattern is not being updated
1267 VFN_DEBUG_MESSAGE("WXPowderPatternGraph:OnPaint():2:"<<mObs.numElements(),5)
1269 VFN_DEBUG_MESSAGE("WXPowderPatternGraph:OnPaint():3:min="
1270 <<mMinX<<", max="<<mMaxX<<", width="
1271 <<width<<",margin="<<mMargin,5)
1274 dc.SetPen(* wxLIGHT_GREY_PEN);
1276 for(long i=0;i<nbPoint;i++)
1278 if((mX(i)>mMinX)&&(mX(i)<mMaxX))
1280 x=this->Point2ScreenX(i);
1281 y1=this->Data2ScreenY(mObs(i)-mSigma(i)/2.);
1282 y2=this->Data2ScreenY(mObs(i)+mSigma(i)/2.);
1284 dc.DrawLine(x,y1,x,y2);
1288 // Draw Axis (sort of)
1291 dc.SetPen(* wxBLACK_PEN);
1292 dc.DrawLine(mMargin*3,height-mMargin,mMargin*3,mMargin);
1293 dc.DrawLine(mMargin*3,height-mMargin,width,height-mMargin);
1294 const int nbTick=10;//approximate
1298 xc=(wxCoord)mMargin*3;
1299 REAL miny=mMinIntensity,maxy=mMaxIntensity;
1300 if(mYScale==1) {miny=sqrt(miny) ;maxy=sqrt(maxy);}
1301 if(mYScale==2) {miny=log10(miny);maxy=log10(maxy);}
1302 REAL yStep=pow((float)10,(float)floor(log10((maxy-miny)/nbTick)));
1303 yStep *= floor((maxy-miny)/yStep/nbTick);
1304 for(REAL ys=yStep*ceil(miny/yStep);ys<maxy;ys+=yStep)
1307 if(mYScale==1) {y=ys*ys;}
1308 if(mYScale==2) {y=pow((float)10,(float)ys);}
1309 yc=this->Data2ScreenY(y);
1310 dc.DrawLine(xc-3,yc,xc+3,yc);
1311 fontInfo.Printf(_T("%g"),y);
1312 dc.GetTextExtent(fontInfo, &tmpW, &tmpH);
1313 dc.DrawText(fontInfo,xc-tmpW-3,yc-tmpH/2);
1318 yc=(wxCoord)(height-mMargin);
1320 REAL minx=mMinX,maxx=mMaxX;
1321 float mind,maxd;// 1/d
1322 if(mpPattern->GetPowderPattern().GetRadiation().GetWavelengthType()!=WAVELENGTH_TOF)
1324 mind=2*mpPattern->GetPowderPattern().X2STOL(minx*DEG2RAD);
1325 maxd=2*mpPattern->GetPowderPattern().X2STOL(maxx*DEG2RAD);
1329 mind=2*mpPattern->GetPowderPattern().X2STOL(minx);
1330 maxd=2*mpPattern->GetPowderPattern().X2STOL(maxx);
1332 if(mXScale==1) {minx=mind; maxx=maxd;}
1333 if(mXScale==2) {minx=2*M_PI*mind;maxx=2*M_PI*maxd;}
1335 REAL xStep=pow((float)10,(float)floor(log10((maxx-minx)/nbTick)));
1336 xStep *= floor((maxx-minx)/xStep/nbTick);
1337 for(REAL xs=xStep*ceil(minx/xStep);xs<maxx;xs+=xStep)
1340 if(mXScale==1) {x=mpPattern->GetPowderPattern().STOL2X(xs/2);}
1341 if(mXScale==2) {x=mpPattern->GetPowderPattern().STOL2X(xs/(4*M_PI));}
1342 if(mXScale==0) xc=this->Data2ScreenX(x);
1345 if(mpPattern->GetPowderPattern().GetRadiation().GetWavelengthType()!=WAVELENGTH_TOF)
1346 xc=this->Data2ScreenX(RAD2DEG*x);
1347 else xc=this->Data2ScreenX(x);
1349 dc.DrawLine(xc,yc-3,xc,yc+3);
1350 fontInfo.Printf(_T("%g"),xs);
1351 dc.GetTextExtent(fontInfo, &tmpW, &tmpH);
1352 dc.DrawText(fontInfo,xc-tmpW/2,yc+6);
1356 // Draw cumulated Chi^2, scaled
1358 dc.SetPen(* wxGREY_PEN);
1359 wxCoord x1,y1,x2,y2;
1360 x2=this->Point2ScreenX(0);
1361 const REAL s=(mMaxIntensity-mMinIntensity)/mChi2Cumul(mpPattern->GetPowderPattern().GetNbPointUsed()-1);
1362 y2=this->Data2ScreenY(mMinIntensity+mChi2Cumul(0)*s);
1363 for(unsigned long i=0;i<mpPattern->GetPowderPattern().GetNbPointUsed();i++)
1365 if((mX(i)>mMinX)&&(mX(i)<mMaxX))
1369 x2=this->Point2ScreenX(i);
1370 y2=this->Data2ScreenY(mMinIntensity+mChi2Cumul(i)*s);
1371 dc.DrawLine(x1,y1,x2,y2);
1375 // Draw observed pattern
1376 VFN_DEBUG_MESSAGE("WXPowderPatternGraph:OnPaint():4:",5)
1379 wxCoord x1,y1,x2,y2;
1380 x2=this->Point2ScreenX(0);
1381 y2=this->Data2ScreenY(mObs(0));
1382 for(long i=0;i<nbPoint;i++)
1384 if((mX(i)>mMinX)&&(mX(i)<mMaxX))
1388 x2=this->Point2ScreenX(i);
1389 y2=this->Data2ScreenY(mObs(i));
1390 dc.DrawLine(x1,y1,x2,y2);
1395 // Draw calculated pattern
1396 VFN_DEBUG_MESSAGE("WXPowderPatternGraph:OnPaint():5:",5)
1398 dc.SetPen(* wxRED_PEN);
1399 wxCoord x1,y1,x2,y2;
1400 x2=this->Point2ScreenX(0);
1401 y2=this->Data2ScreenY(mCalc(0));
1402 for(long i=0;i<nbPoint;i++)
1404 if((mX(i)>mMinX)&&(mX(i)<mMaxX))
1408 x2=this->Point2ScreenX(i);
1409 y2=this->Data2ScreenY(mCalc(i));
1410 dc.DrawLine(x1,y1,x2,y2);
1416 list<list<pair<const REAL ,const string > > > vLabel;
1417 if(true==mDisplayLabel) // "vLabel=mvLabelList;" does not work (gcc 4.1.1)
1418 for(list<list<pair<const REAL ,const string > > >::const_iterator
1419 comp=mvLabelList.begin();comp!=mvLabelList.end();++comp) vLabel.push_back(*comp);
1421 if((true==mDisplayPeak)&&(mPeakList.GetPeakList().size()>0))
1423 list<pair<const REAL ,const string > > peakLabels;
1426 for(vector<PeakList::hkl>::const_iterator pos=mPeakList.GetPeakList().begin();pos!=mPeakList.GetPeakList().end();++pos)
1428 const float x=mpPattern->GetPowderPattern().STOL2X(pos->dobs/2);
1431 if(mpPattern->GetPowderPattern().GetRadiation().GetWavelengthType()!=WAVELENGTH_TOF)
1432 sprintf(buf,"#%2u,x=%6.3f d=%6.3fA SPURIOUS?",ix,x*RAD2DEG,1/pos->dobs);
1434 sprintf(buf,"#%2u,x=%6.3f d=%6.3fA SPURIOUS?",ix,x ,1/pos->dobs);
1438 if(mpPattern->GetPowderPattern().GetRadiation().GetWavelengthType()!=WAVELENGTH_TOF)
1439 sprintf(buf,"#%2u,x=%6.2f d=%6.3fA",ix,x*RAD2DEG,1/pos->dobs);
1441 sprintf(buf,"#%2u,x=%6.2f d=%6.3fA",ix,x ,1/pos->dobs);
1444 peakLabels.push_back(make_pair(x,buf));
1446 vLabel.push_back(peakLabels);
1447 // Do we have a list of predicted HKL positions as well ?
1448 if(mPeakList.mvPredictedHKL.size()>0)
1451 for(list<PeakList::hkl>::const_iterator pos=mPeakList.mvPredictedHKL.begin();pos!=mPeakList.mvPredictedHKL.end();++pos)
1453 const float dobs=sqrt(pos->d2calc);
1454 const float x=mpPattern->GetPowderPattern().STOL2X(dobs/2);
1455 sprintf(buf,"?(%2d %2d %2d)?",pos->h,pos->k,pos->l);
1456 peakLabels.push_back(make_pair(x,buf));
1458 vLabel.push_back(peakLabels);
1462 VFN_DEBUG_MESSAGE("WXPowderPatternGraph:OnPaint():5:",5)
1470 unsigned int icomp=0;
1471 // First, Crystalline phases, background (empty), then list of peaks and predicted hkl list
1472 for(list<list<pair<const REAL ,const string > > >::const_iterator comp=vLabel.begin();comp!=vLabel.end();comp++)
1475 {// Only background components should be empty
1481 case 0 : dc.SetPen(wxPen(wxColour( 0, 0, 0),2));dc.SetTextForeground(wxColour( 0, 0, 0));break;
1482 case 1 : dc.SetPen(wxPen(wxColour( 0, 0,255),2));dc.SetTextForeground(wxColour( 0, 0,255));break;
1483 case 2 : dc.SetPen(wxPen(wxColour( 0,255, 0),2));dc.SetTextForeground(wxColour( 0,255, 0));break;
1484 case 3 : dc.SetPen(wxPen(wxColour(255, 0, 0),2));dc.SetTextForeground(wxColour(255, 0, 0));break;
1485 case 4 : dc.SetPen(wxPen(wxColour( 0,255,255),2));dc.SetTextForeground(wxColour( 0,255,255));break;
1486 case 5 : dc.SetPen(wxPen(wxColour(255, 0,255),2));dc.SetTextForeground(wxColour(255, 0,255));break;
1487 case 6 : dc.SetPen(wxPen(wxColour(255,160, 0),2));dc.SetTextForeground(wxColour(255,160, 0));break;
1488 case 7 : dc.SetPen(wxPen(wxColour(128,128,255),2));dc.SetTextForeground(wxColour(128,128,255));break;
1489 case 8 : dc.SetPen(wxPen(wxColour(128,255,128),2));dc.SetTextForeground(wxColour(128,255,128));break;
1490 case 9 : dc.SetPen(wxPen(wxColour(255,128,128),2));dc.SetTextForeground(wxColour(255,128,128));break;
1491 case 10: dc.SetPen(wxPen(wxColour( 0, 0,128),2));dc.SetTextForeground(wxColour( 0, 0,128));break;
1492 case 11: dc.SetPen(wxPen(wxColour( 0, 80, 0),2));dc.SetTextForeground(wxColour( 0, 80, 0));break;
1493 case 12: dc.SetPen(wxPen(wxColour(128, 0, 0),2));dc.SetTextForeground(wxColour(128, 0, 0));break;
1494 default: dc.SetPen(wxPen(wxColour(128,128,128),2));dc.SetTextForeground(wxColour(128,128,128));break;
1497 for(list<pair<const REAL ,const string > >::const_iterator pos=comp->begin();pos!=comp->end();++pos)
1499 REAL point=pos->first;
1500 if(mpPattern->GetPowderPattern().GetRadiation().GetWavelengthType()!=WAVELENGTH_TOF)
1502 if((point>=mMinX)&&(point<=mMaxX))
1506 cout <<"Too many labels (>100): displaying only first 100 and ticking 100 more..."<<endl;
1509 x=this->Data2ScreenX(point);
1510 const REAL pixel=mpPattern->GetPowderPattern().X2Pixel(pos->first);
1511 if(mCalc((long)pixel)>mObs((long)pixel)) yr=mCalc((long)pixel);
1512 else yr=mObs((long)pixel);
1513 y=this->Data2ScreenY(yr);
1515 dc.DrawLine(x,y-5,x,y-10);
1518 fontInfo.Printf(wxString::FromAscii(pos->second.c_str()));
1519 dc.GetTextExtent(fontInfo, &tmpW, &tmpH);
1520 dc.DrawText(fontInfo,x-tmpW/2,y-tmpH*(loop++)-10);
1525 // Draw legend (crystal names, Le Bail mode,...)
1527 if(icomp<mpPattern->GetPowderPattern().GetNbPowderPatternComponent())
1529 PowderPatternDiffraction *pDiff=0;
1530 if(mpPattern->GetPowderPattern().GetPowderPatternComponent(icomp).GetClassName()=="PowderPatternDiffraction")
1532 pDiff=dynamic_cast<PowderPatternDiffraction*> (&(mpPattern->GetPowderPattern().GetPowderPatternComponent(icomp)));
1533 if(pDiff->GetExtractionMode()) legend=wxString::FromAscii((pDiff->GetCrystal().GetName()+" (LE BAIL MODE)").c_str());
1534 else legend=wxString::FromAscii(pDiff->GetCrystal().GetName().c_str());
1539 if((icomp-mpPattern->GetPowderPattern().GetNbPowderPatternComponent())==0)
1540 legend="Found Peaks";
1541 else legend="Indexed HKL";
1543 fontInfo.Printf(legend);
1545 dc.GetTextExtent(fontInfo, &tmpW, &tmpH);
1546 dc.DrawText(fontInfo,(wxCoord)mMargin*3+5,(wxCoord)(mMargin+tmpH*(pen)));
1552 VFN_DEBUG_MESSAGE("WXPowderPatternGraph:OnPaint():End",5)
1555 void WXPowderPatternGraph::OnMouse(wxMouseEvent &event)
1557 if(0 == mpPattern->GetPowderPattern().GetNbPoint()) return;
1558 if(event.Leaving()) return;// wxMSW2.4 bug ?
1559 if(wxMUTEX_NO_ERROR!=mMutex.TryLock())
1564 VFN_DEBUG_MESSAGE("WXPowderPatternGraph:OnMouse()"
1565 <<endl<<"IsButton():"<<event.IsButton()
1566 <<endl<<"ButtonDown():"<<event.ButtonDown()
1567 <<endl<<"Dragging():"<<event.Dragging()
1568 <<endl<<"Entering():"<<event.Entering()
1569 <<endl<<"Leaving():"<<event.Leaving()
1570 <<endl<<"GetButton()"<<event.GetButton()
1571 <<endl<<"GetWheelAxis():"<<event.GetWheelAxis()
1572 <<endl<<"GetWheelDelta():"<<event.GetWheelDelta()
1573 <<endl<<"GetWheelRotation():"<<event.GetWheelRotation()
1574 <<endl<<"Moving():"<<event.Moving()
1576 // Write mouse pointer coordinates
1577 wxClientDC dc(this);
1579 mpParentFrame->PrepareDC(dc);
1581 wxPoint pos=event.GetPosition();
1582 const long x= dc.DeviceToLogicalX(pos.x);
1583 const long y= dc.DeviceToLogicalY(pos.y);
1585 wxCoord width,height;
1586 this->GetSize(&width, &height);
1588 if((x>width)||(y>height))
1593 //cout <<pos.x<<" "<<pos.y<<" "<<x<<" "<<y<<" "<<width<<" "<<height<<endl;
1594 const REAL x0=this->Screen2DataX(x);
1595 const REAL intensity=this->Screen2DataY(y);
1596 if(mpPattern->GetPowderPattern().GetRadiation().GetWavelengthType()==WAVELENGTH_TOF)
1600 (long)(mpPattern->GetPowderPattern().X2PixelCorr(x0));
1601 str.Printf(_T("tof=%6.2f ,I=%12.2f. pixel=#%ld"),x0,intensity,pixel);
1603 mpParentFrame->SetStatusText(str);
1605 str.Printf(_T("d=%6.3fA"),0.5/mpPattern->GetPowderPattern().X2STOL(x0));
1607 mpParentFrame->SetStatusText(str,1);
1612 const REAL intensity=this->Screen2DataY(y);
1616 (long)(mpPattern->GetPowderPattern().X2PixelCorr(x0*DEG2RAD));
1617 str.Printf(_T("2theta=%6.2f ,I=%12.2f. pixel=#%ld"),x0,intensity,pixel);
1618 // SetStatusText() triggers an OnPaint event ? Avoid deadlock by releasing the data mutex..
1620 mpParentFrame->SetStatusText(str);
1622 str.Printf(_T("d=%6.3fA"),0.5/mpPattern->GetPowderPattern().X2STOL(x0*DEG2RAD));
1624 mpParentFrame->SetStatusText(str,1);
1627 if (event.Dragging() && event.LeftIsDown() && (!mIsDragging))
1631 mDraggingIntensity0=intensity;
1635 if(event.LeftUp() && mIsDragging)
1636 {//Finished zooming !
1637 VFN_DEBUG_MESSAGE("WXPowderPatternGraph::OnMouse():Finished zooming...",5)
1640 if( (fabs(x0-mDraggingX0)<.1) || (fabs(mDraggingIntensity0-intensity)< fabs(mMaxIntensity*.02)) )
1645 if(mDraggingIntensity0>intensity)
1647 if(mDraggingIntensity0<0.)
1652 mMinIntensity=intensity;
1653 mMaxIntensity=mDraggingIntensity0;
1662 mMinIntensity=mDraggingIntensity0;
1663 mMaxIntensity=intensity;
1675 mDefaultIntensityScale=false;
1676 mClockAxisLimits.Click();
1678 wxUpdateUIEvent event(ID_POWDER_GRAPH_NEW_PATTERN);
1679 wxPostEvent(this,event);
1683 if(false==event.Dragging()) mIsDragging=false;
1685 if(event.LeftDClick())
1688 this->ResetAxisLimits();
1689 wxUpdateUIEvent event(ID_POWDER_GRAPH_NEW_PATTERN);
1690 wxPostEvent(this,event);
1695 if(event.RightIsDown())
1698 if(mpPattern->GetPowderPattern().IsBeingRefined())
1699 mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_UPDATE, false);
1701 mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_UPDATE, true);
1702 // Store x coordinate to allow adding/removing peaks manually
1704 this->PopupMenu(mpPopUpMenu, event.GetX(), event.GetY() );
1707 if (event.GetWheelDelta()>0)
1708 {// Wheel or double-touch event on OSX + trackpad
1709 if(event.ControlDown())
1711 VFN_DEBUG_MESSAGE("WXPowderPatternGraph::OnMouse(): Mouse Wheel / double touch + control (OSX: command)",2)
1715 VFN_DEBUG_MESSAGE("WXPowderPatternGraph::OnMouse(): Mouse Wheel / double touch",2)
1716 const int delta=event.GetWheelDelta();
1718 if(event.GetWheelAxis()==1) dx=event.GetWheelRotation();
1719 else dy=event.GetWheelRotation();
1725 const long nbPoint=mX.numElements();
1728 const REAL range=mMaxX-mMinX;
1729 mMaxX += range/128.*abs(dx);
1730 if(mX(nbPoint-1)>mX(0))
1732 if(mMaxX>=mX(nbPoint-1)) mMaxX=mX(nbPoint-1);
1736 if(mMaxX>=mX(0)) mMaxX=mX(0);
1742 const REAL range=mMaxX-mMinX;
1743 mMinX -= range/128.*abs(dx);
1744 if(mX(nbPoint-1)>mX(0))
1746 if(mMinX<mX(0)) mMinX=mX(0);
1750 if(mMinX<mX(nbPoint-1)) mMinX=mX(nbPoint-1);
1757 if(abs(mMaxX-mMinX)>1)
1759 const REAL halfrange=(mMaxX-mMinX)/2;
1760 const REAL middle=(mMaxX+mMinX)/2;
1761 //d1,d2 are used to zoom from the mouse position rather than the middle
1762 const REAL d1=(x0-mMinX)/halfrange;
1763 const REAL d2=(mMaxX-x0)/halfrange;
1764 mMinX= middle-halfrange*(64-abs(dy)*d1)/64.;
1765 mMaxX= middle+halfrange*(64-abs(dy)*d2)/64.;
1770 const REAL halfrange=(mMaxX-mMinX)/2;
1771 const REAL middle=(mMaxX+mMinX)/2;
1772 const REAL d1=(x0-mMinX)/halfrange;
1773 const REAL d2=(mMaxX-x0)/halfrange;
1774 mMinX= middle-halfrange*(64+abs(dy)*d1)/64.;
1775 mMaxX= middle+halfrange*(64+abs(dy)*d2)/64.;
1777 if(mX(nbPoint-1)>mX(0))
1779 if(mMinX<mX(0)) mMinX=mX(0);
1780 if(mMaxX>mX(nbPoint-1)) mMaxX=mX(nbPoint-1);
1784 if(mMinX<mX(nbPoint-1)) mMinX=mX(nbPoint-1);
1785 if(mMaxX>mX(0)) mMaxX=mX(0);
1787 if(mDefaultIntensityScale)
1788 {// Adapt max intensity as well
1789 float x0=mMinX,x1=mMaxX;
1790 if(mpPattern->GetPowderPattern().GetRadiation().GetWavelengthType()!=WAVELENGTH_TOF)
1795 long ix0=long(this->mpPattern->GetPowderPattern().X2Pixel(x0));
1796 long ix1=long(this->mpPattern->GetPowderPattern().X2Pixel(x1));
1797 //cout<<"Switch default intensity 1: "<<"["<<ix0<<"] - "<<"["<<ix1<<"]"<<endl;
1799 if(ix0>=mX.numElements()) ix0=mX.numElements()-1;
1801 if(ix1>=mX.numElements()) ix1=mX.numElements()-1;
1804 const long ixtmp=ix0;
1808 const long imin=mObs.imin(ix0,ix1);
1809 const long imax=mObs.imax(ix0,ix1);
1810 const long iminc=mCalc.imin(ix0,ix1);
1811 const long imaxc=mCalc.imax(ix0,ix1);
1812 //cout<<"Switch default intensity 3: "<<mObs(imin)<<"["<<ix0<<"] - "<<mObs(imax)<<"["<<ix1<<"]"<<endl;
1813 if(mObs(imin)<mCalc(iminc)) mMinIntensity=mObs(imin); else mMinIntensity=mCalc(iminc);
1814 if(mObs(imax)>mCalc(imaxc)) mMaxIntensity=mObs(imax); else mMaxIntensity=mCalc(imaxc);
1815 mMaxIntensity=mMaxIntensity+(mMaxIntensity-mMinIntensity)*0.1;
1819 mClockAxisLimits.Click();
1820 wxUpdateUIEvent event(ID_POWDER_GRAPH_NEW_PATTERN);
1821 wxPostEvent(this,event);
1829 void WXPowderPatternGraph::OnMouseWheel(wxMouseEvent &event)
1831 if(0 == mpPattern->GetPowderPattern().GetNbPoint()) return;
1832 VFN_DEBUG_ENTRY("WXPowderPatternGraph::OnMouseWheel()",6)
1833 wxMutexLocker mlock(mMutex);
1834 const long nbPoint=mX.numElements();
1835 if(event.GetWheelRotation()>=event.GetWheelDelta())
1837 const REAL range=mMaxX-mMinX;
1839 if(mX(nbPoint-1)>mX(0))
1841 if(mMaxX>=mX(nbPoint-1)) mMaxX=mX(nbPoint-1);
1845 if(mMaxX>=mX(0)) mMaxX=mX(0);
1849 if(event.GetWheelRotation()<=(-event.GetWheelDelta()))
1851 const REAL range=mMaxX-mMinX;
1853 if(mX(nbPoint-1)>mX(0))
1855 if(mMinX<mX(0)) mMinX=mX(0);
1859 if(mMinX<mX(nbPoint-1)) mMinX=mX(nbPoint-1);
1863 mClockAxisLimits.Click();
1864 wxUpdateUIEvent ev(ID_POWDER_GRAPH_NEW_PATTERN);
1865 wxPostEvent(this,ev);
1866 VFN_DEBUG_EXIT("WXPowderPatternGraph::OnMouseWheel()",6)
1869 void WXPowderPatternGraph::OnUpdate(wxCommandEvent & WXUNUSED(event))
1871 VFN_DEBUG_MESSAGE("WXPowderPatternGraph::OnUpdate()",6)
1872 mpPattern->CrystUpdate(true,true);
1875 void WXPowderPatternGraph::OnToggleLabel(wxCommandEvent &event)
1877 VFN_DEBUG_MESSAGE("WXPowderPatternGraph::OnToggleLabel()",6)
1878 if(event.GetId()==ID_POWDERGRAPH_MENU_TOGGPEAK)
1880 mDisplayPeak = !mDisplayPeak;
1881 if(mDisplayPeak) mpPopUpMenu->SetLabel(ID_POWDERGRAPH_MENU_TOGGPEAK, _T("Hide peaks"));
1882 else mpPopUpMenu->SetLabel(ID_POWDERGRAPH_MENU_TOGGPEAK, _T("Show peaks"));
1884 if(event.GetId()==ID_POWDERGRAPH_MENU_TOGGLELABEL)
1886 mDisplayLabel = !mDisplayLabel;
1887 if(mDisplayLabel) mpPopUpMenu->SetLabel(ID_POWDERGRAPH_MENU_TOGGLELABEL, _T("Hide labels"));
1888 else mpPopUpMenu->SetLabel(ID_POWDERGRAPH_MENU_TOGGLELABEL, _T("Show labels"));
1890 this->Refresh(false);
1893 void WXPowderPatternGraph::OnFindPeaks(wxCommandEvent& WXUNUSED(event))
1895 WXCrystValidateAllUserInput();
1898 (*fpObjCrystInformUser)("Powder pattern: searching for peaks");
1902 mPeakList=mpPattern->GetPowderPattern().FindPeaks(dmin,-1,1000);
1904 if((mPeakList.GetPeakList().size()>30)||(dmin<0.3)) break;
1906 const unsigned int nb=mPeakList.GetPeakList().size();
1907 (*fpObjCrystInformUser)((boost::format("Powder pattern: found %u peaks (dt=%6.3fs)") % nb % chrono.seconds()).str());
1910 mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_SAVEPEAKS, TRUE);
1911 mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_TOGGPEAK, TRUE);
1912 mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_INDEX, TRUE);
1913 mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_ADDPEAK, TRUE);
1914 mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_REMOVEPEAK, TRUE);
1916 // Keep lowest peaks
1917 if(mPeakList.GetPeakList().size()>40) mPeakList.GetPeakList().resize(40);
1918 //mpPattern->CrystUpdate(true,true);
1920 {// display 2nd derivative as 'calc' (will remain until an update to the pattern is made)
1921 CrystVector_REAL obsd2;
1922 obsd2=SavitzkyGolay(mObs,4,2);
1923 const float norm=-obsd2.min();
1930 this->Refresh(false);
1933 void WXPowderPatternGraph::OnLoadPeaks(wxCommandEvent& WXUNUSED(event))
1935 wxFileDialog fn(this,_T("Choose a file"),_T(""),_T(""),_T("*"),wxFD_OPEN);
1936 if(fn.ShowModal() != wxID_OK) return;
1937 ifstream f(fn.GetPath().ToAscii());
1938 if(!f) return;//:TODO:
1939 mPeakList.GetPeakList().clear();
1940 f.imbue(std::locale::classic());
1941 mPeakList.ImportDhklDSigmaIntensity(f);
1944 mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_SAVEPEAKS, TRUE);
1945 mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_TOGGPEAK, TRUE);
1946 mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_INDEX, TRUE);
1947 mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_ADDPEAK, TRUE);
1948 mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_REMOVEPEAK, TRUE);
1949 this->Refresh(false);
1952 void WXPowderPatternGraph::OnSavePeaks(wxCommandEvent& WXUNUSED(event))
1954 wxFileDialog save(this,_T("Choose a file"),_T(""),_T(""),_T("*.txt"),wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
1955 if(save.ShowModal() != wxID_OK) return;
1957 ofstream out(save.GetPath().ToAscii());
1958 if(!out) return;//:TODO:
1959 out.imbue(std::locale::classic());
1960 mPeakList.ExportDhklDSigmaIntensity(out);
1965 void WXPowderPatternGraph::OnChangePeak(wxCommandEvent& event)
1967 if(event.GetId()==ID_POWDERGRAPH_MENU_REMOVEPEAK)
1970 const float d=2*mpPattern->GetPowderPattern().X2STOL(this->Screen2DataX((long)mDraggingX0)*DEG2RAD);
1972 for(unsigned int i=0;i<mPeakList.GetPeakList().size();++i)
1974 float x=mpPattern->GetPowderPattern().STOL2X(mPeakList.GetPeakList()[i].dobs/2);
1975 if(mpPattern->GetPowderPattern().GetRadiation().GetWavelengthType()!=WAVELENGTH_TOF)
1977 x=this->Data2ScreenX(x);
1978 if(abs(x-mDraggingX0)<dist)
1980 dist=abs(x-mDraggingX0);
1983 cout<<__FILE__<<":"<<__LINE__<<": 1/d0="<<d<<" peak #"<<i<<",d="<<1/mPeakList.GetPeakList()[i].dobs
1984 <<"("<<mDraggingX0<<","<<x<<"), mindist="<<dist<<endl;
1986 if(dist>5) mpParentFrame->SetStatusText(_T("Could not find peak close enough"),1);
1989 if(mPeakList.GetPeakList().size()<5) mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_INDEX, FALSE);
1990 if(mPeakList.GetPeakList().size()==0)
1992 mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_TOGGPEAK, FALSE);
1993 mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_SAVEPEAKS, FALSE);
1994 mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_REMOVEPEAK, FALSE);
1997 buf.Printf(_T("Removing peak at d=%6.3f"),1/mPeakList.GetPeakList()[idx].dobs);
1998 mpParentFrame->SetStatusText(buf,1);
1999 mPeakList.RemovePeak(idx);
2000 this->Refresh(false);
2003 if(event.GetId()==ID_POWDERGRAPH_MENU_ADDPEAK)
2006 if(mpPattern->GetPowderPattern().GetRadiation().GetWavelengthType()!=WAVELENGTH_TOF)
2008 d = 2*mpPattern->GetPowderPattern().X2STOL(this->Screen2DataX((long)mDraggingX0 )*DEG2RAD);
2009 // Use 2*local step as sigma
2010 long x1=(long)(mpPattern->GetPowderPattern().STOL2Pixel(d/2));
2012 sig=2*abs( mpPattern->GetPowderPattern().X2STOL(mpPattern->GetPowderPattern().GetPowderPatternX()(x1 ))
2013 -mpPattern->GetPowderPattern().X2STOL(mpPattern->GetPowderPattern().GetPowderPatternX()(x1-1)));
2017 d = 2*mpPattern->GetPowderPattern().X2STOL(this->Screen2DataX((long)mDraggingX0 ));
2018 long x1=(long)(mpPattern->GetPowderPattern().STOL2Pixel(d/2));
2019 cout<<__FILE__<<":"<<__LINE__<<":"<<x1<<endl;
2021 sig=2*abs( mpPattern->GetPowderPattern().X2STOL(mpPattern->GetPowderPattern().GetPowderPatternX()(x1 ))
2022 -mpPattern->GetPowderPattern().X2STOL(mpPattern->GetPowderPattern().GetPowderPatternX()(x1-1)));
2023 cout<<__FILE__<<":"<<__LINE__<<":"<<sig<<endl;
2026 mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_SAVEPEAKS, TRUE);
2027 mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_TOGGPEAK, TRUE);
2028 if(mPeakList.GetPeakList().size()>=5) mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_INDEX, TRUE);
2029 mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_REMOVEPEAK, TRUE);
2032 buf.Printf(_T("Added peak at d=%6.3f"),1/d);
2033 mPeakList.AddPeak(d,1.0,sig);
2034 mpParentFrame->SetStatusText(buf,1);
2035 this->Refresh(false);
2036 mPeakList.Print(cout);
2041 class WXCellExplorer:public wxWindow
2044 WXCellExplorer(wxWindow *parent,PeakList &peaklist,WXPowderPatternGraph *graph=NULL);
2047 void OnIndex(wxCommandEvent &event);
2049 void OnSelectCell(wxCommandEvent &event);
2051 void OnApplyCell(wxCommandEvent &event);
2053 void OnChooseCrystal(wxCommandEvent &event);
2056 void OnAutoLeBail(wxCommandEvent &event);
2058 void OnExportIndexingResults(wxCommandEvent &event);
2060 WXPowderPatternGraph *mpGraph;
2061 PeakList *mpPeakList;
2062 CellExplorer *mpCellExplorer;
2063 wxRadioBox *mpAlgorithm;
2064 wxRadioBox *mpBravais;
2067 wxTextCtrl *mpLengthMin,*mpLengthMax;
2068 wxTextCtrl *mpAngleMin,*mpAngleMax;
2069 wxTextCtrl *mpVolumeMin,*mpVolumeMax;
2070 wxTextCtrl *mpNbSpurious;
2071 wxTextCtrl *mpNbPeak;
2072 wxTextCtrl *mpErrorD;
2073 WXFieldChoice *mpFieldCrystal;
2074 wxTextCtrl *mpStopOnScore,*mpStopOnDepth;
2075 wxTextCtrl *mpReportOnScore,*mpReportOnDepth;
2077 PowderPatternDiffraction *mpDiff;
2078 wxCheckBox *mpWeakDiffraction;
2079 wxCheckBox *mpContinueOnSolution;
2080 wxCheckBox *mpTryCenteredLattice;
2081 wxCheckBox *mpTrySpurious;
2082 wxCheckBox *mpAutomaticLeBail;
2083 DECLARE_EVENT_TABLE()
2085 static const long ID_CELLEXPLORER_INDEX= WXCRYST_ID();
2086 static const long ID_CELLEXPLORER_INDEX_QUICK= WXCRYST_ID();
2087 static const long ID_CELLEXPLORER_WEAK= WXCRYST_ID();
2088 static const long ID_CELLEXPLORER_SELECTCELL= WXCRYST_ID();
2089 static const long ID_CELLEXPLORER_APPLYCELL= WXCRYST_ID();
2090 static const long ID_CELLEXPLORER_CHOOSECRYSTAL= WXCRYST_ID();
2091 static const long ID_CELLEXPLORER_LEBAIL= WXCRYST_ID();
2092 static const long ID_CELLEXPLORER_CENTERED= WXCRYST_ID();
2093 static const long ID_CELLEXPLORER_SPURIOUS= WXCRYST_ID();
2094 static const long ID_CELLEXPLORER_EXPORT= WXCRYST_ID();
2096 BEGIN_EVENT_TABLE(WXCellExplorer, wxWindow)
2097 EVT_BUTTON(ID_CELLEXPLORER_INDEX, WXCellExplorer::OnIndex)
2098 EVT_BUTTON(ID_CELLEXPLORER_INDEX_QUICK, WXCellExplorer::OnIndex)
2099 EVT_LISTBOX(ID_CELLEXPLORER_SELECTCELL, WXCellExplorer::OnSelectCell)
2100 EVT_LISTBOX_DCLICK(ID_CELLEXPLORER_SELECTCELL,WXCellExplorer::OnApplyCell)
2101 EVT_BUTTON(ID_CELLEXPLORER_APPLYCELL, WXCellExplorer::OnApplyCell)
2102 EVT_BUTTON(ID_CELLEXPLORER_CHOOSECRYSTAL, WXCellExplorer::OnChooseCrystal)
2103 EVT_CHECKBOX(ID_CELLEXPLORER_LEBAIL, WXCellExplorer::OnAutoLeBail)
2104 EVT_BUTTON(ID_CELLEXPLORER_EXPORT, WXCellExplorer::OnExportIndexingResults)
2107 //:TODO: allow sorting solutions by number of spurious lines or score
2108 //:TODO: make systematic Le Bail + profile fitting of all solutions, and allow to sort by GoF
2110 WXCellExplorer::WXCellExplorer(wxWindow *parent, PeakList &peaklist, WXPowderPatternGraph *graph):
2111 wxWindow(parent,-1),mpGraph(graph),mpPeakList(&peaklist),mpCellExplorer(0),mpCrystal(0),mpDiff(0)
2113 wxBoxSizer *pSizer1=new wxBoxSizer(wxHORIZONTAL);
2114 this->SetSizer(pSizer1);
2116 wxNotebook *pNotebook = new wxNotebook(this, -1);
2118 pSizer1->Add(pNotebook,0,wxALIGN_TOP);
2121 wxWindow *pQuick=new wxWindow(pNotebook,-1);
2122 pNotebook->AddPage(pQuick,_T("Quick"));
2124 wxStaticBoxSizer *pSizerQuick=new wxStaticBoxSizer(wxVERTICAL,pQuick);
2126 wxButton *pQuickButtonIndex=new wxButton(pQuick,ID_CELLEXPLORER_INDEX_QUICK,_T("Find cell!"));
2127 pSizerQuick->Add(pQuickButtonIndex,0,wxALIGN_CENTER);
2129 wxButton *pQuickButtonExport=new wxButton(pQuick,ID_CELLEXPLORER_EXPORT,_T("Export Indexing Results"));
2130 pSizerQuick->Add(pQuickButtonExport,0,wxALIGN_CENTER);
2132 mpWeakDiffraction=new wxCheckBox(pQuick,ID_CELLEXPLORER_WEAK,_T("Weak Diffraction (scan larger volume)"));
2133 pSizerQuick->Add(mpWeakDiffraction,0,wxALIGN_CENTER);
2135 mpContinueOnSolution=new wxCheckBox(pQuick,ID_CELLEXPLORER_WEAK,_T("Continue exploring after solution"));
2136 pSizerQuick->Add(mpContinueOnSolution,0,wxALIGN_CENTER);
2138 mpTryCenteredLattice=new wxCheckBox(pQuick,ID_CELLEXPLORER_CENTERED,_T("Try Centered Lattices"));
2139 pSizerQuick->Add(mpTryCenteredLattice,0,wxALIGN_CENTER);
2140 mpTryCenteredLattice->SetValue(true);
2142 mpTrySpurious=new wxCheckBox(pQuick,ID_CELLEXPLORER_SPURIOUS,_T("Try with 1 and 2 spurious lines"));
2143 pSizerQuick->Add(mpTrySpurious,0,wxALIGN_CENTER);
2146 pQuick->SetSizer(pSizerQuick);
2147 pSizerQuick->Fit(pQuick);
2148 //pSizerQuick->RecalcSizes();
2150 // Advanced interface
2151 wxWindow *pAdvanced=new wxWindow(pNotebook,-1);
2153 wxStaticBoxSizer *pSizerAdvanced=new wxStaticBoxSizer(wxVERTICAL,pAdvanced);
2155 wxButton *pButton1=new wxButton(pAdvanced,ID_CELLEXPLORER_INDEX,_T("Find cell!"));
2156 pSizerAdvanced->Add(pButton1,0,wxALIGN_CENTER);
2158 wxButton *pQuickButtonExport2=new wxButton(pAdvanced,ID_CELLEXPLORER_EXPORT,_T("Export Indexing Results"));
2159 pSizerAdvanced->Add(pQuickButtonExport2,0,wxALIGN_CENTER);
2161 wxBoxSizer *pLengthSizer=new wxBoxSizer(wxHORIZONTAL);
2162 wxStaticText *pLengthText=new wxStaticText(pAdvanced,-1,_T("Length min, max (A):"));
2163 pLengthSizer->Add(pLengthText,0,wxALIGN_CENTER);
2164 mpLengthMin=new wxTextCtrl(pAdvanced,-1,_T("3"),wxDefaultPosition,wxSize(30,-1),0,
2165 wxTextValidator(wxFILTER_NUMERIC));
2166 pLengthSizer->Add(mpLengthMin,0,wxALIGN_CENTER);
2167 mpLengthMax=new wxTextCtrl(pAdvanced,-1,_T("25"),wxDefaultPosition,wxSize(30,-1),0,
2168 wxTextValidator(wxFILTER_NUMERIC));
2169 pLengthSizer->Add(mpLengthMax,0,wxALIGN_CENTER);
2170 pSizerAdvanced->Add(pLengthSizer,0,wxALIGN_CENTER);
2172 wxBoxSizer *pAngleSizer=new wxBoxSizer(wxHORIZONTAL);
2173 wxStaticText *pAngleText=new wxStaticText(pAdvanced,-1,_T("Angle max(90< <179):"));
2174 pAngleSizer->Add(pAngleText,0,wxALIGN_CENTER);
2175 //mpAngleMin=new wxTextCtrl(this,-1,"90",wxDefaultPosition,wxSize(40,-1),0,
2176 // wxTextValidator(wxFILTER_NUMERIC));
2177 //pAngleSizer->Add(mpAngleMin,0,wxALIGN_CENTER);
2178 mpAngleMax=new wxTextCtrl(pAdvanced,-1,_T("130"),wxDefaultPosition,wxSize(40,-1),0,
2179 wxTextValidator(wxFILTER_NUMERIC));
2180 pAngleSizer->Add(mpAngleMax,0,wxALIGN_CENTER);
2181 pSizerAdvanced->Add(pAngleSizer,0,wxALIGN_CENTER);
2183 wxBoxSizer *pVolumeSizer=new wxBoxSizer(wxHORIZONTAL);
2184 wxStaticText *pVolumeText=new wxStaticText(pAdvanced,-1,_T("Volume min, max (A3):"));
2185 pVolumeSizer->Add(pVolumeText,0,wxALIGN_CENTER);
2186 mpVolumeMin=new wxTextCtrl(pAdvanced,-1,_T("10"),wxDefaultPosition,wxSize(50,-1),0,
2187 wxTextValidator(wxFILTER_NUMERIC));
2188 pVolumeSizer->Add(mpVolumeMin,0,wxALIGN_CENTER);
2189 mpVolumeMax=new wxTextCtrl(pAdvanced,-1,_T("2500"),wxDefaultPosition,wxSize(50,-1),0,
2190 wxTextValidator(wxFILTER_NUMERIC));
2191 pVolumeSizer->Add(mpVolumeMax,0,wxALIGN_CENTER);
2192 pSizerAdvanced->Add(pVolumeSizer,0,wxALIGN_CENTER);
2194 wxBoxSizer *pSpuriousSizer=new wxBoxSizer(wxHORIZONTAL);
2195 wxStaticText *pSpuriousText=new wxStaticText(pAdvanced,-1,_T("Nb spurious lines:"));
2196 pSpuriousSizer->Add(pSpuriousText,0,wxALIGN_CENTER);
2197 mpNbSpurious=new wxTextCtrl(pAdvanced,-1,_T("0"),wxDefaultPosition,wxSize(40,-1),0,
2198 wxTextValidator(wxFILTER_NUMERIC));
2199 pSpuriousSizer->Add(mpNbSpurious,0,wxALIGN_CENTER);
2200 pSizerAdvanced->Add(pSpuriousSizer,0,wxALIGN_CENTER);
2202 wxBoxSizer *pNbPeakSizer=new wxBoxSizer(wxHORIZONTAL);
2203 wxStaticText *pNbPeakText=new wxStaticText(pAdvanced,-1,_T("Use Nb Peaks:"));
2204 pNbPeakSizer->Add(pNbPeakText,0,wxALIGN_CENTER);
2205 mpNbPeak=new wxTextCtrl(pAdvanced,-1,_T("20"),wxDefaultPosition,wxSize(40,-1),0,
2206 wxTextValidator(wxFILTER_NUMERIC));
2207 pNbPeakSizer->Add(mpNbPeak,0,wxALIGN_CENTER);
2208 pSizerAdvanced->Add(pNbPeakSizer,0,wxALIGN_CENTER);
2210 wxBoxSizer *pStopSizer=new wxBoxSizer(wxHORIZONTAL);
2211 wxStaticText* pStopOnScoreText=new wxStaticText(pAdvanced,-1,_T("Stop on Score>"));
2212 pStopSizer->Add(pStopOnScoreText,0,wxALIGN_CENTER);
2213 mpStopOnScore=new wxTextCtrl(pAdvanced,-1,_T("50"),wxDefaultPosition,wxSize(50,-1),0,
2214 wxTextValidator(wxFILTER_NUMERIC));
2215 pStopSizer->Add(mpStopOnScore,0,wxALIGN_CENTER);
2217 wxStaticText* pStopOnDepthText=new wxStaticText(pAdvanced,-1,_T("and depth>="));
2218 pStopSizer->Add(pStopOnDepthText,0,wxALIGN_CENTER);
2219 mpStopOnDepth=new wxTextCtrl(pAdvanced,-1,_T("6"),wxDefaultPosition,wxSize(30,-1),0,
2220 wxTextValidator(wxFILTER_NUMERIC));
2221 pStopSizer->Add(mpStopOnDepth,0,wxALIGN_CENTER);
2222 pSizerAdvanced->Add(pStopSizer,0,wxALIGN_CENTER);
2225 wxBoxSizer *pReportSizer=new wxBoxSizer(wxHORIZONTAL);
2226 wxStaticText* pReportOnScoreText=new wxStaticText(pAdvanced,-1,_T("Report score>"));
2227 pReportSizer->Add(pReportOnScoreText,0,wxALIGN_CENTER);
2228 mpReportOnScore=new wxTextCtrl(pAdvanced,-1,_T("10"),wxDefaultPosition,wxSize(50,-1),0,
2229 wxTextValidator(wxFILTER_NUMERIC));
2230 pReportSizer->Add(mpReportOnScore,0,wxALIGN_CENTER);
2232 wxStaticText* pReportOnDepthText=new wxStaticText(pAdvanced,-1,_T("or depth>="));
2233 pReportSizer->Add(pReportOnDepthText,0,wxALIGN_CENTER);
2234 mpReportOnDepth=new wxTextCtrl(pAdvanced,-1,_T("4"),wxDefaultPosition,wxSize(50,-1),0,
2235 wxTextValidator(wxFILTER_NUMERIC));
2236 pReportSizer->Add(mpReportOnDepth,0,wxALIGN_CENTER);
2237 pSizerAdvanced->Add(pReportSizer,0,wxALIGN_CENTER);
2239 wxBoxSizer *pErrorSizer=new wxBoxSizer(wxHORIZONTAL);
2240 wxStaticText* pErrorText=new wxStaticText(pAdvanced,-1,_T("delta(d)/d^2 error:"));
2241 pErrorSizer->Add(pErrorText,0,wxALIGN_CENTER);
2242 mpErrorD=new wxTextCtrl(pAdvanced,-1,_T("0"),wxDefaultPosition,wxSize(50,-1),0,
2243 wxTextValidator(wxFILTER_NUMERIC));
2244 pErrorSizer->Add(mpErrorD,0,wxALIGN_CENTER);
2245 pSizerAdvanced->Add(pErrorSizer,0,wxALIGN_CENTER);
2247 wxArrayString bravaisChoices;
2248 bravaisChoices.Add(_T("Triclinic"));
2249 bravaisChoices.Add(_T("Monoclinic"));
2250 bravaisChoices.Add(_T("Orthorombic"));
2251 bravaisChoices.Add(_T("Hexagonal"));
2252 bravaisChoices.Add(_T("Rhomboedral"));
2253 bravaisChoices.Add(_T("Tetragonal"));
2254 bravaisChoices.Add(_T("Cubic"));
2255 mpBravais=new wxRadioBox((wxWindow*)pAdvanced,-1,_T("Crystal System"),wxDefaultPosition,wxDefaultSize,bravaisChoices,0,wxRA_SPECIFY_ROWS);
2256 mpBravais->SetSelection(2);
2257 //mpBravais->Enable(0,false);
2258 pSizerAdvanced->Add(mpBravais,0,wxALIGN_CENTER);
2260 wxArrayString algoChoices;
2261 algoChoices.Add(_T("DICVOL"));
2262 //algoChoices.Add(_T("Differential Evolution")); // :TODO: re-enable after testing
2264 mpAlgorithm=new wxRadioBox(pAdvanced,-1,_T("Algorithm"),wxDefaultPosition,wxDefaultSize,algoChoices,0,wxRA_SPECIFY_ROWS);
2265 mpAlgorithm->Enable(1,false);
2266 pSizerAdvanced->Add(mpAlgorithm,0,wxALIGN_CENTER);
2268 pAdvanced->SetSizer(pSizerAdvanced);
2269 pSizerAdvanced->Fit(pAdvanced);
2270 //pSizerAdvanced->RecalcSizes();
2271 pAdvanced->Layout();
2273 pNotebook->AddPage(pAdvanced,_T("Advanced"));
2275 pNotebook->Layout();
2277 wxBoxSizer *pSizer2=new wxBoxSizer(wxVERTICAL);
2279 //wxButton *pButton2=new wxButton(this,ID_CELLEXPLORER_APPLYCELL,"Apply selected cell");
2280 //pSizer2->Add(pButton2,0,wxALIGN_CENTER);
2282 mpFieldCrystal=new WXFieldChoice(this,ID_CELLEXPLORER_CHOOSECRYSTAL,"Choose crystal to apply selected cell to:",200);
2283 pSizer2->Add(mpFieldCrystal,0,wxALIGN_CENTER);
2285 mpAutomaticLeBail=new wxCheckBox(this,ID_CELLEXPLORER_LEBAIL,_T("Automatic Profile Fitting (Le Bail)"));
2286 pSizer2->Add(mpAutomaticLeBail,0,wxALIGN_CENTER);
2288 wxArrayString cells;
2289 mpCell=new wxListBox(this,ID_CELLEXPLORER_SELECTCELL,wxDefaultPosition,wxSize(750,400),cells,wxLB_SINGLE);
2290 mpCell->SetFont(wxFont(9,wxTELETYPE,wxFONTSTYLE_NORMAL,wxFONTWEIGHT_NORMAL));
2291 pSizer2->Add(mpCell,0,wxALIGN_CENTER);
2293 mpLog =new wxTextCtrl(this,-1,_T(""),wxDefaultPosition,wxSize(750,250),wxTE_MULTILINE|wxTE_READONLY|wxTE_DONTWRAP);
2294 mpLog->SetFont(wxFont(9,wxTELETYPE,wxFONTSTYLE_NORMAL,wxFONTWEIGHT_NORMAL));
2295 pSizer2->Add(mpLog,0,wxALIGN_CENTER);
2297 pSizer1->Add(pSizer2,0,wxALIGN_TOP);
2300 pSizer1->Fit(this->GetParent());
2301 pSizer1->SetSizeHints(this);
2303 // Estimate volume from number of peaks at a given dmin
2304 // See J. Appl. Cryst. 20 (1987), 161
2305 unsigned int nb=mpPeakList->GetPeakList().size();
2306 if(nb>20) nb=20;// Just use 20 - beyond that we probably have a lot of weak peaks missed
2307 const float dmin=mpPeakList->GetPeakList()[nb-1].dobs;
2308 const float dmax=mpPeakList->GetPeakList()[0].dobs/10;// /10: assume no peaks at lower resolution
2309 mpLog->AppendText(wxString::Format(_T("Predicted unit vell volume from %2u observed peaks between: dmax=%6.3f A-> dmin=%6.3fA\n"),nb,1/dmax,1/dmin));
2310 mpLog->AppendText(wxString::Format(_T("(Assuming observed lines represent 120%% down to 30%% of existing reflections)\n")));
2311 mpLog->AppendText(wxString::Format(_T(" Cubic P v=%6.0f -> %6.0f A\n"),EstimateCellVolume(dmin,dmax,nb,CUBIC ,LATTICE_P,1.2),EstimateCellVolume(dmin,dmax,nb,CUBIC ,LATTICE_P,0.3)));
2312 mpLog->AppendText(wxString::Format(_T(" Cubic I v=%6.0f -> %6.0f A\n"),EstimateCellVolume(dmin,dmax,nb,CUBIC ,LATTICE_I,1.2),EstimateCellVolume(dmin,dmax,nb,CUBIC ,LATTICE_I,0.3)));
2313 mpLog->AppendText(wxString::Format(_T(" Cubic F v=%6.0f -> %6.0f A\n"),EstimateCellVolume(dmin,dmax,nb,CUBIC ,LATTICE_F,1.2),EstimateCellVolume(dmin,dmax,nb,CUBIC ,LATTICE_F,0.3)));
2314 mpLog->AppendText(wxString::Format(_T(" Tetragonal P v=%6.0f -> %6.0f A\n"),EstimateCellVolume(dmin,dmax,nb,TETRAGONAL ,LATTICE_P,1.2),EstimateCellVolume(dmin,dmax,nb,TETRAGONAL ,LATTICE_P,0.3)));
2315 mpLog->AppendText(wxString::Format(_T(" Tetragonal I v=%6.0f -> %6.0f A\n"),EstimateCellVolume(dmin,dmax,nb,TETRAGONAL ,LATTICE_I,1.2),EstimateCellVolume(dmin,dmax,nb,TETRAGONAL ,LATTICE_I,0.3)));
2316 mpLog->AppendText(wxString::Format(_T(" Orthorombic P v=%6.0f -> %6.0f A\n"),EstimateCellVolume(dmin,dmax,nb,ORTHOROMBIC,LATTICE_P,1.2),EstimateCellVolume(dmin,dmax,nb,ORTHOROMBIC,LATTICE_P,0.3)));
2317 mpLog->AppendText(wxString::Format(_T(" Orthorombic I,C v=%6.0f -> %6.0f A\n"),EstimateCellVolume(dmin,dmax,nb,ORTHOROMBIC,LATTICE_I,1.2),EstimateCellVolume(dmin,dmax,nb,ORTHOROMBIC,LATTICE_I,0.3)));
2318 mpLog->AppendText(wxString::Format(_T(" Orthorombic F v=%6.0f -> %6.0f A\n"),EstimateCellVolume(dmin,dmax,nb,ORTHOROMBIC,LATTICE_F,1.2),EstimateCellVolume(dmin,dmax,nb,ORTHOROMBIC,LATTICE_F,0.3)));
2319 mpLog->AppendText(wxString::Format(_T(" Hexagonal v=%6.0f -> %6.0f A\n"),EstimateCellVolume(dmin,dmax,nb,HEXAGONAL ,LATTICE_P,1.2),EstimateCellVolume(dmin,dmax,nb,HEXAGONAL ,LATTICE_P,0.3)));
2320 mpLog->AppendText(wxString::Format(_T(" Monoclinic P v=%6.0f -> %6.0f A\n"),EstimateCellVolume(dmin,dmax,nb,MONOCLINIC ,LATTICE_P,1.2),EstimateCellVolume(dmin,dmax,nb,MONOCLINIC ,LATTICE_P,0.3)));
2321 mpLog->AppendText(wxString::Format(_T(" Monoclinic C v=%6.0f -> %6.0f A\n"),EstimateCellVolume(dmin,dmax,nb,MONOCLINIC ,LATTICE_C,1.2),EstimateCellVolume(dmin,dmax,nb,MONOCLINIC ,LATTICE_C,0.3)));
2322 mpLog->AppendText(wxString::Format(_T(" Triclinic v=%6.0f -> %6.0f A\n"),EstimateCellVolume(dmin,dmax,nb,TRICLINIC ,LATTICE_P,1.2),EstimateCellVolume(dmin,dmax,nb,TRICLINIC ,LATTICE_P,0.3)));
2325 WXCellExplorer::~WXCellExplorer()
2329 mpDiff->SetExtractionMode(false,false);
2330 mpDiff->UpdateDisplay();
2334 void WXCellExplorer::OnIndex(wxCommandEvent &event)
2338 if(event.GetId()==ID_CELLEXPLORER_INDEX_QUICK)
2340 // Erase spurious record
2341 for(vector<PeakList::hkl>::iterator pos=mpPeakList->mvHKL.begin();pos!=mpPeakList->mvHKL.end();++pos)
2342 pos->isSpurious=false;
2344 // Use at most 30 reflections for indexing
2345 PeakList peaklist=*mpPeakList;
2346 if(peaklist.GetPeakList().size()>20) peaklist.GetPeakList().resize(20);
2348 // Estimate volume from number of peaks at a given dmin
2349 // See J. Appl. Cryst. 20 (1987), 161
2350 unsigned int nb=mpPeakList->GetPeakList().size();
2351 if(nb>20) nb=20;// Just use 20 - beyond that we probably have a lot of weak peaks
2352 float dmin=mpPeakList->GetPeakList()[nb-1].dobs;
2353 const float dmax=mpPeakList->GetPeakList()[0].dobs/10;//assume there are no peaks at lower resolution
2354 mpLog->AppendText(wxString::Format(_T("Predicting volumes from %2u peaks between d=%6.3f and d=%6.3f\n"),nb,1/dmax,1/dmin));
2355 mpLog->AppendText(wxString::Format(_T("Starting indexing using %2u peaks\n"),nb));
2357 mpCellExplorer = new CellExplorer(peaklist,CUBIC,0);
2358 mpCellExplorer->SetLengthMinMax(3,25);
2359 mpCellExplorer->SetAngleMinMax(90*DEG2RAD,140*DEG2RAD);
2360 mpCellExplorer->SetD2Error(0);
2363 if(mpWeakDiffraction->GetValue()) weak_f=0.5;
2364 const bool continueOnSolution=mpContinueOnSolution->GetValue();
2366 const bool noCentered=!(mpTryCenteredLattice->GetValue());
2368 const float stopOnScore=50, reportOnScore=10;
2369 const unsigned int stopOnDepth=6+int(continueOnSolution), reportOnDepth=4;
2371 unsigned int nbSpurious=0;
2372 wxProgressDialog dlgProgress(_T("Indexing..."),_T("Starting Indexing in Quick Mode"),
2373 7,this,wxPD_AUTO_HIDE|wxPD_ELAPSED_TIME|wxPD_CAN_ABORT|wxPD_APP_MODAL);
2375 unsigned int maxNbSpurious=0;
2376 if(mpTrySpurious->GetValue()) maxNbSpurious=2;
2377 while(nbSpurious<=maxNbSpurious)
2379 float t0,minv,maxv,lengthmax;
2380 mpCellExplorer->SetNbSpurious(nbSpurious);
2381 CrystalCentering cent;
2383 for(int lat=0;lat<=2;++lat)
2386 {//LATTICE_P,LATTICE_I,LATTICE_A,LATTICE_B,LATTICE_C,LATTICE_F
2387 case 0:cent=LATTICE_P;centc='P';break;
2388 case 1:cent=LATTICE_I;centc='I';break;
2389 case 2:cent=LATTICE_F;centc='F';break;
2391 minv=EstimateCellVolume(dmin,dmax,nb,CUBIC ,cent,1.5);
2392 maxv=EstimateCellVolume(dmin,dmax,nb,CUBIC ,cent,0.4*weak_f);
2393 mpCellExplorer->SetVolumeMinMax(minv,maxv);
2394 lengthmax=pow(maxv,(float)(1/3.0))*3;
2395 if(lengthmax<25)lengthmax=25;
2396 mpCellExplorer->SetLengthMinMax(3,lengthmax);
2397 mpCellExplorer->SetCrystalSystem(CUBIC);
2398 mpCellExplorer->SetCrystalCentering(cent);
2399 mpLog->AppendText(wxString::Format(_T("CUBIC %c : V= %6.0f -> %6.0f A^3, max length=%6.2fA"),centc,minv,maxv,lengthmax));
2400 t0=chrono.seconds();
2401 if(dlgProgress.Update(0,wxString::Format(_T("CUBIC %c (%u spurious), V=%6.0f-%6.0f, l<%6.2fA\n")
2402 _T("Best Score=%6.1f"),centc,
2403 nbSpurious,minv,maxv,lengthmax,mpCellExplorer->GetBestScore()))==false) break;
2404 mpCellExplorer->DicVol(reportOnScore,reportOnDepth,stopOnScore,stopOnDepth);
2405 mpLog->AppendText(wxString::Format(_T(" -> %3u sols in %6.2fs, best score=%6.1f\n"),
2406 (unsigned int)(mpCellExplorer->GetSolutions().size()),chrono.seconds()-t0,mpCellExplorer->GetBestScore()));
2408 if(noCentered) break;
2410 for(int lat=0;lat<=1;++lat)
2411 if((mpCellExplorer->GetBestScore()<=stopOnScore)||continueOnSolution)
2414 {//LATTICE_P,LATTICE_I,LATTICE_A,LATTICE_B,LATTICE_C,LATTICE_F
2415 case 0:cent=LATTICE_P;centc='P';break;
2416 case 1:cent=LATTICE_I;centc='I';break;
2418 minv=EstimateCellVolume(dmin,dmax,nb,TETRAGONAL,cent,1.5);
2419 maxv=EstimateCellVolume(dmin,dmax,nb,TETRAGONAL,cent,0.4*weak_f);
2420 mpCellExplorer->SetVolumeMinMax(minv,maxv);
2421 float lengthmax=pow(maxv,(float)(1/3.0))*3;
2422 if(lengthmax<25)lengthmax=25;
2423 mpCellExplorer->SetLengthMinMax(3,lengthmax);
2424 mpCellExplorer->SetCrystalSystem(TETRAGONAL);
2425 mpCellExplorer->SetCrystalCentering(cent);
2426 mpLog->AppendText(wxString::Format(_T("TETRAGONAL %c : V= %6.0f -> %6.0f A^3, max length=%6.2fA"),centc,minv,maxv,lengthmax));
2427 t0=chrono.seconds();
2428 if(dlgProgress.Update(1,wxString::Format(_T("TETRAGONAL %c (%u spurious), V=%6.0f-%6.0f, l<%6.2fA\n")
2429 _T("Best Score=%6.1f"),centc,
2430 nbSpurious,minv,maxv,lengthmax,mpCellExplorer->GetBestScore()))==false) break;
2431 mpCellExplorer->DicVol(reportOnScore,reportOnDepth,stopOnScore,stopOnDepth);
2432 mpLog->AppendText(wxString::Format(_T(" -> %3u sols in %6.2fs, best score=%6.1f\n"),
2433 (unsigned int)(mpCellExplorer->GetSolutions().size()),chrono.seconds()-t0,mpCellExplorer->GetBestScore()));
2435 if(noCentered) break;
2437 if((mpCellExplorer->GetBestScore()<=stopOnScore)||continueOnSolution)
2439 minv=EstimateCellVolume(dmin,dmax,nb,RHOMBOEDRAL,LATTICE_P,1.5);
2440 maxv=EstimateCellVolume(dmin,dmax,nb,RHOMBOEDRAL,LATTICE_P,0.4*weak_f);
2441 mpCellExplorer->SetVolumeMinMax(minv,maxv);
2442 lengthmax=pow(maxv,(float)(1/3.0))*3;
2443 if(lengthmax<25)lengthmax=25;
2444 mpCellExplorer->SetLengthMinMax(3,lengthmax);
2445 mpCellExplorer->SetCrystalSystem(RHOMBOEDRAL);
2446 mpCellExplorer->SetCrystalCentering(LATTICE_P);
2447 mpLog->AppendText(wxString::Format(_T("RHOMBOEDRAL : V= %6.0f -> %6.0f A^3, max length=%6.2fA"),minv,maxv,lengthmax));
2448 t0=chrono.seconds();
2449 if(dlgProgress.Update(2,wxString::Format(_T("RHOMBOEDRAL (%u spurious), V=%6.0f-%6.0f, l<%6.2fA\n")
2450 _T("Best Score=%6.1f"),
2451 nbSpurious,minv,maxv,lengthmax,mpCellExplorer->GetBestScore()))==false) break;
2452 mpCellExplorer->DicVol(reportOnScore,reportOnDepth,stopOnScore,stopOnDepth);
2453 mpLog->AppendText(wxString::Format(_T(" -> %3u sols in %6.2fs, best score=%6.1f\n"),
2454 (unsigned int)(mpCellExplorer->GetSolutions().size()),chrono.seconds()-t0,mpCellExplorer->GetBestScore()));
2457 if((mpCellExplorer->GetBestScore()<=stopOnScore)||continueOnSolution)
2459 minv=EstimateCellVolume(dmin,dmax,nb,HEXAGONAL,LATTICE_P,1.5);
2460 maxv=EstimateCellVolume(dmin,dmax,nb,HEXAGONAL,LATTICE_P,0.4*weak_f);
2461 mpCellExplorer->SetVolumeMinMax(minv,maxv);
2462 lengthmax=pow(maxv,(float)(1/3.0))*3;
2463 if(lengthmax<25)lengthmax=25;
2464 mpCellExplorer->SetLengthMinMax(3,lengthmax);
2465 mpCellExplorer->SetCrystalSystem(HEXAGONAL);
2466 mpCellExplorer->SetCrystalCentering(LATTICE_P);
2467 mpLog->AppendText(wxString::Format(_T("HEXAGONAL : V= %6.0f -> %6.0f A^3, max length=%6.2fA"),minv,maxv,lengthmax));
2468 t0=chrono.seconds();
2469 if(dlgProgress.Update(3,wxString::Format(_T("HEXAGONAL (%u spurious), V=%6.0f-%6.0f, l<%6.2fA\n")
2470 _T("Best Score=%6.1f"),
2471 nbSpurious,minv,maxv,lengthmax,mpCellExplorer->GetBestScore()))==false) break;
2472 mpCellExplorer->DicVol(reportOnScore,reportOnDepth,stopOnScore,stopOnDepth);
2473 mpLog->AppendText(wxString::Format(_T(" -> %3u sols in %6.2fs, best score=%6.1f\n"),
2474 (unsigned int)(mpCellExplorer->GetSolutions().size()),chrono.seconds()-t0,mpCellExplorer->GetBestScore()));
2477 for(int lat=0;lat<=5;++lat)
2478 if((mpCellExplorer->GetBestScore()<=stopOnScore)||continueOnSolution)
2481 {//LATTICE_P,LATTICE_I,LATTICE_A,LATTICE_B,LATTICE_C,LATTICE_F
2482 case 0:cent=LATTICE_P;centc='P';break;
2483 case 1:cent=LATTICE_I;centc='I';break;
2484 case 2:cent=LATTICE_A;centc='A';break;
2485 case 3:cent=LATTICE_B;centc='B';break;
2486 case 4:cent=LATTICE_C;centc='C';break;
2487 case 5:cent=LATTICE_F;centc='F';break;
2489 minv=EstimateCellVolume(dmin,dmax,nb,ORTHOROMBIC,cent,1.5);
2490 maxv=EstimateCellVolume(dmin,dmax,nb,ORTHOROMBIC,cent,0.4*weak_f);
2491 mpCellExplorer->SetVolumeMinMax(minv,maxv);
2492 lengthmax=pow(maxv,(float)(1/3.0))*3;
2493 if(lengthmax<25)lengthmax=25;
2494 mpCellExplorer->SetLengthMinMax(3,lengthmax);
2495 mpCellExplorer->SetCrystalSystem(ORTHOROMBIC);
2496 mpCellExplorer->SetCrystalCentering(cent);
2497 mpLog->AppendText(wxString::Format(_T("ORTHOROMBIC %c: V= %6.0f -> %6.0f A^3, max length=%6.2fA"),centc,minv,maxv,lengthmax));
2498 t0=chrono.seconds();
2499 if(dlgProgress.Update(4,wxString::Format(_T("ORTHOROMBIC %c (%u spurious), V=%6.0f-%6.0f, l<%6.2fA\n")
2500 _T("Best Score=%6.1f"),centc,
2501 nbSpurious,minv,maxv,lengthmax,mpCellExplorer->GetBestScore()))==false) break;
2502 mpCellExplorer->DicVol(reportOnScore,reportOnDepth,stopOnScore,stopOnDepth);
2503 mpLog->AppendText(wxString::Format(_T(" -> %3u sols in %6.2fs, best score=%6.1f\n"),
2504 (unsigned int)(mpCellExplorer->GetSolutions().size()),chrono.seconds()-t0,mpCellExplorer->GetBestScore()));
2506 if(noCentered) break;
2508 for(int lat=0;lat<=3;++lat)
2509 if((mpCellExplorer->GetBestScore()<=stopOnScore)||continueOnSolution)
2512 {//LATTICE_P,LATTICE_I,LATTICE_A,LATTICE_B,LATTICE_C,LATTICE_F
2513 case 0:cent=LATTICE_P;centc='P';break;
2514 case 1:cent=LATTICE_C;centc='C';break;
2515 case 2:cent=LATTICE_I;centc='I';break;
2516 case 3:cent=LATTICE_A;centc='A';break;
2518 minv=EstimateCellVolume(dmin,dmax,nb,MONOCLINIC,cent,1.5);
2519 maxv=EstimateCellVolume(dmin,dmax,nb,MONOCLINIC,cent,0.4*weak_f);
2520 mpCellExplorer->SetVolumeMinMax(minv,maxv);
2521 lengthmax=pow(maxv,(float)(1/3.0))*3;
2522 if(lengthmax<25)lengthmax=25;
2523 mpCellExplorer->SetLengthMinMax(3,lengthmax);
2524 mpCellExplorer->SetCrystalSystem(MONOCLINIC);
2525 mpCellExplorer->SetCrystalCentering(cent);
2526 mpLog->AppendText(wxString::Format(_T("MONOCLINIC %c : V= %6.0f -> %6.0f A^3, max length=%6.2fA"),centc,minv,maxv,lengthmax));
2527 t0=chrono.seconds();
2528 if(dlgProgress.Update(5,wxString::Format(_T("MONOCLINIC %c (%u spurious), V=%6.0f-%6.0f, l<%6.2fA\n")
2529 _T("Best Score=%6.1f"),centc,
2530 nbSpurious,minv,maxv,lengthmax,mpCellExplorer->GetBestScore()))==false) break;
2531 mpCellExplorer->DicVol(reportOnScore,reportOnDepth,stopOnScore,stopOnDepth);
2532 mpLog->AppendText(wxString::Format(_T(" -> %3u sols in %6.2fs, best score=%6.1f\n"),
2533 (unsigned int)(mpCellExplorer->GetSolutions().size()),chrono.seconds()-t0,mpCellExplorer->GetBestScore()));
2535 if(noCentered) break;
2539 if((mpCellExplorer->GetBestScore()>=stopOnScore)||(nbSpurious>3)) break;
2540 mpLog->AppendText(wxString::Format(_T("\n Trying now with %2u spurious peaks\n"),nbSpurious));
2546 // Erase spurious record
2547 for(vector<PeakList::hkl>::iterator pos=mpPeakList->mvHKL.begin();pos!=mpPeakList->mvHKL.end();++pos)
2548 pos->isSpurious=false;
2551 double lmin,lmax,amin=90,amax,vmin,vmax,error,stopOnScore,reportOnScore;
2552 long nbspurious,nbPeak,stopOnDepth,reportOnDepth;
2553 s=mpLengthMin->GetValue();s.ToDouble(&lmin);
2554 s=mpLengthMax->GetValue();s.ToDouble(&lmax);
2555 //s=mpAngleMin->GetValue();s.ToDouble(&amin);
2556 s=mpAngleMax->GetValue();s.ToDouble(&amax);
2557 s=mpVolumeMin->GetValue();s.ToDouble(&vmin);
2558 s=mpVolumeMax->GetValue();s.ToDouble(&vmax);
2559 s=mpNbSpurious->GetValue();s.ToLong( urious);
2560 s=mpNbPeak->GetValue();s.ToLong(&nbPeak);
2561 s=mpErrorD->GetValue();s.ToDouble(&error);
2562 s=mpStopOnScore->GetValue();s.ToDouble(&stopOnScore);
2563 s=mpStopOnDepth->GetValue();s.ToLong(&stopOnDepth);
2564 s=mpReportOnScore->GetValue();s.ToDouble(&reportOnScore);
2565 s=mpReportOnDepth->GetValue();s.ToLong(&reportOnDepth);
2567 // Use at most 30 reflections for indexing
2568 if(mpPeakList->GetPeakList().size()>nbPeak) mpPeakList->GetPeakList().resize(nbPeak);
2570 mpCellExplorer = new CellExplorer(*mpPeakList,(CrystalSystem)(mpBravais->GetSelection()),0);
2572 mpCellExplorer->SetLengthMinMax((float)lmin,(float)lmax);
2573 mpCellExplorer->SetAngleMinMax((float)amin*DEG2RAD,(float)amax*DEG2RAD);
2574 mpCellExplorer->SetVolumeMinMax((float)vmin,(float)vmax);
2575 mpCellExplorer->SetNbSpurious((unsigned int)nbspurious);
2576 mpCellExplorer->SetD2Error((float)(error*error));
2578 mpCellExplorer->SetCrystalCentering(LATTICE_P);
2580 cout<<lmin<<" "<<lmax<<" "<<amin<<" "<<amax<<" "<<vmin<<" "<<vmax<<" "<<(unsigned int)nbspurious<<" "<<error*error<<endl;
2582 mpCellExplorer->DicVol(reportOnScore,reportOnDepth,stopOnScore,stopOnDepth);
2584 if(mpAlgorithm->GetSelection()==0) mpCellExplorer->DicVol(reportOnScore,reportOnDepth,stopOnScore,stopOnDepth);
2587 for(unsigned int i=0;i<20;++i)
2589 mpCellExplorer->Evolution(5000,true,0.7,0.5,50);
2590 if(mpCellExplorer->GetBestScore()>stopOnScore) break;
2595 mpLog->AppendText(wxString::Format(_T("Finished indexing, bestscore=%6.1f, elapsed time=%6.2fs\n"),
2596 mpCellExplorer->GetBestScore(),chrono.seconds()));
2597 // Merge similar solutions - useful here for solutions from different runs/different systems
2598 mpCellExplorer->ReduceSolutions();
2599 if(mpCellExplorer->GetSolutions().size()>0)
2604 for(list<pair<RecUnitCell,float> >::const_iterator pos=mpCellExplorer->GetSolutions().begin();
2605 pos!=mpCellExplorer->GetSolutions().end();++pos)
2607 vector<float> uc=pos->first.DirectUnitCell();
2608 if(pos==mpCellExplorer->GetSolutions().begin()) bestvol=uc[6]*.99999;
2609 const float relvol=uc[6]/bestvol;
2611 switch(pos->first.mlattice)
2613 case TRICLINIC:sys="TRICLINIC"; break;
2614 case MONOCLINIC:sys="MONOCLINIC"; break;
2615 case ORTHOROMBIC:sys="ORTHOROMBIC"; break;
2616 case HEXAGONAL:sys="HEXAGONAL"; break;
2617 case RHOMBOEDRAL:sys="RHOMBOEDRAL"; break;
2618 case TETRAGONAL:sys="TETRAGONAL"; break;
2619 case CUBIC:sys="CUBIC"; break;
2622 switch(pos->first.mCentering)
2624 case LATTICE_P:centc='P'; break;
2625 case LATTICE_I:centc='I'; break;
2626 case LATTICE_A:centc='A'; break;
2627 case LATTICE_B:centc='B'; break;
2628 case LATTICE_C:centc='C'; break;
2629 case LATTICE_F:centc='F'; break;
2631 stringstream spurious;
2632 if(pos->first.mNbSpurious>0)
2633 spurious<<"(nbspurious = "<<pos->first.mNbSpurious<<")";
2635 sprintf(buf,"Score=%6.1f V=%6.1f(%3.1fV) %6.3f %6.3f %6.3f %6.2f %6.2f %6.2f %s %c %s",pos->second,
2636 uc[6],relvol,uc[0],uc[1],uc[2],uc[3]*RAD2DEG,uc[4]*RAD2DEG,uc[5]*RAD2DEG,sys.c_str(),centc,spurious.str().c_str());
2638 sols.Add(wxString::FromAscii(buf));
2643 if(mpGraph!=0) mpGraph->Refresh(FALSE);
2645 void WXCellExplorer::OnSelectCell(wxCommandEvent &event)
2647 VFN_DEBUG_ENTRY("WXCellExplorer::OnSelectCell()",7)
2648 const int choice=mpCell->GetSelection();
2649 if(choice!=wxNOT_FOUND)
2653 s=mpNbSpurious->GetValue();s.ToLong( urious);
2655 list<pair<RecUnitCell,float> >::const_iterator pos=mpCellExplorer->GetSolutions().begin();
2656 for(int i=0;i<choice;++i)++pos;// We need a random access ?
2657 // This will update the hkl in the list and therefore on the graph
2658 Score(*mpPeakList,pos->first,nbspurious,true,true,true);
2661 // Apply crystal structure
2662 list<pair<RecUnitCell,float> >::const_iterator pos=mpCellExplorer->GetSolutions().begin();
2663 for(int i=0;i<choice;++i)++pos;// We need a random access ?
2664 vector<float> uc=pos->first.DirectUnitCell();
2665 mpCrystal->GetPar("a").SetValue(uc[0]);
2666 mpCrystal->GetPar("b").SetValue(uc[1]);
2667 mpCrystal->GetPar("c").SetValue(uc[2]);
2668 mpCrystal->GetPar("alpha").SetValue(uc[3]);
2669 mpCrystal->GetPar("beta").SetValue(uc[4]);
2670 mpCrystal->GetPar("gamma").SetValue(uc[5]);
2671 // Choose the spcegroup with the highest possible symmetry given the centering used.
2672 // We only try P, I, F, but also handle others, just in case
2673 switch(pos->first.mCentering)
2677 switch(pos->first.mlattice)
2679 case TRICLINIC:mpCrystal->ChangeSpaceGroup("P-1");break;
2680 case MONOCLINIC:mpCrystal->ChangeSpaceGroup("P2/m");break;
2681 case ORTHOROMBIC:mpCrystal->ChangeSpaceGroup("Pmmm");break;
2682 case HEXAGONAL:mpCrystal->ChangeSpaceGroup("P6/mmm");break;
2683 case RHOMBOEDRAL:mpCrystal->ChangeSpaceGroup("R-3m");break;
2684 case TETRAGONAL:mpCrystal->ChangeSpaceGroup("P4/mmm");break;
2685 case CUBIC:mpCrystal->ChangeSpaceGroup("Pm-3m");break;
2691 switch(pos->first.mlattice)
2693 case MONOCLINIC:mpCrystal->ChangeSpaceGroup("I2/m");break;
2694 case ORTHOROMBIC:mpCrystal->ChangeSpaceGroup("I222");break;
2695 case TETRAGONAL:mpCrystal->ChangeSpaceGroup("I4/mmm");break;
2696 case CUBIC:mpCrystal->ChangeSpaceGroup("Im-3m");break;
2702 switch(pos->first.mlattice)
2704 case MONOCLINIC:mpCrystal->ChangeSpaceGroup("A2/m");break;
2705 case ORTHOROMBIC:mpCrystal->ChangeSpaceGroup("Amm2");break;
2711 switch(pos->first.mlattice)
2713 case MONOCLINIC:mpCrystal->ChangeSpaceGroup("C2/m");break;
2714 case ORTHOROMBIC:mpCrystal->ChangeSpaceGroup("Cmmm");break;
2718 case LATTICE_F://,LATTICE_A,LATTICE_B,LATTICE_C};
2720 switch(pos->first.mlattice)
2722 case ORTHOROMBIC:mpCrystal->ChangeSpaceGroup("Fmmm");break;
2723 case CUBIC:mpCrystal->ChangeSpaceGroup("Fm-3m");break;
2728 mpCrystal->UpdateDisplay();
2731 if(mpAutomaticLeBail->GetValue())
2733 VFN_DEBUG_MESSAGE("WXCellExplorer::OnSelectCell():auto-Le Bail",7);
2735 const bool fitzero=true,
2740 fitdispltransp=false,
2744 wxProgressDialog dlgProgress(_T("Le Bail and Profile Fitting"),_T("Le Bail Fitting, cycle #0/20"),
2745 25,this,wxPD_AUTO_HIDE|wxPD_ELAPSED_TIME|wxPD_CAN_ABORT|wxPD_APP_MODAL);
2746 mpDiff->SetExtractionMode(true,true);
2747 VFN_DEBUG_MESSAGE("WXCellExplorer::OnSelectCell():auto-Le Bail",7);
2749 LSQNumObj lsqobj("Profile Fitting object");
2750 lsqobj.SetRefinedObj(mpDiff->GetParentPowderPattern(),0,true,true);
2751 lsqobj.PrepareRefParList(true);
2752 lsqobj.SetParIsUsed(gpRefParTypeObjCryst,false);
2753 lsqobj.SetParIsUsed(gpRefParTypeScattDataScale,true);
2754 lsqobj.SetParIsUsed(gpRefParTypeScattDataProfile,true);
2755 lsqobj.SetParIsUsed(gpRefParTypeScattDataCorrPos,true);
2756 lsqobj.SetParIsUsed(gpRefParTypeScattDataBackground,true);
2757 lsqobj.SetParIsUsed(gpRefParTypeUnitCell,true);
2758 lsqobj.SetParIsFixed(gpRefParTypeObjCryst,true);
2759 lsqobj.SetParIsFixed(gpRefParTypeScattDataScale,false);
2760 std::list<RefinablePar*> vnewpar;
2761 std::list<const RefParType*> vnewpartype;
2763 // :TODO: take car of other profiles than pseudo-voigt (DE-PV)
2765 // Start from default values
2766 // :TODO: store values initially set by user, if any ?
2767 lsqobj.GetCompiledRefinedObj().GetPar("Zero").SetValue(0);
2768 lsqobj.GetCompiledRefinedObj().GetPar("W").SetValue(0.01*DEG2RAD*DEG2RAD);
2769 lsqobj.GetCompiledRefinedObj().GetPar("U").SetValue(0);
2770 lsqobj.GetCompiledRefinedObj().GetPar("V").SetValue(0);
2771 lsqobj.GetCompiledRefinedObj().GetPar("Eta0").SetValue(0.5);
2772 lsqobj.GetCompiledRefinedObj().GetPar("Eta1").SetValue(0);
2773 lsqobj.GetCompiledRefinedObj().GetPar("Asym0").SetValue(1);
2774 lsqobj.GetCompiledRefinedObj().GetPar("Asym1").SetValue(0);
2775 lsqobj.GetCompiledRefinedObj().GetPar("Asym2").SetValue(0);
2776 lsqobj.GetCompiledRefinedObj().GetPar("2ThetaDispl").SetValue(0);
2777 lsqobj.GetCompiledRefinedObj().GetPar("2ThetaTransp").SetValue(0);
2779 // Start from bayesian-optimised background
2780 const unsigned int nbcomp= mpGraph->GetWXPowderPattern().GetPowderPattern().GetNbPowderPatternComponent();
2781 for(unsigned int i=0;i<nbcomp;++i)
2782 if(mpGraph->GetWXPowderPattern().GetPowderPattern().GetPowderPatternComponent(i).GetClassName()=="PowderPatternBackground")
2784 mpLog->AppendText(wxString::Format(_T("Bayesian optimisation of background\n\n")));
2785 if(dlgProgress.Update(0,_T("Bayesian optimisation of background"))==false) return;
2786 PowderPatternBackground *pback=dynamic_cast<PowderPatternBackground *>
2787 (&(mpGraph->GetWXPowderPattern().GetPowderPattern().GetPowderPatternComponent(i)));
2788 pback->UnFixAllPar();
2789 pback->OptimizeBayesianBackground();
2793 mpLog->AppendText(wxString::Format(_T("Starting 20 Le Bail cycles\n")));
2794 for(int i=0;i<10;++i)
2796 VFN_DEBUG_MESSAGE("WXCellExplorer::OnSelectCell():auto-Le Bail #"<<i,7);
2797 mpDiff->ExtractLeBail(2);
2798 mpDiff->GetParentPowderPattern().FitScaleFactorForRw();
2799 VFN_DEBUG_MESSAGE("WXCellExplorer::OnSelectCell():auto-Le Bail #"<<i,7);
2800 mpDiff->GetParentPowderPattern().UpdateDisplay();
2801 if(dlgProgress.Update(i,wxString::Format(_T("Le Bail Fitting, cycle #%d/20"),i*2))==false) return;
2803 mpLog->AppendText(wxString::Format(_T(" => Rwp=%5.3f%%, GoF=%7.3f\n"),
2804 mpDiff->GetParentPowderPattern().GetRw()*100,
2805 mpDiff->GetParentPowderPattern().GetChi2()
2806 /mpDiff->GetParentPowderPattern().GetNbPointUsed()));
2808 if(fitzero) vnewpar.push_back(&lsqobj.GetCompiledRefinedObj().GetPar("Zero"));
2811 mpLog->AppendText(wxString::Format(_T("Fitting zero shift\n")));
2812 if(dlgProgress.Update(11,_T("Fitting zero shift"))==false) return;
2813 const bool result = lsqobj.SafeRefine(vnewpar, vnewpartype, 1.01, 5,true,false);
2814 if(!result) mpLog->AppendText(_T(" OUPS: parameter did not improve fit => fix & continue\n"));
2817 vnewpartype.clear();
2818 mpDiff->GetParentPowderPattern().FitScaleFactorForRw();
2819 mpDiff->GetParentPowderPattern().UpdateDisplay();
2820 mpLog->AppendText(wxString::Format(_T(" => Rwp=%6.3f%%, GoF=%7.3f\n"),
2821 mpDiff->GetParentPowderPattern().GetRw()*100,
2822 mpDiff->GetParentPowderPattern().GetChi2()
2823 /mpDiff->GetParentPowderPattern().GetNbPointUsed()));
2825 if(fitwidth0) vnewpar.push_back(&lsqobj.GetCompiledRefinedObj().GetPar("W"));
2828 mpLog->AppendText(wxString::Format(_T("Fitting zero constant width\n")));
2829 if(dlgProgress.Update(11,_T("Fitting constant width"))==false) return;
2830 const bool result = lsqobj.SafeRefine(vnewpar, vnewpartype, 1.01, 5,true,false);
2831 if(!result) mpLog->AppendText(_T(" OUPS: parameter did not improve fit => fix & continue\n"));
2834 vnewpartype.clear();
2835 mpDiff->GetParentPowderPattern().FitScaleFactorForRw();
2836 mpDiff->GetParentPowderPattern().UpdateDisplay();
2837 mpLog->AppendText(wxString::Format(_T(" => Rwp=%6.3f%%, GoF=%7.3f\n"),
2838 mpDiff->GetParentPowderPattern().GetRw()*100,
2839 mpDiff->GetParentPowderPattern().GetChi2()
2840 /mpDiff->GetParentPowderPattern().GetNbPointUsed()));
2843 if(fitwidth) vnewpar.push_back(&lsqobj.GetCompiledRefinedObj().GetPar("U"));
2844 if(fitwidth) vnewpar.push_back(&lsqobj.GetCompiledRefinedObj().GetPar("V"));
2845 if(fiteta) vnewpar.push_back(&lsqobj.GetCompiledRefinedObj().GetPar("Eta0"));
2846 if(fitwidth||fiteta)
2848 mpLog->AppendText(wxString::Format(_T("Fitting width and gaussian/lorentzian fixed mix\n")));
2849 if(dlgProgress.Update(12,_T("Fitting variable width and gaussian/lorentzian fixed mix"))==false) return;
2850 const bool result = lsqobj.SafeRefine(vnewpar, vnewpartype, 1.01, 5,true,false);
2851 if(!result) mpLog->AppendText(_T(" OUPS: parameter did not improve fit => fix & continue\n"));
2853 vnewpartype.clear();
2854 mpDiff->GetParentPowderPattern().FitScaleFactorForRw();
2855 mpDiff->GetParentPowderPattern().UpdateDisplay();
2856 mpLog->AppendText(wxString::Format(_T(" => Rwp=%6.3f%%, GoF=%7.3f\n"),
2857 mpDiff->GetParentPowderPattern().GetRw()*100,
2858 mpDiff->GetParentPowderPattern().GetChi2()
2859 /mpDiff->GetParentPowderPattern().GetNbPointUsed()));
2862 if(fiteta) vnewpar.push_back(&lsqobj.GetCompiledRefinedObj().GetPar("Eta1"));
2865 mpLog->AppendText(wxString::Format(_T("Fitting variable width and gaussian/lorentzian mix\n")));
2866 if(dlgProgress.Update(13,_T("Fitting variable width and gaussian/lorentzian mix"))==false) return;
2867 const bool result = lsqobj.SafeRefine(vnewpar, vnewpartype, 1.01, 5,true,false);
2868 if(!result) mpLog->AppendText(_T(" OUPS: parameter did not improve fit => fix & continue\n"));
2870 vnewpartype.clear();
2871 mpDiff->GetParentPowderPattern().FitScaleFactorForRw();
2872 mpDiff->GetParentPowderPattern().UpdateDisplay();
2873 mpLog->AppendText(wxString::Format(_T(" => Rwp=%6.3f%%, GoF=%7.3f\n"),
2874 mpDiff->GetParentPowderPattern().GetRw()*100,
2875 mpDiff->GetParentPowderPattern().GetChi2()
2876 /mpDiff->GetParentPowderPattern().GetNbPointUsed()));
2879 if(fitasym) vnewpar.push_back(&lsqobj.GetCompiledRefinedObj().GetPar("Asym0"));
2880 if(fitasym) vnewpar.push_back(&lsqobj.GetCompiledRefinedObj().GetPar("Asym1"));
2881 if(fitasym) vnewpar.push_back(&lsqobj.GetCompiledRefinedObj().GetPar("Asym2"));
2882 if(fitdispltransp) vnewpar.push_back(&lsqobj.GetCompiledRefinedObj().GetPar("2ThetaDispl"));
2883 if(fitdispltransp) vnewpar.push_back(&lsqobj.GetCompiledRefinedObj().GetPar("2ThetaTransp"));
2884 if(fitdispltransp||fitasym)
2886 mpLog->AppendText(wxString::Format(_T("Fitting assymetry and sample displacement/transparency\n")));
2887 if(dlgProgress.Update(14,_T("Fitting assymetry and sample displacement/transparency"))==false) return;
2888 const bool result = lsqobj.SafeRefine(vnewpar, vnewpartype, 1.01, 5,true,false);
2889 if(!result) mpLog->AppendText(_T(" OUPS: parameter did not improve fit => fix & continue\n"));
2891 vnewpartype.clear();
2892 mpDiff->GetParentPowderPattern().FitScaleFactorForRw();
2893 mpDiff->GetParentPowderPattern().UpdateDisplay();
2894 mpLog->AppendText(wxString::Format(_T(" => Rwp=%6.3f%%, GoF=%7.3f\n"),
2895 mpDiff->GetParentPowderPattern().GetRw()*100,
2896 mpDiff->GetParentPowderPattern().GetChi2()
2897 /mpDiff->GetParentPowderPattern().GetNbPointUsed()));
2902 lsqobj.SetParIsFixed(gpRefParTypeScattDataBackground,false);
2903 // Make sure points beyond max resolution are not optimized
2904 const unsigned int nbcomp= mpGraph->GetWXPowderPattern().GetPowderPattern().GetNbPowderPatternComponent();
2905 for(unsigned int i=0;i<nbcomp;++i)
2906 if(mpGraph->GetWXPowderPattern().GetPowderPattern().GetPowderPatternComponent(i).GetClassName()=="PowderPatternBackground")
2908 PowderPatternBackground *pback=dynamic_cast<PowderPatternBackground *>
2909 (&(mpGraph->GetWXPowderPattern().GetPowderPattern().GetPowderPatternComponent(i)));
2910 pback->FixParametersBeyondMaxresolution(lsqobj.GetCompiledRefinedObj());
2912 for(unsigned int i=0; i<lsqobj.GetCompiledRefinedObj().GetNbPar();i++)
2913 if( (lsqobj.GetCompiledRefinedObj().GetPar(i).IsFixed()==false)
2914 &&(lsqobj.GetCompiledRefinedObj().GetPar(i).GetType()==gpRefParTypeScattDataBackground))
2915 vnewpar.push_back(&lsqobj.GetCompiledRefinedObj().GetPar(i));
2917 mpLog->AppendText(wxString::Format(_T("Fitting background\n")));
2918 if(dlgProgress.Update(15,_T("Fitting background"))==false) return;
2919 const bool result = lsqobj.SafeRefine(vnewpar, vnewpartype, 1.01, 5,true,false);
2920 if(!result) mpLog->AppendText(_T(" OUPS: parameter did not improve fit => fix & continue\n"));
2922 vnewpartype.clear();
2923 mpDiff->GetParentPowderPattern().FitScaleFactorForRw();
2924 mpDiff->GetParentPowderPattern().UpdateDisplay();
2925 mpLog->AppendText(wxString::Format(_T(" => Rwp=%6.3f%%, GoF=%7.3f\n"),
2926 mpDiff->GetParentPowderPattern().GetRw()*100,
2927 mpDiff->GetParentPowderPattern().GetChi2()
2928 /mpDiff->GetParentPowderPattern().GetNbPointUsed()));
2931 if(fitcell) vnewpartype.push_back(gpRefParTypeUnitCell);
2934 mpLog->AppendText(wxString::Format(_T("Fitting unit cell\n")));
2935 if(dlgProgress.Update(16,_T("Fitting unit cell"))==false) return;
2936 const bool result = lsqobj.SafeRefine(vnewpar, vnewpartype, 1.01, 5,true,false);
2937 if(!result) mpLog->AppendText(_T(" OUPS: parameter did not improve fit => fix & continue\n"));
2939 vnewpartype.clear();
2940 mpDiff->GetParentPowderPattern().FitScaleFactorForRw();
2941 mpDiff->GetParentPowderPattern().UpdateDisplay();
2942 mpLog->AppendText(wxString::Format(_T(" => Rwp=%6.3f%%, GoF=%7.3f\n"),
2943 mpDiff->GetParentPowderPattern().GetRw()*100,
2944 mpDiff->GetParentPowderPattern().GetChi2()
2945 /mpDiff->GetParentPowderPattern().GetNbPointUsed()));
2948 // Run Le Bail again from scratch
2949 const REAL lastchi2=mpDiff->GetParentPowderPattern().GetChi2();
2950 CrystVector_REAL lastFhklObsSq;
2951 lastFhklObsSq = mpDiff->GetFhklObsSq();
2952 mpDiff->SetExtractionMode(true,true);
2953 mpLog->AppendText(wxString::Format(_T("Starting 10 Le Bail cycles\n")));
2954 for(int i=17;i<22;++i)
2956 if(dlgProgress.Update(i,wxString::Format(_T("Le Bail Fitting, cycle #%d/10"),(i-17)*2))==false) return;
2957 mpDiff->ExtractLeBail(2);
2958 mpDiff->GetParentPowderPattern().FitScaleFactorForRw();
2959 mpDiff->GetParentPowderPattern().UpdateDisplay();
2961 cout<<"Before/after last Le Bail: "<<lastchi2<<" "<<mpDiff->GetParentPowderPattern().GetChi2()<<endl;
2962 if(mpDiff->GetParentPowderPattern().GetChi2() > lastchi2)
2964 mpLog->AppendText(_T("Fit did not improve during last LeBail => reverting to previous intensities\n"));
2965 mpDiff->SetFhklObsSq(lastFhklObsSq);
2966 mpDiff->GetParentPowderPattern().FitScaleFactorForRw();
2968 mpLog->AppendText(wxString::Format(_T(" => Rwp=%5.3f%%, GoF=%7.3f\n"),
2969 mpDiff->GetParentPowderPattern().GetRw()*100,
2970 mpDiff->GetParentPowderPattern().GetChi2()
2971 /mpDiff->GetParentPowderPattern().GetNbPointUsed()));
2973 mpLog->AppendText(wxString::Format(_T("Last fit...\n")));
2974 if(dlgProgress.Update(23,_T("Last fit..."))==false) return;
2975 lsqobj.SafeRefine(vnewpar, vnewpartype, 1.01, 5,true,false);
2976 mpDiff->GetParentPowderPattern().FitScaleFactorForRw();
2977 mpLog->AppendText(wxString::Format(_T(" => Rwp=%5.3f%%, GoF=%7.3f\n"),
2978 mpDiff->GetParentPowderPattern().GetRw()*100,
2979 mpDiff->GetParentPowderPattern().GetChi2()
2980 /mpDiff->GetParentPowderPattern().GetNbPointUsed()));
2981 mpDiff->GetParentPowderPattern().UpdateDisplay();
2982 mpCrystal->UpdateDisplay();
2985 catch(const ObjCrystException &except)
2987 mpLog->AppendText(wxString::Format(_T(" OOPS : refinement diverged ! Aborting.")));
2989 if(mpGraph!=0) mpGraph->Refresh(FALSE);
2990 //:TODO: store refined cell parameters, display GoF in cell list
2992 VFN_DEBUG_EXIT("WXCellExplorer::OnSelectCell",7)
2994 void WXCellExplorer::OnApplyCell(wxCommandEvent &event)
2996 const int choice=mpCell->GetSelection();
2997 if((mpCrystal!=0)&&(choice!=wxNOT_FOUND))
2999 list<pair<RecUnitCell,float> >::const_iterator pos=mpCellExplorer->GetSolutions().begin();
3000 for(int i=0;i<choice;++i)++pos;// We need a random access ?
3001 vector<float> uc=pos->first.DirectUnitCell();
3002 mpCrystal->GetPar("a").SetValue(uc[0]);
3003 mpCrystal->GetPar("b").SetValue(uc[1]);
3004 mpCrystal->GetPar("c").SetValue(uc[2]);
3005 mpCrystal->GetPar("alpha").SetValue(uc[3]);
3006 mpCrystal->GetPar("beta").SetValue(uc[4]);
3007 mpCrystal->GetPar("gamma").SetValue(uc[5]);
3008 mpCrystal->UpdateDisplay();
3011 wxCommandEvent ev(ID_POWDERGRAPH_MENU_UPDATE);
3012 mpGraph->OnUpdate(ev);
3017 void WXCellExplorer::OnChooseCrystal(wxCommandEvent &event)
3019 VFN_DEBUG_MESSAGE("WXCellExplorer::OnChooseCrystal()",6)
3020 WXCrystValidateAllUserInput();
3023 mpCrystal=WXDialogChooseFromRegistry(gCrystalRegistry,(wxWindow*)this, "Choose a Crystal Structure:",choice);
3026 mpFieldCrystal->SetValue("No Crystal chosen");
3027 mpAutomaticLeBail->SetValue(false);
3030 mpFieldCrystal->SetValue(mpCrystal->GetName());
3033 void WXCellExplorer::OnAutoLeBail(wxCommandEvent &event)
3037 mpAutomaticLeBail->SetValue(false);
3040 VFN_DEBUG_ENTRY("WXCellExplorer::OnAutoLeBail()",7)
3041 // Check if powder pattern has a background phase
3042 const unsigned int nbcomp= mpGraph->GetWXPowderPattern().GetPowderPattern().GetNbPowderPatternComponent();
3043 bool needBackground=true;
3044 for(unsigned int i=0;i<nbcomp;++i)
3045 if(mpGraph->GetWXPowderPattern().GetPowderPattern().GetPowderPatternComponent(i).GetClassName()=="PowderPatternBackground")
3047 needBackground=false;
3052 int answer =wxMessageBox(_T("To automatically run profile-fitting\n")
3053 _T("and Le Bail extraction, you must have\n")
3054 _T("defined a background phase for the pattern\n")
3055 _T("and you will need to choose a crystal phase\n\n")
3056 _T("Do you want to do that now ?"),
3057 _T("Add Background ?"),wxYES_NO|wxICON_QUESTION);
3060 mpAutomaticLeBail->SetValue(false);
3064 mpGraph->GetWXPowderPattern().OnMenuAddCompBackgdBayesian(ev);
3066 // Check if a crystal structure has been selected to apply the calculated cell
3069 if(gCrystalRegistry.GetNb()==0)
3071 mpCrystal=new Crystal(4,5,6,"P1");
3072 mpCrystal->SetName("Indexing Result");
3073 wxTheApp->GetTopWindow()->Layout();
3074 wxTheApp->GetTopWindow()->SendSizeEvent();
3078 int answer =wxMessageBox(_T("To automatically run profile-fitting\n")
3079 _T("and Le Bail extraction, you must have\n")
3080 _T("defined a Crystal phase to apply the cell to\n\n")
3081 _T("Do you want to use an EXISTING crystal structure ?\n")
3082 _T("(otherwise a new one will be created for you)"),
3083 _T("Select Crystal ?"),wxYES_NO|wxICON_QUESTION);
3086 mpCrystal=new Crystal(4,5,6,"P1");
3087 mpCrystal->SetName("Indexing Result");
3088 wxTheApp->GetTopWindow()->Layout();
3089 wxTheApp->GetTopWindow()->SendSizeEvent();
3094 this->OnChooseCrystal(ev);
3095 if(0==mpCrystal) return;
3100 // Now make sure this Crystal structure is used by the powder pattern object
3101 bool needPowderPatternDiffraction=true;
3102 unsigned int nbPowderPatternDiffraction=0;
3103 for(unsigned int i=0;i<nbcomp;++i)
3104 if(mpGraph->GetWXPowderPattern().GetPowderPattern().GetPowderPatternComponent(i).GetClassName()=="PowderPatternDiffraction")
3106 nbPowderPatternDiffraction++;
3107 mpDiff=dynamic_cast<PowderPatternDiffraction*>
3108 (&(mpGraph->GetWXPowderPattern().GetPowderPattern().GetPowderPatternComponent(i)));
3109 if(&(mpDiff->GetCrystal())==mpCrystal)
3111 needPowderPatternDiffraction=false;
3115 VFN_DEBUG_MESSAGE("WXCellExplorer::OnAutoLeBail():needPowderPatternDiffraction=="<<needPowderPatternDiffraction,7)
3116 if(needPowderPatternDiffraction)
3118 if(nbPowderPatternDiffraction>0)
3120 int answer =wxMessageBox(_T("To automatically run profile-fitting\n")
3121 _T("and Le Bail extraction, you must assign\n")
3122 _T("the Crystal to a Diffraction Component\n\n")
3123 _T("Do you want to use an already existing one ?"),
3124 _T("Use Crystal Phase ?"),wxYES_NO|wxICON_QUESTION);
3127 //if(nbPowderPatternDiffraction==1) :TODO: handle multiple phases
3129 for(unsigned int i=0;i<nbcomp;++i)
3130 if(mpGraph->GetWXPowderPattern().GetPowderPattern().GetPowderPatternComponent(i).GetClassName()=="PowderPatternDiffraction")
3132 mpDiff=dynamic_cast<PowderPatternDiffraction*>
3133 (&(mpGraph->GetWXPowderPattern().GetPowderPattern().GetPowderPatternComponent(i)));
3134 mpDiff->SetCrystal(*mpCrystal);
3141 {// Create one crystalline phase
3142 VFN_DEBUG_MESSAGE("WXCellExplorer::OnAutoLeBail():Create PowderPatternDiffraction",7)
3143 mpDiff=new PowderPatternDiffraction;
3144 mpDiff->SetCrystal(*mpCrystal);
3145 mpGraph->GetWXPowderPattern().GetPowderPattern().AddPowderPatternComponent(*mpDiff);
3146 if(mpGraph->GetWXPowderPattern().GetPowderPattern().GetRadiation().GetWavelengthType()==WAVELENGTH_TOF)
3148 wxCommandEvent event(wxEVT_COMMAND_MENU_SELECTED,ID_POWDERDIFF_PROFILE_DEPV);
3149 wxPostEvent(mpDiff->WXGet(),event);
3151 mpGraph->GetWXPowderPattern().GetPowderPattern().Prepare();
3152 mpGraph->GetWXPowderPattern().CrystUpdate();
3153 wxTheApp->GetTopWindow()->Layout();
3154 wxTheApp->GetTopWindow()->SendSizeEvent();
3157 // Limit resolution (:TODO: Take into account density of peask to limit to ~100 reflections)
3158 unsigned int nbpeak = mpPeakList->GetPeakList().size();
3159 if(nbpeak>40) nbpeak = 40;
3160 REAL max_stol = mpPeakList->GetPeakList()[nbpeak-1].dobs/2;
3161 if(max_stol>0.5) max_stol=0.5;
3162 mpDiff->GetParentPowderPattern().SetMaxSinThetaOvLambda(max_stol);
3163 mpLog->AppendText(wxString::Format(_T("\n\nNOTE: automatically set max(sin(theta)/lambda)=%5.3f (d=%5.2fA) for automatic Le Bail & profile fitting\n\n"), max_stol,1/(2*max_stol)));
3164 mpDiff->GetParentPowderPattern().UpdateDisplay();
3165 // If one cell is already selected, do optimization immediately
3166 if(mpCell->GetSelection()>=0)
3168 VFN_DEBUG_MESSAGE("WXCellExplorer::OnAutoLeBail()->OnSelectCell()",7)
3169 cout<<mpCell->GetSelection()<<endl;
3171 this->OnSelectCell(ev);
3173 VFN_DEBUG_EXIT("WXCellExplorer::OnAutoLeBail()",7)
3176 void WXCellExplorer::OnExportIndexingResults(wxCommandEvent &event)
3179 if(mpCellExplorer==0) ok = false;
3182 if(mpCellExplorer->GetSolutions().size()==0) ok = false;
3186 wxMessageDialog dumbUser(this,_T("There are no solutions. Index first !"),
3187 _T("Whooops"),wxOK|wxICON_EXCLAMATION);
3188 dumbUser.ShowModal();
3192 wxFileDialog save(this,_T("Choose a file"),_T(""),_T(""),_T("*.csv"),wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
3193 if(save.ShowModal() != wxID_OK) return;
3195 ofstream out(save.GetPath().ToAscii());
3196 if(!out) return;//:TODO:
3200 out <<"Score, Volume, Volume/V_best, a, b, c, alpha, beta, gamma, Lattice, Centering, NbSpurious"<<endl;
3201 for(list<pair<RecUnitCell,float> >::const_iterator pos=mpCellExplorer->GetSolutions().begin();
3202 pos!=mpCellExplorer->GetSolutions().end();++pos)
3204 vector<float> uc=pos->first.DirectUnitCell();
3205 if(pos==mpCellExplorer->GetSolutions().begin()) bestvol=uc[6]*.99999;
3206 const float relvol=uc[6]/bestvol;
3208 switch(pos->first.mlattice)
3210 case TRICLINIC:sys="TRICLINIC"; break;
3211 case MONOCLINIC:sys="MONOCLINIC"; break;
3212 case ORTHOROMBIC:sys="ORTHOROMBIC"; break;
3213 case HEXAGONAL:sys="HEXAGONAL"; break;
3214 case RHOMBOEDRAL:sys="RHOMBOEDRAL"; break;
3215 case TETRAGONAL:sys="TETRAGONAL"; break;
3216 case CUBIC:sys="CUBIC"; break;
3219 switch(pos->first.mCentering)
3221 case LATTICE_P:centc='P'; break;
3222 case LATTICE_I:centc='I'; break;
3223 case LATTICE_A:centc='A'; break;
3224 case LATTICE_B:centc='B'; break;
3225 case LATTICE_C:centc='C'; break;
3226 case LATTICE_F:centc='F'; break;
3228 stringstream spurious;
3229 if(pos->first.mNbSpurious>0)
3230 spurious<<"(nbspurious = "<<pos->first.mNbSpurious<<")";
3232 out<<pos->second<<","<<uc[6]<<","<<relvol<<","<<uc[0]<<","<<uc[1]<<","<<uc[2]<<","
3233 <<uc[3]*RAD2DEG<<","<<uc[4]*RAD2DEG<<","<<uc[5]*RAD2DEG<<","
3234 <<sys.c_str()<<","<<centc<<","<<pos->first.mNbSpurious<<endl;
3243 void WXPowderPatternGraph::OnIndex(wxCommandEvent& WXUNUSED(event))
3245 wxFrame *mpFrame=new wxFrame(this,-1,_T("Fox cell Explorer (EXPERIMENTAL)"));
3246 WXCellExplorer *mpWXCellExplorer;
3247 mpWXCellExplorer=new WXCellExplorer(mpFrame,mPeakList,this);
3248 mpFrame->Show(TRUE);
3251 void WXPowderPatternGraph::OnChangeScale(wxCommandEvent& event)
3253 VFN_DEBUG_MESSAGE("WXPowderPatternGraph::OnChangeScale()",10)
3254 if(event.GetId()==ID_POWDERGRAPH_MENU_XSCALE_DATA) mXScale=0;
3255 if(event.GetId()==ID_POWDERGRAPH_MENU_XSCALE_D) mXScale=1;
3256 if(event.GetId()==ID_POWDERGRAPH_MENU_XSCALE_2PID) mXScale=2;
3257 if(event.GetId()==ID_POWDERGRAPH_MENU_YSCALE_LINEAR)mYScale=0;
3258 if(event.GetId()==ID_POWDERGRAPH_MENU_YSCALE_SQRT) mYScale=1;
3259 if(event.GetId()==ID_POWDERGRAPH_MENU_YSCALE_LOG10) mYScale=2;
3261 mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_XSCALE_DATA, TRUE);
3262 mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_XSCALE_D, TRUE);
3263 mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_XSCALE_2PID, TRUE);
3264 mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_YSCALE_LINEAR, TRUE);
3265 mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_YSCALE_SQRT, TRUE);
3266 mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_YSCALE_LOG10, TRUE);
3268 if(mXScale==0) mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_XSCALE_DATA, FALSE);
3269 if(mXScale==1) mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_XSCALE_D, FALSE);
3270 if(mXScale==2) mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_XSCALE_2PID, FALSE);
3271 if(mYScale==0)mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_YSCALE_LINEAR, FALSE);
3272 if(mYScale==1) mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_YSCALE_SQRT, FALSE);
3273 if(mYScale==2) mpPopUpMenu->Enable(ID_POWDERGRAPH_MENU_YSCALE_LOG10, FALSE);
3275 this->Refresh(false);
3278 void WXPowderPatternGraph::OnLeBail(wxCommandEvent& event)
3280 wxFrame *pFrame=new wxFrame(this,-1,_T("Profile Fitting"));
3281 WXProfileFitting *pFit;
3282 pFit=new WXProfileFitting(pFrame,&(this->GetWXPowderPattern().GetPowderPattern()));
3286 void WXPowderPatternGraph::OnKeyDown(wxKeyEvent& event)
3288 wxMutexLocker mlock(mMutex);
3289 const long nbPoint=mX.numElements();
3291 switch(event.GetKeyCode())
3295 const REAL range=mMaxX-mMinX;
3297 if(mX(nbPoint-1)>mX(0))
3299 if(mMinX<mX(0)) mMinX=mX(0);
3303 if(mMinX<mX(nbPoint-1)) mMinX=mX(nbPoint-1);
3310 const REAL range=mMaxX-mMinX;
3312 if(mX(nbPoint-1)>mX(0))
3314 if(mMaxX>=mX(nbPoint-1)) mMaxX=mX(nbPoint-1);
3318 if(mMaxX>=mX(0)) mMaxX=mX(0);
3325 REAL max=mObs.max(),min=mObs.min();
3326 if(min<1e-6*max)min=1e-6*max;
3329 const REAL range=log10(max)-log10(min);
3330 mMinIntensity*=pow(10,range/8);
3331 mMaxIntensity*=pow(10,range/8);
3334 const REAL range=mMaxIntensity-mMinIntensity;
3335 mMinIntensity+=range/8;
3336 mMaxIntensity+=range/8;
3341 REAL max=mObs.max(),min=mObs.min();
3342 if(min<1e-6*max)min=1e-6*max;
3345 const REAL range=log10(max)-log10(min);
3346 mMinIntensity*=pow(10,-range/8);
3347 mMaxIntensity*=pow(10,-range/8);
3350 const REAL range=mMaxIntensity-mMinIntensity;
3351 mMinIntensity-=range/8;
3352 if(mMinIntensity<1e-6*max) mMinIntensity=1e-6*max;
3353 mMaxIntensity=mMinIntensity+range;
3356 case(43):// WXK_ADD ?
3358 if(abs(mMaxX-mMinX)>1)
3360 const REAL halfrange=(mMaxX-mMinX)/2;
3361 const REAL middle=(mMaxX+mMinX)/2;
3362 mMinX= (long)(middle-halfrange*4./5.);
3363 mMaxX = (long)(middle+halfrange*4./5.);
3367 case(45):// WXK_SUBTRACT ?
3369 const REAL halfrange=(mMaxX-mMinX)/2;
3370 const REAL middle=(mMaxX+mMinX)/2;
3371 mMinX= (long)(middle-halfrange*5./4.);
3372 mMaxX = (long)(middle+halfrange*5./4.);
3373 if(mX(nbPoint-1)>mX(0))
3375 if(mMinX<mX(0)) mMinX=mX(0);
3376 if(mMaxX>mX(nbPoint-1)) mMaxX=mX(nbPoint-1);
3380 if(mMinX<mX(nbPoint-1)) mMinX=mX(nbPoint-1);
3381 if(mMaxX>mX(0)) mMaxX=mX(0);
3385 case(42):// WXK_MULTIPLY
3387 const REAL range=mMaxIntensity-mMinIntensity;
3388 mMaxIntensity=mMinIntensity+range*4./5.;
3391 case(47):// WXK_DIVIDE
3393 const REAL range=mMaxIntensity-mMinIntensity;
3394 mMaxIntensity=mMinIntensity+range*5./4.;
3399 VFN_DEBUG_MESSAGE("WXPowderPatternGraph::OnKeyDown(): no command for key #"<<event.GetKeyCode(),5);
3400 cout<<"WXPowderPatternGraph::OnKeyDown(): no command for key #"<<event.GetKeyCode()<<endl;
3403 mClockAxisLimits.Click();
3404 wxUpdateUIEvent ev(ID_POWDER_GRAPH_NEW_PATTERN);
3405 wxPostEvent(this,ev);
3409 void WXPowderPatternGraph::OnSize(wxSizeEvent& event)
3411 this->Refresh(false);
3414 WXPowderPattern& WXPowderPatternGraph::GetWXPowderPattern(){return *mpPattern;}
3415 const WXPowderPattern& WXPowderPatternGraph::GetWXPowderPattern()const{return *mpPattern;}
3417 void WXPowderPatternGraph::SetPattern(const CrystVector_REAL &x,
3418 const CrystVector_REAL &obs,
3419 const CrystVector_REAL &calc,
3420 const CrystVector_REAL &sigma,
3421 const CrystVector_REAL &chi2Cumul)
3423 VFN_DEBUG_ENTRY("WXPowderPatternGraph::SetPattern(x,obs,calc,sigma)",4)
3426 if(mpPattern->GetPowderPattern().GetRadiation().GetWavelengthType()!=WAVELENGTH_TOF) mX*=RAD2DEG;
3428 //mCalc=SavitzkyGolay(obs,4,2);
3429 //mCalc *= -obs.max()/mCalc.max();
3432 mChi2Cumul=chi2Cumul;
3433 // Reset the zoom parameters, only for the first display or if the limits of the
3434 // full pattern have changed
3436 ||(mpPattern->GetPowderPattern().GetClockPowderPatternPar()>mClockAxisLimits))
3439 this->ResetAxisLimits();
3443 mvLabelList.clear();
3444 for(unsigned int i=0;i<mpPattern->GetPowderPattern().GetNbPowderPatternComponent();++i)
3445 mvLabelList.push_back(mpPattern->GetPowderPattern()
3446 .GetPowderPatternComponent(i).GetPatternLabelList());
3449 // If we only send an OnPaint event, only the parts which have been erased are redrawn
3450 // (under windows). SO we must force the complete Refresh of the window... in the
3451 // main thread of course...
3452 if(true==wxThread::IsMain())
3454 this->Refresh(false);
3458 wxUpdateUIEvent event(ID_POWDER_GRAPH_NEW_PATTERN);
3459 wxPostEvent(this,event);
3461 //cout<<FormatVertVector<REAL>(x,obs,calc,sigma)<<endl;
3462 VFN_DEBUG_EXIT("WXPowderPatternGraph::SetPattern(x,obs,calc,sigma)"<<mX.numElements()<<","<<mCalc.numElements()<<","<<mObs.numElements()<<","<<mSigma.numElements()<<",",4)
3465 void WXPowderPatternGraph::OnRedrawNewPattern(wxUpdateUIEvent& WXUNUSED(event))
3467 VFN_DEBUG_MESSAGE("WXPowderPatternGraph::SetPattern()",5)
3468 this->Refresh(false);
3471 void WXPowderPatternGraph::ResetAxisLimits()
3473 wxMutexLocker mlock(mMutex);
3474 mMaxIntensity=mObs.max();
3475 mMinIntensity=mObs.min();
3476 const float max=mObs.max();
3477 const float min=mObs.min();
3478 if(max>mMaxIntensity) mMaxIntensity=max;
3479 if(min<mMinIntensity) mMinIntensity=min;
3480 if(mMinIntensity<=0) mMinIntensity=max/1e6;
3481 mMaxIntensity=mMaxIntensity+(mMaxIntensity-mMinIntensity)*0.1;
3484 mDefaultIntensityScale=true;
3485 mClockAxisLimits.Click();
3486 VFN_DEBUG_MESSAGE("WXPowderPatternGraph::ResetAxisLimits():"<<mMinIntensity<<","<<mMaxIntensity<<","<<mMinX<<","<<mMaxX,10)
3488 long WXPowderPatternGraph::Data2ScreenX(const REAL x)const
3490 wxCoord width,height;
3491 this->GetSize(&width, &height);
3492 REAL xs=x,minx=mMinX,maxx=mMaxX;
3496 if(mpPattern->GetPowderPattern().GetRadiation().GetWavelengthType()!=WAVELENGTH_TOF)
3498 d=2*mpPattern->GetPowderPattern().X2STOL(xs*DEG2RAD);
3499 mind=2*mpPattern->GetPowderPattern().X2STOL(minx*DEG2RAD);
3500 maxd=2*mpPattern->GetPowderPattern().X2STOL(maxx*DEG2RAD);
3504 d=2*mpPattern->GetPowderPattern().X2STOL(xs);
3505 mind=2*mpPattern->GetPowderPattern().X2STOL(minx);
3506 maxd=2*mpPattern->GetPowderPattern().X2STOL(maxx);
3508 if(mXScale==1) {xs=d;minx=mind;maxx=maxd;}
3509 if(mXScale==2) {xs=2*M_PI*d;minx=2*M_PI*mind;maxx=2*M_PI*maxd;}
3510 return (long)(mMargin*3+(xs-minx)*(width-3*mMargin)/(maxx-minx));
3512 long WXPowderPatternGraph::Point2ScreenX(const long x)const
3514 return this->Data2ScreenX(mX(x));
3516 long WXPowderPatternGraph::Data2ScreenY(const REAL y)const
3518 wxCoord width,height;
3519 this->GetSize(&width, &height);
3520 REAL ys=y,miny=mMinIntensity,maxy=mMaxIntensity;
3523 if(mYScale==1) {ys=sqrt(ys) ;miny=sqrt(miny) ;maxy=sqrt(maxy);}
3524 if(mYScale==2) {ys=log10(ys);miny=log10(miny);maxy=log10(maxy);}
3525 return (long)(height-mMargin-(ys-miny)*(height-2*mMargin)/(maxy-miny));
3527 REAL WXPowderPatternGraph::Screen2DataX(const long x)const
3529 wxCoord width,height;
3530 this->GetSize(&width, &height);
3531 REAL minx=mMinX,maxx=mMaxX;
3533 if(mpPattern->GetPowderPattern().GetRadiation().GetWavelengthType()!=WAVELENGTH_TOF)
3535 mind=2*mpPattern->GetPowderPattern().X2STOL(minx*DEG2RAD);
3536 maxd=2*mpPattern->GetPowderPattern().X2STOL(maxx*DEG2RAD);
3540 mind=2*mpPattern->GetPowderPattern().X2STOL(minx);
3541 maxd=2*mpPattern->GetPowderPattern().X2STOL(maxx);
3547 REAL stol=(minx+(x-mMargin*3)*(maxx-minx)/(REAL)(width-3*mMargin))/2;
3548 if(mpPattern->GetPowderPattern().GetRadiation().GetWavelengthType()!=WAVELENGTH_TOF)
3549 return mpPattern->GetPowderPattern().STOL2X(stol)*RAD2DEG;
3551 return mpPattern->GetPowderPattern().STOL2X(stol);
3557 REAL stol=(minx+(x-mMargin*3)*(maxx-minx)/(REAL)(width-3*mMargin))/(4*M_PI);
3558 if(mpPattern->GetPowderPattern().GetRadiation().GetWavelengthType()!=WAVELENGTH_TOF)
3559 return mpPattern->GetPowderPattern().STOL2X(stol)*RAD2DEG;
3561 return mpPattern->GetPowderPattern().STOL2X(stol);
3563 return mMinX+(x-mMargin*3)*(mMaxX-mMinX)/(REAL)(width-3*mMargin);
3565 REAL WXPowderPatternGraph::Screen2DataY(const long y)const
3567 wxCoord width,height;
3568 this->GetSize(&width, &height);
3569 REAL miny=mMinIntensity,maxy=mMaxIntensity;
3570 if(mYScale==1) {miny=sqrt(miny) ;maxy=sqrt(maxy);}
3571 if(mYScale==2) {miny=log10(miny);maxy=log10(maxy);}
3572 REAL ys=miny+(height-mMargin-y)*(maxy-miny)/(REAL)(height-2*mMargin);
3573 if(mYScale==1) ys=ys*ys;
3574 if(mYScale==2) ys=pow((float)10,(float)ys);
3580 // WXPowderPatternBackgound
3583 static const long ID_POWDERBACKGROUND_GRID= WXCRYST_ID();
3584 static const long ID_POWDERBACKGROUND_NEWBAYESIAN= WXCRYST_ID();
3586 BEGIN_EVENT_TABLE(WXPowderPatternBackground, wxWindow)
3587 EVT_MENU(ID_POWDERBACKGROUND_IMPORT,
3588 WXPowderPatternBackground::OnMenuImportUserBackground)
3589 EVT_MENU(ID_POWDERBACKGROUND_OPTIMIZEBAYESIAN,
3590 WXPowderPatternBackground::OnMenuOptimizeBayesianBackground)
3591 EVT_GRID_CMD_CELL_CHANGED(ID_POWDERBACKGROUND_GRID,
3592 WXPowderPatternBackground::OnEditGridBackgroundPoint)
3593 EVT_MENU(ID_POWDERBACKGROUND_NEWBAYESIAN,
3594 WXPowderPatternBackground::OnMenuAutomaticBayesianBackground)
3597 WXPowderPatternBackground::WXPowderPatternBackground(wxWindow *parent,
3598 PowderPatternBackground *b):
3599 WXRefinableObj(parent,b),mpPowderPatternBackground(b),mNeedUpdateUI(false),mIsSelfUpdating(false)
3601 mpWXTitle->SetForegroundColour(wxColour(0,255,0));
3603 mpMenuBar->AddMenu("Object",ID_REFOBJ_MENU_OBJ);
3604 mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_OBJ,ID_POWDERBACKGROUND_IMPORT,"Import");
3605 mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_OBJ,ID_POWDERBACKGROUND_OPTIMIZEBAYESIAN,
3606 "Bayesian Optimization");
3607 mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_OBJ,ID_POWDERBACKGROUND_NEWBAYESIAN,
3608 "New Automatic Background (Change Number of Points)");
3609 VFN_DEBUG_MESSAGE(mpMenuBar->GetSize().GetWidth()<<","<<mpMenuBar->GetSize().GetHeight(),10);
3610 //mpSizer->SetItemMinSize(mpMenuBar,
3611 // mpMenuBar->GetSize().GetWidth(),
3612 // mpMenuBar->GetSize().GetHeight());
3614 #ifdef USE_BACKGROUND_MAXLIKE_ERROR
3615 WXCrystObjBasic* pFieldModelSigma=mpPowderPatternBackground
3616 ->GetPar("ML Model Error").wxCreate(this);
3617 mpSizer->Add(pFieldModelSigma,0,wxALIGN_LEFT);
3618 mList.Add(pFieldModelSigma);
3620 // List of background points
3621 wxGridCellAttr* cellAttrFloat = new wxGridCellAttr;
3622 cellAttrFloat->SetRenderer(new wxGridCellFloatRenderer(10,3));
3623 cellAttrFloat->SetEditor(new wxGridCellFloatEditor(10,3));
3625 mpGridBackgroundPoint= new wxGrid(this,ID_POWDERBACKGROUND_GRID);
3626 mpGridBackgroundPoint->SetSize(400,300);
3627 mpGridBackgroundPoint->EnableScrolling(true,true);
3628 mpGridBackgroundPoint->SetSizeHints(-1,300,-1,300);
3629 mpGridBackgroundPoint->SetDefaultColSize(150);
3630 mpGridBackgroundPoint->CreateGrid(0,2);
3631 mpGridBackgroundPoint->SetColAttr(0,cellAttrFloat);
3632 mpGridBackgroundPoint->SetColAttr(1,cellAttrFloat->Clone());
3633 mpGridBackgroundPoint->SetColLabelValue(0,_T("Position"));
3634 mpGridBackgroundPoint->SetColLabelValue(1,_T("Intensity"));
3635 mpGridBackgroundPoint->AutoSizeRows();
3636 mpSizer->Add(mpGridBackgroundPoint,0,wxALIGN_LEFT);
3637 mpTopSizer->SetSizeHints(this);
3639 this->CrystUpdate(true);
3641 void WXPowderPatternBackground::OnMenuImportUserBackground(wxCommandEvent & WXUNUSED(event))
3643 VFN_DEBUG_MESSAGE("WXPowderPatternBackground::OnMenuImportUserBackground()",6)
3644 WXCrystValidateAllUserInput();
3645 wxFileDialog *open= new wxFileDialog(this,_T("Choose background file with 2Theta Ibackgd"),
3646 _T(""),_T(""),_T("*.*"),wxFD_OPEN | wxFD_FILE_MUST_EXIST);
3647 if(open->ShowModal() != wxID_OK) return;
3648 mpPowderPatternBackground->ImportUserBackground(string(open->GetPath().ToAscii()));
3651 void WXPowderPatternBackground::OnMenuOptimizeBayesianBackground(wxCommandEvent & WXUNUSED(event))
3653 VFN_DEBUG_ENTRY("WXPowderPatternBackground::OnMenuOptimizeBayesianBackground()",6)
3654 WXCrystValidateAllUserInput();
3655 mpPowderPatternBackground->UnFixAllPar();
3656 mpPowderPatternBackground->OptimizeBayesianBackground();
3657 mpPowderPatternBackground->FixAllPar();
3658 this->CrystUpdate();
3659 VFN_DEBUG_EXIT("WXPowderPatternBackground::OnMenuOptimizeBayesianBackground()",6)
3661 void WXPowderPatternBackground::OnMenuAutomaticBayesianBackground(wxCommandEvent & WXUNUSED(event))
3663 VFN_DEBUG_ENTRY("WXPowderPatternBackground::OnMenuAutomaticBayesianBackground()",6)
3664 WXCrystValidateAllUserInput();
3666 long nbPointSpline=20;
3667 wxString mes(_T("Number of Interpolation Points"));
3669 s.Printf(_T("%ld"),nbPointSpline);
3670 wxTextEntryDialog dialog(this,mes,_T("Automatic Bayesian (David-Sivia) Background"),
3672 dialog.SetTextValidator(wxTextValidator(wxFILTER_DIGITS));
3673 if(wxID_OK!=dialog.ShowModal())
3675 VFN_DEBUG_EXIT("WXPowderPatternBackground::OnMenuAutomaticBayesianBackground():Canceled",6)
3678 dialog.GetValue().ToLong(&nbPointSpline);
3679 wxProgressDialog dlgProgress(_T("Automatic Bayesian Background"),_T("Automatic Background, Initializing..."),
3680 4,this,wxPD_AUTO_HIDE|wxPD_ELAPSED_TIME|wxPD_CAN_ABORT|wxPD_APP_MODAL);
3681 if(nbPointSpline<2) nbPointSpline=2;
3683 CrystVector_REAL x(nbPointSpline),backgd(nbPointSpline);
3684 const CrystVector_REAL *pObs=&(mpPowderPatternBackground->GetParentPowderPattern().GetPowderPatternObs());
3685 const unsigned long nbPoint=mpPowderPatternBackground->GetParentPowderPattern().GetNbPoint();
3686 const float xmin=mpPowderPatternBackground->GetParentPowderPattern()
3687 .GetPowderPatternX()(0),
3688 xmax=mpPowderPatternBackground->GetParentPowderPattern()
3689 .GetPowderPatternX()(nbPoint-1);
3690 for(int i=0;i<nbPointSpline;i++)
3691 {// xmax is not necessarily > xmin, but in the right order (TOF)
3692 x(i)=xmin+(xmax-xmin)/(REAL)(nbPointSpline-1)*REAL(i);
3693 REAL x1=xmin+(xmax-xmin)/(REAL)(nbPointSpline-1)*REAL(i-.2);
3694 REAL x2=xmin+(xmax-xmin)/(REAL)(nbPointSpline-1)*REAL(i+.2);
3695 long n1=(long)(mpPowderPatternBackground->GetParentPowderPattern().X2Pixel(x1));
3696 long n2=(long)(mpPowderPatternBackground->GetParentPowderPattern().X2Pixel(x2));
3698 if(n2>(long)nbPoint)n2=nbPoint;
3699 backgd(i)=(*pObs)(n1);
3700 for(long j=n1;j<n2;j++)
3701 if((*pObs)(j)<backgd(i))backgd(i)=(*pObs)(j);
3703 mpPowderPatternBackground->SetInterpPoints(x,backgd);
3705 //mpPowderPatternBackground->GetParentPowderPattern().Prepare();
3706 mpPowderPatternBackground->UnFixAllPar();
3707 mpPowderPatternBackground->GetOption(0).SetChoice(0);//linear
3708 if(dlgProgress.Update(1,_T("Automatic Background: Optimizing Linear Model..."))==false) return;
3709 mpPowderPatternBackground->OptimizeBayesianBackground();
3710 mpPowderPatternBackground->GetOption(0).SetChoice(1);//spline
3711 if(dlgProgress.Update(2,_T("Automatic Background: Optimizing Spline Model..."))==false) return;
3712 mpPowderPatternBackground->OptimizeBayesianBackground();
3713 mpPowderPatternBackground->FixAllPar();
3715 this->CrystUpdate();
3716 VFN_DEBUG_EXIT("WXPowderPatternBackground::OnMenuAutomaticBayesianBackground()",6)
3718 void WXPowderPatternBackground::OnEditGridBackgroundPoint(wxGridEvent &e)
3720 if(mIsSelfUpdating) return;
3721 WXCrystValidateAllUserInput();
3722 VFN_DEBUG_ENTRY("WXPowderPatternBackground::OnEditGridBackgroundPoint():"<<e.GetRow()<<","<<e.GetCol(),10)
3723 const long r=e.GetRow();
3724 const long c=e.GetCol();
3725 wxString s=mpGridBackgroundPoint->GetCellValue(r,c);
3729 if(mpPowderPatternBackground->GetParentPowderPattern().GetRadiation().GetWavelengthType()!=WAVELENGTH_TOF)f=DEG2RAD;
3734 if(d!=mBackgroundInterpPointX(r))
3735 mBackgroundInterpPointX(r)=d*f;
3739 if(d!=mBackgroundInterpPointX(r))
3740 mBackgroundInterpPointIntensity(r)=d;
3743 mpPowderPatternBackground->SetInterpPoints(mBackgroundInterpPointX,
3744 mBackgroundInterpPointIntensity);
3745 // The order of the points might have changed
3746 mBackgroundInterpPointX =*(mpPowderPatternBackground->GetInterpPoints().first);
3747 mBackgroundInterpPointIntensity=*(mpPowderPatternBackground->GetInterpPoints().second);
3751 mpPowderPatternBackground->GetParentPowderPattern().UpdateDisplay();
3752 VFN_DEBUG_EXIT("WXPowderPatternBackground::OnEditGridBackgroundPoint():"<<e.GetRow()<<","<<e.GetCol(),10)
3755 void WXPowderPatternBackground::CrystUpdate(const bool uui,const bool lock)
3757 if(lock) mMutex.Lock();
3758 this->WXRefinableObj::CrystUpdate(uui,false);
3759 if(false==mpPowderPatternBackground->IsBeingRefined())
3761 const long diff=mpPowderPatternBackground->GetInterpPoints().first->numElements()
3762 -mpGridBackgroundPoint->GetNumberRows();
3766 mpGridBackgroundPoint->AppendRows(diff);
3771 mpGridBackgroundPoint->DeleteRows(0,-diff);
3774 if( (MaxDifference(mBackgroundInterpPointX ,
3775 *(mpPowderPatternBackground->GetInterpPoints().first )))
3776 ||(MaxDifference(mBackgroundInterpPointIntensity,
3777 *(mpPowderPatternBackground->GetInterpPoints().second))))
3781 mBackgroundInterpPointX =*(mpPowderPatternBackground->GetInterpPoints().first);
3782 mBackgroundInterpPointIntensity=*(mpPowderPatternBackground->GetInterpPoints().second);
3785 if(lock) mMutex.Unlock();
3788 void WXPowderPatternBackground::UpdateUI(const bool lock)
3790 if(lock) mMutex.Lock();
3794 if(mpPowderPatternBackground->GetParentPowderPattern().GetRadiation().GetWavelengthType()!=WAVELENGTH_TOF)f=RAD2DEG;
3795 const long nb=mBackgroundInterpPointX.numElements();
3796 mIsSelfUpdating=true;
3797 for(long i=0;i<nb;++i)
3800 tmp.Printf(_T("%f"),f*mBackgroundInterpPointX(i));
3801 mpGridBackgroundPoint->SetCellValue(i,0,tmp);
3802 tmp.Printf(_T("%f"),mBackgroundInterpPointIntensity(i));
3803 mpGridBackgroundPoint->SetCellValue(i,1,tmp);
3805 mIsSelfUpdating=false;
3808 mNeedUpdateUI=false;
3809 this->WXRefinableObj::UpdateUI(false);
3810 if(lock) mMutex.Unlock();
3813 bool WXPowderPatternBackground::Enable(bool e)
3815 if(0!=mpGridBackgroundPoint) mpGridBackgroundPoint->Enable(e);
3816 return this->::wxWindow::Enable(e);
3821 // WXTexturePhaseMarchDollase
3824 WXTexturePhaseMarchDollase::WXTexturePhaseMarchDollase(wxWindow *parent,
3825 TexturePhaseMarchDollase *pObj,
3826 TextureMarchDollase* pTex):
3827 WXCrystObjBasic(parent),mpTexturePhaseMarchDollase(pObj)
3829 VFN_DEBUG_ENTRY("WXTexturePhaseMarchDollase::WXTexturePhaseMarchDollase()",5)
3830 mpSizer=new wxBoxSizer(wxHORIZONTAL);
3831 this->SetSizer(mpSizer);
3833 WXCrystObjBasic* pFieldFraction=pTex->GetPar(&(pObj->mFraction)).WXCreate(this);
3834 mpSizer->Add(pFieldFraction,0,wxALIGN_LEFT);
3835 mList.Add(pFieldFraction);
3837 WXCrystObjBasic* pFieldMarch=pTex->GetPar(&(pObj->mMarchCoeff)).WXCreate(this);
3838 mpSizer->Add(pFieldMarch,0,wxALIGN_LEFT);
3839 mList.Add(pFieldMarch);
3841 WXCrystObjBasic* pFieldH=pTex->GetPar(&(pObj->mH)).WXCreate(this);
3842 mpSizer->Add(pFieldH,0,wxALIGN_LEFT);
3845 WXCrystObjBasic* pFieldK=pTex->GetPar(&(pObj->mK)).WXCreate(this);
3846 mpSizer->Add(pFieldK,0,wxALIGN_LEFT);
3849 WXCrystObjBasic* pFieldL=pTex->GetPar(&(pObj->mL)).WXCreate(this);
3850 mpSizer->Add(pFieldL,0,wxALIGN_LEFT);
3853 this->CrystUpdate(true);
3854 VFN_DEBUG_EXIT("WXTexturePhaseMarchDollase::WXTexturePhaseMarchDollase()",5)
3857 WXTexturePhaseMarchDollase::~WXTexturePhaseMarchDollase()
3859 mpTexturePhaseMarchDollase->WXNotifyDelete();
3861 void WXTexturePhaseMarchDollase::CrystUpdate(const bool uui,const bool lock)
3863 if(lock) mMutex.Lock();
3864 mList.CrystUpdate(uui,false);
3865 if(lock) mMutex.Unlock();
3867 void WXTexturePhaseMarchDollase::UpdateUI(const bool lock)
3869 if(lock) mMutex.Lock();
3870 mList.UpdateUI(false);
3871 if(lock) mMutex.Unlock();
3876 // WXTextureMarchDollase
3879 BEGIN_EVENT_TABLE(WXTextureMarchDollase, wxWindow)
3880 EVT_MENU(ID_POWDERTEXTURE_MENU_ADDPHASE, WXTextureMarchDollase::OnAddTexturePhase)
3881 EVT_MENU(ID_POWDERTEXTURE_MENU_DELETEPHASE,WXTextureMarchDollase::OnDeleteTexturePhase)
3882 EVT_UPDATE_UI(ID_CRYST_UPDATEUI, WXRefinableObj::OnUpdateUI)
3885 WXTextureMarchDollase::WXTextureMarchDollase(wxWindow *parent, TextureMarchDollase*obj):
3886 WXRefinableObj(parent,(RefinableObj*)obj),mpTextureMarchDollase(obj)
3888 VFN_DEBUG_ENTRY("WXTextureMarchDollase::WXTextureMarchDollase()",5)
3890 mpMenuBar->AddMenu("Phases",ID_REFOBJ_MENU_OBJ);
3891 mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_OBJ,ID_POWDERTEXTURE_MENU_ADDPHASE,
3894 WXRegistry<TexturePhaseMarchDollase> *pWXPhaseRegistry
3895 =mpTextureMarchDollase->mPhaseRegistry.WXCreate(this);
3896 mpSizer->Add(pWXPhaseRegistry,0,wxALIGN_LEFT);
3897 mList.Add(pWXPhaseRegistry);
3898 this->CrystUpdate(true);
3899 this->SetToolTip(_T("Texture for this crystalline phase.\n")
3900 _T("You can describe the preferred orientation using ")
3901 _T("the March-Dollase model (use the menu).\n\n")
3902 _T("Although possible, it is not recommended to enable ")
3903 _T("the global optimization of texture parameters, ")
3904 _T("as it is *extremely* slow"));
3905 VFN_DEBUG_EXIT("WXTextureMarchDollase::WXTextureMarchDollase()",5)
3907 void WXTextureMarchDollase::OnAddTexturePhase(wxCommandEvent & WXUNUSED(event))
3909 VFN_DEBUG_ENTRY("WXTextureMarchDollase::OnAddTexturePhase()",5)
3910 mpTextureMarchDollase->AddPhase(0.,1.,1,0,0);
3911 VFN_DEBUG_EXIT("WXTextureMarchDollase::OnAddTexturePhase()",5)
3913 void WXTextureMarchDollase::OnDeleteTexturePhase(wxCommandEvent & WXUNUSED(event))
3919 // WXTextureEllipsoid
3922 WXTextureEllipsoid::WXTextureEllipsoid(wxWindow *parent, TextureEllipsoid *pObj):
3923 WXCrystObj(parent),mpTextureEllipsoid(pObj)
3925 VFN_DEBUG_ENTRY("WXTextureEllipsoid::WXTextureEllipsoid()",6)
3926 mpWXTitle->SetLabel("Texture ellipsoid");
3927 mpWXTitle->SetForegroundColour(wxColour(0,0,255));
3929 wxBoxSizer* sizer1=new wxBoxSizer(wxHORIZONTAL);
3930 WXCrystObjBasic* pFieldEPR1=mpTextureEllipsoid->GetPar((long)0).WXCreate(this);
3931 WXCrystObjBasic* pFieldEPR2=mpTextureEllipsoid->GetPar(1).WXCreate(this);
3932 WXCrystObjBasic* pFieldEPR3=mpTextureEllipsoid->GetPar(2).WXCreate(this);
3933 sizer1->Add(pFieldEPR1,0);
3934 sizer1->Add(pFieldEPR2,0);
3935 sizer1->Add(pFieldEPR3,0);
3936 mList.Add(pFieldEPR1);
3937 mList.Add(pFieldEPR2);
3938 mList.Add(pFieldEPR3);
3939 mpSizer->Add(sizer1);
3940 pFieldEPR1->SetToolTip(_T("Texture Ellipsoidal function parameters:\n")
3941 _T("Icorr = Iobs[ 1 + (EPR1*h^2 + EPR2*k^2 + EPR3*l^2 + EPR4*2hk + EPR5*2hl + EPR6*2kl) * 0.001d^2 ]^-1.5"));
3942 pFieldEPR2->SetToolTip(_T("Texture Ellipsoidal function parameters:\n")
3943 _T("Icorr = Iobs[ 1 + (EPR1*h^2 + EPR2*k^2 + EPR3*l^2 + EPR4*2hk + EPR5*2hl + EPR6*2kl) * 0.001d^2 ]^-1.5"));
3944 pFieldEPR3->SetToolTip(_T("Texture Ellipsoidal function parameters:\n")
3945 _T("Icorr = Iobs[ 1 + (EPR1*h^2 + EPR2*k^2 + EPR3*l^2 + EPR4*2hk + EPR5*2hl + EPR6*2kl) * 0.001d^2 ]^-1.5"));
3947 wxBoxSizer* sizer2=new wxBoxSizer(wxHORIZONTAL);
3948 WXCrystObjBasic* pFieldEPR4=mpTextureEllipsoid->GetPar(3).WXCreate(this);
3949 WXCrystObjBasic* pFieldEPR5=mpTextureEllipsoid->GetPar(4).WXCreate(this);
3950 WXCrystObjBasic* pFieldEPR6=mpTextureEllipsoid->GetPar(5).WXCreate(this);
3951 sizer2->Add(pFieldEPR4,0);
3952 sizer2->Add(pFieldEPR5,0);
3953 sizer2->Add(pFieldEPR6,0);
3954 mList.Add(pFieldEPR4);
3955 mList.Add(pFieldEPR5);
3956 mList.Add(pFieldEPR6);
3957 mpSizer->Add(sizer2);
3958 pFieldEPR4->SetToolTip(_T("Texture Ellipsoidal function parameters:\n")
3959 _T("Icorr = Iobs[ 1 + (EPR1*h^2 + EPR2*k^2 + EPR3*l^2 + EPR4*2hk + EPR5*2hl + EPR6*2kl) * 0.001d^2 ]^-1.5"));
3960 pFieldEPR5->SetToolTip(_T("Texture Ellipsoidal function parameters:\n")
3961 _T("Icorr = Iobs[ 1 + (EPR1*h^2 + EPR2*k^2 + EPR3*l^2 + EPR4*2hk + EPR5*2hl + EPR6*2kl) * 0.001d^2 ]^-1.5"));
3962 pFieldEPR6->SetToolTip(_T("Texture Ellipsoidal function parameters:\n")
3963 _T("Icorr = Iobs[ 1 + (EPR1*h^2 + EPR2*k^2 + EPR3*l^2 + EPR4*2hk + EPR5*2hl + EPR6*2kl) * 0.001d^2 ]^-1.5"));
3965 this->CrystUpdate(true);
3966 VFN_DEBUG_EXIT("WXTextureEllipsoid::WXTextureEllipsoid()",6)
3968 WXTextureEllipsoid::~WXTextureEllipsoid()
3970 mpTextureEllipsoid->WXNotifyDelete();
3972 bool WXTextureEllipsoid::OnChangeName(const int id)
3980 // WXPowderPatternDiffraction
3983 static const long ID_POWDERDIFF_PROFILE= WXCRYST_ID();
3984 static const long ID_POWDERDIFF_PROFILE_PV= WXCRYST_ID();
3985 static const long ID_POWDERDIFF_PROFILE_PV_ANISO= WXCRYST_ID();
3986 static const long ID_POWDERDIFF_LEBAIL= WXCRYST_ID();
3987 static const long ID_POWDERDIFF_PROFILEFITTINGMODE= WXCRYST_ID();
3988 static const long ID_POWDERDIFF_USELOCALLATTICEPAR= WXCRYST_ID();
3990 BEGIN_EVENT_TABLE(WXPowderPatternDiffraction, wxWindow)
3991 EVT_BUTTON(ID_POWDERDIFF_CRYSTAL,WXPowderPatternDiffraction::OnChangeCrystal)
3992 EVT_MENU(ID_POWDERDIFF_SAVEHKLFCALC,
3993 WXPowderPatternDiffraction::OnMenuSaveHKLFcalc)
3994 EVT_MENU(ID_POWDERDIFF_PROFILE_PV, WXPowderPatternDiffraction::OnChangeProfile)
3995 EVT_MENU(ID_POWDERDIFF_PROFILE_PV_ANISO, WXPowderPatternDiffraction::OnChangeProfile)
3996 EVT_MENU(ID_POWDERDIFF_PROFILE_DEPV, WXPowderPatternDiffraction::OnChangeProfile)
3997 EVT_MENU(ID_POWDERDIFF_LEBAIL, WXPowderPatternDiffraction::OnLeBail)
3998 EVT_CHECKBOX(ID_POWDERDIFF_PROFILEFITTINGMODE,WXPowderPatternDiffraction::OnLeBail)
3999 EVT_CHECKBOX(ID_POWDERDIFF_USELOCALLATTICEPAR,WXPowderPatternDiffraction::OnFreezeLatticePar)
4000 EVT_UPDATE_UI(ID_CRYST_UPDATEUI, WXRefinableObj::OnUpdateUI)
4003 WXPowderPatternDiffraction::WXPowderPatternDiffraction(wxWindow *parent,
4004 PowderPatternDiffraction *p):
4005 WXRefinableObj(parent,p),mpPowderPatternDiffraction(p),
4006 mFreezeLatticePar(false),mFrozenLatticePar(6),mNeedLayout(false)
4008 VFN_DEBUG_ENTRY("WXPowderPatternDiffraction::WXPowderPatternDiffraction()",6)
4009 mpWXTitle->SetForegroundColour(wxColour(0,255,0));
4011 mpMenuBar->AddMenu("File",ID_REFOBJ_MENU_OBJ);
4012 mpMenuBar->AddMenuItem(ID_REFOBJ_MENU_OBJ,ID_POWDERDIFF_SAVEHKLFCALC,
4014 mpMenuBar->AddMenu("Profile",ID_POWDERDIFF_PROFILE);
4015 mpMenuBar->AddMenuItem(ID_POWDERDIFF_PROFILE,ID_POWDERDIFF_PROFILE_PV,
4016 "Pseudo-Voigt (X-Ray & monochromatic neutron)");
4017 mpMenuBar->AddMenuItem(ID_POWDERDIFF_PROFILE,ID_POWDERDIFF_PROFILE_PV_ANISO,
4018 "Anisotropic Pseudo-Voigt (X-Ray & monochromatic neutron)");
4019 mpMenuBar->AddMenuItem(ID_POWDERDIFF_PROFILE,ID_POWDERDIFF_PROFILE_DEPV,
4020 "Double-Exponential Pseudo-Voigt (neutron TOF)");
4021 mpMenuBar->GetMenu(ID_POWDERDIFF_PROFILE).AppendSeparator();
4022 mpMenuBar->AddMenuItem(ID_POWDERDIFF_PROFILE,ID_POWDERDIFF_LEBAIL,
4023 "Profile Fitting + Le Bail Extraction");
4024 //mpSizer->SetItemMinSize(mpMenuBar,
4025 // mpMenuBar->GetSize().GetWidth(),
4026 // mpMenuBar->GetSize().GetHeight());
4027 // Profile Fitting Mode
4028 mpProfileFittingMode= new wxCheckBox(this,ID_POWDERDIFF_PROFILEFITTINGMODE,
4029 _T("Profile Fitting (Le Bail) Mode"));
4030 mpSizer->Add(mpProfileFittingMode,0,wxALIGN_LEFT);
4032 mpFieldCrystal=new WXFieldChoice(this,ID_POWDERDIFF_CRYSTAL,"Crystal:",300);
4033 mpSizer->Add(mpFieldCrystal,0,wxALIGN_LEFT);
4034 mList.Add(mpFieldCrystal);
4035 mpFieldCrystal->SetToolTip(_T("Crystal structure for this diffraction phase\n")
4036 _T("Click on the button to select another structure"));
4037 // Freeze lattice par ?
4038 wxSizer *pSizerFreezePar=new wxBoxSizer(wxHORIZONTAL);
4039 mpFreezeLatticePar= new wxCheckBox(this,ID_POWDERDIFF_USELOCALLATTICEPAR, _T("Freeze lattice par."));
4040 pSizerFreezePar->Add(mpFreezeLatticePar);
4041 mpGridFrozenLatticePar=new wxGrid(this,-1,wxDefaultPosition,wxDefaultSize);
4042 mpGridFrozenLatticePar->SetColLabelSize(0);
4043 mpGridFrozenLatticePar->SetRowLabelSize(0);
4044 mpGridFrozenLatticePar->DisableDragRowSize();
4045 pSizerFreezePar->Add(mpGridFrozenLatticePar);
4046 mpGridFrozenLatticePar->SetDefaultEditor(new wxGridCellFloatEditor(7,4));
4047 mpGridFrozenLatticePar->SetDefaultRenderer(new wxGridCellFloatRenderer(7,4));
4048 mpGridFrozenLatticePar->EnableScrolling(false,false);
4049 mpGridFrozenLatticePar->ShowScrollbars(wxSHOW_SB_NEVER ,wxSHOW_SB_NEVER );
4050 mpGridFrozenLatticePar->CreateGrid(1,6);
4051 mpGridFrozenLatticePar->SetDefaultColSize(60);
4052 mpGridFrozenLatticePar->EnableEditing(false);
4053 mpSizer->AddSpacer(1);
4054 mpSizer->Add(pSizerFreezePar);
4055 mpSizer->AddSpacer(1);
4057 //Global Biso factor
4058 WXCrystObjBasic* fieldGlobalBiso
4059 =mpPowderPatternDiffraction->GetPar(&(mpPowderPatternDiffraction->mGlobalBiso))
4061 mList.Add(fieldGlobalBiso);
4062 mpSizer->Add(fieldGlobalBiso);
4063 // Texture (March Dollase
4064 WXTextureMarchDollase* pTexMD
4065 =new WXTextureMarchDollase(this,&(mpPowderPatternDiffraction->mCorrTextureMarchDollase));
4067 mpSizer->Add(pTexMD);
4068 // Texture Ellipsoid
4069 WXTextureEllipsoid* pTexEllips
4070 =new WXTextureEllipsoid(this,&(mpPowderPatternDiffraction->mCorrTextureEllipsoid));
4071 mList.Add(pTexEllips);
4072 mpSizer->Add(pTexEllips);
4075 if(mpPowderPatternDiffraction->mpReflectionProfile!=0)
4077 VFN_DEBUG_ENTRY("WXPowderPatternDiffraction::WXPowderPatternDiffraction()",6)
4078 WXCrystObjBasic* pWXProf=mpPowderPatternDiffraction
4079 ->mpReflectionProfile->WXCreate(this);
4080 mpSizer->Add(pWXProf);
4082 VFN_DEBUG_EXIT("WXPowderPatternDiffraction::WXPowderPatternDiffraction()",6)
4085 this->CrystUpdate(true);
4086 VFN_DEBUG_EXIT("WXPowderPatternDiffraction::WXPowderPatternDiffraction()",6)
4089 void WXPowderPatternDiffraction::OnChangeCrystal(wxCommandEvent & WXUNUSED(event))
4091 VFN_DEBUG_MESSAGE("WXPowderPatternDiffraction::OnChangeCrystal()",6)
4092 WXCrystValidateAllUserInput();
4094 Crystal *cryst=dynamic_cast<Crystal*>
4095 ( WXDialogChooseFromRegistry(gCrystalRegistry,(wxWindow*)this,
4096 "Choose a Crystal Structure:",choice));
4097 if(0==cryst) return;
4098 mpPowderPatternDiffraction->SetCrystal(*cryst);
4099 this->CrystUpdate(true);
4101 void WXPowderPatternDiffraction::OnMenuSaveHKLFcalc(wxCommandEvent & WXUNUSED(event))
4103 VFN_DEBUG_MESSAGE("WXPowderPatternDiffraction::OnMenuSaveHKLFcalc()",6)
4104 WXCrystValidateAllUserInput();
4105 wxFileDialog save(this,_T("Choose a file to save to"),_T(""),_T(""),_T("*.txt"),wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
4106 if(save.ShowModal() != wxID_OK) return;
4108 ofstream out(save.GetPath().ToAscii());
4109 if(!out) return;//:TODO:
4110 mpPowderPatternDiffraction->PrintFhklCalc(out);
4114 void WXPowderPatternDiffraction::CrystUpdate(const bool uui,const bool lock)
4116 VFN_DEBUG_MESSAGE("WXPowderPatternDiffraction::CrystUpdate()",10)
4117 if(lock) mMutex.Lock();
4118 for(unsigned int i=0;i<6;i++) mFrozenLatticePar(i)=mpPowderPatternDiffraction->GetFrozenLatticePar(i);
4119 if(mFreezeLatticePar!=mpPowderPatternDiffraction->FreezeLatticePar())
4121 mFreezeLatticePar=mpPowderPatternDiffraction->FreezeLatticePar();
4124 this->WXRefinableObj::CrystUpdate(uui,false);
4125 if(lock) mMutex.Unlock();
4128 void WXPowderPatternDiffraction::UpdateUI(const bool lock)
4130 VFN_DEBUG_MESSAGE("WXPowderPatternDiffraction::UpdateUI()",10)
4131 if(lock) mMutex.Lock();
4132 mpFieldCrystal->SetValue(mpPowderPatternDiffraction->GetCrystal().GetName());
4133 mpProfileFittingMode->SetValue(mpPowderPatternDiffraction->GetExtractionMode());
4134 mpPowderPatternDiffraction->mCorrTextureEllipsoid.UpdateEllipsoidPar();
4135 mpGridFrozenLatticePar->Show(mFreezeLatticePar);
4136 if(mFreezeLatticePar)
4138 for(unsigned int i=0;i<3;++i) mpGridFrozenLatticePar->SetCellValue(0, i, wxString::Format("%.4f",mFrozenLatticePar(i)));
4139 for(unsigned int i=3;i<6;++i) mpGridFrozenLatticePar->SetCellValue(0, i, wxString::Format("%.3f",mFrozenLatticePar(i)*180/M_PI));
4141 mpFreezeLatticePar->SetValue(mFreezeLatticePar);
4144 VFN_DEBUG_MESSAGE("WXPowderPatternDiffraction::UpdateUI():Layout !", 10)
4148 if(lock) mMutex.Unlock();
4149 this->WXRefinableObj::UpdateUI(lock);
4151 bool WXPowderPatternDiffraction::Enable(bool e)
4153 if(0!=mpGridFrozenLatticePar) mpGridFrozenLatticePar->Enable(e);
4154 return this->::wxWindow::Enable(e);
4157 void WXPowderPatternDiffraction::OnChangeProfile(wxCommandEvent & event)
4159 VFN_DEBUG_ENTRY("WXPowderPatternDiffraction::OnChangeProfile()",6)
4160 WXCrystValidateAllUserInput();
4162 if(event.GetId()==ID_POWDERDIFF_PROFILE_PV)
4164 if(mpPowderPatternDiffraction->mpReflectionProfile==0)
4166 ReflectionProfilePseudoVoigt *p= new ReflectionProfilePseudoVoigt;
4167 mpPowderPatternDiffraction->SetProfile(p);
4171 if(mpPowderPatternDiffraction->mpReflectionProfile->GetClassName()
4172 !="ReflectionProfilePseudoVoigt")
4174 ReflectionProfilePseudoVoigt *p= new ReflectionProfilePseudoVoigt;
4175 if(mpPowderPatternDiffraction->mpReflectionProfile->GetClassName()=="ReflectionProfilePseudoVoigtAnisotropic")
4177 p->GetPar("U").SetValue(mpPowderPatternDiffraction->mpReflectionProfile->GetPar("U").GetValue());
4178 p->GetPar("V").SetValue(mpPowderPatternDiffraction->mpReflectionProfile->GetPar("V").GetValue());
4179 p->GetPar("W").SetValue(mpPowderPatternDiffraction->mpReflectionProfile->GetPar("W").GetValue());
4180 p->GetPar("Eta0").SetValue(mpPowderPatternDiffraction->mpReflectionProfile->GetPar("Eta0").GetValue());
4181 p->GetPar("Eta1").SetValue(mpPowderPatternDiffraction->mpReflectionProfile->GetPar("Eta1").GetValue());
4182 p->GetPar("Asym0").SetValue(mpPowderPatternDiffraction->mpReflectionProfile->GetPar("Asym0").GetValue());
4183 p->GetPar("Asym1").SetValue(mpPowderPatternDiffraction->mpReflectionProfile->GetPar("Asym1").GetValue());
4184 p->GetPar("Asym2").SetValue(mpPowderPatternDiffraction->mpReflectionProfile->GetPar("Asym2").GetValue());
4186 mpPowderPatternDiffraction->SetProfile(p);
4190 if(event.GetId()==ID_POWDERDIFF_PROFILE_PV_ANISO)
4192 if(mpPowderPatternDiffraction->mpReflectionProfile==0)
4194 ReflectionProfilePseudoVoigtAnisotropic *p= new ReflectionProfilePseudoVoigtAnisotropic;
4195 mpPowderPatternDiffraction->SetProfile(p);
4199 if(mpPowderPatternDiffraction->mpReflectionProfile->GetClassName()
4200 !="ReflectionProfilePseudoVoigtAnisotropic")
4202 ReflectionProfilePseudoVoigtAnisotropic *p= new ReflectionProfilePseudoVoigtAnisotropic;
4203 if(mpPowderPatternDiffraction->mpReflectionProfile->GetClassName()=="ReflectionProfilePseudoVoigt")
4205 p->GetPar("U").SetValue(mpPowderPatternDiffraction->mpReflectionProfile->GetPar("U").GetValue());
4206 p->GetPar("V").SetValue(mpPowderPatternDiffraction->mpReflectionProfile->GetPar("V").GetValue());
4207 p->GetPar("W").SetValue(mpPowderPatternDiffraction->mpReflectionProfile->GetPar("W").GetValue());
4208 p->GetPar("Eta0").SetValue(mpPowderPatternDiffraction->mpReflectionProfile->GetPar("Eta0").GetValue());
4209 p->GetPar("Eta1").SetValue(mpPowderPatternDiffraction->mpReflectionProfile->GetPar("Eta1").GetValue());
4210 p->GetPar("Asym0").SetValue(mpPowderPatternDiffraction->mpReflectionProfile->GetPar("Asym0").GetValue());
4211 p->GetPar("Asym1").SetValue(mpPowderPatternDiffraction->mpReflectionProfile->GetPar("Asym1").GetValue());
4212 p->GetPar("Asym2").SetValue(mpPowderPatternDiffraction->mpReflectionProfile->GetPar("Asym2").GetValue());
4213 p->GetPar("X").SetValue(sqrt(mpPowderPatternDiffraction->mpReflectionProfile->GetPar("W").GetValue()));
4215 mpPowderPatternDiffraction->SetProfile(p);
4219 if(event.GetId()==ID_POWDERDIFF_PROFILE_DEPV)
4221 if(mpPowderPatternDiffraction->mpReflectionProfile==0)
4223 ReflectionProfileDoubleExponentialPseudoVoigt *p=
4224 new ReflectionProfileDoubleExponentialPseudoVoigt
4225 (mpPowderPatternDiffraction->GetCrystal());
4226 mpPowderPatternDiffraction->SetProfile(p);
4230 if(mpPowderPatternDiffraction->mpReflectionProfile->GetClassName()
4231 !="ReflectionProfileDoubleExponentialPseudoVoigt")
4233 ReflectionProfileDoubleExponentialPseudoVoigt *p=
4234 new ReflectionProfileDoubleExponentialPseudoVoigt
4235 (mpPowderPatternDiffraction->GetCrystal());
4236 mpPowderPatternDiffraction->SetProfile(p);
4242 mpPowderPatternDiffraction->mpReflectionProfile->WXCreate(this);
4243 mList.Add(mpPowderPatternDiffraction->mpReflectionProfile->WXGet());
4244 mpSizer->Add(mpPowderPatternDiffraction->mpReflectionProfile->WXGet());
4245 wxTheApp->GetTopWindow()->Layout();
4246 wxTheApp->GetTopWindow()->SendSizeEvent();
4247 mpPowderPatternDiffraction->GetParentPowderPattern().UpdateDisplay();
4249 VFN_DEBUG_EXIT("WXPowderPatternDiffraction::OnChangeProfile()",6)
4253 static const long ID_PROFILEFITTING_RUN= WXCRYST_ID();
4254 static const long ID_PROFILEFITTING_RUN_MANUAL= WXCRYST_ID();
4255 static const long ID_PROFILEFITTING_EXPLORE_SPG= WXCRYST_ID();
4256 static const long ID_PROFILEFITTING_EXPLORE_SPG_QUICK= WXCRYST_ID();
4258 BEGIN_EVENT_TABLE(WXProfileFitting, wxWindow)
4259 EVT_BUTTON(ID_PROFILEFITTING_RUN, WXProfileFitting::OnFit)
4260 EVT_BUTTON(ID_PROFILEFITTING_RUN_MANUAL, WXProfileFitting::OnFit)
4261 EVT_BUTTON(ID_PROFILEFITTING_EXPLORE_SPG, WXProfileFitting::OnExploreSpacegroups)
4262 EVT_BUTTON(ID_PROFILEFITTING_EXPLORE_SPG_QUICK, WXProfileFitting::OnExploreSpacegroups)
4265 WXProfileFitting::WXProfileFitting(wxWindow *parent,PowderPattern *pPattern,PowderPatternDiffraction *pDiff):
4266 wxWindow(parent,-1),mpPattern(pPattern),mpDiff(pDiff),mLSQ("Profile Fitting object"),mpList(0)
4268 wxBoxSizer *pSizer0=new wxBoxSizer(wxVERTICAL);
4269 this->SetSizer(pSizer0);
4271 wxNotebook *pNotebook = new wxNotebook(this, -1,wxDefaultPosition,wxSize(600,400));
4272 pSizer0->Add(pNotebook,0,wxALIGN_CENTER);
4274 wxWindow *pQuick=new wxWindow(pNotebook,-1);
4275 pNotebook->AddPage(pQuick,_T("Quick Fit"),true);
4276 wxBoxSizer *pSizer=new wxBoxSizer(wxVERTICAL);
4278 wxButton *pButton1=new wxButton(pQuick,ID_PROFILEFITTING_RUN,_T("Le Bail + Fit Profile !"));
4279 pSizer->Add(pButton1,0,wxALIGN_CENTER);
4282 // List crystal phases
4283 wxArrayString choices;
4285 unsigned int nb=mpPattern->GetNbPowderPatternComponent();
4286 for(unsigned int i=0;i<nb;++i)
4287 if(mpPattern->GetPowderPatternComponent(i).GetClassName()==string("PowderPatternDiffraction"))
4289 pDiff=dynamic_cast<PowderPatternDiffraction*>(&(mpPattern->GetPowderPatternComponent(i)));
4292 cout<<"WXProfileFitting::WXProfileFitting():"<<pDiff<<":"<<mpPattern->GetPowderPatternComponent(i).GetName()
4293 <<","<<pDiff->GetCrystal().GetName()<<endl;
4294 choices.Add(wxString::FromAscii(pDiff->GetCrystal().GetName().c_str())
4295 +wxString::Format(_T(", a=%6.3f b=%6.3f c=%6.3f"),
4296 pDiff->GetCrystal().GetLatticePar(0),
4297 pDiff->GetCrystal().GetLatticePar(1),
4298 pDiff->GetCrystal().GetLatticePar(2)));
4299 //cout<<"WXProfileFitting::WXProfileFitting():"<<choices[choices.Count()-1]<<","<<pDiff<<endl;
4303 if(choices.GetCount()==0)
4305 wxMessageBox(_T("To run Le Bail & Profile fitting, you \n")
4306 _T("need at least one crystalline phase !"),
4307 _T("Missing crystalline phase !"),
4308 wxYES_NO|wxICON_ERROR);
4309 this->GetParent()->Destroy();
4312 if(choices.GetCount()==1)
4314 cout<<"WXProfileFitting::WXProfileFitting():"<<choices[0]<<","<<pDiff<<endl;
4319 wxStaticText *pLabel=new wxStaticText(pQuick,-1,_T("Crystalline Phase to Fit:"));
4320 pSizer->Add(pLabel,0,wxALIGN_CENTER);
4322 mpList=new wxListBox(pQuick,-1,wxDefaultPosition,wxSize(-1,80),choices,wxLB_SINGLE);
4323 mpList->SetSelection(0);
4324 pSizer->Add(mpList,0,wxALIGN_CENTER);
4330 wxArrayInt selections;
4331 mpList->GetSelections(selections);
4332 const int choice=selections[0];
4334 unsigned int nb=mpPattern->GetNbPowderPatternComponent();
4335 for(unsigned int i=0;i<nb;++i)
4336 if(mpPattern->GetPowderPatternComponent(i).GetClassName()==string("PowderPatternDiffraction"))
4338 pDiff=dynamic_cast<PowderPatternDiffraction*>(&(mpPattern->GetPowderPatternComponent(i)));
4339 cout<<"WXProfileFitting::WXProfileFitting():"<<pDiff<<":"<<mpPattern->GetPowderPatternComponent(i).GetName()<<endl;
4345 cout<<"Chosen:"<<mpPattern->GetPowderPatternComponent(i).GetName()<<endl;
4348 cout<<"Not chosen:"<<mpPattern->GetPowderPatternComponent(i).GetName()<<endl;
4352 wxArrayString fitChoices;
4353 if(mpDiff->GetProfile().GetClassName()=="ReflectionProfileDoubleExponentialPseudoVoigt")
4355 fitChoices.Add(_T("Fit Zero shift"));
4356 fitChoices.Add(_T("Fit Instrumental Width (alpha1,beta0,beta1)"));
4357 fitChoices.Add(_T("Fit Size/Strain Broadening (sigma1,gamma2)"));
4358 fitChoices.Add(_T("Fit Background"));
4359 fitChoices.Add(_T("Fit Unit Cell"));
4363 fitChoices.Add(_T("Fit Zero shift"));
4364 fitChoices.Add(_T("Fit Constant Width"));
4365 fitChoices.Add(_T("Fit Variable Width"));
4366 fitChoices.Add(_T("Fit Gaussian-Lorentzian Mixing"));
4367 fitChoices.Add(_T("Fit Asymmetric parameters"));
4368 fitChoices.Add(_T("Fit Displacement+Transparency"));
4369 fitChoices.Add(_T("Fit Background"));
4370 fitChoices.Add(_T("Fit Unit Cell"));
4372 mpFitCheckList=new wxCheckListBox(pQuick,-1,wxDefaultPosition,wxDefaultSize,fitChoices);
4373 if(mpDiff->GetProfile().GetClassName()=="ReflectionProfileDoubleExponentialPseudoVoigt")
4375 mpFitCheckList->Check(0,false);
4376 mpFitCheckList->Check(1,false);
4377 mpFitCheckList->Check(2,true);
4378 mpFitCheckList->Check(3,true);
4379 mpFitCheckList->Check(4,true);
4383 mpFitCheckList->Check(0,true);
4384 mpFitCheckList->Check(1,true);
4385 mpFitCheckList->Check(2,true);
4386 mpFitCheckList->Check(3,true);
4387 mpFitCheckList->Check(4,true);
4388 mpFitCheckList->Check(5,true);
4389 mpFitCheckList->Check(6,true);
4390 mpFitCheckList->Check(7,true);
4392 pSizer->Add(mpFitCheckList,1,wxEXPAND);
4394 pQuick->SetSizer(pSizer);
4395 pSizer->SetSizeHints(pQuick);
4399 // prepare LSQ object
4400 mLSQ.SetRefinedObj(pDiff->GetParentPowderPattern(),0,true,true);
4401 mLSQ.PrepareRefParList(true);
4402 //mLSQ.SetParIsUsed(gpRefParTypeObjCryst,false);
4403 //mLSQ.SetParIsUsed(gpRefParTypeScattDataScale,true);
4404 //mLSQ.SetParIsUsed(gpRefParTypeScattDataProfile,true);
4405 //mLSQ.SetParIsUsed(gpRefParTypeScattDataCorrPos,true);
4406 //mLSQ.SetParIsUsed(gpRefParTypeScattDataBackground,true);
4407 //mLSQ.SetParIsUsed(gpRefParTypeUnitCell,true);
4408 mLSQ.SetParIsUsed(gpRefParTypeScatt,false);
4409 mLSQ.SetParIsUsed(gpRefParTypeScattPow,false);
4410 //mLSQ.SetParIsFixed(gpRefParTypeObjCryst,true);
4411 //mLSQ.SetParIsFixed(gpRefParTypeScattDataScale,false);
4413 wxScrolledWindow *pManual=new wxScrolledWindow(pNotebook,-1,wxDefaultPosition,
4414 wxSize(400,250),wxHSCROLL | wxVSCROLL);
4415 wxBoxSizer *pSizerManual=new wxBoxSizer(wxVERTICAL);
4417 wxButton *pButton2=new wxButton(pManual,ID_PROFILEFITTING_RUN_MANUAL,_T("Le Bail + Fit Profile !"));
4418 pSizerManual->Add(pButton2,0,wxALIGN_CENTER);
4419 //pManual->SetSize(pQuick->GetSize());
4420 pSizerManual->Add(mLSQ.WXCreate(pManual),1,wxALIGN_CENTER);
4421 mLSQ.WXGet()->CrystUpdate(true,true);
4422 pManual->SetScrollRate(10,10);
4423 pManual->SetSizer(pSizerManual);
4425 pSizerManual->FitInside(pManual);
4427 pNotebook->AddPage(pManual,_T("Manual Fit"),true);
4429 // Spacegroup exploration
4430 wxScrolledWindow *pSpgExplor=new wxScrolledWindow(pNotebook,-1,wxDefaultPosition,
4431 wxSize(600,250),wxHSCROLL | wxVSCROLL);
4432 wxBoxSizer *pSizerSpgExplor=new wxBoxSizer(wxVERTICAL);
4434 wxButton *pButton3=new wxButton(pSpgExplor,ID_PROFILEFITTING_EXPLORE_SPG,_T("Try all possible spacegroups - Le Bail + Least Squares (SLOW)"));
4435 pSizerSpgExplor->Add(pButton3,0,wxALIGN_CENTER);
4436 wxButton *pButton4=new wxButton(pSpgExplor,ID_PROFILEFITTING_EXPLORE_SPG_QUICK,_T("Try all possible spacegroups - Le Bail only"));
4437 pSizerSpgExplor->Add(pButton4,0,wxALIGN_CENTER);
4439 pSpgExplor->SetSizer(pSizerSpgExplor);
4440 pSpgExplor->Layout();
4441 pSizerSpgExplor->FitInside(pSpgExplor);
4443 pNotebook->AddPage(pSpgExplor,_T("Spacegroup Explorer"),true);
4445 pNotebook->ChangeSelection(0);
4446 mpLog =new wxTextCtrl(this,-1,_T(""),wxDefaultPosition,wxSize(600,300),wxTE_MULTILINE|wxTE_READONLY|wxTE_DONTWRAP);
4447 mpLog->SetFont(wxFont(10,wxTELETYPE,wxFONTSTYLE_NORMAL,wxFONTWEIGHT_NORMAL));
4448 pSizer0->Add(mpLog,1,wxEXPAND);
4449 mpLog->AppendText(wxString::Format(_T("Profile fitting & Space Group exploration:\n")));
4450 mpLog->AppendText(wxString::Format(_T("\nTo perform a QUICK fit:\n")));
4451 mpLog->AppendText(wxString::Format(_T(" - if you are not too far to a reasonable fit, just use 'Le Bail + Fit profile',\n")));
4452 mpLog->AppendText(wxString::Format(_T(" the parameters will be progressively relaxed to avoid divergence\n")));
4453 mpLog->AppendText(wxString::Format(_T(" - you can also choose to only refine some groups of parameters for more safety\n")));
4454 mpLog->AppendText(wxString::Format(_T("\nYou can also perform a MANUAL fit (nececessary for advanced fit, or anisotropic profiles):\n")));
4455 mpLog->AppendText(wxString::Format(_T(" - select the Manual Fit tab\n")));
4456 mpLog->AppendText(wxString::Format(_T(" - select the individual parameters to refine (check the 'R')\n")));
4457 mpLog->AppendText(wxString::Format(_T(" - you can also set some limits by right-clicking on 'L'\n")));
4458 mpLog->AppendText(wxString::Format(_T("\n Spacegroup exploration:\n")));
4459 mpLog->AppendText(wxString::Format(_T(" - use this after a good profile fitting has been obtained.\n")));
4460 mpLog->AppendText(wxString::Format(_T(" - Fox will try a le Bail Fit on all possible spacegroup settings.\n")));
4461 mpLog->AppendText(wxString::Format(_T(" which are compatible with the current unit cell.\n")));
4462 mpLog->AppendText(wxString::Format(_T(" - try the 'Le Bail only' option first (much faster, no profile fitting for each spacegroup)\n")));
4463 mpLog->AppendText(wxString::Format(_T("---------------------------------------------------------------------------------------------\n\n")));
4465 //pSizer0->Layout();
4466 pSizer0->SetSizeHints(this);
4467 //pSizer0->Fit(this);
4468 pSizer0->Fit(this->GetParent());
4472 WXProfileFitting::~WXProfileFitting()
4474 if(mpDiff!=0) mpDiff->SetExtractionMode(false);
4477 unsigned int nb=mpPattern->GetNbPowderPatternComponent();
4478 for(unsigned int i=0;i<nb;++i)
4479 if(mpPattern->GetPowderPatternComponent(i).GetClassName()==string("PowderPatternDiffraction"))
4481 PowderPatternDiffraction *pDiff=dynamic_cast<PowderPatternDiffraction*>(&(mpPattern->GetPowderPatternComponent(i)));
4482 if(pDiff!=0) pDiff->SetExtractionMode(false);
4485 mpPattern->UpdateDisplay();
4488 void WXProfileFitting::OnFit(wxCommandEvent &event)
4490 WXCrystValidateAllUserInput();
4491 // Map of crystalline phases to be fitted (or not)
4492 map<PowderPatternDiffraction *,bool> vpDiff;
4493 // Multiple phases can be fitted - which one was chosen ?
4496 wxArrayInt selections;
4497 mpList->GetSelections(selections);
4498 const int choice=selections[0];
4500 unsigned int nb=mpPattern->GetNbPowderPatternComponent();
4501 for(unsigned int i=0;i<nb;++i)
4502 if(mpPattern->GetPowderPatternComponent(i).GetClassName()==string("PowderPatternDiffraction"))
4504 PowderPatternDiffraction *pDiff=dynamic_cast<PowderPatternDiffraction*>(&(mpPattern->GetPowderPatternComponent(i)));
4505 cout<<"WXProfileFitting::WXProfileFitting():"<<pDiff<<":"<<mpPattern->GetPowderPatternComponent(i).GetName()<<endl;
4508 if(ct++==choice) vpDiff[pDiff]=true;
4509 else vpDiff[pDiff]=false;
4514 {// A single phase may have been pre-selected, but others may be present
4515 unsigned int nb=mpPattern->GetNbPowderPatternComponent();
4516 for(unsigned int i=0;i<nb;++i)
4517 if(mpPattern->GetPowderPatternComponent(i).GetClassName()==string("PowderPatternDiffraction"))
4519 PowderPatternDiffraction *pDiff=dynamic_cast<PowderPatternDiffraction*>(&(mpPattern->GetPowderPatternComponent(i)));
4520 cout<<"WXProfileFitting::WXProfileFitting():"<<pDiff<<":"<<mpPattern->GetPowderPatternComponent(i).GetName()<<endl;
4523 if(pDiff==mpDiff) vpDiff[pDiff]=true;
4524 else vpDiff[pDiff]=false;
4529 if(mpDiff!=0) pDiff=mpDiff;
4532 unsigned int nb=mpPattern->GetNbPowderPatternComponent();
4534 const unsigned int n0=mpList->GetSelection();
4535 for(unsigned int i=0;i<nb;++i)
4537 if(mpPattern->GetPowderPatternComponent(i).GetClassName()==string("PowderPatternDiffraction"))
4539 pDiff=dynamic_cast<PowderPatternDiffraction*>(&(mpPattern->GetPowderPatternComponent(i)));
4548 cout<<"Selected PowderPatternDiffraction:"<<mpDiff->GetName()<<","<<mpDiff->GetCrystal().GetName()<<endl;
4550 for(map<PowderPatternDiffraction *,bool>::iterator pos=vpDiff.begin();pos!=vpDiff.end();++pos)
4551 if(pos->second) pos->first->SetExtractionMode(true,true);
4553 mpLog->AppendText(wxString::Format(_T("Starting 20 Le Bail cycles\n")));
4554 wxProgressDialog dlgProgress(_T("Le Bail and Profile Fitting"),_T("Le Bail Fitting, cycle #0/20"),
4555 18,this,wxPD_AUTO_HIDE|wxPD_ELAPSED_TIME|wxPD_CAN_ABORT|wxPD_APP_MODAL);
4556 for(int i=0;i<10;++i)
4558 for(map<PowderPatternDiffraction *,bool>::iterator pos=vpDiff.begin();pos!=vpDiff.end();++pos)
4560 {// Only one should be in LeBail mode, but this code is general
4561 pos->first->ExtractLeBail(2);
4562 pos->first->GetParentPowderPattern().FitScaleFactorForRw();
4563 pos->first->GetParentPowderPattern().UpdateDisplay();
4565 if(dlgProgress.Update(i,wxString::Format(_T("Le Bail Fitting, cycle #%d/20"),i*2))==false) return;
4567 mpLog->AppendText(wxString::Format(_T(" => Rwp=%5.3f%%, GoF=%7.3f\n"),
4568 mpDiff->GetParentPowderPattern().GetRw()*100,
4569 mpDiff->GetParentPowderPattern().GetChi2()
4570 /mpDiff->GetParentPowderPattern().GetNbPointUsed()));
4572 if(event.GetId()==ID_PROFILEFITTING_RUN)
4574 bool fitzero=false,fitwidth0=false,fitwidth=false,fiteta=false,
4575 fitasym=false,fitdispltransp=false,fitbackgd=false,fitcell=false,
4576 fitanisotropic=false,
4577 fitTOFInstWidth=false,fitTOFBroadening=false;
4579 if(mpDiff->GetProfile().GetClassName()=="ReflectionProfileDoubleExponentialPseudoVoigt")
4581 mpDiff->GetProfile().Print();
4582 fitzero=mpFitCheckList->IsChecked(0);
4583 fitTOFInstWidth=mpFitCheckList->IsChecked(1);
4584 fitTOFBroadening=mpFitCheckList->IsChecked(2);
4585 fitbackgd=mpFitCheckList->IsChecked(3);
4586 fitcell=mpFitCheckList->IsChecked(4);
4590 fitzero=mpFitCheckList->IsChecked(0);
4591 fitwidth0=mpFitCheckList->IsChecked(1);
4592 fitwidth=mpFitCheckList->IsChecked(2);
4593 fiteta=mpFitCheckList->IsChecked(3);
4594 fitasym=mpFitCheckList->IsChecked(4);
4595 fitdispltransp=mpFitCheckList->IsChecked(5);
4596 fitbackgd=mpFitCheckList->IsChecked(6);
4597 fitcell=mpFitCheckList->IsChecked(7);
4600 mLSQ.SetParIsFixed(gpRefParTypeScattDataScale,false);
4601 std::list<RefinablePar*> vnewpar;
4602 std::list<const RefParType*> vnewpartype;
4603 mLSQ.SafeRefine(vnewpar,vnewpartype,2,true,false);
4605 if(fitzero) vnewpar.push_back(&mLSQ.GetCompiledRefinedObj().GetPar("Zero"));
4607 for(map<PowderPatternDiffraction *,bool>::iterator pos=vpDiff.begin();pos!=vpDiff.end();++pos)
4608 if(pos->second) vnewpar.push_back(&mLSQ.GetCompiledRefinedObj().GetPar("W"));
4610 for(map<PowderPatternDiffraction *,bool>::iterator pos=vpDiff.begin();pos!=vpDiff.end();++pos)
4611 if((pos->second) && (pos->first->GetProfile().GetClassName()=="ReflectionProfilePseudoVoigtAnisotropic"))
4612 vnewpar.push_back(&mLSQ.GetCompiledRefinedObj().GetPar("X"));
4613 if(fitzero||fitwidth0)
4615 mpLog->AppendText(wxString::Format(_T("Fitting zero shift && constant width\n")));
4616 if(dlgProgress.Update(11,_T("Fitting zero shift && constant width"))==false) return;
4617 const bool result = mLSQ.SafeRefine(vnewpar, vnewpartype, 1.01, 5,true,false);
4618 if(!result) mpLog->AppendText(_T(" OUPS: parameter did not improve fit => fix & continue\n"));
4620 vnewpartype.clear();
4621 mpDiff->ExtractLeBail(2);
4622 mpDiff->GetParentPowderPattern().UpdateDisplay();
4623 mpLog->AppendText(wxString::Format(_T(" => Rwp=%6.3f%%, GoF=%7.3f\n"),
4624 mpDiff->GetParentPowderPattern().GetRw()*100,
4625 mpDiff->GetParentPowderPattern().GetChi2()
4626 /mpDiff->GetParentPowderPattern().GetNbPointUsed()));
4629 for(map<PowderPatternDiffraction *,bool>::iterator pos=vpDiff.begin();pos!=vpDiff.end();++pos)
4630 if(pos->second) vnewpar.push_back(&mLSQ.GetCompiledRefinedObj().GetPar("U"));
4632 for(map<PowderPatternDiffraction *,bool>::iterator pos=vpDiff.begin();pos!=vpDiff.end();++pos)
4633 if(pos->second) vnewpar.push_back(&mLSQ.GetCompiledRefinedObj().GetPar("V"));
4635 for(map<PowderPatternDiffraction *,bool>::iterator pos=vpDiff.begin();pos!=vpDiff.end();++pos)
4636 if((pos->second) && (pos->first->GetProfile().GetClassName()=="ReflectionProfilePseudoVoigtAnisotropic"))
4637 vnewpar.push_back(&mLSQ.GetCompiledRefinedObj().GetPar("Y"));
4639 for(map<PowderPatternDiffraction *,bool>::iterator pos=vpDiff.begin();pos!=vpDiff.end();++pos)
4640 if((pos->second) && (pos->first->GetProfile().GetClassName()=="ReflectionProfilePseudoVoigtAnisotropic"))
4641 vnewpar.push_back(&mLSQ.GetCompiledRefinedObj().GetPar("P"));
4643 for(map<PowderPatternDiffraction *,bool>::iterator pos=vpDiff.begin();pos!=vpDiff.end();++pos)
4644 if(pos->second) vnewpar.push_back(&mLSQ.GetCompiledRefinedObj().GetPar("Eta0"));
4645 if(fitwidth||fiteta)
4647 mpLog->AppendText(wxString::Format(_T("Fitting width and gaussian/lorentzian fixed mix\n")));
4648 if(dlgProgress.Update(12,_T("Fitting variable width and gaussian/lorentzian fixed mix"))==false) return;
4649 const bool result = mLSQ.SafeRefine(vnewpar, vnewpartype, 1.01, 5,true,false);
4650 if(!result) mpLog->AppendText(_T(" OUPS: parameter did not improve fit => fix & continue\n"));
4652 vnewpartype.clear();
4653 mpDiff->ExtractLeBail(2);
4654 mpDiff->GetParentPowderPattern().UpdateDisplay();
4655 mpLog->AppendText(wxString::Format(_T(" => Rwp=%6.3f%%, GoF=%7.3f\n"),
4656 mpDiff->GetParentPowderPattern().GetRw()*100,
4657 mpDiff->GetParentPowderPattern().GetChi2()
4658 /mpDiff->GetParentPowderPattern().GetNbPointUsed()));
4663 mpDiff->GetProfile().Print();
4664 for(map<PowderPatternDiffraction *,bool>::iterator pos=vpDiff.begin();pos!=vpDiff.end();++pos)
4667 vnewpar.push_back(&mLSQ.GetCompiledRefinedObj().GetPar("Alpha1"));
4668 vnewpar.push_back(&mLSQ.GetCompiledRefinedObj().GetPar("Beta0"));
4669 vnewpar.push_back(&mLSQ.GetCompiledRefinedObj().GetPar("Beta1"));
4671 mpLog->AppendText(wxString::Format(_T("Fitting TOF instrumental width (alpha1,beta0,beta1)\n")));
4672 if(dlgProgress.Update(12,_T("Fitting TOF instrumental width (alpha1,beta0,beta1)"))==false) return;
4673 const bool result = mLSQ.SafeRefine(vnewpar, vnewpartype, 1.01, 5,true,false);
4674 if(!result) mpLog->AppendText(_T(" OUPS: parameter did not improve fit => fix & continue\n"));
4676 vnewpartype.clear();
4677 mpDiff->ExtractLeBail(2);
4678 mpDiff->GetParentPowderPattern().UpdateDisplay();
4679 mpLog->AppendText(wxString::Format(_T(" => Rwp=%6.3f%%, GoF=%7.3f\n"),
4680 mpDiff->GetParentPowderPattern().GetRw()*100,
4681 mpDiff->GetParentPowderPattern().GetChi2()
4682 /mpDiff->GetParentPowderPattern().GetNbPointUsed()));
4684 if(fitTOFBroadening)
4686 mpDiff->GetProfile().Print();
4687 for(map<PowderPatternDiffraction *,bool>::iterator pos=vpDiff.begin();pos!=vpDiff.end();++pos)
4690 vnewpar.push_back(&mLSQ.GetCompiledRefinedObj().GetPar("GaussianSigma1"));
4691 //vnewpar.push_back(&mLSQ.GetCompiledRefinedObj().GetPar("LorentzianGamma2"));
4692 //vnewpar.push_back(&mLSQ.GetCompiledRefinedObj().GetPar("GaussianSigma1"));
4693 //vnewpar.push_back(&mLSQ.GetCompiledRefinedObj().GetPar("LorentzianGamma2"));
4695 mpLog->AppendText(wxString::Format(_T("Fitting size/strain broadening parameters (sigma1,gamma2)\n")));
4696 if(dlgProgress.Update(12,_T("Fitting size/strain broadening parameters (sigma1,gamma2)"))==false) return;
4697 const bool result = mLSQ.SafeRefine(vnewpar, vnewpartype, 1.01, 5,true,false);
4698 if(!result) mpLog->AppendText(_T(" OUPS: parameter did not improve fit => fix & continue\n"));
4700 vnewpartype.clear();
4701 mpDiff->ExtractLeBail(2);
4702 mpDiff->GetParentPowderPattern().UpdateDisplay();
4703 mpLog->AppendText(wxString::Format(_T(" => Rwp=%6.3f%%, GoF=%7.3f\n"),
4704 mpDiff->GetParentPowderPattern().GetRw()*100,
4705 mpDiff->GetParentPowderPattern().GetChi2()
4706 /mpDiff->GetParentPowderPattern().GetNbPointUsed()));
4707 for(map<PowderPatternDiffraction *,bool>::iterator pos=vpDiff.begin();pos!=vpDiff.end();++pos)
4709 vnewpar.push_back(&mLSQ.GetCompiledRefinedObj().GetPar("GaussianSigma1"));
4712 if(fiteta) mLSQ.SetParIsFixed(mpDiff->GetProfile().GetPar("Eta1"),false);
4715 mpLog->AppendText(wxString::Format(_T("Fitting gaussian/lorentzian mix\n")));
4716 if(dlgProgress.Update(13,_T("Fitting variable width and gaussian/lorentzian mix"))==false) return;
4717 const bool result = mLSQ.SafeRefine(vnewpar, vnewpartype, 1.01, 5,true,false);
4718 if(!result) mpLog->AppendText(_T(" OUPS: parameter did not improve fit => fix & continue\n"));
4720 vnewpartype.clear();
4721 mpDiff->ExtractLeBail(2);
4722 mpDiff->GetParentPowderPattern().UpdateDisplay();
4723 mpLog->AppendText(wxString::Format(_T(" => Rwp=%6.3f%%, GoF=%7.3f\n"),
4724 mpDiff->GetParentPowderPattern().GetRw()*100,
4725 mpDiff->GetParentPowderPattern().GetChi2()
4726 /mpDiff->GetParentPowderPattern().GetNbPointUsed()));
4730 for(map<PowderPatternDiffraction *,bool>::iterator pos=vpDiff.begin();pos!=vpDiff.end();++pos)
4731 if(pos->second) vnewpar.push_back(&mLSQ.GetCompiledRefinedObj().GetPar("Asym0"));
4733 for(map<PowderPatternDiffraction *,bool>::iterator pos=vpDiff.begin();pos!=vpDiff.end();++pos)
4734 if(pos->second) vnewpar.push_back(&mLSQ.GetCompiledRefinedObj().GetPar("Asym1"));
4736 for(map<PowderPatternDiffraction *,bool>::iterator pos=vpDiff.begin();pos!=vpDiff.end();++pos)
4737 if(pos->second) vnewpar.push_back(&mLSQ.GetCompiledRefinedObj().GetPar("Asym2"));
4739 for(map<PowderPatternDiffraction *,bool>::iterator pos=vpDiff.begin();pos!=vpDiff.end();++pos)
4740 if(pos->second) vnewpar.push_back(&mLSQ.GetCompiledRefinedObj().GetPar("2ThetaDispl"));
4742 for(map<PowderPatternDiffraction *,bool>::iterator pos=vpDiff.begin();pos!=vpDiff.end();++pos)
4743 if(pos->second) vnewpar.push_back(&mLSQ.GetCompiledRefinedObj().GetPar("2ThetaTransp"));
4744 if(fitdispltransp||fitasym)
4746 mpLog->AppendText(wxString::Format(_T("Fitting assymetry and sample displacement/transparency\n")));
4747 if(dlgProgress.Update(14,_T("Fitting assymetry and sample displacement/transparency"))==false) return;
4748 const bool result = mLSQ.SafeRefine(vnewpar, vnewpartype, 1.01, 5,true,false);
4749 if(!result) mpLog->AppendText(_T(" OUPS: parameter did not improve fit => fix & continue\n"));
4751 vnewpartype.clear();
4752 mpDiff->ExtractLeBail(2);
4753 mpDiff->GetParentPowderPattern().UpdateDisplay();
4754 mpLog->AppendText(wxString::Format(_T(" => Rwp=%6.3f%%, GoF=%7.3f\n"),
4755 mpDiff->GetParentPowderPattern().GetRw()*100,
4756 mpDiff->GetParentPowderPattern().GetChi2()
4757 /mpDiff->GetParentPowderPattern().GetNbPointUsed()));
4762 mLSQ.SetParIsFixed(gpRefParTypeScattDataBackground,false);
4763 // Make sure points beyond max resolution are not optimized
4764 const unsigned int nbcomp= mpDiff->GetParentPowderPattern().GetNbPowderPatternComponent();
4765 for(unsigned int i=0;i<nbcomp;++i)
4766 if(mpDiff->GetParentPowderPattern().GetPowderPatternComponent(i).GetClassName()=="PowderPatternBackground")
4768 PowderPatternBackground *pback=dynamic_cast<PowderPatternBackground *>
4769 (&(mpDiff->GetParentPowderPattern().GetPowderPatternComponent(i)));
4770 pback->FixParametersBeyondMaxresolution(mLSQ.GetCompiledRefinedObj());
4772 for(unsigned int i=0; i<mLSQ.GetCompiledRefinedObj().GetNbPar();i++)
4773 if( (mLSQ.GetCompiledRefinedObj().GetPar(i).IsFixed()==false)
4774 &&(mLSQ.GetCompiledRefinedObj().GetPar(i).GetType()==gpRefParTypeScattDataBackground))
4775 vnewpar.push_back(&mLSQ.GetCompiledRefinedObj().GetPar(i));
4777 mpLog->AppendText(wxString::Format(_T("Fitting background\n")));
4778 if(dlgProgress.Update(15,_T("Fitting background"))==false) return;
4779 const bool result = mLSQ.SafeRefine(vnewpar, vnewpartype, 1.01, 5,true,false);
4780 if(!result) mpLog->AppendText(_T(" OUPS: parameter did not improve fit => fix & continue\n"));
4782 vnewpartype.clear();
4783 mpDiff->ExtractLeBail(2);
4784 mpDiff->GetParentPowderPattern().UpdateDisplay();
4785 mpLog->AppendText(wxString::Format(_T(" => Rwp=%6.3f%%, GoF=%7.3f\n"),
4786 mpDiff->GetParentPowderPattern().GetRw()*100,
4787 mpDiff->GetParentPowderPattern().GetChi2()
4788 /mpDiff->GetParentPowderPattern().GetNbPointUsed()));
4793 vnewpartype.push_back(gpRefParTypeUnitCell);
4795 // Fix uc parameters of unrefined phases
4796 for(map<PowderPatternDiffraction *,bool>::iterator pos=vpDiff.begin();pos!=vpDiff.end();++pos)
4797 if(!(pos->second)) mLSQ.SetParIsFixed(pos->first->GetCrystal(),true);
4799 mpLog->AppendText(wxString::Format(_T("Fitting unit cell\n")));
4800 if(dlgProgress.Update(16,_T("Fitting unit cell"))==false) return;
4801 const bool result = mLSQ.SafeRefine(vnewpar, vnewpartype, 1.01, 5,true,false);
4802 if(!result) mpLog->AppendText(_T(" OUPS: parameter did not improve fit => fix & continue\n"));
4804 vnewpartype.clear();
4805 mpDiff->ExtractLeBail(2);
4806 mpDiff->GetParentPowderPattern().UpdateDisplay();
4807 mpLog->AppendText(wxString::Format(_T(" => Rwp=%6.3f%%, GoF=%7.3f\n"),
4808 mpDiff->GetParentPowderPattern().GetRw()*100,
4809 mpDiff->GetParentPowderPattern().GetChi2()
4810 /mpDiff->GetParentPowderPattern().GetNbPointUsed()));
4813 catch(const ObjCrystException &except)
4815 mpLog->AppendText(wxString::Format(_T(" OOPS : refinement diverged ! Aborting. Try with fewer parameters ?\n")));
4816 mLSQ.EndOptimization();
4823 std::list<RefinablePar*> vnewpar;
4824 std::list<const RefParType*> vnewpartype;
4825 mpLog->AppendText(wxString::Format(_T("Profile fitting (manual):\n")));
4826 mpLog->AppendText(wxString::Format(_T(" Initial values: Rwp=%6.3f%%, GoF=%7.3f\n"),
4827 mpDiff->GetParentPowderPattern().GetRw()*100,
4828 mpDiff->GetParentPowderPattern().GetChi2()
4829 /mpDiff->GetParentPowderPattern().GetNbPointUsed()));
4830 mpLog->AppendText(wxString::Format(_T("3 LSQ cycles...\n")));
4831 if(false==mLSQ.SafeRefine(vnewpar, vnewpartype, 1.05, 5,true,false))
4832 mpLog->AppendText(_T(" OUPS: Fit did not improve fit => reverting\n"));
4833 mpLog->AppendText(wxString::Format(_T(" => Rwp=%6.3f%%, GoF=%7.3f\n"),
4834 mpDiff->GetParentPowderPattern().GetRw()*100,
4835 mpDiff->GetParentPowderPattern().GetChi2()
4836 /mpDiff->GetParentPowderPattern().GetNbPointUsed()));
4837 mpLog->AppendText(wxString::Format(_T("2 Le Bail cycles...\n")));
4838 if(dlgProgress.Update(9,_T("Manual Le Bail + Profile fitting"))==false) return;
4839 mpDiff->ExtractLeBail(2);
4840 mpLog->AppendText(wxString::Format(_T(" => Rwp=%6.3f%%, GoF=%7.3f\n"),
4841 mpDiff->GetParentPowderPattern().GetRw()*100,
4842 mpDiff->GetParentPowderPattern().GetChi2()
4843 /mpDiff->GetParentPowderPattern().GetNbPointUsed()));
4844 mpLog->AppendText(wxString::Format(_T("3 LSQ cycles...\n")));
4845 if(dlgProgress.Update(13,_T("Manual Le Bail + Profile fitting"))==false) return;
4846 if(false==mLSQ.SafeRefine(vnewpar, vnewpartype, 1.05, 5,true,false))
4847 mpLog->AppendText(_T(" OUPS: Fit did not improve fit => reverting\n"));
4848 if(dlgProgress.Update(17,_T("Manual Le Bail + Profile fitting"))==false) return;
4849 mpDiff->GetParentPowderPattern().UpdateDisplay();
4850 mpLog->AppendText(wxString::Format(_T(" => Rwp=%6.3f%%, GoF=%7.3f\n"),
4851 mpDiff->GetParentPowderPattern().GetRw()*100,
4852 mpDiff->GetParentPowderPattern().GetChi2()
4853 /mpDiff->GetParentPowderPattern().GetNbPointUsed()));
4855 catch(const ObjCrystException &except)
4857 mpLog->AppendText(wxString::Format(_T(" OOPS : refinement diverged ! Aborting.\n")));
4858 if(mLSQ.GetCompiledRefinedObj().GetNbParNotFixed() <= 1)
4859 mpLog->AppendText(wxString::Format(_T(" You had selected only %ld parameters to refine !!\n"), mLSQ.GetCompiledRefinedObj().GetNbParNotFixed()));
4860 else mpLog->AppendText(wxString::Format(_T(" Change selection of parameters to refine ?\n")));
4861 mLSQ.EndOptimization();
4864 mLSQ.WXGet()->CrystUpdate(true,true);
4865 mpDiff->GetCrystal().UpdateDisplay();
4869 void WXProfileFitting::OnExploreSpacegroups(wxCommandEvent &event)
4871 WXCrystValidateAllUserInput();
4872 TAU_PROFILE("WXProfileFitting::OnExploreSpacegroups()","void (wxCommandEvent &)",TAU_DEFAULT);
4873 PowderPatternDiffraction *pDiff=0;
4874 if(mpDiff!=0) pDiff=mpDiff;
4877 unsigned int nb=mpPattern->GetNbPowderPatternComponent();
4879 const unsigned int n0=mpList->GetSelection();
4880 for(unsigned int i=0;i<nb;++i)
4882 if(mpPattern->GetPowderPatternComponent(i).GetClassName()==string("PowderPatternDiffraction"))
4884 pDiff=dynamic_cast<PowderPatternDiffraction*>(&(mpPattern->GetPowderPatternComponent(i)));
4892 cout<<"Selected PowderPatternDiffraction:"<<pDiff->GetName()<<","<<pDiff->GetCrystal().GetName()<<endl;
4894 pDiff->SetExtractionMode(true,true);
4895 Crystal *pCrystal=&(pDiff->GetCrystal());
4897 // Keep initial lattice parameters & spg
4898 const REAL a=pCrystal->GetLatticePar(0),
4899 b=pCrystal->GetLatticePar(1),
4900 c=pCrystal->GetLatticePar(2),
4901 d=pCrystal->GetLatticePar(3),
4902 e=pCrystal->GetLatticePar(4),
4903 f=pCrystal->GetLatticePar(5);
4904 const string spgname=pCrystal->GetSpaceGroup().GetName();
4905 const string name=pCrystal->GetName();
4907 const cctbx::uctbx::unit_cell uc(scitbx::af::double6(a,b,c,d*RAD2DEG,e*RAD2DEG,f*RAD2DEG));
4909 cctbx::sgtbx::space_group_symbol_iterator it=cctbx::sgtbx::space_group_symbol_iterator();
4911 // First, count compatible spacegroups
4912 unsigned int nbspg=0;
4913 //unsigned int hmlen=0;
4916 cctbx::sgtbx::space_group_symbols s=it.next();
4917 if(s.number()==0) break;
4918 cctbx::sgtbx::space_group spg(s);
4919 if(spg.is_compatible_unit_cell(uc,0.01,0.1)) nbspg++;
4920 //if(s.universal_hermann_mauguin().size()>hmlen) hmlen=s.universal_hermann_mauguin().size();
4922 mpLog->AppendText(wxString::Format(_T("Beginning spacegroup exploration... %u to go...\n"),nbspg));
4923 //cout<<"Max HM symbol length:"<<hmlen<<endl;
4924 unsigned int nbcycle=1;
4925 if(event.GetId()==ID_PROFILEFITTING_EXPLORE_SPG) nbcycle=3;
4926 wxProgressDialog dlgProgress(_T("Trying compatible spacegroups"),_T("Starting........\n......\n......"),
4927 nbspg*nbcycle,this,wxPD_AUTO_HIDE|wxPD_ELAPSED_TIME|wxPD_CAN_ABORT|wxPD_APP_MODAL);
4929 list<SPGScore> vSPG;
4931 SpaceGroupExplorer ex(pDiff);
4933 // we don't have the extinction symbols, so do it the stupid way
4934 // create a fingerprint of systematically extinct reflections
4935 // for 0<H<5 0<K<5 0<L<7
4936 std::map<std::vector<bool>,SPGScore> vSPGExtinctionFingerprint;
4938 // Nb refl below max sin(theta/lambda) for p1, to compute nGoF
4939 unsigned int nb_refl_p1=1;
4941 // Try & optimize every spacegroup
4942 it=cctbx::sgtbx::space_group_symbol_iterator();
4945 bool user_stop=false;
4948 cctbx::sgtbx::space_group_symbols s=it.next();
4949 if(s.number()==0) break;
4950 cctbx::sgtbx::space_group spg(s);
4951 bool compat=spg.is_compatible_unit_cell(uc,0.01,0.1);
4955 const string hm=s.universal_hermann_mauguin();
4956 cout<<s.number()<<","<<hm.c_str()<<","<<(int)compat<<endl;
4957 mpLog->AppendText(wxString::Format(_T(" (#%3d) %-14s:"),s.number(),wxString::FromAscii(hm.c_str()).c_str()));
4959 pCrystal->Init(a,b,c,d,e,f,hm,name);
4960 std::vector<bool> fgp=spgExtinctionFingerprint(*pCrystal,spg);
4961 std::map<std::vector<bool>,SPGScore>::iterator posfgp=vSPGExtinctionFingerprint.find(fgp);
4962 if(posfgp!=vSPGExtinctionFingerprint.end())
4964 mpDiff->SetExtractionMode(true,true); //:TODO: why is this needed to actually get the updated GetNbReflBelowMaxSinThetaOvLambda ?
4965 unsigned int nbrefl = pDiff->GetNbReflBelowMaxSinThetaOvLambda();
4966 REAL ngof = (posfgp->second.ngof * nbrefl) / posfgp->second.nbreflused;
4967 SPGScore score = SPGScore(hm.c_str(),posfgp->second.rw,posfgp->second.gof, posfgp->second.nbextinct446, ngof, nbrefl);
4968 vSPG.push_back(score);
4969 cout<<"Spacegroup:"<<hm<<" has same extinctions as:"<<posfgp->second.hm<<endl;
4970 //mpLog->AppendText(_T(" same as:")+wxString::FromAscii(posfgp->second.hm.c_str())+_T("\n"));
4971 mpLog->AppendText(wxString::Format(_T(" same refl as %13s nGoF=%9.5f (%3u reflections, %3u extinct)\n"),
4972 wxString::FromAscii(posfgp->second.hm.c_str()), score.ngof, score.nbreflused, score.nbextinct446));
4976 SPGScore score = ex.Run(spg, event.GetId()==ID_PROFILEFITTING_EXPLORE_SPG, false, false);
4977 pDiff->GetParentPowderPattern().UpdateDisplay();
4978 if(s.number() == 1) nb_refl_p1 = score.nbreflused;
4979 score.ngof *= mpDiff->GetNbReflBelowMaxSinThetaOvLambda() / (float)nb_refl_p1;
4981 if(dlgProgress.Update(i*nbcycle,wxString::FromAscii(hm.c_str())+wxString::Format(_T(" (%u cycles)\n Rwp=%5.2f%%\n GoF=%9.2f"),
4982 nbcycle,score.rw,score.gof))==false) user_stop=true;
4984 if(user_stop) break;
4985 vSPG.push_back(score);
4986 mpLog->AppendText(wxString::Format(_T(" Rwp= %5.2f%% GoF=%8.3f nGoF=%9.5f (%3u reflections, %3u extinct)\n"),score.rw,score.gof,score.ngof, score.nbreflused,score.nbextinct446));
4987 vSPGExtinctionFingerprint.insert(make_pair(fgp,score));
4990 if(user_stop) break;
4992 // sort results by GoF
4993 vSPG.sort(compareSPGScore);
4994 mpLog->AppendText(wxString::Format(_T("\n\nBEST Solutions, from min_nGoF to 4*min_nGof:\n")));
4995 mpLog->AppendText(wxString::Format(_T("\nThe number of reflections use for the fit is given, and\n"
4996 " \'extinct\' gives the number of extinct reflections\n")));
4997 mpLog->AppendText(wxString::Format(_T(" for 0<=H<=4 0<=K<=4 0<=L<=6 \n\n")));
4998 mpLog->AppendText(wxString::Format(_T("GoF = Chi^2 / nb observed points\n\n")));
4999 mpLog->AppendText(wxString::Format(_T("nGof = iGoF_P1 * (nb_refl) / (nb_refl_P1) \n"
5000 " where iGoF_P1 is the integrated Goodness-of-Fit \n"
5001 " using P1 integration intervals.\n"
5002 " This takes into account the number of used reflections\n"
5003 " and is the best indicator\n\n")));
5004 for(list<SPGScore>::const_iterator pos=vSPG.begin();pos!=vSPG.end();++pos)
5006 if( (pos->ngof>(4*vSPG.begin()->ngof))) break;
5007 mpLog->AppendText(wxString::Format(_T(" Rwp=%5.2f%% GoF=%8.2f nGoF=%9.5f: (%3u reflections, %3u extinct) "),pos->rw,pos->gof,pos->ngof, pos->nbreflused,pos->nbextinct446)+wxString::FromAscii(pos->hm.c_str())+_T(" \n"));
5009 mpLog->AppendText(wxString::Format(_T("\n\nYou can copy the chosen spacegroup symbol in the Crystal window\n")));
5010 mpLog->AppendText(wxString::Format(_T("\n\nThe spacegroup with the best nGoF has been applied\n")));
5011 // Set best solution
5012 pCrystal->ChangeSpaceGroup(vSPG.front().hm);
5013 pDiff->GetParentPowderPattern().UpdateDisplay();
5014 pDiff->SetExtractionMode(true,true);
5015 pDiff->ExtractLeBail(5);
5016 pDiff->GetParentPowderPattern().UpdateDisplay();
5017 ex.RunAll(event.GetId()==ID_PROFILEFITTING_EXPLORE_SPG, true);
5020 void WXPowderPatternDiffraction::OnLeBail(wxCommandEvent &event)
5022 WXCrystValidateAllUserInput();
5023 if((event.GetId()==ID_POWDERDIFF_PROFILEFITTINGMODE)&&(mpProfileFittingMode->GetValue()==false))
5025 mpPowderPatternDiffraction->SetExtractionMode(false);
5026 mpPowderPatternDiffraction->GetParentPowderPattern().UpdateDisplay();
5029 mpPowderPatternDiffraction->SetExtractionMode(true,false);
5030 wxFrame *pFrame=new wxFrame(this,-1,_T("Profile Fitting"));
5031 WXProfileFitting *pFit;
5032 pFit=new WXProfileFitting(pFrame,&(mpPowderPatternDiffraction->GetParentPowderPattern()),mpPowderPatternDiffraction);
5036 void WXPowderPatternDiffraction::OnFreezeLatticePar(wxCommandEvent &event)
5038 mpPowderPatternDiffraction->FreezeLatticePar(mpFreezeLatticePar->GetValue());
5044 // WXProfilePseudoVoigt
5047 WXProfilePseudoVoigt::WXProfilePseudoVoigt(wxWindow *parent, ReflectionProfilePseudoVoigt *prof):
5048 WXCrystObj(parent),mpProfile(prof)
5050 VFN_DEBUG_ENTRY("WXProfilePseudoVoigt::WXProfilePseudoVoigt()",6)
5051 mpWXTitle->SetLabel("Pseudo-Voigt profile");
5052 mpWXTitle->SetForegroundColour(wxColour(0,0,255));
5054 wxBoxSizer* sizer1=new wxBoxSizer(wxHORIZONTAL);
5055 WXCrystObjBasic* pFieldCagliotiU=mpProfile->GetPar("U").WXCreate(this);
5056 WXCrystObjBasic* pFieldCagliotiV=mpProfile->GetPar("V").WXCreate(this);
5057 WXCrystObjBasic* pFieldCagliotiW=mpProfile->GetPar("W").WXCreate(this);;
5058 sizer1->Add(pFieldCagliotiU,0);
5059 sizer1->Add(pFieldCagliotiV,0);
5060 sizer1->Add(pFieldCagliotiW,0);
5061 mList.Add(pFieldCagliotiU);
5062 mList.Add(pFieldCagliotiV);
5063 mList.Add(pFieldCagliotiW);
5064 mpSizer->Add(sizer1);
5065 pFieldCagliotiU->SetToolTip(_T("Width Parameters (Caglioti's law):\n")
5066 _T("fwhm=[W+V*tan(theta)+U*tan^2(theta)]^1/2"));
5067 pFieldCagliotiV->SetToolTip(_T("Width Parameters (Caglioti's law):\n")
5068 _T("fwhm=[W+V*tan(theta)+U*tan^2(theta)]^1/2"));
5069 pFieldCagliotiW->SetToolTip(_T("Width Parameters (Caglioti's law):\n")
5070 _T("fwhm=[W+V*tan(theta)+U*tan^2(theta)]^1/2"));
5072 wxBoxSizer* sizer2=new wxBoxSizer(wxHORIZONTAL);
5073 WXCrystObjBasic* pFieldEta0=mpProfile->GetPar("Eta0").WXCreate(this);
5074 WXCrystObjBasic* pFieldEta1=mpProfile->GetPar("Eta1").WXCreate(this);
5075 sizer2->Add(pFieldEta0,0);
5076 sizer2->Add(pFieldEta1,0);
5077 mList.Add(pFieldEta0);
5078 mList.Add(pFieldEta1);
5079 mpSizer->Add(sizer2);
5080 pFieldEta0->SetToolTip(_T("Gaussian/Lorentzian mixing parameters:\n")
5081 _T(" PV(x) = eta*L(x) + (1-eta)*G(x)\n\n")
5082 _T("eta=Eta0+Eta11*2theta"));
5083 pFieldEta1->SetToolTip(_T("Gaussian/Lorentzian mixing parameters:\n")
5084 _T(" PV(x) = eta*L(x) + (1-eta)*G(x)\n\n")
5085 _T("eta=Eta0+Eta11*2theta"));
5086 // Asymmetry parameter
5087 wxBoxSizer* sizer3=new wxBoxSizer(wxHORIZONTAL);
5088 //WXCrystObjBasic* pFieldAsymA0=mpProfile->GetPar("AsymA0").WXCreate(this);
5089 //WXCrystObjBasic* pFieldAsymA1=mpProfile->GetPar("AsymA1").WXCreate(this);
5090 //WXCrystObjBasic* pFieldAsymB0=mpProfile->GetPar("AsymB0").WXCreate(this);
5091 //WXCrystObjBasic* pFieldAsymB1=mpProfile->GetPar("AsymB1").WXCreate(this);
5092 //sizer3->Add(pFieldAsymA0,0);
5093 //sizer3->Add(pFieldAsymA1,0);
5094 //sizer3->Add(pFieldAsymB0,0);
5095 //sizer3->Add(pFieldAsymB1,0);
5096 //mList.Add(pFieldAsymA0);
5097 //mList.Add(pFieldAsymA1);
5098 //mList.Add(pFieldAsymB0);
5099 //mList.Add(pFieldAsymB1);
5100 WXCrystObjBasic* pFieldAsym0=mpProfile->GetPar("Asym0").WXCreate(this);
5101 WXCrystObjBasic* pFieldAsym1=mpProfile->GetPar("Asym1").WXCreate(this);
5102 WXCrystObjBasic* pFieldAsym2=mpProfile->GetPar("Asym2").WXCreate(this);
5103 sizer3->Add(pFieldAsym0,0);
5104 sizer3->Add(pFieldAsym1,0);
5105 sizer3->Add(pFieldAsym2,0);
5106 mList.Add(pFieldAsym0);
5107 mList.Add(pFieldAsym1);
5108 mList.Add(pFieldAsym2);
5109 mpSizer->Add(sizer3);
5111 pFieldAsym0->SetToolTip(_T("Asymmetry parameters:\n\n")
5112 _T("A=A0+A1/sin(2theta)+A2/sin^2(2theta) "));
5113 pFieldAsym1->SetToolTip(_T("Asymmetry parameters:\n\n")
5114 _T("A=A0+A1/sin(2theta)+A2/sin^2(2theta) "));
5115 pFieldAsym2->SetToolTip(_T("Asymmetry parameters:\n\n")
5116 _T("A=A0+A1/sin(2theta)+A2/sin^2(2theta) "));
5118 this->CrystUpdate(true);
5119 VFN_DEBUG_EXIT("WXProfilePseudoVoigt::WXProfilePseudoVoigt()",6)
5121 WXProfilePseudoVoigt::~WXProfilePseudoVoigt()
5123 mpProfile->WXNotifyDelete();
5125 bool WXProfilePseudoVoigt::OnChangeName(const int id)
5132 // WXProfilePseudoVoigtAnisotropic
5135 WXProfilePseudoVoigtAnisotropic::WXProfilePseudoVoigtAnisotropic(wxWindow *parent, ReflectionProfilePseudoVoigtAnisotropic *prof):
5136 WXCrystObj(parent),mpProfile(prof)
5138 VFN_DEBUG_ENTRY("WXProfilePseudoVoigtAnisotropic::WXProfilePseudoVoigtAnisotropic()",6)
5139 mpWXTitle->SetLabel("Pseudo-Voigt Anisotropic profile");
5140 mpWXTitle->SetForegroundColour(wxColour(0,0,255));
5142 wxBoxSizer* sizer1=new wxBoxSizer(wxHORIZONTAL);
5143 WXCrystObjBasic* pFieldCagliotiU=mpProfile->GetPar("U").WXCreate(this);
5144 WXCrystObjBasic* pFieldCagliotiV=mpProfile->GetPar("V").WXCreate(this);
5145 WXCrystObjBasic* pFieldCagliotiW=mpProfile->GetPar("W").WXCreate(this);;
5146 WXCrystObjBasic* pFieldScherrerP=mpProfile->GetPar("P").WXCreate(this);;
5147 sizer1->Add(pFieldCagliotiU,0);
5148 sizer1->Add(pFieldCagliotiV,0);
5149 sizer1->Add(pFieldCagliotiW,0);
5150 sizer1->Add(pFieldScherrerP,0);
5151 mList.Add(pFieldCagliotiU);
5152 mList.Add(pFieldCagliotiV);
5153 mList.Add(pFieldCagliotiW);
5154 mList.Add(pFieldScherrerP);
5155 mpSizer->Add(sizer1);
5156 pFieldCagliotiU->SetToolTip(_T("Gaussian Width Parameters:\n")
5157 _T("fwhm=[W+V*tan(theta)+U*tan^2(theta)+P/cos^2(theta)]^1/2"));
5158 pFieldCagliotiV->SetToolTip(_T("Gaussian Width Parameters:\n")
5159 _T("fwhm=[W+V*tan(theta)+U*tan^2(theta)+P/cos^2(theta)]^1/2"));
5160 pFieldCagliotiW->SetToolTip(_T("Gaussian Width Parameters:\n")
5161 _T("fwhm=[W+V*tan(theta)+U*tan^2(theta)+P/cos^2(theta)]^1/2"));
5162 pFieldScherrerP->SetToolTip(_T("Gaussian Width Parameters:\n")
5163 _T("fwhm=[W+V*tan(theta)+U*tan^2(theta)+P/cos^2(theta)]^1/2"));
5164 // Lorentzian & Mixing parameter
5165 wxBoxSizer* sizer2=new wxBoxSizer(wxHORIZONTAL);
5166 WXCrystObjBasic* pFieldEta0=mpProfile->GetPar("Eta0").WXCreate(this);
5167 WXCrystObjBasic* pFieldEta1=mpProfile->GetPar("Eta1").WXCreate(this);
5168 WXCrystObjBasic* pFieldX=mpProfile->GetPar("X").WXCreate(this);
5169 WXCrystObjBasic* pFieldY=mpProfile->GetPar("Y").WXCreate(this);
5170 sizer2->Add(pFieldEta0,0);
5171 sizer2->Add(pFieldEta1,0);
5172 sizer2->Add(pFieldX,0);
5173 sizer2->Add(pFieldY,0);
5176 mList.Add(pFieldEta0);
5177 mList.Add(pFieldEta1);
5178 mpSizer->Add(sizer2);
5179 pFieldEta0->SetToolTip(_T("Gaussian/Lorentzian mixing parameters:\n")
5180 _T(" PV(x) = eta*L(x) + (1-eta)*G(x)\n\n")
5181 _T("eta=Eta0+Eta11*2theta"));
5183 pFieldEta1->SetToolTip(_T("Gaussian/Lorentzian mixing parameters:\n")
5184 _T(" PV(x) = eta*L(x) + (1-eta)*G(x)\n\n")
5185 _T("eta=Eta0+Eta1*2theta"));
5187 pFieldX->SetToolTip(_T("Lorentzian width:\n")
5188 _T(" FWHM(x) = X/cos(theta) + (Y + gam_L/sin^2(theta))*tan(theta)\n\n")
5189 _T("gam_L=gam_hh*H^2 + gam_kk*K^2 + gam_ll*L^2\n")
5190 _T(" +gam_hk*HK + gam_hl*HL + gam_kl*HL"));
5192 pFieldY->SetToolTip(_T("Lorentzian width:\n")
5193 _T(" FWHM(x) = X/cos(theta) + (Y + gam_L/sin^2(theta))*tan(theta)\n\n")
5194 _T("gam_L=gam_hh*H^2 + gam_kk*K^2 + gam_ll*L^2\n")
5195 _T(" +gam_hk*HK + gam_hl*HL + gam_kl*HL"));
5197 // Anisotropic coefficients
5198 wxBoxSizer* sizerA=new wxBoxSizer(wxHORIZONTAL);
5199 WXCrystObjBasic* pFieldGHH=mpProfile->GetPar("G_HH").WXCreate(this);
5200 WXCrystObjBasic* pFieldGKK=mpProfile->GetPar("G_KK").WXCreate(this);
5201 WXCrystObjBasic* pFieldGLL=mpProfile->GetPar("G_LL").WXCreate(this);
5202 WXCrystObjBasic* pFieldGHK=mpProfile->GetPar("G_HK").WXCreate(this);
5203 WXCrystObjBasic* pFieldGHL=mpProfile->GetPar("G_HL").WXCreate(this);
5204 WXCrystObjBasic* pFieldGKL=mpProfile->GetPar("G_KL").WXCreate(this);
5205 sizerA->Add(pFieldGHH,0);
5206 sizerA->Add(pFieldGKK,0);
5207 sizerA->Add(pFieldGLL,0);
5208 sizerA->Add(pFieldGHK,0);
5209 sizerA->Add(pFieldGHL,0);
5210 sizerA->Add(pFieldGKL,0);
5211 mList.Add(pFieldGHH);
5212 mList.Add(pFieldGKK);
5213 mList.Add(pFieldGLL);
5214 mList.Add(pFieldGHK);
5215 mList.Add(pFieldGHL);
5216 mList.Add(pFieldGKL);
5217 mpSizer->Add(sizerA);
5218 pFieldGHH->SetToolTip(_T("Lorentzian width:\n")
5219 _T(" FWHM(x) = X/cos(theta) + (Y + gam_L/sin^2(theta))*tan(theta)\n\n")
5220 _T("gam_L=gam_hh*H^2 + gam_kk*K^2 + gam_ll*L^2\n")
5221 _T(" +gam_hk*HK + gam_hl*HL + gam_kl*HL"));
5222 pFieldGKK->SetToolTip(_T("Lorentzian width:\n")
5223 _T(" FWHM(x) = X/cos(theta) + (Y + gam_L/sin^2(theta))*tan(theta)\n\n")
5224 _T("gam_L=gam_hh*H^2 + gam_kk*K^2 + gam_ll*L^2\n")
5225 _T(" +gam_hk*HK + gam_hl*HL + gam_kl*HL"));
5226 pFieldGLL->SetToolTip(_T("Lorentzian width:\n")
5227 _T(" FWHM(x) = X/cos(theta) + (Y + gam_L/sin^2(theta))*tan(theta)\n\n")
5228 _T("gam_L=gam_hh*H^2 + gam_kk*K^2 + gam_ll*L^2\n")
5229 _T(" +gam_hk*HK + gam_hl*HL + gam_kl*HL"));
5230 pFieldGHK->SetToolTip(_T("Lorentzian width:\n")
5231 _T(" FWHM(x) = X/cos(theta) + (Y + gam_L/sin^2(theta))*tan(theta)\n\n")
5232 _T("gam_L=gam_hh*H^2 + gam_kk*K^2 + gam_ll*L^2\n")
5233 _T(" +gam_hk*HK + gam_hl*HL + gam_kl*HL"));
5234 pFieldGHL->SetToolTip(_T("Lorentzian width:\n")
5235 _T(" FWHM(x) = X/cos(theta) + (Y + gam_L/sin^2(theta))*tan(theta)\n\n")
5236 _T("gam_L=gam_hh*H^2 + gam_kk*K^2 + gam_ll*L^2\n")
5237 _T(" +gam_hk*HK + gam_hl*HL + gam_kl*HL"));
5238 pFieldGKL->SetToolTip(_T("Lorentzian width:\n")
5239 _T(" FWHM(x) = X/cos(theta) + (Y + gam_L/sin^2(theta))*tan(theta)\n\n")
5240 _T("gam_L=gam_hh*H^2 + gam_kk*K^2 + gam_ll*L^2\n")
5241 _T(" +gam_hk*HK + gam_hl*HL + gam_kl*HL"));
5243 // Asymmetry parameters
5244 wxBoxSizer* sizer3=new wxBoxSizer(wxHORIZONTAL);
5245 WXCrystObjBasic* pFieldAsym0=mpProfile->GetPar("Asym0").WXCreate(this);
5246 WXCrystObjBasic* pFieldAsym1=mpProfile->GetPar("Asym1").WXCreate(this);
5247 WXCrystObjBasic* pFieldAsym2=mpProfile->GetPar("Asym2").WXCreate(this);
5248 sizer3->Add(pFieldAsym0,0);
5249 sizer3->Add(pFieldAsym1,0);
5250 sizer3->Add(pFieldAsym2,0);
5251 mList.Add(pFieldAsym0);
5252 mList.Add(pFieldAsym1);
5253 mList.Add(pFieldAsym2);
5254 mpSizer->Add(sizer3);
5256 pFieldAsym0->SetToolTip(_T("Asymmetry parameters:\n\n")
5257 _T("A=A0+A1/sin(2theta)+A2/sin^2(2theta) "));
5258 pFieldAsym1->SetToolTip(_T("Asymmetry parameters:\n\n")
5259 _T("A=A0+A1/sin(2theta)+A2/sin^2(2theta) "));
5260 pFieldAsym2->SetToolTip(_T("Asymmetry parameters:\n\n")
5261 _T("A=A0+A1/sin(2theta)+A2/sin^2(2theta) "));
5263 this->CrystUpdate(true);
5264 VFN_DEBUG_EXIT("WXProfilePseudoVoigtAnisotropic::WXProfilePseudoVoigtAnisotropic()",6)
5267 WXProfilePseudoVoigtAnisotropic::~WXProfilePseudoVoigtAnisotropic()
5269 mpProfile->WXNotifyDelete();
5272 bool WXProfilePseudoVoigtAnisotropic::OnChangeName(const int id)
5279 // WXProfileDoubleExponentialPseudoVoigt
5282 WXProfileDoubleExponentialPseudoVoigt::WXProfileDoubleExponentialPseudoVoigt
5283 (wxWindow *parent, ReflectionProfileDoubleExponentialPseudoVoigt *prof):
5284 WXCrystObj(parent),mpProfile(prof)
5286 VFN_DEBUG_ENTRY("WXProfileDoubleExponentialPseudoVoigt::WXProfileDoubleExponentialPseudoVoigt()",6)
5287 mpWXTitle->SetLabel("Double-Exponential Pseudo-Voigt profile (for neutron TOF)");
5288 mpWXTitle->SetForegroundColour(wxColour(0,0,255));
5290 wxBoxSizer* sizer1=new wxBoxSizer(wxHORIZONTAL);
5291 WXCrystObjBasic* pFieldCagliotiA0=mpProfile->GetPar("Alpha0").WXCreate(this);
5292 WXCrystObjBasic* pFieldCagliotiA =mpProfile->GetPar("Alpha1").WXCreate(this);
5293 WXCrystObjBasic* pFieldCagliotiB0=mpProfile->GetPar("Beta0").WXCreate(this);
5294 WXCrystObjBasic* pFieldCagliotiB1=mpProfile->GetPar("Beta1").WXCreate(this);
5295 sizer1->Add(pFieldCagliotiA0,0);
5296 sizer1->Add(pFieldCagliotiA,0);
5297 sizer1->Add(pFieldCagliotiB0,0);
5298 sizer1->Add(pFieldCagliotiB1,0);
5299 mList.Add(pFieldCagliotiA0);
5300 mList.Add(pFieldCagliotiA);
5301 mList.Add(pFieldCagliotiB0);
5302 mList.Add(pFieldCagliotiB1);
5303 mpSizer->Add(sizer1);
5305 wxBoxSizer* sizer2=new wxBoxSizer(wxHORIZONTAL);
5306 WXCrystObjBasic* pFieldSigma0=mpProfile->GetPar("GaussianSigma0").WXCreate(this);
5307 WXCrystObjBasic* pFieldSigma1=mpProfile->GetPar("GaussianSigma1").WXCreate(this);
5308 WXCrystObjBasic* pFieldSigma2=mpProfile->GetPar("GaussianSigma2").WXCreate(this);
5309 sizer2->Add(pFieldSigma0,0);
5310 sizer2->Add(pFieldSigma1,0);
5311 sizer2->Add(pFieldSigma2,0);
5312 mList.Add(pFieldSigma0);
5313 mList.Add(pFieldSigma1);
5314 mList.Add(pFieldSigma2);
5315 mpSizer->Add(sizer2);
5317 wxBoxSizer* sizer3=new wxBoxSizer(wxHORIZONTAL);
5318 WXCrystObjBasic* pFieldGamma0=mpProfile->GetPar("LorentzianGamma0").WXCreate(this);
5319 WXCrystObjBasic* pFieldGamma1=mpProfile->GetPar("LorentzianGamma1").WXCreate(this);
5320 WXCrystObjBasic* pFieldGamma2=mpProfile->GetPar("LorentzianGamma2").WXCreate(this);
5321 sizer3->Add(pFieldGamma0,0);
5322 sizer3->Add(pFieldGamma1,0);
5323 sizer3->Add(pFieldGamma2,0);
5324 mList.Add(pFieldGamma0);
5325 mList.Add(pFieldGamma1);
5326 mList.Add(pFieldGamma2);
5327 mpSizer->Add(sizer3);
5329 this->CrystUpdate(true);
5330 VFN_DEBUG_EXIT("WXProfileDoubleExponentialPseudoVoigt::WXProfileDoubleExponentialPseudoVoigt()",6)
5332 WXProfileDoubleExponentialPseudoVoigt::~WXProfileDoubleExponentialPseudoVoigt()
5334 mpProfile->WXNotifyDelete();
5336 bool WXProfileDoubleExponentialPseudoVoigt::OnChangeName(const int id)
The namespace which includes all objects (crystallographic and algorithmic) in ObjCryst++.
CrystMutex mMutex
Mutex used to lock data when preparing to update the UI in non-main thread.
void UpdateUI(const bool mutexlock=false)
Forces all objects in the list to update.
void CrystUpdate(const bool updateUI=false, const bool mutexlock=false)
Forces all objects in the list to update.
void OnToggleCollapse(wxCommandEvent &WXUNUSED(event))
Only display the title, and collapse everything else.
void OnMenuLeBail(wxCommandEvent &event)
Profile fitting & Le Bail intensity extraction.
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.