25 #include "ObjCryst/ObjCryst/Indexing.h"
26 #include "ObjCryst/Quirks/VFNDebug.h"
27 #include "ObjCryst/Quirks/VFNStreamFormat.h"
28 #include "ObjCryst/Quirks/Chronometer.h"
33 #define M_PI 3.14159265358979323846264338327950288
37 #define DEG2RAD (M_PI/180.)
40 #define RAD2DEG (180./M_PI)
47 const CrystalSystem system,
const CrystalCentering centering,
const float kappa)
49 const float q1=dmin*dmin*dmin-dmax*dmax*dmax;
50 const float q2=dmin*dmin -dmax*dmax;
55 return nbrefl/(C0*kappa*q1);
59 if(centering==LATTICE_P) D0=0.862;
60 if(centering==LATTICE_I) D0=0.475;
61 if(centering==LATTICE_F) D0=0.354;
62 return pow(nbrefl/(D0*kappa*q2),(
float)1.5);
65 if(system==MONOCLINIC) {C0=1.047;D0=0.786*.85;}
66 if(system==ORTHORHOMBIC){C0=0.524;D0=1.36 *.85;}
67 if(system==HEXAGONAL) {C0=0.150;D0=1.04 *.85;}
68 if(system==RHOMBOEDRAL){C0=0.230;D0=1.04 *.85;}
69 if(system==TETRAGONAL) {C0=0.214;D0=1.25 *.85;}
70 if((centering==LATTICE_I)||(centering==LATTICE_A)||(centering==LATTICE_B)||(centering==LATTICE_C)) {C0/=2;D0/=2;}
71 if(centering==LATTICE_F){C0/=4;D0/=4;}
72 const float alpha=D0*q2/(3*C0*q1), beta=nbrefl/(2*kappa*C0*q1);
73 const float eta=beta-alpha*alpha*alpha,gamma=sqrt(beta*beta-2*beta*alpha*alpha*alpha);
74 const float v=pow(pow(eta+gamma,(
float)(1/3.))+pow(fabs(eta-gamma),(
float)(1/3.))-alpha,(
float)3);
81 RecUnitCell::RecUnitCell(
const float zero,
const float p0,
const float p1,
const float p2,
82 const float p3,
const float p4,
const float p5,
CrystalSystem lattice,
83 const CrystalCentering cent,
const unsigned int nbspurious):
84 mlattice(lattice),mCentering(cent),mNbSpurious(nbspurious)
100 void RecUnitCell::operator=(
const RecUnitCell &rhs)
102 for(
unsigned int i=0;i<7;++i)
par[i]=rhs.par[i];
103 mlattice=rhs.mlattice;
104 mCentering=rhs.mCentering;
108 float RecUnitCell::hkl2d(
const float h,
const float k,
const float l,REAL *derivpar,
const unsigned int derivhkl)
const
110 if((derivpar==NULL)&&(derivhkl==0))
136 return par[0]+
par[1]*
par[1]*(h*h + k*k + l*l + 2*
par[2]*(h*k + k*l + h*l));
146 return par[0]+
par[1]*
par[1]*(h*h+k*k+l*l);
172 return par[1]*
par[1]*(2*h + k);
177 return par[1]*
par[1]*(2*h + 2*
par[2]*(k + l));
213 return par[1]*
par[1]*(2*k + h);
218 return par[1]*
par[1]*(2*k + l*l + 2*
par[2]*(h + l));
259 return par[1]*
par[1]*(2*l + 2*
par[2]*(k + h));
275 if(derivpar==&
par[0])
return 1.0;
276 if(derivpar==(
par+1))
287 return 2*
par[1]*h*h + 2*
par[3]*
par[4]*h*l;
297 return 2*
par[1]*(h*h + k*k + h*k);
302 return 2*
par[1]*(h*h + k*k + l*l + 2*
par[2]*(h*k + k*l + h*l));
307 return 2*
par[1]*(h*h + k*k);
312 return 2*
par[1]*(h*h+k*k+l*l);
317 if(derivpar==(
par+2))
338 return 2*
par[2]*l*l ;
343 return par[1]*
par[1]*(h*h + k*k + l*l + 2*(h*k + k*l + h*l));
358 if(derivpar==(
par+3))
369 return 2*
par[3]*l*l + 2*
par[1]*
par[4]*h*l;
399 if(derivpar==(
par+4))
410 return 2*
par[1]*
par[3]*h*l;
420 if(derivpar==(
par+5))
436 if(derivpar==(
par+6))
457 const RecUnitCell &delta,
float & dmin,
float &dmax)
const
459 const float p0m=
par[0]-delta.
par[0] , p0p=
par[0]+delta.
par[0],
470 float p4mm,p5mm,p6mm,p4pp,p5pp,p6pp;
471 if((h*k)>0){p4mm=p4m;p4pp=p4p;}
else{p4mm=p4p;p4pp=p4m;}
472 if((k*l)>0){p5mm=p5m;p5pp=p5p;}
else{p5mm=p5p;p5pp=p5m;}
473 if((h*l)>0){p6mm=p6m;p6pp=p6p;}
else{p6mm=p6p;p6pp=p6m;}
474 dmin=p0m+p1m*h*h+p2m*k*k+p3m*l*l+p4mm*h*k+p5mm*k*l+p6mm*h*l;
475 dmax=p0p+p1p*h*h+p2p*k*k+p3p*l*l+p4pp*h*k+p5pp*k*l+p6pp*h*l;
489 dmin = p0m + p1m*p1m*h*h + p2m*p2m*k*k + p3m*p3m*l*l + 2*p1m*p3m*p4m*h*l;
490 dmax = p0p + p1p*p1p*h*h + p2p*p2p*k*k + p3p*p3p*l*l + 2*p1p*p3p*p4p*h*l;
495 const bool b1=(h*(
par[1]*h+
par[3]*
par[4]*l))>0;
496 const bool b3=(l*(
par[3]*l+
par[1]*
par[4]*h))>0;
499 dmin = p0m + p1m*p1m*h*h + p2m*p2m*k*k + p3m*p3m*l*l + 2*p1m*p3m*p4p*h*l;
500 dmax = p0p + p1p*p1p*h*h + p2p*p2p*k*k + p3p*p3p*l*l + 2*p1p*p3p*p4m*h*l;
505 dmin = p0m + p1m*p1m*h*h + p2m*p2m*k*k + p3p*p3p*l*l + 2*p1m*p3p*p4p*h*l;
506 dmax = p0p + p1p*p1p*h*h + p2p*p2p*k*k + p3m*p3m*l*l + 2*p1p*p3m*p4m*h*l;
511 dmin = p0m + p1p*p1p*h*h + p2m*p2m*k*k + p3m*p3m*l*l + 2*p1p*p3m*p4p*h*l;
512 dmax = p0p + p1m*p1m*h*h + p2p*p2p*k*k + p3p*p3p*l*l + 2*p1m*p3p*p4m*h*l;
517 dmin = p0m + p1p*p1p*h*h + p2m*p2m*k*k + p3p*p3p*l*l + 2*p1p*p3p*p4p*h*l;
518 dmax = p0p + p1m*p1m*h*h + p2p*p2p*k*k + p3m*p3m*l*l + 2*p1m*p3m*p4m*h*l;
525 dmin= p0m + p1m*p1m*h*h + p2m*p2m*k*k + p3m*p3m*l*l;
526 dmax= p0p + p1p*p1p*h*h + p2p*p2p*k*k + p3p*p3p*l*l;
531 dmin=p0m+p1m*p1m*(h*h + k*k + h*k)+ p2m*p2m*l*l ;
532 dmax=p0p+p1p*p1p*(h*h + k*k + h*k)+ p2p*p2p*l*l ;
537 if((h*k + k*l + h*l)>=0)
539 dmin= p0m+p1m*p1m*(h*h + k*k + l*l + 2*p2m*(h*k + k*l + h*l));
540 dmax= p0p+p1p*p1p*(h*h + k*k + l*l + 2*p2p*(h*k + k*l + h*l));
544 dmin= p0m+p1m*p1m*(h*h + k*k + l*l + 2*p2p*(h*k + k*l + h*l));
545 dmax= p0p+p1p*p1p*(h*h + k*k + l*l + 2*p2m*(h*k + k*l + h*l));
551 dmin= p0m + p1m*p1m*(h*h + k*k) + p2m*p2m*l*l;
552 dmax= p0p + p1p*p1p*(h*h + k*k) + p2p*p2p*l*l;
557 dmin=p0m + p1m*p1m*(h*h+k*k+l*l);
558 dmax=p0p + p1p*p1p*(h*h+k*k+l*l);
567 float aa,bb,cc,calphaa,cbetaa,cgammaa,salphaa,sbetaa,sgammaa;
575 calphaa=
par[5]/(2*bb*cc);
576 cbetaa =
par[6]/(2*aa*cc);
577 cgammaa=
par[4]/(2*aa*bb);
578 salphaa=sqrt(abs(1-calphaa*calphaa));
579 sbetaa =sqrt(abs(1-cbetaa *cbetaa));
580 sgammaa=sqrt(abs(1-cgammaa*cgammaa));
592 sbetaa =sqrt(abs(1-cbetaa *cbetaa));
619 sgammaa=0.8660254037844386;
630 salphaa=sqrt(abs(1-calphaa *calphaa));
666 const float vv=sqrt(abs(1-calphaa*calphaa-cbetaa*cbetaa-cgammaa*cgammaa+2*calphaa*cbetaa*cgammaa));
668 const float a=salphaa/(aa*vv);
669 const float b=sbetaa /(bb*vv);
670 const float c=sgammaa/(cc*vv);
672 const float calpha=(cbetaa *cgammaa-calphaa)/(sbetaa *sgammaa);
673 const float cbeta =(calphaa*cgammaa-cbetaa )/(salphaa*sgammaa);
674 const float cgamma=(calphaa*cbetaa -cgammaa)/(salphaa*sbetaa );
676 const float alpha=acos( calpha );
677 const float beta =acos( cbeta );
678 const float gamma=acos( cgamma );
680 const float v=a*b*c*sqrt(1-calpha*calpha-cbeta*cbeta-cgamma*cgamma+2*calpha*cbeta*cgamma);
682 vector<float>
par(7);
693 PeakList::hkl0::hkl0(
const int h0,
const int k0,
const int l0):
698 PeakList::hkl::hkl(
const float d,
const float i,
const float ds,
const float is,
699 const int h0,
const int k0,
const int l0,
const float dc0):
700 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),
701 h(h0),k(k0),l(l0),isIndexed(false),isSpurious(false),stats(0),
702 d2calc(dc0),d2diff(0)
705 bool compareHKL_d(
const PeakList::hkl &d1,
const PeakList::hkl &d2)
707 return d1.dobs < d2.dobs;
716 PeakList::PeakList(
const PeakList &old)
721 void PeakList::operator=(
const PeakList &rhs)
723 VFN_DEBUG_ENTRY(
"PeakList::operator=(PeakList &old)",10);
725 VFN_DEBUG_EXIT(
"PeakList::operator=(PeakList &old)",10);
728 PeakList::~PeakList()
731 void PeakList::ImportDhklDSigmaIntensity(istream &is,
float defaultsigma)
737 cout<<__FILE__<<
":"<<__LINE__<<
" "<<
mvHKL.size()<<
":d="<<d;
738 if(is.good()==
false)
break;
740 if(is.good()==
false)
break;
742 if(sigma<=0) sigma=d*defaultsigma;
743 if(iobs<=0) iobs=1.0;
744 mvHKL.push_back(hkl(1/d,iobs,1/(d-sigma/2)-1/(d+sigma/2)));
745 cout<<
"+/-"<<sigma<<
", I="<<iobs<<
" 1/d="<<1/d<<endl;
746 if(is.good()==
false)
break;
749 cout<<
"Imported "<<
mvHKL.size()<<
" observed reflection positions."<<endl;
752 void PeakList::ImportDhklIntensity(istream &is)
760 mvHKL.push_back(hkl(1/d,iobs));
761 cout<<__FILE__<<
":"<<__LINE__<<
" "<<
mvHKL.size()<<
":d="<<d<<
", I="<<iobs<<
" 1/d="<<1/d<<endl;
765 cout<<
"Imported "<<
mvHKL.size()<<
" observed reflection positions."<<endl;
768 void PeakList::ImportDhkl(istream &is)
770 std::vector<std::pair<float,float> > v;
776 mvHKL.push_back(hkl(1/d));
777 cout<<__FILE__<<
":"<<__LINE__<<
" "<<
mvHKL.size()<<
":d="<<d<<
" 1/d="<<1/d<<endl;
781 cout<<
"Imported "<<v.size()<<
" observed reflection positions."<<endl;
785 template<
class T,
class U>
bool comparePairFirst(std::pair<T,U> &p1, std::pair<T,U> &p2)
787 return p1.first < p2.first;
790 void PeakList::Import2ThetaIntensity(istream &is,
const float wavelength)
792 std::list<std::pair<float,float> > v;
799 d=2*sin(d/2*DEG2RAD)/wavelength;
800 mvHKL.push_back(hkl(1/d,iobs));
801 cout<<__FILE__<<
":"<<__LINE__<<
" "<<
mvHKL.size()<<
":d="<<1/d<<
", I="<<iobs<<
" 1/d="<<d<<endl;
802 if((is.eof())||v.size()>=20)
break;
805 cout<<
"Imported "<<v.size()<<
" observed reflection positions."<<endl;
808 float alpha,
float beta,
float gamma,
809 bool deg,
unsigned int nb,
unsigned int nbspurious,
810 float sigma,
float percentMissing,
const bool verbose,
813 if(deg){alpha*=DEG2RAD;beta*=DEG2RAD;gamma*=DEG2RAD;}
814 const float v=sqrt(1-cos(alpha)*cos(alpha)-cos(beta)*cos(beta)-cos(gamma)*cos(gamma)
815 +2*cos(alpha)*cos(beta)*cos(gamma));
817 const float aa=sin(alpha)/a/v;
818 const float bb=sin(beta )/b/v;
819 const float cc=sin(gamma)/c/v;
821 const float alphaa=acos( (cos(beta )*cos(gamma)-cos(alpha))/sin(beta )/sin(gamma) );
822 const float betaa =acos( (cos(alpha)*cos(gamma)-cos(beta ))/sin(alpha)/sin(gamma) );
823 const float gammaa=acos( (cos(alpha)*cos(beta )-cos(gamma))/sin(alpha)/sin(beta ) );
825 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);
826 std::list<float> vd2;
828 for(
int h=0;h<=20;h++)
829 for(
int k=-20;k<=20;k++)
831 if((h==0) && (k<0)) k=0;
832 for(
int l=-20;l<=20;l++)
834 if((h==0) && (k==0) && (l<=0)) l=1;
835 vd2.push_back(sqrt(ruc.
hkl2d(h,k,l)));
839 std::list<float>::iterator pos=vd2.begin();
840 if(percentMissing>0.90) percentMissing=0.90;
841 for(;pos!=vd2.end();++pos)
843 if((rand()/
float(RAND_MAX))<percentMissing) *pos=1e10;
849 const float atol=1e-5;
850 for(std::list<float>::iterator p1=vd2.begin(), p2=++vd2.begin(); p2!=vd2.end();)
852 if(fabs(*p2-*p1)<atol) p2=vd2.erase(p2);
857 const float dmin=*pos/2;
858 for(
unsigned int i=0;i<nb;++i)pos++;
859 const float dmax=*pos;
861 for(
unsigned int i=0;i<nbspurious;++i)
863 const unsigned int idx=1+i*nb/nbspurious+(rand()%nbspurious);
865 for(
unsigned int j=0;j<idx;++j) pos++;
866 *pos=dmin+rand()/float(RAND_MAX)*(dmax-dmin);
870 for(
unsigned int i=0;i<nb;++i)
873 const float ds=d*sigma;
874 float d1=d+ds*(rand()/float(RAND_MAX)*2-1);
882 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);
883 cout<<
"PeakList::Simulate():"<<buf<<endl;
889 void PeakList::ExportDhklDSigmaIntensity(std::ostream &os)
const
891 for(vector<PeakList::hkl>::const_iterator pos=
mvHKL.begin();pos!=
mvHKL.end();++pos)
893 const float sigma=1/(pos->dobs-pos->dobssigma/2)-1/(pos->dobs+pos->dobssigma/2);
894 os<< std::fixed << setw(6) << setprecision(3) << 1/pos->dobs <<
" "<< sigma <<
" "<< std::scientific << pos->iobs <<endl;
898 void PeakList::AddPeak(
const float d,
const float iobs,
const float dobssigma,
const float iobssigma,
899 const int h,
const int k,
const int l,
const float d2calc)
904 for(vector<hkl>::const_iterator pos=
mvHKL.begin();pos!=
mvHKL.end();++pos)
907 if(s>0)
mvHKL.push_back(
hkl(d,iobs,s,iobssigma,h,k,l,d2calc));
908 else mvHKL.push_back(
hkl(d,iobs,1e-4,iobssigma,h,k,l,d2calc));
910 else mvHKL.push_back(
hkl(d,iobs,dobssigma,iobssigma,h,k,l,d2calc));
915 void PeakList::RemovePeak(
unsigned int idx)
921 void PeakList::Print(std::ostream &os)
const
925 os<<
"PeakList, with "<<
mvHKL.size()<<
" peaks"<<endl;
926 for(vector<PeakList::hkl>::const_iterator pos=
mvHKL.begin();pos!=
mvHKL.end();++pos)
928 const float sigma=1/(pos->dobs-pos->dobssigma/2)-1/(pos->dobs+pos->dobssigma/2);
930 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",
931 i++,1/pos->dobs,sigma,
932 1/sqrt(abs(pos->d2calc)),1/sqrt(abs(pos->d2calc))-1/pos->dobs,
933 pos->iobs,pos->h,pos->k,pos->l,pos->isSpurious,pos->stats);
935 sprintf(buf,
"#%3d d=%6.3f+/-%6.3f iobs=%6.3f UNINDEXED Spurious=%1d stats=%6lu",
936 i++,1/pos->dobs,1/(pos->dobs-pos->dobssigma/2)-1/(pos->dobs+pos->dobssigma/2),
937 pos->iobs,pos->isSpurious,pos->stats);
949 const bool verbose,
const bool storehkl,
const bool storePredictedHKL)
951 const bool autozero=
false;
952 vector<PeakList::hkl>::const_iterator pos,first,last;
955 if(storehkl) pos->isIndexed=
false;
962 unsigned long nbCalc=0;
964 float predict_coeff=1;
965 if(storePredictedHKL)predict_coeff=2;
966 const float dmax=dhkl.
mvHKL[nb-1].d2obs*predict_coeff*1.05;
968 switch(rpar.mlattice)
996 switch(rpar.mCentering)
998 case LATTICE_P:stepk=1;stepl=1;
break;
999 case LATTICE_I:stepk=1;stepl=2;
break;
1000 case LATTICE_A:stepk=1;stepl=2;
break;
1001 case LATTICE_B:stepk=1;stepl=2;
break;
1002 case LATTICE_C:stepk=2;stepl=1;
break;
1003 case LATTICE_F:stepk=2;stepl=2;
break;
1008 unsigned long nbCalcH,nbCalcK;
1012 for(
int sk=sk0;sk<=1;sk+=2)
1015 if(stepk==2) k=(h%2);
1020 for(
int sl=sl0;sl<=1;sl+=2)
1031 if(rpar.mlattice==MONOCLINIC) sl=1;
1032 if((sk<0)||(sl<0)) l=1;
1043 if(rpar.mCentering==LATTICE_I) l+=(h+k+l)%2;
1044 if(rpar.mCentering==LATTICE_A) l+=(k+l)%2;
1045 if( (rpar.mCentering==LATTICE_B)
1046 ||(rpar.mCentering==LATTICE_F)) l+=(h+l)%2;
1050 const float d2=rpar.
hkl2d(h,sk*k,sl*l);
1055 if((sl*rpar.
hkl2d(h,sk*k,sl*l,NULL,3))>=0)
break;
1058 nbCalc++;nbCalcK++;nbCalcH++;
1059 if(storePredictedHKL)
1064 for(pos=first;pos!=last;++pos)
1066 const float tmp=d2-pos->d2obs;
1070 if(fabs(tmp)<fabs(pos->d2diff))
1078 pos->isIndexed=
true;
1094 if((sk*rpar.
hkl2d(h,sk*k,0,NULL,2))>=0)
break;
1098 if(nbCalcH==0)
break;
1100 float epsilon=0.0,zero=0.0;
1108 epsilon +=fabs(pos->d2diff-zero);
1112 list<pair<float,unsigned int> > vdiff_idx;
1115 vdiff_idx.push_back(make_pair(fabs(pos->d2diff),i++));
1116 vdiff_idx.sort(comparePairFirst<float,unsigned int>);
1118 for(list<pair<float,unsigned int> >::reverse_iterator rpos=vdiff_idx.rbegin();rpos!=vdiff_idx.rend();++rpos)
1120 epsilon -= fabs(rpos->first-zero);
1121 if(storehkl) dhkl.
GetPeakList()[rpos->second].isIndexed=
false;
1123 if(++i==nbSpurious)
break;
1132 epstmp+=fabs(pos->d2diff-zero);
1135 cout<<
"epsilon="<<epstmp<<
", dmax="<<dmax<<
" ,nb="<<nb<<
" ,nbcalc="<<nbCalc<<endl;
1149 if(nbCalc==0)
return 0;
1150 const float score=(dmax/predict_coeff)*nb/(2*epsilon*nbCalc);
1154 cout<<
"Final score:"<<score<<
", nbCalc="<<nbCalc<<
" ,<epsilon>="<<epsilon<<
" nb="<<nb<<
" Qn="<<sqrt(dmax)<<endl;
1161 CellExplorer::CellExplorer(
const PeakList &dhkl,
const CrystalSystem lattice,
const unsigned int nbSpurious):
1162 mnpar(3),mpPeakList(&dhkl),
1163 mLengthMin(4),mLengthMax(25),
1164 mAngleMin(M_PI),mAngleMax(2*M_PI/3),
1165 mVolumeMin(0),mVolumeMax(1600),
1166 mZeroShiftMin(0),mZeroShiftMax(0),
1167 mlattice(lattice),mCentering(LATTICE_P),mNbSpurious(nbSpurious),
1168 mObs(0),mCalc(0),mWeight(0),mDeriv(0),mBestScore(0.0),
1169 mMinScoreReport(10),mMaxDicVolDepth(6),mDicVolDepthReport(6),
1175 void CellExplorer::Evolution(
unsigned int ng,
const bool randomize,
const float f,
const float cr,
unsigned int np)
1178 const bool autozero=
true;
1181 vector<pair<RecUnitCell,float> > vRUC(np);
1182 vector<pair<RecUnitCell,float> > vTrial(np);
1183 float bestScore=-1e20;
1184 vector<pair<RecUnitCell,float> >::iterator bestpos=vRUC.begin();
1186 const clock_t mTime0=clock();
1190 for(
unsigned int i=0;i<vRUC.size();++i)
1192 vRUC[i].first.mlattice=mlattice;
1193 vTrial[i].first.mlattice=mlattice;
1194 for(
unsigned int k=0;k<mnpar;++k) vRUC[i].first.par[k]=mMin[k]+mAmp[k]*rand()/(float)RAND_MAX;
1195 vRUC[i].second=
Score(*mpPeakList,vRUC[i].first,mNbSpurious);
1199 for(
unsigned long i=ng;i>0;--i)
1201 for(
unsigned j=0;j<np;j++)
1205 unsigned int r1=j,r2=j,r3=j;
1206 while(r1==j)r1=rand()%np;
1207 while((r2==j)||(r1==r2))r2=rand()%np;
1208 while((r3==j)||(r3==r1)||(r3==r2))r3=rand()%np;
1209 unsigned int ncr=1+(int)(cr*mnpar*rand()/(float)RAND_MAX);
1210 unsigned int ncr0=rand()%mnpar;
1211 RecUnitCell *t0=&(vTrial[j].first);
1212 RecUnitCell *c0=&(vRUC[j].first);
1213 RecUnitCell *c1=&(vRUC[r1].first);
1214 RecUnitCell *c2=&(vRUC[r2].first);
1215 RecUnitCell *c3=&(vRUC[r3].first);
1216 for(
unsigned int k=0;k<mnpar;++k)t0->par[k] = c0->par[k];
1217 for(
unsigned int k=0;k<ncr;++k)
1219 const unsigned l=(ncr0+k)%mnpar;
1220 const float v1=c1->par[l]-mMin[l];
1221 const float v2=c2->par[l]-mMin[l];
1222 const float v3=c3->par[l]-mMin[l];
1223 t0->par[l]=mMin[l]+fmod(v1+f*(v2-v3)+3*mAmp[l],mAmp[l]);
1228 unsigned int r1=j,r2=j,r3=j;
1229 while(r1==j)r1=rand()%np;
1230 while((r2==j)||(r1==r2))r2=rand()%np;
1231 while((r3==j)||(r3==r1)||(r3==r2))r3=rand()%np;
1232 unsigned int ncr=1+(int)(cr*(mnpar-1)*rand()/(float)RAND_MAX);
1233 unsigned int ncr0=rand()%mnpar;
1234 RecUnitCell *t0=&(vTrial[j].first);
1235 RecUnitCell *c0=&(vRUC[j].first);
1237 RecUnitCell *c2=&(vRUC[r2].first);
1238 RecUnitCell *c3=&(vRUC[r3].first);
1239 RecUnitCell *best=&(bestpos->first);
1240 for(
unsigned int k=0;k<6;++k)t0->par[k] = c0->par[k];
1241 for(
unsigned int k=0;k<ncr;++k)
1243 const unsigned l=(ncr0+k)%mnpar;
1244 const float v0=c0->par[l]-mMin[l];
1246 const float v2=c2->par[l]-mMin[l];
1247 const float v3=c3->par[l]-mMin[l];
1248 const float vb=best->par[l]-mMin[l];
1249 t0->par[l]=mMin[l]+fmod(vb+f*(vb-v0)+f*(v2-v3)+5*mAmp[l],mAmp[l]);
1254 const float amp=.05/(1+i*.01);
1255 RecUnitCell *t0=&(vTrial[j].first);
1256 for(
unsigned int k=0;k<6;++k)
1259 t0->par[k] = mMin[k]+ fmod((
float)(amp*mAmp[k]*(rand()/(
float)RAND_MAX-0.5)+5*mAmp[k]),(
float)mAmp[k]);
1264 vector<pair<RecUnitCell,float> >::iterator posTrial,pos;
1265 posTrial=vTrial.begin();
1267 for(;posTrial!=vTrial.end();)
1270 if(autozero) posTrial->first.par[0]=0;
1278 float v0=posTrial->first.par[1]*posTrial->first.par[2]*posTrial->first.par[3];
1279 while(v0<1/mVolumeMax)
1281 const unsigned int i=rand()%3+1;
1282 posTrial->first.par[i]*=1/(mVolumeMax*v0)+1e-4;
1283 if(posTrial->first.par[i]>(mMin[i]+mAmp[i])) posTrial->first.par[i]=mMin[i]+mAmp[i];
1284 v0=posTrial->first.par[1]*posTrial->first.par[2]*posTrial->first.par[3];
1300 const float score=
Score(*mpPeakList,posTrial->first,mNbSpurious);
1301 if(score > pos->second)
1304 const REAL *p0=posTrial->first.par;
1305 REAL *p1=pos->first.par;
1306 for(
unsigned int k=0;k<mnpar;++k) *p1++ = *p0++;
1329 vector<float> par=bestpos->first.DirectUnitCell();
1330 cout<<
"Generation #"<<ng-i<<
", Best score="<<bestScore
1331 <<
" Trial: a="<<par[0]<<
", b="<<par[1]<<
", c="<<par[2]<<
", alpha="
1332 <<par[3]*RAD2DEG<<
", beta="<<par[4]*RAD2DEG<<
", gamma="<<par[5]*RAD2DEG<<
", V="<<par[6]
1333 <<
" "<<(ng-i)*np/((clock()-mTime0)/(float)CLOCKS_PER_SEC)<<
" trials/s"
1338 for(vector<pair<RecUnitCell,float> >::iterator pos=vRUC.begin();pos!=vRUC.end();++pos)
1340 if(pos==bestpos)
continue;
1341 for(
unsigned int k=0;k<mnpar;++k) pos->first.par[k]=mMin[k]+mAmp[k]*rand()/(float)RAND_MAX;
1359 mRecUnitCell=bestpos->first;
1360 float score=
Score(*mpPeakList,mRecUnitCell,mNbSpurious,
false,
true);
1361 vector<float> par=mRecUnitCell.DirectUnitCell();
1362 cout<<__FILE__<<
":"<<__LINE__<<
" Best-DE : a="<<par[0]<<
", b="<<par[1]<<
", c="<<par[2]<<
", alpha="
1363 <<par[3]*RAD2DEG<<
", beta="<<par[4]*RAD2DEG<<
", gamma="<<par[5]*RAD2DEG<<
", V="<<par[6]
1364 <<
", score="<<bestpos->second
1365 <<
" ("<<ng*np/((clock()-mTime0)/(
float)CLOCKS_PER_SEC)<<
" trials/s)"<<endl;
1366 if(score>mMinScoreReport*.5)
1369 mRecUnitCell=bestpos->first;
1370 this->LSQRefine(10,
true,
true);
1371 par=mRecUnitCell.DirectUnitCell();
1372 score=
Score(*mpPeakList,mRecUnitCell,mNbSpurious,
false,
true);
1373 cout<<__FILE__<<
":"<<__LINE__<<
" Best-LSQ: a="<<par[0]<<
", b="<<par[1]<<
", c="<<par[2]<<
", alpha="
1374 <<par[3]*RAD2DEG<<
", beta="<<par[4]*RAD2DEG<<
", gamma="<<par[5]*RAD2DEG<<
", V="<<par[6]
1375 <<
", score="<<score<<endl;
1376 if((score>mMinScoreReport)&&(score>(mBestScore/3)))
1378 if(score>mBestScore) mBestScore=score;
1379 mvSolution.push_back(make_pair(mRecUnitCell,score));
1380 mvSolution.back().first.mNbSpurious = mNbSpurious;
1381 this->ReduceSolutions(
true);
1386 void CellExplorer::SetLengthMinMax(
const float min,
const float max)
1391 void CellExplorer::SetAngleMinMax(
const float min,
const float max)
1396 void CellExplorer::SetVolumeMinMax(
const float min,
const float max)
1401 void CellExplorer::SetNbSpurious(
const unsigned int nb)
1405 void CellExplorer::SetMinMaxZeroShift(
const float min,
const float max)
1411 void CellExplorer::SetCrystalSystem(
const CrystalSystem system)
1416 void CellExplorer::SetCrystalCentering(
const CrystalCentering cent)
1421 void CellExplorer::SetD2Error(
const float err){mD2Error=err;}
1423 const string& CellExplorer::GetClassName()
const
1425 const static string className=
"CellExplorer";
1428 const string& CellExplorer::GetName()
const
1430 const static string name=
"Some CellExplorer Object";
1433 void CellExplorer::Print()
const
1435 this->RefinableObj::Print();
1437 unsigned int CellExplorer::GetNbLSQFunction()
const
1440 const CrystVector_REAL& CellExplorer::GetLSQCalc(
const unsigned int)
const
1442 VFN_DEBUG_ENTRY(
"CellExplorer::GetLSQCalc()",2)
1444 for(vector<PeakList::hkl>::const_iterator pos=mpPeakList->GetPeakList().begin();pos!=mpPeakList->GetPeakList().end();++pos)
1447 mCalc(j++)=mRecUnitCell.hkl2d(pos->h,pos->k,pos->l);
1450 VFN_DEBUG_EXIT(
"CellExplorer::GetLSQCalc()",2)
1453 const CrystVector_REAL& CellExplorer::GetLSQObs(
const unsigned int)
const
1455 VFN_DEBUG_MESSAGE(
"CellExplorer::GetLSQObs()",2)
1458 const CrystVector_REAL& CellExplorer::GetLSQWeight(
const unsigned int)
const
1460 VFN_DEBUG_MESSAGE(
"CellExplorer::GetLSQWeight()",2)
1464 const CrystVector_REAL& CellExplorer::GetLSQDeriv(
const unsigned int,
RefinablePar &refpar)
1466 VFN_DEBUG_ENTRY(
"CellExplorer::GetLSQDeriv()",2)
1468 if(refpar.
GetName()==
"Reciprocal unit cell par #0") par=mRecUnitCell.par+1;
1470 if(refpar.
GetName()==
"Reciprocal unit cell par #1") par=mRecUnitCell.par+2;
1472 if(refpar.
GetName()==
"Reciprocal unit cell par #2") par=mRecUnitCell.par+3;
1474 if(refpar.
GetName()==
"Reciprocal unit cell par #3") par=mRecUnitCell.par+4;
1476 if(refpar.
GetName()==
"Reciprocal unit cell par #4") par=mRecUnitCell.par+5;
1478 if(refpar.
GetName()==
"Reciprocal unit cell par #5") par=mRecUnitCell.par+6;
1480 if(refpar.
GetName()==
"Zero") par=mRecUnitCell.par+0;
1481 else cout<<__FILE__<<
":"<<__LINE__<<
":Parameter not found:"<<refpar.
GetName()<<endl;
1483 for(vector<PeakList::hkl>::const_iterator pos=mpPeakList->GetPeakList().begin();pos!=mpPeakList->GetPeakList().end();++pos)
1485 VFN_DEBUG_MESSAGE(
"CellExplorer::GetLSQDeriv():"<<j<<
"/"<<mpPeakList->GetPeakList().size(),2)
1486 VFN_DEBUG_MESSAGE(
"CellExplorer::GetLSQDeriv():"<<pos->h<<
","<<pos->k<<
","<<pos->l,2)
1488 mDeriv(j++)=mRecUnitCell.hkl2d(pos->h,pos->k,pos->l,par);
1490 VFN_DEBUG_EXIT(
"CellExplorer::GetLSQDeriv()",2)
1494 void CellExplorer::BeginOptimization(
const bool allowApproximations,
const bool enableRestraints)
1496 VFN_DEBUG_ENTRY(
"CellExplorer::BeginOptimization()",5)
1497 Score(*mpPeakList,mRecUnitCell,mNbSpurious,
false,
true,
false);
1498 const unsigned int nb=mpPeakList->GetPeakList().size();
1499 mCalc.resize(nb-mNbSpurious);
1500 mObs.resize(nb-mNbSpurious);
1501 mWeight.resize(nb-mNbSpurious);
1502 mDeriv.resize(nb-mNbSpurious);
1505 for(vector<PeakList::hkl>::const_iterator pos=mpPeakList->GetPeakList().begin();pos!=mpPeakList->GetPeakList().end();++pos)
1506 if(thres<pos->iobs) thres=pos->iobs;
1511 for(vector<PeakList::hkl>::const_iterator pos=mpPeakList->GetPeakList().begin();pos!=mpPeakList->GetPeakList().end();++pos)
1516 if(mObs(j)>thres) mWeight(j)=1;
1517 else mWeight(j)=mObs(j)/thres;
1537 this->RefinableObj::BeginOptimization(allowApproximations,enableRestraints);
1538 VFN_DEBUG_EXIT(
"CellExplorer::BeginOptimization()",5)
1541 void CellExplorer::LSQRefine(
int nbCycle,
bool useLevenbergMarquardt,
const bool silent)
1543 if(mNbLSQExcept>100)
1545 if(!silent) cout<<
"CellExplorer::LSQRefine(): LSQ was disabled, too many (>100) exceptions caught. Weird unit cell parameters ?";
1548 VFN_DEBUG_ENTRY(
"CellExplorer::LSQRefine()",5)
1549 mLSQObj.SetRefinedObj(*this);
1550 mLSQObj.PrepareRefParList(true);
1553 try {mLSQObj.Refine(nbCycle,useLevenbergMarquardt,silent);}
1554 catch(
const ObjCrystException &except)
1556 if(++mNbLSQExcept>100) cout<<
"WARNING CellExplorer::LSQRefine(): LSQ was disabled, too many (>100) exceptions caught. Weird unit cell parameters ?"<<endl ;
1558 if(!silent) mpPeakList->Print(cout);
1559 VFN_DEBUG_EXIT(
"CellExplorer::LSQRefine()",5)
1576 const unsigned int nbUnindexed=0,
const bool verbose=
false,
unsigned int useStoredHKL=0,
1577 const unsigned int maxNbMissingBelow5=0)
1580 int nbIndexed=nb-nbUnindexed;
1582 if(maxNbMissingBelow5>0) d5=dhkl.
GetPeakList()[4].d2obs;
1584 unsigned int nbMissingBelow5=0;
1586 vector<PeakList::hkl>::const_iterator pos,first,last,end;
1589 unsigned int nbUnIx = 0;
1592 pos->isIndexed=
false;
1593 for(list<PeakList::hkl0>::const_iterator phkl0=pos->vDicVolHKL.begin();phkl0!=pos->vDicVolHKL.end();++phkl0)
1596 par.
hkl2d_delta(phkl0->h,phkl0->k,phkl0->l,dpar,d0,d1);
1597 if((pos->d2obsmax>=d0) && (d1>=pos->d2obsmin))
1599 pos->d2calc=(d0+d1)/2;
1600 pos->isIndexed=
true;
1601 if(--nbIndexed==0)
return true;
1605 if(!(pos->isIndexed))
if(++nbUnIx>nbUnindexed)
return false;
1609 const bool storePossibleHKL=(useStoredHKL==2);
1611 if(storePossibleHKL)
1614 pos->isIndexed=
false;
1615 pos->vDicVolHKL.clear();
1626 switch(par.mlattice)
1656 switch(par.mCentering)
1658 case LATTICE_P:stepk=1;stepl=1;
break;
1659 case LATTICE_I:stepk=1;stepl=2;
break;
1660 case LATTICE_A:stepk=1;stepl=2;
break;
1661 case LATTICE_B:stepk=1;stepl=2;
break;
1662 case LATTICE_C:stepk=2;stepl=1;
break;
1663 case LATTICE_F:stepk=2;stepl=2;
break;
1673 unsigned long nbCalcH,nbCalcK;
1676 if(verbose) cout<<
"H="<<h<<endl;
1678 for(
int sk=sk0;sk<=1;sk+=2)
1681 if(stepk==2) k=(h%2);
1685 if(verbose) cout<<
"K="<<k*sk<<endl;
1687 for(
int sl=sl0;sl<=1;sl+=2)
1699 if(par.mlattice==MONOCLINIC) sl=1;
1700 if((sk<0)||(sl<0)) l0=1;
1711 if(par.mCentering==LATTICE_I) l0+=(h+k+l0)%2;
1712 if(par.mCentering==LATTICE_A) l0+=(k+l0)%2;
1713 if( (par.mCentering==LATTICE_B)
1714 ||(par.mCentering==LATTICE_F)) l0+=(h+l0)%2;
1716 if(verbose) cout<<
"SL="<<sl<<
", L0="<<l0<<
", STEPL="<<stepl<<
", Centering="<<par.mCentering<<endl;
1719 if(verbose) cout<<
"L="<<l<<
","<<sl<<endl;
1722 if(d0<dmax) {nbCalcH++;nbCalcK++;}
1723 if((d1<dmin)&&(maxNbMissingBelow5==0))
continue;
1726 if(par.mlattice==TRICLINIC)
1729 if(verbose) cout<<
"L?="<< par.
hkl2d(h,sk*k,sl*l,NULL,3)*sl <<
", dmax="<<dmax<<endl;
1730 if((par.
hkl2d(h,sk*k,sl*l,NULL,3)*sl)>0)
break;
1734 bool missing=(d0<d5)&&(maxNbMissingBelow5>0);
1735 for(pos=first;pos!=end;++pos)
1737 if(pos==last)
break;
1738 if((!storePossibleHKL)&&(pos->isIndexed)&&missing)
continue;
1739 const float d2obs=pos->d2obs,d2obsmin=pos->d2obsmin, d2obsmax=pos->d2obsmax;
1740 if((d2obsmax>=d0) && (d1>=d2obsmin))
1743 if(!(pos->isIndexed))
1745 pos->d2calc=(d0+d1)/2;
1747 pos->isIndexed=
true;
1749 if(verbose) cout<<d1<<
" < ? <"<<d0<<
"("<<h<<
","<<sk*k<<
","<<sl*l<<
"): "<<d2obs<<
" (remaining to index:"<<nbIndexed<<
")"<<endl;
1750 if(storePossibleHKL)
1754 if((!storePossibleHKL)&&(nbIndexed==0))
return true;
1755 if(pos==first){first++;dmin=first->d2obsmin;}
1756 if(pos==last){last--;dmax=last->d2obsmax;}
1760 if(missing)
if(++nbMissingBelow5>=maxNbMissingBelow5)
return false;
1763 if(nbCalcK==0)
break;
1766 if(nbCalcH==0)
break;
1772 return nbIndexed<=0;
1775 float CellExplorer::GetBestScore()
const{
return mBestScore;}
1776 const std::list<std::pair<RecUnitCell,float> >& CellExplorer::GetSolutions()
const {
return mvSolution;}
1777 std::list<std::pair<RecUnitCell,float> >& CellExplorer::GetSolutions() {
return mvSolution;}
1779 unsigned int CellExplorer::RDicVol(RecUnitCell par0,RecUnitCell dpar,
unsigned int depth,
unsigned long &nbCalc,
const float minV,
const float maxV,vector<unsigned int> vdepth)
1781 static bool localverbose=
false;
1782 if(mlattice==TRICLINIC)
1784 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];
1785 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];
1786 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];
1789 if((p1m>p2p)||(p2m>p3p))
return 0;
1792 if((p4m>p1p)||(-p4p>p1p))
return 0;
1793 if((p5m>p2p)||(-p5p>p2p))
return 0;
1794 if((p6m>p1p)||(-p6p>p1p))
return 0;
1796 const float max6=p1p+p2p-p4m-p5m;
1797 if((p6m>max6)||(-p6p>max6))
return 0;
1799 float p6mm,p6pp,p5mm,p5pp,p4mm,p4pp;
1801 if((p4*p5-2*p2*p6)>0) {p6pp=p6p;p6mm=p6m;}
1802 else{p6pp=p6m;p6mm=p6p;}
1804 if((p4*p6-2*p1*p5)>0) {p5pp=p5p;p5mm=p5m;}
1805 else{p5pp=p5m;p5mm=p5p;}
1807 if((p5*p6-2*p3*p4)>0) {p4pp=p4p;p4mm=p4m;}
1808 else{p4pp=p4m;p4mm=p4p;}
1812 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))));
1813 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))));
1814 if((vmin0>maxV)||(vmax0<minV))
return 0;
1817 if((depth>0)&&(depth<=2))
1819 RecUnitCell parm=par0,parp=par0;
1820 for(
unsigned int i=0;i<6;++i) {parm.par[i]-=dpar.par[i];parp.par[i]+=dpar.par[i];}
1821 vector<float> parmd=parm.DirectUnitCell();
1822 vector<float> parpd=parp.DirectUnitCell();
1823 if((parpd[6]>maxV)||(parmd[6]<minV))
return 0;
1825 unsigned int useStoredHKL=1;
1826 if(depth==0) useStoredHKL=2;
1828 unsigned int maxMissingBelow5=0;
1830 if(mlattice==TRICLINIC) maxMissingBelow5=5;
1832 bool indexed=
DichoIndexed(*mpPeakList,par0,dpar,mNbSpurious,localverbose,useStoredHKL,maxMissingBelow5);
1836 if( (!indexed) && (depth>=4))
1839 indexed=
DichoIndexed(*mpPeakList,par0,dpar,mNbSpurious,
false,useStoredHKL,maxMissingBelow5);
1844 if((indexed)&&(useStoredHKL==2))
1847 unsigned int nbident=0;
1848 for(vector<PeakList::hkl>::const_iterator pos=mpPeakList->GetPeakList().begin();pos!=mpPeakList->GetPeakList().end();)
1850 if(pos->vDicVolHKL.size()==1)
1852 const PeakList::hkl0 h0=pos->vDicVolHKL.front();
1853 if(++pos==mpPeakList->GetPeakList().end())
break;
1854 if(pos->vDicVolHKL.size()==1)
1856 const PeakList::hkl0 h1=pos->vDicVolHKL.front();
1857 if((h0.h==h1.h)&&(h0.k==h1.k)&&(h0.l==h1.l)) nbident++;
1858 if(nbident>mNbSpurious) {indexed=
false;
break;}
1866 if(vdepth.size()==0)
1868 vdepth.resize(mnpar-1);
1869 for(vector<unsigned int>::iterator pos=vdepth.begin();pos!=vdepth.end();) *pos++=depth;
1872 for(vector<unsigned int>::iterator pos=vdepth.begin();pos!=vdepth.end();++pos)
if(*pos<depth)*pos=depth;
1877 vector<pair<unsigned int,float> > vq0(3);
1878 for(
unsigned int i=0;i<3;++i) {vq0[i].first=0;vq0[i].second=0.0;}
1879 RecUnitCell par0orig=par0,dparorig=dpar;
1880 for(vector<PeakList::hkl>::const_iterator pos=mpPeakList->GetPeakList().begin();pos!=mpPeakList->GetPeakList().end();++pos)
1882 if(pos->vDicVolHKL.size()==1)
1884 const PeakList::hkl0 h0=pos->vDicVolHKL.front();
1885 if((h0.k==0)&&(h0.l==0)) {vq0[0].first+=1 ; vq0[0].second+=pos->dobs/h0.h;}
1887 if((h0.h==0)&&(h0.l==0)) {vq0[1].first+=1 ; vq0[1].second+=pos->dobs/h0.k;}
1889 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;}
1896 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;}
1897 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;}
1898 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;}
1903 if(vq0[0].first>0) {par0.par[1]=vq0[0].second/vq0[0].first ; vdepth[0]=mDicVolDepthReport;dpar.par[1]*=.0625;}
1904 if(vq0[1].first>0) {par0.par[2]=vq0[1].second/vq0[1].first ; vdepth[1]=mDicVolDepthReport;dpar.par[2]*=.0625;}
1905 if(vq0[2].first>0) {par0.par[3]=vq0[2].second/vq0[2].first ; vdepth[2]=mDicVolDepthReport;dpar.par[3]*=.0625;}
1910 if(vq0[0].first>0) {par0.par[1]=vq0[0].second/vq0[0].first ; vdepth[0]=mDicVolDepthReport;dpar.par[1]*=.0625;}
1911 if(vq0[1].first>0) {par0.par[2]=vq0[1].second/vq0[1].first ; vdepth[1]=mDicVolDepthReport;dpar.par[2]*=.0625;}
1912 if(vq0[2].first>0) {par0.par[3]=vq0[2].second/vq0[2].first ; vdepth[2]=mDicVolDepthReport;dpar.par[3]*=.0625;}
1915 case HEXAGONAL:
break;
1916 case RHOMBOEDRAL:
break;
1917 case TETRAGONAL:
break;
1921 unsigned int newdepth=40;
1922 for(vector<unsigned int>::iterator pos=vdepth.begin();pos!=vdepth.end();++pos)
if(*pos<newdepth) newdepth=*pos;
1923 if(newdepth>depth) depth=newdepth;
1924 if((vq0[0].first>0)||(vq0[1].first>0)||(vq0[2].first>0))
1926 indexed=
DichoIndexed(*mpPeakList,par0,dpar,mNbSpurious,
false,1,maxMissingBelow5);
1930 RecUnitCell parm=par0orig,parp=par0;
1931 for(
unsigned int i=0;i<6;++i) {parm.par[i]-=dparorig.par[i];parp.par[i]+=dparorig.par[i];}
1932 vector<float> parmd=parm.DirectUnitCell();
1933 vector<float> parpd=parp.DirectUnitCell();
1935 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",
1936 parpd[0],parmd[0],parpd[1],parmd[1],parpd[2],parmd[2],parpd[3]*RAD2DEG,parmd[3]*RAD2DEG,
1937 parpd[4]*RAD2DEG,parmd[4]*RAD2DEG,parpd[5]*RAD2DEG,parmd[5]*RAD2DEG,parpd[6],parmd[6]);
1938 for(
unsigned int i = 0; i < depth; ++i) cout <<
" ";
1939 cout<<buf<<
"level="<<depth<<
", indexed="<<indexed<<endl;
1942 RecUnitCell parm=par0,parp=par0;
1943 for(
unsigned int i=0;i<6;++i) {parm.par[i]-=dpar.par[i];parp.par[i]+=dpar.par[i];}
1944 vector<float> parmd=parm.DirectUnitCell();
1945 vector<float> parpd=parp.DirectUnitCell();
1947 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",
1948 parpd[0],parmd[0],parpd[1],parmd[1],parpd[2],parmd[2],parpd[3]*RAD2DEG,parmd[3]*RAD2DEG,
1949 parpd[4]*RAD2DEG,parmd[4]*RAD2DEG,parpd[5]*RAD2DEG,parmd[5]*RAD2DEG,parpd[6],parmd[6]);
1950 for(
unsigned int i = 0; i < depth; ++i) cout <<
" ";
1951 cout<<buf<<
"level="<<depth<<
", indexed="<<indexed<<endl;
1959 RecUnitCell parm=par0,parp=par0;
1960 for(
unsigned int i=0;i<4;++i) {parm.par[i]-=dpar.par[i];parp.par[i]+=dpar.par[i];}
1961 for(
unsigned int i=4;i<7;++i) {parm.par[i]+=dpar.par[i];parp.par[i]-=dpar.par[i];}
1962 vector<float> parmd=parm.DirectUnitCell();
1963 vector<float> parpd=parp.DirectUnitCell();
1965 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",
1966 parpd[0],parmd[0],parpd[1],parmd[1],parpd[2],parmd[2],parpd[3]*RAD2DEG,parmd[3]*RAD2DEG,
1967 parpd[4]*RAD2DEG,parmd[4]*RAD2DEG,parpd[5]*RAD2DEG,parmd[5]*RAD2DEG,parpd[6],parmd[6]);
1968 for(
unsigned int i = 0; i < depth; ++i) cout <<
" ";
1969 cout<<buf<<
"level="<<depth<<
", indexed="<<indexed<<
"("<<mvSolution.size()<<
" sol.)"<<endl;
1988 unsigned int deeperSolutions=0;
1989 if(depth<mMaxDicVolDepth)
1993 RecUnitCell parm=par0,parp=par0;
1994 for(
unsigned int i=0;i<6;++i) {parm.par[i]-=dpar.par[i];parp.par[i]+=dpar.par[i];}
1995 vector<float> parmd=parm.DirectUnitCell();
1996 vector<float> parpd=parp.DirectUnitCell();
1998 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",
1999 parpd[0],parmd[0],parpd[1],parmd[1],parpd[2],parmd[2],parpd[3]*RAD2DEG,parmd[3]*RAD2DEG,
2000 parpd[4]*RAD2DEG,parmd[4]*RAD2DEG,parpd[5]*RAD2DEG,parmd[5]*RAD2DEG,parpd[6],parmd[6]);
2001 for(
unsigned int i=0;i<depth;++i) cout<<
" ";
2002 cout<<
"Depth="<<depth<<
" "<<buf<<endl;
2003 for(
int i=0;i<=6;++i)cout<<par0.par[i]<<
",";
2004 for(
int i=0;i<=6;++i)cout<<dpar.par[i]<<
",";
2007 RecUnitCell par=par0;
2009 dpar.par[0]=0.5*dpar.par[0];
2012 for(
unsigned int i=1;i<mnpar;++i) dpar.par[i]*=(0.5+0.5*(vdepth[i-1]>depth));
2014 for(
int i0=-1;i0<=1;i0+=2)
2017 if(localverbose) cout<<__FILE__<<
":"<<__LINE__<<
":"<<par.par[3]<<
" +/- "<<dpar.par[3]<<
" ("<<vdepth[2]<<
")"<<endl;
2019 if(vdepth[0]==depth) {par.par[1]=par0.par[1]+i0*dpar.par[1];}
2022 deeperSolutions+=RDicVol(par,dpar, depth+1,nbCalc,minV,maxV,vdepth);
2024 for(
int i1=-1;i1<=1;i1+=2)
2026 if(vdepth[1]==depth) {par.par[2]=par0.par[2]+i1*dpar.par[2];}
2029 deeperSolutions+=RDicVol(par,dpar, depth+1,nbCalc,minV,maxV,vdepth);
2031 for(
int i2=-1;i2<=1;i2+=2)
2033 if(vdepth[2]==depth) {par.par[3]=par0.par[3]+i2*dpar.par[3];}
2036 deeperSolutions+=RDicVol(par,dpar, depth+1,nbCalc,minV,maxV,vdepth);
2038 for(
int i3=-1;i3<=1;i3+=2)
2040 if(vdepth[3]==depth)par.par[4]=par0.par[4]+i3*dpar.par[4];
2043 deeperSolutions+=RDicVol(par,dpar, depth+1,nbCalc,minV,maxV,vdepth);
2045 for(
int i4=-1;i4<=1;i4+=2)
2047 par.par[5]=par0.par[5]+i4*dpar.par[5];
2051 for(
int i5=-1;i5<=1;i5+=2)
2053 par.par[6]=par0.par[6]+i5*dpar.par[6];
2055 deeperSolutions+=RDicVol(par,dpar, depth+1,nbCalc,minV,maxV,vdepth);
2063 if((deeperSolutions==0) &&(depth>=mDicVolDepthReport))
2066 vector<float> par=mRecUnitCell.DirectUnitCell();
2067 float score=
Score(*mpPeakList,mRecUnitCell,mNbSpurious,
false,
true,
false);
2070 if(depth<(mMaxDicVolDepth-1))
2071 if(mvNbSolutionDepth[depth+2]>100)report=
false;
2072 if(report && (((score>(mMinScoreReport*.5))&&(depth>=mDicVolDepthReport)) || (depth>=mMaxDicVolDepth)))
2075 cout<<__FILE__<<
":"<<__LINE__<<
" Depth="<<depth<<
" (DIC) ! a="<<par[0]<<
", b="<<par[1]<<
", c="<<par[2]<<
", alpha="
2076 <<par[3]*RAD2DEG<<
", beta="<<par[4]*RAD2DEG<<
", gamma="<<par[5]*RAD2DEG<<
", V="<<par[6]
2077 <<
", score="<<score<<endl;
2078 this->LSQRefine(5,
true,
true);
2081 score=
Score(*mpPeakList,mRecUnitCell,mNbSpurious,
false,
true,
false);
2082 this->LSQRefine(5,
true,
true);
2084 par=mRecUnitCell.DirectUnitCell();
2085 score=
Score(*mpPeakList,mRecUnitCell,mNbSpurious,
false,
true,
false);
2086 if( ((score>mMinScoreReport)||(depth>=mDicVolDepthReport))
2087 &&((mvSolution.size()<50)||(score>(mBestScore/3)))
2088 &&((mvSolution.size()<50)||(score>mMinScoreReport)))
2090 if((score>(mBestScore))||((score>(mBestScore*0.8))&&(mvSolution.size()<50)))
2094 RecUnitCell parm=par0,parp=par0;
2095 for(
unsigned int i=0;i<4;++i) {parm.par[i]-=dpar.par[i];parp.par[i]+=dpar.par[i];}
2096 for(
unsigned int i=4;i<7;++i) {parm.par[i]+=dpar.par[i];parp.par[i]-=dpar.par[i];}
2097 vector<float> parmd=parm.DirectUnitCell();
2098 vector<float> parpd=parp.DirectUnitCell();
2099 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",
2100 parpd[0],parmd[0],parpd[1],parmd[1],parpd[2],parmd[2],parpd[3]*RAD2DEG,parmd[3]*RAD2DEG,
2101 parpd[4]*RAD2DEG,parmd[4]*RAD2DEG,parpd[5]*RAD2DEG,parmd[5]*RAD2DEG,parpd[6],parmd[6]);
2102 for(
unsigned int i = 0; i < depth; ++i) cout <<
" ";
2104 cout<<buf<<
"level="<<depth<<
", indexed="<<indexed<<
"("<<mvSolution.size()<<
" sol.)"<<endl;
2105 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",
2106 parp.par[1],parm.par[1],parp.par[2],parm.par[2],parp.par[3],parm.par[3],parp.par[4],parm.par[4],
2107 parp.par[5],parm.par[5],parp.par[6],parm.par[6]);
2108 for(
unsigned int i = 0; i < depth; ++i) cout <<
" ";
2109 cout<<buf<<
"level="<<depth<<
", indexed="<<indexed<<
"("<<mvSolution.size()<<
" sol.)"<<endl;
2111 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",
2112 par[0],par[1],par[2],par[3]*RAD2DEG,par[4]*RAD2DEG,par[5]*RAD2DEG,par[6],score,mvSolution.size());
2116 mvSolution.push_back(make_pair(mRecUnitCell,score));
2117 mvSolution.back().first.mNbSpurious = mNbSpurious;
2118 mvNbSolutionDepth[depth]+=1;
2119 if((mvSolution.size()>1100)&&(rand()%1000==0))
2121 cout<<mvSolution.size()<<
" solutions ! Redparing..."<<endl;
2122 this->ReduceSolutions(
true);
2123 cout<<
"-> "<<mvSolution.size()<<
" remaining"<<endl;
2128 return deeperSolutions+1;
2133 vector<float> linspace(
float min,
float max,
unsigned int nb)
2135 vector<float> v(nb);
2136 for(
unsigned int i=0;i<nb;++i) v[i]=min+(max-min)*i/(nb-1);
2140 void CellExplorer::DicVol(
const float minScore,
const unsigned int minDepth,
const float stopOnScore,
const unsigned int stopOnDepth)
2143 mDicVolDepthReport=minDepth;
2144 mMinScoreReport=minScore;
2146 if(minDepth>mMaxDicVolDepth) mMaxDicVolDepth=minDepth;
2147 mvNbSolutionDepth.resize(mMaxDicVolDepth+1);
2148 for(
unsigned int i=0;i<=mMaxDicVolDepth;++i) mvNbSolutionDepth[i]=0;
2151 vstep=(mVolumeMax-mVolumeMin)/(ceil((mVolumeMax-mVolumeMin)/500)-0.0001);
2152 mCosAngMax=abs(cos(mAngleMax));
2153 const float cosangstep=mCosAngMax/(ceil(mCosAngMax/.08)-.0001);
2154 if(((mVolumeMax-mVolumeMin)/vstep)>10) vstep=(mVolumeMax-mVolumeMin)/9.999;
2155 if(((mLengthMax-mLengthMin)/latstep)>25) latstep=(mLengthMax-mLengthMin)/24.9999;
2157 cout<<mLengthMin<<
"->"<<mLengthMax<<
","<<latstep<<
","<<(mLengthMax-mLengthMin)/latstep<<endl;
2158 cout<<mAngleMin<<
"->"<<mAngleMax<<
","<<cosangstep<<
","<<mCosAngMax<<
","<<(mAngleMax-mAngleMin)/cosangstep<<endl;
2159 cout<<mVolumeMin<<
"->"<<mVolumeMax<<
","<<vstep<<
","<<(mVolumeMax-mVolumeMin)/vstep<<endl;
2161 par0.mlattice=mlattice;
2162 dpar.mlattice=mlattice;
2163 par0.mCentering=mCentering;
2164 dpar.mCentering=mCentering;
2168 unsigned long nbCalc=0;
2171 list<pair<RecUnitCell,float> >::iterator bestpos;
2172 bool breakDepth=
false;
2175 for(
float minv=mVolumeMin;minv<mVolumeMax;minv+=vstep)
2177 float maxv=minv+vstep;
2178 if(maxv>mVolumeMax)maxv=mVolumeMax;
2179 cout<<
"Starting: V="<<minv<<
"->"<<maxv<<endl;
2180 const float minr=1/(mLengthMax*mLengthMax);
2181 const float maxr=1/(mLengthMin*mLengthMin);
2182 const float stepr=(maxr-minr)/24.999;
2184 for(
unsigned int i=0;i<=5;i++)
2188 case 0: p1=mpPeakList->GetPeakList()[0].d2obs ;p2=mpPeakList->GetPeakList()[1].d2obs ;
break;
2189 case 1: p1=mpPeakList->GetPeakList()[0].d2obs ;p2=mpPeakList->GetPeakList()[2].d2obs ;
break;
2190 case 2: p1=mpPeakList->GetPeakList()[1].d2obs/2;p2=mpPeakList->GetPeakList()[0].d2obs ;
break;
2191 case 3: p1=mpPeakList->GetPeakList()[1].d2obs/2;p2=mpPeakList->GetPeakList()[2].d2obs ;
break;
2192 case 4: p1=mpPeakList->GetPeakList()[2].d2obs/2;p2=mpPeakList->GetPeakList()[0].d2obs ;
break;
2193 case 5: p1=mpPeakList->GetPeakList()[2].d2obs/2;p2=mpPeakList->GetPeakList()[1].d2obs ;
break;
2197 cout<<
"Trying #"<<i<<
": a*="<<p1<<
", b*="<<p2<<endl;
2200 const float step3r=(max3r-min3r)/(ceil((max3r-min3r)/stepr)-.001);
2201 vector<unsigned int> vdepth(mnpar-1);
2202 for(vector<unsigned int>::iterator pos=vdepth.begin();pos!=vdepth.end();) *pos++=0;
2205 for(
float p3=min3r;p3<max3r;p3+=step3r)
2208 const float max4r=p3+step3r;
2209 const float step4r=max4r/(ceil(max4r/stepr)-.001);
2210 for(
float p4=0;p4<max4r;p4+=step4r)
2213 float max5r=(p2+stepr);
2214 const float step5r=max5r/(ceil(max5r/stepr)-.001);
2215 for(
float p5=0;p5<max5r;p5+=step5r)
2217 float max6r=(p1+stepr);
2218 const float step6r=max6r/(ceil(max6r/stepr)-.001);
2219 for(
float p6=-max6r;p6<max6r;p6+=step6r)
2222 dpar.par[1]=stepr*pow(
float(0.51),
int(vdepth[0]));
2223 dpar.par[2]=stepr*pow(
float(0.51),
int(vdepth[1]));
2224 dpar.par[3]=step3r*0.51;
2225 dpar.par[4]=step4r*0.51;
2226 dpar.par[5]=step5r*0.51;
2227 dpar.par[6]=step6r*0.51;
2232 par0.par[3]=p3+step3r/2;
2233 par0.par[4]=p4+step4r/2;
2234 par0.par[5]=p5+step5r/2;
2235 par0.par[6]=p6+step6r/2;
2240 RDicVol(par0,dpar,0,nbCalc,minv,maxv,vdepth);
2245 cout<<
"Finished trying: a*="<<p1<<
" A, b*="<<p2<<
" A, "<<nbCalc
2246 <<
" unit cells tested, "<<nbCalc/chrono.seconds()<<
" tests/s, Elapsed time="
2247 <<chrono.seconds()<<
"s, Best score="<<mBestScore<<
", "<<stopOnScore<<
", "<<breakDepth<<endl;
2250 for(
unsigned int i=stopOnDepth; i<mvNbSolutionDepth.size();++i)
2251 if(mvNbSolutionDepth[i]>1) {breakDepth=
true;
break;}
2252 if((mBestScore>stopOnScore)&&(breakDepth))
break;
2254 cout<<
"Finished triclinic QUICK tests for: V="<<minv<<
"->"<<maxv<<
" A^3, "<<nbCalc
2255 <<
" unit cells tested, "<<nbCalc/chrono.seconds()<<
" tests/s, Elapsed time="
2256 <<chrono.seconds()<<
"s, Best score="<<mBestScore<<endl;
2257 if((mBestScore>stopOnScore)&&(breakDepth))
break;
2259 if((mBestScore<stopOnScore)||(!breakDepth))
2260 for(
float minv=mVolumeMin;minv<mVolumeMax;minv+=vstep)
2262 float maxv=minv+vstep;
2263 if(maxv>mVolumeMax)maxv=mVolumeMax;
2264 cout<<
"Starting: V="<<minv<<
"->"<<maxv<<endl;
2269 const unsigned int nbstep=25;
2270 vector<float> v1=linspace(mLengthMin,mLengthMax,nbstep);
2271 const float lstep=v1[1]-v1[0];
2272 for(
unsigned int i1=0;i1<(nbstep-1);++i1)
2274 const float p1 =(1/(v1[i1]*v1[i1])+1/(v1[i1+1]*v1[i1+1]))/2;
2275 const float dp1=(1/(v1[i1]*v1[i1])-1/(v1[i1+1]*v1[i1+1]))/2;
2278 const unsigned int nb2=int((v1[i1+1]-mLengthMin)/lstep+2.001);
2279 vector<float> v2=linspace(mLengthMin,v1[i1+1],nb2);
2282 for(
unsigned int i2=0;i2<(nb2-1);++i2)
2284 const float p2 =(1/(v2[i2]*v2[i2])+1/(v2[i2+1]*v2[i2+1]))/2;
2285 const float dp2=(1/(v2[i2]*v2[i2])-1/(v2[i2+1]*v2[i2+1]))/2;
2287 const unsigned int nb3=int((v2[i2+1]-mLengthMin)/lstep+2.001);
2288 vector<float> v3=linspace(mLengthMin,v2[i2+1],nb3);
2289 for(
unsigned int i3=0;i3<(nb3-1);++i3)
2291 const float p3 =(1/(v3[i3]*v3[i3])+1/(v3[i3+1]*v3[i3+1]))/2;
2292 const float dp3=(1/(v3[i3]*v3[i3])-1/(v3[i3+1]*v3[i3+1]))/2;
2296 const float vmin3=1/sqrt((p1+dp1)*(p2+dp2)*(p3+dp3));
2297 const float vmax3=1/sqrt((p1-dp1)*(p2-dp2)*(p3-dp3))*2;
2298 if(vmax3<minv)
continue;
2299 if(vmin3>maxv)
continue;
2307 const unsigned int nb4=int((p1+dp1)/(4*dp1)+2.001);
2308 vector<float> v4=linspace(0,p1+dp1,nb4);
2309 for(
unsigned int i4=0;i4<(nb4-1);++i4)
2311 const float p4 =(v4[i4+1]+v4[i4])/2;
2312 const float dp4=(v4[i4+1]-v4[i4])/2;
2314 const unsigned int nb5=int((p2+dp2)/(4*dp2)+2.001);
2315 vector<float> v5=linspace(0,p2+dp2,nb5);
2316 for(
unsigned int i5=0;i5<(nb5-1);++i5)
2318 const float p5 =(v5[i5+1]+v5[i5])/2;
2319 const float dp5=(v5[i5+1]-v5[i5])/2;
2322 float vmax6=(p1+dp1)+(p2+dp2)-(p4-dp4)-(p5-dp5);
2323 if(vmax6>(p1+dp1)) vmax6=p1+dp1;
2324 if(vmax6<0)
continue;
2325 const unsigned int nb6=int((2*vmax6)/(4*dp1)+2.001);
2326 vector<float> v6=linspace(-vmax6,vmax6,nb6);
2328 for(
unsigned int i6=0;i6<(nb6-1);++i6)
2330 const float p6 =(v6[i6+1]+v6[i6])/2;
2331 const float dp6=(v6[i6+1]-v6[i6])/2;
2354 RDicVol(par0,dpar,0,nbCalc,minv,maxv);
2367 vector<float> parlarged,parsmalld;
2368 latstep=(mLengthMax-mLengthMin)/24.999;
2369 for(
float x4=0;x4<mCosAngMax+cosangstep;x4+=cosangstep)
2371 const float sinbeta=sqrt(abs(1-x4*x4));
2372 float x1=mLengthMin;
2373 for(;x1<mLengthMax;x1+=latstep)
2375 float x2=mLengthMin;
2376 for(;x2<mLengthMax;x2+=latstep)
2379 const float x3step=(mLengthMax-x1)/(ceil((mLengthMax-x1)/latstep)-0.001);
2380 for(;x3<mLengthMax;x3+=x3step)
2382 if((x3*x4)>x1)
break;
2383 dpar.par[1]=(1/(x1)-1/(x1+latstep))*0.5/sinbeta;
2384 dpar.par[2]=(1/(x2)-1/(x2+latstep))*0.5/sinbeta;
2385 dpar.par[3]=(1/(x3)-1/(x3+x3step ))*0.5/sinbeta;
2386 dpar.par[4]=cosangstep*0.5;
2389 par0.par[1]=(1/(x1)+1/(x1+latstep))*0.5/sinbeta;
2390 par0.par[2]=(1/(x2)+1/(x2+latstep))*0.5/sinbeta;
2391 par0.par[3]=(1/(x3)+1/(x3+x3step ))*0.5/sinbeta;
2392 par0.par[4]=x4+cosangstep*.5;
2394 const float smallv=x1*x2*x3*sinbeta;
2395 if(smallv>maxv)
break;
2396 const float largev=(x1+latstep)*(x2+latstep)*(x3+latstep)*(sinbeta+cosangstep);
2397 if(largev<minv)
continue;
2405 RDicVol(par0,dpar,0,nbCalc,minv,maxv);
2411 for(list<pair<RecUnitCell,float> >::iterator pos=mvSolution.begin();pos!=mvSolution.end();++pos)
2413 const float score=pos->second;
2414 if(score>bestscore) {bestscore=score;bestpos=pos;}
2416 bool breakDepth=
false;
2418 for(
unsigned int i=stopOnDepth; i<mvNbSolutionDepth.size();++i)
2419 if(mvNbSolutionDepth[i]>1) {breakDepth=
true;
break;}
2420 if((bestscore>stopOnScore)&&(breakDepth))
break;
2431 const float a=6.25,b=16.75,c=16.75;
2432 dpar.par[1]=(1/(a-.25)-1/(a+.25))*0.5;
2433 dpar.par[2]=(1/(b-.25)-1/(b+.25))*0.5;
2434 dpar.par[3]=(1/(c-.25)-1/(c+.25))*0.5;
2439 RDicVol(par0,dpar,0,nbCalc,minv,maxv);
2442 latstep=(mLengthMax-mLengthMin)/24.999;
2443 for(
float x1=mLengthMin;x1<mLengthMax;x1+=latstep)
2445 for(
float x2=x1;x2<mLengthMax;x2+=latstep)
2447 for(
float x3=x2;x3<mLengthMax;x3+=latstep)
2449 dpar.par[1]=(1/(x1)-1/(x1+latstep))*0.5;
2450 dpar.par[2]=(1/(x2)-1/(x2+latstep))*0.5;
2451 dpar.par[3]=(1/(x3)-1/(x3+latstep))*0.5;
2454 par0.par[1]=(1/(x1)+1/(x1+latstep))*0.5;
2455 par0.par[2]=(1/(x2)+1/(x2+latstep))*0.5;
2456 par0.par[3]=(1/(x3)+1/(x3+latstep))*0.5;
2458 const float vmin=x1*x2*x3,vmax=(x1+latstep)*(x2+latstep)*(x3+latstep);
2459 if(vmin>maxv)
break;
2460 if(vmax>=minv) RDicVol(par0,dpar,0,nbCalc,minv,maxv);
2462 if((x1*x2*x2)>maxv)
break;
2464 if((x1*x1*x1)>maxv)
break;
2470 vector<float> parlarged,parsmalld;
2471 latstep=(mLengthMax-mLengthMin)/24.999;
2472 for(
float x1=mLengthMin;;x1+=latstep)
2474 for(
float x2=mLengthMin;x2<(mLengthMax+latstep);x2+=latstep)
2476 dpar.par[1]=(1/(x1)-1/(x1+latstep))*0.5;
2477 dpar.par[2]=(1/(x2)-1/(x2+latstep))*0.5;
2480 par0.par[1]=(1/(x1)+1/(x1+latstep))*0.5;
2481 par0.par[2]=(1/(x2)+1/(x2+latstep))*0.5;
2484 for(
unsigned int i=0;i<6;++i) {parlarge.
par[i]-=dpar.par[i];parsmall.par[i]+=dpar.par[i];}
2486 parsmalld=parsmall.DirectUnitCell();
2493 if((parsmalld[6]<maxv)&&(parlarged[6]>minv))
2496 RDicVol(par0,dpar,0,nbCalc,minv,maxv);
2500 if(parlarged[0]>mLengthMax)
break;
2506 latstep=(mLengthMax-mLengthMin)/24.999;
2507 for(
float x1=mLengthMin;x1<(mLengthMax+latstep);x1+=latstep)
2509 for(
float x2=0;x2<mCosAngMax+cosangstep;x2+=cosangstep)
2511 dpar.par[1]=latstep/2*1.1;
2512 dpar.par[2]=cosangstep/2*1.1;
2515 par0.par[1]=x1-latstep/2*1.1;
2516 par0.par[2]=x2-cosangstep/2*1.1;
2517 vector<float> par=par0.DirectUnitCell();
2518 if((par[6]<maxv)&&(par[6]>minv))
2520 RDicVol(par0,dpar,0,nbCalc,minv,maxv);
2528 vector<float> parlarged,parsmalld;
2529 latstep=(mLengthMax-mLengthMin)/24.999;
2530 for(
float x1=mLengthMin;x1<mLengthMax;x1+=latstep)
2532 for(
float x2=mLengthMin;x2<mLengthMax;x2+=latstep)
2534 dpar.par[1]=(1/(x1)-1/(x1+latstep))*0.5;
2535 dpar.par[2]=(1/(x2)-1/(x2+latstep))*0.5;
2538 par0.par[1]=(1/(x1)+1/(x1+latstep))*0.5;
2539 par0.par[2]=(1/(x2)+1/(x2+latstep))*0.5;
2542 for(
unsigned int i=0;i<6;++i) {parlarge.
par[i]-=dpar.par[i];parsmall.par[i]+=dpar.par[i];}
2544 parsmalld=parsmall.DirectUnitCell();
2551 if((parsmalld[6]<maxv)&&(parlarged[6]>minv))
2553 RDicVol(par0,dpar,0,nbCalc,minv,maxv);
2555 if(parsmalld[6]>maxv)
break;
2557 if((x1*mLengthMin*mLengthMin)>maxv)
break;
2563 latstep=(mLengthMax-mLengthMin)/24.999;
2564 cout<<mLengthMax<<
","<<mLengthMin<<
","<<latstep<<endl;
2565 for(
float x1=mLengthMin;x1<(mLengthMax+latstep);x1+=latstep)
2567 dpar.par[1]=(1/(x1)-1/(x1+latstep))*0.5;
2570 par0.par[1]=(1/(x1)+1/(x1+latstep))*0.5;
2572 const float vmin=x1*x1*x1,vmax=(x1+latstep)*(x1+latstep)*(x1+latstep);
2574 if(vmax>minv) RDicVol(par0,dpar,0,nbCalc,minv,maxv);
2579 cout<<
"Finished: V="<<minv<<
"->"<<maxv<<
" A^3, "<<nbCalc
2580 <<
" unit cells tested, "<<nbCalc/chrono.seconds()<<
" tests/s, Elapsed time="
2581 <<chrono.seconds()<<
"s"<<endl;
2582 for(list<pair<RecUnitCell,float> >::iterator pos=mvSolution.begin();pos!=mvSolution.end();++pos)
2584 const float score=pos->second;
2585 if(score>bestscore) {bestscore=score;bestpos=pos;}
2587 bool breakDepth=
false;
2589 for(
unsigned int i=stopOnDepth; i<mvNbSolutionDepth.size();++i)
2590 if(mvNbSolutionDepth[i]>1) {breakDepth=
true;
break;}
2591 if((bestscore>stopOnScore)&&(breakDepth))
break;
2606 this->ReduceSolutions(
true);
2607 bestscore=0;bestpos=mvSolution.end();
2608 for(list<pair<RecUnitCell,float> >::iterator pos=mvSolution.begin();pos!=mvSolution.end();++pos)
2610 const float score=
Score(*mpPeakList,pos->first,mNbSpurious);
2611 if(score>bestscore) {bestpos=pos;bestscore=score;}
2612 vector<float> par=pos->first.DirectUnitCell();
2613 cout<<__FILE__<<
":"<<__LINE__<<
" Solution ? a="<<par[0]<<
", b="<<par[1]<<
", c="<<par[2]
2614 <<
", alpha="<<par[3]*RAD2DEG<<
", beta="<<par[4]*RAD2DEG<<
", gamma="<<par[5]*RAD2DEG
2615 <<
", V="<<par[6]<<
", score="<<score<<endl;
2617 if(bestpos!=mvSolution.end())
2619 vector<float> par=bestpos->first.DirectUnitCell();
2620 cout<<__FILE__<<
":"<<__LINE__<<
" BEST ? a="<<par[0]<<
", b="<<par[1]<<
", c="<<par[2]
2621 <<
", alpha="<<par[3]*RAD2DEG<<
", beta="<<par[4]*RAD2DEG<<
", gamma="<<par[5]*RAD2DEG
2622 <<
", V="<<par[6]<<
", score="<<bestscore<<endl;
2623 cout<<nbCalc<<
"unit cells tested, "<<nbCalc/chrono.seconds()<<
" tests/s, Elapsed time="
2624 <<chrono.seconds()<<
"s"<<endl;
2634 for(
unsigned int i=0;i<6;++i) diff += abs(par0[i]-par1[i]);
2635 return (diff/6)<delta;
2638 bool compareRUCScore(std::pair<RecUnitCell,float> &p1, std::pair<RecUnitCell,float> &p2)
2640 return p1.second > p2.second;
2643 void CellExplorer::ReduceSolutions(
const bool updateReportThreshold)
2645 const bool verbose=
false;
2646 std::list<std::pair<RecUnitCell,float> > vSolution2;
2649 for(list<pair<RecUnitCell,float> >::iterator pos=mvSolution.begin();pos!=mvSolution.end();)
2651 if(pos->second<(mBestScore/5)) pos=mvSolution.erase(pos);
2654 if(updateReportThreshold&& ((mBestScore/5)>mMinScoreReport))
2656 cout<<
"CellExplorer::ReduceSolutions(): update threshold for report from "
2657 <<mMinScoreReport<<
" to "<<mBestScore/5<<endl;
2658 mMinScoreReport=mBestScore/5;
2661 while(mvSolution.size()>0)
2663 vSolution2.push_back(mvSolution.front());
2664 mvSolution.pop_front();
2665 vector<float> par=vSolution2.back().first.DirectUnitCell();
2667 cout<<__FILE__<<
":"<<__LINE__<<
" SOLUTION: a="<<par[0]<<
", b="<<par[1]<<
", c="<<par[2]
2668 <<
", alpha="<<par[3]*RAD2DEG<<
", beta="<<par[4]*RAD2DEG<<
", gamma="<<par[5]*RAD2DEG
2669 <<
", V="<<par[6]<<
", score="<<vSolution2.back().second<<
", SIMILAR TO:"<<endl;
2670 for(list<pair<RecUnitCell,float> >::iterator pos=mvSolution.begin();pos!=mvSolution.end();)
2672 if(SimilarRUC(pos->first,vSolution2.back().first))
2674 par=pos->first.DirectUnitCell();
2676 cout<<__FILE__<<
":"<<__LINE__<<
" 1: a="<<par[0]<<
", b="<<par[1]<<
", c="<<par[2]
2677 <<
", alpha="<<par[3]*RAD2DEG<<
", beta="<<par[4]*RAD2DEG<<
", gamma="<<par[5]*RAD2DEG
2678 <<
", V="<<par[6]<<
", score="<<pos->second<<
" ("<<mvSolution.size()<<
")"<<endl;
2679 if(vSolution2.back().first.mlattice==pos->first.mlattice)
2681 if(pos->second>vSolution2.back().second) vSolution2.back()=*pos;
2683 else if(vSolution2.back().first.mlattice<pos->first.mlattice) vSolution2.back()=*pos;
2684 pos=mvSolution.erase(pos);
2688 par=pos->first.DirectUnitCell();
2690 cout<<__FILE__<<
":"<<__LINE__<<
" 0: a="<<par[0]<<
", b="<<par[1]<<
", c="<<par[2]
2691 <<
", alpha="<<par[3]*RAD2DEG<<
", beta="<<par[4]*RAD2DEG<<
", gamma="<<par[5]*RAD2DEG
2692 <<
", V="<<par[6]<<
", score="<<pos->second<<
" ("<<mvSolution.size()<<
")"<<endl;
2697 mvSolution=vSolution2;
2698 mvSolution.sort(compareRUCScore);
2701 if(mvSolution.size()>100)
2703 mvSolution.resize(100);
2704 if(updateReportThreshold && (mvSolution.back().second>mMinScoreReport))
2706 cout<<
"CellExplorer::ReduceSolutions(): update threshold for report from "
2707 <<mMinScoreReport<<
" to "<<mvSolution.back().second<<endl;
2708 mMinScoreReport=mvSolution.back().second;
2714 void CellExplorer::Init()
2720 vector<pair<RecUnitCell,float> >::iterator pos;
2721 const float min_latt=1./mLengthMax;
2722 const float max_latt=1./mLengthMin;
2723 const float amp_crossp=abs(cos(mAngleMax));
2725 mMin[0]=.00;mAmp[0]=.00;
2729 mMin[1]=min_latt;mAmp[1]=max_latt-min_latt;
2730 mMin[2]=min_latt;mAmp[2]=max_latt-min_latt;
2731 mMin[3]=min_latt;mAmp[3]=max_latt-min_latt;
2732 mMin[4]=0;mAmp[4]=amp_crossp;
2733 mMin[5]=0;mAmp[5]=amp_crossp;
2734 mMin[6]=0;mAmp[6]=amp_crossp;
2738 mMin[1]=min_latt;mAmp[1]=max_latt-min_latt;
2739 mMin[2]=min_latt;mAmp[2]=max_latt-min_latt;
2740 mMin[3]=min_latt;mAmp[3]=max_latt-min_latt;
2741 mMin[4]=0;mAmp[4]=amp_crossp;
2745 mMin[1]=min_latt;mAmp[1]=max_latt-min_latt;
2746 mMin[2]=min_latt;mAmp[2]=max_latt-min_latt;
2747 mMin[3]=min_latt;mAmp[3]=max_latt-min_latt;
2751 mMin[1]=min_latt;mAmp[1]=max_latt-min_latt;
2752 mMin[2]=min_latt;mAmp[2]=max_latt-min_latt;
2756 mMin[1]=min_latt;mAmp[1]=max_latt-min_latt;
2757 mMin[2]=-amp_crossp;mAmp[2]=2*amp_crossp;
2761 mMin[1]=min_latt;mAmp[1]=max_latt-min_latt;
2762 mMin[2]=min_latt;mAmp[2]=max_latt-min_latt;
2766 mMin[1]=min_latt;mAmp[1]=max_latt-min_latt;
2772 unsigned int nb1=0,nb2=0;
2813 this->ResetParList();
2815 RefinablePar tmp(
"Zero",mRecUnitCell.par+0,-0.01,0.01,gpRefParTypeObjCryst,REFPAR_DERIV_STEP_ABSOLUTE,
2816 true,
false,
true,
false);
2817 tmp.SetDerivStep(1e-4);
2821 string str=
"Reciprocal unit cell par #";
2822 for(
unsigned int i=0;i<nb1;++i)
2824 sprintf(buf,
"%i",i);
2825 RefinablePar tmp(str+(
string)buf,mRecUnitCell.par+i+1,
2826 0.01,1.,gpRefParTypeObjCryst,REFPAR_DERIV_STEP_ABSOLUTE,
2827 false,
false,
true,
false);
2828 tmp.SetDerivStep(1e-4);
2831 for(
unsigned int i=nb1;i<(nb1+nb2);++i)
2833 sprintf(buf,
"%i",i);
2834 RefinablePar tmp(str+(
string)buf,mRecUnitCell.par+i+1,
2835 0.0,0.5,gpRefParTypeObjCryst,REFPAR_DERIV_STEP_ABSOLUTE,
2836 false,
false,
true,
false);
2837 tmp.SetDerivStep(1e-4);
The namespace which includes all objects (crystallographic and algorithmic) in ObjCryst++.
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.
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 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.
CrystalSystem
Different lattice types.
Lightweight class describing the reciprocal unit cell, for the fast computation of d*_hkl^2.
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...
unsigned int mNbSpurious
The number of spurious lines used to match this RecUnitCell.
REAL par[7]
The 6 parameters defining 1/d_hkl^2 = d*_hkl^2, for different crystal classes, from: d*_hkl^2 = zero ...
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.
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, const unsigned int nbspurious=0)
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.
Class to store positions of observed reflections.
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, const bool merge=false)
Generate a list of simulated peak positions, from given lattice parameters.
vector< hkl > & GetPeakList()
Get peak list.
list< hkl > mvPredictedHKL
Full list of calculated HKL positions for a given solution, up to a given resolution After finding a ...
vector< hkl > mvHKL
Predict peak positions Best h,k,l for each observed peak (for least-squares refinement) This is store...
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.
One set of Miller indices, a possible indexation for a reflection.
One observed diffraction line, to be indexed.
Generic class for parameters of refinable objects.
string GetName() const
Get the parameter's name.
Simple chronometer class, with microsecond precision.