Ejemplo n.º 1
0
/**Convert a binned workspace to point data
 *
 * @param workspace :: The input workspace
 * @return the converted workspace containing point data
 */
MatrixWorkspace_sptr
SplineInterpolation::convertBinnedData(MatrixWorkspace_sptr workspace) const {
  if (workspace->isHistogramData()) {
    const size_t histNo = workspace->getNumberHistograms();
    const size_t size = workspace->y(0).size();

    // make a new workspace for the point data
    MatrixWorkspace_sptr pointWorkspace =
        WorkspaceFactory::Instance().create(workspace, histNo, size, size);

    // loop over each histogram
    for (size_t i = 0; i < histNo; ++i) {
      const auto &xValues = workspace->x(i);
      pointWorkspace->setSharedY(i, workspace->sharedY(i));

      auto &newXValues = pointWorkspace->mutableX(i);

      // set x values to be average of bin bounds
      for (size_t j = 0; j < size; ++j) {
        newXValues[j] = (xValues[j] + xValues[j + 1]) / 2;
      }
    }

    return pointWorkspace;
  }

  return workspace;
}
Ejemplo n.º 2
0
/** Populates the output workspaces
* @param inWS :: [input] The input workspace
* @param spec :: [input] The current spectrum being analyzed
* @param nspec :: [input] The total number of histograms in the input workspace
* @param result :: [input] The result to be written in the output workspace
* @param outWS :: [input] The output workspace to populate
*/
void MaxEnt::populateDataWS(const MatrixWorkspace_sptr &inWS, size_t spec,
                            size_t nspec, const std::vector<double> &result,
                            MatrixWorkspace_sptr &outWS) {

  if (result.size() % 2)
    throw std::invalid_argument("Cannot write results to output workspaces");

  int npoints = static_cast<int>(result.size() / 2);
  int npointsX = inWS->isHistogramData() ? npoints + 1 : npoints;
  MantidVec X(npointsX);
  MantidVec YR(npoints);
  MantidVec YI(npoints);
  MantidVec E(npoints, 0.);

  double x0 = inWS->readX(spec)[0];
  double dx = inWS->readX(spec)[1] - x0;

  for (int i = 0; i < npoints; i++) {
    X[i] = x0 + i * dx;
    YR[i] = result[2 * i];
    YI[i] = result[2 * i + 1];
  }
  if (npointsX == npoints + 1)
    X[npoints] = x0 + npoints * dx;

  outWS->dataX(spec).assign(X.begin(), X.end());
  outWS->dataY(spec).assign(YR.begin(), YR.end());
  outWS->dataE(spec).assign(E.begin(), E.end());
  outWS->dataX(nspec + spec).assign(X.begin(), X.end());
  outWS->dataY(nspec + spec).assign(YI.begin(), YI.end());
  outWS->dataE(nspec + spec).assign(E.begin(), E.end());
}
Ejemplo n.º 3
0
/**
 * This function gets the input workspace. In the case for a RebinnedOutput
 * workspace, it must be cleaned before proceeding. Other workspaces are
 * untouched.
 * @return the input workspace, cleaned if necessary
 */
MatrixWorkspace_sptr Integration::getInputWorkspace() {
  MatrixWorkspace_sptr temp = getProperty("InputWorkspace");

  if (temp->id() == "RebinnedOutput") {
    // Clean the input workspace in the RebinnedOutput case for nan's and
    // inf's in order to treat the data correctly later.
    IAlgorithm_sptr alg = this->createChildAlgorithm("ReplaceSpecialValues");
    alg->setProperty<MatrixWorkspace_sptr>("InputWorkspace", temp);
    std::string outName = "_" + temp->getName() + "_clean";
    alg->setProperty("OutputWorkspace", outName);
    alg->setProperty("NaNValue", 0.0);
    alg->setProperty("NaNError", 0.0);
    alg->setProperty("InfinityValue", 0.0);
    alg->setProperty("InfinityError", 0.0);
    alg->executeAsChildAlg();
    temp = alg->getProperty("OutputWorkspace");
  }

  // To integrate point data it will be converted to histograms
  if (!temp->isHistogramData()) {
    auto alg = this->createChildAlgorithm("ConvertToHistogram");
    alg->setProperty<MatrixWorkspace_sptr>("InputWorkspace", temp);
    std::string outName = "_" + temp->getName() + "_histogram";
    alg->setProperty("OutputWorkspace", outName);
    alg->executeAsChildAlg();
    temp = alg->getProperty("OutputWorkspace");
    temp->setDistribution(true);
  }

  return temp;
}
Ejemplo n.º 4
0
/** Compares the properties of the input workspace with the reference
 * @param ws : the testee workspace
 * @param checkNumberHistograms : whether to check also the number of histograms
 * @return : empty if compatible, error message otherwises
 */
std::string
RunCombinationHelper::checkCompatibility(MatrixWorkspace_sptr ws,
                                         bool checkNumberHistograms) {
  std::string errors;
  if (ws->getNumberHistograms() != m_numberSpectra && checkNumberHistograms)
    errors += "different number of histograms; ";
  if (ws->getAxis(0)->unit()->unitID() != m_xUnit)
    errors += "different X units; ";
  if (ws->getAxis(1)->unit()->unitID() != m_spectrumAxisUnit)
    errors += "different spectrum axis units; ";
  if (ws->YUnit() != m_yUnit)
    errors += "different Y units; ";
  if (ws->isHistogramData() != m_isHistogramData)
    errors += "different distribution or histogram type; ";
  if (ws->detectorInfo().isScanning() != m_isScanning)
    errors += "a mix of workspaces with and without detector scans; ";
  if (m_isScanning && ws->detectorInfo().size() != m_numberDetectors)
    errors += "workspaces with detectors scans have different number of "
              "detectors; ";
  if (ws->getInstrument()->getName() != m_instrumentName)
    errors += "different instrument names; ";
  if (ws->getNumberHistograms() == m_numberSpectra) {
    if (!m_hasDx.empty()) {
      for (unsigned int i = 0; i < m_numberSpectra; ++i) {
        if (m_hasDx[i] != ws->hasDx(i)) {
          errors += "spectra must have either Dx values or not; ";
          break;
        }
      }
    }
  }
  return errors;
}
Ejemplo n.º 5
0
 /**
  * Returns true if the algorithm needs to be run.
  * @param inputWS pointer to input workspace
  * @returns True if the input workspace needs to be run through this algorithm
  */
 bool ConvertToPointData::isProcessingRequired(const MatrixWorkspace_sptr inputWS) const
 {
   if( !inputWS->isHistogramData() )
   {
     g_log.information() << "Input workspace already contains point data. "
       << "OutputWorkspace set to InputWorkspace value.\n";
     return false;
   }
   return true;
 }
