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==ORTHOROMBIC){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)
812 if(deg){alpha*=DEG2RAD;beta*=DEG2RAD;gamma*=DEG2RAD;}
813 const float v=sqrt(1-cos(alpha)*cos(alpha)-cos(beta)*cos(beta)-cos(gamma)*cos(gamma)
814 +2*cos(alpha)*cos(beta)*cos(gamma));
816 const float aa=sin(alpha)/a/v;
817 const float bb=sin(beta )/b/v;
818 const float cc=sin(gamma)/c/v;
820 const float alphaa=acos( (cos(beta )*cos(gamma)-cos(alpha))/sin(beta )/sin(gamma) );
821 const float betaa =acos( (cos(alpha)*cos(gamma)-cos(beta ))/sin(alpha)/sin(gamma) );
822 const float gammaa=acos( (cos(alpha)*cos(beta )-cos(gamma))/sin(alpha)/sin(beta ) );
824 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);
825 std::list<float> vd2;
827 for(
int h=0;h<=20;h++)
828 for(
int k=-20;k<=20;k++)
830 if((h==0) && (k<0)) k=0;
831 for(
int l=-20;l<=20;l++)
833 if((h==0) && (k==0) && (l<=0)) l=1;
834 vd2.push_back(sqrt(ruc.
hkl2d(h,k,l)));
838 std::list<float>::iterator pos=vd2.begin();
839 if(percentMissing>0.90) percentMissing=0.90;
840 for(;pos!=vd2.end();++pos)
842 if((rand()/
float(RAND_MAX))<percentMissing) *pos=1e10;
846 const float dmin=*pos/2;
847 for(
unsigned int i=0;i<nb;++i)pos++;
848 const float dmax=*pos;
850 for(
unsigned int i=0;i<nbspurious;++i)
852 const unsigned int idx=1+i*nb/nbspurious+(rand()%nbspurious);
854 for(
unsigned int j=0;j<idx;++j) pos++;
855 *pos=dmin+rand()/float(RAND_MAX)*(dmax-dmin);
859 for(
unsigned int i=0;i<nb;++i)
862 const float ds=d*sigma;
863 float d1=d+ds*(rand()/float(RAND_MAX)*2-1);
871 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);
872 cout<<
"PeakList::Simulate():"<<buf<<endl;
878 void PeakList::ExportDhklDSigmaIntensity(std::ostream &os)
const
880 for(vector<PeakList::hkl>::const_iterator pos=
mvHKL.begin();pos!=
mvHKL.end();++pos)
882 const float sigma=1/(pos->dobs-pos->dobssigma/2)-1/(pos->dobs+pos->dobssigma/2);
883 os<< std::fixed << setw(6) << setprecision(3) << 1/pos->dobs <<
" "<< sigma <<
" "<< std::scientific << pos->iobs <<endl;
887 void PeakList::AddPeak(
const float d,
const float iobs,
const float dobssigma,
const float iobssigma,
888 const int h,
const int k,
const int l,
const float d2calc)
893 for(vector<hkl>::const_iterator pos=
mvHKL.begin();pos!=
mvHKL.end();++pos)
896 if(s>0)
mvHKL.push_back(
hkl(d,iobs,s,iobssigma,h,k,l,d2calc));
897 else mvHKL.push_back(
hkl(d,iobs,1e-4,iobssigma,h,k,l,d2calc));
899 else mvHKL.push_back(
hkl(d,iobs,dobssigma,iobssigma,h,k,l,d2calc));
904 void PeakList::RemovePeak(
unsigned int idx)
910 void PeakList::Print(std::ostream &os)
const
914 os<<
"PeakList, with "<<
mvHKL.size()<<
" peaks"<<endl;
915 for(vector<PeakList::hkl>::const_iterator pos=
mvHKL.begin();pos!=
mvHKL.end();++pos)
917 const float sigma=1/(pos->dobs-pos->dobssigma/2)-1/(pos->dobs+pos->dobssigma/2);
919 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",
920 i++,1/pos->dobs,sigma,
921 1/sqrt(abs(pos->d2calc)),1/sqrt(abs(pos->d2calc))-1/pos->dobs,
922 pos->iobs,pos->h,pos->k,pos->l,pos->isSpurious,pos->stats);
924 sprintf(buf,
"#%3d d=%6.3f+/-%6.3f iobs=%6.3f UNINDEXED Spurious=%1d stats=%6lu",
925 i++,1/pos->dobs,1/(pos->dobs-pos->dobssigma/2)-1/(pos->dobs+pos->dobssigma/2),
926 pos->iobs,pos->isSpurious,pos->stats);
938 const bool verbose,
const bool storehkl,
const bool storePredictedHKL)
940 const bool autozero=
false;
941 vector<PeakList::hkl>::const_iterator pos,first,last;
944 if(storehkl) pos->isIndexed=
false;
951 unsigned long nbCalc=0;
953 float predict_coeff=1;
954 if(storePredictedHKL)predict_coeff=2;
955 const float dmax=dhkl.
mvHKL[nb-1].d2obs*predict_coeff*1.05;
957 switch(rpar.mlattice)
985 switch(rpar.mCentering)
987 case LATTICE_P:stepk=1;stepl=1;
break;
988 case LATTICE_I:stepk=1;stepl=2;
break;
989 case LATTICE_A:stepk=1;stepl=2;
break;
990 case LATTICE_B:stepk=1;stepl=2;
break;
991 case LATTICE_C:stepk=2;stepl=1;
break;
992 case LATTICE_F:stepk=2;stepl=2;
break;
997 unsigned long nbCalcH,nbCalcK;
1001 for(
int sk=sk0;sk<=1;sk+=2)
1004 if(stepk==2) k=(h%2);
1009 for(
int sl=sl0;sl<=1;sl+=2)
1020 if(rpar.mlattice==MONOCLINIC) sl=1;
1021 if((sk<0)||(sl<0)) l=1;
1032 if(rpar.mCentering==LATTICE_I) l+=(h+k+l)%2;
1033 if(rpar.mCentering==LATTICE_A) l+=(k+l)%2;
1034 if( (rpar.mCentering==LATTICE_B)
1035 ||(rpar.mCentering==LATTICE_F)) l+=(h+l)%2;
1039 const float d2=rpar.
hkl2d(h,sk*k,sl*l);
1044 if((sl*rpar.
hkl2d(h,sk*k,sl*l,NULL,3))>=0)
break;
1047 nbCalc++;nbCalcK++;nbCalcH++;
1048 if(storePredictedHKL)
1053 for(pos=first;pos!=last;++pos)
1055 const float tmp=d2-pos->d2obs;
1059 if(fabs(tmp)<fabs(pos->d2diff))
1067 pos->isIndexed=
true;
1083 if((sk*rpar.
hkl2d(h,sk*k,0,NULL,2))>=0)
break;
1087 if(nbCalcH==0)
break;
1089 float epsilon=0.0,zero=0.0;
1097 epsilon +=fabs(pos->d2diff-zero);
1101 list<pair<float,unsigned int> > vdiff_idx;
1104 vdiff_idx.push_back(make_pair(fabs(pos->d2diff),i++));
1105 vdiff_idx.sort(comparePairFirst<float,unsigned int>);
1107 for(list<pair<float,unsigned int> >::reverse_iterator rpos=vdiff_idx.rbegin();rpos!=vdiff_idx.rend();++rpos)
1109 epsilon -= fabs(rpos->first-zero);
1110 if(storehkl) dhkl.
GetPeakList()[rpos->second].isIndexed=
false;
1112 if(++i==nbSpurious)
break;
1121 epstmp+=fabs(pos->d2diff-zero);
1124 cout<<
"epsilon="<<epstmp<<
", dmax="<<dmax<<
" ,nb="<<nb<<
" ,nbcalc="<<nbCalc<<endl;
1138 if(nbCalc==0)
return 0;
1139 const float score=(dmax/predict_coeff)*nb/(2*epsilon*nbCalc);
1143 cout<<
"Final score:"<<score<<
", nbCalc="<<nbCalc<<
" ,<epsilon>="<<epsilon<<
" nb="<<nb<<
" Qn="<<sqrt(dmax)<<endl;
1150 CellExplorer::CellExplorer(
const PeakList &dhkl,
const CrystalSystem lattice,
const unsigned int nbSpurious):
1151 mnpar(3),mpPeakList(&dhkl),
1152 mLengthMin(4),mLengthMax(25),
1153 mAngleMin(M_PI),mAngleMax(2*M_PI/3),
1154 mVolumeMin(0),mVolumeMax(1600),
1155 mZeroShiftMin(0),mZeroShiftMax(0),
1156 mlattice(lattice),mCentering(LATTICE_P),mNbSpurious(nbSpurious),
1157 mObs(0),mCalc(0),mWeight(0),mDeriv(0),mBestScore(0.0),
1158 mMinScoreReport(10),mMaxDicVolDepth(6),mDicVolDepthReport(6),
1164 void CellExplorer::Evolution(
unsigned int ng,
const bool randomize,
const float f,
const float cr,
unsigned int np)
1167 const bool autozero=
true;
1170 vector<pair<RecUnitCell,float> > vRUC(np);
1171 vector<pair<RecUnitCell,float> > vTrial(np);
1172 float bestScore=-1e20;
1173 vector<pair<RecUnitCell,float> >::iterator bestpos=vRUC.begin();
1175 const clock_t mTime0=clock();
1179 for(
unsigned int i=0;i<vRUC.size();++i)
1181 vRUC[i].first.mlattice=mlattice;
1182 vTrial[i].first.mlattice=mlattice;
1183 for(
unsigned int k=0;k<mnpar;++k) vRUC[i].first.par[k]=mMin[k]+mAmp[k]*rand()/(float)RAND_MAX;
1184 vRUC[i].second=
Score(*mpPeakList,vRUC[i].first,mNbSpurious);
1188 for(
unsigned long i=ng;i>0;--i)
1190 for(
unsigned j=0;j<np;j++)
1194 unsigned int r1=j,r2=j,r3=j;
1195 while(r1==j)r1=rand()%np;
1196 while((r2==j)||(r1==r2))r2=rand()%np;
1197 while((r3==j)||(r3==r1)||(r3==r2))r3=rand()%np;
1198 unsigned int ncr=1+(int)(cr*mnpar*rand()/(float)RAND_MAX);
1199 unsigned int ncr0=rand()%mnpar;
1200 RecUnitCell *t0=&(vTrial[j].first);
1201 RecUnitCell *c0=&(vRUC[j].first);
1202 RecUnitCell *c1=&(vRUC[r1].first);
1203 RecUnitCell *c2=&(vRUC[r2].first);
1204 RecUnitCell *c3=&(vRUC[r3].first);
1205 for(
unsigned int k=0;k<mnpar;++k)t0->par[k] = c0->par[k];
1206 for(
unsigned int k=0;k<ncr;++k)
1208 const unsigned l=(ncr0+k)%mnpar;
1209 const float v1=c1->par[l]-mMin[l];
1210 const float v2=c2->par[l]-mMin[l];
1211 const float v3=c3->par[l]-mMin[l];
1212 t0->par[l]=mMin[l]+fmod(v1+f*(v2-v3)+3*mAmp[l],mAmp[l]);
1217 unsigned int r1=j,r2=j,r3=j;
1218 while(r1==j)r1=rand()%np;
1219 while((r2==j)||(r1==r2))r2=rand()%np;
1220 while((r3==j)||(r3==r1)||(r3==r2))r3=rand()%np;
1221 unsigned int ncr=1+(int)(cr*(mnpar-1)*rand()/(float)RAND_MAX);
1222 unsigned int ncr0=rand()%mnpar;
1223 RecUnitCell *t0=&(vTrial[j].first);
1224 RecUnitCell *c0=&(vRUC[j].first);
1226 RecUnitCell *c2=&(vRUC[r2].first);
1227 RecUnitCell *c3=&(vRUC[r3].first);
1228 RecUnitCell *best=&(bestpos->first);
1229 for(
unsigned int k=0;k<6;++k)t0->par[k] = c0->par[k];
1230 for(
unsigned int k=0;k<ncr;++k)
1232 const unsigned l=(ncr0+k)%mnpar;
1233 const float v0=c0->par[l]-mMin[l];
1235 const float v2=c2->par[l]-mMin[l];
1236 const float v3=c3->par[l]-mMin[l];
1237 const float vb=best->par[l]-mMin[l];
1238 t0->par[l]=mMin[l]+fmod(vb+f*(vb-v0)+f*(v2-v3)+5*mAmp[l],mAmp[l]);
1243 const float amp=.05/(1+i*.01);
1244 RecUnitCell *t0=&(vTrial[j].first);
1245 for(
unsigned int k=0;k<6;++k)
1248 t0->par[k] = mMin[k]+ fmod((
float)(amp*mAmp[k]*(rand()/(
float)RAND_MAX-0.5)+5*mAmp[k]),(
float)mAmp[k]);
1253 vector<pair<RecUnitCell,float> >::iterator posTrial,pos;
1254 posTrial=vTrial.begin();
1256 for(;posTrial!=vTrial.end();)
1259 if(autozero) posTrial->first.par[0]=0;
1267 float v0=posTrial->first.par[1]*posTrial->first.par[2]*posTrial->first.par[3];
1268 while(v0<1/mVolumeMax)
1270 const unsigned int i=rand()%3+1;
1271 posTrial->first.par[i]*=1/(mVolumeMax*v0)+1e-4;
1272 if(posTrial->first.par[i]>(mMin[i]+mAmp[i])) posTrial->first.par[i]=mMin[i]+mAmp[i];
1273 v0=posTrial->first.par[1]*posTrial->first.par[2]*posTrial->first.par[3];
1289 const float score=
Score(*mpPeakList,posTrial->first,mNbSpurious);
1290 if(score > pos->second)
1293 const REAL *p0=posTrial->first.par;
1294 REAL *p1=pos->first.par;
1295 for(
unsigned int k=0;k<mnpar;++k) *p1++ = *p0++;
1318 vector<float> par=bestpos->first.DirectUnitCell();
1319 cout<<
"Generation #"<<ng-i<<
", Best score="<<bestScore
1320 <<
" Trial: a="<<par[0]<<
", b="<<par[1]<<
", c="<<par[2]<<
", alpha="
1321 <<par[3]*RAD2DEG<<
", beta="<<par[4]*RAD2DEG<<
", gamma="<<par[5]*RAD2DEG<<
", V="<<par[6]
1322 <<
" "<<(ng-i)*np/((clock()-mTime0)/(float)CLOCKS_PER_SEC)<<
" trials/s"
1327 for(vector<pair<RecUnitCell,float> >::iterator pos=vRUC.begin();pos!=vRUC.end();++pos)
1329 if(pos==bestpos)
continue;
1330 for(
unsigned int k=0;k<mnpar;++k) pos->first.par[k]=mMin[k]+mAmp[k]*rand()/(float)RAND_MAX;
1348 mRecUnitCell=bestpos->first;
1349 float score=
Score(*mpPeakList,mRecUnitCell,mNbSpurious,
false,
true);
1350 vector<float> par=mRecUnitCell.DirectUnitCell();
1351 cout<<__FILE__<<
":"<<__LINE__<<
" Best-DE : a="<<par[0]<<
", b="<<par[1]<<
", c="<<par[2]<<
", alpha="
1352 <<par[3]*RAD2DEG<<
", beta="<<par[4]*RAD2DEG<<
", gamma="<<par[5]*RAD2DEG<<
", V="<<par[6]
1353 <<
", score="<<bestpos->second
1354 <<
" ("<<ng*np/((clock()-mTime0)/(
float)CLOCKS_PER_SEC)<<
" trials/s)"<<endl;
1355 if(score>mMinScoreReport*.5)
1358 mRecUnitCell=bestpos->first;
1359 this->LSQRefine(10,
true,
true);
1360 par=mRecUnitCell.DirectUnitCell();
1361 score=
Score(*mpPeakList,mRecUnitCell,mNbSpurious,
false,
true);
1362 cout<<__FILE__<<
":"<<__LINE__<<
" Best-LSQ: 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="<<score<<endl;
1365 if((score>mMinScoreReport)&&(score>(mBestScore/3)))
1367 if(score>mBestScore) mBestScore=score;
1368 mvSolution.push_back(make_pair(mRecUnitCell,score));
1369 mvSolution.back().first.mNbSpurious = mNbSpurious;
1370 this->ReduceSolutions(
true);
1375 void CellExplorer::SetLengthMinMax(
const float min,
const float max)
1380 void CellExplorer::SetAngleMinMax(
const float min,
const float max)
1385 void CellExplorer::SetVolumeMinMax(
const float min,
const float max)
1390 void CellExplorer::SetNbSpurious(
const unsigned int nb)
1394 void CellExplorer::SetMinMaxZeroShift(
const float min,
const float max)
1400 void CellExplorer::SetCrystalSystem(
const CrystalSystem system)
1405 void CellExplorer::SetCrystalCentering(
const CrystalCentering cent)
1410 void CellExplorer::SetD2Error(
const float err){mD2Error=err;}
1412 const string& CellExplorer::GetClassName()
const
1414 const static string className=
"CellExplorer";
1417 const string& CellExplorer::GetName()
const
1419 const static string name=
"Some CellExplorer Object";
1422 void CellExplorer::Print()
const
1424 this->RefinableObj::Print();
1426 unsigned int CellExplorer::GetNbLSQFunction()
const
1429 const CrystVector_REAL& CellExplorer::GetLSQCalc(
const unsigned int)
const
1431 VFN_DEBUG_ENTRY(
"CellExplorer::GetLSQCalc()",2)
1433 for(vector<PeakList::hkl>::const_iterator pos=mpPeakList->GetPeakList().begin();pos!=mpPeakList->GetPeakList().end();++pos)
1436 mCalc(j++)=mRecUnitCell.hkl2d(pos->h,pos->k,pos->l);
1439 VFN_DEBUG_EXIT(
"CellExplorer::GetLSQCalc()",2)
1442 const CrystVector_REAL& CellExplorer::GetLSQObs(
const unsigned int)
const
1444 VFN_DEBUG_MESSAGE(
"CellExplorer::GetLSQObs()",2)
1447 const CrystVector_REAL& CellExplorer::GetLSQWeight(
const unsigned int)
const
1449 VFN_DEBUG_MESSAGE(
"CellExplorer::GetLSQWeight()",2)
1453 const CrystVector_REAL& CellExplorer::GetLSQDeriv(
const unsigned int,
RefinablePar &refpar)
1455 VFN_DEBUG_ENTRY(
"CellExplorer::GetLSQDeriv()",2)
1457 if(refpar.
GetName()==
"Reciprocal unit cell par #0") par=mRecUnitCell.par+1;
1459 if(refpar.
GetName()==
"Reciprocal unit cell par #1") par=mRecUnitCell.par+2;
1461 if(refpar.
GetName()==
"Reciprocal unit cell par #2") par=mRecUnitCell.par+3;
1463 if(refpar.
GetName()==
"Reciprocal unit cell par #3") par=mRecUnitCell.par+4;
1465 if(refpar.
GetName()==
"Reciprocal unit cell par #4") par=mRecUnitCell.par+5;
1467 if(refpar.
GetName()==
"Reciprocal unit cell par #5") par=mRecUnitCell.par+6;
1469 if(refpar.
GetName()==
"Zero") par=mRecUnitCell.par+0;
1470 else cout<<__FILE__<<
":"<<__LINE__<<
":Parameter not found:"<<refpar.
GetName()<<endl;
1472 for(vector<PeakList::hkl>::const_iterator pos=mpPeakList->GetPeakList().begin();pos!=mpPeakList->GetPeakList().end();++pos)
1474 VFN_DEBUG_MESSAGE(
"CellExplorer::GetLSQDeriv():"<<j<<
"/"<<mpPeakList->GetPeakList().size(),2)
1475 VFN_DEBUG_MESSAGE(
"CellExplorer::GetLSQDeriv():"<<pos->h<<
","<<pos->k<<
","<<pos->l,2)
1477 mDeriv(j++)=mRecUnitCell.hkl2d(pos->h,pos->k,pos->l,par);
1479 VFN_DEBUG_EXIT(
"CellExplorer::GetLSQDeriv()",2)
1483 void CellExplorer::BeginOptimization(
const bool allowApproximations,
const bool enableRestraints)
1485 VFN_DEBUG_ENTRY(
"CellExplorer::BeginOptimization()",5)
1486 Score(*mpPeakList,mRecUnitCell,mNbSpurious,
false,
true,
false);
1487 const unsigned int nb=mpPeakList->GetPeakList().size();
1488 mCalc.resize(nb-mNbSpurious);
1489 mObs.resize(nb-mNbSpurious);
1490 mWeight.resize(nb-mNbSpurious);
1491 mDeriv.resize(nb-mNbSpurious);
1494 for(vector<PeakList::hkl>::const_iterator pos=mpPeakList->GetPeakList().begin();pos!=mpPeakList->GetPeakList().end();++pos)
1495 if(thres<pos->iobs) thres=pos->iobs;
1500 for(vector<PeakList::hkl>::const_iterator pos=mpPeakList->GetPeakList().begin();pos!=mpPeakList->GetPeakList().end();++pos)
1505 if(mObs(j)>thres) mWeight(j)=1;
1506 else mWeight(j)=mObs(j)/thres;
1526 this->RefinableObj::BeginOptimization(allowApproximations,enableRestraints);
1527 VFN_DEBUG_EXIT(
"CellExplorer::BeginOptimization()",5)
1530 void CellExplorer::LSQRefine(
int nbCycle,
bool useLevenbergMarquardt,
const bool silent)
1532 if(mNbLSQExcept>100)
1534 if(!silent) cout<<
"CellExplorer::LSQRefine(): LSQ was disabled, too many (>100) exceptions caught. Weird unit cell parameters ?";
1537 VFN_DEBUG_ENTRY(
"CellExplorer::LSQRefine()",5)
1538 mLSQObj.SetRefinedObj(*this);
1539 mLSQObj.PrepareRefParList(true);
1542 try {mLSQObj.Refine(nbCycle,useLevenbergMarquardt,silent);}
1543 catch(
const ObjCrystException &except)
1545 if(++mNbLSQExcept>100) cout<<
"WARNING CellExplorer::LSQRefine(): LSQ was disabled, too many (>100) exceptions caught. Weird unit cell parameters ?"<<endl ;
1547 if(!silent) mpPeakList->Print(cout);
1548 VFN_DEBUG_EXIT(
"CellExplorer::LSQRefine()",5)
1565 const unsigned int nbUnindexed=0,
const bool verbose=
false,
unsigned int useStoredHKL=0,
1566 const unsigned int maxNbMissingBelow5=0)
1569 int nbIndexed=nb-nbUnindexed;
1571 if(maxNbMissingBelow5>0) d5=dhkl.
GetPeakList()[4].d2obs;
1573 unsigned int nbMissingBelow5=0;
1575 vector<PeakList::hkl>::const_iterator pos,first,last,end;
1578 unsigned int nbUnIx = 0;
1581 pos->isIndexed=
false;
1582 for(list<PeakList::hkl0>::const_iterator phkl0=pos->vDicVolHKL.begin();phkl0!=pos->vDicVolHKL.end();++phkl0)
1585 par.
hkl2d_delta(phkl0->h,phkl0->k,phkl0->l,dpar,d0,d1);
1586 if((pos->d2obsmax>=d0) && (d1>=pos->d2obsmin))
1588 pos->d2calc=(d0+d1)/2;
1589 pos->isIndexed=
true;
1590 if(--nbIndexed==0)
return true;
1594 if(!(pos->isIndexed))
if(++nbUnIx>nbUnindexed)
return false;
1598 const bool storePossibleHKL=(useStoredHKL==2);
1600 if(storePossibleHKL)
1603 pos->isIndexed=
false;
1604 pos->vDicVolHKL.clear();
1615 switch(par.mlattice)
1645 switch(par.mCentering)
1647 case LATTICE_P:stepk=1;stepl=1;
break;
1648 case LATTICE_I:stepk=1;stepl=2;
break;
1649 case LATTICE_A:stepk=1;stepl=2;
break;
1650 case LATTICE_B:stepk=1;stepl=2;
break;
1651 case LATTICE_C:stepk=2;stepl=1;
break;
1652 case LATTICE_F:stepk=2;stepl=2;
break;
1662 unsigned long nbCalcH,nbCalcK;
1665 if(verbose) cout<<
"H="<<h<<endl;
1667 for(
int sk=sk0;sk<=1;sk+=2)
1670 if(stepk==2) k=(h%2);
1674 if(verbose) cout<<
"K="<<k*sk<<endl;
1676 for(
int sl=sl0;sl<=1;sl+=2)
1688 if(par.mlattice==MONOCLINIC) sl=1;
1689 if((sk<0)||(sl<0)) l0=1;
1700 if(par.mCentering==LATTICE_I) l0+=(h+k+l0)%2;
1701 if(par.mCentering==LATTICE_A) l0+=(k+l0)%2;
1702 if( (par.mCentering==LATTICE_B)
1703 ||(par.mCentering==LATTICE_F)) l0+=(h+l0)%2;
1705 if(verbose) cout<<
"SL="<<sl<<
", L0="<<l0<<
", STEPL="<<stepl<<
", Centering="<<par.mCentering<<endl;
1708 if(verbose) cout<<
"L="<<l<<
","<<sl<<endl;
1711 if(d0<dmax) {nbCalcH++;nbCalcK++;}
1712 if((d1<dmin)&&(maxNbMissingBelow5==0))
continue;
1715 if(par.mlattice==TRICLINIC)
1718 if(verbose) cout<<
"L?="<< par.
hkl2d(h,sk*k,sl*l,NULL,3)*sl <<
", dmax="<<dmax<<endl;
1719 if((par.
hkl2d(h,sk*k,sl*l,NULL,3)*sl)>0)
break;
1723 bool missing=(d0<d5)&&(maxNbMissingBelow5>0);
1724 for(pos=first;pos!=end;++pos)
1726 if(pos==last)
break;
1727 if((!storePossibleHKL)&&(pos->isIndexed)&&missing)
continue;
1728 const float d2obs=pos->d2obs,d2obsmin=pos->d2obsmin, d2obsmax=pos->d2obsmax;
1729 if((d2obsmax>=d0) && (d1>=d2obsmin))
1732 if(!(pos->isIndexed))
1734 pos->d2calc=(d0+d1)/2;
1736 pos->isIndexed=
true;
1738 if(verbose) cout<<d1<<
" < ? <"<<d0<<
"("<<h<<
","<<sk*k<<
","<<sl*l<<
"): "<<d2obs<<
" (remaining to index:"<<nbIndexed<<
")"<<endl;
1739 if(storePossibleHKL)
1743 if((!storePossibleHKL)&&(nbIndexed==0))
return true;
1744 if(pos==first){first++;dmin=first->d2obsmin;}
1745 if(pos==last){last--;dmax=last->d2obsmax;}
1749 if(missing)
if(++nbMissingBelow5>=maxNbMissingBelow5)
return false;
1752 if(nbCalcK==0)
break;
1755 if(nbCalcH==0)
break;
1761 return nbIndexed<=0;
1764 float CellExplorer::GetBestScore()
const{
return mBestScore;}
1765 const std::list<std::pair<RecUnitCell,float> >& CellExplorer::GetSolutions()
const {
return mvSolution;}
1766 std::list<std::pair<RecUnitCell,float> >& CellExplorer::GetSolutions() {
return mvSolution;}
1768 unsigned int CellExplorer::RDicVol(RecUnitCell par0,RecUnitCell dpar,
unsigned int depth,
unsigned long &nbCalc,
const float minV,
const float maxV,vector<unsigned int> vdepth)
1770 static bool localverbose=
false;
1771 if(mlattice==TRICLINIC)
1773 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];
1774 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];
1775 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];
1778 if((p1m>p2p)||(p2m>p3p))
return 0;
1781 if((p4m>p1p)||(-p4p>p1p))
return 0;
1782 if((p5m>p2p)||(-p5p>p2p))
return 0;
1783 if((p6m>p1p)||(-p6p>p1p))
return 0;
1785 const float max6=p1p+p2p-p4m-p5m;
1786 if((p6m>max6)||(-p6p>max6))
return 0;
1788 float p6mm,p6pp,p5mm,p5pp,p4mm,p4pp;
1790 if((p4*p5-2*p2*p6)>0) {p6pp=p6p;p6mm=p6m;}
1791 else{p6pp=p6m;p6mm=p6p;}
1793 if((p4*p6-2*p1*p5)>0) {p5pp=p5p;p5mm=p5m;}
1794 else{p5pp=p5m;p5mm=p5p;}
1796 if((p5*p6-2*p3*p4)>0) {p4pp=p4p;p4mm=p4m;}
1797 else{p4pp=p4m;p4mm=p4p;}
1801 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))));
1802 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))));
1803 if((vmin0>maxV)||(vmax0<minV))
return 0;
1806 if((depth>0)&&(depth<=2))
1808 RecUnitCell parm=par0,parp=par0;
1809 for(
unsigned int i=0;i<6;++i) {parm.par[i]-=dpar.par[i];parp.par[i]+=dpar.par[i];}
1810 vector<float> parmd=parm.DirectUnitCell();
1811 vector<float> parpd=parp.DirectUnitCell();
1812 if((parpd[6]>maxV)||(parmd[6]<minV))
return 0;
1814 unsigned int useStoredHKL=1;
1815 if(depth==0) useStoredHKL=2;
1817 unsigned int maxMissingBelow5=0;
1819 if(mlattice==TRICLINIC) maxMissingBelow5=5;
1821 bool indexed=
DichoIndexed(*mpPeakList,par0,dpar,mNbSpurious,localverbose,useStoredHKL,maxMissingBelow5);
1825 if( (!indexed) && (depth>=4))
1828 indexed=
DichoIndexed(*mpPeakList,par0,dpar,mNbSpurious,
false,useStoredHKL,maxMissingBelow5);
1833 if((indexed)&&(useStoredHKL==2))
1836 unsigned int nbident=0;
1837 for(vector<PeakList::hkl>::const_iterator pos=mpPeakList->GetPeakList().begin();pos!=mpPeakList->GetPeakList().end();)
1839 if(pos->vDicVolHKL.size()==1)
1841 const PeakList::hkl0 h0=pos->vDicVolHKL.front();
1842 if(++pos==mpPeakList->GetPeakList().end())
break;
1843 if(pos->vDicVolHKL.size()==1)
1845 const PeakList::hkl0 h1=pos->vDicVolHKL.front();
1846 if((h0.h==h1.h)&&(h0.k==h1.k)&&(h0.l==h1.l)) nbident++;
1847 if(nbident>mNbSpurious) {indexed=
false;
break;}
1855 if(vdepth.size()==0)
1857 vdepth.resize(mnpar-1);
1858 for(vector<unsigned int>::iterator pos=vdepth.begin();pos!=vdepth.end();) *pos++=depth;
1861 for(vector<unsigned int>::iterator pos=vdepth.begin();pos!=vdepth.end();++pos)
if(*pos<depth)*pos=depth;
1866 vector<pair<unsigned int,float> > vq0(3);
1867 for(
unsigned int i=0;i<3;++i) {vq0[i].first=0;vq0[i].second=0.0;}
1868 RecUnitCell par0orig=par0,dparorig=dpar;
1869 for(vector<PeakList::hkl>::const_iterator pos=mpPeakList->GetPeakList().begin();pos!=mpPeakList->GetPeakList().end();++pos)
1871 if(pos->vDicVolHKL.size()==1)
1873 const PeakList::hkl0 h0=pos->vDicVolHKL.front();
1874 if((h0.k==0)&&(h0.l==0)) {vq0[0].first+=1 ; vq0[0].second+=pos->dobs/h0.h;}
1876 if((h0.h==0)&&(h0.l==0)) {vq0[1].first+=1 ; vq0[1].second+=pos->dobs/h0.k;}
1878 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;}
1885 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;}
1886 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;}
1887 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;}
1892 if(vq0[0].first>0) {par0.par[1]=vq0[0].second/vq0[0].first ; vdepth[0]=mDicVolDepthReport;dpar.par[1]*=.0625;}
1893 if(vq0[1].first>0) {par0.par[2]=vq0[1].second/vq0[1].first ; vdepth[1]=mDicVolDepthReport;dpar.par[2]*=.0625;}
1894 if(vq0[2].first>0) {par0.par[3]=vq0[2].second/vq0[2].first ; vdepth[2]=mDicVolDepthReport;dpar.par[3]*=.0625;}
1899 if(vq0[0].first>0) {par0.par[1]=vq0[0].second/vq0[0].first ; vdepth[0]=mDicVolDepthReport;dpar.par[1]*=.0625;}
1900 if(vq0[1].first>0) {par0.par[2]=vq0[1].second/vq0[1].first ; vdepth[1]=mDicVolDepthReport;dpar.par[2]*=.0625;}
1901 if(vq0[2].first>0) {par0.par[3]=vq0[2].second/vq0[2].first ; vdepth[2]=mDicVolDepthReport;dpar.par[3]*=.0625;}
1904 case HEXAGONAL:
break;
1905 case RHOMBOEDRAL:
break;
1906 case TETRAGONAL:
break;
1910 unsigned int newdepth=40;
1911 for(vector<unsigned int>::iterator pos=vdepth.begin();pos!=vdepth.end();++pos)
if(*pos<newdepth) newdepth=*pos;
1912 if(newdepth>depth) depth=newdepth;
1913 if((vq0[0].first>0)||(vq0[1].first>0)||(vq0[2].first>0))
1915 indexed=
DichoIndexed(*mpPeakList,par0,dpar,mNbSpurious,
false,1,maxMissingBelow5);
1919 RecUnitCell parm=par0orig,parp=par0;
1920 for(
unsigned int i=0;i<6;++i) {parm.par[i]-=dparorig.par[i];parp.par[i]+=dparorig.par[i];}
1921 vector<float> parmd=parm.DirectUnitCell();
1922 vector<float> parpd=parp.DirectUnitCell();
1924 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",
1925 parpd[0],parmd[0],parpd[1],parmd[1],parpd[2],parmd[2],parpd[3]*RAD2DEG,parmd[3]*RAD2DEG,
1926 parpd[4]*RAD2DEG,parmd[4]*RAD2DEG,parpd[5]*RAD2DEG,parmd[5]*RAD2DEG,parpd[6],parmd[6]);
1927 for(
unsigned int i = 0; i < depth; ++i) cout <<
" ";
1928 cout<<buf<<
"level="<<depth<<
", indexed="<<indexed<<endl;
1931 RecUnitCell parm=par0,parp=par0;
1932 for(
unsigned int i=0;i<6;++i) {parm.par[i]-=dpar.par[i];parp.par[i]+=dpar.par[i];}
1933 vector<float> parmd=parm.DirectUnitCell();
1934 vector<float> parpd=parp.DirectUnitCell();
1936 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",
1937 parpd[0],parmd[0],parpd[1],parmd[1],parpd[2],parmd[2],parpd[3]*RAD2DEG,parmd[3]*RAD2DEG,
1938 parpd[4]*RAD2DEG,parmd[4]*RAD2DEG,parpd[5]*RAD2DEG,parmd[5]*RAD2DEG,parpd[6],parmd[6]);
1939 for(
unsigned int i = 0; i < depth; ++i) cout <<
" ";
1940 cout<<buf<<
"level="<<depth<<
", indexed="<<indexed<<endl;
1948 RecUnitCell parm=par0,parp=par0;
1949 for(
unsigned int i=0;i<4;++i) {parm.par[i]-=dpar.par[i];parp.par[i]+=dpar.par[i];}
1950 for(
unsigned int i=4;i<7;++i) {parm.par[i]+=dpar.par[i];parp.par[i]-=dpar.par[i];}
1951 vector<float> parmd=parm.DirectUnitCell();
1952 vector<float> parpd=parp.DirectUnitCell();
1954 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",
1955 parpd[0],parmd[0],parpd[1],parmd[1],parpd[2],parmd[2],parpd[3]*RAD2DEG,parmd[3]*RAD2DEG,
1956 parpd[4]*RAD2DEG,parmd[4]*RAD2DEG,parpd[5]*RAD2DEG,parmd[5]*RAD2DEG,parpd[6],parmd[6]);
1957 for(
unsigned int i = 0; i < depth; ++i) cout <<
" ";
1958 cout<<buf<<
"level="<<depth<<
", indexed="<<indexed<<
"("<<mvSolution.size()<<
" sol.)"<<endl;
1977 unsigned int deeperSolutions=0;
1978 if(depth<mMaxDicVolDepth)
1982 RecUnitCell parm=par0,parp=par0;
1983 for(
unsigned int i=0;i<6;++i) {parm.par[i]-=dpar.par[i];parp.par[i]+=dpar.par[i];}
1984 vector<float> parmd=parm.DirectUnitCell();
1985 vector<float> parpd=parp.DirectUnitCell();
1987 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",
1988 parpd[0],parmd[0],parpd[1],parmd[1],parpd[2],parmd[2],parpd[3]*RAD2DEG,parmd[3]*RAD2DEG,
1989 parpd[4]*RAD2DEG,parmd[4]*RAD2DEG,parpd[5]*RAD2DEG,parmd[5]*RAD2DEG,parpd[6],parmd[6]);
1990 for(
unsigned int i=0;i<depth;++i) cout<<
" ";
1991 cout<<
"Depth="<<depth<<
" "<<buf<<endl;
1992 for(
int i=0;i<=6;++i)cout<<par0.par[i]<<
",";
1993 for(
int i=0;i<=6;++i)cout<<dpar.par[i]<<
",";
1996 RecUnitCell par=par0;
1998 dpar.par[0]=0.5*dpar.par[0];
2001 for(
unsigned int i=1;i<mnpar;++i) dpar.par[i]*=(0.5+0.5*(vdepth[i-1]>depth));
2003 for(
int i0=-1;i0<=1;i0+=2)
2006 if(localverbose) cout<<__FILE__<<
":"<<__LINE__<<
":"<<par.par[3]<<
" +/- "<<dpar.par[3]<<
" ("<<vdepth[2]<<
")"<<endl;
2008 if(vdepth[0]==depth) {par.par[1]=par0.par[1]+i0*dpar.par[1];}
2011 deeperSolutions+=RDicVol(par,dpar, depth+1,nbCalc,minV,maxV,vdepth);
2013 for(
int i1=-1;i1<=1;i1+=2)
2015 if(vdepth[1]==depth) {par.par[2]=par0.par[2]+i1*dpar.par[2];}
2018 deeperSolutions+=RDicVol(par,dpar, depth+1,nbCalc,minV,maxV,vdepth);
2020 for(
int i2=-1;i2<=1;i2+=2)
2022 if(vdepth[2]==depth) {par.par[3]=par0.par[3]+i2*dpar.par[3];}
2025 deeperSolutions+=RDicVol(par,dpar, depth+1,nbCalc,minV,maxV,vdepth);
2027 for(
int i3=-1;i3<=1;i3+=2)
2029 if(vdepth[3]==depth)par.par[4]=par0.par[4]+i3*dpar.par[4];
2032 deeperSolutions+=RDicVol(par,dpar, depth+1,nbCalc,minV,maxV,vdepth);
2034 for(
int i4=-1;i4<=1;i4+=2)
2036 par.par[5]=par0.par[5]+i4*dpar.par[5];
2040 for(
int i5=-1;i5<=1;i5+=2)
2042 par.par[6]=par0.par[6]+i5*dpar.par[6];
2044 deeperSolutions+=RDicVol(par,dpar, depth+1,nbCalc,minV,maxV,vdepth);
2052 if((deeperSolutions==0) &&(depth>=mDicVolDepthReport))
2055 vector<float> par=mRecUnitCell.DirectUnitCell();
2056 float score=
Score(*mpPeakList,mRecUnitCell,mNbSpurious,
false,
true,
false);
2059 if(depth<(mMaxDicVolDepth-1))
2060 if(mvNbSolutionDepth[depth+2]>100)report=
false;
2061 if(report && (((score>(mMinScoreReport*.5))&&(depth>=mDicVolDepthReport)) || (depth>=mMaxDicVolDepth)))
2064 cout<<__FILE__<<
":"<<__LINE__<<
" Depth="<<depth<<
" (DIC) ! a="<<par[0]<<
", b="<<par[1]<<
", c="<<par[2]<<
", alpha="
2065 <<par[3]*RAD2DEG<<
", beta="<<par[4]*RAD2DEG<<
", gamma="<<par[5]*RAD2DEG<<
", V="<<par[6]
2066 <<
", score="<<score<<endl;
2067 this->LSQRefine(5,
true,
true);
2070 score=
Score(*mpPeakList,mRecUnitCell,mNbSpurious,
false,
true,
false);
2071 this->LSQRefine(5,
true,
true);
2073 par=mRecUnitCell.DirectUnitCell();
2074 score=
Score(*mpPeakList,mRecUnitCell,mNbSpurious,
false,
true,
false);
2075 if( ((score>mMinScoreReport)||(depth>=mDicVolDepthReport))
2076 &&((mvSolution.size()<50)||(score>(mBestScore/3)))
2077 &&((mvSolution.size()<50)||(score>mMinScoreReport)))
2079 if((score>(mBestScore))||((score>(mBestScore*0.8))&&(mvSolution.size()<50)))
2083 RecUnitCell parm=par0,parp=par0;
2084 for(
unsigned int i=0;i<4;++i) {parm.par[i]-=dpar.par[i];parp.par[i]+=dpar.par[i];}
2085 for(
unsigned int i=4;i<7;++i) {parm.par[i]+=dpar.par[i];parp.par[i]-=dpar.par[i];}
2086 vector<float> parmd=parm.DirectUnitCell();
2087 vector<float> parpd=parp.DirectUnitCell();
2088 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",
2089 parpd[0],parmd[0],parpd[1],parmd[1],parpd[2],parmd[2],parpd[3]*RAD2DEG,parmd[3]*RAD2DEG,
2090 parpd[4]*RAD2DEG,parmd[4]*RAD2DEG,parpd[5]*RAD2DEG,parmd[5]*RAD2DEG,parpd[6],parmd[6]);
2091 for(
unsigned int i = 0; i < depth; ++i) cout <<
" ";
2093 cout<<buf<<
"level="<<depth<<
", indexed="<<indexed<<
"("<<mvSolution.size()<<
" sol.)"<<endl;
2094 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",
2095 parp.par[1],parm.par[1],parp.par[2],parm.par[2],parp.par[3],parm.par[3],parp.par[4],parm.par[4],
2096 parp.par[5],parm.par[5],parp.par[6],parm.par[6]);
2097 for(
unsigned int i = 0; i < depth; ++i) cout <<
" ";
2098 cout<<buf<<
"level="<<depth<<
", indexed="<<indexed<<
"("<<mvSolution.size()<<
" sol.)"<<endl;
2100 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",
2101 par[0],par[1],par[2],par[3]*RAD2DEG,par[4]*RAD2DEG,par[5]*RAD2DEG,par[6],score,mvSolution.size());
2105 mvSolution.push_back(make_pair(mRecUnitCell,score));
2106 mvSolution.back().first.mNbSpurious = mNbSpurious;
2107 mvNbSolutionDepth[depth]+=1;
2108 if((mvSolution.size()>1100)&&(rand()%1000==0))
2110 cout<<mvSolution.size()<<
" solutions ! Redparing..."<<endl;
2111 this->ReduceSolutions(
true);
2112 cout<<
"-> "<<mvSolution.size()<<
" remaining"<<endl;
2117 return deeperSolutions+1;
2122 vector<float> linspace(
float min,
float max,
unsigned int nb)
2124 vector<float> v(nb);
2125 for(
unsigned int i=0;i<nb;++i) v[i]=min+(max-min)*i/(nb-1);
2129 void CellExplorer::DicVol(
const float minScore,
const unsigned int minDepth,
const float stopOnScore,
const unsigned int stopOnDepth)
2132 mDicVolDepthReport=minDepth;
2133 mMinScoreReport=minScore;
2135 if(minDepth>mMaxDicVolDepth) mMaxDicVolDepth=minDepth;
2136 mvNbSolutionDepth.resize(mMaxDicVolDepth+1);
2137 for(
unsigned int i=0;i<=mMaxDicVolDepth;++i) mvNbSolutionDepth[i]=0;
2140 vstep=(mVolumeMax-mVolumeMin)/(ceil((mVolumeMax-mVolumeMin)/500)-0.0001);
2141 mCosAngMax=abs(cos(mAngleMax));
2142 const float cosangstep=mCosAngMax/(ceil(mCosAngMax/.08)-.0001);
2143 if(((mVolumeMax-mVolumeMin)/vstep)>10) vstep=(mVolumeMax-mVolumeMin)/9.999;
2144 if(((mLengthMax-mLengthMin)/latstep)>25) latstep=(mLengthMax-mLengthMin)/24.9999;
2146 cout<<mLengthMin<<
"->"<<mLengthMax<<
","<<latstep<<
","<<(mLengthMax-mLengthMin)/latstep<<endl;
2147 cout<<mAngleMin<<
"->"<<mAngleMax<<
","<<cosangstep<<
","<<mCosAngMax<<
","<<(mAngleMax-mAngleMin)/cosangstep<<endl;
2148 cout<<mVolumeMin<<
"->"<<mVolumeMax<<
","<<vstep<<
","<<(mVolumeMax-mVolumeMin)/vstep<<endl;
2150 par0.mlattice=mlattice;
2151 dpar.mlattice=mlattice;
2152 par0.mCentering=mCentering;
2153 dpar.mCentering=mCentering;
2157 unsigned long nbCalc=0;
2160 list<pair<RecUnitCell,float> >::iterator bestpos;
2161 bool breakDepth=
false;
2164 for(
float minv=mVolumeMin;minv<mVolumeMax;minv+=vstep)
2166 float maxv=minv+vstep;
2167 if(maxv>mVolumeMax)maxv=mVolumeMax;
2168 cout<<
"Starting: V="<<minv<<
"->"<<maxv<<endl;
2169 const float minr=1/(mLengthMax*mLengthMax);
2170 const float maxr=1/(mLengthMin*mLengthMin);
2171 const float stepr=(maxr-minr)/24.999;
2173 for(
unsigned int i=0;i<=5;i++)
2177 case 0: p1=mpPeakList->GetPeakList()[0].d2obs ;p2=mpPeakList->GetPeakList()[1].d2obs ;
break;
2178 case 1: p1=mpPeakList->GetPeakList()[0].d2obs ;p2=mpPeakList->GetPeakList()[2].d2obs ;
break;
2179 case 2: p1=mpPeakList->GetPeakList()[1].d2obs/2;p2=mpPeakList->GetPeakList()[0].d2obs ;
break;
2180 case 3: p1=mpPeakList->GetPeakList()[1].d2obs/2;p2=mpPeakList->GetPeakList()[2].d2obs ;
break;
2181 case 4: p1=mpPeakList->GetPeakList()[2].d2obs/2;p2=mpPeakList->GetPeakList()[0].d2obs ;
break;
2182 case 5: p1=mpPeakList->GetPeakList()[2].d2obs/2;p2=mpPeakList->GetPeakList()[1].d2obs ;
break;
2186 cout<<
"Trying #"<<i<<
": a*="<<p1<<
", b*="<<p2<<endl;
2189 const float step3r=(max3r-min3r)/(ceil((max3r-min3r)/stepr)-.001);
2190 vector<unsigned int> vdepth(mnpar-1);
2191 for(vector<unsigned int>::iterator pos=vdepth.begin();pos!=vdepth.end();) *pos++=0;
2194 for(
float p3=min3r;p3<max3r;p3+=step3r)
2197 const float max4r=p3+step3r;
2198 const float step4r=max4r/(ceil(max4r/stepr)-.001);
2199 for(
float p4=0;p4<max4r;p4+=step4r)
2202 float max5r=(p2+stepr);
2203 const float step5r=max5r/(ceil(max5r/stepr)-.001);
2204 for(
float p5=0;p5<max5r;p5+=step5r)
2206 float max6r=(p1+stepr);
2207 const float step6r=max6r/(ceil(max6r/stepr)-.001);
2208 for(
float p6=-max6r;p6<max6r;p6+=step6r)
2211 dpar.par[1]=stepr*pow(
float(0.51),
int(vdepth[0]));
2212 dpar.par[2]=stepr*pow(
float(0.51),
int(vdepth[1]));
2213 dpar.par[3]=step3r*0.51;
2214 dpar.par[4]=step4r*0.51;
2215 dpar.par[5]=step5r*0.51;
2216 dpar.par[6]=step6r*0.51;
2221 par0.par[3]=p3+step3r/2;
2222 par0.par[4]=p4+step4r/2;
2223 par0.par[5]=p5+step5r/2;
2224 par0.par[6]=p6+step6r/2;
2229 RDicVol(par0,dpar,0,nbCalc,minv,maxv,vdepth);
2234 cout<<
"Finished trying: a*="<<p1<<
" A, b*="<<p2<<
" A, "<<nbCalc
2235 <<
" unit cells tested, "<<nbCalc/chrono.seconds()<<
" tests/s, Elapsed time="
2236 <<chrono.seconds()<<
"s, Best score="<<mBestScore<<
", "<<stopOnScore<<
", "<<breakDepth<<endl;
2239 for(
unsigned int i=stopOnDepth; i<mvNbSolutionDepth.size();++i)
2240 if(mvNbSolutionDepth[i]>1) {breakDepth=
true;
break;}
2241 if((mBestScore>stopOnScore)&&(breakDepth))
break;
2243 cout<<
"Finished triclinic QUICK tests for: V="<<minv<<
"->"<<maxv<<
" A^3, "<<nbCalc
2244 <<
" unit cells tested, "<<nbCalc/chrono.seconds()<<
" tests/s, Elapsed time="
2245 <<chrono.seconds()<<
"s, Best score="<<mBestScore<<endl;
2246 if((mBestScore>stopOnScore)&&(breakDepth))
break;
2248 if((mBestScore<stopOnScore)||(!breakDepth))
2249 for(
float minv=mVolumeMin;minv<mVolumeMax;minv+=vstep)
2251 float maxv=minv+vstep;
2252 if(maxv>mVolumeMax)maxv=mVolumeMax;
2253 cout<<
"Starting: V="<<minv<<
"->"<<maxv<<endl;
2258 const unsigned int nbstep=25;
2259 vector<float> v1=linspace(mLengthMin,mLengthMax,nbstep);
2260 const float lstep=v1[1]-v1[0];
2261 for(
unsigned int i1=0;i1<(nbstep-1);++i1)
2263 const float p1 =(1/(v1[i1]*v1[i1])+1/(v1[i1+1]*v1[i1+1]))/2;
2264 const float dp1=(1/(v1[i1]*v1[i1])-1/(v1[i1+1]*v1[i1+1]))/2;
2267 const unsigned int nb2=int((v1[i1+1]-mLengthMin)/lstep+2.001);
2268 vector<float> v2=linspace(mLengthMin,v1[i1+1],nb2);
2271 for(
unsigned int i2=0;i2<(nb2-1);++i2)
2273 const float p2 =(1/(v2[i2]*v2[i2])+1/(v2[i2+1]*v2[i2+1]))/2;
2274 const float dp2=(1/(v2[i2]*v2[i2])-1/(v2[i2+1]*v2[i2+1]))/2;
2276 const unsigned int nb3=int((v2[i2+1]-mLengthMin)/lstep+2.001);
2277 vector<float> v3=linspace(mLengthMin,v2[i2+1],nb3);
2278 for(
unsigned int i3=0;i3<(nb3-1);++i3)
2280 const float p3 =(1/(v3[i3]*v3[i3])+1/(v3[i3+1]*v3[i3+1]))/2;
2281 const float dp3=(1/(v3[i3]*v3[i3])-1/(v3[i3+1]*v3[i3+1]))/2;
2285 const float vmin3=1/sqrt((p1+dp1)*(p2+dp2)*(p3+dp3));
2286 const float vmax3=1/sqrt((p1-dp1)*(p2-dp2)*(p3-dp3))*2;
2287 if(vmax3<minv)
continue;
2288 if(vmin3>maxv)
continue;
2296 const unsigned int nb4=int((p1+dp1)/(4*dp1)+2.001);
2297 vector<float> v4=linspace(0,p1+dp1,nb4);
2298 for(
unsigned int i4=0;i4<(nb4-1);++i4)
2300 const float p4 =(v4[i4+1]+v4[i4])/2;
2301 const float dp4=(v4[i4+1]-v4[i4])/2;
2303 const unsigned int nb5=int((p2+dp2)/(4*dp2)+2.001);
2304 vector<float> v5=linspace(0,p2+dp2,nb5);
2305 for(
unsigned int i5=0;i5<(nb5-1);++i5)
2307 const float p5 =(v5[i5+1]+v5[i5])/2;
2308 const float dp5=(v5[i5+1]-v5[i5])/2;
2311 float vmax6=(p1+dp1)+(p2+dp2)-(p4-dp4)-(p5-dp5);
2312 if(vmax6>(p1+dp1)) vmax6=p1+dp1;
2313 if(vmax6<0)
continue;
2314 const unsigned int nb6=int((2*vmax6)/(4*dp1)+2.001);
2315 vector<float> v6=linspace(-vmax6,vmax6,nb6);
2317 for(
unsigned int i6=0;i6<(nb6-1);++i6)
2319 const float p6 =(v6[i6+1]+v6[i6])/2;
2320 const float dp6=(v6[i6+1]-v6[i6])/2;
2343 RDicVol(par0,dpar,0,nbCalc,minv,maxv);
2356 vector<float> parlarged,parsmalld;
2357 latstep=(mLengthMax-mLengthMin)/24.999;
2358 for(
float x4=0;x4<mCosAngMax+cosangstep;x4+=cosangstep)
2360 const float sinbeta=sqrt(abs(1-x4*x4));
2361 float x1=mLengthMin;
2362 for(;x1<mLengthMax;x1+=latstep)
2364 float x2=mLengthMin;
2365 for(;x2<mLengthMax;x2+=latstep)
2368 const float x3step=(mLengthMax-x1)/(ceil((mLengthMax-x1)/latstep)-0.001);
2369 for(;x3<mLengthMax;x3+=x3step)
2371 if((x3*x4)>x1)
break;
2372 dpar.par[1]=(1/(x1)-1/(x1+latstep))*0.5/sinbeta;
2373 dpar.par[2]=(1/(x2)-1/(x2+latstep))*0.5/sinbeta;
2374 dpar.par[3]=(1/(x3)-1/(x3+x3step ))*0.5/sinbeta;
2375 dpar.par[4]=cosangstep*0.5;
2378 par0.par[1]=(1/(x1)+1/(x1+latstep))*0.5/sinbeta;
2379 par0.par[2]=(1/(x2)+1/(x2+latstep))*0.5/sinbeta;
2380 par0.par[3]=(1/(x3)+1/(x3+x3step ))*0.5/sinbeta;
2381 par0.par[4]=x4+cosangstep*.5;
2383 const float smallv=x1*x2*x3*sinbeta;
2384 if(smallv>maxv)
break;
2385 const float largev=(x1+latstep)*(x2+latstep)*(x3+latstep)*(sinbeta+cosangstep);
2386 if(largev<minv)
continue;
2394 RDicVol(par0,dpar,0,nbCalc,minv,maxv);
2400 for(list<pair<RecUnitCell,float> >::iterator pos=mvSolution.begin();pos!=mvSolution.end();++pos)
2402 const float score=pos->second;
2403 if(score>bestscore) {bestscore=score;bestpos=pos;}
2405 bool breakDepth=
false;
2407 for(
unsigned int i=stopOnDepth; i<mvNbSolutionDepth.size();++i)
2408 if(mvNbSolutionDepth[i]>1) {breakDepth=
true;
break;}
2409 if((bestscore>stopOnScore)&&(breakDepth))
break;
2420 const float a=6.25,b=16.75,c=16.75;
2421 dpar.par[1]=(1/(a-.25)-1/(a+.25))*0.5;
2422 dpar.par[2]=(1/(b-.25)-1/(b+.25))*0.5;
2423 dpar.par[3]=(1/(c-.25)-1/(c+.25))*0.5;
2428 RDicVol(par0,dpar,0,nbCalc,minv,maxv);
2431 latstep=(mLengthMax-mLengthMin)/24.999;
2432 for(
float x1=mLengthMin;x1<mLengthMax;x1+=latstep)
2434 for(
float x2=x1;x2<mLengthMax;x2+=latstep)
2436 for(
float x3=x2;x3<mLengthMax;x3+=latstep)
2438 dpar.par[1]=(1/(x1)-1/(x1+latstep))*0.5;
2439 dpar.par[2]=(1/(x2)-1/(x2+latstep))*0.5;
2440 dpar.par[3]=(1/(x3)-1/(x3+latstep))*0.5;
2443 par0.par[1]=(1/(x1)+1/(x1+latstep))*0.5;
2444 par0.par[2]=(1/(x2)+1/(x2+latstep))*0.5;
2445 par0.par[3]=(1/(x3)+1/(x3+latstep))*0.5;
2447 const float vmin=x1*x2*x3,vmax=(x1+latstep)*(x2+latstep)*(x3+latstep);
2448 if(vmin>maxv)
break;
2449 if(vmax>=minv) RDicVol(par0,dpar,0,nbCalc,minv,maxv);
2451 if((x1*x2*x2)>maxv)
break;
2453 if((x1*x1*x1)>maxv)
break;
2459 vector<float> parlarged,parsmalld;
2460 latstep=(mLengthMax-mLengthMin)/24.999;
2461 for(
float x1=mLengthMin;;x1+=latstep)
2463 for(
float x2=mLengthMin;x2<(mLengthMax+latstep);x2+=latstep)
2465 dpar.par[1]=(1/(x1)-1/(x1+latstep))*0.5;
2466 dpar.par[2]=(1/(x2)-1/(x2+latstep))*0.5;
2469 par0.par[1]=(1/(x1)+1/(x1+latstep))*0.5;
2470 par0.par[2]=(1/(x2)+1/(x2+latstep))*0.5;
2473 for(
unsigned int i=0;i<6;++i) {parlarge.
par[i]-=dpar.par[i];parsmall.par[i]+=dpar.par[i];}
2475 parsmalld=parsmall.DirectUnitCell();
2482 if((parsmalld[6]<maxv)&&(parlarged[6]>minv))
2485 RDicVol(par0,dpar,0,nbCalc,minv,maxv);
2489 if(parlarged[0]>mLengthMax)
break;
2495 latstep=(mLengthMax-mLengthMin)/24.999;
2496 for(
float x1=mLengthMin;x1<(mLengthMax+latstep);x1+=latstep)
2498 for(
float x2=0;x2<mCosAngMax+cosangstep;x2+=cosangstep)
2500 dpar.par[1]=latstep/2*1.1;
2501 dpar.par[2]=cosangstep/2*1.1;
2504 par0.par[1]=x1-latstep/2*1.1;
2505 par0.par[2]=x2-cosangstep/2*1.1;
2506 vector<float> par=par0.DirectUnitCell();
2507 if((par[6]<maxv)&&(par[6]>minv))
2509 RDicVol(par0,dpar,0,nbCalc,minv,maxv);
2517 vector<float> parlarged,parsmalld;
2518 latstep=(mLengthMax-mLengthMin)/24.999;
2519 for(
float x1=mLengthMin;x1<mLengthMax;x1+=latstep)
2521 for(
float x2=mLengthMin;x2<mLengthMax;x2+=latstep)
2523 dpar.par[1]=(1/(x1)-1/(x1+latstep))*0.5;
2524 dpar.par[2]=(1/(x2)-1/(x2+latstep))*0.5;
2527 par0.par[1]=(1/(x1)+1/(x1+latstep))*0.5;
2528 par0.par[2]=(1/(x2)+1/(x2+latstep))*0.5;
2531 for(
unsigned int i=0;i<6;++i) {parlarge.
par[i]-=dpar.par[i];parsmall.par[i]+=dpar.par[i];}
2533 parsmalld=parsmall.DirectUnitCell();
2540 if((parsmalld[6]<maxv)&&(parlarged[6]>minv))
2542 RDicVol(par0,dpar,0,nbCalc,minv,maxv);
2544 if(parsmalld[6]>maxv)
break;
2546 if((x1*mLengthMin*mLengthMin)>maxv)
break;
2552 latstep=(mLengthMax-mLengthMin)/24.999;
2553 cout<<mLengthMax<<
","<<mLengthMin<<
","<<latstep<<endl;
2554 for(
float x1=mLengthMin;x1<(mLengthMax+latstep);x1+=latstep)
2556 dpar.par[1]=(1/(x1)-1/(x1+latstep))*0.5;
2559 par0.par[1]=(1/(x1)+1/(x1+latstep))*0.5;
2561 const float vmin=x1*x1*x1,vmax=(x1+latstep)*(x1+latstep)*(x1+latstep);
2563 if(vmax>minv) RDicVol(par0,dpar,0,nbCalc,minv,maxv);
2568 cout<<
"Finished: V="<<minv<<
"->"<<maxv<<
" A^3, "<<nbCalc
2569 <<
" unit cells tested, "<<nbCalc/chrono.seconds()<<
" tests/s, Elapsed time="
2570 <<chrono.seconds()<<
"s"<<endl;
2571 for(list<pair<RecUnitCell,float> >::iterator pos=mvSolution.begin();pos!=mvSolution.end();++pos)
2573 const float score=pos->second;
2574 if(score>bestscore) {bestscore=score;bestpos=pos;}
2576 bool breakDepth=
false;
2578 for(
unsigned int i=stopOnDepth; i<mvNbSolutionDepth.size();++i)
2579 if(mvNbSolutionDepth[i]>1) {breakDepth=
true;
break;}
2580 if((bestscore>stopOnScore)&&(breakDepth))
break;
2595 this->ReduceSolutions(
true);
2596 bestscore=0;bestpos=mvSolution.end();
2597 for(list<pair<RecUnitCell,float> >::iterator pos=mvSolution.begin();pos!=mvSolution.end();++pos)
2599 const float score=
Score(*mpPeakList,pos->first,mNbSpurious);
2600 if(score>bestscore) {bestpos=pos;bestscore=score;}
2601 vector<float> par=pos->first.DirectUnitCell();
2602 cout<<__FILE__<<
":"<<__LINE__<<
" Solution ? a="<<par[0]<<
", b="<<par[1]<<
", c="<<par[2]
2603 <<
", alpha="<<par[3]*RAD2DEG<<
", beta="<<par[4]*RAD2DEG<<
", gamma="<<par[5]*RAD2DEG
2604 <<
", V="<<par[6]<<
", score="<<score<<endl;
2606 if(bestpos!=mvSolution.end())
2608 vector<float> par=bestpos->first.DirectUnitCell();
2609 cout<<__FILE__<<
":"<<__LINE__<<
" BEST ? a="<<par[0]<<
", b="<<par[1]<<
", c="<<par[2]
2610 <<
", alpha="<<par[3]*RAD2DEG<<
", beta="<<par[4]*RAD2DEG<<
", gamma="<<par[5]*RAD2DEG
2611 <<
", V="<<par[6]<<
", score="<<bestscore<<endl;
2612 cout<<nbCalc<<
"unit cells tested, "<<nbCalc/chrono.seconds()<<
" tests/s, Elapsed time="
2613 <<chrono.seconds()<<
"s"<<endl;
2623 for(
unsigned int i=0;i<6;++i) diff += abs(par0[i]-par1[i]);
2624 return (diff/6)<delta;
2627 bool compareRUCScore(std::pair<RecUnitCell,float> &p1, std::pair<RecUnitCell,float> &p2)
2629 return p1.second > p2.second;
2632 void CellExplorer::ReduceSolutions(
const bool updateReportThreshold)
2634 const bool verbose=
false;
2635 std::list<std::pair<RecUnitCell,float> > vSolution2;
2638 for(list<pair<RecUnitCell,float> >::iterator pos=mvSolution.begin();pos!=mvSolution.end();)
2640 if(pos->second<(mBestScore/5)) pos=mvSolution.erase(pos);
2643 if(updateReportThreshold&& ((mBestScore/5)>mMinScoreReport))
2645 cout<<
"CellExplorer::ReduceSolutions(): update threshold for report from "
2646 <<mMinScoreReport<<
" to "<<mBestScore/5<<endl;
2647 mMinScoreReport=mBestScore/5;
2650 while(mvSolution.size()>0)
2652 vSolution2.push_back(mvSolution.front());
2653 mvSolution.pop_front();
2654 vector<float> par=vSolution2.back().first.DirectUnitCell();
2656 cout<<__FILE__<<
":"<<__LINE__<<
" SOLUTION: a="<<par[0]<<
", b="<<par[1]<<
", c="<<par[2]
2657 <<
", alpha="<<par[3]*RAD2DEG<<
", beta="<<par[4]*RAD2DEG<<
", gamma="<<par[5]*RAD2DEG
2658 <<
", V="<<par[6]<<
", score="<<vSolution2.back().second<<
", SIMILAR TO:"<<endl;
2659 for(list<pair<RecUnitCell,float> >::iterator pos=mvSolution.begin();pos!=mvSolution.end();)
2661 if(SimilarRUC(pos->first,vSolution2.back().first))
2663 par=pos->first.DirectUnitCell();
2665 cout<<__FILE__<<
":"<<__LINE__<<
" 1: a="<<par[0]<<
", b="<<par[1]<<
", c="<<par[2]
2666 <<
", alpha="<<par[3]*RAD2DEG<<
", beta="<<par[4]*RAD2DEG<<
", gamma="<<par[5]*RAD2DEG
2667 <<
", V="<<par[6]<<
", score="<<pos->second<<
" ("<<mvSolution.size()<<
")"<<endl;
2668 if(vSolution2.back().first.mlattice==pos->first.mlattice)
2670 if(pos->second>vSolution2.back().second) vSolution2.back()=*pos;
2672 else if(vSolution2.back().first.mlattice<pos->first.mlattice) vSolution2.back()=*pos;
2673 pos=mvSolution.erase(pos);
2677 par=pos->first.DirectUnitCell();
2679 cout<<__FILE__<<
":"<<__LINE__<<
" 0: a="<<par[0]<<
", b="<<par[1]<<
", c="<<par[2]
2680 <<
", alpha="<<par[3]*RAD2DEG<<
", beta="<<par[4]*RAD2DEG<<
", gamma="<<par[5]*RAD2DEG
2681 <<
", V="<<par[6]<<
", score="<<pos->second<<
" ("<<mvSolution.size()<<
")"<<endl;
2686 mvSolution=vSolution2;
2687 mvSolution.sort(compareRUCScore);
2690 if(mvSolution.size()>100)
2692 mvSolution.resize(100);
2693 if(updateReportThreshold && (mvSolution.back().second>mMinScoreReport))
2695 cout<<
"CellExplorer::ReduceSolutions(): update threshold for report from "
2696 <<mMinScoreReport<<
" to "<<mvSolution.back().second<<endl;
2697 mMinScoreReport=mvSolution.back().second;
2703 void CellExplorer::Init()
2709 vector<pair<RecUnitCell,float> >::iterator pos;
2710 const float min_latt=1./mLengthMax;
2711 const float max_latt=1./mLengthMin;
2712 const float amp_crossp=abs(cos(mAngleMax));
2714 mMin[0]=.00;mAmp[0]=.00;
2718 mMin[1]=min_latt;mAmp[1]=max_latt-min_latt;
2719 mMin[2]=min_latt;mAmp[2]=max_latt-min_latt;
2720 mMin[3]=min_latt;mAmp[3]=max_latt-min_latt;
2721 mMin[4]=0;mAmp[4]=amp_crossp;
2722 mMin[5]=0;mAmp[5]=amp_crossp;
2723 mMin[6]=0;mAmp[6]=amp_crossp;
2727 mMin[1]=min_latt;mAmp[1]=max_latt-min_latt;
2728 mMin[2]=min_latt;mAmp[2]=max_latt-min_latt;
2729 mMin[3]=min_latt;mAmp[3]=max_latt-min_latt;
2730 mMin[4]=0;mAmp[4]=amp_crossp;
2734 mMin[1]=min_latt;mAmp[1]=max_latt-min_latt;
2735 mMin[2]=min_latt;mAmp[2]=max_latt-min_latt;
2736 mMin[3]=min_latt;mAmp[3]=max_latt-min_latt;
2740 mMin[1]=min_latt;mAmp[1]=max_latt-min_latt;
2741 mMin[2]=min_latt;mAmp[2]=max_latt-min_latt;
2745 mMin[1]=min_latt;mAmp[1]=max_latt-min_latt;
2746 mMin[2]=-amp_crossp;mAmp[2]=2*amp_crossp;
2750 mMin[1]=min_latt;mAmp[1]=max_latt-min_latt;
2751 mMin[2]=min_latt;mAmp[2]=max_latt-min_latt;
2755 mMin[1]=min_latt;mAmp[1]=max_latt-min_latt;
2761 unsigned int nb1=0,nb2=0;
2802 this->ResetParList();
2804 RefinablePar tmp(
"Zero",mRecUnitCell.par+0,-0.01,0.01,gpRefParTypeObjCryst,REFPAR_DERIV_STEP_ABSOLUTE,
2805 true,
false,
true,
false);
2806 tmp.SetDerivStep(1e-4);
2810 string str=
"Reciprocal unit cell par #";
2811 for(
unsigned int i=0;i<nb1;++i)
2813 sprintf(buf,
"%i",i);
2814 RefinablePar tmp(str+(
string)buf,mRecUnitCell.par+i+1,
2815 0.01,1.,gpRefParTypeObjCryst,REFPAR_DERIV_STEP_ABSOLUTE,
2816 false,
false,
true,
false);
2817 tmp.SetDerivStep(1e-4);
2820 for(
unsigned int i=nb1;i<(nb1+nb2);++i)
2822 sprintf(buf,
"%i",i);
2823 RefinablePar tmp(str+(
string)buf,mRecUnitCell.par+i+1,
2824 0.0,0.5,gpRefParTypeObjCryst,REFPAR_DERIV_STEP_ABSOLUTE,
2825 false,
false,
true,
false);
2826 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.
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.
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.
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.