/** 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)); }