예제 #1
0
/** loadData
*  Load the counts data from an NXInt into a workspace
*/
void LoadMuonNexus2::loadData(const Mantid::NeXus::NXInt &counts,
                              const std::vector<double> &timeBins, int wsIndex,
                              int period, int spec,
                              API::MatrixWorkspace_sptr localWorkspace) {
  MantidVec &X = localWorkspace->dataX(wsIndex);
  MantidVec &Y = localWorkspace->dataY(wsIndex);
  MantidVec &E = localWorkspace->dataE(wsIndex);
  X.assign(timeBins.begin(), timeBins.end());

  int nBins = 0;
  int *data = nullptr;

  if (counts.rank() == 3) {
    nBins = counts.dim2();
    data = &counts(period, spec, 0);
  } else if (counts.rank() == 2) {
    nBins = counts.dim1();
    data = &counts(spec, 0);
  } else {
    throw std::runtime_error("Data have unsupported dimansionality");
  }
  assert(nBins + 1 == static_cast<int>(timeBins.size()));

  Y.assign(data, data + nBins);
  typedef double (*uf)(double);
  uf dblSqrt = std::sqrt;
  std::transform(Y.begin(), Y.end(), E.begin(), dblSqrt);
}
예제 #2
0
void RadiusSum::setUpOutputWorkspace(std::vector<double> &values) {

  g_log.debug() << "Output calculated, setting up the output workspace\n";

  API::MatrixWorkspace_sptr outputWS = API::WorkspaceFactory::Instance().create(
      inputWS, 1, values.size() + 1, values.size());

  g_log.debug() << "Set the data\n";
  MantidVec &refY = outputWS->dataY(0);
  std::copy(values.begin(), values.end(), refY.begin());

  g_log.debug() << "Set the bins limits\n";
  MantidVec &refX = outputWS->dataX(0);
  double bin_size = (max_radius - min_radius) / num_bins;

  for (int i = 0; i < (static_cast<int>(refX.size())) - 1; i++)
    refX[i] = min_radius + i * bin_size;
  refX.back() = max_radius;

  // configure the axis:
  // for numeric images, the axis are the same as the input workspace, and are
  // copied in the creation.

  // for instrument related, the axis Y (1) continues to be the same.
  // it is necessary to change only the axis X. We have to change it to radius.
  if (inputWorkspaceHasInstrumentAssociated(inputWS)) {
    API::Axis *const horizontal = new API::NumericAxis(refX.size());
    auto labelX = UnitFactory::Instance().create("Label");
    boost::dynamic_pointer_cast<Units::Label>(labelX)->setLabel("Radius");
    horizontal->unit() = labelX;
    outputWS->replaceAxis(0, horizontal);
  }

  setProperty("OutputWorkspace", outputWS);
}
예제 #3
0
/**
 * Perform a call to nxgetslab, via the NexusClasses wrapped methods for a given blocksize. The xbins are read along with
 * each call to the data/error loading
 * @param data :: The NXDataSet object of y values
 * @param errors :: The NXDataSet object of error values
 * @param xbins :: The xbin NXDataSet
 * @param blocksize :: The blocksize to use
 * @param nchannels :: The number of channels for the block
 * @param hist :: The workspace index to start reading into
 * @param wsIndex :: The workspace index to save data into
 * @param local_workspace :: A pointer to the workspace
 */
void LoadNexusProcessed::loadBlock(NXDataSetTyped<double> & data, NXDataSetTyped<double> & errors, NXDouble & xbins,
    int64_t blocksize, int64_t nchannels, int64_t &hist, int64_t& wsIndex,
    API::MatrixWorkspace_sptr local_workspace)
{
  data.load(static_cast<int>(blocksize),static_cast<int>(hist));
  double *data_start = data();
  double *data_end = data_start + nchannels;
  errors.load(static_cast<int>(blocksize),static_cast<int>(hist));
  double *err_start = errors();
  double *err_end = err_start + nchannels;
  xbins.load(static_cast<int>(blocksize),static_cast<int>(hist));
  const int64_t nxbins(nchannels + 1);
  double *xbin_start = xbins();
  double *xbin_end = xbin_start + nxbins;
  int64_t final(hist + blocksize);
  while( hist < final )
  {
    MantidVec& Y = local_workspace->dataY(wsIndex);
    Y.assign(data_start, data_end);
    data_start += nchannels; data_end += nchannels;
    MantidVec& E = local_workspace->dataE(wsIndex);
    E.assign(err_start, err_end);
    err_start += nchannels; err_end += nchannels;
    MantidVec& X = local_workspace->dataX(wsIndex);
    X.assign(xbin_start, xbin_end);
    xbin_start += nxbins; xbin_end += nxbins;
    ++hist;
    ++wsIndex;
  }
}
예제 #4
0
/** Smoothing using Butterworth filter.
 *  @param n ::     The cutoff frequency control parameter.
 *               Cutoff frequency = my/n where my is the
 *               number of sample points in the data.
 *               As with the "Zeroing" case, the cutoff
 *               frequency is truncated to an integer value
 *               and set to 1 if the truncated value was zero.
 *  @param order :: The order of the Butterworth filter, 1, 2, etc.
 *               This must be a positive integer.
 *  @param unfilteredWS :: workspace for storing the unfiltered Fourier
 * transform of the input spectrum
 *  @param filteredWS :: workspace for storing the filtered spectrum
 */
void FFTSmooth2::Butterworth(int n, int order,
                             API::MatrixWorkspace_sptr &unfilteredWS,
                             API::MatrixWorkspace_sptr &filteredWS) {
  int mx = static_cast<int>(unfilteredWS->readX(0).size());
  int my = static_cast<int>(unfilteredWS->readY(0).size());
  int ny = my / n;

  if (ny == 0)
    ny = 1;

  filteredWS =
      API::WorkspaceFactory::Instance().create(unfilteredWS, 2, mx, my);

  const Mantid::MantidVec &Yr = unfilteredWS->readY(0);
  const Mantid::MantidVec &Yi = unfilteredWS->readY(1);
  const Mantid::MantidVec &X = unfilteredWS->readX(0);

  Mantid::MantidVec &yr = filteredWS->dataY(0);
  Mantid::MantidVec &yi = filteredWS->dataY(1);
  Mantid::MantidVec &xr = filteredWS->dataX(0);
  Mantid::MantidVec &xi = filteredWS->dataX(1);

  xr.assign(X.begin(), X.end());
  xi.assign(X.begin(), X.end());
  yr.assign(Yr.size(), 0);
  yi.assign(Yr.size(), 0);

  double cutoff = ny;

  for (int i = 0; i < my; i++) {
    double scale = 1.0 / (1.0 + pow(i / cutoff, 2 * order));
    yr[i] = scale * Yr[i];
    yi[i] = scale * Yi[i];
  }
}
예제 #5
0
/** Smoothing by zeroing.
 *  @param n :: The order of truncation
 *  @param unfilteredWS :: workspace for storing the unfiltered Fourier
 * transform of the input spectrum
 *  @param filteredWS :: workspace for storing the filtered spectrum
 */
void FFTSmooth2::zero(int n, API::MatrixWorkspace_sptr &unfilteredWS,
                      API::MatrixWorkspace_sptr &filteredWS) {
  int mx = static_cast<int>(unfilteredWS->readX(0).size());
  int my = static_cast<int>(unfilteredWS->readY(0).size());
  int ny = my / n;

  if (ny == 0)
    ny = 1;

  filteredWS =
      API::WorkspaceFactory::Instance().create(unfilteredWS, 2, mx, my);

  const Mantid::MantidVec &Yr = unfilteredWS->readY(0);
  const Mantid::MantidVec &Yi = unfilteredWS->readY(1);
  const Mantid::MantidVec &X = unfilteredWS->readX(0);

  Mantid::MantidVec &yr = filteredWS->dataY(0);
  Mantid::MantidVec &yi = filteredWS->dataY(1);
  Mantid::MantidVec &xr = filteredWS->dataX(0);
  Mantid::MantidVec &xi = filteredWS->dataX(1);

  xr.assign(X.begin(), X.end());
  xi.assign(X.begin(), X.end());
  yr.assign(Yr.size(), 0);
  yi.assign(Yr.size(), 0);

  for (int i = 0; i < ny; i++) {
    yr[i] = Yr[i];
    yi[i] = Yi[i];
  }
}
예제 #6
0
/** Execute the algorithm.
 */
void DampSq::exec()
{
    // TODO Auto-generated execute stub

    // 1. Generate new workspace
    API::MatrixWorkspace_const_sptr isqspace = getProperty("InputWorkspace");
    API::MatrixWorkspace_sptr osqspace = WorkspaceFactory::Instance().create(isqspace, 1, isqspace->size(), isqspace->size());

    int mode = getProperty("Mode");
    double qmax = getProperty("QMax");

    if (mode < 1 || mode > 4) {
        g_log.error("Damp mode can only be 1, 2, 3, or 4");
        return;
    }

    // 2. Get access to all
    const MantidVec& iQVec = isqspace->dataX(0);
    const MantidVec& iSVec = isqspace->dataY(0);
    const MantidVec& iEVec = isqspace->dataE(0);

    MantidVec& oQVec = osqspace->dataX(0);
    MantidVec& oSVec = osqspace->dataY(0);
    MantidVec& oEVec = osqspace->dataE(0);

    // 3. Calculation
    double dqmax = qmax - iQVec[0];

    double damp;
    for (unsigned int i = 0; i < iQVec.size(); i ++) {
        // a) calculate damp coefficient
        switch (mode) {
        case 1:
            damp = dampcoeff1(iQVec[i], qmax, dqmax);
            break;
        case 2:
            damp = dampcoeff2(iQVec[i], qmax, dqmax);;
            break;
        case 3:
            damp = dampcoeff3(iQVec[i], qmax, dqmax);;
            break;
        case 4:
            damp = dampcoeff4(iQVec[i], qmax, dqmax);;
            break;
        default:
            damp = 0;
            break;
        }
        // b) calculate new S(q)
        oQVec[i] = iQVec[i];
        oSVec[i] = 1 + damp*(iSVec[i]-1);
        oEVec[i] = damp*iEVec[i];
    }  // i

    // 4. Over
    setProperty("OutputWorkspace", osqspace);

    return;
}
예제 #7
0
/** Performs the Holtzer transformation: IQ v Q
 *  @param ws The workspace to be transformed
 */
void IQTransform::holtzer(API::MatrixWorkspace_sptr ws)
{
  MantidVec& X = ws->dataX(0);
  MantidVec& Y = ws->dataY(0);
  MantidVec& E = ws->dataE(0);
  std::transform(Y.begin(),Y.end(),X.begin(),Y.begin(),std::multiplies<double>());
  std::transform(E.begin(),E.end(),X.begin(),E.begin(),std::multiplies<double>());

  ws->setYUnitLabel("I x Q");
}
예제 #8
0
/** Performs the Porod transformation: IQ^4 v Q
 *  @param ws The workspace to be transformed
 */
