void SetLoggerSettings() { Oscl_Vector<LoggerConfigElement, OsclMemAllocator>::iterator it; PVLoggerAppender *appender = NULL; OsclRefCounter *refCounter = NULL; if (iLoggerConfigElements.empty()) { return; } if (iAppenderType == 0) { appender = new StdErrAppender<TimeAndIdLayout, 1024>(); OsclRefCounterSA<LogAppenderDestructDealloc<StdErrAppender<TimeAndIdLayout, 1024> > > *appenderRefCounter = new OsclRefCounterSA<LogAppenderDestructDealloc<StdErrAppender<TimeAndIdLayout, 1024> > >(appender); refCounter = appenderRefCounter; } else if (iAppenderType == 1) { OSCL_wHeapString<OsclMemAllocator> logfilename(OUTPUTNAME_PREPEND_WSTRING); logfilename += _STRLIT_WCHAR("player.log"); appender = (PVLoggerAppender*)TextFileAppender<TimeAndIdLayout, 1024>::CreateAppender(logfilename.get_str()); OsclRefCounterSA<LogAppenderDestructDealloc<TextFileAppender<TimeAndIdLayout, 1024> > > *appenderRefCounter = new OsclRefCounterSA<LogAppenderDestructDealloc<TextFileAppender<TimeAndIdLayout, 1024> > >(appender); refCounter = appenderRefCounter; } else { OSCL_wHeapString<OsclMemAllocator> logfilename(OUTPUTNAME_PREPEND_WSTRING); logfilename += _STRLIT_WCHAR("player.log"); appender = (PVLoggerAppender*)MemAppender<TimeAndIdLayout, 1024>::CreateAppender(logfilename.get_str()); OsclRefCounterSA<LogAppenderDestructDealloc<MemAppender<TimeAndIdLayout, 1024> > > *appenderRefCounter = new OsclRefCounterSA<LogAppenderDestructDealloc<MemAppender<TimeAndIdLayout, 1024> > >(appender); refCounter = appenderRefCounter; } OsclSharedPtr<PVLoggerAppender> appenderPtr(appender, refCounter); for (it = iLoggerConfigElements.begin(); it != iLoggerConfigElements.end(); it++) { PVLogger *node = NULL; node = PVLogger::GetLoggerObject(it->iLoggerString); node->AddAppender(appenderPtr); node->SetLogLevel(it->iLogLevel); } }
/****************************************************************************//** * * *******************************************************************************/ int main(int argc, char *argv[]) { typedef double TFLOAT; if (argc<5 || argc>8) { std::cerr << "Usage: " << (argc?argv[0]:"average") << " CONFIG_FILE FTEMPLATES FPARTICLES [LOGFILE] [DO_FSC] [WEDGE_THRESHOLD]" "\n" "compiled at " __DATE__ " " __TIME__ " from " __FILE__ "\n" " CONFIG_FILE : filename of the parallel correlation program." "\n" " FTEMPLATES : filename of the textfile with the names of the templates." "\n" " FPARTICLES : filename of the textfile with the names of the particles." "\n" " ANGLES : filename of the textfile with the angles." "\n" " LOGFILE : optional parameter for the log file. '-' for STDOUT." "\n" " DO_FSC : optional parameter to decide whether to compute the FSC (yes or no)." "\n" " WEDGE_THRESHOLD : Voxels of the averaged wedge are set to zero if they are SMALLER then WEDGE_THRESHOLD% of the number of particles (default 0 == no cutoff)." << std::endl; return -1; } double use_threshold = 0.005; if (argc >= 8) { try { use_threshold = boost::lexical_cast<double>(argv[7]); } catch (boost::bad_lexical_cast &) { throw std::invalid_argument("The WEDGE_THRESHOLD must be a floating point number."); } if (use_threshold > 1 && use_threshold <= 100) { use_threshold = use_threshold/100.; } if (use_threshold > 1 || use_threshold <= 0) { throw std::invalid_argument("WEDGE_THRESHOLD must be either a prozentual value ]1, 100] or relative between ]0.0, 1.0]."); } } bool do_fourier_shell = true; if (argc >= 7) { std::string p(argv[6]); std::transform(p.begin(), p.end(), p.begin(), &toupper); if (p=="YES" || p=="1" || p=="FSC" || p=="TRUE") { do_fourier_shell = true; } else if (p=="NO" || p=="0" || p=="FALSE") { do_fourier_shell = false; } else { std::cerr << "Argument 6 (do_fsc) must be either \"yes\" or \"no\"." << std::endl; return -2; } } std::size_t itemplate, iparticle, ntemplates, nparticles, i; std::vector<std::string> ftemplates, fparticles; std::vector<boost::shared_ptr<tom::Volume<double> > > angles; std::vector<helper::triple<double, double, double> > anglesv; std::vector<boost::shared_ptr<tom::WedgeDescriptor<TFLOAT> > > wedge_templates, wedge_particles; std::vector<tom::cc_peak<TFLOAT> > peak_list; tom::corr::ConfigDataServer c; std::string outputdir; std::stringstream clog; std::auto_ptr<std::ofstream> f; std::auto_ptr<helper::ostream_swapper> stream_swapper; clog.precision(20); clog << "# start " << (argc>0?argv[0]:"average") << " at " << helper::now2str() << " (compiled at " __DATE__ " " __TIME__ ")." << std::endl; // Parse the input files. clog << "# parse configuration (" << argv[1] << ")" << std::endl; c.read_from_conf(argv[1]); clog << "# parse filelist for templates (" << argv[2] << ")" << std::endl; tom::corr::parse_filelist(argv[2], ftemplates, wedge_templates, 1); ntemplates = ftemplates.size(); clog << "# " << ntemplates << " templates read.\n" "# parse filelist for particles (" << argv[3] << ")" << std::endl; tom::corr::parse_filelist(argv[3], fparticles, wedge_particles, 1); nparticles = fparticles.size(); clog << "# " << nparticles << " particles read.\n" "# parse the list of angles (" << argv[4] << ")" << std::endl; tom::corr::parse_angleslist(argv[4], ntemplates, nparticles, angles); clog << "# parse peak list (" << c.peakfilename << ")" << std::endl; tom::corr::parse_peaklist(c.peakfilename, peak_list, anglesv, ntemplates, nparticles); clog << "#\n# use a threshold for the wedge of " << use_threshold << "\n# (values in the summed wedge are set to zero if they are smaller then the relative threshold compared to the number of particles).\n" << std::endl; tom::avg::filename_generator f_gen(c.outputdir); // open the logfile. { std::ostream *use_log = &std::clog; std::string logfilename(argc>=6 ? argv[5] : "-"); if (logfilename != "-") { f.reset(new std::ofstream(logfilename.c_str(), std::ios::out | std::ios::trunc)); if (!f->good()) { f.reset(NULL); clog << "# ERROR: could not open log-file \"" << logfilename << "\" for writing. Use CERR instead." << std::endl; } else { use_log = f.get(); } } *use_log << clog.rdbuf() << std::flush; clog.clear(); stream_swapper.reset(new helper::ostream_swapper(clog, *use_log)); } // Find out, which particles average to which template. std::vector<std::vector<std::size_t> > use_particles(ntemplates), use_particles1(ntemplates), use_particles2(ntemplates), use_particles3(ntemplates); for (iparticle=0; iparticle<nparticles; iparticle++) { std::size_t max_index = ntemplates; double max_ccvalue = - std::numeric_limits<double>::infinity(); for (itemplate=0; itemplate<ntemplates; itemplate++) { i = itemplate * nparticles + iparticle; if (angles[i].get()) { assert(angles[i]->getSizeX()==3 && angles[i]->getSizeZ()==1); if (peak_list[i].angle_idx < 0) { clog << "# WARNING: no peak found for template #" << itemplate << ", particle #" << iparticle << "." << std::endl; continue; } else { if (static_cast<std::size_t>(peak_list[i].angle_idx) >= angles[i]->getSizeY()) { clog << "# WARNING: peak-index for template #" << itemplate << ", particle #" << iparticle << " is larger then the entire angle-list (" << peak_list[i].angle_idx << " vs. " << angles[i]->getSizeY() << "). Using peak from file." << std::endl; } else { boost::tuples::tuple<double &, double &, double &> a = boost::tuples::tie(angles[i]->get(0, peak_list[i].angle_idx, 0), angles[i]->get(0, peak_list[i].angle_idx, 0), angles[i]->get(0, peak_list[i].angle_idx, 0)); if (fabs(a.get<0>()-anglesv[i].x)>1e-7 || fabs(a.get<0>()-anglesv[i].x)>1e-7 || fabs(a.get<0>()-anglesv[i].x)>1e-7) { clog << "# WARNING: peak-index for template #" << itemplate << ", particle #" << iparticle << " differs from angles list and peakfile: (" << a.get<0>() << " vs. " << anglesv[i].x << "; " << a.get<0>() << " vs. " << anglesv[i].x << "; " << a.get<0>() << " vs. " << anglesv[i].x << "). Take from peak-file." << std::endl; } } } } else { if (peak_list[i].angle_idx >= 0) { clog << "# WARNING: peak-index for template #" << itemplate << ", particle #" << iparticle << " given, but the angles list is empty. Using peak from file." << std::endl; } else { // everything is fine. continue; } } const double shiftx = - peak_list[i].x; const double shifty = - peak_list[i].y; const double shiftz = - peak_list[i].z; if (fabs(shiftx) > c.volsize/2 || fabs(shifty) > c.volsize/2 || fabs(shiftz) > c.volsize/2) { clog << "# WARNING: the shift of template #" << itemplate << ", particle #" << iparticle << " is too large for the volume of size " << c.volsize << " (" << shiftx << "," << shifty << "," << shiftz << ")." << std::endl; continue; } if (max_index==ntemplates || max_ccvalue<peak_list[i].val) { max_ccvalue = peak_list[i].val; max_index = itemplate; } } if (max_index != ntemplates) { use_particles[max_index].push_back(iparticle); } } // Split the list of particles in two sets for the FSC. if (do_fourier_shell) { for (itemplate=0; itemplate<ntemplates; itemplate++) { std::size_t size = use_particles[itemplate].size(); if (size >= 2) { const std::vector<std::size_t> &v_ = use_particles [itemplate]; std::vector<std::size_t> &v1 = use_particles1[itemplate]; std::vector<std::size_t> &v2 = use_particles2[itemplate]; std::vector<std::size_t> &v3 = use_particles3[itemplate]; v1.resize(0); v2.resize(0); v3.resize(0); if (size%2) { size--; v3.push_back(v_[size]); } v1.reserve(size/2); v2.reserve(size/2); for (iparticle=0; iparticle<size; iparticle+=2) { v1.push_back(v_[iparticle]); } for (iparticle=1; iparticle<size; iparticle+=2) { v2.push_back(v_[iparticle]); } } } } else { clog << "# don't compute the Fourier Shell Correlation." << std::endl; } // Init the spheremask std::auto_ptr<const tom::Volume<TFLOAT> > mask_sphere; if (c.sphere_mask_inner_radius>0 || c.sphere_mask_sigma>0) { tom::Volume<TFLOAT> *p; mask_sphere.reset(p = new tom::Volume<TFLOAT>(c.volsize, c.volsize, c.volsize, NULL,NULL)); tom::init_spheremask(*p, c.sphere_mask_inner_radius, c.sphere_mask_sigma, c.sphere_mask_cutoff_radius); } tom::Volume<TFLOAT> avg(c.volsize, c.volsize, c.volsize, tom::fftw::fftw_malloc<TFLOAT>(), tom::fftw::fftw_free<TFLOAT>()); tom::Volume<TFLOAT> avgwedge(c.volsize, c.volsize, c.volsize, NULL,NULL); tom::Volume<TFLOAT> avgwedge_half(avgwedge, NULL, c.volsize, c.volsize, c.volsize/2+1, avgwedge.getStrideX(), avgwedge.getStrideY(), avgwedge.getStrideZ()); tom::Volume<TFLOAT> avgwedge_sqrtn(c.volsize, c.volsize, c.volsize, NULL,NULL); tom::Volume<TFLOAT> avgwedge_sqrtn_half(avgwedge_sqrtn, NULL, c.volsize, c.volsize, c.volsize/2+1, avgwedge.getStrideX(), avgwedge.getStrideY(), avgwedge.getStrideZ()); tom::Volume<TFLOAT> avg2(c.volsize, c.volsize, c.volsize, NULL,NULL); tom::Volume<TFLOAT> avgwedge2(c.volsize, c.volsize, c.volsize, NULL,NULL); tom::Volume<TFLOAT> avgwedge2_half(avgwedge2, NULL, c.volsize, c.volsize, c.volsize/2+1, avgwedge2.getStrideX(), avgwedge2.getStrideY(), avgwedge2.getStrideZ()); tom::Volume<std::complex<TFLOAT> > avg_ft(c.volsize, c.volsize, c.volsize/2+1, tom::fftw::fftw_malloc<TFLOAT>(), tom::fftw::fftw_free<TFLOAT>()); tom::Volume<std::complex<TFLOAT> > avg_ft2(c.volsize, c.volsize, c.volsize/2+1, tom::fftw::fftw_malloc<TFLOAT>(), tom::fftw::fftw_free<TFLOAT>()); tom::fftw::Plan<TFLOAT> plan_fwd(avg2, avg_ft, c.fftw_flag | FFTW_DESTROY_INPUT); tom::fftw::Plan<TFLOAT> plan_bwd(avg_ft, avg2, c.fftw_flag | FFTW_DESTROY_INPUT); std::auto_ptr<tom::Volume<TFLOAT> > vtemplate; tom::Volume<std::complex<TFLOAT> > vtemplate_ft(c.volsize, c.volsize, c.volsize/2+1, tom::fftw::fftw_malloc<TFLOAT>(), tom::fftw::fftw_free<TFLOAT>()); tom::fftw::Plan<TFLOAT> plan_vtemplate(avg, vtemplate_ft, c.fftw_flag | FFTW_DESTROY_INPUT); // Volumes for the fourier shell correlation. std::auto_ptr<tom::Volume<TFLOAT> > FSC_v, FSC_w2; std::auto_ptr<tom::Volume<std::complex<TFLOAT> > > FSC_f1, FSC_f2, FSC_f1_half, FSC_f2_half; std::auto_ptr<tom::fftw::Plan<TFLOAT> > FSC_plan1, FSC_plan2; if (do_fourier_shell) { FSC_v.reset( new tom::Volume<TFLOAT>(c.volsize, c.volsize, c.volsize, tom::fftw::fftw_malloc<TFLOAT>(), tom::fftw::fftw_free<TFLOAT>())); FSC_f1.reset( new tom::Volume<std::complex<TFLOAT> >(c.volsize, c.volsize, c.volsize, tom::fftw::fftw_malloc<TFLOAT>(), tom::fftw::fftw_free<TFLOAT>())); FSC_f2.reset( new tom::Volume<std::complex<TFLOAT> >(c.volsize, c.volsize, c.volsize, tom::fftw::fftw_malloc<TFLOAT>(), tom::fftw::fftw_free<TFLOAT>())); FSC_f1_half.reset( new tom::Volume<std::complex<TFLOAT> >(*FSC_f1, NULL, c.volsize, c.volsize, c.volsize/2+1, FSC_f1->getStrideX(), FSC_f1->getStrideY(), FSC_f1->getStrideZ())); FSC_f2_half.reset( new tom::Volume<std::complex<TFLOAT> >(*FSC_f2, NULL, c.volsize, c.volsize, c.volsize/2+1, FSC_f2->getStrideX(), FSC_f2->getStrideY(), FSC_f2->getStrideZ())); FSC_plan1.reset( new tom::fftw::Plan<TFLOAT>(*FSC_v, *FSC_f1_half, c.fftw_flag | FFTW_DESTROY_INPUT)); FSC_plan2.reset( new tom::fftw::Plan<TFLOAT>(*FSC_v, *FSC_f2_half, c.fftw_flag | FFTW_DESTROY_INPUT)); FSC_w2.reset( new tom::Volume<TFLOAT>(c.volsize, c.volsize, c.volsize/2+1, tom::fftw::fftw_malloc<TFLOAT>(), tom::fftw::fftw_free<TFLOAT>())); } double mean, variance; std::vector<std::size_t>::const_iterator culvit; // Const Unsigned Long Vector ITerator std::vector<tom::avg::st_average_result> av(ntemplates); double threshold = 1; // Now compute the average, the FSC, the CC and save it to file. for (itemplate=0; itemplate<ntemplates; itemplate++) { const std::vector<std::size_t> &v_ = use_particles [itemplate]; const std::vector<std::size_t> &v1 = use_particles1[itemplate]; const std::vector<std::size_t> &v2 = use_particles2[itemplate]; const std::vector<std::size_t> &v3 = use_particles3[itemplate]; threshold = v_.size()*use_threshold; // cut off. assert(std::set<std::size_t>(v_.begin(), v_.end()).size() == v_.size() && (!do_fourier_shell || (v_.size()<2 || v_.size()==(v1.size()+v2.size()+v3.size())))); if (v_.empty()) { continue; } tom::avg::st_average_result &ar = av[itemplate]; ar.use_idx = v_; // Read the original template from file. try { tom::Volume<TFLOAT> *p; tom::read_from_em(p, ftemplates[itemplate], NULL,NULL,NULL, NULL, NULL,NULL); vtemplate.reset(p); } catch (std::exception &e) { std::stringstream ss; ss << "# The template #" << itemplate << " (" << ftemplates[itemplate] << ") does not exist."; if (c.force_files_exist) { clog << ss.str() << " ABORT"; throw; } clog << ss << " SKIP CC correlation."; vtemplate.reset(NULL); } if (vtemplate.get()) { // normalise it and compute its fourier transformation. vtemplate->stat(mean, variance, false); vtemplate->shift_scale<TFLOAT>(-mean, 1./sqrt(variance)); avg.setValues(*vtemplate); plan_vtemplate.execute(avg, vtemplate_ft); } // Average the particles. if (!v1.empty() && v1.size()==v2.size()) { assert(do_fourier_shell); tom::avg::average(c.volsize, fparticles, wedge_particles, v1, itemplate, mask_sphere.get(), peak_list, anglesv, c.force_files_exist, &clog, avg, avgwedge_half); tom::avg::average(c.volsize, fparticles, wedge_particles, v2, itemplate, mask_sphere.get(), peak_list, anglesv, c.force_files_exist, &clog, avg2, avgwedge2_half); std::vector<double> res; std::size_t n_shells = c.volsize/2; FSC_w2->setValues(avgwedge_half); tom::element_wise_set_below_threshold<TFLOAT>(*FSC_w2, threshold*v1.size()/static_cast<double>(v_.size()), 0); tom::avg::apply_avgwedge(avg, *FSC_w2, mask_sphere.get(), c.fftw_flag, *FSC_v); //FSC_v->setValues(avg); //FSC_v->write_to_em("FSC_v1.em", NULL); FSC_plan1->execute(*FSC_v, *FSC_f1_half); FSC_w2->setValues(avgwedge2_half); tom::element_wise_set_below_threshold<TFLOAT>(*FSC_w2, threshold*v2.size()/static_cast<double>(v_.size()), 0); tom::avg::apply_avgwedge(avg2, *FSC_w2, mask_sphere.get(), c.fftw_flag, *FSC_v); //FSC_v->setValues(avg2); //FSC_v->write_to_em("FSC_v2.em", NULL); FSC_plan2->execute(*FSC_v, *FSC_f2_half); tom::fourier_shell_correlation(*FSC_f1_half, false, *FSC_f2_half, false, c.volsize, n_shells, res); ar.fsc.resize(n_shells); for (std::size_t i=0; i<n_shells; i++) { ar.fsc[i].first = res[i+n_shells*1]; ar.fsc[i].second = res[i+n_shells*7]; } //tom::Volume<double>(&res[0], n_shells, 11, 1, 0,0,0, false, NULL).write_to_em("FSC_cc.em", NULL); tom::element_wise_add<TFLOAT, TFLOAT>(avg, avg2); tom::element_wise_add<TFLOAT, TFLOAT>(avgwedge_half, avgwedge2_half); if (!v3.empty()) { // Add the missing partivle to the average. tom::avg::average(c.volsize, fparticles, wedge_particles, v3, itemplate, mask_sphere.get(), peak_list, anglesv, c.force_files_exist, &clog, avg2, avgwedge2_half); tom::element_wise_add<TFLOAT, TFLOAT>(avg, avg2); tom::element_wise_add<TFLOAT, TFLOAT>(avgwedge_half, avgwedge2_half); } } else { tom::avg::average(c.volsize, fparticles, wedge_particles, v_, itemplate, mask_sphere.get(), peak_list, anglesv, c.force_files_exist, &clog, avg, avgwedge_half); } //////////////////////////////////////////////////////////////////////// // Save the average volume (the pure sum): avg_s avg.write_to_em(f_gen.get_avg_s(itemplate), NULL); tom::hermitian_symmetry_to_full(avgwedge); tom::fftshift(avgwedge, avgwedge2, true); avgwedge2.write_to_em(f_gen.get_avgwedge_s(itemplate), NULL); if (vtemplate.get()) { // Compute the correlation with the original template. avg.stat(mean, variance, false); if (variance) { avg2.setValues(avg); // make a copy for normalising. avg2.shift_scale<TFLOAT>(-mean, 1./sqrt(variance)); plan_fwd.execute(avg2, avg_ft); tom::element_wise_conj_multiply<std::complex<TFLOAT>, std::complex<TFLOAT> >(avg_ft, vtemplate_ft); plan_bwd.execute(avg_ft, avg2); ar.ccval_s.reset(new double((avg2.get(0,0,0)/avg2.numel())/avg2.numel())); } } //////////////////////////////////////////////////////////////////////// // Set values below threshold in volume to 0 tom::element_wise_set_below_threshold<TFLOAT>(avgwedge_half, threshold, 0); tom::hermitian_symmetry_to_full(avgwedge); avg2.setValues(avg); plan_fwd.execute(avg2, avg_ft); avg_ft2.setValues(avg_ft); //////////////////////////////////////////////////////////////////////// // Compute the average with frequencies weighted by N set_where_binary_mask_not_set<std::complex<TFLOAT>, TFLOAT>(avg_ft, avgwedge_half, 0); avg_ft.get(0,0,0) = 0; plan_bwd.execute(avg_ft, avg2); if (mask_sphere.get()) { tom::norm_mask<TFLOAT, TFLOAT, double>(avg2, *mask_sphere, tom::norm::NORM_STDDEV_1, NULL, true); } else { if ((variance=avg2.variance_mean_free(false))) { avg2.shift_scale<TFLOAT>(0, 1./sqrt(variance)); } } avg2.write_to_em(f_gen.get_avg_n(itemplate), NULL); tom::fftshift(avgwedge, avgwedge2, true); avgwedge2.write_to_em(f_gen.get_avgwedge_n(itemplate), NULL); if (vtemplate.get()) { // Compute the correlation with the original template. avg2.stat(mean, variance, false); if (variance) { avg2.shift_scale<TFLOAT>(-mean, 1./sqrt(variance)); plan_fwd.execute(avg2, avg_ft); tom::element_wise_conj_multiply<std::complex<TFLOAT>, std::complex<TFLOAT> >(avg_ft, vtemplate_ft); plan_bwd.execute(avg_ft, avg2); ar.ccval_n.reset(new double((avg2.get(0,0,0)/avg2.numel())/avg2.numel())); } } //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// // Compute the average with frequencies weighted by sqrt(N) avgwedge_sqrtn_half.setValues(avgwedge_half); tom::element_wise_operation(avgwedge_sqrtn_half, &tom::math::sqrt<TFLOAT>); avg_ft.setValues(avg_ft2); tom::element_wise_div<std::complex<TFLOAT>, TFLOAT>(avg_ft, avgwedge_sqrtn_half, std::complex<TFLOAT>(0,0)); avg_ft.get(0,0,0) = 0; plan_bwd.execute(avg_ft, avg2); if (mask_sphere.get()) { tom::norm_mask<TFLOAT, TFLOAT, double>(avg2, *mask_sphere, tom::norm::NORM_STDDEV_1, NULL, true); } else { if ((variance=avg2.variance_mean_free(false))) { avg2.shift_scale<TFLOAT>(0, 1./sqrt(variance)); } } avg2.write_to_em(f_gen.get_avg_sqrtn(itemplate), NULL); tom::hermitian_symmetry_to_full(avgwedge_sqrtn); tom::fftshift(avgwedge_sqrtn, avgwedge2, true); avgwedge2.write_to_em(f_gen.get_avgwedge_sqrtn(itemplate), NULL); if (vtemplate.get()) { // Compute the correlation with the original template. avg2.stat(mean, variance, false); if (variance) { avg2.shift_scale<TFLOAT>(-mean, 1./sqrt(variance)); plan_fwd.execute(avg2, avg_ft); tom::element_wise_conj_multiply<std::complex<TFLOAT>, std::complex<TFLOAT> >(avg_ft, vtemplate_ft); plan_bwd.execute(avg_ft, avg2); ar.ccval_sqrtn.reset(new double((avg2.get(0,0,0)/avg2.numel())/avg2.numel())); } } //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// // Compute the average with frequencies weighted by 1 avgwedge2_half.setValues(avgwedge_half); avg_ft.setValues(avg_ft2); tom::element_wise_div<std::complex<TFLOAT>, TFLOAT>(avg_ft, avgwedge2_half, std::complex<TFLOAT>(0,0)); avg_ft.get(0,0,0) = 0; plan_bwd.execute(avg_ft, avg2); if (mask_sphere.get()) { tom::norm_mask<TFLOAT, TFLOAT, double>(avg2, *mask_sphere, tom::norm::NORM_STDDEV_1, NULL, true); } else { if ((variance=avg2.variance_mean_free(false))) { avg2.shift_scale<TFLOAT>(0, 1./sqrt(variance)); } } avg2.write_to_em(f_gen.get_avg_1(itemplate), NULL); tom::make_binary(avgwedge2); tom::hermitian_symmetry_to_full(avgwedge2); tom::fftshift(avgwedge2, avgwedge, true); avgwedge.write_to_em(f_gen.get_avgwedge_1(itemplate), NULL); if (vtemplate.get()) { // Compute the correlation with the original template. avg2.stat(mean, variance, false); if (variance) { avg2.shift_scale<TFLOAT>(-mean, 1./sqrt(variance)); plan_fwd.execute(avg2, avg_ft); tom::element_wise_conj_multiply<std::complex<TFLOAT>, std::complex<TFLOAT> >(avg_ft, vtemplate_ft); plan_bwd.execute(avg_ft, avg2); ar.ccval_1.reset(new double((avg2.get(0,0,0)/avg2.numel())/avg2.numel())); } } //////////////////////////////////////////////////////////////////////// } tom::avg::write_average_to_log(clog, ftemplates, fparticles, av, c.outputdir); clog << "# finished at " << helper::now2str() << std::endl; return 0; }