00001 #include "basisfunc_imager1d.h"
00002
00003 #include "message.h"
00004 #include "constants.h"
00005
00006 #include "tnt_array1d.h"
00007 #include "linalg.h"
00008 #include "lsqrinvert.h"
00009 #include "integratevec.h"
00010 #include <cmath>
00011
00012 using namespace TNT;
00013 using namespace std;
00014
00015 #define __USE_GSL__
00016
00017 #define __IMAGER_EPSILON 1e-10
00018 #define __TYPICAL_SOURCE_SCALE__ 1e-4 //in fm^-3
00019
00020
00021 bool CBasisFuncImager1d::Read( const parameterMap& m ){
00022
00023 CGeneralImager1d::Read( m );
00024 constrain_origin = parameter::getB(m,"constrain_origin",false);
00025 constrain_rmin_zero = parameter::getB(m,"constrain_rmin_zero",false);
00026 constrain_rmax_zero_slope = parameter::getB(m,"constrain_rmax_zero_slope",false);
00027 constrain_rmax_zero = parameter::getB(m,"constrain_rmax_zero",false);
00028 return true;
00029 }
00030
00031
00032
00033 bool CBasisFuncImager1d::Write( parameterMap& m ){
00034
00035 CGeneralImager1d::Write( m );
00036 parameter::set(m,"constrain_origin",constrain_origin);
00037 parameter::set(m,"constrain_rmin_zero",constrain_rmin_zero);
00038 parameter::set(m,"constrain_rmax_zero_slope",constrain_rmax_zero_slope);
00039 parameter::set(m,"constrain_rmax_zero",constrain_rmax_zero);
00040 return true;
00041 }
00042
00043
00045 bool CBasisFuncImager1d::convertCorrelationToSource( const CCorrFtn1dHisto& corrin, CSourceFtnBase& souout, const parameterMap& m, const CKernel* _kernelPtr ){
00046
00047 CBasisFunctionExpansion1d* souPtr = dynamic_cast<CBasisFunctionExpansion1d*>(&souout);
00048 if (souPtr==NULL)
00049 throw MESSAGE<<"Source argument must derive from CBasisFunctionExpansion1d"<<ENDM_FATAL;
00050
00051
00052 cout <<" Initializing imager, "<<flush;
00053
00054 l = corrin.l;
00055 ndata_corr = corrin.ndata;
00056 qmax = corrin.rightBinEdge(corrin.ndata-1);
00057 kernel_particle1 = corrin.particle1;
00058 kernel_particle2 = corrin.particle2;
00059
00060 Read( parameter::getMap( m, "imager_settings" ) );
00061
00062 qmax = std::min(corrin.rightBinEdge(corrin.ndata-1),qmax);
00063 qmin = std::max(corrin.leftBinEdge(0),qmin);
00064 dq = corrin.binWidth(0);
00065 q0 = qmin+dq/2.;
00066
00067
00068 cout <<"kernel, "<<flush;
00069 if ( _kernelPtr == NULL ) set_kernel( parameter::getMap( m, "kernel_settings" ) );
00070 else set_kernel( _kernelPtr );
00071
00072
00073 cout <<"and working copy of data."<<endl;
00074 get_usable_data( corrin );
00075
00076
00077 if ( !initialize_source( corrwork, souout, parameter::getMap(m,"source_settings") ) ) return false;
00078 ndata_sou = souPtr->ndata;
00079 cout << " Source will have "<<ndata_sou<<" coefficients"<<endl;
00080
00081
00082 if ( ndata_corr <= 1 ) throw MESSAGE<<"Correlation has no data, ndata_corr = "<<ndata_corr<<ENDM_FATAL;
00083 if ( souPtr->ndata <= 1 ) throw MESSAGE<<"Source has no space for data, ndata_sou = "<<ndata_sou<<ENDM_FATAL;
00084
00085
00086 if ( kmtx != CKernelMatrix( l, ndata_corr, q0, dq, ndata_sou, true, kernel_particle1, kernel_particle2 ) )
00087 {
00088 cout << " Generating kmtx:"<<endl;
00089 set_kmtx(corrwork, *souPtr, m);
00090 }
00091
00092 imageit(*souPtr);
00093 return true;
00094 }
00095
00096
00098 bool CBasisFuncImager1d::convertSourceToCorrelation( const CSourceFtnBase& souin, CCorrFtn1dHisto& corrout, const parameterMap& m, const CKernel* _kernelPtr ){
00099
00100 const CBasisFunctionExpansion1d* souPtr = dynamic_cast<const CBasisFunctionExpansion1d*>(&souin);
00101 if (souPtr==NULL) throw MESSAGE<<"Source argument must derive from CBasisFunctionExpansion1d"<<ENDM_FATAL;
00102
00103
00104 l = souPtr->l;
00105 ndata_sou = souPtr->ndata;
00106 rmax = souPtr->getRightSupport(souPtr->ndata-1);
00107 rmin = souPtr->getLeftSupport(0);
00108 kernel_particle1 = souin.particle1;
00109 kernel_particle2 = souin.particle2;
00110
00111
00112 Read( parameter::getMap( m, "imager_settings" ) );
00113
00114
00115 if ( _kernelPtr == NULL ) set_kernel( parameter::getMap( m, "kernel_settings" ) );
00116 else set_kernel( _kernelPtr );
00117
00118
00119 if ( !initialize_correlation( souin, corrout, parameter::getMap(m,"correlation_settings") ) ) return false;
00120 if ( ndata_sou <= 1 ) throw MESSAGE<<"Source has no data, ndata_sou = "<<ndata_sou<<ENDM_FATAL;
00121 if ( ndata_corr <= 1 ) ndata_corr = max( corrout.ndata, ndata_sou );
00122 corrout.covmtx_is_active=true;
00123 corrout.setDim( ndata_corr );
00124 corrout.setFixedWidthBins(dq,q0);
00125
00126
00127 if ( kmtx != CKernelMatrix( l, ndata_corr, q0, dq, ndata_sou, true, kernel_particle1, kernel_particle2 ) ) {
00128 cout << " Generating kmtx:"<<endl;
00129 set_kmtx( corrout, *souPtr, m );
00130 }
00131 unimageit( *souPtr, corrout );
00132 return true;
00133 }
00134
00135
00136 void CBasisFuncImager1d::unimageit(const CBasisFunctionExpansion1d& souin, CCorrFtn1dHisto& corrout){
00137
00138
00139 corrout.data=(1./__TYPICAL_SOURCE_SCALE__)*kmtx*souin.data;
00140
00141
00142 Array2D< double > covmtx;
00143 if (souin.covmtx_is_active) covmtx = souin.covmtx;
00144 else covmtx = makeDiagSquared( souin.uncert );
00145
00146
00147 corrout.covmtx=(1./(__TYPICAL_SOURCE_SCALE__*__TYPICAL_SOURCE_SCALE__))
00148 * matmult(matmult(kmtx,covmtx),transpose(kmtx));
00149 corrout.syncUncert();
00150
00151
00152 if (l==0) {
00153 for (int i=0;i<corrout.data.dim();i++) corrout.data[i]=corrout.data[i]+1.0;
00154 }
00155 }
00156
00157
00159 double CBasisFuncImager1d::imageit(CBasisFunctionExpansion1d& souout){
00160
00161
00162 set_constraints(souout);
00163
00164
00165 cout << " Inverting..."<<endl;
00166 if (num_constraints>0) {
00167 cout << " Using constraints"<<endl;
00168 CLSqrInvertSVDLagrange inverter( kmtx, conmtx, convec );
00169 inverter.solve( corrwork.data, corrwork.covmtx );
00170 souout.data = inverter.model();
00171 souout.covmtx = inverter.covmodel();
00172 cout << " Lagrange Multiplier vector:\n";
00173 cout << inverter.lagrange_multipliers() << endl;
00174 } else
00175 LeastSquaresInvert( corrwork.data, corrwork.covmtx, kmtx, souout.data, souout.covmtx );
00176
00177
00178 souout.data = __TYPICAL_SOURCE_SCALE__*souout.data;
00179 souout.covmtx = __TYPICAL_SOURCE_SCALE__*__TYPICAL_SOURCE_SCALE__*souout.covmtx;
00180 souout.covmtx_is_active = true;
00181
00182
00183 double chi2 = 0.0, tmp = 0.0;
00184 Array1D<double> residual = (1.0/__TYPICAL_SOURCE_SCALE__)*kmtx*souout.data - corrwork.data;
00185 for (int i=0;i<corrwork.ndata;++i){
00186 tmp = residual[i]/sqrt(corrwork.covmtx[i][i]);
00187 chi2+=tmp*tmp;
00188 }
00189
00190 if (isnan(chi2)) throw MESSAGE << "Imaging failed, chi^2 is NaN!"<< ENDM_FATAL;
00191 if (chi2/corrwork.ndata>1e3) MESSAGE<<"Terrible chi^2, something is probably wrong!"<<ENDM_SEVERE;
00192 if (chi2/corrwork.ndata<1e-3) MESSAGE<<"Way too good chi^2, you're over resolving something!"<<ENDM_SEVERE;
00193 cout << " Final chi^2 = " << chi2 << endl;
00194 cout << " Final chi^2/NDF = " << chi2/corrwork.ndata << endl;
00195
00196
00197 cout << " Synching uncertainty with covariance" << endl;
00198 souout.syncUncert();
00199
00200 return chi2;
00201 }
00202
00203
00204 bool CBasisFuncImager1d::set_no_data( CSourceFtnBase& souout ){
00205
00206 cout << " Zeroed data, skipping the imaging...\n";
00207 Array1D<double> tmpcoef(ndata_sou,0.0);
00208 Array2D<double> tmpcov(ndata_sou,ndata_sou,0.0);
00209 CBasisFunctionExpansion1d* souPtr = dynamic_cast<CBasisFunctionExpansion1d*>(&souout);
00210 if (souPtr==NULL) throw MESSAGE<<"Source argument must derive from CBasisFunctionExpansion1d"<<ENDM_FATAL;
00211 souPtr->data = tmpcoef;
00212 souPtr->covmtx = tmpcov;
00213 souPtr->ndata = ndata_sou;
00214 souPtr->xmin = 0.0;
00215 souPtr->xmax = rmax;
00216 souPtr->syncUncert();
00217 return true;
00218 }
00219
00220
00221 bool CBasisFuncImager1d::initialize_source( const CCorrFtn1dHisto& corrin, CSourceFtnBase& souout, const parameterMap& m ){
00222
00223 CBasisFunctionExpansion1d* souPtr = dynamic_cast<CBasisFunctionExpansion1d*>(&souout);
00224 if (souPtr==NULL) throw MESSAGE<<"Source argument must derive from CBasisFunctionExpansion1d"<<ENDM_FATAL;
00225 return CGeneralImager1d::initialize_source(corrin,souout,m);
00226 }
00227
00228
00229 void CBasisFuncImager1d::set_constraints( const CBasisFunctionExpansion1d& souout ){
00230
00231 if ( ndata_sou != souout.ndata )
00232 throw MESSAGE << "ndata_sou ("<<ndata_sou<<") != souout.ndata ("<<souout.ndata<<")!!!" <<ENDM_FATAL;
00233
00234 cout << " Setting up constraints"<<endl;
00235
00236
00237 num_constraints=0;
00238 if (constrain_origin) {
00239 if (souout.l == 0) {num_constraints+=1;} else {num_constraints+=2;}
00240 }
00241 if (constrain_rmax_zero_slope) num_constraints+=1;
00242 if (constrain_rmax_zero) num_constraints+=1;
00243 if (num_constraints>0)
00244 cout<<" Initializing "<<num_constraints<<" valid constraints\n";
00245 else {
00246 cout<<" No constraints to initialize\n";
00247 return;
00248 }
00249
00250
00251 Array2D<double> _conmtx(num_constraints,souout.ndata);
00252 Array1D<double> _convec(num_constraints,0.0);
00253 conmtx=_conmtx;
00254 convec=_convec;
00255 int icons=0;
00256
00257
00258
00259 if (constrain_origin) {
00260 cout << " Constraining dS_lm(0)/dr = 0"<<endl;
00261 for (int i=0;i<souout.ndata;++i){conmtx[icons][i]=souout.basisFunction(0.0,i,1);}
00262 icons++;
00263 }
00264
00265
00266 if ((souout.l!=0)&&constrain_origin) {
00267 cout << " Constraining S_lm(0) = 0 for l > 0"<<endl;
00268 for (int i=0;i<souout.ndata;++i){conmtx[icons][i]=souout.basisFunction(0.0,i,0);}
00269 icons++;
00270 }
00271
00272
00273 if ((souout.l!=0)&&constrain_rmin_zero) {
00274 cout << " Constraining S_lm(rmin) = 0"<<endl;
00275 for (int i=0;i<souout.ndata;++i){conmtx[icons][i]=souout.basisFunction(rmin,i,0);}
00276 icons++;
00277 }
00278
00279
00280 if (constrain_rmax_zero) {
00281 cout << " Constraining S_lm(rmax) = 0"<<endl;
00282 for (int i=0;i<souout.ndata;++i){conmtx[icons][i]=souout.basisFunction(rmax,i,0);}
00283 icons++;
00284 }
00285
00286
00287 if (constrain_rmax_zero_slope) {
00288 cout << " Constraining dS_lm(rmax)/dr = 0"<<endl;
00289 for (int i=0;i<souout.ndata;++i){conmtx[icons][i]=souout.basisFunction(rmax,i,1);}
00290 icons++;
00291 }
00292 }
00293
00294
00295 void CBasisFuncImager1d::set_kmtx( const CCorrFtn1dHisto& corrin, const CBasisFunctionExpansion1d& souout, const parameterMap& m ){
00296
00297 sourcePtr = &souout;
00298 CKernelMatrix kmtx_tmp(corrin.l, ndata_corr, q0, dq, ndata_sou, true, kernel_particle1, kernel_particle2);
00299
00300 CIntegrateVector integrate;
00301 double dq, qmin, qmax, rmin, rmax;
00302 integrate.SetNDim(2);
00303 integrate.SetNumFunc(1);
00304 integrate.SetMaxPts(1000);
00305 __l=corrin.l;
00306 for (int i=0;i<kmtx_tmp.dim1();++i){
00307 for (int j=0;j<kmtx_tmp.dim2();++j){
00308 dq = corrin.binWidth(i);
00309 qmin = corrin.getLeftSupport(i);
00310 qmax = corrin.getRightSupport(i);
00311 rmin = sourcePtr->getLeftSupport(j);
00312 rmax = sourcePtr->getRightSupport(j);
00313 __j = j;
00314 integrate.SetLimits(0,qmin,qmax);
00315 integrate.SetLimits(1,rmin,rmax);
00316 if (qmax<=qmin) kmtx_tmp[i][j]=0.0;
00317 else {
00318 integrate.Compute(this,kp_integrand);
00319 kmtx_tmp[i][j]=integrate.GetResults(0)/dq*__TYPICAL_SOURCE_SCALE__;
00320 }
00321 }
00322 }
00323
00324 kmtx = kmtx_tmp;
00325 sourcePtr = NULL;
00326 cout <<" The kmtx has been generated!"<<endl;
00327 }
00328
00329
00330 void CBasisFuncImager1d::kp_integrand(void* classptr, int* ndim, double* x, int* numfunc, double* f){
00331
00332 CBasisFuncImager1d *cls = (CBasisFuncImager1d*)classptr;
00333 f[0]=4.*PI*x[1]*x[1]*
00334 (cls->kernelPtr->GetValue(cls->__l,x[0],x[1]))*
00335 (cls->sourcePtr->basisFunction(x[1],cls->__j,0));
00336 };
00337