void IQTransform::porod(API::MatrixWorkspace_sptr ws)
{
  MantidVec& X = ws->dataX(0);
  MantidVec& Y = ws->dataY(0);
  MantidVec& E = ws->dataE(0);
  MantidVec Q4(X.size());
  std::transform(X.begin(),X.end(),X.begin(),Q4.begin(),VectorHelper::TimesSquares<double>());
  std::transform(Y.begin(),Y.end(),Q4.begin(),Y.begin(),std::multiplies<double>());
  std::transform(E.begin(),E.end(),Q4.begin(),E.begin(),std::multiplies<double>());

  ws->setYUnitLabel("I x Q^4");
}
예제 #9
0
/** Performs a log-log transformation: Ln(I) v Ln(Q)
 *  @param ws The workspace to be transformed
 *  @throw std::range_error if an attempt is made to take log of a negative number
 */
void IQTransform::logLog(API::MatrixWorkspace_sptr ws)
{
  MantidVec& X = ws->dataX(0);
  MantidVec& Y = ws->dataY(0);
  MantidVec& E = ws->dataE(0);
  std::transform(X.begin(),X.end(),X.begin(),VectorHelper::Log<double>());
  std::transform(E.begin(),E.end(),Y.begin(),E.begin(),std::divides<double>());
  std::transform(Y.begin(),Y.end(),Y.begin(),VectorHelper::LogNoThrow<double>());

  ws->setYUnitLabel("Ln(I)");
  m_label->setLabel("Ln(Q)");
}
예제 #10
0
/** Performs the Guinier (sheets) transformation: Ln(IQ^2) v Q^2
 *  @param ws The workspace to be transformed
 *  @throw std::range_error if an attempt is made to take log of a negative number
 */
void IQTransform::guinierSheets(API::MatrixWorkspace_sptr ws)
{
  MantidVec& X = ws->dataX(0);
  MantidVec& Y = ws->dataY(0);
  MantidVec& E = ws->dataE(0);
  std::transform(E.begin(),E.end(),Y.begin(),E.begin(),std::divides<double>());
  std::transform(X.begin(),X.end(),X.begin(),VectorHelper::Squares<double>());
  std::transform(Y.begin(),Y.end(),X.begin(),Y.begin(),std::multiplies<double>());
  std::transform(Y.begin(),Y.end(),Y.begin(),VectorHelper::LogNoThrow<double>());

  ws->setYUnitLabel("Ln(I x Q^2)");
  m_label->setLabel("Q^2");
}
예제 #11
0
/** Convert the workspace units according to a simple output = a * (input^b) relationship
 *  @param outputWS :: the output workspace
 *  @param factor :: the conversion factor a to apply
 *  @param power :: the Power b to apply to the conversion
 */
