/* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ < BioEM software for Bayesian inference of Electron Microscopy images> Copyright (C) 2016 Pilar Cossio, David Rohr, Fabio Baruffa, Markus Rampp, Volker Lindenstruth and Gerhard Hummer. Max Planck Institute of Biophysics, Frankfurt, Germany. Frankfurt Institute for Advanced Studies, Goethe University Frankfurt, Germany. Max Planck Computing and Data Facility, Garching, Germany. Released under the GNU Public License, v3. See license statement for terms of distribution. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/ #ifdef WITH_MPI #include #define MPI_CHK(expr) \ if (expr != MPI_SUCCESS) \ { \ fprintf(stderr, "Error in MPI function %s: %d\n", __FILE__, __LINE__); \ } #endif #include #include #include #include #include #include #include #include #include #include #include #include #ifdef WITH_OPENMP #include #endif #include #include #include "timer.h" #include "autotuner.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]); enum myColor { COLOR_PROJECTION, COLOR_CONVOLUTION, COLOR_COMPARISON, COLOR_WORKLOAD }; // Projection number is stored in category attribute // Convolution number is stored in payload attribute #define cuda_custom_timeslot(name,iMap,iConv,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.category = iMap; \ eventAttrib.payloadType = NVTX_PAYLOAD_TYPE_UNSIGNED_INT64; \ eventAttrib.payload.llValue = iConv; \ eventAttrib.messageType = NVTX_MESSAGE_TYPE_ASCII; \ eventAttrib.message.ascii = name; \ nvtxRangePushEx(&eventAttrib); \ } #define cuda_custom_timeslot_end nvtxRangePop(); #else #define cuda_custom_timeslot(name,iMap,iConv,cid) #define cuda_custom_timeslot_end #endif #include "bioem_algorithm.h" using namespace boost; namespace po = boost::program_options; namespace bran= boost::random; using namespace std; /* For dvl nodes in hydra with problem in boost namespace std { typedef decltype(nullptr) nullptr_t; }*/ // 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")); nProjectionsAtOnce = getenv("BIOEM_PROJECTIONS_AT_ONCE") == NULL ? 1 : atoi(getenv("BIOEM_PROJECTIONS_AT_ONCE")); Autotuning = false; } 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; std::string infile, modelfile, mapfile,Inputanglefile,Inputbestmap; if (mpi_rank == 0) { // *** Inizialzing default variables *** std::string infile, modelfile, mapfile,Inputanglefile,Inputbestmap; Model.readPDB = false; param.param_device.writeAngles = false; param.dumpMap = false; param.loadMap = false; RefMap.readMRC = false; RefMap.readMultMRC = false; param.notuniformangles=false; yesoutfilename=false; // ************************************************************************************* cout << " ++++++++++++ FROM COMMAND LINE +++++++++++\n\n"; // ************************************************************************************* // ********************* Command line reading input with BOOST ************************ try { po::options_description desc("Command line inputs"); desc.add_options() ("Modelfile", po::value< std::string>() , "(Mandatory) Name of model file") ("Particlesfile", po::value< std::string>(), "if BioEM (Mandatory) Name of particle-image file") ("Inputfile", po::value(), "if BioEM (Mandatory) Name of input parameter file") ("PrintBestCalMap", po::value< std::string>(), "(Optional) Only print best calculated map. NO BioEM (!)") ("ReadOrientation", po::value< std::string>(), "(Optional) Read file name containing orientations") ("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 read from particle-image file") ("LoadMapDump", "(Optional) Read Maps from dump option") ("OutputFile", po::value< std::string>(), "(Optional) For changing the outputfile name") ("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("ReadOrientation",-1); p.add("PrintBestCalMap",-1); p.add("DumpMaps", -1); p.add("LoadMapDump", -1); p.add("OutputFile",-1); po::variables_map vm; po::store(po::command_line_parser(ac, av). options(desc).positional(p).run(), vm); po::notify(vm); if((ac < 4)) { 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("ReadOrientation")) { cout << "Reading Orientation from file: " << vm["ReadOrientation"].as< std::string >() << "\n"; cout << "Important! if using Quaternions, include \n"; cout << "QUATERNIONS keyword in INPUT PARAMETER FILE\n"; cout << "First row in file should be the total number of orientations (int)\n"; cout << "Euler angle format should be alpha (12.6f) beta (12.6f) gamma (12.6f)\n"; cout << "Quaternion format q1 (12.6f) q2 (12.6f) q3 (12.6f) q4 (12.6f)\n"; Inputanglefile = vm["ReadOrientation"].as< std::string >(); param.notuniformangles=true; } if (vm.count("OutputFile")) { OutfileName = vm["OutputFile"].as< std::string >(); cout << "Writing OUTPUT to: " << vm["OutputFile"].as< std::string >() << "\n"; yesoutfilename=true; } if (vm.count("PrintBestCalMap")) { cout << "Reading Euler Angles from file: " << vm["PrintBestCalMap"].as< std::string >() << "\n"; Inputbestmap = vm["PrintBestCalMap"].as< std::string >(); param.printModel=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(!Model.readPDB){ cout << "Note: Reading model in simple text format (not PDB)\n"; cout << "---- x y z radius density ------- \n"; } if (DebugOutput >= 2 && mpi_rank == 0) timer.ResetStart(); // ********************* Reading Parameter Input *************************** if(!param.printModel){ // Standard definition for BioEM param.readParameters(infile.c_str()); // ********************* Reading Particle Maps Input ********************** RefMap.readRefMaps(param, mapfile.c_str()); } else{ // Reading parameters for only writting down Best projection param.forprintBest(Inputbestmap.c_str()); } // ********************* Reading Model Input ****************************** Model.readModel(param, modelfile.c_str()); cout << "**NOTE:: look at file COORDREAD to confirm that the Model coordinates are correct\n"; if (DebugOutput >= 2 && mpi_rank == 0) printf("Reading Input Data Time: %f\n", timer.GetCurrentElapsedTime()); if(param.param_device.writeCC && mpi_size>1){ cout << "Exiting::: WRITE CROSS-CORRELATION ONLY VAILD FOR 1 MPI PROCESS\n"; exit(1); } // Generating Grids of orientations if(!param.printModel)param.CalculateGridsParam(Inputanglefile.c_str()); } #ifdef WITH_MPI // ********************* MPI inizialization/ Transfer of parameters****************** if (mpi_size > 1) { if (DebugOutput >= 2 && mpi_rank == 0) timer.ResetStart(); MPI_Bcast(¶m, sizeof(param), MPI_BYTE, 0, MPI_COMM_WORLD); //We have to reinitialize all pointers !!!!!!!!!!!! if (mpi_rank != 0) param.angprior = NULL; if (mpi_rank != 0)param.angles = (myfloat3_t*) mallocchk(param.nTotGridAngles * sizeof (myfloat3_t)); MPI_Bcast(param.angles, param.nTotGridAngles * sizeof (myfloat3_t),MPI_BYTE, 0, MPI_COMM_WORLD); #ifdef DEBUG for(int n=0;n= 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(); // ****************** For debugging ********************* 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(); } // ****************** For autotuning ********************** if ((getenv("GPU") && atoi(getenv("GPU"))) && ((!getenv("GPUWORKLOAD") || (atoi(getenv("GPUWORKLOAD")) == -1))) && (!getenv("BIOEM_DEBUG_BREAK") || (atoi(getenv("BIOEM_DEBUG_BREAK")) > FIRST_STABLE))) { Autotuning = true; if (mpi_rank == 0) printf("Autotuning of GPUWorkload enabled:\n\tAlgorithm %d\n\tRecalibration at every %d projections\n\tComparisons are considered stable after first %d comparisons\n", AUTOTUNING_ALGORITHM, RECALIB_FACTOR, FIRST_STABLE); } else { Autotuning = false; if (mpi_rank == 0) printf("Autotuning of GPUWorkload disabled\n"); } // ****************** Initializing pointers ********************* deviceInit(); if (DebugOutput >= 2 && mpi_rank == 0) { printf("Time Device Init %f\n", timer.GetCurrentElapsedTime()); timer.ResetStart(); } if(!param.printModel)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(); } 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; 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 if(!param.printModel) RefMap.precalculate(param, *this); if (DebugOutput >= 3) printf("\tTime Precalculate Maps: %f\n", timer.GetCurrentElapsedTime()); return(0); } int bioem::run() { // ************************************************************************************** // ********** Secondary routine for printing out the only best projection *************** // ************************************************************************************** if(mpi_rank == 0 && param.printModel){ //Only works for 1 MPI process (not parallelized) cout << "\nAnalysis for printing best projection::: \n \n" ; mycomplex_t* proj_mapsFFT; myfloat_t* conv_map = NULL; mycomplex_t* conv_mapFFT; myfloat_t sumCONV, sumsquareCONV; proj_mapsFFT = (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); conv_map = (myfloat_t*) myfftw_malloc(sizeof(myfloat_t) * param.param_device.NumberPixels * param.param_device.NumberPixels); cout << "...... Calculating Projection .......................\n " ; createProjection(0, proj_mapsFFT); cout << "...... Calculating Convolution .......................\n " ; createConvolutedProjectionMap(0, 0, proj_mapsFFT, conv_map, conv_mapFFT, sumCONV, sumsquareCONV); } // ************************************************************************************** // **** Main BioEM routine, projects, convolutes and compares with Map using OpenMP **** // ************************************************************************************** // **** 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"); // Contros for MPI if(mpi_size > param.nTotGridAngles){ cout << "EXIT: Wrong MPI setup More MPI processes than orientations\n"; exit(1); } // 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 = -FLT_MAX; //Problem if using double presicion 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 = -FLT_MAX; } } if (param.param_device.writeCC) { int cc=0; for (int cent_x = 0; cent_x < param.param_device.NumberPixels; cent_x = cent_x + param.param_device.CCdisplace) { for (int cent_y = 0; cent_y < param.param_device.NumberPixels; cent_y = cent_y + param.param_device.CCdisplace) { bioem_Probability_cc& pProbCC = pProb.getProbCC(iRefMap, cc); //Debuggin:: cout << iRefMap << " " << cc << " " << cent_x << " " << cent_y << "\n"; if(!param.param_device.CCwithBayes) { pProbCC.forCC=-FLT_MAX; }else { pProbCC.forCC = 0.0; pProbCC.ConstCC=-FLT_MAX; } cc++; } } if(!FFTAlgo){cout << "Cross correlation calculation must be with enviormental variable FFTALGO=1\n"; exit(1);} } } if(!FFTAlgo){cout << "Remark: Not using FFT algorithm. Not using Prior in B-Env.";} // ************************************************************************************** deviceStartRun(); // ******************************** MAIN CYCLE ****************************************** mycomplex_t* proj_mapsFFT; myfloat_t* conv_map = NULL; mycomplex_t* conv_mapFFT; myfloat_t sumCONV, sumsquareCONV; //allocating fftw_complex vector const int ProjMapSize = (param.FFTMapSize + 64) & ~63; //Make sure this is properly aligned for fftw..., Actually this should be ensureb by using FFTMapSize, but it is not due to a bug in CUFFT which cannot handle padding properly //******** Alocating Vectors ************* proj_mapsFFT = (mycomplex_t *) myfftw_malloc(sizeof(mycomplex_t) * ProjMapSize * nProjectionsAtOnce); 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; /* Autotuning */ Autotuner aut; if (Autotuning) { aut.Initialize(AUTOTUNING_ALGORITHM, FIRST_STABLE); rebalanceWrapper(aut.Workload()); } 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; // **************************Loop Over orientations*************************************** for (int iOrientAtOnce = iOrientStart; iOrientAtOnce < iOrientEnd; iOrientAtOnce += nProjectionsAtOnce) { // *************************************************************************************** // ***** Creating Projection for given orientation and transforming to Fourier space ***** if (DebugOutput >= 1) timer2.ResetStart(); if (DebugOutput >= 2) timer.ResetStart(); int iTmpEnd = std::min(iOrientEnd, iOrientAtOnce + nProjectionsAtOnce); // **************************Parallel orientations for projections at once*************** #pragma omp parallel for for (int iOrient = iOrientAtOnce; iOrient < iTmpEnd;iOrient++) { createProjection(iOrient, &proj_mapsFFT[(iOrient - iOrientAtOnce) * ProjMapSize]); } if (DebugOutput >= 2) printf("\tTime Projection %d: %f (rank %d)\n", iOrientAtOnce, timer.GetCurrentElapsedTime(), mpi_rank); /* Recalibrate if needed */ if (Autotuning && ((iOrientAtOnce - iOrientStart) % RECALIB_FACTOR == 0) && ((iOrientEnd - iOrientAtOnce) > RECALIB_FACTOR) && (iOrientAtOnce != iOrientStart)) { aut.Reset(); rebalanceWrapper(aut.Workload()); } for (int iOrient = iOrientAtOnce; iOrient < iTmpEnd;iOrient++) { mycomplex_t* proj_mapFFT = &proj_mapsFFT[(iOrient - iOrientAtOnce) * ProjMapSize]; // *************************************************************************************** // ***** **** Internal Loop over PSF/CTF 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); if ((DebugOutput >= 2) || (Autotuning && aut.Needed(iConv))) timer.ResetStart(); myfloat_t amp,pha,env; amp=param.CtfParam[iConv].pos[0]; pha=param.CtfParam[iConv].pos[1]; env=param.CtfParam[iConv].pos[2]; // ******************Internal loop over Reference images CUDA or OpenMP****************** // *** Comparing each calculated convoluted map with all experimental maps *** compareRefMaps(iOrient, iConv, amp, pha, env, conv_map, conv_mapFFT, sumCONV, sumsquareCONV); double compTime=0.; if (DebugOutput >= 2) { 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; if (Autotuning) printf("\t\tTime Comparison %d %d: %f sec (%f GFlops, %f GB/s (cached), %f GB/s, with GPU workload %d%%) (rank %d)\n", iOrient, iConv, compTime, nFlops / 1000000000., nGBs / 1000000000., nGBs2 / 1000000000., aut.Workload(), mpi_rank); else 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 (Autotuning && aut.Needed(iConv)) { if (compTime == 0.) compTime = timer.GetCurrentElapsedTime(); aut.Tune(compTime); if (aut.Finished() && DebugOutput >= 2) printf("\t\tOptimal GPU workload %d%% (rank %d)\n", aut.Workload(), mpi_rank); rebalanceWrapper(aut.Workload()); } } if (DebugOutput >= 1) { printf("\tTotal time for projection %d: %f (rank %d)\n", iOrient, timer2.GetCurrentElapsedTime(), mpi_rank); timer2.ResetStart(); } } } //deallocating fftw_complex vector myfftw_free(proj_mapsFFT); myfftw_free(conv_mapFFT); if (!FFTAlgo) myfftw_free(conv_map); deviceFinishRun(); // ************* Collecing all the probabilities from MPI replicas *************** #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); #ifdef DEBUG cout << "Reduction " << mpi_rank << " Map " << i << " Prob " << pProbMap.Total << " Const " << pProbMap.Constoadd << "\n"; #endif 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; //temporary array that has the mpirank for the highest pProb.constant } 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++) { for (int j = 0;j < param.nTotGridAngles;j++) { // tmp1[i] = pProb.getProbMap(i).Constoadd; // bioem_Probability_angle& pProbAngle = pProb.getProbAngle(i, j); tmp1[i * param.nTotGridAngles + j]= pProb.getProbAngle(i, j).ConstAngle; } } 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 // ************* Writing Out Probabilities *************** if (mpi_rank == 0) { // Output for Angle Probability File ofstream angProbfile; if(param.param_device.writeAngles) { angProbfile.open ("ANG_PROB"); angProbfile <<"************************* HEADER:: NOTATION *******************************************\n"; if(!param.doquater){ angProbfile <<" RefMap: MapNumber ; alpha[rad] - beta[rad] - gamma[rad] - logP - cal log Probability + Constant: Numerical Const.+ log (volume) + prior ang\n" ;} else { angProbfile <<" RefMap: MapNumber ; q1 - q2 -q3 - logP- cal log Probability + Constant: Numerical Const. + log (volume) + prior ang\n" ;}; angProbfile <<"************************* HEADER:: NOTATION *******************************************\n"; // angProbfile <<"Model Used: " << modelfile.c_str() << "\n"; // angProbfile <<"Input Used: " << infile.c_str() << "\n"; } // Output for Cross Correlation File ofstream ccProbfile; if(param.param_device.writeCC) { ccProbfile.open ("CROSS_CORRELATION"); ccProbfile <<"************************* HEADER:: NOTATION *******************************************\n"; ccProbfile <<" RefMap: MapNumber ; Pixel x - Pixel y - Cross-Correlation \n"; ccProbfile <<"Note that the highest Cross-correlation is the best.\n"; ccProbfile <<"If the particles are flipped, include the keyward FLIPPED in the Param file.\n"; ccProbfile <<"************************* HEADER:: NOTATION *******************************************\n"; } // Output for Standard Probability ofstream outputProbFile; if(!yesoutfilename)OutfileName="Output_Probabilities"; outputProbFile.open (OutfileName.c_str()); outputProbFile <<"************************* HEADER:: NOTATION *******************************************\n"; outputProbFile << "Notation= RefMap: MapNumber ; LogProb natural logarithm of posterior Probability ; Constant: Numerical Const. for adding Probabilities \n"; if(!param.doquater){ if(param.usepsf){ outputProbFile << "Notation= RefMap: MapNumber ; Maximizing Param: MaxLogProb - alpha[rad] - beta[rad] - gamma[rad] - PSF amp - PSF phase - PSF envelope - center x - center y - normalization - offsett \n";}else{ outputProbFile << "Notation= RefMap: MapNumber ; Maximizing Param: MaxLogProb - alpha[rad] - beta[rad] - gamma[rad] - CTF amp - CTF defocus - CTF B-Env - center x - center y - normalization - offsett \n";} }else { if(param.usepsf){ // if( localcc[rx * param.param_device.NumberPixels + ry] < outputProbFile << "Notation= RefMap: MapNumber ; Maximizing Param: MaxLogProb - q1 - q2 - q3 - q4 -PSF amp - PSF phase - PSF envelope - center x - center y - normalization - offsett \n"; }else{ outputProbFile << "Notation= RefMap: MapNumber ; Maximizing Param: MaxLogProb - q1 - q2 - q3 - q4 - CTF amp - CTF defocus - CTF B-Env - center x - center y - normalization - offsett \n"; }} if(param.writeCTF) outputProbFile << " RefMap: MapNumber ; CTFMaxParm: defocus - b-Env (B ref. Penzeck 2010)\n"; if(param.yespriorAngles) outputProbFile << "**** Remark: Using Prior Proability in Angles ****\n"; outputProbFile <<"************************* HEADER:: NOTATION *******************************************\n\n"; // Loop over reference maps // ************* Over all maps *************** for (int iRefMap = 0; iRefMap < RefMap.ntotRefMap; iRefMap ++) { // **** Total Probability *** bioem_Probability_map& pProbMap = pProb.getProbMap(iRefMap); //Controll for Value of Total Probability // cout << pProbMap.Total << " " << pProbMap.Constoadd << " " << FLT_MAX <<" " << log(FLT_MAX) << "\n"; if(pProbMap.Total>1.e-38){ outputProbFile << "RefMap: " << iRefMap << " LogProb: " << 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 << (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)) << " "; }else{ outputProbFile << "Warining! with Map " << iRefMap << "Numerical Integrated Probability without constant = 0.0;\n"; outputProbFile << "Warining RefMap: " << iRefMap << "Check that constant is finite: " << pProbMap.Constoadd << "\n"; outputProbFile << "Warining RefMap: i) check model, ii) check refmap , iii) check GPU on/off command inconsitency\n"; // outputProbFile << "Warning! " << iRefMap << " LogProb: " << 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] << " [] "; if(param.doquater)outputProbFile << param.angles[pProbMap.max.max_prob_orient].quat4 << " [] "; outputProbFile << param.CtfParam[pProbMap.max.max_prob_conv].pos[0] << " [] "; if(!param.usepsf){outputProbFile << param.CtfParam[pProbMap.max.max_prob_conv].pos[1]/ 2.f /M_PI / param.elecwavel * 0.0001 << " [micro-m] "; }else{outputProbFile << param.CtfParam[pProbMap.max.max_prob_conv].pos[1] << " [1/A²] ";} if(!param.usepsf){outputProbFile << param.CtfParam[pProbMap.max.max_prob_conv].pos[2] << " [A²] ";} else{outputProbFile << param.CtfParam[pProbMap.max.max_prob_conv].pos[2] << " [1/A²] ";} outputProbFile << pProbMap.max.max_prob_cent_x << " [pix] "; outputProbFile << pProbMap.max.max_prob_cent_y << " [pix] " ; if(FFTAlgo){outputProbFile << pProbMap.max.max_prob_norm << " [] " ;}else{outputProbFile << "N.A." << " [] ";} if(FFTAlgo){outputProbFile << pProbMap.max.max_prob_mu << " [] ";}else{outputProbFile << "N.A." << " [] ";} outputProbFile << "\n"; // Writing out CTF parameters if requiered if(param.writeCTF && param.usepsf){ myfloat_t denomi; denomi = param.CtfParam[pProbMap.max.max_prob_conv].pos[1] * param.CtfParam[pProbMap.max.max_prob_conv].pos[1] + param.CtfParam[pProbMap.max.max_prob_conv].pos[2] * param.CtfParam[pProbMap.max.max_prob_conv].pos[2]; outputProbFile << "RefMap: " << iRefMap << " CTFMaxParam: "; outputProbFile << 2*M_PI*param.CtfParam[pProbMap.max.max_prob_conv].pos[1]/denomi/param.elecwavel*0.0001 << " [micro-m] "; outputProbFile << 4*M_PI*M_PI*param.CtfParam[pProbMap.max.max_prob_conv].pos[2]/denomi << " [A²] \n"; } //*************** Writing Individual Angle probabilities if(param.param_device.writeAngles) { for (int iOrient = 0; iOrient < param.nTotGridAngles; iOrient++) { bioem_Probability_angle& pProbAngle = pProb.getProbAngle(iRefMap, iOrient); myfloat_t logp=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); if(!param.doquater){ // For Euler Angles if(param.yespriorAngles){ logp+=param.angprior[iOrient]; angProbfile << " " << iRefMap << " " << param.angles[iOrient].pos[0] << " " << param.angles[iOrient].pos[1] << " " << param.angles[iOrient].pos[2] << " " << logp << " Separated: " << 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) << " " << param.angprior[iOrient] << "\n"; } else { angProbfile << " " << iRefMap << " " << param.angles[iOrient].pos[0] << " " << param.angles[iOrient].pos[1] << " " << param.angles[iOrient].pos[2] << " " << logp << " Separated: "<< 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) << "\n"; } }else { // Samething but for Quaternions if(param.yespriorAngles){ logp+=param.angprior[iOrient]; angProbfile << " " << iRefMap << " " << param.angles[iOrient].pos[0] << " " << param.angles[iOrient].pos[1] << " " << param.angles[iOrient].pos[2] << " " << param.angles[iOrient].quat4 << " " << logp << " Separated: " << 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) << " " << param.angprior[iOrient] << "\n"; } else { angProbfile << " " << iRefMap << " " << param.angles[iOrient].pos[0] << " " << param.angles[iOrient].pos[1] << " " << param.angles[iOrient].pos[2] << " " << param.angles[iOrient].quat4 << " " << logp << " Separated: "<< 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) << "\n"; } } } } //************* Writing Cross-Correlations if requiered //************* This is currently not in the manual ***** if(param.param_device.writeCC){ int cc=0; int halfPix; int rx=0; int ry=0; myfloat_t localcc[ (param.param_device.NumberPixels+1) * (param.param_device.NumberPixels+1) ]; int used[(param.param_device.NumberPixels+1) * (param.param_device.NumberPixels+1)]; halfPix = param.param_device.NumberPixels / 2 ; // Ordering the centers of the Cross Correlation for (int rx = 0; rx < param.param_device.NumberPixels ; rx++) { for (int ry = 0; ry < param.param_device.NumberPixels ; ry++) { localcc[ rx * param.param_device.NumberPixels + ry ] = 0.0; used[ rx * param.param_device.NumberPixels + ry ]= 0; } } for (int cent_x = 0; cent_x < param.param_device.NumberPixels ; cent_x = cent_x + param.param_device.CCdisplace) { for (int cent_y = 0; cent_y < param.param_device.NumberPixels ; cent_y = cent_y + param.param_device.CCdisplace) { //localcc[ rx * param.param_device.NumberPixels + ry ] = 0.0; bioem_Probability_cc& pProbCC = pProb.getProbCC(iRefMap, cc); // Applying Periodic boundary conditions to the CC if(cent_x < halfPix && cent_y < halfPix){ // ccProbfile << " " << iRefMap << " " << (myfloat_t) halfPix - cent_x << " " << halfPix - cent_y << " " << pProbCC.forCC <<"\n"; rx = halfPix - cent_x; ry = halfPix - cent_y;} if(cent_x >= halfPix && cent_y < halfPix){ // ccProbfile << " " << iRefMap << " " << (myfloat_t) 3 * halfPix - cent_x << " " << halfPix - cent_y << " " << pProbCC.forCC <<"\n"; rx = 3 * halfPix - cent_x; ry = halfPix - cent_y;} if(cent_x < halfPix && cent_y >= halfPix){ // ccProbfile << " " << iRefMap << " " << (myfloat_t) halfPix - cent_x << " " << 3 * halfPix - cent_y << " " << pProbCC.forCC <<"\n"; rx = halfPix - cent_x; ry = 3 * halfPix - cent_y;} if(cent_x >= halfPix && cent_y >= halfPix){ // ccProbfile << " " << iRefMap << " " << 3* halfPix - cent_x << " " << 3 * halfPix - cent_y << " " << pProbCC.forCC <<"\n"; rx = 3 * halfPix - cent_x; ry = 3 * halfPix - cent_y;} // cout << " TT " << cent_x << " " << rx << " " << cent_y << " " << ry << " " << pProbCC.forCC << "\n"; if(!param.param_device.CCwithBayes){ localcc[ rx * param.param_device.NumberPixels + ry ] = pProbCC.forCC; }else{ localcc[ rx * param.param_device.NumberPixels + ry ] = log(pProbCC.forCC)+pProbCC.ConstCC; } used[ rx * param.param_device.NumberPixels + ry] = 1; cc++; } // ccProbfile << "\n"; } if(!param.ignoreCCoff){ /* for (int rx = param.param_device.CCdisplace; rx < param.param_device.NumberPixels ; rx = rx + param.param_device.CCdisplace) { for (int ry = param.param_device.CCdisplace; ry < param.param_device.NumberPixels ; ry = ry + param.param_device.CCdisplace) {*/ for (int rx = param.param_device.CCdisplace; rx < param.param_device.NumberPixels ; rx++) { for (int ry = param.param_device.CCdisplace; ry < param.param_device.NumberPixels ; ry++) { if(used[ rx * param.param_device.NumberPixels + ry ] == 1){ ccProbfile << "RefMap: "<< iRefMap << " " << rx << " " << ry << " " << localcc[ rx * param.param_device.NumberPixels + ry ] << "\n" ; }else{ if(localcc[ rx * param.param_device.NumberPixels + ry ] <= -FLT_MAX)ccProbfile << "RefMap: "<< iRefMap << " " << rx << " " << ry << " " << -FLT_MAX << "\n" ; } // cout << " cc " << rx << " " << ry << " " << localcc[ rx * param.param_device.NumberPixels + ry ] <<"\n" ; } // ccProbfile << "\n"; } }else{ for (int rx = param.param_device.CCdisplace; rx < param.param_device.NumberPixels ; rx++) { for (int ry = param.param_device.CCdisplace; ry < param.param_device.NumberPixels ; ry++) { if(used[ rx * param.param_device.NumberPixels + ry ] == 1){ ccProbfile << "RefMap: "<< iRefMap << " " << rx << " " << ry << " " << localcc[ rx * param.param_device.NumberPixels + ry ] << "\n" ; }else{ if(localcc[ rx * param.param_device.NumberPixels + ry ] <= -FLT_MAX)ccProbfile << "RefMap: "<< iRefMap << " " << rx << " " << ry << " " << -FLT_MAX << "\n" ; } } // ccProbfile << "\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, myfloat_t amp, myfloat_t pha, myfloat_t env, 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 ***** //*************************************************************************************** cuda_custom_timeslot("Comparison", iOrient, iConv, COLOR_COMPARISON); if (FFTAlgo) { //With FFT Algorithm #pragma omp parallel for schedule(dynamic, 1) for (int iRefMap = startMap; iRefMap < RefMap.ntotRefMap; iRefMap ++) { const int num = omp_get_thread_num(); calculateCCFFT(iRefMap, iOrient, iConv, amp, pha, env, sumC, sumsquareC, localmultFFT, param.fft_scratch_complex[num], param.fft_scratch_real[num]); } } else { //Without FFT Algorithm #pragma omp parallel for schedule(dynamic, 1) for (int iRefMap = startMap; iRefMap < RefMap.ntotRefMap; iRefMap ++) { compareRefMapShifted < -1 > (iRefMap, iOrient, iConv, amp, pha, env, sumC, sumsquareC, conv_map, pProb, param.param_device, RefMap); } } cuda_custom_timeslot_end; return(0); } inline void bioem::calculateCCFFT(int iRefMap, int iOrient, int iConv, myfloat_t amp, myfloat_t pha, myfloat_t env, myfloat_t sumC, myfloat_t sumsquareC, mycomplex_t* localConvFFT, mycomplex_t* localCCT, myfloat_t* lCC) { //*************************************************************************************** //***** Calculating cross correlation in FFTALGOrithm ***** for(int i = 0; i < param.param_device.NumberPixels; i++) { for(int j = 0; j < param.param_device.NumberPixels; j++) lCC[i * param.param_device.NumberPixels + j] = 0.f; } 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); // printf("HereCC %p %f %d %d %d %d \n", &lCC[139 * param.param_device.NumberPixels + 139],lCC[139 * param.param_device.NumberPixels + 139],mpi_rank,iConv,iOrient,iRefMap); doRefMapFFT(iRefMap, iOrient, iConv, amp, pha, env, lCC, sumC, sumsquareC, pProb, param.param_device, RefMap); #ifdef DEBUG if (param.param_device.writeCC) { int cc=0; for (int cent_x = 0; cent_x < param.param_device.NumberPixels ; cent_x = cent_x + param.param_device.CCdisplace) { for (int cent_y = 0; cent_y < param.param_device.NumberPixels ; cent_y = cent_y + param.param_device.CCdisplace) { cout << "CHECKCC " << " " << cent_x << " " << cent_y <<" " << lCC[cent_x * param.param_device.NumberPixels + cent_y] / (myfloat_t) (param.param_device.NumberPixels * param.param_device.NumberPixels ) << "\n"; cc++; } } } #endif } int bioem::createProjection(int iMap, mycomplex_t* mapFFT) { // ************************************************************************************** // **** BioEM Create Projection routine in Euler angles / Quaternions ****************** // ********************* and turns projection into Fourier space ************************ // ************************************************************************************** cuda_custom_timeslot("Projection", iMap, 0, COLOR_PROJECTION); 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)); //*************** Rotating the model **************************** //*************** Quaternions **************************** if(param.doquater){ myfloat_t quater[4]; //quaternion quater[0]=param.angles[iMap].pos[0]; quater[1]=param.angles[iMap].pos[1]; quater[2]=param.angles[iMap].pos[2]; quater[3]=param.angles[iMap].quat4; //Rotation Matrix for Quaterions (wikipeda) rotmat[0][0] = 1- 2 * quater[1] * quater[1] - 2 * quater[2] * quater[2]; rotmat[1][0] = 2 * ( quater[0] * quater[1] - quater[2] * quater[3]); rotmat[2][0] = 2 * ( quater[0] * quater[2] + quater[1] * quater[3]); rotmat[0][1] = 2 * ( quater[0] * quater[1] + quater[2] * quater[3]); rotmat[1][1] = 1- 2 * quater[0] * quater[0] - 2 * quater[2] * quater[2]; rotmat[2][1] = 2 * ( quater[1] * quater[2] - quater[0] * quater[3]); rotmat[0][2] = 2 * ( quater[0] * quater[2] - quater[1] * quater[3]); rotmat[1][2] = 2 * ( quater[1] * quater[2] + quater[0] * quater[3]); rotmat[2][2] = 1- 2 * quater[0] * quater[0] - 2 * quater[1] * quater[1]; } else{ //*************** Euler Angles**************************** // Doing Euler angles instead of Quaternions alpha = param.angles[iMap].pos[0]; beta = param.angles[iMap].pos[1]; gam = param.angles[iMap].pos[2]; //*** To see how things are going: #ifdef DEBUG cout << "Id " << omp_get_thread_num() << " Angs: " << alpha << " " << beta << " " << gam << "\n"; #endif // ********** Creat Rotation with pre-defiend grid of orientations********** // Same notation as in Goldstein and Mathematica 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); } // The rotation matrix is calculated either for the quaternions or for the euler angles 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]; } } } if(param.printrotmod) { for(int n = 0; n < Model.nPointsModel; n++) cout << "ROTATED " << iMap << " " << n <<" "<< RotatedPointsModel[n].pos[0] << " " << RotatedPointsModel[n].pos[1] << " " << RotatedPointsModel[n].pos[2] << "\n"; } int i, j; //*************** Creating projection **************************** //********** Projection with radius *************** int irad; myfloat_t dist, rad2; myfloat_t tempden=0.0; for(int n = 0; n < Model.nPointsModel; n++) { if(Model.points[n].radius <= param.pixelSize){ // cout << "Radius less than Pixel size: use keyword NO_PROJECT_RADIUS in inputfile\n"; 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 >= 0) cout << "WARNING:::: Model Point out of Projection map: " << i << ", " << j << "\n"; // continue; if(not param.ignorepointsout)exit(1); } localproj[i * param.param_device.NumberPixels + j] += Model.points[n].density; tempden += Model.points[n].density; // exit(1); }else{ //Getting Centers of Sphere i = floor(RotatedPointsModel[n].pos[0] / param.pixelSize + (myfloat_t) param.param_device.NumberPixels / 2.0f + 0.5f) -param.shiftX; j = floor(RotatedPointsModel[n].pos[1] / param.pixelSize + (myfloat_t) param.param_device.NumberPixels / 2.0f + 0.5f) -param.shiftY; //Getting the radius irad=int( Model.points[n].radius / param.pixelSize ) + 1; rad2= Model.points[n].radius * Model.points[n].radius; if (i < 0 || j < 0 || i >= param.param_device.NumberPixels || j >= param.param_device.NumberPixels) { if (DebugOutput >= 0) cout << "WARNING::: Model Point out of Projection map: " << i << ", " << j << "\n"; cout << "Model point " << n << "Rotation: " << iMap <<" "<< RotatedPointsModel[n].pos[0] << " " << RotatedPointsModel[n].pos[1] << " " << RotatedPointsModel[n].pos[2] << "\n"; cout << "Original coor " << n <<" " << Model.points[n].point.pos[0] << " " << Model.points[n].point.pos[1] << " " <(std::time(0))); //Uniform Noise: bran::uniform_int_distribution<> dist(1, 6); //Gaussian noise bran::normal_distribution <> distn(0.0,param.stnoise); memcpy(tmp, localmultFFT, sizeof(mycomplex_t) * param.param_device.NumberPixels * param.param_device.NumberFFTPixels1D); // **** Bringing convoluted Map to real Space **** myfftw_execute_dft_c2r(param.fft_plan_c2r_backward, tmp, Mapconv); myfloat_t norm2 = (myfloat_t) (param.param_device.NumberPixels * param.param_device.NumberPixels); ofstream myexamplemap; myexamplemap.open ("BESTMAP"); for(int k = 0; k < param.param_device.NumberPixels; k++) { for(int j = 0; j < param.param_device.NumberPixels; j++) { if(!param.withnoise){ myexamplemap << "\nMAP " << k+param.ddx << " " << j+param.ddy << " " << Mapconv[k * param.param_device.NumberPixels + j] / norm2 *param.bestnorm +param.bestoff ; } else { myexamplemap << "\nMAP " << k+param.ddx << " " << j+param.ddy << " " << Mapconv[k * param.param_device.NumberPixels + j] / norm2 *param.bestnorm +param.bestoff+distn(gen); // cout << distn(gen) << "CHECK\n"; } } myexamplemap << " \n"; } myexamplemap.close(); cout << "\n\nBest map printed in file: BESTMAP with gnuplot format in columns 2, 3 and 4. \n\n\n"; exit(1); } cuda_custom_timeslot_end; return(0); } int bioem::calcross_cor(myfloat_t* localmap, myfloat_t& sum, myfloat_t& sumsquare) { // *********************** Routine to calculate Cross correlations*********************** sum = 0.0; sumsquare = 0.0; for (int i = 0; i < param.param_device.NumberPixels; i++) { for (int j = 0; j < param.param_device.NumberPixels; j++) { // Calculate Sum of pixels sum += localmap[i * param.param_device.NumberPixels + j]; // Calculate Sum of pixels squared sumsquare += localmap[i * param.param_device.NumberPixels + j] * localmap[i * param.param_device.NumberPixels + j]; } } return(0); } int bioem::deviceInit() { return(0); } int bioem::deviceStartRun() { return(0); } int bioem::deviceFinishRun() { return(0); } void* bioem::malloc_device_host(size_t size) { return(mallocchk(size)); } void bioem::free_device_host(void* ptr) { free(ptr); } void bioem::rebalanceWrapper(int workload) { cuda_custom_timeslot("Rebalance workload", -1, workload, COLOR_WORKLOAD); rebalance(workload); cuda_custom_timeslot_end; } void bioem::rebalance(int workload) {}