int main(int argc, char *argv[]) { try { StandardException exc; if(argc < 3) { std::string exceptionString = "Need to specify the spline type (linear or cubic) and the number of (internal) knots."; exc.set(exceptionString); throw exc; } bool isLinear = true; if(argv[1][0] == 'c') isLinear = false; const int nKnots = std::atoi(argv[2]); if(nKnots < 0 || nKnots > 100) { std::stringstream exceptionStr; exceptionStr << "The number of knots " << nKnots << " is invalid. Needs to be positive and not larger than 100."; exc.set(exceptionStr.str()); throw exc; } bool varyNEff = false; bool varySumMNu = false; for(int i = 3; i < argc; ++i) { if(std::string(argv[i]) == "neff") varyNEff = true; if(std::string(argv[i]) == "sum_mnu") varySumMNu = true; } int nPar = 4 + 2 * (nKnots + 2) - 2; if(varyNEff) { ++nPar; output_screen("Varying N_eff!" << std::endl); } else { output_screen("N_eff not being varied. To vary it give \"neff\" as an extra argument." << std::endl); } if(varySumMNu) { ++nPar; output_screen("Varying sum_mnu!" << std::endl); } else { output_screen("sum_mnu not being varied. To vary it give \"sum_mnu\" as an extra argument." << std::endl); } // for A_planck ++nPar; const double kMin = 0.8e-6; const double kMax = 1.2; const double aMin = -2; const double aMax = 4; std::vector<double> kVals(nKnots + 2); std::vector<double> amplitudes(nKnots + 2, 2e-9); kVals[0] = kMin; kVals.back() = kMax; const double deltaLogK = (std::log(kMax) - std::log(kMin)) / (nKnots + 1); for(int i = 1; i < kVals.size() - 1; ++i) kVals[i] = std::exp(std::log(kMin) + i * deltaLogK); SplineWithDegenerateNeutrinosParams params(isLinear, 0.022, 0.12, 0.7, 0.1, kVals, amplitudes, 3.046, 0, 0, varyNEff, varySumMNu); #ifdef COSMO_PLANCK_15 PlanckLikelihood planckLike(true, true, true, false, true, false, false, false, 100); #else ERROR NOT IMPLEMENTED; #endif planckLike.setModelCosmoParams(¶ms); std::stringstream root; root << "knotted_"; if(isLinear) root << "linear_"; else root << "cubic_"; root << nKnots; if(varyNEff) root << "_neff"; if(varySumMNu) root << "_summnu"; PolyChord pc(nPar, planckLike, 300, root.str(), 3 * (4 + (varyNEff ? 1 : 0) + (varySumMNu ? 1 : 0))); int paramIndex = 0; pc.setParam(paramIndex++, "ombh2", 0.02, 0.025, 1); pc.setParam(paramIndex++, "omch2", 0.1, 0.2, 1); pc.setParam(paramIndex++, "h", 0.55, 0.85, 1); pc.setParam(paramIndex++, "tau", 0.02, 0.20, 1); if(varyNEff) pc.setParam(paramIndex++, "n_eff", 2.0, 5.0, 1); if(varySumMNu) pc.setParam(paramIndex++, "sum_mnu", 0.001, 3.0, 1); for(int i = 1; i < kVals.size() - 1; ++i) { std::stringstream paramName; paramName << "k_" << i; pc.setParamSortedUniform(paramIndex++, paramName.str(), std::log(kMin), std::log(kMax), 0, 2); } for(int i = 0; i < amplitudes.size(); ++i) { std::stringstream paramName; paramName << "a_" << i; pc.setParam(paramIndex++, paramName.str(), aMin, aMax, 2); } #ifdef COSMO_PLANCK_15 pc.setParamGauss(paramIndex++, "A_planck", 1, 0.0025, 3); #else ERROR NOT IMPLEMENTED; #endif check(paramIndex == nPar, ""); const std::vector<double> fracs{0.7, 0.25, 0.05}; pc.setParameterHierarchy(fracs); pc.run(true); } catch (std::exception& e) { output_screen("EXCEPTION CAUGHT!!! " << std::endl << e.what() << std::endl); output_screen("Terminating!" << std::endl); return 1; } return 0; }
void MnScanner::run(bool res) { CosmoMPI::create().barrier(); StandardException exc; nFixed_ = 0; for(int i = 0; i < n_; ++i) { if(paramPriors_[i].empty()) ++nFixed_; } check(nFixed_ < n_, "cannot have all of the parameters fixed"); int IS = 1; // do Nested Importance Sampling? int mmodal = 0; // do mode separation? int ceff = (accurateEvidence_ ? 0 : 1); // run in constant efficiency mode? double efr = (accurateEvidence_ ? 0.3 : 0.8); // set the required efficiency double tol = 0.5; // tol, defines the stopping criteria int ndims = n_ - nFixed_; // dimensionality (no. of free parameters) int nPar = n_ - nFixed_; // total no. of parameters including free & derived parameters int nClsPar = n_ - nFixed_; // no. of parameters to do mode separation on int updInt = 100; // after how many iterations feedback is required & the output files should be updated // note: posterior files are updated & dumper routine is called after every updInt*10 iterations double Ztol = -1E90; // all the modes with logZ < Ztol are ignored int maxModes = 100; // expected max no. of modes (used only for memory allocation) int pWrap[ndims]; // which parameters to have periodic boundary conditions? for(int i = 0; i < ndims; i++) pWrap[i] = 0; //char root[100] = fileRoot_.c_str(); // root for output files int seed = -1; // random no. generator seed, if < 0 then take the seed from system clock int fb = 1; // need feedback on standard output? int resume = res; // resume from a previous job? int outfile = 1; // write output files? int initMPI = 0; // initialize MPI routines?, relevant only if compiling with MPI // set it to F if you want your main program to handle MPI initialization double logZero = -1E90; // points with loglike < logZero will be ignored by MultiNest int maxiter = 0; // max no. of iterations, a non-positive value means infinity. MultiNest will terminate if either it // has done max no. of iterations or convergence criterion (defined through tol) has been satisfied void* context = (void*) this; // Creating the paramnames file std::stringstream paramNamesFileName; paramNamesFileName << fileRoot_ << ".paramnames"; std::ofstream outPar(paramNamesFileName.str().c_str()); if(!outPar) { std::stringstream exceptionStr; exceptionStr << "Cannot write into paramnames file " << paramNamesFileName.str() << "."; exc.set(exceptionStr.str()); throw exc; } for(int i = 0; i < n_; ++i) { outPar << paramNames_[i] << '\t' << paramNames_[i] << std::endl; } outPar.close(); // calling MultiNest try { nested::run(IS, mmodal, ceff, nLive_, tol, efr, ndims, nPar, nClsPar, maxModes, updInt, Ztol, fileRoot_, seed, pWrap, fb, resume, outfile, initMPI, logZero, maxiter, myLogLike, myDumper, context); } catch (std::exception& e) { dumpInfo(e.what()); throw e; } CosmoMPI::create().barrier(); }
void MnScanner::dumper(int &nSamples, int &nlive, int &nPar, double **physLive, double **posterior, double **paramConstr, double &maxLogLike, double &logZ, double &INSLogZ, double &logZerr) { StandardException exc; check(nPar == n_ - nFixed_, ""); // convert the 2D Fortran arrays to C++ arrays // the posterior distribution // postdist will have nPar parameters in the first nPar columns & loglike value & the posterior probability in the last two columns int i, j; std::stringstream postFileName; postFileName << fileRoot_ << "posterior.txt"; std::ofstream outPost(postFileName.str().c_str()); if(!outPost) { std::stringstream exceptionStr; exceptionStr << "Cannot write into posterior distribution file " << postFileName.str() << "."; exc.set(exceptionStr.str()); throw exc; } double postdist[nSamples][nPar + 2]; for( i = 0; i < nPar + 2; i++ ) for( j = 0; j < nSamples; j++ ) postdist[j][i] = posterior[0][i * nSamples + j]; for(i = 0; i < nSamples; ++i) { for(j = 0; j < nPar + 1; ++j) outPost << postdist[i][j] << ' '; outPost << postdist[i][nPar + 1] << std::endl; } outPost.close(); // last set of live points // pLivePts will have nPar parameters in the first nPar columns & loglike value in the last column double pLivePts[nlive][nPar + 1]; for( i = 0; i < nPar + 1; i++ ) for( j = 0; j < nlive; j++ ) pLivePts[j][i] = physLive[0][i * nlive + j]; std::stringstream constrFileName; constrFileName << fileRoot_ << "parameter_constraints.txt"; std::ofstream outConstr(constrFileName.str().c_str()); if(!outConstr) { std::stringstream exceptionStr; exceptionStr << "Cannot write into constraints file " << constrFileName.str() << "."; exc.set(exceptionStr.str()); throw exc; } outConstr << "Constraints from " << nSamples << " samples:" << std::endl; outConstr << "log(Z) = " << logZ << "+-" << logZerr << std::endl; outConstr << "INS log(Z) = " << INSLogZ << "+-" << logZerr << std::endl; // parameter constraints j = 0; for(i = 0; i < n_; ++i) { if(paramPriors_[i].empty()) { paramsMean_[i] = paramsFixed_[i]; paramsStd_[i] = 0.0; paramsBest_[i] = paramsFixed_[i]; } else { paramsMean_[i] = paramConstr[0][j]; paramsStd_[i] = paramConstr[0][nPar + j]; paramsBest_[i] = paramConstr[0][2 * nPar + j]; ++j; } outConstr << paramNames_[i] << ": " << paramsBest_[i] << " " << paramsMean_[i] << "+-" << paramsStd_[i] << std::endl; } outConstr.close(); }
int main(int argc, char *argv[]) { try { StandardException exc; using namespace Math; // Check if this is the master MPI process bool isMaster = true; #ifdef COSMO_MPI int hasMpiInitialized; MPI_Initialized(&hasMpiInitialized); if(!hasMpiInitialized) MPI_Init(NULL, NULL); int rank; MPI_Comm_rank(MPI_COMM_WORLD, &rank); if(rank != 0) isMaster = false; #endif // Create the likelihood ExampleMHLikelihood like; std::string root = "example_files/metropolis_hastings"; // Create the Metropolis-Hastings sampler MetropolisHastings mh(2, like, root); // Assign parameter names and ranges const double xMin = -10, xMax = 10, yMin = -10, yMax = 10; mh.setParam(0, "x", xMin, xMax, 0, 5, 0.5, 0.05); mh.setParam(1, "y", yMin, yMax, 0, 5, 0.5, 0.05); // Set the Metropolis-Hastings sampler to vary both parameters together as one block std::vector<int> blocks(1, 2); mh.specifyParameterBlocks(blocks); // Choose the burnin and run const unsigned long burnin = 1000; const int nChains = mh.run(1000000, 0, burnin, MetropolisHastings::GELMAN_RUBIN, 0.00001); // Only the master process will analyze the results if(isMaster) { // Read the resulting chain(s) with thinning const unsigned int thin = 1; MarkovChain chain(nChains, root.c_str(), burnin, thin); // Get the one dimensional marginalized posterior distributions, Gaussian smoothed with a scale of 0.3 Posterior1D* px = chain.posterior(0, Posterior1D::GAUSSIAN_SMOOTHING); Posterior1D* py = chain.posterior(1, Posterior1D::GAUSSIAN_SMOOTHING); // Get the two dimensional posterior distribution, gaussian smoothed with a scale of 0.25 Posterior2D* pxy = chain.posterior(0, 1); // Write the distributions into text files output_screen("Writing the distributions into text files..." << std::endl); px->writeIntoFile("example_files/mh_px.txt"); py->writeIntoFile("example_files/mh_py.txt"); pxy->writeIntoFile("example_files/mh_pxy.txt"); output_screen("OK" << std::endl); // Write the contour levels for the 2D distribution into a text file. This can be used later to make contour plots std::ofstream out("example_files/mh_contour_levels.txt"); if(!out) { std::stringstream exceptionStr; exceptionStr << "Cannot write into file example_files/mh_contour_levels.txt."; exc.set(exceptionStr.str()); throw exc; } out << pxy->get1SigmaLevel() << std::endl; //out << pxy->get2SigmaLevel() << std::endl; out.close(); // Delete the posterior distributions delete px; delete py; delete pxy; } // Finalize MPI if not done so yet #ifdef COSMO_MPI int hasMpiFinalized; MPI_Finalized(&hasMpiFinalized); if(!hasMpiFinalized) MPI_Finalize(); #endif } catch (std::exception& e) { output_screen("EXCEPTION CAUGHT!!! " << std::endl << e.what() << std::endl); output_screen("Terminating!" << std::endl); return 1; } return 0; }
int main(int argc, char *argv[]) { try { StandardException exc; if(argc < 5) { std::string exceptionStr = "Input chain file, the indices of the two parameters for the contour plot (starting from 1), the output file, and the posterior resolution (i.e. number of points, optional, default = 100) must be specified."; exc.set(exceptionStr); throw exc; } std::stringstream paramsStr; paramsStr << argv[2] << ' ' << argv[3]; int p1, p2; paramsStr >> p1 >> p2; if(p1 <= 0) { std::stringstream exceptionStr; exceptionStr << "Invalid parameter index " << argv[2] << ". Needs to be a positive integer."; exc.set(exceptionStr.str()); throw exc; } if(p2 <= 0) { std::stringstream exceptionStr; exceptionStr << "Invalid parameter index " << argv[3] << ". Needs to be a positive integer."; exc.set(exceptionStr.str()); throw exc; } int res = 100; if(argc > 5) { std::stringstream resStr; resStr << argv[5]; resStr >> res; if(res <= 0) { std::stringstream exceptionStr; exceptionStr << "Invalid resolution " << argv[5] << ". Needs to be a positive integer."; exc.set(exceptionStr.str()); throw exc; } } std::vector<ChainElement> chain; std::ifstream in(argv[1]); if(!in) { std::stringstream exceptionStr; exceptionStr << "Input chain file " << argv[1] << " cannot be read."; exc.set(exceptionStr.str()); throw exc; } const int n = (p1 > p2 ? p1 : p2); output_screen("Reading the chain..." << std::endl); double maxP = 0; while(!in.eof()) { std::string s; std::getline(in, s); if(s == "") break; ChainElement e; chain.push_back(e); std::stringstream str(s); str >> e.p >> e.like; e.params.resize(n); for(int i = 0; i < n; ++i) str >> e.params[i]; if(e.p > maxP) maxP = e.p; chain.push_back(e); } in.close(); output_screen("OK" << std::endl); const double minP = maxP * 1e-6; output_screen("Creating the posterior distributions..." << std::endl); double min1 = 1e100, max1 = -1e100, min2 = 1e100, max2 = -1e100; for(unsigned long i = 0; i < chain.size(); ++i) { const ChainElement& e = chain[i]; if(e.p < minP) continue; if(e.params[p1] < min1) min1 = e.params[p1]; if(e.params[p1] > max1) max1 = e.params[p1]; if(e.params[p2] < min2) min2 = e.params[p2]; if(e.params[p2] > max2) max2 = e.params[p2]; } const double d1 = (max1 - min1) / res; const double d2 = (max2 - min2) / res; std::vector<double> x(res), y(res); for(int i = 0; i < res; ++i) { x[i] = min1 + d1 * i + d1 / 2; y[i] = min2 + d2 * i + d2 / 2; } std::vector<std::vector<double> > z(res); for(int i = 0; i < res; ++i) z[i].resize(res, 0.0); double totalP = 0; for(unsigned long i = 0; i < chain.size(); ++i) { const ChainElement& e = chain[i]; if(e.p < minP) continue; const double param1 = e.params[p1]; check(param1 >= min1, ""); int j1 = (int)std::floor((param1 - min1) / d1); check(j1 >= 0, ""); if(j1 >= res) j1 = res - 1; const double param2 = e.params[p2]; check(param2 >= min2, ""); int j2 = (int)std::floor((param2 - min2) / d2); check(j2 >= 0, ""); if(j2 >= res) j2 = res - 1; z[j1][j2] += e.p; totalP += e.p; } output_screen("OK" << std::endl); output_screen("Writing the output..." << std::endl); std::ofstream out(argv[4]); if(!out) { std::stringstream exceptionStr; exceptionStr << "Cannot write into the output file " << argv[4] << "."; exc.set(exceptionStr.str()); throw exc; } double prob = 0; unsigned long i = 0; while(prob < 1 - 1e-5 && i < chain.size()) { if(chain[i].p > minP) { out << chain[i].params[p1 - 1] << ' ' << chain[i].params[p2 - 1] << ' ' << prob << std::endl; } prob += chain[i].p; ++i; } out.close(); output_screen("OK" << std::endl); } catch (std::exception& e)
void TestLikeHigh::runSubTest(unsigned int i, double& res, double& expected, std::string& subTestName) { using namespace Math; check(i >= 0 && i < 1, "invalid index " << i); const long nSide = 2048; const int lMaxSim = 2 * int(nSide); const int lMin = 31; const int lMax = 2000; const double fwhm = double(5) / 60.0; const int n = 5000; const double h = 0.6704; const double omBH2 = 0.022032; const double omCH2 = 0.12038; const double tau = 0.0925; const double ns = 0.9619; const double as = 2.2154e-9; const double pivot = 0.05; LambdaCDMParams paramsLCDM(omBH2, omCH2, h, tau, ns, as, pivot); CMB cmb; std::vector<double> clTT; output_screen1("Calculating Cl..." << std::endl); cmb.preInitialize(lMaxSim + 1000, false, true, false); cmb.initialize(paramsLCDM, true, false, true, false); cmb.getLensedCl(&clTT); output_screen1("OK" << std::endl); double nl = 0.005; std::vector<double> beam(lMaxSim + 1); Utils::readPixelWindowFunction(beam, nSide, lMaxSim, fwhm); Healpix_Map<double> uniformMask; uniformMask.SetNside(nSide, RING); for(unsigned long i = 0; i < uniformMask.Npix(); ++i) uniformMask[i] = 1; Healpix_Map<double>& mask = uniformMask; const double omegaPixel = 4 * Math::pi / mask.Npix(); const double w = omegaPixel / nl; // mask out some stuff std::stringstream maskFileName; maskFileName << "slow_test_files/test_highl_mask_" << i << ".fits"; std::stringstream maskFileName1; maskFileName1 << "slow_test_files/test_highl_mask_ap_" << i << ".fits"; Healpix_Map<double> apodizedMask; if(!fileExists(maskFileName.str().c_str())) { output_screen1("Masking out some regions..." << std::endl); int nRegions = 25; time_t seed1 = 1000000; Math::UniformRealGenerator thetaGen(seed1, pi / 50, pi - pi / 50), phiGen(seed1 + 1, 0, 2 * pi), angleGen(seed1 + 2, pi / 60, pi / 40); std::vector<double> maskTheta(nRegions), maskPhi(nRegions), maskAngle(nRegions); for(int i = 0; i < nRegions; ++i) { maskTheta[i] = thetaGen.generate(); maskPhi[i] = phiGen.generate(); maskAngle[i] = angleGen.generate(); } Utils::maskRegions(mask, maskTheta, maskPhi, maskAngle); for(unsigned long i = 0; i < mask.Npix(); ++i) { double theta, phi; pix2ang_ring(nSide, i, &theta, &phi); if(theta < Math::pi / 2 + pi / 20 && theta > pi / 2 - pi / 20) mask[i] = 0; } output_screen1("OK" << std::endl); fitshandle outMaskHandle; outMaskHandle.create(maskFileName.str().c_str()); write_Healpix_map_to_fits(outMaskHandle, mask, PLANCK_FLOAT64); outMaskHandle.close(); } else read_Healpix_map_from_fits(maskFileName.str(), mask); if(!fileExists(maskFileName1.str().c_str())) { output_screen1("Apodizing the mask..." << std::endl); MaskApodizer ap(mask); const double apAngle = 30.0 / 60.0 / 180.0 * pi; ap.apodize(MaskApodizer::COSINE_APODIZATION, apAngle, apodizedMask); output_screen1("OK" << std::endl); fitshandle outMaskHandle1; outMaskHandle1.create(maskFileName1.str().c_str()); write_Healpix_map_to_fits(outMaskHandle1, apodizedMask, PLANCK_FLOAT64); outMaskHandle1.close(); } else read_Healpix_map_from_fits(maskFileName1.str(), apodizedMask); check(apodizedMask.Nside() == nSide, ""); Healpix_Map<double> noiseWeight, noiseInvMat; noiseWeight.SetNside(nSide, RING); noiseInvMat.SetNside(nSide, RING); double nwAvg = 0; for(unsigned long i = 0; i < noiseWeight.Npix(); ++i) { noiseInvMat[i] = w; nwAvg += 1.0 / noiseInvMat[i]; noiseWeight[i] = noiseInvMat[i] * apodizedMask[i]; } nwAvg /= noiseWeight.Npix(); check(nwAvg > 0, ""); nl = omegaPixel * nwAvg; std::vector<double> nlTT(lMaxSim + 1, nl); std::ofstream outCl("slow_test_files/test_like_high_cl.txt"); for(int l = 0; l <= lMax; ++l) { const double factor = l * (l + 1) / (2 * Math::pi); outCl << l << '\t' << clTT[l] * factor << '\t' << nlTT[l] * factor << std::endl; } outCl.close(); std::stringstream couplingKernelFileName; couplingKernelFileName << "slow_test_files/" << "test_highl_mask_" << i << "_cc.txt"; std::stringstream noiseCouplingKernelFileName; noiseCouplingKernelFileName << "slow_test_files/" << "test_highl_noise_" << i << "_cc.txt"; output_screen1("Calculating mask coupling kernel..." << std::endl); Master::calculateCouplingKernel(apodizedMask, lMax + 500, couplingKernelFileName.str().c_str()); output_screen1("OK" << std::endl); output_screen1("Calculating noise coupling kernel..." << std::endl); Master::calculateCouplingKernel(noiseWeight, lMax + 500, noiseCouplingKernelFileName.str().c_str()); output_screen1("OK" << std::endl); Master master(apodizedMask, couplingKernelFileName.str().c_str(), beam, NULL, lMax + 500); output_screen1("Starting simulations..." << std::endl); time_t seed = std::time(0); StandardException exc; std::ofstream outLike("slow_test_files/test_highl_likes.txt"); if(!outLike) { std::string exceptionStr = "Cannot write into file slow_test_files/test_highl_likes.txt"; exc.set(exceptionStr); throw exc; } Math::Histogram<double> chi2Hist; Healpix_Map<double> noiseMap; noiseMap.SetNside(nSide, RING); ProgressMeter meter(n); for(int i = 0; i < n; ++i) { Alm<xcomplex<double> > alm, noiseAlm; Simulate::simulateAlm(clTT, alm, lMaxSim, seed); ++seed; Math::GaussianGenerator noiseGen(seed, 0.0, 1.0); for(unsigned long j = 0; j < noiseMap.Npix(); ++j) { check(noiseInvMat[j] > 0, ""); const double r = noiseGen.generate(); noiseMap[j] = r * std::sqrt(1.0 / noiseInvMat[j]); } ++seed; noiseAlm.Set(lMaxSim, lMaxSim); arr<double> weight(2 * noiseMap.Nside(), 1); map2alm(noiseMap, noiseAlm, weight); for(int l = 0; l <= lMaxSim; ++l) { for(int m = 0; m <= l; ++m) { alm(l, m) += noiseAlm(l, m); alm(l, m) *= beam[l]; } } Healpix_Map<double> map; map.SetNside(nSide, RING); alm2map(alm, map); master.calculate(map); std::vector<double> clSim(lMax + 1); for(int l = 0; l <= lMax; ++l) { std::map<double, double> ps = master.powerSpectrum(); check(ps.find(double(l)) != ps.end(), ""); const double lFactor = (l == 0 ? 1 : 2.0 * Math::pi / double(l * (l + 1))); clSim[l] = ps[double(l)] * lFactor - nlTT[l]; } LikelihoodHigh likelihood(clSim, nlTT, couplingKernelFileName.str().c_str(), lMin, lMax, noiseCouplingKernelFileName.str().c_str()); double like; like = likelihood.calculate(clTT); outLike << like << std::endl; chi2Hist.addData(like); meter.advance(); } outLike.close(); output_screen1("OK" << std::endl); chi2Hist.createHistogram(chi2Hist.min(), chi2Hist.max()); typedef Math::Histogram<double>::HistogramType HistogramType; const HistogramType& chi2Histogram = chi2Hist.getHistogram(); output_screen1("A total of " << chi2Hist.getDataSize() << " elements in the histogram." << std::endl); output_screen1("Calculating the chi squared distribution..." << std::endl); std::ofstream outDist("slow_test_files/test_highl_chi2.txt"); if(!outDist) { std::string exceptionStr = "Cannot write into file slow_test_files/test_highl_chi2.txt."; exc.set(exceptionStr); throw exc; } const double min = chi2Hist.min(), max = chi2Hist.max(); const int dof = lMax - lMin; Math::ChiSquared chi2(dof); int num = 10000; const double step = (max - min) / num; for(int i = 0; i < num; ++i) { const double x = min + step * i; const double y = chi2.evaluate(x); outDist << x << ' ' << y << std::endl; } outDist.close(); output_screen1("OK" << std::endl); std::ofstream outChi2("slow_test_files/test_highl_chi2_histogram.txt"); if(!outChi2) { std::string exceptionStr = "Cannot write into file slow_test_files/test_highl_chi2_histogram.txt."; exc.set(exceptionStr); throw exc; } double normalization = chi2Hist.getDataSize() * (chi2Hist.max() - chi2Hist.min()) / chi2Histogram.size(); const double deltaX = (chi2Hist.max() - chi2Hist.min()) / chi2Histogram.size(); double myChi2 = 0; int myDof = 0; for(HistogramType::const_iterator it = chi2Histogram.begin(); it != chi2Histogram.end(); ++it) { ++myDof; const double x = (*it).first + deltaX / 2; const double y = (double)(*it).second / normalization; outChi2 << x << ' ' << y << std::endl; const double expectedY = chi2.evaluate(x); const double diff = y - expectedY; const double e = std::sqrt(expectedY / normalization); myChi2 += diff * diff / (e * e); } output_screen("Chi^2 = " << myChi2 << " per " << myDof - 1 << " degrees of freedom." << std::endl); outChi2.close(); res = 1; expected = 1; const double chi2PerDof = myChi2 / (myDof - 1); const double chi2Sigma = std::sqrt(2.0 * (myDof - 1)); if(std::abs(myChi2 - myDof +1) > 5 * chi2Sigma) { output_screen("FAIL: Not a good fit!" << std::endl); res = 0; } subTestName = "highl"; }