void ConvertUnits::convertQuickly(API::MatrixWorkspace_sptr outputWS, const double& factor, const double& power)
{
  Progress prog(this,0.2,1.0,m_numberOfSpectra);
  int64_t numberOfSpectra_i = static_cast<int64_t>(m_numberOfSpectra); // cast to make openmp happy

  // See if the workspace has common bins - if so the X vector can be common
  // First a quick check using the validator
  CommonBinsValidator sameBins;
  bool commonBoundaries = false;
  if ( sameBins.isValid(outputWS) == "" )
  {
    commonBoundaries =  WorkspaceHelpers::commonBoundaries(outputWS);
    // Only do the full check if the quick one passes
    if (commonBoundaries)
    {
      // Calculate the new (common) X values
      MantidVec::iterator iter;
      for (iter = outputWS->dataX(0).begin(); iter != outputWS->dataX(0).end(); ++iter)
      {
        *iter = factor * std::pow(*iter,power);
      }

      MantidVecPtr xVals;
      xVals.access() = outputWS->dataX(0);

      PARALLEL_FOR1(outputWS)
      for (int64_t j = 1; j < numberOfSpectra_i; ++j)
      {
        PARALLEL_START_INTERUPT_REGION
        outputWS->setX(j,xVals);
        prog.report("Convert to " + m_outputUnit->unitID());
        PARALLEL_END_INTERUPT_REGION
      }
      PARALLEL_CHECK_INTERUPT_REGION
      if (!m_inputEvents) // if in event mode the work is done
        return;
    }
  }
예제 #12
0
/** Performs a transformation of the form: Q^A x I^B x Ln(Q^C x I^D x E) v Q^F x
 * I^G x Ln(Q^H x I^I x J).
 *  Uses the 'GeneralFunctionConstants' property where A-J are the 10 (ordered)
 * input constants.
 *  @param ws The workspace to be transformed
 *  @throw std::range_error if an attempt is made to take log of a negative
 * number
 */
void IQTransform::general(API::MatrixWorkspace_sptr ws) {
  MantidVec &X = ws->dataX(0);
  MantidVec &Y = ws->dataY(0);
  MantidVec &E = ws->dataE(0);
  const std::vector<double> C = getProperty("GeneralFunctionConstants");
  // Check for the correct number of elements
  if (C.size() != 10) {
    std::string mess(
        "The General transformation requires 10 values to be provided.");
    g_log.error(mess);
    throw std::invalid_argument(mess);
  }

  for (size_t i = 0; i < Y.size(); ++i) {
    double tmpX = std::pow(X[i], C[7]) * std::pow(Y[i], C[8]) * C[9];
    if (tmpX <= 0.0)
      throw std::range_error(
          "Attempt to take log of a zero or negative number.");
    tmpX = std::pow(X[i], C[5]) * std::pow(Y[i], C[6]) * std::log(tmpX);
    const double tmpY = std::pow(X[i], C[2]) * std::pow(Y[i], C[3]) * C[4];
    if (tmpY <= 0.0)
      throw std::range_error(
          "Attempt to take log of a zero or negative number.");
    const double newY =
        std::pow(X[i], C[0]) * std::pow(Y[i], C[1]) * std::log(tmpY);

    E[i] *= std::pow(X[i], C[0]) *
            (C[1] * std::pow(Y[i], C[1] - 1) * std::log(tmpY) +
             ((std::pow(Y[i], C[1]) * std::pow(X[i], C[2]) * C[4] * C[3] *
               std::pow(Y[i], C[3] - 1)) /
              tmpY));
    X[i] = tmpX;
    Y[i] = newY;
  }

  std::stringstream ylabel;
  ylabel << "Q^" << C[0] << " x I^" << C[1] << " x Ln( Q^" << C[2] << " x I^"
         << C[3] << " x " << C[4] << ")";
  ws->setYUnitLabel(ylabel.str());
  std::stringstream xlabel;
  xlabel << "Q^" << C[5] << " x I^" << C[6] << " x Ln( Q^" << C[7] << " x I^"
         << C[8] << " x " << C[9] << ")";
  m_label->setLabel(xlabel.str());
}
예제 #13
0
/**
 * Here is the main logic to perform the transformation, to calculate the bin
 *position in degree for each spectrum.
 *
 * The first part of the method is to check if the pixel position is inside the
 *ring defined as minRadio and maxRadio.
 *
 * To do this, it deducts the pixel position. This deduction follows the
 *followin assumption:
 *
 *  - the spectrum_index == row number
 *  - the position in the 'Y' direction is given by getAxis(1)[spectrum_index]
 *  - the position in the 'X' direction is the central point of the bin
 *(dataX[column] + dataX[column+1])/2
 *
 * Having the position of the pixel, as defined above, if the distance is
 *outside the ring defined by minRadio, maxRadio,
 * it defines the bin position as -1.
 *
 * If the pixel is inside the ring, it calculates the angle of the pixel and
 *calls fromAngleToBin to define the bin
 * position.
 * @param ws: pointer to the workspace
 * @param spectrum_index: index of the spectrum
 * @param bins_pos: bin positions (for each column inside the spectrum, the
 *correspondent bin_pos)
 */
void RingProfile::getBinForPixel(const API::MatrixWorkspace_sptr ws,
                                 int spectrum_index,
                                 std::vector<int> &bins_pos) {

  if (bins_pos.size() != ws->dataY(spectrum_index).size())
    throw std::runtime_error("Invalid bin positions vector");

  API::NumericAxis *oldAxis2 = dynamic_cast<API::NumericAxis *>(ws->getAxis(1));
  // assumption y position is the ws->getAxis(1)(spectrum_index)
  if (!oldAxis2) {
    throw std::logic_error("Failed to cast workspace axis to NumericAxis");
  }

  // calculate ypos, the difference of y - centre and  the square of this
  // difference
  double ypos = (*oldAxis2)(spectrum_index);
  double diffy = ypos - centre_y;
  double diffy_quad = pow(diffy, 2.0);

  // the reference to X bins (the limits for each pixel in the horizontal
  // direction)
  auto xvec = ws->dataX(spectrum_index);

  // for each pixel inside this row
  for (size_t i = 0; i < xvec.size() - 1; i++) {

    double xpos = (xvec[i] + xvec[i + 1]) /
                  2.0; // the x position is the centre of the bins boundaries
    double diffx = xpos - centre_x;
    // calculate the distance => norm of pixel position - centre
    double distance = sqrt(pow(diffx, 2.0) + diffy_quad);

    // check if the distance is inside the ring
    if (distance < min_radius || distance > max_radius || distance == 0) {
      bins_pos[i] = -1;
      continue;
    }

    double angle = atan2(diffy, diffx);

    // call fromAngleToBin (radians)
    bins_pos[i] = fromAngleToBin(angle, false);
  }
}
예제 #14
0
/** Performs the Debye-Bueche transformation: 1/sqrt(I) v Q^2
 *  The output is set to zero for negative input Y values
 *  @param ws The workspace to be transformed
 */
void IQTransform::debyeBueche(API::MatrixWorkspace_sptr ws) {
  MantidVec &X = ws->dataX(0);
  MantidVec &Y = ws->dataY(0);
  MantidVec &E = ws->dataE(0);
  std::transform(X.begin(), X.end(), X.begin(),
                 VectorHelper::Squares<double>());
  for (size_t i = 0; i < Y.size(); ++i) {
    if (Y[i] > 0.0) {
      Y[i] = 1.0 / std::sqrt(Y[i]);
      E[i] *= std::pow(Y[i], 3);
    } else {
      Y[i] = 0.0;
      E[i] = 0.0;
    }
  }

  ws->setYUnitLabel("1/sqrt(I)");
  m_label->setLabel("Q^2");
}
예제 #15
0
  /** Create output workspace
   */
  API::MatrixWorkspace_sptr GeneratePeaks::createOutputWorkspace()
  {
    // Reference workspace and output workspace
    API::MatrixWorkspace_sptr outputWS;

    m_newWSFromParent = true;
    if (!inputWS && binParameters.empty())
    {
      // Error! Neither bin parameters or reference workspace is given.
      std::string errmsg("Must define either InputWorkspace or BinningParameters.");
      g_log.error(errmsg);
      throw std::invalid_argument(errmsg);
    }
    else if (inputWS)
    {
      // Generate Workspace2D from input workspace
      if (!binParameters.empty())
        g_log.notice() << "Both binning parameters and input workspace are given. "
                       << "Using input worksapce to generate output workspace!\n";

      outputWS = API::WorkspaceFactory::Instance().create(inputWS, inputWS->getNumberHistograms(),
                                                          inputWS->dataX(0).size(), inputWS->dataY(0).size());

      std::set<specid_t>::iterator siter;
      // Only copy the X-values from spectra with peaks specified in the table workspace.
      for (siter = m_spectraSet.begin(); siter != m_spectraSet.end(); ++siter)
      {
        specid_t iws = *siter;
        std::copy(inputWS->dataX(iws).begin(), inputWS->dataX(iws).end(), outputWS->dataX(iws).begin());
      }

      m_newWSFromParent = true;
    }
    else
    {
      // Generate a one-spectrum Workspace2D from binning
      outputWS = createDataWorkspace(binParameters);
      m_newWSFromParent = false;
    }

    return outputWS;
  }
예제 #16
0
/** Unwraps an X array, converting the units to wavelength along the way.
 *  @param tempWS ::   A pointer to the temporary workspace in which the results
 * are being stored
 *  @param spectrum :: The workspace index
 *  @param Ld ::       The flightpath for the detector related to this spectrum
 *  @return A 3-element vector containing the bins at which the upper and lower
 * ranges start & end
 */
const std::vector<int>
UnwrapMonitor::unwrapX(const API::MatrixWorkspace_sptr &tempWS,
                       const int &spectrum, const double &Ld) {
  // Create and initalise the vector that will store the bin ranges, and will be
  // returned
  // Elements are: 0 - Lower range start, 1 - Lower range end, 2 - Upper range
  // start
  std::vector<int> binRange(3, -1);

  // Calculate cut-off times
  const double T1 = m_Tmax - (m_Tmin * (1 - (Ld / m_LRef)));
  const double T2 = m_Tmax * (Ld / m_LRef);

  // Create a temporary vector to store the lower range of the unwrapped
  // histograms
  std::vector<double> tempX_L;
  tempX_L.reserve(
      m_XSize); // Doing this possible gives a small efficiency increase
  // Create a vector for the upper range. Make it a reference to the output
  // histogram to save an assignment later
  MantidVec &tempX_U = tempWS->dataX(spectrum);
  tempX_U.clear();
  tempX_U.reserve(m_XSize);

  // Get a reference to the input x data
  const MantidVec &xdata = m_inputWS->readX(spectrum);
  // Loop over histogram, selecting bins in appropriate ranges.
  // At the moment, the data in the bin in which a cut-off sits is excluded.
  for (unsigned int bin = 0; bin < m_XSize; ++bin) {
    // This is the time-of-flight value under consideration in the current
    // iteration of the loop
    const double tof = xdata[bin];
    // First deal with bins where m_Tmin < tof < T2
    if (tof < T2) {
      const double wavelength = (m_conversionConstant * tof) / Ld;
      tempX_L.push_back(wavelength);
      // Record the bins that fall in this range for copying over the data &
      // errors
      if (binRange[0] == -1)
        binRange[0] = bin;
      binRange[1] = bin;
    }
    // Now do the bins where T1 < tof < m_Tmax
    else if (tof > T1) {
      const double velocity = Ld / (tof - m_Tmax + m_Tmin);
      const double wavelength = m_conversionConstant / velocity;
      tempX_U.push_back(wavelength);
      // Remove the duplicate boundary bin
      if (tof == m_Tmax && std::abs(wavelength - tempX_L.front()) < 1.0e-5)
        tempX_U.pop_back();
      // Record the bins that fall in this range for copying over the data &
      // errors
      if (binRange[2] == -1)
        binRange[2] = bin;
    }
  } // loop over X values

  // Deal with the (rare) case that a detector (e.g. downstream monitor) is at a
  // longer flightpath than m_LRef
  if (Ld > m_LRef) {
    std::pair<int, int> binLimits =
        this->handleFrameOverlapped(xdata, Ld, tempX_L);
    binRange[0] = binLimits.first;
    binRange[1] = binLimits.second;
  }

  // Record the point at which the unwrapped sections are joined, first time
  // through only
  Property *join = getProperty("JoinWavelength");
  if (join->isDefault()) {
    g_log.information() << "Joining wavelength: " << tempX_L.front()
                        << " Angstrom\n";
    setProperty("JoinWavelength", tempX_L.front());
  }

  // Append first vector to back of second
  tempX_U.insert(tempX_U.end(), tempX_L.begin(), tempX_L.end());

  return binRange;
}
/**
 * Splits multiperiod histogram data into seperate workspaces and puts them in
 * a group
 *
 * @param numPeriods :: number of periods
 **/
void LoadNexusMonitors2::splitMutiPeriodHistrogramData(
    const size_t numPeriods) {
  // protection - we should not have entered the routine if these are not true
  // More than 1 period
  if (numPeriods < 2) {
    g_log.warning()
        << "Attempted to split multiperiod histogram workspace with "
        << numPeriods << "periods, aborted." << std::endl;
    return;
  }

  // Y array should be divisible by the number of periods
  if (m_workspace->blocksize() % numPeriods != 0) {
    g_log.warning()
        << "Attempted to split multiperiod histogram workspace with "
        << m_workspace->blocksize() << "data entries, into " << numPeriods
        << "periods."
           " Aborted." << std::endl;
    return;
  }

  WorkspaceGroup_sptr wsGroup(new WorkspaceGroup);
  size_t yLength = m_workspace->blocksize() / numPeriods;
  size_t xLength = yLength + 1;
  size_t numSpectra = m_workspace->getNumberHistograms();
  ISISRunLogs monLogCreator(m_workspace->run(), static_cast<int>(numPeriods));
  for (size_t i = 0; i < numPeriods; i++) {
    // create the period workspace
    API::MatrixWorkspace_sptr wsPeriod =
        API::WorkspaceFactory::Instance().create(m_workspace, numSpectra,
                                                 xLength, yLength);

    // assign x values - restart at start for all periods
    for (size_t specIndex = 0; specIndex < numSpectra; specIndex++) {
      MantidVec &outputVec = wsPeriod->dataX(specIndex);
      const MantidVec &inputVec = m_workspace->readX(specIndex);
      for (size_t index = 0; index < xLength; index++) {
        outputVec[index] = inputVec[index];
      }
    }

    // assign y values - use the values offset by the period number
    for (size_t specIndex = 0; specIndex < numSpectra; specIndex++) {
      MantidVec &outputVec = wsPeriod->dataY(specIndex);
      const MantidVec &inputVec = m_workspace->readY(specIndex);
      for (size_t index = 0; index < yLength; index++) {
        outputVec[index] = inputVec[(yLength * i) + index];
      }
    }

    // assign E values
    for (size_t specIndex = 0; specIndex < numSpectra; specIndex++) {
      MantidVec &outputVec = wsPeriod->dataE(specIndex);
      const MantidVec &inputVec = m_workspace->readE(specIndex);
      for (size_t index = 0; index < yLength; index++) {
        outputVec[index] = inputVec[(yLength * i) + index];
      }
    }

    // add period logs
    monLogCreator.addPeriodLogs(static_cast<int>(i + 1),
                                wsPeriod->mutableRun());

    // add to workspace group
    wsGroup->addWorkspace(wsPeriod);
  }

  // set the output workspace
  this->setProperty("OutputWorkspace", wsGroup);
}
예제 #18
0
/** Executes the algorithm
 *  @throw Exception::FileError If the calibration file cannot be opened and read successfully
 *  @throw Exception::InstrumentDefinitionError If unable to obtain the source-sample distance
 */
void AlignDetectors::exec()
{
    // Get the input workspace
    MatrixWorkspace_sptr inputWS = getProperty("InputWorkspace");

    // Read in the calibration data
    const std::string calFileName = getProperty("CalibrationFile");
    OffsetsWorkspace_sptr offsetsWS = getProperty("OffsetsWorkspace");

    progress(0.0,"Reading calibration file");
    if (offsetsWS && !calFileName.empty())
        throw std::invalid_argument("You must specify either CalibrationFile or OffsetsWorkspace but not both.");
    if (!offsetsWS && calFileName.empty())
        throw std::invalid_argument("You must specify either CalibrationFile or OffsetsWorkspace.");

    if (!calFileName.empty())
    {
        // Load the .cal file
        IAlgorithm_sptr alg = createChildAlgorithm("LoadCalFile");
        alg->setPropertyValue("CalFilename", calFileName);
        alg->setProperty("InputWorkspace", inputWS);
        alg->setProperty<bool>("MakeGroupingWorkspace", false);
        alg->setProperty<bool>("MakeOffsetsWorkspace", true);
        alg->setProperty<bool>("MakeMaskWorkspace", false);
        alg->setPropertyValue("WorkspaceName", "temp");
        alg->executeAsChildAlg();
        offsetsWS = alg->getProperty("OutputOffsetsWorkspace");
    }

    const int64_t numberOfSpectra = inputWS->getNumberHistograms();

    // generate map of the tof->d conversion factors
    this->tofToDmap = calcTofToD_ConversionMap(inputWS, offsetsWS);

    //Check if its an event workspace
    EventWorkspace_const_sptr eventW = boost::dynamic_pointer_cast<const EventWorkspace>(inputWS);
    if (eventW != NULL)
    {
        this->execEvent();
        return;
    }

    API::MatrixWorkspace_sptr outputWS = getProperty("OutputWorkspace");
    // If input and output workspaces are not the same, create a new workspace for the output
    if (outputWS != inputWS )
    {
        outputWS = WorkspaceFactory::Instance().create(inputWS);
        setProperty("OutputWorkspace",outputWS);
    }

    // Set the final unit that our output workspace will have
    outputWS->getAxis(0)->unit() = UnitFactory::Instance().create("dSpacing");

    // Initialise the progress reporting object
    Progress progress(this,0.0,1.0,numberOfSpectra);

    // Loop over the histograms (detector spectra)
    PARALLEL_FOR2(inputWS,outputWS)
    for (int64_t i = 0; i < int64_t(numberOfSpectra); ++i)
    {
        PARALLEL_START_INTERUPT_REGION
        try {
            // Get the input spectrum number at this workspace index
            const ISpectrum * inSpec = inputWS->getSpectrum(size_t(i));
            const double factor = calcConversionFromMap(this->tofToDmap, inSpec->getDetectorIDs());

            // Get references to the x data
            MantidVec& xOut = outputWS->dataX(i);

            // Make sure reference to input X vector is obtained after output one because in the case
            // where the input & output workspaces are the same, it might move if the vectors were shared.
            const MantidVec& xIn = inSpec->readX();

            //std::transform( xIn.begin(), xIn.end(), xOut.begin(), std::bind2nd(std::multiplies<double>(), factor) );
            // the above transform creates wrong output in parallel in debug in Visual Studio
            for(size_t k = 0; k < xOut.size(); ++k)
            {
                xOut[k] = xIn[k] * factor;
            }

            // Copy the Y&E data
            outputWS->dataY(i) = inSpec->readY();
            outputWS->dataE(i) = inSpec->readE();

        } catch (Exception::NotFoundError &) {
            // Zero the data in this case
            outputWS->dataX(i).assign(outputWS->readX(i).size(),0.0);
            outputWS->dataY(i).assign(outputWS->readY(i).size(),0.0);
            outputWS->dataE(i).assign(outputWS->readE(i).size(),0.0);
        }
        progress.report();
        PARALLEL_END_INTERUPT_REGION
    }
    PARALLEL_CHECK_INTERUPT_REGION

}
예제 #19
0
/**
 * Execute smoothing of a single spectrum.
 * @param inputWS :: A workspace to pick a spectrum from.
 * @param wsIndex :: An index of a spectrum to smooth.
 * @return :: A single-spectrum workspace with the smoothed data.
 */
API::MatrixWorkspace_sptr
WienerSmooth::smoothSingleSpectrum(API::MatrixWorkspace_sptr inputWS,
                                   size_t wsIndex) {
  size_t dataSize = inputWS->blocksize();

  // it won't work for very small workspaces
  if (dataSize < 4) {
    g_log.debug() << "No smoothing, spectrum copied." << std::endl;
    return copyInput(inputWS, wsIndex);
  }

  // Due to the way RealFFT works the input should be even-sized
  const bool isOddSize = dataSize % 2 != 0;
  if (isOddSize) {
    // add a fake value to the end to make size even
    inputWS = copyInput(inputWS, wsIndex);
    wsIndex = 0;
    auto &X = inputWS->dataX(wsIndex);
    auto &Y = inputWS->dataY(wsIndex);
    auto &E = inputWS->dataE(wsIndex);
    double dx = X[dataSize - 1] - X[dataSize - 2];
    X.push_back(X.back() + dx);
    Y.push_back(Y.back());
    E.push_back(E.back());
  }

  // the input vectors
  auto &X = inputWS->readX(wsIndex);
  auto &Y = inputWS->readY(wsIndex);
  auto &E = inputWS->readE(wsIndex);

  // Digital fourier transform works best for data oscillating around 0.
  // Fit a spline with a small number of break points to the data.
  // Make sure that the spline passes through the first and the last points
  // of the data.
  // The fitted spline will be subtracted from the data and the difference
  // will be smoothed with the Wiener filter. After that the spline will be
  // added to the smoothed data to produce the output.

  // number of spline break points, must be smaller than the data size but
  // between 2 and 10
  size_t nbreak = 10;
  if (nbreak * 3 > dataSize)
    nbreak = dataSize / 3;

  // NB. The spline mustn't fit too well to the data. If it does smoothing
  // doesn't happen.
  // TODO: it's possible that the spline is unnecessary and a simple linear
  // function will
  //       do a better job.

  g_log.debug() << "Spline break points " << nbreak << std::endl;

  // define the spline
  API::IFunction_sptr spline =
      API::FunctionFactory::Instance().createFunction("BSpline");
  auto xInterval = getStartEnd(X, inputWS->isHistogramData());
  spline->setAttributeValue("StartX", xInterval.first);
  spline->setAttributeValue("EndX", xInterval.second);
  spline->setAttributeValue("NBreak", static_cast<int>(nbreak));
  // fix the first and last parameters to the first and last data values
  spline->setParameter(0, Y.front());
  spline->fix(0);
  size_t lastParamIndex = spline->nParams() - 1;
  spline->setParameter(lastParamIndex, Y.back());
  spline->fix(lastParamIndex);

  // fit the spline to the data
  auto fit = createChildAlgorithm("Fit");
  fit->initialize();
  fit->setProperty("Function", spline);
  fit->setProperty("InputWorkspace", inputWS);
  fit->setProperty("WorkspaceIndex", static_cast<int>(wsIndex));
  fit->setProperty("CreateOutput", true);
  fit->execute();

  // get the fit output workspace; spectrum 2 contains the difference that is to
  // be smoothed
  API::MatrixWorkspace_sptr fitOut = fit->getProperty("OutputWorkspace");

  // Fourier transform the difference spectrum
  auto fourier = createChildAlgorithm("RealFFT");
  fourier->initialize();
  fourier->setProperty("InputWorkspace", fitOut);
  fourier->setProperty("WorkspaceIndex", 2);
  // we don't require bin linearity as we don't need the exact transform
  fourier->setProperty("IgnoreXBins", true);
  fourier->execute();

  API::MatrixWorkspace_sptr fourierOut =
      fourier->getProperty("OutputWorkspace");

  // spectrum 2 of the transformed workspace has the transform modulus which is
  // a square
  // root of the power spectrum
  auto &powerSpec = fourierOut->dataY(2);
  // convert the modulus to power spectrum wich is the base of the Wiener filter
  std::transform(powerSpec.begin(), powerSpec.end(), powerSpec.begin(),
                 PowerSpectrum());

  // estimate power spectrum's noise as the average of its high frequency half
  size_t n2 = powerSpec.size();
  double noise =
      std::accumulate(powerSpec.begin() + n2 / 2, powerSpec.end(), 0.0);
  noise /= static_cast<double>(n2);

  // index of the maximum element in powerSpec
  const size_t imax = static_cast<size_t>(std::distance(
      powerSpec.begin(), std::max_element(powerSpec.begin(), powerSpec.end())));

  if (noise == 0.0) {
    noise = powerSpec[imax] / guessSignalToNoiseRatio;
  }

  g_log.debug() << "Maximum signal " << powerSpec[imax] << std::endl;
  g_log.debug() << "Noise          " << noise << std::endl;

  // storage for the Wiener filter, initialized with 0.0's
  std::vector<double> wf(n2);

  // The filter consists of two parts:
  //   1) low frequency region, from 0 until the power spectrum falls to the
  //   noise level, filter is calculated
  //      from the power spectrum
  //   2) high frequency noisy region, filter is a smooth function of frequency
  //   decreasing to 0

  // the following code is an adaptation of a fortran routine
  // noise starting index
  size_t i0 = 0;
  // intermediate variables
  double xx = 0.0;
  double xy = 0.0;
  double ym = 0.0;
  // low frequency filter values: the higher the power spectrum the closer the
  // filter to 1.0
  for (size_t i = 0; i < n2; ++i) {
    double cd1 = powerSpec[i] / noise;
    if (cd1 < 1.0 && i > imax) {
      i0 = i;
      break;
    }
    double cd2 = log(cd1);
    wf[i] = cd1 / (1.0 + cd1);
    double j = static_cast<double>(i + 1);
    xx += j * j;
    xy += j * cd2;
    ym += cd2;
  }

  // i0 should always be > 0 but in case something goes wrong make a check
  if (i0 > 0) {
    g_log.debug() << "Noise start index " << i0 << std::endl;

    // high frequency filter values: smooth decreasing function
    double ri0f = static_cast<double>(i0 + 1);
    double xm = (1.0 + ri0f) / 2;
    ym /= ri0f;
    double a1 = (xy - ri0f * xm * ym) / (xx - ri0f * xm * xm);
    double b1 = ym - a1 * xm;

    g_log.debug() << "(a1,b1) = (" << a1 << ',' << b1 << ')' << std::endl;

    const double dblev = -20.0;
    // cut-off index
    double ri1 = floor((dblev / 4 - b1) / a1);
    if (ri1 < static_cast<double>(i0)) {
      g_log.warning() << "Failed to build Wiener filter: no smoothing."
                      << std::endl;
      ri1 = static_cast<double>(i0);
    }
    size_t i1 = static_cast<size_t>(ri1);
    if (i1 > n2)
      i1 = n2;
    for (size_t i = i0; i < i1; ++i) {
      double s = exp(a1 * static_cast<double>(i + 1) + b1);
      wf[i] = s / (1.0 + s);
    }
    // wf[i] for i1 <= i < n2 are 0.0

    g_log.debug() << "Cut-off index " << i1 << std::endl;
  } else {
    g_log.warning() << "Power spectrum has an unexpected shape: no smoothing"
                    << std::endl;
    return copyInput(inputWS, wsIndex);
  }

  // multiply the fourier transform by the filter
  auto &re = fourierOut->dataY(0);
  auto &im = fourierOut->dataY(1);

  std::transform(re.begin(), re.end(), wf.begin(), re.begin(),
                 std::multiplies<double>());
  std::transform(im.begin(), im.end(), wf.begin(), im.begin(),
                 std::multiplies<double>());

  // inverse fourier transform
  fourier = createChildAlgorithm("RealFFT");
  fourier->initialize();
  fourier->setProperty("InputWorkspace", fourierOut);
  fourier->setProperty("IgnoreXBins", true);
  fourier->setPropertyValue("Transform", "Backward");
  fourier->execute();

  API::MatrixWorkspace_sptr out = fourier->getProperty("OutputWorkspace");
  auto &background = fitOut->readY(1);
  auto &y = out->dataY(0);

  if (y.size() != background.size()) {
    throw std::logic_error("Logic error: inconsistent arrays");
  }

  // add the spline "background" to the smoothed data
  std::transform(y.begin(), y.end(), background.begin(), y.begin(),
                 std::plus<double>());

  // copy the x-values and errors from the original spectrum
  // remove the last values for odd-sized inputs
  if (isOddSize) {
    out->dataX(0).assign(X.begin(), X.end() - 1);
    out->dataE(0).assign(E.begin(), E.end() - 1);
    out->dataY(0).resize(Y.size() - 1);
  } else {
    out->setX(0, X);
    out->dataE(0).assign(E.begin(), E.end());
  }

  return out;
}
예제 #20
0
/**
 * Executes the algorithm
 */
void ScaleX::exec()
{
  //Get input workspace and offset
  const MatrixWorkspace_sptr inputW = getProperty("InputWorkspace");
  m_algFactor = getProperty("Factor");
  m_parname = getPropertyValue("InstrumentParameter");
  m_combine = getProperty("Combine");
  if(m_combine && m_parname.empty())
  {
    throw std::invalid_argument("Combine behaviour requested but the InstrumentParameter argument is blank.");
  }

  const std::string op = getPropertyValue("Operation");
  API::MatrixWorkspace_sptr outputW = createOutputWS(inputW);
  //Get number of histograms
  int histnumber = static_cast<int>(inputW->getNumberHistograms());
  m_progress = new API::Progress(this, 0.0, 1.0, histnumber+1);
  m_progress->report("Scaling X");
  m_wi_min = 0;
  m_wi_max = histnumber-1;
  //check if workspace indexes have been set
  int tempwi_min = getProperty("IndexMin");
  int tempwi_max = getProperty("IndexMax");
  if ( tempwi_max != Mantid::EMPTY_INT() )
  {
    if ((m_wi_min <= tempwi_min) && (tempwi_min <= tempwi_max) && (tempwi_max <= m_wi_max))
    {
      m_wi_min = tempwi_min;
      m_wi_max = tempwi_max;
    }
    else
    {
      g_log.error("Invalid Workspace Index min/max properties");
      throw std::invalid_argument("Inconsistent properties defined");
    }
  }
  // Setup appropriate binary function
  const bool multiply = (op=="Multiply");
  if(multiply) m_binOp = std::multiplies<double>();
  else m_binOp = std::plus<double>();

  //Check if its an event workspace
  EventWorkspace_const_sptr eventWS = boost::dynamic_pointer_cast<const EventWorkspace>(inputW);
  if (eventWS != NULL)
  {
    this->execEvent();
    return;
  }

  // do the shift in X
  PARALLEL_FOR2(inputW, outputW)
  for (int i = 0; i < histnumber; ++i)
  {
    PARALLEL_START_INTERUPT_REGION

    //Copy y and e data
    auto & outY = outputW->dataY(i);
    outY = inputW->dataY(i);
    auto & outE = outputW->dataE(i);
    outE = inputW->dataE(i);

    auto & outX = outputW->dataX(i);
    const auto & inX = inputW->readX(i);
    //Change bin value by offset
    if ((i >= m_wi_min) && (i <= m_wi_max))
    {
      double factor = getScaleFactor(inputW, i);
      // Do the offsetting
      std::transform(inX.begin(), inX.end(), outX.begin(), std::bind2nd(m_binOp, factor));
      // reverse the vector if multiplicative factor was negative
      if(multiply && factor < 0.0)
      {
        std::reverse( outX.begin(), outX.end() );
        std::reverse( outY.begin(), outY.end() );
        std::reverse( outE.begin(), outE.end() );
      }
    }
    else
    {
      outX = inX; //copy
    }
    m_progress->report("Scaling X");

    PARALLEL_END_INTERUPT_REGION
  }
  PARALLEL_CHECK_INTERUPT_REGION

  // Copy units
  if (outputW->getAxis(0)->unit().get())
    outputW->getAxis(0)->unit() = inputW->getAxis(0)->unit();
  try
  {
    if (inputW->getAxis(1)->unit().get())
      outputW->getAxis(1)->unit() = inputW->getAxis(1)->unit();
  }
  catch(Exception::IndexError &)
  {
    // OK, so this isn't a Workspace2D
  }
  // Assign it to the output workspace property
  setProperty("OutputWorkspace",outputW);
}
예제 #21
0
  /** Generate peaks in the given output workspace
    * @param functionmap :: map to contain the list of functions with key as their spectra
    * @param dataWS :: output matrix workspace
    */
  void GeneratePeaks::generatePeaks(const std::map<specid_t, std::vector<std::pair<double, API::IFunction_sptr> > >& functionmap,
                                    API::MatrixWorkspace_sptr dataWS)
  {
    // Calcualte function
    std::map<specid_t, std::vector<std::pair<double, API::IFunction_sptr> > >::const_iterator mapiter;
    for (mapiter = functionmap.begin(); mapiter != functionmap.end(); ++mapiter)
    {
      // Get spec id and translated to wsindex in the output workspace
      specid_t specid = mapiter->first;
      specid_t wsindex;
      if (m_newWSFromParent) wsindex = specid;
      else wsindex = m_SpectrumMap[specid];

      const std::vector<std::pair<double, API::IFunction_sptr> >& vec_centrefunc = mapiter->second;
      size_t numpeaksinspec = mapiter->second.size();

      for (size_t ipeak = 0; ipeak < numpeaksinspec; ++ipeak)
      {
        const std::pair<double, API::IFunction_sptr>& centrefunc = vec_centrefunc[ipeak];

        // Determine boundary
        API::IPeakFunction_sptr thispeak = getPeakFunction(centrefunc.second);
        double centre = centrefunc.first;
        double fwhm = thispeak->fwhm();

        //
        const MantidVec& X = dataWS->dataX(wsindex);
        double leftbound = centre - m_numPeakWidth*fwhm;
        if (ipeak > 0)
        {
          // Not left most peak.
          API::IPeakFunction_sptr leftPeak = getPeakFunction(vec_centrefunc[ipeak-1].second);

          double middle = 0.5*(centre + leftPeak->centre());
          if (leftbound < middle)
            leftbound = middle;
        }
        std::vector<double>::const_iterator left = std::lower_bound(X.begin(), X.end(), leftbound);
        if (left == X.end())
          left = X.begin();

        double rightbound = centre + m_numPeakWidth*fwhm;
        if (ipeak != numpeaksinspec-1)
        {
          // Not the rightmost peak
          IPeakFunction_sptr rightPeak = getPeakFunction(vec_centrefunc[ipeak+1].second);
          double middle = 0.5*(centre + rightPeak->centre());
          if (rightbound > middle)
            rightbound = middle;
        }
        std::vector<double>::const_iterator right = std::lower_bound(left + 1, X.end(), rightbound);

        // Build domain & function
        API::FunctionDomain1DVector domain(left, right); //dataWS->dataX(wsindex));

        // Evaluate the function
        API::FunctionValues values(domain);
        centrefunc.second->function(domain, values);

        // Put to output
        std::size_t offset = (left-X.begin());
        std::size_t numY = values.size();
        for (std::size_t i = 0; i < numY; i ++)
        {
          dataWS->dataY(wsindex)[i + offset] += values[i];
        }

      } // ENDFOR(ipeak)

    }

    return;
  }
예제 #22
0
		/** Executes the rebin algorithm
		*
		*  @throw runtime_error Thrown if
		*/
		void Rebunch::exec()
		{
			// retrieve the properties
			int n_bunch=getProperty("NBunch");

			// Get the input workspace
			MatrixWorkspace_const_sptr inputW = getProperty("InputWorkspace");

			bool dist = inputW->isDistribution();

			// workspace independent determination of length
                        int histnumber = static_cast<int>(inputW->size()/inputW->blocksize());

			/*
			const std::vector<double>& Xold = inputW->readX(0);
			const std::vector<double>& Yold = inputW->readY(0);
			int size_x=Xold.size();
			int size_y=Yold.size();
			*/
                        int size_x = static_cast<int>(inputW->readX(0).size());
                        int size_y = static_cast<int>(inputW->readY(0).size());

			//signal is the same length for histogram and point data
			int ny=(size_y/n_bunch);
			if(size_y%n_bunch >0)ny+=1;
			// default is for hist
			int nx=ny+1;
			bool point=false;
			if (size_x==size_y)
			{
				point=true;
				nx=ny;
			}

			// make output Workspace the same type is the input, but with new length of signal array
			API::MatrixWorkspace_sptr outputW = API::WorkspaceFactory::Instance().create(inputW,histnumber,nx,ny);

            int progress_step = histnumber / 100;
            if (progress_step == 0) progress_step = 1;
			PARALLEL_FOR2(inputW,outputW)
			for (int hist=0; hist <  histnumber;hist++)
			{
				PARALLEL_START_INTERUPT_REGION
				// Ensure that axis information are copied to the output workspace if the axis exists
			        try
				{
				  outputW->getAxis(1)->spectraNo(hist)=inputW->getAxis(1)->spectraNo(hist);
				}
				catch( Exception::IndexError& )
				{ 
				  // Not a Workspace2D
				}

				// get const references to input Workspace arrays (no copying)
				const MantidVec& XValues = inputW->readX(hist);
				const MantidVec& YValues = inputW->readY(hist);
				const MantidVec& YErrors = inputW->readE(hist);

				//get references to output workspace data (no copying)
				MantidVec& XValues_new=outputW->dataX(hist);
				MantidVec& YValues_new=outputW->dataY(hist);
				MantidVec& YErrors_new=outputW->dataE(hist);

				// output data arrays are implicitly filled by function
				if(point)
				{
					rebunch_point(XValues,YValues,YErrors,XValues_new,YValues_new,YErrors_new,n_bunch);
				}
				else
				{
					rebunch_hist(XValues,YValues,YErrors,XValues_new,YValues_new,YErrors_new,n_bunch, dist);
				}

				if (hist % progress_step == 0)
				{
				  progress(double(hist)/histnumber);
				  interruption_point();
				}
				PARALLEL_END_INTERUPT_REGION
			}
			PARALLEL_CHECK_INTERUPT_REGION
			outputW->isDistribution(dist);

			// Copy units
			if (outputW->getAxis(0)->unit().get())
			  outputW->getAxis(0)->unit() = inputW->getAxis(0)->unit();
			try
			{
			  if (inputW->getAxis(1)->unit().get())
			    outputW->getAxis(1)->unit() = inputW->getAxis(1)->unit();
			}
			catch(Exception::IndexError&) {
			  // OK, so this isn't a Workspace2D
			}

			// Assign it to the output workspace property
			setProperty("OutputWorkspace",outputW);

			return;
		}
예제 #23
0
/** Executes the algorithm
 *  @throw Exception::FileError If the calibration file cannot be opened and
 * read successfully
 *  @throw Exception::InstrumentDefinitionError If unable to obtain the
 * source-sample distance
 */
void AlignDetectors::exec() {
  // Get the input workspace
  MatrixWorkspace_sptr inputWS = getProperty("InputWorkspace");

  this->getCalibrationWS(inputWS);

  // Initialise the progress reporting object
  m_numberOfSpectra = static_cast<int64_t>(inputWS->getNumberHistograms());

  // Check if its an event workspace
  EventWorkspace_const_sptr eventW =
      boost::dynamic_pointer_cast<const EventWorkspace>(inputWS);
  if (eventW != nullptr) {
    this->execEvent();
    return;
  }

  API::MatrixWorkspace_sptr outputWS = getProperty("OutputWorkspace");
  // If input and output workspaces are not the same, create a new workspace for
  // the output
  if (outputWS != inputWS) {
    outputWS = WorkspaceFactory::Instance().create(inputWS);
    setProperty("OutputWorkspace", outputWS);
  }

  // Set the final unit that our output workspace will have
  setXAxisUnits(outputWS);

  ConversionFactors converter = ConversionFactors(m_calibrationWS);

  Progress progress(this, 0.0, 1.0, m_numberOfSpectra);

  // Loop over the histograms (detector spectra)
  PARALLEL_FOR2(inputWS, outputWS)
  for (int64_t i = 0; i < m_numberOfSpectra; ++i) {
    PARALLEL_START_INTERUPT_REGION
    try {
      // Get the input spectrum number at this workspace index
      auto inSpec = inputWS->getSpectrum(size_t(i));
      auto toDspacing = converter.getConversionFunc(inSpec->getDetectorIDs());

      // Get references to the x data
      MantidVec &xOut = outputWS->dataX(i);

      // Make sure reference to input X vector is obtained after output one
      // because in the case
      // where the input & output workspaces are the same, it might move if the
      // vectors were shared.
      const MantidVec &xIn = inSpec->readX();

      std::transform(xIn.begin(), xIn.end(), xOut.begin(), toDspacing);

      // Copy the Y&E data
      outputWS->dataY(i) = inSpec->readY();
      outputWS->dataE(i) = inSpec->readE();

    } catch (Exception::NotFoundError &) {
      // Zero the data in this case
      outputWS->dataX(i).assign(outputWS->readX(i).size(), 0.0);
      outputWS->dataY(i).assign(outputWS->readY(i).size(), 0.0);
      outputWS->dataE(i).assign(outputWS->readE(i).size(), 0.0);
    }
    progress.report();
    PARALLEL_END_INTERUPT_REGION
  }
  PARALLEL_CHECK_INTERUPT_REGION
}
예제 #24
0
void LoadDaveGrp::exec()
{
  const std::string filename = this->getProperty("Filename");

  int yLength = 0;

  MantidVec *xAxis = new MantidVec();
  MantidVec *yAxis = new MantidVec();

  std::vector<MantidVec *> data;
  std::vector<MantidVec *> errors;

  this->ifile.open(filename.c_str());
  if (this->ifile.is_open())
  {
    // Size of x axis
    this->getAxisLength(this->xLength);
    // Size of y axis
    this->getAxisLength(yLength);
    // This is also the number of groups (spectra)
    this->nGroups = yLength;
    // Read in the x axis values
    this->getAxisValues(xAxis, static_cast<std::size_t>(this->xLength));
    // Read in the y axis values
    this->getAxisValues(yAxis, static_cast<std::size_t>(yLength));
    // Read in the data
    this->getData(data, errors);
  }
  this->ifile.close();

  // Scale the x-axis if it is in micro-eV to get it to meV
  const bool isUeV = this->getProperty("IsMicroEV");
  if (isUeV)
  {
    MantidVec::iterator iter;
    for (iter = xAxis->begin(); iter != xAxis->end(); ++iter)
    {
      *iter /= 1000.0;
    }
  }

  // Create workspace
  API::MatrixWorkspace_sptr outputWorkspace = \
      boost::dynamic_pointer_cast<API::MatrixWorkspace>\
      (API::WorkspaceFactory::Instance().create("Workspace2D", this->nGroups,
      this->xLength, yLength));
  // Force the workspace to be a distribution
  outputWorkspace->isDistribution(true);

  // Set the x-axis units
  outputWorkspace->getAxis(0)->unit() = Kernel::UnitFactory::Instance().create(this->getProperty("XAxisUnits"));

  API::Axis* const verticalAxis = new API::NumericAxis(yLength);
  // Set the y-axis units
  verticalAxis->unit() = Kernel::UnitFactory::Instance().create(this->getProperty("YAxisUnits"));

  outputWorkspace->replaceAxis(1, verticalAxis);

  for(int i = 0; i < this->nGroups; i++)
  {
    outputWorkspace->dataX(i) = *xAxis;
    outputWorkspace->dataY(i) = *data[i];
    outputWorkspace->dataE(i) = *errors[i];
    verticalAxis->setValue(i, yAxis->at(i));

    delete data[i];
    delete errors[i];
  }

  delete xAxis;
  delete yAxis;

  outputWorkspace->mutableRun().addProperty("Filename",filename);
  this->setProperty("OutputWorkspace", outputWorkspace);
}
예제 #25
0
/**
*  Move the user selected spectra in the input workspace into groups in the output workspace
*  @param inputWS :: user selected input workspace for the algorithm
*  @param outputWS :: user selected output workspace for the algorithm
*  @param prog4Copy :: the amount of algorithm progress to attribute to moving a single spectra
*  @return number of new grouped spectra
*/
size_t GroupDetectors2::formGroups( API::MatrixWorkspace_const_sptr inputWS, API::MatrixWorkspace_sptr outputWS, 
            const double prog4Copy)
{
  // get "Behaviour" string
  const std::string behaviour = getProperty("Behaviour");
  int bhv = 0;
  if ( behaviour == "Average" ) bhv = 1;

  API::MatrixWorkspace_sptr beh = API::WorkspaceFactory::Instance().create(
    "Workspace2D", static_cast<int>(m_GroupSpecInds.size()), 1, 1);

  g_log.debug() << name() << ": Preparing to group spectra into " << m_GroupSpecInds.size() << " groups\n";

  // where we are copying spectra to, we start copying to the start of the output workspace
  size_t outIndex = 0;
  // Only used for averaging behaviour. We may have a 1:1 map where a Divide would be waste as it would be just dividing by 1
  bool requireDivide(false);
  for ( storage_map::const_iterator it = m_GroupSpecInds.begin(); it != m_GroupSpecInds.end() ; ++it )
  {
    // This is the grouped spectrum
    ISpectrum * outSpec = outputWS->getSpectrum(outIndex);

    // The spectrum number of the group is the key
    outSpec->setSpectrumNo(it->first);
    // Start fresh with no detector IDs
    outSpec->clearDetectorIDs();

    // Copy over X data from first spectrum, the bin boundaries for all spectra are assumed to be the same here
    outSpec->dataX() = inputWS->readX(0);

    // the Y values and errors from spectra being grouped are combined in the output spectrum
    // Keep track of number of detectors required for masking
    size_t nonMaskedSpectra(0);
    beh->dataX(outIndex)[0] = 0.0;
    beh->dataE(outIndex)[0] = 0.0;
    for( std::vector<size_t>::const_iterator wsIter = it->second.begin(); wsIter != it->second.end(); ++wsIter)
    {
      const size_t originalWI = *wsIter;

      // detectors to add to firstSpecNum
      const ISpectrum * fromSpectrum = inputWS->getSpectrum(originalWI);

      // Add up all the Y spectra and store the result in the first one
      // Need to keep the next 3 lines inside loop for now until ManagedWorkspace mru-list works properly
      MantidVec &firstY = outSpec->dataY();
      MantidVec::iterator fYit;
      MantidVec::iterator fEit = outSpec->dataE().begin();
      MantidVec::const_iterator Yit = fromSpectrum->dataY().begin();
      MantidVec::const_iterator Eit = fromSpectrum->dataE().begin();
      for (fYit = firstY.begin(); fYit != firstY.end(); ++fYit, ++fEit, ++Yit, ++Eit)
      {
        *fYit += *Yit;
        // Assume 'normal' (i.e. Gaussian) combination of errors
        *fEit = std::sqrt( (*fEit)*(*fEit) + (*Eit)*(*Eit) );
      }

      // detectors to add to the output spectrum
      outSpec->addDetectorIDs(fromSpectrum->getDetectorIDs() );
      try
      {
        Geometry::IDetector_const_sptr det = inputWS->getDetector(originalWI);
        if( !det->isMasked() ) ++nonMaskedSpectra;
      }
      catch(Exception::NotFoundError&)
      {
        // If a detector cannot be found, it cannot be masked
        ++nonMaskedSpectra;
      }
    }
    if( nonMaskedSpectra == 0 ) ++nonMaskedSpectra; // Avoid possible divide by zero
    if(!requireDivide) requireDivide = (nonMaskedSpectra > 1);
    beh->dataY(outIndex)[0] = static_cast<double>(nonMaskedSpectra);

    // make regular progress reports and check for cancelling the algorithm
    if ( outIndex % INTERVAL == 0 )
    {
      m_FracCompl += INTERVAL*prog4Copy;
      if ( m_FracCompl > 1.0 )
        m_FracCompl = 1.0;
      progress(m_FracCompl);
      interruption_point();
    }
    outIndex ++;
  }
  
  // Refresh the spectraDetectorMap
  outputWS->generateSpectraMap();

  if ( bhv == 1 && requireDivide )
  {
    g_log.debug() << "Running Divide algorithm to perform averaging.\n";
    Mantid::API::IAlgorithm_sptr divide = createChildAlgorithm("Divide");
    divide->initialize();
    divide->setProperty<API::MatrixWorkspace_sptr>("LHSWorkspace", outputWS);
    divide->setProperty<API::MatrixWorkspace_sptr>("RHSWorkspace", beh);
    divide->setProperty<API::MatrixWorkspace_sptr>("OutputWorkspace", outputWS);
    divide->execute();
  }

  g_log.debug() << name() << " created " << outIndex << " new grouped spectra\n";
  return outIndex;
}
예제 #26
0
/** Executes the algorithm
 *
 */
void SplineBackground::exec()
{

  API::MatrixWorkspace_sptr inWS = getProperty("InputWorkspace");
  int spec = getProperty("WorkspaceIndex");

  if (spec > static_cast<int>(inWS->getNumberHistograms()))
    throw std::out_of_range("WorkspaceIndex is out of range.");

  const MantidVec& X = inWS->readX(spec);
  const MantidVec& Y = inWS->readY(spec);
  const MantidVec& E = inWS->readE(spec);
  const bool isHistogram = inWS->isHistogramData();

  const int ncoeffs = getProperty("NCoeff");
  const int k = 4; // order of the spline + 1 (cubic)
  const int nbreak = ncoeffs - (k - 2);

  if (nbreak <= 0)
    throw std::out_of_range("Too low NCoeff");

  gsl_bspline_workspace *bw;
  gsl_vector *B;

  gsl_vector *c, *w, *x, *y;
  gsl_matrix *Z, *cov;
  gsl_multifit_linear_workspace *mw;
  double chisq;

  int n = static_cast<int>(Y.size());
  bool isMasked = inWS->hasMaskedBins(spec);
  std::vector<int> masked(Y.size());
  if (isMasked)
  {
    for(API::MatrixWorkspace::MaskList::const_iterator it=inWS->maskedBins(spec).begin();it!=inWS->maskedBins(spec).end();++it)
      masked[it->first] = 1;
    n -= static_cast<int>(inWS->maskedBins(spec).size());
  }

  if (n < ncoeffs)
  {
    g_log.error("Too many basis functions (NCoeff)");
    throw std::out_of_range("Too many basis functions (NCoeff)");
  }

  /* allocate a cubic bspline workspace (k = 4) */
  bw = gsl_bspline_alloc(k, nbreak);
  B = gsl_vector_alloc(ncoeffs);

  x = gsl_vector_alloc(n);
  y = gsl_vector_alloc(n);
  Z = gsl_matrix_alloc(n, ncoeffs);
  c = gsl_vector_alloc(ncoeffs);
  w = gsl_vector_alloc(n);
  cov = gsl_matrix_alloc(ncoeffs, ncoeffs);
  mw = gsl_multifit_linear_alloc(n, ncoeffs);

  /* this is the data to be fitted */
  int j = 0;
  for (MantidVec::size_type i = 0; i < Y.size(); ++i)
  {
    if (isMasked && masked[i]) continue;
    gsl_vector_set(x, j, (isHistogram ? (0.5*(X[i]+X[i+1])) : X[i])); // Middle of the bins, if a histogram
    gsl_vector_set(y, j, Y[i]);
    gsl_vector_set(w, j, E[i]>0.?1./(E[i]*E[i]):0.);

    ++j;
  }

  if (n != j)
  {
    gsl_bspline_free(bw);
    gsl_vector_free(B);
    gsl_vector_free(x);
    gsl_vector_free(y);
    gsl_matrix_free(Z);
    gsl_vector_free(c);
    gsl_vector_free(w);
    gsl_matrix_free(cov);
    gsl_multifit_linear_free(mw);

    throw std::runtime_error("Assertion failed: n != j");
  }

  double xStart = X.front();
  double xEnd =   X.back();

  /* use uniform breakpoints */
  gsl_bspline_knots_uniform(xStart, xEnd, bw);

  /* construct the fit matrix X */
  for (int i = 0; i < n; ++i)
  {
    double xi=gsl_vector_get(x, i);

    /* compute B_j(xi) for all j */
    gsl_bspline_eval(xi, B, bw);

    /* fill in row i of X */
    for (j = 0; j < ncoeffs; ++j)
    {
      double Bj = gsl_vector_get(B, j);
      gsl_matrix_set(Z, i, j, Bj);
    }
  }

  /* do the fit */
  gsl_multifit_wlinear(Z, w, y, c, cov, &chisq, mw);

  /* output the smoothed curve */
  API::MatrixWorkspace_sptr outWS = WorkspaceFactory::Instance().create(inWS,1,X.size(),Y.size());
  {
    outWS->getAxis(1)->setValue(0, inWS->getAxis(1)->spectraNo(spec));
    double xi, yi, yerr;
    for (MantidVec::size_type i=0;i<Y.size();i++)
    {
      xi = X[i];
      gsl_bspline_eval(xi, B, bw);
      gsl_multifit_linear_est(B, c, cov, &yi, &yerr);
      outWS->dataY(0)[i] = yi;
      outWS->dataE(0)[i] = yerr;
    }
    outWS->dataX(0) = X;
  }

  gsl_bspline_free(bw);
  gsl_vector_free(B);
  gsl_vector_free(x);
  gsl_vector_free(y);
  gsl_matrix_free(Z);
  gsl_vector_free(c);
  gsl_vector_free(w);
  gsl_matrix_free(cov);
  gsl_multifit_linear_free(mw);

  setProperty("OutputWorkspace",outWS);

}
예제 #27
0
/**
*  Move the user selected spectra in the input workspace into groups in the output workspace
*  @param inputWS :: user selected input workspace for the algorithm
*  @param outputWS :: user selected output workspace for the algorithm
*  @param prog4Copy :: the amount of algorithm progress to attribute to moving a single spectra
*  @return number of new grouped spectra
*/
size_t GroupDetectors2::formGroupsEvent( DataObjects::EventWorkspace_const_sptr inputWS, DataObjects::EventWorkspace_sptr  outputWS,
            const double prog4Copy)
{
  // get "Behaviour" string
  const std::string behaviour = getProperty("Behaviour");
  int bhv = 0;
  if ( behaviour == "Average" ) bhv = 1;

  API::MatrixWorkspace_sptr beh = API::WorkspaceFactory::Instance().create(
    "Workspace2D", static_cast<int>(m_GroupSpecInds.size()), 1, 1);

  g_log.debug() << name() << ": Preparing to group spectra into " << m_GroupSpecInds.size() << " groups\n";


  // where we are copying spectra to, we start copying to the start of the output workspace
  size_t outIndex = 0;
  // Only used for averaging behaviour. We may have a 1:1 map where a Divide would be waste as it would be just dividing by 1
  bool requireDivide(false);
  for ( storage_map::const_iterator it = m_GroupSpecInds.begin(); it != m_GroupSpecInds.end() ; ++it )
  {
    // This is the grouped spectrum
    EventList & outEL = outputWS->getEventList(outIndex);

    // The spectrum number of the group is the key
    outEL.setSpectrumNo(it->first);
    // Start fresh with no detector IDs
    outEL.clearDetectorIDs();

    // the Y values and errors from spectra being grouped are combined in the output spectrum
    // Keep track of number of detectors required for masking
    size_t nonMaskedSpectra(0);
    beh->dataX(outIndex)[0] = 0.0;
    beh->dataE(outIndex)[0] = 0.0;
    for( std::vector<size_t>::const_iterator wsIter = it->second.begin(); wsIter != it->second.end(); ++wsIter)
    {
      const size_t originalWI = *wsIter;

      const EventList & fromEL=inputWS->getEventList(originalWI);
      //Add the event lists with the operator
      outEL += fromEL;


      // detectors to add to the output spectrum
      outEL.addDetectorIDs(fromEL.getDetectorIDs() );
      try
      {
        Geometry::IDetector_const_sptr det = inputWS->getDetector(originalWI);
        if( !det->isMasked() ) ++nonMaskedSpectra;
      }
      catch(Exception::NotFoundError&)
      {
        // If a detector cannot be found, it cannot be masked
        ++nonMaskedSpectra;
      }
    }
    if( nonMaskedSpectra == 0 ) ++nonMaskedSpectra; // Avoid possible divide by zero
    if(!requireDivide) requireDivide = (nonMaskedSpectra > 1);
    beh->dataY(outIndex)[0] = static_cast<double>(nonMaskedSpectra);

    // make regular progress reports and check for cancelling the algorithm
    if ( outIndex % INTERVAL == 0 )
    {
      m_FracCompl += INTERVAL*prog4Copy;
      if ( m_FracCompl > 1.0 )
        m_FracCompl = 1.0;
      progress(m_FracCompl);
      interruption_point();
    }
    outIndex ++;
  }

  // Refresh the spectraDetectorMap
  outputWS->doneAddingEventLists();

  if ( bhv == 1 && requireDivide )
  {
    g_log.debug() << "Running Divide algorithm to perform averaging.\n";
    Mantid::API::IAlgorithm_sptr divide = createChildAlgorithm("Divide");
    divide->initialize();
    divide->setProperty<API::MatrixWorkspace_sptr>("LHSWorkspace", outputWS);
    divide->setProperty<API::MatrixWorkspace_sptr>("RHSWorkspace", beh);
    divide->setProperty<API::MatrixWorkspace_sptr>("OutputWorkspace", outputWS);
    divide->execute();
  }


  g_log.debug() << name() << " created " << outIndex << " new grouped spectra\n";
  return outIndex;
}
/** Convert the workspace units using TOF as an intermediate step in the
 * conversion
 * @param fromUnit :: The unit of the input workspace
 * @param outputWS :: The output workspace
 */
void ConvertUnitsUsingDetectorTable::convertViaTOF(
    Kernel::Unit_const_sptr fromUnit, API::MatrixWorkspace_sptr outputWS) {
  using namespace Geometry;

  // Let's see if we are using a TableWorkspace to override parameters
  TableWorkspace_sptr paramWS = getProperty("DetectorParameters");

  // See if we have supplied a DetectorParameters Workspace
  // TODO: Check if paramWS is NULL and if so throw an exception

  //      const std::string l1ColumnLabel("l1");

  // Let's check all the columns exist and are readable
  try {
    auto spectraColumnTmp = paramWS->getColumn("spectra");
    auto l1ColumnTmp = paramWS->getColumn("l1");
    auto l2ColumnTmp = paramWS->getColumn("l2");
    auto twoThetaColumnTmp = paramWS->getColumn("twotheta");
    auto efixedColumnTmp = paramWS->getColumn("efixed");
    auto emodeColumnTmp = paramWS->getColumn("emode");
  } catch (...) {
    throw Exception::InstrumentDefinitionError(
        "DetectorParameter TableWorkspace is not defined correctly.");
  }

  // Now let's read them into some vectors.
  auto l1Column = paramWS->getColVector<double>("l1");
  auto l2Column = paramWS->getColVector<double>("l2");
  auto twoThetaColumn = paramWS->getColVector<double>("twotheta");
  auto efixedColumn = paramWS->getColVector<double>("efixed");
  auto emodeColumn = paramWS->getColVector<int>("emode");
  auto spectraColumn = paramWS->getColVector<int>("spectra");

  EventWorkspace_sptr eventWS =
      boost::dynamic_pointer_cast<EventWorkspace>(outputWS);
  assert(static_cast<bool>(eventWS) == m_inputEvents); // Sanity check

  Progress prog(this, 0.2, 1.0, m_numberOfSpectra);
  int64_t numberOfSpectra_i =
      static_cast<int64_t>(m_numberOfSpectra); // cast to make openmp happy

  // Get the unit object for each workspace
  Kernel::Unit_const_sptr outputUnit = outputWS->getAxis(0)->unit();

  std::vector<double> emptyVec;
  int failedDetectorCount = 0;

  // ConstColumnVector<int> spectraNumber = paramWS->getVector("spectra");

  // TODO: Check why this parallel stuff breaks
  // Loop over the histograms (detector spectra)
  // PARALLEL_FOR1(outputWS)
  for (int64_t i = 0; i < numberOfSpectra_i; ++i) {

    // Lets find what row this spectrum ID appears in our detector table.

    // PARALLEL_START_INTERUPT_REGION

    std::size_t wsid = i;

    try {

      double deg2rad = M_PI / 180.;

      auto det = outputWS->getDetector(i);
      int specid = det->getID();

      // int spectraNumber = static_cast<int>(spectraColumn->toDouble(i));
      // wsid = outputWS->getIndexFromSpectrumNumber(spectraNumber);
      g_log.debug() << "###### Spectra #" << specid
                    << " ==> Workspace ID:" << wsid << std::endl;

      // Now we need to find the row that contains this spectrum
      std::vector<int>::iterator specIter;

      specIter = std::find(spectraColumn.begin(), spectraColumn.end(), specid);
      if (specIter != spectraColumn.end()) {
        size_t detectorRow = std::distance(spectraColumn.begin(), specIter);
        double l1 = l1Column[detectorRow];
        double l2 = l2Column[detectorRow];
        double twoTheta = twoThetaColumn[detectorRow] * deg2rad;
        double efixed = efixedColumn[detectorRow];
        int emode = emodeColumn[detectorRow];

        g_log.debug() << "specId from detector table = "
                      << spectraColumn[detectorRow] << std::endl;

        // l1 = l1Column->toDouble(detectorRow);
        // l2 = l2Column->toDouble(detectorRow);
        // twoTheta = deg2rad * twoThetaColumn->toDouble(detectorRow);
        // efixed = efixedColumn->toDouble(detectorRow);
        // emode = static_cast<int>(emodeColumn->toDouble(detectorRow));

        g_log.debug() << "###### Spectra #" << specid
                      << " ==> Det Table Row:" << detectorRow << std::endl;

        g_log.debug() << "\tL1=" << l1 << ",L2=" << l2 << ",TT=" << twoTheta
                      << ",EF=" << efixed << ",EM=" << emode << std::endl;

        // Make local copies of the units. This allows running the loop in
        // parallel
        Unit *localFromUnit = fromUnit->clone();
        Unit *localOutputUnit = outputUnit->clone();
        /// @todo Don't yet consider hold-off (delta)
        const double delta = 0.0;
        // Convert the input unit to time-of-flight
        localFromUnit->toTOF(outputWS->dataX(wsid), emptyVec, l1, l2, twoTheta,
                             emode, efixed, delta);
        // Convert from time-of-flight to the desired unit
        localOutputUnit->fromTOF(outputWS->dataX(wsid), emptyVec, l1, l2,
                                 twoTheta, emode, efixed, delta);
        // EventWorkspace part, modifying the EventLists.
        if (m_inputEvents) {
          eventWS->getEventList(wsid)
              .convertUnitsViaTof(localFromUnit, localOutputUnit);
        }
        // Clear unit memory
        delete localFromUnit;
        delete localOutputUnit;

      } else {
        // Not found
        g_log.debug() << "Spectrum " << specid << " not found!" << std::endl;
        failedDetectorCount++;
        outputWS->maskWorkspaceIndex(wsid);
      }

    } catch (Exception::NotFoundError &) {
      // Get to here if exception thrown when calculating distance to detector
      failedDetectorCount++;
      // Since you usually (always?) get to here when there's no attached
      // detectors, this call is
      // the same as just zeroing out the data (calling clearData on the
      // spectrum)
      outputWS->maskWorkspaceIndex(i);
    }

    prog.report("Convert to " + m_outputUnit->unitID());
    // PARALLEL_END_INTERUPT_REGION
  } // loop over spectra
  // PARALLEL_CHECK_INTERUPT_REGION

  if (failedDetectorCount != 0) {
    g_log.information() << "Something went wrong for " << failedDetectorCount
                        << " spectra. Masking spectrum." << std::endl;
  }
  if (m_inputEvents)
    eventWS->clearMRU();
}
예제 #29
0
/** Carries out the bin-by-bin normalisation
 *  @param inputWorkspace The input workspace
 *  @param outputWorkspace The result workspace
 */
void NormaliseToMonitor::normaliseBinByBin(API::MatrixWorkspace_sptr inputWorkspace,
                                           API::MatrixWorkspace_sptr& outputWorkspace)
{ 
  EventWorkspace_sptr inputEvent = boost::dynamic_pointer_cast<EventWorkspace>(inputWorkspace);
  EventWorkspace_sptr outputEvent;

  // Only create output workspace if different to input one
  if (outputWorkspace != inputWorkspace )
  {
    if (inputEvent)
    {
      //Make a brand new EventWorkspace
      outputEvent = boost::dynamic_pointer_cast<EventWorkspace>(
          API::WorkspaceFactory::Instance().create("EventWorkspace", inputEvent->getNumberHistograms(), 2, 1));
      //Copy geometry and data
      API::WorkspaceFactory::Instance().initializeFromParent(inputEvent, outputEvent, false);
      outputEvent->copyDataFrom( (*inputEvent) );
      outputWorkspace = boost::dynamic_pointer_cast<MatrixWorkspace>(outputEvent);
    }
    else
      outputWorkspace = WorkspaceFactory::Instance().create(inputWorkspace);
  }

  // Get hold of the monitor spectrum
  const MantidVec& monX = m_monitor->readX(0);
  MantidVec& monY = m_monitor->dataY(0);
  MantidVec& monE = m_monitor->dataE(0);
  // Calculate the overall normalisation just the once if bins are all matching
  if (m_commonBins) this->normalisationFactor(m_monitor->readX(0),&monY,&monE);


  const size_t numHists = inputWorkspace->getNumberHistograms();
  MantidVec::size_type specLength = inputWorkspace->blocksize();
  Progress prog(this,0.0,1.0,numHists);
  // Loop over spectra
  PARALLEL_FOR3(inputWorkspace,outputWorkspace,m_monitor)
  for (int64_t i = 0; i < int64_t(numHists); ++i)
  {
    PARALLEL_START_INTERUPT_REGION
    prog.report();

    const MantidVec& X = inputWorkspace->readX(i);
    // If not rebinning, just point to our monitor spectra, otherwise create new vectors
    MantidVec* Y = ( m_commonBins ? &monY : new MantidVec(specLength) );
    MantidVec* E = ( m_commonBins ? &monE : new MantidVec(specLength) );

    if (!m_commonBins)
    {
      // ConvertUnits can give X vectors of all zeroes - skip these, they cause problems
      if (X.back() == 0.0 && X.front() == 0.0) continue;
      // Rebin the monitor spectrum to match the binning of the current data spectrum
      VectorHelper::rebinHistogram(monX,monY,monE,X,*Y,*E,false);
      // Recalculate the overall normalisation factor
      this->normalisationFactor(X,Y,E);
    }

    if (inputEvent)
    {
      // ----------------------------------- EventWorkspace ---------------------------------------
      EventList & outEL = outputEvent->getEventList(i);
      outEL.divide(X, *Y, *E);
    }
    else
    {
      // ----------------------------------- Workspace2D ---------------------------------------
      const MantidVec& inY = inputWorkspace->readY(i);
      const MantidVec& inE = inputWorkspace->readE(i);
      MantidVec& YOut = outputWorkspace->dataY(i);
      MantidVec& EOut = outputWorkspace->dataE(i);
      outputWorkspace->dataX(i) = inputWorkspace->readX(i);
      // The code below comes more or less straight out of Divide.cpp
      for (MantidVec::size_type k = 0; k < specLength; ++k)
      {
        // Get references to the input Y's
        const double& leftY = inY[k];
        const double& rightY = (*Y)[k];

        // Calculate result and store in local variable to avoid overwriting original data if
        // output workspace is same as one of the input ones
        const double newY = leftY/rightY;

        if (fabs(rightY)>1.0e-12 && fabs(newY)>1.0e-12)
        {
          const double lhsFactor = (inE[k]<1.0e-12|| fabs(leftY)<1.0e-12) ? 0.0 : pow((inE[k]/leftY),2);
          const double rhsFactor = (*E)[k]<1.0e-12 ? 0.0 : pow(((*E)[k]/rightY),2);
          EOut[k] = std::abs(newY) * sqrt(lhsFactor+rhsFactor);
        }

        // Now store the result
        YOut[k] = newY;
      } // end Workspace2D case
    } // end loop over current spectrum

    if (!m_commonBins) { delete Y; delete E; }
    PARALLEL_END_INTERUPT_REGION
  } // end loop over spectra
  PARALLEL_CHECK_INTERUPT_REGION
}
예제 #30
0
파일: ScaleX.cpp 프로젝트: trnielsen/mantid
    /**
     * Executes the algorithm
     */
    void ScaleX::exec()
    {
      //Get input workspace and offset
      const MatrixWorkspace_sptr inputW = getProperty("InputWorkspace");

      factor = getProperty("Factor");

      API::MatrixWorkspace_sptr outputW = createOutputWS(inputW);

      //Get number of histograms
      int histnumber = static_cast<int>(inputW->getNumberHistograms());

      m_progress = new API::Progress(this, 0.0, 1.0, histnumber+1);
      m_progress->report("Scaling X");

	    wi_min = 0;
      wi_max = histnumber-1;
      //check if workspace indexes have been set
      int tempwi_min = getProperty("IndexMin");
      int tempwi_max = getProperty("IndexMax");
      if ( tempwi_max != Mantid::EMPTY_INT() )
      {
        if ((wi_min <= tempwi_min) && (tempwi_min <= tempwi_max) && (tempwi_max <= wi_max))
        {
          wi_min = tempwi_min;
          wi_max = tempwi_max;
        }
        else
        {
          g_log.error("Invalid Workspace Index min/max properties");
          throw std::invalid_argument("Inconsistent properties defined");
        }
      }


      //Check if its an event workspace
      EventWorkspace_const_sptr eventWS = boost::dynamic_pointer_cast<const EventWorkspace>(inputW);
      if (eventWS != NULL)
      {
        this->execEvent();
        return;
      }

      // do the shift in X
      PARALLEL_FOR2(inputW, outputW)
      for (int i=0; i < histnumber; ++i)
      {
        PARALLEL_START_INTERUPT_REGION
        //Do the offsetting
        for (int j=0; j <  static_cast<int>(inputW->readX(i).size()); ++j)
        {
          //Change bin value by offset
          if ((i >= wi_min) && (i <= wi_max)) outputW->dataX(i)[j] = inputW->readX(i)[j] * factor;
          else outputW->dataX(i)[j] = inputW->readX(i)[j];
        }
        //Copy y and e data
        outputW->dataY(i) = inputW->dataY(i);
        outputW->dataE(i) = inputW->dataE(i);

        if( (i >= wi_min) && (i <= wi_max) && factor<0 )
        {
          std::reverse( outputW->dataX(i).begin(), outputW->dataX(i).end() );
          std::reverse( outputW->dataY(i).begin(), outputW->dataY(i).end() );
          std::reverse( outputW->dataE(i).begin(), outputW->dataE(i).end() );
        }

        m_progress->report("Scaling X");
        PARALLEL_END_INTERUPT_REGION
      }
      PARALLEL_CHECK_INTERUPT_REGION

      // Copy units
      if (outputW->getAxis(0)->unit().get())
          outputW->getAxis(0)->unit() = inputW->getAxis(0)->unit();
      try
      {
          if (inputW->getAxis(1)->unit().get())
              outputW->getAxis(1)->unit() = inputW->getAxis(1)->unit();
      }
      catch(Exception::IndexError &) {
          // OK, so this isn't a Workspace2D
      }

      // Assign it to the output workspace property
      setProperty("OutputWorkspace",outputW);
    }