Exemplo n.º 1
0
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(&params);

        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;
}
Exemplo n.º 2
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();
}
Exemplo n.º 3
0
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;
}
Exemplo n.º 5
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)
Exemplo n.º 6
0
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";
}