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 
3866 void PowderPattern::SetPowderPatternObsSigma(const CrystVector_REAL& sigma)
3867 {
3868  VFN_DEBUG_MESSAGE("PowderPattern::SetPowderPatternObsSigma()",5)
3869  if((unsigned long)sigma.numElements() != mNbPoint)
3870  {
3871  throw(ObjCrystException("PowderPattern::SetPowderPatternObsSigma(vect): The \
3872 supplied vector of sigma does not have the expected number of points!"));
3873  }
3874 
3875  mPowderPatternObsSigma = sigma;
3877  this->SetWeightToInvSigmaSq();
3878  mClockIntegratedFactorsPrep.Reset();
3879 }
3880 void PowderPattern::SavePowderPattern(const string &filename) const
3881 {
3882  VFN_DEBUG_MESSAGE("PowderPattern::SavePowderPattern",5)
3883  this->CalcPowderPattern();
3884  ofstream out(filename.c_str());
3885  CrystVector_REAL ttheta;
3886  ttheta=mX;
3887  if(this->GetRadiation().GetWavelengthType()!=WAVELENGTH_TOF) ttheta *= RAD2DEG;
3888 
3889  CrystVector_REAL diff;
3890  diff=mPowderPatternObs;
3891  diff-=mPowderPatternCalc;
3892  out << "# 2Theta/TOF Iobs ICalc Iobs-Icalc Weight Comp0" << endl;
3893  out << FormatVertVector<REAL>(ttheta,
3896  diff,mPowderPatternWeight,
3897  mPowderPatternComponentRegistry.GetObj(0).mPowderPatternCalc,16,8);
3898  out.close();
3899  VFN_DEBUG_MESSAGE("DiffractionDataPowder::SavePowderPattern:End",3)
3900 }
3901 
3902 void PowderPattern::PrintObsCalcData(ostream&os)const
3903 {
3904  VFN_DEBUG_MESSAGE("DiffractionDataPowder::PrintObsCalcData()",5);
3905  CrystVector_REAL ttheta;
3906  ttheta=mX;
3907  if(this->GetRadiation().GetWavelengthType()!=WAVELENGTH_TOF) ttheta *= RAD2DEG;
3908  os << "PowderPattern : " << mName <<endl;
3909  os << " 2Theta/TOF Obs Sigma Calc Weight" <<endl;
3910  os << FormatVertVector<REAL>(ttheta,mPowderPatternObs,mPowderPatternObsSigma,
3912  // mPowderPatternComponentRegistry.GetObj(0).mPowderPatternCalc,12,4);
3913 }
3914 
3916 {
3917  if( (0==this->GetPowderPatternObs().numElements())
3918  ||(0==GetNbPowderPatternComponent()))
3919  {
3920  return 0;
3921  }
3922  this->CalcPowderPattern();
3923  TAU_PROFILE("PowderPattern::GetR()","void ()",TAU_DEFAULT);
3924 
3925  REAL tmp1=0.;
3926  REAL tmp2=0.;
3927 
3928  unsigned long maxPoints=mNbPointUsed;
3929  if( (true==mStatisticsExcludeBackground)
3930  &&(mPowderPatternBackgroundCalc.numElements()>0))
3931  {
3932  const REAL *p1, *p2, *p3;
3933  p1=mPowderPatternCalc.data();
3934  p2=mPowderPatternObs.data();
3935  p3=mPowderPatternBackgroundCalc.data();
3936  const long nbExclude=mExcludedRegionMinX.numElements();
3937  if(0==nbExclude)
3938  {
3939  VFN_DEBUG_MESSAGE("PowderPattern::GetR():Exclude Backgd",4);
3940  for(unsigned long i=0;i<maxPoints;i++)
3941  {
3942  tmp1 += ((*p1)-(*p2)) * ((*p1)-(*p2));
3943  tmp2 += ((*p2)-(*p3)) * ((*p2)-(*p3));
3944  p1++;p2++;p3++;
3945  }
3946  }
3947  else
3948  {
3949  VFN_DEBUG_MESSAGE("PowderPattern::GetR():Exclude Backgd,Exclude regions",4);
3950  unsigned long min,max;
3951  unsigned long i=0;
3952  for(int j=0;j<nbExclude;j++)
3953  {
3954  min=(unsigned long)floor(this->X2Pixel(mExcludedRegionMinX(j)));
3955  max=(unsigned long)ceil (this->X2Pixel(mExcludedRegionMaxX(j)));
3956  if(min>maxPoints) break;
3957  if(max>maxPoints)max=maxPoints;
3958  for(;i<min;i++)
3959  {
3960  tmp1 += ((*p1)-(*p2)) * ((*p1)-(*p2));
3961  tmp2 += ((*p2)-(*p3)) * ((*p2)-(*p3));
3962  p1++;p2++;p3++;
3963  }
3964  p1 += max-i;
3965  p2 += max-i;
3966  p3 += max-i;
3967  i += max-i;
3968  }
3969  for(;i<maxPoints;i++)
3970  {
3971  tmp1 += ((*p1)-(*p2)) * ((*p1)-(*p2));
3972  tmp2 += ((*p2)-(*p3)) * ((*p2)-(*p3));
3973  p1++;p2++;p3++;
3974  }
3975 
3976  }
3977  } // Exclude Background ?
3978  else
3979  {
3980  const REAL *p1, *p2;
3981  p1=mPowderPatternCalc.data();
3982  p2=mPowderPatternObs.data();
3983  const long nbExclude=mExcludedRegionMinX.numElements();
3984  if(0==nbExclude)
3985  {
3986  VFN_DEBUG_MESSAGE("PowderPattern::GetR()",4);
3987  for(unsigned long i=0;i<maxPoints;i++)
3988  {
3989  tmp1 += ((*p1)-(*p2))*((*p1)-(*p2));
3990  tmp2 += (*p2) * (*p2);
3991  //cout <<i<<":"<< tmp1 << " "<<tmp2 << " " << *p1 <<" "<<*p2<<endl;
3992  p1++;p2++;
3993  }
3994  }
3995  else
3996  {
3997  VFN_DEBUG_MESSAGE("PowderPattern::GetR(),Exclude regions",4);
3998  unsigned long min,max;
3999  unsigned long i=0;
4000  for(int j=0;j<nbExclude;j++)
4001  {
4002  min=(unsigned long)floor(this->X2Pixel(mExcludedRegionMinX(j)));
4003  max=(unsigned long)ceil (this->X2Pixel(mExcludedRegionMaxX(j)));
4004  if(min>maxPoints) break;
4005  if(max>maxPoints)max=maxPoints;
4006  for(;i<min;i++)
4007  {
4008  tmp1 += ((*p1)-(*p2))*((*p1)-(*p2));
4009  tmp2 += (*p2) * (*p2);
4010  p1++;p2++;
4011  }
4012  p1 += max-i;
4013  p2 += max-i;
4014  i += max-i;
4015  }
4016  for(;i<maxPoints;i++)
4017  {
4018  tmp1 += ((*p1)-(*p2))*((*p1)-(*p2));
4019  tmp2 += (*p2) * (*p2);
4020  p1++;p2++;
4021  }
4022  }
4023  }
4024 
4025  VFN_DEBUG_MESSAGE("PowderPattern::GetR()="<<sqrt(tmp1/tmp2),4);
4026  //cout << FormatVertVector<REAL>(mPowderPatternCalc,mPowderPatternObs);
4027  //this->SavePowderPattern("refinedPattern.out");
4028  //abort();
4029  return sqrt(tmp1/tmp2);
4030 }
4031 
4032 REAL PowderPattern::GetIntegratedR()const
4033 {
4034  if( (0==this->GetPowderPatternObs().numElements())
4035  ||(0==GetNbPowderPatternComponent()))
4036  {
4037  return 0;
4038  }
4039  this->CalcPowderPattern();
4040  this->PrepareIntegratedRfactor();
4041  VFN_DEBUG_ENTRY("PowderPattern::GetIntegratedR()",4);
4042  TAU_PROFILE("PowderPattern::GetIntegratedR()","void ()",TAU_DEFAULT);
4043 
4044  REAL tmp1=0.;
4045  REAL tmp2=0.;
4046  const long numInterval=mIntegratedPatternMin.numElements();
4047  if( (true==mStatisticsExcludeBackground)
4048  &&(mPowderPatternBackgroundCalc.numElements()>0))
4049  {
4050  const REAL *p1, *p2, *p3;
4051  CrystVector_REAL integratedCalc(numInterval);
4052  integratedCalc=0;
4053  CrystVector_REAL backgdCalc(numInterval);
4054  backgdCalc=0;
4055  REAL *pp1=integratedCalc.data();
4056  REAL *pp2=backgdCalc.data();
4057  for(int i=0;i<numInterval;i++)
4058  {
4059  const long max=mIntegratedPatternMax(i);
4060  p1=mPowderPatternCalc.data()+mIntegratedPatternMin(i);
4061  for(int j=mIntegratedPatternMin(i);j<=max;j++) *pp1 += *p1++;
4062  pp1++;
4063  p1=mPowderPatternBackgroundCalc.data()+mIntegratedPatternMin(i);
4064  for(int j=mIntegratedPatternMin(i);j<=max;j++) *pp2 += *p1++;
4065  pp2++;
4066  }
4067 
4068  p1=integratedCalc.data();
4069  p2=mIntegratedObs.data();
4070  p3=backgdCalc.data();
4071  VFN_DEBUG_MESSAGE("PowderPattern::GetIntegratedR():Exclude Backgd",2);
4072  for(long i=0;i<numInterval;i++)
4073  {
4074  tmp1 += ((*p1)-(*p2)) * ((*p1)-(*p2));
4075  tmp2 += ((*p2)-(*p3)) * ((*p2)-(*p3));
4076  p1++;p2++;p3++;
4077  }
4078  } // Exclude Background ?
4079  else
4080  {
4081  const REAL *p1, *p2;
4082  CrystVector_REAL integratedCalc(numInterval);
4083  integratedCalc=0;
4084  REAL *pp1=integratedCalc.data();
4085  for(int i=0;i<numInterval;i++)
4086  {
4087  const long max=mIntegratedPatternMax(i);
4088  p1=mPowderPatternCalc.data()+mIntegratedPatternMin(i);
4089  for(int j=mIntegratedPatternMin(i);j<=max;j++) *pp1 += *p1++;
4090  pp1++;
4091  }
4092  p1=integratedCalc.data();
4093  p2=mIntegratedObs.data();
4094  VFN_DEBUG_MESSAGE("PowderPattern::GetIntegratedR()",2);
4095  for(long i=0;i<numInterval;i++)
4096  {
4097  tmp1 += ((*p1)-(*p2))*((*p1)-(*p2));
4098  tmp2 += (*p2) * (*p2);
4099  //cout <<i<<":"<< tmp1 << " "<<tmp2 << " " << *p1 <<" "<<*p2<<endl;
4100  p1++;p2++;
4101  }
4102  }
4103 
4104  VFN_DEBUG_EXIT("PowderPattern::GetIntegratedR()="<<sqrt(tmp1/tmp2),4);
4105  return sqrt(tmp1/tmp2);
4106 }
4107 
4109 {
4110  if( (0==this->GetPowderPatternObs().numElements())
4111  ||(0==GetNbPowderPatternComponent()))
4112  {
4113  return 0;
4114  }
4115  this->CalcPowderPattern();
4116  TAU_PROFILE("PowderPattern::GetRw()","void ()",TAU_DEFAULT);
4117  VFN_DEBUG_MESSAGE("PowderPattern::GetRw()",3);
4118 
4119 
4120  //cout <<FormatVertVector<REAL>(mPowderPatternObs,
4121  // mPowderPatternCalc,
4122  // mPowderPatternWeight);
4123  REAL tmp1=0.;
4124  REAL tmp2=0.;
4125 
4126  unsigned long maxPoints=mNbPointUsed;
4127 
4128  if( (true==mStatisticsExcludeBackground)
4129  &&(mPowderPatternBackgroundCalc.numElements()>0))
4130  {
4131  VFN_DEBUG_MESSAGE("PowderPattern::GetRw():Exclude Backgd",3);
4132  const REAL *p1, *p2, *p3, *p4;
4133  p1=mPowderPatternCalc.data();
4134  p2=mPowderPatternObs.data();
4135  p3=mPowderPatternBackgroundCalc.data();
4136  p4=mPowderPatternWeight.data();
4137  const long nbExclude=mExcludedRegionMinX.numElements();
4138  if(0==nbExclude)
4139  {
4140  for(unsigned long i=0;i<maxPoints;i++)
4141  {
4142  tmp1 += *p4 * ((*p1)-(*p2)) * ((*p1)-(*p2));
4143  tmp2 += *p4++ * ((*p2)-(*p3)) * ((*p2)-(*p3));
4144  p1++;p2++;p3++;
4145  }
4146  }
4147  else
4148  {
4149  unsigned long min,max;
4150  unsigned long i=0;
4151  for(int j=0;j<nbExclude;j++)
4152  {
4153  min=(unsigned long)floor(this->X2Pixel(mExcludedRegionMinX(j)));
4154  max=(unsigned long)ceil (this->X2Pixel(mExcludedRegionMaxX(j)));
4155  if(min>maxPoints) break;
4156  if(max>maxPoints)max=maxPoints;
4157  for(;i<min;i++)
4158  {
4159  tmp1 += *p4 * ((*p1)-(*p2)) * ((*p1)-(*p2));
4160  tmp2 += *p4++ * ((*p2)-(*p3)) * ((*p2)-(*p3));
4161  p1++;p2++;p3++;
4162  }
4163  p1 += max-i;
4164  p2 += max-i;
4165  p3 += max-i;
4166  p4 += max-i;
4167  i += max-i;
4168  }
4169  for(;i<maxPoints;i++)
4170  {
4171  tmp1 += *p4 * ((*p1)-(*p2)) * ((*p1)-(*p2));
4172  tmp2 += *p4++ * ((*p2)-(*p3)) * ((*p2)-(*p3));
4173  p1++;p2++;p3++;
4174  }
4175 
4176  }
4177  }
4178  else
4179  {
4180  VFN_DEBUG_MESSAGE("PowderPattern::GetRw()",3);
4181  const REAL *p1, *p2, *p4;
4182  p1=mPowderPatternCalc.data();
4183  p2=mPowderPatternObs.data();
4184  p4=mPowderPatternWeight.data();
4185  const long nbExclude=mExcludedRegionMinX.numElements();
4186  if(0==nbExclude)
4187  {
4188  for(unsigned long i=0;i<maxPoints;i++)
4189  {
4190  tmp1 += *p4 * ((*p1)-(*p2))*((*p1)-(*p2));
4191  tmp2 += *p4++ * (*p2) * (*p2);
4192  p1++;p2++;
4193  }
4194  }
4195  else
4196  {
4197  unsigned long min,max;
4198  unsigned long i=0;
4199  for(int j=0;j<nbExclude;j++)
4200  {
4201  min=(unsigned long)floor(this->X2Pixel(mExcludedRegionMinX(j)));
4202  max=(unsigned long)ceil (this->X2Pixel(mExcludedRegionMaxX(j)));
4203  if(min>maxPoints) break;
4204  if(max>maxPoints)max=maxPoints;
4205  for(;i<min;i++)
4206  {
4207  tmp1 += *p4 * ((*p1)-(*p2))*((*p1)-(*p2));
4208  tmp2 += *p4++ * (*p2) * (*p2);
4209  p1++;p2++;
4210  }
4211  p1 += max-i;
4212  p2 += max-i;
4213  p4 += max-i;
4214  i += max-i;
4215  }
4216  for(;i<maxPoints;i++)
4217  {
4218  tmp1 += *p4 * ((*p1)-(*p2))*((*p1)-(*p2));
4219  tmp2 += *p4++ * (*p2) * (*p2);
4220  p1++;p2++;
4221  }
4222  }
4223  }
4224  VFN_DEBUG_MESSAGE("PowderPattern::GetRw()="<<sqrt(tmp1/tmp2),3);
4225  return sqrt(tmp1/tmp2);
4226 }
4227 REAL PowderPattern::GetIntegratedRw()const
4228 {
4229  if( (0==this->GetPowderPatternObs().numElements())
4230  ||(0==GetNbPowderPatternComponent()))
4231  {
4232  return 0;
4233  }
4234  this->CalcPowderPattern();
4235  this->PrepareIntegratedRfactor();
4236  TAU_PROFILE("PowderPattern::GetIntegratedRw()","void ()",TAU_DEFAULT);
4237 
4238  REAL tmp1=0.;
4239  REAL tmp2=0.;
4240  const long numInterval=mIntegratedPatternMin.numElements();
4241  if( (true==mStatisticsExcludeBackground)
4242  &&(mPowderPatternBackgroundCalc.numElements()>0))
4243  {
4244  const REAL *p1, *p2, *p3, *p4;
4245  CrystVector_REAL integratedCalc(numInterval);
4246  integratedCalc=0;
4247  CrystVector_REAL backgdCalc(numInterval);
4248  backgdCalc=0;
4249  REAL *pp1=integratedCalc.data();
4250  REAL *pp2=backgdCalc.data();
4251  for(int i=0;i<numInterval;i++)
4252  {
4253  const long max=mIntegratedPatternMax(i);
4254  p1=mPowderPatternCalc.data()+mIntegratedPatternMin(i);
4255  for(int j=mIntegratedPatternMin(i);j<=max;j++) *pp1 += *p1++;
4256  pp1++;
4257  p1=mPowderPatternBackgroundCalc.data()+mIntegratedPatternMin(i);
4258  for(int j=mIntegratedPatternMin(i);j<=max;j++) *pp2 += *p1++;
4259  pp2++;
4260  }
4261 
4262  p1=integratedCalc.data();
4263  p2=mIntegratedObs.data();
4264  p3=backgdCalc.data();
4265  if(mIntegratedWeight.numElements()==0) p4=mIntegratedWeightObs.data();
4266  else p4=mIntegratedWeight.data();
4267  VFN_DEBUG_MESSAGE("PowderPattern::GetIntegratedRw():Exclude Backgd",4);
4268  for(long i=0;i<numInterval;i++)
4269  {
4270  tmp1 += *p4 * ((*p1)-(*p2)) * ((*p1)-(*p2));
4271  tmp2 += *p4++ * ((*p2)-(*p3)) * ((*p2)-(*p3));
4272  //cout <<i<<": " <<mIntegratedPatternMin(i)<<"->"<<mIntegratedPatternMax(i)
4273  // <<" "<< tmp1 << " "<<tmp2 << " " << *p1 <<" "<<*p2<<" "<<*p3<<" "<<*(p4-1) <<endl;
4274  p1++;p2++;p3++;
4275  }
4276  } // Exclude Background ?
4277  else
4278  {
4279  const REAL *p1, *p2, *p4;
4280  CrystVector_REAL integratedCalc(numInterval);
4281  integratedCalc=0;
4282  REAL *pp1=integratedCalc.data();
4283  for(int i=0;i<numInterval;i++)
4284  {
4285  const long max=mIntegratedPatternMax(i);
4286  p1=mPowderPatternCalc.data()+mIntegratedPatternMin(i);
4287  for(int j=mIntegratedPatternMin(i);j<=max;j++) *pp1 += *p1++;
4288  pp1++;
4289  }
4290  p1=integratedCalc.data();
4291  p2=mIntegratedObs.data();
4292  if(mIntegratedWeight.numElements()==0) p4=mIntegratedWeightObs.data();
4293  else p4=mIntegratedWeight.data();
4294  VFN_DEBUG_MESSAGE("PowderPattern::GetIntegratedRw()",4);
4295  for(long i=0;i<numInterval;i++)
4296  {
4297  tmp1 += *p4 * ((*p1)-(*p2))*((*p1)-(*p2));
4298  tmp2 += *p4++ * (*p2) * (*p2);
4299  //cout <<i<<":"<< tmp1 << " "<<tmp2 << " " << *p1 <<" "<<*p2<<endl;
4300  p1++;p2++;
4301  }
4302  }
4303 
4304  VFN_DEBUG_MESSAGE("PowderPattern::GetIntegratedRw()="<<sqrt(tmp1/tmp2),4);
4305  //cout << FormatVertVector<REAL>(mPowderPatternCalc,mPowderPatternObs);
4306  //this->SavePowderPattern("refinedPattern.out");
4307  //abort();
4308  return sqrt(tmp1/tmp2);
4309 }
4310 
4312 {
4313  if( (0==this->GetPowderPatternObs().numElements())
4314  ||(0==GetNbPowderPatternComponent()))
4315  {
4316  mChi2=0.;
4317  return mChi2;
4318  }
4319  this->CalcNbPointUsed();
4320  if(mClockChi2>mClockMaster) return mChi2;
4321 
4322  this->CalcPowderPattern();
4323  if( (mClockChi2>mClockPowderPatternPar)
4324  &&(mClockChi2>mClockScaleFactor)
4325  &&(mClockChi2>mClockPowderPatternCalc)) return mChi2;
4326  // We want the best scale factor
4327  this->FitScaleFactorForRw();
4328 
4329  TAU_PROFILE("PowderPattern::GetChi2()","void ()",TAU_DEFAULT);
4330 
4331  VFN_DEBUG_ENTRY("PowderPattern::GetChi2()",3);
4332 
4333  const unsigned long maxPoints=mNbPointUsed;
4334 
4335  mChi2=0.;
4336  mChi2LikeNorm=0.;
4337  VFN_DEBUG_MESSAGE("PowderPattern::GetChi2()Integrated profiles",3);
4338  const REAL * RESTRICT p1, * RESTRICT p2, * RESTRICT p3;
4339  p1=mPowderPatternCalc.data();
4340  p2=mPowderPatternObs.data();
4341  p3=mPowderPatternWeight.data();
4342  const long nbExclude=mExcludedRegionMinX.numElements();
4343  if(0==nbExclude)
4344  {
4345  for(unsigned long i=0;i<maxPoints;i++)
4346  {
4347  mChi2 += *p3 * ((*p1)-(*p2))*((*p1)-(*p2));
4348  if(*p3<=0) p3++;
4349  else mChi2LikeNorm -= log(*p3++);
4350  p1++;p2++;
4351  }
4352  }
4353  else
4354  {
4355  unsigned long min,max;
4356  unsigned long i=0;
4357  for(int j=0;j<nbExclude;j++)
4358  {
4359  min=(unsigned long)floor(this->X2Pixel(mExcludedRegionMinX(j)));
4360  max=(unsigned long)ceil (this->X2Pixel(mExcludedRegionMaxX(j)));
4361  if(min>maxPoints) break;
4362  if(max>maxPoints)max=maxPoints;
4363  for(;i<min;i++)
4364  {
4365  mChi2 += *p3 * ((*p1)-(*p2))*((*p1)-(*p2));
4366  if(*p3<=0) p3++;
4367  else mChi2LikeNorm -= log(*p3++);
4368  p1++;p2++;
4369  }
4370  p1 += max-i;
4371  p2 += max-i;
4372  p3 += max-i;
4373  i += max-i;
4374  }
4375  for(;i<maxPoints;i++)
4376  {
4377  mChi2 += *p3 * ((*p1)-(*p2))*((*p1)-(*p2));
4378  if(*p3<=0) p3++;
4379  else mChi2LikeNorm -= log(*p3++);
4380  p1++;p2++;
4381  }
4382  }
4383  mChi2LikeNorm/=2;
4384  VFN_DEBUG_MESSAGE("Chi^2="<<mChi2<<", log(norm)="<<mChi2LikeNorm,3)
4385  mClockChi2.Click();
4386  VFN_DEBUG_EXIT("PowderPattern::GetChi2()="<<mChi2,3);
4387  return mChi2;
4388 }
4389 
4391 {
4392  if( (0==this->GetPowderPatternObs().numElements())
4393  ||(0==GetNbPowderPatternComponent()))
4394  {
4395  mIntegratedChi2=0.;
4396  return mIntegratedChi2;
4397  }
4398  this->CalcNbPointUsed();
4399  if(mClockIntegratedChi2>mClockMaster) return mIntegratedChi2;
4400 
4402  if( (mClockChi2>mClockPowderPatternPar)
4403  &&(mClockChi2>mClockScaleFactor)
4404  &&(mClockChi2>mClockPowderPatternIntegratedCalc)) return mIntegratedChi2;
4405 
4406  // We want the best scale factor
4407  this->FitScaleFactorForIntegratedRw();
4408 
4409  TAU_PROFILE("PowderPattern::GetIntegratedChi2()","void ()",TAU_DEFAULT);
4410 
4411  VFN_DEBUG_ENTRY("PowderPattern::GetIntegratedChi2()",3);
4412 
4413  mIntegratedChi2=0.;
4414  mIntegratedChi2LikeNorm=0.;
4415  VFN_DEBUG_MESSAGE("PowderPattern::GetIntegratedChi2()",3);
4416  const REAL * RESTRICT p1, * RESTRICT p2, * RESTRICT p3;
4417  p1=mPowderPatternIntegratedCalc.data();
4418  p2=mIntegratedObs.data();
4419  if(mIntegratedWeight.numElements()==0) p3=mIntegratedWeightObs.data();
4420  else p3=mIntegratedWeight.data();
4421  double weightProd=1.;
4422  VFN_DEBUG_MESSAGE("PowderPattern::GetIntegratedIntegratedRw()",4);
4423  for(unsigned long i=0;i<mNbIntegrationUsed;)
4424  {
4425  // group weights to avoid computing too many log()
4426  // group only a limited number to avoid underflow...
4427  for(unsigned long j=0;j<32;++j)
4428  {
4429  mIntegratedChi2 += *p3 * ((*p1)-(*p2))*((*p1)-(*p2));
4430  if(*p3>0) weightProd *= *p3;
4431  p1++;p2++;p3++;
4432  if(++i == mNbIntegrationUsed) break;
4433  }
4434  mIntegratedChi2LikeNorm -= log(weightProd);
4435  weightProd=1.;
4436  }
4437  mIntegratedChi2LikeNorm/=2;
4438  VFN_DEBUG_MESSAGE("Chi^2="<<mIntegratedChi2<<", log(norm)="<<mIntegratedChi2LikeNorm,3)
4439  mClockIntegratedChi2.Click();
4440  VFN_DEBUG_EXIT("PowderPattern::GetChi2()="<<mIntegratedChi2,3);
4441  return mIntegratedChi2;
4442 }
4443 
4445 {
4446  if(0 == mOptProfileIntegration.GetChoice()) return this->GetIntegratedChi2();
4447  else return this->GetChi2();
4448 }
4449 
4451 {
4452  if( (0==this->GetPowderPatternObs().numElements())
4453  ||(0==GetNbPowderPatternComponent()))
4454  {
4455  return ;
4456  }
4457  this->CalcPowderPattern();
4458  TAU_PROFILE("PowderPattern::FitScaleFactorForR()","void ()",TAU_DEFAULT);
4459  VFN_DEBUG_ENTRY("PowderPattern::FitScaleFactorForR()",3);
4460  // Which components are scalable ?
4461  mScalableComponentIndex.resize(mPowderPatternComponentRegistry.GetNb());
4462  int nbScale=0;
4463  for(int i=0;i<mPowderPatternComponentRegistry.GetNb();i++)
4464  {
4465  if(mPowderPatternComponentRegistry.GetObj(i).IsScalable())
4466  mScalableComponentIndex(nbScale++)=i;
4467  }
4468  VFN_DEBUG_MESSAGE("-> Number of Scale Factors:"<<nbScale<<":Index:"<<endl<<mScalableComponentIndex,3);
4469  if(0==nbScale)
4470  {
4471  VFN_DEBUG_EXIT("PowderPattern::FitScaleFactorForR(): No scalable component!",3);
4472  return;
4473  }
4474  mScalableComponentIndex.resizeAndPreserve(nbScale);
4475  // prepare matrices
4476  mFitScaleFactorM.resize(nbScale,nbScale);
4477  mFitScaleFactorB.resize(nbScale,1);
4478  mFitScaleFactorX.resize(nbScale,1);
4479  // Build Matrix & Vector for LSQ
4480  const long nbExclude=mExcludedRegionMinX.numElements();
4481  if(0==nbExclude)
4482  {
4483  for(int i=0;i<nbScale;i++)
4484  {
4485  for(int j=i;j<nbScale;j++)
4486  {
4487  // Here use a direct access to the powder spectrum, since
4488  // we know it has just been recomputed
4489  const REAL *p1=mPowderPatternComponentRegistry.GetObj(mScalableComponentIndex(i))
4490  .mPowderPatternCalc.data();
4491  const REAL *p2=mPowderPatternComponentRegistry.GetObj(mScalableComponentIndex(j))
4492  .mPowderPatternCalc.data();
4493  REAL m=0.;
4494  for(unsigned long k=0;k<mNbPointUsed;k++) m += *p1++ * *p2++;
4495  mFitScaleFactorM(i,j)=m;
4496  mFitScaleFactorM(j,i)=m;
4497  }
4498  }
4499  for(int i=0;i<nbScale;i++)
4500  {
4501  const REAL *p1=mPowderPatternObs.data();
4502  const REAL *p2=mPowderPatternComponentRegistry.GetObj(mScalableComponentIndex(i))
4503  .mPowderPatternCalc.data();
4504  REAL b=0.;
4505  if(mPowderPatternBackgroundCalc.numElements()<=1)
4506  for(unsigned long k=0;k<mNbPointUsed;k++) b += *p1++ * *p2++;
4507  else
4508  {
4509  const REAL *p3=mPowderPatternBackgroundCalc.data();
4510  for(unsigned long k=0;k<mNbPointUsed;k++) b += (*p1++ - *p3++) * *p2++;
4511  }
4512  mFitScaleFactorB(i,0) =b;
4513  }
4514  }
4515  else
4516  {
4517  unsigned long min,max;
4518  for(int i=0;i<nbScale;i++)
4519  {
4520  for(int j=i;j<nbScale;j++)
4521  {
4522  // Here use a direct access to the powder spectrum, since
4523  // we know it has just been recomputed
4524  const REAL *p1=mPowderPatternComponentRegistry.GetObj(mScalableComponentIndex(i))
4525  .mPowderPatternCalc.data();
4526  const REAL *p2=mPowderPatternComponentRegistry.GetObj(mScalableComponentIndex(j))
4527  .mPowderPatternCalc.data();
4528  REAL m=0.;
4529  unsigned long l=0;
4530  for(int k=0;k<nbExclude;k++)
4531  {
4532  min=(unsigned long)floor(this->X2Pixel(mExcludedRegionMinX(j)));
4533  max=(unsigned long)ceil (this->X2Pixel(mExcludedRegionMaxX(j)));
4534  if(min>mNbPointUsed) break;
4535  if(max>mNbPointUsed)max=mNbPointUsed;
4537  for(;l<min;l++) m += *p1++ * *p2++;
4538  p1 += max-l;
4539  p2 += max-l;
4540  l = max;
4541  }
4542  for(;l<mNbPointUsed;l++) m += *p1++ * *p2++;
4543  mFitScaleFactorM(i,j)=m;
4544  mFitScaleFactorM(j,i)=m;
4545  }
4546  }
4547  for(int i=0;i<nbScale;i++)
4548  {
4549  const REAL *p1=mPowderPatternObs.data();
4550  const REAL *p2=mPowderPatternComponentRegistry
4551  .GetObj(mScalableComponentIndex(i))
4552  .mPowderPatternCalc.data();
4553  REAL b=0.;
4554  unsigned long l=0;
4555  if(mPowderPatternBackgroundCalc.numElements()<=1)
4556  {
4557  for(int k=0;k<nbExclude;k++)
4558  {
4559  min=(unsigned long)floor(this->X2Pixel(mExcludedRegionMinX(k)));
4560  max=(unsigned long)ceil (this->X2Pixel(mExcludedRegionMaxX(k)));
4561  if(min>mNbPointUsed) break;
4562  if(max>mNbPointUsed)max=mNbPointUsed;
4564  for(;l<min;l++) b += *p1++ * *p2++;
4565  p1 += max-l;
4566  p2 += max-l;
4567  l = max;
4568  }
4569  for(;l<mNbPointUsed;l++) b += *p1++ * *p2++;
4570  }
4571  else
4572  {
4573  const REAL *p3=mPowderPatternBackgroundCalc.data();
4574  for(int k=0;k<nbExclude;k++)
4575  {
4576  min=(unsigned long)floor(this->X2Pixel(mExcludedRegionMinX(k)));
4577  max=(unsigned long)ceil (this->X2Pixel(mExcludedRegionMaxX(k)));
4578  if(min>mNbPointUsed) break;
4579  if(max>mNbPointUsed)max=mNbPointUsed;
4581  for(;l<min;l++) b += (*p1++ - *p3++) * *p2++;
4582  p1 += max-l;
4583  p2 += max-l;
4584  l = max;
4585  }
4586  for(;l<mNbPointUsed;l++) b += (*p1++ - *p3++) * *p2++;
4587  }
4588  mFitScaleFactorB(i,0) =b;
4589  }
4590  }
4591  if(1==nbScale) mFitScaleFactorX=mFitScaleFactorB(0)/mFitScaleFactorM(0);
4592  else
4593  mFitScaleFactorX=product(InvertMatrix(mFitScaleFactorM),mFitScaleFactorB);
4594  VFN_DEBUG_MESSAGE("B, M, X"<<endl<<mFitScaleFactorB<<endl<<mFitScaleFactorM<<endl<<mFitScaleFactorX,2)
4595  for(int i=0;i<nbScale;i++)
4596  {
4597  const REAL * p1=mPowderPatternComponentRegistry.GetObj(mScalableComponentIndex(i))
4598  .mPowderPatternCalc.data();
4599  REAL * p0 = mPowderPatternCalc.data();
4600  const REAL s = mFitScaleFactorX(i)
4601  -mScaleFactor(mScalableComponentIndex(i));
4602  if(ISNAN_OR_INF(s))
4603  {
4604  (*fpObjCrystInformUser)("Warning:FitScaleFactorForR: working around NaN scale factor...");
4605  continue;
4606  }
4607  for(unsigned long j=0;j<mNbPointUsed;j++) *p0++ += s * *p1++;
4608  VFN_DEBUG_MESSAGE("-> Old:"<<mScaleFactor(mScalableComponentIndex(i)) <<" Change:"<<mFitScaleFactorX(i),2);
4609  mScaleFactor(mScalableComponentIndex(i)) = mFitScaleFactorX(i);
4611  mClockPowderPatternCalc.Click();//we *did* correct the spectrum
4612  }
4613  VFN_DEBUG_EXIT("PowderPattern::FitScaleFactorForR():End",3);
4614 }
4615 
4616 void PowderPattern::FitScaleFactorForIntegratedR()const
4617 {
4618  if( (0==this->GetPowderPatternObs().numElements())
4619  ||(0==GetNbPowderPatternComponent()))
4620  {
4621  return ;
4622  }
4623  this->CalcPowderPattern();
4624  this->PrepareIntegratedRfactor();
4625  VFN_DEBUG_ENTRY("PowderPattern::FitScaleFactorForIntegratedR()",3);
4626  TAU_PROFILE("PowderPattern::FitScaleFactorForIntegratedR()","void ()",TAU_DEFAULT);
4627  // Which components are scalable ?
4628  mScalableComponentIndex.resize(mPowderPatternComponentRegistry.GetNb());
4629  int nbScale=0;
4630  for(int i=0;i<mPowderPatternComponentRegistry.GetNb();i++)
4631  {
4632  if(mPowderPatternComponentRegistry.GetObj(i).IsScalable())
4633  mScalableComponentIndex(nbScale++)=i;
4634  }
4635  VFN_DEBUG_MESSAGE("-> Number of Scale Factors:"<<nbScale<<":Index:"<<endl<<mScalableComponentIndex,2);
4636  if(0==nbScale)
4637  {
4638  VFN_DEBUG_EXIT("PowderPattern::FitScaleFactorForIntegratedR(): No scalable component!",3);
4639  return;
4640  }
4641  mScalableComponentIndex.resizeAndPreserve(nbScale);
4642  // prepare matrices
4643  mFitScaleFactorM.resize(nbScale,nbScale);
4644  mFitScaleFactorB.resize(nbScale,1);
4645  mFitScaleFactorX.resize(nbScale,1);
4646  // Build Matrix & Vector for LSQ
4647  VFN_DEBUG_MESSAGE("PowderPattern::FitScaleFactorForIntegratedR():1",2);
4648  const long numInterval=mIntegratedPatternMin.numElements();
4649  CrystVector_REAL *integratedCalc= new CrystVector_REAL[nbScale];
4650  for(int i=0;i<nbScale;i++)
4651  {
4652  integratedCalc[i].resize(numInterval);
4653 
4654  // Here use a direct access to the powder spectrum, since
4655  // we know it has just been recomputed
4656  const REAL *p1=mPowderPatternComponentRegistry.GetObj(mScalableComponentIndex(i))
4657  .mPowderPatternCalc.data();
4658 
4659  REAL *p2=integratedCalc[i].data();
4660  for(int j=0;j<numInterval;j++)
4661  {
4662  const long max=mIntegratedPatternMax(j);
4663  p1=mPowderPatternComponentRegistry.GetObj(mScalableComponentIndex(i))
4664  .mPowderPatternCalc.data()+mIntegratedPatternMin(j);
4665  *p2=0;
4666  for(int k=mIntegratedPatternMin(j);k<=max;k++) *p2 += *p1++;
4667  //cout <<"Calc#"<<i<<":"<< mIntegratedPatternMin(j) << " "
4668  // <<mIntegratedPatternMax(j)<<" "
4669  // << *p2<<endl;
4670  p2++;
4671  }
4672  }
4673  VFN_DEBUG_MESSAGE("PowderPattern::FitScaleFactorForIntegratedR():2",2);
4674  CrystVector_REAL backdIntegrated(numInterval);
4675  if(mPowderPatternBackgroundCalc.numElements()>1)
4676  {
4677  const REAL *p1;
4678  REAL *p2=backdIntegrated.data();
4679  for(int j=0;j<numInterval;j++)
4680  {
4681  const long max=mIntegratedPatternMax(j);
4682  p1=mPowderPatternBackgroundCalc.data()+mIntegratedPatternMin(j);
4683  *p2=0;
4684  for(int k=mIntegratedPatternMin(j);k<=max;k++) *p2 += *p1++;
4685  //cout <<"Backgd:"<< mIntegratedPatternMin(j) << " "
4686  // <<mIntegratedPatternMax(j)<<" "
4687  // << *p2<<endl;
4688  p2++;
4689  }
4690  }
4691 
4692  //if(mPowderPatternBackgroundCalc.numElements()<=1)
4693  // cout<< FormatVertVector<REAL>(integratedCalc[0],mIntegratedObs,mIntegratedWeight,backdIntegrated)<<endl;
4694  //else
4695  // cout<< FormatVertVector<REAL>(integratedCalc[0],mIntegratedObs,mIntegratedWeight)<<endl;
4696  VFN_DEBUG_MESSAGE("PowderPattern::FitScaleFactorForIntegratedR():3",2);
4697  for(int i=0;i<nbScale;i++)
4698  {
4699  for(int j=i;j<nbScale;j++)
4700  {
4701  const REAL *p1=integratedCalc[i].data();
4702  const REAL *p2=integratedCalc[j].data();
4703  REAL m=0.;
4704  for(long k=0;k<numInterval;k++)
4705  {
4706  m += *p1++ * *p2++;
4707  //cout <<"M:"<< mIntegratedPatternMin(k) << " "<<mIntegratedPatternMax(k)<<" "<<m<<endl;
4708  }
4709  mFitScaleFactorM(i,j)=m;
4710  mFitScaleFactorM(j,i)=m;
4711  }
4712  }
4713  VFN_DEBUG_MESSAGE("PowderPattern::FitScaleFactorForIntegratedR():4",2);
4714  for(int i=0;i<nbScale;i++)
4715  {
4716  const REAL *p1=mIntegratedObs.data();
4717  const REAL *p2=integratedCalc[i].data();
4718  REAL b=0.;
4719  if(mPowderPatternBackgroundCalc.numElements()<=1)
4720  for(long k=0;k<numInterval;k++)
4721  {
4722  b += *p1++ * *p2++;
4723  //cout<<"B:"<<mIntegratedPatternMin(k)<<" "<<mIntegratedPatternMax(k)<<" "<<b<<endl;
4724  }
4725  else
4726  {
4727  const REAL *p3=backdIntegrated.data();
4728  for(long k=0;k<numInterval;k++)
4729  {
4730  //cout<<"B(minus backgd):"<<mIntegratedPatternMin(k)<<" "
4731  // <<mIntegratedPatternMax(k)<<" "
4732  // <<*p1<<" "<<*p2<<" "<<*p3<<" "<<b<<endl;
4733  b += (*p1++ - *p3++) * *p2++;
4734  }
4735  }
4736  mFitScaleFactorB(i,0) =b;
4737  }
4738  VFN_DEBUG_MESSAGE("PowderPattern::FitScaleFactorForIntegratedR():5",2);
4739 
4740  if(1==nbScale) mFitScaleFactorX=mFitScaleFactorB(0)/mFitScaleFactorM(0);
4741  else
4742  mFitScaleFactorX=product(InvertMatrix(mFitScaleFactorM),mFitScaleFactorB);
4743  VFN_DEBUG_MESSAGE("B, M, X"<<endl<<mFitScaleFactorB<<endl<<mFitScaleFactorM<<endl<<mFitScaleFactorX,3)
4744  for(int i=0;i<nbScale;i++)
4745  {
4746  const REAL * p1=mPowderPatternComponentRegistry.GetObj(mScalableComponentIndex(i))
4747  .mPowderPatternCalc.data();
4748  REAL * p0 = mPowderPatternCalc.data();
4749  const REAL s = mFitScaleFactorX(i)
4750  -mScaleFactor(mScalableComponentIndex(i));
4751  if(ISNAN_OR_INF(s))
4752  {
4753  (*fpObjCrystInformUser)("Warning:FitScaleFactorForIntegratedR: working around NaN scale factor...");
4754  continue;
4755  }
4756  for(unsigned long j=0;j<mNbPointUsed;j++) *p0++ += s * *p1++;
4757  VFN_DEBUG_MESSAGE("-> Old:"<<mScaleFactor(mScalableComponentIndex(i)) <<" New:"<<mFitScaleFactorX(i),3);
4758  mScaleFactor(mScalableComponentIndex(i)) = mFitScaleFactorX(i);
4760  mClockPowderPatternCalc.Click();//we *did* correct the spectrum
4761  }
4762  delete[] integratedCalc;
4763  VFN_DEBUG_EXIT("PowderPattern::FitScaleFactorForIntegratedR():End",3);
4764 }
4765 
4767 {
4768  if( (0==this->GetPowderPatternObs().numElements())
4769  ||(0==GetNbPowderPatternComponent()))
4770  {
4771  return ;
4772  }
4773  TAU_PROFILE("PowderPattern::FitScaleFactorForRw()","void ()",TAU_DEFAULT);
4774  VFN_DEBUG_ENTRY("PowderPattern::FitScaleFactorForRw()",3);
4775  this->CalcPowderPattern();
4776  //:TODO: take into account excluded regions...
4777  // Which components are scalable ?
4778  mScalableComponentIndex.resize(mPowderPatternComponentRegistry.GetNb());
4779  int nbScale=0;
4780  for(int i=0;i<mPowderPatternComponentRegistry.GetNb();i++)
4781  {
4782  if(mPowderPatternComponentRegistry.GetObj(i).IsScalable())
4783  mScalableComponentIndex(nbScale++)=i;
4784  }
4785  VFN_DEBUG_MESSAGE("-> Number of Scale Factors:"<<nbScale<<":Index:"<<endl<<mScalableComponentIndex,2);
4786  if(0==nbScale)
4787  {
4788  VFN_DEBUG_EXIT("PowderPattern::FitScaleFactorForRw(): No scalable component!",3);
4789  return;
4790  }
4791  mScalableComponentIndex.resizeAndPreserve(nbScale);
4792  // prepare matrices
4793  mFitScaleFactorM.resize(nbScale,nbScale);
4794  mFitScaleFactorB.resize(nbScale,1);
4795  mFitScaleFactorX.resize(nbScale,1);
4796  // Build Matrix & Vector for LSQ
4797  const long nbExclude=mExcludedRegionMinX.numElements();
4798  if(0==nbExclude)
4799  {
4800  for(int i=0;i<nbScale;i++)
4801  {
4802  for(int j=i;j<nbScale;j++)
4803  {
4804  // Here use a direct access to the powder spectrum, since
4805  // we know it has just been recomputed
4806  const REAL *p1=mPowderPatternComponentRegistry.GetObj(mScalableComponentIndex(i))
4807  .mPowderPatternCalc.data();
4808  const REAL *p2=mPowderPatternComponentRegistry.GetObj(mScalableComponentIndex(j))
4809  .mPowderPatternCalc.data();
4810  const REAL *p3=mPowderPatternWeight.data();
4811  REAL m=0.;
4812  for(unsigned long k=0;k<mNbPointUsed;k++) m += *p1++ * *p2++ * *p3++;
4813  mFitScaleFactorM(i,j)=m;
4814  mFitScaleFactorM(j,i)=m;
4815  }
4816  }
4817  for(int i=0;i<nbScale;i++)
4818  {
4819  const REAL *p1=mPowderPatternObs.data();
4820  const REAL *p2=mPowderPatternComponentRegistry.GetObj(mScalableComponentIndex(i))
4821  .mPowderPatternCalc.data();
4822  const REAL *p3=mPowderPatternWeight.data();
4823  REAL b=0.;
4824  if(mPowderPatternBackgroundCalc.numElements()<=1)
4825  for(unsigned long k=0;k<mNbPointUsed;k++) b += *p1++ * *p2++ * *p3++;
4826  else
4827  {
4828  const REAL *p4=mPowderPatternBackgroundCalc.data();
4829  for(unsigned long k=0;k<mNbPointUsed;k++)
4830  b += (*p1++ - *p4++) * *p2++ * *p3++;
4831  }
4832  mFitScaleFactorB(i,0) =b;
4833  }
4834  }
4835  else
4836  {
4837  unsigned long min,max;
4838  for(int i=0;i<nbScale;i++)
4839  {
4840  for(int j=i;j<nbScale;j++)
4841  {
4842  // Here use a direct access to the powder spectrum, since
4843  // we know it has just been recomputed
4844  const REAL *p1=mPowderPatternComponentRegistry.GetObj(mScalableComponentIndex(i))
4845  .mPowderPatternCalc.data();
4846  const REAL *p2=mPowderPatternComponentRegistry.GetObj(mScalableComponentIndex(j))
4847  .mPowderPatternCalc.data();
4848  const REAL *p3=mPowderPatternWeight.data();
4849  REAL m=0.;
4850  unsigned long l=0;
4851  for(int k=0;k<nbExclude;k++)
4852  {
4853  min=(unsigned long)floor(this->X2Pixel(mExcludedRegionMinX(j)));
4854  max=(unsigned long)ceil (this->X2Pixel(mExcludedRegionMaxX(j)));
4855  if(min>mNbPointUsed) break;
4856  if(max>mNbPointUsed)max=mNbPointUsed;
4858  for(;l<min;l++) m += *p1++ * *p2++ * *p3++;
4859  p1 += max-l;
4860  p2 += max-l;
4861  p3 += max-l;
4862  l = max;
4863  }
4864  for(;l<mNbPointUsed;l++) m += *p1++ * *p2++ * *p3++;
4865  mFitScaleFactorM(i,j)=m;
4866  mFitScaleFactorM(j,i)=m;
4867  }
4868  }
4869  for(int i=0;i<nbScale;i++)
4870  {
4871  const REAL *p1=mPowderPatternObs.data();
4872  const REAL *p2=mPowderPatternComponentRegistry
4873  .GetObj(mScalableComponentIndex(i))
4874  .mPowderPatternCalc.data();
4875  const REAL *p3=mPowderPatternWeight.data();
4876  REAL b=0.;
4877  unsigned long l=0;
4878  if(mPowderPatternBackgroundCalc.numElements()<=1)
4879  {
4880  for(int k=0;k<nbExclude;k++)
4881  {
4882  min=(unsigned long)floor(this->X2Pixel(mExcludedRegionMinX(k)));
4883  max=(unsigned long)ceil (this->X2Pixel(mExcludedRegionMaxX(k)));
4884  if(min>mNbPointUsed) break;
4885  if(max>mNbPointUsed)max=mNbPointUsed;
4887  for(;l<min;l++) b += *p1++ * *p2++ * *p3++;
4888  p1 += max-l;
4889  p2 += max-l;
4890  p3 += max-l;
4891  l = max;
4892  }
4893  for(;l<mNbPointUsed;l++) b += *p1++ * *p2++ * *p3++;
4894  }
4895  else
4896  {
4897  const REAL *p4=mPowderPatternBackgroundCalc.data();
4898  for(int k=0;k<nbExclude;k++)
4899  {
4900  min=(unsigned long)floor(this->X2Pixel(mExcludedRegionMinX(k)));
4901  max=(unsigned long)ceil (this->X2Pixel(mExcludedRegionMaxX(k)));
4902  if(min>mNbPointUsed) break;
4903  if(max>mNbPointUsed)max=mNbPointUsed;
4905  for(;l<min;l++) b += (*p1++ - *p4++) * *p2++ * *p3++;
4906  p1 += max-l;
4907  p2 += max-l;
4908  p3 += max-l;
4909  l = max;
4910  }
4911  for(;l<mNbPointUsed;l++) b += (*p1++ - *p4++) * *p2++ * *p3++;
4912  }
4913  mFitScaleFactorB(i,0) =b;
4914  }
4915  }
4916  if(1==nbScale) mFitScaleFactorX=mFitScaleFactorB(0)/mFitScaleFactorM(0);
4917  else
4918  mFitScaleFactorX=product(InvertMatrix(mFitScaleFactorM),mFitScaleFactorB);
4919  VFN_DEBUG_MESSAGE("B, M, X"<<endl<<mFitScaleFactorB<<endl<<mFitScaleFactorM<<endl<<mFitScaleFactorX,2)
4920  for(int i=0;i<nbScale;i++)
4921  {
4922  const REAL * p1=mPowderPatternComponentRegistry.GetObj(mScalableComponentIndex(i))
4923  .mPowderPatternCalc.data();
4924  REAL * p0 = mPowderPatternCalc.data();
4925  const REAL s = mFitScaleFactorX(i)
4926  -mScaleFactor(mScalableComponentIndex(i));
4927  if(ISNAN_OR_INF(s))
4928  {
4929  (*fpObjCrystInformUser)("Warning:FitScaleFactorForRw working around NaN scale factor...");
4930  continue;
4931  }
4932  for(unsigned long j=0;j<mNbPointUsed;j++) *p0++ += s * *p1++;
4933  VFN_DEBUG_MESSAGE("-> Old:"<<mScaleFactor(mScalableComponentIndex(i)) <<" Change:"<<mFitScaleFactorX(i),3);
4934  mScaleFactor(mScalableComponentIndex(i)) = mFitScaleFactorX(i);
4936  mClockPowderPatternCalc.Click();//we *did* correct the spectrum
4937  }
4938  VFN_DEBUG_EXIT("PowderPattern::FitScaleFactorForRw():End",3);
4939 }
4940 
4941 void PowderPattern::FitScaleFactorForIntegratedRw()const
4942 {
4943  if( (0==this->GetPowderPatternObs().numElements())
4944  ||(0==GetNbPowderPatternComponent()))
4945  {
4946  return ;
4947  }
4950  VFN_DEBUG_ENTRY("PowderPattern::FitScaleFactorForIntegratedRw()",3);
4951  TAU_PROFILE("PowderPattern::FitScaleFactorForIntegratedRw()","void ()",TAU_DEFAULT);
4952  // Which components are scalable ? Which scalable calculated components have a non-null variance ?
4953  mScalableComponentIndex.resize(mPowderPatternComponentRegistry.GetNb());
4954  CrystVector_REAL vScalableVarianceIndex(mPowderPatternComponentRegistry.GetNb());
4955  int nbScale=0;
4956  int nbVarCalc=0;
4957  for(int i=0;i<mPowderPatternComponentRegistry.GetNb();i++)
4958  {
4959  if(mPowderPatternComponentRegistry.GetObj(i).IsScalable())
4960  mScalableComponentIndex(nbScale++)=i;
4961  if(mPowderPatternComponentRegistry.GetObj(i).HasPowderPatternCalcVariance())
4962  {
4963  if(0!=mPowderPatternComponentRegistry.GetObj(i)
4964  .GetPowderPatternIntegratedCalcVariance().first->numElements())
4965  vScalableVarianceIndex(nbVarCalc++)=i;
4966  }
4967  }
4968  VFN_DEBUG_MESSAGE("-> Number of Scale Factors:"<<nbScale<<"("<<nbVarCalc
4969  <<"with variance). Index:"<<endl<<mScalableComponentIndex,2);
4970  if(0==nbScale)
4971  {
4972  VFN_DEBUG_EXIT("PowderPattern::FitScaleFactorForIntegratedRw(): No scalable component!",3);
4973  return;
4974  }
4975  bool again;
4976  unsigned int ctagain=0;
4977  RECALC_SCALE_FACTOR_VARIANCE_FitScaleFactorForIntegratedRw:
4978  if(false)//if((nbScale==1)&&(nbVarCalc==1))
4979  {// Special case when using ML error, the scale appears also in the weight so we have to
4980  // use a 2nd-degree equation (ax^2+bx+c=0) to get the scale factor.
4981  double a=0.,b=0.,c=0.;// possible overflows...
4982  REAL newscale;
4983  {
4984  const REAL * RESTRICT p1=mIntegratedObs.data();
4985  const REAL * RESTRICT p2=mPowderPatternComponentRegistry.GetObj(mScalableComponentIndex(0))
4986  .GetPowderPatternIntegratedCalc().first->data();
4987  const REAL * RESTRICT p1v=mIntegratedVarianceObs.data();
4988  const REAL * RESTRICT p2v=mPowderPatternComponentRegistry.GetObj(mScalableComponentIndex(0))
4989  .GetPowderPatternIntegratedCalcVariance().first->data();
4990  if(mPowderPatternBackgroundIntegratedCalc.numElements()<=1)
4991  {
4992  for(unsigned long k=mNbIntegrationUsed;k>0;k--)
4993  {
4994  a += *p2v * *p1 * *p2;
4995  b += *p2 * *p2 * *p1v - *p1 * *p1 * *p2v;
4996  c -= *p1 * *p2 * *p1v;
4997  p1++;p2++;p1v++;p2v++;
4998  }
4999  }
5000  else
5001  {
5002  const REAL * RESTRICT p3=mPowderPatternBackgroundIntegratedCalc.data();
5003  for(unsigned long k=mNbIntegrationUsed;k>0;k--)
5004  {
5005  a += *p2v * (*p1 - *p3) * *p2;
5006  b += *p2 * *p2 * *p1v - (*p1 - *p3) * (*p1 - *p3) * *p2v;
5007  c -= (*p1 - *p3) * *p2 * *p1v;
5008  p1++;p2++;p1v++;p2v++;p3++;
5009  }
5010  }
5011  // Only one >0 solution to the 2nd degree equation
5012  newscale=(REAL)((-b+sqrt(b*b-4*a*c))/(2*a));
5013  }
5014  {// Store new scale, and correct old calculated pattern
5015  const REAL s = newscale-mScaleFactor(mScalableComponentIndex(0));
5016  const REAL s2 = newscale*newscale
5017  -mScaleFactor(mScalableComponentIndex(0))
5018  *mScaleFactor(mScalableComponentIndex(0));
5019  REAL * RESTRICT p0 = mPowderPatternIntegratedCalc.data();
5020  const REAL * RESTRICT p1=mPowderPatternComponentRegistry.GetObj(mScalableComponentIndex(0))
5021  .GetPowderPatternIntegratedCalc().first->data();
5022  REAL * RESTRICT p0v = mPowderPatternVarianceIntegrated.data();
5023  const REAL * RESTRICT p1v=mPowderPatternComponentRegistry.GetObj(mScalableComponentIndex(0))
5024  .GetPowderPatternIntegratedCalcVariance().first->data();
5025  REAL * RESTRICT p0w = mIntegratedWeight.data();
5026  for(unsigned long j=mNbIntegrationUsed;j>0;j--)
5027  {
5028  *p0++ += s * *p1++;
5029  *p0v += s2 * *p1v++;
5030  if(*p0v <=0) {*p0w++ =0;p0v++;}else *p0w++ = 1. / *p0v++;
5031  }
5032  }
5033  mScaleFactor(mScalableComponentIndex(0)) = newscale;
5035  mClockPowderPatternIntegratedCalc.Click();//we *did* correct the spectrum
5036  }
5037  else
5038  {
5039  again=false;
5040  mScalableComponentIndex.resizeAndPreserve(nbScale);
5041  // prepare matrices
5042  mFitScaleFactorM.resize(nbScale,nbScale);
5043  mFitScaleFactorB.resize(nbScale,1);
5044  mFitScaleFactorX.resize(nbScale,1);
5045  // Build Matrix & Vector for LSQ
5046  VFN_DEBUG_MESSAGE("PowderPattern::FitScaleFactorForIntegratedRw():1",2);
5047  vector<const CrystVector_REAL*> integratedCalc;
5048  for(int i=0;i<nbScale;i++)
5049  {
5050  integratedCalc.push_back(mPowderPatternComponentRegistry.
5051  GetObj(mScalableComponentIndex(i))
5052  .GetPowderPatternIntegratedCalc().first);
5053  }
5054  VFN_DEBUG_MESSAGE("PowderPattern::FitScaleFactorForIntegratedRw():3",2);
5055  for(int i=0;i<nbScale;i++)
5056  {
5057  for(int j=i;j<nbScale;j++)
5058  {
5059  const REAL * RESTRICT p1=integratedCalc[i]->data();
5060  const REAL * RESTRICT p2=integratedCalc[j]->data();
5061  const REAL * RESTRICT p3;
5062  if(mIntegratedWeight.numElements()==0)
5063  {
5064  p3=mIntegratedWeightObs.data();
5065  if(ctagain>5) VFN_DEBUG_MESSAGE("ctagain="<<ctagain<<", using mIntegratedWeightObs",5);
5066  }
5067  else
5068  {
5069  p3=mIntegratedWeight.data();
5070  if(ctagain>5) VFN_DEBUG_MESSAGE("ctagain="<<ctagain<<", using mIntegratedWeight",5);
5071  }
5072  REAL m=0.;
5073  if(j==i)
5074  for(unsigned long k=mNbIntegrationUsed;k>0;k--)
5075  {m += *p1 * *p1 * *p3++; p1++;}
5076  else
5077  for(unsigned long k=mNbIntegrationUsed;k>0;k--)
5078  m += *p1++ * *p2++ * *p3++;
5079  mFitScaleFactorM(i,j)=m;
5080  mFitScaleFactorM(j,i)=m;
5081  }
5082  }
5083  VFN_DEBUG_MESSAGE("PowderPattern::FitScaleFactorForIntegratedRw():4",2);
5084  for(int i=0;i<nbScale;i++)
5085  {
5086  const REAL * RESTRICT p1=mIntegratedObs.data();
5087  const REAL * RESTRICT p2=integratedCalc[i]->data();
5088  const REAL * RESTRICT p4;
5089  if(mIntegratedWeight.numElements()==0) p4=mIntegratedWeightObs.data();
5090  else p4=mIntegratedWeight.data();
5091  REAL b=0.;
5092  if(mPowderPatternBackgroundIntegratedCalc.numElements()<=1)
5093  {
5094  for(unsigned long k=mNbIntegrationUsed;k>0;k--)
5095  {
5096  b += *p1++ * *p2++ * *p4++;
5097  //cout<<"B:"<<mIntegratedPatternMin(k)<<" "<<mIntegratedPatternMax(k)<<" "<<b<<endl;
5098  }
5099  }
5100  else
5101  {
5102  const REAL * RESTRICT p3=mPowderPatternBackgroundIntegratedCalc.data();
5103  for(unsigned long k=mNbIntegrationUsed;k>0;k--)
5104  {
5105  //cout<<"B(minus backgd):"<<mIntegratedPatternMin(k)<<" "
5106  // <<mIntegratedPatternMax(k)<<" "
5107  // <<*p1<<" "<<*p2<<" "<<*p3<<" "<<b<<endl;
5108  b += (*p1++ - *p3++) * *p2++ * *p4++;
5109  }
5110  }
5111  mFitScaleFactorB(i,0) =b;
5112  }
5113  VFN_DEBUG_MESSAGE("PowderPattern::FitScaleFactorForIntegratedRw():5",2);
5114 
5115  if(1==nbScale) mFitScaleFactorX=mFitScaleFactorB(0)/mFitScaleFactorM(0);
5116  else if(1<nbScale)
5117  mFitScaleFactorX=product(InvertMatrix(mFitScaleFactorM),mFitScaleFactorB);
5118  VFN_DEBUG_MESSAGE("B, M, X"<<endl<<mFitScaleFactorB<<endl<<mFitScaleFactorM<<endl<<mFitScaleFactorX,3)
5119  //Correct the variance, if necessary
5120  if(nbVarCalc>0)
5121  {
5122  //if(ctagain>0) cout <<"ctgain, sumvar="<<log(mPowderPatternVarianceIntegrated.sum());
5123  for(int i=0;i<nbScale;i++)
5124  {
5125  if(mPowderPatternComponentRegistry.GetObj(mScalableComponentIndex(i)).HasPowderPatternCalcVariance())
5126  {
5127  if(0!=mPowderPatternComponentRegistry.GetObj(mScalableComponentIndex(i))
5128  .GetPowderPatternIntegratedCalcVariance().first->numElements())
5129  {
5130  const REAL * RESTRICT p1=mPowderPatternComponentRegistry.GetObj(mScalableComponentIndex(i))
5131  .GetPowderPatternIntegratedCalcVariance().first->data();
5132  //cout <<",sumvar(i)="<<log(mPowderPatternComponentRegistry.GetObj(mScalableComponentIndex(i))
5133  // .GetPowderPatternIntegratedCalcVariance().first->sum());
5134  REAL * RESTRICT p0 = mPowderPatternVarianceIntegrated.data();
5135  const REAL s2 = mFitScaleFactorX(i)*mFitScaleFactorX(i)
5136  -mScaleFactor(mScalableComponentIndex(i))
5137  *mScaleFactor(mScalableComponentIndex(i));
5138  for(unsigned long j=mNbIntegrationUsed;j>0;j--) *p0++ += s2 * *p1++;
5139  }
5140  }
5141  }
5142  //if(ctagain>0) cout <<" ->"<<log(mPowderPatternVarianceIntegrated.sum())
5143  // <<" , sumobsvar="<<log(mIntegratedVarianceObs.sum())<<endl;
5144  REAL * RESTRICT p0 = mIntegratedWeight.data();
5145  const REAL * RESTRICT p1=mPowderPatternVarianceIntegrated.data();
5146  for(unsigned long j=mNbIntegrationUsed;j>0;j--)
5147  if(*p1 <=0) {*p0++ =0;p1++;}
5148  else *p0++ = 1. / *p1++;
5149 
5150  }
5151  // Correct the calculated integrated pattern
5152  for(int i=0;i<nbScale;i++)
5153  {
5154  const REAL * RESTRICT p1=mPowderPatternComponentRegistry.GetObj(mScalableComponentIndex(i))
5155  .GetPowderPatternIntegratedCalc().first->data();
5156  REAL * RESTRICT p0 = mPowderPatternIntegratedCalc.data();
5157  const REAL s = mFitScaleFactorX(i)
5158  -mScaleFactor(mScalableComponentIndex(i));
5159  if(ISNAN_OR_INF(s))
5160  {
5161  (*fpObjCrystInformUser)("Warning:FitScaleFactorForIntegratedRw: working around NaN scale factor...");
5162  continue;
5163  }
5164  if(nbVarCalc>0)
5165  {
5166  if(abs(s/mFitScaleFactorX(i))>0.001)
5167  {
5168  again=true;
5169  //cout<<"log(scale) :"<<log(mScaleFactor(mScalableComponentIndex(i)))
5170  // <<"->"<<log(mFitScaleFactorX(i))<<" Again="<<ctagain++<<endl;
5171  }
5172  if((!again)&&(ctagain>0))
5173  {
5174  VFN_DEBUG_MESSAGE("log(scale) :"<<log(mScaleFactor(mScalableComponentIndex(i)))
5175  <<"->"<<log(mFitScaleFactorX(i))<<" Again="<<ctagain,5);
5176  }
5177  }
5178  for(unsigned long j=mNbIntegrationUsed;j>0;j--) *p0++ += s * *p1++;
5179  if(ctagain>5)
5180  {
5181  VFN_DEBUG_MESSAGE("->log(scale) Old :"<<log(mScaleFactor(mScalableComponentIndex(i))) <<" New:"<<log(mFitScaleFactorX(i)),10);
5182  }
5183  mScaleFactor(mScalableComponentIndex(i)) = mFitScaleFactorX(i);
5184  }
5185 
5187  mClockPowderPatternIntegratedCalc.Click();//we *did* correct the spectrum
5188  }
5189  if(again && (ctagain<20))
5190  {
5191  ctagain++;
5192  if(ctagain>5)
5193  {
5194  VFN_DEBUG_MESSAGE("PowderPattern::FitScaleFactorForIntegratedRw(), scaling again #"<<ctagain,10)
5195  }
5196  goto RECALC_SCALE_FACTOR_VARIANCE_FitScaleFactorForIntegratedRw;
5197  }
5198  VFN_DEBUG_EXIT("PowderPattern::FitScaleFactorForIntegratedRw():End",3);
5199 }
5200 
5202 {
5203  VFN_DEBUG_MESSAGE("PowderPattern::SetSigmaToSqrtIobs()",5);
5204  for(long i=0;i<mPowderPatternObs.numElements();i++)
5205  mPowderPatternObsSigma(i)=sqrt(fabs(mPowderPatternObs(i)));
5206 }
5207 void PowderPattern::SetWeightToInvSigmaSq(const REAL minRelatSigma)
5208 {
5209  VFN_DEBUG_MESSAGE("PowderPattern::SetWeightToInvSigmaSq()",5);
5210  //:KLUDGE: If less than 1e-4*max, set to 0.... Do not give weight to unobserved points
5211  const REAL min=MaxAbs(mPowderPatternObsSigma)*minRelatSigma;
5212  //mPowderPatternWeight.resize(mPowderPatternObsSigma.numElements());
5213  REAL tmp;
5214  for(long i=0;i<mPowderPatternObsSigma.numElements();i++)
5215  {
5216  tmp = mPowderPatternObsSigma(i);
5217  if(tmp<min) mPowderPatternWeight(i)= 1./min/min;
5218  else mPowderPatternWeight(i) =1./tmp/tmp;
5219  }
5220 }
5222 {
5223  VFN_DEBUG_MESSAGE("PowderPattern::SetWeightToSinTheta()",5);
5224  //mPowderPatternWeight.resize(mPowderPatternObs.numElements());
5226 }
5227 void PowderPattern::SetWeightPolynomial(const REAL a, const REAL b,
5228  const REAL c,
5229  const REAL minRelatIobs)
5230 {
5231  VFN_DEBUG_MESSAGE("PowderPattern::SetWeightPolynomial()",5);
5232  const REAL min=MaxAbs(mPowderPatternObs)*minRelatIobs;
5233  REAL tmp;
5234  for(long i=0;i<mPowderPatternWeight.numElements();i++)
5235  {
5236  tmp=mPowderPatternObs(i);
5237  if(tmp<min)
5238  mPowderPatternWeight(i) = 1./(a+min+b*min*min+c*min*min*min);
5239  else mPowderPatternWeight(i) = 1./(a+tmp+b*tmp*tmp+c*tmp*tmp*tmp);
5240  }
5241 }
5242 
5243 void PowderPattern::BeginOptimization(const bool allowApproximations,
5244  const bool enableRestraints)
5245 {
5246  this->Prepare();
5247  if(0 == mOptProfileIntegration.GetChoice()) this->FitScaleFactorForIntegratedRw();
5248  else this->FitScaleFactorForRw();
5249  this->RefinableObj::BeginOptimization(allowApproximations,enableRestraints);
5250 }
5251 
5252 //void PowderPattern::SetApproximationFlag(const bool allow)
5253 //{// Do we need this ?
5254 // this->Prepare();
5255 // if(0 == mOptProfileIntegration.GetChoice()) this->FitScaleFactorForIntegratedRw();
5256 // else this->FitScaleFactorForRw();
5257 // this->RefinableObj::SetApproximationFlag(allow);
5258 //}
5259 
5260 void PowderPattern::GlobalOptRandomMove(const REAL mutationAmplitude,
5261  const RefParType *type)
5262 {
5263  if(mRandomMoveIsDone) return;
5264  this->RefinableObj::GlobalOptRandomMove(mutationAmplitude,type);
5265 }
5266 
5267 void PowderPattern::AddExcludedRegion(const REAL min,const REAL max)
5268 {
5269  VFN_DEBUG_MESSAGE("PowderPattern::AddExcludedRegion()",5)
5270  const int num=mExcludedRegionMinX.numElements();
5271  if(num>0)
5272  {
5273  mExcludedRegionMinX.resizeAndPreserve(num+1);
5274  mExcludedRegionMaxX.resizeAndPreserve(num+1);
5275  }
5276  else
5277  {
5278  mExcludedRegionMinX.resize(1);
5279  mExcludedRegionMaxX.resize(1);
5280  }
5281  mExcludedRegionMinX(num)=min;
5282  mExcludedRegionMaxX(num)=max;
5283 
5284  //ensure regions are sorted by ascending 2thetamin
5285  CrystVector_long subs;
5286  subs=SortSubs(mExcludedRegionMinX);
5287  CrystVector_REAL tmp1,tmp2;
5288  tmp1=mExcludedRegionMinX;
5289  tmp2=mExcludedRegionMaxX;
5290  for(int i=0;i<mExcludedRegionMinX.numElements();i++)
5291  {
5292  mExcludedRegionMinX(i)=tmp1(subs(i));
5293  mExcludedRegionMaxX(i)=tmp2(subs(i));
5294  }
5296  VFN_DEBUG_MESSAGE("PowderPattern::Add2ThetaExcludedRegion():End",5)
5297 }
5298 
5300 {
5301  REAL tmp=this->GetChi2_Option();
5302  if(mOptProfileIntegration.GetChoice()==0) tmp+=mIntegratedChi2LikeNorm;
5303  else tmp+=mChi2LikeNorm;
5304  return tmp;
5305 }
5306 
5307 unsigned int PowderPattern::GetNbLSQFunction()const{return 2;}
5308 
5309 const CrystVector_REAL&
5310  PowderPattern::GetLSQCalc(const unsigned int idx) const
5311 {
5312  TAU_PROFILE("PowderPattern::GetLSQCalc()","void ()",TAU_DEFAULT);
5313  switch(idx)
5314  {
5315  case 1:
5316  {
5319  break;
5320  }
5321  default:
5322  {
5324  mPowderPatternUsedCalc.resizeAndPreserve(mNbPointUsed);
5325  break;
5326  }
5327  }
5328  return mPowderPatternUsedCalc;
5329 }
5330 
5331 const CrystVector_REAL&
5332  PowderPattern::GetLSQObs(const unsigned int idx) const
5333 {
5334  TAU_PROFILE("PowderPattern::GetLSQObs()","void ()",TAU_DEFAULT);
5335  switch(idx)
5336  {
5337  case 1:
5338  {
5339  this->PrepareIntegratedRfactor();
5340  mPowderPatternUsedObs=mIntegratedObs;
5341  break;
5342  }
5343  default:
5344  {
5346  mPowderPatternUsedObs.resizeAndPreserve(mNbPointUsed);
5347  break;
5348  }
5349  }
5350  return mPowderPatternUsedObs;
5351 }
5352 
5353 const CrystVector_REAL&
5354  PowderPattern::GetLSQWeight(const unsigned int idx) const
5355 {
5356  TAU_PROFILE("PowderPattern::GetLSQWeight()","void ()",TAU_DEFAULT);
5357  switch(idx)
5358  {
5359  case 1:
5360  {
5361  this->PrepareIntegratedRfactor();
5362  // :KLUDGE: When variance is used, mIntegratedWeight will change at each powder pattern calculation,
5363  // so this might be quite wrong...
5364  if(mIntegratedWeight.numElements()==0)
5365  mPowderPatternUsedWeight=mIntegratedWeightObs;
5366  else mPowderPatternUsedWeight=mIntegratedWeight;
5367  break;
5368  }
5369  default:
5370  {
5372  mPowderPatternUsedWeight.resizeAndPreserve(mNbPointUsed);
5373  break;
5374  }
5375  }
5376  return mPowderPatternUsedWeight;
5377 }
5378 
5379 std::map<RefinablePar*, CrystVector_REAL>& PowderPattern::GetLSQ_FullDeriv(const unsigned int idx,std::set<RefinablePar *> &vPar)
5380 {
5381  TAU_PROFILE("PowderPattern::GetLSQ_FullDeriv()","void ()",TAU_DEFAULT);
5382  //return this->RefinableObj::GetLSQ_FullDeriv(idx,vPar);
5383  if(idx==1)
5384  {
5385  this->CalcPowderPatternIntegrated_FullDeriv(vPar);
5386  #if 0
5387  std::map<RefinablePar*, CrystVector_REAL> fullderiv_old;
5388  std::vector<const CrystVector_REAL*> v;
5389  int n=0;
5390  //cout<<"PowderPattern::GetLSQ_FullDeriv(integrated):scales:"<<mScaleFactor<<endl;
5391  cout<<"PowderPattern::GetLSQ_FullDeriv(integrated):parameters:"<<endl;
5392  for(std::set<RefinablePar*>::iterator par=vPar.begin();par!=vPar.end();++par)
5393  {
5394  v.push_back(&(mPowderPatternIntegrated_FullDeriv[*par]));
5395  fullderiv_old[*par]=this->GetLSQDeriv(idx,*(*par));
5396  v.push_back(&(fullderiv_old[*par]));
5397  cout<<(*par)->GetName()<<":"<<mPowderPatternIntegrated_FullDeriv[*par].size()<<","<<fullderiv_old[*par].size()<<endl;
5398  if(++n>8) break;
5399  }
5400  cout<<"PowderPattern::GetLSQ_FullDeriv(integrated):"<<endl<<FormatVertVector<REAL>(v,12,1,20)<<endl;
5401  //exit(0);
5402  #endif
5403  return mPowderPatternIntegrated_FullDeriv;
5404  }
5405  mPowderPattern_FullDeriv=this->GetPowderPattern_FullDeriv(vPar);
5406  return mPowderPattern_FullDeriv;
5407 }
5408 
5410 {
5411  VFN_DEBUG_MESSAGE("PowderPattern::Prepare()",5);
5412  for(int i=0;i<mPowderPatternComponentRegistry.GetNb();i++)
5413  {
5414  mPowderPatternComponentRegistry.GetObj(i).SetMaxSinThetaOvLambda(mMaxSinThetaOvLambda);
5415  mPowderPatternComponentRegistry.GetObj(i).Prepare();
5416  }
5417 }
5419  CrystVector_uint & groupIndex,
5420  unsigned int &first) const
5421 {
5422  // One group for scales, one for theta error parameters
5423  unsigned int scaleIndex=0;
5424  unsigned int thetaIndex=0;
5425  VFN_DEBUG_MESSAGE("PowderPattern::GetGeneGroup()",4)
5426  for(long i=0;i<obj.GetNbPar();i++)
5427  for(long j=0;j<this->GetNbPar();j++)
5428  if(&(obj.GetPar(i)) == &(this->GetPar(j)))
5429  {
5431  {
5432  if(scaleIndex==0) scaleIndex=first++;
5433  groupIndex(i)=scaleIndex;
5434  }
5435  else //gpRefParTypeScattDataCorrPos
5436  {
5437  if(thetaIndex==0) thetaIndex=first++;
5438  groupIndex(i)=thetaIndex;
5439  }
5440  }
5441 }
5442 
5444 {
5446  for(int i=0;i<mPowderPatternComponentRegistry.GetNb();i++)
5447  {
5448  mPowderPatternComponentRegistry.GetObj(i).SetMaxSinThetaOvLambda(mMaxSinThetaOvLambda);
5449  }
5450 }
5451 
5453 
5454 const CrystVector_long& PowderPattern::GetIntegratedProfileMin()const
5455 {
5456  this->PrepareIntegratedRfactor();
5457  return mIntegratedPatternMin;
5458 }
5459 
5460 const CrystVector_long& PowderPattern::GetIntegratedProfileMax()const
5461 {
5462  this->PrepareIntegratedRfactor();
5463  return mIntegratedPatternMax;
5464 }
5465 
5467 {
5468  return mClockIntegratedFactorsPrep;
5469 }
5470 
5471 REAL PowderPattern::STOL2X(const REAL stol)const
5472 {
5473  REAL x;
5474  if(this->GetRadiation().GetWavelengthType()==WAVELENGTH_TOF)
5475  {
5476  if(stol>0) x = 1.0/(2*stol); else return 0;
5477  x = mDIFC*x+mDIFA*x*x;
5478  VFN_DEBUG_MESSAGE("PowderPattern::STOL2X("<<stol<<","<<1.0/(2*stol)<<")="<<x,2)
5479  }
5480  else
5481  {
5482  x=stol*this->GetWavelength();
5483  if(abs(x)<1.0) x=2*asin(x); else x=2*M_PI;
5484  }
5485  return x;
5486 }
5487 
5488 REAL PowderPattern::X2STOL(const REAL x)const
5489 {
5490  REAL stol;
5491  if(this->GetRadiation().GetWavelengthType()==WAVELENGTH_TOF)
5492  {
5493  if(abs(mDIFA)>abs(mDIFC*1e-6))
5494  {
5495  const REAL delta=mDIFC*mDIFC+4.0*mDIFA*x;
5496  stol = (-mDIFC+sqrt(delta))/(2.0*mDIFA);
5497  stol = 1/(2.0*stol);
5498  }
5499  else stol=mDIFC/(2.0*x);
5500  }
5501  else
5502  stol=sin(x/2.0)/this->GetWavelength();
5503  VFN_DEBUG_MESSAGE("PowderPattern::X2STOL("<<x<<")="<<stol,2)
5504  return stol;
5505 }
5506 
5507 REAL PowderPattern::STOL2Pixel(const REAL stol)const
5508 {
5509  return this->X2Pixel(this->STOL2X(stol));
5510 }
5511 
5512 PeakList PowderPattern::FindPeaks(const float dmin,const float maxratio,const unsigned int maxpeak)
5513 {
5514  const long nb=this->GetNbPoint() ;
5515  // Limit peak detection to 1.5A resolution
5516  long start,finish;
5517  if(this->GetRadiation().GetWavelengthType()!=WAVELENGTH_TOF)
5518  {
5519  start=1;// do not start at 0, if this is a simulation that really start at theta=0...
5520  for(finish=0;finish<nb;++finish)
5521  {
5522  const REAL d=1/(this->X2STOL(this->GetPowderPatternX()(finish))*2);
5523  if(d<dmin) break;
5524  }
5525  }
5526  else
5527  {
5528  finish=nb-1;
5529  for(start=nb-1;start>=0;--start)
5530  {
5531  const REAL d=1/(this->X2STOL(this->GetPowderPatternX()(start))*2);
5532  if(d<dmin) break;
5533  }
5534  }
5535  // First evaluate approximate width (in number of pixels) of reflections
5536  unsigned int width_golay=10;
5537  {
5538  CrystVector_REAL obs;
5539  const int nbwidth=9;
5540  CrystVector_long width(nbwidth);
5541  width=0;
5542  obs=this->GetPowderPatternObs();
5543  // Zero excluded regions.
5544  for(long i= 0;i<mExcludedRegionMinX.numElements();i++)
5545  {
5546  long min,max;
5547  min=(long)floor(this->X2Pixel(mExcludedRegionMinX(i)));
5548  max=(long)ceil (this->X2Pixel(mExcludedRegionMaxX(i)));
5549  if(min<0) min = 0;
5550  if(max>=obs.numElements()) max = obs.numElements();
5551  for(long j=min;j<max;j++) obs(j) = 0;
5552  }
5553  const long nb=obs.numElements();
5554  for(int j=0;j<nbwidth;j++)
5555  {
5556  const long imax=obs.imax(nb/10,nb-1);
5557  const REAL iobs_max=obs(imax);
5558  REAL thres=iobs_max;
5559  long i;
5560  for(i=imax-100;i<(imax+100);++i)
5561  {
5562  if(i<0){i=0;continue;}
5563  if(i>=nb) break;
5564  if(obs(i)<thres) thres=obs(i);
5565  }
5566  thres=(iobs_max+thres)/2;
5567  i=imax;
5568  while(obs(i)>=thres)
5569  {
5570  cout<<obs(i)<<" ";
5571  obs(i--)=0;
5572  width(j)+=1;
5573  if(i<0) break;
5574  }
5575  i=imax+1;
5576  while(obs(i)>=thres)
5577  {
5578  cout<<obs(i)<<" ";
5579  obs(i++)=0;
5580  width(j)+=1;
5581  if(i>=nb) break;
5582  }
5583  cout<<endl<<" => "<<width(j)<<endl;
5584  for(i=imax-width(j)*2;i<(imax+width(j)*2);++i)
5585  {
5586  if(i<0) continue;
5587  if(i>=nb) break;
5588  obs(i)=0;
5589  }
5590  }
5591  cout<<"Width of "<<nbwidth<<" strongest peaks:"<<endl<<width;
5592  width_golay=width(SortSubs(width)(nbwidth/2));
5593  cout<<"median width:"<<width_golay<<endl;
5594  if(width_golay<=4)width_golay=4;
5595  if(width_golay>=16)width_golay=16;
5596  }
5597 
5598  // get 2nd derivative
5599  CrystVector_REAL obsd2;
5600  obsd2=SavitzkyGolay(this->GetPowderPatternObs(),width_golay,2);
5601  // Zero excluded regions.
5602  for(long i= 0;i<mExcludedRegionMinX.numElements();i++)
5603  {
5604  long min,max;
5605  min=(long)floor(this->X2Pixel(mExcludedRegionMinX(i)));
5606  max=(long)ceil (this->X2Pixel(mExcludedRegionMaxX(i)));
5607  if(min<0) min = 0;
5608  if(max>=obsd2.numElements()) max = obsd2.numElements();
5609  for(long j=min;j<max;j++) obsd2(j) = 0;
5610  }
5611  const float norm=-obsd2.min();
5612  // Normalize, so that the derivative has the same extent as the observed pattern
5613  obsd2 *= mPowderPatternObs.max()/(-norm);
5614 
5615  REAL min_iobs;
5616  if(maxratio<0)
5617  {//Automatic discrimination - get an idea of noise from the distribution of the scond derivative
5618  CrystVector_REAL tmp;
5619  tmp=obsd2;
5620  tmp.resizeAndPreserve(tmp.numElements()/4);// First quarter, avoid too many peaks
5621  CrystVector<long> sub(tmp.numElements());
5622  QuickSortSubs(tmp,sub,tmp.numElements()-1,0);
5623  min_iobs=5*(tmp(tmp.numElements()/2)-tmp(tmp.numElements()/4));
5624  //cout<<__FILE__<<":"<<__LINE__<<" MIN_IOBS (automatic)="<<min_iobs<<endl;
5625  }else min_iobs=-1;// This will be set after highest peak is found
5626  PeakList pl;
5627  int nbav_min=0;//minimum numerb of points over which the peak is integrated
5628  while(true)
5629  {// Start from max
5630  const long imax=obsd2.imax(start,finish);
5631  REAL iobs=obsd2(imax);
5632  if(iobs<=0) break;
5633  REAL xmax=mX(imax)*iobs;
5634  long nbav=1;
5635  long i=imax;
5636  REAL lastiobs=obsd2(i);
5637  const REAL iobs_max=lastiobs;
5638  //cout<<i<<":"<<lastiobs<<":"<<mX(i)*RAD2DEG<<endl;
5639  while(true)
5640  {
5641  if(i<=1) break;
5642  if(obsd2(--i)>=lastiobs) break;
5643  lastiobs=obsd2(i);
5644  obsd2(i)=0;
5645  iobs+=lastiobs;
5646  xmax+=mX(i)*lastiobs;nbav++;
5647  if(lastiobs<=0) break;
5648  //cout<<i<<":"<<lastiobs<<":"<<mX(i)*RAD2DEG<<endl;
5649  }
5650  float dleft=mX(i+1);
5651  i=imax;
5652  lastiobs=obsd2(i);
5653  while(true)
5654  {
5655  if(i>=(nb-2)) break;
5656  if(obsd2(++i)>=lastiobs) break;
5657  lastiobs=obsd2(i);
5658  obsd2(i)=0;
5659  iobs+=lastiobs;
5660  xmax+=mX(i)*lastiobs;nbav++;
5661  if(lastiobs<=0) break;
5662  //cout<<i<<":"<<lastiobs<<":"<<mX(i)*RAD2DEG<<endl;
5663  }
5664  float dright=mX(i-1);
5665  xmax/=iobs;
5666  obsd2(imax)=0;
5667  REAL dmax=this->X2STOL(xmax)*2;
5668  dright=this->X2STOL(dright)*2;
5669  dleft =this->X2STOL(dleft)*2;
5670  //TODO : evaluate min intensity ratio from noise ?
5671  if(min_iobs<0)
5672  {
5673  cout<<this->GetPowderPatternObsSigma()(imax)<<","<<this->GetPowderPatternObs()(imax)<<endl;
5674  min_iobs=iobs/nbav*maxratio;
5675  //cout<<__FILE__<<":"<<__LINE__<<" MIN_IOBS="<<min_iobs<<endl;
5676  }
5677  if(nbav_min==0)
5678  {
5679  nbav_min=nbav/2;
5680  if(nbav_min<3)nbav_min=3;
5681  }
5682  if(pl.GetPeakList().size()>maxpeak) break;
5683  float sigma=this->GetPowderPatternObsSigma()(imax);
5684  if(this->GetRadiation().GetWavelengthType()!=WAVELENGTH_TOF)
5685  xmax *= RAD2DEG;
5686  cout<<"Peak #"<<pl.GetPeakList().size()<<"imax="<<imax<<", x="<<xmax<<",d="<<1/dmax<<", d2iobs_max="<<iobs_max
5687  <<", d2Iobs="<<iobs<<", nbav="<<nbav<<", min_iobs="<<min_iobs<<",sigma="<<sigma<<endl;
5688  if( ((nbav>=nbav_min) &&(iobs_max>min_iobs)&&((iobs/nbav)>min_iobs))
5689  ||((nbav>=nbav_min) &&(iobs_max>min_iobs)&&((iobs/nbav)>min_iobs*.2)&&((iobs/nbav)>3*sigma))
5690  ||((nbav>=nbav_min/2)&&(iobs_max>min_iobs)&&((iobs/nbav)>min_iobs*2 )&&((iobs/nbav)>6*sigma)))
5691  {
5692  pl.AddPeak(dmax,iobs,abs(dright-dleft)*.25);
5693  if((pl.GetPeakList().size()==1)&&(maxratio<0)&&(min_iobs<0.005*iobs/nbav)) min_iobs=0.005*iobs/nbav;
5694  }
5695  }
5696  pl.Print(cout);
5697  return pl;
5698 }
5699 
5700 const CrystVector_REAL& PowderPattern::GetScaleFactor() const{return mScaleFactor;}
5701 
5702 CrystVector_REAL& PowderPattern::GetScaleFactor(){return mScaleFactor;}
5703 
5704 //Local structures to export atoms, bond and angle restraints
5705 struct exportAtom
5706 {
5707  exportAtom(string n,REAL X, REAL Y, REAL Z,REAL b,REAL o,const ScatteringPower *pow):
5708  name(n),x(X),y(Y),z(Z),biso(b),occ(o),occMult(1),mpScattPow(pow){}
5709  string name;
5710  REAL x,y,z,biso,occ;
5712  int occMult;
5713  const ScatteringPower *mpScattPow;
5714 };
5715 
5716 struct exportBond
5717 {
5718  exportBond(const string &a1,const string &a2, REAL d, REAL s):
5719  at1(a1),at2(a2),dist(d),sigma(s){}
5720  string at1,at2;
5721  REAL dist,sigma;
5722 };
5723 
5724 struct exportAngle
5725 {
5726  exportAngle(const string &a1,const string &a2,const string &a3, REAL a, REAL s):
5727  at1(a1),at2(a2),at3(a3),ang(a),sigma(s){}
5728  string at1,at2,at3;
5729  REAL ang,sigma;
5730 };
5731 
5732 void PowderPattern::ExportFullprof(const std::string &prefix)const
5733 {
5734  // Analyze our data - background ? number of crystalline phases ?
5735  const PowderPatternBackground *pBackground=0;
5736  vector<const PowderPatternDiffraction*> vDiff;
5737  for(unsigned int i=0;i<this->GetNbPowderPatternComponent();i++)
5738  {
5739  if(this->GetPowderPatternComponent(i).GetClassName()=="PowderPatternBackground")
5740  pBackground=dynamic_cast<const PowderPatternBackground*>(&(this->GetPowderPatternComponent(i)));
5741  if(this->GetPowderPatternComponent(i).GetClassName()=="PowderPatternDiffraction")
5742  vDiff.push_back(dynamic_cast<const PowderPatternDiffraction*>(&(this->GetPowderPatternComponent(i))));
5743  }
5744  if((pBackground==0)||vDiff.size()==0) return;
5745 
5746  // Powder data file
5747  ofstream dat((prefix+".dat").c_str());
5748  dat<<"XYDATA"<<endl
5749  <<"INTER 1.0 1.0 0"<<endl<<endl<<endl<<endl<<endl;
5750 
5751  CrystVector_REAL ttheta;
5752  ttheta=mX;
5753  if(this->GetRadiation().GetWavelengthType()!=WAVELENGTH_TOF) ttheta *= RAD2DEG;
5754  dat << FormatVertVector<REAL>(ttheta,mPowderPatternObs,mPowderPatternObsSigma,12,4);
5755  dat.close();
5756 
5757  // PCR file
5758  ofstream pcr((prefix+".pcr").c_str());
5759  // if(!pcr) :TODO:
5760 
5761  // Title
5762  pcr<<"Fox/ObjCryst exported file:"<<this->GetName()<<endl;
5763  // Number of patterns
5764  pcr<<"NPATT 1"<<endl;
5765  // Weight of each pattern
5766  pcr<<"W_PAT 1.0"<<endl;
5767  // Multi-pattern format
5768  pcr<<"! Nph Dum Ias Nre Cry Opt Aut"<<endl;
5769  pcr<<" "<<vDiff.size()
5770  <<" 0 0 0 0 1 1 "<<endl;
5771  // For each phase
5772  {
5773  int job=0;
5774  if(this->GetRadiation().GetRadiationType()==RAD_XRAY) job=0;
5775  if(this->GetRadiation().GetRadiationType()==RAD_NEUTRON) job=1;
5776  //:TODO: TOF:
5777  pcr<<"! Job Npr Nba Nex Nsc Nor Iwg Ilo Res Ste Uni Cor Anm"<<endl
5778  <<" "<<job
5779  <<" 5 "<<pBackground->GetInterpPoints().first->numElements()
5780  <<" 0 0 1 0 0 0 1 0 0 0"<<endl;
5781  }
5782  // Names of data files
5783  string shortName;
5784  {// Strip path for data file
5785  std::string::size_type idx =prefix.rfind("/");
5786  std::string::size_type idx2=prefix.rfind("\\");
5787  std::string::size_type idx3=prefix.rfind(":");
5788  if(((long)idx2!=(long)string::npos)&&((long)idx2>(long)idx))idx=idx2;
5789  if(((long)idx3!=(long)string::npos)&&((long)idx3>(long)idx))idx=idx3;
5790  if(idx==string::npos)
5791  shortName=prefix;
5792  else
5793  shortName=prefix.substr(idx+1);
5794  }
5795  pcr<<"! File names of data files"<<endl;
5796  pcr<<shortName<<".dat"<<endl;
5797  // Output options...
5798  pcr<<"! Mat Pcr Syo Rpa Sym Sho"<<endl
5799  <<" 1 1 0 -1 0 0 "<<endl;
5800  // Output options... For each pattern
5801  pcr<<"! Ipr Ppl Ioc Ls1 Ls2 Ls3 Prf Ins Hkl Fou Ana"<<endl
5802  <<" 0 0 0 0 0 0 1 10 0 0 1 "<<endl;
5803  // Fixed experimental parameters For each 2-theta pattern :TODO: Check !
5804  int wdt=16;
5805  if(this->GetRadiation().GetRadiationType()==RAD_NEUTRON) wdt=10;
5806  pcr<<"!lambda1 lambda2 Ratio Bkpos Wdt Cthm muR AsyLim Rpolarz -> Patt #1"<<endl
5807  <<this->GetRadiation().GetWavelength()(0)<<" "<<this->GetRadiation().GetWavelength()(0)
5808  << " 0 0 "<<wdt
5809  <<" 0 0 0 0.95"<<endl;
5810  // Refinement parameters - changes are damped !!
5811  pcr<<"!NCY Eps R_at R_an R_pr R_gl"<<endl
5812  <<" 5 0.2 1.0 1.0 1.0 1.0"<<endl;
5813  // Refinement parameters & powder data range, for each 2theta pattern
5814  pcr<<"! Thmin Step Thmax PSD Sent0 -> Patt #1"<<endl
5815  <<" 0 0 0 0 0"<<endl;
5816  // Background points
5817  pcr<<"!2Theta Background for Pattern #1"<<endl;
5818  for(long i=0;i<pBackground->GetInterpPoints().first->numElements();i++)
5819  pcr<<(*(pBackground->GetInterpPoints().first))(i)*RAD2DEG<<" "
5820  <<(*(pBackground->GetInterpPoints().second))(i)<<" 0.0"<<endl;
5821  // Number of refined parameters - just use one for the scale factor !
5822  pcr<<"!"<<endl<<"!"<<endl<<"1 !Number of refined parameters"<<endl;
5823  // Powder data experimental set-up II (refinable parameters)
5824  pcr<<"! Zero Code Sycos Code Sysin Code Lambda Code More -> Patt #1"<<endl;
5825  pcr<<" "<<mXZero*RAD2DEG <<" 0.0 "
5826  <<m2ThetaDisplacement*RAD2DEG <<" 0.0 "
5827  <<m2ThetaTransparency*RAD2DEG <<" 0.0 "
5828  <<"0.000 0.0 0"<<endl;
5829  // PHASE DESCRIPTIONS
5830  for(unsigned int i=0;i<vDiff.size();++i)
5831  {
5832  pcr<<"!-------------------------------------------------------------------------------"<<endl
5833  <<"! Data for PHASE number: "<<i<<" ==> Current R_Bragg for Pattern# 1: 0.00 "<<endl
5834  <<"!-------------------------------------------------------------------------------"<<endl;
5835  //Phase name
5836  pcr<<vDiff[i]->GetCrystal().GetName()<<endl;
5837 
5838  // List all atoms, remove overlapping ones
5839  map<int,exportAtom> vExportAtom;
5840  list<exportBond> vExportBond;
5841  list<exportAngle> vExportAngle;
5842  {
5843  CrystMatrix_REAL minDistTable;
5844  minDistTable=vDiff[i]->GetCrystal().GetMinDistanceTable(-1.);
5845  unsigned long k=0;
5846  // list0 is the full scattering component list with all atoms except dummies,
5847  // and a correct mDynPopCorr
5848  const ScatteringComponentList list0=vDiff[i]->GetCrystal().GetScatteringComponentList();
5849  for(int s=0;s<vDiff[i]->GetCrystal().GetScattererRegistry().GetNb();s++)
5850  {
5851  const ScatteringComponentList list=vDiff[i]->GetCrystal().GetScatt(s).GetScatteringComponentList();
5852 
5853  // If we have a Molecule, remember the names used for the atoms to describe restraints
5854  // We can't use the original atom names as they might not be unique in the crystal
5855  const Molecule *pMol=0;
5856  if(vDiff[i]->GetCrystal().GetScatt(s).GetClassName()=="Molecule")
5857  pMol=dynamic_cast<const Molecule*>(&(vDiff[i]->GetCrystal().GetScatt(s)));
5858  map<const MolAtom*,string> vMolAtomName;
5859 
5860  for(int j=0;j<list.GetNbComponent();j++)
5861  {
5862  if(0==list(j).mpScattPow) continue;//Can this happen ?
5863  bool redundant=false;
5864  for(unsigned long l=0;l<k;++l)
5865  if(abs(minDistTable(l,k))<0.5)
5866  {
5867  map<int,exportAtom>::iterator pos=vExportAtom.find(l);
5868  if(pos!=vExportAtom.end()) pos->second.occMult+=1;
5869  redundant=true;//-1 means dist > 10A
5870  }
5871  if(!redundant)
5872  {
5873  //:TODO: avoid non-alphanumeric characters in name
5874  stringstream name;
5875  name<<list(j).mpScattPow->GetName()<<k+1;
5876  vExportAtom.insert(make_pair(k,exportAtom(name.str(),
5877  list(j).mX,list(j).mY,list(j).mZ,
5878  list(j).mpScattPow->GetBiso(),
5879  list(j).mOccupancy*list0(k).mDynPopCorr,
5880  list(j).mpScattPow)));
5881  if(pMol!=0) vMolAtomName.insert(make_pair(pMol->GetAtomList()[j],name.str()));
5882  }
5883  k++;
5884  }
5885  if(pMol!=0)
5886  {
5887  for(vector<MolBond*>::const_iterator pos=pMol->GetBondList().begin();
5888  pos!=pMol->GetBondList().end();++pos)
5889  {
5890  map<const MolAtom*,string>::const_iterator p1,p2;
5891  p1=vMolAtomName.find(&((*pos)->GetAtom1()));
5892  p2=vMolAtomName.find(&((*pos)->GetAtom2()));
5893  if( (p1!=vMolAtomName.end()) && (p2!=vMolAtomName.end()))
5894  vExportBond.push_back(exportBond(p1->second, p2->second,
5895  (*pos)->GetLength0(),(*pos)->GetLengthSigma()));
5896  }
5897 
5898  for(vector<MolBondAngle*>::const_iterator pos=pMol->GetBondAngleList().begin();
5899  pos!=pMol->GetBondAngleList().end();++pos)
5900  {
5901  map<const MolAtom*,string>::const_iterator p1,p2,p3;
5902  p1=vMolAtomName.find(&((*pos)->GetAtom1()));
5903  p2=vMolAtomName.find(&((*pos)->GetAtom2()));
5904  p3=vMolAtomName.find(&((*pos)->GetAtom3()));
5905  if( (p1!=vMolAtomName.end()) && (p2!=vMolAtomName.end()) && (p3!=vMolAtomName.end()))
5906  vExportAngle.push_back(exportAngle(p1->second, p2->second,p3->second,
5907  (*pos)->GetAngle0(),(*pos)->GetAngleSigma()));
5908  }
5909  }
5910  }
5911  // :TODO: recognize special positions, and move the atoms on them.
5912  // :TODO: list atoms excluded, commented out
5913  }
5914 
5915  // Main control codes line for the phase
5916  //:TODO: extract distance (Dis) and bond angle (Ang) restraints whenever possible
5917  //const ScatteringComponentList *pSC=&(vDiff[i]->GetCrystal().GetScatteringComponentList());
5918  pcr<<"!Nat Dis Ang Jbt Isy Str Furth ATZ Nvk More"<<endl
5919  << vExportAtom.size() <<" "<<vExportBond.size()<<" "<<vExportAngle.size()
5920  <<" 0 0 0 0 1.0 0 1"<<endl;
5921  pcr<<"!Jvi Jdi Hel Sol Mom Ter N_Domains"<<endl
5922  <<" 0 3 0 0 0 0 0"<<endl;
5923  // Contribution to the patterns
5924  pcr<<"!Contributions (0/1) of this phase to the patterns"<<endl
5925  <<" 1"<<endl;
5926  //
5927  pcr<<"!Irf Npr Jtyp Nsp_Ref Ph_Shift for Pattern#"<<i<<endl
5928  <<" 0 0 0 0 0"<<endl;
5929  pcr<<"! Pr1 Pr2 Pr3 Brind. Rmua Rmub Rmuc for Pattern#"<<i<<endl
5930  <<" 1.0 1.0 1.0 1.0 0.0 0.0 0.0"<<endl;
5931 
5932  // Limits for distance calculations
5933  pcr<<"! Max_dst(dist) (angles) Bond-Valence Calc."<<endl
5934  <<" 2.7000 1.5000 0"<<endl;
5935 
5936  // Space group symbol
5937  pcr<<vDiff[i]->GetCrystal().GetSpaceGroup().GetCCTbxSpg().match_tabulated_settings().hermann_mauguin()
5938  <<" <- Space Group Symbol"<<endl;
5939  // Atomic parameters
5940  pcr<<"!Atom Typ X Y Z Biso Occ In Fin N_t Spc / Codes"<<endl;
5941  for(map<int,exportAtom>::const_iterator pos=vExportAtom.begin();pos!=vExportAtom.end();++pos)
5942  {
5943  pcr<<pos->second.name
5944  <<" "<<pos->second.mpScattPow->GetSymbol()<<" "
5945  <<pos->second.x<<" "<<pos->second.y<<" "<<pos->second.z<<" "
5946  <<pos->second.biso<<" "
5947  <<pos->second.occ*pos->second.occMult<<" 0 0 0 0"<<endl
5948  <<" 0 0 0 0 0"<<endl;
5949  }
5950  // POWDER DATA-I: PROFILE PARAMETERS FOR EACH PATTERN
5951  REAL eta0=vDiff[0]->GetProfile().GetPar("Eta0").GetHumanValue();
5952  if(eta0<.01) eta0=.01;
5953  else if(eta0>.99) eta0=.99;
5954  pcr<<"!Scale Shape1 Bov Str1 Str2 Str3 Strain-Model"<<endl
5955  <<" 1.0 "<<eta0
5956  <<" 0.0 0.0 0.0 0.0 0"<<endl
5957  <<" 1.0 0.0 0.0 0.0 0.0 0.0 0"<<endl;
5958 
5959  // :TODO: make sure the profile used corrseponds to pseudo-Voigt first !
5960  pcr<<"! U V W X Y GauSiz LorSiz Size-Model"<<endl;
5961  // :NOTE: we need to separate the 3 next lines, or the same number is generated
5962  // three times when compiled with Visual c++ express 2008 (compiler bug ?)
5963  pcr<<vDiff[i]->GetProfile().GetPar("U").GetHumanValue()<<" ";
5964  pcr<<vDiff[i]->GetProfile().GetPar("V").GetHumanValue()<<" ";
5965  pcr<<vDiff[i]->GetProfile().GetPar("W").GetHumanValue()<<" ";
5966  pcr<< " 0.0 0.0 0.0 0.0 "<<endl
5967  << " 0.0 0.0 0.0 0.0 0.0 0.0 0.0 "<<endl;
5968  // Cell parameters
5969  pcr<<"! a b c alpha beta gamma #Cell Info"<<endl
5970  <<vDiff[i]->GetCrystal().GetLatticePar(0)<<" "
5971  <<vDiff[i]->GetCrystal().GetLatticePar(1)<<" "
5972  <<vDiff[i]->GetCrystal().GetLatticePar(2)<<" "
5973  <<vDiff[i]->GetCrystal().GetLatticePar(3)*RAD2DEG<<" "
5974  <<vDiff[i]->GetCrystal().GetLatticePar(4)*RAD2DEG<<" "
5975  <<vDiff[i]->GetCrystal().GetLatticePar(5)*RAD2DEG<<endl
5976  <<" 0.0 0.0 0.0 0.0 0.0 0.0"<<endl;
5977  pcr<<"! Pref1 Pref2 alpha0 beta0 alpha1 beta1 ?"<<endl
5978  <<" 0.0 0.0 0.0 0.0 0.0 0.0"<<endl
5979  <<" 0.0 0.0 0.0 0.0 0.0 0.0"<<endl;
5980  // ??
5981  //pcr<<"! ??"<<endl
5982  // <<"0.00 0.00 0.00000 0.00"<<endl;
5983  if(vExportBond.size()>0)
5984  {
5985  pcr<<"!Soft distance constraints"<<endl;
5986  for(list<exportBond>::const_iterator pos=vExportBond.begin();pos!=vExportBond.end();++pos)
5987  {
5988  pcr<<pos->at1<<" "<<pos->at2<<" 1 0 0 0 "<<pos->dist<<" "<<pos->sigma<<endl;
5989  }
5990  }
5991  if(vExportBond.size()>0)
5992  {
5993  pcr<<"!Soft angle constraints"<<endl;
5994  for(list<exportAngle>::const_iterator pos=vExportAngle.begin();pos!=vExportAngle.end();++pos)
5995  {
5996  pcr<<pos->at1<<" "<<pos->at2<<" "<<pos->at3<<" 1 1 0 0 0 0 0 0 "
5997  <<pos->ang*RAD2DEG<<" "<<pos->sigma*RAD2DEG<<endl;
5998  }
5999  }
6000  }
6001  pcr.close();
6002 }
6003 
6004 void PowderPattern::SetMuR(const REAL muR) {mMuR=muR; mClockCorrAbs.Click();}
6005 
6006 REAL PowderPattern::GetMuR() const {return mMuR;}
6007 
6009 {
6010  this->CalcNbPointUsed();
6012 
6013  TAU_PROFILE("PowderPattern::CalcPowderPattern()","void ()",TAU_DEFAULT);
6014  VFN_DEBUG_ENTRY("PowderPattern::CalcPowderPattern()",3);
6015  if(mPowderPatternComponentRegistry.GetNb()==0)
6016  {
6017  mPowderPatternCalc.resize(mNbPoint);
6019 
6023 
6024  const REAL *p0 = mPowderPatternVariance.data();
6025  REAL *p1=mPowderPatternWeight.data();
6026  for(unsigned long j=0;j<mNbPoint;j++)
6027  {
6028  if(*p0 <=0) {*p1 =0.;}
6029  else *p1 = 1. / *p0;
6030  p0++;p1++;
6031  }
6032  VFN_DEBUG_EXIT("PowderPattern::CalcPowderPattern():no components!",3);
6033  return;
6034  }
6035  TAU_PROFILE_TIMER(timer1,"PowderPattern::CalcPowderPattern1()Calc components","", TAU_FIELD);
6036  TAU_PROFILE_TIMER(timer2,"PowderPattern::CalcPowderPattern2(Add spectrums-scaled)"\
6037  ,"", TAU_FIELD);
6038  TAU_PROFILE_TIMER(timer3,"PowderPattern::CalcPowderPattern2(Add spectrums-backgd1)"\
6039  ,"", TAU_FIELD);
6040  TAU_PROFILE_TIMER(timer4,"PowderPattern::CalcPowderPattern2(Add spectrums-backgd2)"\
6041  ,"", TAU_FIELD);
6042  TAU_PROFILE_TIMER(timer5,"PowderPattern::CalcPowderPattern3(Variance)","", TAU_FIELD);
6043  TAU_PROFILE_START(timer1);
6044  for(int i=0;i<mPowderPatternComponentRegistry.GetNb();i++)
6045  mPowderPatternComponentRegistry.GetObj(i).CalcPowderPattern();
6046  TAU_PROFILE_STOP(timer1);
6047  VFN_DEBUG_MESSAGE("PowderPattern::CalcPowderPattern():Calculated components..",3);
6048  bool b=false;
6050  {
6051  b=true;
6052  }
6053  else
6054  for(int i=0;i<mPowderPatternComponentRegistry.GetNb();i++)
6056  mPowderPatternComponentRegistry.GetObj(i).GetClockPowderPatternCalc())
6057  {
6058  b=true;
6059  break;
6060  }
6061 
6062  if(false==b)
6063  {
6064  VFN_DEBUG_EXIT("PowderPattern::CalcPowderPattern():no need to recalc",3);
6065  return;
6066  }
6067  mPowderPatternCalc.resize(mNbPoint);
6068  int nbBackgd=0;//count number of background phases
6069  for(int i=0;i<mPowderPatternComponentRegistry.GetNb();i++)
6070  {//THIS SHOULD GO FASTER (PRE-FETCHING ARRAY DATA?)
6071  VFN_DEBUG_MESSAGE("PowderPattern::CalcPowderPattern():Adding "<< mPowderPatternComponentRegistry.GetObj(i).GetName(),3);
6072  if(true==mPowderPatternComponentRegistry.GetObj(i).IsScalable())
6073  {
6074  TAU_PROFILE_START(timer2);
6075  if(0==i)
6076  {
6077  const REAL * p1=mPowderPatternComponentRegistry.GetObj(i)
6078  .mPowderPatternCalc.data();
6079  REAL * p0 = mPowderPatternCalc.data();
6080  const REAL s = mScaleFactor(i);
6081  for(unsigned long j=0;j<mNbPointUsed;j++) *p0++ = s * *p1++;
6082  if(!(this->IsBeingRefined())) for(unsigned long j=mNbPointUsed;j<mNbPoint;j++) *p0++ = 0;
6083  }
6084  else
6085  {
6086  const REAL * p1=mPowderPatternComponentRegistry.GetObj(i)
6087  .mPowderPatternCalc.data();
6088  REAL * p0 = mPowderPatternCalc.data();
6089  const REAL s = mScaleFactor(i);
6090  for(unsigned long j=0;j<mNbPointUsed;j++) *p0++ += s * *p1++;
6091  }
6092  TAU_PROFILE_STOP (timer2);
6093  }
6094  else
6095  {// This is a background phase
6096  TAU_PROFILE_START(timer3);
6097  if(0==i)
6098  {
6099  const REAL * p1=mPowderPatternComponentRegistry.GetObj(i)
6100  .mPowderPatternCalc.data();
6101  REAL * p0 = mPowderPatternCalc.data();
6102  for(unsigned long j=0;j<mNbPointUsed;j++) *p0++ = *p1++;
6103  if(!(this->IsBeingRefined())) for(unsigned long j=mNbPointUsed;j<mNbPoint;j++) *p0++ = 0;
6104  }
6105  else
6106  {
6107  const REAL * p1=mPowderPatternComponentRegistry.GetObj(i)
6108  .mPowderPatternCalc.data();
6109  REAL * p0 = mPowderPatternCalc.data();
6110  for(unsigned long j=0;j<mNbPointUsed;j++) *p0++ += *p1++;
6111 
6112  }
6113  TAU_PROFILE_STOP(timer3);
6114  TAU_PROFILE_START(timer4);
6115  // The following is useless if there is only one background phase...
6116  if(0==nbBackgd)
6117  {
6119  REAL *p0 = mPowderPatternBackgroundCalc.data();
6120  const REAL *p1=mPowderPatternComponentRegistry.GetObj(i)
6121  .mPowderPatternCalc.data();
6122  for(unsigned long j=0;j<mNbPointUsed;j++) *p0++ = *p1++;
6123  if(!(this->IsBeingRefined())) for(unsigned long j=mNbPointUsed;j<mNbPoint;j++) *p0++ = 0;
6124  }
6125  else
6126  {
6127  REAL *p0 = mPowderPatternBackgroundCalc.data();
6128  const REAL *p1=mPowderPatternComponentRegistry.GetObj(i)
6129  .mPowderPatternCalc.data();
6130  for(unsigned long j=0;j<mNbPointUsed;j++) *p0++ += *p1++;
6131  }
6132  nbBackgd++;
6133  TAU_PROFILE_STOP(timer4);
6134  }
6135  }
6136  if(0==nbBackgd) mPowderPatternBackgroundCalc.resize(0);//:KLUDGE:
6137 
6138  TAU_PROFILE_START(timer5);
6139  // Calc variance
6140  {
6141  VFN_DEBUG_MESSAGE("PowderPattern::CalcPowderPattern():variance",2);
6144  for(int i=0;i<mPowderPatternComponentRegistry.GetNb();i++)
6145  {
6146  if(mPowderPatternComponentRegistry.GetObj(i).HasPowderPatternCalcVariance())
6147  {
6148  if(0==mPowderPatternComponentRegistry.GetObj(i).GetPowderPatternCalcVariance()
6149  .numElements()) break;
6150 
6151  REAL *p0 = mPowderPatternVariance.data();
6152  const REAL *p1=mPowderPatternComponentRegistry.GetObj(i)
6153  .GetPowderPatternCalcVariance().data();
6154 
6155  if(true==mPowderPatternComponentRegistry.GetObj(i).IsScalable())
6156  {
6157  const REAL s2 = mScaleFactor(i) * mScaleFactor(i);
6158  for(unsigned long j=0;j<mNbPointUsed;j++) *p0++ += s2 * *p1++;
6159  }
6160  else for(unsigned long j=0;j<mNbPointUsed;j++) *p0++ += *p1++;
6161  }
6162  }
6163  REAL *p0 = mPowderPatternWeight.data();
6164  const REAL *p1=mPowderPatternVariance.data();
6165  for(unsigned long j=0;j<mNbPointUsed;j++)
6166  if(*p1 <=0) {*p0++ =0;p1++;}
6167  else *p0++ = 1. / *p1++;
6168  }
6170  TAU_PROFILE_STOP(timer5);
6171  VFN_DEBUG_EXIT("PowderPattern::CalcPowderPattern():End",3);
6172 }
6173 
6174 void PowderPattern::CalcPowderPattern_FullDeriv(std::set<RefinablePar*> &vPar)
6175 {
6176  TAU_PROFILE("PowderPattern::CalcPowderPattern_FullDeriv()","void ()",TAU_DEFAULT);
6177  this->CalcPowderPattern();
6178  mPowderPattern_FullDeriv.clear();
6179  if(mPowderPatternComponentRegistry.GetNb()==0) return;
6180  std::vector<std::map<RefinablePar*,CrystVector_REAL>*> comps;
6181  for(int i=0;i<mPowderPatternComponentRegistry.GetNb();i++)
6182  comps.push_back(&(mPowderPatternComponentRegistry.GetObj(i).GetPowderPattern_FullDeriv(vPar)));
6183 
6184  for(std::set<RefinablePar *>::iterator par=vPar.begin();par!=vPar.end();++par)
6185  {
6186  if(*par==0) continue;
6187  for(int i=0;i<mPowderPatternComponentRegistry.GetNb();i++)
6188  {
6189  if((*par)->GetPointer()==mScaleFactor.data()+i)
6190  {
6191  mPowderPattern_FullDeriv[*par]=mPowderPatternComponentRegistry.GetObj(i).GetPowderPatternCalc();
6192  continue;
6193  }
6194  else
6195  {
6196  if((*(comps[i]))[*par].size()==0) continue;
6197  }
6198  if(true==mPowderPatternComponentRegistry.GetObj(i).IsScalable())
6199  {
6200  if(mPowderPattern_FullDeriv[*par].size()==0)
6201  {
6202  mPowderPattern_FullDeriv[*par].resize(mNbPoint);// :TODO: only use mNbPointUsed
6203  const REAL * p1=(*comps[i])[*par].data();
6204  REAL * p0 = mPowderPattern_FullDeriv[*par].data();
6205  const REAL s = mScaleFactor(i);
6206  for(unsigned long j=0;j<mNbPointUsed;j++) *p0++ = s * *p1++;
6207  for(unsigned long j=mNbPointUsed;j<mNbPoint;j++) *p0++ = 0;// :TODO: only use mNbPointUsed
6208  }
6209  else
6210  {
6211  const REAL * p1=(*comps[i])[*par].data();
6212  REAL * p0 = mPowderPattern_FullDeriv[*par].data();
6213  const REAL s = mScaleFactor(i);
6214  for(unsigned long j=0;j<mNbPointUsed;j++) *p0++ += s * *p1++;
6215  }
6216  }
6217  else
6218  {// This is a background phase
6219  if(mPowderPattern_FullDeriv[*par].size()==0)
6220  {
6221  mPowderPattern_FullDeriv[*par].resize(mNbPoint);// :TODO: only use mNbPointUsed
6222  const REAL * p1=(*comps[i])[*par].data();
6223  REAL * p0 = mPowderPattern_FullDeriv[*par].data();
6224  for(unsigned long j=0;j<mNbPointUsed;j++) *p0++ = *p1++;
6225  for(unsigned long j=mNbPointUsed;j<mNbPoint;j++) *p0++ = 0;
6226  }
6227  else
6228  {
6229  const REAL * p1=(*comps[i])[*par].data();
6230  REAL * p0 = mPowderPattern_FullDeriv[*par].data();
6231  for(unsigned long j=0;j<mNbPointUsed;j++) *p0++ += *p1++;
6232 
6233  }
6234  }
6235  }
6236  }
6237  #if 0
6238  std::map<RefinablePar*, CrystVector_REAL> oldDeriv;
6239  std::vector<const CrystVector_REAL*> v;
6240  int n=0;
6241  for(std::map<RefinablePar*, CrystVector_REAL>::reverse_iterator pos=mPowderPattern_FullDeriv.rbegin();pos!=mPowderPattern_FullDeriv.rend();++pos)
6242  {
6243  if(pos->first==0) continue;
6244  if(pos->second.size()==0) continue;
6245 
6246  const REAL step=pos->first->GetDerivStep();
6247  pos->first->Mutate(step);
6248  this->CalcPowderPattern();
6249  oldDeriv[pos->first]=mPowderPatternCalc;
6250  pos->first->Mutate(-2*step);
6251  this->CalcPowderPattern();
6252  oldDeriv[pos->first]-=mPowderPatternCalc;
6253  oldDeriv[pos->first]/=2*step;
6254  pos->first->Mutate(step);
6255 
6256  v.push_back(&(pos->second));
6257  v.push_back(&(oldDeriv[pos->first]));
6258  cout<<pos->first->GetName()<<":"<<pos->second.size()<<","<<oldDeriv[pos->first].size()<<endl;
6259  if(++n>8) break;
6260  }
6261  cout<<FormatVertVector<REAL>(v,16)<<endl;
6262  exit(0);
6263  #endif
6264 }
6265 
6267 {
6268  this->CalcNbPointUsed();
6270 
6271  this->PrepareIntegratedRfactor();
6272  TAU_PROFILE("PowderPattern::CalcPowderPatternIntegrated()","void ()",TAU_DEFAULT);
6273  VFN_DEBUG_ENTRY("PowderPattern::CalcPowderPatternIntegrated()",4);
6274  if(mPowderPatternComponentRegistry.GetNb()==0)
6275  {
6276  mPowderPatternIntegratedCalc.resize(0);
6278  VFN_DEBUG_EXIT("PowderPattern::CalcPowderPatternIntegrated():no components!",4);
6279  return;
6280  }
6281  TAU_PROFILE_TIMER(timer1,"PowderPattern::CalcPowderPatternIntegrated()1:Calc components",\
6282  "", TAU_FIELD);
6283  TAU_PROFILE_TIMER(timer2,"PowderPattern::CalcPowderPatternIntegrated()2:Add comps-scaled"\
6284  ,"", TAU_FIELD);
6285  TAU_PROFILE_TIMER(timer3,"PowderPattern::CalcPowderPatternIntegrated()2:Add backgd1"\
6286  ,"", TAU_FIELD);
6287  TAU_PROFILE_TIMER(timer4,"PowderPattern::CalcPowderPatternIntegrated()2:Add backgd2"\
6288  ,"", TAU_FIELD);
6289  TAU_PROFILE_TIMER(timer5,"PowderPattern::CalcPowderPatternIntegrated()3:Variance"
6290  ,"", TAU_FIELD);
6291  TAU_PROFILE_START(timer1);
6292  vector< pair<const CrystVector_REAL*,const RefinableObjClock*> > comps;
6293  for(int i=0;i<mPowderPatternComponentRegistry.GetNb();i++)
6294  {
6295  comps.push_back(mPowderPatternComponentRegistry.GetObj(i).
6296  GetPowderPatternIntegratedCalc());
6297  }
6298  TAU_PROFILE_STOP(timer1);
6299  bool b=false;
6301  {
6302  b=true;
6303  }
6304  else
6305  for(vector< pair<const CrystVector_REAL*,const RefinableObjClock*> >::iterator
6306  pos=comps.begin();pos!=comps.end();++pos)
6307  if(mClockPowderPatternCalc < *(pos->second) )
6308  {
6309  b=true;
6310  break;
6311  }
6312 
6313  if(false==b)
6314  {
6315  VFN_DEBUG_EXIT("PowderPattern::CalcPowderPatternIntegrated():no need to recalc",4);
6316  return;
6317  }
6318  VFN_DEBUG_MESSAGE("PowderPattern::CalcPowderPatternIntegrated():Recalc",3);
6319  mPowderPatternIntegratedCalc.resize(mNbIntegrationUsed);
6320  int nbBackgd=0;//count number of background phases
6321  for(int i=0;i<mPowderPatternComponentRegistry.GetNb();i++)
6322  {
6323  VFN_DEBUG_MESSAGE("PowderPattern::CalcPowderPatternIntegrated():Adding "\
6324  << mPowderPatternComponentRegistry.GetObj(i).GetName(),3);
6325  if(true==mPowderPatternComponentRegistry.GetObj(i).IsScalable())
6326  {
6327  TAU_PROFILE_START(timer2);
6328  if(0==i)
6329  {
6330  const REAL * RESTRICT p1= comps[i].first->data();
6331  REAL * RESTRICT p0 = mPowderPatternIntegratedCalc.data();
6332  const REAL s = mScaleFactor(i);
6333  for(unsigned long j=mNbIntegrationUsed;j>0;j--) *p0++ = s * *p1++;
6334  }
6335  else
6336  {
6337  const REAL * RESTRICT p1= comps[i].first->data();
6338  REAL * RESTRICT p0 = mPowderPatternIntegratedCalc.data();
6339  const REAL s = mScaleFactor(i);
6340  for(unsigned long j=mNbIntegrationUsed;j>0;j--) *p0++ += s * *p1++;
6341  }
6342  TAU_PROFILE_STOP (timer2);
6343  }
6344  else
6345  {// This is a background phase
6346  TAU_PROFILE_START(timer3);
6347  if(0==i)
6348  {
6349  const REAL * RESTRICT p1= comps[i].first->data();
6350  REAL * RESTRICT p0 = mPowderPatternIntegratedCalc.data();
6351  for(unsigned long j=mNbIntegrationUsed;j>0;j--) *p0++ = *p1++;
6352  }
6353  else
6354  {
6355  const REAL * RESTRICT p1= comps[i].first->data();
6356  REAL * RESTRICT p0 = mPowderPatternIntegratedCalc.data();
6357  for(unsigned long j=mNbIntegrationUsed;j>0;j--) *p0++ += *p1++;
6358 
6359  }
6360  TAU_PROFILE_STOP(timer3);
6361  TAU_PROFILE_START(timer4);
6362  // The following is useless if there is only one background phase...
6363  if(0==nbBackgd)
6364  {
6365  mPowderPatternBackgroundIntegratedCalc.resize(mNbIntegrationUsed);
6366  const REAL * RESTRICT p1= comps[i].first->data();
6367  REAL * RESTRICT p0 = mPowderPatternBackgroundIntegratedCalc.data();
6368  for(unsigned long j=mNbIntegrationUsed;j>0;j--) *p0++ = *p1++;
6369  }
6370  else
6371  {
6372  const REAL * RESTRICT p1= comps[i].first->data();
6373  REAL * RESTRICT p0 = mPowderPatternBackgroundIntegratedCalc.data();
6374  for(unsigned long j=mNbIntegrationUsed;j>0;j--) *p0++ += *p1++;
6375  }
6376  nbBackgd++;
6377  TAU_PROFILE_STOP(timer4);
6378  }
6379  }
6380  TAU_PROFILE_START(timer5);
6381  if(0==nbBackgd) mPowderPatternBackgroundIntegratedCalc.resize(0);
6382  // Calc variance
6383  bool useCalcVariance=false;
6384  for(int i=0;i<mPowderPatternComponentRegistry.GetNb();i++)
6385  if(mPowderPatternComponentRegistry.GetObj(i).HasPowderPatternCalcVariance())
6386  if(mPowderPatternComponentRegistry.GetObj(i)
6387  .GetPowderPatternIntegratedCalcVariance().first->numElements() !=0)
6388  useCalcVariance=true;
6389  if(useCalcVariance)
6390  {
6391  VFN_DEBUG_MESSAGE("PowderPattern::CalcPowderPatternIntegrated():variance",3);
6392  {
6393  mPowderPatternVarianceIntegrated.resize(mNbIntegrationUsed);
6394  mIntegratedWeight.resize(mNbIntegrationUsed);
6395  const REAL * RESTRICT p1= mIntegratedVarianceObs.data();
6396  REAL * RESTRICT p0 = mPowderPatternVarianceIntegrated.data();
6397  for(unsigned long j=mNbIntegrationUsed;j>0;j--) *p0++ = *p1++;
6398  }
6399  //cout <<"PowderPattern::CalcPowderPatternIntegrated():variance"
6400  // <<"obsvarsum="<<log(mIntegratedVarianceObs.sum());
6401  for(int i=0;i<mPowderPatternComponentRegistry.GetNb();i++)
6402  {
6403  if(mPowderPatternComponentRegistry.GetObj(i).HasPowderPatternCalcVariance())
6404  {
6405  if(0==mPowderPatternComponentRegistry.GetObj(i)
6406  .GetPowderPatternIntegratedCalcVariance().first->numElements()) break;
6407 
6408  const REAL * RESTRICT p1= mPowderPatternComponentRegistry.GetObj(i)
6409  .GetPowderPatternIntegratedCalcVariance().first->data();
6410  //cout <<",sumvar(i)="<<log(mPowderPatternComponentRegistry.GetObj(i)
6411  // .GetPowderPatternIntegratedCalcVariance().first->sum());
6412  REAL * RESTRICT p0 = mPowderPatternVarianceIntegrated.data();
6413 
6414  if(true==mPowderPatternComponentRegistry.GetObj(i).IsScalable())
6415  {
6416  const REAL s2 = mScaleFactor(i) * mScaleFactor(i);
6417  for(unsigned long j=mNbIntegrationUsed;j>0;j--) *p0++ += s2 * *p1++;
6418  }
6419  else for(unsigned long j=mNbIntegrationUsed;j>0;j--) *p0++ += *p1++;
6420 
6421  }
6422  }
6423  //cout <<endl;
6424  REAL *p0 = mIntegratedWeight.data();
6425  const REAL *p1=mPowderPatternVarianceIntegrated.data();
6426  for(unsigned long j=mNbIntegrationUsed;j>0;j--)
6427  if(*p1 <=0) {*p0++ =0;p1++;}
6428  else *p0++ = 1. / *p1++;
6429  }
6430  else mIntegratedWeight.resize(0);
6432  TAU_PROFILE_STOP(timer5);
6433  /*
6434  // Compare-DEBUG ONLY
6435  {
6436  VFN_DEBUG_MESSAGE("PowderPattern::CalcPowderPatternIntegrated():Check",10);
6437  this->CalcPowderPattern();
6438  CrystVector_REAL integr(mNbIntegrationUsed);
6439  for(int k=0;k<mPowderPatternComponentRegistry.GetNb();k++)
6440  {
6441  VFN_DEBUG_MESSAGE("PowderPattern::CalcPowderPatternIntegrated():Check #"<<k,10);
6442  integr=0;
6443  const CrystVector_REAL *v
6444  =&(mPowderPatternComponentRegistry.GetObj(k).GetPowderPatternCalc());
6445  for(unsigned int i=0;i<mNbIntegrationUsed;i++)
6446  {
6447  integr(i)=0;
6448  for(int j=mIntegratedPatternMin(i);j<=mIntegratedPatternMax(i);j++)
6449  {
6450  integr(i) += (*v)(j);
6451  }
6452  }
6453  cout << "Integrated intensities, Component #"<<k<<endl
6454  << FormatVertVector<REAL> (integr,*(comps[k].first))<<endl;
6455  }
6456  }
6457  */
6458  VFN_DEBUG_EXIT("PowderPattern::CalcPowderPatternIntegrated():End",4);
6459 }
6460 
6461 void PowderPattern::CalcPowderPatternIntegrated_FullDeriv(std::set<RefinablePar *> &vPar)
6462 {
6463  TAU_PROFILE("PowderPattern::CalcPowderPatternIntegrated_FullDeriv()","void ()",TAU_DEFAULT);
6465  this->CalcNbPointUsed();
6466 
6467  this->PrepareIntegratedRfactor();
6468  mPowderPatternUsed_FullDeriv.clear();
6469  if(mPowderPatternComponentRegistry.GetNb()==0) return;
6470  std::vector<map<RefinablePar*,CrystVector_REAL>*> comps;
6471  for(int i=0;i<mPowderPatternComponentRegistry.GetNb();i++)
6472  {
6473  comps.push_back(&(mPowderPatternComponentRegistry.GetObj(i).
6474  GetPowderPatternIntegrated_FullDeriv(vPar)));
6475  }
6476  //RefinablePar *scalePar;
6477  //cout<<"PowderPattern::CalcPowderPatternIntegrated_FullDeriv():"<<endl;
6478  mPowderPatternIntegrated_FullDeriv.clear();
6479  for(std::set<RefinablePar *>::iterator par=vPar.begin();par!=vPar.end();++par)
6480  {
6481  if(*par==0) continue; //:TODO: store the calculated (non-derived) pattern here ?
6482  for(int i=0;i<mPowderPatternComponentRegistry.GetNb();i++)
6483  {
6484  if((*par)->GetPointer()==mScaleFactor.data()+i)
6485  {
6486  //scalePar=*par;
6487  mPowderPatternIntegrated_FullDeriv[*par]=*(mPowderPatternComponentRegistry.GetObj(i).GetPowderPatternIntegratedCalc().first);
6488  //cout<<"PowderPattern::CalcPowderPatternIntegrated_FullDeriv():scale #"<<i<<":"<<(*par)->GetName()<<":"<<(*par)->GetPointer()<<":"<<mPowderPatternUsed_FullDeriv[*par]<<endl;
6489  continue;
6490  }
6491  else
6492  {
6493  if((*(comps[i]))[*par].size()==0) continue;
6494  }
6495  if(true==mPowderPatternComponentRegistry.GetObj(i).IsScalable())
6496  {
6497  if(mPowderPatternIntegrated_FullDeriv[*par].size()==0)
6498  {
6499  mPowderPatternIntegrated_FullDeriv[*par].resize(mNbIntegrationUsed);
6500  const REAL * RESTRICT p1= (*(comps[i]))[*par].data();
6501  REAL * RESTRICT p0 = mPowderPatternIntegrated_FullDeriv[*par].data();
6502  const REAL s = mScaleFactor(i);
6503  for(unsigned long j=mNbIntegrationUsed;j>0;j--)
6504  {
6505  #if 1
6506  *p0++ = s * *p1++;
6507  #else
6508  *p0 = s * *p1;
6509  if((j==mNbIntegrationUsed)&&((*par)->GetName()=="Cimetidine_C11_x")) cout<<__FILE__<<":"<<__LINE__<<":"<<*p0<<","<<s<<"*"<<*p1<<endl;
6510  p0++;p1++;
6511  #endif
6512  }
6513  }
6514  else
6515  {
6516  const REAL * RESTRICT p1= (*(comps[i]))[*par].data();
6517  REAL * RESTRICT p0 = mPowderPatternIntegrated_FullDeriv[*par].data();
6518  const REAL s = mScaleFactor(i);
6519  for(unsigned long j=mNbIntegrationUsed;j>0;j--)
6520  {
6521  #if 1
6522  *p0++ += s * *p1++;
6523  #else
6524  *p0 += s * *p1;
6525  if((j==mNbIntegrationUsed)&&((*par)->GetName()=="Cimetidine_C11_x")) cout<<__FILE__<<":"<<__LINE__<<":"<<*p0<<","<<s<<"*"<<*p1<<endl;
6526  p0++;p1++;
6527  #endif
6528  }
6529  }
6530  }
6531  else
6532  {// This is a background phase
6533  if(mPowderPatternIntegrated_FullDeriv[*par].size()==0)
6534  {
6535  mPowderPatternIntegrated_FullDeriv[*par].resize(mNbIntegrationUsed);
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  else
6550  {
6551  const REAL * RESTRICT p1= (*(comps[i]))[*par].data();
6552  REAL * RESTRICT p0 = mPowderPatternIntegrated_FullDeriv[*par].data();
6553  for(unsigned long j=mNbIntegrationUsed;j>0;j--)
6554  {
6555  #if 1
6556  *p0++ += *p1++;
6557  #else
6558  *p0 += *p1;
6559  if((j==mNbIntegrationUsed)&&((*par)->GetName()=="Cimetidine_C11_x")) cout<<__FILE__<<":"<<__LINE__<<":"<<*p0<<","<<*p1<<endl;
6560  p0++;p1++;
6561  #endif
6562  }
6563  }
6564  }
6565  #if 0
6566  if((*par)->GetName()=="Cimetidine_C11_x")
6567  cout<<"PowderPattern::CalcPowderPatternIntegrated_FullDeriv():"
6568  <<(*par)->GetName()<<":s="<<mScaleFactor(i)<<", d[0]="<<(*(comps[i]))[*par](0)
6569  <<", integ="<<mPowderPatternIntegrated_FullDeriv[*par](0)<<endl;
6570  #endif
6571  }
6572  }
6573 
6574 
6575  //cout<<"PowderPattern::CalcPowderPatternIntegrated_FullDeriv():scale #"<<1<<":"<<scalePar->GetName()<<":"<<scalePar->GetPointer()<<":"<<mPowderPatternUsed_FullDeriv[scalePar]<<endl;
6576 }
6577 
6579 {
6580  this->InitOptions();
6581  {
6582  RefinablePar tmp("Zero",&mXZero,-.05,.05,gpRefParTypeScattDataCorrPos,
6583  REFPAR_DERIV_STEP_ABSOLUTE,true,true,true,false,RAD2DEG);
6585  tmp.SetDerivStep(1e-6);
6586  this->AddPar(tmp);
6587  }
6588  {
6589  RefinablePar tmp("2ThetaDispl",&m2ThetaDisplacement,-.05,.05,gpRefParTypeScattDataCorrPos,
6590  REFPAR_DERIV_STEP_ABSOLUTE,true,true,true,false,RAD2DEG);
6592  tmp.SetDerivStep(1e-6);
6593  this->AddPar(tmp);
6594  }
6595  {
6596  RefinablePar tmp("2ThetaTransp",&m2ThetaTransparency,-.05,.05,gpRefParTypeScattDataCorrPos,
6597  REFPAR_DERIV_STEP_ABSOLUTE,true,true,true,false,RAD2DEG);
6599  tmp.SetDerivStep(1e-6);
6600  this->AddPar(tmp);
6601  }
6602  {
6603  RefinablePar tmp("DIFC",&mDIFC,0,1e6,gpRefParTypeScattDataCorrPos,
6604  REFPAR_DERIV_STEP_ABSOLUTE,true,true,true,false,1.0);
6606  tmp.SetDerivStep(1e-2);
6607  this->AddPar(tmp);
6608  }
6609  {
6610  RefinablePar tmp("DIFA",&mDIFA,-1e4,1e4,gpRefParTypeScattDataCorrPos,
6611  REFPAR_DERIV_STEP_ABSOLUTE,true,true,true,false,1.0);
6613  tmp.SetDerivStep(1e-4);
6614  this->AddPar(tmp);
6615  }
6616  {
6617  RefinablePar tmp("MuR",&mMuR,0,1000,gpRefParTypeScattDataCorrIntAbsorp,
6618  REFPAR_DERIV_STEP_ABSOLUTE,true,true,true,false,1.0);
6620  tmp.SetDerivStep(1e-4);
6621  this->AddPar(tmp);
6622  }
6623 }
6625 {
6626  bool needPrep=false;
6627  for(int i=0;i<mPowderPatternComponentRegistry.GetNb();i++)
6628  {
6629  mPowderPatternComponentRegistry.GetObj(i).GetBraggLimits();
6630  if(mPowderPatternComponentRegistry.GetObj(i).GetClockBraggLimits()
6631  >mClockIntegratedFactorsPrep)
6632  {
6633  needPrep=true;
6634  break;
6635  }
6636  }
6637 
6638  // If using max sin(theta)/lambda
6639  this->CalcNbPointUsed();
6640  if(mClockIntegratedFactorsPrep<mClockNbPointUsed) needPrep=true;
6641 
6642  if(false==needPrep)return;
6643  VFN_DEBUG_ENTRY("PowderPattern::PrepareIntegratedRfactor()",3);
6644  TAU_PROFILE("PowderPattern::PrepareIntegratedRfactor()","void ()",TAU_DEFAULT);
6645 
6646  // Aggregate all limiting pixels in a single list
6647  {
6648  list<long> vLimits;
6649 
6650  for(int i=0;i<mPowderPatternComponentRegistry.GetNb();i++)
6651  {
6652  const CrystVector_long vLim=mPowderPatternComponentRegistry.GetObj(i).GetBraggLimits();
6653  for(int j=0;j<vLim.numElements();j++) vLimits.push_back(vLim(j));
6654  }
6655  if(vLimits.size()<2)
6656  {
6657  mIntegratedPatternMin.resize(0);
6658  mIntegratedPatternMax.resize(0);
6659  mNbIntegrationUsed=0;
6660  mClockIntegratedFactorsPrep.Click();
6661  return;
6662  VFN_DEBUG_EXIT("PowderPattern::PrepareIntegratedRfactor(): no intervals !",3);
6663  }
6664  vLimits.sort();
6665  if(*(vLimits.begin())<0)
6666  {
6667  vLimits.push_back(0);
6668  vLimits.sort();
6669  }
6670  for(list<long>::iterator pos=vLimits.begin();pos!=vLimits.end();)
6671  {
6672  if( (*pos<0) || (*pos>=long(mNbPointUsed)) ) pos=vLimits.erase(pos);
6673  else ++pos;
6674  }
6675 
6676  // Try to avoid too small intervals
6677  list<long> vLimits2;
6678  list<long>::iterator pos1=vLimits.begin();
6679  list<long>::iterator pos2=pos1;pos2++;
6680  for(;pos2!=vLimits.end();)
6681  {
6682  const long pix1=*pos1;
6683  //cout<<__FILE__<<":"<<__LINE__<<":"<<pix1<<endl;
6684  vLimits2.push_back(pix1);
6685  for(;;)
6686  {
6687  pos1=pos2++;
6688  if(pos2==vLimits.end()) break;
6689  if(*pos2>(pix1+8)) break;
6690  }
6691  }
6692  vLimits2.push_back(*pos1);
6693 
6694  // Try to avoid too small intervals (2nd pass)
6695  pos1=vLimits2.begin();
6696  pos2=pos1;pos2++;
6697  for(;pos2!=vLimits2.end();)
6698  {
6699  //cout<<__FILE__<<":"<<__LINE__<<":"<<*pos1<<" -> "<<*pos2<<endl;
6700  if( *pos2<=((*pos1)+2))
6701  {
6702  //cout<<__FILE__<<":"<<__LINE__<<":"<<*pos1<<" -> "<<*pos2<<"...PLONK";
6703  pos2=vLimits2.erase(pos2);
6704  //cout<<"->"<<*pos2<<endl;
6705  }
6706  else {pos1++;pos2++;}
6707  }
6708 
6709  // Create min/max pairs
6710  list<pair<long,long> > vLimits3;
6711  pos1=vLimits2.begin();
6712  pos2=pos1;pos2++;
6713  for(;pos2!=vLimits2.end();)
6714  {
6715  if(*pos2!=(long(mNbPointUsed)-1)) vLimits3.push_back(make_pair(*pos1++,*pos2++-1));
6716  else vLimits3.push_back(make_pair(*pos1++,*pos2++));
6717  //cout<<__FILE__<<":"<<__LINE__<<":"<<vLimits3.back().first<<" -> "<<vLimits3.back().second<<endl;
6718  }
6719 
6720  mIntegratedPatternMin.resize(vLimits3.size());
6721  mIntegratedPatternMax.resize(vLimits3.size());
6722  unsigned long i=0;
6723  for(list<pair<long,long> >::iterator pos=vLimits3.begin();pos!=vLimits3.end();++pos)
6724  {
6725  mIntegratedPatternMin(i)=pos->first;
6726  mIntegratedPatternMax(i++)=pos->second;
6727  }
6728  }
6729  long numInterval=mIntegratedPatternMin.numElements();
6730  CrystVector_bool keep(numInterval);
6731  keep=true;
6732  // Take care of excluded regions (change integration areas accordingly)
6733  // regions are sorted by ascending theta
6734  const long nbExclude=mExcludedRegionMinX.numElements();
6735  if(nbExclude>0)
6736  {
6737  VFN_DEBUG_MESSAGE("PowderPattern::PrepareIntegratedRfactor():5:Excluded regions("<<nbExclude<<")",3);
6738  long j=0;
6739  long minExcl,maxExcl;
6740  minExcl=(long)floor(this->X2Pixel(mExcludedRegionMinX(j)));
6741  maxExcl=(long)ceil (this->X2Pixel(mExcludedRegionMaxX(j)));
6742  for(int i=0;i<nbExclude;i++)
6743  {
6744  while(mIntegratedPatternMax(j)<minExcl)
6745  {
6746  j++;
6747  if(j>=numInterval) break;
6748  }
6749  if(j>=numInterval) break;
6750  while(mIntegratedPatternMin(j)<maxExcl)
6751  {
6752  if( (mIntegratedPatternMin(j)>minExcl) &&(mIntegratedPatternMax(j)<maxExcl))
6753  keep(j)=false;
6754  if( (mIntegratedPatternMin(j)<minExcl) &&(mIntegratedPatternMax(j)<maxExcl))
6755  mIntegratedPatternMax(j)=minExcl;
6756  if( (mIntegratedPatternMin(j)>minExcl) &&(mIntegratedPatternMax(j)>maxExcl))
6757  mIntegratedPatternMin(j)=maxExcl;
6758  if(j==(numInterval-1)) break;
6759  j++;
6760  }
6761  minExcl=(long)(this->X2Pixel(mExcludedRegionMinX(i)));
6762  maxExcl=(long)(this->X2Pixel(mExcludedRegionMaxX(i)));
6763  //go back if one integration segment is concerned by several exclusion zones...
6764  if(j!=0)
6765  while(mIntegratedPatternMax(j)>=minExcl)
6766  {
6767  j--;
6768  if(j==0) break;
6769  }
6770  }
6771  }
6772  // Keep only the selected intervals
6773  VFN_DEBUG_MESSAGE("PowderPattern::PrepareIntegratedRfactor():6",3);
6774  long j=0;
6775  for(int i=0;i<numInterval;i++)
6776  {
6777  if(keep(i))
6778  {
6779  mIntegratedPatternMin(j )=mIntegratedPatternMin(i);
6780  mIntegratedPatternMax(j++)=mIntegratedPatternMax(i);
6781  }
6782  }
6783  numInterval=j;
6784  mIntegratedPatternMax.resizeAndPreserve(numInterval);
6785  mIntegratedPatternMin.resizeAndPreserve(numInterval);
6786 
6787  VFN_DEBUG_MESSAGE("PowderPattern::PrepareIntegratedRfactor():intervals"<<endl\
6788  <<FormatVertVector<long>(mIntegratedPatternMin,mIntegratedPatternMax),2);
6789  // Integrate Obs and weight arrays
6790  mIntegratedObs.resize(numInterval);
6791  mIntegratedVarianceObs.resize(numInterval);
6792  mIntegratedVarianceObs=0;
6793  mIntegratedObs=0;
6794  mIntegratedWeightObs.resize(numInterval);
6795  for(int i=0;i<numInterval;i++)
6796  {
6797  for(int j=mIntegratedPatternMin(i);j<=mIntegratedPatternMax(i);j++)
6798  {
6799  mIntegratedObs (i)+=mPowderPatternObs(j);
6800  mIntegratedVarianceObs(i)+=mPowderPatternObsSigma(j)*mPowderPatternObsSigma(j);
6801  }
6802  if(mIntegratedVarianceObs(i) <= 0) mIntegratedWeightObs(i)=0;
6803  else mIntegratedWeightObs(i)=1./mIntegratedVarianceObs(i);
6804  }
6805 
6806 
6807  //cout<<FormatVertVector<REAL>(mIntegratedPatternMin,
6808  // mIntegratedPatternMax,
6809  // mIntegratedObs,mIntegratedWeight,12,6)<<endl;
6810  mNbIntegrationUsed=mIntegratedPatternMin.numElements();
6811  mClockIntegratedFactorsPrep.Click();
6812  VFN_DEBUG_EXIT("PowderPattern::PrepareIntegratedRfactor()",3);
6813 }
6815 {
6816  if(this->IsBeingRefined())return;
6817  unsigned long tmp;
6818  // Use the first point of the profile of the first reflection not calculated
6819  if(this->GetRadiation().GetWavelengthType()==WAVELENGTH_TOF)
6820  {
6821  tmp=(unsigned long)(this->X2PixelCorr(this->STOL2X(mMaxSinThetaOvLambda)));
6822  }
6823  else
6824  {
6825  REAL sinth=mMaxSinThetaOvLambda*this->GetWavelength();
6826  if(1>fabs(sinth)) tmp=(unsigned long)(this->X2PixelCorr(2*asin(sinth))); else tmp=mNbPoint;
6827  }
6828  if(tmp>mNbPoint) tmp= mNbPoint;
6829  if(tmp !=mNbPointUsed)
6830  {
6831  mNbPointUsed=tmp;
6832  mClockNbPointUsed.Click();
6833  VFN_DEBUG_MESSAGE("PowderPattern::CalcNbPointUsed():"<<mNbPointUsed<<" max(sin(theta)/lambda)="<<mMaxSinThetaOvLambda, 3)
6834  }
6835 
6836 }
6837 
6839 {
6840  VFN_DEBUG_MESSAGE("PowderPattern::InitOptions()",5)
6841  static string OptProfileIntegrationName;
6842  static string OptProfileIntegrationChoices[2];
6843 
6844  static bool needInitNames=true;
6845  if(true==needInitNames)
6846  {
6847  OptProfileIntegrationName="Use Integrated Profiles";
6848  OptProfileIntegrationChoices[0]="Yes (recommended)";
6849  OptProfileIntegrationChoices[1]="No";
6850 
6851  needInitNames=false;//Only once for the class
6852  }
6853  mOptProfileIntegration.Init(2,&OptProfileIntegrationName,OptProfileIntegrationChoices);
6854  this->AddOption(&mOptProfileIntegration);
6855 }
6856 
6857 #ifdef __WX__CRYST__
6858 WXCrystObjBasic* PowderPattern::WXCreate(wxWindow* parent)
6859 {
6860  //:TODO: Check mpWXCrystObj==0
6861  mpWXCrystObj=new WXPowderPattern(parent,this);
6862  return mpWXCrystObj;
6863 }
6864 #endif
6865 
6867 //
6868 // Spacegroup Explorer
6869 //
6871 
6875 SPGScore::SPGScore(const string &s, const REAL r, const REAL g, const unsigned int nbextinct, const REAL ngof, const unsigned int nbrefl):
6876  hm(s),rw(r),gof(g),ngof(ngof),nbextinct446(nbextinct),nbreflused(nbrefl)
6877  {};
6878 
6879 
6880 bool compareSPGScore(const SPGScore &s1, const SPGScore &s2)
6881 {
6882  if(s1.ngof > 0.00001 && s2.ngof >0.00001) return s1.ngof < s2.ngof;
6883  return s1.gof < s2.gof;
6884 }
6885 
6888 std::vector<bool> spgExtinctionFingerprint(Crystal &c, const cctbx::sgtbx::space_group &spg)
6889 {
6890  // We don't have the extinction symbol, so do it the stupid way
6891  std::vector<bool> fingerprint(5*5*7-1+6);
6892  long i=0;
6893  fingerprint[i++]=c.GetPar("a").IsUsed();
6894  fingerprint[i++]=c.GetPar("b").IsUsed();
6895  fingerprint[i++]=c.GetPar("c").IsUsed();
6896  fingerprint[i++]=c.GetPar("alpha").IsUsed();
6897  fingerprint[i++]=c.GetPar("beta").IsUsed();
6898  fingerprint[i++]=c.GetPar("gamma").IsUsed();
6899  for(long h=0;h<5;++h)
6900  for(long k=0;k<5;++k)
6901  for (long l=0;l<7;++l)
6902  {
6903  if((h+k+l)==0) continue;
6904  cctbx::miller::index<long> hkl(scitbx::vec3<long>(h,k,l));
6905  if(i>=fingerprint.size()) cout<<"WHOOOOOOOOOOOOOPS"<<endl;
6906  fingerprint[i++] =spg.is_sys_absent(hkl);
6907  }
6908  return fingerprint;
6909 }
6910 
6914 SpaceGroupExplorer::SpaceGroupExplorer(PowderPatternDiffraction *pd):
6915  mpDiff(pd){};
6916 
6917 SPGScore SpaceGroupExplorer::Run(const string &spgId, const bool fitprofile,
6918  const bool verbose, const bool restore_orig,
6919  const bool update_display, const REAL relative_length_tolerance,
6920  const REAL absolute_angle_tolerance_degree)
6921 {
6922  cctbx::sgtbx::space_group sg;
6923  try
6924  {
6925  // Should work as a HM symbol or number
6926  cctbx::sgtbx::space_group_symbols sgs=cctbx::sgtbx::space_group_symbols(spgId);
6927  sg = cctbx::sgtbx::space_group(sgs);
6928  }
6929  catch(exception ex1)
6930  {
6931  try
6932  {
6933  // Try as a Hall symbol
6934  sg = cctbx::sgtbx::space_group(spgId);
6935  }
6936  catch(exception ex2)
6937  {
6938  string emsg = "Space group symbol '" + spgId + "' not recognized";
6939  throw ObjCrystException(emsg);
6940  }
6941  }
6942  return this->Run(sg, fitprofile, verbose, restore_orig, update_display,
6943  relative_length_tolerance, absolute_angle_tolerance_degree);
6944 }
6945 
6946 SPGScore SpaceGroupExplorer::Run(const cctbx::sgtbx::space_group &spg, const bool fitprofile, const bool verbose,
6947  const bool restore_orig, const bool update_display,
6948  const REAL relative_length_tolerance, const REAL absolute_angle_tolerance_degree)
6949 {
6950  TAU_PROFILE("SpaceGroupExplorer::Run()","void (wxCommandEvent &)",TAU_DEFAULT);
6951  TAU_PROFILE_TIMER(timer1,"SpaceGroupExplorer::Run()LSQ-P1","", TAU_FIELD);
6952  TAU_PROFILE_TIMER(timer2,"SpaceGroupExplorer::Run()LSQ1","", TAU_FIELD);
6953  TAU_PROFILE_TIMER(timer3,"SpaceGroupExplorer::Run()LSQ2","", TAU_FIELD);
6954  Crystal *pCrystal=&(mpDiff->GetCrystal());
6955  // Keep initial lattice parameters & spg
6956  const REAL a=pCrystal->GetLatticePar(0),
6957  b=pCrystal->GetLatticePar(1),
6958  c=pCrystal->GetLatticePar(2),
6959  d=pCrystal->GetLatticePar(3),
6960  e=pCrystal->GetLatticePar(4),
6961  f=pCrystal->GetLatticePar(5);
6962  const string spghm=pCrystal->GetSpaceGroup().GetCCTbxSpg().match_tabulated_settings().hermann_mauguin();
6963  const string name=pCrystal->GetName();
6964  // Set up new spacegroup
6965  const cctbx::sgtbx::space_group_symbols s = spg.match_tabulated_settings();
6966  const string hm=s.universal_hermann_mauguin();
6967  const cctbx::uctbx::unit_cell uc(scitbx::af::double6(a,b,c,d*RAD2DEG,e*RAD2DEG,f*RAD2DEG));
6968  if(!spg.is_compatible_unit_cell(uc,relative_length_tolerance,absolute_angle_tolerance_degree))
6969  {
6970  throw ObjCrystException("Spacegroup is not compatible with unit cell.");
6971  }
6972  mpDiff->GetCrystal().Init(a,b,c,d,e,f,hm,name);
6973  mpDiff->SetExtractionMode(true,true);
6974  unsigned int nbcycle=1;
6975  if(update_display) mpDiff->GetParentPowderPattern().UpdateDisplay();
6976  // Number of free parameters (not taking into account refined profile/background parameters)
6977  unsigned int nbfreepar=mpDiff->GetProfileFitNetNbObs();
6978  if(nbfreepar<1) nbfreepar=1; // Should not happen !
6979 
6980  // Create the LSQ obj even if the profile is not fitted, to allow restoring all parameters
6981  LSQNumObj lsq;
6982  lsq.SetRefinedObj(mpDiff->GetParentPowderPattern(),0,true,true);
6983  lsq.PrepareRefParList(true);
6984  const unsigned int saved_par = lsq.GetCompiledRefinedObj().CreateParamSet("SpaceGroupExplorer saved parameters");
6985  lsq.GetCompiledRefinedObj().SaveParamSet(saved_par);
6986 
6987  Chronometer chrono;
6988  for(unsigned int j=0;j<nbcycle;j++)
6989  {
6990  // First, Le Bail
6991  mpDiff->SetExtractionMode(true,true);
6992  const float t0=chrono.seconds();
6993  if(verbose) cout<<"Doing Le Bail, t="<<FormatFloat(t0,6,2)<<"s";
6994  mpDiff->ExtractLeBail(5);
6995  if(verbose) cout<<", dt="<<FormatFloat(chrono.seconds()-t0,6,2)<<"s"<<endl;
6996  //mpDiff->GetParentPowderPattern().FitScaleFactorForIntegratedRw();
6997  if(fitprofile)
6998  {// Perform LSQ
6999  TAU_PROFILE_START(timer2);
7000  lsq.SetParIsFixed(gpRefParTypeObjCryst,true);
7001  lsq.SetParIsFixed(gpRefParTypeScattDataScale,false);
7002  std::list<RefinablePar*> vnewpar;
7003  std::list<const RefParType*> vnewpartype;
7004  // Only do the full monty for P1, keep the parameters for other spacegroups
7005  if(s.number()==1) vnewpar.push_back(&lsq.GetCompiledRefinedObj().GetPar("Zero"));
7006  lsq.SetParIsFixed(gpRefParTypeUnitCell,false);
7007  lsq.SafeRefine(vnewpar, vnewpartype,1.01,2,true,true);
7008  vnewpar.clear();
7009  TAU_PROFILE_STOP(timer2);
7010  if(s.number()==1)
7011  {
7012  TAU_PROFILE_START(timer1);
7013  vnewpar.push_back(&lsq.GetCompiledRefinedObj().GetPar("2ThetaDispl"));
7014  vnewpar.push_back(&lsq.GetCompiledRefinedObj().GetPar("2ThetaTransp"));
7015  lsq.SafeRefine(vnewpar, vnewpartype,1.01,2,true,true);
7016  vnewpar.clear();
7017  lsq.SetParIsFixed(gpRefParTypeScattDataBackground,false);
7018  // Fix background point beyond optimized domain
7019  const unsigned int nbcomp= mpDiff->GetParentPowderPattern().GetNbPowderPatternComponent();
7020  for(unsigned int i=0;i<nbcomp;++i)
7021  if(mpDiff->GetParentPowderPattern().GetPowderPatternComponent(i).GetClassName()=="PowderPatternBackground")
7022  {
7023  PowderPatternBackground *pback=dynamic_cast<PowderPatternBackground *>
7024  (&(mpDiff->GetParentPowderPattern().GetPowderPatternComponent(i)));
7025  pback->FixParametersBeyondMaxresolution(lsq.GetCompiledRefinedObj());
7026  }
7027  for(unsigned int i=0; i<lsq.GetCompiledRefinedObj().GetNbPar();i++)
7028  if( (lsq.GetCompiledRefinedObj().GetPar(i).IsFixed()==false)
7029  &&(lsq.GetCompiledRefinedObj().GetPar(i).GetType()==gpRefParTypeScattDataBackground))
7030  vnewpar.push_back(&lsq.GetCompiledRefinedObj().GetPar(i));
7031  lsq.SafeRefine(vnewpar,vnewpartype,1.01,2,true,true);
7032  vnewpar.clear();
7033  TAU_PROFILE_STOP(timer1);
7034  }
7035  // restart from equal intensities
7036  mpDiff->SetExtractionMode(true,true);
7037  mpDiff->ExtractLeBail(5);
7038  TAU_PROFILE_START(timer3);
7039  lsq.SafeRefine(vnewpar,vnewpartype,1.01,3,true,true);
7040  TAU_PROFILE_STOP(timer3);
7041  //mpLog->AppendText(wxString::Format(_T("%5.2f%%/"),pDiff->GetParentPowderPattern().GetRw()*100));
7042  //mpDiff->GetParentPowderPattern().FitScaleFactorForIntegratedRw();
7043  }
7044  if(update_display) mpDiff->GetParentPowderPattern().UpdateDisplay();
7045  const REAL rw=mpDiff->GetParentPowderPattern().GetRw()*100;
7046  const REAL gof=mpDiff->GetParentPowderPattern().GetChi2()/mpDiff->GetParentPowderPattern().GetNbPointUsed();
7047  if(verbose) cout << boost::format(" (cycle #%u)\n Rwp=%5.2f%%\n GoF=%9.2f") % j % rw % gof <<endl;
7048  }
7049  const REAL rw=mpDiff->GetParentPowderPattern().GetRw()*100;
7050  const REAL gof=mpDiff->GetParentPowderPattern().GetChi2()/nbfreepar;
7051  const REAL ngof = this->GetP1IntegratedGoF();
7052  unsigned int nbextinct446=0;
7053  std::vector<bool> fgp=spgExtinctionFingerprint(*pCrystal,spg);
7054  for(unsigned int i=6;i<fgp.size();++i) nbextinct446+=(unsigned int)(fgp[i]);
7055  const unsigned int nbrefl = mpDiff->GetNbReflBelowMaxSinThetaOvLambda();
7056  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;
7057 
7058  if(restore_orig)
7059  {
7060  mpDiff->GetCrystal().Init(a,b,c,d,e,f,spghm,name);
7061  lsq.GetCompiledRefinedObj().RestoreParamSet(saved_par);
7062  if (update_display)
7063  {
7064  mpDiff->GetCrystal().UpdateDisplay();
7065  this->mpDiff->GetParentPowderPattern().UpdateDisplay();
7066  }
7067  }
7068 
7069  return SPGScore(hm.c_str(),rw,gof,nbextinct446, ngof, nbrefl);
7070 }
7071 
7072 void SpaceGroupExplorer::RunAll(const bool fitprofile_all, const bool verbose, const bool keep_best,
7073  const bool update_display, const bool fitprofile_p1,
7074  const REAL relative_length_tolerance, const REAL absolute_angle_tolerance_degree)
7075 {
7076  Crystal *pCrystal=&(mpDiff->GetCrystal());
7077 
7078  // Initial lattice parameters & spg
7079  const REAL a=pCrystal->GetLatticePar(0),
7080  b=pCrystal->GetLatticePar(1),
7081  c=pCrystal->GetLatticePar(2),
7082  d=pCrystal->GetLatticePar(3),
7083  e=pCrystal->GetLatticePar(4),
7084  f=pCrystal->GetLatticePar(5);
7085  const cctbx::uctbx::unit_cell uc(scitbx::af::double6(a,b,c,d*RAD2DEG,e*RAD2DEG,f*RAD2DEG));
7086  const string spghm=pCrystal->GetSpaceGroup().GetCCTbxSpg().match_tabulated_settings().hermann_mauguin();
7087  const string name=pCrystal->GetName();
7088 
7089  cctbx::sgtbx::space_group_symbol_iterator it=cctbx::sgtbx::space_group_symbol_iterator();
7090  // First, count compatible spacegroups
7091  unsigned int nbspg=0;
7092  for(;;)
7093  {
7094  cctbx::sgtbx::space_group_symbols s=it.next();
7095  if(s.number()==0) break;
7096  cctbx::sgtbx::space_group spg(s);
7097  if(spg.is_compatible_unit_cell(uc,relative_length_tolerance, absolute_angle_tolerance_degree)) nbspg++;
7098  //if(s.universal_hermann_mauguin().size()>hmlen) hmlen=s.universal_hermann_mauguin().size();
7099  }
7100  if(verbose) cout << boost::format("Beginning spacegroup exploration... %u to go...\n") % nbspg;
7101 
7102  mvSPG.clear();
7103  mvSPGExtinctionFingerprint.clear();
7104 
7105  // Nb refl below max sin(theta/lambda) for p1, to compute nGoF
7106  unsigned int nb_refl_p1=1;
7107 
7108  it=cctbx::sgtbx::space_group_symbol_iterator();
7109  Chronometer chrono;
7110  chrono.start();
7111  for(int i=0;;)
7112  {
7113  cctbx::sgtbx::space_group_symbols s=it.next();
7114  if(s.number()==0) break;
7115  cctbx::sgtbx::space_group spg(s);
7116  bool compat=spg.is_compatible_unit_cell(uc,relative_length_tolerance,absolute_angle_tolerance_degree);
7117  if(compat)
7118  {
7119  i++;
7120  const string hm=s.universal_hermann_mauguin();
7121  // cout<<s.number()<<","<<hm.c_str()<<","<<(int)compat<<endl;
7122  pCrystal->Init(a,b,c,d,e,f,hm,name);
7123 
7124  std::vector<bool> fgp=spgExtinctionFingerprint(*pCrystal,spg);
7125  std::map<std::vector<bool>,SPGScore>::iterator posfgp=mvSPGExtinctionFingerprint.find(fgp);
7126  if(posfgp!=mvSPGExtinctionFingerprint.end())
7127  {
7128  pCrystal->Init(a,b,c,d,e,f,hm,name);
7129  mpDiff->SetExtractionMode(true,true); //:TODO: why is this needed to actually get the updated GetNbReflBelowMaxSinThetaOvLambda ?
7130  unsigned int nbrefl = mpDiff->GetNbReflBelowMaxSinThetaOvLambda();
7131  REAL ngof = (posfgp->second.ngof * nbrefl) / posfgp->second.nbreflused;
7132  mvSPG.push_back(SPGScore(hm.c_str(),posfgp->second.rw,posfgp->second.gof,posfgp->second.nbextinct446, ngof, nbrefl));
7133  if(verbose) cout<<boost::format(" (#%3d) %-14s: Rwp= %5.2f%% GoF=%9.2f nGoF=%9.2f (%3u reflections, %3u extinct)")
7134  % s.number() % hm.c_str() % mvSPG.back().rw % mvSPG.back().gof % mvSPG.back().ngof % mvSPG.back().nbreflused % mvSPG.back().nbextinct446
7135  <<" [same extinctions as:"<<posfgp->second.hm<<"]\n";
7136  }
7137  else
7138  {
7139  if(((s.number()==1) && fitprofile_p1) || fitprofile_all) mvSPG.push_back(this->Run(spg, true, false, false, update_display,
7140  relative_length_tolerance, absolute_angle_tolerance_degree));
7141  else mvSPG.push_back(this->Run(spg, false, false, true, update_display,relative_length_tolerance,absolute_angle_tolerance_degree));
7142  if(s.number() == 1) nb_refl_p1 = mvSPG.back().nbreflused;
7143  mvSPG.back().ngof *= mpDiff->GetNbReflBelowMaxSinThetaOvLambda() / (float)nb_refl_p1;
7144  mvSPGExtinctionFingerprint.insert(make_pair(fgp, mvSPG.back()));
7145 
7146  if(verbose) cout<<boost::format(" (#%3d) %-14s: Rwp= %5.2f%% GoF=%9.2f nGoF=%9.2f (%3u reflections, %3u extinct)\n")
7147  % s.number() % hm.c_str() % mvSPG.back().rw % mvSPG.back().gof % mvSPG.back().ngof % mvSPG.back().nbreflused % mvSPG.back().nbextinct446;
7148  }
7149  }
7150  }
7151  mvSPG.sort(compareSPGScore);
7152  if(keep_best)
7153  {
7154  if(verbose) cout<<"Restoring best spacegroup: "<<mvSPG.front().hm<<endl;
7155  pCrystal->ChangeSpaceGroup(mvSPG.front().hm);
7156  }
7157  else
7158  {
7159  // Go back to original lattice and spacegroup & update display
7160  pCrystal->Init(a,b,c,d,e,f,spghm,name);
7161  }
7162  mpDiff->SetExtractionMode(true,true);
7163  mpDiff->ExtractLeBail(5);
7164  if(update_display)
7165  {
7166  pCrystal->UpdateDisplay();
7167  this->mpDiff->GetParentPowderPattern().UpdateDisplay();
7168  }
7169 
7170 }
7171 
7172 const list<SPGScore>& SpaceGroupExplorer::GetScores() const
7173 {
7174  return mvSPG;
7175 }
7176 
7177 REAL SpaceGroupExplorer::GetP1IntegratedGoF()
7178 {
7179  if(mpDiff->GetCrystal().GetSpaceGroup().GetSpaceGroupNumber()==1)
7180  {
7181  mpDiff->GetPowderPatternIntegratedCalc();
7182  mP1IntegratedProfileMin = mpDiff->GetParentPowderPattern().GetIntegratedProfileMin();
7183  mP1IntegratedProfileMax = mpDiff->GetParentPowderPattern().GetIntegratedProfileMax();
7184  // cout<<"Updating mP1IntegratedProfileMin/Max:"<<endl
7185  // <<FormatVertVectorHKLFloats<REAL>(mP1IntegratedProfileMin, mP1IntegratedProfileMax,mP1IntegratedProfileMax)<<endl;
7186  }
7187  else if (mP1IntegratedProfileMin.size()==0) return 0;
7188 
7189  //cout<<FormatVertVectorHKLFloats<REAL>(mpDiff->GetH(), mpDiff->GetK(), mpDiff->GetL(), mpDiff->GetFhklCalcSq());
7190  REAL integratedChi2=0.;
7191  REAL integratedChi2LikeNorm=0.;
7192  const REAL * RESTRICT p1, * RESTRICT p2, * RESTRICT p3;
7193  CrystVector_REAL const* pcalc = &(mpDiff->GetParentPowderPattern().GetPowderPatternCalc());
7194  CrystVector_REAL const* pobs = &(mpDiff->GetParentPowderPattern().GetPowderPatternObs());
7195  CrystVector_REAL const* psigma = &(mpDiff->GetParentPowderPattern().GetPowderPatternObsSigma());
7196  const unsigned int jmax = mpDiff->GetParentPowderPattern().GetNbPointUsed();
7197  REAL chi2=0;
7198  unsigned int nbpoint = 0;
7199  for(unsigned long i=0;i<mP1IntegratedProfileMin.size();i++)
7200  {
7201  if(mP1IntegratedProfileMin(i) > jmax) break;
7202  if(mP1IntegratedProfileMax(i) < 0) continue;
7203  REAL v=0, c=0, o=0;
7204  for(unsigned long j=mP1IntegratedProfileMin(i); j<=mP1IntegratedProfileMax(i); j++)
7205  {
7206  if(j<0) continue;
7207  if(j >= jmax) break;
7208  nbpoint++;
7209  c += (*pcalc)(j); // calc
7210  o += (*pobs)(j); // obs
7211  v += (*psigma)(j)*(*psigma)(j); // variance
7212  }
7213  if(v>0) chi2 += (c-o)*(c-o)/v;
7214  }
7215  return chi2 / nbpoint;
7216 }
7217 
7218 }//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.
void SetPowderPatternObsSigma(const CrystVector_REAL &sigma)
Set sigma for each point of the observed powder pattern.
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.