// Transform --------------------------------------------------------------- void FourierTransformer::Transform(int sign) { if (sign == FFTW_FORWARD) { fftw_execute(fPlanForward); // Normalisation of the transform unsigned long int size = 0; if (fReal != NULL) { size = MULTIDIM_SIZE(*fReal); } else if (fComplex != NULL) { size = MULTIDIM_SIZE(*fComplex); } else { REPORT_ERROR("No complex nor real data defined"); } FOR_ALL_DIRECT_ELEMENTS_IN_MULTIDIMARRAY(fFourier) DIRECT_MULTIDIM_ELEM(fFourier, n) /= size; } else if (sign == FFTW_BACKWARD) { fftw_execute(fPlanBackward); } }
void ParticleSorterMpi::run() { int total_nr_images = MDin.numberOfObjects(); features.resize(total_nr_images, NR_FEATURES); // Each node does part of the work long int my_first_image, my_last_image, my_nr_images; divide_equally(total_nr_images, node->size, node->rank, my_first_image, my_last_image); my_nr_images = my_last_image - my_first_image + 1; int barstep; if (verb > 0) { std::cout << "Calculating sorting features for all input particles..." << std::endl; init_progress_bar(my_nr_images); barstep = XMIPP_MAX(1, my_nr_images/ 60); } long int ipart = 0; FOR_ALL_OBJECTS_IN_METADATA_TABLE(MDin) { if (ipart >= my_first_image && ipart <= my_last_image) { if (verb > 0 && ipart % barstep == 0) progress_bar(ipart); calculateFeaturesOneParticle(ipart); } ipart++; } if (verb > 0) progress_bar(my_nr_images); // Combine results from all nodes MultidimArray<double> allnodes_features; allnodes_features.resize(features); MPI_Allreduce(MULTIDIM_ARRAY(features), MULTIDIM_ARRAY(allnodes_features), MULTIDIM_SIZE(features), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); features = allnodes_features; // Only the master writes out files if (verb > 0) { normaliseFeatures(); writeFeatures(); } }
/* MAIN -------------------------------------------------------------------- */ int main(int argc, char **argv) { // For parallelization int rank, size, num_img_tot; int c,nn,imgno,opt_refno,iaux; double LL,sumw_allrefs,sumcorr; double aux,wsum_sigma_noise2, wsum_sigma_offset; std::vector<Matrix3D<double > > wsum_Mref; std::vector<Matrix3D<double > > wsum_Mwedge; std::vector<double> sumw; Matrix3D<double> Maux, Mauxbig; FileName fn_img,fn_tmp; Matrix1D<double> oneline(0); DocFile DFo,DFf; SelFile SFo,SFa; Prog_MLalign3D_prm prm; // Init Parallel interface MPI_Init(&argc, &argv); MPI_Comm_rank(MPI_COMM_WORLD, &rank); MPI_Comm_size(MPI_COMM_WORLD, &size); // Get input parameters try { // Read command line prm.read(argc,argv); // Select only relevant part of selfile for this rank mpiSelectPart(prm.SF, rank,size,num_img_tot); prm.produce_Side_info(); if (rank==0) prm.show(); else prm.verb=0; } catch (XmippError XE) {if (rank==0) {std::cout << XE; prm.usage();} MPI_Finalize(); exit(1);} try { Maux.resize(prm.dim,prm.dim,prm.dim); Maux.setXmippOrigin(); Mauxbig.resize(prm.bigdim,prm.bigdim,prm.bigdim); Mauxbig.setXmippOrigin(); DFo.reserve(2*prm.SF.ImgNo()+1); DFf.reserve(2*prm.SFr.ImgNo()+4); SFa.reserve(prm.Niter*prm.nr_ref); SFa.clear(); // Loop over all iterations for (int iter=prm.istart; iter<=prm.Niter; iter++) { if (prm.verb>0) std::cerr << " multi-reference refinement: iteration " << iter <<" of "<< prm.Niter<<std::endl; DFo.clear(); if (rank==0) DFo.append_comment("Headerinfo columns: rot (1), tilt (2), psi (3), Xoff (4), Yoff (5), Zoff (6), WedNo (7) Ref (8), Pmax/sumP (9)"); // Integrate over all images prm.ML_sum_over_all_images(prm.SF,prm.Iref,LL,sumcorr,DFo, wsum_Mref,wsum_Mwedge, wsum_sigma_noise2,wsum_sigma_offset,sumw); // Here MPI_allreduce of all wsums,LL and sumcorr !!! MPI_Allreduce(&LL,&aux,1,MPI_DOUBLE,MPI_SUM,MPI_COMM_WORLD); LL=aux; MPI_Allreduce(&sumcorr,&aux,1,MPI_DOUBLE,MPI_SUM,MPI_COMM_WORLD); sumcorr=aux; MPI_Allreduce(&wsum_sigma_offset,&aux,1,MPI_DOUBLE,MPI_SUM,MPI_COMM_WORLD); wsum_sigma_offset=aux; MPI_Allreduce(&wsum_sigma_noise2,&aux,1,MPI_DOUBLE,MPI_SUM,MPI_COMM_WORLD); wsum_sigma_noise2=aux; for (int refno=0;refno<prm.nr_ref; refno++) { MPI_Allreduce(MULTIDIM_ARRAY(wsum_Mref[refno]),MULTIDIM_ARRAY(Maux), MULTIDIM_SIZE(wsum_Mref[refno]),MPI_DOUBLE,MPI_SUM,MPI_COMM_WORLD); wsum_Mref[refno]=Maux; MPI_Allreduce(MULTIDIM_ARRAY(wsum_Mwedge[refno]),MULTIDIM_ARRAY(Mauxbig), MULTIDIM_SIZE(wsum_Mwedge[refno]),MPI_DOUBLE,MPI_SUM,MPI_COMM_WORLD); wsum_Mwedge[refno]=Mauxbig; MPI_Allreduce(&sumw[refno],&aux,1,MPI_DOUBLE,MPI_SUM,MPI_COMM_WORLD); sumw[refno]=aux; } // Update model parameters prm.update_parameters(wsum_Mref,wsum_Mwedge, wsum_sigma_noise2,wsum_sigma_offset, sumw,sumcorr,sumw_allrefs,iter); // All nodes write out temporary DFo fn_img.compose(prm.fn_root,rank,"tmpdoc"); DFo.write(fn_img); MPI_Barrier(MPI_COMM_WORLD); if (rank==0) { prm.write_output_files(iter,SFa,DFf,sumw_allrefs,sumw,LL,sumcorr); // Write out docfile with optimal transformation & references DFo.clear(); for (int rank2=0; rank2<size; rank2++) { fn_img.compose(prm.fn_root,rank2,"tmpdoc"); int ln=DFo.LineNo(); DFo.append(fn_img); DFo.locate(DFo.get_last_key()); DFo.next(); DFo.remove_current(); system(((std::string)"rm -f "+fn_img).c_str()); } fn_tmp=prm.fn_root+"_it"; fn_tmp.compose(fn_tmp,iter,"doc"); DFo.write(fn_tmp); } } // end loop iterations } catch (XmippError XE) {if (rank==0) {std::cout << XE; prm.usage();} MPI_Finalize(); exit(1);} MPI_Finalize(); return 0; }
// Fit the beam-induced translations for all average micrographs void ParticlePolisherMpi::fitMovementsAllMicrographs() { int total_nr_micrographs = exp_model.average_micrographs.size(); // Each node does part of the work long int my_first_micrograph, my_last_micrograph, my_nr_micrographs; divide_equally(total_nr_micrographs, node->size, node->rank, my_first_micrograph, my_last_micrograph); my_nr_micrographs = my_last_micrograph - my_first_micrograph + 1; // Loop over all average micrographs int barstep; if (verb > 0) { std::cout << " + Fitting straight paths for beam-induced movements in all micrographs ... " << std::endl; init_progress_bar(my_nr_micrographs); barstep = XMIPP_MAX(1, my_nr_micrographs/ 60); } for (long int i = my_first_micrograph; i <= my_last_micrograph; i++) { if (verb > 0 && i % barstep == 0) progress_bar(i); fitMovementsOneMicrograph(i); } // Wait until all micrographs have been done MPI_Barrier(MPI_COMM_WORLD); if (verb > 0) { progress_bar(my_nr_micrographs); } // Combine results from all nodes MultidimArray<DOUBLE> allnodes_fitted_movements; allnodes_fitted_movements.resize(fitted_movements); MPI_Allreduce(MULTIDIM_ARRAY(fitted_movements), MULTIDIM_ARRAY(allnodes_fitted_movements), MULTIDIM_SIZE(fitted_movements), MY_MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); fitted_movements = allnodes_fitted_movements; // Set the fitted movements in the xoff and yoff columns of the exp_model.MDimg for (long int ipart = 0; ipart < exp_model.numberOfParticles(); ipart++) { long int part_id = exp_model.particles[ipart].id; DOUBLE xoff = DIRECT_A2D_ELEM(fitted_movements, part_id, 0); DOUBLE yoff = DIRECT_A2D_ELEM(fitted_movements, part_id, 1); exp_model.MDimg.setValue(EMDL_ORIENT_ORIGIN_X, xoff, part_id); exp_model.MDimg.setValue(EMDL_ORIENT_ORIGIN_Y, yoff, part_id); } if (node->isMaster()) { // Write out the STAR file with all the fitted movements FileName fn_tmp = fn_in.withoutExtension() + "_" + fn_out + ".star"; exp_model.MDimg.write(fn_tmp); std::cout << " + Written out all fitted movements in STAR file: " << fn_tmp << std::endl; } }
void ParticlePolisherMpi::optimiseBeamTilt() { // This function assumes the shiny particles are in exp_mdel.MDimg!! if (beamtilt_max <= 0. && defocus_shift_max <= 0.) return; if (minres_beamtilt < maxres_model) { if (verb > 0) std::cout << " Skipping beamtilt correction, as the resolution of the shiny reconstruction does not go beyond minres_beamtilt of " << minres_beamtilt << " Ang." << std::endl; return; } getBeamTiltGroups(); initialiseSquaredDifferenceVectors(); int total_nr_micrographs = exp_model.micrographs.size(); // Each node does part of the work long int my_first_micrograph, my_last_micrograph, my_nr_micrographs; divide_equally(total_nr_micrographs, node->size, node->rank, my_first_micrograph, my_last_micrograph); my_nr_micrographs = my_last_micrograph - my_first_micrograph + 1; // Loop over all average micrographs int barstep; if (verb > 0) { std::cout << " + Optimising beamtilts and/or defocus values in all micrographs ... " << std::endl; init_progress_bar(my_nr_micrographs); barstep = XMIPP_MAX(1, my_nr_micrographs/ 60); } for (long int i = my_first_micrograph; i <= my_last_micrograph; i++) { if (verb > 0 && i % barstep == 0) progress_bar(i); optimiseBeamTiltAndDefocusOneMicrograph(i); } if (verb > 0) progress_bar(my_nr_micrographs); // Combine results from all nodes if (beamtilt_max > 0.) { MultidimArray<DOUBLE> allnodes_diff2_beamtilt; allnodes_diff2_beamtilt.initZeros(diff2_beamtilt); MPI_Allreduce(MULTIDIM_ARRAY(diff2_beamtilt), MULTIDIM_ARRAY(allnodes_diff2_beamtilt), MULTIDIM_SIZE(diff2_beamtilt), MY_MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); diff2_beamtilt = allnodes_diff2_beamtilt; } if (defocus_shift_max > 0.) { MultidimArray<DOUBLE> allnodes_defocus_shift_allmics; allnodes_defocus_shift_allmics.initZeros(defocus_shift_allmics); MPI_Allreduce(MULTIDIM_ARRAY(defocus_shift_allmics), MULTIDIM_ARRAY(allnodes_defocus_shift_allmics), MULTIDIM_SIZE(defocus_shift_allmics), MY_MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); defocus_shift_allmics = allnodes_defocus_shift_allmics; } // Now get the final optimised beamtilts and defocus shifts, and write results to the MetadataTable applyOptimisedBeamTiltsAndDefocus(); // Write the new MDTable to disc if (verb > 0) exp_model.MDimg.write(fn_out + ".star"); }
void ParticlePolisherMpi::calculateAllSingleFrameReconstructionsAndBfactors() { FileName fn_star = fn_in.withoutExtension() + "_" + fn_out + "_bfactors.star"; if (!do_start_all_over && readStarFileBfactors(fn_star)) { if (verb > 0) std::cout << " + " << fn_star << " already exists: skipping calculation average of per-frame B-factors." <<std::endl; return; } DOUBLE bfactor, offset, corr_coeff; int total_nr_frames = last_frame - first_frame + 1; long int my_first_frame, my_last_frame, my_nr_frames; // Loop over all frames (two halves for each frame!) to be included in the reconstruction // Each node does part of the work divide_equally(2*total_nr_frames, node->size, node->rank, my_first_frame, my_last_frame); my_nr_frames = my_last_frame - my_first_frame + 1; if (verb > 0) { std::cout << " + Calculating per-frame reconstructions ... " << std::endl; init_progress_bar(my_nr_frames); } for (long int i = my_first_frame; i <= my_last_frame; i++) { int iframe = (i >= total_nr_frames) ? i - total_nr_frames : i; iframe += first_frame; int ihalf = (i >= total_nr_frames) ? 2 : 1; calculateSingleFrameReconstruction(iframe, ihalf); if (verb > 0) progress_bar(i - my_first_frame + 1); } if (verb > 0) { progress_bar(my_nr_frames); } MPI_Barrier(MPI_COMM_WORLD); // Also calculate the average of all single-frames for both halves if (node->rank == 0) calculateAverageAllSingleFrameReconstructions(1); else if (node->rank == 1) calculateAverageAllSingleFrameReconstructions(2); // Wait until all reconstructions have been done, and calculate the B-factors per-frame MPI_Barrier(MPI_COMM_WORLD); calculateBfactorSingleFrameReconstruction(-1, bfactor, offset, corr_coeff); // FSC between the two averages, also reads mask MPI_Barrier(MPI_COMM_WORLD); // Loop over all frames (two halves for each frame!) to be included in the reconstruction // Each node does part of the work divide_equally(total_nr_frames, node->size, node->rank, my_first_frame, my_last_frame); my_nr_frames = my_last_frame - my_first_frame + 1; if (verb > 0) { std::cout << " + Calculating per-frame B-factors ... " << std::endl; init_progress_bar(my_nr_frames); } for (long int i = first_frame+my_first_frame; i <= first_frame+my_last_frame; i++) { calculateBfactorSingleFrameReconstruction(i, bfactor, offset, corr_coeff); int iframe = i - first_frame; DIRECT_A1D_ELEM(perframe_bfactors, iframe * 3 + 0) = bfactor; DIRECT_A1D_ELEM(perframe_bfactors, iframe * 3 + 1) = offset; DIRECT_A1D_ELEM(perframe_bfactors, iframe * 3 + 2) = corr_coeff; if (verb > 0) progress_bar(i - first_frame - my_first_frame + 1); } // Combine results from all nodes MultidimArray<DOUBLE> allnodes_perframe_bfactors; allnodes_perframe_bfactors.resize(perframe_bfactors); MPI_Allreduce(MULTIDIM_ARRAY(perframe_bfactors), MULTIDIM_ARRAY(allnodes_perframe_bfactors), MULTIDIM_SIZE(perframe_bfactors), MY_MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); perframe_bfactors = allnodes_perframe_bfactors; if (verb > 0) { progress_bar(my_nr_frames); writeStarFileBfactors(fn_star); // Also write a STAR file with the relative contributions of each frame to all frequencies fn_star = fn_in.withoutExtension() + "_" + fn_out + "_relweights.star"; writeStarFileRelativeWeights(fn_star); } }
void FourierTransformer::setFourier(MultidimArray<Complex >& inputFourier) { memcpy(MULTIDIM_ARRAY(fFourier), MULTIDIM_ARRAY(inputFourier), MULTIDIM_SIZE(inputFourier) * 2 * sizeof(double)); }
void correctMapForMTF(MultidimArray<Complex >& FT, int ori_size, FileName& fn_mtf) { MetaDataTable MDmtf; if (!fn_mtf.isStarFile()) { REPORT_ERROR("correctMapForMTF ERROR: input MTF file is not a STAR file."); } MDmtf.read(fn_mtf); MultidimArray<double> mtf_resol, mtf_value; mtf_resol.resize(MDmtf.numberOfObjects()); mtf_value.resize(mtf_resol); int i = 0; FOR_ALL_OBJECTS_IN_METADATA_TABLE(MDmtf) { MDmtf.getValue(EMDL_RESOLUTION_INVPIXEL, DIRECT_A1D_ELEM(mtf_resol, i)); // resolution needs to be given in 1/pix MDmtf.getValue(EMDL_POSTPROCESS_MTF_VALUE, DIRECT_A1D_ELEM(mtf_value, i)); if (DIRECT_A1D_ELEM(mtf_value, i) < 1e-10) { std::cerr << " i= " << i << " mtf_value[i]= " << DIRECT_A1D_ELEM(mtf_value, i) << std::endl; REPORT_ERROR("Postprocessing::sharpenMap ERROR: zero or negative values encountered in MTF curve!"); } i++; } double xsize = (double)ori_size; FOR_ALL_ELEMENTS_IN_FFTW_TRANSFORM(FT) { int r2 = kp * kp + ip * ip + jp * jp; double res = sqrt((double)r2) / xsize; // get resolution in 1/pixel if (res < 0.5) { // Find the suitable MTF value int i_0 = 0; for (int ii = 0; ii < XSIZE(mtf_resol); ii++) { if (DIRECT_A1D_ELEM(mtf_resol, ii) > res) { break; } i_0 = ii; } // linear interpolation: y = y_0 + (y_1 - y_0)*(x-x_0)/(x1_x0) double mtf; double x_0 = DIRECT_A1D_ELEM(mtf_resol, i_0); if (i_0 == MULTIDIM_SIZE(mtf_resol) - 1 || i_0 == 0) // check boundaries of the array { mtf = DIRECT_A1D_ELEM(mtf_value, i_0); } else { double x_1 = DIRECT_A1D_ELEM(mtf_resol, i_0 + 1); double y_0 = DIRECT_A1D_ELEM(mtf_value, i_0); double y_1 = DIRECT_A1D_ELEM(mtf_value, i_0 + 1); mtf = y_0 + (y_1 - y_0) * (res - x_0) / (x_1 - x_0); } // Divide Fourier component by the MTF DIRECT_A3D_ELEM(FT, k, i, j) /= mtf; } } }
// Transform --------------------------------------------------------------- void FourierTransformer::Transform(int sign) { if (sign == FFTW_FORWARD) { fftw_execute(fPlanForward); if (sign == normSign) { unsigned long int size=0; if(fReal!=NULL) size = MULTIDIM_SIZE(*fReal); else if (fComplex!= NULL) size = MULTIDIM_SIZE(*fComplex); else REPORT_ERROR(ERR_UNCLASSIFIED,"No complex nor real data defined"); double isize=1.0/size; double *ptr=(double*)MULTIDIM_ARRAY(fFourier); size_t nmax=(fFourier.nzyxdim/4)*4; for (size_t n=0; n<nmax; n+=4) { *ptr++ *= isize; *ptr++ *= isize; *ptr++ *= isize; *ptr++ *= isize; *ptr++ *= isize; *ptr++ *= isize; *ptr++ *= isize; *ptr++ *= isize; } for (size_t n=nmax; n<fFourier.nzyxdim; ++n) { *ptr++ *= isize; *ptr++ *= isize; } } } else if (sign == FFTW_BACKWARD) { fftw_execute(fPlanBackward); if (sign == normSign) { unsigned long int size=0; if(fReal!=NULL) { size = MULTIDIM_SIZE(*fReal); double isize=1.0/size; FOR_ALL_DIRECT_ELEMENTS_IN_MULTIDIMARRAY(*fReal) DIRECT_MULTIDIM_ELEM(*fReal,n) *= isize; } else if (fComplex!= NULL) { size = MULTIDIM_SIZE(*fComplex); double isize=1.0/size; double *ptr=(double*)MULTIDIM_ARRAY(*fComplex); FOR_ALL_DIRECT_ELEMENTS_IN_MULTIDIMARRAY(*fComplex) { *ptr++ *= isize; *ptr++ *= isize; } }
void FourierTransformer::setFourier(const MultidimArray<std::complex<double> > &inputFourier) { memcpy(MULTIDIM_ARRAY(fFourier),MULTIDIM_ARRAY(inputFourier), MULTIDIM_SIZE(inputFourier)*2*sizeof(double)); }
void MpiProgReconstructADMM::shareVolume(MultidimArray<double> &V) { MPI_Allreduce(MPI_IN_PLACE, MULTIDIM_ARRAY(V), MULTIDIM_SIZE(V), MPI_DOUBLE, MPI_SUM, MPI_COMM_WORLD); synchronize(); }
void Postprocessing::divideByMtf(MultidimArray<Complex > &FT) { if (fn_mtf != "") { if (verb > 0) { std::cout << "== Dividing map by the MTF of the detector ..." << std::endl; std::cout.width(35); std::cout << std::left <<" + mtf STAR-file: "; std::cout << fn_mtf << std::endl; } MetaDataTable MDmtf; if (!fn_mtf.isStarFile()) REPORT_ERROR("Postprocessing::divideByMtf ERROR: input MTF file is not a STAR file."); MDmtf.read(fn_mtf); MultidimArray<DOUBLE> mtf_resol, mtf_value; mtf_resol.resize(MDmtf.numberOfObjects()); mtf_value.resize(mtf_resol); int i =0; FOR_ALL_OBJECTS_IN_METADATA_TABLE(MDmtf) { MDmtf.getValue(EMDL_RESOLUTION_INVPIXEL, DIRECT_A1D_ELEM(mtf_resol, i) ); // resolution needs to be given in 1/pix MDmtf.getValue(EMDL_POSTPROCESS_MTF_VALUE, DIRECT_A1D_ELEM(mtf_value, i) ); if (DIRECT_A1D_ELEM(mtf_value, i) < 1e-10) { std::cerr << " i= " << i << " mtf_value[i]= " << DIRECT_A1D_ELEM(mtf_value, i) << std::endl; REPORT_ERROR("Postprocessing::sharpenMap ERROR: zero or negative values encountered in MTF curve!"); } i++; } DOUBLE xsize = (DOUBLE)XSIZE(I1()); FOR_ALL_ELEMENTS_IN_FFTW_TRANSFORM(FT) { int r2 = kp * kp + ip * ip + jp * jp; DOUBLE res = sqrt((DOUBLE)r2)/xsize; // get resolution in 1/pixel if (res < 0.5 ) { // Find the suitable MTF value int i_0 = 0; for (int ii = 0; ii < XSIZE(mtf_resol); ii++) { if (DIRECT_A1D_ELEM(mtf_resol, ii) > res) break; i_0 = ii; } // linear interpolation: y = y_0 + (y_1 - y_0)*(x-x_0)/(x1_x0) DOUBLE mtf; DOUBLE x_0 = DIRECT_A1D_ELEM(mtf_resol, i_0); if (i_0 == MULTIDIM_SIZE(mtf_resol) - 1 || i_0 == 0) // check boundaries of the array mtf = DIRECT_A1D_ELEM(mtf_value, i_0); else { DOUBLE x_1 = DIRECT_A1D_ELEM(mtf_resol, i_0 + 1); DOUBLE y_0 = DIRECT_A1D_ELEM(mtf_value, i_0); DOUBLE y_1 = DIRECT_A1D_ELEM(mtf_value, i_0 + 1); mtf = y_0 + (y_1 - y_0)*(res - x_0)/(x_1 - x_0); } // Divide Fourier component by the MTF DIRECT_A3D_ELEM(FT, k, i, j) /= mtf; } } } }