Esempio n. 1
0
/** Executes the algorithm
 *  @throw std::out_of_range If a property is set to an invalid value for the
 * input workspace
 */
void ExtractSpectra::execEvent() {
  double minX_val = getProperty("XMin");
  double maxX_val = getProperty("XMax");
  if (isEmpty(minX_val))
    minX_val = eventW->getTofMin();
  if (isEmpty(maxX_val))
    maxX_val = eventW->getTofMax();

  // Retrieve and validate the input properties
  this->checkProperties();
  HistogramData::BinEdges XValues_new(2);
  if (m_commonBoundaries) {
    auto &oldX = m_inputWorkspace->x(m_workspaceIndexList.front());
    XValues_new =
        HistogramData::BinEdges(oldX.begin() + m_minX, oldX.begin() + m_maxX);
  }

  if (m_maxX - m_minX < 2) {
    // create new output X axis
    std::vector<double> rb_params{minX_val, maxX_val - minX_val, maxX_val};
    static_cast<void>(VectorHelper::createAxisFromRebinParams(
        rb_params, XValues_new.mutableRawData()));
  }

  // run inplace branch if appropriate
  MatrixWorkspace_sptr OutputWorkspace = this->getProperty("OutputWorkspace");
  bool inPlace = (OutputWorkspace == m_inputWorkspace);
  if (inPlace)
    g_log.debug("Cropping EventWorkspace in-place.");

  // Create the output workspace
  eventW->sortAll(TOF_SORT, nullptr);
  auto outputWorkspace = create<EventWorkspace>(
      *m_inputWorkspace,
      Indexing::extract(m_inputWorkspace->indexInfo(), m_workspaceIndexList),
      XValues_new);
  outputWorkspace->sortAll(TOF_SORT, nullptr);

  Progress prog(this, 0.0, 1.0, 2 * m_workspaceIndexList.size());
  eventW->sortAll(Mantid::DataObjects::TOF_SORT, &prog);
  // Loop over the required workspace indices, copying in the desired bins
  PARALLEL_FOR_IF(Kernel::threadSafe(*m_inputWorkspace, *outputWorkspace))
  for (int j = 0; j < static_cast<int>(m_workspaceIndexList.size()); ++j) {
    PARALLEL_START_INTERUPT_REGION
    auto i = m_workspaceIndexList[j];
    const EventList &el = eventW->getSpectrum(i);
    // The output event list
    EventList &outEL = outputWorkspace->getSpectrum(j);

    switch (el.getEventType()) {
    case TOF: {
      std::vector<TofEvent> moreevents;
      moreevents.reserve(el.getNumberEvents()); // assume all will make it
      copyEventsHelper(el.getEvents(), moreevents, minX_val, maxX_val);
      outEL += moreevents;
      break;
    }
    case WEIGHTED: {
      std::vector<WeightedEvent> moreevents;
      moreevents.reserve(el.getNumberEvents()); // assume all will make it
      copyEventsHelper(el.getWeightedEvents(), moreevents, minX_val, maxX_val);
      outEL += moreevents;
      break;
    }
    case WEIGHTED_NOTIME: {
      std::vector<WeightedEventNoTime> moreevents;
      moreevents.reserve(el.getNumberEvents()); // assume all will make it
      copyEventsHelper(el.getWeightedEventsNoTime(), moreevents, minX_val,
                       maxX_val);
      outEL += moreevents;
      break;
    }
    }
    outEL.setSortOrder(el.getSortType());

    bool hasDx = eventW->hasDx(i);

    if (!m_commonBoundaries) {
      // If the X axis is NOT common, then keep the initial X axis, just clear
      // the events
      outEL.setX(el.ptrX());
      outEL.setSharedDx(el.sharedDx());
    } else {
      // X is already set in workspace creation, just set Dx if necessary.
      if (hasDx) {
        auto &oldDx = m_inputWorkspace->dx(i);
        outEL.setPointStandardDeviations(oldDx.begin() + m_minX,
                                         oldDx.begin() + m_maxX - m_histogram);
      }
    }

    // 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);
      }
    }
    // When cropping in place, you can clear out old memory from the input one!
    if (inPlace) {
      eventW->getSpectrum(i).clear();
    }
    prog.report();
    PARALLEL_END_INTERUPT_REGION
  }
  PARALLEL_CHECK_INTERUPT_REGION

  setProperty("OutputWorkspace", std::move(outputWorkspace));
}
/** Executes the algorithm
 *  @throw std::out_of_range If a property is set to an invalid value for the
 * input workspace
 */
