Example #1
0
/** Converts an EventWorkspace to an equivalent Workspace2D
 * @param inputMatrixW :: input event workspace
 * @return a MatrixWorkspace_sptr
 */
MatrixWorkspace_sptr
EventWorkspaceHelpers::convertEventTo2D(MatrixWorkspace_sptr inputMatrixW) {
  EventWorkspace_sptr inputW =
      boost::dynamic_pointer_cast<EventWorkspace>(inputMatrixW);
  if (!inputW)
    throw std::invalid_argument("EventWorkspaceHelpers::convertEventTo2D(): "
                                "Input workspace is not an EventWorkspace.");

  size_t numBins = inputW->blocksize();

  // Make a workspace 2D version of it
  MatrixWorkspace_sptr outputW;
  outputW = WorkspaceFactory::Instance().create(
      "Workspace2D", inputW->getNumberHistograms(), numBins + 1, numBins);
  WorkspaceFactory::Instance().initializeFromParent(inputW, outputW, false);

  // Now let's set all the X bins and values
  for (size_t i = 0; i < inputW->getNumberHistograms(); i++) {
    outputW->getSpectrum(i).copyInfoFrom(inputW->getSpectrum(i));
    outputW->setX(i, inputW->refX(i));

    MantidVec &Yout = outputW->dataY(i);
    const MantidVec &Yin = inputW->readY(i);
    for (size_t j = 0; j < numBins; j++)
      Yout[j] = Yin[j];

    MantidVec &Eout = outputW->dataE(i);
    const MantidVec &Ein = inputW->readE(i);
    for (size_t j = 0; j < numBins; j++)
      Eout[j] = Ein[j];
  }

  return outputW;
}
Example #2
0
/** Creates the output workspace, setting the axes according to the input
 * binning parameters
 *  @param[in]  inputWorkspace The input workspace
 *  @param[in]  binParams The bin parameters from the user
 *  @param[out] newAxis        The 'vertical' axis defined by the given
 * parameters
 *  @return A pointer to the newly-created workspace
 */
API::MatrixWorkspace_sptr
SofQW::setUpOutputWorkspace(API::MatrixWorkspace_const_sptr inputWorkspace,
                            const std::vector<double> &binParams,
                            std::vector<double> &newAxis) {
  // Create vector to hold the new X axis values
  MantidVecPtr xAxis;
  xAxis.access() = inputWorkspace->readX(0);
  const int xLength = static_cast<int>(xAxis->size());
  // Create a vector to temporarily hold the vertical ('y') axis and populate
  // that
  const int yLength = static_cast<int>(
      VectorHelper::createAxisFromRebinParams(binParams, newAxis));

  // Create the output workspace
  MatrixWorkspace_sptr outputWorkspace = WorkspaceFactory::Instance().create(
      inputWorkspace, yLength - 1, xLength, xLength - 1);
  // Create a numeric axis to replace the default vertical one
  Axis *const verticalAxis = new BinEdgeAxis(newAxis);
  outputWorkspace->replaceAxis(1, verticalAxis);

  // Now set the axis values
  for (int i = 0; i < yLength - 1; ++i) {
    outputWorkspace->setX(i, xAxis);
  }

  // Set the axis units
  verticalAxis->unit() = UnitFactory::Instance().create("MomentumTransfer");
  verticalAxis->title() = "|Q|";

  // Set the X axis title (for conversion to MD)
  outputWorkspace->getAxis(0)->title() = "Energy transfer";

  return outputWorkspace;
}
Example #3
0
/** Reads from the third line of the input file to the end assuming it contains
*  2D data
*  @param firstLine :: the second line in the file
*  @return a workspace containing the loaded data
*  @throw NotFoundError if there is compulsulary data is missing from the file
*  @throw invalid_argument if there is an inconsistency in the header
* information
*/
const MatrixWorkspace_sptr LoadRKH::read2D(const std::string &firstLine) {
  g_log.information()
      << "file appears to contain 2D information, reading in 2D data mode\n";

  MatrixWorkspace_sptr outWrksp;
  MantidVec axis0Data;
  Progress prog(read2DHeader(firstLine, outWrksp, axis0Data));
  const size_t nAxis1Values = outWrksp->getNumberHistograms();

  for (size_t i = 0; i < nAxis1Values; ++i) {
    // set the X-values to the common bin values we read above
    MantidVecPtr toPass;
    toPass.access() = axis0Data;
    outWrksp->setX(i, toPass);

    // now read in the Y values
    MantidVec &YOut = outWrksp->dataY(i);
    for (double &value : YOut) {
      m_fileIn >> value;
    }
    prog.report("Loading Y data");
  } // loop on to the next spectrum

  // the error values form one big block after the Y-values
  for (size_t i = 0; i < nAxis1Values; ++i) {
    MantidVec &EOut = outWrksp->dataE(i);
    for (double &value : EOut) {
      m_fileIn >> value;
    }
    prog.report("Loading error estimates");
  } // loop on to the next spectrum

  return outWrksp;
}
Example #4
0
/** Executes the algorithm
 */
void MultiplyRange::exec()
{
  // Get the input workspace and other properties
  MatrixWorkspace_const_sptr inputWS = getProperty("InputWorkspace");
  m_startBin = getProperty("StartBin");
  m_endBin = getProperty("EndBin");
  m_factor = getProperty("Factor");

  // A few checks on the input properties
  const int specSize = static_cast<int>(inputWS->blocksize());
  if ( isEmpty(m_endBin) ) m_endBin = specSize - 1;

  if ( m_endBin >= specSize )
  {
    g_log.error("EndBin out of range!");
    throw std::out_of_range("EndBin out of range!");
  }
  if ( m_endBin < m_startBin )
  {
    g_log.error("StartBin must be less than or equal to EndBin");
    throw std::out_of_range("StartBin must be less than or equal to EndBin");
  }

  // Only create the output workspace if it's different to the input one
  MatrixWorkspace_sptr outputWS = getProperty("OutputWorkspace");
  if ( outputWS != inputWS )
  {
    outputWS = WorkspaceFactory::Instance().create(inputWS);
    setProperty("OutputWorkspace",outputWS);
  }

  // Get the count of histograms in the input workspace
  const int histogramCount = static_cast<int>(inputWS->getNumberHistograms());
  Progress progress(this,0.0,1.0,histogramCount);
  // Loop over spectra
  PARALLEL_FOR2(inputWS,outputWS)
  for (int i = 0; i < histogramCount; ++i)
  {
    PARALLEL_START_INTERUPT_REGION
    // Copy over the bin boundaries
    outputWS->setX(i,inputWS->refX(i));
    // Copy over the data
    outputWS->dataY(i) = inputWS->readY(i);
    outputWS->dataE(i) = inputWS->readE(i);
    MantidVec& newY = outputWS->dataY(i);
    MantidVec& newE = outputWS->dataE(i);

    // Now multiply the requested range
    std::transform(newY.begin()+m_startBin,newY.begin()+m_endBin+1,newY.begin()+m_startBin,
                     std::bind2nd(std::multiplies<double>(),m_factor));
    std::transform(newE.begin()+m_startBin,newE.begin()+m_endBin+1,newE.begin()+m_startBin,
                     std::bind2nd(std::multiplies<double>(),m_factor));

    progress.report();
    PARALLEL_END_INTERUPT_REGION
  }
  PARALLEL_CHECK_INTERUPT_REGION

}
Example #5
0
/** Creates the output workspace, setting the X vector to the bins boundaries in
 * Qx.
 *  @return A pointer to the newly-created workspace
 */
