/** Rebunches histogram data data according to n_bunch input * * @param xold :: old x data * @param yold :: old y data * @param eold :: old e data * @param xnew :: new x data * @param ynew :: new y data * @param enew :: new e data * @param n_bunch :: number of data points to bunch together for each new point * @throw runtime_error Thrown if algorithm cannot execute * @throw invalid_argument Thrown if input to function is incorrect **/ void Rebunch::rebunch_hist_frequencies(const HistogramX &xold, const HistogramY &yold, const HistogramE &eold, HistogramX &xnew, HistogramY &ynew, HistogramE &enew, const size_t n_bunch) { double width; size_t size_x = xold.size(); size_t size_y = yold.size(); double ysum, esum; size_t hi_index = size_x - 1; size_t wbins = size_y / n_bunch; size_t rem = size_y % n_bunch; size_t i, j; int i_in = 0; j = 0; while (j < wbins) { ysum = 0.0; esum = 0.0; for (i = 1; i <= n_bunch; i++) { width = xold[i_in + 1] - xold[i_in]; ysum += yold[i_in] * width; esum += eold[i_in] * eold[i_in] * width * width; i_in++; } // average contributing x values ynew[j] = ysum; enew[j] = sqrt(esum); j++; } if (rem != 0) { ysum = 0.0; esum = 0.0; for (i = 1; i <= rem; i++) { width = xold[i_in + 1] - xold[i_in]; ysum += yold[i_in] * width; esum += eold[i_in] * eold[i_in] * width * width; i_in++; } ynew[j] = ysum; enew[j] = sqrt(esum); } j = 0; xnew[j] = xold[0]; j++; for (i = n_bunch; i < hi_index; i += n_bunch) { xnew[j] = xold[i]; j++; } xnew[j] = xold[hi_index]; for (i = 0; i < ynew.size(); i++) { width = xnew[i + 1] - xnew[i]; ynew[i] = ynew[i] / width; enew[i] = enew[i] / width; } }
void CalculateCarpenterSampleCorrection::calculate_ms_correction( const double angle_deg, const double radius, const double coeff1, const double coeff2, const double coeff3, const Points &wavelength, HistogramY &y_val) { const size_t NUM_Y = y_val.size(); bool is_histogram = false; if (wavelength.size() == NUM_Y + 1) is_histogram = true; else if (wavelength.size() == NUM_Y) is_histogram = false; else throw std::runtime_error("Data is neither historgram or density"); // initialize Z array for this angle vector<double> Z = createZ(angle_deg); const double Q2 = coeff1 * coeff2; const double sigsct = coeff2 * coeff3; for (size_t j = 0; j < NUM_Y; j++) { double wl_val = wavelength[j]; if (is_histogram) // average with next value wl_val = .5 * (wl_val + wavelength[j + 1]); y_val[j] = calculate_ms_factor(radius, Q2, sigsct, Z, wl_val); } }
/** Rebunches point data data according to n_bunch input * * @param xold :: old x data * @param yold :: old y data * @param eold :: old e data * @param xnew :: new x data * @param ynew :: new y data * @param enew :: new e data * @param n_bunch :: number of data points to bunch together for each new point * @throw runtime_error Thrown if algorithm cannot execute * @throw invalid_argument Thrown if input to function is incorrect **/ void Rebunch::rebunch_point(const HistogramX &xold, const HistogramY &yold, const HistogramE &eold, HistogramX &xnew, HistogramY &ynew, HistogramE &enew, const size_t n_bunch) { size_t size_y = yold.size(); double xsum, ysum, esum; size_t wbins = size_y / n_bunch; size_t rem = size_y % n_bunch; size_t i, j; int i_in = 0; j = 0; while (j < wbins) { xsum = 0.0; ysum = 0.0; esum = 0.0; for (i = 1; i <= n_bunch; i++) { xsum += xold[i_in]; ysum += yold[i_in]; esum += eold[i_in] * eold[i_in]; i_in++; } // average contributing x values xnew[j] = xsum / static_cast<double>(n_bunch); ynew[j] = ysum / static_cast<double>(n_bunch); enew[j] = sqrt(esum) / static_cast<double>(n_bunch); j++; } if (rem != 0) { xsum = 0.0; ysum = 0.0; esum = 0.0; for (i = 1; i <= rem; i++) { xsum += xold[i_in]; ysum += yold[i_in]; esum += eold[i_in] * eold[i_in]; i_in++; } xnew[j] = xsum / static_cast<double>(rem); ynew[j] = ysum / static_cast<double>(rem); enew[j] = sqrt(esum) / static_cast<double>(rem); } }
/** A Fourier transform of a derivative of order `n` has a factor of `i^n` where * `i` is the imaginary unit. This code multiplies the Fourier transform of the * input function `(re[j], im[j])` by `(2*pi*nu)^n` without using * `std::complex`. * @param nu :: complete real X of input histogram * @param &re :: complete real Y of input histogram * @param &im :: complete imaginary Y of input histogram */ void FFTDerivative::multiplyTransform(HistogramX &nu, HistogramY &re, HistogramY &im) { int dn = getProperty("Order"); bool swap_re_im = dn % 2 != 0; int sign_re = 1; int sign_im = -1; switch (dn % 4) { case 1: sign_re = 1; sign_im = -1; break; case 2: sign_re = -1; sign_im = -1; break; case 3: sign_re = -1; sign_im = 1; break; } // Multiply the transform by (2*pi*i*w)**dn for (size_t j = 0; j < re.size(); ++j) { double w = 2 * M_PI * nu[j]; double ww = w; for (int k = dn; k > 1; --k) { ww *= w; } double a = sign_re * re[j] * ww; double b = sign_im * im[j] * ww; if (swap_re_im) { re[j] = b; im[j] = a; } else { re[j] = a; im[j] = b; } } }