void ExtractSpectra::execEvent() {
  m_histogram = m_inputWorkspace->isHistogramData();
  double minX_val = getProperty("XMin");
  double maxX_val = getProperty("XMax");
  if (isEmpty(minX_val))
    minX_val = eventW->getTofMin();
  if (isEmpty(maxX_val))
    maxX_val = eventW->getTofMax();

  // Check for common boundaries in input workspace
  m_commonBoundaries = WorkspaceHelpers::commonBoundaries(m_inputWorkspace);

  // Retrieve and validate the input properties
  this->checkProperties();
  cow_ptr<MantidVec> XValues_new;
  if (m_commonBoundaries) {
    const MantidVec &oldX =
        m_inputWorkspace->readX(m_workspaceIndexList.front());
    XValues_new.access().assign(oldX.begin() + m_minX, oldX.begin() + m_maxX);
  }
  size_t ntcnew = m_maxX - m_minX;

  if (ntcnew < 2) {
    // create new output X axis
    std::vector<double> rb_params;
    rb_params.push_back(minX_val);
    rb_params.push_back(maxX_val - minX_val);
    rb_params.push_back(maxX_val);
    ntcnew = VectorHelper::createAxisFromRebinParams(rb_params,
                                                     XValues_new.access());
  }

  // run inplace branch if appropriate
  MatrixWorkspace_sptr OutputWorkspace = this->getProperty("OutputWorkspace");
  bool inPlace = (OutputWorkspace == m_inputWorkspace);
  if (inPlace)
    g_log.debug("Cropping EventWorkspace in-place.");

  // Create the output workspace
  EventWorkspace_sptr outputWorkspace =
      boost::dynamic_pointer_cast<EventWorkspace>(
          API::WorkspaceFactory::Instance().create(
              "EventWorkspace", m_workspaceIndexList.size(), ntcnew,
              ntcnew - m_histogram));
  eventW->sortAll(TOF_SORT, nullptr);
  outputWorkspace->sortAll(TOF_SORT, nullptr);
  // Copy required stuff from it
  API::WorkspaceFactory::Instance().initializeFromParent(m_inputWorkspace,
                                                         outputWorkspace, true);

  Progress prog(this, 0.0, 1.0, 2 * m_workspaceIndexList.size());
  eventW->sortAll(Mantid::DataObjects::TOF_SORT, &prog);
  // Loop over the required workspace indices, copying in the desired bins
  PARALLEL_FOR2(m_inputWorkspace, outputWorkspace)
  for (int j = 0; j < static_cast<int>(m_workspaceIndexList.size()); ++j) {
    PARALLEL_START_INTERUPT_REGION
    auto i = m_workspaceIndexList[j];
    const EventList &el = eventW->getEventList(i);
    // The output event list
    EventList &outEL = outputWorkspace->getOrAddEventList(j);
    //    // left side of the crop - will erase 0 -> endLeft
    //    std::size_t endLeft;
    //    // right side of the crop - will erase endRight->numEvents+1
    //    std::size_t endRight;

    switch (el.getEventType()) {
    case TOF: {
      std::vector<TofEvent> moreevents;
      moreevents.reserve(el.getNumberEvents()); // assume all will make it
      copyEventsHelper(el.getEvents(), moreevents, minX_val, maxX_val);
      outEL += moreevents;
      break;
    }
    case WEIGHTED: {
      std::vector<WeightedEvent> moreevents;
      moreevents.reserve(el.getNumberEvents()); // assume all will make it
      copyEventsHelper(el.getWeightedEvents(), moreevents, minX_val, maxX_val);
      outEL += moreevents;
      break;
    }
    case WEIGHTED_NOTIME: {
      std::vector<WeightedEventNoTime> moreevents;
      moreevents.reserve(el.getNumberEvents()); // assume all will make it
      copyEventsHelper(el.getWeightedEventsNoTime(), moreevents, minX_val,
                       maxX_val);
      outEL += moreevents;
      break;
    }
    }
    outEL.setSortOrder(el.getSortType());

    // Copy spectrum number & detector IDs
    outEL.copyInfoFrom(el);

    bool hasDx = eventW->hasDx(i);

    if (!m_commonBoundaries) {
      // If the X axis is NOT common, then keep the initial X axis, just clear
      // the events
      outEL.setX(el.dataX());
      if (hasDx) {
        outEL.setDx(el.dataDx());
      }
    } else {
      // Common bin boundaries get all set to the same value
      outEL.setX(XValues_new);
      if (hasDx) {
        const MantidVec &oldDx = m_inputWorkspace->readDx(i);
        cow_ptr<MantidVec> DxValues_new;
        DxValues_new.access().assign(oldDx.begin() + m_minX,
                                     oldDx.begin() + m_maxX);
        outEL.setDx(DxValues_new);
      }
    }

    // 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);
      }
    }
    // When cropping in place, you can clear out old memory from the input one!
    if (inPlace) {
      eventW->getEventList(i).clear();
      Mantid::API::MemoryManager::Instance().releaseFreeMemory();
    }
    prog.report();
    PARALLEL_END_INTERUPT_REGION
  }
  PARALLEL_CHECK_INTERUPT_REGION

  setProperty("OutputWorkspace",
              boost::dynamic_pointer_cast<MatrixWorkspace>(outputWorkspace));
}