Vector_double stfnum::get_scale(Vector_double& data, double oldx) { Vector_double xyscale(4); if (data.size() == 0) { xyscale[0] = 1.0/oldx; xyscale[1] = 0.0; xyscale[2] = 1.0; xyscale[3] = 0.0; return xyscale; } double ymin,ymax,amp,off; ymin = *data.begin(); ymax = ymin; for (Vector_double::iterator it = data.begin(); it != data.end(); ++it) { double v = *it; if (v < ymin) ymin = v; else if (ymax < v) ymax = v; } amp = ymax - ymin; off = ymin / amp; data = stfio::vec_scal_mul(data, 1.0 / amp); data = stfio::vec_scal_minus(data, off); xyscale[0] = 1.0/(data.size()*oldx); xyscale[1] = 0; xyscale[2] = 1.0/amp; xyscale[3] = off; return xyscale; }
std::map<double, int> stf::histogram(const Vector_double& data, int nbins) { if (nbins==-1) { nbins = int(data.size()/100.0); } double fmax = *std::max_element(data.begin(), data.end()); double fmin = *std::min_element(data.begin(), data.end()); fmax += (fmax-fmin)*1e-9; double bin = (fmax-fmin)/nbins; std::map<double,int> histo; for (int nbin=0; fmin + nbin*bin < fmax; ++nbin) { histo[fmin + nbin*bin] = 0; } for (std::size_t npoint=0; npoint < data.size(); ++npoint) { int nbin = int((data[npoint]-fmin) / bin); histo[fmin + nbin*bin]++; } return histo; }
Vector_double stf::deconvolve(const Vector_double& data, const Vector_double& templ, int SR, double hipass, double lopass, stfio::ProgressInfo& progDlg) { bool skipped = false; progDlg.Update( 0, "Starting deconvolution...", &skipped ); if (data.size()<=0 || templ.size() <=0 || templ.size() > data.size()) { std::out_of_range e("subscript out of range in stf::filter()"); throw e; } /* pad templ */ Vector_double templ_padded(data.size()); std::copy(templ.begin(), templ.end(), templ_padded.begin()); if (templ.size() < templ_padded.size()) { std::fill(templ_padded.begin()+templ.size(), templ_padded.end(), 0); } Vector_double data_return(data.size()); if (skipped) { data_return.resize(0); return data_return; } double *in_data, *in_templ_padded; //fftw_complex is a double[2]; hence, out is an array of //double[2] with out[n][0] being the real and out[n][1] being //the imaginary part. fftw_complex *out_data, *out_templ_padded; fftw_plan p_data, p_templ, p_inv; //memory allocation as suggested by fftw: in_data =(double *)fftw_malloc(sizeof(double) * data.size()); out_data = (fftw_complex *)fftw_malloc(sizeof(fftw_complex) * ((int)(data.size()/2)+1)); in_templ_padded =(double *)fftw_malloc(sizeof(double) * templ_padded.size()); out_templ_padded = (fftw_complex *)fftw_malloc(sizeof(fftw_complex) * ((int)(templ_padded.size()/2)+1)); std::copy(data.begin(), data.end(), &in_data[0]); std::copy(templ_padded.begin(), templ_padded.end(), &in_templ_padded[0]); //plan the ffts and execute them: p_data =fftw_plan_dft_r2c_1d((int)data.size(), in_data, out_data, FFTW_ESTIMATE); fftw_execute(p_data); p_templ =fftw_plan_dft_r2c_1d((int)templ_padded.size(), in_templ_padded, out_templ_padded, FFTW_ESTIMATE); fftw_execute(p_templ); double SI=1.0/SR; //the sampling interval progDlg.Update( 25, "Performing deconvolution...", &skipped ); if (skipped) { data_return.resize(0); return data_return; } Vector_double f_c(1); for (std::size_t n_point=0; n_point < (unsigned int)(data.size()/2)+1; ++n_point) { /* highpass filter */ double f = n_point / (data.size()*SI); double rslt_hi = 1.0; if (hipass > 0) { f_c[0] = hipass; rslt_hi = 1.0-fgaussColqu(f, f_c); } /* lowpass filter */ double rslt_lo = 1.0; if (lopass > 0) { f_c[0] = lopass; rslt_lo= fgaussColqu(f, f_c); } /* do the division in place */ double a = out_data[n_point][0]; double b = out_data[n_point][1]; double c = out_templ_padded[n_point][0]; double d = out_templ_padded[n_point][1]; double mag2 = c*c + d*d; out_data[n_point][0] = rslt_hi * rslt_lo * (a*c + b*d)/mag2; out_data[n_point][1] = rslt_hi * rslt_lo * (b*c - a*d)/mag2; } //do the reverse fft: p_inv = fftw_plan_dft_c2r_1d((int)data.size(),out_data, in_data, FFTW_ESTIMATE); fftw_execute(p_inv); //fill the return array, adding the offset, and scaling by data.size() //(because fftw computes an unnormalized transform): for (std::size_t n_point=0; n_point < data.size(); ++n_point) { data_return[n_point]= in_data[n_point]/data.size(); } fftw_destroy_plan(p_data); fftw_destroy_plan(p_templ); fftw_destroy_plan(p_inv); fftw_free(in_data); fftw_free(out_data); fftw_free(in_templ_padded); fftw_free(out_templ_padded); progDlg.Update( 50, "Computing data histogram...", &skipped ); if (skipped) { data_return.resize(0); return data_return; } int nbins = int(data_return.size()/500.0); std::map<double, int> histo = histogram(data_return, nbins); double max_value = -1; double max_time = 0; double maxhalf_time = 0; Vector_double histo_fit(0); for (std::map<double,int>::const_iterator it=histo.begin(); it != histo.end(); ++it) { if (it->second > max_value) { max_value = it->second; max_time = it->first; } histo_fit.push_back(it->second); #ifdef _STFDEBUG std::cout << it->first << "\t" << it->second << std::endl; #endif } for (std::map<double,int>::const_iterator it=histo.begin(); it != histo.end(); ++it) { if (it->second > 0.5*max_value) { maxhalf_time = it->first; break; } } maxhalf_time = fabs(max_time-maxhalf_time); progDlg.Update( 75, "Fitting Gaussian...", &skipped ); if (skipped) { data_return.resize(0); return data_return; } /* Fit Gaussian to histogram */ Vector_double opts = LM_default_opts(); std::string info; int warning; std::vector< stf::storedFunc > funcLib = stf::GetFuncLib(); double interval = (++histo.begin())->first-histo.begin()->first; /* Initial parameter guesses */ Vector_double pars(3); pars[0] = max_value; pars[1] = (max_time - histo.begin()->first); pars[2] = maxhalf_time *sqrt(2.0)/2.35482; #ifdef _STFDEBUG std::cout << "nbins: " << nbins << std::endl; std::cout << "initial values:" << std::endl; for (std::size_t np=0; np<pars.size(); ++np) { std::cout << pars[np] << std::endl; } #endif #ifdef _STFDEBUG double chisqr = #endif lmFit(histo_fit, interval, funcLib[funcLib.size()-1], opts, true, pars, info, warning ); #ifdef _STFDEBUG std::cout << chisqr << "\t" << interval << std::endl; std::cout << "final values:" << std::endl; for (std::size_t np=0; np<pars.size(); ++np) { std::cout << pars[np] << std::endl; } #endif double sigma = pars[2]/sqrt(2.0); /* return data in terms of sigma */ for (std::size_t n_point=0; n_point < data.size(); ++n_point) { data_return[n_point] /= sigma; } progDlg.Update( 100, "Done.", &skipped ); return data_return; }
Vector_double stfio::vec_vec_div(const Vector_double& vec1, const Vector_double& vec2) { Vector_double ret_vec(vec1.size()); std::transform(vec1.begin(), vec1.end(), vec2.begin(), ret_vec.begin(), std::divides<double>()); return ret_vec; }
Vector_double stfio::vec_scal_div(const Vector_double& vec, double scalar) { Vector_double ret_vec(vec.size(), scalar); std::transform(vec.begin(), vec.end(), ret_vec.begin(), ret_vec.begin(), std::divides<double>()); return ret_vec; }