Skip to content

Commit ced2b9c

Browse files
committed
Improve indexing: use the integrated goodness-of-fit based on P1 integration intervals as a default indicator, normalised by the number of reflections used (* nb_refl / nb_refl_P1). Improve output. Make sure calculations are done correctly when switching lattice or spacegroup.
1 parent 1a80575 commit ced2b9c

4 files changed

Lines changed: 113 additions & 37 deletions

File tree

ObjCryst/ObjCryst/PowderPattern.cpp

Lines changed: 68 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1195,6 +1195,7 @@ void PowderPatternDiffraction::ExtractLeBail(unsigned int nbcycle)
11951195
}
11961196
mClockFhklObsSq.Click();
11971197
//cout<<"PowderPatternDiffraction::ExtractLeBail():results (scale factor="<<mpParentPowderPattern->GetScaleFactor(*this)*1e6<<")" <<endl<< FormatVertVectorHKLFloats<REAL>(mH,mK,mL,this->GetFhklCalcSq(),mFhklObsSq,10,4,nbrefl)<<endl;
1198+
mClockIhklCalc.Reset(); // During Le Bail
11981199
}
11991200
// Store extracted data in a single crystal data object
12001201
if(mpLeBailData==0) mpLeBailData=new DiffractionDataSingleCrystal(*mpCrystal,false);
@@ -2387,6 +2388,7 @@ void PowderPatternDiffraction::CalcFrozenBMatrix()const
23872388
void PowderPatternDiffraction::PrepareIntegratedProfile()const
23882389
{
23892390
this->CalcPowderReflProfile();
2391+
this->GetNbReflBelowMaxSinThetaOvLambda();
23902392

23912393
if( (mClockIntegratedProfileFactor>mClockProfileCalc)
23922394
&&(mClockIntegratedProfileFactor>mpParentPowderPattern->GetIntegratedProfileLimitsClock())
@@ -4508,7 +4510,7 @@ void PowderPattern::FitScaleFactorForR()const
45084510
-mScaleFactor(mScalableComponentIndex(i));
45094511
if(ISNAN_OR_INF(s))
45104512
{
4511-
(*fpObjCrystInformUser)("Warning: working around NaN scale factor...");
4513+
(*fpObjCrystInformUser)("Warning:FitScaleFactorForR: working around NaN scale factor...");
45124514
continue;
45134515
}
45144516
for(unsigned long j=0;j<mNbPointUsed;j++) *p0++ += s * *p1++;
@@ -4657,7 +4659,7 @@ void PowderPattern::FitScaleFactorForIntegratedR()const
46574659
-mScaleFactor(mScalableComponentIndex(i));
46584660
if(ISNAN_OR_INF(s))
46594661
{
4660-
(*fpObjCrystInformUser)("Warning: working around NaN scale factor...");
4662+
(*fpObjCrystInformUser)("Warning:FitScaleFactorForIntegratedR: working around NaN scale factor...");
46614663
continue;
46624664
}
46634665
for(unsigned long j=0;j<mNbPointUsed;j++) *p0++ += s * *p1++;
@@ -4833,7 +4835,7 @@ void PowderPattern::FitScaleFactorForRw()const
48334835
-mScaleFactor(mScalableComponentIndex(i));
48344836
if(ISNAN_OR_INF(s))
48354837
{
4836-
(*fpObjCrystInformUser)("Warning: working around NaN scale factor...");
4838+
(*fpObjCrystInformUser)("Warning:FitScaleFactorForRw working around NaN scale factor...");
48374839
continue;
48384840
}
48394841
for(unsigned long j=0;j<mNbPointUsed;j++) *p0++ += s * *p1++;
@@ -5065,7 +5067,7 @@ void PowderPattern::FitScaleFactorForIntegratedRw()const
50655067
-mScaleFactor(mScalableComponentIndex(i));
50665068
if(ISNAN_OR_INF(s))
50675069
{
5068-
(*fpObjCrystInformUser)("Warning: working around NaN scale factor...");
5070+
(*fpObjCrystInformUser)("Warning:FitScaleFactorForIntegratedRw: working around NaN scale factor...");
50695071
continue;
50705072
}
50715073
if(nbVarCalc>0)
@@ -6779,14 +6781,14 @@ WXCrystObjBasic* PowderPattern::WXCreate(wxWindow* parent)
67796781
/** Structure to hold the score corresponding to a given spacegroup.
67806782
*
67816783
*/
6782-
SPGScore::SPGScore(const string &s, const REAL r, const REAL g, const unsigned int nbextinct, const REAL ngof):
6783-
hm(s),rw(r),gof(g),ngof(ngof),nbextinct446(nbextinct)
6784+
SPGScore::SPGScore(const string &s, const REAL r, const REAL g, const unsigned int nbextinct, const REAL ngof, const unsigned int nbrefl):
6785+
hm(s),rw(r),gof(g),ngof(ngof),nbextinct446(nbextinct),nbreflused(nbrefl)
67846786
{};
67856787

67866788

67876789
bool compareSPGScore(const SPGScore &s1, const SPGScore &s2)
67886790
{
6789-
if(s1.ngof > 0.01 && s2.ngof >0.01) return s1.ngof < s2.ngof;
6791+
if(s1.ngof > 0.00001 && s2.ngof >0.00001) return s1.ngof < s2.ngof;
67906792
return s1.gof < s2.gof;
67916793
}
67926794

@@ -6855,7 +6857,6 @@ SPGScore SpaceGroupExplorer::Run(const cctbx::sgtbx::space_group &spg, const boo
68556857
TAU_PROFILE_TIMER(timer1,"SpaceGroupExplorer::Run()LSQ-P1","", TAU_FIELD);
68566858
TAU_PROFILE_TIMER(timer2,"SpaceGroupExplorer::Run()LSQ1","", TAU_FIELD);
68576859
TAU_PROFILE_TIMER(timer3,"SpaceGroupExplorer::Run()LSQ2","", TAU_FIELD);
6858-
mpDiff->SetExtractionMode(true,true);
68596860
Crystal *pCrystal=&(mpDiff->GetCrystal());
68606861
// Keep initial lattice parameters & spg
68616862
const REAL a=pCrystal->GetLatticePar(0),
@@ -6875,6 +6876,7 @@ SPGScore SpaceGroupExplorer::Run(const cctbx::sgtbx::space_group &spg, const boo
68756876
throw ObjCrystException("Spacegroup is not compatible with unit cell.");
68766877
}
68776878
mpDiff->GetCrystal().Init(a,b,c,d,e,f,hm,name);
6879+
mpDiff->SetExtractionMode(true,true);
68786880
unsigned int nbcycle=1;
68796881
if(update_display) mpDiff->GetParentPowderPattern().UpdateDisplay();
68806882
// Number of free parameters (not taking into account refined profile/background parameters)
@@ -6897,7 +6899,7 @@ SPGScore SpaceGroupExplorer::Run(const cctbx::sgtbx::space_group &spg, const boo
68976899
if(verbose) cout<<"Doing Le Bail, t="<<FormatFloat(t0,6,2)<<"s";
68986900
mpDiff->ExtractLeBail(5);
68996901
if(verbose) cout<<", dt="<<FormatFloat(chrono.seconds()-t0,6,2)<<"s"<<endl;
6900-
mpDiff->GetParentPowderPattern().FitScaleFactorForRw();
6902+
//mpDiff->GetParentPowderPattern().FitScaleFactorForIntegratedRw();
69016903
if(fitprofile)
69026904
{// Perform LSQ
69036905
TAU_PROFILE_START(timer2);
@@ -6943,7 +6945,7 @@ SPGScore SpaceGroupExplorer::Run(const cctbx::sgtbx::space_group &spg, const boo
69436945
lsq.SafeRefine(vnewpar,vnewpartype,1.01,3,true,true);
69446946
TAU_PROFILE_STOP(timer3);
69456947
//mpLog->AppendText(wxString::Format(_T("%5.2f%%/"),pDiff->GetParentPowderPattern().GetRw()*100));
6946-
mpDiff->GetParentPowderPattern().FitScaleFactorForRw();
6948+
//mpDiff->GetParentPowderPattern().FitScaleFactorForIntegratedRw();
69476949
}
69486950
if(update_display) mpDiff->GetParentPowderPattern().UpdateDisplay();
69496951
const REAL rw=mpDiff->GetParentPowderPattern().GetRw()*100;
@@ -6952,10 +6954,12 @@ SPGScore SpaceGroupExplorer::Run(const cctbx::sgtbx::space_group &spg, const boo
69526954
}
69536955
const REAL rw=mpDiff->GetParentPowderPattern().GetRw()*100;
69546956
const REAL gof=mpDiff->GetParentPowderPattern().GetChi2()/nbfreepar;
6957+
const REAL ngof = this->GetP1IntegratedGoF();
69556958
unsigned int nbextinct446=0;
69566959
std::vector<bool> fgp=spgExtinctionFingerprint(*pCrystal,spg);
69576960
for(unsigned int i=6;i<fgp.size();++i) nbextinct446+=(unsigned int)(fgp[i]);
6958-
if(verbose>0) cout << boost::format(" Rwp= %5.2f%% GoF=%9.2f (%2u extinct refls)") % rw % gof % nbextinct446<<endl;
6961+
const unsigned int nbrefl = mpDiff->GetNbReflBelowMaxSinThetaOvLambda();
6962+
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;
69596963

69606964
if(restore_orig)
69616965
{
@@ -6968,7 +6972,7 @@ SPGScore SpaceGroupExplorer::Run(const cctbx::sgtbx::space_group &spg, const boo
69686972
}
69696973
}
69706974

6971-
return SPGScore(hm.c_str(),rw,gof,nbextinct446);
6975+
return SPGScore(hm.c_str(),rw,gof,nbextinct446, ngof, nbrefl);
69726976
}
69736977

69746978
void SpaceGroupExplorer::RunAll(const bool fitprofile_all, const bool verbose, const bool keep_best,
@@ -7027,18 +7031,24 @@ void SpaceGroupExplorer::RunAll(const bool fitprofile_all, const bool verbose, c
70277031
std::map<std::vector<bool>,SPGScore>::iterator posfgp=mvSPGExtinctionFingerprint.find(fgp);
70287032
if(posfgp!=mvSPGExtinctionFingerprint.end())
70297033
{
7030-
mvSPG.push_back(SPGScore(hm.c_str(),posfgp->second.rw,posfgp->second.gof,posfgp->second.nbextinct446, posfgp->second.ngof));
7031-
if(verbose) cout<<"Spacegroup:"<<hm<<" has same extinctions as:"<<posfgp->second.hm<<endl;
7034+
pCrystal->Init(a,b,c,d,e,f,hm,name);
7035+
mpDiff->SetExtractionMode(true,true); //:TODO: why is this needed to actually get the updated GetNbReflBelowMaxSinThetaOvLambda ?
7036+
unsigned int nbrefl = mpDiff->GetNbReflBelowMaxSinThetaOvLambda();
7037+
REAL ngof = (posfgp->second.ngof * nbrefl) / posfgp->second.nbreflused;
7038+
mvSPG.push_back(SPGScore(hm.c_str(),posfgp->second.rw,posfgp->second.gof,posfgp->second.nbextinct446, ngof, posfgp->second.nbreflused));
7039+
if(verbose) cout<<boost::format(" (#%3d) %-14s: Rwp= %5.2f%% GoF=%9.2f nGoF=%9.2f (%3u reflections, %3u extinct)\n")
7040+
% s.number() % hm.c_str() % mvSPG.back().rw % mvSPG.back().gof % mvSPG.back().ngof % mvSPG.back().nbreflused % mvSPG.back().nbextinct446
7041+
<<" [same extinctions as:"<<posfgp->second.hm<<"]";
70327042
}
70337043
else
70347044
{
70357045
if(((s.number()==1) && fitprofile_p1) || fitprofile_all) mvSPG.push_back(this->Run(spg, true, false, false, update_display));
70367046
else mvSPG.push_back(this->Run(spg, false, false, true, update_display));
7037-
mvSPG.back().ngof = mvSPG.back().gof * mpDiff->GetNbReflBelowMaxSinThetaOvLambda() / (float)nb_refl_p1;
7047+
mvSPG.back().ngof *= mpDiff->GetNbReflBelowMaxSinThetaOvLambda() / (float)nb_refl_p1;
70387048
mvSPGExtinctionFingerprint.insert(make_pair(fgp, mvSPG.back()));
70397049

7040-
if(verbose) cout<<boost::format(" (#%3d) %-14s: Rwp= %5.2f%% GoF=%9.2f nGoF=%9.2f (%2u extinct refls)\n")
7041-
% s.number() % hm.c_str() % mvSPG.back().rw % mvSPG.back().gof % mvSPG.back().ngof % mvSPG.back().nbextinct446;
7050+
if(verbose) cout<<boost::format(" (#%3d) %-14s: Rwp= %5.2f%% GoF=%9.2f nGoF=%9.2f (%3u reflections, %3u extinct)\n")
7051+
% s.number() % hm.c_str() % mvSPG.back().rw % mvSPG.back().gof % mvSPG.back().ngof % mvSPG.back().nbreflused % mvSPG.back().nbextinct446;
70427052
}
70437053
}
70447054
}
@@ -7067,5 +7077,46 @@ const list<SPGScore>& SpaceGroupExplorer::GetScores() const
70677077
{
70687078
return mvSPG;
70697079
}
7080+
7081+
REAL SpaceGroupExplorer::GetP1IntegratedGoF()
7082+
{
7083+
if(mpDiff->GetCrystal().GetSpaceGroup().GetSpaceGroupNumber()==1)
7084+
{
7085+
mpDiff->GetPowderPatternIntegratedCalc();
7086+
mP1IntegratedProfileMin = mpDiff->GetParentPowderPattern().GetIntegratedProfileMin();
7087+
mP1IntegratedProfileMax = mpDiff->GetParentPowderPattern().GetIntegratedProfileMax();
7088+
cout<<"Updating mP1IntegratedProfileMin/Max:"<<endl
7089+
<<FormatVertVectorHKLFloats<REAL>(mP1IntegratedProfileMin, mP1IntegratedProfileMax,mP1IntegratedProfileMax)<<endl;
7090+
}
7091+
else if (mP1IntegratedProfileMin.size()==0) return 0;
7092+
7093+
//cout<<FormatVertVectorHKLFloats<REAL>(mpDiff->GetH(), mpDiff->GetK(), mpDiff->GetL(), mpDiff->GetFhklCalcSq());
7094+
REAL integratedChi2=0.;
7095+
REAL integratedChi2LikeNorm=0.;
7096+
const REAL * RESTRICT p1, * RESTRICT p2, * RESTRICT p3;
7097+
CrystVector_REAL const* pcalc = &(mpDiff->GetParentPowderPattern().GetPowderPatternCalc());
7098+
CrystVector_REAL const* pobs = &(mpDiff->GetParentPowderPattern().GetPowderPatternObs());
7099+
CrystVector_REAL const* psigma = &(mpDiff->GetParentPowderPattern().GetPowderPatternObsSigma());
7100+
const unsigned int jmax = mpDiff->GetParentPowderPattern().GetNbPointUsed();
7101+
REAL chi2=0;
7102+
unsigned int nbpoint = 0;
7103+
for(unsigned long i=0;i<mP1IntegratedProfileMin.size();i++)
7104+
{
7105+
if(mP1IntegratedProfileMin(i) > jmax) break;
7106+
if(mP1IntegratedProfileMax(i) < 0) continue;
7107+
REAL v=0, c=0, o=0;
7108+
for(unsigned long j=mP1IntegratedProfileMin(i); j<=mP1IntegratedProfileMax(i); j++)
7109+
{
7110+
if(j<0) continue;
7111+
if(j >= jmax) break;
7112+
nbpoint++;
7113+
c += (*pcalc)(j); // calc
7114+
o += (*pobs)(j); // obs
7115+
v += (*psigma)(j)*(*psigma)(j); // variance
7116+
}
7117+
if(v>0) chi2 += (c-o)*(c-o)/v;
7118+
}
7119+
return chi2 / nbpoint;
7120+
}
70707121

70717122
}//namespace ObjCryst

ObjCryst/ObjCryst/PowderPattern.h

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1169,15 +1169,22 @@ CrystVector_REAL PowderProfileLorentz(const CrystVector_REAL theta,
11691169
*/
11701170
struct SPGScore
11711171
{
1172-
SPGScore(const string &s, const REAL r, const REAL g, const unsigned int nbextinct, const REAL ngof=0);
1172+
SPGScore(const string &s, const REAL r, const REAL g, const unsigned int nbextinct, const REAL ngof=0, const unsigned int nbrefl=0);
11731173
string hm;
11741174
/// Rw factor, from PowderPattern::GetRw()
11751175
REAL rw;
11761176
/// Goodness-of-fit, from PowderPattern::GetChi2() normalised by
11771177
REAL gof;
1178-
/// Normalised goodness-of-fit = gof * (nb_refl) / (nb_refl in P1)
1178+
/// Normalised & integrated goodness-of-fit = iGoF * (nb_refl) / (nb_refl in P1),
1179+
/// where iGoF is the integrated goodness-of-fit, computed using the integration
1180+
/// intervals determined for the P1 spacegroup. This is only computed
1181+
/// if the P1 spacegroup was tested first.
11791182
REAL ngof;
1183+
/// Number of extinct reflections for 0<=H<=4, 0<=K<=4, 0<=L<=6, which
1184+
/// can be used as unique fingerprint for the spacegroup systematic extinctions.
11801185
unsigned int nbextinct446;
1186+
/// Number of reflections used for the fit.
1187+
unsigned int nbreflused;
11811188
};
11821189

11831190
bool compareSPGScore(const SPGScore &s1, const SPGScore &s2);
@@ -1221,6 +1228,8 @@ class SpaceGroupExplorer
12211228
SPGScore Run(const cctbx::sgtbx::space_group &spg, const bool fitprofile=false,
12221229
const bool verbose=false, const bool restore_orig=false, const bool update_display=true);
12231230
/** Run test on all spacegroups compatible with the unit cell
1231+
* Note that all scores's ngof values will be multiplied by nb_refl/nb_refl_P1 to
1232+
* have a better indicator of the quality taking into account the number of reflections used.
12241233
*
12251234
* \param fitprofile_all: if true, will perform a full profile fitting instead of just Le Bail
12261235
* extraction for all spacegroups. Much slower. By default, the profile fitting is only
@@ -1236,8 +1245,15 @@ class SpaceGroupExplorer
12361245
/// Get the list of all scores obatined after using RunAll()
12371246
const list<SPGScore>& GetScores() const;
12381247
private:
1248+
/// Compute the integrated goodness-of-fit using P1 integration intervals. If this is called
1249+
/// and the spacegroup is P1, this initialises the P1 intervals as well. If the intervals
1250+
/// have not been initialised and the spaceroup is not P1, zero is returned.
1251+
REAL GetP1IntegratedGoF();
12391252
/// PwderPatternDiffraction for which we explore the spacegroups
12401253
PowderPatternDiffraction *mpDiff;
1254+
/// Min and max of intervals for integration domains, for the P1 specegroup. This is
1255+
/// used to compute a normalised integrated goodness of fit using the same intervals
1256+
CrystVector_REAL mP1IntegratedProfileMin,mP1IntegratedProfileMax;
12411257
/// List of scores for the explore spacegroups
12421258
list<SPGScore> mvSPG;
12431259
/// Map extinction fingerprint

ObjCryst/ObjCryst/UnitCell.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,7 @@ void UnitCell::Init(const REAL a, const REAL b, const REAL c, const REAL alpha,
350350
mCellDim(3)=alpha;
351351
mCellDim(4)=beta;
352352
mCellDim(5)=gamma;
353+
mClockLatticePar.Click();
353354

354355
mClockMetricMatrix.Reset();
355356
mClockLatticeParUpdate.Reset();

0 commit comments

Comments
 (0)