API::MatrixWorkspace_sptr
Qxy::setUpOutputWorkspace(API::MatrixWorkspace_const_sptr inputWorkspace) {
  const double max = getProperty("MaxQxy");
  const double delta = getProperty("DeltaQ");

  int bins = static_cast<int>(max / delta);
  if (bins * delta != max)
    ++bins; // Stop at first boundary past MaxQxy if max is not a multiple of
            // delta
  const double startVal = -1.0 * delta * bins;
  bins *= 2; // go from -max to +max
  bins += 1; // Add 1 - this is a histogram

  // Create an output workspace with the same meta-data as the input
  MatrixWorkspace_sptr outputWorkspace = WorkspaceFactory::Instance().create(
      inputWorkspace, bins - 1, bins, bins - 1);
  // ... but clear the masking from the parameter map as we don't want to carry
  // that over since this is essentially
  // a 2D rebin
  ParameterMap &pmap = outputWorkspace->instrumentParameters();
  pmap.clearParametersByName("masked");

  // Create a numeric axis to replace the vertical one
  Axis *verticalAxis = new BinEdgeAxis(bins);
  outputWorkspace->replaceAxis(1, verticalAxis);

  // Build up the X values
  Kernel::cow_ptr<MantidVec> axis;
  MantidVec &horizontalAxisRef = axis.access();
  horizontalAxisRef.resize(bins);
  for (int i = 0; i < bins; ++i) {
    const double currentVal = startVal + i * delta;
    // Set the X value
    horizontalAxisRef[i] = currentVal;
    // Set the Y value on the axis
    verticalAxis->setValue(i, currentVal);
  }

  // Fill the X vectors in the output workspace
  for (int i = 0; i < bins - 1; ++i) {
    outputWorkspace->setX(i, axis);
    for (int j = 0; j < bins - j; ++j) {
      outputWorkspace->dataY(i)[j] = std::numeric_limits<double>::quiet_NaN();
      outputWorkspace->dataE(i)[j] = std::numeric_limits<double>::quiet_NaN();
    }
  }

  // Set the axis units
  outputWorkspace->getAxis(1)->unit() = outputWorkspace->getAxis(0)->unit() =
      UnitFactory::Instance().create("MomentumTransfer");
  // Set the 'Y' unit (gets confusing here...this is probably a Z axis in this
  // case)
  outputWorkspace->setYUnitLabel("Cross Section (1/cm)");

  setProperty("OutputWorkspace", outputWorkspace);
  return outputWorkspace;
}
Example #6
0
MatrixWorkspace_sptr
PolarizationCorrection::copyShapeAndFill(MatrixWorkspace_sptr &base,
                                         const double &value) {
  MatrixWorkspace_sptr wsTemplate = WorkspaceFactory::Instance().create(base);
  // Copy the x-array across to the new workspace.
  for (size_t i = 0; i < wsTemplate->getNumberHistograms(); ++i) {
    wsTemplate->setX(i, base->refX(i));
  }
  auto zeroed = this->multiply(wsTemplate, 0);
  auto filled = this->add(zeroed, value);
  return filled;
}
Example #7
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);
}
Example #8
0
/** Creates the output workspace, its size, units, etc.
*  @param binParams the bin boundary specification using the same same syntax as param the Rebin algorithm
*  @return A pointer to the newly-created workspace
*/
API::MatrixWorkspace_sptr Q1D2::setUpOutputWorkspace(const std::vector<double> & binParams) const
{
  // Calculate the output binning
  MantidVecPtr XOut;
  size_t sizeOut = static_cast<size_t>(
    VectorHelper::createAxisFromRebinParams(binParams, XOut.access()));

  // Now create the output workspace
  MatrixWorkspace_sptr outputWS = WorkspaceFactory::Instance().create(m_dataWS,1,sizeOut,sizeOut-1);
  outputWS->getAxis(0)->unit() = UnitFactory::Instance().create("MomentumTransfer");
  outputWS->setYUnitLabel("1/cm");

  // Set the X vector for the output workspace
  outputWS->setX(0, XOut);
  outputWS->isDistribution(true);

  outputWS->getSpectrum(0)->clearDetectorIDs();
  outputWS->getSpectrum(0)->setSpectrumNo(1);

  return outputWS;
}
Example #9
0
/**
 * Sets a new preview spectrum for the mini plot.
 *
 * @param value workspace index
 */
void ResNorm::previewSpecChanged(int value) {
  m_previewSpec = value;

  // Update vanadium plot
  if (m_uiForm.dsVanadium->isValid())
    m_uiForm.ppPlot->addSpectrum(
        "Vanadium", m_uiForm.dsVanadium->getCurrentDataName(), m_previewSpec);

  // Update fit plot
  std::string fitWsGroupName(m_pythonExportWsName + "_Fit_Workspaces");
  std::string fitParamsName(m_pythonExportWsName + "_Fit");
  if (AnalysisDataService::Instance().doesExist(fitWsGroupName)) {
    WorkspaceGroup_sptr fitWorkspaces =
        AnalysisDataService::Instance().retrieveWS<WorkspaceGroup>(
            fitWsGroupName);
    ITableWorkspace_sptr fitParams =
        AnalysisDataService::Instance().retrieveWS<ITableWorkspace>(
            fitParamsName);
    if (fitWorkspaces && fitParams) {
      Column_const_sptr scaleFactors = fitParams->getColumn("Scaling");
      std::string fitWsName(fitWorkspaces->getItem(m_previewSpec)->name());
      MatrixWorkspace_const_sptr fitWs =
          AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>(
              fitWsName);

      MatrixWorkspace_sptr fit = WorkspaceFactory::Instance().create(fitWs, 1);
      fit->setX(0, fitWs->readX(1));
      fit->getSpectrum(0)->setData(fitWs->readY(1), fitWs->readE(1));

      for (size_t i = 0; i < fit->blocksize(); i++)
        fit->dataY(0)[i] /= scaleFactors->cell<double>(m_previewSpec);

      m_uiForm.ppPlot->addSpectrum("Fit", fit, 0, Qt::red);
    }
  }
}
Example #10
0
/**
 * Setup the output workspace
 * @param parent :: A pointer to the input workspace
 * @param newXBins [out] :: An output vector to be filled with the new X bin boundaries
 * @param newYBins [out] :: An output vector to be filled with the new Y bin boundaries
 * @return A pointer to the output workspace
 */