Ejemplo n.º 6
0
/**Convert a binned workspace to point data
 *
 * @param workspace :: The input workspace
 * @return the converted workspace containing point data
 */
MatrixWorkspace_sptr
SplineSmoothing::convertBinnedData(MatrixWorkspace_sptr workspace) {
    if (workspace->isHistogramData()) {
        auto alg = createChildAlgorithm("ConvertToPointData");
        alg->setProperty("InputWorkspace", workspace);
        alg->execute();
        return alg->getProperty("OutputWorkspace");
    } else {
        return workspace;
    }
}
Ejemplo n.º 7
0
/** Sets the properties of the reference (usually first) workspace,
 * to later check the compatibility of the others with the reference
 * @param ref : the reference workspace
 */
void RunCombinationHelper::setReferenceProperties(MatrixWorkspace_sptr ref) {
  m_numberSpectra = ref->getNumberHistograms();
  m_numberDetectors = ref->detectorInfo().size();
  m_xUnit = ref->getAxis(0)->unit()->unitID();
  m_spectrumAxisUnit = ref->getAxis(1)->unit()->unitID();
  m_yUnit = ref->YUnit();
  m_isHistogramData = ref->isHistogramData();
  m_isScanning = ref->detectorInfo().isScanning();
  m_instrumentName = ref->getInstrument()->getName();
  if (m_numberSpectra) {
    m_hasDx.reserve(m_numberSpectra);
    for (unsigned int i = 0; i < m_numberSpectra; ++i)
      m_hasDx.push_back(ref->hasDx(i));
  }
}
Ejemplo n.º 8
0
void IQTransform::exec()
{
  MatrixWorkspace_sptr inputWS = getProperty("InputWorkspace");
  // Print a warning if the input workspace has more than one spectrum
  if ( inputWS->getNumberHistograms() > 1 )
  {
    g_log.warning("This algorithm is intended for use on single-spectrum workspaces.\n"
                  "Only the first spectrum will be transformed.");
  }

  // Do background subtraction from a workspace first because it doesn't like
  // potential conversion to point data that follows. Requires a temporary workspace.
  MatrixWorkspace_sptr tmpWS;
  MatrixWorkspace_sptr backgroundWS = getProperty("BackgroundWorkspace");
  if ( backgroundWS ) tmpWS = subtractBackgroundWS(inputWS,backgroundWS);
  else tmpWS = inputWS;

  // Create the output workspace
  const size_t length = tmpWS->blocksize();
  MatrixWorkspace_sptr outputWS = WorkspaceFactory::Instance().create(inputWS,1,length,length);
  m_label->setLabel("");
  outputWS->setYUnit("");
  // Copy the data over. Assume single spectrum input (output will be).
  // Take the mid-point of histogram bins
  if ( tmpWS->isHistogramData() )
  {
    VectorHelper::convertToBinCentre(tmpWS->readX(0),outputWS->dataX(0));
  }
  else
  {
    outputWS->setX(0,tmpWS->refX(0));
  }
  MantidVec& Y = outputWS->dataY(0) = tmpWS->dataY(0);
  outputWS->dataE(0) = tmpWS->dataE(0);

  // Subtract a constant background if requested
  const double background = getProperty("BackgroundValue");
  if ( background > 0.0 ) subtractBackgroundValue(Y,background);

  // Select the desired transformation function and call it
  TransformFunc f = m_transforms.find(getProperty("TransformType"))->second;
  (this->*f)(outputWS);

  // Need the generic label unit on this (unless the unit on the X axis hasn't changed)
  if ( ! m_label->caption().empty() ) outputWS->getAxis(0)->unit() = m_label;
  setProperty("OutputWorkspace",outputWS);
}
Ejemplo n.º 9
0
void NormaliseToMonitor::exec() {
  // Get the input workspace
  const MatrixWorkspace_sptr inputWS = getProperty("InputWorkspace");
  MatrixWorkspace_sptr outputWS = getProperty("OutputWorkspace");
  // First check the inputs
  checkProperties(inputWS);

  bool isSingleCountWorkspace = false;
  try {
    isSingleCountWorkspace =
        (!inputWS->isHistogramData()) && (inputWS->blocksize() == 1);
  } catch (std::length_error &) {
    // inconsistent bin size, not a single count workspace
    isSingleCountWorkspace = false;
  }

  // See if the normalization with integration properties are set.
  const bool integrate = setIntegrationProps(isSingleCountWorkspace);

  if (integrate)
    normaliseByIntegratedCount(inputWS, outputWS, isSingleCountWorkspace);
  else
    normaliseBinByBin(inputWS, outputWS);

  setProperty("OutputWorkspace", outputWS);
  std::string norm_ws_name = getPropertyValue("NormFactorWS");
  if (!norm_ws_name.empty()) {
    std::string out_name = getPropertyValue("OutputWorkspace");
    if (out_name == norm_ws_name) {
      // if the normalization factor workspace name coincides with output
      // workspace name, add _normFactor suffix to this name
      norm_ws_name = norm_ws_name + "_normFactor";
      auto pProp = (this->getPointerToProperty("NormFactorWS"));
      pProp->setValue(norm_ws_name);
    }
    if (!integrate)
      m_monitor = extractMonitorSpectra(m_monitor, m_workspaceIndexes);
    setProperty("NormFactorWS", m_monitor);
  }
}
Ejemplo n.º 10
0
void FFTDerivative::execRealFFT()
{

  MatrixWorkspace_sptr inWS = getProperty("InputWorkspace");
  MatrixWorkspace_sptr outWS;

  size_t n = inWS->getNumberHistograms();
  API::Progress progress(this,0,1,n);

  size_t ny = inWS->readY(0).size();
  size_t nx = inWS->readX(0).size();

  // Workspace for holding a copy of a spectrum. Each spectrum is symmetrized to minimize
  // possible edge effects.
  MatrixWorkspace_sptr copyWS = boost::dynamic_pointer_cast<Mantid::API::MatrixWorkspace>
    (Mantid::API::WorkspaceFactory::Instance().create(inWS,1,nx+ny,ny+ny));

  bool isHist = (nx != ny);

  for(size_t spec = 0; spec < n; ++spec)
  {

    const Mantid::MantidVec& x0 = inWS->readX(spec);
    const Mantid::MantidVec& y0 = inWS->readY(spec);

    Mantid::MantidVec& x1 = copyWS->dataX(0);
    Mantid::MantidVec& y1 = copyWS->dataY(0);

    double xx = 2*x0[0];

    x1[ny] = x0[0];
    y1[ny] = y0[0];

    for(size_t i = 1; i < ny; ++i)
    {
      size_t j1 = ny - i;
      size_t j2 = ny + i;
      x1[j1] = xx - x0[i];
      x1[j2] = x0[i];
      y1[j1] = y1[j2] = y0[i];
    }

    x1[0] = 2*x1[1] - x1[2];
    y1[0] = y0.back();

    if (isHist)
    {
      x1[y1.size()] = x0[ny];
    }

    // Transform symmetrized spectrum
    IAlgorithm_sptr fft = createChildAlgorithm("RealFFT");
    fft->setProperty("InputWorkspace",copyWS);
    fft->setProperty("WorkspaceIndex",0);
    fft->setProperty("Transform","Forward");
    fft->execute();

    MatrixWorkspace_sptr transWS = fft->getProperty("OutputWorkspace");

    Mantid::MantidVec& nu = transWS->dataX(0);
    Mantid::MantidVec& re = transWS->dataY(0);
    Mantid::MantidVec& im = transWS->dataY(1);

    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;
      }
    }

    // Inverse transform
    fft = createChildAlgorithm("RealFFT");
    fft->setProperty("InputWorkspace",transWS);
    fft->setProperty("Transform","Backward");
    fft->execute();

    transWS = fft->getProperty("OutputWorkspace");

    size_t m2 = transWS->readY(0).size() / 2;
    size_t my = m2 + ((transWS->readY(0).size() % 2) ? 1 : 0);
    size_t mx = my + (transWS->isHistogramData() ? 1 : 0);

    if (!outWS)
    {
      outWS = boost::dynamic_pointer_cast<Mantid::API::MatrixWorkspace>
        (Mantid::API::WorkspaceFactory::Instance().create(inWS,n,mx,my));
    }

    // Save the upper half of the inverse transform for output
    Mantid::MantidVec& x = outWS->dataX(spec);
    Mantid::MantidVec& y = outWS->dataY(spec);
    double dx = x1[0];
    std::copy(transWS->dataX(0).begin() + m2,transWS->dataX(0).end(),x.begin());
    std::transform(x.begin(),x.end(),x.begin(),std::bind2nd(std::plus<double>(),dx));
    std::copy(transWS->dataY(0).begin() + m2,transWS->dataY(0).end(),y.begin());

    // shift the data to make x and x0 match. using linear interpolation.
    if (x.size() != x0.size() && false)// TODO: doesn't work at the moment. needs to be working
    {
      std::cerr << "(my != x0.size()) " << x0[0] << "!=" << x[0] << std::endl;
      dx = x0[0] - x[0];
      assert(dx > 0.0);
      double f = (x0[0] - x[0]) / (x0[1] - x0[0]);
      for(size_t i = 0; i < my - 1; ++i)
      {
        y[i] += (y[i+1] - y[i]) * f;
        x[i] = x0[i];
      }
      x.back() += dx;

    }

    progress.report();

  }

  setProperty("OutputWorkspace",outWS);

}
Ejemplo n.º 11
0
/** Execute the algorithm.
 */
