FOX/ObjCryst++  2022
PowderPattern.cpp
1 /* ObjCryst++ Object-Oriented Crystallographic Library
2  (c) 2000-2002 Vincent Favre-Nicolin vincefn@users.sourceforge.net
3  2000-2001 University of Geneva (Switzerland)
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program; if not, write to the Free Software
17  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 */
19 /*
20 * source file for LibCryst++ PowderPattern class
21 *
22 */
23 
24 #include <cstdlib>
25 
26 #include <typeinfo>
27 #include <stdio.h> //for sprintf()
28 #include <boost/format.hpp>
29 
30 #include "cctbx/sgtbx/space_group.h" // For fullprof export
31 
32 #include "ObjCryst/ObjCryst/PowderPattern.h"
33 #include "ObjCryst/ObjCryst/Molecule.h" // For fullprof export
34 #include "ObjCryst/ObjCryst/PowderPatternBackgroundBayesianMinimiser.h"
35 #include "ObjCryst/RefinableObj/Simplex.h"
36 #include "ObjCryst/Quirks/VFNDebug.h"
37 #include "ObjCryst/Quirks/VFNStreamFormat.h"
38 #include "ObjCryst/ObjCryst/CIF.h"
39 #include "ObjCryst/Quirks/Chronometer.h"
40 #ifdef __WX__CRYST__
41  #include "ObjCryst/wxCryst/wxPowderPattern.h"
42 #endif
43 
44 #include <fstream>
45 #include <iomanip>
46 #include <sstream>
47 
48 #ifdef _MSC_VER // MS VC++ predefined macros....
49 #undef min
50 #undef max
51 #endif
52 
53 //#define USE_BACKGROUND_MAXLIKE_ERROR
54 
55 #define POSSIBLY_UNUSED(expr) (void)(expr)
56 
57 namespace ObjCryst
58 {
60 //
61 // Cylinder absorption correction
62 //
65 ScatteringCorr(data), mpPowderPatternDiff(&data)
66 {}
67 
68 CylinderAbsCorr::~CylinderAbsCorr()
69 {}
70 
71 const string & CylinderAbsCorr::GetName() const
72 {
73  //So far, we do not need a personalized name...
74  const static string mName="CylinderAbsCorr";
75  return mName;
76 }
77 
78 const string & CylinderAbsCorr::GetClassName() const
79 {
80  const static string className="CylinderAbsCorr";
81  return className;
82 }
83 
85 {
86  mpData->GetTheta(); // Make sure theta is up-to-date
88  && (mpData->GetClockTheta()<mClockCorrCalc)) return;
89  TAU_PROFILE("CylinderAbsCorr::CalcCorr()","void ()",TAU_DEFAULT);
90  mCorr.resize(mpData->GetNbRefl());
91  const REAL muR = mpPowderPatternDiff->GetParentPowderPattern().GetMuR();
92  if(muR == 0)
93  {
94  mCorr = 1;
95  return;
96  }
97  for(long i=0;i<mpData->GetNbRefl();i++)
98  {
99  const REAL s2 = pow(sin(mpData->GetTheta()(i)),2);
100  if(muR<=3)
101  {
102  const REAL t0 = 16.0/(3.*M_PI);
103  const REAL t1 = (25.99978-0.01911*pow(s2,0.25))*exp(-0.024551*s2)+ 0.109561*sqrt(s2)-26.04556;
104  const REAL t2 = -0.02489-0.39499*s2+1.219077*pow(s2,1.5)- 1.31268*pow(s2,2)+0.871081*pow(s2,2.5)-0.2327*pow(s2,3);
105  const REAL t3 = 0.003045+0.018167*s2-0.03305*pow(s2,2);
106  const REAL t = -t0*muR-t1*pow(muR,2)-t2*pow(muR,3)-t3*pow(muR,4);
107  mCorr(i) = exp(t);
108  }
109  else
110  {
111  const REAL t1 = 1.433902+11.07504*s2-8.77629*s2*s2+ 10.02088*s2*s2*s2-3.36778*s2*s2*s2*s2;
112  const REAL t2 = (0.013869-0.01249*s2)*exp(3.27094*s2)+ (0.337894+13.77317*s2)/pow(1.0+11.53544*s2, 1.555039);
113  const REAL t3 = 1.933433/pow(1.0+23.12967*s2, 1.686715) -0.13576*sqrt(s2)+1.163198;
114  const REAL t4 = 0.044365-0.04259/pow(1.0+0.41051*s2, 148.4202);
115  const REAL t = (t1-t4)/pow(1+t2*(muR-3),t3)+t4;
116  mCorr(i) = t/100;
117  }
118  }
119 
121 }
122 
124 //
125 // PowderPatternComponent
126 //
129  gPowderPatternComponentRegistry("List of all PowderPattern Components");
130 
131 PowderPatternComponent::PowderPatternComponent():
132 mIsScalable(false),mpParentPowderPattern(0)
133 {
134  gPowderPatternComponentRegistry.Register(*this);
135  mClockMaster.AddChild(mClockBraggLimits);
136 }
137 
138 PowderPatternComponent::PowderPatternComponent(const PowderPatternComponent &old):
139 mIsScalable(old.mIsScalable),
140 mpParentPowderPattern(old.mpParentPowderPattern)
141 {
142  mClockMaster.AddChild(mClockBraggLimits);
143  if(mpParentPowderPattern!=0)
144  {
145  mClockMaster.AddChild(mpParentPowderPattern->GetClockPowderPatternPar());
146  mClockMaster.AddChild(mpParentPowderPattern->GetClockPowderPatternXCorr());
147  mClockMaster.AddChild(mpParentPowderPattern->GetClockPowderPatternRadiation());
148  }
149 }
150 
151 PowderPatternComponent::~PowderPatternComponent()
152 {
153  gPowderPatternComponentRegistry.DeRegister(*this);
154 }
155 
157 {
158  const static string className="PowderPatternComponent";
159  return className;
160 }
161 
163 {
164  return *mpParentPowderPattern;
165 }
166 
167 std::map<RefinablePar*,CrystVector_REAL>& PowderPatternComponent::GetPowderPattern_FullDeriv(std::set<RefinablePar *> &vPar)
168 {
169  this->CalcPowderPattern_FullDeriv(vPar);
170  return mPowderPattern_FullDeriv;
171 }
172 
173 std::map<RefinablePar*,CrystVector_REAL>& PowderPatternComponent::GetPowderPatternIntegrated_FullDeriv(std::set<RefinablePar *> &vPar)
174 {
176  return mPowderPatternIntegrated_FullDeriv;
177 }
178 
180 {
181  return *mpParentPowderPattern;
182 }
183 
185 
187 {
189 }
191 {
192  return mClockBraggLimits;
193 }
194 
195 const list<pair<const REAL, const string> >& PowderPatternComponent::GetPatternLabelList()const
196 {
197  return mvLabel;
198 }
199 
200 void PowderPatternComponent::CalcPowderPattern_FullDeriv(std::set<RefinablePar *> &vPar)
201 {
202  TAU_PROFILE("PowderPatternComponent::CalcPowderPattern_FullDeriv()","void ()",TAU_DEFAULT);
203  mPowderPattern_FullDeriv.clear();
204  for(std::set<RefinablePar *>::iterator par=vPar.begin();par!=vPar.end();par++)
205  {
206  if(*par==0)
207  {
208  mPowderPattern_FullDeriv[*par]=this->GetPowderPatternCalc();
209  continue;
210  }
211  const REAL step=(*par)->GetDerivStep();
212  (*par)->Mutate(step);
213  mPowderPattern_FullDeriv[*par] =this->GetPowderPatternCalc();
214  (*par)->Mutate(-2*step);
215  mPowderPattern_FullDeriv[*par]-=this->GetPowderPatternCalc();
216  (*par)->Mutate(step);
217  mPowderPattern_FullDeriv[*par]/= step*2;
218  if(MaxAbs(mPowderPattern_FullDeriv[*par])==0)
219  mPowderPattern_FullDeriv[*par].resize(0);
220  }
221 }
222 
224 {
225  TAU_PROFILE("PowderPatternComponent::CalcPowderPatternIntegrated_FullDeriv()","void ()",TAU_DEFAULT);
226  mPowderPatternIntegrated_FullDeriv.clear();
227  for(std::set<RefinablePar *>::iterator par=vPar.begin();par!=vPar.end();par++)
228  {
229  if(*par==0)
230  {
231  mPowderPatternIntegrated_FullDeriv[*par]=*(this->GetPowderPatternIntegratedCalc().first);
232  continue;
233  }
234  const REAL step=(*par)->GetDerivStep();
235  (*par)->Mutate(step);
236  mPowderPatternIntegrated_FullDeriv[*par] =*(this->GetPowderPatternIntegratedCalc().first);
237  (*par)->Mutate(-2*step);
238  mPowderPatternIntegrated_FullDeriv[*par]-=*(this->GetPowderPatternIntegratedCalc().first);
239  (*par)->Mutate(step);
240  mPowderPatternIntegrated_FullDeriv[*par]/= step*2;
241  if(MaxAbs(mPowderPatternIntegrated_FullDeriv[*par])==0)
242  mPowderPatternIntegrated_FullDeriv[*par].resize(0);
243  }
244 }
245 
247 //
248 // PowderPatternBackground
249 //
251 PowderPatternBackground::PowderPatternBackground():
252 mBackgroundNbPoint(0),
253 mMaxSinThetaOvLambda(10),mModelVariance(0)
254 {
255  mClockMaster.AddChild(mClockBackgroundPoint);
256  this->InitOptions();
257 }
258 
259 PowderPatternBackground::PowderPatternBackground(const PowderPatternBackground &old):
260 mBackgroundNbPoint(old.mBackgroundNbPoint),
261 mBackgroundInterpPointX(old.mBackgroundInterpPointX),
262 mBackgroundInterpPointIntensity(old.mBackgroundInterpPointIntensity),
263 mMaxSinThetaOvLambda(10),mModelVariance(0)
264 {
265  mClockMaster.AddChild(mClockBackgroundPoint);
266  this->InitOptions();
267  mInterpolationModel.SetChoice(old.mInterpolationModel.GetChoice());
268 }
269 
270 PowderPatternBackground::~PowderPatternBackground(){}
272 {
273  const static string className="PowderPatternBackground";
274  return className;
275 }
276 
278 {
279  if(mpParentPowderPattern!=0)
286 }
287 const CrystVector_REAL& PowderPatternBackground::GetPowderPatternCalc()const
288 {
289  this->CalcPowderPattern();
290  return mPowderPatternCalc;
291 }
292 
293 pair<const CrystVector_REAL*,const RefinableObjClock*>
295 {
296  VFN_DEBUG_MESSAGE("PowderPatternBackground::GetPowderPatternIntegratedCalc()",3)
297  this->CalcPowderPatternIntegrated();
299 }
300 
302 {
303  VFN_DEBUG_MESSAGE("PowderPatternBackground::ImportUserBackground():"<<filename,5)
304  ifstream fin (filename.c_str());
305  if(!fin)
306  {
307  throw ObjCrystException("PowderPatternBackground::ImportUserBackground() : \
308 Error opening file for input:"+filename);
309  }
310  long max=100;
311  CrystVector_REAL bckgd2Theta(max),bckgd(max);
312 
313  long nbPoints=0;
314  do
315  {
316  fin >> bckgd2Theta(nbPoints);
317  fin >> bckgd(nbPoints);
318  if(!fin) break;
319  VFN_DEBUG_MESSAGE("Background=" << bckgd(nbPoints)\
320  <<" at 2theta="<<bckgd2Theta(nbPoints),3)
321  nbPoints++;
322  if(nbPoints==max)
323  {
324  max += 100;
325  bckgd2Theta.resizeAndPreserve(max);
326  bckgd.resizeAndPreserve(max);
327  }
328  } while(fin.eof() == false);
329  fin.close();
330  bckgd2Theta.resizeAndPreserve(nbPoints);
331  bckgd.resizeAndPreserve(nbPoints);
332  if(mpParentPowderPattern!=0)
333  { if((this->GetParentPowderPattern().GetRadiation().GetWavelengthType()==WAVELENGTH_MONOCHROMATIC)
334  ||(this->GetParentPowderPattern().GetRadiation().GetWavelengthType()==WAVELENGTH_ALPHA12))
335  bckgd2Theta*= DEG2RAD;
336  } else bckgd2Theta*= DEG2RAD;
337 
338  this->SetInterpPoints(bckgd2Theta,bckgd);
339  this->InitRefParList();
341  {
342  char buf [200];
343  sprintf(buf,"Imported %d background points",(int)nbPoints);
344  (*fpObjCrystInformUser)((string)buf);
345  }
346  this->UpdateDisplay();
347  VFN_DEBUG_MESSAGE("PowderPatternBackground::ImportUserBackground():finished",5)
348 }
349 void PowderPatternBackground::SetInterpPoints(const CrystVector_REAL tth,
350  const CrystVector_REAL backgd)
351 {
352  VFN_DEBUG_ENTRY("PowderPatternBackground::SetInterpPoints():",5)
353  if( (tth.numElements()!=backgd.numElements())
354  ||(tth.numElements()<2))
355  {
356  throw ObjCrystException("PowderPatternBackground::SetInterpPoints() : \
357 number of points differ or less than 2 points !");
358  }
359  mBackgroundNbPoint=tth.numElements();
362  // Sort in ascending order, disregarding radiation type.
363  CrystVector<long> subs;
364  subs=SortSubs(tth);
365 
366  for(long i=0;i<mBackgroundNbPoint;++i)
367  {
368  mBackgroundInterpPointX(i)=tth(subs(i));
369  mBackgroundInterpPointIntensity(i)=backgd(subs(i));
370  }
371  this->InitRefParList();
373  VFN_DEBUG_EXIT("PowderPatternBackground::SetInterpPoints()",5)
374 }
375 
376 const pair<const CrystVector_REAL*,const CrystVector_REAL*> PowderPatternBackground::GetInterpPoints()const
377 {
379 }
380 
382  CrystVector_uint & groupIndex,
383  unsigned int &first) const
384 {
385  // One group for all background points
386  unsigned int index=0;
387  VFN_DEBUG_MESSAGE("PowderPatternBackground::GetGeneGroup()",4)
388  for(long i=0;i<obj.GetNbPar();i++)
389  for(long j=0;j<this->GetNbPar();j++)
390  if(&(obj.GetPar(i)) == &(this->GetPar(j)))
391  {
392  if(index==0) index=first++;
393  groupIndex(i)=index;
394  }
395 }
396 
397 void PowderPatternBackground::BeginOptimization(const bool allowApproximations,
398  const bool enableRestraints)
399 {
400  this->RefinableObj::BeginOptimization(allowApproximations,enableRestraints);
401 }
402 
404 {
405  this->CalcPowderPattern();
407 }
408 
409 pair<const CrystVector_REAL*,const RefinableObjClock*>
411 {
412  this->CalcPowderPatternIntegrated();
413  return make_pair(&mPowderPatternIntegratedCalcVariance,
415 }
416 
418 {
419  #ifdef USE_BACKGROUND_MAXLIKE_ERROR
420  return true;
421  #else
422  return false;
423  #endif
424 }
425 
427 {
428 }
429 
431 {
432  VFN_DEBUG_ENTRY("PowderPatternBackground::OptimizeBayesianBackground()",5);
433  TAU_PROFILE("PowderPatternBackground::OptimizeBayesianBackground()","void ()",TAU_DEFAULT);
435  SimplexObj simplex("Simplex Test");
436  simplex.AddRefinableObj(min);
437 
438  long nbcycle;
439  REAL llk=simplex.GetLogLikelihood();
440  long ct=0;
441  cout<<"Initial Chi^2(BayesianBackground)="<<llk<<endl;
443  mBackgroundInterpPointIntensity.max()/1000.0);
444 
445  {
446  char buf [200];
447  sprintf(buf,"Optimizing Background, Cycle %d, Chi^2(Background)=%f",
448  (int)ct,(float)llk);
449  (*fpObjCrystInformUser)((string)buf);
450  }
451  nbcycle=500*mBackgroundNbPoint;
452  simplex.Optimize(nbcycle,false);
453  llk=simplex.GetLogLikelihood();
454  cout<<ct<<", Chi^2(BayesianBackground)="<<llk<<endl;
455 
457  {
458  char buf [200];
459  sprintf(buf,"Done Optimizing Bayesian Background, Chi^2(Background)=%f",(float)llk);
460  (*fpObjCrystInformUser)((string)buf);
461  }
462 
463  LSQNumObj lsq;
464  lsq.SetRefinedObj(min,0,true,true);
465  lsq.PrepareRefParList(true);
467  try {lsq.Refine(10,true,false);}
468  catch(const ObjCrystException &except){};
469 
471  VFN_DEBUG_EXIT("PowderPatternBackground::OptimizeBayesianBackground()",5);
472 }
473 
475 {
476  //Auto-fix points beyond used range
477  unsigned long nbpoint=this->GetParentPowderPattern().GetNbPointUsed();
478  for(long j=0;j<mBackgroundNbPoint;j++)
479  if(this->GetParentPowderPattern().X2Pixel(mBackgroundInterpPointX(j))>nbpoint)
480  {
481  // obj.GetPar(&mBackgroundInterpPointIntensity(j)).Print();
482  obj.GetPar(&mBackgroundInterpPointIntensity(j)).SetIsFixed(true);
483  }
484 }
485 
487 {
489 
490  //:TODO: This needs serious optimization !
493  &&(mClockPowderPatternCalc>mInterpolationModel.GetClock())) return;
494  TAU_PROFILE("PowderPatternBackground::CalcPowderPattern()","void ()",TAU_DEFAULT);
495  VFN_DEBUG_MESSAGE("PowderPatternBackground::CalcPowderPattern()",3);
496 
497  const unsigned long nb=mpParentPowderPattern->GetNbPoint();
498  mPowderPatternCalc.resize(nb);
499  if(nb!=0)
500  switch(mInterpolationModel.GetChoice())
501  {
502  case POWDER_BACKGROUND_LINEAR:
503  {
504  VFN_DEBUG_MESSAGE("PowderPatternBackground::CalcPowderPattern()..Linear",2)
505  REAL p1,p2;
506  REAL b1,b2;
507  if(mBackgroundNbPoint==0)
508  {
510  break;
511  }
512  VFN_DEBUG_MESSAGE("PowderPatternBackground::CalcPowderPattern()"<<nb,2)
513  this->InitSpline();
514  REAL *b=mPowderPatternCalc.data();
519  long point=1;
520  for(unsigned long i=0;i<nb;i++)
521  {
522  if(i >= p2)
523  {
524  if(point < mBackgroundNbPoint-1)
525  {
526  b1=b2;
527  p1=p2;
530  point++ ;
531  }
532  }
533  *b = (b1*(p2-i)+b2*(i-p1))/(p2-p1) ;
534  b++;
535  }
536  break;
537  }
538  case POWDER_BACKGROUND_CUBIC_SPLINE:
539  {
541  else
542  {
543  this->InitSpline();
544  mPowderPatternCalc=mvSpline((REAL)0,(REAL)1,nb);
545  }
546  break;
547  }
548  }
549  VFN_DEBUG_MESSAGE("PowderPatternBackground::CalcPowderPattern()",3);
550  #ifdef USE_BACKGROUND_MAXLIKE_ERROR
551  {
552  mPowderPatternCalcVariance.resize(nb);
553  const REAL step=mModelVariance*mModelVariance/(REAL)nbPoint;
554  REAL var=0;
555  REAL *p=mPowderPatternCalcVariance.data();
556  for(long i=0;i<nb;i++) {*p++ = var;var +=step;}
557  }
559  #endif
561  VFN_DEBUG_MESSAGE("PowderPatternBackground::CalcPowderPattern():End",3);
562 }
563 
564 void PowderPatternBackground::CalcPowderPattern_FullDeriv(std::set<RefinablePar*> &vPar)
565 {
566  TAU_PROFILE("PowderPatternBackground::CalcPowderPattern_FullDeriv()","void ()",TAU_DEFAULT);
567  const unsigned long nb=mpParentPowderPattern->GetNbPoint();
568  mPowderPattern_FullDeriv.clear();
569  if((nb==0)||(mBackgroundNbPoint==0)) return;
570  for(std::set<RefinablePar*>::iterator par=vPar.begin();par!=vPar.end();++par)
571  {
572  if((*par)==0) mPowderPattern_FullDeriv[*par]=this->GetPowderPatternCalc();
573  else
574  for(int j = 0; j < mBackgroundNbPoint; j++)
575  {
576  if((*par)->GetPointer()!=mBackgroundInterpPointIntensity.data()+j) continue;
577  const REAL step=(*par)->GetDerivStep();
578  (*par)->Mutate(step);
579  mPowderPattern_FullDeriv[*par] =this->GetPowderPatternCalc();
580  (*par)->Mutate(-2*step);
581  mPowderPattern_FullDeriv[*par]-=this->GetPowderPatternCalc();
582  (*par)->Mutate(step);
583  mPowderPattern_FullDeriv[*par]/= step*2;
584  if(MaxAbs(mPowderPattern_FullDeriv[*par])==0)
585  mPowderPattern_FullDeriv[*par].resize(0);
586  }
587  }
588 }
589 
590 void PowderPatternBackground::CalcPowderPatternIntegrated() const
591 {
593 
594  this->CalcPowderPattern();// :TODO: Optimize
597  return;
598 
599  VFN_DEBUG_ENTRY("PowderPatternBackground::CalcPowderPatternIntegrated()",3)
600  TAU_PROFILE("PowderPatternBackground::CalcPowderPatternIntegrated()","void ()",TAU_DEFAULT);
601  const CrystVector_long *pMin=&(mpParentPowderPattern->GetIntegratedProfileMin());
602  const CrystVector_long *pMax=&(mpParentPowderPattern->GetIntegratedProfileMax());
603 
604  const long numInterval=pMin->numElements();
605  mPowderPatternIntegratedCalc.resize(numInterval);
606  REAL * RESTRICT p2=mPowderPatternIntegratedCalc.data();
607  for(int j=0;j<numInterval;j++)
608  {
609  const long max=(*pMax)(j);
610  const REAL * RESTRICT p1=mPowderPatternCalc.data()+(*pMin)(j);
611  *p2=0;
612  for(int k=(*pMin)(j);k<=max;k++) *p2 += *p1++;
613  p2++;
614  }
615  #ifdef USE_BACKGROUND_MAXLIKE_ERROR
616  mPowderPatternIntegratedCalcVariance.resize(numInterval);
618  for(int j=0;j<numInterval;j++)
619  {
620  const long max=(*pMax)(j);
621  const REAL *p1=mPowderPatternCalcVariance.data()+(*pMin)(j);
622  *p2=0;
623  for(int k=(*pMin)(j);k<=max;k++) *p2 += *p1++;
624  p2++;
625  }
627  #endif
629  VFN_DEBUG_EXIT("PowderPatternBackground::CalcPowderPatternIntegrated()",3)
630 }
631 
633 {
634  TAU_PROFILE("PowderPatternBackground::CalcPowderPatternIntegrated_FullDeriv()","void ()",TAU_DEFAULT);
635  //cout<<"PowderPatternBackground::CalcPowderPatternIntegrated_FullDeriv"<<endl;
636  const unsigned long nb=mpParentPowderPattern->GetNbPoint();
637  mPowderPatternIntegrated_FullDeriv.clear();
638  if((nb==0)||(mBackgroundNbPoint==0)) return;
639  for(std::set<RefinablePar*>::iterator par=vPar.begin();par!=vPar.end();++par)
640  {
641  if((*par)==0) mPowderPattern_FullDeriv[*par]=this->GetPowderPatternCalc();
642  else
643  for(int j = 0; j < mBackgroundNbPoint; j++)
644  {
645  if((*par)->GetPointer()!=mBackgroundInterpPointIntensity.data()+j) continue;
646  const REAL step=(*par)->GetDerivStep();
647  (*par)->Mutate(step);
648  mPowderPatternIntegrated_FullDeriv[*par] =*(this->GetPowderPatternIntegratedCalc().first);
649  (*par)->Mutate(-2*step);
650  mPowderPatternIntegrated_FullDeriv[*par]-=*(this->GetPowderPatternIntegratedCalc().first);
651  (*par)->Mutate(step);
652  mPowderPatternIntegrated_FullDeriv[*par]/= step*2;
653  if(MaxAbs(mPowderPatternIntegrated_FullDeriv[*par])==0)
654  mPowderPatternIntegrated_FullDeriv[*par].resize(0);
655  }
656  }
657  #if 0
658  std::map<RefinablePar*, CrystVector_REAL> newDeriv=mPowderPatternIntegrated_FullDeriv;
660  std::vector<const CrystVector_REAL*> v;
661  int n=0;
662  for(std::map<RefinablePar*, CrystVector_REAL>::reverse_iterator pos=mPowderPatternIntegrated_FullDeriv.rbegin();pos!=mPowderPatternIntegrated_FullDeriv.rend();++pos)
663  {
664  cout<<pos->first->GetName()<<":"<<pos->second.size()<<","<<newDeriv[pos->first].size()<<endl;
665  if(pos->second.size()==0) continue;
666  v.push_back(&(pos->second));
667  v.push_back(&(newDeriv[pos->first]));
668  if(++n>8) break;
669  }
670  if(v.size()>0) cout<<"PowderPatternBackground::CalcPowderPatternIntegrated_FullDeriv():"<<endl<<FormatVertVector<REAL>(v,12,1,20)<<endl;
671  //exit(0);
672  #endif
673 }
674 
676 {
677 }
678 const CrystVector_long& PowderPatternBackground::GetBraggLimits()const
679 {
680  // no integration interval for the background
681  mIntegratedReflLimits.resize(0);
682  return mIntegratedReflLimits;
683 }
684 
686 {
689 }
690 
691 void PowderPatternBackground::InitRefParList()
692 {
693  this->ResetParList();
694  REAL *p=mBackgroundInterpPointIntensity.data();
695  char buf [10];
696  string str="Background_Point_";
697  //for(int i=0;i<3;i++)
698  for(int i=0;i<mBackgroundNbPoint;i++)
699  {
700  sprintf(buf,"%d",i);
701  RefinablePar tmp(str+(string)buf,p++,
702  0.,1000.,gpRefParTypeScattDataBackground,REFPAR_DERIV_STEP_RELATIVE,
703  false,true,true,false,1.);
704  tmp.SetGlobalOptimStep(10.);
705  tmp.AssignClock(mClockBackgroundPoint);
706  tmp.SetDerivStep(1e-3);
707  this->AddPar(tmp);
708  }
709  #ifdef USE_BACKGROUND_MAXLIKE_ERROR
710  {
711  RefinablePar tmp("ML Model Error",&mModelVariance,
712  0.,100000.,gpRefParTypeObjCryst,REFPAR_DERIV_STEP_RELATIVE,
713  true,true,true,false,1.);
714  tmp.AssignClock(mClockBackgroundPoint);
715  tmp.SetDerivStep(1e-3);
716  //tmp.SetGlobalOptimStep(10.);
717  tmp.SetGlobalOptimStep(sqrt(mBackgroundInterpPointIntensity.sum()
718  /mBackgroundInterpPointIntensity.numElements()));
719  this->AddPar(tmp);
720  }
721  #endif
722 }
723 
724 void PowderPatternBackground::InitOptions()
725 {
726  VFN_DEBUG_MESSAGE("PowderPatternBackground::InitOptions()",5)
727  static string InterpolationModelName;
728  static string InterpolationModelChoices[2];
729 
730  static bool needInitNames=true;
731  if(true==needInitNames)
732  {
733  InterpolationModelName="Interpolation Model";
734  InterpolationModelChoices[0]="Linear";
735  InterpolationModelChoices[1]="Spline";
736  //InterpolationModelChoices[2]="Chebyshev";
737 
738  needInitNames=false;//Only once for the class
739  }
740  mInterpolationModel.Init(2,&InterpolationModelName,InterpolationModelChoices);
743  mInterpolationModel.SetChoice(1);
744 }
745 
746 void PowderPatternBackground::InitSpline()const
747 {
750  &&(mClockSpline>this->GetParentPowderPattern().GetRadiation().GetClockWavelength())) return;
751 
753 
754  // The points must be in ascending order
755  // Take care later of neutron TOF, as the powder apttern data may not have been initialized yet.
756  CrystVector<long> subs;
757  subs=SortSubs(mBackgroundInterpPointX);
758 
759  if(this->GetParentPowderPattern().GetRadiation().GetWavelengthType()==WAVELENGTH_TOF)
760  {
762  for(long i=0;i<mBackgroundNbPoint;++i)
763  mPointOrder(i)=subs(mBackgroundNbPoint-1-i);
764  }
765  else mPointOrder=subs;
766 
767  CrystVector_REAL ipixel(mBackgroundNbPoint);
768 
769  for(long i=0;i<mBackgroundNbPoint;++i)
770  {
771  mvSplinePixel(i)=
774  }
775 
776  mvSpline.Init(mvSplinePixel,ipixel);
778 }
779 
780 #ifdef __WX__CRYST__
781 WXCrystObjBasic* PowderPatternBackground::WXCreate(wxWindow* parent)
782 {
783  //:TODO: Check mpWXCrystObj==0
784  mpWXCrystObj=new WXPowderPatternBackground(parent,this);
785  return mpWXCrystObj;
786 }
787 #endif
789 //
790 // PowderPatternDiffraction
791 //
793 PowderPatternDiffraction::PowderPatternDiffraction():
794 mpReflectionProfile(0),
795 mCorrLorentz(*this),mCorrPolar(*this),mCorrSlitAperture(*this),
796 mCorrTextureMarchDollase(*this),mCorrTextureEllipsoid(*this),mCorrTOF(*this),mCorrCylAbs(*this),mExtractionMode(false),
797 mpLeBailData(0),mFrozenLatticePar(6),mFreezeLatticePar(false),mFrozenBMatrix(3,3),mGenHKLBMatrix(3,3)
798 {
799  VFN_DEBUG_MESSAGE("PowderPatternDiffraction::PowderPatternDiffraction()",10)
800  mIsScalable=true;
801  this->InitOptions();
802  this->SetProfile(new ReflectionProfilePseudoVoigt);
803  this->SetIsIgnoringImagScattFact(true);
804  this->AddSubRefObj(mCorrTextureMarchDollase);
805  this->AddSubRefObj(mCorrTextureEllipsoid);
806  mClockMaster.AddChild(mClockProfilePar);
807  mClockMaster.AddChild(mClockLorentzPolarSlitCorrPar);
808  mClockMaster.AddChild(mpReflectionProfile->GetClockMaster());
809  for(unsigned int i=0;i<3;++i) mFrozenLatticePar(i)=5;
810  for(unsigned int i=3;i<6;++i) mFrozenLatticePar(i)=M_PI/2;
811  mGenHKLBMatrix=0;
812 }
813 
814 PowderPatternDiffraction::PowderPatternDiffraction(const PowderPatternDiffraction &old):
815 mpReflectionProfile(0),
816 mCorrLorentz(*this),mCorrPolar(*this),mCorrSlitAperture(*this),
817 mCorrTextureMarchDollase(*this),mCorrTextureEllipsoid(*this),mCorrTOF(*this),mCorrCylAbs(*this),mExtractionMode(false),
818 mpLeBailData(0),mFrozenLatticePar(6),mFreezeLatticePar(old.FreezeLatticePar()),mFrozenBMatrix(3,3),mGenHKLBMatrix(3,3)
819 {
820  this->AddSubRefObj(mCorrTextureMarchDollase);
821  this->AddSubRefObj(mCorrTextureEllipsoid);
822  this->SetIsIgnoringImagScattFact(true);
823  this->SetProfile(old.mpReflectionProfile->CreateCopy());
824  #if 0 //:TODO:
825  if(old.mpLeBailData!=0)
826  {
827  mpLeBailData=new DiffractionDataSingleCrystal(false);
828  *mpLeBailData = *(old.mpLeBailData);
829  }
830  #endif
831  mClockMaster.AddChild(mClockProfilePar);
832  mClockMaster.AddChild(mClockLorentzPolarSlitCorrPar);
833  mClockMaster.AddChild(mpReflectionProfile->GetClockMaster());
834  for(unsigned int i=0;i<6;++i) mFrozenLatticePar(i)=old.GetFrozenLatticePar(i);
835  mGenHKLBMatrix=0;
836 }
837 
838 PowderPatternDiffraction::~PowderPatternDiffraction()
839 {
840  if(mpReflectionProfile!=0)
841  {
842  this->RemoveSubRefObj(*mpReflectionProfile);
843  delete mpReflectionProfile;
844  }
845 }
847 {
848  const static string className="PowderPatternDiffraction";
849  return className;
850 }
851 
853 {
854  return new PowderPatternDiffraction(*this);
855 }
856 
858 {
859  if(mpParentPowderPattern!=0)
867 }
868 
870 {
871  this->CalcPowderPattern();
872  return mPowderPatternCalc;
873 }
874 
875 pair<const CrystVector_REAL*,const RefinableObjClock*>
877 {
878  this->CalcPowderPatternIntegrated();
880 }
881 
883  const REAL w, const REAL u, const REAL v,
884  const REAL eta0, const REAL eta1)
885 {
886  VFN_DEBUG_MESSAGE("PowderPatternDiffraction::SetReflectionProfilePar()",5)
888  p->SetProfilePar(w,u,v,eta0,eta1);
889  this->SetProfile(p);
890 }
891 
893 {
894  if(p==mpReflectionProfile) return;
895  if(mpReflectionProfile!=0)
896  {
897  this->RemoveSubRefObj(*mpReflectionProfile);
898  delete mpReflectionProfile;
899  }
900  mpReflectionProfile= p;
901  this->AddSubRefObj(*mpReflectionProfile);
902  mClockMaster.AddChild(mpReflectionProfile->GetClockMaster());
903 }
904 
906 {
907  return *mpReflectionProfile;
908 }
909 
911 {
912  return *mpReflectionProfile;
913 }
914 
915 // Disable the base-class function.
916 void PowderPatternDiffraction::GenHKLFullSpace(
917  const REAL maxTheta, const bool useMultiplicity) const
918 {
919  // This should be never called.
920  abort();
921 }
922 
923 void PowderPatternDiffraction::GenHKLFullSpace()const
924 {
925  VFN_DEBUG_ENTRY("PowderPatternDiffraction::GenHKLFullSpace():",5)
926  float stol;
927  if(this->GetRadiation().GetWavelengthType()==WAVELENGTH_TOF)
928  stol=mpParentPowderPattern->X2STOL(mpParentPowderPattern->GetPowderPatternXMin());
929  else
930  stol=mpParentPowderPattern->X2STOL(mpParentPowderPattern->GetPowderPatternXMax());
931  if(stol>2) stol=2; // Do not go beyond 0.25 A resolution (mostly for TOF data)
932  this->ScatteringData::GenHKLFullSpace2(stol,true);
933  if((mExtractionMode) && (mFhklObsSq.numElements()!=this->GetNbRefl()))
934  {// Reflections changed, so ScatteringData::PrepareHKLarrays() probably reseted mFhklObsSq
935  VFN_DEBUG_ENTRY("PowderPatternDiffraction::GenHKLFullSpace(): need to resize observed intensities",7)
936  const int n0 = mFhklObsSq.numElements();
937  mFhklObsSq.resizeAndPreserve(this->GetNbRefl());
938  for(int i=n0;i<this->GetNbRefl();i++) mFhklObsSq(i)=100;
939  }
940  // Save the used Bmatrix
941  mGenHKLBMatrix = this->GetBMatrix();
942  VFN_DEBUG_EXIT("PowderPatternDiffraction::GenHKLFullSpace():"<<this->GetNbRefl(),5)
943 }
944 void PowderPatternDiffraction::BeginOptimization(const bool allowApproximations,
945  const bool enableRestraints)
946 {
947  if(mUseFastLessPreciseFunc!=allowApproximations)
948  {
949  mClockProfileCalc.Reset();
950  mClockGeomStructFact.Reset();
951  mClockStructFactor.Reset();
953  }
954  mUseFastLessPreciseFunc=allowApproximations;
955  this->GetNbReflBelowMaxSinThetaOvLambda();
956  this->RefinableObj::BeginOptimization(allowApproximations,enableRestraints);
957 }
959 {
960  if(mOptimizationDepth==1)
961  {
962  if(mUseFastLessPreciseFunc==true)
963  {
964  mClockProfileCalc.Reset();
965  mClockGeomStructFact.Reset();
966  mClockStructFactor.Reset();
968  }
969  mUseFastLessPreciseFunc=false;
970  this->GetNbReflBelowMaxSinThetaOvLambda();
971  }
973 }
974 
976 {
977  if(mUseFastLessPreciseFunc!=allow)
978  {
979  mClockProfileCalc.Reset();
980  mClockGeomStructFact.Reset();
981  mClockStructFactor.Reset();
983  }
984  mUseFastLessPreciseFunc=allow;
985  this->GetNbReflBelowMaxSinThetaOvLambda();
987 }
988 
990  CrystVector_uint & groupIndex,
991  unsigned int &first) const
992 {
993  // One group for all profile parameters
994  unsigned int index=0;
995  VFN_DEBUG_MESSAGE("PowderPatternDiffraction::GetGeneGroup()",4)
996  for(long i=0;i<obj.GetNbPar();i++)
997  for(long j=0;j<this->GetNbPar();j++)
998  if(&(obj.GetPar(i)) == &(this->GetPar(j)))
999  {
1000  //if(this->GetPar(j).GetType()->IsDescendantFromOrSameAs())
1001  //{
1002  if(index==0) index=first++;
1003  groupIndex(i)=index;
1004  //}
1005  //else //no parameters other than unit cell
1006  }
1007 }
1008 
1010 {
1011 
1013 }
1014 
1015 pair<const CrystVector_REAL*,const RefinableObjClock*>
1017 {
1018  this->CalcPowderPatternIntegrated();
1019  return make_pair(&mPowderPatternIntegratedCalcVariance,
1021 }
1022 
1024 {
1025  return true;
1026 }
1027 
1029 {
1030  bool reprep=(mpCrystal!=0);
1031  this->ScatteringData::SetCrystal(crystal);
1032  // Check if we use DE-PV
1033  if(mpReflectionProfile!=0)
1034  if(mpReflectionProfile->GetClassName()=="ReflectionProfileDoubleExponentialPseudoVoigt")
1035  {
1037  =dynamic_cast<ReflectionProfileDoubleExponentialPseudoVoigt*>(mpReflectionProfile);
1038  p->SetUnitCell((UnitCell)crystal);
1039  }
1040  mClockHKL.Reset();
1041  if(reprep) this->Prepare();
1042 }
1043 
1045 { return mpParentPowderPattern->GetRadiation();}
1046 
1047 void PowderPatternDiffraction::SetExtractionMode(const bool extract,const bool init)
1048 {
1049  VFN_DEBUG_ENTRY("PowderPatternDiffraction::SetExtractionMode(),ExtractionMode="<<mExtractionMode<<", nbrefl="<<this->GetNbRefl(),7)
1050  mExtractionMode=extract;
1051  bool needInit=false;
1052  if(extract)
1053  {
1054  this->FreezeLatticePar(false);
1055  this->Prepare();
1056  mFhklObsSq.resizeAndPreserve(this->GetNbRefl());
1057  }
1058  if(extract && (!init) && (mpLeBailData!=0))
1059  {
1060  // Re-use existing Le Bail data, if list of hkl's is consistent
1061  const long nbrefl=this->GetNbReflBelowMaxSinThetaOvLambda();
1062  if(nbrefl==mpLeBailData->GetNbRefl())
1063  {
1064  for(int i=0;i<nbrefl;++i)
1065  {
1066  if( (mpLeBailData->GetH()(i)==this->GetH()(i))
1067  &&(mpLeBailData->GetK()(i)==this->GetK()(i))
1068  &&(mpLeBailData->GetL()(i)==this->GetL()(i)))
1069  {
1070  mFhklObsSq(i)=mpLeBailData->GetFhklObsSq()(i);
1071  }
1072  else
1073  {
1074  needInit=true;
1075  VFN_DEBUG_MESSAGE("PowderPatternDiffraction::SetExtractionMode():: Forcing initialize, cannot re-use: hkl list differs",10);
1076  break;
1077  }
1078 
1079  }
1080  }
1081  else
1082  {
1083  needInit=true;
1084  VFN_DEBUG_MESSAGE("PowderPatternDiffraction::SetExtractionMode():: Forcing initialize, cannot re-use: different number of reflections",10);
1085  }
1086  }
1087  if((extract && init) || needInit)
1088  {
1089  VFN_DEBUG_MESSAGE("PowderPatternDiffraction::SetExtractionMode():: Initializing intensities to 100",10);
1090  mFhklObsSq=100;
1091  }
1092  if((mExtractionMode==false)&&(mFhklObsSq.numElements()>0))
1093  {// Leaving extraction mode, so update extracted single crystal data
1094  VFN_DEBUG_ENTRY("PowderPatternDiffraction::SetExtractionMode(),LEAVING Le Bail Mode",7)
1095  if(mpLeBailData==0) mpLeBailData=new DiffractionDataSingleCrystal(this->GetCrystal(),false);
1096  // Update wavelength & name
1097  mpLeBailData->SetWavelength(this->GetRadiation().GetWavelength()(0));
1098  mpLeBailData->SetRadiationType(this->GetRadiation().GetRadiationType());
1099  char buf[200];
1100  sprintf(buf,"LeBail (d=%4.2fA):",1/(2*abs(mMaxSinThetaOvLambda)+1e-6));
1101  mpLeBailData->SetName(string(buf)+this->GetCrystal().GetName());
1102 
1103  const unsigned long nbrefl=this->GetNbReflBelowMaxSinThetaOvLambda();
1104  CrystVector_REAL iobs(nbrefl),sigma(nbrefl);
1105  CrystVector_long h(nbrefl),k(nbrefl),l(nbrefl);
1106  sigma=1;
1107  for(unsigned long i=0;i<nbrefl;++i)
1108  {
1109  h(i)=mIntH(i);
1110  k(i)=mIntK(i);
1111  l(i)=mIntL(i);
1112  iobs(i)=mFhklObsSq(i);
1113  }
1114  mpLeBailData->SetHklIobs(h,k,l,iobs,sigma);
1115  // Erase mFhklObsSq - only used during extraction mode.
1116  mFhklObsSq.resize(0);
1117  }
1118  mClockIhklCalc.Reset();mClockMaster.Reset();
1119  mClockFhklObsSq.Click();
1120  VFN_DEBUG_EXIT("PowderPatternDiffraction::SetExtractionMode(),ExtractionMode="<<mExtractionMode<<", nbrefl="<<this->GetNbRefl(),7)
1121 }
1122 
1123 bool PowderPatternDiffraction::GetExtractionMode()const{return mExtractionMode;}
1124 
1126 {
1127  VFN_DEBUG_ENTRY("PowderPatternDiffraction::ExtractLeBail()",7)
1128  TAU_PROFILE("PowderPatternDiffraction::ExtractLeBail()","void (int)",TAU_DEFAULT);
1129 
1130  if(mExtractionMode==false) this->SetExtractionMode(true,true);// Should not have to do this here !
1131  if(mFhklObsSq.numElements()!=this->GetNbRefl())
1132  {//Something went wrong !
1133  VFN_DEBUG_ENTRY("PowderPatternDiffraction::ExtractLeBail() mFhklObsSq.size() != NbRefl !!!!!!",7)
1134  mFhklObsSq.resize(this->GetNbRefl());
1135  mFhklObsSq=100;
1136  }
1137  // First get the observed powder pattern, minus the contribution of all other phases.
1138  CrystVector_REAL obs,iextract,calc;
1139  iextract=mFhklObsSq;
1140  mFhklObsSq=0;
1141  mClockFhklObsSq.Click();
1142  // Get the observed and calculated powder pattern (excluding this diffraction phase)
1145  mFhklObsSq=iextract;
1146  mClockFhklObsSq.Click();
1147  // We take here the reflections which are centered below the max(sin(theta)/lambda)
1148  // actually more reflections are calculated, but the pattern is only calculated up to
1149  // max(sin(theta)/lambda).
1150  const unsigned long nbrefl=this->ScatteringData::GetNbReflBelowMaxSinThetaOvLambda();
1151  iextract=0;
1152  for(;nbcycle>0;nbcycle--)
1153  {
1154  //cout<<"PowderPatternDiffraction::ExtractLeBail(): cycle #"<<nbcycle<<endl;
1155  calc=this->GetPowderPatternCalc();
1156  for(unsigned int k0=0;k0<nbrefl;++k0)
1157  {
1158  if(mvReflProfile[k0].profile.numElements()==0) continue; // May happen for reflections near limits ?
1159  REAL s1=0;
1160  //cout<<mH(k0)<<" "<<mK(k0)<<" "<<mL(k0)<<" , Iobs=??"<<endl;
1161  long last=mvReflProfile[k0].last,first;
1163  if(mvReflProfile[k0].first<0)first=0;
1164  else first=(mvReflProfile[k0].first);
1165  const REAL *p1=mvReflProfile[k0].profile.data()+(first-mvReflProfile[k0].first);
1166  const REAL *p2=calc.data()+first;
1167  const REAL *pobs=obs.data()+first;
1168  for(long i=first;i<=last;++i)
1169  {
1170  const REAL s2=*p2++;
1171  const REAL tmp=*pobs++ * *p1++;
1172  if( (s2<1e-8) ) // || (tmp<=0)
1173  {// Avoid <0 intensities (should not happen, it means profile is <0)
1174  //cout<<"S2? "<< int(mH(k0))<<" "<<int(mK(k0))<<" "<<int(mL(k0)) <<" calc(i="<<i<<")"<<calc(i)<<" obs(i="<<i<<")="<<obs(i)<<", tmp="<<tmp<<" profile(i)="<<mvReflProfile[k0].profile(i-mvReflProfile[k0].first)<<" "<<mFhklObsSq(k0)<<endl;
1175  continue ;
1176  }
1177  s1 += tmp /s2;
1178  //cout<<" "<<s2<<" "<<obs(i)<<" "<<mvReflProfile[k0].profile(i-mvReflProfile[k0].first)<<" "<<mFhklObsSq(k0)<<endl;
1179  }
1180  if((s1>1e-8)&&(!ISNAN_OR_INF(s1))) iextract(k0)=s1*mFhklObsSq(k0);
1181  else iextract(k0)=1e-8;//:KLUDGE: should <0 intensities be allowed ?
1182  //if(nbcycle==1) cout<<" Le Bail "<<int(mH(k0))<<" "<<int(mK(k0))<<" "<<int(mL(k0))<<" , Iobs="<<iextract(k0)<<endl;
1183  }
1184  mFhklObsSq=iextract;
1185  if(this->GetCrystal().GetScatteringComponentList().GetNbComponent()>0)
1186  {// Change scale factor if we have some atoms in the structure
1187  const REAL* p1=this->GetFhklCalcSq() .data();
1188  const REAL* p2=mFhklObsSq.data();
1189  REAL tmp1=0,tmp2=0;
1190  for(long i=nbrefl;i>0;i--)
1191  {
1192  tmp1 += (*p1) * (*p2++);
1193  tmp2 += (*p1) * (*p1);
1194  p1++;
1195  }
1196  //cout<<"SCALING: tmp2="<<tmp2<<",tmp1="<<tmp1<<endl;
1197  mFhklObsSq*=tmp2/tmp1;
1198  }
1199  mClockFhklObsSq.Click();
1200  //cout<<"PowderPatternDiffraction::ExtractLeBail():results (scale factor="<<mpParentPowderPattern->GetScaleFactor(*this)*1e6<<")" <<endl<< FormatVertVectorHKLFloats<REAL>(mH,mK,mL,this->GetFhklCalcSq(),mFhklObsSq,10,4,nbrefl)<<endl;
1201  mClockIhklCalc.Reset(); // During Le Bail
1202  }
1203  // Store extracted data in a single crystal data object
1204  if(mpLeBailData==0) mpLeBailData=new DiffractionDataSingleCrystal(*mpCrystal,false);
1205  {
1206  VFN_DEBUG_MESSAGE("PowderPatternDiffraction::ExtractLeBail(): creating single crystal extracted data",7)
1207  CrystVector_REAL iobs(nbrefl),sigma(nbrefl);
1208  CrystVector_long h(nbrefl),k(nbrefl),l(nbrefl);
1209  sigma=1;
1210  for(unsigned long i=0;i<nbrefl;++i)
1211  {
1212  h(i)=mIntH(i);
1213  k(i)=mIntK(i);
1214  l(i)=mIntL(i);
1215  iobs(i)=mFhklObsSq(i);
1216  }
1217  mpLeBailData->SetHklIobs(h,k,l,iobs,sigma);
1218  }
1219  VFN_DEBUG_EXIT("PowderPatternDiffraction::ExtractLeBail()mFhklObsSq.size()=="<<mFhklObsSq.numElements(),7)
1220 }
1222 {
1223  if(this->IsBeingRefined()) return mNbReflUsed;
1224  VFN_DEBUG_MESSAGE("PowderPatternDiffraction::GetNbReflBelowMaxSinThetaOvLambda(): "<<mNbReflUsed<<"/"<<mNbRefl<<" [max sin(theta)/lambda="<<mMaxSinThetaOvLambda<<"]",4)
1225  this->CalcPowderReflProfile();
1226  const long nbpoint=mpParentPowderPattern->GetNbPointUsed();
1227  if((mNbReflUsed>0)&&(mNbReflUsed<mNbRefl))
1228  {
1229  if( (mvReflProfile[mNbReflUsed ].first>nbpoint)
1230  &&(mvReflProfile[mNbReflUsed-1].first<=nbpoint)) return mNbReflUsed;
1231  }
1232 
1233  if((mNbReflUsed==mNbRefl) && (mvReflProfile[mNbReflUsed-1].profile.numElements()>0))
1234  if(mvReflProfile[mNbReflUsed-1].first<=nbpoint)return mNbReflUsed;
1235 
1236 
1237  long i;
1238  for(i=0;i<mNbRefl;i++)
1239  {
1240  if(mvReflProfile[i].first>nbpoint) break;
1241  }
1242  if(i!=mNbReflUsed)
1243  {
1244  mNbReflUsed=i;
1245  mClockNbReflUsed.Click();
1246  VFN_DEBUG_MESSAGE("->Changed Max sin(theta)/lambda="<<mMaxSinThetaOvLambda\
1247  <<" nb refl="<<mNbReflUsed,4)
1248  }
1249  return mNbReflUsed;
1250 }
1251 
1252 void PowderPatternDiffraction::SetFrozenLatticePar(const unsigned int i, REAL v)
1253 {
1254  const REAL old=mFrozenLatticePar(i);
1255  cout<<"PowderPatternDiffraction::SetFrozenLatticePar("<<i<<":"<<v<<")"<<endl;
1256  if(old==v) return;
1257  mFrozenLatticePar(i)=v;
1258  this->CalcFrozenBMatrix();
1259 }
1260 
1261 REAL PowderPatternDiffraction::GetFrozenLatticePar(const unsigned int i) const {return mFrozenLatticePar(i);}
1262 
1264 {
1265  VFN_DEBUG_MESSAGE("PowderPatternDiffraction::FreezeLatticePar("<<use<<")", 10)
1266  if(use==mFreezeLatticePar) return;
1267  mFreezeLatticePar=use;
1268  mFrozenLatticePar=this->GetCrystal().GetLatticePar();
1269  if(use) this->CalcFrozenBMatrix();
1270  mClockTheta.Reset();
1271  this->UpdateDisplay();
1272 }
1273 
1274 bool PowderPatternDiffraction::FreezeLatticePar() const {return mFreezeLatticePar;}
1275 
1277 {
1278  unsigned int nb=0;
1279  unsigned int irefl=0;
1280  unsigned int ilast=0;
1281  while(this->GetParentPowderPattern().STOL2Pixel(mSinThetaLambda(irefl))<0)
1282  {
1283  irefl++;
1284  if(irefl>=this->GetNbReflBelowMaxSinThetaOvLambda()) break;
1285  }
1286  while(irefl<this->GetNbReflBelowMaxSinThetaOvLambda())
1287  {
1288  const REAL stol = mSinThetaLambda(irefl);
1289  while(mSinThetaLambda(irefl)==stol)
1290  {
1291  //cout<<int(mH(irefl))<<" "<<int(mK(irefl))<<" "<<int(mL(irefl))<<endl;
1292  irefl++;
1293  if(irefl>=this->GetNbReflBelowMaxSinThetaOvLambda()) break;
1294  }
1295  const int nbnew =this->GetParentPowderPattern().STOL2Pixel(stol)-ilast;
1296  if(nbnew>1) nb += nbnew-1;
1297  //cout<<" => Added "<< nbnew-1<< "net observed points ("<<this->GetParentPowderPattern().STOL2Pixel(stol)<<"-"<<ilast<<")"<<endl;
1298  ilast=this->GetParentPowderPattern().STOL2Pixel(stol);
1299  }
1300  //cout<<"Final number of net observed points: "<<nb<<endl;
1301  return nb;
1302 }
1303 
1305 {
1306  if(mpLeBailData==NULL) return false;
1307  return mpLeBailData->GetFhklObsSq().size() > 0;
1308 }
1309 
1310 const CrystVector_REAL& PowderPatternDiffraction::GetFhklObsSq() const
1311 {
1312  if(mpLeBailData==NULL)
1313  throw ObjCrystException("PowderPatternDiffraction::GetFhklObsSq(): no extracted intensities available");
1314  return mpLeBailData->GetFhklObsSq();
1315 }
1316 
1318 {
1319  this->GetNbReflBelowMaxSinThetaOvLambda();
1321  TAU_PROFILE("PowderPatternDiffraction::CalcPowderPattern()-Apply profiles","void (bool)",TAU_DEFAULT);
1322 
1323  VFN_DEBUG_ENTRY("PowderPatternDiffraction::CalcPowderPattern():",3)
1324 
1325  if(this->GetCrystal().GetSpaceGroup().GetClockSpaceGroup()>mClockHKL)
1326  {
1327  VFN_DEBUG_MESSAGE("PowderPatternDiffraction::CalcPowderPattern():"
1328  "spacegroup has changed, re-generating HKL's",5)
1329  this->GenHKLFullSpace();
1330  }
1331  else if((!this->IsBeingRefined()) && (this->GetCrystal().GetClockLatticePar()>mClockHKL))
1332  {
1333  // Check if the B matrix changed significantly and requires regenerating the HKL's
1334  // This is never done during optimisation
1335 
1336  //mBMatrix = aa , bb*cos(gammaa) , cc*cos(betaa) ,
1337  // 0 , bb*sin(gammaa) ,-cc*sin(betaa)*cos(alpha),
1338  // 0 , 0 ,1/c;
1339  bool needgen=false;
1340  const REAL r = 0.005; // Tolerate 0.5% difference
1341  if(abs(this->GetBMatrix()(0)-mGenHKLBMatrix(0))>(r*this->GetBMatrix()(0))) needgen=true;
1342  else if(abs(this->GetBMatrix()(4)-mGenHKLBMatrix(4))>(r*this->GetBMatrix()(4))) needgen=true;
1343  else if(abs(this->GetBMatrix()(1)-mGenHKLBMatrix(1))>(r*this->GetBMatrix()(4))) needgen=true;
1344  else if(abs(this->GetBMatrix()(8)-mGenHKLBMatrix(8))>(r*this->GetBMatrix()(8))) needgen=true;
1345  else if(abs(this->GetBMatrix()(2)-mGenHKLBMatrix(2))>(r*this->GetBMatrix()(8))) needgen=true;
1346  else if(abs(this->GetBMatrix()(5)-mGenHKLBMatrix(5))>(r*this->GetBMatrix()(8))) needgen=true;
1347  if(needgen)
1348  {
1349  VFN_DEBUG_MESSAGE("PowderPatternDiffraction::CalcPowderPattern():"
1350  "lattice parameters have changed by more than 0.5%, re-generating HKL's",5)
1351  this->GenHKLFullSpace();
1352  }
1353  }
1354 
1355  this->CalcIhkl();
1356  this->CalcPowderReflProfile();
1357 
1358  if( (mClockPowderPatternCalc>mClockIhklCalc)
1359  &&(mClockPowderPatternCalc>mClockProfileCalc)) return;
1360 
1361  if(true) //:TODO: false == mUseFastLessPreciseFunc
1362  {
1363  const long nbRefl=this->GetNbRefl();
1364  VFN_DEBUG_MESSAGE("PowderPatternDiffraction::CalcPowderPattern\
1365 Applying profiles for "<<nbRefl<<" reflections",2)
1366  long step; // number of reflections at the same place and with the same (assumed) profile
1367  const long specNbPoints=mpParentPowderPattern->GetNbPoint();
1368  mPowderPatternCalc.resize(specNbPoints);
1370  const bool useML= (mIhklCalcVariance.numElements() != 0);
1371  if(useML)
1372  {
1373  mPowderPatternCalcVariance.resize(specNbPoints);
1375  }
1376  else mPowderPatternCalcVariance.resize(0);
1377  VFN_DEBUG_MESSAGE("PowderPatternDiffraction::CalcPowderPattern() Has variance:"<<useML,2)
1378 
1379  for(long i=0;i<mNbRefl;i += step)
1380  {
1381  if(mvReflProfile[i].profile.numElements()==0)
1382  {
1383  step=1;
1384  if(i>=mNbReflUsed) break;// After sin(theta)/lambda limit
1385  else continue; // before beginning of pattern ?
1386  }
1387 
1388  VFN_DEBUG_MESSAGE("PowderPatternDiffraction::CalcPowderPattern()#"<<i,2)
1389  REAL intensity=0.;
1390  REAL var=0.;
1391  //check if the next reflection is at the same theta. If this is true,
1392  //Then assume that the profile is exactly the same, unless it is anisotropic
1393  for(step=0; ;)
1394  {
1395  intensity += mIhklCalc(i + step);
1396  if(useML) var += mIhklCalcVariance(i + step);
1397  step++;
1398  if(mpReflectionProfile->IsAnisotropic()) break;// Anisotropic profiles
1399  if( (i+step) >= nbRefl) break;
1400  if(mSinThetaLambda(i+step) > (mSinThetaLambda(i)+1e-5) ) break;
1401  }
1402  VFN_DEBUG_MESSAGE("Apply profile(Monochromatic)Refl("<<i<<")"\
1403  <<mIntH(i)<<" "<<mIntK(i)<<" "<<mIntL(i)<<" "\
1404  <<" I="<<intensity<<" stol="<<mSinThetaLambda(i)\
1405  <<",pixel #"<<mvReflProfile[i].first<<"->"<<mvReflProfile[i].last,2)
1406  {
1407  const long first=mvReflProfile[i].first,last=mvReflProfile[i].last;
1408  const REAL *p2 = mvReflProfile[i].profile.data();
1409  REAL *p3 = mPowderPatternCalc.data()+first;
1410  for(long j=first;j<=last;j++) *p3++ += *p2++ * intensity;
1411  if(useML)
1412  {
1413  const REAL *p2 = mvReflProfile[i].profile.data();
1414  REAL *p3 = mPowderPatternCalcVariance.data()+first;
1415  for(long j=first;j<=last;j++) *p3++ += *p2++ * var;
1416  }
1417  }
1418  }
1419  }
1420  else
1421  {
1422  //:TODO:
1423  throw ObjCrystException("PowderPatternDiffraction::CalcPowderPattern() : \
1424  FAST option not yet implemented !");
1425  }
1427  VFN_DEBUG_EXIT("PowderPatternDiffraction::CalcPowderPattern: End.",3)
1428 }
1429 
1430 void PowderPatternDiffraction::CalcPowderPattern_FullDeriv(std::set<RefinablePar*> &vPar)
1431 {
1432  TAU_PROFILE("PowderPatternDiffraction::CalcPowderPattern_FullDeriv()","void ()",TAU_DEFAULT);
1433  //cout<<"PowderPatternDiffraction::CalcPowderPattern_FullDeriv"<<endl;
1434  this->CalcPowderPattern();
1435  bool notYetDerivProfiles=true;
1436  mIhkl_FullDeriv.clear();
1437  mvReflProfile_FullDeriv.clear();
1438  mPowderPattern_FullDeriv.clear();
1439  for(std::set<RefinablePar*>::iterator par=vPar.begin();par!=vPar.end();++par)
1440  {
1441  if(*par==0) continue;
1442  if((*par)->IsFixed()) continue;
1443  if((*par)->IsUsed()==false) continue;
1444  if( (*par)->GetType()->IsDescendantFromOrSameAs(gpRefParTypeScatt)
1445  ||(*par)->GetType()->IsDescendantFromOrSameAs(gpRefParTypeScattPow))
1446  {
1447  this->CalcIhkl_FullDeriv(vPar);
1448  }
1449  if(notYetDerivProfiles)
1450  {
1451  if( (*par)->GetType()->IsDescendantFromOrSameAs(gpRefParTypeRadiation)
1452  ||(*par)->GetType()->IsDescendantFromOrSameAs(gpRefParTypeUnitCell)
1453  ||(*par)->GetType()->IsDescendantFromOrSameAs(gpRefParTypeScattDataCorrPos)
1454  ||(*par)->GetType()->IsDescendantFromOrSameAs(gpRefParTypeScattDataProfile))
1455  {
1456  this->CalcPowderReflProfile_FullDeriv(vPar);
1457  notYetDerivProfiles=false;
1458  }
1459  }
1460  }
1461 
1462  //this->CalcPowderReflProfile();
1463  for(std::set<RefinablePar*>::iterator par=vPar.begin();par!=vPar.end();++par)
1464  {
1465  if(*par==0) mPowderPattern_FullDeriv[*par]=this->GetPowderPatternCalc();
1466  else
1467  {
1468  if((*par)->IsFixed()) continue;
1469  if((*par)->IsUsed()==false) continue;
1470  if(mIhkl_FullDeriv[*par].size()!=0)
1471  {
1472  const long nbRefl=this->GetNbRefl();
1473  long step; // number of reflections at the same place and with the same (assumed) profile
1474  const long specNbPoints=mpParentPowderPattern->GetNbPoint();
1475  mPowderPattern_FullDeriv[*par].resize(specNbPoints);
1476  mPowderPattern_FullDeriv[*par]=0;
1477 
1478  for(long i=0;i<mNbReflUsed;i += step)
1479  {
1480  if(mvReflProfile[i].profile.numElements()==0)
1481  {
1482  step=1;
1483  if(i>=mNbReflUsed) break;
1484  else continue;
1485  }
1486 
1487  REAL intensity=0.;
1488  //check if the next reflection is at the same theta. If this is true,
1489  //Then assume that the profile is exactly the same, unless it is anisotropic
1490  for(step=0; ;)
1491  {
1492  intensity += mIhkl_FullDeriv[*par](i + step);
1493  step++;
1494  if(mpReflectionProfile->IsAnisotropic()) break;// Anisotropic profiles
1495  if( (i+step) >= nbRefl) break;
1496  if(mSinThetaLambda(i+step) > (mSinThetaLambda(i)+1e-5) ) break;
1497  }
1498  {
1499  const long first=mvReflProfile[i].first,last=mvReflProfile[i].last;
1500  const REAL *p2 = mvReflProfile[i].profile.data();
1501  REAL *p3 = mPowderPattern_FullDeriv[*par].data()+first;
1502  for(long j=first;j<=last;j++) *p3++ += *p2++ * intensity;
1503  }
1504  }
1505  }
1506  if(mvReflProfile_FullDeriv[*par].size()!=0)
1507  {
1508  const long nbRefl=this->GetNbRefl();
1509  long step; // number of reflections at the same place and with the same (assumed) profile
1510  const long specNbPoints=mpParentPowderPattern->GetNbPoint();
1511  mPowderPattern_FullDeriv[*par].resize(specNbPoints);
1512  mPowderPattern_FullDeriv[*par]=0;// :TODO: use only the number of points actually used
1513  cout<<__FILE__<<":"<<__LINE__<<":PowderPatternDiffraction::CalcPowderPattern_FullDeriv():par="<<(*par)->GetName()<<endl;
1514  for(long i=0;i<mNbReflUsed;i += step)
1515  {
1516  if(mvReflProfile[i].profile.numElements()==0)
1517  {
1518  step=1;
1519  if(i>=mNbReflUsed) break;
1520  else continue;
1521  }
1522 
1523  REAL intensity=0.;
1524  //check if the next reflection is at the same theta. If this is true,
1525  //Then assume that the profile is exactly the same, unless it is anisotropic
1526  for(step=0; ;)
1527  {
1528  intensity += mIhklCalc(i + step);
1529  step++;
1530  if(mpReflectionProfile->IsAnisotropic()) break;// Anisotropic profiles
1531  if( (i+step) >= nbRefl) break;
1532  if(mSinThetaLambda(i+step) > (mSinThetaLambda(i)+1e-5) ) break;
1533  }
1534  if(mvReflProfile_FullDeriv[*par][i].size()>0)// Some profiles may be unaffected by a given parameter
1535  {
1536  const long first=mvReflProfile[i].first,last=mvReflProfile[i].last;
1537  const REAL *p2 = mvReflProfile_FullDeriv[*par][i].data();
1538  REAL *p3 = mPowderPattern_FullDeriv[*par].data()+first;
1539  for(long j=first;j<=last;j++) *p3++ += *p2++ * intensity;
1540  }
1541  }
1542  }
1543  }
1544  }
1545  #if 0
1546  std::map<RefinablePar*, CrystVector_REAL> newDeriv=mPowderPattern_FullDeriv;
1547  this->PowderPatternComponent::CalcPowderPattern_FullDeriv(vPar);
1548  std::vector<const CrystVector_REAL*> v;
1549  int n=0;
1550  for(std::map<RefinablePar*, CrystVector_REAL>::reverse_iterator pos=mPowderPattern_FullDeriv.rbegin();pos!=mPowderPattern_FullDeriv.rend();++pos)
1551  {
1552  if(pos->first==0) continue;
1553  if(pos->second.size()==0) continue;
1554  v.push_back(&(newDeriv[pos->first]));
1555  v.push_back(&(pos->second));
1556  cout<<pos->first->GetName()<<":"<<pos->second.size()<<","<<newDeriv[pos->first].size()<<endl;
1557  if(++n>8) break;
1558  }
1559  cout<<FormatVertVector<REAL>(v,16,4,1000)<<endl;
1560  //exit(0);
1561  #endif
1562 }
1563 
1564 void PowderPatternDiffraction::CalcPowderPatternIntegrated() const
1565 {
1566  this->GetNbReflBelowMaxSinThetaOvLambda();
1568  TAU_PROFILE("PowderPatternDiffraction::CalcPowderPatternIntegrated()","void (bool)",TAU_DEFAULT);
1569  TAU_PROFILE_TIMER(timer1,"PowderPatternDiffraction::CalcPowderPatternIntegrated()1","", TAU_FIELD);
1570  TAU_PROFILE_TIMER(timer2,"PowderPatternDiffraction::CalcPowderPatternIntegrated()2","", TAU_FIELD);
1571 
1572  this->CalcIhkl();
1573  TAU_PROFILE_START(timer1);
1574  this->PrepareIntegratedProfile();
1575  TAU_PROFILE_STOP(timer1);
1576 
1577  if( (mClockPowderPatternIntegratedCalc>mClockIhklCalc)
1578  &&(mClockPowderPatternIntegratedCalc>mClockIntegratedProfileFactor)
1580  return;
1581  VFN_DEBUG_ENTRY("PowderPatternDiffraction::CalcPowderPatternIntegrated()",3)
1582  const long nbRefl=this->GetNbRefl();
1583 
1584  const long nb=mpParentPowderPattern->GetIntegratedProfileMin().numElements();
1585  mPowderPatternIntegratedCalc.resize(nb);
1587  const bool useML= (mIhklCalcVariance.numElements() != 0);
1588  if(useML)
1589  {
1592  }
1593  else mPowderPatternIntegratedCalcVariance.resize(0);
1594  const REAL * RESTRICT psith=mSinThetaLambda.data();
1595  const REAL * RESTRICT pI=mIhklCalc.data();
1596  const REAL * RESTRICT pIvar=mIhklCalcVariance.data();
1597  vector< pair<unsigned long, CrystVector_REAL> >::const_iterator pos;
1598  pos=mIntegratedProfileFactor.begin();
1599  TAU_PROFILE_START(timer2);
1600  for(long i=0;i<mNbReflUsed;)
1601  {
1602  VFN_DEBUG_MESSAGE("PowderPatternDiffraction::CalcPowderPatternIntegrated():"<<i,2)
1603  REAL intensity=0.;
1604  REAL var=0.;
1605  const REAL thmax=*psith+1e-5;
1606  //check if the next reflection is at the same theta. If this is true,
1607  //Then assume that the profile is exactly the same, unless profiles are anisotropic.
1608  for(;;)
1609  {
1610  intensity += *pI++;
1611  if(useML) var += *pIvar++;
1612  if( ++i >= nbRefl) break;
1613  if( *(++psith) > thmax ) break;
1614  if(mpReflectionProfile->IsAnisotropic()) break;// Anisotropic profile
1615  ++pos;
1616  }
1617  VFN_DEBUG_MESSAGE("PowderPatternDiffraction::CalcPowderPatternIntegrated():"<<i,2)
1618  REAL * RESTRICT pData=mPowderPatternIntegratedCalc.data()+pos->first;
1619  const REAL * RESTRICT pFact=pos->second.data();
1620  const unsigned long nb=pos->second.numElements();
1621  //cout <<i<<" - "<< intensity<<"*:";
1622  for(unsigned long j=nb;j>0;j--)
1623  {
1624  //cout <<pos->first+j<<"("<<*pFact<<","<<*pData<<") ";
1625  *pData++ += intensity * *pFact++ ;
1626  }
1627  //cout<<endl;
1628 
1629  if(useML)
1630  {
1631  const REAL * RESTRICT pFact=pos->second.data();
1632  REAL * RESTRICT pVar=mPowderPatternIntegratedCalcVariance.data()+pos->first;
1633  for(unsigned long j=nb;j>0;j--) *pVar++ += var * *pFact++ ;
1634  }
1635  ++pos;
1636  }
1637  TAU_PROFILE_STOP(timer2);
1638  #ifdef __DEBUG__
1639  if(gVFNDebugMessageLevel<3)
1640  {
1641  this->CalcPowderPattern();
1642  CrystVector_REAL integr(nb),min(nb),max(nb),diff(nb),index(nb);
1643  integr=0;
1644  for(long i=0;i<nb;i++)
1645  {
1646  index(i)=i;
1649  integr(i)=0;
1651  j<=mpParentPowderPattern->GetIntegratedProfileMax()(i);j++)
1652  {
1653  integr(i) += mPowderPatternCalc(j);
1654  }
1655  diff(i)=1.-mPowderPatternIntegratedCalc(i)/integr(i);
1656  }
1657  cout << "Integrated intensities, Component"<<endl
1659  (index,min,max,integr,mPowderPatternIntegratedCalc,diff,20,6)<<endl;
1660  }
1661  #endif
1663  VFN_DEBUG_EXIT("PowderPatternDiffraction::CalcPowderPatternIntegrated",3)
1664 }
1665 
1667 {
1668  TAU_PROFILE("PowderPatternDiffraction::CalcPowderPatternIntegrated_FullDeriv()","void ()",TAU_DEFAULT);
1669  //cout<<"PowderPatternDiffraction::CalcPowderPatternIntegrated_FullDeriv"<<endl;
1670  //this->PowderPatternComponent::CalcPowderPatternIntegrated_FullDeriv(vPar);
1671  //return;
1672 
1673  this->CalcPowderPatternIntegrated();
1674  this->CalcIhkl_FullDeriv(vPar);
1675  const long nbRefl=this->GetNbRefl();
1676  //#define PowderPatternDiffraction_CalcPowderPatternIntegrated_FullDerivDEBUG
1677  #ifdef PowderPatternDiffraction_CalcPowderPatternIntegrated_FullDerivDEBUG
1679  std::map<RefinablePar*, CrystVector_REAL> oldDeriv=mPowderPatternIntegrated_FullDeriv;
1680  #endif
1681  const long nbprof=mpParentPowderPattern->GetIntegratedProfileMin().size();
1682  long ctpar=0;
1683  mPowderPatternIntegrated_FullDeriv.clear();
1684  for(std::set<RefinablePar*>::iterator par=vPar.begin();par!=vPar.end();++par)
1685  {
1686  if(*par==0) mPowderPatternIntegrated_FullDeriv[*par]=mPowderPatternIntegratedCalc;
1687  else
1688  {
1689  if(mIhkl_FullDeriv[*par].size()==0) continue;
1690  if(mPowderPatternIntegrated_FullDeriv[*par].size()==0)
1691  {
1692  mPowderPatternIntegrated_FullDeriv[*par].resize(nbprof);
1693  mPowderPatternIntegrated_FullDeriv[*par]=0;
1694  }
1695  const REAL * RESTRICT psith=mSinThetaLambda.data();
1696  const REAL * RESTRICT pI=mIhkl_FullDeriv[*par].data();
1697  // :TODO: also handle derivatives of profile parameters ? Though one should not
1698  // refine profiles using integrated profiles !
1699  vector< pair<unsigned long, CrystVector_REAL> >::const_iterator pos=mIntegratedProfileFactor.begin();
1700 
1701  for(long i=0;i<mNbReflUsed;)
1702  {
1703  REAL intensity=0.;
1704  const REAL thmax=*psith+1e-5;
1705  for(;;)
1706  {
1707  intensity += *pI++;
1708  if( ++i >= nbRefl) break;
1709  if( *(++psith) > thmax ) break;
1710  if(mpReflectionProfile->IsAnisotropic()) break;// Anisotropic profile
1711  ++pos;
1712  }
1713  REAL * RESTRICT pData=mPowderPatternIntegrated_FullDeriv[*par].data()+pos->first;
1714  const REAL * RESTRICT pFact=pos->second.data();
1715  const unsigned long nb=pos->second.numElements();
1716  #ifdef PowderPatternDiffraction_CalcPowderPatternIntegrated_FullDerivDEBUG
1717  if((i<5)&&(ctpar<8)) cout<<__FILE__<<":"<<__LINE__<<":"<<(*par)->GetName()<<"i="<<setw(16)<<i<<":I="<<setw(16)<<intensity<<endl;
1718  #endif
1719  for(unsigned long j=nb;j>0;j--)
1720  {
1721  #ifdef PowderPatternDiffraction_CalcPowderPatternIntegrated_FullDerivDEBUG
1722  *pData += intensity * *pFact ;
1723  if((i<5)&&((*par)->GetName()=="Cimetidine_C11_x")&&(pos->first==0)&&(nb==j)) cout<<nb-j<<" SUM1"<<setw(16)<<*pData<<", dI="<<setw(16)<<intensity<<", prof="<<setw(16)<<*pFact<<endl;
1724  pData++;pFact++ ;
1725  #else
1726  *pData++ += intensity * *pFact++ ;
1727  #endif
1728  }
1729  ++pos;
1730  ctpar++;
1731  }
1732  }
1733  }
1734  #ifdef PowderPatternDiffraction_CalcPowderPatternIntegrated_FullDerivDEBUG
1735  std::vector<const CrystVector_REAL*> v;
1736  int n=0;
1737  cout<<"PowderPatternDiffraction::CalcPowderPatternIntegrated_FullDeriv():parameters:"<<endl;
1738  for(std::set<RefinablePar*>::iterator par=vPar.begin();par!=vPar.end();++par)
1739  {
1740  if(mPowderPatternIntegrated_FullDeriv[*par].size()==0) continue;
1741  v.push_back(&(mPowderPatternIntegrated_FullDeriv[*par]));
1742  v.push_back(&(oldDeriv[*par]));
1743  cout<<(*par)->GetName()<<":"<<mPowderPatternIntegrated_FullDeriv[*par].size()<<","<<oldDeriv[*par].size()<<endl;
1744  if(++n>6) break;
1745  }
1746  cout<<"PowderPatternDiffraction::CalcPowderPatternIntegrated_FullDeriv():"<<endl<<FormatVertVector<REAL>(v,12,1,20)<<endl;
1747  //exit(0);
1748  #endif
1749 }
1750 
1752 {
1753  this->CalcSinThetaLambda();
1755  if( (mClockProfileCalc>mClockProfilePar)
1756  &&(mClockProfileCalc>mpReflectionProfile->GetClockMaster())
1757  &&(mClockProfileCalc>mClockTheta)
1758  &&(mClockProfileCalc>this->GetRadiation().GetClockWavelength())
1759  &&(mClockProfileCalc>mpParentPowderPattern->GetClockPowderPatternXCorr())
1760  &&(mClockProfileCalc>mClockHKL)
1761  &&(mClockProfileCalc>mpParentPowderPattern->GetClockNbPointUsed())) return;
1762 
1763  TAU_PROFILE("PowderPatternDiffraction::CalcPowderReflProfile()","void (bool)",TAU_DEFAULT);
1764  VFN_DEBUG_ENTRY("PowderPatternDiffraction::CalcPowderReflProfile()",5)
1765 
1766  //Calc all profiles
1767  mvLabel.clear();
1768  stringstream label;
1769 
1770  unsigned int nbLine=1;
1771  CrystVector_REAL spectrumDeltaLambdaOvLambda;
1772  CrystVector_REAL spectrumFactor;//relative weigths of different lines of X-Ray tube
1773  switch(this->GetRadiation().GetWavelengthType())
1774  {
1775  case WAVELENGTH_MONOCHROMATIC:
1776  {
1777  spectrumDeltaLambdaOvLambda.resize(1);spectrumDeltaLambdaOvLambda=0.0;
1778  spectrumFactor.resize(1);spectrumFactor=1.0;
1779  break;
1780  }
1781  case WAVELENGTH_ALPHA12:
1782  {
1783  nbLine=2;
1784  spectrumDeltaLambdaOvLambda.resize(2);
1785  spectrumDeltaLambdaOvLambda(0)
1786  =-this->GetRadiation().GetXRayTubeDeltaLambda()
1787  *this->GetRadiation().GetXRayTubeAlpha2Alpha1Ratio()
1788  /(1+this->GetRadiation().GetXRayTubeAlpha2Alpha1Ratio())
1789  /this->GetRadiation().GetWavelength()(0);
1790  spectrumDeltaLambdaOvLambda(1)
1791  = this->GetRadiation().GetXRayTubeDeltaLambda()
1792  /(1+this->GetRadiation().GetXRayTubeAlpha2Alpha1Ratio())
1793  /this->GetRadiation().GetWavelength()(0);
1794 
1795  spectrumFactor.resize(2);
1796  spectrumFactor(0)=1./(1.+this->GetRadiation().GetXRayTubeAlpha2Alpha1Ratio());
1797  spectrumFactor(1)=this->GetRadiation().GetXRayTubeAlpha2Alpha1Ratio()
1798  /(1.+this->GetRadiation().GetXRayTubeAlpha2Alpha1Ratio());
1799  break;
1800  }
1801  case WAVELENGTH_TOF:
1802  {
1803  spectrumDeltaLambdaOvLambda.resize(1);spectrumDeltaLambdaOvLambda=0.0;
1804  spectrumFactor.resize(1);spectrumFactor=1.0;
1805  break;
1806  }
1807  default: throw ObjCrystException("PowderPatternDiffraction::PrepareIntegratedProfile():\
1808 Radiation must be either monochromatic, from an X-Ray Tube, or neutron TOF !!");
1809  }
1810 
1811 
1812  VFN_DEBUG_MESSAGE("PowderPatternDiffraction::CalcPowderReflProfile():\
1813 Computing all Profiles",5)
1814  REAL center,// center of current reflection (depends on line if several)
1815  x0; // theoretical (uncorrected for zero's, etc..) position of center of line
1816  long first,last;// first & last point of the stored profile
1817  CrystVector_REAL vx,reflProfile,tmpV;
1818  mvReflProfile.resize(this->GetNbRefl());
1819  for(unsigned int i=0;i<this->GetNbRefl();i++)
1820  {
1821  mvReflProfile[i].first=0;
1822  mvReflProfile[i].last=0;
1823  mvReflProfile[i].profile.resize(0);
1824  }
1825  VFN_DEBUG_MESSAGE("PowderPatternDiffraction::CalcPowderReflProfile()",5)
1826 
1827  for(unsigned int line=0;line<nbLine;line++)
1828  {
1829  for(long i=0;i<this->GetNbRefl();i++)
1830  {// Only the reflections contributing below the max(sin(theta)/lambda) will be computed
1831  VFN_DEBUG_ENTRY("PowderPatternDiffraction::CalcPowderReflProfile()#"<<i,5)
1832  x0=mpParentPowderPattern->STOL2X(mSinThetaLambda(i));
1833 
1834  VFN_DEBUG_MESSAGE("PowderPatternDiffraction::CalcPowderReflProfile()#"<<i,5)
1835  if(nbLine>1)
1836  {// we have several lines, not centered on the profile range
1837  center = mpParentPowderPattern->X2XCorr(
1838  x0+2*tan(x0/2.0)*spectrumDeltaLambdaOvLambda(line));
1839  }
1840  else center=mpParentPowderPattern->X2XCorr(x0);
1841  REAL fact=1.0;
1842  if(!mUseFastLessPreciseFunc) fact=5.0;
1843  const REAL halfwidth=mpReflectionProfile->GetFullProfileWidth(0.04,center,mH(i),mK(i),mL(i))*fact;
1844  if(line==0)
1845  {
1846  // For an X-Ray tube, label on first (strongest) of reflections lines (Kalpha1)
1847  label.str("");
1848  label<<mIntH(i)<<" "<<mIntK(i)<<" "<<mIntL(i);
1849  mvLabel.push_back(make_pair(center,label.str()));
1850  REAL spectrumwidth=0.0;
1851  if(this->GetRadiation().GetWavelengthType()==WAVELENGTH_ALPHA12)
1852  {// We need to shift the last point to include 2 lines in the profile
1853  spectrumwidth=2*this->GetRadiation().GetXRayTubeDeltaLambda()
1854  /this->GetRadiation().GetWavelength()(0)*tan(x0/2.0);
1855  }
1856  first=(long)(mpParentPowderPattern->X2Pixel(center-halfwidth));
1857  last =(long)(mpParentPowderPattern->X2Pixel(center+halfwidth+spectrumwidth));
1858  if(this->GetRadiation().GetWavelengthType()==WAVELENGTH_TOF)
1859  {
1860  const long f=first;
1861  first=last;
1862  last=f;
1863  }
1864  if(first>last)
1865  { // Whoops - should not happen !! Unless there is a strange (dis)order for the x coordinates...
1866  cout<<"PowderPatternDiffraction::CalcPowderReflProfile(), line"<<__LINE__<<"first>last !! :"<<first<<","<<last<<endl;
1867  first=(first+last)/2;
1868  last=first;
1869  }
1870  first -=1;
1871  last+=1;
1872  VFN_DEBUG_MESSAGE("PowderPatternDiffraction::CalcPowderReflProfile():"<<first<<","<<last<<","<<center,3)
1873  if(first>last)
1874  {
1875  cout<<__FILE__<<__LINE__<<endl;
1876  exit(0);
1877  }
1878  if((last>=0)&&(first<(long)(mpParentPowderPattern->GetNbPoint())))
1879  {
1880  if(first<0) first=0;
1881  if(last>=(long)(mpParentPowderPattern->GetNbPoint()))
1883  vx.resize(last-first+1);
1884  }
1885  else vx.resize(0); // store no profile if reflection out of pattern
1886  mvReflProfile[i].first=first;
1887  mvReflProfile[i].last=last;
1888  }
1889  else
1890  {
1891  first=mvReflProfile[i].first;
1892  last=mvReflProfile[i].last;
1893  if((last>=0)&&(first<(long)(mpParentPowderPattern->GetNbPoint())))
1894  vx.resize(last-first+1);
1895  else vx.resize(0);
1896  vx.resize(last-first+1);
1897  }
1898  if((last>=0)&&(first<(long)(mpParentPowderPattern->GetNbPoint())))
1899  {
1900  {
1901  const REAL *p0=mpParentPowderPattern->GetPowderPatternX().data()+first;
1902  REAL *p1=vx.data();
1903  for(long i=first;i<=last;i++) *p1++ = *p0++;
1904  }
1905 
1906  VFN_DEBUG_MESSAGE("PowderPatternDiffraction::CalcPowderReflProfile():"<<first<<","<<last<<","<<center,3)
1907  reflProfile=mpReflectionProfile->GetProfile(vx,center,mH(i),mK(i),mL(i));
1908  VFN_DEBUG_MESSAGE("PowderPatternDiffraction::CalcPowderReflProfile()",2)
1909  if(nbLine>1) reflProfile *=spectrumFactor(line);
1910  if(line==0) mvReflProfile[i].profile = reflProfile;
1911  else mvReflProfile[i].profile += reflProfile;
1912  }
1913  else
1914  { // reflection is out of pattern, so store no profile
1915  mvReflProfile[i].profile.resize(0);
1916  }
1917  VFN_DEBUG_EXIT("PowderPatternDiffraction::CalcPowderReflProfile():\
1918 Computing all Profiles: Reflection #"<<i,5)
1919  if(first>(long)(mpParentPowderPattern->GetNbPointUsed())) break;
1920  }
1921  }
1922  mClockProfileCalc.Click();
1923  VFN_DEBUG_EXIT("PowderPatternDiffraction::CalcPowderReflProfile()",5)
1924 }
1925 
1927 {
1928  TAU_PROFILE("PowderPatternDiffraction::CalcPowderReflProfile_FullDeriv()","void (bool)",TAU_DEFAULT);
1929  cout<<__FILE__<<":"<<__LINE__<<":PowderPatternDiffraction::CalcPowderReflProfile_FullDeriv()"<<endl;
1930  this->CalcPowderReflProfile();
1931  unsigned int nbLine=1;
1932  CrystVector_REAL spectrumDeltaLambdaOvLambda;
1933  CrystVector_REAL spectrumFactor;//relative weigths of different lines of X-Ray tube
1934  switch(this->GetRadiation().GetWavelengthType())
1935  {
1936  case WAVELENGTH_MONOCHROMATIC:
1937  {
1938  spectrumDeltaLambdaOvLambda.resize(1);spectrumDeltaLambdaOvLambda=0.0;
1939  spectrumFactor.resize(1);spectrumFactor=1.0;
1940  break;
1941  }
1942  case WAVELENGTH_ALPHA12:
1943  {
1944  nbLine=2;
1945  spectrumDeltaLambdaOvLambda.resize(2);
1946  spectrumDeltaLambdaOvLambda(0)
1947  =-this->GetRadiation().GetXRayTubeDeltaLambda()
1948  *this->GetRadiation().GetXRayTubeAlpha2Alpha1Ratio()
1949  /(1+this->GetRadiation().GetXRayTubeAlpha2Alpha1Ratio())
1950  /this->GetRadiation().GetWavelength()(0);
1951  spectrumDeltaLambdaOvLambda(1)
1952  = this->GetRadiation().GetXRayTubeDeltaLambda()
1953  /(1+this->GetRadiation().GetXRayTubeAlpha2Alpha1Ratio())
1954  /this->GetRadiation().GetWavelength()(0);
1955 
1956  spectrumFactor.resize(2);
1957  spectrumFactor(0)=1./(1.+this->GetRadiation().GetXRayTubeAlpha2Alpha1Ratio());
1958  spectrumFactor(1)=this->GetRadiation().GetXRayTubeAlpha2Alpha1Ratio()
1959  /(1.+this->GetRadiation().GetXRayTubeAlpha2Alpha1Ratio());
1960  break;
1961  }
1962  case WAVELENGTH_TOF:
1963  {
1964  spectrumDeltaLambdaOvLambda.resize(1);spectrumDeltaLambdaOvLambda=0.0;
1965  spectrumFactor.resize(1);spectrumFactor=1.0;
1966  break;
1967  }
1968  default: throw ObjCrystException("PowderPatternDiffraction::CalcPowderReflProfile_FullDeriv():\
1969 Radiation must be either monochromatic, from an X-Ray Tube, or neutron TOF !!");
1970  }
1971  REAL center,// center of current reflection (depends on line if several)
1972  x0; // theoretical (uncorrected for zero's, etc..) position of center of line
1973  long first,last;// first & last point of the stored profile
1974  CrystVector_REAL vx,reflProfile,tmpV;
1975 
1976  // Derivative vs the shift of the reflection center
1977  vector<CrystVector_REAL> vReflProfile_DerivCenter(mNbReflUsed);
1978 
1979  mvReflProfile_FullDeriv.clear();
1980  for(std::set<RefinablePar*>::iterator par=vPar.begin();par!=vPar.end();++par)
1981  {
1982  if(*par==0) continue;
1983  if( (*par)->GetType()->IsDescendantFromOrSameAs(gpRefParTypeRadiation)
1984  ||(*par)->GetType()->IsDescendantFromOrSameAs(gpRefParTypeUnitCell)
1985  ||(*par)->GetType()->IsDescendantFromOrSameAs(gpRefParTypeScattDataCorrPos)
1986  ||(*par)->GetType()->IsDescendantFromOrSameAs(gpRefParTypeScattDataProfile))
1987  {
1988  mvReflProfile_FullDeriv[*par].resize(mNbReflUsed);
1989 
1990  for(unsigned int line=0;line<nbLine;line++)
1991  {
1992  for(long i=0;i<mNbReflUsed;i++)
1993  {
1994  x0=mpParentPowderPattern->STOL2X(mSinThetaLambda(i));
1995 
1996  if(nbLine>1)
1997  {// we have several lines, not centered on the profile range
1998  center = mpParentPowderPattern->X2XCorr(
1999  x0+2*tan(x0/2.0)*spectrumDeltaLambdaOvLambda(line));
2000  }
2001  else center=mpParentPowderPattern->X2XCorr(x0);
2002 
2003  first=mvReflProfile[i].first;
2004  last=mvReflProfile[i].last;
2005  if((last>=0)&&(first<(long)(mpParentPowderPattern->GetNbPoint())))
2006  vx.resize(last-first+1);
2007  else vx.resize(0);
2008  vx.resize(last-first+1);
2009  if((last>=0)&&(first<(long)(mpParentPowderPattern->GetNbPoint())))
2010  {
2011  {
2012  const REAL *p0=mpParentPowderPattern->GetPowderPatternX().data()+first;
2013  REAL *p1=vx.data();
2014  for(long i=first;i<=last;i++) *p1++ = *p0++;
2015  }
2016 
2017  if((*par)->GetType()->IsDescendantFromOrSameAs(gpRefParTypeScattDataProfile))
2018  {// Parameter only affects profile
2019  //if(i==0) cout<<"PowderPatternDiffraction::CalcPowderReflProfile_FullDeriv()par="<<(*par)->GetName()<<":refl #"<<i<<endl;
2020  //:TODO: analytical derivatives
2021  const REAL step=(*par)->GetDerivStep();
2022  (*par)->Mutate(step);
2023  reflProfile=mpReflectionProfile->GetProfile(vx,center,mH(i),mK(i),mL(i));
2024  (*par)->Mutate(-2*step);
2025  reflProfile-=mpReflectionProfile->GetProfile(vx,center,mH(i),mK(i),mL(i));
2026  (*par)->Mutate(step);
2027  reflProfile/=2*step;
2028  }
2029  else
2030  {// Parameter affects reflection center
2031  REAL dcenter=0;
2032  {
2033  //:TODO: analytical derivatives
2034  const REAL step=(*par)->GetDerivStep();
2035  (*par)->Mutate(step);
2036  REAL x1=mpParentPowderPattern->STOL2X(this->CalcSinThetaLambda(mH(i),mK(i),mL(i)));
2037  if(nbLine>1) dcenter = mpParentPowderPattern->X2XCorr(x1+2*tan(x1/2.0)*spectrumDeltaLambdaOvLambda(line));
2038  else dcenter = mpParentPowderPattern->X2XCorr(x1);
2039  (*par)->Mutate(-2*step);
2040  x1=mpParentPowderPattern->STOL2X(this->CalcSinThetaLambda(mH(i),mK(i),mL(i)));
2041  if(nbLine>1) dcenter-= mpParentPowderPattern->X2XCorr(x1+2*tan(x1/2.0)*spectrumDeltaLambdaOvLambda(line));
2042  else dcenter-= mpParentPowderPattern->X2XCorr(x1);
2043  (*par)->Mutate(step);
2044  dcenter/=2*step;
2045  }
2046 
2047  if(dcenter!=0)
2048  {
2049  //if(i==0) cout<<"PowderPatternDiffraction::CalcPowderReflProfile_FullDeriv()par="<<(*par)->GetName()<<":refl #"<<i<<", dcenter="<<setw(8)<<dcenter<<endl;
2050  if(vReflProfile_DerivCenter[i].size()==0)
2051  {
2052  const REAL step=1e-4;//:TODO: adapt for TOF
2053  vReflProfile_DerivCenter[i] =mpReflectionProfile->GetProfile(vx,center+step,mH(i),mK(i),mL(i));
2054  vReflProfile_DerivCenter[i]-=mpReflectionProfile->GetProfile(vx,center-step,mH(i),mK(i),mL(i));
2055  vReflProfile_DerivCenter[i]/=2*step;
2056  }
2057  reflProfile=vReflProfile_DerivCenter[i];
2058  reflProfile*=dcenter;
2059  }
2060  else
2061  {
2062  //if(i==0) cout<<"PowderPatternDiffraction::CalcPowderReflProfile_FullDeriv()par="<<(*par)->GetName()<<":refl #"<<i<<" => Parameter affects nothing ?"<<endl;
2063  reflProfile.resize(0);
2064  }
2065  }
2066  if(reflProfile.size()>0)
2067  {
2068  if(nbLine>1) reflProfile *=spectrumFactor(line);
2069  if(line==0) mvReflProfile_FullDeriv[*par][i] = reflProfile;
2070  else mvReflProfile_FullDeriv[*par][i] += reflProfile;
2071  }
2072  }
2073  }
2074  }
2075  }
2076  }
2077 }
2078 
2080 {
2081  bool needRecalc=false;
2082 
2083  this->CalcSinThetaLambda();
2084  if((mClockIntensityCorr<mClockTheta)||(mClockIntensityCorr<this->GetClockNbReflBelowMaxSinThetaOvLambda())) needRecalc=true;
2085 
2086  const CrystVector_REAL *mpCorr[6] = {0, 0, 0, 0, 0, 0};
2087 
2088  if(this->GetRadiation().GetWavelengthType()==WAVELENGTH_TOF)
2089  {
2090  mpCorr[0]=&(mCorrTOF.GetCorr());
2091  if(mClockIntensityCorr<mCorrTOF.GetClockCorr()) needRecalc=true;
2092  }
2093  else
2094  {
2095  mpCorr[0]=&(mCorrLorentz.GetCorr());
2096  if(mClockIntensityCorr<mCorrLorentz.GetClockCorr()) needRecalc=true;
2097 
2098  if(this->GetRadiation().GetRadiationType()==RAD_XRAY)
2099  {
2100  mpCorr[1]=&(mCorrPolar.GetCorr());
2101  if(mClockIntensityCorr<mCorrPolar.GetClockCorr()) needRecalc=true;
2102  }
2103 
2104  mpCorr[2]=&(mCorrSlitAperture.GetCorr());
2105  if(mClockIntensityCorr<mCorrSlitAperture.GetClockCorr()) needRecalc=true;
2106 
2107  if(mpParentPowderPattern!=NULL)
2108  {
2109  mpCorr[5] = &(mCorrCylAbs.GetCorr());
2110  if(mClockIntensityCorr<mCorrCylAbs.GetClockCorr()) needRecalc=true;
2111  }
2112  }
2113 
2114  if(mCorrTextureMarchDollase.GetNbPhase()>0)
2115  {
2116  mpCorr[3]=&(mCorrTextureMarchDollase.GetCorr());
2117  if(mClockIntensityCorr<mCorrTextureMarchDollase.GetClockCorr()) needRecalc=true;
2118  }
2119  mpCorr[4]=&(mCorrTextureEllipsoid.GetCorr());
2120  if(mClockIntensityCorr<mCorrTextureEllipsoid.GetClockCorr()) needRecalc=true;
2121 
2122  if(needRecalc==false) return;
2123 
2124  TAU_PROFILE("PowderPatternDiffraction::CalcIntensityCorr()","void ()",TAU_DEFAULT);
2125  VFN_DEBUG_MESSAGE("PowderPatternDiffraction::CalcIntensityCorr()",2)
2126  mIntensityCorr.resize(mNbRefl);
2127  REAL *pCorr=mIntensityCorr.data();
2128  const REAL *p=mpCorr[0]->data();
2129  for(long i=mNbReflUsed;i>0;i--) *pCorr++ = *p++;
2130  if(this->GetRadiation().GetWavelengthType()!=WAVELENGTH_TOF)
2131  {
2132  if(this->GetRadiation().GetRadiationType()==RAD_XRAY)
2133  {
2134  pCorr=mIntensityCorr.data();
2135  p=mpCorr[1]->data();
2136  const REAL* p2=mpCorr[2]->data();
2137  for(long i=mNbReflUsed;i>0;i--) *pCorr++ *= *p++ * *p2++;
2138  }
2139  else
2140  {
2141  pCorr=mIntensityCorr.data();
2142  p=mpCorr[2]->data();
2143  for(long i=mNbReflUsed;i>0;i--) *pCorr++ *= *p++;
2144  }
2145  }
2146  if(mCorrTextureMarchDollase.GetNbPhase()>0)
2147  {
2148  pCorr=mIntensityCorr.data();
2149  p=mpCorr[3]->data();
2150  for(long i=mNbReflUsed;i>0;i--) *pCorr++ *= *p++;
2151  }
2152  if(mpCorr[4]->numElements()>0)
2153  {
2154  pCorr=mIntensityCorr.data();
2155  p=mpCorr[4]->data();
2156  for(long i=mNbReflUsed;i>0;i--) *pCorr++ *= *p++;
2157  }
2158  if(mpCorr[5] != NULL)
2159  if(mpCorr[5]->numElements()>0)
2160  {
2161  pCorr=mIntensityCorr.data();
2162  p=mpCorr[5]->data();
2163  for(long i=mNbReflUsed;i>0;i--) *pCorr++ *= *p++;
2164  }
2165  mClockIntensityCorr.Click();
2166  VFN_DEBUG_MESSAGE("PowderPatternDiffraction::CalcIntensityCorr():finished",2)
2167 }
2168 
2170 {
2171  this->CalcIntensityCorr();
2172  if(mExtractionMode==true)
2173  {
2174  VFN_DEBUG_MESSAGE("PowderPatternDiffraction::CalcIhkl():"<<mFhklObsSq.numElements()<<","<<mIntensityCorr.numElements()<<","<<mMultiplicity.numElements(),7);
2175  mIhklCalc=mFhklObsSq;
2176  mIhklCalc*=mIntensityCorr;
2177  mIhklCalc*=mMultiplicity;
2178  mClockIhklCalc.Click();
2179  return;
2180  }
2181  this->CalcStructFactor();
2182  if( (mClockIhklCalc>mClockIntensityCorr)
2183  &&(mClockIhklCalc>mClockStructFactor)
2184  &&(mClockIhklCalc>mClockNbReflUsed)) return;
2185 
2186  VFN_DEBUG_MESSAGE("PowderPatternDiffraction::CalcIhkl()",3)
2187  TAU_PROFILE("PowderPatternDiffraction::CalcIhkl()","void ()",TAU_DEFAULT);
2188  const REAL * RESTRICT pr,* RESTRICT pi,* RESTRICT pcorr;
2189  const int * RESTRICT mult;
2190  REAL * RESTRICT p;
2191 
2192  pr=mFhklCalcReal.data();
2193  pi=mFhklCalcImag.data();
2194  pcorr=mIntensityCorr.data();
2195 
2196  mult=mMultiplicity.data();
2197  mIhklCalc.resize(mNbRefl);
2198  p=mIhklCalc.data();
2199  if(mFhklCalcVariance.numElements()>0)
2200  {
2201  const REAL * RESTRICT pv=mFhklCalcVariance.data();
2202  for(long i=mNbReflUsed;i>0;i--)
2203  {
2204  *p++ = *mult++ * (*pr * *pr + *pi * *pi + 2 * *pv++) * *pcorr++;
2205  pr++;
2206  pi++;
2207  }
2208  }
2209  else
2210  {
2211  for(long i=mNbReflUsed;i>0;i--)
2212  {
2213  *p++ = *mult++ * (*pr * *pr + *pi * *pi) * *pcorr++;
2214  pr++;
2215  pi++;
2216  }
2217  }
2218  if(mFhklCalcVariance.numElements()==0)
2219  {
2220  VFN_DEBUG_MESSAGE("PowderPatternDiffraction::CalcIhkl(): No Calc Variance",2)
2221  mIhklCalcVariance.resize(0);
2222  VFN_DEBUG_MESSAGE(endl<<
2223  FormatVertVectorHKLFloats<REAL>(mH,mK,mL,mSinThetaLambda,
2224  mFhklCalcReal,
2225  mFhklCalcImag,
2226  mIhklCalc,
2227  mIntensityCorr
2228  ),2)
2229  }
2230  else
2231  {
2232  VFN_DEBUG_MESSAGE("PowderPatternDiffraction::CalcIhkl(): Calc Variance",2)
2233  mIhklCalcVariance.resize(mNbRefl);
2234  REAL * RESTRICT pVar2=mIhklCalcVariance.data();
2235 
2236  const REAL * RESTRICT pInt=mIhklCalc.data();
2237  const REAL * RESTRICT pVar=mFhklCalcVariance.data();
2238  pcorr=mIntensityCorr.data();
2239  mult=mMultiplicity.data();
2240 
2241  for(long j=mNbReflUsed;j>0;j--)
2242  {
2243  *pVar2++ = (4* *mult) * *pcorr * *pVar *(*pInt++ - (*mult * *pcorr) * *pVar);
2244  pVar++;mult++;pcorr++;
2245  }
2246  VFN_DEBUG_MESSAGE(endl<<
2247  FormatVertVectorHKLFloats<REAL>(mH,mK,mL,mSinThetaLambda,
2248  mFhklCalcReal,
2249  mIhklCalc,
2250  mExpectedIntensityFactor,
2251  mIntensityCorr,
2252  mMultiplicity,
2253  mvLuzzatiFactor[&(mpCrystal->GetScatteringPowerRegistry().GetObj(0))],
2254  mFhklCalcVariance,
2255  mIhklCalcVariance),2);
2256  VFN_DEBUG_MESSAGE(mNbRefl<<" "<<mNbReflUsed,2)
2257  }
2258 
2259  //cout <<FormatVertVector<REAL>(mTheta,mIhklCalc,mMultiplicity,
2260  // mFhklCalcReal,mFhklCalcImag,mIntensityCorr);
2261  mClockIhklCalc.Click();
2262  VFN_DEBUG_MESSAGE("PowderPatternDiffraction::CalcIhkl():End",3)
2263 }
2264 
2265 void PowderPatternDiffraction::CalcIhkl_FullDeriv(std::set<RefinablePar*> &vPar)
2266 {
2267  TAU_PROFILE("PowderPatternDiffraction::CalcIhkl_FullDeriv()","void ()",TAU_DEFAULT);
2268  //cout<<"PowderPatternDiffraction::CalcIhkl_FullDeriv()"<<endl;
2269  this->CalcIntensityCorr();//:TODO: derivatives of intensity corrections (Texture, displacement parameters,...)
2270  mIhkl_FullDeriv.clear();
2271  if(mExtractionMode==true)
2272  {
2273  //:TODO: handle Pawley refinements of I(hkl)
2274  return;
2275  }
2276  this->CalcStructFactor_FullDeriv(vPar);
2277 
2278  for(std::set<RefinablePar*>::iterator par=vPar.begin();par!=vPar.end();++par)
2279  {
2280  if(*par==0) mIhkl_FullDeriv[*par]=mIhklCalc;
2281  else
2282  {
2283  if(mFhklCalcReal_FullDeriv[*par].size()==0) continue;
2284  const REAL * RESTRICT pr,* RESTRICT pi,* RESTRICT prd,* RESTRICT pid,* RESTRICT pcorr;
2285  const int * RESTRICT mult;
2286  REAL * RESTRICT p;
2287 
2288  pr=mFhklCalcReal.data();
2289  pi=mFhklCalcImag.data();
2290  prd=mFhklCalcReal_FullDeriv[*par].data();
2291  pid=mFhklCalcImag_FullDeriv[*par].data();
2292  pcorr=mIntensityCorr.data();//:TODO: derivatives of intensity corrections (Texture, displacement parameters,...)
2293 
2294  mult=mMultiplicity.data();
2295  mIhkl_FullDeriv[*par].resize(mNbRefl);
2296  p=mIhkl_FullDeriv[*par].data();
2297  if(mFhklCalcImag_FullDeriv[*par].size()==0)
2298  for(long i=mNbReflUsed;i>0;i--) *p++ = *mult++ * 2 * *pr++ * *prd++ * *pcorr++;
2299  else
2300  for(long i=mNbReflUsed;i>0;i--) *p++ = *mult++ * 2 *(*pr++ * *prd++ + *pi++ * *pid++) * *pcorr++;
2301  }
2302  }
2303  #if 0
2304  std::map<RefinablePar*, CrystVector_REAL> oldDeriv;
2305  std::vector<const CrystVector_REAL*> v;
2306  v.push_back(&mH);
2307  v.push_back(&mK);
2308  v.push_back(&mL);
2309  CrystVector_REAL m;
2310  m=mMultiplicity;
2311  v.push_back(&m);
2312  v.push_back(&mIntensityCorr);
2313  int n=0;
2314  for(std::set<RefinablePar*>::iterator par=vPar.begin();par!=vPar.end();++par)
2315  {
2316  if((*par)==0) continue;
2317  if(mIhkl_FullDeriv[*par].size()==0) continue;
2318 
2319  const REAL step=(*par)->GetDerivStep();
2320  (*par)->Mutate(step);
2321  this->CalcIhkl();
2322  oldDeriv[*par]=mIhklCalc;
2323  (*par)->Mutate(-2*step);
2324  this->CalcIhkl();
2325  oldDeriv[*par]-=mIhklCalc;
2326  oldDeriv[*par]/=2*step;
2327  (*par)->Mutate(step);
2328 
2329  v.push_back(&(mIhkl_FullDeriv[*par]));
2330  v.push_back(&(oldDeriv[*par]));
2331  cout<<(*par)->GetName()<<":"<<mIhkl_FullDeriv[*par].size()<<","<<oldDeriv[*par].size()<<", step="<<setw(16)<<step<<endl;
2332  if(++n>5) break;
2333  }
2334  cout<<"PowderPatternDiffraction::CalcIhkl_FullDeriv():"<<endl<<FormatVertVectorHKLFloats<REAL>(v,12,1,20)<<endl;
2335  //exit(0);
2336  #endif
2337 }
2338 
2340 {
2341  if( (this->GetCrystal().GetSpaceGroup().GetClockSpaceGroup()>mClockHKL)
2342  ||(this->GetCrystal().GetClockLatticePar()>mClockHKL)
2343  ||(this->GetRadiation().GetClockWavelength()>mClockHKL)
2345  this->GenHKLFullSpace();
2346  //if(0==this->GetNbRefl()) this->GenHKLFullSpace();
2347 }
2348 void PowderPatternDiffraction::InitOptions()
2349 {
2350  VFN_DEBUG_MESSAGE("PowderPatternDiffraction::InitOptions()",5)
2351  #if 0
2352  static string ReflectionProfileTypeName;
2353  static string ReflectionProfileTypeChoices[3];
2354 
2355  static bool needInitNames=true;
2356  if(true==needInitNames)
2357  {
2358  ReflectionProfileTypeName="Profile Type";
2359  ReflectionProfileTypeChoices[0]="Gaussian";
2360  ReflectionProfileTypeChoices[1]="Lorentzian";
2361  ReflectionProfileTypeChoices[2]="Pseudo-Voigt";
2362 
2363  needInitNames=false;//Only once for the class
2364  }
2365  mReflectionProfileType.Init(3,&ReflectionProfileTypeName,ReflectionProfileTypeChoices);
2366  this->AddOption(&mReflectionProfileType);
2367  #endif
2368 }
2369 const CrystVector_long& PowderPatternDiffraction::GetBraggLimits()const
2370 {
2371  this->CalcPowderReflProfile();
2372  if((mClockProfileCalc>mClockBraggLimits)&&(this->GetNbReflBelowMaxSinThetaOvLambda()>0))
2373  {
2374  VFN_DEBUG_ENTRY("PowderPatternDiffraction::GetBraggLimits(*min,*max)",3)
2375  TAU_PROFILE("PowderPatternDiffraction::GetBraggLimits()","void ()",TAU_DEFAULT);
2376  mIntegratedReflLimits.resize(this->GetNbReflBelowMaxSinThetaOvLambda());
2377  long i = 0;
2378  mIntegratedReflLimits(i)=mvReflProfile[0].first;
2379  for(;i<(this->GetNbReflBelowMaxSinThetaOvLambda()-1);++i)
2380  mIntegratedReflLimits(i+1)=(mvReflProfile[i].first+mvReflProfile[i].last+mvReflProfile[i+1].first+mvReflProfile[i+1].last)/4;
2381  mIntegratedReflLimits(i)=mvReflProfile[i].last;
2383  VFN_DEBUG_EXIT("PowderPatternDiffraction::GetBraggLimits(*min,*max)",3)
2384  }
2385  return mIntegratedReflLimits;
2386 }
2387 
2390 
2391 const CrystMatrix_REAL& PowderPatternDiffraction::GetBMatrix()const
2392 {
2393  if(mFreezeLatticePar) return mFrozenBMatrix;
2394  return this->ScatteringData::GetBMatrix();
2395 }
2396 
2398 {
2399  VFN_DEBUG_MESSAGE("PowderPatternDiffraction::CalcFrozenBMatrix()", 10)
2400  REAL a,b,c,alpha,beta,gamma;//direct space parameters
2401  REAL aa,bb,cc,alphaa,betaa,gammaa;//reciprocal space parameters
2402  POSSIBLY_UNUSED(alphaa);
2403  REAL v;//volume of the unit cell
2404  a=mFrozenLatticePar(0);
2405  b=mFrozenLatticePar(1);
2406  c=mFrozenLatticePar(2);
2407  alpha=mFrozenLatticePar(3);
2408  beta=mFrozenLatticePar(4);
2409  gamma=mFrozenLatticePar(5);
2410 
2411  v=sqrt(1-cos(alpha)*cos(alpha)-cos(beta)*cos(beta)-cos(gamma)*cos(gamma)
2412  +2*cos(alpha)*cos(beta)*cos(gamma));
2413 
2414  aa=sin(alpha)/a/v;
2415  bb=sin(beta )/b/v;
2416  cc=sin(gamma)/c/v;
2417 
2418  alphaa=acos( (cos(beta )*cos(gamma)-cos(alpha))/sin(beta )/sin(gamma) );
2419  betaa =acos( (cos(alpha)*cos(gamma)-cos(beta ))/sin(alpha)/sin(gamma) );
2420  gammaa=acos( (cos(alpha)*cos(beta )-cos(gamma))/sin(alpha)/sin(beta ) );
2421 
2422  mFrozenBMatrix = aa , bb*cos(gammaa) , cc*cos(betaa) ,
2423  0 , bb*sin(gammaa) ,-cc*sin(betaa)*cos(alpha),
2424  0 , 0 ,1/c;
2425 }
2426 
2427 void PowderPatternDiffraction::PrepareIntegratedProfile()const
2428 {
2429  this->CalcPowderReflProfile();
2430  this->GetNbReflBelowMaxSinThetaOvLambda();
2431 
2432  if( (mClockIntegratedProfileFactor>mClockProfileCalc)
2433  &&(mClockIntegratedProfileFactor>mpParentPowderPattern->GetIntegratedProfileLimitsClock())
2434  &&(mClockIntegratedProfileFactor>mClockNbReflUsed))
2435  return;
2436  VFN_DEBUG_ENTRY("PowderPatternDiffraction::PrepareIntegratedProfile()",7)
2437  TAU_PROFILE("PowderPatternDiffraction::PrepareIntegratedProfile()","void ()",TAU_DEFAULT);
2438  const CrystVector_long *pMin=&(mpParentPowderPattern->GetIntegratedProfileMin());
2439  const CrystVector_long *pMax=&(mpParentPowderPattern->GetIntegratedProfileMax());
2440 
2441  const long numInterval=pMin->numElements();
2442 
2443  vector< map<long, REAL> > vIntegratedProfileFactor;
2444  vIntegratedProfileFactor.resize(mNbReflUsed);
2445  vector< map<long, REAL> >::iterator pos1;
2446  pos1=vIntegratedProfileFactor.begin();
2447 
2448  mIntegratedProfileFactor.resize(mNbReflUsed);
2449  vector< pair<unsigned long, CrystVector_REAL> >::iterator pos2;
2450  pos2=mIntegratedProfileFactor.begin();
2451  for(long i=0;i<mNbReflUsed;i++)
2452  {
2453  pos1->clear();
2454  long firstInterval=numInterval;
2455  for(long j=0;j<numInterval;j++)
2456  {
2457  const long first0 = mvReflProfile[i].first;
2458  const long last0 = mvReflProfile[i].last ;
2459  const long first= first0>(*pMin)(j) ? first0:(*pMin)(j);
2460  const long last = last0 <(*pMax)(j) ? last0 :(*pMax)(j);
2461  if((first<=last) && (mvReflProfile[i].profile.size()>0))
2462  {
2463  if(firstInterval>j) firstInterval=j;
2464  if(pos1->find(j) == pos1->end()) (*pos1)[j]=0.;
2465  REAL *fact = &((*pos1)[j]);//this creates the 'j' entry if necessary
2466  const REAL *p2 = mvReflProfile[i].profile.data()+(first-first0);
2467  //cout << i<<","<<j<<","<<first<<","<<last<<":"<<*fact<<"/"<<mNbReflUsed<<","<<mNbRefl<<endl;
2468  for(long k=first;k<=last;k++) *fact += *p2++;
2469  }
2470  }
2471  pos2->first=firstInterval;
2472  pos2->second.resize(pos1->size());
2473  REAL *pFact=pos2->second.data();
2474  for(map<long, REAL>::const_iterator pos=pos1->begin();pos!=pos1->end();++pos)
2475  *pFact++ = pos->second;
2476  pos1++;
2477  pos2++;
2478  }
2479  mClockIntegratedProfileFactor.Click();
2480  #ifdef __DEBUG__
2481  if(gVFNDebugMessageLevel<3)
2482  {
2483  unsigned long i=0;
2484  for(vector< pair<unsigned long, CrystVector_REAL> >::const_iterator
2485  pos=mIntegratedProfileFactor.begin();
2486  pos!=mIntegratedProfileFactor.end();++pos)
2487  {
2488  cout <<"Integrated profile factors for reflection #"<<i++<<" ";
2489  for(int j=0;j<pos->second.numElements();++j)
2490  cout << j+pos->first<<"("<<pos->second(j)<<") ";
2491  cout<<endl;
2492  }
2493  }
2494  #endif
2495 
2496  VFN_DEBUG_EXIT("PowderPatternDiffraction::PrepareIntegratedProfile()",7)
2497 }
2498 
2499 #ifdef __WX__CRYST__
2500 WXCrystObjBasic* PowderPatternDiffraction::WXCreate(wxWindow* parent)
2501 {
2502  //:TODO: Check mpWXCrystObj==0
2503  mpWXCrystObj=new WXPowderPatternDiffraction(parent,this);
2504  return mpWXCrystObj;
2505 }
2506 #endif
2507 
2509 //
2510 // PowderPattern
2511 //
2513 ObjRegistry<PowderPattern>
2514  gPowderPatternRegistry("List of all PowderPattern objects");
2515 
2516 PowderPattern::PowderPattern():
2517 mIsXAscending(true),mNbPoint(0),
2518 mXZero(0.),m2ThetaDisplacement(0.),m2ThetaTransparency(0.),
2519 mDIFC(48277.14),mDIFA(-6.7),
2520 mScaleFactor(20),mMuR(0), mUseFastLessPreciseFunc(false),
2521 mStatisticsExcludeBackground(false),mMaxSinThetaOvLambda(10),mNbPointUsed(0)
2522 {
2523  mScaleFactor=1;
2524  mSubObjRegistry.SetName("SubObjRegistry for a PowderPattern object");
2525  mPowderPatternComponentRegistry.SetName("Powder Pattern Components");
2526  this->AddSubRefObj(mRadiation);
2527  this->Init();
2528  gPowderPatternRegistry.Register(*this);
2529  gTopRefinableObjRegistry.Register(*this);
2530  mClockMaster.AddChild(mClockPowderPatternPar);
2531  mClockMaster.AddChild(mClockNbPointUsed);
2532  mClockMaster.AddChild(mClockPowderPatternXCorr);
2533  mClockMaster.AddChild(mClockScaleFactor);
2534  mClockMaster.AddChild(mClockPowderPatternRadiation);
2535  mClockMaster.AddChild(mClockCorrAbs);
2536 }
2537 
2538 PowderPattern::PowderPattern(const PowderPattern &old):
2539 mIsXAscending(old.mIsXAscending),mNbPoint(old.mNbPoint),
2540 mRadiation(old.mRadiation),
2541 mXZero(old.mXZero),m2ThetaDisplacement(old.m2ThetaDisplacement),
2542 m2ThetaTransparency(old.m2ThetaTransparency),
2543 mDIFC(old.mDIFC),mDIFA(old.mDIFA),
2544 mPowderPatternComponentRegistry(old.mPowderPatternComponentRegistry),
2545 mScaleFactor(old.mScaleFactor),mMuR(old.mMuR),
2546 mUseFastLessPreciseFunc(old.mUseFastLessPreciseFunc),
2547 mStatisticsExcludeBackground(old.mStatisticsExcludeBackground),
2548 mMaxSinThetaOvLambda(old.mMaxSinThetaOvLambda),mNbPointUsed(old.mNbPointUsed)
2549 {
2550  mX=old.mX;
2551  this->Init();
2552  mSubObjRegistry.SetName("SubObjRegistry for a PowderPattern :"+mName);
2553  gPowderPatternRegistry.Register(*this);
2554  gTopRefinableObjRegistry.Register(*this);
2555  this->AddSubRefObj(mRadiation);
2556  mClockMaster.AddChild(mClockPowderPatternPar);
2557  mClockMaster.AddChild(mClockNbPointUsed);
2558  mClockMaster.AddChild(mClockPowderPatternXCorr);
2559  mClockMaster.AddChild(mClockScaleFactor);
2560  mClockMaster.AddChild(mClockPowderPatternRadiation);
2561 }
2562 
2563 PowderPattern::~PowderPattern()
2564 {
2565  gPowderPatternRegistry.DeRegister(*this);
2566  for(int i=0;i<mPowderPatternComponentRegistry.GetNb();i++)
2567  {
2568  mPowderPatternComponentRegistry.GetObj(i).DeRegisterClient(*this);
2569  this->RemoveSubRefObj(mPowderPatternComponentRegistry.GetObj(i));
2570  delete &(mPowderPatternComponentRegistry.GetObj(i));
2571  }
2572  gTopRefinableObjRegistry.DeRegister(*this);
2573 }
2574 const string& PowderPattern::GetClassName() const
2575 {
2576  const static string className="PowderPattern";
2577  return className;
2578 }
2579 
2581 {
2582  VFN_DEBUG_ENTRY("PowderPattern::AddPowderPatternComponent():"<<comp.GetName(),5)
2583  comp.SetParentPowderPattern(*this);
2584  this->AddSubRefObj(comp);
2585  comp.RegisterClient(*this);
2587  mClockIntegratedFactorsPrep.Reset();
2588  mPowderPatternComponentRegistry.Register(comp);
2589  //:TODO: check if there are enough scale factors
2590  //mScaleFactor.resizeAndPreserve(mPowderPatternComponentRegistry.GetNb());
2591  mScaleFactor(mPowderPatternComponentRegistry.GetNb()-1)=1.;
2593  if(comp.IsScalable())
2594  {//Init refinable parameter
2595  RefinablePar tmp("Scale_"+comp.GetName(),mScaleFactor.data()+mPowderPatternComponentRegistry.GetNb()-1,
2596  1e-10,1e10,gpRefParTypeScattDataScale,REFPAR_DERIV_STEP_RELATIVE,
2597  false,true,true,false,1.);
2598  tmp.SetGlobalOptimStep(0.);
2600  tmp.SetDerivStep(1e-4);
2601  this->AddPar(tmp);
2602  }
2603  //this->UpdateDisplay();
2604  VFN_DEBUG_EXIT("PowderPattern::AddPowderPatternComponent():"<<comp.GetName(),5)
2605 }
2606 
2608 {
2609  VFN_DEBUG_ENTRY("PowderPattern::RemovePowderPatternComponent():"<<comp.GetName(),5)
2610  if(comp.IsScalable())
2611  {
2612  // Remove one scale factor parameter
2613  cout<<"PowderPattern::RemovePowderPatternComponent: removing 1 scale paramater"<<endl;
2614  this->Print();
2615  this->RemovePar(&this->GetPar(mScaleFactor.data()+mPowderPatternComponentRegistry.GetNb()-1));
2616  this->Print();
2617  }
2618 
2619  this->RemoveSubRefObj(comp);
2620  comp.DeRegisterClient(*this);
2622  mClockIntegratedFactorsPrep.Reset();
2623  mPowderPatternComponentRegistry.DeRegister(comp);
2624 
2625  // Shift scale factors
2626  unsigned int i=0;
2627  for(unsigned int i=0;i<this->GetNbPowderPatternComponent();i++)
2628  if(&comp == &this->GetPowderPatternComponent(i)) break;
2629  for(unsigned int j=i;j<this->GetNbPowderPatternComponent()-1;j++) mScaleFactor(j) = mScaleFactor(j+1);
2630 
2632  this->UpdateDisplay();
2633  VFN_DEBUG_EXIT("PowderPattern::RemovePowderPatternComponent():"<<comp.GetName(),5)
2634 }
2635 
2637 {
2638  VFN_DEBUG_ENTRY("PowderPattern::RemovePowderPatternComponent():"<<i,5)
2639  this->RemovePowderPatternComponent(mPowderPatternComponentRegistry.GetObj(i));
2640  VFN_DEBUG_EXIT("PowderPattern::RemovePowderPatternComponent():"<<i,5)
2641 }
2642 
2643 
2645 {
2646  return mPowderPatternComponentRegistry.GetNb();
2647 }
2648 
2650  (const string &name)const
2651 {
2652  return mPowderPatternComponentRegistry.GetObj(name);
2653 }
2654 
2656  (const int i) const
2657 {
2658  return mPowderPatternComponentRegistry.GetObj(i);
2659 }
2660 
2662  (const string &name)
2663 {
2664  return mPowderPatternComponentRegistry.GetObj(name);
2665 }
2666 
2668  (const int i)
2669 {
2670  return mPowderPatternComponentRegistry.GetObj(i);
2671 }
2672 
2673 REAL PowderPattern::GetScaleFactor(const int i)const{return mScaleFactor(i);}
2674 
2676 {
2677  unsigned int i=0;
2678  for(;i<mPowderPatternComponentRegistry.GetNb();++i)
2679  {
2680  if(&(mPowderPatternComponentRegistry.GetObj(i))==&comp) break;
2681  }
2682  if(i==mPowderPatternComponentRegistry.GetNb())
2683  throw ObjCrystException("PowderPattern::GetScaleFactor(comp) : no such component");
2684  return mScaleFactor(i);
2685 }
2686 void PowderPattern::SetScaleFactor(const int i, REAL s){ mScaleFactor(i)=s;}
2687 
2689 {
2690  unsigned int i=0;
2691  for(;i<mPowderPatternComponentRegistry.GetNb();++i)
2692  {
2693  if(&(mPowderPatternComponentRegistry.GetObj(i))==&comp) break;
2694  }
2695  if(i==mPowderPatternComponentRegistry.GetNb())
2696  throw ObjCrystException("PowderPattern::GetScaleFactor(comp) : no such component");
2697  mScaleFactor(i)=s;
2698 }
2699 
2701  const REAL step,
2702  unsigned long nbPoint)
2703 {
2704  VFN_DEBUG_MESSAGE("PowderPattern::SetPowderPatternPar():"<<min<<","<<step<<","<<nbPoint,3)
2705  mNbPoint=nbPoint;
2706  mX.resize(mNbPoint);
2707  for(unsigned long i=0;i<mNbPoint;i++) mX(i)=min+step*i;
2708  mPowderPatternObs.resizeAndPreserve(mNbPoint);
2709  mPowderPatternObsSigma.resizeAndPreserve(mNbPoint);
2710  mPowderPatternWeight.resizeAndPreserve(mNbPoint);
2712 }
2713 void PowderPattern::SetPowderPatternX(const CrystVector_REAL &x)
2714 {
2715  mNbPoint=x.numElements();
2716  if(&x != &mX) mX=x;
2717  mPowderPatternObs.resizeAndPreserve(mNbPoint);
2718  mPowderPatternObsSigma.resizeAndPreserve(mNbPoint);
2719  mPowderPatternWeight.resizeAndPreserve(mNbPoint);
2721  if(mNbPoint < 2 || mX(mNbPoint-1) > mX(0)) mIsXAscending=true;
2722  else mIsXAscending=false;
2723  VFN_DEBUG_MESSAGE("PowderPattern::SetPowderPatternX() is ascending="<<mIsXAscending,5)
2724 }
2725 
2726 unsigned long PowderPattern::GetNbPoint()const {return mNbPoint;}
2727 
2728 unsigned long PowderPattern::GetNbPointUsed()const
2729 {
2730  if(!this->IsBeingRefined()) this->CalcNbPointUsed();
2731  return mNbPointUsed;
2732 }
2733 
2734 const RefinableObjClock& PowderPattern::GetClockNbPointUsed()const{return mClockNbPointUsed;}
2735 
2737 {
2738  mRadiation=radiation;
2740 }
2742 
2744 
2746 {
2748 }
2749 
2751 void PowderPattern::SetWavelength(const REAL lambda)
2752 {
2753  VFN_DEBUG_MESSAGE("PowderPattern::SetWavelength(lambda)",3)
2754  mRadiation.SetWavelength(lambda);
2755 }
2756 
2757 void PowderPattern::SetWavelength(const string &XRayTubeElementName,const REAL alpha12ratio)
2758 {
2759  VFN_DEBUG_MESSAGE("PowderPattern::SetWavelength(wavelength)",3)
2760  mRadiation.SetWavelength(XRayTubeElementName,alpha12ratio);
2761 }
2762 
2764 
2765 const CrystVector_REAL& PowderPattern::GetPowderPatternCalc()const
2766 {
2767  this->CalcPowderPattern();
2768  return mPowderPatternCalc;
2769 }
2770 
2771 std::map<RefinablePar*,CrystVector_REAL>& PowderPattern::GetPowderPattern_FullDeriv(std::set<RefinablePar *> &vPar)
2772 {
2773  this->CalcPowderPattern_FullDeriv(vPar);
2774  return mPowderPattern_FullDeriv;
2775 }
2776 
2777 const CrystVector_REAL& PowderPattern::GetPowderPatternObs()const
2778 {
2779  return mPowderPatternObs;
2780 }
2781 
2782 const CrystVector_REAL& PowderPattern::GetPowderPatternObsSigma()const
2783 {
2784  return mPowderPatternObsSigma;
2785 }
2786 
2787 const CrystVector_REAL& PowderPattern::GetPowderPatternVariance()const
2788 {
2789  return mPowderPatternVariance;
2790 }
2791 
2792 const CrystVector_REAL& PowderPattern::GetPowderPatternWeight()const
2793 {
2794  return mPowderPatternWeight;
2795 }
2796 
2798 {
2799  if(mNbPoint==0) return 0;//:KLUDGE: ?
2800  if(true==mIsXAscending) return mX(0);
2801  return mX(mNbPoint-1);
2802 }
2803 
2805 {
2806  if(mNbPoint==0) return 0;//:KLUDGE: ?
2807  return abs((-mX(0)+mX(mNbPoint-1))/(mNbPoint-1));
2808 }
2809 
2811 {
2812  if(mNbPoint==0) return 0;//:KLUDGE: ?
2813  if(true==mIsXAscending) return mX(mNbPoint-1);
2814  return mX(0);
2815 }
2816 const CrystVector_REAL& PowderPattern::GetPowderPatternX()const
2817 {
2818  return mX;
2819 }
2820 
2821 const CrystVector_REAL& PowderPattern::GetChi2Cumul(const int m)const
2822 {
2823  VFN_DEBUG_ENTRY("PowderPattern::GetChi2Cumul()",3)
2824  mChi2Cumul.resize(mNbPoint);
2825  int mode = m;
2826  if((mode!=0) && (mode!=1)) mode = mOptProfileIntegration.GetChoice();
2827  if(0 == mode)
2828  {
2830  if(mNbIntegrationUsed==0)
2831  mChi2Cumul=0;
2832  else
2833  {
2834  const REAL *pObs=mIntegratedObs.data();
2835  const REAL *pCalc=mPowderPatternIntegratedCalc.data();
2836  const REAL *pWeight;
2837  if(mIntegratedWeight.numElements()==0) pWeight=mIntegratedWeightObs.data();
2838  else pWeight=mIntegratedWeight.data();
2839 
2840  REAL *pC2Cu=mChi2Cumul.data();
2841  for(int i=0;i<mIntegratedPatternMin(0);i++) *pC2Cu++ = 0;
2842  REAL chi2cumul=0,tmp;
2843  for(unsigned long j=1;j<mNbIntegrationUsed;j++)
2844  {
2845  tmp=(*pObs++ - *pCalc++) ;
2846  chi2cumul += *pWeight++ * tmp*tmp;
2847  for(int i=mIntegratedPatternMin(j-1);i<mIntegratedPatternMin(j);i++) *pC2Cu++ =chi2cumul;
2848 
2849  if(mIntegratedPatternMin(j)>(int)mNbPointUsed)
2850  {
2851  for(unsigned int i=mIntegratedPatternMin(j);i<mNbPoint;i++) *pC2Cu++ =chi2cumul;
2852  break;
2853  }
2854  }
2855  pC2Cu=mChi2Cumul.data()+mIntegratedPatternMin(mNbIntegrationUsed-1);
2856  for(unsigned int i=mIntegratedPatternMin(mNbIntegrationUsed-1);i<mNbPoint;i++) *pC2Cu++ =chi2cumul;
2857  }
2858  }
2859  else
2860  {
2861  this->CalcPowderPattern();
2862  const REAL *pObs=mPowderPatternObs.data();
2863  const REAL *pCalc=mPowderPatternCalc.data();
2864  const REAL *pWeight=mPowderPatternWeight.data();
2865  REAL *pC2Cu=mChi2Cumul.data();
2866  REAL chi2cumul=0,tmp;
2867  for(unsigned int i=0;i<mNbPointUsed;i++)
2868  {
2869  tmp = (*pObs++ - *pCalc++) ;
2870  chi2cumul += *pWeight++ * tmp*tmp;
2871  *pC2Cu++ = chi2cumul;
2872  }
2873  }
2874  VFN_DEBUG_EXIT("PowderPattern::GetChi2Cumul()",3)
2875  return mChi2Cumul;
2876 }
2877 
2879 { return mClockPowderPatternCalc;}
2880 
2882 { return mClockPowderPatternPar;}
2883 
2886 
2888 { return mClockPowderPatternXCorr;}
2889 
2891 { return mClockCorrAbs;}
2892 
2893 void PowderPattern::SetXZero(const REAL newZero)
2894 {
2895  mXZero=newZero;
2897 }
2898 
2899 void PowderPattern::Set2ThetaDisplacement(const REAL displacement)
2900 {
2901  m2ThetaDisplacement=displacement;
2903 }
2904 
2905 void PowderPattern::Set2ThetaTransparency(const REAL transparency)
2906 {
2907  m2ThetaTransparency=transparency;
2909 }
2910 
2911 REAL PowderPattern::X2XCorr(const REAL x0)const
2912 {
2913  REAL x=x0;
2914  if( (mRadiation.GetWavelengthType()==WAVELENGTH_MONOCHROMATIC)
2915  ||(mRadiation.GetWavelengthType()==WAVELENGTH_ALPHA12))
2916  x += m2ThetaDisplacement*cos(x/2) +m2ThetaTransparency*sin(x);
2917 
2918  return x+mXZero;
2919 }
2920 
2921 REAL PowderPattern::X2PixelCorr(const REAL x0)const
2922 {
2923  return this->X2Pixel(this->X2XCorr(x0));
2924 }
2925 
2926 REAL PowderPattern::X2Pixel(const REAL x)const
2927 {
2928  //:TODO: faster if the step is actually constant.
2929  // Step may not be constant, so we guess twice before step-search
2930  REAL pixx;
2931  if(mIsXAscending==false)
2932  {
2933  VFN_DEBUG_MESSAGE("PowderPattern::X2Pixel()",1)
2934  long pix=(long)(mNbPoint-1-(x-this->GetPowderPatternXMin())/this->GetPowderPatternXStep());
2935  if((pix>0)&&(pix<((long)mNbPoint-1)))
2936  {
2937  // Why floor() and ceil() don't return a bloody integer is beyond me
2938  const REAL localStep=mX(pix)-mX(pix+1);
2939  if(localStep>0) pix -= (long)((x-mX(pix))/localStep);
2940  }
2941  VFN_DEBUG_MESSAGE("PowderPattern::X2Pixel():"<<x<<","<<pix,1)
2942  if(pix<1) pix=1;
2943  if(pix>((long)mNbPoint-2))pix=(long)mNbPoint-2;
2944  VFN_DEBUG_MESSAGE("PowderPattern::X2Pixel():"<<x<<","<<pix<<","<<mX(pix),1)
2945  if(mX(pix)<x)
2946  {
2947  for(;;pix--)
2948  {
2949  VFN_DEBUG_MESSAGE("PowderPattern::X2Pixel():"<<x<<","<<pix<<","<<mX(pix),1)
2950  if(mX(pix)>=x) break;
2951  if(pix==0) break;
2952  }
2953  }
2954  else
2955  {
2956  for(;;pix++)
2957  {
2958  if(mX(pix)<=x) {pix--;break;}
2959  if(pix==((long)mNbPoint-2)) break;
2960  }
2961  }
2962  // This assumes step is at least localy constant...
2963  VFN_DEBUG_MESSAGE("PowderPattern::X2Pixel():"<<x<<","<<pix<<","<<mX(pix),1)
2964  const REAL localStep=mX(pix)-mX(pix+1);
2965  pixx = (REAL)pix-(x-mX(pix))/localStep;
2966  VFN_DEBUG_MESSAGE("PowderPattern::X2Pixel():"<<x<<","<<pix<<","<<mX(pix),1)
2967  }
2968  else
2969  {
2970  VFN_DEBUG_MESSAGE("PowderPattern::X2Pixel():"<<x<<","<<this->GetPowderPatternXMin()<<","<<this->GetPowderPatternXMax(),1)
2971  long pix=(long)((x-this->GetPowderPatternXMin())/this->GetPowderPatternXStep());
2972  if((pix>0)&&(pix<((long)mNbPoint-1)))
2973  {
2974  // Why floor() and ceil() don't return a bloody integer is beyond me
2975  const REAL localStep=mX(pix+1)-mX(pix);
2976  if(localStep>0) pix += (long)((x-mX(pix))/localStep);
2977  }
2978  VFN_DEBUG_MESSAGE("PowderPattern::X2Pixel():"<<x<<","<<pix,1)
2979  if(pix<1) pix=1;
2980  if(pix>((long)mNbPoint-2))pix=(long)mNbPoint-2;
2981  VFN_DEBUG_MESSAGE("PowderPattern::X2Pixel():"<<x<<","<<pix<<","<<mX(pix),1)
2982  if(x<mX(pix))
2983  {
2984  for(;;pix--)
2985  {
2986  VFN_DEBUG_MESSAGE("PowderPattern::X2Pixel():"<<x<<","<<pix<<","<<mX(pix),1)
2987  if(mX(pix)<=x) break;
2988  if(pix==0) break;
2989  }
2990  }
2991  else
2992  {
2993  for(;;pix++)
2994  {
2995  VFN_DEBUG_MESSAGE("PowderPattern::X2Pixel():"<<x<<","<<pix<<","<<mX(pix),1)
2996  if(mX(pix)>=x) {pix-- ;break;}
2997  if(pix==((long)mNbPoint-2)) break;
2998  }
2999  }
3000  VFN_DEBUG_MESSAGE("PowderPattern::X2Pixel():"<<x<<","<<pix<<","<<mX(pix),1)
3001  if(pix>((long)mNbPoint-2))pix=(long)mNbPoint-2;
3002  // This assumes step is at least localy constant...
3003  const REAL localStep=mX(pix+1)-mX(pix);
3004  VFN_DEBUG_MESSAGE("PowderPattern::X2Pixel():"<<x<<","<<pix<<","<<mX(pix)<<","<<localStep,1)
3005  pixx = (REAL)pix+(x-mX(pix))/localStep;
3006  }
3007  VFN_DEBUG_MESSAGE("PowderPattern::X2Pixel():"<<x<<","<<pixx,1)
3008  return pixx;
3009 }
3010 
3012 {
3013  //15.000 0.030 70.000 LANI4FE#1 REC 800 4JRS
3014  //2447. 2418. 2384. 2457. 2398. 2374. 2378. 2383.
3015  //...
3016  VFN_DEBUG_MESSAGE("PowderPattern::ImportPowderPatternFullprof() : \
3017 from file : "+filename,5)
3018  ifstream fin(filename.c_str());
3019  if(!fin)
3020  {
3021  throw ObjCrystException("PowderPattern::ImportPowderPatternFullprof() : \
3022 Error opening file for input:"+filename);
3023  }
3024  REAL min,max,step;
3025  fin >> min >> step >> max;
3026  min *= DEG2RAD;
3027  max *= DEG2RAD;
3028  step *= DEG2RAD;
3029  this->SetPowderPatternPar(min,step,(long)((max-min)/step+1.001));
3030  VFN_DEBUG_MESSAGE("PowderPattern::ImportPowderPatternFullprof() :"\
3031  << " 2Theta min=" << min*RAD2DEG << " 2Theta max=" << max*RAD2DEG \
3032  << " NbPoints=" << mNbPoint,5)
3033  mPowderPatternObs.resize (mNbPoint);
3036 
3037  char tmpComment[200];
3038  fin.getline(tmpComment,100);
3039  //if(""==mName) mName.append(tmpComment);
3040 
3041  for(unsigned long i=0;i<mNbPoint;i++) fin >> mPowderPatternObs(i);
3042  fin.close();
3043  this->SetSigmaToSqrtIobs();
3044  this->SetWeightToInvSigmaSq();
3046  this->UpdateDisplay();
3047  {
3048  char buf [200];
3049  sprintf(buf,"Imported powder pattern: %d points, 2theta=%7.3f -> %7.3f, step=%6.3f",
3050  (int)mNbPoint,min*RAD2DEG,max*RAD2DEG,step*RAD2DEG);
3051  (*fpObjCrystInformUser)((string)buf);
3052  }
3053  VFN_DEBUG_MESSAGE("PowderPattern::ImportFullProfPattern():finished:"<<mNbPoint<<" points",5)
3054 }
3055 
3056 void PowderPattern::ImportPowderPatternPSI_DMC(const string &filename)
3057 {
3058  VFN_DEBUG_MESSAGE("PowderPattern::ImportPowderPatternPSI_DMC() : \
3059 from file : "+filename,5)
3060  ifstream fin(filename.c_str());
3061  if(!fin)
3062  {
3063  throw ObjCrystException("PowderPattern::ImportPowderPatternPSI_DMC() : \
3064 Error opening file for input:"+filename);
3065  }
3066  //Skip the first two lines
3067  char tmpComment[200];
3068  fin.getline(tmpComment,190);
3069  fin.getline(tmpComment,190);
3070  REAL min,max,step;
3071  fin >> min >> step >> max;
3072  min *= DEG2RAD;
3073  max *= DEG2RAD;
3074  step *= DEG2RAD;
3075  this->SetPowderPatternPar(min,step,(unsigned long)((max-min)/step+1.001));
3076  VFN_DEBUG_MESSAGE("PowderPattern::ImportPowderPatternPSI_DMC() :"\
3077  << " 2Theta min=" << min*RAD2DEG << " 2Theta max=" << max*RAD2DEG \
3078  << " NbPoints=" << mNbPoint,5)
3079  mPowderPatternObs.resize (mNbPoint);
3082 
3083  fin.getline(tmpComment,100);
3084  //if(""==mName) mName.append(tmpComment);
3085 
3086  for(unsigned long i=0;i<mNbPoint;i++) fin >> mPowderPatternObs(i);
3087  for(unsigned long i=0;i<mNbPoint;i++) fin >> mPowderPatternObsSigma(i);
3088  fin.close();
3089  this->SetWeightToInvSigmaSq();
3091  this->UpdateDisplay();
3092  {
3093  char buf [200];
3094  sprintf(buf,"Imported powder pattern: %d points, 2theta=%7.3f -> %7.3f, step=%6.3f",
3095  (int)mNbPoint,min*RAD2DEG,max*RAD2DEG,step*RAD2DEG);
3096  (*fpObjCrystInformUser)((string)buf);
3097  }
3098  VFN_DEBUG_MESSAGE("PowderPattern::ImportPowderPatternPSI_DMC():finished",5)
3099 }
3100 
3102 {
3103  VFN_DEBUG_MESSAGE("PowderPattern::ImportPowderPatternILL_D1AD2B() : \
3104 from file : "+filename,5)
3105  ifstream fin(filename.c_str());
3106  if(!fin)
3107  {
3108  throw ObjCrystException("PowderPattern::ImportPowderPatternILL_D1AD2B() : \
3109 Error opening file for input:"+filename);
3110  }
3111  //Skip the first three lines
3112  char tmpComment[200];
3113  fin.getline(tmpComment,190);
3114  fin.getline(tmpComment,190);
3115  fin.getline(tmpComment,190);
3116 
3117  fin >> mNbPoint;
3118  fin.getline(tmpComment,190);
3119  REAL min,step;
3120  fin >> min >> step;
3121  min *= DEG2RAD;
3122  step *= DEG2RAD;
3123  this->SetPowderPatternPar(min,step,mNbPoint);
3124  VFN_DEBUG_MESSAGE("PowderPattern::ImportPowderPatternILL_D1AD2B() :"\
3125  << " 2Theta min=" << min*RAD2DEG << " 2Theta max=" << min*RAD2DEG+mNbPoint*step*RAD2DEG \
3126  << " NbPoints=" << mNbPoint,5)
3127  mPowderPatternObs.resize (mNbPoint);
3130 
3131  //if(""==mName) mName.append(tmpComment);
3132 
3133  for(unsigned long i=0;i<mNbPoint;i++) fin >> mPowderPatternObs(i);
3134  for(unsigned long i=0;i<mNbPoint;i++) fin >> mPowderPatternObsSigma(i);
3135  fin.close();
3136  this->SetWeightToInvSigmaSq();
3138  this->UpdateDisplay();
3139  {
3140  char buf [200];
3141  sprintf(buf,"Imported powder pattern: %d points, 2theta=%7.3f -> %7.3f, step=%6.3f",
3142  (int)mNbPoint,min*RAD2DEG,(min+step*(mNbPoint-1))*RAD2DEG,
3143  step*RAD2DEG);
3144  (*fpObjCrystInformUser)((string)buf);
3145  }
3146  VFN_DEBUG_MESSAGE("PowderPattern::ImportPowderPatternILL_D1AD2B():finished",5)
3147 }
3148 
3149 void PowderPattern::ImportPowderPatternXdd(const string &filename)
3150 {
3151  VFN_DEBUG_MESSAGE("PowderPattern::ImportPowderPatternXdd():from file :" \
3152  +filename,5)
3153  ifstream fin (filename.c_str());
3154  if(!fin)
3155  {
3156  throw ObjCrystException("PowderPattern::ImportPowderPatternXdd() : \
3157 Error opening file for input:"+filename);
3158  }
3159  char tmpComment[200];
3160  fin.getline(tmpComment,100);
3161  //if(""==mName) mName.append(tmpComment);
3162  REAL min,max,step,tmp;
3163  fin >> min >> step >> max;
3164  min *= DEG2RAD;
3165  max *= DEG2RAD;
3166  step *= DEG2RAD;
3167  this->SetPowderPatternPar(min,step,(long)((max-min)/step+1.001));
3168  mPowderPatternObs.resize (mNbPoint);
3170  mPowderPatternCalc.resize(mNbPoint);
3173 
3174  fin >> tmp; //Count time
3175  fin >> tmp; //unused
3176  fin >> tmp; //unused (wavelength?)
3177 
3178  for(unsigned long i=0;i<mNbPoint;i++) fin >> mPowderPatternObs(i);
3179  fin.close();
3180  this->SetSigmaToSqrtIobs();
3181  this->SetWeightToInvSigmaSq();
3182  this->UpdateDisplay();
3183  {
3184  char buf [200];
3185  sprintf(buf,"Imported powder pattern: %d points, 2theta=%7.3f -> %7.3f, step=%6.3f",
3186  (int)mNbPoint,min*RAD2DEG,max*RAD2DEG,step*RAD2DEG);
3187  (*fpObjCrystInformUser)((string)buf);
3188  }
3189  VFN_DEBUG_MESSAGE("DiffractionDataPowder::ImportXddPattern() :finished",5)
3190 }
3191 
3193 {
3194  VFN_DEBUG_ENTRY("PowderPattern::ImportPowderPatternSietronicsCPI():from file :" \
3195  +filename,5)
3196  ifstream fin (filename.c_str());
3197  if(!fin)
3198  {
3199  throw ObjCrystException("PowderPattern::ImportPowderPatternSietronicsCPI() : \
3200 Error opening file for input:"+filename);
3201  }
3202  char tmpComment[300];
3203  fin.getline(tmpComment,100);
3204  VFN_DEBUG_MESSAGE(" ->Discarded comment :"<<tmpComment,1)
3205  REAL min,max,step;
3206  fin >> min >> max >> step;
3207  min *= DEG2RAD;
3208  max *= DEG2RAD;
3209  step *= DEG2RAD;
3210  this->SetPowderPatternPar(min,step,(long)((max-min)/step+1.001));
3211  mPowderPatternObs.resize (mNbPoint);
3213  mPowderPatternCalc.resize(mNbPoint);
3216 
3217  //Following lines are ignored (no fixed format ?)
3218  string str;
3219  do
3220  {
3221  fin>>str;
3222  VFN_DEBUG_MESSAGE(" ->Read :"<<str,1)
3223  } while ("SCANDATA"!=str);
3224 
3225  for(unsigned long i=0;i<mNbPoint;i++) fin >> mPowderPatternObs(i);
3226  fin.close();
3227  this->SetSigmaToSqrtIobs();
3228  this->SetWeightToInvSigmaSq();
3230  this->UpdateDisplay();
3231  {
3232  char buf [200];
3233  sprintf(buf,"Imported powder pattern: %d points, 2theta=%7.3f -> %7.3f, step=%6.3f",
3234  (int)mNbPoint,min*RAD2DEG,max*RAD2DEG,step*RAD2DEG);
3235  (*fpObjCrystInformUser)((string)buf);
3236  }
3237  VFN_DEBUG_EXIT("DiffractionDataPowder::ImportPowderPatternSietronicsCPI()",5)
3238 }
3239 
3240 void PowderPattern::ImportPowderPattern2ThetaObsSigma(const string &filename,const int nbSkip)
3241 {
3242  VFN_DEBUG_MESSAGE("DiffractionDataPowder::ImportPowderPattern2ThetaObsSigma():from:" \
3243  +filename,5)
3244  ifstream fin (filename.c_str());
3245  if(!fin)
3246  {
3247  throw ObjCrystException("PowderPattern::ImportPowderPattern2ThetaObsSigma():\
3248 Error opening file for input:"+filename);
3249  }
3250  {//Get rid of first lines
3251  char tmpComment[200];
3252  for(int i=0;i<nbSkip;i++) fin.getline(tmpComment,150);
3253  }
3254  mPowderPatternObs.resize (500);
3255  mPowderPatternObsSigma.resize(500);
3256  mX.resize(500);
3257  mNbPoint=0;
3258 
3259  do
3260  {
3261  fin >> mX (mNbPoint);
3262  fin >> mPowderPatternObs (mNbPoint);
3264  //cout << mX (mNbPoint)<<" "
3265  // << mPowderPatternObs (mNbPoint)<<" "
3266  // << mPowderPatternObsSigma(mNbPoint)<<endl;
3267  if(!fin) break;
3268  mNbPoint++;
3269  if( (mNbPoint%500)==0)
3270  {
3271  mX.resizeAndPreserve(mNbPoint+500);
3272  mPowderPatternObs.resizeAndPreserve(mNbPoint+500);
3273  mPowderPatternObsSigma.resizeAndPreserve(mNbPoint+500);
3274  }
3275  } while(fin.eof() == false);
3276  fin.close();
3277 
3278  mX.resizeAndPreserve (mNbPoint);
3279  mPowderPatternObs.resizeAndPreserve (mNbPoint);
3280  mPowderPatternObsSigma.resizeAndPreserve(mNbPoint);
3282 
3283  mX *= DEG2RAD;
3284 
3285  this->SetWeightToInvSigmaSq();
3287  this->UpdateDisplay();
3288  {
3289  char buf [200];
3290  sprintf(buf,"Imported powder pattern: %d points, 2theta=%7.3f -> %7.3f, step=%6.3f",
3291  (int)mNbPoint,this->GetPowderPatternXMin()*RAD2DEG,
3292  this->GetPowderPatternXMax()*RAD2DEG,
3293  this->GetPowderPatternXStep()*RAD2DEG);
3294  (*fpObjCrystInformUser)((string)buf);
3295  }
3296  VFN_DEBUG_MESSAGE("PowderPattern::ImportPowderPattern2ThetaObsSigma()\
3297 :finished: "<<mNbPoint<<" points",5)
3298 }
3299 
3300 void PowderPattern::ImportPowderPattern2ThetaObs(const string &filename,const int nbSkip)
3301 {
3302  VFN_DEBUG_MESSAGE("PowderPattern::ImportPowderPattern2ThetaObs():from:" \
3303  +filename,5)
3304  ifstream fin (filename.c_str());
3305  if(!fin)
3306  {
3307  throw ObjCrystException("PowderPattern::ImportPowderPattern2ThetaObs():\
3308 Error opening file for input:"+filename);
3309  }
3310  {//Get rid of first lines
3311  char tmpComment[200];
3312  for(int i=0;i<nbSkip;i++) fin.getline(tmpComment,150);
3313  }
3314  mPowderPatternObs.resize (500);
3315  mPowderPatternObsSigma.resize(500);
3316  mX.resize(500);
3317  mNbPoint=0;
3318 
3319  do
3320  {
3321  fin >> mX(mNbPoint);
3322  fin >> mPowderPatternObs (mNbPoint);
3324  =sqrt(mPowderPatternObs(mNbPoint));
3325  if(!fin) break;
3326  mNbPoint++;
3327  if( (mNbPoint%500)==0)
3328  {
3329  mX.resizeAndPreserve(mNbPoint+500);
3330  mPowderPatternObs.resizeAndPreserve(mNbPoint+500);
3331  mPowderPatternObsSigma.resizeAndPreserve(mNbPoint+500);
3332  }
3333  } while(fin.eof() == false);
3334  fin.close();
3335 
3336  mX.resizeAndPreserve (mNbPoint);
3337  mPowderPatternObs.resizeAndPreserve (mNbPoint);
3338  mPowderPatternObsSigma.resizeAndPreserve(mNbPoint);
3340 
3341  mX *= DEG2RAD;
3342 
3343  this->SetSigmaToSqrtIobs();
3344  this->SetWeightToInvSigmaSq();
3346  this->UpdateDisplay();
3347  {
3348  char buf [200];
3349  sprintf(buf,"Imported powder pattern: %d points, 2theta=%7.3f -> %7.3f, step=%6.3f",
3350  (int)mNbPoint,this->GetPowderPatternXMin()*RAD2DEG,
3351  this->GetPowderPatternXMax()*RAD2DEG,
3352  this->GetPowderPatternXStep()*RAD2DEG);
3353  (*fpObjCrystInformUser)((string)buf);
3354  }
3355  VFN_DEBUG_MESSAGE("PowderPattern::ImportPowderPattern2ThetaObs():finished",5)
3356 }
3357 
3359 {
3360 
3361  //Sample 4: NaY + CF2=CCL2 T=20K, Lambda: 2.343 A.
3362  // 100 0 0.100 70 0 0
3363  // 3.000
3364  // 500000. 12000. 0.00 0.00
3365  //70 570369 569668 562868 532769 527469 495669 481969 452767 429468 4132
3366  //68 393269 372067 353769 337068 328268 310270 299469 296470 294668 2780
3367  //...
3368  //14 255814 282714 274014 281314 300314 302714 301114 298014 313214 3097
3369  //14 286914 295714 305214 300714 288311 295511 288511 3024 8 2937 7 2883
3370  // 7 2905 7 2895 7 2767 7 2777 7 2758 7 2495 7 2507 7 2496 7 2382 7 2329
3371  // 7 2542 7 2415 7 2049 7 2389 7 2270 7 2157 6 2227 6 2084 3 1875 2 2094
3372  // 1 1867
3373  // -1000
3374  // -10000
3375  VFN_DEBUG_MESSAGE("PowderPattern::ImportPowderPatternMultiDetectorLLBG42() : \
3376 from file : "+filename,5)
3377  ifstream fin(filename.c_str());
3378  if(!fin)
3379  {
3380  throw ObjCrystException("PowderPattern::ImportPowderPatternMultiDetectorLLBG42() : \
3381 Error opening file for input:"+filename);
3382  }
3383 
3384  string str;
3385  getline(fin,str);
3386  float junk;
3387  REAL min,step;
3388  fin >>junk>>junk>>step>>junk>>junk>>junk>>min>>junk>>junk>>junk>>junk;
3389  min *= DEG2RAD;
3390  step *= DEG2RAD;
3391  VFN_DEBUG_MESSAGE("PowderPattern::ImportPowderPatternMultiDetectorLLBG42() :"\
3392  << " 2Theta min=" << min*RAD2DEG << " 2Theta step=" << step*RAD2DEG,5)
3393  mPowderPatternObs.resize (500);
3394  mPowderPatternObsSigma.resize (500);
3395 
3396  getline(fin,str);//finish reading line
3397 
3398  float tmp;
3399  string sub;
3400  float ct,iobs;
3401  mNbPoint=0;
3402  for(;;)
3403  {
3404  getline(fin,str);
3405  sscanf(str.c_str(),"%f",&tmp);
3406  if(tmp<0) break;
3407  const unsigned int nb=str.length()/8;
3408  for(unsigned int i=0;i<nb;i++)
3409  {
3410  if(mNbPoint==(unsigned int)mPowderPatternObs.numElements())
3411  {
3412  mPowderPatternObs.resizeAndPreserve(mNbPoint+500);
3413  mPowderPatternObsSigma.resizeAndPreserve(mNbPoint+500);
3414  }
3415  sub=str.substr(i*8,8);
3416  sscanf(sub.c_str(),"%2f%6f",&ct,&iobs);
3418  mPowderPatternObsSigma(mNbPoint++)=sqrt(iobs/ct);
3419  }
3420  }
3421  this->SetPowderPatternPar(min,step,mNbPoint);
3422  //exit(1);
3423  mPowderPatternObs.resizeAndPreserve (mNbPoint);
3424  mPowderPatternObsSigma.resizeAndPreserve (mNbPoint);
3425  mPowderPatternWeight.resizeAndPreserve(mNbPoint);
3426 
3427  fin.close();
3428  this->SetWeightToInvSigmaSq();
3430  this->UpdateDisplay();
3431  {
3432  char buf [200];
3433  sprintf(buf,"Imported powder pattern: %d points, 2theta=%7.3f -> %7.3f, step=%6.3f",
3434  (int)mNbPoint,min*RAD2DEG,mX(mNbPoint-1)*RAD2DEG,step*RAD2DEG);
3435  (*fpObjCrystInformUser)((string)buf);
3436  }
3437  VFN_DEBUG_MESSAGE("PowderPattern::ImportPowderPatternMultiDetectorLLBG42():finished:"<<mNbPoint<<" points",5)
3438 }
3439 
3441 {
3442  //1.550 0.005 66.000
3443  // 213.135 193.243 208.811 185.873 231.607 200.995 196.792 187.516 215.977 199.634
3444  // 17.402 16.570 12.180 11.491 18.141 11.950 11.824 11.542 17.518 11.909
3445  // 211.890 185.740 204.610 200.645 199.489 169.549 203.189 178.298 186.241 198.522
3446  // 12.269 11.487 17.051 11.939 11.905 10.975 16.992 11.255 11.503 11.876
3447  VFN_DEBUG_MESSAGE("PowderPattern::ImportPowderPatternFullprof4() : \
3448 from file : "+filename,5)
3449  ifstream fin(filename.c_str());
3450  if(!fin)
3451  {
3452  throw ObjCrystException("PowderPattern::ImportPowderPatternFullprof4() : \
3453 Error opening file for input:"+filename);
3454  }
3455  REAL min,step,max;
3456  fin >> min >> step >> max;
3457  min *= DEG2RAD;
3458  max *= DEG2RAD;
3459  step *= DEG2RAD;
3460  this->SetPowderPatternPar(min,step,(long)((max-min)/step+1.001));
3461  VFN_DEBUG_MESSAGE("PowderPattern::ImportPowderPatternFullprof4() :"\
3462  << " 2Theta min=" << min*RAD2DEG << " 2Theta max=" << max*RAD2DEG \
3463  << " NbPoints=" << mNbPoint,5)
3464  mPowderPatternObs.resize (mNbPoint);
3467 
3468  string str;
3469  getline(fin,str);//read end of first line
3470 
3471  unsigned ct=0;
3472  unsigned ctSig=0;
3473  float line[10];
3474  for(;ct<mNbPoint;)
3475  {
3476  getline(fin,str);
3477  for(unsigned int i=0;i<str.size();i++) if(' '==str[i]) str[i]='0';
3478  sscanf(str.c_str(),"%8f%8f%8f%8f%8f%8f%8f%8f%8f%8f",
3479  line+0,line+1,line+2,line+3,line+4,line+5,line+6,line+7,line+8,line+9);
3480  for(unsigned int j=0;j<10;j++)
3481  if(ct<mNbPoint) mPowderPatternObs(ct++)=line[j];
3482  getline(fin,str);
3483  for(unsigned int i=0;i<str.size();i++) if(' '==str[i]) str[i]='0';
3484  sscanf(str.c_str(),"%8f%8f%8f%8f%8f%8f%8f%8f%8f%8f",
3485  line+0,line+1,line+2,line+3,line+4,line+5,line+6,line+7,line+8,line+9);
3486  for(unsigned int j=0;j<10;j++)
3487  if(ctSig<mNbPoint) mPowderPatternObsSigma(ctSig++)=line[j];
3488  }
3489  fin.close();
3490  this->SetWeightToInvSigmaSq();
3492  this->UpdateDisplay();
3493  {
3494  char buf [200];
3495  sprintf(buf,"Imported powder pattern: %d points, 2theta=%7.3f -> %7.3f, step=%6.3f",
3496  (int)mNbPoint,min*RAD2DEG,max*RAD2DEG,
3497  step*RAD2DEG);
3498  (*fpObjCrystInformUser)((string)buf);
3499  }
3500  VFN_DEBUG_MESSAGE("PowderPattern::ImportFullProfPattern4():finished:"<<mNbPoint<<" points",5)
3501 }
3502 
3504 {
3505  VFN_DEBUG_MESSAGE("DiffractionDataPowder::ImportPowderPatternTOF_ISIS_XYSigma():from:" \
3506  +filename,5)
3507  ifstream fin (filename.c_str());
3508  if(!fin)
3509  {
3510  throw ObjCrystException("PowderPattern::ImportPowderPatternTOF_ISIS_XYSigma():\
3511 Error opening file for input:"+filename);
3512  }
3513  {//Get rid of first line
3514  char junk[400];
3515  fin.getline(junk,150);
3516  }
3517  mPowderPatternObs.resize (500);
3518  mPowderPatternObsSigma.resize(500);
3519  mX.resize(500);
3520  mNbPoint=0;
3521 
3522  do
3523  {
3524  fin >> mX (mNbPoint);
3525  fin >> mPowderPatternObs (mNbPoint);
3527  //cout << mX (mNbPoint)<<" "
3528  // << mPowderPatternObs (mNbPoint)<<" "
3529  // << mPowderPatternObsSigma(mNbPoint)<<endl;
3530  if(!fin) break;
3531  mNbPoint++;
3532  if( (mNbPoint%500)==0)
3533  {
3534  mX.resizeAndPreserve(mNbPoint+500);
3535  mPowderPatternObs.resizeAndPreserve(mNbPoint+500);
3536  mPowderPatternObsSigma.resizeAndPreserve(mNbPoint+500);
3537  }
3538  } while(fin.eof() == false);
3539  fin.close();
3540 
3541  mX.resizeAndPreserve (mNbPoint);
3542  mPowderPatternObs.resizeAndPreserve (mNbPoint);
3543  mPowderPatternObsSigma.resizeAndPreserve(mNbPoint);
3545 
3546  // Reverse order of arrays, so that we are in ascending order of sin(theta)/lambda
3547  REAL tmp;
3548  for(unsigned long i=0;i<(mNbPoint/2);i++)
3549  {
3550  tmp=mX(i);
3551  mX(i)=mX(mNbPoint-1-i);
3552  mX(mNbPoint-1-i)=tmp;
3553 
3554  tmp=mPowderPatternObs(i);
3556  mPowderPatternObs(mNbPoint-1-i)=tmp;
3557 
3558  tmp=mPowderPatternObsSigma(i);
3561  }
3562  this->SetPowderPatternX(mX);
3563 
3564  this->SetWeightToInvSigmaSq();
3565  this->SetRadiationType(RAD_NEUTRON);
3566  this->GetRadiation().SetWavelengthType(WAVELENGTH_TOF);
3568  this->UpdateDisplay();
3569  {
3570  char buf [200];
3571  sprintf(buf,"Imported TOF powder pattern: %d points, TOF=%7.3f -> %7.3f",
3572  (int)mNbPoint,this->GetPowderPatternXMin(),
3573  this->GetPowderPatternXMax());
3574  (*fpObjCrystInformUser)((string)buf);
3575  }
3576  VFN_DEBUG_MESSAGE("PowderPattern::ImportPowderPatternTOF_ISIS_XYSigma()\
3577 :finished: "<<mNbPoint<<" points",5)
3578 }
3579 
3580 void PowderPattern::ImportPowderPatternGSAS(const string &filename)
3581 {
3582  VFN_DEBUG_ENTRY("PowderPattern::ImportPowderPatternGSAS():file:"<<filename,5)
3583  ifstream fin (filename.c_str());
3584  if(!fin)
3585  {
3586  throw ObjCrystException("PowderPattern::ImportPowderPatternGSAS():\
3587 Error opening file for input:"+filename);
3588  }
3589  {//Get rid of title
3590  char title[81];
3591  fin.read(title,80);
3592  while(isprint(fin.peek())==false)
3593  {
3594  if(fin.eof()) break;
3595  fin.get();
3596  }
3597  cout<<"Title:"<<title<<endl;
3598  if(this->GetName()=="Change Me!") this->SetName(title);
3599  }
3600 
3601  //BANK 1 38101 7620 CONST 200.00 0.10 0 0 ESD
3602  int numBank,nbRecords;
3603  string binType, type;
3604  float bcoeff[4];
3605  //string line;
3606  char line[81];
3607  char bank[5];
3608  do
3609  {
3610  fin.getline(line,80);
3611  while(isprint(fin.peek())==false)
3612  {
3613  if(fin.eof()) break;
3614  fin.get();
3615  }
3616  sscanf(line,"%4s",bank);
3617  if(fin.eof())
3618  throw ObjCrystException("PowderPattern::ImportPowderPatternGSAS():\
3619 Could not find BANK statement !! In file: "+filename);
3620  }
3621  while(string(bank)!=string("BANK"));
3622 
3623  {
3624  line[80]='\0';
3625  char binTypeC[20],typeC[20];
3626  sscanf(line,"%4s%d %ld %d %s %f %f %f %f %s",bank,&numBank,&mNbPoint,&nbRecords,
3627  binTypeC,&bcoeff[0],&bcoeff[1],&bcoeff[2],&bcoeff[3],typeC);
3628  binType=binTypeC;
3629  type=typeC;
3630  }
3631  if(binType=="CONST") binType="CONS";
3632  if((type!="ALT")&&(type!="ESD")) type="STD";
3633 
3634  cout<<"BANK #"<<numBank<<endl;
3635  cout<<"Number of data points:"<<mNbPoint<<endl;
3636  cout<<"Number of records:"<<nbRecords<<endl;
3637  cout<<"BinType:"<<binType<<endl;
3638  cout<<"BCoeff[1-4]:"<<bcoeff[0]<<","<<bcoeff[1]<<","<<bcoeff[2]<<","<<bcoeff[3]<<endl;
3639  cout<<"Type:"<<type<<endl;
3640 
3641  mPowderPatternObs.resize (mNbPoint);
3643  mX.resize(mNbPoint);
3644  bool importOK=false;
3645  if((binType=="CONS") && (type=="ESD"))
3646  {
3647  this->SetPowderPatternPar(bcoeff[0]*DEG2RAD/100,bcoeff[1]*DEG2RAD/100,mNbPoint);
3648  string sub;
3649  unsigned long point=0;
3650  REAL iobs,isig;
3651  string substr;
3652  for(long i=0;i<nbRecords;i++)
3653  {
3654  fin.read(line,80);
3655  line[80]='\0';
3656  while(isprint(fin.peek())==false)
3657  {
3658  if(fin.eof()) break;
3659  fin.get();
3660  }
3661  for(unsigned int j=0;j<5;j++)
3662  {
3663  /*
3664  substr=string(line).substr(j*16,16);
3665  sscanf(substr.c_str(),"%8f%8f",&iobs,&isig);
3666  */
3667  substr=string(line).substr(j*16+0 ,8);
3668  istringstream(substr) >> iobs;
3669  substr=string(line).substr(j*16+8 ,8);
3670  istringstream(substr) >> isig;
3671 
3672  mPowderPatternObs(point)=iobs;
3673  mPowderPatternObsSigma(point++)=isig;
3674  if(point==mNbPoint) break;
3675  }
3676  if(point==mNbPoint) break;
3677  }
3678  importOK=true;
3679  }
3680  if((binType=="CONS") && (type=="STD"))
3681  {
3682  this->SetPowderPatternPar(bcoeff[0]*DEG2RAD/100,bcoeff[1]*DEG2RAD/100,mNbPoint);
3683  unsigned long point=0;
3684  REAL iobs;
3685  int nc;
3686  string substr;
3687  for(long i=0;i<nbRecords;i++)
3688  {
3689  fin.read(line,80);
3690  line[80]='\0';
3691  while(isprint(fin.peek())==false)
3692  {
3693  if(fin.eof()) break;
3694  fin.get();
3695  }
3696  for(unsigned int j=0;j<10;j++)
3697  {
3698  /*
3699  substr=string(line).substr(j*8,8);
3700  if(substr.substr(0,2)==string(" "))
3701  {
3702  nc=1;
3703  sscanf(substr.c_str(),"%8f",&iobs);
3704  }
3705  else sscanf(substr.c_str(),"%2d%6f",&nc,&iobs);
3706  */
3707  substr=string(line).substr(j*8+0 ,2);
3708  if(substr==" ") nc=1;
3709  else sscanf(substr.c_str(),"%d",&nc);
3710  substr=string(line).substr(j*8+2 ,6);
3711  istringstream(substr) >> iobs;
3712  mPowderPatternObs(point)=iobs;
3713  mPowderPatternObsSigma(point++)=sqrt(iobs)/sqrt((REAL)nc);
3714  if(point==mNbPoint) break;
3715  }
3716  if(point==mNbPoint) break;
3717  }
3718  importOK=true;
3719  }
3720  if((binType=="RALF") && (type=="ALT"))
3721  {
3722  this->SetRadiationType(RAD_NEUTRON);
3723  this->GetRadiation().SetWavelengthType(WAVELENGTH_TOF);
3725 
3726  unsigned long point=0;
3727  REAL x,iobs,iobssigma;
3728  string substr;
3729  for(long i=0;i<nbRecords;i++)
3730  {
3731  fin.read(line,80);
3732  line[80]='\0';
3733  while(isprint(fin.peek())==false)
3734  {
3735  if(fin.eof()) break;
3736  fin.get();
3737  }
3738  for(unsigned int j=0;j<4;j++)
3739  {//4 records per line
3740  /* Does not work because sscanf ignores the leading spaces and shifts the reading !
3741  substr=string(line).substr(j*20,20);
3742  sscanf(substr.c_str(),"%8f%7f%5f",&x,&iobs,&iobssigma);
3743  */
3744  substr=string(line).substr(j*20+0 ,8);
3745  istringstream(substr) >> x;
3746  substr=string(line).substr(j*20+8 ,7);
3747  istringstream(substr) >> iobs;
3748  substr=string(line).substr(j*20+15,5);
3749  istringstream(substr) >> iobssigma;
3750  mPowderPatternObs(point)=iobs;
3751  mPowderPatternObsSigma(point)=iobssigma;
3752  mX(point)=x/32;
3753  if(++point==mNbPoint) break;
3754  }
3755  if(point==mNbPoint) break;
3756  }
3757  // Reverse order of arrays, so that we are in ascending order of sin(theta)/lambda
3758  REAL tmp;
3759  for(unsigned long i=0;i<(mNbPoint/2);i++)
3760  {
3761  tmp=mX(i);
3762  mX(i)=mX(mNbPoint-1-i);
3763  mX(mNbPoint-1-i)=tmp;
3764 
3765  tmp=mPowderPatternObs(i);
3767  mPowderPatternObs(mNbPoint-1-i)=tmp;
3768 
3769  tmp=mPowderPatternObsSigma(i);
3772  }
3773  importOK=true;
3774  }
3775  fin.close();
3776  if(!importOK)
3777  {
3778  mNbPoint=0;
3779  mPowderPatternObs.resize (mNbPoint);
3781  mX.resize(mNbPoint);
3782  throw ObjCrystException("PowderPattern::ImportPowderPatternGSAS(): Sorry, \
3783 this type of format is not handled yet (send an example file to the Fox author)!:"+filename);
3784  }
3786  this->SetPowderPatternX(mX);
3787  this->SetWeightToInvSigmaSq();
3788 
3789  this->UpdateDisplay();
3790  if(this->GetRadiation().GetWavelengthType()==WAVELENGTH_TOF)
3791  {
3792  char buf [200];
3793  sprintf(buf,"Imported powder pattern: %d points, tof=%7.3f us-> %7.3f us",
3794  (int)mNbPoint,this->GetPowderPatternXMin(),
3795  this->GetPowderPatternXMax());
3796  (*fpObjCrystInformUser)((string)buf);
3797  }
3798  else
3799  {
3800  char buf [200];
3801  sprintf(buf,"Imported powder pattern: %d points, 2theta=%7.3f -> %7.3f, step=%6.3f",
3802  (int)mNbPoint,this->GetPowderPatternXMin()*RAD2DEG,
3803  this->GetPowderPatternXMax()*RAD2DEG,
3804  this->GetPowderPatternXStep()*RAD2DEG);
3805  (*fpObjCrystInformUser)((string)buf);
3806  }
3807  VFN_DEBUG_EXIT("PowderPattern::ImportPowderPatternGSAS():file:"<<filename,5)
3808 }
3809 
3811 {
3812  VFN_DEBUG_ENTRY("PowderPattern::ImportPowderPatternCIF():file:",5)
3813  for(map<string,CIFData>::const_iterator pos=cif.mvData.begin();pos!=cif.mvData.end();++pos)
3814  if(pos->second.mPowderPatternObs.size()>10)
3815  {
3816  mNbPoint=pos->second.mPowderPatternObs.size();
3817  mX.resize(mNbPoint);
3818  mPowderPatternObs.resize(mNbPoint);
3821  if(pos->second.mDataType==WAVELENGTH_TOF)
3822  {
3823  this->SetRadiationType(RAD_NEUTRON);
3824  this->GetRadiation().SetWavelengthType(WAVELENGTH_TOF);
3826  }
3827  else this->GetRadiation().SetWavelength(pos->second.mWavelength);
3828  for(unsigned long i=0;i<mNbPoint;++i)
3829  {
3830  mPowderPatternObs(i)=pos->second.mPowderPatternObs[i];
3831  mX(i)=pos->second.mPowderPatternX[i];
3832  mPowderPatternObsSigma(i)=pos->second.mPowderPatternSigma[i];
3833  }
3834  this->SetWeightToInvSigmaSq();
3835  this->SetPowderPatternX(mX);
3836  }
3837  VFN_DEBUG_EXIT("PowderPattern::ImportPowderPatternCIF():file:",5)
3838 }
3839 
3840 
3841 void PowderPattern::SetPowderPatternObs(const CrystVector_REAL& obs)
3842 {
3843  VFN_DEBUG_MESSAGE("PowderPattern::SetPowderPatternObs()",5)
3844  if((unsigned long)obs.numElements() != mNbPoint)
3845  {
3846  throw(ObjCrystException("PowderPattern::SetPowderPatternObs(vect): The \
3847 supplied vector of observed intensities does not have the expected number of points!"));
3848  }
3849 
3850  mPowderPatternObs=obs;
3851  mPowderPatternObsSigma.resize(mPowderPatternObs.numElements());
3853 
3854  this->SetSigmaToSqrtIobs();
3855  this->SetWeightToInvSigmaSq();
3856  mClockIntegratedFactorsPrep.Reset();
3857  {
3858  char buf [200];
3859  sprintf(buf,"Changed powder pattern: %d points, 2theta=%7.3f -> %7.3f, step=%6.3f",
3860  (int)mNbPoint,mX(0)*RAD2DEG,mX(mNbPoint-1)*RAD2DEG,
3861  (mX(mNbPoint-1)-mX(0))/(mNbPoint-1)*RAD2DEG);
3862  (*fpObjCrystInformUser)((string)buf);
3863  }
3864 }
3865 void PowderPattern::SavePowderPattern(const string &filename) const
3866 {
3867  VFN_DEBUG_MESSAGE("PowderPattern::SavePowderPattern",5)
3868  this->CalcPowderPattern();
3869  ofstream out(filename.c_str());
3870  CrystVector_REAL ttheta;
3871  ttheta=mX;
3872  if(this->GetRadiation().GetWavelengthType()!=WAVELENGTH_TOF) ttheta *= RAD2DEG;
3873 
3874  CrystVector_REAL diff;
3875  diff=mPowderPatternObs;
3876  diff-=mPowderPatternCalc;
3877  out << "# 2Theta/TOF Iobs ICalc Iobs-Icalc Weight Comp0" << endl;
3878  out << FormatVertVector<REAL>(ttheta,
3881  diff,mPowderPatternWeight,
3882  mPowderPatternComponentRegistry.GetObj(0).mPowderPatternCalc,16,8);
3883  out.close();
3884  VFN_DEBUG_MESSAGE("DiffractionDataPowder::SavePowderPattern:End",3)
3885 }
3886 
3887 void PowderPattern::PrintObsCalcData(ostream&os)const
3888 {
3889  VFN_DEBUG_MESSAGE("DiffractionDataPowder::PrintObsCalcData()",5);
3890  CrystVector_REAL ttheta;
3891  ttheta=mX;
3892  if(this->GetRadiation().GetWavelengthType()!=WAVELENGTH_TOF) ttheta *= RAD2DEG;
3893  os << "PowderPattern : " << mName <<endl;
3894  os << " 2Theta/TOF Obs Sigma Calc Weight" <<endl;
3895  os << FormatVertVector<REAL>(ttheta,mPowderPatternObs,mPowderPatternObsSigma,
3897  // mPowderPatternComponentRegistry.GetObj(0).mPowderPatternCalc,12,4);
3898 }
3899 
3901 {
3902  if( (0==this->GetPowderPatternObs().numElements())
3903  ||(0==GetNbPowderPatternComponent()))
3904  {
3905  return 0;
3906  }
3907  this->CalcPowderPattern();
3908  TAU_PROFILE("PowderPattern::GetR()","void ()",TAU_DEFAULT);
3909 
3910  REAL tmp1=0.;
3911  REAL tmp2=0.;
3912 
3913  unsigned long maxPoints=mNbPointUsed;
3914  if( (true==mStatisticsExcludeBackground)
3915  &&(mPowderPatternBackgroundCalc.numElements()>0))
3916  {
3917  const REAL *p1, *p2, *p3;
3918  p1=mPowderPatternCalc.data();
3919  p2=mPowderPatternObs.data();
3920  p3=mPowderPatternBackgroundCalc.data();
3921  const long nbExclude=mExcludedRegionMinX.numElements();
3922  if(0==nbExclude)
3923  {
3924  VFN_DEBUG_MESSAGE("PowderPattern::GetR():Exclude Backgd",4);
3925  for(unsigned long i=0;i<maxPoints;i++)
3926  {
3927  tmp1 += ((*p1)-(*p2)) * ((*p1)-(*p2));
3928  tmp2 += ((*p2)-(*p3)) * ((*p2)-(*p3));
3929  p1++;p2++;p3++;
3930  }
3931  }
3932  else
3933  {
3934  VFN_DEBUG_MESSAGE("PowderPattern::GetR():Exclude Backgd,Exclude regions",4);
3935  unsigned long min,max;
3936  unsigned long i=0;
3937  for(int j=0;j<nbExclude;j++)
3938  {
3939  min=(unsigned long)floor(this->X2Pixel(mExcludedRegionMinX(j)));
3940  max=(unsigned long)ceil (this->X2Pixel(mExcludedRegionMaxX(j)));
3941  if(min>maxPoints) break;
3942  if(max>maxPoints)max=maxPoints;
3943  for(;i<min;i++)
3944  {
3945  tmp1 += ((*p1)-(*p2)) * ((*p1)-(*p2));
3946  tmp2 += ((*p2)-(*p3)) * ((*p2)-(*p3));
3947  p1++;p2++;p3++;
3948  }
3949  p1 += max-i;
3950  p2 += max-i;
3951  p3 += max-i;
3952  i += max-i;
3953  }
3954  for(;i<maxPoints;i++)
3955  {
3956  tmp1 += ((*p1)-(*p2)) * ((*p1)-(*p2));
3957  tmp2 += ((*p2)-(*p3)) * ((*p2)-(*p3));
3958  p1++;p2++;p3++;
3959  }
3960 
3961  }
3962  } // Exclude Background ?
3963  else
3964  {
3965  const REAL *p1, *p2;
3966  p1=mPowderPatternCalc.data();
3967  p2=mPowderPatternObs.data();
3968  const long nbExclude=mExcludedRegionMinX.numElements();
3969  if(0==nbExclude)
3970  {
3971  VFN_DEBUG_MESSAGE("PowderPattern::GetR()",4);
3972  for(unsigned long i=0;i<maxPoints;i++)
3973  {
3974  tmp1 += ((*p1)-(*p2))*((*p1)-(*p2));
3975  tmp2 += (*p2) * (*p2);
3976  //cout <<i<<":"<< tmp1 << " "<<tmp2 << " " << *p1 <<" "<<*p2<<endl;
3977  p1++;p2++;
3978  }
3979  }
3980  else
3981  {
3982  VFN_DEBUG_MESSAGE("PowderPattern::GetR(),Exclude regions",4);
3983  unsigned long min,max;
3984  unsigned long i=0;
3985  for(int j=0;j<nbExclude;j++)
3986  {
3987  min=(unsigned long)floor(this->X2Pixel(mExcludedRegionMinX(j)));
3988  max=(unsigned long)ceil (this->X2Pixel(mExcludedRegionMaxX(j)));
3989  if(min>maxPoints) break;
3990  if(max>maxPoints)max=maxPoints;
3991  for(;i<min;i++)
3992  {
3993  tmp1 += ((*p1)-(*p2))*((*p1)-(*p2));
3994  tmp2 += (*p2) * (*p2);
3995  p1++;p2++;
3996  }
3997  p1 += max-i;
3998  p2 += max-i;
3999  i += max-i;
4000  }
4001  for(;i<maxPoints;i++)
4002  {
4003  tmp1 += ((*p1)-(*p2))*((*p1)-(*p2));
4004  tmp2 += (*p2) * (*p2);
4005  p1++;p2++;
4006  }
4007  }
4008  }
4009 
4010  VFN_DEBUG_MESSAGE("PowderPattern::GetR()="<<sqrt(tmp1/tmp2),4);
4011  //cout << FormatVertVector<REAL>(mPowderPatternCalc,mPowderPatternObs);
4012  //this->SavePowderPattern("refinedPattern.out");
4013  //abort();
4014  return sqrt(tmp1/tmp2);
4015 }
4016 
4017 REAL PowderPattern::GetIntegratedR()const
4018 {
4019  if( (0==this->GetPowderPatternObs().numElements())
4020  ||(0==GetNbPowderPatternComponent()))
4021  {
4022  return 0;
4023  }
4024  this->CalcPowderPattern();
4025  this->PrepareIntegratedRfactor();
4026  VFN_DEBUG_ENTRY("PowderPattern::GetIntegratedR()",4);
4027  TAU_PROFILE("PowderPattern::GetIntegratedR()","void ()",TAU_DEFAULT);
4028 
4029  REAL tmp1=0.;
4030  REAL tmp2=0.;
4031  const long numInterval=mIntegratedPatternMin.numElements();
4032  if( (true==mStatisticsExcludeBackground)
4033  &&(mPowderPatternBackgroundCalc.numElements()>0))
4034  {
4035  const REAL *p1, *p2, *p3;
4036  CrystVector_REAL integratedCalc(numInterval);
4037  integratedCalc=0;
4038  CrystVector_REAL backgdCalc(numInterval);
4039  backgdCalc=0;
4040  REAL *pp1=integratedCalc.data();
4041  REAL *pp2=backgdCalc.data();
4042  for(int i=0;i<numInterval;i++)
4043  {
4044  const long max=mIntegratedPatternMax(i);
4045  p1=mPowderPatternCalc.data()+mIntegratedPatternMin(i);
4046  for(int j=mIntegratedPatternMin(i);j<=max;j++) *pp1 += *p1++;
4047  pp1++;
4048  p1=mPowderPatternBackgroundCalc.data()+mIntegratedPatternMin(i);
4049  for(int j=mIntegratedPatternMin(i);j<=max;j++) *pp2 += *p1++;
4050  pp2++;
4051  }
4052 
4053  p1=integratedCalc.data();
4054  p2=mIntegratedObs.data();
4055  p3=backgdCalc.data();
4056  VFN_DEBUG_MESSAGE("PowderPattern::GetIntegratedR():Exclude Backgd",2);
4057  for(long i=0;i<numInterval;i++)
4058  {
4059  tmp1 += ((*p1)-(*p2)) * ((*p1)-(*p2));
4060  tmp2 += ((*p2)-(*p3)) * ((*p2)-(*p3));
4061  p1++;p2++;p3++;
4062  }
4063  } // Exclude Background ?
4064  else
4065  {
4066  const REAL *p1, *p2;
4067  CrystVector_REAL integratedCalc(numInterval);
4068  integratedCalc=0;
4069  REAL *pp1=integratedCalc.data();
4070  for(int i=0;i<numInterval;i++)
4071  {
4072  const long max=mIntegratedPatternMax(i);
4073  p1=mPowderPatternCalc.data()+mIntegratedPatternMin(i);
4074  for(int j=mIntegratedPatternMin(i);j<=max;j++) *pp1 += *p1++;
4075  pp1++;
4076  }
4077  p1=integratedCalc.data();
4078  p2=mIntegratedObs.data();
4079  VFN_DEBUG_MESSAGE("PowderPattern::GetIntegratedR()",2);
4080  for(long i=0;i<numInterval;i++)
4081  {
4082  tmp1 += ((*p1)-(*p2))*((*p1)-(*p2));
4083  tmp2 += (*p2) * (*p2);
4084  //cout <<i<<":"<< tmp1 << " "<<tmp2 << " " << *p1 <<" "<<*p2<<endl;
4085  p1++;p2++;
4086  }
4087  }
4088 
4089  VFN_DEBUG_EXIT("PowderPattern::GetIntegratedR()="<<sqrt(tmp1/tmp2),4);
4090  return sqrt(tmp1/tmp2);
4091 }
4092 
4094 {
4095  if( (0==this->GetPowderPatternObs().numElements())
4096  ||(0==GetNbPowderPatternComponent()))
4097  {
4098  return 0;
4099  }
4100  this->CalcPowderPattern();
4101  TAU_PROFILE("PowderPattern::GetRw()","void ()",TAU_DEFAULT);
4102  VFN_DEBUG_MESSAGE("PowderPattern::GetRw()",3);
4103 
4104 
4105  //cout <<FormatVertVector<REAL>(mPowderPatternObs,
4106  // mPowderPatternCalc,
4107  // mPowderPatternWeight);
4108  REAL tmp1=0.;
4109  REAL tmp2=0.;
4110 
4111  unsigned long maxPoints=mNbPointUsed;
4112 
4113  if( (true==mStatisticsExcludeBackground)
4114  &&(mPowderPatternBackgroundCalc.numElements()>0))
4115  {
4116  VFN_DEBUG_MESSAGE("PowderPattern::GetRw():Exclude Backgd",3);
4117  const REAL *p1, *p2, *p3, *p4;
4118  p1=mPowderPatternCalc.data();
4119  p2=mPowderPatternObs.data();
4120  p3=mPowderPatternBackgroundCalc.data();
4121  p4=mPowderPatternWeight.data();
4122  const long nbExclude=mExcludedRegionMinX.numElements();
4123  if(0==nbExclude)
4124  {
4125  for(unsigned long i=0;i<maxPoints;i++)
4126  {
4127  tmp1 += *p4 * ((*p1)-(*p2)) * ((*p1)-(*p2));
4128  tmp2 += *p4++ * ((*p2)-(*p3)) * ((*p2)-(*p3));
4129  p1++;p2++;p3++;
4130  }
4131  }
4132  else
4133  {
4134  unsigned long min,max;
4135  unsigned long i=0;
4136  for(int j=0;j<nbExclude;j++)
4137  {
4138  min=(unsigned long)floor(this->X2Pixel(mExcludedRegionMinX(j)));
4139  max=(unsigned long)ceil (this->X2Pixel(mExcludedRegionMaxX(j)));
4140  if(min>maxPoints) break;
4141  if(max>maxPoints)max=maxPoints;
4142  for(;i<min;i++)
4143  {
4144  tmp1 += *p4 * ((*p1)-(*p2)) * ((*p1)-(*p2));
4145  tmp2 += *p4++ * ((*p2)-(*p3)) * ((*p2)-(*p3));
4146  p1++;p2++;p3++;
4147  }
4148  p1 += max-i;
4149  p2 += max-i;
4150  p3 += max-i;
4151  p4 += max-i;
4152  i += max-i;
4153  }
4154  for(;i<maxPoints;i++)
4155  {
4156  tmp1 += *p4 * ((*p1)-(*p2)) * ((*p1)-(*p2));
4157  tmp2 += *p4++ * ((*p2)-(*p3)) * ((*p2)-(*p3));
4158  p1++;p2++;p3++;
4159  }
4160 
4161  }
4162  }
4163  else
4164  {
4165  VFN_DEBUG_MESSAGE("PowderPattern::GetRw()",3);
4166  const REAL *p1, *p2, *p4;
4167  p1=mPowderPatternCalc.data();
4168  p2=mPowderPatternObs.data();
4169  p4=mPowderPatternWeight.data();
4170  const long nbExclude=mExcludedRegionMinX.numElements();
4171  if(0==nbExclude)
4172  {
4173  for(unsigned long i=0;i<maxPoints;i++)
4174  {
4175  tmp1 += *p4 * ((*p1)-(*p2))*((*p1)-(*p2));
4176  tmp2 += *p4++ * (*p2) * (*p2);
4177  p1++;p2++;
4178  }
4179  }
4180  else
4181  {
4182  unsigned long min,max;
4183  unsigned long i=0;
4184  for(int j=0;j<nbExclude;j++)
4185  {
4186  min=(unsigned long)floor(this->X2Pixel(mExcludedRegionMinX(j)));
4187  max=(unsigned long)ceil (this->X2Pixel(mExcludedRegionMaxX(j)));
4188  if(min>maxPoints) break;
4189  if(max>maxPoints)max=maxPoints;
4190  for(;i<min;i++)
4191  {
4192  tmp1 += *p4 * ((*p1)-(*p2))*((*p1)-(*p2));
4193  tmp2 += *p4++ * (*p2) * (*p2);
4194  p1++;p2++;
4195  }
4196  p1 += max-i;
4197  p2 += max-i;
4198  p4 += max-i;
4199  i += max-i;
4200  }
4201  for(;i<maxPoints;i++)
4202  {
4203  tmp1 += *p4 * ((*p1)-(*p2))*((*p1)-(*p2));
4204  tmp2 += *p4++ * (*p2) * (*p2);
4205  p1++;p2++;
4206  }
4207  }
4208  }
4209  VFN_DEBUG_MESSAGE("PowderPattern::GetRw()="<<sqrt(tmp1/tmp2),3);
4210  return sqrt(tmp1/tmp2);
4211 }
4212 REAL PowderPattern::GetIntegratedRw()const
4213 {
4214  if( (0==this->GetPowderPatternObs().numElements())
4215  ||(0==GetNbPowderPatternComponent()))
4216  {
4217  return 0;
4218  }
4219  this->CalcPowderPattern();
4220  this->PrepareIntegratedRfactor();
4221  TAU_PROFILE("PowderPattern::GetIntegratedRw()","void ()",TAU_DEFAULT);
4222 
4223  REAL tmp1=0.;
4224  REAL tmp2=0.;
4225  const long numInterval=mIntegratedPatternMin.numElements();
4226  if( (true==mStatisticsExcludeBackground)
4227  &&(mPowderPatternBackgroundCalc.numElements()>0))
4228  {
4229  const REAL *p1, *p2, *p3, *p4;
4230  CrystVector_REAL integratedCalc(numInterval);
4231  integratedCalc=0;
4232  CrystVector_REAL backgdCalc(numInterval);
4233  backgdCalc=0;
4234  REAL *pp1=integratedCalc.data();
4235  REAL *pp2=backgdCalc.data();
4236  for(int i=0;i<numInterval;i++)
4237  {
4238  const long max=mIntegratedPatternMax(i);
4239  p1=mPowderPatternCalc.data()+mIntegratedPatternMin(i);
4240  for(int j=mIntegratedPatternMin(i);j<=max;j++) *pp1 += *p1++;
4241  pp1++;
4242  p1=mPowderPatternBackgroundCalc.data()+mIntegratedPatternMin(i);
4243  for(int j=mIntegratedPatternMin(i);j<=max;j++) *pp2 += *p1++;
4244  pp2++;
4245  }
4246 
4247  p1=integratedCalc.data();
4248  p2=mIntegratedObs.data();
4249  p3=backgdCalc.data();
4250  if(mIntegratedWeight.numElements()==0) p4=mIntegratedWeightObs.data();
4251  else p4=mIntegratedWeight.data();
4252  VFN_DEBUG_MESSAGE("PowderPattern::GetIntegratedRw():Exclude Backgd",4);
4253  for(long i=0;i<numInterval;i++)
4254  {
4255  tmp1 += *p4 * ((*p1)-(*p2)) * ((*p1)-(*p2));
4256  tmp2 += *p4++ * ((*p2)-(*p3)) * ((*p2)-(*p3));
4257  //cout <<i<<": " <<mIntegratedPatternMin(i)<<"->"<<mIntegratedPatternMax(i)
4258  // <<" "<< tmp1 << " "<<tmp2 << " " << *p1 <<" "<<*p2<<" "<<*p3<<" "<<*(p4-1) <<endl;
4259  p1++;p2++;p3++;
4260  }
4261  } // Exclude Background ?
4262  else
4263  {
4264  const REAL *p1, *p2, *p4;
4265  CrystVector_REAL integratedCalc(numInterval);
4266  integratedCalc=0;
4267  REAL *pp1=integratedCalc.data();
4268  for(int i=0;i<numInterval;i++)
4269  {
4270  const long max=mIntegratedPatternMax(i);
4271  p1=mPowderPatternCalc.data()+mIntegratedPatternMin(i);
4272  for(int j=mIntegratedPatternMin(i);j<=max;j++) *pp1 += *p1++;
4273  pp1++;
4274  }
4275  p1=integratedCalc.data();
4276  p2=mIntegratedObs.data();
4277  if(mIntegratedWeight.numElements()==0) p4=mIntegratedWeightObs.data();
4278  else p4=mIntegratedWeight.data();
4279  VFN_DEBUG_MESSAGE("PowderPattern::GetIntegratedRw()",4);
4280  for(long i=0;i<numInterval;i++)
4281  {
4282  tmp1 += *p4 * ((*p1)-(*p2))*((*p1)-(*p2));
4283  tmp2 += *p4++ * (*p2) * (*p2);
4284  //cout <<i<<":"<< tmp1 << " "<<tmp2 << " " << *p1 <<" "<<*p2<<endl;
4285  p1++;p2++;
4286  }
4287  }
4288 
4289  VFN_DEBUG_MESSAGE("PowderPattern::GetIntegratedRw()="<<sqrt(tmp1/tmp2),4);
4290  //cout << FormatVertVector<REAL>(mPowderPatternCalc,mPowderPatternObs);
4291  //this->SavePowderPattern("refinedPattern.out");
4292  //abort();
4293  return sqrt(tmp1/tmp2);
4294 }
4295 
4297 {
4298  if( (0==this->GetPowderPatternObs().numElements())
4299  ||(0==GetNbPowderPatternComponent()))
4300  {
4301  mChi2=0.;
4302  return mChi2;
4303  }
4304  this->CalcNbPointUsed();
4305  if(mClockChi2>mClockMaster) return mChi2;
4306 
4307  this->CalcPowderPattern();
4308  if( (mClockChi2>mClockPowderPatternPar)
4309  &&(mClockChi2>mClockScaleFactor)
4310  &&(mClockChi2>mClockPowderPatternCalc)) return mChi2;
4311  // We want the best scale factor
4312  this->FitScaleFactorForRw();
4313 
4314  TAU_PROFILE("PowderPattern::GetChi2()","void ()",TAU_DEFAULT);
4315 
4316  VFN_DEBUG_ENTRY("PowderPattern::GetChi2()",3);
4317 
4318  const unsigned long maxPoints=mNbPointUsed;
4319 
4320  mChi2=0.;
4321  mChi2LikeNorm=0.;
4322  VFN_DEBUG_MESSAGE("PowderPattern::GetChi2()Integrated profiles",3);
4323  const REAL * RESTRICT p1, * RESTRICT p2, * RESTRICT p3;
4324  p1=mPowderPatternCalc.data();
4325  p2=mPowderPatternObs.data();
4326  p3=mPowderPatternWeight.data();
4327  const long nbExclude=mExcludedRegionMinX.numElements();
4328  if(0==nbExclude)
4329  {
4330  for(unsigned long i=0;i<maxPoints;i++)
4331  {
4332  mChi2 += *p3 * ((*p1)-(*p2))*((*p1)-(*p2));
4333  if(*p3<=0) p3++;
4334  else mChi2LikeNorm -= log(*p3++);
4335  p1++;p2++;
4336  }
4337  }
4338  else
4339  {
4340  unsigned long min,max;
4341  unsigned long i=0;
4342  for(int j=0;j<nbExclude;j++)
4343  {
4344  min=(unsigned long)floor(this->X2Pixel(mExcludedRegionMinX(j)));
4345  max=(unsigned long)ceil (this->X2Pixel(mExcludedRegionMaxX(j)));
4346  if(min>maxPoints) break;
4347  if(max>maxPoints)max=maxPoints;
4348  for(;i<min;i++)
4349  {
4350  mChi2 += *p3 * ((*p1)-(*p2))*((*p1)-(*p2));
4351  if(*p3<=0) p3++;
4352  else mChi2LikeNorm -= log(*p3++);
4353  p1++;p2++;
4354  }
4355  p1 += max-i;
4356  p2 += max-i;
4357  p3 += max-i;
4358  i += max-i;
4359  }
4360  for(;i<maxPoints;i++)
4361  {
4362  mChi2 += *p3 * ((*p1)-(*p2))*((*p1)-(*p2));
4363  if(*p3<=0) p3++;
4364  else mChi2LikeNorm -= log(*p3++);
4365  p1++;p2++;
4366  }
4367  }
4368  mChi2LikeNorm/=2;
4369  VFN_DEBUG_MESSAGE("Chi^2="<<mChi2<<", log(norm)="<<mChi2LikeNorm,3)
4370  mClockChi2.Click();
4371  VFN_DEBUG_EXIT("PowderPattern::GetChi2()="<<mChi2,3);
4372  return mChi2;
4373 }
4374 
4376 {
4377  if( (0==this->GetPowderPatternObs().numElements())
4378  ||(0==GetNbPowderPatternComponent()))
4379  {
4380  mIntegratedChi2=0.;
4381  return mIntegratedChi2;
4382  }
4383  this->CalcNbPointUsed();
4384  if(mClockIntegratedChi2>mClockMaster) return mIntegratedChi2;
4385 
4387  if( (mClockChi2>mClockPowderPatternPar)
4388  &&(mClockChi2>mClockScaleFactor)
4389  &&(mClockChi2>mClockPowderPatternIntegratedCalc)) return mIntegratedChi2;
4390 
4391  // We want the best scale factor
4392  this->FitScaleFactorForIntegratedRw();
4393 
4394  TAU_PROFILE("PowderPattern::GetIntegratedChi2()","void ()",TAU_DEFAULT);
4395 
4396  VFN_DEBUG_ENTRY("PowderPattern::GetIntegratedChi2()",3);
4397 
4398  mIntegratedChi2=0.;
4399  mIntegratedChi2LikeNorm=0.;
4400  VFN_DEBUG_MESSAGE("PowderPattern::GetIntegratedChi2()",3);
4401  const REAL * RESTRICT p1, * RESTRICT p2, * RESTRICT p3;
4402  p1=mPowderPatternIntegratedCalc.data();
4403  p2=mIntegratedObs.data();
4404  if(mIntegratedWeight.numElements()==0) p3=mIntegratedWeightObs.data();
4405  else p3=mIntegratedWeight.data();
4406  double weightProd=1.;
4407  VFN_DEBUG_MESSAGE("PowderPattern::GetIntegratedIntegratedRw()",4);
4408  for(unsigned long i=0;i<mNbIntegrationUsed;)
4409  {
4410  // group weights to avoid computing too many log()
4411  // group only a limited number to avoid underflow...
4412  for(unsigned long j=0;j<32;++j)
4413  {
4414  mIntegratedChi2 += *p3 * ((*p1)-(*p2))*((*p1)-(*p2));
4415  if(*p3>0) weightProd *= *p3;
4416  p1++;p2++;p3++;
4417  if(++i == mNbIntegrationUsed) break;
4418  }
4419  mIntegratedChi2LikeNorm -= log(weightProd);
4420  weightProd=1.;
4421  }
4422  mIntegratedChi2LikeNorm/=2;
4423  VFN_DEBUG_MESSAGE("Chi^2="<<mIntegratedChi2<<", log(norm)="<<mIntegratedChi2LikeNorm,3)
4424  mClockIntegratedChi2.Click();
4425  VFN_DEBUG_EXIT("PowderPattern::GetChi2()="<<mIntegratedChi2,3);
4426  return mIntegratedChi2;
4427 }
4428 
4430 {
4431  if(0 == mOptProfileIntegration.GetChoice()) return this->GetIntegratedChi2();
4432  else return this->GetChi2();
4433 }
4434 
4436 {
4437  if( (0==this->GetPowderPatternObs().numElements())
4438  ||(0==GetNbPowderPatternComponent()))
4439  {
4440  return ;
4441  }
4442  this->CalcPowderPattern();
4443  TAU_PROFILE("PowderPattern::FitScaleFactorForR()","void ()",TAU_DEFAULT);
4444  VFN_DEBUG_ENTRY("PowderPattern::FitScaleFactorForR()",3);
4445  // Which components are scalable ?
4446  mScalableComponentIndex.resize(mPowderPatternComponentRegistry.GetNb());
4447  int nbScale=0;
4448  for(int i=0;i<mPowderPatternComponentRegistry.GetNb();i++)
4449  {
4450  if(mPowderPatternComponentRegistry.GetObj(i).IsScalable())
4451  mScalableComponentIndex(nbScale++)=i;
4452  }
4453  VFN_DEBUG_MESSAGE("-> Number of Scale Factors:"<<nbScale<<":Index:"<<endl<<mScalableComponentIndex,3);
4454  if(0==nbScale)
4455  {
4456  VFN_DEBUG_EXIT("PowderPattern::FitScaleFactorForR(): No scalable component!",3);
4457  return;
4458  }
4459  mScalableComponentIndex.resizeAndPreserve(nbScale);
4460  // prepare matrices
4461  mFitScaleFactorM.resize(nbScale,nbScale);
4462  mFitScaleFactorB.resize(nbScale,1);
4463  mFitScaleFactorX.resize(nbScale,1);
4464  // Build Matrix & Vector for LSQ
4465  const long nbExclude=mExcludedRegionMinX.numElements();
4466  if(0==nbExclude)
4467  {
4468  for(int i=0;i<nbScale;i++)
4469  {
4470  for(int j=i;j<nbScale;j++)
4471  {
4472  // Here use a direct access to the powder spectrum, since
4473  // we know it has just been recomputed
4474  const REAL *p1=mPowderPatternComponentRegistry.GetObj(mScalableComponentIndex(i))
4475  .mPowderPatternCalc.data();
4476  const REAL *p2=mPowderPatternComponentRegistry.GetObj(mScalableComponentIndex(j))
4477  .mPowderPatternCalc.data();
4478  REAL m=0.;
4479  for(unsigned long k=0;k<mNbPointUsed;k++) m += *p1++ * *p2++;
4480  mFitScaleFactorM(i,j)=m;
4481  mFitScaleFactorM(j,i)=m;
4482  }
4483  }
4484  for(int i=0;i<nbScale;i++)
4485  {
4486  const REAL *p1=mPowderPatternObs.data();
4487  const REAL *p2=mPowderPatternComponentRegistry.GetObj(mScalableComponentIndex(i))
4488  .mPowderPatternCalc.data();
4489  REAL b=0.;
4490  if(mPowderPatternBackgroundCalc.numElements()<=1)
4491  for(unsigned long k=0;k<mNbPointUsed;k++) b += *p1++ * *p2++;
4492  else
4493  {
4494  const REAL *p3=mPowderPatternBackgroundCalc.data();
4495  for(unsigned long k=0;k<mNbPointUsed;k++) b += (*p1++ - *p3++) * *p2++;
4496  }
4497  mFitScaleFactorB(i,0) =b;
4498  }
4499  }
4500  else
4501  {
4502  unsigned long min,max;
4503  for(int i=0;i<nbScale;i++)
4504  {
4505  for(int j=i;j<nbScale;j++)
4506  {
4507  // Here use a direct access to the powder spectrum, since
4508  // we know it has just been recomputed
4509  const REAL *p1=mPowderPatternComponentRegistry.GetObj(mScalableComponentIndex(i))
4510  .mPowderPatternCalc.data();
4511  const REAL *p2=mPowderPatternComponentRegistry.GetObj(mScalableComponentIndex(j))
4512  .mPowderPatternCalc.data();
4513  REAL m=0.;
4514  unsigned long l=0;
4515  for(int k=0;k<nbExclude;k++)
4516  {
4517  min=(unsigned long)floor(this->X2Pixel(mExcludedRegionMinX(j)));
4518  max=(unsigned long)ceil (this->X2Pixel(mExcludedRegionMaxX(j)));
4519  if(min>mNbPointUsed) break;
4520  if(max>mNbPointUsed)max=mNbPointUsed;
4522  for(;l<min;l++) m += *p1++ * *p2++;
4523  p1 += max-l;
4524  p2 += max-l;
4525  l = max;
4526  }
4527  for(;l<mNbPointUsed;l++) m += *p1++ * *p2++;
4528  mFitScaleFactorM(i,j)=m;
4529  mFitScaleFactorM(j,i)=m;
4530  }
4531  }
4532  for(int i=0;i<nbScale;i++)
4533  {
4534  const REAL *p1=mPowderPatternObs.data();
4535  const REAL *p2=mPowderPatternComponentRegistry
4536  .GetObj(mScalableComponentIndex(i))
4537  .mPowderPatternCalc.data();
4538  REAL b=0.;
4539  unsigned long l=0;
4540  if(mPowderPatternBackgroundCalc.numElements()<=1)
4541  {
4542  for(int k=0;k<nbExclude;k++)
4543  {
4544  min=(unsigned long)floor(this->X2Pixel(mExcludedRegionMinX(k)));
4545  max=(unsigned long)ceil (this->X2Pixel(mExcludedRegionMaxX(k)));
4546  if(min>mNbPointUsed) break;
4547  if(max>mNbPointUsed)max=mNbPointUsed;
4549  for(;l<min;l++) b += *p1++ * *p2++;
4550  p1 += max-l;
4551  p2 += max-l;
4552  l = max;
4553  }
4554  for(;l<mNbPointUsed;l++) b += *p1++ * *p2++;
4555  }
4556  else
4557  {
4558  const REAL *p3=mPowderPatternBackgroundCalc.data();
4559  for(int k=0;k<nbExclude;k++)
4560  {
4561  min=(unsigned long)floor(this->X2Pixel(mExcludedRegionMinX(k)));
4562  max=(unsigned long)ceil (this->X2Pixel(mExcludedRegionMaxX(k)));
4563  if(min>mNbPointUsed) break;
4564  if(max>mNbPointUsed)max=mNbPointUsed;
4566  for(;l<min;l++) b += (*p1++ - *p3++) * *p2++;
4567  p1 += max-l;
4568  p2 += max-l;
4569  l = max;
4570  }
4571  for(;l<mNbPointUsed;l++) b += (*p1++ - *p3++) * *p2++;
4572  }
4573  mFitScaleFactorB(i,0) =b;
4574  }
4575  }
4576  if(1==nbScale) mFitScaleFactorX=mFitScaleFactorB(0)/mFitScaleFactorM(0);
4577  else
4578  mFitScaleFactorX=product(InvertMatrix(mFitScaleFactorM),mFitScaleFactorB);
4579  VFN_DEBUG_MESSAGE("B, M, X"<<endl<<mFitScaleFactorB<<endl<<mFitScaleFactorM<<endl<<mFitScaleFactorX,2)
4580  for(int i=0;i<nbScale;i++)
4581  {
4582  const REAL * p1=mPowderPatternComponentRegistry.GetObj(mScalableComponentIndex(i))
4583  .mPowderPatternCalc.data();
4584  REAL * p0 = mPowderPatternCalc.data();
4585  const REAL s = mFitScaleFactorX(i)
4586  -mScaleFactor(mScalableComponentIndex(i));
4587  if(ISNAN_OR_INF(s))
4588  {
4589  (*fpObjCrystInformUser)("Warning:FitScaleFactorForR: working around NaN scale factor...");
4590  continue;
4591  }
4592  for(unsigned long j=0;j<mNbPointUsed;j++) *p0++ += s * *p1++;
4593  VFN_DEBUG_MESSAGE("-> Old:"<<mScaleFactor(mScalableComponentIndex(i)) <<" Change:"<<mFitScaleFactorX(i),2);
4594  mScaleFactor(mScalableComponentIndex(i)) = mFitScaleFactorX(i);
4596  mClockPowderPatternCalc.Click();//we *did* correct the spectrum
4597  }
4598  VFN_DEBUG_EXIT("PowderPattern::FitScaleFactorForR():End",3);
4599 }
4600 
4601 void PowderPattern::FitScaleFactorForIntegratedR()const
4602 {
4603  if( (0==this->GetPowderPatternObs().numElements())
4604  ||(0==GetNbPowderPatternComponent()))
4605  {
4606  return ;
4607  }
4608  this->CalcPowderPattern();
4609  this->PrepareIntegratedRfactor();
4610  VFN_DEBUG_ENTRY("PowderPattern::FitScaleFactorForIntegratedR()",3);
4611  TAU_PROFILE("PowderPattern::FitScaleFactorForIntegratedR()","void ()",TAU_DEFAULT);
4612  // Which components are scalable ?
4613  mScalableComponentIndex.resize(mPowderPatternComponentRegistry.GetNb());
4614  int nbScale=0;
4615  for(int i=0;i<mPowderPatternComponentRegistry.GetNb();i++)
4616  {
4617  if(mPowderPatternComponentRegistry.GetObj(i).IsScalable())
4618  mScalableComponentIndex(nbScale++)=i;
4619  }
4620  VFN_DEBUG_MESSAGE("-> Number of Scale Factors:"<<nbScale<<":Index:"<<endl<<mScalableComponentIndex,2);
4621  if(0==nbScale)
4622  {
4623  VFN_DEBUG_EXIT("PowderPattern::FitScaleFactorForIntegratedR(): No scalable component!",3);
4624  return;
4625  }
4626  mScalableComponentIndex.resizeAndPreserve(nbScale);
4627  // prepare matrices
4628  mFitScaleFactorM.resize(nbScale,nbScale);
4629  mFitScaleFactorB.resize(nbScale,1);
4630  mFitScaleFactorX.resize(nbScale,1);
4631  // Build Matrix & Vector for LSQ
4632  VFN_DEBUG_MESSAGE("PowderPattern::FitScaleFactorForIntegratedR():1",2);
4633  const long numInterval=mIntegratedPatternMin.numElements();
4634  CrystVector_REAL *integratedCalc= new CrystVector_REAL[nbScale];
4635  for(int i=0;i<nbScale;i++)
4636  {
4637  integratedCalc[i].resize(numInterval);
4638 
4639  // Here use a direct access to the powder spectrum, since
4640  // we know it has just been recomputed
4641  const REAL *p1=mPowderPatternComponentRegistry.GetObj(mScalableComponentIndex(i))
4642  .mPowderPatternCalc.data();
4643 
4644  REAL *p2=integratedCalc[i].data();
4645  for(int j=0;j<numInterval;j++)
4646  {
4647  const long max=mIntegratedPatternMax(j);
4648  p1=mPowderPatternComponentRegistry.GetObj(mScalableComponentIndex(i))
4649  .mPowderPatternCalc.data()+mIntegratedPatternMin(j);
4650  *p2=0;
4651  for(int k=mIntegratedPatternMin(j);k<=max;k++) *p2 += *p1++;
4652  //cout <<"Calc#"<<i<<":"<< mIntegratedPatternMin(j) << " "
4653  // <<mIntegratedPatternMax(j)<<" "
4654  // << *p2<<endl;
4655  p2++;
4656  }
4657  }
4658  VFN_DEBUG_MESSAGE("PowderPattern::FitScaleFactorForIntegratedR():2",2);
4659  CrystVector_REAL backdIntegrated(numInterval);
4660  if(mPowderPatternBackgroundCalc.numElements()>1)
4661  {
4662  const REAL *p1;
4663  REAL *p2=backdIntegrated.data();
4664  for(int j=0;j<numInterval;j++)
4665  {
4666  const long max=mIntegratedPatternMax(j);
4667  p1=mPowderPatternBackgroundCalc.data()+mIntegratedPatternMin(j);
4668  *p2=0;
4669  for(int k=mIntegratedPatternMin(j);k<=max;k++) *p2 += *p1++;
4670  //cout <<"Backgd:"<< mIntegratedPatternMin(j) << " "
4671  // <<mIntegratedPatternMax(j)<<" "
4672  // << *p2<<endl;
4673  p2++;
4674  }
4675  }
4676 
4677  //if(mPowderPatternBackgroundCalc.numElements()<=1)
4678  // cout<< FormatVertVector<REAL>(integratedCalc[0],mIntegratedObs,mIntegratedWeight,backdIntegrated)<<endl;
4679  //else
4680  // cout<< FormatVertVector<REAL>(integratedCalc[0],mIntegratedObs,mIntegratedWeight)<<endl;
4681  VFN_DEBUG_MESSAGE("PowderPattern::FitScaleFactorForIntegratedR():3",2);
4682  for(int i=0;i<nbScale;i++)
4683  {
4684  for(int j=i;j<nbScale;j++)
4685  {
4686  const REAL *p1=integratedCalc[i].data();
4687  const REAL *p2=integratedCalc[j].data();
4688  REAL m=0.;
4689  for(long k=0;k<numInterval;k++)
4690  {
4691  m += *p1++ * *p2++;
4692  //cout <<"M:"<< mIntegratedPatternMin(k) << " "<<mIntegratedPatternMax(k)<<" "<<m<<endl;
4693  }
4694  mFitScaleFactorM(i,j)=m;
4695  mFitScaleFactorM(j,i)=m;
4696  }
4697  }
4698  VFN_DEBUG_MESSAGE("PowderPattern::FitScaleFactorForIntegratedR():4",2);
4699  for(int i=0;i<nbScale;i++)
4700  {
4701  const REAL *p1=mIntegratedObs.data();
4702  const REAL *p2=integratedCalc[i].data();
4703  REAL b=0.;
4704  if(mPowderPatternBackgroundCalc.numElements()<=1)
4705  for(long k=0;k<numInterval;k++)
4706  {
4707  b += *p1++ * *p2++;
4708  //cout<<"B:"<<mIntegratedPatternMin(k)<<" "<<mIntegratedPatternMax(k)<<" "<<b<<endl;
4709  }
4710  else
4711  {
4712  const REAL *p3=backdIntegrated.data();
4713  for(long k=0;k<numInterval;k++)
4714  {
4715  //cout<<"B(minus backgd):"<<mIntegratedPatternMin(k)<<" "
4716  // <<mIntegratedPatternMax(k)<<" "
4717  // <<*p1<<" "<<*p2<<" "<<*p3<<" "<<b<<endl;
4718  b += (*p1++ - *p3++) * *p2++;
4719  }
4720  }
4721  mFitScaleFactorB(i,0) =b;
4722  }
4723  VFN_DEBUG_MESSAGE("PowderPattern::FitScaleFactorForIntegratedR():5",2);
4724 
4725  if(1==nbScale) mFitScaleFactorX=mFitScaleFactorB(0)/mFitScaleFactorM(0);
4726  else
4727  mFitScaleFactorX=product(InvertMatrix(mFitScaleFactorM),mFitScaleFactorB);
4728  VFN_DEBUG_MESSAGE("B, M, X"<<endl<<mFitScaleFactorB<<endl<<mFitScaleFactorM<<endl<<mFitScaleFactorX,3)
4729  for(int i=0;i<nbScale;i++)
4730  {
4731  const REAL * p1=mPowderPatternComponentRegistry.GetObj(mScalableComponentIndex(i))
4732  .mPowderPatternCalc.data();
4733  REAL * p0 = mPowderPatternCalc.data();
4734  const REAL s = mFitScaleFactorX(i)
4735  -mScaleFactor(mScalableComponentIndex(i));
4736  if(ISNAN_OR_INF(s))
4737  {
4738  (*fpObjCrystInformUser)("Warning:FitScaleFactorForIntegratedR: working around NaN scale factor...");
4739  continue;
4740  }
4741  for(unsigned long j=0;j<mNbPointUsed;j++) *p0++ += s * *p1++;
4742  VFN_DEBUG_MESSAGE("-> Old:"<<mScaleFactor(mScalableComponentIndex(i)) <<" New:"<<mFitScaleFactorX(i),3);
4743  mScaleFactor(mScalableComponentIndex(i)) = mFitScaleFactorX(i);
4745  mClockPowderPatternCalc.Click();//we *did* correct the spectrum
4746  }
4747  delete[] integratedCalc;
4748  VFN_DEBUG_EXIT("PowderPattern::FitScaleFactorForIntegratedR():End",3);
4749 }
4750 
4752 {
4753  if( (0==this->GetPowderPatternObs().numElements())
4754  ||(0==GetNbPowderPatternComponent()))
4755  {
4756  return ;
4757  }
4758  TAU_PROFILE("PowderPattern::FitScaleFactorForRw()","void ()",TAU_DEFAULT);
4759  VFN_DEBUG_ENTRY("PowderPattern::FitScaleFactorForRw()",3);
4760  this->CalcPowderPattern();
4761  //:TODO: take into account excluded regions...
4762  // Which components are scalable ?
4763  mScalableComponentIndex.resize(mPowderPatternComponentRegistry.GetNb());
4764  int nbScale=0;
4765  for(int i=0;i<mPowderPatternComponentRegistry.GetNb();i++)
4766  {
4767  if(mPowderPatternComponentRegistry.GetObj(i).IsScalable())
4768  mScalableComponentIndex(nbScale++)=i;
4769  }
4770  VFN_DEBUG_MESSAGE("-> Number of Scale Factors:"<<nbScale<<":Index:"<<endl<<mScalableComponentIndex,2);
4771  if(0==nbScale)
4772  {
4773  VFN_DEBUG_EXIT("PowderPattern::FitScaleFactorForRw(): No scalable component!",3);
4774  return;
4775  }
4776  mScalableComponentIndex.resizeAndPreserve(nbScale);
4777  // prepare matrices
4778  mFitScaleFactorM.resize(nbScale,nbScale);
4779  mFitScaleFactorB.resize(nbScale,1);
4780  mFitScaleFactorX.resize(nbScale,1);
4781  // Build Matrix & Vector for LSQ
4782  const long nbExclude=mExcludedRegionMinX.numElements();
4783  if(0==nbExclude)
4784  {
4785  for(int i=0;i<nbScale;i++)
4786  {
4787  for(int j=i;j<nbScale;j++)
4788  {
4789  // Here use a direct access to the powder spectrum, since
4790  // we know it has just been recomputed
4791  const REAL *p1=mPowderPatternComponentRegistry.GetObj(mScalableComponentIndex(i))
4792  .mPowderPatternCalc.data();
4793  const REAL *p2=mPowderPatternComponentRegistry.GetObj(mScalableComponentIndex(j))
4794  .mPowderPatternCalc.data();
4795  const REAL *p3=mPowderPatternWeight.data();
4796  REAL m=0.;
4797  for(unsigned long k=0;k<mNbPointUsed;k++) m += *p1++ * *p2++ * *p3++;
4798  mFitScaleFactorM(i,j)=m;
4799  mFitScaleFactorM(j,i)=m;
4800  }
4801  }
4802  for(int i=0;i<nbScale;i++)
4803  {
4804  const REAL *p1=mPowderPatternObs.data();
4805  const REAL *p2=mPowderPatternComponentRegistry.GetObj(mScalableComponentIndex(i))
4806  .mPowderPatternCalc.data();
4807  const REAL *p3=mPowderPatternWeight.data();
4808  REAL b=0.;
4809  if(mPowderPatternBackgroundCalc.numElements()<=1)
4810  for(unsigned long k=0;k<mNbPointUsed;k++) b += *p1++ * *p2++ * *p3++;
4811  else
4812  {
4813  const REAL *p4=mPowderPatternBackgroundCalc.data();
4814  for(unsigned long k=0;k<mNbPointUsed;k++)
4815  b += (*p1++ - *p4++) * *p2++ * *p3++;
4816  }
4817  mFitScaleFactorB(i,0) =b;
4818  }
4819  }
4820  else
4821  {
4822  unsigned long min,max;
4823  for(int i=0;i<nbScale;i++)
4824  {
4825  for(int j=i;j<nbScale;j++)
4826  {
4827  // Here use a direct access to the powder spectrum, since
4828  // we know it has just been recomputed
4829  const REAL *p1=mPowderPatternComponentRegistry.GetObj(mScalableComponentIndex(i))
4830  .mPowderPatternCalc.data();
4831  const REAL *p2=mPowderPatternComponentRegistry.GetObj(mScalableComponentIndex(j))
4832  .mPowderPatternCalc.data();
4833  const REAL *p3=mPowderPatternWeight.data();
4834  REAL m=0.;
4835  unsigned long l=0;
4836  for(int k=0;k<nbExclude;k++)
4837  {
4838  min=(unsigned long)floor(this->X2Pixel(mExcludedRegionMinX(j)));
4839  max=(unsigned long)ceil (this->X2Pixel(mExcludedRegionMaxX(j)));
4840  if(min>mNbPointUsed) break;
4841  if(max>mNbPointUsed)max=mNbPointUsed;
4843  for(;l<min;l++) m += *p1++ * *p2++ * *p3++;
4844  p1 += max-l;
4845  p2 += max-l;
4846  p3 += max-l;
4847  l = max;
4848  }
4849  for(;l<mNbPointUsed;l++) m += *p1++ * *p2++ * *p3++;
4850  mFitScaleFactorM(i,j)=m;
4851  mFitScaleFactorM(j,i)=m;
4852  }
4853  }
4854  for(int i=0;i<nbScale;i++)
4855  {
4856  const REAL *p1=mPowderPatternObs.data();
4857  const REAL *p2=mPowderPatternComponentRegistry
4858  .GetObj(mScalableComponentIndex(i))
4859  .mPowderPatternCalc.data();
4860  const REAL *p3=mPowderPatternWeight.data();
4861  REAL b=0.;
4862  unsigned long l=0;
4863  if(mPowderPatternBackgroundCalc.numElements()<=1)
4864  {
4865  for(int k=0;k<nbExclude;k++)
4866  {
4867  min=(unsigned long)floor(this->X2Pixel(mExcludedRegionMinX(k)));
4868  max=(unsigned long)ceil (this->X2Pixel(mExcludedRegionMaxX(k)));
4869  if(min>mNbPointUsed) break;
4870  if(max>mNbPointUsed)max=mNbPointUsed;
4872  for(;l<min;l++) b += *p1++ * *p2++ * *p3++;
4873  p1 += max-l;
4874  p2 += max-l;
4875  p3 += max-l;
4876  l = max;
4877  }
4878  for(;l<mNbPointUsed;l++) b += *p1++ * *p2++ * *p3++;
4879  }
4880  else
4881  {
4882  const REAL *p4=mPowderPatternBackgroundCalc.data();
4883  for(int k=0;k<nbExclude;k++)
4884  {
4885  min=(unsigned long)floor(this->X2Pixel(mExcludedRegionMinX(k)));
4886  max=(unsigned long)ceil (this->X2Pixel(mExcludedRegionMaxX(k)));
4887  if(min>mNbPointUsed) break;
4888  if(max>mNbPointUsed)max=mNbPointUsed;
4890  for(;l<min;l++) b += (*p1++ - *p4++) * *p2++ * *p3++;
4891  p1 += max-l;
4892  p2 += max-l;
4893  p3 += max-l;
4894  l = max;
4895  }
4896  for(;l<mNbPointUsed;l++) b += (*p1++ - *p4++) * *p2++ * *p3++;
4897  }
4898  mFitScaleFactorB(i,0) =b;
4899  }
4900  }
4901  if(1==nbScale) mFitScaleFactorX=mFitScaleFactorB(0)/mFitScaleFactorM(0);
4902  else
4903  mFitScaleFactorX=product(InvertMatrix(mFitScaleFactorM),mFitScaleFactorB);
4904  VFN_DEBUG_MESSAGE("B, M, X"<<endl<<mFitScaleFactorB<<endl<<mFitScaleFactorM<<endl<<mFitScaleFactorX,2)
4905  for(int i=0;i<nbScale;i++)
4906  {
4907  const REAL * p1=mPowderPatternComponentRegistry.GetObj(mScalableComponentIndex(i))
4908  .mPowderPatternCalc.data();
4909  REAL * p0 = mPowderPatternCalc.data();
4910  const REAL s = mFitScaleFactorX(i)
4911  -mScaleFactor(mScalableComponentIndex(i));
4912  if(ISNAN_OR_INF(s))
4913  {
4914  (*fpObjCrystInformUser)("Warning:FitScaleFactorForRw working around NaN scale factor...");
4915  continue;
4916  }
4917  for(unsigned long j=0;j<mNbPointUsed;j++) *p0++ += s * *p1++;
4918  VFN_DEBUG_MESSAGE("-> Old:"<<mScaleFactor(mScalableComponentIndex(i)) <<" Change:"<<mFitScaleFactorX(i),3);
4919  mScaleFactor(mScalableComponentIndex(i)) = mFitScaleFactorX(i);
4921  mClockPowderPatternCalc.Click();//we *did* correct the spectrum
4922  }
4923  VFN_DEBUG_EXIT("PowderPattern::FitScaleFactorForRw():End",3);
4924 }
4925 
4926 void PowderPattern::FitScaleFactorForIntegratedRw()const
4927 {
4928  if( (0==this->GetPowderPatternObs().numElements())
4929  ||(0==GetNbPowderPatternComponent()))
4930  {
4931  return ;
4932  }
4935  VFN_DEBUG_ENTRY("PowderPattern::FitScaleFactorForIntegratedRw()",3);
4936  TAU_PROFILE("PowderPattern::FitScaleFactorForIntegratedRw()","void ()",TAU_DEFAULT);
4937  // Which components are scalable ? Which scalable calculated components have a non-null variance ?
4938  mScalableComponentIndex.resize(mPowderPatternComponentRegistry.GetNb());
4939  CrystVector_REAL vScalableVarianceIndex(mPowderPatternComponentRegistry.GetNb());
4940  int nbScale=0;
4941  int nbVarCalc=0;
4942  for(int i=0;i<mPowderPatternComponentRegistry.GetNb();i++)
4943  {
4944  if(mPowderPatternComponentRegistry.GetObj(i).IsScalable())
4945  mScalableComponentIndex(nbScale++)=i;
4946  if(mPowderPatternComponentRegistry.GetObj(i).HasPowderPatternCalcVariance())
4947  {
4948  if(0!=mPowderPatternComponentRegistry.GetObj(i)
4949  .GetPowderPatternIntegratedCalcVariance().first->numElements())
4950  vScalableVarianceIndex(nbVarCalc++)=i;
4951  }
4952  }
4953  VFN_DEBUG_MESSAGE("-> Number of Scale Factors:"<<nbScale<<"("<<nbVarCalc
4954  <<"with variance). Index:"<<endl<<mScalableComponentIndex,2);
4955  if(0==nbScale)
4956  {
4957  VFN_DEBUG_EXIT("PowderPattern::FitScaleFactorForIntegratedRw(): No scalable component!",3);
4958  return;
4959  }
4960  bool again;
4961  unsigned int ctagain=0;
4962  RECALC_SCALE_FACTOR_VARIANCE_FitScaleFactorForIntegratedRw:
4963  if(false)//if((nbScale==1)&&(nbVarCalc==1))
4964  {// Special case when using ML error, the scale appears also in the weight so we have to
4965  // use a 2nd-degree equation (ax^2+bx+c=0) to get the scale factor.
4966  double a=0.,b=0.,c=0.;// possible overflows...
4967  REAL newscale;
4968  {
4969  const REAL * RESTRICT p1=mIntegratedObs.data();
4970  const REAL * RESTRICT p2=mPowderPatternComponentRegistry.GetObj(mScalableComponentIndex(0))
4971  .GetPowderPatternIntegratedCalc().first->data();
4972  const REAL * RESTRICT p1v=mIntegratedVarianceObs.data();
4973  const REAL * RESTRICT p2v=mPowderPatternComponentRegistry.GetObj(mScalableComponentIndex(0))
4974  .GetPowderPatternIntegratedCalcVariance().first->data();
4975  if(mPowderPatternBackgroundIntegratedCalc.numElements()<=1)
4976  {
4977  for(unsigned long k=mNbIntegrationUsed;k>0;k--)
4978  {
4979  a += *p2v * *p1 * *p2;
4980  b += *p2 * *p2 * *p1v - *p1 * *p1 * *p2v;
4981  c -= *p1 * *p2 * *p1v;
4982  p1++;p2++;p1v++;p2v++;
4983  }
4984  }
4985  else
4986  {
4987  const REAL * RESTRICT p3=mPowderPatternBackgroundIntegratedCalc.data();
4988  for(unsigned long k=mNbIntegrationUsed;k>0;k--)
4989  {
4990  a += *p2v * (*p1 - *p3) * *p2;
4991  b += *p2 * *p2 * *p1v - (*p1 - *p3) * (*p1 - *p3) * *p2v;
4992  c -= (*p1 - *p3) * *p2 * *p1v;
4993  p1++;p2++;p1v++;p2v++;p3++;
4994  }
4995  }
4996  // Only one >0 solution to the 2nd degree equation
4997  newscale=(REAL)((-b+sqrt(b*b-4*a*c))/(2*a));
4998  }
4999  {// Store new scale, and correct old calculated pattern
5000  const REAL s = newscale-mScaleFactor(mScalableComponentIndex(0));
5001  const REAL s2 = newscale*newscale
5002  -mScaleFactor(mScalableComponentIndex(0))
5003  *mScaleFactor(mScalableComponentIndex(0));
5004  REAL * RESTRICT p0 = mPowderPatternIntegratedCalc.data();
5005  const REAL * RESTRICT p1=mPowderPatternComponentRegistry.GetObj(mScalableComponentIndex(0))
5006  .GetPowderPatternIntegratedCalc().first->data();
5007  REAL * RESTRICT p0v = mPowderPatternVarianceIntegrated.data();
5008  const REAL * RESTRICT p1v=mPowderPatternComponentRegistry.GetObj(mScalableComponentIndex(0))
5009  .GetPowderPatternIntegratedCalcVariance().first->data();
5010  REAL * RESTRICT p0w = mIntegratedWeight.data();
5011  for(unsigned long j=mNbIntegrationUsed;j>0;j--)
5012  {
5013  *p0++ += s * *p1++;
5014  *p0v += s2 * *p1v++;
5015  if(*p0v <=0) {*p0w++ =0;p0v++;}else *p0w++ = 1. / *p0v++;
5016  }
5017  }
5018  mScaleFactor(mScalableComponentIndex(0)) = newscale;
5020  mClockPowderPatternIntegratedCalc.Click();//we *did* correct the spectrum
5021  }
5022  else
5023  {
5024  again=false;
5025  mScalableComponentIndex.resizeAndPreserve(nbScale);
5026  // prepare matrices
5027  mFitScaleFactorM.resize(nbScale,nbScale);
5028  mFitScaleFactorB.resize(nbScale,1);
5029  mFitScaleFactorX.resize(nbScale,1);
5030  // Build Matrix & Vector for LSQ
5031  VFN_DEBUG_MESSAGE("PowderPattern::FitScaleFactorForIntegratedRw():1",2);
5032  vector<const CrystVector_REAL*> integratedCalc;
5033  for(int i=0;i<nbScale;i++)
5034  {
5035  integratedCalc.push_back(mPowderPatternComponentRegistry.
5036  GetObj(mScalableComponentIndex(i))
5037  .GetPowderPatternIntegratedCalc().first);
5038  }
5039  VFN_DEBUG_MESSAGE("PowderPattern::FitScaleFactorForIntegratedRw():3",2);
5040  for(int i=0;i<nbScale;i++)
5041  {
5042  for(int j=i;j<nbScale;j++)
5043  {
5044  const REAL * RESTRICT p1=integratedCalc[i]->data();
5045  const REAL * RESTRICT p2=integratedCalc[j]->data();
5046  const REAL * RESTRICT p3;
5047  if(mIntegratedWeight.numElements()==0)
5048  {
5049  p3=mIntegratedWeightObs.data();
5050  if(ctagain>5) VFN_DEBUG_MESSAGE("ctagain="<<ctagain<<", using mIntegratedWeightObs",5);
5051  }
5052  else
5053  {
5054  p3=mIntegratedWeight.data();
5055  if(ctagain>5) VFN_DEBUG_MESSAGE("ctagain="<<ctagain<<", using mIntegratedWeight",5);
5056  }
5057  REAL m=0.;
5058  if(j==i)
5059  for(unsigned long k=mNbIntegrationUsed;k>0;k--)
5060  {m += *p1 * *p1 * *p3++; p1++;}
5061  else
5062  for(unsigned long k=mNbIntegrationUsed;k>0;k--)
5063  m += *p1++ * *p2++ * *p3++;
5064  mFitScaleFactorM(i,j)=m;
5065  mFitScaleFactorM(j,i)=m;
5066  }
5067  }
5068  VFN_DEBUG_MESSAGE("PowderPattern::FitScaleFactorForIntegratedRw():4",2);
5069  for(int i=0;i<nbScale;i++)
5070  {
5071  const REAL * RESTRICT p1=mIntegratedObs.data();
5072  const REAL * RESTRICT p2=integratedCalc[i]->data();
5073  const REAL * RESTRICT p4;
5074  if(mIntegratedWeight.numElements()==0) p4=mIntegratedWeightObs.data();
5075  else p4=mIntegratedWeight.data();
5076  REAL b=0.;
5077  if(mPowderPatternBackgroundIntegratedCalc.numElements()<=1)
5078  {
5079  for(unsigned long k=mNbIntegrationUsed;k>0;k--)
5080  {
5081  b += *p1++ * *p2++ * *p4++;
5082  //cout<<"B:"<<mIntegratedPatternMin(k)<<" "<<mIntegratedPatternMax(k)<<" "<<b<<endl;
5083  }
5084  }
5085  else
5086  {
5087  const REAL * RESTRICT p3=mPowderPatternBackgroundIntegratedCalc.data();
5088  for(unsigned long k=mNbIntegrationUsed;k>0;k--)
5089  {
5090  //cout<<"B(minus backgd):"<<mIntegratedPatternMin(k)<<" "
5091  // <<mIntegratedPatternMax(k)<<" "
5092  // <<*p1<<" "<<*p2<<" "<<*p3<<" "<<b<<endl;
5093  b += (*p1++ - *p3++) * *p2++ * *p4++;
5094  }
5095  }
5096  mFitScaleFactorB(i,0) =b;
5097  }
5098  VFN_DEBUG_MESSAGE("PowderPattern::FitScaleFactorForIntegratedRw():5",2);
5099 
5100  if(1==nbScale) mFitScaleFactorX=mFitScaleFactorB(0)/mFitScaleFactorM(0);
5101  else if(1<nbScale)
5102  mFitScaleFactorX=product(InvertMatrix(mFitScaleFactorM),mFitScaleFactorB);
5103  VFN_DEBUG_MESSAGE("B, M, X"<<endl<<mFitScaleFactorB<<endl<<mFitScaleFactorM<<endl<<mFitScaleFactorX,3)
5104  //Correct the variance, if necessary
5105  if(nbVarCalc>0)
5106  {
5107  //if(ctagain>0) cout <<"ctgain, sumvar="<<log(mPowderPatternVarianceIntegrated.sum());
5108  for(int i=0;i<nbScale;i++)
5109  {
5110  if(mPowderPatternComponentRegistry.GetObj(mScalableComponentIndex(i)).HasPowderPatternCalcVariance())
5111  {
5112  if(0!=mPowderPatternComponentRegistry.GetObj(mScalableComponentIndex(i))
5113  .GetPowderPatternIntegratedCalcVariance().first->numElements())
5114  {
5115  const REAL * RESTRICT p1=mPowderPatternComponentRegistry.GetObj(mScalableComponentIndex(i))
5116  .GetPowderPatternIntegratedCalcVariance().first->data();
5117  //cout <<",sumvar(i)="<<log(mPowderPatternComponentRegistry.GetObj(mScalableComponentIndex(i))
5118  // .GetPowderPatternIntegratedCalcVariance().first->sum());
5119  REAL * RESTRICT p0 = mPowderPatternVarianceIntegrated.data();
5120  const REAL s2 = mFitScaleFactorX(i)*mFitScaleFactorX(i)
5121  -mScaleFactor(mScalableComponentIndex(i))
5122  *mScaleFactor(mScalableComponentIndex(i));
5123  for(unsigned long j=mNbIntegrationUsed;j>0;j--) *p0++ += s2 * *p1++;
5124  }
5125  }
5126  }
5127  //if(ctagain>0) cout <<" ->"<<log(mPowderPatternVarianceIntegrated.sum())
5128  // <<" , sumobsvar="<<log(mIntegratedVarianceObs.sum())<<endl;
5129  REAL * RESTRICT p0 = mIntegratedWeight.data();
5130  const REAL * RESTRICT p1=mPowderPatternVarianceIntegrated.data();
5131  for(unsigned long j=mNbIntegrationUsed;j>0;j--)
5132  if(*p1 <=0) {*p0++ =0;p1++;}
5133  else *p0++ = 1. / *p1++;
5134 
5135  }
5136  // Correct the calculated integrated pattern
5137  for(int i=0;i<nbScale;i++)
5138  {
5139  const REAL * RESTRICT p1=mPowderPatternComponentRegistry.GetObj(mScalableComponentIndex(i))
5140  .GetPowderPatternIntegratedCalc().first->data();
5141  REAL * RESTRICT p0 = mPowderPatternIntegratedCalc.data();
5142  const REAL s = mFitScaleFactorX(i)
5143  -mScaleFactor(mScalableComponentIndex(i));
5144  if(ISNAN_OR_INF(s))
5145  {
5146  (*fpObjCrystInformUser)("Warning:FitScaleFactorForIntegratedRw: working around NaN scale factor...");
5147  continue;
5148  }
5149  if(nbVarCalc>0)
5150  {
5151  if(abs(s/mFitScaleFactorX(i))>0.001)
5152  {
5153  again=true;
5154  //cout<<"log(scale) :"<<log(mScaleFactor(mScalableComponentIndex(i)))
5155  // <<"->"<<log(mFitScaleFactorX(i))<<" Again="<<ctagain++<<endl;
5156  }
5157  if((!again)&&(ctagain>0))
5158  {
5159  VFN_DEBUG_MESSAGE("log(scale) :"<<log(mScaleFactor(mScalableComponentIndex(i)))
5160  <<"->"<<log(mFitScaleFactorX(i))<<" Again="<<ctagain,5);
5161  }
5162  }
5163  for(unsigned long j=mNbIntegrationUsed;j>0;j--) *p0++ += s * *p1++;
5164  if(ctagain>5)
5165  {
5166  VFN_DEBUG_MESSAGE("->log(scale) Old :"<<log(mScaleFactor(mScalableComponentIndex(i))) <<" New:"<<log(mFitScaleFactorX(i)),10);
5167  }
5168  mScaleFactor(mScalableComponentIndex(i)) = mFitScaleFactorX(i);
5169  }
5170 
5172  mClockPowderPatternIntegratedCalc.Click();//we *did* correct the spectrum
5173  }
5174  if(again && (ctagain<20))
5175  {
5176  ctagain++;
5177  if(ctagain>5)
5178  {
5179  VFN_DEBUG_MESSAGE("PowderPattern::FitScaleFactorForIntegratedRw(), scaling again #"<<ctagain,10)
5180  }
5181  goto RECALC_SCALE_FACTOR_VARIANCE_FitScaleFactorForIntegratedRw;
5182  }
5183  VFN_DEBUG_EXIT("PowderPattern::FitScaleFactorForIntegratedRw():End",3);
5184 }
5185 
5187 {
5188  VFN_DEBUG_MESSAGE("PowderPattern::SetSigmaToSqrtIobs()",5);
5189  for(long i=0;i<mPowderPatternObs.numElements();i++)
5190  mPowderPatternObsSigma(i)=sqrt(fabs(mPowderPatternObs(i)));
5191 }
5192 void PowderPattern::SetWeightToInvSigmaSq(const REAL minRelatSigma)
5193 {
5194  VFN_DEBUG_MESSAGE("PowderPattern::SetWeightToInvSigmaSq()",5);
5195  //:KLUDGE: If less than 1e-4*max, set to 0.... Do not give weight to unobserved points
5196  const REAL min=MaxAbs(mPowderPatternObsSigma)*minRelatSigma;
5197  //mPowderPatternWeight.resize(mPowderPatternObsSigma.numElements());
5198  REAL tmp;
5199  for(long i=0;i<mPowderPatternObsSigma.numElements();i++)
5200  {
5201  tmp = mPowderPatternObsSigma(i);
5202  if(tmp<min) mPowderPatternWeight(i)= 1./min/min;
5203  else mPowderPatternWeight(i) =1./tmp/tmp;
5204  }
5205 }
5207 {
5208  VFN_DEBUG_MESSAGE("PowderPattern::SetWeightToSinTheta()",5);
5209  //mPowderPatternWeight.resize(mPowderPatternObs.numElements());
5211 }
5212 void PowderPattern::SetWeightPolynomial(const REAL a, const REAL b,
5213  const REAL c,
5214  const REAL minRelatIobs)
5215 {
5216  VFN_DEBUG_MESSAGE("PowderPattern::SetWeightPolynomial()",5);
5217  const REAL min=MaxAbs(mPowderPatternObs)*minRelatIobs;
5218  REAL tmp;
5219  for(long i=0;i<mPowderPatternWeight.numElements();i++)
5220  {
5221  tmp=mPowderPatternObs(i);
5222  if(tmp<min)
5223  mPowderPatternWeight(i) = 1./(a+min+b*min*min+c*min*min*min);
5224  else mPowderPatternWeight(i) = 1./(a+tmp+b*tmp*tmp+c*tmp*tmp*tmp);
5225  }
5226 }
5227 
5228 void PowderPattern::BeginOptimization(const bool allowApproximations,
5229  const bool enableRestraints)
5230 {
5231  this->Prepare();
5232  if(0 == mOptProfileIntegration.GetChoice()) this->FitScaleFactorForIntegratedRw();
5233  else this->FitScaleFactorForRw();
5234  this->RefinableObj::BeginOptimization(allowApproximations,enableRestraints);
5235 }
5236 
5237 //void PowderPattern::SetApproximationFlag(const bool allow)
5238 //{// Do we need this ?
5239 // this->Prepare();
5240 // if(0 == mOptProfileIntegration.GetChoice()) this->FitScaleFactorForIntegratedRw();
5241 // else this->FitScaleFactorForRw();
5242 // this->RefinableObj::SetApproximationFlag(allow);
5243 //}
5244 
5245 void PowderPattern::GlobalOptRandomMove(const REAL mutationAmplitude,
5246  const RefParType *type)
5247 {
5248  if(mRandomMoveIsDone) return;
5249  this->RefinableObj::GlobalOptRandomMove(mutationAmplitude,type);
5250 }
5251 
5252 void PowderPattern::AddExcludedRegion(const REAL min,const REAL max)
5253 {
5254  VFN_DEBUG_MESSAGE("PowderPattern::AddExcludedRegion()",5)
5255  const int num=mExcludedRegionMinX.numElements();
5256  if(num>0)
5257  {
5258  mExcludedRegionMinX.resizeAndPreserve(num+1);
5259  mExcludedRegionMaxX.resizeAndPreserve(num+1);
5260  }
5261  else
5262  {
5263  mExcludedRegionMinX.resize(1);
5264  mExcludedRegionMaxX.resize(1);
5265  }
5266  mExcludedRegionMinX(num)=min;
5267  mExcludedRegionMaxX(num)=max;
5268 
5269  //ensure regions are sorted by ascending 2thetamin
5270  CrystVector_long subs;
5271  subs=SortSubs(mExcludedRegionMinX);
5272  CrystVector_REAL tmp1,tmp2;
5273  tmp1=mExcludedRegionMinX;
5274  tmp2=mExcludedRegionMaxX;
5275  for(int i=0;i<mExcludedRegionMinX.numElements();i++)
5276  {
5277  mExcludedRegionMinX(i)=tmp1(subs(i));
5278  mExcludedRegionMaxX(i)=tmp2(subs(i));
5279  }
5281  VFN_DEBUG_MESSAGE("PowderPattern::Add2ThetaExcludedRegion():End",5)
5282 }
5283 
5285 {
5286  REAL tmp=this->GetChi2_Option();
5287  if(mOptProfileIntegration.GetChoice()==0) tmp+=mIntegratedChi2LikeNorm;
5288  else tmp+=mChi2LikeNorm;
5289  return tmp;
5290 }
5291 
5292 unsigned int PowderPattern::GetNbLSQFunction()const{return 2;}
5293 
5294 const CrystVector_REAL&
5295  PowderPattern::GetLSQCalc(const unsigned int idx) const
5296 {
5297  TAU_PROFILE("PowderPattern::GetLSQCalc()","void ()",TAU_DEFAULT);
5298  switch(idx)
5299  {
5300  case 1:
5301  {
5304  break;
5305  }
5306  default:
5307  {
5309  mPowderPatternUsedCalc.resizeAndPreserve(mNbPointUsed);
5310  break;
5311  }
5312  }
5313  return mPowderPatternUsedCalc;
5314 }
5315 
5316 const CrystVector_REAL&
5317  PowderPattern::GetLSQObs(const unsigned int idx) const
5318 {
5319  TAU_PROFILE("PowderPattern::GetLSQObs()","void ()",TAU_DEFAULT);
5320  switch(idx)
5321  {
5322  case 1:
5323  {
5324  this->PrepareIntegratedRfactor();
5325  mPowderPatternUsedObs=mIntegratedObs;
5326  break;
5327  }
5328  default:
5329  {
5331  mPowderPatternUsedObs.resizeAndPreserve(mNbPointUsed);
5332  break;
5333  }
5334  }
5335  return mPowderPatternUsedObs;
5336 }
5337 
5338 const CrystVector_REAL&
5339  PowderPattern::GetLSQWeight(const unsigned int idx) const
5340 {
5341  TAU_PROFILE("PowderPattern::GetLSQWeight()","void ()",TAU_DEFAULT);
5342  switch(idx)
5343  {
5344  case 1:
5345  {
5346  this->PrepareIntegratedRfactor();
5347  // :KLUDGE: When variance is used, mIntegratedWeight will change at each powder pattern calculation,
5348  // so this might be quite wrong...
5349  if(mIntegratedWeight.numElements()==0)
5350  mPowderPatternUsedWeight=mIntegratedWeightObs;
5351  else mPowderPatternUsedWeight=mIntegratedWeight;
5352  break;
5353  }
5354  default:
5355  {
5357  mPowderPatternUsedWeight.resizeAndPreserve(mNbPointUsed);
5358  break;
5359  }
5360  }
5361  return mPowderPatternUsedWeight;
5362 }
5363 
5364 std::map<RefinablePar*, CrystVector_REAL>& PowderPattern::GetLSQ_FullDeriv(const unsigned int idx,std::set<RefinablePar *> &vPar)
5365 {
5366  TAU_PROFILE("PowderPattern::GetLSQ_FullDeriv()","void ()",TAU_DEFAULT);
5367  //return this->RefinableObj::GetLSQ_FullDeriv(idx,vPar);
5368  if(idx==1)
5369  {
5370  this->CalcPowderPatternIntegrated_FullDeriv(vPar);
5371  #if 0
5372  std::map<RefinablePar*, CrystVector_REAL> fullderiv_old;
5373  std::vector<const CrystVector_REAL*> v;
5374  int n=0;
5375  //cout<<"PowderPattern::GetLSQ_FullDeriv(integrated):scales:"<<mScaleFactor<<endl;
5376  cout<<"PowderPattern::GetLSQ_FullDeriv(integrated):parameters:"<<endl;
5377  for(std::set<RefinablePar*>::iterator par=vPar.begin();par!=vPar.end();++par)
5378  {
5379  v.push_back(&(mPowderPatternIntegrated_FullDeriv[*par]));
5380  fullderiv_old[*par]=this->GetLSQDeriv(idx,*(*par));
5381  v.push_back(&(fullderiv_old[*par]));
5382  cout<<(*par)->GetName()<<":"<<mPowderPatternIntegrated_FullDeriv[*par].size()<<","<<fullderiv_old[*par].size()<<endl;
5383  if(++n>8) break;
5384  }
5385  cout<<"PowderPattern::GetLSQ_FullDeriv(integrated):"<<endl<<FormatVertVector<REAL>(v,12,1,20)<<endl;
5386  //exit(0);
5387  #endif
5388  return mPowderPatternIntegrated_FullDeriv;
5389  }
5390  mPowderPattern_FullDeriv=this->GetPowderPattern_FullDeriv(vPar);
5391  return mPowderPattern_FullDeriv;
5392 }
5393 
5395 {
5396  VFN_DEBUG_MESSAGE("PowderPattern::Prepare()",5);
5397  for(int i=0;i<mPowderPatternComponentRegistry.GetNb();i++)
5398  {
5399  mPowderPatternComponentRegistry.GetObj(i).SetMaxSinThetaOvLambda(mMaxSinThetaOvLambda);
5400  mPowderPatternComponentRegistry.GetObj(i).Prepare();
5401  }
5402 }
5404  CrystVector_uint & groupIndex,
5405  unsigned int &first) const
5406 {
5407  // One group for scales, one for theta error parameters
5408  unsigned int scaleIndex=0;
5409  unsigned int thetaIndex=0;
5410  VFN_DEBUG_MESSAGE("PowderPattern::GetGeneGroup()",4)
5411  for(long i=0;i<obj.GetNbPar();i++)
5412  for(long j=0;j<this->GetNbPar();j++)
5413  if(&(obj.GetPar(i)) == &(this->GetPar(j)))
5414  {
5416  {
5417  if(scaleIndex==0) scaleIndex=first++;
5418  groupIndex(i)=scaleIndex;
5419  }
5420  else //gpRefParTypeScattDataCorrPos
5421  {
5422  if(thetaIndex==0) thetaIndex=first++;
5423  groupIndex(i)=thetaIndex;
5424  }
5425  }
5426 }
5427 
5429 {
5431  for(int i=0;i<mPowderPatternComponentRegistry.GetNb();i++)
5432  {
5433  mPowderPatternComponentRegistry.GetObj(i).SetMaxSinThetaOvLambda(mMaxSinThetaOvLambda);
5434  }
5435 }
5436 
5438 
5439 const CrystVector_long& PowderPattern::GetIntegratedProfileMin()const
5440 {
5441  this->PrepareIntegratedRfactor();
5442  return mIntegratedPatternMin;
5443 }
5444 
5445 const CrystVector_long& PowderPattern::GetIntegratedProfileMax()const
5446 {
5447  this->PrepareIntegratedRfactor();
5448  return mIntegratedPatternMax;
5449 }
5450 
5452 {
5453  return mClockIntegratedFactorsPrep;
5454 }
5455 
5456 REAL PowderPattern::STOL2X(const REAL stol)const
5457 {
5458  REAL x;
5459  if(this->GetRadiation().GetWavelengthType()==WAVELENGTH_TOF)
5460  {
5461  if(stol>0) x = 1.0/(2*stol); else return 0;
5462  x = mDIFC*x+mDIFA*x*x;
5463  VFN_DEBUG_MESSAGE("PowderPattern::STOL2X("<<stol<<","<<1.0/(2*stol)<<")="<<x,2)
5464  }
5465  else
5466  {
5467  x=stol*this->GetWavelength();
5468  if(abs(x)<1.0) x=2*asin(x); else x=2*M_PI;
5469  }
5470  return x;
5471 }
5472 
5473 REAL PowderPattern::X2STOL(const REAL x)const
5474 {
5475  REAL stol;
5476  if(this->GetRadiation().GetWavelengthType()==WAVELENGTH_TOF)
5477  {
5478  if(abs(mDIFA)>abs(mDIFC*1e-6))
5479  {
5480  const REAL delta=mDIFC*mDIFC+4.0*mDIFA*x;
5481  stol = (-mDIFC+sqrt(delta))/(2.0*mDIFA);
5482  stol = 1/(2.0*stol);
5483  }
5484  else stol=mDIFC/(2.0*x);
5485  }
5486  else
5487  stol=sin(x/2.0)/this->GetWavelength();
5488  VFN_DEBUG_MESSAGE("PowderPattern::X2STOL("<<x<<")="<<stol,2)
5489  return stol;
5490 }
5491 
5492 REAL PowderPattern::STOL2Pixel(const REAL stol)const
5493 {
5494  return this->X2Pixel(this->STOL2X(stol));
5495 }
5496 
5497 PeakList PowderPattern::FindPeaks(const float dmin,const float maxratio,const unsigned int maxpeak)
5498 {
5499  const long nb=this->GetNbPoint() ;
5500  // Limit peak detection to 1.5A resolution
5501  long start,finish;
5502  if(this->GetRadiation().GetWavelengthType()!=WAVELENGTH_TOF)
5503  {
5504  start=1;// do not start at 0, if this is a simulation that really start at theta=0...
5505  for(finish=0;finish<nb;++finish)
5506  {
5507  const REAL d=1/(this->X2STOL(this->GetPowderPatternX()(finish))*2);
5508  if(d<dmin) break;
5509  }
5510  }
5511  else
5512  {
5513  finish=nb-1;
5514  for(start=nb-1;start>=0;--start)
5515  {
5516  const REAL d=1/(this->X2STOL(this->GetPowderPatternX()(start))*2);
5517  if(d<dmin) break;
5518  }
5519  }
5520  // First evaluate approximate width (in number of pixels) of reflections
5521  unsigned int width_golay=10;
5522  {
5523  CrystVector_REAL obs;
5524  const int nbwidth=9;
5525  CrystVector_long width(nbwidth);
5526  width=0;
5527  obs=this->GetPowderPatternObs();
5528  // Zero excluded regions.
5529  for(long i= 0;i<mExcludedRegionMinX.numElements();i++)
5530  {
5531  long min,max;
5532  min=(long)floor(this->X2Pixel(mExcludedRegionMinX(i)));
5533  max=(long)ceil (this->X2Pixel(mExcludedRegionMaxX(i)));
5534  if(min<0) min = 0;
5535  if(max>=obs.numElements()) max = obs.numElements();
5536  for(long j=min;j<max;j++) obs(j) = 0;
5537  }
5538  const long nb=obs.numElements();
5539  for(int j=0;j<nbwidth;j++)
5540  {
5541  const long imax=obs.imax(nb/10,nb-1);
5542  const REAL iobs_max=obs(imax);
5543  REAL thres=iobs_max;
5544  long i;
5545  for(i=imax-100;i<(imax+100);++i)
5546  {
5547  if(i<0){i=0;continue;}
5548  if(i>=nb) break;
5549  if(obs(i)<thres) thres=obs(i);
5550  }
5551  thres=(iobs_max+thres)/2;
5552  i=imax;
5553  while(obs(i)>=thres)
5554  {
5555  cout<<obs(i)<<" ";
5556  obs(i--)=0;
5557  width(j)+=1;
5558  if(i<0) break;
5559  }
5560  i=imax+1;
5561  while(obs(i)>=thres)
5562  {
5563  cout<<obs(i)<<" ";
5564  obs(i++)=0;
5565  width(j)+=1;
5566  if(i>=nb) break;
5567  }
5568  cout<<endl<<" => "<<width(j)<<endl;
5569  for(i=imax-width(j)*2;i<(imax+width(j)*2);++i)
5570  {
5571  if(i<0) continue;
5572  if(i>=nb) break;
5573  obs(i)=0;
5574  }
5575  }
5576  cout<<"Width of "<<nbwidth<<" strongest peaks:"<<endl<<width;
5577  width_golay=width(SortSubs(width)(nbwidth/2));
5578  cout<<"median width:"<<width_golay<<endl;
5579  if(width_golay<=4)width_golay=4;
5580  if(width_golay>=16)width_golay=16;
5581  }
5582 
5583  // get 2nd derivative
5584  CrystVector_REAL obsd2;
5585  obsd2=SavitzkyGolay(this->GetPowderPatternObs(),width_golay,2);
5586  // Zero excluded regions.
5587  for(long i= 0;i<mExcludedRegionMinX.numElements();i++)
5588  {
5589  long min,max;
5590  min=(long)floor(this->X2Pixel(mExcludedRegionMinX(i)));
5591  max=(long)ceil (this->X2Pixel(mExcludedRegionMaxX(i)));
5592  if(min<0) min = 0;
5593  if(max>=obsd2.numElements()) max = obsd2.numElements();
5594  for(long j=min;j<max;j++) obsd2(j) = 0;
5595  }
5596  const float norm=-obsd2.min();
5597  // Normalize, so that the derivative has the same extent as the observed pattern
5598  obsd2 *= mPowderPatternObs.max()/(-norm);
5599 
5600  REAL min_iobs;
5601  if(maxratio<0)
5602  {//Automatic discrimination - get an idea of noise from the distribution of the scond derivative
5603  CrystVector_REAL tmp;
5604  tmp=obsd2;
5605  tmp.resizeAndPreserve(tmp.numElements()/4);// First quarter, avoid too many peaks
5606  CrystVector<long> sub(tmp.numElements());
5607  QuickSortSubs(tmp,sub,tmp.numElements()-1,0);
5608  min_iobs=5*(tmp(tmp.numElements()/2)-tmp(tmp.numElements()/4));
5609  //cout<<__FILE__<<":"<<__LINE__<<" MIN_IOBS (automatic)="<<min_iobs<<endl;
5610  }else min_iobs=-1;// This will be set after highest peak is found
5611  PeakList pl;
5612  int nbav_min=0;//minimum numerb of points over which the peak is integrated
5613  while(true)
5614  {// Start from max
5615  const long imax=obsd2.imax(start,finish);
5616  REAL iobs=obsd2(imax);
5617  if(iobs<=0) break;
5618  REAL xmax=mX(imax)*iobs;
5619  long nbav=1;
5620  long i=imax;
5621  REAL lastiobs=obsd2(i);
5622  const REAL iobs_max=lastiobs;
5623  //cout<<i<<":"<<lastiobs<<":"<<mX(i)*RAD2DEG<<endl;
5624  while(true)
5625  {
5626  if(i<=1) break;
5627  if(obsd2(--i)>=lastiobs) break;
5628  lastiobs=obsd2(i);
5629  obsd2(i)=0;
5630  iobs+=lastiobs;
5631  xmax+=mX(i)*lastiobs;nbav++;
5632  if(lastiobs<=0) break;
5633  //cout<<i<<":"<<lastiobs<<":"<<mX(i)*RAD2DEG<<endl;
5634  }
5635  float dleft=mX(i+1);
5636  i=imax;
5637  lastiobs=obsd2(i);
5638  while(true)
5639  {
5640  if(i>=(nb-2)) break;
5641  if(obsd2(++i)>=lastiobs) break;
5642  lastiobs=obsd2(i);
5643  obsd2(i)=0;
5644  iobs+=lastiobs;
5645  xmax+=mX(i)*lastiobs;nbav++;
5646  if(lastiobs<=0) break;
5647  //cout<<i<<":"<<lastiobs<<":"<<mX(i)*RAD2DEG<<endl;
5648  }
5649  float dright=mX(i-1);
5650  xmax/=iobs;
5651  obsd2(imax)=0;
5652  REAL dmax=this->X2STOL(xmax)*2;
5653  dright=this->X2STOL(dright)*2;
5654  dleft =this->X2STOL(dleft)*2;
5655  //TODO : evaluate min intensity ratio from noise ?
5656  if(min_iobs<0)
5657  {
5658  cout<<this->GetPowderPatternObsSigma()(imax)<<","<<this->GetPowderPatternObs()(imax)<<endl;
5659  min_iobs=iobs/nbav*maxratio;
5660  //cout<<__FILE__<<":"<<__LINE__<<" MIN_IOBS="<<min_iobs<<endl;
5661  }
5662  if(nbav_min==0)
5663  {
5664  nbav_min=nbav/2;
5665  if(nbav_min<3)nbav_min=3;
5666  }
5667  if(pl.GetPeakList().size()>maxpeak) break;
5668  float sigma=this->GetPowderPatternObsSigma()(imax);
5669  if(this->GetRadiation().GetWavelengthType()!=WAVELENGTH_TOF)
5670  xmax *= RAD2DEG;
5671  cout<<"Peak #"<<pl.GetPeakList().size()<<"imax="<<imax<<", x="<<xmax<<",d="<<1/dmax<<", d2iobs_max="<<iobs_max
5672  <<", d2Iobs="<<iobs<<", nbav="<<nbav<<", min_iobs="<<min_iobs<<",sigma="<<sigma<<endl;
5673  if( ((nbav>=nbav_min) &&(iobs_max>min_iobs)&&((iobs/nbav)>min_iobs))
5674  ||((nbav>=nbav_min) &&(iobs_max>min_iobs)&&((iobs/nbav)>min_iobs*.2)&&((iobs/nbav)>3*sigma))
5675  ||((nbav>=nbav_min/2)&&(iobs_max>min_iobs)&&((iobs/nbav)>min_iobs*2 )&&((iobs/nbav)>6*sigma)))
5676  {
5677  pl.AddPeak(dmax,iobs,abs(dright-dleft)*.25);
5678  if((pl.GetPeakList().size()==1)&&(maxratio<0)&&(min_iobs<0.005*iobs/nbav)) min_iobs=0.005*iobs/nbav;
5679  }
5680  }
5681  pl.Print(cout);
5682  return pl;
5683 }
5684 
5685 const CrystVector_REAL& PowderPattern::GetScaleFactor() const{return mScaleFactor;}
5686 
5687 CrystVector_REAL& PowderPattern::GetScaleFactor(){return mScaleFactor;}
5688 
5689 //Local structures to export atoms, bond and angle restraints
5690 struct exportAtom
5691 {
5692  exportAtom(string n,REAL X, REAL Y, REAL Z,REAL b,REAL o,const ScatteringPower *pow):
5693  name(n),x(X),y(Y),z(Z),biso(b),occ(o),occMult(1),mpScattPow(pow){}
5694  string name;
5695  REAL x,y,z,biso,occ;
5697  int occMult;
5698  const ScatteringPower *mpScattPow;
5699 };
5700 
5701 struct exportBond
5702 {
5703  exportBond(const string &a1,const string &a2, REAL d, REAL s):
5704  at1(a1),at2(a2),dist(d),sigma(s){}
5705  string at1,at2;
5706  REAL dist,sigma;
5707 };
5708 
5709 struct exportAngle
5710 {
5711  exportAngle(const string &a1,const string &a2,const string &a3, REAL a, REAL s):
5712  at1(a1),at2(a2),at3(a3),ang(a),sigma(s){}
5713  string at1,at2,at3;
5714  REAL ang,sigma;
5715 };
5716 
5717 void PowderPattern::ExportFullprof(const std::string &prefix)const
5718 {
5719  // Analyze our data - background ? number of crystalline phases ?
5720  const PowderPatternBackground *pBackground=0;
5721  vector<const PowderPatternDiffraction*> vDiff;
5722  for(unsigned int i=0;i<this->GetNbPowderPatternComponent();i++)
5723  {
5724  if(this->GetPowderPatternComponent(i).GetClassName()=="PowderPatternBackground")
5725  pBackground=dynamic_cast<const PowderPatternBackground*>(&(this->GetPowderPatternComponent(i)));
5726  if(this->GetPowderPatternComponent(i).GetClassName()=="PowderPatternDiffraction")
5727  vDiff.push_back(dynamic_cast<const PowderPatternDiffraction*>(&(this->GetPowderPatternComponent(i))));
5728  }
5729  if((pBackground==0)||vDiff.size()==0) return;
5730 
5731  // Powder data file
5732  ofstream dat((prefix+".dat").c_str());
5733  dat<<"XYDATA"<<endl
5734  <<"INTER 1.0 1.0 0"<<endl<<endl<<endl<<endl<<endl;
5735 
5736  CrystVector_REAL ttheta;
5737  ttheta=mX;
5738  if(this->GetRadiation().GetWavelengthType()!=WAVELENGTH_TOF) ttheta *= RAD2DEG;
5739  dat << FormatVertVector<REAL>(ttheta,mPowderPatternObs,mPowderPatternObsSigma,12,4);
5740  dat.close();
5741 
5742  // PCR file
5743  ofstream pcr((prefix+".pcr").c_str());
5744  // if(!pcr) :TODO:
5745 
5746  // Title
5747  pcr<<"Fox/ObjCryst exported file:"<<this->GetName()<<endl;
5748  // Number of patterns
5749  pcr<<"NPATT 1"<<endl;
5750  // Weight of each pattern
5751  pcr<<"W_PAT 1.0"<<endl;
5752  // Multi-pattern format
5753  pcr<<"! Nph Dum Ias Nre Cry Opt Aut"<<endl;
5754  pcr<<" "<<vDiff.size()
5755  <<" 0 0 0 0 1 1 "<<endl;
5756  // For each phase
5757  {
5758  int job=0;
5759  if(this->GetRadiation().GetRadiationType()==RAD_XRAY) job=0;
5760  if(this->GetRadiation().GetRadiationType()==RAD_NEUTRON) job=1;
5761  //:TODO: TOF:
5762  pcr<<"! Job Npr Nba Nex Nsc Nor Iwg Ilo Res Ste Uni Cor Anm"<<endl
5763  <<" "<<job
5764  <<" 5 "<<pBackground->GetInterpPoints().first->numElements()
5765  <<" 0 0 1 0 0 0 1 0 0 0"<<endl;
5766  }
5767  // Names of data files
5768  string shortName;
5769  {// Strip path for data file
5770  std::string::size_type idx =prefix.rfind("/");
5771  std::string::size_type idx2=prefix.rfind("\\");
5772  std::string::size_type idx3=prefix.rfind(":");
5773  if(((long)idx2!=(long)string::npos)&&((long)idx2>(long)idx))idx=idx2;
5774  if(((long)idx3!=(long)string::npos)&&((long)idx3>(long)idx))idx=idx3;
5775  if(idx==string::npos)
5776  shortName=prefix;
5777  else
5778  shortName=prefix.substr(idx+1);
5779  }
5780  pcr<<"! File names of data files"<<endl;
5781  pcr<<shortName<<".dat"<<endl;
5782  // Output options...
5783  pcr<<"! Mat Pcr Syo Rpa Sym Sho"<<endl
5784  <<" 1 1 0 -1 0 0 "<<endl;
5785  // Output options... For each pattern
5786  pcr<<"! Ipr Ppl Ioc Ls1 Ls2 Ls3 Prf Ins Hkl Fou Ana"<<endl
5787  <<" 0 0 0 0 0 0 1 10 0 0 1 "<<endl;
5788  // Fixed experimental parameters For each 2-theta pattern :TODO: Check !
5789  int wdt=16;
5790  if(this->GetRadiation().GetRadiationType()==RAD_NEUTRON) wdt=10;
5791  pcr<<"!lambda1 lambda2 Ratio Bkpos Wdt Cthm muR AsyLim Rpolarz -> Patt #1"<<endl
5792  <<this->GetRadiation().GetWavelength()(0)<<" "<<this->GetRadiation().GetWavelength()(0)
5793  << " 0 0 "<<wdt
5794  <<" 0 0 0 0.95"<<endl;
5795  // Refinement parameters - changes are damped !!
5796  pcr<<"!NCY Eps R_at R_an R_pr R_gl"<<endl
5797  <<" 5 0.2 1.0 1.0 1.0 1.0"<<endl;
5798  // Refinement parameters & powder data range, for each 2theta pattern
5799  pcr<<"! Thmin Step Thmax PSD Sent0 -> Patt #1"<<endl
5800  <<" 0 0 0 0 0"<<endl;
5801  // Background points
5802  pcr<<"!2Theta Background for Pattern #1"<<endl;
5803  for(long i=0;i<pBackground->GetInterpPoints().first->numElements();i++)
5804  pcr<<(*(pBackground->GetInterpPoints().first))(i)*RAD2DEG<<" "
5805  <<(*(pBackground->GetInterpPoints().second))(i)<<" 0.0"<<endl;
5806  // Number of refined parameters - just use one for the scale factor !
5807  pcr<<"!"<<endl<<"!"<<endl<<"1 !Number of refined parameters"<<endl;
5808  // Powder data experimental set-up II (refinable parameters)
5809  pcr<<"! Zero Code Sycos Code Sysin Code Lambda Code More -> Patt #1"<<endl;
5810  pcr<<" "<<mXZero*RAD2DEG <<" 0.0 "
5811  <<m2ThetaDisplacement*RAD2DEG <<" 0.0 "
5812  <<m2ThetaTransparency*RAD2DEG <<" 0.0 "
5813  <<"0.000 0.0 0"<<endl;
5814  // PHASE DESCRIPTIONS
5815  for(unsigned int i=0;i<vDiff.size();++i)
5816  {
5817  pcr<<"!-------------------------------------------------------------------------------"<<endl
5818  <<"! Data for PHASE number: "<<i<<" ==> Current R_Bragg for Pattern# 1: 0.00 "<<endl
5819  <<"!-------------------------------------------------------------------------------"<<endl;
5820  //Phase name
5821  pcr<<vDiff[i]->GetCrystal().GetName()<<endl;
5822 
5823  // List all atoms, remove overlapping ones
5824  map<int,exportAtom> vExportAtom;
5825  list<exportBond> vExportBond;
5826  list<exportAngle> vExportAngle;
5827  {
5828  CrystMatrix_REAL minDistTable;
5829  minDistTable=vDiff[i]->GetCrystal().GetMinDistanceTable(-1.);
5830  unsigned long k=0;
5831  // list0 is the full scattering component list with all atoms except dummies,
5832  // and a correct mDynPopCorr
5833  const ScatteringComponentList list0=vDiff[i]->GetCrystal().GetScatteringComponentList();
5834  for(int s=0;s<vDiff[i]->GetCrystal().GetScattererRegistry().GetNb();s++)
5835  {
5836  const ScatteringComponentList list=vDiff[i]->GetCrystal().GetScatt(s).GetScatteringComponentList();
5837 
5838  // If we have a Molecule, remember the names used for the atoms to describe restraints
5839  // We can't use the original atom names as they might not be unique in the crystal
5840  const Molecule *pMol=0;
5841  if(vDiff[i]->GetCrystal().GetScatt(s).GetClassName()=="Molecule")
5842  pMol=dynamic_cast<const Molecule*>(&(vDiff[i]->GetCrystal().GetScatt(s)));
5843  map<const MolAtom*,string> vMolAtomName;
5844 
5845  for(int j=0;j<list.GetNbComponent();j++)
5846  {
5847  if(0==list(j).mpScattPow) continue;//Can this happen ?
5848  bool redundant=false;
5849  for(unsigned long l=0;l<k;++l)
5850  if(abs(minDistTable(l,k))<0.5)
5851  {
5852  map<int,exportAtom>::iterator pos=vExportAtom.find(l);
5853  if(pos!=vExportAtom.end()) pos->second.occMult+=1;
5854  redundant=true;//-1 means dist > 10A
5855  }
5856  if(!redundant)
5857  {
5858  //:TODO: avoid non-alphanumeric characters in name
5859  stringstream name;
5860  name<<list(j).mpScattPow->GetName()<<k+1;
5861  vExportAtom.insert(make_pair(k,exportAtom(name.str(),
5862  list(j).mX,list(j).mY,list(j).mZ,
5863  list(j).mpScattPow->GetBiso(),
5864  list(j).mOccupancy*list0(k).mDynPopCorr,
5865  list(j).mpScattPow)));
5866  if(pMol!=0) vMolAtomName.insert(make_pair(pMol->GetAtomList()[j],name.str()));
5867  }
5868  k++;
5869  }
5870  if(pMol!=0)
5871  {
5872  for(vector<MolBond*>::const_iterator pos=pMol->GetBondList().begin();
5873  pos!=pMol->GetBondList().end();++pos)
5874  {
5875  map<const MolAtom*,string>::const_iterator p1,p2;
5876  p1=vMolAtomName.find(&((*pos)->GetAtom1()));
5877  p2=vMolAtomName.find(&((*pos)->GetAtom2()));
5878  if( (p1!=vMolAtomName.end()) && (p2!=vMolAtomName.end()))
5879  vExportBond.push_back(exportBond(p1->second, p2->second,
5880  (*pos)->GetLength0(),(*pos)->GetLengthSigma()));
5881  }
5882 
5883  for(vector<MolBondAngle*>::const_iterator pos=pMol->GetBondAngleList().begin();
5884  pos!=pMol->GetBondAngleList().end();++pos)
5885  {
5886  map<const MolAtom*,string>::const_iterator p1,p2,p3;
5887  p1=vMolAtomName.find(&((*pos)->GetAtom1()));
5888  p2=vMolAtomName.find(&((*pos)->GetAtom2()));
5889  p3=vMolAtomName.find(&((*pos)->GetAtom3()));
5890  if( (p1!=vMolAtomName.end()) && (p2!=vMolAtomName.end()) && (p3!=vMolAtomName.end()))
5891  vExportAngle.push_back(exportAngle(p1->second, p2->second,p3->second,
5892  (*pos)->GetAngle0(),(*pos)->GetAngleSigma()));
5893  }
5894  }
5895  }
5896  // :TODO: recognize special positions, and move the atoms on them.
5897  // :TODO: list atoms excluded, commented out
5898  }
5899 
5900  // Main control codes line for the phase
5901  //:TODO: extract distance (Dis) and bond angle (Ang) restraints whenever possible
5902  //const ScatteringComponentList *pSC=&(vDiff[i]->GetCrystal().GetScatteringComponentList());
5903  pcr<<"!Nat Dis Ang Jbt Isy Str Furth ATZ Nvk More"<<endl
5904  << vExportAtom.size() <<" "<<vExportBond.size()<<" "<<vExportAngle.size()
5905  <<" 0 0 0 0 1.0 0 1"<<endl;
5906  pcr<<"!Jvi Jdi Hel Sol Mom Ter N_Domains"<<endl
5907  <<" 0 3 0 0 0 0 0"<<endl;
5908  // Contribution to the patterns
5909  pcr<<"!Contributions (0/1) of this phase to the patterns"<<endl
5910  <<" 1"<<endl;
5911  //
5912  pcr<<"!Irf Npr Jtyp Nsp_Ref Ph_Shift for Pattern#"<<i<<endl
5913  <<" 0 0 0 0 0"<<endl;
5914  pcr<<"! Pr1 Pr2 Pr3 Brind. Rmua Rmub Rmuc for Pattern#"<<i<<endl
5915  <<" 1.0 1.0 1.0 1.0 0.0 0.0 0.0"<<endl;
5916 
5917  // Limits for distance calculations
5918  pcr<<"! Max_dst(dist) (angles) Bond-Valence Calc."<<endl
5919  <<" 2.7000 1.5000 0"<<endl;
5920 
5921  // Space group symbol
5922  pcr<<vDiff[i]->GetCrystal().GetSpaceGroup().GetCCTbxSpg().match_tabulated_settings().hermann_mauguin()
5923  <<" <- Space Group Symbol"<<endl;
5924  // Atomic parameters
5925  pcr<<"!Atom Typ X Y Z Biso Occ In Fin N_t Spc / Codes"<<endl;
5926  for(map<int,exportAtom>::const_iterator pos=vExportAtom.begin();pos!=vExportAtom.end();++pos)
5927  {
5928  pcr<<pos->second.name
5929  <<" "<<pos->second.mpScattPow->GetSymbol()<<" "
5930  <<pos->second.x<<" "<<pos->second.y<<" "<<pos->second.z<<" "
5931  <<pos->second.biso<<" "
5932  <<pos->second.occ*pos->second.occMult<<" 0 0 0 0"<<endl
5933  <<" 0 0 0 0 0"<<endl;
5934  }
5935  // POWDER DATA-I: PROFILE PARAMETERS FOR EACH PATTERN
5936  REAL eta0=vDiff[0]->GetProfile().GetPar("Eta0").GetHumanValue();
5937  if(eta0<.01) eta0=.01;
5938  else if(eta0>.99) eta0=.99;
5939  pcr<<"!Scale Shape1 Bov Str1 Str2 Str3 Strain-Model"<<endl
5940  <<" 1.0 "<<eta0
5941  <<" 0.0 0.0 0.0 0.0 0"<<endl
5942  <<" 1.0 0.0 0.0 0.0 0.0 0.0 0"<<endl;
5943 
5944  // :TODO: make sure the profile used corrseponds to pseudo-Voigt first !
5945  pcr<<"! U V W X Y GauSiz LorSiz Size-Model"<<endl;
5946  // :NOTE: we need to separate the 3 next lines, or the same number is generated
5947  // three times when compiled with Visual c++ express 2008 (compiler bug ?)
5948  pcr<<vDiff[i]->GetProfile().GetPar("U").GetHumanValue()<<" ";
5949  pcr<<vDiff[i]->GetProfile().GetPar("V").GetHumanValue()<<" ";
5950  pcr<<vDiff[i]->GetProfile().GetPar("W").GetHumanValue()<<" ";
5951  pcr<< " 0.0 0.0 0.0 0.0 "<<endl
5952  << " 0.0 0.0 0.0 0.0 0.0 0.0 0.0 "<<endl;
5953  // Cell parameters
5954  pcr<<"! a b c alpha beta gamma #Cell Info"<<endl
5955  <<vDiff[i]->GetCrystal().GetLatticePar(0)<<" "
5956  <<vDiff[i]->GetCrystal().GetLatticePar(1)<<" "
5957  <<vDiff[i]->GetCrystal().GetLatticePar(2)<<" "
5958  <<vDiff[i]->GetCrystal().GetLatticePar(3)*RAD2DEG<<" "
5959  <<vDiff[i]->GetCrystal().GetLatticePar(4)*RAD2DEG<<" "
5960  <<vDiff[i]->GetCrystal().GetLatticePar(5)*RAD2DEG<<endl
5961  <<" 0.0 0.0 0.0 0.0 0.0 0.0"<<endl;
5962  pcr<<"! Pref1 Pref2 alpha0 beta0 alpha1 beta1 ?"<<endl
5963  <<" 0.0 0.0 0.0 0.0 0.0 0.0"<<endl
5964  <<" 0.0 0.0 0.0 0.0 0.0 0.0"<<endl;
5965  // ??
5966  //pcr<<"! ??"<<endl
5967  // <<"0.00 0.00 0.00000 0.00"<<endl;
5968  if(vExportBond.size()>0)
5969  {
5970  pcr<<"!Soft distance constraints"<<endl;
5971  for(list<exportBond>::const_iterator pos=vExportBond.begin();pos!=vExportBond.end();++pos)
5972  {
5973  pcr<<pos->at1<<" "<<pos->at2<<" 1 0 0 0 "<<pos->dist<<" "<<pos->sigma<<endl;
5974  }
5975  }
5976  if(vExportBond.size()>0)
5977  {
5978  pcr<<"!Soft angle constraints"<<endl;
5979  for(list<exportAngle>::const_iterator pos=vExportAngle.begin();pos!=vExportAngle.end();++pos)
5980  {
5981  pcr<<pos->at1<<" "<<pos->at2<<" "<<pos->at3<<" 1 1 0 0 0 0 0 0 "
5982  <<pos->ang*RAD2DEG<<" "<<pos->sigma*RAD2DEG<<endl;
5983  }
5984  }
5985  }
5986  pcr.close();
5987 }
5988 
5989 void PowderPattern::SetMuR(const REAL muR) {mMuR=muR; mClockCorrAbs.Click();}
5990 
5991 REAL PowderPattern::GetMuR() const {return mMuR;}
5992 
5994 {
5995  this->CalcNbPointUsed();
5997 
5998  TAU_PROFILE("PowderPattern::CalcPowderPattern()","void ()",TAU_DEFAULT);
5999  VFN_DEBUG_ENTRY("PowderPattern::CalcPowderPattern()",3);
6000  if(mPowderPatternComponentRegistry.GetNb()==0)
6001  {
6002  mPowderPatternCalc.resize(mNbPoint);
6004 
6008 
6009  const REAL *p0 = mPowderPatternVariance.data();
6010  REAL *p1=mPowderPatternWeight.data();
6011  for(unsigned long j=0;j<mNbPoint;j++)
6012  {
6013  if(*p0 <=0) {*p1 =0.;}
6014  else *p1 = 1. / *p0;
6015  p0++;p1++;
6016  }
6017  VFN_DEBUG_EXIT("PowderPattern::CalcPowderPattern():no components!",3);
6018  return;
6019  }
6020  TAU_PROFILE_TIMER(timer1,"PowderPattern::CalcPowderPattern1()Calc components","", TAU_FIELD);
6021  TAU_PROFILE_TIMER(timer2,"PowderPattern::CalcPowderPattern2(Add spectrums-scaled)"\
6022  ,"", TAU_FIELD);
6023  TAU_PROFILE_TIMER(timer3,"PowderPattern::CalcPowderPattern2(Add spectrums-backgd1)"\
6024  ,"", TAU_FIELD);
6025  TAU_PROFILE_TIMER(timer4,"PowderPattern::CalcPowderPattern2(Add spectrums-backgd2)"\
6026  ,"", TAU_FIELD);
6027  TAU_PROFILE_TIMER(timer5,"PowderPattern::CalcPowderPattern3(Variance)","", TAU_FIELD);
6028  TAU_PROFILE_START(timer1);
6029  for(int i=0;i<mPowderPatternComponentRegistry.GetNb();i++)
6030  mPowderPatternComponentRegistry.GetObj(i).CalcPowderPattern();
6031  TAU_PROFILE_STOP(timer1);
6032  VFN_DEBUG_MESSAGE("PowderPattern::CalcPowderPattern():Calculated components..",3);
6033  bool b=false;
6035  {
6036  b=true;
6037  }
6038  else
6039  for(int i=0;i<mPowderPatternComponentRegistry.GetNb();i++)
6041  mPowderPatternComponentRegistry.GetObj(i).GetClockPowderPatternCalc())
6042  {
6043  b=true;
6044  break;
6045  }
6046 
6047  if(false==b)
6048  {
6049  VFN_DEBUG_EXIT("PowderPattern::CalcPowderPattern():no need to recalc",3);
6050  return;
6051  }
6052  mPowderPatternCalc.resize(mNbPoint);
6053  int nbBackgd=0;//count number of background phases
6054  for(int i=0;i<mPowderPatternComponentRegistry.GetNb();i++)
6055  {//THIS SHOULD GO FASTER (PRE-FETCHING ARRAY DATA?)
6056  VFN_DEBUG_MESSAGE("PowderPattern::CalcPowderPattern():Adding "<< mPowderPatternComponentRegistry.GetObj(i).GetName(),3);
6057  if(true==mPowderPatternComponentRegistry.GetObj(i).IsScalable())
6058  {
6059  TAU_PROFILE_START(timer2);
6060  if(0==i)
6061  {
6062  const REAL * p1=mPowderPatternComponentRegistry.GetObj(i)
6063  .mPowderPatternCalc.data();
6064  REAL * p0 = mPowderPatternCalc.data();
6065  const REAL s = mScaleFactor(i);
6066  for(unsigned long j=0;j<mNbPointUsed;j++) *p0++ = s * *p1++;
6067  if(!(this->IsBeingRefined())) for(unsigned long j=mNbPointUsed;j<mNbPoint;j++) *p0++ = 0;
6068  }
6069  else
6070  {
6071  const REAL * p1=mPowderPatternComponentRegistry.GetObj(i)
6072  .mPowderPatternCalc.data();
6073  REAL * p0 = mPowderPatternCalc.data();
6074  const REAL s = mScaleFactor(i);
6075  for(unsigned long j=0;j<mNbPointUsed;j++) *p0++ += s * *p1++;
6076  }
6077  TAU_PROFILE_STOP (timer2);
6078  }
6079  else
6080  {// This is a background phase
6081  TAU_PROFILE_START(timer3);
6082  if(0==i)
6083  {
6084  const REAL * p1=mPowderPatternComponentRegistry.GetObj(i)
6085  .mPowderPatternCalc.data();
6086  REAL * p0 = mPowderPatternCalc.data();
6087  for(unsigned long j=0;j<mNbPointUsed;j++) *p0++ = *p1++;
6088  if(!(this->IsBeingRefined())) for(unsigned long j=mNbPointUsed;j<mNbPoint;j++) *p0++ = 0;
6089  }
6090  else
6091  {
6092  const REAL * p1=mPowderPatternComponentRegistry.GetObj(i)
6093  .mPowderPatternCalc.data();
6094  REAL * p0 = mPowderPatternCalc.data();
6095  for(unsigned long j=0;j<mNbPointUsed;j++) *p0++ += *p1++;
6096 
6097  }
6098  TAU_PROFILE_STOP(timer3);
6099  TAU_PROFILE_START(timer4);
6100  // The following is useless if there is only one background phase...
6101  if(0==nbBackgd)
6102  {
6104  REAL *p0 = mPowderPatternBackgroundCalc.data();
6105  const REAL *p1=mPowderPatternComponentRegistry.GetObj(i)
6106  .mPowderPatternCalc.data();
6107  for(unsigned long j=0;j<mNbPointUsed;j++) *p0++ = *p1++;
6108  if(!(this->IsBeingRefined())) for(unsigned long j=mNbPointUsed;j<mNbPoint;j++) *p0++ = 0;
6109  }
6110  else
6111  {
6112  REAL *p0 = mPowderPatternBackgroundCalc.data();
6113  const REAL *p1=mPowderPatternComponentRegistry.GetObj(i)
6114  .mPowderPatternCalc.data();
6115  for(unsigned long j=0;j<mNbPointUsed;j++) *p0++ += *p1++;
6116  }
6117  nbBackgd++;
6118  TAU_PROFILE_STOP(timer4);
6119  }
6120  }
6121  if(0==nbBackgd) mPowderPatternBackgroundCalc.resize(0);//:KLUDGE:
6122 
6123  TAU_PROFILE_START(timer5);
6124  // Calc variance
6125  {
6126  VFN_DEBUG_MESSAGE("PowderPattern::CalcPowderPattern():variance",2);
6129  for(int i=0;i<mPowderPatternComponentRegistry.GetNb();i++)
6130  {
6131  if(mPowderPatternComponentRegistry.GetObj(i).HasPowderPatternCalcVariance())
6132  {
6133  if(0==mPowderPatternComponentRegistry.GetObj(i).GetPowderPatternCalcVariance()
6134  .numElements()) break;
6135 
6136  REAL *p0 = mPowderPatternVariance.data();
6137  const REAL *p1=mPowderPatternComponentRegistry.GetObj(i)
6138  .GetPowderPatternCalcVariance().data();
6139 
6140  if(true==mPowderPatternComponentRegistry.GetObj(i).IsScalable())
6141  {
6142  const REAL s2 = mScaleFactor(i) * mScaleFactor(i);
6143  for(unsigned long j=0;j<mNbPointUsed;j++) *p0++ += s2 * *p1++;
6144  }
6145  else for(unsigned long j=0;j<mNbPointUsed;j++) *p0++ += *p1++;
6146  }
6147  }
6148  REAL *p0 = mPowderPatternWeight.data();
6149  const REAL *p1=mPowderPatternVariance.data();
6150  for(unsigned long j=0;j<mNbPointUsed;j++)
6151  if(*p1 <=0) {*p0++ =0;p1++;}
6152  else *p0++ = 1. / *p1++;
6153  }
6155  TAU_PROFILE_STOP(timer5);
6156  VFN_DEBUG_EXIT("PowderPattern::CalcPowderPattern():End",3);
6157 }
6158 
6159 void PowderPattern::CalcPowderPattern_FullDeriv(std::set<RefinablePar*> &vPar)
6160 {
6161  TAU_PROFILE("PowderPattern::CalcPowderPattern_FullDeriv()","void ()",TAU_DEFAULT);
6162  this->CalcPowderPattern();
6163  mPowderPattern_FullDeriv.clear();
6164  if(mPowderPatternComponentRegistry.GetNb()==0) return;
6165  std::vector<std::map<RefinablePar*,CrystVector_REAL>*> comps;
6166  for(int i=0;i<mPowderPatternComponentRegistry.GetNb();i++)
6167  comps.push_back(&(mPowderPatternComponentRegistry.GetObj(i).GetPowderPattern_FullDeriv(vPar)));
6168 
6169  for(std::set<RefinablePar *>::iterator par=vPar.begin();par!=vPar.end();++par)
6170  {
6171  if(*par==0) continue;
6172  for(int i=0;i<mPowderPatternComponentRegistry.GetNb();i++)
6173  {
6174  if((*par)->GetPointer()==mScaleFactor.data()+i)
6175  {
6176  mPowderPattern_FullDeriv[*par]=mPowderPatternComponentRegistry.GetObj(i).GetPowderPatternCalc();
6177  continue;
6178  }
6179  else
6180  {
6181  if((*(comps[i]))[*par].size()==0) continue;
6182  }
6183  if(true==mPowderPatternComponentRegistry.GetObj(i).IsScalable())
6184  {
6185  if(mPowderPattern_FullDeriv[*par].size()==0)
6186  {
6187  mPowderPattern_FullDeriv[*par].resize(mNbPoint);// :TODO: only use mNbPointUsed
6188  const REAL * p1=(*comps[i])[*par].data();
6189  REAL * p0 = mPowderPattern_FullDeriv[*par].data();
6190  const REAL s = mScaleFactor(i);
6191  for(unsigned long j=0;j<mNbPointUsed;j++) *p0++ = s * *p1++;
6192  for(unsigned long j=mNbPointUsed;j<mNbPoint;j++) *p0++ = 0;// :TODO: only use mNbPointUsed
6193  }
6194  else
6195  {
6196  const REAL * p1=(*comps[i])[*par].data();
6197  REAL * p0 = mPowderPattern_FullDeriv[*par].data();
6198  const REAL s = mScaleFactor(i);
6199  for(unsigned long j=0;j<mNbPointUsed;j++) *p0++ += s * *p1++;
6200  }
6201  }
6202  else
6203  {// This is a background phase
6204  if(mPowderPattern_FullDeriv[*par].size()==0)
6205  {
6206  mPowderPattern_FullDeriv[*par].resize(mNbPoint);// :TODO: only use mNbPointUsed
6207  const REAL * p1=(*comps[i])[*par].data();
6208  REAL * p0 = mPowderPattern_FullDeriv[*par].data();
6209  for(unsigned long j=0;j<mNbPointUsed;j++) *p0++ = *p1++;
6210  for(unsigned long j=mNbPointUsed;j<mNbPoint;j++) *p0++ = 0;
6211  }
6212  else
6213  {
6214  const REAL * p1=(*comps[i])[*par].data();
6215  REAL * p0 = mPowderPattern_FullDeriv[*par].data();
6216  for(unsigned long j=0;j<mNbPointUsed;j++) *p0++ += *p1++;
6217 
6218  }
6219  }
6220  }
6221  }
6222  #if 0
6223  std::map<RefinablePar*, CrystVector_REAL> oldDeriv;
6224  std::vector<const CrystVector_REAL*> v;
6225  int n=0;
6226  for(std::map<RefinablePar*, CrystVector_REAL>::reverse_iterator pos=mPowderPattern_FullDeriv.rbegin();pos!=mPowderPattern_FullDeriv.rend();++pos)
6227  {
6228  if(pos->first==0) continue;
6229  if(pos->second.size()==0) continue;
6230 
6231  const REAL step=pos->first->GetDerivStep();
6232  pos->first->Mutate(step);
6233  this->CalcPowderPattern();
6234  oldDeriv[pos->first]=mPowderPatternCalc;
6235  pos->first->Mutate(-2*step);
6236  this->CalcPowderPattern();
6237  oldDeriv[pos->first]-=mPowderPatternCalc;
6238  oldDeriv[pos->first]/=2*step;
6239  pos->first->Mutate(step);
6240 
6241  v.push_back(&(pos->second));
6242  v.push_back(&(oldDeriv[pos->first]));
6243  cout<<pos->first->GetName()<<":"<<pos->second.size()<<","<<oldDeriv[pos->first].size()<<endl;
6244  if(++n>8) break;
6245  }
6246  cout<<FormatVertVector<REAL>(v,16)<<endl;
6247  exit(0);
6248  #endif
6249 }
6250 
6252 {
6253  this->CalcNbPointUsed();
6255 
6256  this->PrepareIntegratedRfactor();
6257  TAU_PROFILE("PowderPattern::CalcPowderPatternIntegrated()","void ()",TAU_DEFAULT);
6258  VFN_DEBUG_ENTRY("PowderPattern::CalcPowderPatternIntegrated()",4);
6259  if(mPowderPatternComponentRegistry.GetNb()==0)
6260  {
6261  mPowderPatternIntegratedCalc.resize(0);
6263  VFN_DEBUG_EXIT("PowderPattern::CalcPowderPatternIntegrated():no components!",4);
6264  return;
6265  }
6266  TAU_PROFILE_TIMER(timer1,"PowderPattern::CalcPowderPatternIntegrated()1:Calc components",\
6267  "", TAU_FIELD);
6268  TAU_PROFILE_TIMER(timer2,"PowderPattern::CalcPowderPatternIntegrated()2:Add comps-scaled"\
6269  ,"", TAU_FIELD);
6270  TAU_PROFILE_TIMER(timer3,"PowderPattern::CalcPowderPatternIntegrated()2:Add backgd1"\
6271  ,"", TAU_FIELD);
6272  TAU_PROFILE_TIMER(timer4,"PowderPattern::CalcPowderPatternIntegrated()2:Add backgd2"\
6273  ,"", TAU_FIELD);
6274  TAU_PROFILE_TIMER(timer5,"PowderPattern::CalcPowderPatternIntegrated()3:Variance"
6275  ,"", TAU_FIELD);
6276  TAU_PROFILE_START(timer1);
6277  vector< pair<const CrystVector_REAL*,const RefinableObjClock*> > comps;
6278  for(int i=0;i<mPowderPatternComponentRegistry.GetNb();i++)
6279  {
6280  comps.push_back(mPowderPatternComponentRegistry.GetObj(i).
6281  GetPowderPatternIntegratedCalc());
6282  }
6283  TAU_PROFILE_STOP(timer1);
6284  bool b=false;
6286  {
6287  b=true;
6288  }
6289  else
6290  for(vector< pair<const CrystVector_REAL*,const RefinableObjClock*> >::iterator
6291  pos=comps.begin();pos!=comps.end();++pos)
6292  if(mClockPowderPatternCalc < *(pos->second) )
6293  {
6294  b=true;
6295  break;
6296  }
6297 
6298  if(false==b)
6299  {
6300  VFN_DEBUG_EXIT("PowderPattern::CalcPowderPatternIntegrated():no need to recalc",4);
6301  return;
6302  }
6303  VFN_DEBUG_MESSAGE("PowderPattern::CalcPowderPatternIntegrated():Recalc",3);
6304  mPowderPatternIntegratedCalc.resize(mNbIntegrationUsed);
6305  int nbBackgd=0;//count number of background phases
6306  for(int i=0;i<mPowderPatternComponentRegistry.GetNb();i++)
6307  {
6308  VFN_DEBUG_MESSAGE("PowderPattern::CalcPowderPatternIntegrated():Adding "\
6309  << mPowderPatternComponentRegistry.GetObj(i).GetName(),3);
6310  if(true==mPowderPatternComponentRegistry.GetObj(i).IsScalable())
6311  {
6312  TAU_PROFILE_START(timer2);
6313  if(0==i)
6314  {
6315  const REAL * RESTRICT p1= comps[i].first->data();
6316  REAL * RESTRICT p0 = mPowderPatternIntegratedCalc.data();
6317  const REAL s = mScaleFactor(i);
6318  for(unsigned long j=mNbIntegrationUsed;j>0;j--) *p0++ = s * *p1++;
6319  }
6320  else
6321  {
6322  const REAL * RESTRICT p1= comps[i].first->data();
6323  REAL * RESTRICT p0 = mPowderPatternIntegratedCalc.data();
6324  const REAL s = mScaleFactor(i);
6325  for(unsigned long j=mNbIntegrationUsed;j>0;j--) *p0++ += s * *p1++;
6326  }
6327  TAU_PROFILE_STOP (timer2);
6328  }
6329  else
6330  {// This is a background phase
6331  TAU_PROFILE_START(timer3);
6332  if(0==i)
6333  {
6334  const REAL * RESTRICT p1= comps[i].first->data();
6335  REAL * RESTRICT p0 = mPowderPatternIntegratedCalc.data();
6336  for(unsigned long j=mNbIntegrationUsed;j>0;j--) *p0++ = *p1++;
6337  }
6338  else
6339  {
6340  const REAL * RESTRICT p1= comps[i].first->data();
6341  REAL * RESTRICT p0 = mPowderPatternIntegratedCalc.data();
6342  for(unsigned long j=mNbIntegrationUsed;j>0;j--) *p0++ += *p1++;
6343 
6344  }
6345  TAU_PROFILE_STOP(timer3);
6346  TAU_PROFILE_START(timer4);
6347  // The following is useless if there is only one background phase...
6348  if(0==nbBackgd)
6349  {
6350  mPowderPatternBackgroundIntegratedCalc.resize(mNbIntegrationUsed);
6351  const REAL * RESTRICT p1= comps[i].first->data();
6352  REAL * RESTRICT p0 = mPowderPatternBackgroundIntegratedCalc.data();
6353  for(unsigned long j=mNbIntegrationUsed;j>0;j--) *p0++ = *p1++;
6354  }
6355  else
6356  {
6357  const REAL * RESTRICT p1= comps[i].first->data();
6358  REAL * RESTRICT p0 = mPowderPatternBackgroundIntegratedCalc.data();
6359  for(unsigned long j=mNbIntegrationUsed;j>0;j--) *p0++ += *p1++;
6360  }
6361  nbBackgd++;
6362  TAU_PROFILE_STOP(timer4);
6363  }
6364  }
6365  TAU_PROFILE_START(timer5);
6366  if(0==nbBackgd) mPowderPatternBackgroundIntegratedCalc.resize(0);
6367  // Calc variance
6368  bool useCalcVariance=false;
6369  for(int i=0;i<mPowderPatternComponentRegistry.GetNb();i++)
6370  if(mPowderPatternComponentRegistry.GetObj(i).HasPowderPatternCalcVariance())
6371  if(mPowderPatternComponentRegistry.GetObj(i)
6372  .GetPowderPatternIntegratedCalcVariance().first->numElements() !=0)
6373  useCalcVariance=true;
6374  if(useCalcVariance)
6375  {
6376  VFN_DEBUG_MESSAGE("PowderPattern::CalcPowderPatternIntegrated():variance",3);
6377  {
6378  mPowderPatternVarianceIntegrated.resize(mNbIntegrationUsed);
6379  mIntegratedWeight.resize(mNbIntegrationUsed);
6380  const REAL * RESTRICT p1= mIntegratedVarianceObs.data();
6381  REAL * RESTRICT p0 = mPowderPatternVarianceIntegrated.data();
6382  for(unsigned long j=mNbIntegrationUsed;j>0;j--) *p0++ = *p1++;
6383  }
6384  //cout <<"PowderPattern::CalcPowderPatternIntegrated():variance"
6385  // <<"obsvarsum="<<log(mIntegratedVarianceObs.sum());
6386  for(int i=0;i<mPowderPatternComponentRegistry.GetNb();i++)
6387  {
6388  if(mPowderPatternComponentRegistry.GetObj(i).HasPowderPatternCalcVariance())
6389  {
6390  if(0==mPowderPatternComponentRegistry.GetObj(i)
6391  .GetPowderPatternIntegratedCalcVariance().first->numElements()) break;
6392 
6393  const REAL * RESTRICT p1= mPowderPatternComponentRegistry.GetObj(i)
6394  .GetPowderPatternIntegratedCalcVariance().first->data();
6395  //cout <<",sumvar(i)="<<log(mPowderPatternComponentRegistry.GetObj(i)
6396  // .GetPowderPatternIntegratedCalcVariance().first->sum());
6397  REAL * RESTRICT p0 = mPowderPatternVarianceIntegrated.data();
6398 
6399  if(true==mPowderPatternComponentRegistry.GetObj(i).IsScalable())
6400  {
6401  const REAL s2 = mScaleFactor(i) * mScaleFactor(i);
6402  for(unsigned long j=mNbIntegrationUsed;j>0;j--) *p0++ += s2 * *p1++;
6403  }
6404  else for(unsigned long j=mNbIntegrationUsed;j>0;j--) *p0++ += *p1++;
6405 
6406  }
6407  }
6408  //cout <<endl;
6409  REAL *p0 = mIntegratedWeight.data();
6410  const REAL *p1=mPowderPatternVarianceIntegrated.data();
6411  for(unsigned long j=mNbIntegrationUsed;j>0;j--)
6412  if(*p1 <=0) {*p0++ =0;p1++;}
6413  else *p0++ = 1. / *p1++;
6414  }
6415  else mIntegratedWeight.resize(0);
6417  TAU_PROFILE_STOP(timer5);
6418  /*
6419  // Compare-DEBUG ONLY
6420  {
6421  VFN_DEBUG_MESSAGE("PowderPattern::CalcPowderPatternIntegrated():Check",10);
6422  this->CalcPowderPattern();
6423  CrystVector_REAL integr(mNbIntegrationUsed);
6424  for(int k=0;k<mPowderPatternComponentRegistry.GetNb();k++)
6425  {
6426  VFN_DEBUG_MESSAGE("PowderPattern::CalcPowderPatternIntegrated():Check #"<<k,10);
6427  integr=0;
6428  const CrystVector_REAL *v
6429  =&(mPowderPatternComponentRegistry.GetObj(k).GetPowderPatternCalc());
6430  for(unsigned int i=0;i<mNbIntegrationUsed;i++)
6431  {
6432  integr(i)=0;
6433  for(int j=mIntegratedPatternMin(i);j<=mIntegratedPatternMax(i);j++)
6434  {
6435  integr(i) += (*v)(j);
6436  }
6437  }
6438  cout << "Integrated intensities, Component #"<<k<<endl
6439  << FormatVertVector<REAL> (integr,*(comps[k].first))<<endl;
6440  }
6441  }
6442  */
6443  VFN_DEBUG_EXIT("PowderPattern::CalcPowderPatternIntegrated():End",4);
6444 }
6445 
6446 void PowderPattern::CalcPowderPatternIntegrated_FullDeriv(std::set<RefinablePar *> &vPar)
6447 {
6448  TAU_PROFILE("PowderPattern::CalcPowderPatternIntegrated_FullDeriv()","void ()",TAU_DEFAULT);
6450  this->CalcNbPointUsed();
6451 
6452  this->PrepareIntegratedRfactor();
6453  mPowderPatternUsed_FullDeriv.clear();
6454  if(mPowderPatternComponentRegistry.GetNb()==0) return;
6455  std::vector<map<RefinablePar*,CrystVector_REAL>*> comps;
6456  for(int i=0;i<mPowderPatternComponentRegistry.GetNb();i++)
6457  {
6458  comps.push_back(&(mPowderPatternComponentRegistry.GetObj(i).
6459  GetPowderPatternIntegrated_FullDeriv(vPar)));
6460  }
6461  //RefinablePar *scalePar;
6462  //cout<<"PowderPattern::CalcPowderPatternIntegrated_FullDeriv():"<<endl;
6463  mPowderPatternIntegrated_FullDeriv.clear();
6464  for(std::set<RefinablePar *>::iterator par=vPar.begin();par!=vPar.end();++par)
6465  {
6466  if(*par==0) continue; //:TODO: store the calculated (non-derived) pattern here ?
6467  for(int i=0;i<mPowderPatternComponentRegistry.GetNb();i++)
6468  {
6469  if((*par)->GetPointer()==mScaleFactor.data()+i)
6470  {
6471  //scalePar=*par;
6472  mPowderPatternIntegrated_FullDeriv[*par]=*(mPowderPatternComponentRegistry.GetObj(i).GetPowderPatternIntegratedCalc().first);
6473  //cout<<"PowderPattern::CalcPowderPatternIntegrated_FullDeriv():scale #"<<i<<":"<<(*par)->GetName()<<":"<<(*par)->GetPointer()<<":"<<mPowderPatternUsed_FullDeriv[*par]<<endl;
6474  continue;
6475  }
6476  else
6477  {
6478  if((*(comps[i]))[*par].size()==0) continue;
6479  }
6480  if(true==mPowderPatternComponentRegistry.GetObj(i).IsScalable())
6481  {
6482  if(mPowderPatternIntegrated_FullDeriv[*par].size()==0)
6483  {
6484  mPowderPatternIntegrated_FullDeriv[*par].resize(mNbIntegrationUsed);
6485  const REAL * RESTRICT p1= (*(comps[i]))[*par].data();
6486  REAL * RESTRICT p0 = mPowderPatternIntegrated_FullDeriv[*par].data();
6487  const REAL s = mScaleFactor(i);
6488  for(unsigned long j=mNbIntegrationUsed;j>0;j--)
6489  {
6490  #if 1
6491  *p0++ = s * *p1++;
6492  #else
6493  *p0 = s * *p1;
6494  if((j==mNbIntegrationUsed)&&((*par)->GetName()=="Cimetidine_C11_x")) cout<<__FILE__<<":"<<__LINE__<<":"<<*p0<<","<<s<<"*"<<*p1<<endl;
6495  p0++;p1++;
6496  #endif
6497  }
6498  }
6499  else
6500  {
6501  const REAL * RESTRICT p1= (*(comps[i]))[*par].data();
6502  REAL * RESTRICT p0 = mPowderPatternIntegrated_FullDeriv[*par].data();
6503  const REAL s = mScaleFactor(i);
6504  for(unsigned long j=mNbIntegrationUsed;j>0;j--)
6505  {
6506  #if 1
6507  *p0++ += s * *p1++;
6508  #else
6509  *p0 += s * *p1;
6510  if((j==mNbIntegrationUsed)&&((*par)->GetName()=="Cimetidine_C11_x")) cout<<__FILE__<<":"<<__LINE__<<":"<<*p0<<","<<s<<"*"<<*p1<<endl;
6511  p0++;p1++;
6512  #endif
6513  }
6514  }
6515  }
6516  else
6517  {// This is a background phase
6518  if(mPowderPatternIntegrated_FullDeriv[*par].size()==0)
6519  {
6520  mPowderPatternIntegrated_FullDeriv[*par].resize(mNbIntegrationUsed);
6521  const REAL * RESTRICT p1= (*(comps[i]))[*par].data();
6522  REAL * RESTRICT p0 = mPowderPatternIntegrated_FullDeriv[*par].data();
6523  for(unsigned long j=mNbIntegrationUsed;j>0;j--)
6524  {
6525  #if 1
6526  *p0++ = *p1++;
6527  #else
6528  *p0 = *p1;
6529  if((j==mNbIntegrationUsed)&&((*par)->GetName()=="Cimetidine_C11_x")) cout<<__FILE__<<":"<<__LINE__<<":"<<*p0<<","<<*p1<<endl;
6530  p0++;p1++;
6531  #endif
6532  }
6533  }
6534  else
6535  {
6536  const REAL * RESTRICT p1= (*(comps[i]))[*par].data();
6537  REAL * RESTRICT p0 = mPowderPatternIntegrated_FullDeriv[*par].data();
6538  for(unsigned long j=mNbIntegrationUsed;j>0;j--)
6539  {
6540  #if 1
6541  *p0++ += *p1++;
6542  #else
6543  *p0 += *p1;
6544  if((j==mNbIntegrationUsed)&&((*par)->GetName()=="Cimetidine_C11_x")) cout<<__FILE__<<":"<<__LINE__<<":"<<*p0<<","<<*p1<<endl;
6545  p0++;p1++;
6546  #endif
6547  }
6548  }
6549  }
6550  #if 0
6551  if((*par)->GetName()=="Cimetidine_C11_x")
6552  cout<<"PowderPattern::CalcPowderPatternIntegrated_FullDeriv():"
6553  <<(*par)->GetName()<<":s="<<mScaleFactor(i)<<", d[0]="<<(*(comps[i]))[*par](0)
6554  <<", integ="<<mPowderPatternIntegrated_FullDeriv[*par](0)<<endl;
6555  #endif
6556  }
6557  }
6558 
6559 
6560  //cout<<"PowderPattern::CalcPowderPatternIntegrated_FullDeriv():scale #"<<1<<":"<<scalePar->GetName()<<":"<<scalePar->GetPointer()<<":"<<mPowderPatternUsed_FullDeriv[scalePar]<<endl;
6561 }
6562 
6564 {
6565  this->InitOptions();
6566  {
6567  RefinablePar tmp("Zero",&mXZero,-.05,.05,gpRefParTypeScattDataCorrPos,
6568  REFPAR_DERIV_STEP_ABSOLUTE,true,true,true,false,RAD2DEG);
6570  tmp.SetDerivStep(1e-6);
6571  this->AddPar(tmp);
6572  }
6573  {
6574  RefinablePar tmp("2ThetaDispl",&m2ThetaDisplacement,-.05,.05,gpRefParTypeScattDataCorrPos,
6575  REFPAR_DERIV_STEP_ABSOLUTE,true,true,true,false,RAD2DEG);
6577  tmp.SetDerivStep(1e-6);
6578  this->AddPar(tmp);
6579  }
6580  {
6581  RefinablePar tmp("2ThetaTransp",&m2ThetaTransparency,-.05,.05,gpRefParTypeScattDataCorrPos,
6582  REFPAR_DERIV_STEP_ABSOLUTE,true,true,true,false,RAD2DEG);
6584  tmp.SetDerivStep(1e-6);
6585  this->AddPar(tmp);
6586  }
6587  {
6588  RefinablePar tmp("DIFC",&mDIFC,0,1e6,gpRefParTypeScattDataCorrPos,
6589  REFPAR_DERIV_STEP_ABSOLUTE,true,true,true,false,1.0);
6591  tmp.SetDerivStep(1e-2);
6592  this->AddPar(tmp);
6593  }
6594  {
6595  RefinablePar tmp("DIFA",&mDIFA,-1e4,1e4,gpRefParTypeScattDataCorrPos,
6596  REFPAR_DERIV_STEP_ABSOLUTE,true,true,true,false,1.0);
6598  tmp.SetDerivStep(1e-4);
6599  this->AddPar(tmp);
6600  }
6601  {
6602  RefinablePar tmp("MuR",&mMuR,0,1000,gpRefParTypeScattDataCorrIntAbsorp,
6603  REFPAR_DERIV_STEP_ABSOLUTE,true,true,true,false,1.0);
6605  tmp.SetDerivStep(1e-4);
6606  this->AddPar(tmp);
6607  }
6608 }
6610 {
6611  bool needPrep=false;
6612  for(int i=0;i<mPowderPatternComponentRegistry.GetNb();i++)
6613  {
6614  mPowderPatternComponentRegistry.GetObj(i).GetBraggLimits();
6615  if(mPowderPatternComponentRegistry.GetObj(i).GetClockBraggLimits()
6616  >mClockIntegratedFactorsPrep)
6617  {
6618  needPrep=true;
6619  break;
6620  }
6621  }
6622 
6623  // If using max sin(theta)/lambda
6624  this->CalcNbPointUsed();
6625  if(mClockIntegratedFactorsPrep<mClockNbPointUsed) needPrep=true;
6626 
6627  if(false==needPrep)return;
6628  VFN_DEBUG_ENTRY("PowderPattern::PrepareIntegratedRfactor()",3);
6629  TAU_PROFILE("PowderPattern::PrepareIntegratedRfactor()","void ()",TAU_DEFAULT);
6630 
6631  // Aggregate all limiting pixels in a single list
6632  {
6633  list<long> vLimits;
6634 
6635  for(int i=0;i<mPowderPatternComponentRegistry.GetNb();i++)
6636  {
6637  const CrystVector_long vLim=mPowderPatternComponentRegistry.GetObj(i).GetBraggLimits();
6638  for(int j=0;j<vLim.numElements();j++) vLimits.push_back(vLim(j));
6639  }
6640  if(vLimits.size()<2)
6641  {
6642  mIntegratedPatternMin.resize(0);
6643  mIntegratedPatternMax.resize(0);
6644  mNbIntegrationUsed=0;
6645  mClockIntegratedFactorsPrep.Click();
6646  return;
6647  VFN_DEBUG_EXIT("PowderPattern::PrepareIntegratedRfactor(): no intervals !",3);
6648  }
6649  vLimits.sort();
6650  if(*(vLimits.begin())<0)
6651  {
6652  vLimits.push_back(0);
6653  vLimits.sort();
6654  }
6655  for(list<long>::iterator pos=vLimits.begin();pos!=vLimits.end();)
6656  {
6657  if( (*pos<0) || (*pos>=long(mNbPointUsed)) ) pos=vLimits.erase(pos);
6658  else ++pos;
6659  }
6660 
6661  // Try to avoid too small intervals
6662  list<long> vLimits2;
6663  list<long>::iterator pos1=vLimits.begin();
6664  list<long>::iterator pos2=pos1;pos2++;
6665  for(;pos2!=vLimits.end();)
6666  {
6667  const long pix1=*pos1;
6668  //cout<<__FILE__<<":"<<__LINE__<<":"<<pix1<<endl;
6669  vLimits2.push_back(pix1);
6670  for(;;)
6671  {
6672  pos1=pos2++;
6673  if(pos2==vLimits.end()) break;
6674  if(*pos2>(pix1+8)) break;
6675  }
6676  }
6677  vLimits2.push_back(*pos1);
6678 
6679  // Try to avoid too small intervals (2nd pass)
6680  pos1=vLimits2.begin();
6681  pos2=pos1;pos2++;
6682  for(;pos2!=vLimits2.end();)
6683  {
6684  //cout<<__FILE__<<":"<<__LINE__<<":"<<*pos1<<" -> "<<*pos2<<endl;
6685  if( *pos2<=((*pos1)+2))
6686  {
6687  //cout<<__FILE__<<":"<<__LINE__<<":"<<*pos1<<" -> "<<*pos2<<"...PLONK";
6688  pos2=vLimits2.erase(pos2);
6689  //cout<<"->"<<*pos2<<endl;
6690  }
6691  else {pos1++;pos2++;}
6692  }
6693 
6694  // Create min/max pairs
6695  list<pair<long,long> > vLimits3;
6696  pos1=vLimits2.begin();
6697  pos2=pos1;pos2++;
6698  for(;pos2!=vLimits2.end();)
6699  {
6700  if(*pos2!=(long(mNbPointUsed)-1)) vLimits3.push_back(make_pair(*pos1++,*pos2++-1));
6701  else vLimits3.push_back(make_pair(*pos1++,*pos2++));
6702  //cout<<__FILE__<<":"<<__LINE__<<":"<<vLimits3.back().first<<" -> "<<vLimits3.back().second<<endl;
6703  }
6704 
6705  mIntegratedPatternMin.resize(vLimits3.size());
6706  mIntegratedPatternMax.resize(vLimits3.size());
6707  unsigned long i=0;
6708  for(list<pair<long,long> >::iterator pos=vLimits3.begin();pos!=vLimits3.end();++pos)
6709  {
6710  mIntegratedPatternMin(i)=pos->first;
6711  mIntegratedPatternMax(i++)=pos->second;
6712  }
6713  }
6714  long numInterval=mIntegratedPatternMin.numElements();
6715  CrystVector_bool keep(numInterval);
6716  keep=true;
6717  // Take care of excluded regions (change integration areas accordingly)
6718  // regions are sorted by ascending theta
6719  const long nbExclude=mExcludedRegionMinX.numElements();
6720  if(nbExclude>0)
6721  {
6722  VFN_DEBUG_MESSAGE("PowderPattern::PrepareIntegratedRfactor():5:Excluded regions("<<nbExclude<<")",3);
6723  long j=0;
6724  long minExcl,maxExcl;
6725  minExcl=(long)floor(this->X2Pixel(mExcludedRegionMinX(j)));
6726  maxExcl=(long)ceil (this->X2Pixel(mExcludedRegionMaxX(j)));
6727  for(int i=0;i<nbExclude;i++)
6728  {
6729  while(mIntegratedPatternMax(j)<minExcl)
6730  {
6731  j++;
6732  if(j>=numInterval) break;
6733  }
6734  if(j>=numInterval) break;
6735  while(mIntegratedPatternMin(j)<maxExcl)
6736  {
6737  if( (mIntegratedPatternMin(j)>minExcl) &&(mIntegratedPatternMax(j)<maxExcl))
6738  keep(j)=false;
6739  if( (mIntegratedPatternMin(j)<minExcl) &&(mIntegratedPatternMax(j)<maxExcl))
6740  mIntegratedPatternMax(j)=minExcl;
6741  if( (mIntegratedPatternMin(j)>minExcl) &&(mIntegratedPatternMax(j)>maxExcl))
6742  mIntegratedPatternMin(j)=maxExcl;
6743  if(j==(numInterval-1)) break;
6744  j++;
6745  }
6746  minExcl=(long)(this->X2Pixel(mExcludedRegionMinX(i)));
6747  maxExcl=(long)(this->X2Pixel(mExcludedRegionMaxX(i)));
6748  //go back if one integration segment is concerned by several exclusion zones...
6749  if(j!=0)
6750  while(mIntegratedPatternMax(j)>=minExcl)
6751  {
6752  j--;
6753  if(j==0) break;
6754  }
6755  }
6756  }
6757  // Keep only the selected intervals
6758  VFN_DEBUG_MESSAGE("PowderPattern::PrepareIntegratedRfactor():6",3);
6759  long j=0;
6760  for(int i=0;i<numInterval;i++)
6761  {
6762  if(keep(i))
6763  {
6764  mIntegratedPatternMin(j )=mIntegratedPatternMin(i);
6765  mIntegratedPatternMax(j++)=mIntegratedPatternMax(i);
6766  }
6767  }
6768  numInterval=j;
6769  mIntegratedPatternMax.resizeAndPreserve(numInterval);
6770  mIntegratedPatternMin.resizeAndPreserve(numInterval);
6771 
6772  VFN_DEBUG_MESSAGE("PowderPattern::PrepareIntegratedRfactor():intervals"<<endl\
6773  <<FormatVertVector<long>(mIntegratedPatternMin,mIntegratedPatternMax),2);
6774  // Integrate Obs and weight arrays
6775  mIntegratedObs.resize(numInterval);
6776  mIntegratedVarianceObs.resize(numInterval);
6777  mIntegratedVarianceObs=0;
6778  mIntegratedObs=0;
6779  mIntegratedWeightObs.resize(numInterval);
6780  for(int i=0;i<numInterval;i++)
6781  {
6782  for(int j=mIntegratedPatternMin(i);j<=mIntegratedPatternMax(i);j++)
6783  {
6784  mIntegratedObs (i)+=mPowderPatternObs(j);
6785  mIntegratedVarianceObs(i)+=mPowderPatternObsSigma(j)*mPowderPatternObsSigma(j);
6786  }
6787  if(mIntegratedVarianceObs(i) <= 0) mIntegratedWeightObs(i)=0;
6788  else mIntegratedWeightObs(i)=1./mIntegratedVarianceObs(i);
6789  }
6790 
6791 
6792  //cout<<FormatVertVector<REAL>(mIntegratedPatternMin,
6793  // mIntegratedPatternMax,
6794  // mIntegratedObs,mIntegratedWeight,12,6)<<endl;
6795  mNbIntegrationUsed=mIntegratedPatternMin.numElements();
6796  mClockIntegratedFactorsPrep.Click();
6797  VFN_DEBUG_EXIT("PowderPattern::PrepareIntegratedRfactor()",3);
6798 }
6800 {
6801  if(this->IsBeingRefined())return;
6802  unsigned long tmp;
6803  // Use the first point of the profile of the first reflection not calculated
6804  if(this->GetRadiation().GetWavelengthType()==WAVELENGTH_TOF)
6805  {
6806  tmp=(unsigned long)(this->X2PixelCorr(this->STOL2X(mMaxSinThetaOvLambda)));
6807  }
6808  else
6809  {
6810  REAL sinth=mMaxSinThetaOvLambda*this->GetWavelength();
6811  if(1>fabs(sinth)) tmp=(unsigned long)(this->X2PixelCorr(2*asin(sinth))); else tmp=mNbPoint;
6812  }
6813  if(tmp>mNbPoint) tmp= mNbPoint;
6814  if(tmp !=mNbPointUsed)
6815  {
6816  mNbPointUsed=tmp;
6817  mClockNbPointUsed.Click();
6818  VFN_DEBUG_MESSAGE("PowderPattern::CalcNbPointUsed():"<<mNbPointUsed<<" max(sin(theta)/lambda)="<<mMaxSinThetaOvLambda, 3)
6819  }
6820 
6821 }
6822 
6824 {
6825  VFN_DEBUG_MESSAGE("PowderPattern::InitOptions()",5)
6826  static string OptProfileIntegrationName;
6827  static string OptProfileIntegrationChoices[2];
6828 
6829  static bool needInitNames=true;
6830  if(true==needInitNames)
6831  {
6832  OptProfileIntegrationName="Use Integrated Profiles";
6833  OptProfileIntegrationChoices[0]="Yes (recommended)";
6834  OptProfileIntegrationChoices[1]="No";
6835 
6836  needInitNames=false;//Only once for the class
6837  }
6838  mOptProfileIntegration.Init(2,&OptProfileIntegrationName,OptProfileIntegrationChoices);
6839  this->AddOption(&mOptProfileIntegration);
6840 }
6841 
6842 #ifdef __WX__CRYST__
6843 WXCrystObjBasic* PowderPattern::WXCreate(wxWindow* parent)
6844 {
6845  //:TODO: Check mpWXCrystObj==0
6846  mpWXCrystObj=new WXPowderPattern(parent,this);
6847  return mpWXCrystObj;
6848 }
6849 #endif
6850 
6852 //
6853 // Spacegroup Explorer
6854 //
6856 
6860 SPGScore::SPGScore(const string &s, const REAL r, const REAL g, const unsigned int nbextinct, const REAL ngof, const unsigned int nbrefl):
6861  hm(s),rw(r),gof(g),ngof(ngof),nbextinct446(nbextinct),nbreflused(nbrefl)
6862  {};
6863 
6864 
6865 bool compareSPGScore(const SPGScore &s1, const SPGScore &s2)
6866 {
6867  if(s1.ngof > 0.00001 && s2.ngof >0.00001) return s1.ngof < s2.ngof;
6868  return s1.gof < s2.gof;
6869 }
6870 
6873 std::vector<bool> spgExtinctionFingerprint(Crystal &c, const cctbx::sgtbx::space_group &spg)
6874 {
6875  // We don't have the extinction symbol, so do it the stupid way
6876  std::vector<bool> fingerprint(5*5*7-1+6);
6877  long i=0;
6878  fingerprint[i++]=c.GetPar("a").IsUsed();
6879  fingerprint[i++]=c.GetPar("b").IsUsed();
6880  fingerprint[i++]=c.GetPar("c").IsUsed();
6881  fingerprint[i++]=c.GetPar("alpha").IsUsed();
6882  fingerprint[i++]=c.GetPar("beta").IsUsed();
6883  fingerprint[i++]=c.GetPar("gamma").IsUsed();
6884  for(long h=0;h<5;++h)
6885  for(long k=0;k<5;++k)
6886  for (long l=0;l<7;++l)
6887  {
6888  if((h+k+l)==0) continue;
6889  cctbx::miller::index<long> hkl(scitbx::vec3<long>(h,k,l));
6890  if(i>=fingerprint.size()) cout<<"WHOOOOOOOOOOOOOPS"<<endl;
6891  fingerprint[i++] =spg.is_sys_absent(hkl);
6892  }
6893  return fingerprint;
6894 }
6895 
6899 SpaceGroupExplorer::SpaceGroupExplorer(PowderPatternDiffraction *pd):
6900  mpDiff(pd){};
6901 
6902 SPGScore SpaceGroupExplorer::Run(const string &spgId, const bool fitprofile,
6903  const bool verbose, const bool restore_orig,
6904  const bool update_display, const REAL relative_length_tolerance,
6905  const REAL absolute_angle_tolerance_degree)
6906 {
6907  cctbx::sgtbx::space_group sg;
6908  try
6909  {
6910  // Should work as a HM symbol or number
6911  cctbx::sgtbx::space_group_symbols sgs=cctbx::sgtbx::space_group_symbols(spgId);
6912  sg = cctbx::sgtbx::space_group(sgs);
6913  }
6914  catch(exception ex1)
6915  {
6916  try
6917  {
6918  // Try as a Hall symbol
6919  sg = cctbx::sgtbx::space_group(spgId);
6920  }
6921  catch(exception ex2)
6922  {
6923  string emsg = "Space group symbol '" + spgId + "' not recognized";
6924  throw ObjCrystException(emsg);
6925  }
6926  }
6927  return this->Run(sg, fitprofile, verbose, restore_orig, update_display,
6928  relative_length_tolerance, absolute_angle_tolerance_degree);
6929 }
6930 
6931 SPGScore SpaceGroupExplorer::Run(const cctbx::sgtbx::space_group &spg, const bool fitprofile, const bool verbose,
6932  const bool restore_orig, const bool update_display,
6933  const REAL relative_length_tolerance, const REAL absolute_angle_tolerance_degree)
6934 {
6935  TAU_PROFILE("SpaceGroupExplorer::Run()","void (wxCommandEvent &)",TAU_DEFAULT);
6936  TAU_PROFILE_TIMER(timer1,"SpaceGroupExplorer::Run()LSQ-P1","", TAU_FIELD);
6937  TAU_PROFILE_TIMER(timer2,"SpaceGroupExplorer::Run()LSQ1","", TAU_FIELD);
6938  TAU_PROFILE_TIMER(timer3,"SpaceGroupExplorer::Run()LSQ2","", TAU_FIELD);
6939  Crystal *pCrystal=&(mpDiff->GetCrystal());
6940  // Keep initial lattice parameters & spg
6941  const REAL a=pCrystal->GetLatticePar(0),
6942  b=pCrystal->GetLatticePar(1),
6943  c=pCrystal->GetLatticePar(2),
6944  d=pCrystal->GetLatticePar(3),
6945  e=pCrystal->GetLatticePar(4),
6946  f=pCrystal->GetLatticePar(5);
6947  const string spghm=pCrystal->GetSpaceGroup().GetCCTbxSpg().match_tabulated_settings().hermann_mauguin();
6948  const string name=pCrystal->GetName();
6949  // Set up new spacegroup
6950  const cctbx::sgtbx::space_group_symbols s = spg.match_tabulated_settings();
6951  const string hm=s.universal_hermann_mauguin();
6952  const cctbx::uctbx::unit_cell uc(scitbx::af::double6(a,b,c,d*RAD2DEG,e*RAD2DEG,f*RAD2DEG));
6953  if(!spg.is_compatible_unit_cell(uc,relative_length_tolerance,absolute_angle_tolerance_degree))
6954  {
6955  throw ObjCrystException("Spacegroup is not compatible with unit cell.");
6956  }
6957  mpDiff->GetCrystal().Init(a,b,c,d,e,f,hm,name);
6958  mpDiff->SetExtractionMode(true,true);
6959  unsigned int nbcycle=1;
6960  if(update_display) mpDiff->GetParentPowderPattern().UpdateDisplay();
6961  // Number of free parameters (not taking into account refined profile/background parameters)
6962  unsigned int nbfreepar=mpDiff->GetProfileFitNetNbObs();
6963  if(nbfreepar<1) nbfreepar=1; // Should not happen !
6964 
6965  // Create the LSQ obj even if the profile is not fitted, to allow restoring all parameters
6966  LSQNumObj lsq;
6967  lsq.SetRefinedObj(mpDiff->GetParentPowderPattern(),0,true,true);
6968  lsq.PrepareRefParList(true);
6969  const unsigned int saved_par = lsq.GetCompiledRefinedObj().CreateParamSet("SpaceGroupExplorer saved parameters");
6970  lsq.GetCompiledRefinedObj().SaveParamSet(saved_par);
6971 
6972  Chronometer chrono;
6973  for(unsigned int j=0;j<nbcycle;j++)
6974  {
6975  // First, Le Bail
6976  mpDiff->SetExtractionMode(true,true);
6977  const float t0=chrono.seconds();
6978  if(verbose) cout<<"Doing Le Bail, t="<<FormatFloat(t0,6,2)<<"s";
6979  mpDiff->ExtractLeBail(5);
6980  if(verbose) cout<<", dt="<<FormatFloat(chrono.seconds()-t0,6,2)<<"s"<<endl;
6981  //mpDiff->GetParentPowderPattern().FitScaleFactorForIntegratedRw();
6982  if(fitprofile)
6983  {// Perform LSQ
6984  TAU_PROFILE_START(timer2);
6985  lsq.SetParIsFixed(gpRefParTypeObjCryst,true);
6986  lsq.SetParIsFixed(gpRefParTypeScattDataScale,false);
6987  std::list<RefinablePar*> vnewpar;
6988  std::list<const RefParType*> vnewpartype;
6989  // Only do the full monty for P1, keep the parameters for other spacegroups
6990  if(s.number()==1) vnewpar.push_back(&lsq.GetCompiledRefinedObj().GetPar("Zero"));
6991  lsq.SetParIsFixed(gpRefParTypeUnitCell,false);
6992  lsq.SafeRefine(vnewpar, vnewpartype,1.01,2,true,true);
6993  vnewpar.clear();
6994  TAU_PROFILE_STOP(timer2);
6995  if(s.number()==1)
6996  {
6997  TAU_PROFILE_START(timer1);
6998  vnewpar.push_back(&lsq.GetCompiledRefinedObj().GetPar("2ThetaDispl"));
6999  vnewpar.push_back(&lsq.GetCompiledRefinedObj().GetPar("2ThetaTransp"));
7000  lsq.SafeRefine(vnewpar, vnewpartype,1.01,2,true,true);
7001  vnewpar.clear();
7002  lsq.SetParIsFixed(gpRefParTypeScattDataBackground,false);
7003  // Fix background point beyond optimized domain
7004  const unsigned int nbcomp= mpDiff->GetParentPowderPattern().GetNbPowderPatternComponent();
7005  for(unsigned int i=0;i<nbcomp;++i)
7006  if(mpDiff->GetParentPowderPattern().GetPowderPatternComponent(i).GetClassName()=="PowderPatternBackground")
7007  {
7008  PowderPatternBackground *pback=dynamic_cast<PowderPatternBackground *>
7009  (&(mpDiff->GetParentPowderPattern().GetPowderPatternComponent(i)));
7010  pback->FixParametersBeyondMaxresolution(lsq.GetCompiledRefinedObj());
7011  }
7012  for(unsigned int i=0; i<lsq.GetCompiledRefinedObj().GetNbPar();i++)
7013  if( (lsq.GetCompiledRefinedObj().GetPar(i).IsFixed()==false)
7014  &&(lsq.GetCompiledRefinedObj().GetPar(i).GetType()==gpRefParTypeScattDataBackground))
7015  vnewpar.push_back(&lsq.GetCompiledRefinedObj().GetPar(i));
7016  lsq.SafeRefine(vnewpar,vnewpartype,1.01,2,true,true);
7017  vnewpar.clear();
7018  TAU_PROFILE_STOP(timer1);
7019  }
7020  // restart from equal intensities
7021  mpDiff->SetExtractionMode(true,true);
7022  mpDiff->ExtractLeBail(5);
7023  TAU_PROFILE_START(timer3);
7024  lsq.SafeRefine(vnewpar,vnewpartype,1.01,3,true,true);
7025  TAU_PROFILE_STOP(timer3);
7026  //mpLog->AppendText(wxString::Format(_T("%5.2f%%/"),pDiff->GetParentPowderPattern().GetRw()*100));
7027  //mpDiff->GetParentPowderPattern().FitScaleFactorForIntegratedRw();
7028  }
7029  if(update_display) mpDiff->GetParentPowderPattern().UpdateDisplay();
7030  const REAL rw=mpDiff->GetParentPowderPattern().GetRw()*100;
7031  const REAL gof=mpDiff->GetParentPowderPattern().GetChi2()/mpDiff->GetParentPowderPattern().GetNbPointUsed();
7032  if(verbose) cout << boost::format(" (cycle #%u)\n Rwp=%5.2f%%\n GoF=%9.2f") % j % rw % gof <<endl;
7033  }
7034  const REAL rw=mpDiff->GetParentPowderPattern().GetRw()*100;
7035  const REAL gof=mpDiff->GetParentPowderPattern().GetChi2()/nbfreepar;
7036  const REAL ngof = this->GetP1IntegratedGoF();
7037  unsigned int nbextinct446=0;
7038  std::vector<bool> fgp=spgExtinctionFingerprint(*pCrystal,spg);
7039  for(unsigned int i=6;i<fgp.size();++i) nbextinct446+=(unsigned int)(fgp[i]);
7040  const unsigned int nbrefl = mpDiff->GetNbReflBelowMaxSinThetaOvLambda();
7041  if(verbose>0) cout << boost::format(" Rwp= %5.2f%% GoF=%9.2f nGoF =%9.2f (%3u reflections, %3u extinct)") % rw % gof % ngof % nbrefl % nbextinct446<<endl;
7042 
7043  if(restore_orig)
7044  {
7045  mpDiff->GetCrystal().Init(a,b,c,d,e,f,spghm,name);
7046  lsq.GetCompiledRefinedObj().RestoreParamSet(saved_par);
7047  if (update_display)
7048  {
7049  mpDiff->GetCrystal().UpdateDisplay();
7050  this->mpDiff->GetParentPowderPattern().UpdateDisplay();
7051  }
7052  }
7053 
7054  return SPGScore(hm.c_str(),rw,gof,nbextinct446, ngof, nbrefl);
7055 }
7056 
7057 void SpaceGroupExplorer::RunAll(const bool fitprofile_all, const bool verbose, const bool keep_best,
7058  const bool update_display, const bool fitprofile_p1,
7059  const REAL relative_length_tolerance, const REAL absolute_angle_tolerance_degree)
7060 {
7061  Crystal *pCrystal=&(mpDiff->GetCrystal());
7062 
7063  // Initial lattice parameters & spg
7064  const REAL a=pCrystal->GetLatticePar(0),
7065  b=pCrystal->GetLatticePar(1),
7066  c=pCrystal->GetLatticePar(2),
7067  d=pCrystal->GetLatticePar(3),
7068  e=pCrystal->GetLatticePar(4),
7069  f=pCrystal->GetLatticePar(5);
7070  const cctbx::uctbx::unit_cell uc(scitbx::af::double6(a,b,c,d*RAD2DEG,e*RAD2DEG,f*RAD2DEG));
7071  const string spghm=pCrystal->GetSpaceGroup().GetCCTbxSpg().match_tabulated_settings().hermann_mauguin();
7072  const string name=pCrystal->GetName();
7073 
7074  cctbx::sgtbx::space_group_symbol_iterator it=cctbx::sgtbx::space_group_symbol_iterator();
7075  // First, count compatible spacegroups
7076  unsigned int nbspg=0;
7077  for(;;)
7078  {
7079  cctbx::sgtbx::space_group_symbols s=it.next();
7080  if(s.number()==0) break;
7081  cctbx::sgtbx::space_group spg(s);
7082  if(spg.is_compatible_unit_cell(uc,relative_length_tolerance, absolute_angle_tolerance_degree)) nbspg++;
7083  //if(s.universal_hermann_mauguin().size()>hmlen) hmlen=s.universal_hermann_mauguin().size();
7084  }
7085  if(verbose) cout << boost::format("Beginning spacegroup exploration... %u to go...\n") % nbspg;
7086 
7087  mvSPG.clear();
7088  mvSPGExtinctionFingerprint.clear();
7089 
7090  // Nb refl below max sin(theta/lambda) for p1, to compute nGoF
7091  unsigned int nb_refl_p1=1;
7092 
7093  it=cctbx::sgtbx::space_group_symbol_iterator();
7094  Chronometer chrono;
7095  chrono.start();
7096  for(int i=0;;)
7097  {
7098  cctbx::sgtbx::space_group_symbols s=it.next();
7099  if(s.number()==0) break;
7100  cctbx::sgtbx::space_group spg(s);
7101  bool compat=spg.is_compatible_unit_cell(uc,relative_length_tolerance,absolute_angle_tolerance_degree);
7102  if(compat)
7103  {
7104  i++;
7105  const string hm=s.universal_hermann_mauguin();
7106  // cout<<s.number()<<","<<hm.c_str()<<","<<(int)compat<<endl;
7107  pCrystal->Init(a,b,c,d,e,f,hm,name);
7108 
7109  std::vector<bool> fgp=spgExtinctionFingerprint(*pCrystal,spg);
7110  std::map<std::vector<bool>,SPGScore>::iterator posfgp=mvSPGExtinctionFingerprint.find(fgp);
7111  if(posfgp!=mvSPGExtinctionFingerprint.end())
7112  {
7113  pCrystal->Init(a,b,c,d,e,f,hm,name);
7114  mpDiff->SetExtractionMode(true,true); //:TODO: why is this needed to actually get the updated GetNbReflBelowMaxSinThetaOvLambda ?
7115  unsigned int nbrefl = mpDiff->GetNbReflBelowMaxSinThetaOvLambda();
7116  REAL ngof = (posfgp->second.ngof * nbrefl) / posfgp->second.nbreflused;
7117  mvSPG.push_back(SPGScore(hm.c_str(),posfgp->second.rw,posfgp->second.gof,posfgp->second.nbextinct446, ngof, nbrefl));
7118  if(verbose) cout<<boost::format(" (#%3d) %-14s: Rwp= %5.2f%% GoF=%9.2f nGoF=%9.2f (%3u reflections, %3u extinct)")
7119  % s.number() % hm.c_str() % mvSPG.back().rw % mvSPG.back().gof % mvSPG.back().ngof % mvSPG.back().nbreflused % mvSPG.back().nbextinct446
7120  <<" [same extinctions as:"<<posfgp->second.hm<<"]\n";
7121  }
7122  else
7123  {
7124  if(((s.number()==1) && fitprofile_p1) || fitprofile_all) mvSPG.push_back(this->Run(spg, true, false, false, update_display,
7125  relative_length_tolerance, absolute_angle_tolerance_degree));
7126  else mvSPG.push_back(this->Run(spg, false, false, true, update_display,relative_length_tolerance,absolute_angle_tolerance_degree));
7127  if(s.number() == 1) nb_refl_p1 = mvSPG.back().nbreflused;
7128  mvSPG.back().ngof *= mpDiff->GetNbReflBelowMaxSinThetaOvLambda() / (float)nb_refl_p1;
7129  mvSPGExtinctionFingerprint.insert(make_pair(fgp, mvSPG.back()));
7130 
7131  if(verbose) cout<<boost::format(" (#%3d) %-14s: Rwp= %5.2f%% GoF=%9.2f nGoF=%9.2f (%3u reflections, %3u extinct)\n")
7132  % s.number() % hm.c_str() % mvSPG.back().rw % mvSPG.back().gof % mvSPG.back().ngof % mvSPG.back().nbreflused % mvSPG.back().nbextinct446;
7133  }
7134  }
7135  }
7136  mvSPG.sort(compareSPGScore);
7137  if(keep_best)
7138  {
7139  if(verbose) cout<<"Restoring best spacegroup: "<<mvSPG.front().hm<<endl;
7140  pCrystal->ChangeSpaceGroup(mvSPG.front().hm);
7141  }
7142  else
7143  {
7144  // Go back to original lattice and spacegroup & update display
7145  pCrystal->Init(a,b,c,d,e,f,spghm,name);
7146  }
7147  mpDiff->SetExtractionMode(true,true);
7148  mpDiff->ExtractLeBail(5);
7149  if(update_display)
7150  {
7151  pCrystal->UpdateDisplay();
7152  this->mpDiff->GetParentPowderPattern().UpdateDisplay();
7153  }
7154 
7155 }
7156 
7157 const list<SPGScore>& SpaceGroupExplorer::GetScores() const
7158 {
7159  return mvSPG;
7160 }
7161 
7162 REAL SpaceGroupExplorer::GetP1IntegratedGoF()
7163 {
7164  if(mpDiff->GetCrystal().GetSpaceGroup().GetSpaceGroupNumber()==1)
7165  {
7166  mpDiff->GetPowderPatternIntegratedCalc();
7167  mP1IntegratedProfileMin = mpDiff->GetParentPowderPattern().GetIntegratedProfileMin();
7168  mP1IntegratedProfileMax = mpDiff->GetParentPowderPattern().GetIntegratedProfileMax();
7169  // cout<<"Updating mP1IntegratedProfileMin/Max:"<<endl
7170  // <<FormatVertVectorHKLFloats<REAL>(mP1IntegratedProfileMin, mP1IntegratedProfileMax,mP1IntegratedProfileMax)<<endl;
7171  }
7172  else if (mP1IntegratedProfileMin.size()==0) return 0;
7173 
7174  //cout<<FormatVertVectorHKLFloats<REAL>(mpDiff->GetH(), mpDiff->GetK(), mpDiff->GetL(), mpDiff->GetFhklCalcSq());
7175  REAL integratedChi2=0.;
7176  REAL integratedChi2LikeNorm=0.;
7177  const REAL * RESTRICT p1, * RESTRICT p2, * RESTRICT p3;
7178  CrystVector_REAL const* pcalc = &(mpDiff->GetParentPowderPattern().GetPowderPatternCalc());
7179  CrystVector_REAL const* pobs = &(mpDiff->GetParentPowderPattern().GetPowderPatternObs());
7180  CrystVector_REAL const* psigma = &(mpDiff->GetParentPowderPattern().GetPowderPatternObsSigma());
7181  const unsigned int jmax = mpDiff->GetParentPowderPattern().GetNbPointUsed();
7182  REAL chi2=0;
7183  unsigned int nbpoint = 0;
7184  for(unsigned long i=0;i<mP1IntegratedProfileMin.size();i++)
7185  {
7186  if(mP1IntegratedProfileMin(i) > jmax) break;
7187  if(mP1IntegratedProfileMax(i) < 0) continue;
7188  REAL v=0, c=0, o=0;
7189  for(unsigned long j=mP1IntegratedProfileMin(i); j<=mP1IntegratedProfileMax(i); j++)
7190  {
7191  if(j<0) continue;
7192  if(j >= jmax) break;
7193  nbpoint++;
7194  c += (*pcalc)(j); // calc
7195  o += (*pobs)(j); // obs
7196  v += (*psigma)(j)*(*psigma)(j); // variance
7197  }
7198  if(v>0) chi2 += (c-o)*(c-o)/v;
7199  }
7200  return chi2 / nbpoint;
7201 }
7202 
7203 }//namespace ObjCryst
The namespace which includes all objects (crystallographic and algorithmic) in ObjCryst++.
Definition: doc-main.h:25
ReflectionProfileType
Profile type for powder (could it be used fopr single crystals on 2D detectors ?)
Definition: General.h:105
const RefParType * gpRefParTypeScattDataScale
Type for scattering data scale factors.
std::vector< bool > spgExtinctionFingerprint(Crystal &c, const cctbx::sgtbx::space_group &spg)
Function which determines the unique extinction fingerprint of a spacegroup, by calculating all prese...
ObjRegistry< PowderPatternComponent > gPowderPatternComponentRegistry("List of all PowderPattern Components")
Global registry for all PowderPatternComponent objects.
RadiationType
Type of radiation used.
Definition: General.h:96
const RefParType * gpRefParTypeScattDataCorrIntAbsorp
Parameter type for absorption correction.
const RefParType * gpRefParTypeScattDataCorrPos
Parameter type for correction to peak positions.
const RefParType * gpRefParTypeScattDataProfile
Type for reflection profile.
bool ISNAN_OR_INF(REAL r)
Test if the value is a NaN.
Definition: ObjCryst/IO.cpp:97
const RefParType * gpRefParTypeScattDataBackground
Parameter type for background intensity.
const RefParType * gpRefParTypeObjCryst
Top RefParType for the ObjCryst++ library.
ObjRegistry< RefinableObj > gTopRefinableObjRegistry("Global Top RefinableObj registry")
This is a special registry for 'top' object for an optimization.
Main CIF class - parses the stream and separates data blocks, comments, items, loops.
Definition: CIF.h:170
std::map< std::string, CIFData > mvData
The data blocks, after parsing. The key is the name of the data block.
Definition: CIF.h:181
Crystal class: Unit cell, spacegroup, scatterers.
Definition: Crystal.h:98
DiffractionData object for Single Crystal analysis.
Exception class for ObjCryst++ library.
Definition: General.h:122
Class to store positions of observed reflections.
Definition: Indexing.h:117
vector< hkl > & GetPeakList()
Get peak list.
Definition: Indexing.cpp:931
void AddPeak(const float d, const float iobs=1.0, const float dobssigma=0.0, const float iobssigma=0.0, const int h=0, const int k=0, const int l=0, const float d2calc=0)
Add one peak.
Definition: Indexing.cpp:887
Molecule : class for complex scatterer descriptions using cartesian coordinates with bond length/angl...
Definition: Molecule.h:760
virtual const string & GetName() const
Get the name of this object.
virtual void CalcCorr() const
Do the computation of corrected intensities.
CylinderAbsCorr(const PowderPatternDiffraction &data)
Constructor.
virtual const string & GetClassName() const
Get the name of the class.
Generic class to compute components (eg the contribution of a given phase, or background) of a powder...
Definition: PowderPattern.h:73
CrystVector_REAL mPowderPatternCalcVariance
The variance associated to each point of the calculated powder pattern.
virtual const string & GetClassName() const
Name for this class ("RefinableObj", "Crystal",...).
bool IsScalable() const
Is this component scalable ?
virtual const CrystVector_REAL & GetPowderPatternCalc() const =0
Get the calculated powder pattern for this component.
RefinableObjClock mClockPowderPatternIntegratedVarianceCalc
When was the 'integrated' powder pattern variance last computed ?
RefinableObjClock mClockPowderPatternVarianceCalc
When was the powder pattern variance last computed ?
virtual void SetParentPowderPattern(PowderPattern &)=0
Set the PowderPattern object which uses this component.
RefinableObjClock mClockBraggLimits
Get last time the Bragg Limits were changed.
const PowderPattern & GetParentPowderPattern() const
Get the PowderPattern object which uses this component.
virtual void CalcPowderPatternIntegrated_FullDeriv(std::set< RefinablePar * > &vPar)
Calc the integrated powder pattern.
CrystVector_REAL mPowderPatternIntegratedCalc
The calculated powder pattern, integrated.
bool mIsScalable
Scalable ? (crystal phase = scalable, background= not scalable)
RefinableObjClock mClockPowderPatternCalc
When was the powder pattern last computed ?
list< pair< const REAL,const string > > mvLabel
The labels associated to different points of the pattern.
virtual pair< const CrystVector_REAL *, const RefinableObjClock * > GetPowderPatternIntegratedCalc() const =0
Get the integrated values of the powder pattern.
CrystVector_long mIntegratedReflLimits
Interval limits around each reflection, for integrated R-factors.
const RefinableObjClock & GetClockPowderPatternCalc() const
Last time the powder pattern was calculated.
PowderPattern * mpParentPowderPattern
The PowderPattern object in which this component is included.
RefinableObjClock mClockPowderPatternIntegratedCalc
When was the 'integrated' powder pattern last computed ?
CrystVector_REAL mPowderPatternCalc
The calculated component of a powder pattern.
CrystVector_REAL mPowderPatternIntegratedCalcVariance
The variance associated to each point of the calculated powder pattern, integrated.
const RefinableObjClock & GetClockBraggLimits() const
Get last time the Bragg Limits were changed.
const list< pair< const REAL,const string > > & GetPatternLabelList() const
Get a list of labels for the pattern (usually reflection indexes).
Phase to compute a background contribution to a powder pattern using an interpolation.
virtual void CalcPowderPatternIntegrated_FullDeriv(std::set< RefinablePar * > &vPar)
Calc the integrated powder pattern.
void OptimizeBayesianBackground()
Optimize the background using a Bayesian approach.
virtual bool HasPowderPatternCalcVariance() const
Does this component have a variance associated with each calculated point ? i.e., do we use maximum l...
CrystVector_long mPointOrder
Subscript of the points, sorted the correct order, taking into account the type of radiation (monochr...
CrystVector_REAL mvSplinePixel
Vector of pixel values between each interval, for faster CubicSpline calculations.
int mBackgroundNbPoint
Number of fitting points for background.
virtual void TagNewBestConfig() const
During a global optimization, tells the object that the current config is the latest "best" config.
virtual void SetMaxSinThetaOvLambda(const REAL max)
Set the maximum value for sin(theta)/lambda.
virtual void BeginOptimization(const bool allowApproximations=false, const bool enableRestraints=false)
This should be called by any optimization class at the begining of an optimization.
CubicSpline mvSpline
Spline used for interpolation.
CrystVector_REAL mBackgroundInterpPointX
Vector of 2theta values for the fitting points of the background.
virtual void GetGeneGroup(const RefinableObj &obj, CrystVector_uint &groupIndex, unsigned int &firstGroup) const
Get the gene group assigned to each parameter.
virtual void CalcPowderPattern() const
Calc the powder pattern.
virtual void SetParentPowderPattern(PowderPattern &)
Set the PowderPattern object which uses this component.
virtual const CrystVector_REAL & GetPowderPatternCalcVariance() const
Get the variance associated to each point of the calculated powder pattern, for this component.
void FixParametersBeyondMaxresolution(RefinableObj &obj)
Fix parameters corresponding to points of the pattern that are not actually calculated.
virtual const string & GetClassName() const
Name for this class ("RefinableObj", "Crystal",...).
virtual pair< const CrystVector_REAL *, const RefinableObjClock * > GetPowderPatternIntegratedCalcVariance() const
Get the variance associated to each point of the calculated powder pattern, for this component (integ...
RefObjOpt mInterpolationModel
Type of interpolation performed: linear or cubic spline.
CrystVector_REAL mBackgroundInterpPointIntensity
Values of background at interpolating points.
REAL mMaxSinThetaOvLambda
Maximum sin(theta)/lambda for all calculations (10 by default).
virtual pair< const CrystVector_REAL *, const RefinableObjClock * > GetPowderPatternIntegratedCalc() const
Get the integrated values of the powder pattern.
RefinableObjClock mClockBackgroundPoint
Modification of the interpolated points.
void ImportUserBackground(const string &filename)
Import background points from a file (with two columns 2theta (or tof), intensity)
virtual const CrystVector_long & GetBraggLimits() const
Get the pixel positions separating the integration intervals around reflections.
virtual const CrystVector_REAL & GetPowderPatternCalc() const
Get the calculated powder pattern for this component.
RefinableObjClock mClockSpline
Initialization of the spline.
REAL mModelVariance
Constant error (sigma) on the calculated pattern, due to an incomplete model.
Class to compute the contribution to a powder pattern from a crystalline phase.
void SetExtractionMode(const bool extract=true, const bool init=false)
Prepare intensity extraction (Le Bail or Pawley)
const ReflectionProfile & GetProfile() const
Get reflection profile.
virtual pair< const CrystVector_REAL *, const RefinableObjClock * > GetPowderPatternIntegratedCalcVariance() const
Get the variance associated to each point of the calculated powder pattern, for this component (integ...
unsigned int GetProfileFitNetNbObs() const
Get the 'net' number of observed intensities, minus the number of reflections, for a profile fit.
void SetFrozenLatticePar(const unsigned int i, REAL v)
Change one parameter in mFrozenLatticePar. This triggers a call to CalcLocalBMatrix() if the paramete...
REAL GetFrozenLatticePar(const unsigned int i) const
Access to one parameter in mFrozenLatticePar.
virtual const CrystVector_REAL & GetPowderPatternCalc() const
Get the calculated powder pattern for this component.
virtual pair< const CrystVector_REAL *, const RefinableObjClock * > GetPowderPatternIntegratedCalc() const
Get the integrated values of the powder pattern.
const CrystVector_REAL & GetFhklObsSq() const
Get the extracted structure factors modulus (squared), e.g.
virtual void CalcPowderPatternIntegrated_FullDeriv(std::set< RefinablePar * > &vPar)
Calc the integrated powder pattern.
virtual void CalcPowderPattern() const
Calc the powder pattern.
virtual void SetCrystal(Crystal &crystal)
Set the crystal for this experiment.
void CalcPowderReflProfile_FullDeriv(std::set< RefinablePar * > &vPar)
virtual void SetMaxSinThetaOvLambda(const REAL max)
Set the maximum value for sin(theta)/lambda.
virtual bool HasPowderPatternCalcVariance() const
Does this component have a variance associated with each calculated point ? i.e., do we use maximum l...
virtual const CrystVector_REAL & GetPowderPatternCalcVariance() const
Get the variance associated to each point of the calculated powder pattern, for this component.
virtual void GetGeneGroup(const RefinableObj &obj, CrystVector_uint &groupIndex, unsigned int &firstGroup) const
Get the gene group assigned to each parameter.
void SetReflectionProfilePar(const ReflectionProfileType prof, const REAL fwhmCagliotiW, const REAL fwhmCagliotiU=0, const REAL fwhmCagliotiV=0, const REAL eta0=0.5, const REAL eta1=0.)
Set reflection profile parameters.
virtual long GetNbReflBelowMaxSinThetaOvLambda() const
Recalc, and get the number of reflections which should be actually used, due to the maximuml sin(thet...
bool GetExtractionMode() const
Return true if in extraction mode, i.e. using extracted intensities instead of computed structure fac...
virtual const CrystVector_long & GetBraggLimits() const
Get the pixel positions separating the integration intervals around reflections.
void ExtractLeBail(unsigned int nbcycle=1)
Extract intensities using Le Bail method.
virtual const string & GetClassName() const
Name for this class ("RefinableObj", "Crystal",...).
virtual void EndOptimization()
This should be called by any optimization class at the end of an optimization.
virtual void SetParentPowderPattern(PowderPattern &)
Set the PowderPattern object which uses this component.
void SetProfile(ReflectionProfile *prof)
Assign a new profile.
virtual PowderPatternDiffraction * CreateCopy() const
So-called virtual copy constructor.
bool HasFhklObsSq() const
Return true if there are extracted (le Bail) squared structure factors, false otherwise.
virtual const CrystMatrix_REAL & GetBMatrix() const
This can use either locally stored lattice parameters from mLocalLatticePar, or the Crystal's,...
void CalcFrozenBMatrix() const
Calculate the local BMatrix, used if mFreezeLatticePar is true.
virtual void SetApproximationFlag(const bool allow)
Enable or disable numerical approximations.
bool FreezeLatticePar() const
Do we use local cell parameters ? (see mFrozenLatticePar)
virtual const Radiation & GetRadiation() const
Get the radiation object for this data.
Powder pattern class, with an observed pattern and several calculated components to modelize the patt...
REAL X2Pixel(const REAL x) const
Get the pixel number on the experimental pattern, corresponding to a given (experimental) x coordinat...
void AddPowderPatternComponent(PowderPatternComponent &)
Add a component (phase, backround) to this pattern.
REAL X2STOL(const REAL x) const
Convert X (either 2theta or TOF) to sin(theta)/lambda, depending on the type of radiation.
CrystVector_REAL mPowderPatternCalc
The calculated powder pattern.
Radiation mRadiation
The Radiation corresponding to this experiment.
REAL STOL2X(const REAL stol) const
Convert sin(theta)/lambda to X (i.e.
virtual const CrystVector_REAL & GetLSQObs(const unsigned int) const
Get the observed values for the LSQ function.
const RefinableObjClock & GetClockNbPointUsed() const
Clock corresponding to the last time the number of points used was changed.
CrystVector_REAL mChi2Cumul
The cumulative Chi^2 (integrated or not, depending on the option)
void PrepareIntegratedRfactor() const
Prepare the calculation of the integrated R-factors.
REAL GetIntegratedChi2() const
Return integrated Chi^2.
REAL GetWavelength() const
wavelength of the experiment (in Angstroems)
CrystVector_REAL mPowderPatternBackgroundIntegratedCalc
The calculated powder pattern part which corresponds to 'background' (eg non-scalable components),...
unsigned long mNbPoint
Number of points in the pattern.
REAL GetPowderPatternXMax() const
Get the maximum 2theta.
void ImportPowderPattern2ThetaObs(const string &fileName, const int nbSkip=0)
Import file with 2 columns 2Theta Iobs.
void ImportPowderPatternPSI_DMC(const string &filename)
Import powder pattern, format DMC from PSI.
const CrystVector_long & GetIntegratedProfileMin() const
Get the list of first pixels for the integration intervals.
void SetSigmaToSqrtIobs()
Set sigma=sqrt(Iobs)
void CalcPowderPatternIntegrated() const
Calc the integrated powder pattern.
void ImportPowderPatternFullprof4(const string &fileName)
Import diffraction data from a file, with the first line has 2ThetaMin, step, 2thetaMax,...
REAL GetR() const
Unweighted R-factor.
virtual const CrystVector_REAL & GetLSQWeight(const unsigned int) const
Get the weight values for the LSQ function.
const RefinableObjClock & GetClockPowderPatternPar() const
When were the pattern parameters (2theta range, step) changed ?
const RefinableObjClock & GetIntegratedProfileLimitsClock() const
When were the integration intervals last changed ?
void SetWeightPolynomial(const REAL a, const REAL b, const REAL c, const REAL minRelatIobs=1e-3)
Set w = 1/(a+ Iobs + b*Iobs^2+c*Iobs^3)
const PowderPatternComponent & GetPowderPatternComponent(const string &name) const
Access to a component of the powder pattern.
const CrystVector_REAL & GetPowderPatternWeight() const
Get the weight for each point of the powder pattern.
void CalcNbPointUsed() const
Calculate the number of points of the pattern actually used, from the maximum value of sin(theta)/lam...
void ImportPowderPatternFullprof(const string &fullprofFileName)
Import fullprof-style diffraction data.
virtual std::map< RefinablePar *, CrystVector_REAL > & GetLSQ_FullDeriv(const unsigned int, std::set< RefinablePar * > &vPar)
Get the first derivative for the LSQ function for each parameter supplied in a list.
virtual void SetMaxSinThetaOvLambda(const REAL max)
Set the maximum value for sin(theta)/lambda.
CrystVector_REAL mPowderPatternUsedCalc
The calculated powder pattern. Cropped to the maximum sin(theta)/lambda for LSQ.
void ImportPowderPatternXdd(const string &fileName)
Import *.xdd diffraction data (Topas,...).
virtual unsigned int GetNbLSQFunction() const
Number of LSQ functions.
const CrystVector_REAL & GetPowderPatternVariance() const
Get the variance (obs+model) for each point of the powder pattern.
void ImportPowderPatternCIF(const CIF &cif)
Import CIF powder pattern data.
CrystVector_REAL mPowderPatternUsedObs
The calculated powder pattern. Cropped to the maximum sin(theta)/lambda for LSQ.
REAL GetMuR() const
Get the $\mu R$ value.
void SetWeightToUnit()
Set w = 1.
REAL mMaxSinThetaOvLambda
Displacement correction : REAL m2ThetaDisplacement; Transparency correction : REAL m2ThetaTranspare...
void SetXZero(const REAL newZero)
Change Zero in x (2theta,tof)
void ExportFullprof(const std::string &prefix) const
Export powder pattern & crystal structure in Fullprof format.
void SetScaleFactor(const int i, REAL s)
Access to the scale factor of components (will be 1 for background components)
void SetPowderPatternX(const CrystVector_REAL &x)
Set the x coordinate of the powder pattern : either the 2theta or time-of-flight values for each reco...
CrystVector_REAL mExcludedRegionMinX
Min coordinate for for all excluded regions.
CrystVector_REAL mPowderPatternWeight
The weight for each point of the pattern.
unsigned long GetNbPoint() const
Number of points ?
REAL GetPowderPatternXStep() const
Get the average step in 2theta.
REAL GetRw() const
Get the weighted R-factor.
void Set2ThetaTransparency(const REAL transparency)
Change transparency correction .
virtual const CrystVector_REAL & GetLSQCalc(const unsigned int) const
Get the current calculated value for the LSQ function.
CrystVector_REAL mExcludedRegionMaxX
Max coordinate for 2theta for all excluded regions.
void ImportPowderPatternGSAS(const string &fileName)
Import GSAS standard powder pattern data (see GSAS manual).
void SetRadiation(const Radiation &radiation)
Set the radiation.
CrystVector_REAL mPowderPatternVarianceIntegrated
The complete variance associated to each point of the powder pattern, taking into account observation...
RadiationType GetRadiationType() const
Neutron or x-ray experiment ?
void RemovePowderPatternComponent(PowderPatternComponent &)
Remove a powder pattern component.
void SetPowderPatternObs(const CrystVector_REAL &obs)
Set observed powder pattern from vector array.
REAL X2PixelCorr(const REAL x) const
Get the pixel number on the experimental pattern, from the theoretical (uncorrected) x coordinate,...
const Radiation & GetRadiation() const
Neutron or x-ray experiment ?
RefinableObjClock mClockPowderPatternIntegratedCalc
When was the powder pattern (integrated) last computed ?
void ImportPowderPatternILL_D1A5(const string &filename)
Import powder pattern, format from ILL D1A/D2B (format without counter info)
const RefinableObjClock & GetClockPowderPatternAbsCorr() const
When were the absorption correction parameters (muR) last changed ?
void CalcPowderPattern() const
Calc the powder pattern.
const CrystVector_REAL & GetPowderPatternX() const
Get the vector of X (2theta or time-of-flight) coordinates.
unsigned long GetNbPointUsed() const
Number of points actually calculated (below the chosen max(sin(theta)/lambda)) ?
void AddExcludedRegion(const REAL min2Theta, const REAL max2theta)
Add an Exclusion region, in 2theta, which will be ignored when computing R's XMLInput values must be,...
virtual void GlobalOptRandomMove(const REAL mutationAmplitude, const RefParType *type=gpRefParTypeObjCryst)
Make a random move of the current configuration.
void ImportPowderPatternTOF_ISIS_XYSigma(const string &fileName)
Import TOF file (ISIS type, 3 columns t, Iobs, sigma(Iobs))
const CrystVector_REAL & GetChi2Cumul(const int mode=-1) const
Get the powder pattern cumulative Chi^2.
CrystVector_REAL mPowderPatternBackgroundCalc
The calculated powder pattern part which corresponds to 'background' (eg non-scalable components).
CrystVector_REAL mPowderPatternObs
The observed powder pattern.
virtual void GetGeneGroup(const RefinableObj &obj, CrystVector_uint &groupIndex, unsigned int &firstGroup) const
Get the gene group assigned to each parameter.
RefinableObjClock mClockPowderPatternCalc
When was the powder pattern last computed ?
CrystVector_REAL mPowderPatternObsSigma
The sigma of the observed pattern.
virtual REAL GetLogLikelihood() const
Get -log(likelihood) of the current configuration for the object.
CrystVector_REAL mPowderPatternUsedWeight
The weight for each point of the pattern. Cropped to the maximum sin(theta)/lambda for LSQ.
REAL STOL2Pixel(const REAL stol) const
Convert sin(theta)/lambda to pixel, depending on the type of radiation.
REAL GetPowderPatternXMin() const
Get the Minimum 2theta.
virtual void InitOptions()
Initialize options.
virtual void Init()
Init parameters and options.
void FitScaleFactorForRw() const
Fit the scale(s) factor of each component to minimize Rw.
REAL GetChi2() const
Return conventionnal Chi^2.
REAL GetMaxSinThetaOvLambda() const
Get the maximum value for sin(theta)/lambda.
RefinableObjClock mClockScaleFactor
Last modification of the scale factor.
CrystVector_REAL mPowderPatternIntegratedCalc
The calculated powder pattern, integrated.
void ImportPowderPatternMultiDetectorLLBG42(const string &fileName)
diffraction data in a multi-detector format (fullprof format #6).
void PrintObsCalcData(ostream &os=cout) const
Print to thee screen/console the observed and calculated pattern (long, mostly useful for debugging)
const CrystVector_REAL & GetPowderPatternObs() const
Get the observed powder pattern.
CrystVector_REAL mX
Vector of x coordinates (either 2theta or time-of-flight) for the pattern.
unsigned int GetNbPowderPatternComponent() const
Number of components.
CrystVector_REAL mPowderPatternVariance
The complete variance associated to each point of the powder pattern, taking into account observation...
RefinableObjClock mClockCorrAbs
Last modification of absorption correction parameters.
const RefinableObjClock & GetClockPowderPatternCalc() const
Last time the pattern was calculated.
REAL X2XCorr(const REAL x) const
Get the experimental x (2theta, tof) from the theoretical value, taking into account all corrections ...
void SetRadiationType(const RadiationType radiation)
Set the radiation type.
PeakList FindPeaks(const float dmin=2.0, const float maxratio=0.01, const unsigned int maxpeak=100)
Find peaks in the pattern.
void ImportPowderPatternSietronicsCPI(const string &fileName)
Import *.cpi Sietronics diffraction data.
void SetPowderPatternPar(const REAL min, const REAL step, unsigned long nbPoint)
\briefSet the powder pattern angular range & resolution parameter.
const CrystVector_long & GetIntegratedProfileMax() const
Get the list of last pixels for the integration intervals.
void SetWeightToInvSigmaSq(const REAL minRelatSigma=1e-3)
Set w = 1/sigma^2.
void FitScaleFactorForR() const
Fit the scale(s) factor of each component to minimize R.
const CrystVector_REAL & GetPowderPatternCalc() const
Get the calculated powder pattern.
virtual void BeginOptimization(const bool allowApproximations=false, const bool enableRestraints=false)
This should be called by any optimization class at the begining of an optimization.
RefinableObjClock mClockPowderPatternXCorr
Corrections to 2Theta.
bool mIsXAscending
Is the mX vector sorted in ascending order ? (true for 2theta, false for TOF)
RefinableObjClock mClockPowderPatternPar
When were the pattern parameters (2theta or time-of-flight range) changed ?
REAL mXZero
Zero correction : Thus mPowderPattern2ThetaMin=(mPowderPattern2ThetaMin-m2ThetaZero)
const RefinableObjClock & GetClockPowderPatternRadiation() const
When were the radiation parameter (radiation type, wavelength) changed ?
void SetMuR(const REAL muR)
Set the $\mu R$ value for cylinder absorption correction.
REAL GetChi2_Option() const
Return the conventionnal or integrated Chi^2, depending on the option.
void SavePowderPattern(const string &filename="powderPattern.out") const
Save powder pattern to one file, text format, 3 columns theta Iobs Icalc.
void SetWavelength(const REAL lambda)
Set the wavelength of the experiment (in Angstroems).
void Set2ThetaDisplacement(const REAL displacement)
Change displacement correction .
void ImportPowderPattern2ThetaObsSigma(const string &fileName, const int nbSkip=0)
Import file with 3 columns 2Theta Iobs Sigma.
virtual const string & GetClassName() const
Name for this class ("RefinableObj", "Crystal",...).
const CrystVector_REAL & GetScaleFactor() const
Access the scale factors (see PowderPattern::mScaleFactor)
const RefinableObjClock & GetClockPowderPatternXCorr() const
When were the parameters for 2theta/TOF correction (zero, transparency, displacement) last changed ?
RefinableObjClock mClockPowderPatternRadiation
When were the radiation parameter (radiation type, wavelength) changed ?
const CrystVector_REAL & GetPowderPatternObsSigma() const
Get the sigma for each point of the observed powder pattern.
Structure to hold the score corresponding to a given spacegroup.
SPGScore(const string &s, const REAL r, const REAL g, const unsigned int nbextinct, const REAL ngof=0, const unsigned int nbrefl=0)
Structure to hold the score corresponding to a given spacegroup.
This object is used to estimate the background in a powder pattern, using a Bayesian approach (David ...
Abstract base class for reflection profiles.
Pseudo-Voigt reflection profile.
void SetProfilePar(const REAL fwhmCagliotiW, const REAL fwhmCagliotiU=0, const REAL fwhmCagliotiV=0, const REAL eta0=0.5, const REAL eta1=0.)
Set reflection profile parameters.
Double-Exponential Pseudo-Voigt profile for TOF.
void SetUnitCell(const UnitCell &cell)
Set unit cell.
Base class to compute all kind of corrections to intensities: Lorentz, Polar, absorption,...
const ScatteringData * mpData
The associated ScatteringData object.
CrystVector_REAL mCorr
The vector of correction to intensities.
RefinableObjClock mClockCorrCalc
The clock marking the last time the correction was calculated.
Class to define the radiation (type, monochromaticity, wavelength(s)) of an experiment.
WavelengthType GetWavelengthType() const
Get the Wavelength type (monochromatic, Alpha1+Alpha2, Time Of Flight...)
const CrystVector_REAL & GetWavelength() const
Get the wavelength(s) in Angstroems.
void SetRadiationType(const RadiationType)
Set the radiation type (X-Rays, Neutron)
void SetWavelength(const REAL)
Set the (monochromatic) wavelength of the beam.
void SetWavelengthType(const WavelengthType &type)
Set the Wavelength type (monochromatic, Alpha1+Alpha2, Time Of Flight...)
RadiationType GetRadiationType() const
Get the radiation type (X-Rays, Neutron)
Class to compute structure factors for a set of reflections and a Crystal.
const CrystVector_REAL & GetTheta() const
Return an array with theta values for all reflections.
virtual void SetMaxSinThetaOvLambda(const REAL max)
Set the maximum value for sin(theta)/lambda.
virtual void SetCrystal(Crystal &crystal)
Set the crystal for this experiment.
const RefinableObjClock & GetClockTheta() const
Clock the last time the sin(theta)/lambda and theta arrays were re-computed.
CrystVector_REAL mX
reflection coordinates in an orthonormal base
virtual const CrystMatrix_REAL & GetBMatrix() const
Get access to the B matrix used to compute reflection positions.
long GetNbRefl() const
Return the number of reflections in this experiment.
virtual long GetNbReflBelowMaxSinThetaOvLambda() const
Recalc, and get the number of reflections which should be actually used, due to the maximuml sin(thet...
Abstract Base Class to describe the scattering power of any Scatterer component in a crystal.
list of scattering positions in a crystal, associated with the corresponding occupancy and a pointer ...
long GetNbComponent() const
Number of components.
Unit Cell class: Unit cell with spacegroup information.
Definition: UnitCell.h:72
Vector library (Blitz++ mimic) for ObjCryst++.
Definition: CrystVector.h:123
void Init(const CrystVector_REAL &x, const CrystVector_REAL &y, const REAL yp1, const REAL ypn)
Spline with given extremum derivatives.
void AddRefinableObj(RefinableObj &)
Add a refined object. All sub-objects are also added.
virtual REAL GetLogLikelihood() const
The optimized (minimized, actually) function.
(Quick & dirty) Least-Squares Refinement Object with Numerical derivatives
Definition: LSQNumObj.h:39
void Refine(int nbCycle=1, bool useLevenbergMarquardt=false, const bool silent=false, const bool callBeginEndOptimization=true, const float minChi2var=0.01)
Do the refinement.
Definition: LSQNumObj.cpp:106
void SetParIsUsed(const std::string &parName, const bool use)
Set a parameter to be used.
void SetRefinedObj(RefinableObj &obj, const unsigned int LSQFuncIndex=0, const bool init=true, const bool recursive=false)
Choose the object to refine.
Definition: LSQNumObj.cpp:824
void PrepareRefParList(const bool copy_param=false)
Prepare the full parameter list for the refinement.
Definition: LSQNumObj.cpp:913
class of refinable parameter types.
Definition: RefinableObj.h:80
bool IsDescendantFromOrSameAs(const RefParType *type) const
Returns true if the parameter is a descendant of 'type'.
We need to record exactly when refinable objects have been modified for the last time (to avoid re-co...
Definition: RefinableObj.h:140
void Reset()
Reset a Clock to 0, to force an update.
void AddChild(const RefinableObjClock &)
Add a 'child' clock.
void RemoveChild(const RefinableObjClock &)
remove a child clock. This also tells the child clock to remove the parent.
void Click()
Record an event for this clock (generally, the 'time' an object has been modified,...
Generic class for parameters of refinable objects.
Definition: RefinableObj.h:225
void SetDerivStep(const REAL)
Fixed step to use to compute numerical derivative.
void SetGlobalOptimStep(const REAL)
Maximum step to use during Global Optimization algorithms.
bool IsUsed() const
Is the parameter used (if not, it is simply irrelevant in the model) ?
void AssignClock(RefinableObjClock &clock)
Object Registry.
Definition: RefinableObj.h:645
Generic Refinable Object.
Definition: RefinableObj.h:784
virtual void EndOptimization()
This should be called by any optimization class at the end of an optimization.
void AddPar(const RefinablePar &newRefPar)
Add a refinable parameter.
ObjRegistry< RefinableObj > mSubObjRegistry
Registry of RefinableObject needed for this object (owned by this object or not)
bool IsBeingRefined() const
Is the object being refined ? (Can be refined by one algorithm at a time only.)
virtual void SetName(const string &name)
Name of the object.
virtual const CrystVector_REAL & GetLSQDeriv(const unsigned int, RefinablePar &)
Get the first derivative values for the LSQ function, for a given parameter.
virtual void RegisterClient(RefinableObj &) const
Register a new object using this object.
RefinablePar & GetPar(const long i)
Access all parameters in the order they were inputted.
vector< RefinablePar * >::iterator RemovePar(RefinablePar *refPar)
Remove a refinable parameter.
virtual const string & GetName() const
Name of the object.
long GetNbPar() const
Total number of refinable parameter in the object.
void ResetParList()
Re-init the list of refinable parameters, removing all parameters.
virtual void SetApproximationFlag(const bool allow)
Enable or disable numerical approximations.
virtual void BeginOptimization(const bool allowApproximations=false, const bool enableRestraints=false)
This should be called by any optimization class at the begining of an optimization.
const RefinableObjClock & GetClockMaster() const
This clocks records any change in the object. See refinableObj::mClockMaster.
void AddOption(RefObjOpt *opt)
int mOptimizationDepth
Is the object being refined or optimized ? if mOptimizationDepth=0, no optimization is taking place.
virtual void DeRegisterClient(RefinableObj &) const
Deregister an object (which not any more) using this object.
virtual void UpdateDisplay() const
If there is an interface, this should be automatically be called each time there is a 'new,...
RefinableObjClock mClockMaster
Master clock, which is changed whenever the object has been altered.
string mName
Name for this RefinableObject. Should be unique, at least in the same scope.+.
void AddSubRefObj(RefinableObj &)
void SetGlobalOptimStep(const RefParType *type, const REAL step)
Change the maximum step to use during Global Optimization algorithms.
void RemoveSubRefObj(RefinableObj &)
virtual void GlobalOptRandomMove(const REAL mutationAmplitude, const RefParType *type=gpRefParTypeObjCryst)
Make a random move of the current configuration.
Conjugate Gradient Algorithm object.
Definition: Simplex.h:37
virtual void Optimize(long &nbSteps, const bool silent=false, const REAL finalcost=0, const REAL maxTime=-1)
Launch optimization (a single run) for N steps.
Definition: Simplex.cpp:32
Simple chronometer class, with microsecond precision.
Definition: Chronometer.h:35
output a number as a formatted float:
output one or several vectors as (a) column(s):
Output vectors as column arrays, with the first 3 columns printed as integers.
Abstract base class for all objects in wxCryst.
Definition: wxCryst.h:128
WX Class for PowderPattern objects.