MatrixWorkspace_sptr Rebin2D::createOutputWorkspace(MatrixWorkspace_const_sptr parent,
        MantidVec & newXBins,
        MantidVec & newYBins) const
{
    using Kernel::VectorHelper::createAxisFromRebinParams;
    // First create the two sets of bin boundaries
    const int newXSize = createAxisFromRebinParams(getProperty("Axis1Binning"), newXBins);
    const int newYSize = createAxisFromRebinParams(getProperty("Axis2Binning"), newYBins);
    // and now the workspace
    MatrixWorkspace_sptr outputWS;
    if (!this->useFractionalArea)
    {
        outputWS = WorkspaceFactory::Instance().create(parent,newYSize-1,newXSize,newXSize-1);
    }
    else
    {
        outputWS = WorkspaceFactory::Instance().create("RebinnedOutput", newYSize-1, newXSize, newXSize-1);
        WorkspaceFactory::Instance().initializeFromParent(parent, outputWS, true);
    }
    Axis* const verticalAxis = new NumericAxis(newYSize);
    // Meta data
    verticalAxis->unit() = parent->getAxis(1)->unit();
    verticalAxis->title() = parent->getAxis(1)->title();
    outputWS->replaceAxis(1,verticalAxis);

    // Now set the axis values
    for (size_t i=0; i < static_cast<size_t>(newYSize-1); ++i)
    {
        outputWS->setX(i,newXBins);
        verticalAxis->setValue(i,newYBins[i]);
    }
    // One more to set on the 'y' axis
    verticalAxis->setValue(newYSize-1,newYBins[newYSize-1]);

    return outputWS;
}
Example #11
0
  //----------------------------------------------------------------------------------------------
  /// @copydoc Mantid::API::Algorithm::exec()
  void ResetNegatives::exec()
  {
    MatrixWorkspace_sptr inputWS = this->getProperty("InputWorkspace");
    MatrixWorkspace_sptr outputWS = this->getProperty("OutputWorkspace");

    // get the minimum for each spectrum
    IAlgorithm_sptr alg = this->createChildAlgorithm("Min", 0., .1);
    alg->setProperty<MatrixWorkspace_sptr>("InputWorkspace", inputWS);
    alg->executeAsChildAlg();
    MatrixWorkspace_const_sptr minWS = alg->getProperty("OutputWorkspace");

    // determine if there is anything to do
    int64_t nHist = static_cast<int64_t>(minWS->getNumberHistograms());
    bool hasNegative = false;
    for (int64_t i = 0; i < nHist; i++)
    {
      if (minWS->readY(i)[0] < 0)
      {
        hasNegative = true;
      }
      break;
    }

    // get out early if there is nothing to do
    if (!hasNegative)
    {
      g_log.information() << "No values are negative. Copying InputWorkspace to OutputWorkspace\n";
      if (inputWS != outputWS)
      {
        IAlgorithm_sptr alg = this->createChildAlgorithm("CloneWorkspace", .1, 1.);
        alg->setProperty<Workspace_sptr>("InputWorkspace", inputWS);
        alg->executeAsChildAlg();

        Workspace_sptr temp = alg->getProperty("OutputWorkspace");
        setProperty("OutputWorkspace", boost::dynamic_pointer_cast<MatrixWorkspace>(temp));
      }
      return;
    }

    // sort the event list to make it fast and thread safe
    DataObjects::EventWorkspace_const_sptr eventWS
                 = boost::dynamic_pointer_cast<const DataObjects::EventWorkspace>( inputWS );
    if (eventWS)
      eventWS->sortAll(DataObjects::TOF_SORT, NULL);

    Progress prog(this, .1, 1., 2*nHist);

    // generate output workspace - copy X and dY
    outputWS = API::WorkspaceFactory::Instance().create(inputWS);
    PARALLEL_FOR2(inputWS,outputWS)
    for (int64_t i = 0; i < nHist; i++)
    {
      PARALLEL_START_INTERUPT_REGION
      outputWS->dataY(i) = inputWS->readY(i);
      outputWS->dataE(i) = inputWS->readE(i);
      outputWS->setX(i, inputWS->refX(i)); // share the pointer more
      prog.report();
      PARALLEL_END_INTERUPT_REGION
    }
    PARALLEL_CHECK_INTERUPT_REGION

    // do the actual work
    if (this->getProperty("AddMinimum"))
    {
        this->pushMinimum(minWS, outputWS, prog);
    }
    else
    {
      this->changeNegatives(minWS, this->getProperty("ResetValue"), outputWS, prog);
    }

    setProperty("OutputWorkspace",outputWS);
  }
/**
  * Make 2D MatrixWorkspace
  */
