/** Checks that the units of the workspace data are declared match any
 * required units
 *
 * @param value :: The workspace to test
 * @return A user level description of the error or "" for no error
 */
std::string
WorkspaceUnitValidator::checkValidity(const MatrixWorkspace_sptr &value) const {
  // This effectively checks for single-valued workspaces
  if (value->axes() == 0)
    return "A single valued workspace has no unit, which is required for "
           "this algorithm";

  Kernel::Unit_const_sptr unit = value->getAxis(0)->unit();
  // If m_unitID is empty it means that the workspace must have units, which
  // can be anything
  if (m_unitID.empty()) {
    return (
        unit && (!boost::dynamic_pointer_cast<const Kernel::Units::Empty>(unit))
            ? ""
            : "The workspace must have units");
  }
  // now check if the units of the workspace is correct
  else {
    if ((!unit) || (unit->unitID().compare(m_unitID))) {
      return "The workspace must have units of " +
             m_unitID; //+ "; its unit is: " + unit->caption();
    } else
      return "";
  }
}
Example #2
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 #3
0
/**
 * Execute the algorithm.
 */
void RebinByTimeBase::exec() {
  using Mantid::DataObjects::EventWorkspace;
  IEventWorkspace_sptr inWS = getProperty("InputWorkspace");

  if (!boost::dynamic_pointer_cast<EventWorkspace>(inWS)) {
    const std::string algName = this->name();
    throw std::invalid_argument(
        algName + " Algorithm requires an EventWorkspace as an input.");
  }

  MatrixWorkspace_sptr outputWS = getProperty("OutputWorkspace");

  // retrieve the properties
  const std::vector<double> inParams = getProperty("Params");
  std::vector<double> rebinningParams;

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

  const uint64_t nanoSecondsInASecond = static_cast<uint64_t>(1e9);
  const DateAndTime runStartTime = inWS->run().startTime();
  // The validator only passes parameters with size 1, or 3xn.

  double tStep = 0;
  if (inParams.size() >= 3) {
    // Use the start of the run to offset the times provided by the user. pulse
    // time of the events are absolute.
    const DateAndTime startTime = runStartTime + inParams[0];
    const DateAndTime endTime = runStartTime + inParams[2];
    // Rebinning params in nanoseconds.
    rebinningParams.push_back(
        static_cast<double>(startTime.totalNanoseconds()));
    tStep = inParams[1] * nanoSecondsInASecond;
    rebinningParams.push_back(tStep);
    rebinningParams.push_back(static_cast<double>(endTime.totalNanoseconds()));
  } else if (inParams.size() == 1) {
    const uint64_t xmin = getMinX(inWS);
    const uint64_t xmax = getMaxX(inWS);

    rebinningParams.push_back(static_cast<double>(xmin));
    tStep = inParams[0] * nanoSecondsInASecond;
    rebinningParams.push_back(tStep);
    rebinningParams.push_back(static_cast<double>(xmax));
  }

  // Validate the timestep.
  if (tStep <= 0) {
    throw std::invalid_argument(
        "Cannot have a timestep less than or equal to zero.");
  }

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

  MantidVecPtr XValues_new;
  // create new X axis, with absolute times in seconds.
  const int ntcnew = VectorHelper::createAxisFromRebinParams(
      rebinningParams, XValues_new.access());

  ConvertToRelativeTime transformToRelativeT(runStartTime);

  // Transform the output into relative times in seconds.
  MantidVec OutXValues_scaled(XValues_new->size());
  std::transform(XValues_new->begin(), XValues_new->end(),
                 OutXValues_scaled.begin(), transformToRelativeT);

  outputWS = WorkspaceFactory::Instance().create("Workspace2D", histnumber,
                                                 ntcnew, ntcnew - 1);
  WorkspaceFactory::Instance().initializeFromParent(inWS, outputWS, true);

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

  // X-unit is relative time since the start of the run.
  outputWS->getAxis(0)->unit() = boost::make_shared<Units::Time>();

  // Copy the units over too.
  for (int i = 1; i < outputWS->axes(); ++i) {
    outputWS->getAxis(i)->unit() = inWS->getAxis(i)->unit();
  }
  outputWS->setYUnit(inWS->YUnit());
  outputWS->setYUnitLabel(inWS->YUnitLabel());

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

  // Go through all the histograms and set the data
  doHistogramming(inWS, outputWS, XValues_new, OutXValues_scaled, prog);
}
Example #4
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 #5
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)