/*+ VIDE -- Void IDentification and Examination -- ./c_tools/mock/generateFromCatalog.cpp Copyright (C) 2010-2014 Guilhem Lavaux Copyright (C) 2011-2014 P. M. Sutter This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; version 2 of the License. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ #include #include #include #include #include #include #include #include "generateFromCatalog_conf.h" #include "contour_pixels.hpp" #include #include #include #include #define LIGHT_SPEED 299792.458 using namespace std; using boost::format; using namespace CosmoTool; struct NYU_Data { int index; int sector; int region; double ra, dec; double cz; double fgotten; double phi_z; long uniqueID; }; struct Position { double xyz[3]; }; struct ParticleData { vector id_gal; vector ra; vector dec; vector redshift; vector catalogID; vector uniqueID; int id_mask; // PMS int mask_index; // END PMS vector pos; double box[3][2]; double Lmax; }; typedef vector NYU_VData; // this defines the expansion function that we will integrate // Laveaux & Wandelt (2012) Eq. 24 struct my_expan_params { double Om; double w0; double wa; }; double expanFun (double z, void * p) { struct my_expan_params * params = (struct my_expan_params *)p; double Om = (params->Om); double w0 = (params->w0); double wa = (params->wa); //const double h0 = 1.0; const double h0 = 0.71; double ez; double wz = w0 + wa*z/(1+z); ez = Om*pow(1+z,3) + (1.-Om); //ez = Om*pow(1+z,3) + pow(h0,2) * (1.-Om)*pow(1+z,3+3*wz); ez = sqrt(ez); //ez = sqrt(ez)/h0; ez = 1./ez; return ez; } void loadData(const string& fname, NYU_VData & data) { ifstream f(fname.c_str()); while (!f.eof()) { NYU_Data d; f >> d.index >> d.sector >> d.region >> d.ra >> d.dec >> d.cz >> d.fgotten >> d.phi_z; // Maubert - avoid double counting of last particle in array if EOF is after a blank line if (!f) { continue; } // End Maubert d.uniqueID = d.index; data.push_back(d); } } void generateGalaxiesInCube(NYU_VData& data, ParticleData& output_data, bool useComoving, double omegaM) { double d2r = M_PI/180; gsl_function expanF; expanF.function = &expanFun; struct my_expan_params expanParams; double maxZ = 2.0, z, result, error, *dL, *redshifts; int numZ = 1000, iZ; size_t nEval; expanParams.Om = omegaM; expanParams.w0 = -1.0; expanParams.wa = 0.0; expanF.params = &expanParams; dL = (double *) malloc(numZ * sizeof(double)); redshifts = (double *) malloc(numZ * sizeof(double)); for (iZ = 0; iZ < numZ; iZ++) { z = iZ * maxZ/numZ; //gsl_integration_qng(&expanF, 0.0, z, 1.e-6, 1.e-6, &result, &error, &nEval); dL[iZ] = result; redshifts[iZ] = z; } gsl_interp *interp = gsl_interp_alloc(gsl_interp_linear, numZ); gsl_interp_init(interp, redshifts, dL, numZ); gsl_interp_accel *acc = gsl_interp_accel_alloc(); output_data.pos.resize(data.size()); output_data.id_gal.resize(data.size()); output_data.ra.resize(data.size()); output_data.dec.resize(data.size()); output_data.redshift.resize(data.size()); output_data.uniqueID.resize(data.size()); for (int j = 0; j < 3; j++) { output_data.box[j][0] = -INFINITY; output_data.box[j][1] = INFINITY; } for (int i = 0; i < data.size(); i++) { double ra = data[i].ra*d2r, dec = data[i].dec*d2r; Position& p = output_data.pos[i]; if (useComoving) { //double pos = gsl_interp_eval(interp, redshifts, dL, data[i].cz, acc); // Maubert - Lower boundary in redshift set to 0 to be consistent with pruneVoids (was 1.e-6 before). gsl_integration_qng(&expanF, 0.0, data[i].cz/LIGHT_SPEED, 1.e-6, 1.e-6, &result, &error, &nEval); double Dc = result*LIGHT_SPEED; p.xyz[0] = Dc*cos(ra)*cos(dec); p.xyz[1] = Dc*sin(ra)*cos(dec); p.xyz[2] = Dc*sin(dec); } else { p.xyz[0] = data[i].cz*cos(ra)*cos(dec); p.xyz[1] = data[i].cz*sin(ra)*cos(dec); p.xyz[2] = data[i].cz*sin(dec); } //printf("CREATE %e %e\n", data[i].cz, sqrt(p.xyz[0]*p.xyz[0] + p.xyz[1]*p.xyz[1] + p.xyz[2]*p.xyz[2])); output_data.id_gal[i] = data[i].index; output_data.ra[i] = ra; output_data.dec[i] = dec; output_data.redshift[i] = data[i].cz; output_data.uniqueID[i] = data[i].uniqueID; for (int j = 0; j < 3; j++) { if (p.xyz[j] > output_data.box[j][0]) output_data.box[j][0] = p.xyz[j]; if (p.xyz[j] < output_data.box[j][1]) output_data.box[j][1] = p.xyz[j]; } //printf("INSERT GAL %d %e %e %e\n", output_data.id_gal[i], p.xyz[0], p.xyz[1], p.xyz[2]); } // normalize box float left = 1.e99; float right = -1.e99; for (int j = 0; j < 3; j++) { if (output_data.box[j][1] < left) left = output_data.box[j][1]; if (output_data.box[j][0] > right) right = output_data.box[j][0]; } for (int j = 0; j < 3; j++) { output_data.box[j][1] = left; output_data.box[j][0] = right; } cout << format("Galaxy position generated: %d galaxies") % output_data.pos.size() << endl; cout << format("box is %g < x < %g; %g < y < %g; %g < z < %g") % (1e-2*output_data.box[0][1]) % (1e-2*output_data.box[0][0]) % (1e-2*output_data.box[1][1]) % (1e-2*output_data.box[1][0]) % (1e-2*output_data.box[2][1]) % (1e-2*output_data.box[2][0]) << endl; gsl_interp_free(interp); } void generateSurfaceMask(generateFromCatalog_info& args , Healpix_Map& mask, vector& pixel_list, vector& full_mask_list, NYU_VData& data, ParticleData& output_data, bool useComoving, double omegaM) { //Maubert - Needed for comobile distance in mock_sphere gsl_function expanF; expanF.function = &expanFun; struct my_expan_params expanParams; expanParams.Om = omegaM; expanParams.w0 = -1.0; expanParams.wa = 0.0; expanF.params = &expanParams; double result, error ; size_t nEval; //End Maubert - Needed for comobile distance in mock_sphere // Find the first free index int idx = -1; int insertion = 0; double volume = pixel_list.size()*1.0/mask.Npix()*4*M_PI; int numToInsert; for (int i = 0; i < output_data.id_gal.size(); i++) { if (idx < output_data.id_gal[i]) idx = output_data.id_gal[i]+1; } output_data.id_mask = idx; // PMS output_data.mask_index = output_data.id_gal.size(); // END PMS cout << "Generate surface mask..." << endl; double Rmax = -1; for (int j = 0; j < 3; j++) { Rmax = max(Rmax, max(output_data.box[j][0], -output_data.box[j][1])); } output_data.Lmax = Rmax; // PMS - write a small text file with galaxy position FILE *fp; fp = fopen("galaxies.txt", "w"); for (int i = 0; i < data.size(); i++) { Position& p = output_data.pos[i]; fprintf(fp, "%e %e %e\n", (p.xyz[0]), (p.xyz[1]), (p.xyz[2])); } fclose(fp); // END PMS cout << format("Rmax is %g, surface volume is %g") % (Rmax/100) % (volume/(4*M_PI)) << endl; volume *= Rmax*Rmax*Rmax/3/1e6; numToInsert = (int)floor(volume*args.density_fake_arg); cout << format("3d volume to fill: %g (Mpc/h)^3") % volume << endl; cout << format("Will insert %d particles") % numToInsert << endl; fp = fopen("mock_galaxies.txt", "w"); double pct = 0; for (int i = 0; i < numToInsert; i++) { double new_pct = i*100./numToInsert; if (new_pct-pct > 5.) { pct = new_pct; cout << format(" .. %3.0f %%") % pct << endl; } Position p; bool stop_here; do { int p0 = (int)floor(drand48()*pixel_list.size()); vec3 v = mask.pix2vec(pixel_list[p0]); double r = Rmax*pow(drand48(),1./3); p.xyz[0] = v.x * r; p.xyz[1] = v.y * r; p.xyz[2] = v.z * r; stop_here = true; for (int j = 0; j < 3; j++) { if (p.xyz[j] > output_data.box[j][0] || p.xyz[j] < output_data.box[j][1]) stop_here = false; } } while (!stop_here); // PMS : write mock galaxies to a small file for plotting fprintf(fp, "%e %e %e\n", (p.xyz[0]), (p.xyz[1]), (p.xyz[2])); // END PMS output_data.pos.push_back(p); output_data.id_gal.push_back(idx); output_data.ra.push_back(-1); output_data.dec.push_back(-1); output_data.redshift.push_back(-1); output_data.uniqueID.push_back(-1); //printf("INSERT MOCK %d %e %e %e\n", idx, p.xyz[0], p.xyz[1], p.xyz[2]); insertion++; } fclose(fp); // PMS // TEST - insert mock galaxies along box edge fp = fopen("mock_boundary.txt", "w"); double dx[3]; dx[0] = output_data.box[0][1] - output_data.box[0][0]; dx[1] = output_data.box[1][1] - output_data.box[1][0]; dx[2] = output_data.box[2][1] - output_data.box[2][0]; int nPart = 100; // TEST for (int iDir = 0; iDir < 0; iDir++) { for (int iFace = 0; iFace < 0; iFace++) { //for (int iDir = 0; iDir < 3; iDir++) { //for (int iFace = 0; iFace < 2; iFace++) { int iy = (iDir + 1) % 3; int iz = (iDir + 2) % 3; for (int i = 0; i < nPart; i++) { for (int j = 0; j < nPart; j++) { Position p; p.xyz[iDir] = output_data.box[iDir][iFace]; p.xyz[iy] = i * dx[iy]/nPart + output_data.box[iy][0]; p.xyz[iz] = j * dx[iz]/nPart + output_data.box[iz][0]; output_data.pos.push_back(p); output_data.id_gal.push_back(idx); output_data.ra.push_back(-1); output_data.dec.push_back(-1); output_data.redshift.push_back(-1); output_data.uniqueID.push_back(-1); insertion++; fprintf(fp, "%e %e %e\n", (p.xyz[0]), (p.xyz[1]), (p.xyz[2])); } } } } fclose(fp); // END PMS // PMS // TEST - insert mock galaxies along spheres of survey redshift boundaries fp = fopen("mock_sphere.txt", "w"); //Maubert - insert mock galaxies according to useComoving specification // Added & compute rmin & rmax out of loop double rmin ; double rmax ; if (useComoving) { gsl_integration_qng(&expanF, 0.0, args.zMin_arg, 1.e-6, 1.e-6, &result, &error, &nEval); rmin = result* LIGHT_SPEED; gsl_integration_qng(&expanF, 0.0, args.zMax_arg, 1.e-6, 1.e-6, &result, &error, &nEval); rmax = result* LIGHT_SPEED; } else { rmin = args.zMin_arg * LIGHT_SPEED; rmax = args.zMax_arg * LIGHT_SPEED; } //for (int q = 0; q < 0; q++) { for (int q = 0; q < full_mask_list.size(); q++) { vec3 v = mask.pix2vec(full_mask_list[q]); Position p; if (rmin > 0.) { p.xyz[0] = v.x * rmin; p.xyz[1] = v.y * rmin; p.xyz[2] = v.z * rmin; output_data.pos.push_back(p); output_data.id_gal.push_back(idx); output_data.ra.push_back(-1); output_data.dec.push_back(-1); output_data.redshift.push_back(-1); output_data.uniqueID.push_back(-1); insertion++; fprintf(fp, "%e %e %e\n", (p.xyz[0]), (p.xyz[1]), (p.xyz[2])); } p.xyz[0] = v.x * rmax; p.xyz[1] = v.y * rmax; p.xyz[2] = v.z * rmax; output_data.pos.push_back(p); output_data.id_gal.push_back(idx); output_data.ra.push_back(-1); output_data.dec.push_back(-1); output_data.redshift.push_back(-1); output_data.uniqueID.push_back(-1); insertion++; fprintf(fp, "%e %e %e\n", (p.xyz[0]), (p.xyz[1]), (p.xyz[2])); } fclose(fp); // END PMS cout << format("Done. Inserted %d particles.") % insertion << endl; } void saveData(ParticleData& pdata) { NcFile f("particles.nc", NcFile::Replace); assert(f.is_valid()); NcDim *d = f.add_dim("space", 3); NcDim *p = f.add_dim("Np", pdata.pos.size()); NcVar *v = f.add_var("particles", ncDouble, d, p); double *x = new double[pdata.pos.size()]; for (int j = 0; j < 3; j++) { for (int i = 0; i < pdata.pos.size(); i++) x[i] = pdata.pos[i].xyz[j]; v->put_rec(d, x, j); } v = f.add_var("id_gal", ncInt, p); v->put(&pdata.id_gal[0], pdata.id_gal.size()); delete[] x; } void saveForZobov(ParticleData& pdata, const string& fname, const string& paramname) { UnformattedWrite f(fname); static const char axis[] = { 'X', 'Y', 'Z' }; double Lmax = pdata.Lmax; double r2d = 180./M_PI; f.beginCheckpoint(); f.writeInt32(pdata.pos.size()); f.endCheckpoint(); for (int j = 0; j < 3; j++) { cout << format("Writing %c components...") % axis[j] << endl; f.beginCheckpoint(); for (uint32_t i = 0; i < pdata.pos.size(); i++) { f.writeReal32((pdata.pos[i].xyz[j]+Lmax)/(2*Lmax)); } f.endCheckpoint(); } cout << format("Writing RA...") << endl; f.beginCheckpoint(); for (uint32_t i = 0; i < pdata.pos.size(); i++) { f.writeReal32(pdata.ra[i]*r2d); } f.endCheckpoint(); cout << format("Writing Dec...") << endl; f.beginCheckpoint(); for (uint32_t i = 0; i < pdata.pos.size(); i++) { f.writeReal32(pdata.dec[i]*r2d); } f.endCheckpoint(); cout << format("Writing Redshift...") << endl; f.beginCheckpoint(); for (uint32_t i = 0; i < pdata.pos.size(); i++) { f.writeReal32(pdata.redshift[i]); } f.endCheckpoint(); cout << format("Writing Unique ID...") << endl; f.beginCheckpoint(); for (uint32_t i = 0; i < pdata.pos.size(); i++) { f.writeInt64(pdata.uniqueID[i]); } f.endCheckpoint(); NcFile fp(paramname.c_str(), NcFile::Replace); fp.add_att("range_x_min", -Lmax/100.); fp.add_att("range_x_max", Lmax/100.); fp.add_att("range_y_min", -Lmax/100.); fp.add_att("range_y_max", Lmax/100.); fp.add_att("range_z_min", -Lmax/100.); fp.add_att("range_z_max", Lmax/100.); fp.add_att("mask_index", pdata.mask_index); // PMS fp.add_att("is_observation", 1); // PMS int nOutputPart = pdata.mask_index; //int nOutputPart = pdata.pos.size(); NcDim *NumPart_dim = fp.add_dim("numpart_dim", nOutputPart); NcVar *v = fp.add_var("particle_ids", ncInt, NumPart_dim); //NcVar *v2 = fp.add_var("expansion", ncDouble, NumPart_dim); //double *expansion_fac = new double[pdata.pos.size()]; //for (int i = 0; i < pdata.pos.size(); i++) // expansion_fac[i] = 1.0; v->put(&pdata.id_gal[0], nOutputPart); //v2->put(expansion_fac, pdata.pos.size()); //delete[] expansion_fac; /* FILE *infoFile = fopen("sample_info.txt", "w"); fprintf(infoFile, "x_min = %f\n", -Lmax/100.); fprintf(infoFile, "x_max = %f\n", Lmax/100.); fprintf(infoFile, "y_min = %f\n", -Lmax/100.); fprintf(infoFile, "y_max = %f\n", Lmax/100.); fprintf(infoFile, "z_min = %f\n", -Lmax/100.); fprintf(infoFile, "z_max = %f\n", Lmax/100.); fprintf(infoFile, "mask_index = %d\n", pdata.mask_index); fprintf(infoFile, "total_particles = %d\n", pdata.pos.size()); fclose(infoFile); */ } int main(int argc, char **argv) { generateFromCatalog_info args_info; generateFromCatalog_conf_params args_params; generateFromCatalog_conf_init(&args_info); generateFromCatalog_conf_params_init(&args_params); args_params.check_required = 0; if (generateFromCatalog_conf_ext (argc, argv, &args_info, &args_params)) return 1; if (!args_info.configFile_given) { if (generateFromCatalog_conf_required (&args_info, GENERATEFROMCATALOG_CONF_PACKAGE)) return 1; } else { args_params.check_required = 1; args_params.initialize = 0; if (generateFromCatalog_conf_config_file (args_info.configFile_arg, &args_info, &args_params)) return 1; } generateFromCatalog_conf_print_version(); cout << "Loading data " << args_info.catalog_arg << "..." << endl; vector data; Healpix_Map o_mask; vector pixel_list; vector full_mask_list; ParticleData output_data; loadData(args_info.catalog_arg, data); cout << "Loading mask..." << endl; read_Healpix_map_from_fits(args_info.mask_arg, o_mask); Healpix_Map mask; mask.SetNside(128, RING); mask.Import(o_mask); computeContourPixels(mask,pixel_list); computeMaskPixels(mask,full_mask_list); // We compute a cube holding all the galaxies + the survey surface mask cout << "Placing galaxies..." << endl; generateGalaxiesInCube(data, output_data, args_info.useComoving_flag, args_info.omegaM_arg); generateSurfaceMask(args_info, mask, pixel_list, full_mask_list, data, output_data,args_info.useComoving_flag, args_info.omegaM_arg); saveForZobov(output_data, args_info.output_arg, args_info.params_arg); // saveData(output_data); // PMS FILE *fp = fopen("mask_index.txt", "w"); fprintf(fp, "%d", output_data.mask_index); fclose(fp); fp = fopen("total_particles.txt", "w"); fprintf(fp, "%d", output_data.pos.size()); fclose(fp); printf("Done!\n"); // END PMS return 0; }