24 #include "ObjCryst/ObjCryst/Indexing.h"
25 #include "ObjCryst/Quirks/VFNDebug.h"
26 #include "ObjCryst/Quirks/VFNStreamFormat.h"
27 #include "ObjCryst/Quirks/Chronometer.h"
32 #define M_PI 3.14159265358979323846264338327950288
36 #define DEG2RAD (M_PI/180.)
39 #define RAD2DEG (180./M_PI)
46 const CrystalSystem system,
const CrystalCentering centering,
const float kappa)
48 const float q1=dmin*dmin*dmin-dmax*dmax*dmax;
49 const float q2=dmin*dmin -dmax*dmax;
54 return nbrefl/(C0*kappa*q1);
58 if(centering==LATTICE_P) D0=0.862;
59 if(centering==LATTICE_I) D0=0.475;
60 if(centering==LATTICE_F) D0=0.354;
61 return pow(nbrefl/(D0*kappa*q2),(
float)1.5);
64 if(system==MONOCLINIC) {C0=1.047;D0=0.786*.85;}
65 if(system==ORTHOROMBIC){C0=0.524;D0=1.36 *.85;}
66 if(system==HEXAGONAL) {C0=0.150;D0=1.04 *.85;}
67 if(system==RHOMBOEDRAL){C0=0.230;D0=1.04 *.85;}
68 if(system==TETRAGONAL) {C0=0.214;D0=1.25 *.85;}
69 if((centering==LATTICE_I)||(centering==LATTICE_A)||(centering==LATTICE_B)||(centering==LATTICE_C)) {C0/=2;D0/=2;}
70 if(centering==LATTICE_F){C0/=4;D0/=4;}
71 const float alpha=D0*q2/(3*C0*q1), beta=nbrefl/(2*kappa*C0*q1);
72 const float eta=beta-alpha*alpha*alpha,gamma=sqrt(beta*beta-2*beta*alpha*alpha*alpha);
73 const float v=pow(pow(eta+gamma,(
float)(1/3.))+pow((eta-gamma),(
float)(1/3.))-alpha,(
float)3);
80 RecUnitCell::RecUnitCell(
const float zero,
const float p0,
const float p1,
const float p2,
81 const float p3,
const float p4,
const float p5,
CrystalSystem lattice,
82 const CrystalCentering cent):
83 mlattice(lattice),mCentering(cent)
99 void RecUnitCell::operator=(
const RecUnitCell &rhs)
101 for(
unsigned int i=0;i<7;++i)
par[i]=rhs.par[i];
102 mlattice=rhs.mlattice;
103 mCentering=rhs.mCentering;
106 float RecUnitCell::hkl2d(
const float h,
const float k,
const float l,REAL *derivpar,
const unsigned int derivhkl)
const
108 if((derivpar==NULL)&&(derivhkl==0))
134 return par[0]+
par[1]*
par[1]*(h*h + k*k + l*l + 2*
par[2]*(h*k + k*l + h*l));
144 return par[0]+
par[1]*
par[1]*(h*h+k*k+l*l);
170 return par[1]*
par[1]*(2*h + k);
175 return par[1]*
par[1]*(2*h + 2*
par[2]*(k + l));
211 return par[1]*
par[1]*(2*k + h);
216 return par[1]*
par[1]*(2*k + l*l + 2*
par[2]*(h + l));
257 return par[1]*
par[1]*(2*l + 2*
par[2]*(k + h));
273 if(derivpar==&
par[0])
return 1.0;
274 if(derivpar==(
par+1))
285 return 2*
par[1]*h*h + 2*
par[3]*
par[4]*h*l;
295 return 2*
par[1]*(h*h + k*k + h*k);
300 return 2*
par[1]*(h*h + k*k + l*l + 2*
par[2]*(h*k + k*l + h*l));
305 return 2*
par[1]*(h*h + k*k);
310 return 2*
par[1]*(h*h+k*k+l*l);
315 if(derivpar==(
par+2))
336 return 2*
par[2]*l*l ;
341 return par[1]*
par[1]*(h*h + k*k + l*l + 2*(h*k + k*l + h*l));
356 if(derivpar==(
par+3))
367 return 2*
par[3]*l*l + 2*
par[1]*
par[4]*h*l;
397 if(derivpar==(
par+4))
408 return 2*
par[1]*
par[3]*h*l;
418 if(derivpar==(
par+5))
434 if(derivpar==(
par+6))
455 const RecUnitCell &delta,
float & dmin,
float &dmax)
const
457 const float p0m=
par[0]-delta.
par[0] , p0p=
par[0]+delta.
par[0],
468 float p4mm,p5mm,p6mm,p4pp,p5pp,p6pp;
469 if((h*k)>0){p4mm=p4m;p4pp=p4p;}
else{p4mm=p4p;p4pp=p4m;}
470 if((k*l)>0){p5mm=p5m;p5pp=p5p;}
else{p5mm=p5p;p5pp=p5m;}
471 if((h*l)>0){p6mm=p6m;p6pp=p6p;}
else{p6mm=p6p;p6pp=p6m;}
472 dmin=p0m+p1m*h*h+p2m*k*k+p3m*l*l+p4mm*h*k+p5mm*k*l+p6mm*h*l;
473 dmax=p0p+p1p*h*h+p2p*k*k+p3p*l*l+p4pp*h*k+p5pp*k*l+p6pp*h*l;
487 dmin = p0m + p1m*p1m*h*h + p2m*p2m*k*k + p3m*p3m*l*l + 2*p1m*p3m*p4m*h*l;
488 dmax = p0p + p1p*p1p*h*h + p2p*p2p*k*k + p3p*p3p*l*l + 2*p1p*p3p*p4p*h*l;
493 const bool b1=(h*(
par[1]*h+
par[3]*
par[4]*l))>0;
494 const bool b3=(l*(
par[3]*l+
par[1]*
par[4]*h))>0;
497 dmin = p0m + p1m*p1m*h*h + p2m*p2m*k*k + p3m*p3m*l*l + 2*p1m*p3m*p4p*h*l;
498 dmax = p0p + p1p*p1p*h*h + p2p*p2p*k*k + p3p*p3p*l*l + 2*p1p*p3p*p4m*h*l;
503 dmin = p0m + p1m*p1m*h*h + p2m*p2m*k*k + p3p*p3p*l*l + 2*p1m*p3p*p4p*h*l;
504 dmax = p0p + p1p*p1p*h*h + p2p*p2p*k*k + p3m*p3m*l*l + 2*p1p*p3m*p4m*h*l;
509 dmin = p0m + p1p*p1p*h*h + p2m*p2m*k*k + p3m*p3m*l*l + 2*p1p*p3m*p4p*h*l;
510 dmax = p0p + p1m*p1m*h*h + p2p*p2p*k*k + p3p*p3p*l*l + 2*p1m*p3p*p4m*h*l;
515 dmin = p0m + p1p*p1p*h*h + p2m*p2m*k*k + p3p*p3p*l*l + 2*p1p*p3p*p4p*h*l;
516 dmax = p0p + p1m*p1m*h*h + p2p*p2p*k*k + p3m*p3m*l*l + 2*p1m*p3m*p4m*h*l;
523 dmin= p0m + p1m*p1m*h*h + p2m*p2m*k*k + p3m*p3m*l*l;
524 dmax= p0p + p1p*p1p*h*h + p2p*p2p*k*k + p3p*p3p*l*l;
529 dmin=p0m+p1m*p1m*(h*h + k*k + h*k)+ p2m*p2m*l*l ;
530 dmax=p0p+p1p*p1p*(h*h + k*k + h*k)+ p2p*p2p*l*l ;
535 if((h*k + k*l + h*l)>=0)
537 dmin= p0m+p1m*p1m*(h*h + k*k + l*l + 2*p2m*(h*k + k*l + h*l));
538 dmax= p0p+p1p*p1p*(h*h + k*k + l*l + 2*p2p*(h*k + k*l + h*l));
542 dmin= p0m+p1m*p1m*(h*h + k*k + l*l + 2*p2p*(h*k + k*l + h*l));
543 dmax= p0p+p1p*p1p*(h*h + k*k + l*l + 2*p2m*(h*k + k*l + h*l));
549 dmin= p0m + p1m*p1m*(h*h + k*k) + p2m*p2m*l*l;
550 dmax= p0p + p1p*p1p*(h*h + k*k) + p2p*p2p*l*l;
555 dmin=p0m + p1m*p1m*(h*h+k*k+l*l);
556 dmax=p0p + p1p*p1p*(h*h+k*k+l*l);
565 float aa,bb,cc,calphaa,cbetaa,cgammaa,salphaa,sbetaa,sgammaa;
573 calphaa=
par[5]/(2*bb*cc);
574 cbetaa =
par[6]/(2*aa*cc);
575 cgammaa=
par[4]/(2*aa*bb);
576 salphaa=sqrt(abs(1-calphaa*calphaa));
577 sbetaa =sqrt(abs(1-cbetaa *cbetaa));
578 sgammaa=sqrt(abs(1-cgammaa*cgammaa));
590 sbetaa =sqrt(abs(1-cbetaa *cbetaa));
617 sgammaa=0.8660254037844386;
628 salphaa=sqrt(abs(1-calphaa *calphaa));
664 const float vv=sqrt(abs(1-calphaa*calphaa-cbetaa*cbetaa-cgammaa*cgammaa+2*calphaa*cbetaa*cgammaa));
666 const float a=salphaa/(aa*vv);
667 const float b=sbetaa /(bb*vv);
668 const float c=sgammaa/(cc*vv);
670 const float calpha=(cbetaa *cgammaa-calphaa)/(sbetaa *sgammaa);
671 const float cbeta =(calphaa*cgammaa-cbetaa )/(salphaa*sgammaa);
672 const float cgamma=(calphaa*cbetaa -cgammaa)/(salphaa*sbetaa );
674 const float alpha=acos( calpha );
675 const float beta =acos( cbeta );
676 const float gamma=acos( cgamma );
678 const float v=a*b*c*sqrt(1-calpha*calpha-cbeta*cbeta-cgamma*cgamma+2*calpha*cbeta*cgamma);
680 vector<float>
par(7);
691 PeakList::hkl0::hkl0(
const int h0,
const int k0,
const int l0):
696 PeakList::hkl::hkl(
const float d,
const float i,
const float ds,
const float is,
697 const int h0,
const int k0,
const int l0,
const float dc0):
698 dobs(d),dobssigma(ds),d2obs(d*d),d2obsmin((d-ds/2)*(d-ds/2)),d2obsmax((d+ds/2)*(d+ds/2)),iobs(i),iobssigma(is),
699 h(h0),k(k0),l(l0),isIndexed(false),isSpurious(false),stats(0),
700 d2calc(dc0),d2diff(0)
703 bool compareHKL_d(
const PeakList::hkl &d1,
const PeakList::hkl &d2)
705 return d1.dobs < d2.dobs;
714 PeakList::PeakList(
const PeakList &old)
719 void PeakList::operator=(
const PeakList &rhs)
721 VFN_DEBUG_ENTRY(
"PeakList::operator=(PeakList &old)",10);
723 VFN_DEBUG_EXIT(
"PeakList::operator=(PeakList &old)",10);
726 PeakList::~PeakList()
729 void PeakList::ImportDhklDSigmaIntensity(istream &is,
float defaultsigma)
739 if(sigma<=0) sigma=d*defaultsigma;
740 if(iobs<=0) iobs=1.0;
741 mvHKL.push_back(hkl(1/d,iobs,1/(d-sigma/2)-1/(d+sigma/2)));
742 cout<<__FILE__<<
":"<<__LINE__<<
" "<<
mvHKL.size()<<
":d="<<d<<
"+/-"<<sigma<<
", I="<<iobs<<
" 1/d="<<1/d<<endl;
746 cout<<
"Imported "<<
mvHKL.size()<<
" observed reflection positions."<<endl;
749 void PeakList::ImportDhklIntensity(istream &is)
757 mvHKL.push_back(hkl(1/d,iobs));
758 cout<<__FILE__<<
":"<<__LINE__<<
" "<<
mvHKL.size()<<
":d="<<d<<
", I="<<iobs<<
" 1/d="<<1/d<<endl;
762 cout<<
"Imported "<<
mvHKL.size()<<
" observed reflection positions."<<endl;
765 void PeakList::ImportDhkl(istream &is)
767 std::vector<std::pair<float,float> > v;
773 mvHKL.push_back(hkl(1/d));
774 cout<<__FILE__<<
":"<<__LINE__<<
" "<<
mvHKL.size()<<
":d="<<d<<
" 1/d="<<1/d<<endl;
778 cout<<
"Imported "<<v.size()<<
" observed reflection positions."<<endl;
782 template<
class T,
class U>
bool comparePairFirst(std::pair<T,U> &p1, std::pair<T,U> &p2)
784 return p1.first < p2.first;
787 void PeakList::Import2ThetaIntensity(istream &is,
const float wavelength)
789 std::list<std::pair<float,float> > v;
796 d=2*sin(d/2*DEG2RAD)/wavelength;
797 mvHKL.push_back(hkl(1/d,iobs));
798 cout<<__FILE__<<
":"<<__LINE__<<
" "<<
mvHKL.size()<<
":d="<<1/d<<
", I="<<iobs<<
" 1/d="<<d<<endl;
799 if((is.eof())||v.size()>=20)
break;
802 cout<<
"Imported "<<v.size()<<
" observed reflection positions."<<endl;
805 float alpha,
float beta,
float gamma,
806 bool deg,
unsigned int nb,
unsigned int nbspurious,
807 float sigma,
float percentMissing,
const bool verbose)
809 if(deg){alpha*=DEG2RAD;beta*=DEG2RAD;gamma*=DEG2RAD;}
810 const float v=sqrt(1-cos(alpha)*cos(alpha)-cos(beta)*cos(beta)-cos(gamma)*cos(gamma)
811 +2*cos(alpha)*cos(beta)*cos(gamma));
813 const float aa=sin(alpha)/a/v;
814 const float bb=sin(beta )/b/v;
815 const float cc=sin(gamma)/c/v;
817 const float alphaa=acos( (cos(beta )*cos(gamma)-cos(alpha))/sin(beta )/sin(gamma) );
818 const float betaa =acos( (cos(alpha)*cos(gamma)-cos(beta ))/sin(alpha)/sin(gamma) );
819 const float gammaa=acos( (cos(alpha)*cos(beta )-cos(gamma))/sin(alpha)/sin(beta ) );
821 RecUnitCell ruc(zero,aa*aa,bb*bb,cc*cc,2*aa*bb*cos(gammaa),2*bb*cc*cos(alphaa),2*aa*cc*cos(betaa),TRICLINIC,LATTICE_P);
822 std::list<float> vd2;
824 for(
int h=0;h<=20;h++)
825 for(
int k=-20;k<=20;k++)
827 if((h==0) && (k<0)) k=0;
828 for(
int l=-20;l<=20;l++)
830 if((h==0) && (k==0) && (l<=0)) l=1;
831 vd2.push_back(sqrt(ruc.
hkl2d(h,k,l)));
835 std::list<float>::iterator pos=vd2.begin();
836 if(percentMissing>0.90) percentMissing=0.90;
837 for(;pos!=vd2.end();++pos)
839 if((rand()/
float(RAND_MAX))<percentMissing) *pos=1e10;
843 const float dmin=*pos/2;
844 for(
unsigned int i=0;i<nb;++i)pos++;
845 const float dmax=*pos;
847 for(
unsigned int i=0;i<nbspurious;++i)
849 const unsigned int idx=1+i*nb/nbspurious+(rand()%nbspurious);
851 for(
unsigned int j=0;j<idx;++j) pos++;
852 *pos=dmin+rand()/float(RAND_MAX)*(dmax-dmin);
856 for(
unsigned int i=0;i<nb;++i)
859 const float ds=d*sigma;
860 float d1=d+ds*(rand()/float(RAND_MAX)*2-1);
868 sprintf(buf,
"a=%6.3f b=%6.3f c=%6.3f alpha=%6.2f beta=%6.2f gamma=%6.2f V=%8.2f",a,b,c,alpha*RAD2DEG,beta*RAD2DEG,gamma*RAD2DEG,v*a*b*c);
869 cout<<
"PeakList::Simulate():"<<buf<<endl;
875 void PeakList::ExportDhklDSigmaIntensity(std::ostream &os)
const
878 for(vector<PeakList::hkl>::const_iterator pos=
mvHKL.begin();pos!=
mvHKL.end();++pos)
880 const float sigma=1/(pos->dobs-pos->dobssigma/2)-1/(pos->dobs+pos->dobssigma/2);
881 sprintf(buf,
"%6.3f %6.3f %f",1/pos->dobs,sigma,pos->iobs);
886 void PeakList::AddPeak(
const float d,
const float iobs,
const float dobssigma,
const float iobssigma,
887 const int h,
const int k,
const int l,
const float d2calc)
892 for(vector<hkl>::const_iterator pos=
mvHKL.begin();pos!=
mvHKL.end();++pos)
895 if(s>0)
mvHKL.push_back(
hkl(d,iobs,s,iobssigma,h,k,l,d2calc));
896 else mvHKL.push_back(
hkl(d,iobs,1e-4,iobssigma,h,k,l,d2calc));
898 else mvHKL.push_back(
hkl(d,iobs,dobssigma,iobssigma,h,k,l,d2calc));
903 void PeakList::RemovePeak(
unsigned int idx)
909 void PeakList::Print(std::ostream &os)
const
913 os<<
"PeakList, with "<<
mvHKL.size()<<
" peaks"<<endl;
914 for(vector<PeakList::hkl>::const_iterator pos=
mvHKL.begin();pos!=
mvHKL.end();++pos)
916 const float sigma=1/(pos->dobs-pos->dobssigma/2)-1/(pos->dobs+pos->dobssigma/2);
918 sprintf(buf,
"#%3d d=%6.3f+/-%7.4f dcalc=%6.3f, diff=%7.4f, iobs=%6.3f HKL=%2d %2d %2d Spurious=%1d stats=%6lu",
919 i++,1/pos->dobs,sigma,
920 1/sqrt(abs(pos->d2calc)),1/sqrt(abs(pos->d2calc))-1/pos->dobs,
921 pos->iobs,pos->h,pos->k,pos->l,pos->isSpurious,pos->stats);
923 sprintf(buf,
"#%3d d=%6.3f+/-%6.3f iobs=%6.3f UNINDEXED Spurious=%1d stats=%6lu",
924 i++,1/pos->dobs,1/(pos->dobs-pos->dobssigma/2)-1/(pos->dobs+pos->dobssigma/2),
925 pos->iobs,pos->isSpurious,pos->stats);
937 const bool verbose,
const bool storehkl,
const bool storePredictedHKL)
939 const bool autozero=
false;
940 vector<PeakList::hkl>::const_iterator pos,first,last;
943 if(storehkl) pos->isIndexed=
false;
950 unsigned long nbCalc=0;
952 float predict_coeff=1;
953 if(storePredictedHKL)predict_coeff=2;
954 const float dmax=dhkl.
mvHKL[nb-1].d2obs*predict_coeff*1.05;
956 switch(rpar.mlattice)
984 switch(rpar.mCentering)
986 case LATTICE_P:stepk=1;stepl=1;
break;
987 case LATTICE_I:stepk=1;stepl=2;
break;
988 case LATTICE_A:stepk=1;stepl=2;
break;
989 case LATTICE_B:stepk=1;stepl=2;
break;
990 case LATTICE_C:stepk=2;stepl=1;
break;
991 case LATTICE_F:stepk=2;stepl=2;
break;
996 unsigned long nbCalcH,nbCalcK;
1000 for(
int sk=sk0;sk<=1;sk+=2)
1003 if(stepk==2) k=(h%2);
1008 for(
int sl=sl0;sl<=1;sl+=2)
1019 if(rpar.mlattice==MONOCLINIC) sl=1;
1020 if((sk<0)||(sl<0)) l=1;
1031 if(rpar.mCentering==LATTICE_I) l+=(h+k+l)%2;
1032 if(rpar.mCentering==LATTICE_A) l+=(k+l)%2;
1033 if( (rpar.mCentering==LATTICE_B)
1034 ||(rpar.mCentering==LATTICE_F)) l+=(h+l)%2;
1038 const float d2=rpar.
hkl2d(h,sk*k,sl*l);
1043 if((sl*rpar.
hkl2d(h,sk*k,sl*l,NULL,3))>=0)
break;
1046 nbCalc++;nbCalcK++;nbCalcH++;
1047 if(storePredictedHKL)
1052 for(pos=first;pos!=last;++pos)
1054 const float tmp=d2-pos->d2obs;
1058 if(fabs(tmp)<fabs(pos->d2diff))
1066 pos->isIndexed=
true;
1082 if((sk*rpar.
hkl2d(h,sk*k,0,NULL,2))>=0)
break;
1086 if(nbCalcH==0)
break;
1088 float epsilon=0.0,zero=0.0;
1096 epsilon +=fabs(pos->d2diff-zero);
1100 list<pair<float,unsigned int> > vdiff_idx;
1103 vdiff_idx.push_back(make_pair(fabs(pos->d2diff),i++));
1104 vdiff_idx.sort(comparePairFirst<float,unsigned int>);
1106 for(list<pair<float,unsigned int> >::reverse_iterator rpos=vdiff_idx.rbegin();rpos!=vdiff_idx.rend();++rpos)
1108 epsilon -= fabs(rpos->first-zero);
1109 if(storehkl) dhkl.
GetPeakList()[rpos->second].isIndexed=
false;
1111 if(++i==nbSpurious)
break;
1120 epstmp+=fabs(pos->d2diff-zero);
1123 cout<<
"epsilon="<<epstmp<<
", dmax="<<dmax<<
" ,nb="<<nb<<
" ,nbcalc="<<nbCalc<<endl;
1137 if(nbCalc==0)
return 0;
1138 const float score=(dmax/predict_coeff)*nb/(2*epsilon*nbCalc);
1142 cout<<
"Final score:"<<score<<
", nbCalc="<<nbCalc<<
" ,<epsilon>="<<epsilon<<
" nb="<<nb<<
" Qn="<<sqrt(dmax)<<endl;
1149 CellExplorer::CellExplorer(
const PeakList &dhkl,
const CrystalSystem lattice,
const unsigned int nbSpurious):
1150 mnpar(3),mpPeakList(&dhkl),
1151 mLengthMin(4),mLengthMax(25),
1152 mAngleMin(M_PI),mAngleMax(2*M_PI/3),
1153 mVolumeMin(0),mVolumeMax(1600),
1154 mZeroShiftMin(0),mZeroShiftMax(0),
1155 mlattice(lattice),mCentering(LATTICE_P),mNbSpurious(nbSpurious),
1156 mObs(0),mCalc(0),mWeight(0),mDeriv(0),mBestScore(0.0),
1157 mMinScoreReport(10),mMaxDicVolDepth(6),mDicVolDepthReport(6),
1163 void CellExplorer::Evolution(
unsigned int ng,
const bool randomize,
const float f,
const float cr,
unsigned int np)
1166 const bool autozero=
true;
1169 vector<pair<RecUnitCell,float> > vRUC(np);
1170 vector<pair<RecUnitCell,float> > vTrial(np);
1171 float bestScore=-1e20;
1172 vector<pair<RecUnitCell,float> >::iterator bestpos=vRUC.begin();
1174 const clock_t mTime0=clock();
1178 for(
unsigned int i=0;i<vRUC.size();++i)
1180 vRUC[i].first.mlattice=mlattice;
1181 vTrial[i].first.mlattice=mlattice;
1182 for(
unsigned int k=0;k<mnpar;++k) vRUC[i].first.par[k]=mMin[k]+mAmp[k]*rand()/(float)RAND_MAX;
1183 vRUC[i].second=
Score(*mpPeakList,vRUC[i].first,mNbSpurious);
1187 for(
unsigned long i=ng;i>0;--i)
1189 for(
unsigned j=0;j<np;j++)
1193 unsigned int r1=j,r2=j,r3=j;
1194 while(r1==j)r1=rand()%np;
1195 while((r2==j)||(r1==r2))r2=rand()%np;
1196 while((r3==j)||(r3==r1)||(r3==r2))r3=rand()%np;
1197 unsigned int ncr=1+(int)(cr*mnpar*rand()/(float)RAND_MAX);
1198 unsigned int ncr0=rand()%mnpar;
1199 RecUnitCell *t0=&(vTrial[j].first);
1200 RecUnitCell *c0=&(vRUC[j].first);
1201 RecUnitCell *c1=&(vRUC[r1].first);
1202 RecUnitCell *c2=&(vRUC[r2].first);
1203 RecUnitCell *c3=&(vRUC[r3].first);
1204 for(
unsigned int k=0;k<mnpar;++k)t0->par[k] = c0->par[k];
1205 for(
unsigned int k=0;k<ncr;++k)
1207 const unsigned l=(ncr0+k)%mnpar;
1208 const float v1=c1->par[l]-mMin[l];
1209 const float v2=c2->par[l]-mMin[l];
1210 const float v3=c3->par[l]-mMin[l];
1211 t0->par[l]=mMin[l]+fmod(v1+f*(v2-v3)+3*mAmp[l],mAmp[l]);
1216 unsigned int r1=j,r2=j,r3=j;
1217 while(r1==j)r1=rand()%np;
1218 while((r2==j)||(r1==r2))r2=rand()%np;
1219 while((r3==j)||(r3==r1)||(r3==r2))r3=rand()%np;
1220 unsigned int ncr=1+(int)(cr*(mnpar-1)*rand()/(float)RAND_MAX);
1221 unsigned int ncr0=rand()%mnpar;
1222 RecUnitCell *t0=&(vTrial[j].first);
1223 RecUnitCell *c0=&(vRUC[j].first);
1225 RecUnitCell *c2=&(vRUC[r2].first);
1226 RecUnitCell *c3=&(vRUC[r3].first);
1227 RecUnitCell *best=&(bestpos->first);
1228 for(
unsigned int k=0;k<6;++k)t0->par[k] = c0->par[k];
1229 for(
unsigned int k=0;k<ncr;++k)
1231 const unsigned l=(ncr0+k)%mnpar;
1232 const float v0=c0->par[l]-mMin[l];
1234 const float v2=c2->par[l]-mMin[l];
1235 const float v3=c3->par[l]-mMin[l];
1236 const float vb=best->par[l]-mMin[l];
1237 t0->par[l]=mMin[l]+fmod(vb+f*(vb-v0)+f*(v2-v3)+5*mAmp[l],mAmp[l]);
1242 const float amp=.05/(1+i*.01);
1243 RecUnitCell *t0=&(vTrial[j].first);
1244 for(
unsigned int k=0;k<6;++k)
1247 t0->par[k] = mMin[k]+ fmod((
float)(amp*mAmp[k]*(rand()/(
float)RAND_MAX-0.5)+5*mAmp[k]),(
float)mAmp[k]);
1252 vector<pair<RecUnitCell,float> >::iterator posTrial,pos;
1253 posTrial=vTrial.begin();
1255 for(;posTrial!=vTrial.end();)
1258 if(autozero) posTrial->first.par[0]=0;
1266 float v0=posTrial->first.par[1]*posTrial->first.par[2]*posTrial->first.par[3];
1267 while(v0<1/mVolumeMax)
1269 const unsigned int i=rand()%3+1;
1270 posTrial->first.par[i]*=1/(mVolumeMax*v0)+1e-4;
1271 if(posTrial->first.par[i]>(mMin[i]+mAmp[i])) posTrial->first.par[i]=mMin[i]+mAmp[i];
1272 v0=posTrial->first.par[1]*posTrial->first.par[2]*posTrial->first.par[3];
1288 const float score=
Score(*mpPeakList,posTrial->first,mNbSpurious);
1289 if(score > pos->second)
1292 const REAL *p0=posTrial->first.par;
1293 REAL *p1=pos->first.par;
1294 for(
unsigned int k=0;k<mnpar;++k) *p1++ = *p0++;
1317 vector<float> par=bestpos->first.DirectUnitCell();
1318 cout<<
"Generation #"<<ng-i<<
", Best score="<<bestScore
1319 <<
" Trial: a="<<par[0]<<
", b="<<par[1]<<
", c="<<par[2]<<
", alpha="
1320 <<par[3]*RAD2DEG<<
", beta="<<par[4]*RAD2DEG<<
", gamma="<<par[5]*RAD2DEG<<
", V="<<par[6]
1321 <<
" "<<(ng-i)*np/((clock()-mTime0)/(float)CLOCKS_PER_SEC)<<
" trials/s"
1326 for(vector<pair<RecUnitCell,float> >::iterator pos=vRUC.begin();pos!=vRUC.end();++pos)
1328 if(pos==bestpos)
continue;
1329 for(
unsigned int k=0;k<mnpar;++k) pos->first.par[k]=mMin[k]+mAmp[k]*rand()/(float)RAND_MAX;
1347 mRecUnitCell=bestpos->first;
1348 float score=
Score(*mpPeakList,mRecUnitCell,mNbSpurious,
false,
true);
1349 vector<float> par=mRecUnitCell.DirectUnitCell();
1350 cout<<__FILE__<<
":"<<__LINE__<<
" Best-DE : a="<<par[0]<<
", b="<<par[1]<<
", c="<<par[2]<<
", alpha="
1351 <<par[3]*RAD2DEG<<
", beta="<<par[4]*RAD2DEG<<
", gamma="<<par[5]*RAD2DEG<<
", V="<<par[6]
1352 <<
", score="<<bestpos->second
1353 <<
" ("<<ng*np/((clock()-mTime0)/(
float)CLOCKS_PER_SEC)<<
" trials/s)"<<endl;
1354 if(score>mMinScoreReport*.5)
1357 mRecUnitCell=bestpos->first;
1358 this->LSQRefine(10,
true,
true);
1359 par=mRecUnitCell.DirectUnitCell();
1360 score=
Score(*mpPeakList,mRecUnitCell,mNbSpurious,
false,
true);
1361 cout<<__FILE__<<
":"<<__LINE__<<
" Best-LSQ: a="<<par[0]<<
", b="<<par[1]<<
", c="<<par[2]<<
", alpha="
1362 <<par[3]*RAD2DEG<<
", beta="<<par[4]*RAD2DEG<<
", gamma="<<par[5]*RAD2DEG<<
", V="<<par[6]
1363 <<
", score="<<score<<endl;
1364 if((score>mMinScoreReport)&&(score>(mBestScore/3)))
1366 if(score>mBestScore) mBestScore=score;
1367 mvSolution.push_back(make_pair(mRecUnitCell,score));
1368 this->ReduceSolutions(
true);
1373 void CellExplorer::SetLengthMinMax(
const float min,
const float max)
1378 void CellExplorer::SetAngleMinMax(
const float min,
const float max)
1383 void CellExplorer::SetVolumeMinMax(
const float min,
const float max)
1388 void CellExplorer::SetNbSpurious(
const unsigned int nb)
1392 void CellExplorer::SetMinMaxZeroShift(
const float min,
const float max)
1398 void CellExplorer::SetCrystalSystem(
const CrystalSystem system)
1403 void CellExplorer::SetCrystalCentering(
const CrystalCentering cent)
1408 void CellExplorer::SetD2Error(
const float err){mD2Error=err;}
1410 const string& CellExplorer::GetClassName()
const
1412 const static string className=
"CellExplorer";
1415 const string& CellExplorer::GetName()
const
1417 const static string name=
"Some CellExplorer Object";
1420 void CellExplorer::Print()
const
1422 this->RefinableObj::Print();
1424 unsigned int CellExplorer::GetNbLSQFunction()
const
1427 const CrystVector_REAL& CellExplorer::GetLSQCalc(
const unsigned int)
const
1429 VFN_DEBUG_ENTRY(
"CellExplorer::GetLSQCalc()",2)
1431 for(vector<PeakList::hkl>::const_iterator pos=mpPeakList->GetPeakList().begin();pos!=mpPeakList->GetPeakList().end();++pos)
1434 mCalc(j++)=mRecUnitCell.hkl2d(pos->h,pos->k,pos->l);
1437 VFN_DEBUG_EXIT(
"CellExplorer::GetLSQCalc()",2)
1440 const CrystVector_REAL& CellExplorer::GetLSQObs(
const unsigned int)
const
1442 VFN_DEBUG_MESSAGE(
"CellExplorer::GetLSQObs()",2)
1445 const CrystVector_REAL& CellExplorer::GetLSQWeight(
const unsigned int)
const
1447 VFN_DEBUG_MESSAGE(
"CellExplorer::GetLSQWeight()",2)
1451 const CrystVector_REAL& CellExplorer::GetLSQDeriv(
const unsigned int,
RefinablePar &refpar)
1453 VFN_DEBUG_ENTRY(
"CellExplorer::GetLSQDeriv()",2)
1455 if(refpar.
GetName()==
"Reciprocal unit cell par #0") par=mRecUnitCell.par+1;
1457 if(refpar.
GetName()==
"Reciprocal unit cell par #1") par=mRecUnitCell.par+2;
1459 if(refpar.
GetName()==
"Reciprocal unit cell par #2") par=mRecUnitCell.par+3;
1461 if(refpar.
GetName()==
"Reciprocal unit cell par #3") par=mRecUnitCell.par+4;
1463 if(refpar.
GetName()==
"Reciprocal unit cell par #4") par=mRecUnitCell.par+5;
1465 if(refpar.
GetName()==
"Reciprocal unit cell par #5") par=mRecUnitCell.par+6;
1467 if(refpar.
GetName()==
"Zero") par=mRecUnitCell.par+0;
1468 else cout<<__FILE__<<
":"<<__LINE__<<
":Parameter not found:"<<refpar.
GetName()<<endl;
1470 for(vector<PeakList::hkl>::const_iterator pos=mpPeakList->GetPeakList().begin();pos!=mpPeakList->GetPeakList().end();++pos)
1472 VFN_DEBUG_MESSAGE(
"CellExplorer::GetLSQDeriv():"<<j<<
"/"<<mpPeakList->GetPeakList().size(),2)
1473 VFN_DEBUG_MESSAGE(
"CellExplorer::GetLSQDeriv():"<<pos->h<<
","<<pos->k<<
","<<pos->l,2)
1475 mDeriv(j++)=mRecUnitCell.hkl2d(pos->h,pos->k,pos->l,par);
1477 VFN_DEBUG_EXIT(
"CellExplorer::GetLSQDeriv()",2)
1481 void CellExplorer::BeginOptimization(
const bool allowApproximations,
const bool enableRestraints)
1483 VFN_DEBUG_ENTRY(
"CellExplorer::BeginOptimization()",5)
1484 Score(*mpPeakList,mRecUnitCell,mNbSpurious,
false,
true,
false);
1485 const unsigned int nb=mpPeakList->GetPeakList().size();
1486 mCalc.resize(nb-mNbSpurious);
1487 mObs.resize(nb-mNbSpurious);
1488 mWeight.resize(nb-mNbSpurious);
1489 mDeriv.resize(nb-mNbSpurious);
1492 for(vector<PeakList::hkl>::const_iterator pos=mpPeakList->GetPeakList().begin();pos!=mpPeakList->GetPeakList().end();++pos)
1493 if(thres<pos->iobs) thres=pos->iobs;
1498 for(vector<PeakList::hkl>::const_iterator pos=mpPeakList->GetPeakList().begin();pos!=mpPeakList->GetPeakList().end();++pos)
1503 if(mObs(j)>thres) mWeight(j)=1;
1504 else mWeight(j)=mObs(j)/thres;
1524 this->RefinableObj::BeginOptimization(allowApproximations,enableRestraints);
1525 VFN_DEBUG_EXIT(
"CellExplorer::BeginOptimization()",5)
1528 void CellExplorer::LSQRefine(
int nbCycle,
bool useLevenbergMarquardt,
const bool silent)
1530 if(mNbLSQExcept>100)
1532 if(!silent) cout<<
"CellExplorer::LSQRefine(): LSQ was disabled, too many (>100) exceptions caught. Weird unit cell parameters ?";
1535 VFN_DEBUG_ENTRY(
"CellExplorer::LSQRefine()",5)
1536 mLSQObj.SetRefinedObj(*this);
1537 mLSQObj.PrepareRefParList(true);
1540 try {mLSQObj.Refine(nbCycle,useLevenbergMarquardt,silent);}
1541 catch(
const ObjCrystException &except)
1543 if(++mNbLSQExcept>100) cout<<
"WARNING CellExplorer::LSQRefine(): LSQ was disabled, too many (>100) exceptions caught. Weird unit cell parameters ?"<<endl ;
1545 if(!silent) mpPeakList->Print(cout);
1546 VFN_DEBUG_EXIT(
"CellExplorer::LSQRefine()",5)
1563 const unsigned int nbUnindexed=0,
const bool verbose=
false,
unsigned int useStoredHKL=0,
1564 const unsigned int maxNbMissingBelow5=0)
1567 int nbIndexed=nb-nbUnindexed;
1569 if(maxNbMissingBelow5>0) d5=dhkl.
GetPeakList()[4].d2obs;
1571 unsigned int nbMissingBelow5=0;
1573 vector<PeakList::hkl>::const_iterator pos,first,last,end;
1576 unsigned int nbUnIx = 0;
1579 pos->isIndexed=
false;
1580 for(list<PeakList::hkl0>::const_iterator phkl0=pos->vDicVolHKL.begin();phkl0!=pos->vDicVolHKL.end();++phkl0)
1583 par.
hkl2d_delta(phkl0->h,phkl0->k,phkl0->l,dpar,d0,d1);
1584 if((pos->d2obsmax>=d0) && (d1>=pos->d2obsmin))
1586 pos->d2calc=(d0+d1)/2;
1587 pos->isIndexed=
true;
1588 if(--nbIndexed==0)
return true;
1592 if(!(pos->isIndexed))
if(++nbUnIx>nbUnindexed)
return false;
1596 const bool storePossibleHKL=(useStoredHKL==2);
1598 if(storePossibleHKL)
1601 pos->isIndexed=
false;
1602 pos->vDicVolHKL.clear();
1613 switch(par.mlattice)
1643 switch(par.mCentering)
1645 case LATTICE_P:stepk=1;stepl=1;
break;
1646 case LATTICE_I:stepk=1;stepl=2;
break;
1647 case LATTICE_A:stepk=1;stepl=2;
break;
1648 case LATTICE_B:stepk=1;stepl=2;
break;
1649 case LATTICE_C:stepk=2;stepl=1;
break;
1650 case LATTICE_F:stepk=2;stepl=2;
break;
1660 unsigned long nbCalcH,nbCalcK;
1663 if(verbose) cout<<
"H="<<h<<endl;
1665 for(
int sk=sk0;sk<=1;sk+=2)
1668 if(stepk==2) k=(h%2);
1672 if(verbose) cout<<
"K="<<k*sk<<endl;
1674 for(
int sl=sl0;sl<=1;sl+=2)
1686 if(par.mlattice==MONOCLINIC) sl=1;
1687 if((sk<0)||(sl<0)) l0=1;
1698 if(par.mCentering==LATTICE_I) l0+=(h+k+l0)%2;
1699 if(par.mCentering==LATTICE_A) l0+=(k+l0)%2;
1700 if( (par.mCentering==LATTICE_B)
1701 ||(par.mCentering==LATTICE_F)) l0+=(h+l0)%2;
1703 if(verbose) cout<<
"SL="<<sl<<
", L0="<<l0<<
", STEPL="<<stepl<<
", Centering="<<par.mCentering<<endl;
1706 if(verbose) cout<<
"L="<<l<<
","<<sl<<endl;
1709 if(d0<dmax) {nbCalcH++;nbCalcK++;}
1710 if((d1<dmin)&&(maxNbMissingBelow5==0))
continue;
1713 if(par.mlattice==TRICLINIC)
1716 if(verbose) cout<<
"L?="<< par.
hkl2d(h,sk*k,sl*l,NULL,3)*sl <<
", dmax="<<dmax<<endl;
1717 if((par.
hkl2d(h,sk*k,sl*l,NULL,3)*sl)>0)
break;
1721 bool missing=(d0<d5)&&(maxNbMissingBelow5>0);
1722 for(pos=first;pos!=end;++pos)
1724 if(pos==last)
break;
1725 if((!storePossibleHKL)&&(pos->isIndexed)&&missing)
continue;
1726 const float d2obs=pos->d2obs,d2obsmin=pos->d2obsmin, d2obsmax=pos->d2obsmax;
1727 if((d2obsmax>=d0) && (d1>=d2obsmin))
1730 if(!(pos->isIndexed))
1732 pos->d2calc=(d0+d1)/2;
1734 pos->isIndexed=
true;
1736 if(verbose) cout<<d1<<
" < ? <"<<d0<<
"("<<h<<
","<<sk*k<<
","<<sl*l<<
"): "<<d2obs<<
" (remaining to index:"<<nbIndexed<<
")"<<endl;
1737 if(storePossibleHKL)
1741 if((!storePossibleHKL)&&(nbIndexed==0))
return true;
1742 if(pos==first){first++;dmin=first->d2obsmin;}
1743 if(pos==last){last--;dmax=last->d2obsmax;}
1747 if(missing)
if(++nbMissingBelow5>=maxNbMissingBelow5)
return false;
1750 if(nbCalcK==0)
break;
1753 if(nbCalcH==0)
break;
1759 return nbIndexed<=0;
1762 float CellExplorer::GetBestScore()
const{
return mBestScore;}
1763 const std::list<std::pair<RecUnitCell,float> >& CellExplorer::GetSolutions()
const {
return mvSolution;}
1764 std::list<std::pair<RecUnitCell,float> >& CellExplorer::GetSolutions() {
return mvSolution;}
1766 unsigned int CellExplorer::RDicVol(RecUnitCell par0,RecUnitCell dpar,
unsigned int depth,
unsigned long &nbCalc,
const float minV,
const float maxV,vector<unsigned int> vdepth)
1768 static bool localverbose=
false;
1769 if(mlattice==TRICLINIC)
1771 const float p1=par0.par[1] , p2=par0.par[2] , p3=par0.par[3] , p4=par0.par[4] , p5=par0.par[5] , p6=par0.par[6];
1772 const float p1m=p1-dpar.par[1], p2m=p2-dpar.par[2], p3m=p3-dpar.par[3], p4m=p4-dpar.par[4], p5m=p5-dpar.par[5], p6m=p6-dpar.par[6];
1773 const float p1p=p1+dpar.par[1], p2p=p2+dpar.par[2], p3p=p3+dpar.par[3], p4p=p4+dpar.par[4], p5p=p5+dpar.par[5], p6p=p6+dpar.par[6];
1776 if((p1m>p2p)||(p2m>p3p))
return 0;
1779 if((p4m>p1p)||(-p4p>p1p))
return 0;
1780 if((p5m>p2p)||(-p5p>p2p))
return 0;
1781 if((p6m>p1p)||(-p6p>p1p))
return 0;
1783 const float max6=p1p+p2p-p4m-p5m;
1784 if((p6m>max6)||(-p6p>max6))
return 0;
1786 float p6mm,p6pp,p5mm,p5pp,p4mm,p4pp;
1788 if((p4*p5-2*p2*p6)>0) {p6pp=p6p;p6mm=p6m;}
1789 else{p6pp=p6m;p6mm=p6p;}
1791 if((p4*p6-2*p1*p5)>0) {p5pp=p5p;p5mm=p5m;}
1792 else{p5pp=p5m;p5mm=p5p;}
1794 if((p5*p6-2*p3*p4)>0) {p4pp=p4p;p4mm=p4m;}
1795 else{p4pp=p4m;p4mm=p4p;}
1799 const float vmin0=1/sqrt(abs(p1p*p2p*p3p*(1-p5mm*p5mm/(4*p2p*p3p)-p6mm*p6mm/(4*p1p*p3p)-p4mm*p4mm/(4*p1p*p2p)+p4mm*p5mm*p6mm/(4*p1m*p2m*p3m))));
1800 const float vmax0=1/sqrt(abs(p1m*p2m*p3m*(1-p5pp*p5pp/(4*p2m*p3m)-p6pp*p6pp/(4*p1m*p3m)-p4pp*p4pp/(4*p1m*p2m)+p4pp*p5pp*p6pp/(4*p1m*p2m*p3m))));
1801 if((vmin0>maxV)||(vmax0<minV))
return 0;
1804 if((depth>0)&&(depth<=2))
1806 RecUnitCell parm=par0,parp=par0;
1807 for(
unsigned int i=0;i<6;++i) {parm.par[i]-=dpar.par[i];parp.par[i]+=dpar.par[i];}
1808 vector<float> parmd=parm.DirectUnitCell();
1809 vector<float> parpd=parp.DirectUnitCell();
1810 if((parpd[6]>maxV)||(parmd[6]<minV))
return 0;
1812 unsigned int useStoredHKL=1;
1813 if(depth==0) useStoredHKL=2;
1815 unsigned int maxMissingBelow5=0;
1817 if(mlattice==TRICLINIC) maxMissingBelow5=5;
1819 bool indexed=
DichoIndexed(*mpPeakList,par0,dpar,mNbSpurious,localverbose,useStoredHKL,maxMissingBelow5);
1823 if( (!indexed) && (depth>=4))
1826 indexed=
DichoIndexed(*mpPeakList,par0,dpar,mNbSpurious,
false,useStoredHKL,maxMissingBelow5);
1831 if((indexed)&&(useStoredHKL==2))
1834 unsigned int nbident=0;
1835 for(vector<PeakList::hkl>::const_iterator pos=mpPeakList->GetPeakList().begin();pos!=mpPeakList->GetPeakList().end();)
1837 if(pos->vDicVolHKL.size()==1)
1839 const PeakList::hkl0 h0=pos->vDicVolHKL.front();
1840 if(++pos==mpPeakList->GetPeakList().end())
break;
1841 if(pos->vDicVolHKL.size()==1)
1843 const PeakList::hkl0 h1=pos->vDicVolHKL.front();
1844 if((h0.h==h1.h)&&(h0.k==h1.k)&&(h0.l==h1.l)) nbident++;
1845 if(nbident>mNbSpurious) {indexed=
false;
break;}
1853 if(vdepth.size()==0)
1855 vdepth.resize(mnpar-1);
1856 for(vector<unsigned int>::iterator pos=vdepth.begin();pos!=vdepth.end();) *pos++=depth;
1859 for(vector<unsigned int>::iterator pos=vdepth.begin();pos!=vdepth.end();++pos)
if(*pos<depth)*pos=depth;
1864 vector<pair<unsigned int,float> > vq0(3);
1865 for(
unsigned int i=0;i<3;++i) {vq0[i].first=0;vq0[i].second=0.0;}
1866 RecUnitCell par0orig=par0,dparorig=dpar;
1867 for(vector<PeakList::hkl>::const_iterator pos=mpPeakList->GetPeakList().begin();pos!=mpPeakList->GetPeakList().end();++pos)
1869 if(pos->vDicVolHKL.size()==1)
1871 const PeakList::hkl0 h0=pos->vDicVolHKL.front();
1872 if((h0.k==0)&&(h0.l==0)) {vq0[0].first+=1 ; vq0[0].second+=pos->dobs/h0.h;}
1874 if((h0.h==0)&&(h0.l==0)) {vq0[1].first+=1 ; vq0[1].second+=pos->dobs/h0.k;}
1876 if((h0.h==0)&&(h0.k==0)) {vq0[2].first+=1 ; vq0[2].second+=pos->dobs/h0.l;
if(localverbose) cout<<h0.h<<
" "<<h0.k<<
" "<<h0.l<<
": d="<<pos->dobs<<endl;}
1883 if(vq0[0].first>0) {par0.par[1]=vq0[0].second/vq0[0].first ; dpar.par[1]*=pow((
float)0.5,
float(mDicVolDepthReport-vdepth[0]));vdepth[0]=mDicVolDepthReport;}
1884 if(vq0[1].first>0) {par0.par[2]=vq0[1].second/vq0[1].first ; dpar.par[2]*=pow((
float)0.5,
float(mDicVolDepthReport-vdepth[1]));vdepth[1]=mDicVolDepthReport;}
1885 if(vq0[2].first>0) {par0.par[3]=vq0[2].second/vq0[2].first ; dpar.par[3]*=pow((
float)0.5,
float(mDicVolDepthReport-vdepth[2]));vdepth[2]=mDicVolDepthReport;}
1890 if(vq0[0].first>0) {par0.par[1]=vq0[0].second/vq0[0].first ; vdepth[0]=mDicVolDepthReport;dpar.par[1]*=.0625;}
1891 if(vq0[1].first>0) {par0.par[2]=vq0[1].second/vq0[1].first ; vdepth[1]=mDicVolDepthReport;dpar.par[2]*=.0625;}
1892 if(vq0[2].first>0) {par0.par[3]=vq0[2].second/vq0[2].first ; vdepth[2]=mDicVolDepthReport;dpar.par[3]*=.0625;}
1897 if(vq0[0].first>0) {par0.par[1]=vq0[0].second/vq0[0].first ; vdepth[0]=mDicVolDepthReport;dpar.par[1]*=.0625;}
1898 if(vq0[1].first>0) {par0.par[2]=vq0[1].second/vq0[1].first ; vdepth[1]=mDicVolDepthReport;dpar.par[2]*=.0625;}
1899 if(vq0[2].first>0) {par0.par[3]=vq0[2].second/vq0[2].first ; vdepth[2]=mDicVolDepthReport;dpar.par[3]*=.0625;}
1902 case HEXAGONAL:
break;
1903 case RHOMBOEDRAL:
break;
1904 case TETRAGONAL:
break;
1908 unsigned int newdepth=40;
1909 for(vector<unsigned int>::iterator pos=vdepth.begin();pos!=vdepth.end();++pos)
if(*pos<newdepth) newdepth=*pos;
1910 if(newdepth>depth) depth=newdepth;
1911 if((vq0[0].first>0)||(vq0[1].first>0)||(vq0[2].first>0))
1913 indexed=
DichoIndexed(*mpPeakList,par0,dpar,mNbSpurious,
false,1,maxMissingBelow5);
1917 RecUnitCell parm=par0orig,parp=par0;
1918 for(
unsigned int i=0;i<6;++i) {parm.par[i]-=dparorig.par[i];parp.par[i]+=dparorig.par[i];}
1919 vector<float> parmd=parm.DirectUnitCell();
1920 vector<float> parpd=parp.DirectUnitCell();
1922 sprintf(buf,
"orig: a=%5.2f-%5.2f b=%5.2f-%5.2f c=%5.2f-%5.2f alpha=%5.2f-%5.2f beta=%5.2f-%5.2f gamma=%5.2f-%5.2f V=%5.2f-%5.2f",
1923 parpd[0],parmd[0],parpd[1],parmd[1],parpd[2],parmd[2],parpd[3]*RAD2DEG,parmd[3]*RAD2DEG,
1924 parpd[4]*RAD2DEG,parmd[4]*RAD2DEG,parpd[5]*RAD2DEG,parmd[5]*RAD2DEG,parpd[6],parmd[6]);
1925 for(
unsigned int i = 0; i < depth; ++i) cout <<
" ";
1926 cout<<buf<<
"level="<<depth<<
", indexed="<<indexed<<endl;
1929 RecUnitCell parm=par0,parp=par0;
1930 for(
unsigned int i=0;i<6;++i) {parm.par[i]-=dpar.par[i];parp.par[i]+=dpar.par[i];}
1931 vector<float> parmd=parm.DirectUnitCell();
1932 vector<float> parpd=parp.DirectUnitCell();
1934 sprintf(buf,
"bypass: a=%5.2f-%5.2f b=%5.2f-%5.2f c=%5.2f-%5.2f alpha=%5.2f-%5.2f beta=%5.2f-%5.2f gamma=%5.2f-%5.2f V=%5.2f-%5.2f",
1935 parpd[0],parmd[0],parpd[1],parmd[1],parpd[2],parmd[2],parpd[3]*RAD2DEG,parmd[3]*RAD2DEG,
1936 parpd[4]*RAD2DEG,parmd[4]*RAD2DEG,parpd[5]*RAD2DEG,parmd[5]*RAD2DEG,parpd[6],parmd[6]);
1937 for(
unsigned int i = 0; i < depth; ++i) cout <<
" ";
1938 cout<<buf<<
"level="<<depth<<
", indexed="<<indexed<<endl;
1946 RecUnitCell parm=par0,parp=par0;
1947 for(
unsigned int i=0;i<4;++i) {parm.par[i]-=dpar.par[i];parp.par[i]+=dpar.par[i];}
1948 for(
unsigned int i=4;i<7;++i) {parm.par[i]+=dpar.par[i];parp.par[i]-=dpar.par[i];}
1949 vector<float> parmd=parm.DirectUnitCell();
1950 vector<float> parpd=parp.DirectUnitCell();
1952 sprintf(buf,
"a=%5.2f-%5.2f b=%5.2f-%5.2f c=%5.2f-%5.2f alpha=%6.2f-%6.2f beta=%6.2f-%6.2f gamma=%6.2f-%6.2f V=%6.2f-%6.2f",
1953 parpd[0],parmd[0],parpd[1],parmd[1],parpd[2],parmd[2],parpd[3]*RAD2DEG,parmd[3]*RAD2DEG,
1954 parpd[4]*RAD2DEG,parmd[4]*RAD2DEG,parpd[5]*RAD2DEG,parmd[5]*RAD2DEG,parpd[6],parmd[6]);
1955 for(
unsigned int i = 0; i < depth; ++i) cout <<
" ";
1956 cout<<buf<<
"level="<<depth<<
", indexed="<<indexed<<
"("<<mvSolution.size()<<
" sol.)"<<endl;
1975 unsigned int deeperSolutions=0;
1976 if(depth<mMaxDicVolDepth)
1980 RecUnitCell parm=par0,parp=par0;
1981 for(
unsigned int i=0;i<6;++i) {parm.par[i]-=dpar.par[i];parp.par[i]+=dpar.par[i];}
1982 vector<float> parmd=parm.DirectUnitCell();
1983 vector<float> parpd=parp.DirectUnitCell();
1985 sprintf(buf,
"a=%5.2f-%5.2f b=%5.2f-%5.2f c=%5.2f-%5.2f alpha=%5.2f-%5.2f beta=%5.2f-%5.2f gamma=%5.2f-%5.2f V=%5.2f-%5.2f",
1986 parpd[0],parmd[0],parpd[1],parmd[1],parpd[2],parmd[2],parpd[3]*RAD2DEG,parmd[3]*RAD2DEG,
1987 parpd[4]*RAD2DEG,parmd[4]*RAD2DEG,parpd[5]*RAD2DEG,parmd[5]*RAD2DEG,parpd[6],parmd[6]);
1988 for(
unsigned int i=0;i<depth;++i) cout<<
" ";
1989 cout<<
"Depth="<<depth<<
" "<<buf<<endl;
1990 for(
int i=0;i<=6;++i)cout<<par0.par[i]<<
",";
1991 for(
int i=0;i<=6;++i)cout<<dpar.par[i]<<
",";
1994 RecUnitCell par=par0;
1996 dpar.par[0]=0.5*dpar.par[0];
1999 for(
unsigned int i=1;i<mnpar;++i) dpar.par[i]*=(0.5+0.5*(vdepth[i-1]>depth));
2001 for(
int i0=-1;i0<=1;i0+=2)
2004 if(localverbose) cout<<__FILE__<<
":"<<__LINE__<<
":"<<par.par[3]<<
" +/- "<<dpar.par[3]<<
" ("<<vdepth[2]<<
")"<<endl;
2006 if(vdepth[0]==depth) {par.par[1]=par0.par[1]+i0*dpar.par[1];}
2009 deeperSolutions+=RDicVol(par,dpar, depth+1,nbCalc,minV,maxV,vdepth);
2011 for(
int i1=-1;i1<=1;i1+=2)
2013 if(vdepth[1]==depth) {par.par[2]=par0.par[2]+i1*dpar.par[2];}
2016 deeperSolutions+=RDicVol(par,dpar, depth+1,nbCalc,minV,maxV,vdepth);
2018 for(
int i2=-1;i2<=1;i2+=2)
2020 if(vdepth[2]==depth) {par.par[3]=par0.par[3]+i2*dpar.par[3];}
2023 deeperSolutions+=RDicVol(par,dpar, depth+1,nbCalc,minV,maxV,vdepth);
2025 for(
int i3=-1;i3<=1;i3+=2)
2027 if(vdepth[3]==depth)par.par[4]=par0.par[4]+i3*dpar.par[4];
2030 deeperSolutions+=RDicVol(par,dpar, depth+1,nbCalc,minV,maxV,vdepth);
2032 for(
int i4=-1;i4<=1;i4+=2)
2034 par.par[5]=par0.par[5]+i4*dpar.par[5];
2038 for(
int i5=-1;i5<=1;i5+=2)
2040 par.par[6]=par0.par[6]+i5*dpar.par[6];
2042 deeperSolutions+=RDicVol(par,dpar, depth+1,nbCalc,minV,maxV,vdepth);
2050 if((deeperSolutions==0) &&(depth>=mDicVolDepthReport))
2053 vector<float> par=mRecUnitCell.DirectUnitCell();
2054 float score=
Score(*mpPeakList,mRecUnitCell,mNbSpurious,
false,
true,
false);
2057 if(depth<(mMaxDicVolDepth-1))
2058 if(mvNbSolutionDepth[depth+2]>100)report=
false;
2059 if(report && (((score>(mMinScoreReport*.5))&&(depth>=mDicVolDepthReport)) || (depth>=mMaxDicVolDepth)))
2062 cout<<__FILE__<<
":"<<__LINE__<<
" Depth="<<depth<<
" (DIC) ! a="<<par[0]<<
", b="<<par[1]<<
", c="<<par[2]<<
", alpha="
2063 <<par[3]*RAD2DEG<<
", beta="<<par[4]*RAD2DEG<<
", gamma="<<par[5]*RAD2DEG<<
", V="<<par[6]
2064 <<
", score="<<score<<endl;
2065 this->LSQRefine(5,
true,
true);
2068 score=
Score(*mpPeakList,mRecUnitCell,mNbSpurious,
false,
true,
false);
2069 this->LSQRefine(5,
true,
true);
2071 par=mRecUnitCell.DirectUnitCell();
2072 score=
Score(*mpPeakList,mRecUnitCell,mNbSpurious,
false,
true,
false);
2073 if( ((score>mMinScoreReport)||(depth>=mDicVolDepthReport))
2074 &&((mvSolution.size()<50)||(score>(mBestScore/3)))
2075 &&((mvSolution.size()<50)||(score>mMinScoreReport)))
2077 if((score>(mBestScore))||((score>(mBestScore*0.8))&&(mvSolution.size()<50)))
2081 RecUnitCell parm=par0,parp=par0;
2082 for(
unsigned int i=0;i<4;++i) {parm.par[i]-=dpar.par[i];parp.par[i]+=dpar.par[i];}
2083 for(
unsigned int i=4;i<7;++i) {parm.par[i]+=dpar.par[i];parp.par[i]-=dpar.par[i];}
2084 vector<float> parmd=parm.DirectUnitCell();
2085 vector<float> parpd=parp.DirectUnitCell();
2086 sprintf(buf,
"a=%5.2f-%5.2f b=%5.2f-%5.2f c=%5.2f-%5.2f alpha=%6.2f-%6.2f beta=%6.2f-%6.2f gamma=%6.2f-%6.2f V=%6.2f-%6.2f",
2087 parpd[0],parmd[0],parpd[1],parmd[1],parpd[2],parmd[2],parpd[3]*RAD2DEG,parmd[3]*RAD2DEG,
2088 parpd[4]*RAD2DEG,parmd[4]*RAD2DEG,parpd[5]*RAD2DEG,parmd[5]*RAD2DEG,parpd[6],parmd[6]);
2089 for(
unsigned int i = 0; i < depth; ++i) cout <<
" ";
2091 cout<<buf<<
"level="<<depth<<
", indexed="<<indexed<<
"("<<mvSolution.size()<<
" sol.)"<<endl;
2092 sprintf(buf,
"a=%7.5f-%7.5f b=%7.5f-%7.5f c=%7.5f-%7.5f alpha=%7.5f-%7.5f beta=%7.5f-%7.5f gamma=%7.5f-%7.5f",
2093 parp.par[1],parm.par[1],parp.par[2],parm.par[2],parp.par[3],parm.par[3],parp.par[4],parm.par[4],
2094 parp.par[5],parm.par[5],parp.par[6],parm.par[6]);
2095 for(
unsigned int i = 0; i < depth; ++i) cout <<
" ";
2096 cout<<buf<<
"level="<<depth<<
", indexed="<<indexed<<
"("<<mvSolution.size()<<
" sol.)"<<endl;
2098 sprintf(buf,
" Solution ? a=%7.3f b=%7.3f c=%7.3f alpha=%7.3f beta=%7.3f gamma=%7.3f V=%8.2f score=%6.2f #%4lu",
2099 par[0],par[1],par[2],par[3]*RAD2DEG,par[4]*RAD2DEG,par[5]*RAD2DEG,par[6],score,mvSolution.size());
2103 mvSolution.push_back(make_pair(mRecUnitCell,score));
2104 mvNbSolutionDepth[depth]+=1;
2105 if((mvSolution.size()>1100)&&(rand()%1000==0))
2107 cout<<mvSolution.size()<<
" solutions ! Redparing..."<<endl;
2108 this->ReduceSolutions(
true);
2109 cout<<
"-> "<<mvSolution.size()<<
" remaining"<<endl;
2114 return deeperSolutions+1;
2119 vector<float> linspace(
float min,
float max,
unsigned int nb)
2121 vector<float> v(nb);
2122 for(
unsigned int i=0;i<nb;++i) v[i]=min+(max-min)*i/(nb-1);
2126 void CellExplorer::DicVol(
const float minScore,
const unsigned int minDepth,
const float stopOnScore,
const unsigned int stopOnDepth)
2129 mDicVolDepthReport=minDepth;
2130 mMinScoreReport=minScore;
2132 if(minDepth>mMaxDicVolDepth) mMaxDicVolDepth=minDepth;
2133 mvNbSolutionDepth.resize(mMaxDicVolDepth+1);
2134 for(
unsigned int i=0;i<=mMaxDicVolDepth;++i) mvNbSolutionDepth[i]=0;
2137 vstep=(mVolumeMax-mVolumeMin)/(ceil((mVolumeMax-mVolumeMin)/500)-0.0001);
2138 mCosAngMax=abs(cos(mAngleMax));
2139 const float cosangstep=mCosAngMax/(ceil(mCosAngMax/.08)-.0001);
2140 if(((mVolumeMax-mVolumeMin)/vstep)>10) vstep=(mVolumeMax-mVolumeMin)/9.999;
2141 if(((mLengthMax-mLengthMin)/latstep)>25) latstep=(mLengthMax-mLengthMin)/24.9999;
2143 cout<<mLengthMin<<
"->"<<mLengthMax<<
","<<latstep<<
","<<(mLengthMax-mLengthMin)/latstep<<endl;
2144 cout<<mAngleMin<<
"->"<<mAngleMax<<
","<<cosangstep<<
","<<mCosAngMax<<
","<<(mAngleMax-mAngleMin)/cosangstep<<endl;
2145 cout<<mVolumeMin<<
"->"<<mVolumeMax<<
","<<vstep<<
","<<(mVolumeMax-mVolumeMin)/vstep<<endl;
2147 par0.mlattice=mlattice;
2148 dpar.mlattice=mlattice;
2149 par0.mCentering=mCentering;
2150 dpar.mCentering=mCentering;
2154 unsigned long nbCalc=0;
2157 list<pair<RecUnitCell,float> >::iterator bestpos;
2158 bool breakDepth=
false;
2161 for(
float minv=mVolumeMin;minv<mVolumeMax;minv+=vstep)
2163 float maxv=minv+vstep;
2164 if(maxv>mVolumeMax)maxv=mVolumeMax;
2165 cout<<
"Starting: V="<<minv<<
"->"<<maxv<<endl;
2166 const float minr=1/(mLengthMax*mLengthMax);
2167 const float maxr=1/(mLengthMin*mLengthMin);
2168 const float stepr=(maxr-minr)/24.999;
2170 for(
unsigned int i=0;i<=5;i++)
2174 case 0: p1=mpPeakList->GetPeakList()[0].d2obs ;p2=mpPeakList->GetPeakList()[1].d2obs ;
break;
2175 case 1: p1=mpPeakList->GetPeakList()[0].d2obs ;p2=mpPeakList->GetPeakList()[2].d2obs ;
break;
2176 case 2: p1=mpPeakList->GetPeakList()[1].d2obs/2;p2=mpPeakList->GetPeakList()[0].d2obs ;
break;
2177 case 3: p1=mpPeakList->GetPeakList()[1].d2obs/2;p2=mpPeakList->GetPeakList()[2].d2obs ;
break;
2178 case 4: p1=mpPeakList->GetPeakList()[2].d2obs/2;p2=mpPeakList->GetPeakList()[0].d2obs ;
break;
2179 case 5: p1=mpPeakList->GetPeakList()[2].d2obs/2;p2=mpPeakList->GetPeakList()[1].d2obs ;
break;
2183 cout<<
"Trying #"<<i<<
": a*="<<p1<<
", b*="<<p2<<endl;
2186 const float step3r=(max3r-min3r)/(ceil((max3r-min3r)/stepr)-.001);
2187 vector<unsigned int> vdepth(mnpar-1);
2188 for(vector<unsigned int>::iterator pos=vdepth.begin();pos!=vdepth.end();) *pos++=0;
2191 for(
float p3=min3r;p3<max3r;p3+=step3r)
2194 const float max4r=p3+step3r;
2195 const float step4r=max4r/(ceil(max4r/stepr)-.001);
2196 for(
float p4=0;p4<max4r;p4+=step4r)
2199 float max5r=(p2+stepr);
2200 const float step5r=max5r/(ceil(max5r/stepr)-.001);
2201 for(
float p5=0;p5<max5r;p5+=step5r)
2203 float max6r=(p1+stepr);
2204 const float step6r=max6r/(ceil(max6r/stepr)-.001);
2205 for(
float p6=-max6r;p6<max6r;p6+=step6r)
2208 dpar.par[1]=stepr*pow(
float(0.51),
int(vdepth[0]));
2209 dpar.par[2]=stepr*pow(
float(0.51),
int(vdepth[1]));
2210 dpar.par[3]=step3r*0.51;
2211 dpar.par[4]=step4r*0.51;
2212 dpar.par[5]=step5r*0.51;
2213 dpar.par[6]=step6r*0.51;
2218 par0.par[3]=p3+step3r/2;
2219 par0.par[4]=p4+step4r/2;
2220 par0.par[5]=p5+step5r/2;
2221 par0.par[6]=p6+step6r/2;
2226 RDicVol(par0,dpar,0,nbCalc,minv,maxv,vdepth);
2231 cout<<
"Finished trying: a*="<<p1<<
" A, b*="<<p2<<
" A, "<<nbCalc
2232 <<
" unit cells tested, "<<nbCalc/chrono.seconds()<<
" tests/s, Elapsed time="
2233 <<chrono.seconds()<<
"s, Best score="<<mBestScore<<
", "<<stopOnScore<<
", "<<breakDepth<<endl;
2236 for(
unsigned int i=stopOnDepth; i<mvNbSolutionDepth.size();++i)
2237 if(mvNbSolutionDepth[i]>1) {breakDepth=
true;
break;}
2238 if((mBestScore>stopOnScore)&&(breakDepth))
break;
2240 cout<<
"Finished triclinic QUICK tests for: V="<<minv<<
"->"<<maxv<<
" A^3, "<<nbCalc
2241 <<
" unit cells tested, "<<nbCalc/chrono.seconds()<<
" tests/s, Elapsed time="
2242 <<chrono.seconds()<<
"s, Best score="<<mBestScore<<endl;
2243 if((mBestScore>stopOnScore)&&(breakDepth))
break;
2245 if((mBestScore<stopOnScore)||(!breakDepth))
2246 for(
float minv=mVolumeMin;minv<mVolumeMax;minv+=vstep)
2248 float maxv=minv+vstep;
2249 if(maxv>mVolumeMax)maxv=mVolumeMax;
2250 cout<<
"Starting: V="<<minv<<
"->"<<maxv<<endl;
2255 const unsigned int nbstep=25;
2256 vector<float> v1=linspace(mLengthMin,mLengthMax,nbstep);
2257 const float lstep=v1[1]-v1[0];
2258 for(
unsigned int i1=0;i1<(nbstep-1);++i1)
2260 const float p1 =(1/(v1[i1]*v1[i1])+1/(v1[i1+1]*v1[i1+1]))/2;
2261 const float dp1=(1/(v1[i1]*v1[i1])-1/(v1[i1+1]*v1[i1+1]))/2;
2264 const unsigned int nb2=int((v1[i1+1]-mLengthMin)/lstep+2.001);
2265 vector<float> v2=linspace(mLengthMin,v1[i1+1],nb2);
2268 for(
unsigned int i2=0;i2<(nb2-1);++i2)
2270 const float p2 =(1/(v2[i2]*v2[i2])+1/(v2[i2+1]*v2[i2+1]))/2;
2271 const float dp2=(1/(v2[i2]*v2[i2])-1/(v2[i2+1]*v2[i2+1]))/2;
2273 const unsigned int nb3=int((v2[i2+1]-mLengthMin)/lstep+2.001);
2274 vector<float> v3=linspace(mLengthMin,v2[i2+1],nb3);
2275 for(
unsigned int i3=0;i3<(nb3-1);++i3)
2277 const float p3 =(1/(v3[i3]*v3[i3])+1/(v3[i3+1]*v3[i3+1]))/2;
2278 const float dp3=(1/(v3[i3]*v3[i3])-1/(v3[i3+1]*v3[i3+1]))/2;
2282 const float vmin3=1/sqrt((p1+dp1)*(p2+dp2)*(p3+dp3));
2283 const float vmax3=1/sqrt((p1-dp1)*(p2-dp2)*(p3-dp3))*2;
2284 if(vmax3<minv)
continue;
2285 if(vmin3>maxv)
continue;
2293 const unsigned int nb4=int((p1+dp1)/(4*dp1)+2.001);
2294 vector<float> v4=linspace(0,p1+dp1,nb4);
2295 for(
unsigned int i4=0;i4<(nb4-1);++i4)
2297 const float p4 =(v4[i4+1]+v4[i4])/2;
2298 const float dp4=(v4[i4+1]-v4[i4])/2;
2300 const unsigned int nb5=int((p2+dp2)/(4*dp2)+2.001);
2301 vector<float> v5=linspace(0,p2+dp2,nb5);
2302 for(
unsigned int i5=0;i5<(nb5-1);++i5)
2304 const float p5 =(v5[i5+1]+v5[i5])/2;
2305 const float dp5=(v5[i5+1]-v5[i5])/2;
2308 float vmax6=(p1+dp1)+(p2+dp2)-(p4-dp4)-(p5-dp5);
2309 if(vmax6>(p1+dp1)) vmax6=p1+dp1;
2310 if(vmax6<0)
continue;
2311 const unsigned int nb6=int((2*vmax6)/(4*dp1)+2.001);
2312 vector<float> v6=linspace(-vmax6,vmax6,nb6);
2314 for(
unsigned int i6=0;i6<(nb6-1);++i6)
2316 const float p6 =(v6[i6+1]+v6[i6])/2;
2317 const float dp6=(v6[i6+1]-v6[i6])/2;
2340 RDicVol(par0,dpar,0,nbCalc,minv,maxv);
2353 vector<float> parlarged,parsmalld;
2354 latstep=(mLengthMax-mLengthMin)/24.999;
2355 for(
float x4=0;x4<mCosAngMax+cosangstep;x4+=cosangstep)
2357 const float sinbeta=sqrt(abs(1-x4*x4));
2358 float x1=mLengthMin;
2359 for(;x1<mLengthMax;x1+=latstep)
2361 float x2=mLengthMin;
2362 for(;x2<mLengthMax;x2+=latstep)
2365 const float x3step=(mLengthMax-x1)/(ceil((mLengthMax-x1)/latstep)-0.001);
2366 for(;x3<mLengthMax;x3+=x3step)
2368 if((x3*x4)>x1)
break;
2369 dpar.par[1]=(1/(x1)-1/(x1+latstep))*0.5/sinbeta;
2370 dpar.par[2]=(1/(x2)-1/(x2+latstep))*0.5/sinbeta;
2371 dpar.par[3]=(1/(x3)-1/(x3+x3step ))*0.5/sinbeta;
2372 dpar.par[4]=cosangstep*0.5;
2375 par0.par[1]=(1/(x1)+1/(x1+latstep))*0.5/sinbeta;
2376 par0.par[2]=(1/(x2)+1/(x2+latstep))*0.5/sinbeta;
2377 par0.par[3]=(1/(x3)+1/(x3+x3step ))*0.5/sinbeta;
2378 par0.par[4]=x4+cosangstep*.5;
2380 const float smallv=x1*x2*x3*sinbeta;
2381 if(smallv>maxv)
break;
2382 const float largev=(x1+latstep)*(x2+latstep)*(x3+latstep)*(sinbeta+cosangstep);
2383 if(largev<minv)
continue;
2391 RDicVol(par0,dpar,0,nbCalc,minv,maxv);
2397 for(list<pair<RecUnitCell,float> >::iterator pos=mvSolution.begin();pos!=mvSolution.end();++pos)
2399 const float score=pos->second;
2400 if(score>bestscore) {bestscore=score;bestpos=pos;}
2402 bool breakDepth=
false;
2404 for(
unsigned int i=stopOnDepth; i<mvNbSolutionDepth.size();++i)
2405 if(mvNbSolutionDepth[i]>1) {breakDepth=
true;
break;}
2406 if((bestscore>stopOnScore)&&(breakDepth))
break;
2417 const float a=6.25,b=16.75,c=16.75;
2418 dpar.par[1]=(1/(a-.25)-1/(a+.25))*0.5;
2419 dpar.par[2]=(1/(b-.25)-1/(b+.25))*0.5;
2420 dpar.par[3]=(1/(c-.25)-1/(c+.25))*0.5;
2425 RDicVol(par0,dpar,0,nbCalc,minv,maxv);
2428 latstep=(mLengthMax-mLengthMin)/24.999;
2429 for(
float x1=mLengthMin;x1<mLengthMax;x1+=latstep)
2431 for(
float x2=x1;x2<mLengthMax;x2+=latstep)
2433 for(
float x3=x2;x3<mLengthMax;x3+=latstep)
2435 dpar.par[1]=(1/(x1)-1/(x1+latstep))*0.5;
2436 dpar.par[2]=(1/(x2)-1/(x2+latstep))*0.5;
2437 dpar.par[3]=(1/(x3)-1/(x3+latstep))*0.5;
2440 par0.par[1]=(1/(x1)+1/(x1+latstep))*0.5;
2441 par0.par[2]=(1/(x2)+1/(x2+latstep))*0.5;
2442 par0.par[3]=(1/(x3)+1/(x3+latstep))*0.5;
2444 const float vmin=x1*x2*x3,vmax=(x1+latstep)*(x2+latstep)*(x3+latstep);
2445 if(vmin>maxv)
break;
2446 if(vmax>=minv) RDicVol(par0,dpar,0,nbCalc,minv,maxv);
2448 if((x1*x2*x2)>maxv)
break;
2450 if((x1*x1*x1)>maxv)
break;
2456 vector<float> parlarged,parsmalld;
2457 latstep=(mLengthMax-mLengthMin)/24.999;
2458 for(
float x1=mLengthMin;;x1+=latstep)
2460 for(
float x2=mLengthMin;x2<(mLengthMax+latstep);x2+=latstep)
2462 dpar.par[1]=(1/(x1)-1/(x1+latstep))*0.5;
2463 dpar.par[2]=(1/(x2)-1/(x2+latstep))*0.5;
2466 par0.par[1]=(1/(x1)+1/(x1+latstep))*0.5;
2467 par0.par[2]=(1/(x2)+1/(x2+latstep))*0.5;
2470 for(
unsigned int i=0;i<6;++i) {parlarge.
par[i]-=dpar.par[i];parsmall.par[i]+=dpar.par[i];}
2472 parsmalld=parsmall.DirectUnitCell();
2479 if((parsmalld[6]<maxv)&&(parlarged[6]>minv))
2482 RDicVol(par0,dpar,0,nbCalc,minv,maxv);
2486 if(parlarged[0]>mLengthMax)
break;
2492 latstep=(mLengthMax-mLengthMin)/24.999;
2493 for(
float x1=mLengthMin;x1<(mLengthMax+latstep);x1+=latstep)
2495 for(
float x2=0;x2<mCosAngMax+cosangstep;x2+=cosangstep)
2497 dpar.par[1]=latstep/2*1.1;
2498 dpar.par[2]=cosangstep/2*1.1;
2501 par0.par[1]=x1-latstep/2*1.1;
2502 par0.par[2]=x2-cosangstep/2*1.1;
2503 vector<float> par=par0.DirectUnitCell();
2504 if((par[6]<maxv)&&(par[6]>minv))
2506 RDicVol(par0,dpar,0,nbCalc,minv,maxv);
2514 vector<float> parlarged,parsmalld;
2515 latstep=(mLengthMax-mLengthMin)/24.999;
2516 for(
float x1=mLengthMin;x1<mLengthMax;x1+=latstep)
2518 for(
float x2=mLengthMin;x2<mLengthMax;x2+=latstep)
2520 dpar.par[1]=(1/(x1)-1/(x1+latstep))*0.5;
2521 dpar.par[2]=(1/(x2)-1/(x2+latstep))*0.5;
2524 par0.par[1]=(1/(x1)+1/(x1+latstep))*0.5;
2525 par0.par[2]=(1/(x2)+1/(x2+latstep))*0.5;
2528 for(
unsigned int i=0;i<6;++i) {parlarge.
par[i]-=dpar.par[i];parsmall.par[i]+=dpar.par[i];}
2530 parsmalld=parsmall.DirectUnitCell();
2537 if((parsmalld[6]<maxv)&&(parlarged[6]>minv))
2539 RDicVol(par0,dpar,0,nbCalc,minv,maxv);
2541 if(parsmalld[6]>maxv)
break;
2543 if((x1*mLengthMin*mLengthMin)>maxv)
break;
2549 latstep=(mLengthMax-mLengthMin)/24.999;
2550 cout<<mLengthMax<<
","<<mLengthMin<<
","<<latstep<<endl;
2551 for(
float x1=mLengthMin;x1<(mLengthMax+latstep);x1+=latstep)
2553 dpar.par[1]=(1/(x1)-1/(x1+latstep))*0.5;
2556 par0.par[1]=(1/(x1)+1/(x1+latstep))*0.5;
2558 const float vmin=x1*x1*x1,vmax=(x1+latstep)*(x1+latstep)*(x1+latstep);
2560 if(vmax>minv) RDicVol(par0,dpar,0,nbCalc,minv,maxv);
2565 cout<<
"Finished: V="<<minv<<
"->"<<maxv<<
" A^3, "<<nbCalc
2566 <<
" unit cells tested, "<<nbCalc/chrono.seconds()<<
" tests/s, Elapsed time="
2567 <<chrono.seconds()<<
"s"<<endl;
2568 for(list<pair<RecUnitCell,float> >::iterator pos=mvSolution.begin();pos!=mvSolution.end();++pos)
2570 const float score=pos->second;
2571 if(score>bestscore) {bestscore=score;bestpos=pos;}
2573 bool breakDepth=
false;
2575 for(
unsigned int i=stopOnDepth; i<mvNbSolutionDepth.size();++i)
2576 if(mvNbSolutionDepth[i]>1) {breakDepth=
true;
break;}
2577 if((bestscore>stopOnScore)&&(breakDepth))
break;
2592 this->ReduceSolutions(
true);
2593 bestscore=0;bestpos=mvSolution.end();
2594 for(list<pair<RecUnitCell,float> >::iterator pos=mvSolution.begin();pos!=mvSolution.end();++pos)
2596 const float score=
Score(*mpPeakList,pos->first,mNbSpurious);
2597 if(score>bestscore) {bestpos=pos;bestscore=score;}
2598 vector<float> par=pos->first.DirectUnitCell();
2599 cout<<__FILE__<<
":"<<__LINE__<<
" Solution ? a="<<par[0]<<
", b="<<par[1]<<
", c="<<par[2]
2600 <<
", alpha="<<par[3]*RAD2DEG<<
", beta="<<par[4]*RAD2DEG<<
", gamma="<<par[5]*RAD2DEG
2601 <<
", V="<<par[6]<<
", score="<<score<<endl;
2603 if(bestpos!=mvSolution.end())
2605 vector<float> par=bestpos->first.DirectUnitCell();
2606 cout<<__FILE__<<
":"<<__LINE__<<
" BEST ? a="<<par[0]<<
", b="<<par[1]<<
", c="<<par[2]
2607 <<
", alpha="<<par[3]*RAD2DEG<<
", beta="<<par[4]*RAD2DEG<<
", gamma="<<par[5]*RAD2DEG
2608 <<
", V="<<par[6]<<
", score="<<bestscore<<endl;
2609 cout<<nbCalc<<
"unit cells tested, "<<nbCalc/chrono.seconds()<<
" tests/s, Elapsed time="
2610 <<chrono.seconds()<<
"s"<<endl;
2619 for(
unsigned int i=0;i<6;++i) diff += abs(par0[i]-par1[i]);
2620 return (diff/6)<delta;
2623 bool compareRUCScore(std::pair<RecUnitCell,float> &p1, std::pair<RecUnitCell,float> &p2)
2625 return p1.second > p2.second;
2628 void CellExplorer::ReduceSolutions(
const bool updateReportThreshold)
2630 const bool verbose=
false;
2631 std::list<std::pair<RecUnitCell,float> > vSolution2;
2634 for(list<pair<RecUnitCell,float> >::iterator pos=mvSolution.begin();pos!=mvSolution.end();)
2636 if(pos->second<(mBestScore/5)) pos=mvSolution.erase(pos);
2639 if(updateReportThreshold&& ((mBestScore/5)>mMinScoreReport))
2641 cout<<
"CellExplorer::ReduceSolutions(): update threshold for report from "
2642 <<mMinScoreReport<<
" to "<<mBestScore/5<<endl;
2643 mMinScoreReport=mBestScore/5;
2646 while(mvSolution.size()>0)
2648 vSolution2.push_back(mvSolution.front());
2649 mvSolution.pop_front();
2650 vector<float> par=vSolution2.back().first.DirectUnitCell();
2652 cout<<__FILE__<<
":"<<__LINE__<<
" SOLUTION: a="<<par[0]<<
", b="<<par[1]<<
", c="<<par[2]
2653 <<
", alpha="<<par[3]*RAD2DEG<<
", beta="<<par[4]*RAD2DEG<<
", gamma="<<par[5]*RAD2DEG
2654 <<
", V="<<par[6]<<
", score="<<vSolution2.back().second<<
", SIMILAR TO:"<<endl;
2655 for(list<pair<RecUnitCell,float> >::iterator pos=mvSolution.begin();pos!=mvSolution.end();)
2657 if(SimilarRUC(pos->first,vSolution2.back().first))
2659 par=pos->first.DirectUnitCell();
2661 cout<<__FILE__<<
":"<<__LINE__<<
" 1: a="<<par[0]<<
", b="<<par[1]<<
", c="<<par[2]
2662 <<
", alpha="<<par[3]*RAD2DEG<<
", beta="<<par[4]*RAD2DEG<<
", gamma="<<par[5]*RAD2DEG
2663 <<
", V="<<par[6]<<
", score="<<pos->second<<
" ("<<mvSolution.size()<<
")"<<endl;
2664 if(vSolution2.back().first.mlattice==pos->first.mlattice)
2666 if(pos->second>vSolution2.back().second) vSolution2.back()=*pos;
2668 else if(vSolution2.back().first.mlattice<pos->first.mlattice) vSolution2.back()=*pos;
2669 pos=mvSolution.erase(pos);
2673 par=pos->first.DirectUnitCell();
2675 cout<<__FILE__<<
":"<<__LINE__<<
" 0: a="<<par[0]<<
", b="<<par[1]<<
", c="<<par[2]
2676 <<
", alpha="<<par[3]*RAD2DEG<<
", beta="<<par[4]*RAD2DEG<<
", gamma="<<par[5]*RAD2DEG
2677 <<
", V="<<par[6]<<
", score="<<pos->second<<
" ("<<mvSolution.size()<<
")"<<endl;
2682 mvSolution=vSolution2;
2683 mvSolution.sort(compareRUCScore);
2686 if(mvSolution.size()>100)
2688 mvSolution.resize(100);
2689 if(updateReportThreshold && (mvSolution.back().second>mMinScoreReport))
2691 cout<<
"CellExplorer::ReduceSolutions(): update threshold for report from "
2692 <<mMinScoreReport<<
" to "<<mvSolution.back().second<<endl;
2693 mMinScoreReport=mvSolution.back().second;
2699 void CellExplorer::Init()
2705 vector<pair<RecUnitCell,float> >::iterator pos;
2706 const float min_latt=1./mLengthMax;
2707 const float max_latt=1./mLengthMin;
2708 const float amp_crossp=abs(cos(mAngleMax));
2710 mMin[0]=.00;mAmp[0]=.00;
2714 mMin[1]=min_latt;mAmp[1]=max_latt-min_latt;
2715 mMin[2]=min_latt;mAmp[2]=max_latt-min_latt;
2716 mMin[3]=min_latt;mAmp[3]=max_latt-min_latt;
2717 mMin[4]=0;mAmp[4]=amp_crossp;
2718 mMin[5]=0;mAmp[5]=amp_crossp;
2719 mMin[6]=0;mAmp[6]=amp_crossp;
2723 mMin[1]=min_latt;mAmp[1]=max_latt-min_latt;
2724 mMin[2]=min_latt;mAmp[2]=max_latt-min_latt;
2725 mMin[3]=min_latt;mAmp[3]=max_latt-min_latt;
2726 mMin[4]=0;mAmp[4]=amp_crossp;
2730 mMin[1]=min_latt;mAmp[1]=max_latt-min_latt;
2731 mMin[2]=min_latt;mAmp[2]=max_latt-min_latt;
2732 mMin[3]=min_latt;mAmp[3]=max_latt-min_latt;
2736 mMin[1]=min_latt;mAmp[1]=max_latt-min_latt;
2737 mMin[2]=min_latt;mAmp[2]=max_latt-min_latt;
2741 mMin[1]=min_latt;mAmp[1]=max_latt-min_latt;
2742 mMin[2]=-amp_crossp;mAmp[2]=2*amp_crossp;
2746 mMin[1]=min_latt;mAmp[1]=max_latt-min_latt;
2747 mMin[2]=min_latt;mAmp[2]=max_latt-min_latt;
2751 mMin[1]=min_latt;mAmp[1]=max_latt-min_latt;
2757 unsigned int nb1=0,nb2=0;
2798 this->ResetParList();
2800 RefinablePar tmp(
"Zero",mRecUnitCell.par+0,-0.01,0.01,gpRefParTypeObjCryst,REFPAR_DERIV_STEP_ABSOLUTE,
2801 true,
false,
true,
false);
2802 tmp.SetDerivStep(1e-4);
2806 string str=
"Reciprocal unit cell par #";
2807 for(
unsigned int i=0;i<nb1;++i)
2809 sprintf(buf,
"%i",i);
2810 RefinablePar tmp(str+(
string)buf,mRecUnitCell.par+i+1,
2811 0.01,1.,gpRefParTypeObjCryst,REFPAR_DERIV_STEP_ABSOLUTE,
2812 false,
false,
true,
false);
2813 tmp.SetDerivStep(1e-4);
2816 for(
unsigned int i=nb1;i<(nb1+nb2);++i)
2818 sprintf(buf,
"%i",i);
2819 RefinablePar tmp(str+(
string)buf,mRecUnitCell.par+i+1,
2820 0.0,0.5,gpRefParTypeObjCryst,REFPAR_DERIV_STEP_ABSOLUTE,
2821 false,
false,
true,
false);
2822 tmp.SetDerivStep(1e-4);
vector< hkl > & GetPeakList()
Get peak list.
string GetName() const
Get the parameter's name.
list< hkl > mvPredictedHKL
Full list of calculated HKL positions for a given solution, up to a given resolution After finding a ...
Simple chronometer class, with microsecond precision.
bool DichoIndexed(const PeakList &dhkl, const RecUnitCell &par, const RecUnitCell &dpar, const unsigned int nbUnindexed=0, const bool verbose=false, unsigned int useStoredHKL=0, const unsigned int maxNbMissingBelow5=0)
Number of reflexions found in the intervals calculated between par+dpar and par-dpar.
float EstimateCellVolume(const float dmin, const float dmax, const float nbrefl, const CrystalSystem system, const CrystalCentering centering, const float kappa)
Estimate volume from number of peaks at a given dmin See J.
CrystalSystem
Different lattice types.
float hkl2d(const float h, const float k, const float l, REAL *derivpar=NULL, const unsigned int derivhkl=0) const
Compute d*^2 for hkl reflection if deriv != -1, compute derivate versus the corresponding parameter...
Class to store positions of observed reflections.
float Score(const PeakList &dhkl, const RecUnitCell &rpar, const unsigned int nbSpurious, const bool verbose, const bool storehkl, const bool storePredictedHKL)
Compute score for a candidate RecUnitCell and a PeakList.
vector< hkl > mvHKL
Predict peak positions Best h,k,l for each observed peak (for least-squares refinement) This is store...
One set of Miller indices, a possible indexation for a reflection.
REAL par[7]
The 6 parameters defining 1/d_hkl^2 = d*_hkl^2, for different crystal classes, from: d*_hkl^2 = zero ...
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.
Lightweight class describing the reciprocal unit cell, for the fast computation of d*_hkl^2...
One observed diffraction line, to be indexed.
float Simulate(float zero, float a, float b, float c, float alpha, float beta, float gamma, bool deg, unsigned int nb=20, unsigned int nbspurious=0, float sigma=0, float percentMissing=0, const bool verbose=false)
Generate a list of simulated peak positions, from given lattice parameters.
The namespace which includes all objects (crystallographic and algorithmic) in ObjCryst++.
Generic class for parameters of refinable objects.
void hkl2d_delta(const float h, const float k, const float l, const RecUnitCell &delta, float &dmin, float &dmax) const
Compute d*^2 for one hkl reflection: this functions computes a d*^2 range (min,max) for a given range...
RecUnitCell(const float zero=0, const float par0=0, const float par1=0, const float par2=0, const float par3=0, const float par4=0, const float par5=0, CrystalSystem lattice=CUBIC, const CrystalCentering cent=LATTICE_P)
light-weight class storing the reciprocal space unitcell
std::vector< float > DirectUnitCell(const bool equiv=false) const
Compute real space unit cell from reciprocal one.