void ConvertMDHistoToMatrixWorkspace::make2DWorkspace() {
  // get the input workspace
  IMDHistoWorkspace_sptr inputWorkspace = getProperty("InputWorkspace");

  // find the non-integrated dimensions
  Mantid::Geometry::VecIMDDimension_const_sptr nonIntegDims =
      inputWorkspace->getNonIntegratedDimensions();

  auto xDim = nonIntegDims[0];
  auto yDim = nonIntegDims[1];

  size_t nx = xDim->getNBins();
  size_t ny = yDim->getNBins();

  size_t xDimIndex =
      inputWorkspace->getDimensionIndexById(xDim->getDimensionId());
  size_t xStride = calcStride(*inputWorkspace, xDimIndex);

  size_t yDimIndex =
      inputWorkspace->getDimensionIndexById(yDim->getDimensionId());
  size_t yStride = calcStride(*inputWorkspace, yDimIndex);

  // get the normalization of the output
  std::string normProp = getPropertyValue("Normalization");
  Mantid::API::MDNormalization normalization;
  if (normProp == "NoNormalization") {
    normalization = NoNormalization;
  } else if (normProp == "VolumeNormalization") {
    normalization = VolumeNormalization;
  } else if (normProp == "NumEventsNormalization") {
    normalization = NumEventsNormalization;
  } else {
    normalization = NoNormalization;
  }
  signal_t inverseVolume =
      static_cast<signal_t>(inputWorkspace->getInverseVolume());

  // create the output workspace
  MatrixWorkspace_sptr outputWorkspace =
      WorkspaceFactory::Instance().create("Workspace2D", ny, nx + 1, nx);

  // set the x-values
  Mantid::MantidVec &X = outputWorkspace->dataX(0);
  double dx = xDim->getBinWidth();
  double x = xDim->getMinimum();
  for (auto ix = X.begin(); ix != X.end(); ++ix, x += dx) {
    *ix = x;
  }

  // set the y-values and errors
  for (size_t i = 0; i < ny; ++i) {
    if (i > 0)
      outputWorkspace->setX(i, X);
    auto &Y = outputWorkspace->dataY(i);
    auto &E = outputWorkspace->dataE(i);

    size_t yOffset = i * yStride;
    for (size_t j = 0; j < nx; ++j) {
      size_t linearIndex = yOffset + j * xStride;
      signal_t signal = inputWorkspace->getSignalArray()[linearIndex];
      signal_t error = inputWorkspace->getErrorSquaredArray()[linearIndex];
      // apply normalization
      if (normalization != NoNormalization) {
        if (normalization == VolumeNormalization) {
          signal *= inverseVolume;
          error *= inverseVolume;
        } else // normalization == NumEventsNormalization
        {
          signal_t factor = inputWorkspace->getNumEventsArray()[linearIndex];
          factor = factor != 0.0 ? 1.0 / factor : 1.0;
          signal *= factor;
          error *= factor;
        }
      }
      Y[j] = signal;
      E[j] = sqrt(error);
    }
  }

  // set the first axis
  auto labelX = boost::dynamic_pointer_cast<Kernel::Units::Label>(
      Kernel::UnitFactory::Instance().create("Label"));
  labelX->setLabel(xDim->getName());
  outputWorkspace->getAxis(0)->unit() = labelX;

  // set the second axis
  auto yAxis = new NumericAxis(ny);
  for (size_t i = 0; i < ny; ++i) {
    yAxis->setValue(i, yDim->getX(i));
  }
  auto labelY = boost::dynamic_pointer_cast<Kernel::Units::Label>(
      Kernel::UnitFactory::Instance().create("Label"));
  labelY->setLabel(yDim->getName());
  yAxis->unit() = labelY;
  outputWorkspace->replaceAxis(1, yAxis);

  // set the "units" for the y values
  outputWorkspace->setYUnitLabel("Signal");

  // done
  setProperty("OutputWorkspace", outputWorkspace);
}
Example #13
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
Example #14
0
void Qxy::exec()
{
  MatrixWorkspace_const_sptr inputWorkspace = getProperty("InputWorkspace");
  MatrixWorkspace_const_sptr waveAdj = getProperty("WavelengthAdj");
  MatrixWorkspace_const_sptr pixelAdj = getProperty("PixelAdj");
  const bool doGravity = getProperty("AccountForGravity");
  const bool doSolidAngle = getProperty("SolidAngleWeighting");

  //throws if we don't have common binning or another incompatibility
  Qhelper helper;
  helper.examineInput(inputWorkspace, waveAdj, pixelAdj);
  g_log.debug() << "All input workspaces were found to be valid\n";

  // Create the output Qx-Qy grid
  MatrixWorkspace_sptr outputWorkspace = this->setUpOutputWorkspace(inputWorkspace);

  // Will also need an identically-sized workspace to hold the solid angle/time bin masked weight
  MatrixWorkspace_sptr weights = WorkspaceFactory::Instance().create(outputWorkspace);
  // Copy the X values from the output workspace to the solidAngles one
  cow_ptr<MantidVec> axis;
  axis.access() = outputWorkspace->readX(0);
  for ( size_t i = 0; i < weights->getNumberHistograms(); ++i ) weights->setX(i,axis);
  
  const size_t numSpec = inputWorkspace->getNumberHistograms();
  const size_t numBins = inputWorkspace->blocksize();
  
  // the samplePos is often not (0, 0, 0) because the instruments components are moved to account for the beam centre
  const V3D samplePos = inputWorkspace->getInstrument()->getSample()->getPos();
  
  // Set the progress bar (1 update for every one percent increase in progress)
  Progress prog(this, 0.05, 1.0, numSpec);

//  PARALLEL_FOR2(inputWorkspace,outputWorkspace)
  for (int64_t i = 0; i < int64_t(numSpec); ++i)
  {
//    PARALLEL_START_INTERUPT_REGION
    // Get the pixel relating to this spectrum
    IDetector_const_sptr det;
    try {
      det = inputWorkspace->getDetector(i);
    } catch (Exception::NotFoundError&) {
      g_log.warning() << "Spectrum index " << i << " has no detector assigned to it - discarding" << std::endl;
      // Catch if no detector. Next line tests whether this happened - test placed
      // outside here because Mac Intel compiler doesn't like 'continue' in a catch
      // in an openmp block.
    }
    // 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 bins that are included inside the RadiusCut/WaveCutcut off, those to calculate for
    const size_t wavStart = helper.waveLengthCutOff(inputWorkspace, getProperty("RadiusCut"), getProperty("WaveCut"), i);
    if (wavStart >=  inputWorkspace->readY(i).size())
    {
      // all the spectra in this detector are out of range
      continue;
    }


    V3D detPos = det->getPos()-samplePos;
      
    // these will be re-calculated if gravity is on but without gravity there is no need
    double phi = atan2(detPos.Y(),detPos.X());
    double a = cos(phi);
    double b = sin(phi);
    double sinTheta = sin( inputWorkspace->detectorTwoTheta(det)/2.0 );

    // Get references to the data for this spectrum
    const MantidVec& X = inputWorkspace->readX(i);
    const MantidVec& Y = inputWorkspace->readY(i);
    const MantidVec& E = inputWorkspace->readE(i);
 
    const MantidVec& axis = outputWorkspace->readX(0);

    // the solid angle of the detector as seen by the sample is used for normalisation later on
    double angle = det->solidAngle(samplePos);

    // some bins are masked completely or partially, the following vector will contain the fractions
    MantidVec maskFractions;
    if ( inputWorkspace->hasMaskedBins(i) )
    {
      // go through the set and convert it to a vector
      const MatrixWorkspace::MaskList& mask = inputWorkspace->maskedBins(i);
      maskFractions.resize(numBins, 1.0);
      MatrixWorkspace::MaskList::const_iterator it, itEnd(mask.end());
      for (it = mask.begin(); it != itEnd; ++it)
      {
        // The weight for this masked bin is 1 minus the degree to which this bin is masked
        maskFractions[it->first] -= it->second;
      }
    }
    double maskFraction(1);
    
    // this object is not used if gravity correction is off, but it is only constructed once per spectrum
    GravitySANSHelper grav;
    if (doGravity)
    {
      grav = GravitySANSHelper(inputWorkspace, det);
    }

    
    for (int j = static_cast<int>(numBins)-1; j >= static_cast<int>(wavStart); --j)
    {
      if( j < 0 ) break; // Be careful with counting down. Need a better fix but this will work for now
      const double binWidth = X[j+1]-X[j];
      // Calculate the wavelength at the mid-point of this bin
      const double wavLength = X[j]+(binWidth)/2.0;
      
      if (doGravity)
      {
        // SANS instruments must have their y-axis pointing up, show the detector position as where the neutron would be without gravity
        sinTheta = grav.calcComponents(wavLength, a, b);
      }

      // Calculate |Q| for this bin
      const double Q = 4.0*M_PI*sinTheta/wavLength;

      // Now get the x & y components of Q.
      const double Qx = a*Q;
      // Test whether they're in range, if not go to next spectrum.
      if ( Qx < axis.front() || Qx >= axis.back() ) break;
      const double Qy = b*Q;
      if ( Qy < axis.front() || Qy >= axis.back() ) break;
      // Find the indices pointing to the place in the 2D array where this bin's contents should go
      const MantidVec::difference_type xIndex = std::upper_bound(axis.begin(),axis.end(),Qx) - axis.begin() - 1;
      const int yIndex = static_cast<int>(
        std::upper_bound(axis.begin(),axis.end(),Qy) - axis.begin() - 1);
//      PARALLEL_CRITICAL(qxy)    /* Write to shared memory - must protect */
      {
        // the data will be copied to this bin in the output array
        double & outputBinY = outputWorkspace->dataY(yIndex)[xIndex];
        double & outputBinE = outputWorkspace->dataE(yIndex)[xIndex];

        if ( boost::math::isnan(outputBinY))
        {
          outputBinY = outputBinE = 0;
        }
        // Add the contents of the current bin to the 2D array.
        outputBinY += Y[j];
        // add the errors in quadranture
        outputBinE = std::sqrt( (outputBinE*outputBinE) + (E[j]*E[j]) );
        
        // account for masked bins
        if ( ! maskFractions.empty() )
        {
          maskFraction = maskFractions[j];
        }
        // add the total weight for this bin in the weights workspace, 
        // in an equivalent bin to where the data was stored

        // first take into account the product of contributions to the weight which have
        // no errors
        double weight = 0.0;
        if(doSolidAngle)
          weight = maskFraction*angle; 
        else
          weight = maskFraction;
        
        // then the product of contributions which have errors, i.e. optional 
        // pixelAdj and waveAdj contributions

        if (pixelAdj && waveAdj)
        {
          weights->dataY(yIndex)[xIndex] += weight*pixelAdj->readY(i)[0]*waveAdj->readY(0)[j];
          const double pixelYSq = pixelAdj->readY(i)[0]*pixelAdj->readY(i)[0];
          const double pixelESq = pixelAdj->readE(i)[0]*pixelAdj->readE(i)[0]; 
          const double waveYSq = waveAdj->readY(0)[j]*waveAdj->readY(0)[j];
          const double waveESq = waveAdj->readE(0)[j]*waveAdj->readE(0)[j];
          // add product of errors from pixelAdj and waveAdj (note no error on weight is assumed)   
          weights->dataE(yIndex)[xIndex] += weight*weight*(waveESq*pixelYSq + pixelESq*waveYSq);
        }
        else if (pixelAdj)
        {
          weights->dataY(yIndex)[xIndex] += weight*pixelAdj->readY(i)[0];
          const double pixelE = weight*pixelAdj->readE(i)[0]; 
          // add error from pixelAdj
          weights->dataE(yIndex)[xIndex] += pixelE*pixelE;
        }
        else if(waveAdj)
        {
          weights->dataY(yIndex)[xIndex] += weight*waveAdj->readY(0)[j];
          const double waveE = weight*waveAdj->readE(0)[j]; 
          // add error from waveAdj
          weights->dataE(yIndex)[xIndex] += waveE*waveE;
        }
        else
          weights->dataY(yIndex)[xIndex] += weight;
        

      }
    } // loop over single spectrum
    
    prog.report("Calculating Q");

//    PARALLEL_END_INTERUPT_REGION
  } // loop over all spectra
//  PARALLEL_CHECK_INTERUPT_REGION

  // take sqrt of error weight values
  // left to be executed here for computational efficiency
  size_t numHist = weights->getNumberHistograms();
  for (size_t i = 0; i < numHist; i++)
  {
    for (size_t j = 0; j < weights->dataE(i).size(); j++)
    {
      weights->dataE(i)[j] = sqrt(weights->dataE(i)[j]);
    } 
  }

  bool doOutputParts = getProperty("OutputParts");
  if (doOutputParts)
  {
    // copy outputworkspace before it gets further modified
    MatrixWorkspace_sptr ws_sumOfCounts = WorkspaceFactory::Instance().create(outputWorkspace);
    for (size_t i = 0; i < ws_sumOfCounts->getNumberHistograms(); i++)
    {
      ws_sumOfCounts->dataX(i) = outputWorkspace->dataX(i);
      ws_sumOfCounts->dataY(i) = outputWorkspace->dataY(i);
      ws_sumOfCounts->dataE(i) = outputWorkspace->dataE(i);
    }  

    helper.outputParts(this, ws_sumOfCounts, weights);
  }

  // Divide the output data by the solid angles
  outputWorkspace /= weights;
  outputWorkspace->isDistribution(true);

  
  // Count of the number of empty cells
  MatrixWorkspace::const_iterator wsIt(*outputWorkspace);
  int emptyBins = 0;
  for (;wsIt != wsIt.end(); ++wsIt)
  {
      if (wsIt->Y() < 1.0e-12) ++emptyBins;
  }
  // Log the number of empty bins
  g_log.notice() << "There are a total of " << emptyBins << " (" 
                 << (100*emptyBins)/(outputWorkspace->size()) << "%) empty Q bins.\n"; 
}
Example #15
0
/// Exec function
void CreateWorkspace::exec()
{
    // Contortions to get at the vector in the property without copying it
    const Property * const dataXprop = getProperty("DataX");
    const Property * const dataYprop = getProperty("DataY");
    const Property * const dataEprop = getProperty("DataE");
    const std::vector<double>& dataX = *dynamic_cast<const ArrayProperty<double>*>(dataXprop);
    const std::vector<double>& dataY = *dynamic_cast<const ArrayProperty<double>*>(dataYprop);
    const std::vector<double>& dataE = *dynamic_cast<const ArrayProperty<double>*>(dataEprop);

    const int nSpec = getProperty("NSpec");
    const std::string xUnit = getProperty("UnitX");
    const std::string vUnit = getProperty("VerticalAxisUnit");
    const std::vector<std::string> vAxis = getProperty("VerticalAxisValues");
    std::string parentWorkspace = getPropertyValue("ParentWorkspace");

    if ( ( vUnit != "SpectraNumber" ) && ( static_cast<int>(vAxis.size()) != nSpec ) )
    {
        throw std::invalid_argument("Number of y-axis labels must match number of histograms.");
    }

    // Verify length of vectors makes sense with NSpec
    if ( ( dataY.size() % nSpec ) != 0 )
    {
        throw std::invalid_argument("Length of DataY must be divisible by NSpec");
    }
    const std::size_t ySize = dataY.size() / nSpec;

    // Check whether the X values provided are to be re-used for (are common to) every spectrum
    const bool commonX( dataX.size() == ySize || dataX.size() == ySize+1 );

    std::size_t xSize;
    MantidVecPtr XValues;
    if ( commonX )
    {
        xSize = dataX.size();
        XValues.access() = dataX;
    }
    else
    {
        if ( dataX.size() % nSpec != 0 )
        {
            throw std::invalid_argument("Length of DataX must be divisible by NSpec");
        }

        xSize = static_cast<int>(dataX.size()) / nSpec;
        if ( xSize < ySize || xSize > ySize + 1 )
        {
            throw std::runtime_error("DataX width must be as DataY or +1");
        }

    }

    const bool dataE_provided = !dataE.empty();
    if ( dataE_provided && dataY.size() != dataE.size() )
    {
        throw std::runtime_error("DataE (if provided) must be the same size as DataY");
    }

    MatrixWorkspace_sptr parentWS;
    if (!parentWorkspace.empty())
    {
        try
        {
            parentWS = boost::dynamic_pointer_cast<MatrixWorkspace>( AnalysisDataService::Instance().retrieve(parentWorkspace) );
        }
        catch(...)
        {
            g_log.warning("Parent workspace not found");
            // ignore parent workspace
        }
    }

    // Create the OutputWorkspace
    MatrixWorkspace_sptr outputWS;
    if (parentWS)
    {
        // if parent is defined use it to initialise the workspace
        outputWS = WorkspaceFactory::Instance().create(parentWS, nSpec, xSize, ySize);
    }
    else
    {
        // otherwise create a blank workspace
        outputWS = WorkspaceFactory::Instance().create("Workspace2D", nSpec, xSize, ySize);
    }

    Progress progress(this,0,1,nSpec);

    PARALLEL_FOR1(outputWS)
    for ( int i = 0; i < nSpec; i++ )
    {
        PARALLEL_START_INTERUPT_REGION

        const std::vector<double>::difference_type xStart = i*xSize;
        const std::vector<double>::difference_type xEnd = xStart + xSize;
        const std::vector<double>::difference_type yStart = i*ySize;
        const std::vector<double>::difference_type yEnd = yStart + ySize;

        // Just set the pointer if common X bins. Otherwise, copy in the right chunk (as we do for Y).
        if ( commonX )
        {
            outputWS->setX(i,XValues);
        }
        else
        {
            outputWS->dataX(i).assign(dataX.begin()+xStart,dataX.begin()+xEnd);
        }

        outputWS->dataY(i).assign(dataY.begin()+yStart,dataY.begin()+yEnd);

        if ( dataE_provided) outputWS->dataE(i).assign(dataE.begin()+yStart,dataE.begin()+yEnd);

        progress.report();
        PARALLEL_END_INTERUPT_REGION
    }
    PARALLEL_CHECK_INTERUPT_REGION

    // Set the Unit of the X Axis
    try
    {
        outputWS->getAxis(0)->unit() = UnitFactory::Instance().create(xUnit);
    }
    catch ( Exception::NotFoundError & )
    {
        outputWS->getAxis(0)->unit() = UnitFactory::Instance().create("Label");
        Unit_sptr unit = outputWS->getAxis(0)->unit();
        boost::shared_ptr<Units::Label> label = boost::dynamic_pointer_cast<Units::Label>(unit);
        label->setLabel(xUnit, xUnit);
    }

    // Populate the VerticalAxis. A spectra one is there by default with a 1->N mapping
    if ( vUnit != "SpectraNumber" )
    {
        if ( vUnit == "Text" )
        {
            TextAxis* const newAxis = new TextAxis(vAxis.size());
            outputWS->replaceAxis(1, newAxis);
            for ( size_t i = 0; i < vAxis.size(); i++ )
            {
                newAxis->setLabel(i, vAxis[i]);
            }
        }
        else
        {
            NumericAxis* const newAxis = new NumericAxis(vAxis.size());
            newAxis->unit() = UnitFactory::Instance().create(vUnit);
            outputWS->replaceAxis(1, newAxis);
            for ( size_t i = 0; i < vAxis.size(); i++ )
            {
                try
                {
                    newAxis->setValue(i, boost::lexical_cast<double, std::string>(vAxis[i]) );
                }
                catch ( boost::bad_lexical_cast & )
                {
                    throw std::invalid_argument("CreateWorkspace - YAxisValues property could not be converted to a double.");
                }
            }
        }
    }

    // Set distribution flag
    outputWS->isDistribution(getProperty("Distribution"));

    // Set Y Unit label
    if (!parentWS || !getPropertyValue("YUnitLabel").empty())
    {
        outputWS->setYUnitLabel(getProperty("YUnitLabel"));
    }

    // Set Workspace Title
    if (!parentWS || !getPropertyValue("WorkspaceTitle").empty())
    {
        outputWS->setTitle(getProperty("WorkspaceTitle"));
    }

    // Set OutputWorkspace property
    setProperty("OutputWorkspace", outputWS);
}
/// Execute the algorithm in case of a histogrammed data.
void ExtractSpectra::execHistogram() {
  m_histogram = m_inputWorkspace->isHistogramData();
  // Check for common boundaries in input workspace
  m_commonBoundaries = WorkspaceHelpers::commonBoundaries(m_inputWorkspace);

  // Retrieve and validate the input properties
  this->checkProperties();

  // Create the output workspace
  MatrixWorkspace_sptr outputWorkspace = WorkspaceFactory::Instance().create(
      m_inputWorkspace, m_workspaceIndexList.size(), m_maxX - m_minX,
      m_maxX - m_minX - m_histogram);

  // If this is a Workspace2D, get the spectra axes for copying in the spectraNo
  // later
  Axis *inAxis1(nullptr);
  TextAxis *outTxtAxis(nullptr);
  NumericAxis *outNumAxis(nullptr);
  if (m_inputWorkspace->axes() > 1) {
    inAxis1 = m_inputWorkspace->getAxis(1);
    auto outAxis1 = outputWorkspace->getAxis(1);
    outTxtAxis = dynamic_cast<TextAxis *>(outAxis1);
    if (!outTxtAxis)
      outNumAxis = dynamic_cast<NumericAxis *>(outAxis1);
  }

  cow_ptr<MantidVec> newX;
  if (m_commonBoundaries) {
    const MantidVec &oldX =
        m_inputWorkspace->readX(m_workspaceIndexList.front());
    newX.access().assign(oldX.begin() + m_minX, oldX.begin() + m_maxX);
  }

  Progress prog(this, 0.0, 1.0, (m_workspaceIndexList.size()));
  // Loop over the required workspace indices, copying in the desired bins
  for (int j = 0; j < static_cast<int>(m_workspaceIndexList.size()); ++j) {
    auto i = m_workspaceIndexList[j];

    bool hasDx = m_inputWorkspace->hasDx(i);

    // Preserve/restore sharing if X vectors are the same
    if (m_commonBoundaries) {
      outputWorkspace->setX(j, newX);
      if (hasDx) {
        const MantidVec &oldDx = m_inputWorkspace->readDx(i);
        outputWorkspace->dataDx(j)
            .assign(oldDx.begin() + m_minX, oldDx.begin() + m_maxX);
      }
    } else {
      // Safe to just copy whole vector 'cos can't be cropping in X if not
      // common
      outputWorkspace->setX(j, m_inputWorkspace->refX(i));
      if (hasDx) {
        outputWorkspace->setDx(j, m_inputWorkspace->refDx(i));
      }
    }

    const MantidVec &oldY = m_inputWorkspace->readY(i);
    outputWorkspace->dataY(j)
        .assign(oldY.begin() + m_minX, oldY.begin() + (m_maxX - m_histogram));
    const MantidVec &oldE = m_inputWorkspace->readE(i);
    outputWorkspace->dataE(j)
        .assign(oldE.begin() + m_minX, oldE.begin() + (m_maxX - m_histogram));

    // copy over the axis entry for each spectrum, regardless of the type of
    // axes present
    if (inAxis1) {
      if (outTxtAxis) {
        outTxtAxis->setLabel(j, inAxis1->label(i));
      } else if (outNumAxis) {
        outNumAxis->setValue(j, inAxis1->operator()(i));
      }
      // spectra axis is handled by copyInfoFrom line
    }
    // Copy spectrum number & detectors
    outputWorkspace->getSpectrum(j)
        ->copyInfoFrom(*m_inputWorkspace->getSpectrum(i));

    if (!m_commonBoundaries)
      this->cropRagged(outputWorkspace, static_cast<int>(i), j);

    // Propagate bin masking if there is any
    if (m_inputWorkspace->hasMaskedBins(i)) {
      const MatrixWorkspace::MaskList &inputMasks =
          m_inputWorkspace->maskedBins(i);
      MatrixWorkspace::MaskList::const_iterator it;
      for (it = inputMasks.begin(); it != inputMasks.end(); ++it) {
        const size_t maskIndex = (*it).first;
        if (maskIndex >= m_minX && maskIndex < m_maxX - m_histogram)
          outputWorkspace->flagMasked(j, maskIndex - m_minX, (*it).second);
      }
    }
    prog.report();
  }

  setProperty("OutputWorkspace", outputWorkspace);
}
Example #17
0
void TOFSANSResolution::exec()
{
  Workspace2D_sptr iqWS = getProperty("InputWorkspace");
  MatrixWorkspace_sptr reducedWS = getProperty("ReducedWorkspace");
  EventWorkspace_sptr reducedEventWS = boost::dynamic_pointer_cast<EventWorkspace>(reducedWS);
  const double min_wl = getProperty("MinWavelength");
  const double max_wl = getProperty("MaxWavelength");
  double pixel_size_x = getProperty("PixelSizeX");
  double pixel_size_y = getProperty("PixelSizeY");
  double R1 = getProperty("SourceApertureRadius");
  double R2 = getProperty("SampleApertureRadius");
  // Convert to meters
  pixel_size_x /= 1000.0;
  pixel_size_y /= 1000.0;
  R1 /= 1000.0;
  R2 /= 1000.0;
  wl_resolution = getProperty("DeltaT");

  // Although we want the 'ReducedWorkspace' to be an event workspace for this algorithm to do
  // anything, we don't want the algorithm to 'fail' if it isn't
  if (!reducedEventWS)
  {
    g_log.warning() << "An Event Workspace is needed to compute dQ. Calculation skipped." << std::endl;
    return;
  }

  // Calculate the output binning
  const std::vector<double> binParams = getProperty("OutputBinning");

  // Count histogram for normalization
  const int xLength = static_cast<int>(iqWS->readX(0).size());
  std::vector<double> XNorm(xLength-1, 0.0);

  // Create workspaces with each component of the resolution for debugging purposes
  MatrixWorkspace_sptr thetaWS = WorkspaceFactory::Instance().create(iqWS);
  declareProperty(new WorkspaceProperty<>("ThetaError","",Direction::Output));
  setPropertyValue("ThetaError","__"+iqWS->getName()+"_theta_error");
  setProperty("ThetaError",thetaWS);
  thetaWS->setX(0,iqWS->readX(0));
  MantidVec& ThetaY = thetaWS->dataY(0);

  MatrixWorkspace_sptr tofWS = WorkspaceFactory::Instance().create(iqWS);
  declareProperty(new WorkspaceProperty<>("TOFError","",Direction::Output));
  setPropertyValue("TOFError","__"+iqWS->getName()+"_tof_error");
  setProperty("TOFError",tofWS);
  tofWS->setX(0,iqWS->readX(0));
  MantidVec& TOFY = tofWS->dataY(0);

  // Initialize Dq
  MantidVec& DxOut = iqWS->dataDx(0);
  for ( int i = 0; i<xLength-1; i++ ) DxOut[i] = 0.0;

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

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

  PARALLEL_FOR2(reducedEventWS, iqWS)
  for (int i = 0; i < numberOfSpectra; i++)
  {
    PARALLEL_START_INTERUPT_REGION
    IDetector_const_sptr det;
    try {
      det = reducedEventWS->getDetector(i);
    } catch (Exception::NotFoundError&) {
      g_log.warning() << "Spectrum index " << i << " has no detector assigned to it - discarding" << std::endl;
      // Catch if no detector. Next line tests whether this happened - test placed
      // outside here because Mac Intel compiler doesn't like 'continue' in a catch
      // in an openmp block.
    }
    // 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 scattered_flight_path = det->getPos() - samplePos;

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

    EventList& el = reducedEventWS->getEventList(i);
    el.switchTo(WEIGHTED);

    std::vector<WeightedEvent>::iterator itev;
    std::vector<WeightedEvent>::iterator itev_end = el.getWeightedEvents().end();

    for (itev = el.getWeightedEvents().begin(); itev != itev_end; ++itev)
    {
      if ( itev->m_weight != itev->m_weight ) continue;
      if (std::abs(itev->m_weight) == std::numeric_limits<double>::infinity()) continue;
      if ( !isEmpty(min_wl) && itev->m_tof < min_wl ) continue;
      if ( !isEmpty(max_wl) && itev->m_tof > max_wl ) continue;

      const double q = factor/itev->m_tof;
      int iq = 0;

      // Bin assignment depends on whether we have log or linear bins
      if(binParams[1]>0.0)
      {
        iq = (int)floor( (q-binParams[0])/ binParams[1] );
      } else {
        iq = (int)floor(log(q/binParams[0])/log(1.0-binParams[1]));
      }

      const double L2 = scattered_flight_path.norm();
      const double src_to_pixel = L1+L2;
      const double dTheta2 = ( 3.0*R1*R1/(L1*L1) + 3.0*R2*R2*src_to_pixel*src_to_pixel/(L1*L1*L2*L2)
            + 2.0*(pixel_size_x*pixel_size_x+pixel_size_y*pixel_size_y)/(L2*L2) )/12.0;

      const double dwl_over_wl = 3.9560*getTOFResolution(itev->m_tof)/(1000.0*(L1+L2)*itev->m_tof);
      const double dq_over_q = std::sqrt(dTheta2/(theta*theta)+dwl_over_wl*dwl_over_wl);

      PARALLEL_CRITICAL(iq)    /* Write to shared memory - must protect */
      if (iq>=0 && iq < xLength-1 && !dq_over_q!=dq_over_q && dq_over_q>0)
      {
        DxOut[iq] += q*dq_over_q*itev->m_weight;
        XNorm[iq] += itev->m_weight;
        TOFY[iq] += q*std::fabs(dwl_over_wl)*itev->m_weight;
        ThetaY[iq] += q*std::sqrt(dTheta2)/theta*itev->m_weight;
      }
    }

    progress.report("Computing Q resolution");
    PARALLEL_END_INTERUPT_REGION
  }
  PARALLEL_CHECK_INTERUPT_REGION
  // Normalize according to the chosen weighting scheme
  for ( int i = 0; i<xLength-1; i++ )
  {
    if (XNorm[i]>0)
    {
      DxOut[i] /= XNorm[i];
      TOFY[i] /= XNorm[i];
      ThetaY[i] /= XNorm[i];
    }
  }
}
Example #18
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)
Example #19
0
void SmoothData::exec()
{
  // Get the input properties
  MatrixWorkspace_const_sptr inputWorkspace = getProperty("InputWorkspace");

  int npts = getProperty("NPoints");
  // Number of smoothing points must always be an odd number, so add 1 if it isn't.
  if (!(npts%2))
  {
    g_log.information("Adding 1 to number of smoothing points, since it must always be odd");
    ++npts;
  }

  // Check that the number of points in the smoothing isn't larger than the spectrum length
  const int vecSize = static_cast<int>(inputWorkspace->blocksize());
  if ( npts >= vecSize )
  {
    g_log.error("The number of averaging points requested is larger than the spectrum length");
    throw std::out_of_range("The number of averaging points requested is larger than the spectrum length");
  }
  const int halfWidth = (npts-1)/2;

  // Create the output workspace
  MatrixWorkspace_sptr outputWorkspace = WorkspaceFactory::Instance().create(inputWorkspace);

  Progress progress(this,0.0,1.0,inputWorkspace->getNumberHistograms());
  PARALLEL_FOR2(inputWorkspace,outputWorkspace)
  // Loop over all the spectra in the workspace
  for (int i = 0; i < static_cast<int>(inputWorkspace->getNumberHistograms()); ++i)
  {
    PARALLEL_START_INTERUPT_REGION
    // Copy the X data over. Preserves data sharing if present in input workspace.
    outputWorkspace->setX(i,inputWorkspace->refX(i));

    // Now get references to the Y & E vectors in the input and output workspaces
    const MantidVec &Y = inputWorkspace->readY(i);
    const MantidVec &E = inputWorkspace->readE(i);
    MantidVec &newY = outputWorkspace->dataY(i);
    MantidVec &newE = outputWorkspace->dataE(i);

    // Use total to help hold our moving average
    double total = 0.0, totalE = 0.0;
    // First push the values ahead of the current point onto total
    for (int i = 0; i < halfWidth; ++i)
    {
      if ( Y[i] == Y[i] ) total += Y[i]; // Exclude if NaN
      totalE += E[i]*E[i];
    }
    // Now calculate the smoothed values for the 'end' points, where the number contributing
    // to the smoothing will be less than NPoints
    for (int j = 0; j <= halfWidth; ++j)
    {
      const int index = j+halfWidth;
      if ( Y[index] == Y[index] ) total += Y[index]; // Exclude if NaN
      newY[j] = total/(index+1);
      totalE += E[index]*E[index];
      newE[j] = sqrt(totalE)/(index+1);
    }
    // This is the main part, where each data point is the average of NPoints points centred on the
    // current point. Note that the statistical error will be reduced by sqrt(npts) because more
    // data is now contributing to each point.
    for (int k = halfWidth+1; k < vecSize-halfWidth; ++k)
    {
      const int kp = k+halfWidth;
      const int km = k-halfWidth-1;
      total += (Y[kp]!=Y[kp] ? 0.0 : Y[kp]) - (Y[km]!=Y[km] ? 0.0 : Y[km]); // Exclude if NaN
      newY[k] = total/npts;
      totalE += E[kp]*E[kp] - E[km]*E[km];
      // Use of a moving average can lead to rounding error where what should be 
      // zero actually comes out as a tiny negative number - bad news for sqrt so protect
      newE[k] = std::sqrt(std::abs(totalE))/npts;
    }
    // This deals with the 'end' at the tail of each spectrum
    for (int l = vecSize-halfWidth; l < vecSize; ++l)
    {
      const int index = l-halfWidth;
      total -= (Y[index-1]!=Y[index-1] ? 0.0 : Y[index-1]); // Exclude if NaN
      newY[l] = total/(vecSize-index);
      totalE -= E[index-1]*E[index-1];
      newE[l] = std::sqrt(std::abs(totalE))/(vecSize-index);
    }
    progress.report();
    PARALLEL_END_INTERUPT_REGION
  } // Loop over spectra
  PARALLEL_CHECK_INTERUPT_REGION

  // Set the output workspace to its property
  setProperty("OutputWorkspace", outputWorkspace);
}
Example #20
0
	/**
	* Loads data from a selection of the FITS files into the workspace
	* @param workspace The workspace to insert data into
	* @param yVals Reference to a pre-allocated vector to hold data values for the workspace
	* @param eVals Reference to a pre-allocated vector to hold error values for the workspace
	* @param bufferAny Pointer to an allocated memory region which will hold a files worth of data
	* @param x Vector holding the X bin values
	* @param spectraCount Number of data points in each file
	* @param bitsPerPixel Number of bits used to represent one data point 
	* @param binChunkStartIndex Index for the first file to be processed in this chunk 
	*/
	void LoadFITS::loadChunkOfBinsFromFile(MatrixWorkspace_sptr &workspace, vector<vector<double> > &yVals, vector<vector<double> > &eVals, void *&bufferAny, MantidVecPtr &x, size_t spectraCount, int bitsPerPixel, size_t binChunkStartIndex)
	{
		size_t binsThisChunk = m_binChunkSize;
		if((binChunkStartIndex + m_binChunkSize) > m_allHeaderInfo.size())
		{
			// No need to do extra processing if number of bins to process is lower than m_binChunkSize
			// Also used to prevent out of bounds error where a greater number of elements have been reserved.
			binsThisChunk = static_cast<size_t>(m_allHeaderInfo.size() - binChunkStartIndex);
		}       

		uint8_t *buffer8 = NULL;
		uint16_t *buffer16 = NULL;
		uint32_t *buffer32 = NULL;
		
		// create pointer of correct data type to void pointer of the buffer:
		buffer8 = static_cast<uint8_t*>(bufferAny);
		buffer16 = static_cast<uint16_t*>(bufferAny);
		buffer32 = static_cast<uint32_t*>(bufferAny);
		
		for(size_t i=binChunkStartIndex; i < binChunkStartIndex+binsThisChunk ; ++i)
		{      
			// Read Data
			bool fileErr = false;
			FILE * currFile = fopen ( m_allHeaderInfo[i].filePath.c_str(), "rb" );
			if (currFile==NULL) fileErr = true;    

			size_t result = 0;
			if(!fileErr)
			{
				fseek (currFile , FIXED_HEADER_SIZE , SEEK_CUR);
				result = fread(bufferAny, bitsPerPixel/8, spectraCount, currFile);
			}

			if (result != spectraCount) fileErr = true;			

			if(fileErr)
			{
				throw std::runtime_error("Error reading file; possibly invalid data.");	
			}

			for(size_t j=0; j<spectraCount;++j)
			{
				double val = 0;
				if(bitsPerPixel == 8) val = static_cast<double>(buffer8[j]);
				if(bitsPerPixel == 16) val = static_cast<double>(buffer16[j]);
				if(bitsPerPixel == 32) val = static_cast<double>(buffer32[j]);

				yVals[j][i-binChunkStartIndex] = val;
				eVals[j][i-binChunkStartIndex] = sqrt(val);
			}				
			
			// Clear memory associated with the file load
			fclose (currFile);
		}

		// Now load chunk into workspace 
		PARALLEL_FOR1(workspace)
		for (int64_t wi = 0; wi < static_cast<int64_t>(spectraCount); ++wi)
		{
			workspace->setX(wi, x);
			MantidVec *currY = &workspace->dataY(wi);
			MantidVec *currE = &workspace->dataE(wi);
			
			std::copy(yVals[wi].begin(), yVals[wi].end()-(m_binChunkSize-binsThisChunk), currY->begin()+binChunkStartIndex );
			std::copy(eVals[wi].begin(), eVals[wi].end()-(m_binChunkSize-binsThisChunk), currE->begin()+binChunkStartIndex );

			// I expect this will be wanted once IDF is in a more useful state.
			//workspace->getSpectrum(wi)->setDetectorID(detid_t(wi));
			//workspace->getSpectrum(wi)->setSpectrumNo(specid_t(wi+1));
		}           
	}