/** Executes the algorithm * @throw std::invalid_argument If the input workspaces do not meet the requirements of this algorithm */ void ConjoinWorkspaces::execEvent() { //We do not need to check that binning is compatible, just that there is no overlap this->checkForOverlap(event_ws1, event_ws2, false); // Create the output workspace const size_t totalHists = event_ws1->getNumberHistograms() + event_ws2->getNumberHistograms(); // Have the minimum # of histograms in the output. EventWorkspace_sptr output = boost::dynamic_pointer_cast<EventWorkspace>( WorkspaceFactory::Instance().create("EventWorkspace", 1, event_ws1->readX(0).size(), event_ws1->readY(0).size()) ); // Copy over geometry (but not data) from first input workspace WorkspaceFactory::Instance().initializeFromParent(event_ws1,output,true); // Create the X values inside a cow pointer - they will be shared in the output workspace cow_ptr<MantidVec> XValues; XValues.access() = event_ws1->readX(0); // Initialize the progress reporting object m_progress = new API::Progress(this, 0.0, 1.0, totalHists); const int64_t& nhist1 = event_ws1->getNumberHistograms(); for (int64_t i = 0; i < nhist1; ++i) { //Copy the events over output->getOrAddEventList(i) = event_ws1->getEventList(i); //Should fire the copy constructor m_progress->report(); } //For second loop we use the offset from the first const int64_t& nhist2 = event_ws2->getNumberHistograms(); for (int64_t j = 0; j < nhist2; ++j) { //This is the workspace index at which we assign in the output int64_t output_wi = j + nhist1; //Copy the events over output->getOrAddEventList(output_wi) = event_ws2->getEventList(j); //Should fire the copy constructor m_progress->report(); } //This will make the spectramap axis. output->doneAddingEventLists(); //Set the same bins for all output pixels output->setAllX(XValues); this->fixSpectrumNumbers(event_ws1, event_ws2, output); // Delete the input workspaces from the ADS AnalysisDataService::Instance().remove(getPropertyValue("InputWorkspace1")); AnalysisDataService::Instance().remove(getPropertyValue("InputWorkspace2")); // Create & assign an output workspace property with the workspace name the same as the first input declareProperty(new WorkspaceProperty<>("Output",getPropertyValue("InputWorkspace1"),Direction::Output)); setProperty("Output", boost::dynamic_pointer_cast<MatrixWorkspace>(output) ); }
/** Set up an Event workspace * @param numentries :: number of log entries to output * @param times :: vector of Kernel::DateAndTime * @param values :: vector of log value in double */ void ExportTimeSeriesLog::setupEventWorkspace(int numentries, vector<DateAndTime> ×, vector<double> values) { Kernel::DateAndTime runstart( m_dataWS->run().getProperty("run_start")->value()); // Get some stuff from the input workspace const size_t numberOfSpectra = 1; const int YLength = static_cast<int>(m_dataWS->blocksize()); // Make a brand new EventWorkspace EventWorkspace_sptr outEventWS = boost::dynamic_pointer_cast<EventWorkspace>( API::WorkspaceFactory::Instance().create( "EventWorkspace", numberOfSpectra, YLength + 1, YLength)); // Copy geometry over. API::WorkspaceFactory::Instance().initializeFromParent(m_dataWS, outEventWS, false); m_outWS = boost::dynamic_pointer_cast<MatrixWorkspace>(outEventWS); if (!m_outWS) throw runtime_error( "Output workspace cannot be casted to a MatrixWorkspace."); g_log.debug("[DBx336] An output workspace is generated.!"); // Create the output event list (empty) EventList &outEL = outEventWS->getOrAddEventList(0); outEL.switchTo(WEIGHTED_NOTIME); // Allocate all the required memory outEL.reserve(numentries); outEL.clearDetectorIDs(); for (size_t i = 0; i < static_cast<size_t>(numentries); i++) { Kernel::DateAndTime tnow = times[i]; int64_t dt = tnow.totalNanoseconds() - runstart.totalNanoseconds(); // convert to microseconds double dtmsec = static_cast<double>(dt) / 1000.0; outEL.addEventQuickly(WeightedEventNoTime(dtmsec, values[i], values[i])); } // Ensure thread-safety outEventWS->sortAll(TOF_SORT, NULL); // Now, create a default X-vector for histogramming, with just 2 bins. Kernel::cow_ptr<MantidVec> axis; MantidVec &xRef = axis.access(); xRef.resize(2); std::vector<WeightedEventNoTime> &events = outEL.getWeightedEventsNoTime(); xRef[0] = events.begin()->tof(); xRef[1] = events.rbegin()->tof(); // Set the binning axis using this. outEventWS->setX(0, axis); return; }
void CompressEvents::exec() { // Get the input workspace EventWorkspace_sptr inputWS = getProperty("InputWorkspace"); EventWorkspace_sptr outputWS = getProperty("OutputWorkspace"); double tolerance = getProperty("Tolerance"); // Some starting things bool inplace = (inputWS == outputWS); const int noSpectra = static_cast<int>(inputWS->getNumberHistograms()); Progress prog(this,0.0,1.0, noSpectra*2); // Sort the input workspace in-place by TOF. This can be faster if there are few event lists. inputWS->sortAll(TOF_SORT, &prog); // Are we making a copy of the input workspace? if (!inplace) { //Make a brand new EventWorkspace outputWS = boost::dynamic_pointer_cast<EventWorkspace>( API::WorkspaceFactory::Instance().create("EventWorkspace", inputWS->getNumberHistograms(), 2, 1)); //Copy geometry over. API::WorkspaceFactory::Instance().initializeFromParent(inputWS, outputWS, false); // We DONT copy the data though // Do we want to parallelize over event lists, or in each event list bool parallel_in_each = noSpectra < PARALLEL_GET_MAX_THREADS; //parallel_in_each = false; // Loop over the histograms (detector spectra) // Don't parallelize the loop if we are going to parallelize each event list. // cppcheck-suppress syntaxError PRAGMA_OMP( parallel for schedule(dynamic) if (!parallel_in_each) ) for (int i = 0; i < noSpectra; ++i) { PARALLEL_START_INTERUPT_REGION //the loop variable i can't be signed because of OpenMp rules inforced in Linux. Using this signed type suppresses warnings below const size_t index = static_cast<size_t>(i); // The input event list EventList& input_el = inputWS->getEventList(index); // And on the output side EventList & output_el = outputWS->getOrAddEventList(index); // Copy other settings into output output_el.setX( input_el.ptrX() ); // The EventList method does the work. input_el.compressEvents(tolerance, &output_el, parallel_in_each); prog.report("Compressing"); PARALLEL_END_INTERUPT_REGION } PARALLEL_CHECK_INTERUPT_REGION }
void GatherWorkspaces::execEvent() { // Every process in an MPI job must hit this next line or everything hangs! mpi::communicator included; // The communicator containing all processes // The root process needs to create a workspace of the appropriate size EventWorkspace_sptr outputWorkspace; if (included.rank() == 0) { g_log.debug() << "Total number of spectra is " << totalSpec << "\n"; // Create the workspace for the output outputWorkspace = boost::dynamic_pointer_cast<EventWorkspace>( API::WorkspaceFactory::Instance().create("EventWorkspace", sumSpec, numBins + hist, numBins)); // Copy geometry over. API::WorkspaceFactory::Instance().initializeFromParent( eventW, outputWorkspace, true); setProperty("OutputWorkspace", outputWorkspace); ExperimentInfo_sptr inWS = inputWorkspace; outputWorkspace->copyExperimentInfoFrom(inWS.get()); } for (size_t wi = 0; wi < totalSpec; wi++) { if (included.rank() == 0) { // How do we accumulate the data? std::string accum = this->getPropertyValue("AccumulationMethod"); std::vector<Mantid::DataObjects::EventList> out_values; gather(included, eventW->getEventList(wi), out_values, 0); for (int i = 0; i < included.size(); i++) { size_t index = wi; // accum == "Add" if (accum == "Append") index = wi + i * totalSpec; outputWorkspace->dataX(index) = eventW->readX(wi); outputWorkspace->getOrAddEventList(index) += out_values[i]; const ISpectrum *inSpec = eventW->getSpectrum(wi); ISpectrum *outSpec = outputWorkspace->getSpectrum(index); outSpec->clearDetectorIDs(); outSpec->addDetectorIDs(inSpec->getDetectorIDs()); } } else { gather(included, eventW->getEventList(wi), 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() { 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)); }