/* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ < BioEM software for Bayesian inference of Electron Microscopy images> Copyright (C) 2014 Pilar Cossio, David Rohr and Gerhard Hummer. Max Planck Institute of Biophysics, Frankfurt, Germany. See license statement for terms of distribution. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ #include #define MPI_CHK(expr) \ if (expr != MPI_SUCCESS) \ { \ fprintf(stderr, "Error in MPI function %s: %d\n", __FILE__, __LINE__); \ } #include #include #include #include #include #include #include #include #include #ifdef WITH_OPENMP #include #endif #include #include #include "cmodules/timer.h" #include "param.h" #include "bioem.h" #include "model.h" #include "map.h" #ifdef BIOEM_USE_NVTX #include "nvToolsExt.h" const uint32_t colors[] = { 0x0000ff00, 0x000000ff, 0x00ffff00, 0x00ff00ff, 0x0000ffff, 0x00ff0000, 0x00ffffff }; const int num_colors = sizeof(colors)/sizeof(colors[0]); #define cuda_custom_timeslot(name,cid) { \ int color_id = cid; \ color_id = color_id%num_colors;\ nvtxEventAttributes_t eventAttrib = {0}; \ eventAttrib.version = NVTX_VERSION; \ eventAttrib.size = NVTX_EVENT_ATTRIB_STRUCT_SIZE; \ eventAttrib.colorType = NVTX_COLOR_ARGB; \ eventAttrib.color = colors[color_id]; \ eventAttrib.messageType = NVTX_MESSAGE_TYPE_ASCII; \ eventAttrib.message.ascii = name; \ nvtxRangePushEx(&eventAttrib); \ } #define cuda_custom_timeslot_end nvtxRangePop(); #else #define cuda_custom_timeslot(name,cid) #define cuda_custom_timeslot_end #endif #include "bioem_algorithm.h" using namespace boost; namespace po = boost::program_options; using namespace std; // A helper function of Boost template ostream& operator<<(ostream& os, const vector& v) { copy(v.begin(), v.end(), ostream_iterator(os, " ")); return os; } bioem::bioem() { FFTAlgo = getenv("FFTALGO") == NULL ? 1 : atoi(getenv("FFTALGO")); DebugOutput = getenv("BIOEM_DEBUG_OUTPUT") == NULL ? 2 : atoi(getenv("BIOEM_DEBUG_OUTPUT")); } bioem::~bioem() { } int bioem::configure(int ac, char* av[]) { // ************************************************************************************** // **** Configuration Routine using boost for extracting parameters, models and maps **** // ************************************************************************************** // ****** And Precalculating necessary grids, map crosscorrelations and kernels ******** // ************************************************************************************* HighResTimer timer; if (mpi_rank == 0) { // *** Inizialzing default variables *** std::string infile, modelfile, mapfile; Model.readPDB = false; param.param_device.writeAngles = false; param.dumpMap = false; param.loadMap = false; RefMap.readMRC = false; RefMap.readMultMRC = false; // ************************************************************************************* cout << " ++++++++++++ FROM COMMAND LINE +++++++++++\n\n"; // ************************************************************************************* // ********************* Command line reading input with BOOST ************************ try { po::options_description desc("Command line inputs"); desc.add_options() ("Inputfile", po::value(), "(Mandatory) Name of input parameter file") ("Modelfile", po::value< std::string>() , "(Mandatory) Name of model file") ("Particlesfile", po::value< std::string>(), "(Mandatory) Name of paricles file") ("ReadPDB", "(Optional) If reading model file in PDB format") ("ReadMRC", "(Optional) If reading particle file in MRC format") ("ReadMultipleMRC", "(Optional) If reading Multiple MRCs") ("DumpMaps", "(Optional) Dump maps after they were red from maps file") ("LoadMapDump", "(Optional) Read Maps from dump instead of maps file") ("help", "(Optional) Produce help message") ; po::positional_options_description p; p.add("Inputfile", -1); p.add("Modelfile", -1); p.add("Particlesfile", -1); p.add("ReadPDB", -1); p.add("ReadMRC", -1); p.add("ReadMultipleMRC", -1); p.add("DumpMaps", -1); p.add("LoadMapDump", -1); po::variables_map vm; po::store(po::command_line_parser(ac, av). options(desc).positional(p).run(), vm); po::notify(vm); if((ac < 6)) { std::cout << desc << std::endl; return 1; } if (vm.count("help")) { cout << "Usage: options_description [options]\n"; cout << desc; return 1; } if (vm.count("Inputfile")) { cout << "Input file is: "; cout << vm["Inputfile"].as< std::string >() << "\n"; infile = vm["Inputfile"].as< std::string >(); } if (vm.count("Modelfile")) { cout << "Model file is: " << vm["Modelfile"].as< std::string >() << "\n"; modelfile = vm["Modelfile"].as< std::string >(); } if (vm.count("ReadPDB")) { cout << "Reading model file in PDB format.\n"; Model.readPDB = true; } if (vm.count("ReadMRC")) { cout << "Reading particle file in MRC format.\n"; RefMap.readMRC=true; } if (vm.count("ReadMultipleMRC")) { cout << "Reading Multiple MRCs.\n"; RefMap.readMultMRC=true; } if (vm.count("DumpMaps")) { cout << "Dumping Maps after reading from file.\n"; param.dumpMap = true; } if (vm.count("LoadMapDump")) { cout << "Loading Map dump.\n"; param.loadMap = true; } if (vm.count("Particlesfile")) { cout << "Paricle file is: " << vm["Particlesfile"].as< std::string >() << "\n"; mapfile = vm["Particlesfile"].as< std::string >(); } } catch(std::exception& e) { cout << e.what() << "\n"; return 1; } //check for consitency in multiple MRCs if(RefMap.readMultMRC && not(RefMap.readMRC)) { cout << "For Multiple MRCs command --ReadMRC is necesary too"; exit(1); } if (DebugOutput >= 2 && mpi_rank == 0) timer.ResetStart(); // ********************* Reading Parameter Input *************************** param.readParameters(infile.c_str()); // ********************* Reading Model Input ****************************** Model.readModel(modelfile.c_str()); // ********************* Reading Particle Maps Input ********************** RefMap.readRefMaps(param, mapfile.c_str()); if (DebugOutput >= 2 && mpi_rank == 0) printf("Reading Input Data %f\n", timer.GetCurrentElapsedTime()); } #ifdef WITH_MPI if (mpi_size > 1) { if (DebugOutput >= 2 && mpi_rank == 0) timer.ResetStart(); MPI_Bcast(¶m, sizeof(param), MPI_BYTE, 0, MPI_COMM_WORLD); //refCtf, CtfParam, angles automatically filled by precalculare function below MPI_Bcast(&Model, sizeof(Model), MPI_BYTE, 0, MPI_COMM_WORLD); if (mpi_rank != 0) Model.points = (bioem_model::bioem_model_point*) mallocchk(sizeof(bioem_model::bioem_model_point) * Model.nPointsModel); MPI_Bcast(Model.points, sizeof(bioem_model::bioem_model_point) * Model.nPointsModel, MPI_BYTE, 0, MPI_COMM_WORLD); MPI_Bcast(&RefMap, sizeof(RefMap), MPI_BYTE, 0, MPI_COMM_WORLD); if (mpi_rank != 0) RefMap.maps = (myfloat_t*) mallocchk(RefMap.refMapSize * sizeof(myfloat_t) * RefMap.ntotRefMap); MPI_Bcast(RefMap.maps, RefMap.refMapSize * sizeof(myfloat_t) * RefMap.ntotRefMap, MPI_BYTE, 0, MPI_COMM_WORLD); if (DebugOutput >= 2 && mpi_rank == 0) printf("MPI Broadcast of Input Data %f\n", timer.GetCurrentElapsedTime()); } #endif // ****************** Precalculating Necessary Stuff ********************* if (DebugOutput >= 2 && mpi_rank == 0) timer.ResetStart(); param.PrepareFFTs(); if (DebugOutput >= 2 && mpi_rank == 0) { printf("Time Prepare FFTs %f\n", timer.GetCurrentElapsedTime()); timer.ResetStart(); } precalculate(); if (getenv("BIOEM_DEBUG_BREAK")) { const int cut = atoi(getenv("BIOEM_DEBUG_BREAK")); if (param.nTotGridAngles > cut) param.nTotGridAngles = cut; if (param.nTotCTFs > cut) param.nTotCTFs = cut; } if (DebugOutput >= 2 && mpi_rank == 0) { printf("Time Precalculate %f\n", timer.GetCurrentElapsedTime()); timer.ResetStart(); } pProb.init(RefMap.ntotRefMap, param.nTotGridAngles, param.nTotCC, *this); if (DebugOutput >= 2 && mpi_rank == 0) { printf("Time Init Probabilities %f\n", timer.GetCurrentElapsedTime()); timer.ResetStart(); } deviceInit(); if (DebugOutput >= 2 && mpi_rank == 0) printf("Time Device Init %f\n", timer.GetCurrentElapsedTime()); return(0); } void bioem::cleanup() { //Deleting allocated pointers free_device_host(pProb.ptr); RefMap.freePointers(); } int bioem::precalculate() { // ************************************************************************************** // **Precalculating Routine of Orientation grids, Map crosscorrelations and CTF Kernels** // ************************************************************************************** HighResTimer timer; // Generating Grids of orientations if (DebugOutput >= 3) timer.ResetStart(); param.CalculateGridsParam(); if (DebugOutput >= 3) { printf("\tTime Precalculate Grids Param: %f\n", timer.GetCurrentElapsedTime()); timer.ResetStart(); } // Precalculating CTF Kernels stored in class Param param.CalculateRefCTF(); if (DebugOutput >= 3) { printf("\tTime Precalculate CTFs: %f\n", timer.GetCurrentElapsedTime()); timer.ResetStart(); } //Precalculate Maps RefMap.precalculate(param, *this); if (DebugOutput >= 3) printf("\tTime Precalculate Maps: %f\n", timer.GetCurrentElapsedTime()); return(0); } int bioem::run() { // ************************************************************************************** // **** Main BioEM routine, projects, convolutes and compares with Map using OpenMP **** // ************************************************************************************** if (param.printModel) { //.... return(0); } // **** If we want to control the number of threads -> omp_set_num_threads(XX); ****** // ****************** Declarying class of Probability Pointer ************************* if (mpi_rank == 0) printf("\tInitializing Probabilities\n"); // Inizialzing Probabilites to zero and constant to -Infinity for (int iRefMap = 0; iRefMap < RefMap.ntotRefMap; iRefMap ++) { bioem_Probability_map& pProbMap = pProb.getProbMap(iRefMap); pProbMap.Total = 0.0; pProbMap.Constoadd = -9999999; if (param.param_device.writeAngles) { for (int iOrient = 0; iOrient < param.nTotGridAngles; iOrient ++) { bioem_Probability_angle& pProbAngle = pProb.getProbAngle(iRefMap, iOrient); pProbAngle.forAngles = 0.0; pProbAngle.ConstAngle = -99999999; } } if (param.param_device.writeCC) { int cc=0; for (int cent_x = 0; cent_x < param.param_device.NumberPixels -param.param_device.CCdisplace ; cent_x = cent_x + param.param_device.CCdisplace) { for (int cent_y = 0; cent_y < param.param_device.NumberPixels - param.param_device.CCdisplace ; cent_y = cent_y + param.param_device.CCdisplace) { cout << cc << " " << cent_x << " " << cent_y <<"\n"; bioem_Probability_cc& pProbCC = pProb.getProbCC(iRefMap, cc); pProbCC.forCC = 0.0; cc++; } } } } // ************************************************************************************** deviceStartRun(); // ******************************** MAIN CYCLE ****************************************** mycomplex_t* proj_mapFFT; myfloat_t* conv_map = NULL; mycomplex_t* conv_mapFFT; myfloat_t sumCONV, sumsquareCONV; //allocating fftw_complex vector proj_mapFFT = (mycomplex_t *) myfftw_malloc(sizeof(mycomplex_t) * param.param_device.NumberPixels * param.param_device.NumberFFTPixels1D); conv_mapFFT = (mycomplex_t *) myfftw_malloc(sizeof(mycomplex_t) * param.param_device.NumberPixels * param.param_device.NumberFFTPixels1D); if (!FFTAlgo) conv_map = (myfloat_t*) myfftw_malloc(sizeof(myfloat_t) * param.param_device.NumberPixels * param.param_device.NumberPixels); HighResTimer timer, timer2; if (DebugOutput >= 1 && mpi_rank == 0) printf("\tMain Loop GridAngles %d, CTFs %d, RefMaps %d, Shifts (%d/%d)², Pixels %d², OMP Threads %d, MPI Ranks %d\n", param.nTotGridAngles, param.nTotCTFs, RefMap.ntotRefMap, 2 * param.param_device.maxDisplaceCenter + param.param_device.GridSpaceCenter, param.param_device.GridSpaceCenter, param.param_device.NumberPixels, omp_get_max_threads(), mpi_size); const int iOrientStart = (int) ((long long int) mpi_rank * param.nTotGridAngles / mpi_size); int iOrientEnd = (int) ((long long int) (mpi_rank + 1) * param.nTotGridAngles / mpi_size); if (iOrientEnd > param.nTotGridAngles) iOrientEnd = param.nTotGridAngles; for (int iOrient = iOrientStart; iOrient < iOrientEnd; iOrient++) { // *************************************************************************************** // ***** Creating Projection for given orientation and transforming to Fourier space ***** if (DebugOutput >= 1) timer2.ResetStart(); if (DebugOutput >= 2) timer.ResetStart(); createProjection(iOrient, proj_mapFFT); if (DebugOutput >= 2) printf("\tTime Projection %d: %f (rank %d)\n", iOrient, timer.GetCurrentElapsedTime(), mpi_rank); // *************************************************************************************** // ***** **** Internal Loop over convolutions **** ***** for (int iConv = 0; iConv < param.nTotCTFs; iConv++) { // *** Calculating convolutions of projection map and crosscorrelations *** if (DebugOutput >= 2) timer.ResetStart(); createConvolutedProjectionMap(iOrient, iConv, proj_mapFFT, conv_map, conv_mapFFT, sumCONV, sumsquareCONV); if (DebugOutput >= 2) printf("\t\tTime Convolution %d %d: %f (rank %d)\n", iOrient, iConv, timer.GetCurrentElapsedTime(), mpi_rank); // *************************************************************************************** // *** Comparing each calculated convoluted map with all experimental maps *** if (DebugOutput >= 2) timer.ResetStart(); compareRefMaps(iOrient, iConv, conv_map, conv_mapFFT, sumCONV, sumsquareCONV); if (DebugOutput >= 2) { const double compTime = timer.GetCurrentElapsedTime(); const int nShifts = 2 * param.param_device.maxDisplaceCenter / param.param_device.GridSpaceCenter + 1; const double nFlops = (double) RefMap.ntotRefMap * (double) nShifts * (double) nShifts * (((double) param.param_device.NumberPixels - (double) param.param_device.maxDisplaceCenter / 2.) * ((double) param.param_device.NumberPixels - (double) param.param_device.maxDisplaceCenter / 2.) * 5. + 25.) / compTime; const double nGBs = (double) RefMap.ntotRefMap * (double) nShifts * (double) nShifts * (((double) param.param_device.NumberPixels - (double) param.param_device.maxDisplaceCenter / 2.) * ((double) param.param_device.NumberPixels - (double) param.param_device.maxDisplaceCenter / 2.) * 2. + 8.) * (double) sizeof(myfloat_t) / compTime; const double nGBs2 = (double) RefMap.ntotRefMap * ((double) param.param_device.NumberPixels * (double) param.param_device.NumberPixels + 8.) * (double) sizeof(myfloat_t) / compTime; printf("\t\tTime Comparison %d %d: %f sec (%f GFlops, %f GB/s (cached), %f GB/s) (rank %d)\n", iOrient, iConv, compTime, nFlops / 1000000000., nGBs / 1000000000., nGBs2 / 1000000000., mpi_rank); } } if (DebugOutput >= 1) printf("\tTotal time for projection %d: %f (rank %d)\n", iOrient, timer2.GetCurrentElapsedTime(), mpi_rank); } //deallocating fftw_complex vector myfftw_free(proj_mapFFT); myfftw_free(conv_mapFFT); if (!FFTAlgo) myfftw_free(conv_map); deviceFinishRun(); // ************* Writing Out Probabilities *************** // *** Angular Probability *** #ifdef WITH_MPI if (mpi_size > 1) { if (DebugOutput >= 1 && mpi_rank == 0) timer.ResetStart(); //Reduce Constant and summarize probabilities { myfloat_t* tmp1 = new myfloat_t[RefMap.ntotRefMap]; myfloat_t* tmp2 = new myfloat_t[RefMap.ntotRefMap]; myfloat_t* tmp3 = new myfloat_t[RefMap.ntotRefMap]; for (int i = 0;i < RefMap.ntotRefMap;i++) { tmp1[i] = pProb.getProbMap(i).Constoadd; } MPI_Allreduce(tmp1, tmp2, RefMap.ntotRefMap, MY_MPI_FLOAT, MPI_MAX, MPI_COMM_WORLD); for (int i = 0;i < RefMap.ntotRefMap;i++) { bioem_Probability_map& pProbMap = pProb.getProbMap(i); tmp1[i] = pProbMap.Total * exp(pProbMap.Constoadd - tmp2[i]); } MPI_Reduce(tmp1, tmp3, RefMap.ntotRefMap, MY_MPI_FLOAT, MPI_SUM, 0, MPI_COMM_WORLD); //Find MaxProb MPI_Status mpistatus; { int* tmpi1 = new int[RefMap.ntotRefMap]; int* tmpi2 = new int[RefMap.ntotRefMap]; for (int i = 0;i < RefMap.ntotRefMap;i++) { bioem_Probability_map& pProbMap = pProb.getProbMap(i); tmpi1[i] = tmp2[i] <= pProbMap.Constoadd ? mpi_rank : -1; } MPI_Allreduce(tmpi1, tmpi2, RefMap.ntotRefMap, MPI_INT, MPI_MAX, MPI_COMM_WORLD); for (int i = 0;i < RefMap.ntotRefMap;i++) { if (tmpi2[i] == -1) { if (mpi_rank == 0) printf("Error: Could not find highest probability\n"); } else if (tmpi2[i] != 0) //Skip if rank 0 already has highest probability { if (mpi_rank == 0) { MPI_Recv(&pProb.getProbMap(i).max, sizeof(pProb.getProbMap(i).max), MPI_BYTE, tmpi2[i], i, MPI_COMM_WORLD, &mpistatus); } else if (mpi_rank == tmpi2[i]) { MPI_Send(&pProb.getProbMap(i).max, sizeof(pProb.getProbMap(i).max), MPI_BYTE, 0, i, MPI_COMM_WORLD); } } } delete[] tmpi1; delete[] tmpi2; } if (mpi_rank == 0) { for (int i = 0;i < RefMap.ntotRefMap;i++) { bioem_Probability_map& pProbMap = pProb.getProbMap(i); pProbMap.Total = tmp3[i]; pProbMap.Constoadd = tmp2[i]; } } delete[] tmp1; delete[] tmp2; delete[] tmp3; if (DebugOutput >= 1 && mpi_rank == 0 && mpi_size > 1) printf("Time MPI Reduction: %f\n", timer.GetCurrentElapsedTime()); } //Angle Reduction and Probability summation for individual angles if (param.param_device.writeAngles) { const int count = RefMap.ntotRefMap * param.nTotGridAngles; myfloat_t* tmp1 = new myfloat_t[count]; myfloat_t* tmp2 = new myfloat_t[count]; myfloat_t* tmp3 = new myfloat_t[count]; for (int i = 0;i < RefMap.ntotRefMap;i++) { tmp1[i] = pProb.getProbMap(i).Constoadd; } MPI_Allreduce(tmp1, tmp2, count, MY_MPI_FLOAT, MPI_MAX, MPI_COMM_WORLD); for (int i = 0;i < RefMap.ntotRefMap;i++) { for (int j = 0;j < param.nTotGridAngles;j++) { bioem_Probability_angle& pProbAngle = pProb.getProbAngle(i, j); tmp1[i * param.nTotGridAngles + j] = pProbAngle.forAngles * exp(pProbAngle.ConstAngle - tmp2[i * param.nTotGridAngles + j]); } } MPI_Reduce(tmp1, tmp3, count, MY_MPI_FLOAT, MPI_SUM, 0, MPI_COMM_WORLD); if (mpi_rank == 0) { for (int i = 0;i < RefMap.ntotRefMap;i++) { for (int j = 0;j < param.nTotGridAngles;j++) { bioem_Probability_angle& pProbAngle = pProb.getProbAngle(i, j); pProbAngle.forAngles = tmp3[i * param.nTotGridAngles + j]; pProbAngle.ConstAngle = tmp2[i * param.nTotGridAngles + j]; } } } delete[] tmp1; delete[] tmp2; delete[] tmp3; } } #endif if (mpi_rank == 0) { ofstream angProbfile; if(param.param_device.writeAngles) { angProbfile.open ("ANG_PROB"); } ofstream ccProbfile; if(param.param_device.writeCC) { ccProbfile.open ("CROSS_CORRELATION"); } ofstream outputProbFile; outputProbFile.open ("Output_Probabilities"); for (int iRefMap = 0; iRefMap < RefMap.ntotRefMap; iRefMap ++) { // **** Total Probability *** bioem_Probability_map& pProbMap = pProb.getProbMap(iRefMap); outputProbFile << "RefMap " << iRefMap << " Probability " << log(pProbMap.Total) + pProbMap.Constoadd + 0.5 * log(M_PI) + (1 - param.param_device.Ntotpi * 0.5)*(log(2 * M_PI) + 1) + log(param.param_device.volu) << " Constant " << pProbMap.Constoadd << "\n"; outputProbFile << "RefMap " << iRefMap << " Maximizing Param: "; // *** Param that maximize probability**** outputProbFile << (pProbMap.Constoadd + 0.5 * log(M_PI) + (1 - param.param_device.Ntotpi * 0.5) * (log(2 * M_PI) + 1) + log(param.param_device.volu)) << " "; outputProbFile << param.angles[pProbMap.max.max_prob_orient].pos[0] << " "; outputProbFile << param.angles[pProbMap.max.max_prob_orient].pos[1] << " "; outputProbFile << param.angles[pProbMap.max.max_prob_orient].pos[2] << " "; outputProbFile << param.CtfParam[pProbMap.max.max_prob_conv].pos[0] << " "; outputProbFile << param.CtfParam[pProbMap.max.max_prob_conv].pos[1] << " "; outputProbFile << param.CtfParam[pProbMap.max.max_prob_conv].pos[2] << " "; outputProbFile << pProbMap.max.max_prob_cent_x << " "; outputProbFile << pProbMap.max.max_prob_cent_y << " " ; outputProbFile << pProbMap.max.max_prob_norm << " " ; outputProbFile << pProbMap.max.max_prob_mu ; outputProbFile << "\n"; // *** For individual files*** //angProbfile.open ("ANG_PROB_"iRefMap); if(param.param_device.writeAngles) { for (int iOrient = 0; iOrient < param.nTotGridAngles; iOrient++) { bioem_Probability_angle& pProbAngle = pProb.getProbAngle(iRefMap, iOrient); angProbfile << " " << iRefMap << " " << param.angles[iOrient].pos[0] << " " << param.angles[iOrient].pos[1] << " " << param.angles[iOrient].pos[2] << " " << log(pProbAngle.forAngles) + pProbAngle.ConstAngle + 0.5 * log(M_PI) + (1 - param.param_device.Ntotpi * 0.5)*(log(2 * M_PI) + 1) + log(param.param_device.volu) << " " << log(param.param_device.volu) << "\n"; } } if(param.param_device.writeCC) { int cc=0; for (int cent_x = 0; cent_x < param.param_device.NumberPixels -param.param_device.CCdisplace ; cent_x = cent_x + param.param_device.CCdisplace) { for (int cent_y = 0; cent_y < param.param_device.NumberPixels - param.param_device.CCdisplace ; cent_y = cent_y + param.param_device.CCdisplace) { bioem_Probability_cc& pProbCC = pProb.getProbCC(iRefMap, cc); ccProbfile << " " << iRefMap << " " << cent_x << " " << cent_y << " " << pProbCC.forCC <<"\n"; } } } } if(param.param_device.writeAngles) { angProbfile.close(); } if(param.param_device.writeCC) { ccProbfile.close(); } outputProbFile.close(); } return(0); } int bioem::compareRefMaps(int iOrient, int iConv, const myfloat_t* conv_map, mycomplex_t* localmultFFT, myfloat_t sumC, myfloat_t sumsquareC, const int startMap) { //*************************************************************************************** //***** BioEM routine for comparing reference maps to convoluted maps ***** if (FFTAlgo) { //With FFT Algorithm #pragma omp parallel for for (int iRefMap = startMap; iRefMap < RefMap.ntotRefMap; iRefMap ++) { const int num = omp_get_thread_num(); calculateCCFFT(iRefMap, iOrient, iConv, sumC, sumsquareC, localmultFFT, param.fft_scratch_complex[num], param.fft_scratch_real[num]); } } else { //Without FFT Algorithm #pragma omp parallel for for (int iRefMap = startMap; iRefMap < RefMap.ntotRefMap; iRefMap ++) { compareRefMapShifted < -1 > (iRefMap, iOrient, iConv, conv_map, pProb, param.param_device, RefMap); } } return(0); } inline void bioem::calculateCCFFT(int iRefMap, int iOrient, int iConv, myfloat_t sumC, myfloat_t sumsquareC, mycomplex_t* localConvFFT, mycomplex_t* localCCT, myfloat_t* lCC) { //*************************************************************************************** //***** Calculating cross correlation in FFTALGOrithm ***** const mycomplex_t* RefMapFFT = &RefMap.RefMapsFFT[iRefMap * param.FFTMapSize]; for(int i = 0; i < param.param_device.NumberPixels * param.param_device.NumberFFTPixels1D; i++) { localCCT[i][0] = localConvFFT[i][0] * RefMapFFT[i][0] + localConvFFT[i][1] * RefMapFFT[i][1]; localCCT[i][1] = localConvFFT[i][1] * RefMapFFT[i][0] - localConvFFT[i][0] * RefMapFFT[i][1]; } myfftw_execute_dft_c2r(param.fft_plan_c2r_backward, localCCT, lCC); doRefMapFFT(iRefMap, iOrient, iConv, lCC, sumC, sumsquareC, pProb, param.param_device, RefMap); } int bioem::createProjection(int iMap, mycomplex_t* mapFFT) { // ************************************************************************************** // **** BioEM Create Projection routine in Euler angle predefined grid****************** // ********************* and turns projection into Fourier space ************************ // ************************************************************************************** cuda_custom_timeslot("Projection", 0); myfloat3_t RotatedPointsModel[Model.nPointsModel]; myfloat_t rotmat[3][3]; myfloat_t alpha, gam, beta; myfloat_t* localproj; localproj = param.fft_scratch_real[omp_get_thread_num()]; memset(localproj, 0, param.param_device.NumberPixels * param.param_device.NumberPixels * sizeof(*localproj)); alpha = param.angles[iMap].pos[0]; beta = param.angles[iMap].pos[1]; gam = param.angles[iMap].pos[2]; // **** To see how things are going: cout << "Id " << omp_get_thread_num() << " Angs: " << alpha << " " << beta << " " << gam << "\n"; *** // ********** Creat Rotation with pre-defiend grid of orientations********** rotmat[0][0] = cos(gam) * cos(alpha) - cos(beta) * sin(alpha) * sin(gam); rotmat[0][1] = cos(gam) * sin(alpha) + cos(beta) * cos(alpha) * sin(gam); rotmat[0][2] = sin(gam) * sin(beta); rotmat[1][0] = -sin(gam) * cos(alpha) - cos(beta) * sin(alpha) * cos(gam); rotmat[1][1] = -sin(gam) * sin(alpha) + cos(beta) * cos(alpha) * cos(gam); rotmat[1][2] = cos(gam) * sin(beta); rotmat[2][0] = sin(beta) * sin(alpha); rotmat[2][1] = -sin(beta) * cos(alpha); rotmat[2][2] = cos(beta); for(int n = 0; n < Model.nPointsModel; n++) { RotatedPointsModel[n].pos[0] = 0.0; RotatedPointsModel[n].pos[1] = 0.0; RotatedPointsModel[n].pos[2] = 0.0; } for(int n = 0; n < Model.nPointsModel; n++) { for(int k = 0; k < 3; k++) { for(int j = 0; j < 3; j++) { RotatedPointsModel[n].pos[k] += rotmat[k][j] * Model.points[n].point.pos[j]; } } } int i, j; //********** Projection with radius *************** if(param.doaaradius){ int irad; myfloat_t dist, rad2; for(int n = 0; n < Model.nPointsModel; n++) { //Getting Centers of Sphere i = floor(RotatedPointsModel[n].pos[0] / param.pixelSize + (myfloat_t) param.param_device.NumberPixels / 2.0f + 0.5f); j = floor(RotatedPointsModel[n].pos[1] / param.pixelSize + (myfloat_t) param.param_device.NumberPixels / 2.0f + 0.5f); //Getting the radius irad=int( Model.points[n].radius / param.pixelSize ); rad2= Model.points[n].radius * Model.points[n].radius; //Projecting over the radius for(int ii= i - irad; ii < i + irad; ii++) { for(int jj = j - irad; jj < j + irad; jj++) { dist= ( (myfloat_t) (ii-i)*(ii-i)+(jj-j)*(jj-j) ) * param.pixelSize ; if( dist < rad2 ) { localproj[ii * param.param_device.NumberPixels + jj] += param.pixelSize * 2 * sqrt( rad2 - dist ) * Model.points[n].density / Model.NormDen * 3 / (4 * M_PI * rad2 * Model.points[n].radius); } } } } } else { // ************ Simple Projection over the Z axis******************** for(int n = 0; n < Model.nPointsModel; n++) { //Getting pixel that represents coordinates & shifting the start at to Numpix/2,Numpix/2 ) i = floor(RotatedPointsModel[n].pos[0] / param.pixelSize + (myfloat_t) param.param_device.NumberPixels / 2.0f + 0.5f); j = floor(RotatedPointsModel[n].pos[1] / param.pixelSize + (myfloat_t) param.param_device.NumberPixels / 2.0f + 0.5f); if (i < 0 || j < 0 || i >= param.param_device.NumberPixels || j >= param.param_device.NumberPixels) { if (DebugOutput >= 3) cout << "Model Point out of map: " << i << ", " << j << "\n"; continue; } localproj[i * param.param_device.NumberPixels + j] += Model.points[n].density / Model.NormDen; } } // **** Output Just to check**** #ifdef PILAR_DEBUG if(iMap == 10) { ofstream myexamplemap; ofstream myexampleRot; myexamplemap.open ("MAP_i10"); myexampleRot.open ("Rot_i10"); myexamplemap << "ANGLES " << alpha << " " << beta << " " << gam << "\n"; for(int k = 0; k < param.param_device.NumberPixels; k++) { for(int j = 0; j < param.param_device.NumberPixels; j++) myexamplemap << "\nMAP " << k << " " << j << " " << localproj[k * param.param_device.NumberPixels + j]; } myexamplemap << " \n"; for(int n = 0; n < Model.nPointsModel; n++)myexampleRot << "\nCOOR " << RotatedPointsModel[n].pos[0] << " " << RotatedPointsModel[n].pos[1] << " " << RotatedPointsModel[n].pos[2]; myexamplemap.close(); myexampleRot.close(); } #endif // ***** Converting projection to Fourier Space for Convolution later with kernel**** // ********** Omp Critical is necessary with FFTW******* myfftw_execute_dft_r2c(param.fft_plan_r2c_forward, localproj, mapFFT); cuda_custom_timeslot_end; return(0); } int bioem::createConvolutedProjectionMap(int iMap, int iConv, mycomplex_t* lproj, myfloat_t* Mapconv, mycomplex_t* localmultFFT, myfloat_t& sumC, myfloat_t& sumsquareC) { // ************************************************************************************** // **** BioEM Create Convoluted Projection Map routine, multiplies in Fourier ********** // **************** calculated Projection with convoluted precalculated Kernel*********** // *************** and Backtransforming it to real Space ******************************** // ************************************************************************************** cuda_custom_timeslot("Convolution", 1); mycomplex_t* tmp = param.fft_scratch_complex[omp_get_thread_num()]; // **** Multiplying FFTmap with corresponding kernel **** const mycomplex_t* refCTF = ¶m.refCTF[iConv * param.FFTMapSize]; for(int i = 0; i < param.param_device.NumberPixels * param.param_device.NumberFFTPixels1D; i++) { localmultFFT[i][0] = lproj[i][0] * refCTF[i][0] + lproj[i][1] * refCTF[i][1]; localmultFFT[i][1] = lproj[i][1] * refCTF[i][0] - lproj[i][0] * refCTF[i][1]; // cout << "GG " << i << " " << j << " " << refCTF[i][0] << " " << refCTF[i][1] <<" " <