void ResampleX::exec() {
  // generically having access to the input workspace is a good idea
  MatrixWorkspace_sptr inputWS = getProperty("InputWorkspace");
  MatrixWorkspace_sptr outputWS = getProperty("OutputWorkspace");
  bool inPlace = (inputWS == outputWS); // Rebinning in-place
  m_isDistribution = inputWS->isDistribution();
  m_isHistogram = inputWS->isHistogramData();
  const int numSpectra = static_cast<int>(inputWS->getNumberHistograms());

  // the easy parameters
  m_useLogBinning = getProperty("LogBinning");
  m_numBins = getProperty("NumberBins");
  m_preserveEvents = getProperty("PreserveEvents");

  // determine the xmin/xmax for the workspace
  vector<double> xmins = getProperty("XMin");
  vector<double> xmaxs = getProperty("XMax");
  string error = determineXMinMax(inputWS, xmins, xmaxs);
  if (!error.empty())
    throw std::runtime_error(error);

  bool common_limits = true;
  {
    double xmin_common = xmins[0];
    double xmax_common = xmaxs[0];
    for (size_t i = 1; i < xmins.size(); ++i) {
      if (xmins[i] != xmin_common) {
        common_limits = false;
        break;
      }
      if (xmaxs[i] != xmax_common) {
        common_limits = false;
        break;
      }
    }
  }
  if (common_limits) {
    g_log.debug() << "Common limits between all spectra\n";
  } else {
    g_log.debug() << "Does not have common limits between all spectra\n";
  }

  // start doing actual work
  EventWorkspace_const_sptr inputEventWS =
      boost::dynamic_pointer_cast<const EventWorkspace>(inputWS);
  if (inputEventWS != nullptr) {
    if (m_preserveEvents) {
      if (inPlace) {
        g_log.debug() << "Rebinning event workspace in place\n";
      } else {
        g_log.debug() << "Rebinning event workspace out of place\n";
        outputWS = inputWS->clone();
      }
      auto outputEventWS =
          boost::dynamic_pointer_cast<EventWorkspace>(outputWS);

      if (common_limits) {
        // get the delta from the first since they are all the same
        BinEdges xValues(0);
        const double delta = this->determineBinning(xValues.mutableRawData(),
                                                    xmins[0], xmaxs[0]);
        g_log.debug() << "delta = " << delta << "\n";
        outputEventWS->setAllX(xValues);
      } else {
        // initialize progress reporting.
        Progress prog(this, 0.0, 1.0, numSpectra);

        // do the rebinning
        PARALLEL_FOR_IF(Kernel::threadSafe(*inputEventWS, *outputWS))
        for (int wkspIndex = 0; wkspIndex < numSpectra; ++wkspIndex) {
          PARALLEL_START_INTERUPT_REGION
          BinEdges xValues(0);
          const double delta = this->determineBinning(
              xValues.mutableRawData(), xmins[wkspIndex], xmaxs[wkspIndex]);
          g_log.debug() << "delta[wkspindex=" << wkspIndex << "] = " << delta
                        << " xmin=" << xmins[wkspIndex]
                        << " xmax=" << xmaxs[wkspIndex] << "\n";
          outputEventWS->setHistogram(wkspIndex, xValues);
          prog.report(name()); // Report progress
          PARALLEL_END_INTERUPT_REGION
        }
        PARALLEL_CHECK_INTERUPT_REGION
      }
    }    // end if (m_preserveEvents)
    else // event workspace -> matrix workspace
    {
      //--------- Different output, OR you're inplace but not preserving Events
      g_log.information() << "Creating a Workspace2D from the EventWorkspace "
                          << inputEventWS->getName() << ".\n";
      outputWS = create<DataObjects::Workspace2D>(
          *inputWS, numSpectra, HistogramData::BinEdges(m_numBins + 1));

      // Initialize progress reporting.
      Progress prog(this, 0.0, 1.0, numSpectra);

      // Go through all the histograms and set the data
      PARALLEL_FOR_IF(Kernel::threadSafe(*inputEventWS, *outputWS))
      for (int wkspIndex = 0; wkspIndex < numSpectra; ++wkspIndex) {
        PARALLEL_START_INTERUPT_REGION

        // Set the X axis for each output histogram
        MantidVec xValues;
        const double delta =
            this->determineBinning(xValues, xmins[wkspIndex], xmaxs[wkspIndex]);
        g_log.debug() << "delta[wkspindex=" << wkspIndex << "] = " << delta
                      << "\n";
        outputWS->setBinEdges(wkspIndex, xValues);

        // Get a const event list reference. inputEventWS->dataY() doesn't work.
        const EventList &el = inputEventWS->getSpectrum(wkspIndex);
        MantidVec y_data, e_data;
        // The EventList takes care of histogramming.
        el.generateHistogram(xValues, y_data, e_data);

        // Copy the data over.
        outputWS->mutableY(wkspIndex) = std::move(y_data);
        outputWS->mutableE(wkspIndex) = std::move(e_data);

        // Report progress
        prog.report(name());
        PARALLEL_END_INTERUPT_REGION
      }
      PARALLEL_CHECK_INTERUPT_REGION

      // Copy all the axes
      for (int i = 1; i < inputWS->axes(); i++) {
        outputWS->replaceAxis(i, inputWS->getAxis(i)->clone(outputWS.get()));
        outputWS->getAxis(i)->unit() = inputWS->getAxis(i)->unit();
      }

      // Copy the units over too.
      for (int i = 0; i < outputWS->axes(); ++i) {
        outputWS->getAxis(i)->unit() = inputWS->getAxis(i)->unit();
      }
      outputWS->setYUnit(inputEventWS->YUnit());
      outputWS->setYUnitLabel(inputEventWS->YUnitLabel());
    }
    // Assign it to the output workspace property
    setProperty("OutputWorkspace", outputWS);
    return;
  } else // (inputeventWS != NULL)
void TOFSANSResolutionByPixel::exec() {
  MatrixWorkspace_sptr inOutWS = getProperty("Workspace");
  double deltaR = getProperty("DeltaR");
  double R1 = getProperty("SourceApertureRadius");
  double R2 = getProperty("SampleApertureRadius");
  // Convert to meters
  deltaR /= 1000.0;
  R1 /= 1000.0;
  R2 /= 1000.0;

  const MatrixWorkspace_sptr sigmaModeratorVSwavelength =
      getProperty("SigmaModerator");

  // create interpolation table from sigmaModeratorVSwavelength
  Kernel::Interpolation lookUpTable;

  const MantidVec xInterpolate = sigmaModeratorVSwavelength->readX(0);
  const MantidVec yInterpolate = sigmaModeratorVSwavelength->readY(0);

  // prefer the input to be a pointworkspace and create interpolation function
  if (sigmaModeratorVSwavelength->isHistogramData()) {
    g_log.notice() << "mid-points of SigmaModerator histogram bins will be "
                      "used for interpolation.";

    for (size_t i = 0; i < xInterpolate.size() - 1; ++i) {
      const double midpoint = xInterpolate[i + 1] - xInterpolate[i];
      lookUpTable.addPoint(midpoint, yInterpolate[i]);
    }
  } else {
    for (size_t i = 0; i < xInterpolate.size(); ++i) {
      lookUpTable.addPoint(xInterpolate[i], yInterpolate[i]);
    }
  }

  const V3D samplePos = inOutWS->getInstrument()->getSample()->getPos();
  const V3D sourcePos = inOutWS->getInstrument()->getSource()->getPos();
  const V3D SSD = samplePos - sourcePos;
  const double L1 = SSD.norm();

  const int numberOfSpectra = static_cast<int>(inOutWS->getNumberHistograms());
  Progress progress(this, 0.0, 1.0, numberOfSpectra);

  for (int i = 0; i < numberOfSpectra; i++) {
    IDetector_const_sptr det;
    try {
      det = inOutWS->getDetector(i);
    } catch (Exception::NotFoundError &) {
      g_log.information() << "Spectrum index " << i
                          << " has no detector assigned to it - discarding"
                          << std::endl;
    }
    // If no detector found or if it's masked or a monitor, skip onto the next
    // spectrum
    if (!det || det->isMonitor() || det->isMasked())
      continue;

    // Get the flight path from the sample to the detector pixel
    const V3D scatteredFlightPathV3D = det->getPos() - samplePos;

    const double L2 = scatteredFlightPathV3D.norm();
    const double Lsum = L1 + L2;

    // calculate part that is wavelenght independent
    const double dTheta2 = (4.0 * M_PI * M_PI / 12.0) *
                           (3.0 * R1 * R1 / (L1 * L1) +
                            3.0 * R2 * R2 * Lsum * Lsum / (L1 * L1 * L2 * L2) +
                            (deltaR * deltaR) / (L2 * L2));

    // Multiplicative factor to go from lambda to Q
    // Don't get fooled by the function name...
    const double theta = inOutWS->detectorTwoTheta(det);
    const double factor = 4.0 * M_PI * sin(theta / 2.0);

    const MantidVec &xIn = inOutWS->readX(i);
    MantidVec &yIn = inOutWS->dataY(i);
    const size_t xLength = xIn.size();

    // for each wavelenght bin of each pixel calculate a q-resolution
    for (size_t j = 0; j < xLength - 1; j++) {
      // use the midpoint of each bin
      const double wl = (xIn[j + 1] + xIn[j]) / 2.0;
      // Calculate q. Alternatively q could be calculated using ConvertUnit
      const double q = factor / wl;

      // wavelenght spread from bin assumed to be
      const double sigmaSpreadFromBin = xIn[j + 1] - xIn[j];

      // wavelenght spread from moderatorm, converted from microseconds to
      // wavelengths
      const double sigmaModerator =
          lookUpTable.value(wl) * 3.9560 / (1000.0 * Lsum);

      // calculate wavelenght resolution from moderator and histogram time bin
      const double sigmaLambda =
          std::sqrt(sigmaSpreadFromBin * sigmaSpreadFromBin / 12.0 +
                    sigmaModerator * sigmaModerator);

      // calculate sigmaQ for a given lambda and pixel
      const double sigmaOverLambdaTimesQ = q * sigmaLambda / wl;
      const double sigmaQ = std::sqrt(
          dTheta2 / (wl * wl) + sigmaOverLambdaTimesQ * sigmaOverLambdaTimesQ);

      // update inout workspace with this sigmaQ
      yIn[j] = sigmaQ;
    }

    progress.report("Computing Q resolution");
  }
}
Ejemplo n.º 13
0
/** Execute the algorithm.
 */
void ResampleX::exec() {
  // generically having access to the input workspace is a good idea
  MatrixWorkspace_sptr inputWS = getProperty("InputWorkspace");
  MatrixWorkspace_sptr outputWS = getProperty("OutputWorkspace");
  bool inPlace = (inputWS == outputWS); // Rebinning in-place
  m_isDistribution = inputWS->isDistribution();
  m_isHistogram = inputWS->isHistogramData();
  int numSpectra = static_cast<int>(inputWS->getNumberHistograms());

  // the easy parameters
  m_useLogBinning = getProperty("LogBinning");
  m_numBins = getProperty("NumberBins");
  m_preserveEvents = getProperty("PreserveEvents");

  // determine the xmin/xmax for the workspace
  vector<double> xmins = getProperty("XMin");
  vector<double> xmaxs = getProperty("XMax");
  string error = determineXMinMax(inputWS, xmins, xmaxs);
  if (!error.empty())
    throw std::runtime_error(error);

  bool common_limits = true;
  {
    double xmin_common = xmins[0];
    double xmax_common = xmaxs[0];
    for (size_t i = 1; i < xmins.size(); ++i) {
      if (xmins[i] != xmin_common) {
        common_limits = false;
        break;
      }
      if (xmaxs[i] != xmax_common) {
        common_limits = false;
        break;
      }
    }
  }
  if (common_limits) {
    g_log.debug() << "Common limits between all spectra\n";
  } else {
    g_log.debug() << "Does not have common limits between all spectra\n";
  }

  // start doing actual work
  EventWorkspace_const_sptr inputEventWS =
      boost::dynamic_pointer_cast<const EventWorkspace>(inputWS);
  if (inputEventWS != NULL) {
    if (m_preserveEvents) {
      EventWorkspace_sptr outputEventWS =
          boost::dynamic_pointer_cast<EventWorkspace>(outputWS);
      if (inPlace) {
        g_log.debug() << "Rebinning event workspace in place\n";
      } else {
        g_log.debug() << "Rebinning event workspace out of place\n";

        // copy the event workspace to a new EventWorkspace
        outputEventWS = boost::dynamic_pointer_cast<EventWorkspace>(
            API::WorkspaceFactory::Instance().create(
                "EventWorkspace", inputWS->getNumberHistograms(), 2, 1));
        // copy geometry over.
        API::WorkspaceFactory::Instance().initializeFromParent(
            inputEventWS, outputEventWS, false);
        // copy over the data as well.
        outputEventWS->copyDataFrom((*inputEventWS));
      }

      if (common_limits) {
        // get the delta from the first since they are all the same
        MantidVecPtr xValues;
        double delta =
            this->determineBinning(xValues.access(), xmins[0], xmaxs[0]);
        g_log.debug() << "delta = " << delta << "\n";
        outputEventWS->setAllX(xValues);
      } else {
        // initialize progress reporting.
        Progress prog(this, 0.0, 1.0, numSpectra);

        // do the rebinning
        PARALLEL_FOR2(inputEventWS, outputWS)
        for (int wkspIndex = 0; wkspIndex < numSpectra; ++wkspIndex) {
          PARALLEL_START_INTERUPT_REGION
          MantidVec xValues;
          double delta = this->determineBinning(xValues, xmins[wkspIndex],
                                                xmaxs[wkspIndex]);
          g_log.debug() << "delta[wkspindex=" << wkspIndex << "] = " << delta
                        << " xmin=" << xmins[wkspIndex]
                        << " xmax=" << xmaxs[wkspIndex] << "\n";
          outputEventWS->getSpectrum(wkspIndex)->setX(xValues);
          prog.report(name()); // Report progress
          PARALLEL_END_INTERUPT_REGION
        }
        PARALLEL_CHECK_INTERUPT_REGION
      }

      this->setProperty(
          "OutputWorkspace",
          boost::dynamic_pointer_cast<MatrixWorkspace>(outputEventWS));
    }    // end if (m_preserveEvents)
    else // event workspace -> matrix workspace
    {
      //--------- Different output, OR you're inplace but not preserving Events
      //--- create a Workspace2D -------
      g_log.information() << "Creating a Workspace2D from the EventWorkspace "
                          << inputEventWS->getName() << ".\n";

      // Create a Workspace2D
      // This creates a new Workspace2D through a torturous route using the
      // WorkspaceFactory.
      // The Workspace2D is created with an EMPTY CONSTRUCTOR
      outputWS = WorkspaceFactory::Instance().create("Workspace2D", numSpectra,
                                                     m_numBins, m_numBins - 1);
      WorkspaceFactory::Instance().initializeFromParent(inputWS, outputWS,
                                                        true);
      // Initialize progress reporting.
      Progress prog(this, 0.0, 1.0, numSpectra);

      // Go through all the histograms and set the data
      PARALLEL_FOR2(inputEventWS, outputWS)
      for (int wkspIndex = 0; wkspIndex < numSpectra; ++wkspIndex) {
        PARALLEL_START_INTERUPT_REGION

        // Set the X axis for each output histogram
        MantidVec xValues;
        double delta =
            this->determineBinning(xValues, xmins[wkspIndex], xmaxs[wkspIndex]);
        g_log.debug() << "delta[wkspindex=" << wkspIndex << "] = " << delta
                      << "\n";
        outputWS->setX(wkspIndex, xValues);

        // Get a const event list reference. inputEventWS->dataY() doesn't work.
        const EventList &el = inputEventWS->getEventList(wkspIndex);
        MantidVec y_data, e_data;
        // The EventList takes care of histogramming.
        el.generateHistogram(xValues, y_data, e_data);

        // Copy the data over.
        outputWS->dataY(wkspIndex).assign(y_data.begin(), y_data.end());
        outputWS->dataE(wkspIndex).assign(e_data.begin(), e_data.end());

        // Report progress
        prog.report(name());
        PARALLEL_END_INTERUPT_REGION
      }
      PARALLEL_CHECK_INTERUPT_REGION

      // Copy all the axes
      for (int i = 1; i < inputWS->axes(); i++) {
        outputWS->replaceAxis(i, inputWS->getAxis(i)->clone(outputWS.get()));
        outputWS->getAxis(i)->unit() = inputWS->getAxis(i)->unit();
      }

      // Copy the units over too.
      for (int i = 0; i < outputWS->axes(); ++i)
        outputWS->getAxis(i)->unit() = inputWS->getAxis(i)->unit();
      outputWS->setYUnit(inputEventWS->YUnit());
      outputWS->setYUnitLabel(inputEventWS->YUnitLabel());

      // Assign it to the output workspace property
      setProperty("OutputWorkspace", outputWS);
    }
    return;
  } else // (inputeventWS != NULL)
Ejemplo n.º 14
0
void TOFSANSResolutionByPixel::exec() {
  MatrixWorkspace_sptr inWS = getProperty("InputWorkspace");
  double deltaR = getProperty("DeltaR");
  double R1 = getProperty("SourceApertureRadius");
  double R2 = getProperty("SampleApertureRadius");
  const bool doGravity = getProperty("AccountForGravity");

  // Check the input
  checkInput(inWS);

  // Setup outputworkspace
  auto outWS = setupOutputWorkspace(inWS);

  // Convert to meters
  deltaR /= 1000.0;
  R1 /= 1000.0;
  R2 /= 1000.0;

  // The moderator workspace needs to match the data workspace
  // in terms of wavelength binning
  const MatrixWorkspace_sptr sigmaModeratorVSwavelength =
      getModeratorWorkspace(inWS);

  // create interpolation table from sigmaModeratorVSwavelength
  Kernel::Interpolation lookUpTable;

  const auto &xInterpolate = sigmaModeratorVSwavelength->points(0);
  const auto &yInterpolate = sigmaModeratorVSwavelength->y(0);

  // prefer the input to be a pointworkspace and create interpolation function
  if (sigmaModeratorVSwavelength->isHistogramData()) {
    g_log.notice() << "mid-points of SigmaModerator histogram bins will be "
                      "used for interpolation.";
  }

  for (size_t i = 0; i < xInterpolate.size(); ++i) {
    lookUpTable.addPoint(xInterpolate[i], yInterpolate[i]);
  }

  // Calculate the L1 distance
  const V3D samplePos = inWS->getInstrument()->getSample()->getPos();
  const V3D sourcePos = inWS->getInstrument()->getSource()->getPos();
  const V3D SSD = samplePos - sourcePos;
  const double L1 = SSD.norm();

  // Get the collimation length
  double LCollim = getProperty("CollimationLength");

  if (LCollim == 0.0) {
    auto collimationLengthEstimator = SANSCollimationLengthEstimator();
    LCollim = collimationLengthEstimator.provideCollimationLength(inWS);
    g_log.information() << "No collimation length was specified. A default "
                           "collimation length was estimated to be " << LCollim
                        << '\n';
  } else {
    g_log.information() << "The collimation length is  " << LCollim << '\n';
  }

  const int numberOfSpectra = static_cast<int>(inWS->getNumberHistograms());
  Progress progress(this, 0.0, 1.0, numberOfSpectra);

  const auto &spectrumInfo = inWS->spectrumInfo();
  for (int i = 0; i < numberOfSpectra; i++) {
    IDetector_const_sptr det;
    if (!spectrumInfo.hasDetectors(i)) {
      g_log.information() << "Workspace index " << i
                          << " has no detector assigned to it - discarding\n";
      continue;
    }
    // If no detector found or if it's masked or a monitor, skip onto the next
    // spectrum
    if (spectrumInfo.isMonitor(i) || spectrumInfo.isMasked(i))
      continue;

    const double L2 = spectrumInfo.l2(i);
    TOFSANSResolutionByPixelCalculator calculator;
    const double waveLengthIndependentFactor =
        calculator.getWavelengthIndependentFactor(R1, R2, deltaR, LCollim, L2);

    // Multiplicative factor to go from lambda to Q
    // Don't get fooled by the function name...
    const double theta = spectrumInfo.twoTheta(i);
    double sinTheta = sin(0.5 * theta);
    double factor = 4.0 * M_PI * sinTheta;

    const auto &xIn = inWS->x(i);
    const size_t xLength = xIn.size();

    // Gravity correction
    std::unique_ptr<GravitySANSHelper> grav;
    if (doGravity) {
      grav = Kernel::make_unique<GravitySANSHelper>(spectrumInfo, i,
                                                    getProperty("ExtraLength"));
    }

    // Get handles on the outputWorkspace
    auto &yOut = outWS->mutableY(i);
    // for each wavelenght bin of each pixel calculate a q-resolution
    for (size_t j = 0; j < xLength - 1; j++) {
      // use the midpoint of each bin
      const double wl = (xIn[j + 1] + xIn[j]) / 2.0;
      // Calculate q. Alternatively q could be calculated using ConvertUnit
      // If we include a gravity correction we need to adjust sinTheta
      // for each wavelength (in Angstrom)
      if (doGravity) {
        double sinThetaGrav = grav->calcSinTheta(wl);
        factor = 4.0 * M_PI * sinThetaGrav;
      }
      const double q = factor / wl;

      // wavelenght spread from bin assumed to be
      const double sigmaSpreadFromBin = xIn[j + 1] - xIn[j];

      // Get the uncertainty in Q
      auto sigmaQ = calculator.getSigmaQValue(lookUpTable.value(wl),
                                              waveLengthIndependentFactor, q,
                                              wl, sigmaSpreadFromBin, L1, L2);

      // Insert the Q value and the Q resolution into the outputworkspace
      yOut[j] = sigmaQ;
    }
    progress.report("Computing Q resolution");
  }

  // Set the y axis label
  outWS->setYUnitLabel("QResolution");

  setProperty("OutputWorkspace", outWS);
}
Ejemplo n.º 15
0
/** Populates the output workspaces
* @param inWS :: [input] The input workspace
* @param spec :: [input] The current spectrum being analyzed
* @param nspec :: [input] The total number of histograms in the input workspace
* @param result :: [input] The result to be written in the output workspace
* @param outWS :: [input] The output workspace to populate
* @param autoShift :: [input] Whether or not to correct the phase shift
*/
void MaxEnt::populateImageWS(const MatrixWorkspace_sptr &inWS, size_t spec,
                             size_t nspec, const std::vector<double> &result,
                             MatrixWorkspace_sptr &outWS, bool autoShift) {

  if (result.size() % 2)
    throw std::invalid_argument("Cannot write results to output workspaces");

  int npoints = static_cast<int>(result.size() / 2);
  int npointsX = inWS->isHistogramData() ? npoints + 1 : npoints;
  MantidVec X(npointsX);
  MantidVec YR(npoints);
  MantidVec YI(npoints);
  MantidVec E(npoints, 0.);

  double x0 = inWS->readX(spec)[0];
  double dx = inWS->readX(spec)[1] - x0;

  double delta = 1. / dx / npoints;
  int isOdd = (inWS->blocksize() % 2) ? 1 : 0;

  double shift = x0 * 2 * M_PI;
  if (!autoShift)
    shift = 0;

  for (int i = 0; i < npoints; i++) {
    int j = (npoints / 2 + i + isOdd) % npoints;
    X[i] = delta * (-npoints / 2 + i);

    double xShift = X[i] * shift;
    double c = cos(xShift);
    double s = sin(xShift);
    YR[i] = result[2 * j] * c - result[2 * j + 1] * s;
    YI[i] = result[2 * j] * s + result[2 * j + 1] * c;
    YR[i] *= dx;
    YI[i] *= dx;
  }
  if (npointsX == npoints + 1)
    X[npoints] = X[npoints - 1] + delta;

  // Caption & label
  auto inputUnit = inWS->getAxis(0)->unit();
  if (inputUnit) {
    boost::shared_ptr<Kernel::Units::Label> lblUnit =
        boost::dynamic_pointer_cast<Kernel::Units::Label>(
            UnitFactory::Instance().create("Label"));
    if (lblUnit) {

      lblUnit->setLabel(
          inverseCaption[inWS->getAxis(0)->unit()->caption()],
          inverseLabel[inWS->getAxis(0)->unit()->label().ascii()]);
      outWS->getAxis(0)->unit() = lblUnit;
    }
  }

  outWS->dataX(spec).assign(X.begin(), X.end());
  outWS->dataY(spec).assign(YR.begin(), YR.end());
  outWS->dataE(spec).assign(E.begin(), E.end());
  outWS->dataX(nspec + spec).assign(X.begin(), X.end());
  outWS->dataY(nspec + spec).assign(YI.begin(), YI.end());
  outWS->dataE(nspec + spec).assign(E.begin(), E.end());
}
Ejemplo n.º 16
0
/** Execute the algorithm.
 */
void MaxEnt::exec() {

  // MaxEnt parameters
  // Complex data?
  bool complex = getProperty("ComplexData");
  // Image must be positive?
  bool positiveImage = getProperty("PositiveImage");
  // Autoshift
  bool autoShift = getProperty("AutoShift");
  // Increase the number of points in the image by this factor
  size_t densityFactor = getProperty("DensityFactor");
  // Background (default level, sky background, etc)
  double background = getProperty("A");
  // Chi target
  double chiTarget = getProperty("ChiTarget");
  // Required precision for Chi arget
  double chiEps = getProperty("ChiEps");
  // Maximum degree of non-parallelism between S and C
  double angle = getProperty("MaxAngle");
  // Distance penalty for current image
  double distEps = getProperty("DistancePenalty");
  // Maximum number of iterations
  size_t niter = getProperty("MaxIterations");
  // Maximum number of iterations in alpha chop
  size_t alphaIter = getProperty("AlphaChopIterations");
  // Number of spectra and datapoints
  // Read input workspace
  MatrixWorkspace_sptr inWS = getProperty("InputWorkspace");
  // Number of spectra
  size_t nspec = inWS->getNumberHistograms();
  // Number of data points
  size_t npoints = inWS->blocksize() * densityFactor;
  // Number of X bins
  size_t npointsX = inWS->isHistogramData() ? npoints + 1 : npoints;

  // The type of entropy we are going to use (depends on the type of image,
  // positive only, or positive and/or negative)
  MaxentData_sptr maxentData;
  if (positiveImage) {
    maxentData = boost::make_shared<MaxentData>(
        boost::make_shared<MaxentEntropyPositiveValues>());
  } else {
    maxentData = boost::make_shared<MaxentData>(
        boost::make_shared<MaxentEntropyNegativeValues>());
  }

  // Output workspaces
  MatrixWorkspace_sptr outImageWS;
  MatrixWorkspace_sptr outDataWS;
  MatrixWorkspace_sptr outEvolChi;
  MatrixWorkspace_sptr outEvolTest;

  nspec = complex ? nspec / 2 : nspec;
  outImageWS =
      WorkspaceFactory::Instance().create(inWS, 2 * nspec, npointsX, npoints);
  outDataWS =
      WorkspaceFactory::Instance().create(inWS, 2 * nspec, npointsX, npoints);
  outEvolChi = WorkspaceFactory::Instance().create(inWS, nspec, niter, niter);
  outEvolTest = WorkspaceFactory::Instance().create(inWS, nspec, niter, niter);

  npoints *= 2;
  for (size_t s = 0; s < nspec; s++) {

    // Start distribution (flat background)
    std::vector<double> image(npoints, background);

    if (complex) {
      auto dataRe = inWS->readY(s);
      auto dataIm = inWS->readY(s + nspec);
      auto errorsRe = inWS->readE(s);
      auto errorsIm = inWS->readE(s + nspec);
      maxentData->loadComplex(dataRe, dataIm, errorsRe, errorsIm, image,
                              background);
    } else {
      auto data = inWS->readY(s);
      auto error = inWS->readE(s);
      maxentData->loadReal(data, error, image, background);
    }

    // To record the algorithm's progress
    std::vector<double> evolChi(niter, 0.);
    std::vector<double> evolTest(niter, 0.);

    // Progress
    Progress progress(this, 0, 1, niter);

    // Run maxent algorithm
    for (size_t it = 0; it < niter; it++) {

      // Calculate quadratic model coefficients
      // (SB eq. 21 and 24)
      maxentData->calculateQuadraticCoefficients();
      double currAngle = maxentData->getAngle();
      double currChisq = maxentData->getChisq();
      auto coeffs = maxentData->getQuadraticCoefficients();

      // Calculate delta to construct new image (SB eq. 25)
      auto delta = move(coeffs, chiTarget / currChisq, chiEps, alphaIter);

      // Apply distance penalty (SB eq. 33)
      image = maxentData->getImage();
      delta = applyDistancePenalty(delta, coeffs, image, background, distEps);

      // Update image according to 'delta' and calculate the new Chi-square
      maxentData->updateImage(delta);
      currChisq = maxentData->getChisq();

      // Record the evolution of Chi-square and angle(S,C)
      evolChi[it] = currChisq;
      evolTest[it] = currAngle;

      // Stop condition, solution found
      if ((std::abs(currChisq / chiTarget - 1.) < chiEps) &&
          (currAngle < angle)) {
        break;
      }

      // Check for canceling the algorithm
      if (!(it % 1000)) {
        interruption_point();
      }

      progress.report();

    } // iterations

    // Get calculated data
    auto solData = maxentData->getReconstructedData();
    auto solImage = maxentData->getImage();

    // Populate the output workspaces
    populateDataWS(inWS, s, nspec, solData, outDataWS);
    populateImageWS(inWS, s, nspec, solImage, outImageWS, autoShift);

    // Populate workspaces recording the evolution of Chi and Test
    // X values
    for (size_t it = 0; it < niter; it++) {
      outEvolChi->dataX(s)[it] = static_cast<double>(it);
      outEvolTest->dataX(s)[it] = static_cast<double>(it);
    }
    // Y values
    outEvolChi->dataY(s).assign(evolChi.begin(), evolChi.end());
    outEvolTest->dataY(s).assign(evolTest.begin(), evolTest.end());
    // No errors

  } // Next spectrum

  setProperty("EvolChi", outEvolChi);
  setProperty("EvolAngle", outEvolTest);
  setProperty("ReconstructedImage", outImageWS);
  setProperty("ReconstructedData", outDataWS);
}
Ejemplo n.º 17
0
/** Executes the rebin algorithm
*
*  @throw runtime_error Thrown if the bin range does not intersect the range of
*the input workspace
*/
void Rebin::exec() {
  // Get the input workspace
  MatrixWorkspace_sptr inputWS = getProperty("InputWorkspace");
  MatrixWorkspace_sptr outputWS = getProperty("OutputWorkspace");

  // Are we preserving event workspace-iness?
  bool PreserveEvents = getProperty("PreserveEvents");

  // Rebinning in-place
  bool inPlace = (inputWS == outputWS);

  std::vector<double> rbParams =
      rebinParamsFromInput(getProperty("Params"), *inputWS, g_log);

  const bool dist = inputWS->isDistribution();
  const bool isHist = inputWS->isHistogramData();

  // workspace independent determination of length
  const int histnumber = static_cast<int>(inputWS->getNumberHistograms());

  //-------------------------------------------------------

  bool fullBinsOnly = getProperty("FullBinsOnly");

  MantidVecPtr XValues_new;
  // create new output X axis
  const int ntcnew = VectorHelper::createAxisFromRebinParams(
      rbParams, XValues_new.access(), true, fullBinsOnly);

  //---------------------------------------------------------------------------------
  // Now, determine if the input workspace is actually an EventWorkspace
  EventWorkspace_const_sptr eventInputWS =
      boost::dynamic_pointer_cast<const EventWorkspace>(inputWS);

  if (eventInputWS != NULL) {
    //------- EventWorkspace as input -------------------------------------
    EventWorkspace_sptr eventOutputWS =
        boost::dynamic_pointer_cast<EventWorkspace>(outputWS);

    if (inPlace && PreserveEvents) {
      // -------------Rebin in-place, preserving events
      // ----------------------------------------------
      // This only sets the X axis. Actual rebinning will be done upon data
      // access.
      eventOutputWS->setAllX(XValues_new);
      this->setProperty(
          "OutputWorkspace",
          boost::dynamic_pointer_cast<MatrixWorkspace>(eventOutputWS));
    } else if (!inPlace && PreserveEvents) {
      // -------- NOT in-place, but you want to keep events for some reason.
      // ----------------------
      // Must copy the event workspace to a new EventWorkspace (and bin that).

      // Make a brand new EventWorkspace
      eventOutputWS = boost::dynamic_pointer_cast<EventWorkspace>(
          API::WorkspaceFactory::Instance().create(
              "EventWorkspace", inputWS->getNumberHistograms(), 2, 1));
      // Copy geometry over.
      API::WorkspaceFactory::Instance().initializeFromParent(
          inputWS, eventOutputWS, false);
      // You need to copy over the data as well.
      eventOutputWS->copyDataFrom((*eventInputWS));

      // This only sets the X axis. Actual rebinning will be done upon data
      // access.
      eventOutputWS->setAllX(XValues_new);

      // Cast to the matrixOutputWS and save it
      this->setProperty(
          "OutputWorkspace",
          boost::dynamic_pointer_cast<MatrixWorkspace>(eventOutputWS));
    } else {
      //--------- Different output, OR you're inplace but not preserving Events
      //--- create a Workspace2D -------
      g_log.information() << "Creating a Workspace2D from the EventWorkspace "
                          << eventInputWS->getName() << ".\n";

      // Create a Workspace2D
      // This creates a new Workspace2D through a torturous route using the
      // WorkspaceFactory.
      // The Workspace2D is created with an EMPTY CONSTRUCTOR
      outputWS = WorkspaceFactory::Instance().create("Workspace2D", histnumber,
                                                     ntcnew, ntcnew - 1);
      WorkspaceFactory::Instance().initializeFromParent(inputWS, outputWS,
                                                        true);

      // Initialize progress reporting.
      Progress prog(this, 0.0, 1.0, histnumber);

      // Go through all the histograms and set the data
      PARALLEL_FOR3(inputWS, eventInputWS, outputWS)
      for (int i = 0; i < histnumber; ++i) {
        PARALLEL_START_INTERUPT_REGION

        // Set the X axis for each output histogram
        outputWS->setX(i, XValues_new);

        // Get a const event list reference. eventInputWS->dataY() doesn't work.
        const EventList &el = eventInputWS->getEventList(i);
        MantidVec y_data, e_data;
        // The EventList takes care of histogramming.
        el.generateHistogram(*XValues_new, y_data, e_data);

        // Copy the data over.
        outputWS->dataY(i).assign(y_data.begin(), y_data.end());
        outputWS->dataE(i).assign(e_data.begin(), e_data.end());

        // Report progress
        prog.report(name());
        PARALLEL_END_INTERUPT_REGION
      }
      PARALLEL_CHECK_INTERUPT_REGION

      // Copy all the axes
      for (int i = 1; i < inputWS->axes(); i++) {
        outputWS->replaceAxis(i, inputWS->getAxis(i)->clone(outputWS.get()));
        outputWS->getAxis(i)->unit() = inputWS->getAxis(i)->unit();
      }

      // Copy the units over too.
      for (int i = 0; i < outputWS->axes(); ++i)
        outputWS->getAxis(i)->unit() = inputWS->getAxis(i)->unit();
      outputWS->setYUnit(eventInputWS->YUnit());
      outputWS->setYUnitLabel(eventInputWS->YUnitLabel());

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

  } // END ---- EventWorkspace