/** 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; }
/** Executes the algorithm */ void FilterBadPulses::exec() { // the input workspace into the event workspace we already know it is EventWorkspace_sptr inputWS = this->getProperty("InputWorkspace"); // get the proton charge exists in the run object const API::Run& runlogs = inputWS->run(); if (!runlogs.hasProperty("proton_charge")) { throw std::runtime_error("Failed to find \"proton_charge\" in sample logs"); } Kernel::TimeSeriesProperty<double> * pcharge_log = dynamic_cast<Kernel::TimeSeriesProperty<double> *>( runlogs.getLogData("proton_charge") ); Kernel::TimeSeriesPropertyStatistics stats = pcharge_log->getStatistics(); // set the range double min_percent = this->getProperty("LowerCutoff"); min_percent *= .01; // convert it to a percentage (0<x<1) double min_pcharge = stats.mean * min_percent; double max_pcharge = stats.maximum * 1.1; // make sure everything high is in if (min_pcharge >= max_pcharge) { throw std::runtime_error("proton_charge window filters out all of the data"); } this->g_log.information() << "Filtering pcharge outside of " << min_pcharge << " to " << max_pcharge << std::endl; size_t inputNumEvents = inputWS->getNumberEvents(); // sub-algorithme does all of the actual work - do not set the output workspace IAlgorithm_sptr filterAlgo = createSubAlgorithm("FilterByLogValue", 0., 1.); filterAlgo->setProperty("InputWorkspace", inputWS); filterAlgo->setProperty("LogName", "proton_charge"); filterAlgo->setProperty("MinimumValue", min_pcharge); filterAlgo->setProperty("MaximumValue", max_pcharge); filterAlgo->execute(); // just grab the child's output workspace EventWorkspace_sptr outputWS = filterAlgo->getProperty("OutputWorkspace"); size_t outputNumEvents = outputWS->getNumberEvents(); this->setProperty("OutputWorkspace", outputWS); // log the number of events deleted double percent = static_cast<double>(inputNumEvents - outputNumEvents) / static_cast<double>(inputNumEvents); percent *= 100.; if (percent > 10.) { this->g_log.warning() << "Deleted " << (inputNumEvents - outputNumEvents) << " of " << inputNumEvents << " events (" << static_cast<int>(percent) << "%)\n"; } else { this->g_log.information() << "Deleted " << (inputNumEvents - outputNumEvents) << " of " << inputNumEvents << " events (" << static_cast<int>(percent) << "%)\n"; } }
/** 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) ); }
/** Execute the algorithm for a EventWorkspace input * @param ws :: EventWorkspace */ void SmoothNeighbours::execEvent(Mantid::DataObjects::EventWorkspace_sptr ws) { m_progress->resetNumSteps(inWS->getNumberHistograms(), 0.5, 1.0); // Get some stuff from the input workspace const size_t numberOfSpectra = outWI; const int YLength = static_cast<int>(inWS->blocksize()); EventWorkspace_sptr outWS; // Make a brand new EventWorkspace outWS = boost::dynamic_pointer_cast<EventWorkspace>( API::WorkspaceFactory::Instance().create( "EventWorkspace", numberOfSpectra, YLength + 1, YLength)); // Copy geometry over. API::WorkspaceFactory::Instance().initializeFromParent(*ws, *outWS, false); // Ensure thread-safety outWS->sortAll(TOF_SORT, nullptr); this->setProperty("OutputWorkspace", boost::dynamic_pointer_cast<MatrixWorkspace>(outWS)); // Go through all the output workspace PARALLEL_FOR_IF(Kernel::threadSafe(*ws, *outWS)) for (int outWIi = 0; outWIi < int(numberOfSpectra); outWIi++) { PARALLEL_START_INTERUPT_REGION // Create the output event list (empty) EventList &outEL = outWS->getSpectrum(outWIi); // Which are the neighbours? std::vector<weightedNeighbour> &neighbours = m_neighbours[outWIi]; std::vector<weightedNeighbour>::iterator it; for (it = neighbours.begin(); it != neighbours.end(); ++it) { size_t inWI = it->first; // if(sum)outEL.copyInfoFrom(*ws->getSpectrum(inWI)); double weight = it->second; // Copy the event list EventList tmpEL = ws->getSpectrum(inWI); // Scale it tmpEL *= weight; // Add it outEL += tmpEL; } // Copy the single detector ID (of the center) and spectrum number from the // input workspace // if (!sum) outEL.copyInfoFrom(*ws->getSpectrum(outWIi)); m_progress->report("Summing"); PARALLEL_END_INTERUPT_REGION } PARALLEL_CHECK_INTERUPT_REGION // Give the 0-th X bins to all the output spectra. outWS->setAllX(inWS->binEdges(0)); if (expandSumAllPixels) spreadPixels(outWS); }
/** Generate mapping file name from Event workspace's instrument */ static string generateMappingfileName(EventWorkspace_sptr &wksp) { // get the name of the mapping file as set in the parameter files std::vector<string> temp = wksp->getInstrument()->getStringParameter("TS_mapping_file"); if (temp.empty()) return ""; string mapping = temp[0]; // Try to get it from the working directory Poco::File localmap(mapping); if (localmap.exists()) return mapping; // Try to get it from the data directories string dataversion = Mantid::API::FileFinder::Instance().getFullPath(mapping); if (!dataversion.empty()) return dataversion; // get a list of all proposal directories string instrument = wksp->getInstrument()->getName(); Poco::File base("/SNS/" + instrument + "/"); // try short instrument name if (!base.exists()) { instrument = Kernel::ConfigService::Instance().getInstrument(instrument).shortName(); base = Poco::File("/SNS/" + instrument + "/"); if (!base.exists()) return ""; } vector<string> dirs; // poco won't let me reuse temp base.list(dirs); // check all of the proposals for the mapping file in the canonical place const string CAL("_CAL"); const size_t CAL_LEN = CAL.length(); // cache to make life easier vector<string> files; for (auto &dir : dirs) { if ((dir.length() > CAL_LEN) && (dir.compare(dir.length() - CAL.length(), CAL.length(), CAL) == 0)) { std::string path = std::string(base.path()) .append("/") .append(dir) .append("/calibrations/") .append(mapping); if (Poco::File(path).exists()) files.push_back(path); } } if (files.empty()) return ""; else if (files.size() == 1) return files[0]; else // just assume that the last one is the right one, this should never be // fired return *(files.rbegin()); }
/// Called by the foreground thread to fetch data that's accumulated in /// the temporary workspace. The temporary workspace is left empty and /// ready to receive more data. /// @return shared pointer to a workspace containing the accumulated data boost::shared_ptr<Workspace> TOPAZLiveEventDataListener::extractData() { // Check to see if the background thread has thrown an exception. If so, // re-throw it here. if (m_backgroundException) { throw(*m_backgroundException); } // Sanity check - make sure the workspace has been initialized if (!m_workspaceInitialized) { throw std::runtime_error("TOPAZLiveEventDataListener: " "The workspace has not been initialized."); } using namespace DataObjects; // Make a brand new EventWorkspace EventWorkspace_sptr temp = boost::dynamic_pointer_cast<EventWorkspace>( API::WorkspaceFactory::Instance().create( "EventWorkspace", m_eventBuffer->getNumberHistograms(), 2, 1)); // Copy geometry over. API::WorkspaceFactory::Instance().initializeFromParent(*m_eventBuffer, *temp, false); // Clear out the old logs, except for the most recent entry temp->mutableRun().clearOutdatedTimeSeriesLogValues(); // Clear out old monitor logs // TODO: At present, there's no way for monitor logs to be added // to m_monitorLogs. Either implement this feature, or remove // m_monitorLogs! for (auto &monitorLog : m_monitorLogs) { temp->mutableRun().removeProperty(monitorLog); } m_monitorLogs.clear(); // Create a fresh monitor workspace and insert into the new 'main' workspace auto monitorBuffer = m_eventBuffer->monitorWorkspace(); auto newMonitorBuffer = WorkspaceFactory::Instance().create( "EventWorkspace", monitorBuffer->getNumberHistograms(), 1, 1); WorkspaceFactory::Instance().initializeFromParent(*monitorBuffer, *newMonitorBuffer, false); temp->setMonitorWorkspace(newMonitorBuffer); // Lock the mutex and swap the workspaces { std::lock_guard<std::mutex> scopedLock(m_mutex); std::swap(m_eventBuffer, temp); } // mutex automatically unlocks here return temp; }
/** 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; }
void ScaleX::execEvent() { g_log.information("Processing event workspace"); const MatrixWorkspace_const_sptr matrixInputWS = this->getProperty("InputWorkspace"); EventWorkspace_const_sptr inputWS = boost::dynamic_pointer_cast<const EventWorkspace>(matrixInputWS); // generate the output workspace pointer API::MatrixWorkspace_sptr matrixOutputWS = this->getProperty("OutputWorkspace"); EventWorkspace_sptr outputWS; if (matrixOutputWS == matrixInputWS) outputWS = boost::dynamic_pointer_cast<EventWorkspace>(matrixOutputWS); else { //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); //You need to copy over the data as well. outputWS->copyDataFrom( (*inputWS) ); //Cast to the matrixOutputWS and save it matrixOutputWS = boost::dynamic_pointer_cast<MatrixWorkspace>(outputWS); this->setProperty("OutputWorkspace", matrixOutputWS); } int numHistograms = static_cast<int>(inputWS->getNumberHistograms()); PARALLEL_FOR1(outputWS) for (int i=0; i < numHistograms; ++i) { PARALLEL_START_INTERUPT_REGION //Do the offsetting if ((i >= wi_min) && (i <= wi_max)) { outputWS->getEventList(i).scaleTof(factor); if( factor < 0 ) { outputWS->getEventList(i).reverse(); } } m_progress->report("Scaling X"); PARALLEL_END_INTERUPT_REGION } PARALLEL_CHECK_INTERUPT_REGION outputWS->clearMRU(); }
/** Executes the algorithm * */ void SmoothNeighbours::exec() { inWS = getProperty("InputWorkspace"); PreserveEvents = getProperty("PreserveEvents"); expandSumAllPixels = getProperty("ExpandSumAllPixels"); // Use the unit type to translate the entered radius into meters. Radius = translateToMeters(getProperty("RadiusUnits"), getProperty("Radius")); setWeightingStrategy(getProperty("WeightedSum"), Radius); AdjX = getProperty("AdjX"); AdjY = getProperty("AdjY"); Edge = getProperty("ZeroEdgePixels"); nNeighbours = getProperty("NumberOfNeighbours"); // Progress reporting, first for the sorting m_progress = make_unique<Progress>(this, 0.0, 0.2, inWS->getNumberHistograms()); // Run the appropriate method depending on the type of the instrument if (inWS->getInstrument()->containsRectDetectors() == Instrument::ContainsState::Full) findNeighboursRectangular(); else findNeighboursUbiqutious(); EventWorkspace_sptr wsEvent = boost::dynamic_pointer_cast<EventWorkspace>(inWS); if (wsEvent) wsEvent->sortAll(TOF_SORT, m_progress.get()); if (!wsEvent || !PreserveEvents) this->execWorkspace2D(); else if (wsEvent) this->execEvent(wsEvent); else throw std::runtime_error("This algorithm requires a Workspace2D or " "EventWorkspace as its input."); }
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); } } }
/** Validate the input event workspaces * * @param inputWorkspaces The names of the input workspaces * @throw invalid_argument if there is an incompatibility. * @return true if all workspaces are event workspaces and valid. False if any *are not found, */ bool MergeRuns::validateInputsForEventWorkspaces( const std::vector<std::string> &inputWorkspaces) { std::string xUnitID; std::string YUnit; bool dist(false); m_inEventWS.clear(); // Going to check that name of instrument matches - think that's the best // possible at the moment // because if instrument is created from raw file it'll be a different // object std::string instrument; for (size_t i = 0; i < inputWorkspaces.size(); ++i) { // Fetch the next input workspace as an - throw an error if it's not there EventWorkspace_sptr ws = AnalysisDataService::Instance().retrieveWS<EventWorkspace>( inputWorkspaces[i]); if (!ws) { // Either it is not found, or it is not an EventWorkspace return false; } m_inEventWS.push_back(ws); // Check a few things are the same for all input workspaces if (i == 0) { xUnitID = ws->getAxis(0)->unit()->unitID(); YUnit = ws->YUnit(); dist = ws->isDistribution(); instrument = ws->getInstrument()->getName(); } else { testCompatibility(ws, xUnitID, YUnit, dist, instrument); } } // for each input WS name // We got here: all are event workspaces return true; }
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 }
/** Executes the rebin algorithm * * @throw runtime_error Thrown if the bin range does not intersect the range of the input workspace */ void SortEvents::exec() { // Get the input workspace EventWorkspace_sptr eventW = getProperty("InputWorkspace"); //And other properties std::string sortoption = getPropertyValue("SortBy"); //------- EventWorkspace --------------------------- const size_t histnumber = eventW->getNumberHistograms(); //Initialize progress reporting. Progress prog(this,0.0,1.0, histnumber); DataObjects::EventSortType sortType = DataObjects::TOF_SORT; if (sortoption == "Pulse Time") sortType = DataObjects::PULSETIME_SORT; else if (sortoption == "Pulse Time + TOF") sortType = DataObjects::PULSETIMETOF_SORT; //This runs the SortEvents algorithm in parallel eventW->sortAll(sortType, &prog); return; }
void SANSSolidAngleCorrection::execEvent() { MatrixWorkspace_sptr inputWS = getProperty("InputWorkspace"); EventWorkspace_sptr inputEventWS = boost::dynamic_pointer_cast<EventWorkspace>(inputWS); const int numberOfSpectra = static_cast<int>(inputEventWS->getNumberHistograms()); Progress progress(this, 0.0, 1.0, inputEventWS->getNumberHistograms()); // generate the output workspace pointer MatrixWorkspace_sptr outputWS = this->getProperty("OutputWorkspace"); EventWorkspace_sptr outputEventWS; if (outputWS == inputWS) outputEventWS = boost::dynamic_pointer_cast<EventWorkspace>(outputWS); else { // Make a brand new EventWorkspace outputEventWS = boost::dynamic_pointer_cast<EventWorkspace>( WorkspaceFactory::Instance().create( "EventWorkspace", inputEventWS->getNumberHistograms(), 2, 1)); // Copy geometry over. WorkspaceFactory::Instance().initializeFromParent(inputEventWS, outputEventWS, false); // You need to copy over the data as well. outputEventWS->copyDataFrom((*inputEventWS)); // Cast to the matrixOutputWS and save it outputWS = boost::dynamic_pointer_cast<MatrixWorkspace>(outputEventWS); this->setProperty("OutputWorkspace", outputWS); } progress.report("Solid Angle Correction"); PARALLEL_FOR2(inputEventWS, outputEventWS) for (int i = 0; i < numberOfSpectra; i++) { PARALLEL_START_INTERUPT_REGION IDetector_const_sptr det; try { det = inputEventWS->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 (!det) continue; // Skip if we have a monitor or if the detector is masked. if (det->isMonitor() || det->isMasked()) continue; // Compute solid angle correction factor const bool is_tube = getProperty("DetectorTubes"); const double tanTheta = tan(inputEventWS->detectorTwoTheta(det)); const double theta_term = sqrt(tanTheta * tanTheta + 1.0); double corr; if (is_tube) { const double tanAlpha = tan(getYTubeAngle(det, inputWS)); const double alpha_term = sqrt(tanAlpha * tanAlpha + 1.0); corr = alpha_term * theta_term * theta_term; } else { corr = theta_term * theta_term * theta_term; } EventList &el = outputEventWS->getEventList(i); el *= corr; progress.report("Solid Angle Correction"); PARALLEL_END_INTERUPT_REGION } PARALLEL_CHECK_INTERUPT_REGION setProperty("OutputMessage", "Solid angle correction applied"); }
/// Executes the algorithm for events void UnaryOperation::execEvent() { g_log.information("Processing event workspace"); const MatrixWorkspace_const_sptr matrixInputWS = this->getProperty(inputPropName()); EventWorkspace_const_sptr inputWS = boost::dynamic_pointer_cast<const EventWorkspace>(matrixInputWS); // generate the output workspace pointer API::MatrixWorkspace_sptr matrixOutputWS = this->getProperty(outputPropName()); EventWorkspace_sptr outputWS; if (matrixOutputWS == matrixInputWS) { outputWS = boost::dynamic_pointer_cast<EventWorkspace>(matrixOutputWS); } else { // 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); // You need to copy over the data as well. outputWS->copyDataFrom((*inputWS)); // Cast to the matrixOutputWS and save it matrixOutputWS = boost::dynamic_pointer_cast<MatrixWorkspace>(outputWS); this->setProperty("OutputWorkspace", matrixOutputWS); } // Now fetch any properties defined by concrete algorithm retrieveProperties(); int64_t numHistograms = static_cast<int64_t>(inputWS->getNumberHistograms()); API::Progress prog = API::Progress(this, 0.0, 1.0, numHistograms); PARALLEL_FOR1(outputWS) for (int64_t i = 0; i < numHistograms; ++i) { PARALLEL_START_INTERUPT_REGION // switch to weighted events if needed, and use the appropriate helper // function EventList *evlist = outputWS->getEventListPtr(i); switch (evlist->getEventType()) { case TOF: // Switch to weights if needed. evlist->switchTo(WEIGHTED); /* no break */ // Fall through case WEIGHTED: unaryOperationEventHelper(evlist->getWeightedEvents()); break; case WEIGHTED_NOTIME: unaryOperationEventHelper(evlist->getWeightedEventsNoTime()); break; } prog.report(); PARALLEL_END_INTERUPT_REGION } PARALLEL_CHECK_INTERUPT_REGION outputWS->clearMRU(); if (inputWS->getNumberEvents() != outputWS->getNumberEvents()) { g_log.information() << "Number of events has changed!!!" << std::endl; } }
/** Executes the algorithm */ void FilterByTime::exec() { EventWorkspace_const_sptr inputWS = this->getProperty("InputWorkspace"); // ---- Find the start/end times ---- DateAndTime start, stop; double start_dbl, stop_dbl; start_dbl = getProperty("StartTime"); stop_dbl = getProperty("StopTime"); std::string start_str, stop_str; start_str = getPropertyValue("AbsoluteStartTime"); stop_str = getPropertyValue("AbsoluteStopTime"); if ( (start_str != "") && (stop_str != "") && (start_dbl <= 0.0) && (stop_dbl <= 0.0) ) { // Use the absolute string start = DateAndTime( start_str ); stop = DateAndTime( stop_str ); } else if ( (start_str == "") && (stop_str == "") && ((start_dbl > 0.0) || (stop_dbl > 0.0)) ) { // Use the relative times in seconds. DateAndTime first = inputWS->getFirstPulseTime(); DateAndTime last = inputWS->getLastPulseTime(); start = first + start_dbl; if (stop_dbl > 0.0) { stop = first + stop_dbl; } else { this->getLogger().debug() << "No end filter time specified - assuming last pulse" << std::endl; stop = last + 10000.0; // so we get all events - needs to be past last pulse } } else { //Either both or none were specified throw std::invalid_argument("You need to specify either the StartTime or StopTime parameters; or both the AbsoluteStartTime and AbsoluteStopTime parameters; but not other combinations."); } if (stop <= start) throw std::invalid_argument("The stop time should be larger than the start time."); // Make a brand new EventWorkspace EventWorkspace_sptr 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); // But we don't copy the data. setProperty("OutputWorkspace", outputWS); size_t numberOfSpectra = inputWS->getNumberHistograms(); // Initialise the progress reporting object Progress prog(this,0.0,1.0,numberOfSpectra); // Loop over the histograms (detector spectra) PARALLEL_FOR_NO_WSP_CHECK() for (int64_t i = 0; i < int64_t(numberOfSpectra); ++i) { PARALLEL_START_INTERUPT_REGION //Get the output event list (should be empty) EventList& output_el = outputWS->getEventList(i); //and this is the input event list const EventList& input_el = inputWS->getEventList(i); //Perform the filtering input_el.filterByPulseTime(start, stop, output_el); prog.report(); PARALLEL_END_INTERUPT_REGION } PARALLEL_CHECK_INTERUPT_REGION //Now filter out the run, using the DateAndTime type. outputWS->mutableRun().filterByTime(start, stop); }
/** Convert the workspace units using TOF as an intermediate step in the * conversion * @param fromUnit :: The unit of the input workspace * @param outputWS :: The output workspace */ void ConvertUnitsUsingDetectorTable::convertViaTOF( Kernel::Unit_const_sptr fromUnit, API::MatrixWorkspace_sptr outputWS) { using namespace Geometry; // Let's see if we are using a TableWorkspace to override parameters TableWorkspace_sptr paramWS = getProperty("DetectorParameters"); // See if we have supplied a DetectorParameters Workspace // TODO: Check if paramWS is NULL and if so throw an exception // const std::string l1ColumnLabel("l1"); // Let's check all the columns exist and are readable try { auto spectraColumnTmp = paramWS->getColumn("spectra"); auto l1ColumnTmp = paramWS->getColumn("l1"); auto l2ColumnTmp = paramWS->getColumn("l2"); auto twoThetaColumnTmp = paramWS->getColumn("twotheta"); auto efixedColumnTmp = paramWS->getColumn("efixed"); auto emodeColumnTmp = paramWS->getColumn("emode"); } catch (...) { throw Exception::InstrumentDefinitionError( "DetectorParameter TableWorkspace is not defined correctly."); } // Now let's read them into some vectors. auto l1Column = paramWS->getColVector<double>("l1"); auto l2Column = paramWS->getColVector<double>("l2"); auto twoThetaColumn = paramWS->getColVector<double>("twotheta"); auto efixedColumn = paramWS->getColVector<double>("efixed"); auto emodeColumn = paramWS->getColVector<int>("emode"); auto spectraColumn = paramWS->getColVector<int>("spectra"); EventWorkspace_sptr eventWS = boost::dynamic_pointer_cast<EventWorkspace>(outputWS); assert(static_cast<bool>(eventWS) == m_inputEvents); // Sanity check Progress prog(this, 0.2, 1.0, m_numberOfSpectra); int64_t numberOfSpectra_i = static_cast<int64_t>(m_numberOfSpectra); // cast to make openmp happy // Get the unit object for each workspace Kernel::Unit_const_sptr outputUnit = outputWS->getAxis(0)->unit(); std::vector<double> emptyVec; int failedDetectorCount = 0; // ConstColumnVector<int> spectraNumber = paramWS->getVector("spectra"); // TODO: Check why this parallel stuff breaks // Loop over the histograms (detector spectra) // PARALLEL_FOR1(outputWS) for (int64_t i = 0; i < numberOfSpectra_i; ++i) { // Lets find what row this spectrum ID appears in our detector table. // PARALLEL_START_INTERUPT_REGION std::size_t wsid = i; try { double deg2rad = M_PI / 180.; auto det = outputWS->getDetector(i); int specid = det->getID(); // int spectraNumber = static_cast<int>(spectraColumn->toDouble(i)); // wsid = outputWS->getIndexFromSpectrumNumber(spectraNumber); g_log.debug() << "###### Spectra #" << specid << " ==> Workspace ID:" << wsid << std::endl; // Now we need to find the row that contains this spectrum std::vector<int>::iterator specIter; specIter = std::find(spectraColumn.begin(), spectraColumn.end(), specid); if (specIter != spectraColumn.end()) { size_t detectorRow = std::distance(spectraColumn.begin(), specIter); double l1 = l1Column[detectorRow]; double l2 = l2Column[detectorRow]; double twoTheta = twoThetaColumn[detectorRow] * deg2rad; double efixed = efixedColumn[detectorRow]; int emode = emodeColumn[detectorRow]; g_log.debug() << "specId from detector table = " << spectraColumn[detectorRow] << std::endl; // l1 = l1Column->toDouble(detectorRow); // l2 = l2Column->toDouble(detectorRow); // twoTheta = deg2rad * twoThetaColumn->toDouble(detectorRow); // efixed = efixedColumn->toDouble(detectorRow); // emode = static_cast<int>(emodeColumn->toDouble(detectorRow)); g_log.debug() << "###### Spectra #" << specid << " ==> Det Table Row:" << detectorRow << std::endl; g_log.debug() << "\tL1=" << l1 << ",L2=" << l2 << ",TT=" << twoTheta << ",EF=" << efixed << ",EM=" << emode << std::endl; // Make local copies of the units. This allows running the loop in // parallel Unit *localFromUnit = fromUnit->clone(); Unit *localOutputUnit = outputUnit->clone(); /// @todo Don't yet consider hold-off (delta) const double delta = 0.0; // Convert the input unit to time-of-flight localFromUnit->toTOF(outputWS->dataX(wsid), emptyVec, l1, l2, twoTheta, emode, efixed, delta); // Convert from time-of-flight to the desired unit localOutputUnit->fromTOF(outputWS->dataX(wsid), emptyVec, l1, l2, twoTheta, emode, efixed, delta); // EventWorkspace part, modifying the EventLists. if (m_inputEvents) { eventWS->getEventList(wsid) .convertUnitsViaTof(localFromUnit, localOutputUnit); } // Clear unit memory delete localFromUnit; delete localOutputUnit; } else { // Not found g_log.debug() << "Spectrum " << specid << " not found!" << std::endl; failedDetectorCount++; outputWS->maskWorkspaceIndex(wsid); } } catch (Exception::NotFoundError &) { // Get to here if exception thrown when calculating distance to detector failedDetectorCount++; // Since you usually (always?) get to here when there's no attached // detectors, this call is // the same as just zeroing out the data (calling clearData on the // spectrum) outputWS->maskWorkspaceIndex(i); } prog.report("Convert to " + m_outputUnit->unitID()); // PARALLEL_END_INTERUPT_REGION } // loop over spectra // PARALLEL_CHECK_INTERUPT_REGION if (failedDetectorCount != 0) { g_log.information() << "Something went wrong for " << failedDetectorCount << " spectra. Masking spectrum." << std::endl; } if (m_inputEvents) eventWS->clearMRU(); }
void ModeratorTzero::execEvent() { g_log.information("Processing event workspace"); const MatrixWorkspace_const_sptr matrixInputWS = getProperty("InputWorkspace"); EventWorkspace_const_sptr inputWS= boost::dynamic_pointer_cast<const EventWorkspace>(matrixInputWS); // generate the output workspace pointer const size_t numHists = static_cast<size_t>(inputWS->getNumberHistograms()); Mantid::API::MatrixWorkspace_sptr matrixOutputWS = getProperty("OutputWorkspace"); EventWorkspace_sptr outputWS; if (matrixOutputWS == matrixInputWS) { outputWS = boost::dynamic_pointer_cast<EventWorkspace>(matrixOutputWS); } else { //Make a brand new EventWorkspace outputWS = boost::dynamic_pointer_cast<EventWorkspace>(WorkspaceFactory::Instance().create("EventWorkspace", numHists, 2, 1)); //Copy geometry over. WorkspaceFactory::Instance().initializeFromParent(inputWS, outputWS, false); //You need to copy over the data as well. outputWS->copyDataFrom( (*inputWS) ); //Cast to the matrixOutputWS and save it matrixOutputWS = boost::dynamic_pointer_cast<MatrixWorkspace>(outputWS); setProperty("OutputWorkspace", matrixOutputWS); } //Get a pointer to the sample IComponent_const_sptr sample = outputWS->getInstrument()->getSample(); // Loop over the spectra Progress prog(this,0.0,1.0,numHists); //report progress of algorithm PARALLEL_FOR1(outputWS) for (int i = 0; i < static_cast<int>(numHists); ++i) { PARALLEL_START_INTERUPT_REGION size_t wsIndex = static_cast<size_t>(i); EventList &evlist=outputWS->getEventList(wsIndex); if( evlist.getNumberEvents() > 0 ) //don't bother with empty lists { double L1=CalculateL1(matrixOutputWS, wsIndex); // distance from source to sample or monitor double t2=CalculateT2(matrixOutputWS, wsIndex); // time from sample to detector if(t2>=0) //t2 < 0 when no detector info is available { double tof, E1; mu::Parser parser; parser.DefineVar("incidentEnergy", &E1); // associate variable E1 to this parser parser.SetExpr(m_formula); E1=m_convfactor*(L1/m_t1min)*(L1/m_t1min); double min_t0_next=parser.Eval(); // fast neutrons are shifted by min_t0_next, irrespective of tof // fix the histogram bins MantidVec &x=evlist.dataX(); for (MantidVec::iterator iter=x.begin(); iter!=x.end(); ++iter) { tof=*iter; if(tof<m_t1min+t2) tof-=min_t0_next; else tof-=CalculateT0(tof, L1, t2, E1, parser); *iter=tof; } MantidVec tofs=evlist.getTofs(); for(unsigned int itof=0; itof<tofs.size(); itof++) { tof=tofs[itof]+0.002*(rand()%100 -50); // add a [-0.1,0.1] microsecond noise to avoid artifacts resulting from original tof data if(tof<m_t1min+t2) tof-=min_t0_next; else tof-=CalculateT0(tof, L1, t2, E1, parser); tofs[itof]=tof; } evlist.setTofs(tofs); evlist.setSortOrder(Mantid::DataObjects::EventSortType::UNSORTED); } } prog.report(); PARALLEL_END_INTERUPT_REGION } PARALLEL_CHECK_INTERUPT_REGION outputWS->clearMRU(); // Clears the Most Recent Used lists */ } // end of void ModeratorTzero::execEvent()
/** Executes the algorithm *@param localworkspace :: the input workspace *@param indices :: set of indices to sum up */ void SumSpectra::execEvent(EventWorkspace_const_sptr localworkspace, std::set<int> &indices) { // Make a brand new EventWorkspace EventWorkspace_sptr outputWorkspace = boost::dynamic_pointer_cast<EventWorkspace>( API::WorkspaceFactory::Instance().create("EventWorkspace", 1, 2, 1)); // Copy geometry over. API::WorkspaceFactory::Instance().initializeFromParent(localworkspace, outputWorkspace, true); Progress progress(this, 0, 1, indices.size()); // Get the pointer to the output event list EventList &outEL = outputWorkspace->getEventList(0); outEL.setSpectrumNo(m_outSpecId); outEL.clearDetectorIDs(); // Loop over spectra std::set<int>::iterator it; size_t numSpectra(0); size_t numMasked(0); size_t numZeros(0); // for (int i = m_minSpec; i <= m_maxSpec; ++i) for (it = indices.begin(); it != indices.end(); ++it) { int i = *it; // Don't go outside the range. if ((i >= m_numberOfSpectra) || (i < 0)) { g_log.error() << "Invalid index " << i << " was specified. Sum was aborted.\n"; break; } try { // Get the detector object for this spectrum Geometry::IDetector_const_sptr det = localworkspace->getDetector(i); // Skip monitors, if the property is set to do so if (!m_keepMonitors && det->isMonitor()) continue; // Skip masked detectors if (det->isMasked()) { numMasked++; continue; } } catch (...) { // if the detector not found just carry on } numSpectra++; // Add the event lists with the operator const EventList &tOutEL = localworkspace->getEventList(i); if (tOutEL.empty()) { ++numZeros; } outEL += tOutEL; progress.report(); } // Set all X bins on the output cow_ptr<MantidVec> XValues; XValues.access() = localworkspace->readX(0); outputWorkspace->setAllX(XValues); outputWorkspace->mutableRun().addProperty("NumAllSpectra", int(numSpectra), "", true); outputWorkspace->mutableRun().addProperty("NumMaskSpectra", int(numMasked), "", true); outputWorkspace->mutableRun().addProperty("NumZeroSpectra", int(numZeros), "", true); // Assign it to the output workspace property setProperty("OutputWorkspace", boost::dynamic_pointer_cast<MatrixWorkspace>(outputWorkspace)); }
/** Process the event file properly. * @param workspace :: EventWorkspace to write to. */ void LoadEventPreNexus::procEvents(DataObjects::EventWorkspace_sptr &workspace) { this->num_error_events = 0; this->num_good_events = 0; this->num_ignored_events = 0; // Default values in the case of no parallel size_t loadBlockSize = Mantid::Kernel::DEFAULT_BLOCK_SIZE * 2; shortest_tof = static_cast<double>(MAX_TOF_UINT32) * TOF_CONVERSION; longest_tof = 0.; // Initialize progress reporting. size_t numBlocks = (max_events + loadBlockSize - 1) / loadBlockSize; // We want to pad out empty pixels. detid2det_map detector_map; workspace->getInstrument()->getDetectors(detector_map); // -------------- Determine processing mode std::string procMode = getProperty("UseParallelProcessing"); if (procMode == "Serial") parallelProcessing = false; else if (procMode == "Parallel") parallelProcessing = true; else { // Automatic determination. Loading serially (for me) is about 3 million // events per second, // (which is sped up by ~ x 3 with parallel processing, say 10 million per // second, e.g. 7 million events more per seconds). // compared to a setup time/merging time of about 10 seconds per million // detectors. double setUpTime = double(detector_map.size()) * 10e-6; parallelProcessing = ((double(max_events) / 7e6) > setUpTime); g_log.debug() << (parallelProcessing ? "Using" : "Not using") << " parallel processing." << std::endl; } // determine maximum pixel id detid2det_map::iterator it; detid_max = 0; // seems like a safe lower bound for (it = detector_map.begin(); it != detector_map.end(); it++) if (it->first > detid_max) detid_max = it->first; // Pad all the pixels prog->report("Padding Pixels"); this->pixel_to_wkspindex.reserve( detid_max + 1); // starting at zero up to and including detid_max // Set to zero this->pixel_to_wkspindex.assign(detid_max + 1, 0); size_t workspaceIndex = 0; for (it = detector_map.begin(); it != detector_map.end(); it++) { if (!it->second->isMonitor()) { this->pixel_to_wkspindex[it->first] = workspaceIndex; EventList &spec = workspace->getOrAddEventList(workspaceIndex); spec.addDetectorID(it->first); // Start the spectrum number at 1 spec.setSpectrumNo(specid_t(workspaceIndex + 1)); workspaceIndex += 1; } } // For slight speed up loadOnlySomeSpectra = (this->spectra_list.size() > 0); // Turn the spectra list into a map, for speed of access for (std::vector<int64_t>::iterator it = spectra_list.begin(); it != spectra_list.end(); it++) spectraLoadMap[*it] = true; CPUTimer tim; // --------------- Create the partial workspaces // ------------------------------------------ // Vector of partial workspaces, for parallel processing. std::vector<EventWorkspace_sptr> partWorkspaces; std::vector<DasEvent *> buffers; /// Pointer to the vector of events typedef std::vector<TofEvent> *EventVector_pt; /// Bare array of arrays of pointers to the EventVectors EventVector_pt **eventVectors; /// How many threads will we use? size_t numThreads = 1; if (parallelProcessing) numThreads = size_t(PARALLEL_GET_MAX_THREADS); partWorkspaces.resize(numThreads); buffers.resize(numThreads); eventVectors = new EventVector_pt *[numThreads]; // cppcheck-suppress syntaxError PRAGMA_OMP( parallel for if (parallelProcessing) ) for (int i = 0; i < int(numThreads); i++) { // This is the partial workspace we are about to create (if in parallel) EventWorkspace_sptr partWS; if (parallelProcessing) { prog->report("Creating Partial Workspace"); // Create a partial workspace partWS = EventWorkspace_sptr(new EventWorkspace()); // Make sure to initialize. partWS->initialize(1, 1, 1); // Copy all the spectra numbers and stuff (no actual events to copy // though). partWS->copyDataFrom(*workspace); // Push it in the array partWorkspaces[i] = partWS; } else partWS = workspace; // Allocate the buffers buffers[i] = new DasEvent[loadBlockSize]; // For each partial workspace, make an array where index = detector ID and // value = pointer to the events vector eventVectors[i] = new EventVector_pt[detid_max + 1]; EventVector_pt *theseEventVectors = eventVectors[i]; for (detid_t j = 0; j < detid_max + 1; j++) { size_t wi = pixel_to_wkspindex[j]; // Save a POINTER to the vector<tofEvent> theseEventVectors[j] = &partWS->getEventList(wi).getEvents(); } } g_log.debug() << tim << " to create " << partWorkspaces.size() << " workspaces for parallel loading." << std::endl; prog->resetNumSteps(numBlocks, 0.1, 0.8); // ---------------------------------- LOAD THE DATA -------------------------- PRAGMA_OMP( parallel for schedule(dynamic, 1) if (parallelProcessing) ) for (int blockNum = 0; blockNum < int(numBlocks); blockNum++) { PARALLEL_START_INTERUPT_REGION // Find the workspace for this particular thread EventWorkspace_sptr ws; size_t threadNum = 0; if (parallelProcessing) { threadNum = PARALLEL_THREAD_NUMBER; ws = partWorkspaces[threadNum]; } else ws = workspace; // Get the buffer (for this thread) DasEvent *event_buffer = buffers[threadNum]; // Get the speeding-up array of vector<tofEvent> where index = detid. EventVector_pt *theseEventVectors = eventVectors[threadNum]; // Where to start in the file? size_t fileOffset = first_event + (loadBlockSize * blockNum); // May need to reduce size of last (or only) block size_t current_event_buffer_size = (blockNum == int(numBlocks - 1)) ? (max_events - (numBlocks - 1) * loadBlockSize) : loadBlockSize; // Load this chunk of event data (critical block) PARALLEL_CRITICAL(LoadEventPreNexus_fileAccess) { current_event_buffer_size = eventfile->loadBlockAt( event_buffer, fileOffset, current_event_buffer_size); } // This processes the events. Can be done in parallel! procEventsLinear(ws, theseEventVectors, event_buffer, current_event_buffer_size, fileOffset); // Report progress prog->report("Load Event PreNeXus"); PARALLEL_END_INTERUPT_REGION } PARALLEL_CHECK_INTERUPT_REGION g_log.debug() << tim << " to load the data." << std::endl; // ---------------------------------- MERGE WORKSPACES BACK TOGETHER // -------------------------- if (parallelProcessing) { PARALLEL_START_INTERUPT_REGION prog->resetNumSteps(workspace->getNumberHistograms(), 0.8, 0.95); size_t memoryCleared = 0; MemoryManager::Instance().releaseFreeMemory(); // Merge all workspaces, index by index. PARALLEL_FOR_NO_WSP_CHECK() for (int iwi = 0; iwi < int(workspace->getNumberHistograms()); iwi++) { size_t wi = size_t(iwi); // The output event list. EventList &el = workspace->getEventList(wi); el.clear(false); // How many events will it have? size_t numEvents = 0; for (size_t i = 0; i < numThreads; i++) numEvents += partWorkspaces[i]->getEventList(wi).getNumberEvents(); // This will avoid too much copying. el.reserve(numEvents); // Now merge the event lists for (size_t i = 0; i < numThreads; i++) { EventList &partEl = partWorkspaces[i]->getEventList(wi); el += partEl.getEvents(); // Free up memory as you go along. partEl.clear(false); } // With TCMalloc, release memory when you accumulate enough to make sense PARALLEL_CRITICAL(LoadEventPreNexus_trackMemory) { memoryCleared += numEvents; if (memoryCleared > 10000000) // ten million events = about 160 MB { MemoryManager::Instance().releaseFreeMemory(); memoryCleared = 0; } } prog->report("Merging Workspaces"); } // Final memory release MemoryManager::Instance().releaseFreeMemory(); g_log.debug() << tim << " to merge workspaces together." << std::endl; PARALLEL_END_INTERUPT_REGION } PARALLEL_CHECK_INTERUPT_REGION // Delete the buffers for each thread. for (size_t i = 0; i < numThreads; i++) { delete[] buffers[i]; delete[] eventVectors[i]; } delete[] eventVectors; // delete [] pulsetimes; prog->resetNumSteps(3, 0.94, 1.00); // finalize loading prog->report("Deleting Empty Lists"); if (loadOnlySomeSpectra) workspace->deleteEmptyLists(); prog->report("Setting proton charge"); this->setProtonCharge(workspace); g_log.debug() << tim << " to set the proton charge log." << std::endl; // Make sure the MRU is cleared workspace->clearMRU(); // Now, create a default X-vector for histogramming, with just 2 bins. Kernel::cow_ptr<MantidVec> axis; MantidVec &xRef = axis.access(); xRef.resize(2); xRef[0] = shortest_tof - 1; // Just to make sure the bins hold it all xRef[1] = longest_tof + 1; workspace->setAllX(axis); this->pixel_to_wkspindex.clear(); g_log.information() << "Read " << this->num_good_events << " events + " << this->num_error_events << " errors" << ". Shortest TOF: " << shortest_tof << " microsec; longest TOF: " << longest_tof << " microsec." << std::endl; }
/** Carries out the bin-by-bin normalisation * @param inputWorkspace The input workspace * @param outputWorkspace The result workspace */ void NormaliseToMonitor::normaliseBinByBin(API::MatrixWorkspace_sptr inputWorkspace, API::MatrixWorkspace_sptr& outputWorkspace) { EventWorkspace_sptr inputEvent = boost::dynamic_pointer_cast<EventWorkspace>(inputWorkspace); EventWorkspace_sptr outputEvent; // Only create output workspace if different to input one if (outputWorkspace != inputWorkspace ) { if (inputEvent) { //Make a brand new EventWorkspace outputEvent = boost::dynamic_pointer_cast<EventWorkspace>( API::WorkspaceFactory::Instance().create("EventWorkspace", inputEvent->getNumberHistograms(), 2, 1)); //Copy geometry and data API::WorkspaceFactory::Instance().initializeFromParent(inputEvent, outputEvent, false); outputEvent->copyDataFrom( (*inputEvent) ); outputWorkspace = boost::dynamic_pointer_cast<MatrixWorkspace>(outputEvent); } else outputWorkspace = WorkspaceFactory::Instance().create(inputWorkspace); } // Get hold of the monitor spectrum const MantidVec& monX = m_monitor->readX(0); MantidVec& monY = m_monitor->dataY(0); MantidVec& monE = m_monitor->dataE(0); // Calculate the overall normalisation just the once if bins are all matching if (m_commonBins) this->normalisationFactor(m_monitor->readX(0),&monY,&monE); const size_t numHists = inputWorkspace->getNumberHistograms(); MantidVec::size_type specLength = inputWorkspace->blocksize(); Progress prog(this,0.0,1.0,numHists); // Loop over spectra PARALLEL_FOR3(inputWorkspace,outputWorkspace,m_monitor) for (int64_t i = 0; i < int64_t(numHists); ++i) { PARALLEL_START_INTERUPT_REGION prog.report(); const MantidVec& X = inputWorkspace->readX(i); // If not rebinning, just point to our monitor spectra, otherwise create new vectors MantidVec* Y = ( m_commonBins ? &monY : new MantidVec(specLength) ); MantidVec* E = ( m_commonBins ? &monE : new MantidVec(specLength) ); if (!m_commonBins) { // ConvertUnits can give X vectors of all zeroes - skip these, they cause problems if (X.back() == 0.0 && X.front() == 0.0) continue; // Rebin the monitor spectrum to match the binning of the current data spectrum VectorHelper::rebinHistogram(monX,monY,monE,X,*Y,*E,false); // Recalculate the overall normalisation factor this->normalisationFactor(X,Y,E); } if (inputEvent) { // ----------------------------------- EventWorkspace --------------------------------------- EventList & outEL = outputEvent->getEventList(i); outEL.divide(X, *Y, *E); } else { // ----------------------------------- Workspace2D --------------------------------------- const MantidVec& inY = inputWorkspace->readY(i); const MantidVec& inE = inputWorkspace->readE(i); MantidVec& YOut = outputWorkspace->dataY(i); MantidVec& EOut = outputWorkspace->dataE(i); outputWorkspace->dataX(i) = inputWorkspace->readX(i); // The code below comes more or less straight out of Divide.cpp for (MantidVec::size_type k = 0; k < specLength; ++k) { // Get references to the input Y's const double& leftY = inY[k]; const double& rightY = (*Y)[k]; // Calculate result and store in local variable to avoid overwriting original data if // output workspace is same as one of the input ones const double newY = leftY/rightY; if (fabs(rightY)>1.0e-12 && fabs(newY)>1.0e-12) { const double lhsFactor = (inE[k]<1.0e-12|| fabs(leftY)<1.0e-12) ? 0.0 : pow((inE[k]/leftY),2); const double rhsFactor = (*E)[k]<1.0e-12 ? 0.0 : pow(((*E)[k]/rightY),2); EOut[k] = std::abs(newY) * sqrt(lhsFactor+rhsFactor); } // Now store the result YOut[k] = newY; } // end Workspace2D case } // end loop over current spectrum if (!m_commonBins) { delete Y; delete E; } PARALLEL_END_INTERUPT_REGION } // end loop over spectra PARALLEL_CHECK_INTERUPT_REGION }
/** Load the event_workspace field * * @param wksp_cls * @param progressStart * @param progressRange * @return */ API::MatrixWorkspace_sptr LoadNexusProcessed::loadEventEntry(NXData & wksp_cls, NXDouble & xbins, const double& progressStart, const double& progressRange) { NXDataSetTyped<int64_t> indices_data = wksp_cls.openNXDataSet<int64_t>("indices"); indices_data.load(); boost::shared_array<int64_t> indices = indices_data.sharedBuffer(); int numspec = indices_data.dim0()-1; int num_xbins = xbins.dim0(); if (num_xbins < 2) num_xbins = 2; EventWorkspace_sptr ws = boost::dynamic_pointer_cast<EventWorkspace> (WorkspaceFactory::Instance().create("EventWorkspace", numspec, num_xbins, num_xbins-1)); // Set the YUnit label ws->setYUnit(indices_data.attributes("units")); std::string unitLabel = indices_data.attributes("unit_label"); if (unitLabel.empty()) unitLabel = indices_data.attributes("units"); ws->setYUnitLabel(unitLabel); //Handle optional fields. // TODO: Handle inconsistent sizes boost::shared_array<int64_t> pulsetimes; if (wksp_cls.isValid("pulsetime")) { NXDataSetTyped<int64_t> pulsetime = wksp_cls.openNXDataSet<int64_t>("pulsetime"); pulsetime.load(); pulsetimes = pulsetime.sharedBuffer(); } boost::shared_array<double> tofs; if (wksp_cls.isValid("tof")) { NXDouble tof = wksp_cls.openNXDouble("tof"); tof.load(); tofs = tof.sharedBuffer(); } boost::shared_array<float> error_squareds; if (wksp_cls.isValid("error_squared")) { NXFloat error_squared = wksp_cls.openNXFloat("error_squared"); error_squared.load(); error_squareds = error_squared.sharedBuffer(); } boost::shared_array<float> weights; if (wksp_cls.isValid("weight")) { NXFloat weight = wksp_cls.openNXFloat("weight"); weight.load(); weights = weight.sharedBuffer(); } // What type of event lists? EventType type = TOF; if (tofs && pulsetimes && weights && error_squareds) type = WEIGHTED; else if ((tofs && weights && error_squareds)) type = WEIGHTED_NOTIME; else if (pulsetimes && tofs) type = TOF; else throw std::runtime_error("Could not figure out the type of event list!"); // Create all the event lists PARALLEL_FOR_NO_WSP_CHECK() for (int wi=0; wi < numspec; wi++) { PARALLEL_START_INTERUPT_REGION int64_t index_start = indices[wi]; int64_t index_end = indices[wi+1]; if (index_end >= index_start) { EventList & el = ws->getEventList(wi); el.switchTo(type); // Allocate all the required memory el.reserve(index_end - index_start); el.clearDetectorIDs(); for (long i=index_start; i<index_end; i++) switch (type) { case TOF: el.addEventQuickly( TofEvent( tofs[i], DateAndTime(pulsetimes[i])) ); break; case WEIGHTED: el.addEventQuickly( WeightedEvent( tofs[i], DateAndTime(pulsetimes[i]), weights[i], error_squareds[i]) ); break; case WEIGHTED_NOTIME: el.addEventQuickly( WeightedEventNoTime( tofs[i], weights[i], error_squareds[i]) ); break; } // Set the X axis if (this->m_shared_bins) el.setX(this->m_xbins); else { MantidVec x; x.resize(xbins.dim0()); for (int i=0; i < xbins.dim0(); i++) x[i] = xbins(wi, i); el.setX(x); } } progress(progressStart + progressRange*(1.0/numspec)); PARALLEL_END_INTERUPT_REGION } PARALLEL_CHECK_INTERUPT_REGION // Clean up some stuff ws->doneAddingEventLists(); return ws; }
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]; } } }
/** * Execute the align detectors algorithm for an event workspace. */ void AlignDetectors::execEvent() { // g_log.information("Processing event workspace"); // the calibration information is already read in at this point // convert the input workspace into the event workspace we already know it is const MatrixWorkspace_const_sptr matrixInputWS = this->getProperty("InputWorkspace"); EventWorkspace_const_sptr inputWS = boost::dynamic_pointer_cast<const EventWorkspace>(matrixInputWS); // generate the output workspace pointer API::MatrixWorkspace_sptr matrixOutputWS = this->getProperty("OutputWorkspace"); EventWorkspace_sptr outputWS; if (matrixOutputWS == matrixInputWS) outputWS = boost::dynamic_pointer_cast<EventWorkspace>(matrixOutputWS); else { // 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); // You need to copy over the data as well. outputWS->copyDataFrom((*inputWS)); // Cast to the matrixOutputWS and save it matrixOutputWS = boost::dynamic_pointer_cast<MatrixWorkspace>(outputWS); this->setProperty("OutputWorkspace", matrixOutputWS); } // Set the final unit that our output workspace will have setXAxisUnits(outputWS); ConversionFactors converter = ConversionFactors(m_calibrationWS); Progress progress(this, 0.0, 1.0, m_numberOfSpectra); PARALLEL_FOR_NO_WSP_CHECK() for (int64_t i = 0; i < m_numberOfSpectra; ++i) { PARALLEL_START_INTERUPT_REGION auto toDspacing = converter.getConversionFunc( inputWS->getSpectrum(size_t(i))->getDetectorIDs()); outputWS->getEventList(i).convertTof(toDspacing); progress.report(); PARALLEL_END_INTERUPT_REGION } PARALLEL_CHECK_INTERUPT_REGION if (outputWS->getTofMin() < 0.) { std::stringstream msg; msg << "Something wrong with the calibration. Negative minimum d-spacing " "created. d_min = " << outputWS->getTofMin() << " d_max " << outputWS->getTofMax(); g_log.warning(msg.str()); } outputWS->clearMRU(); }
void GroupDetectors2::execEvent() { // Get the input workspace const MatrixWorkspace_const_sptr matrixInputWS = getProperty("InputWorkspace"); EventWorkspace_const_sptr inputWS= boost::dynamic_pointer_cast<const EventWorkspace>(matrixInputWS); const size_t numInHists = inputWS->getNumberHistograms(); progress( m_FracCompl = CHECKBINS ); interruption_point(); // some values loaded into this vector can be negative so this needs to be a signed type std::vector<int64_t> unGroupedInds; //the ungrouped list could be very big but might be none at all unGroupedInds.reserve(numInHists); for( size_t i = 0; i < numInHists ; i++ ) { unGroupedInds.push_back(i); } // read in the input parameters to make that map, if KeepUngroupedSpectra was set we'll need a list of the ungrouped spectrra too getGroups(inputWS, unGroupedInds); // converting the list into a set gets rid of repeated values, here the multiple GroupDetectors2::USED become one USED at the start const std::set<int64_t> unGroupedSet(unGroupedInds.begin(), unGroupedInds.end()); // Check what the user asked to be done with ungrouped spectra const bool keepAll = getProperty("KeepUngroupedSpectra"); // ignore the one USED value in set or ignore all the ungrouped if the user doesn't want them const size_t numUnGrouped = keepAll ? unGroupedSet.size()-1 : 0; //Make a brand new EventWorkspace EventWorkspace_sptr outputWS = boost::dynamic_pointer_cast<EventWorkspace>( WorkspaceFactory::Instance().create("EventWorkspace", m_GroupSpecInds.size()+ numUnGrouped, inputWS->readX(0).size(), inputWS->blocksize())); //Copy geometry over. WorkspaceFactory::Instance().initializeFromParent(inputWS, outputWS, true); // prepare to move the requested histograms into groups, first estimate how long for progress reporting. +1 in the demonator gets rid of any divide by zero risk double prog4Copy=( (1.0 - m_FracCompl)/(static_cast<double>(numInHists-unGroupedSet.size())+1.) )* (keepAll ? static_cast<double>(numInHists-unGroupedSet.size())/static_cast<double>(numInHists): 1.); // Build a new map const size_t outIndex = formGroupsEvent(inputWS, outputWS, prog4Copy); // If we're keeping ungrouped spectra if (keepAll) { // copy them into the output workspace moveOthersEvent(unGroupedSet, inputWS, outputWS, outIndex); } //Set all X bins on the output cow_ptr<MantidVec> XValues; XValues.access() = inputWS->readX(0); outputWS->setAllX(XValues); g_log.information() << name() << " algorithm has finished\n"; setProperty("OutputWorkspace",outputWS); }
/** Execute the algorithm. */ void IntegrateEllipsoids::exec() { // get the input workspace MatrixWorkspace_sptr wksp = getProperty("InputWorkspace"); EventWorkspace_sptr eventWS = boost::dynamic_pointer_cast<EventWorkspace>(wksp); Workspace2D_sptr histoWS = boost::dynamic_pointer_cast<Workspace2D>(wksp); if (!eventWS && !histoWS) { throw std::runtime_error("IntegrateEllipsoids needs either a " "EventWorkspace or Workspace2D as input."); } // error out if there are not events if (eventWS && eventWS->getNumberEvents() <= 0) { throw std::runtime_error( "IntegrateEllipsoids does not work for empty event lists"); } PeaksWorkspace_sptr in_peak_ws = getProperty("PeaksWorkspace"); if (!in_peak_ws) { throw std::runtime_error("Could not read the peaks workspace"); } double radius = getProperty("RegionRadius"); int numSigmas = getProperty("NumSigmas"); double cutoffIsigI = getProperty("CutoffIsigI"); bool specify_size = getProperty("SpecifySize"); double peak_radius = getProperty("PeakSize"); double back_inner_radius = getProperty("BackgroundInnerSize"); double back_outer_radius = getProperty("BackgroundOuterSize"); bool hkl_integ = getProperty("IntegrateInHKL"); bool integrateEdge = getProperty("IntegrateIfOnEdge"); if (!integrateEdge) { // This only fails in the unit tests which say that MaskBTP is not // registered try { runMaskDetectors(in_peak_ws, "Tube", "edges"); runMaskDetectors(in_peak_ws, "Pixel", "edges"); } catch (...) { g_log.error("Can't execute MaskBTP algorithm for this instrument to set " "edge for IntegrateIfOnEdge option"); } calculateE1(in_peak_ws->detectorInfo()); // fill E1Vec for use in detectorQ } Mantid::DataObjects::PeaksWorkspace_sptr peak_ws = getProperty("OutputWorkspace"); if (peak_ws != in_peak_ws) { peak_ws = in_peak_ws->clone(); } // get UBinv and the list of // peak Q's for the integrator std::vector<Peak> &peaks = peak_ws->getPeaks(); size_t n_peaks = peak_ws->getNumberPeaks(); size_t indexed_count = 0; std::vector<V3D> peak_q_list; std::vector<std::pair<double, V3D>> qList; std::vector<V3D> hkl_vectors; for (size_t i = 0; i < n_peaks; i++) // Note: we skip un-indexed peaks { V3D hkl(peaks[i].getH(), peaks[i].getK(), peaks[i].getL()); if (Geometry::IndexingUtils::ValidIndex(hkl, 1.0)) // use tolerance == 1 to // just check for (0,0,0) { peak_q_list.emplace_back(peaks[i].getQLabFrame()); qList.emplace_back(1., V3D(peaks[i].getQLabFrame())); V3D miller_ind(static_cast<double>(boost::math::iround<double>(hkl[0])), static_cast<double>(boost::math::iround<double>(hkl[1])), static_cast<double>(boost::math::iround<double>(hkl[2]))); hkl_vectors.push_back(miller_ind); indexed_count++; } } if (indexed_count < 3) { throw std::runtime_error( "At least three linearly independent indexed peaks are needed."); } // Get UB using indexed peaks and // lab-Q vectors Matrix<double> UB(3, 3, false); Geometry::IndexingUtils::Optimize_UB(UB, hkl_vectors, peak_q_list); Matrix<double> UBinv(UB); UBinv.Invert(); UBinv *= (1.0 / (2.0 * M_PI)); std::vector<double> PeakRadiusVector(n_peaks, peak_radius); std::vector<double> BackgroundInnerRadiusVector(n_peaks, back_inner_radius); std::vector<double> BackgroundOuterRadiusVector(n_peaks, back_outer_radius); if (specify_size) { if (back_outer_radius > radius) throw std::runtime_error( "BackgroundOuterSize must be less than or equal to the RegionRadius"); if (back_inner_radius >= back_outer_radius) throw std::runtime_error( "BackgroundInnerSize must be less BackgroundOuterSize"); if (peak_radius > back_inner_radius) throw std::runtime_error( "PeakSize must be less than or equal to the BackgroundInnerSize"); } // make the integrator Integrate3DEvents integrator(qList, UBinv, radius); // get the events and add // them to the inegrator // set up a descripter of where we are going this->initTargetWSDescr(wksp); // set up the progress bar const size_t numSpectra = wksp->getNumberHistograms(); Progress prog(this, 0.5, 1.0, numSpectra); if (eventWS) { // process as EventWorkspace qListFromEventWS(integrator, prog, eventWS, UBinv, hkl_integ); } else { // process as Workspace2D qListFromHistoWS(integrator, prog, histoWS, UBinv, hkl_integ); } double inti; double sigi; std::vector<double> principalaxis1, principalaxis2, principalaxis3; V3D peak_q; for (size_t i = 0; i < n_peaks; i++) { V3D hkl(peaks[i].getH(), peaks[i].getK(), peaks[i].getL()); if (Geometry::IndexingUtils::ValidIndex(hkl, 1.0)) { peak_q = peaks[i].getQLabFrame(); std::vector<double> axes_radii; Mantid::Geometry::PeakShape_const_sptr shape = integrator.ellipseIntegrateEvents( E1Vec, peak_q, specify_size, peak_radius, back_inner_radius, back_outer_radius, axes_radii, inti, sigi); peaks[i].setIntensity(inti); peaks[i].setSigmaIntensity(sigi); peaks[i].setPeakShape(shape); if (axes_radii.size() == 3) { if (inti / sigi > cutoffIsigI || cutoffIsigI == EMPTY_DBL()) { principalaxis1.push_back(axes_radii[0]); principalaxis2.push_back(axes_radii[1]); principalaxis3.push_back(axes_radii[2]); } } } else { peaks[i].setIntensity(0.0); peaks[i].setSigmaIntensity(0.0); } } if (principalaxis1.size() > 1) { size_t histogramNumber = 3; Workspace_sptr wsProfile = WorkspaceFactory::Instance().create( "Workspace2D", histogramNumber, principalaxis1.size(), principalaxis1.size()); Workspace2D_sptr wsProfile2D = boost::dynamic_pointer_cast<Workspace2D>(wsProfile); AnalysisDataService::Instance().addOrReplace("EllipsoidAxes", wsProfile2D); for (size_t j = 0; j < principalaxis1.size(); j++) { wsProfile2D->dataX(0)[j] = static_cast<double>(j); wsProfile2D->dataY(0)[j] = principalaxis1[j]; wsProfile2D->dataE(0)[j] = std::sqrt(principalaxis1[j]); wsProfile2D->dataX(1)[j] = static_cast<double>(j); wsProfile2D->dataY(1)[j] = principalaxis2[j]; wsProfile2D->dataE(1)[j] = std::sqrt(principalaxis2[j]); wsProfile2D->dataX(2)[j] = static_cast<double>(j); wsProfile2D->dataY(2)[j] = principalaxis3[j]; wsProfile2D->dataE(2)[j] = std::sqrt(principalaxis3[j]); } Statistics stats1 = getStatistics(principalaxis1); g_log.notice() << "principalaxis1: " << " mean " << stats1.mean << " standard_deviation " << stats1.standard_deviation << " minimum " << stats1.minimum << " maximum " << stats1.maximum << " median " << stats1.median << "\n"; Statistics stats2 = getStatistics(principalaxis2); g_log.notice() << "principalaxis2: " << " mean " << stats2.mean << " standard_deviation " << stats2.standard_deviation << " minimum " << stats2.minimum << " maximum " << stats2.maximum << " median " << stats2.median << "\n"; Statistics stats3 = getStatistics(principalaxis3); g_log.notice() << "principalaxis3: " << " mean " << stats3.mean << " standard_deviation " << stats3.standard_deviation << " minimum " << stats3.minimum << " maximum " << stats3.maximum << " median " << stats3.median << "\n"; if (cutoffIsigI != EMPTY_DBL()) { principalaxis1.clear(); principalaxis2.clear(); principalaxis3.clear(); specify_size = true; peak_radius = std::max(std::max(stats1.mean, stats2.mean), stats3.mean) + numSigmas * std::max(std::max(stats1.standard_deviation, stats2.standard_deviation), stats3.standard_deviation); back_inner_radius = peak_radius; back_outer_radius = peak_radius * 1.25992105; // A factor of 2 ^ (1/3) will make the background // shell volume equal to the peak region volume. V3D peak_q; for (size_t i = 0; i < n_peaks; i++) { V3D hkl(peaks[i].getH(), peaks[i].getK(), peaks[i].getL()); if (Geometry::IndexingUtils::ValidIndex(hkl, 1.0)) { peak_q = peaks[i].getQLabFrame(); std::vector<double> axes_radii; integrator.ellipseIntegrateEvents( E1Vec, peak_q, specify_size, peak_radius, back_inner_radius, back_outer_radius, axes_radii, inti, sigi); peaks[i].setIntensity(inti); peaks[i].setSigmaIntensity(sigi); if (axes_radii.size() == 3) { principalaxis1.push_back(axes_radii[0]); principalaxis2.push_back(axes_radii[1]); principalaxis3.push_back(axes_radii[2]); } } else { peaks[i].setIntensity(0.0); peaks[i].setSigmaIntensity(0.0); } } if (principalaxis1.size() > 1) { size_t histogramNumber = 3; Workspace_sptr wsProfile2 = WorkspaceFactory::Instance().create( "Workspace2D", histogramNumber, principalaxis1.size(), principalaxis1.size()); Workspace2D_sptr wsProfile2D2 = boost::dynamic_pointer_cast<Workspace2D>(wsProfile2); AnalysisDataService::Instance().addOrReplace("EllipsoidAxes_2ndPass", wsProfile2D2); for (size_t j = 0; j < principalaxis1.size(); j++) { wsProfile2D2->dataX(0)[j] = static_cast<double>(j); wsProfile2D2->dataY(0)[j] = principalaxis1[j]; wsProfile2D2->dataE(0)[j] = std::sqrt(principalaxis1[j]); wsProfile2D2->dataX(1)[j] = static_cast<double>(j); wsProfile2D2->dataY(1)[j] = principalaxis2[j]; wsProfile2D2->dataE(1)[j] = std::sqrt(principalaxis2[j]); wsProfile2D2->dataX(2)[j] = static_cast<double>(j); wsProfile2D2->dataY(2)[j] = principalaxis3[j]; wsProfile2D2->dataE(2)[j] = std::sqrt(principalaxis3[j]); } } } } // This flag is used by the PeaksWorkspace to evaluate whether it has been // integrated. peak_ws->mutableRun().addProperty("PeaksIntegrated", 1, true); // These flags are specific to the algorithm. peak_ws->mutableRun().addProperty("PeakRadius", PeakRadiusVector, true); peak_ws->mutableRun().addProperty("BackgroundInnerRadius", BackgroundInnerRadiusVector, true); peak_ws->mutableRun().addProperty("BackgroundOuterRadius", BackgroundOuterRadiusVector, true); setProperty("OutputWorkspace", peak_ws); }
/** Execute the algorithm. */ void LoadLiveData::exec() { // The full, post-processed output workspace m_outputWS = this->getProperty("OutputWorkspace"); // Validate inputs if (this->hasPostProcessing()) { if (this->getPropertyValue("AccumulationWorkspace").empty()) throw std::invalid_argument("Must specify the AccumulationWorkspace " "parameter if using PostProcessing."); // The accumulated but not post-processed output workspace m_accumWS = this->getProperty("AccumulationWorkspace"); } else { // No post-processing, so the accumulation and output are the same m_accumWS = m_outputWS; } // Get or create the live listener ILiveListener_sptr listener = this->getLiveListener(); // Do we need to reset the data? bool dataReset = listener->dataReset(); // The listener returns a MatrixWorkspace containing the chunk of live data. Workspace_sptr chunkWS; bool dataNotYetGiven = true; while (dataNotYetGiven) { try { chunkWS = listener->extractData(); dataNotYetGiven = false; } catch (Exception::NotYet &ex) { g_log.warning() << "The " << listener->name() << " is not ready to return data: " << ex.what() << "\n"; g_log.warning() << "Trying again in 10 seconds - cancel the algorithm to stop.\n"; const int tenSeconds = 40; for (int i = 0; i < tenSeconds; ++i) { Poco::Thread::sleep(10000 / tenSeconds); // 250 ms this->interruption_point(); } } } // TODO: Have the ILiveListener tell me exactly the time stamp DateAndTime lastTimeStamp = DateAndTime::getCurrentTime(); this->setPropertyValue("LastTimeStamp", lastTimeStamp.toISO8601String()); // Now we process the chunk Workspace_sptr processed = this->processChunk(chunkWS); bool PreserveEvents = this->getProperty("PreserveEvents"); EventWorkspace_sptr processedEvent = boost::dynamic_pointer_cast<EventWorkspace>(processed); if (!PreserveEvents && processedEvent) { // Convert the monitor workspace, if there is one and it's necessary MatrixWorkspace_sptr monitorWS = processedEvent->monitorWorkspace(); auto monitorEventWS = boost::dynamic_pointer_cast<EventWorkspace>(monitorWS); if (monitorEventWS) { auto monAlg = this->createChildAlgorithm("ConvertToMatrixWorkspace"); monAlg->setProperty("InputWorkspace", monitorEventWS); monAlg->executeAsChildAlg(); if (!monAlg->isExecuted()) g_log.error( "Failed to convert monitors from events to histogram form."); monitorWS = monAlg->getProperty("OutputWorkspace"); } // Now do the main workspace Algorithm_sptr alg = this->createChildAlgorithm("ConvertToMatrixWorkspace"); alg->setProperty("InputWorkspace", processedEvent); std::string outputName = "__anonymous_livedata_convert_" + this->getPropertyValue("OutputWorkspace"); alg->setPropertyValue("OutputWorkspace", outputName); alg->execute(); if (!alg->isExecuted()) throw std::runtime_error("Error when calling ConvertToMatrixWorkspace " "(since PreserveEvents=False). See log."); // Replace the "processed" workspace with the converted one. MatrixWorkspace_sptr temp = alg->getProperty("OutputWorkspace"); if (monitorWS) temp->setMonitorWorkspace(monitorWS); // Set back the monitor workspace processed = temp; } // How do we accumulate the data? std::string accum = this->getPropertyValue("AccumulationMethod"); // If the AccumulationWorkspace does not exist, we always replace the // AccumulationWorkspace. // Also, if the listener said we are resetting the data, then we clear out the // old. if (!m_accumWS || dataReset) accum = "Replace"; g_log.notice() << "Performing the " << accum << " operation.\n"; // Perform the accumulation and set the AccumulationWorkspace workspace if (accum == "Replace") this->replaceChunk(processed); else if (accum == "Append") this->appendChunk(processed); else // Default to Add. this->addChunk(processed); // At this point, m_accumWS is set. if (this->hasPostProcessing()) { // ----------- Run post-processing ------------- this->runPostProcessing(); // Set both output workspaces this->setProperty("AccumulationWorkspace", m_accumWS); this->setProperty("OutputWorkspace", m_outputWS); doSortEvents(m_outputWS); } else { // ----------- No post-processing ------------- m_outputWS = m_accumWS; // We DO NOT set AccumulationWorkspace. this->setProperty("OutputWorkspace", m_outputWS); } // Output group requires some additional handling WorkspaceGroup_sptr out_gws = boost::dynamic_pointer_cast<WorkspaceGroup>(m_outputWS); if (out_gws) { size_t n = static_cast<size_t>(out_gws->getNumberOfEntries()); for (size_t i = 0; i < n; ++i) { auto ws = out_gws->getItem(i); std::string itemName = ws->name(); std::string wsName = getPropertyValue("OutputWorkspace") + "_" + std::to_string(i + 1); if (wsName != itemName) { if (AnalysisDataService::Instance().doesExist(itemName)) { // replace the temporary name with the proper one AnalysisDataService::Instance().rename(itemName, wsName); } } else { // touch the workspace in the ADS to issue a notification to update the // GUI AnalysisDataService::Instance().addOrReplace(itemName, ws); } } } }
/** Executes the algorithm * * @throw runtime_error Thrown if algorithm cannot execute */ void DiffractionEventCalibrateDetectors::exec() { // Try to retrieve optional properties const int maxIterations = getProperty("MaxIterations"); const double peakOpt = getProperty("LocationOfPeakToOptimize"); // Get the input workspace EventWorkspace_sptr inputW = getProperty("InputWorkspace"); // retrieve the properties const std::string rb_params = getProperty("Params"); // Get some stuff from the input workspace Instrument_const_sptr inst = inputW->getInstrument(); // Build a list of Rectangular Detectors std::vector<boost::shared_ptr<RectangularDetector>> detList; // --------- Loading only one bank ---------------------------------- std::string onebank = getProperty("BankName"); bool doOneBank = (onebank != ""); for (int i = 0; i < inst->nelements(); i++) { boost::shared_ptr<RectangularDetector> det; boost::shared_ptr<ICompAssembly> assem; boost::shared_ptr<ICompAssembly> assem2; det = boost::dynamic_pointer_cast<RectangularDetector>((*inst)[i]); if (det) { if (det->getName().compare(onebank) == 0) detList.push_back(det); if (!doOneBank) detList.push_back(det); } else { // Also, look in the first sub-level for RectangularDetectors (e.g. PG3). // We are not doing a full recursive search since that will be very long // for lots of pixels. assem = boost::dynamic_pointer_cast<ICompAssembly>((*inst)[i]); if (assem) { for (int j = 0; j < assem->nelements(); j++) { det = boost::dynamic_pointer_cast<RectangularDetector>((*assem)[j]); if (det) { if (det->getName().compare(onebank) == 0) detList.push_back(det); if (!doOneBank) detList.push_back(det); } else { // Also, look in the second sub-level for RectangularDetectors (e.g. // PG3). // We are not doing a full recursive search since that will be very // long for lots of pixels. assem2 = boost::dynamic_pointer_cast<ICompAssembly>((*assem)[j]); if (assem2) { for (int k = 0; k < assem2->nelements(); k++) { det = boost::dynamic_pointer_cast<RectangularDetector>( (*assem2)[k]); if (det) { if (det->getName().compare(onebank) == 0) detList.push_back(det); if (!doOneBank) detList.push_back(det); } } } } } } } } // set-up minimizer std::string inname = getProperty("InputWorkspace"); std::string outname = inname + "2"; // getProperty("OutputWorkspace"); IAlgorithm_sptr algS = createChildAlgorithm("SortEvents"); algS->setProperty("InputWorkspace", inputW); algS->setPropertyValue("SortBy", "X Value"); algS->executeAsChildAlg(); // Write DetCal File std::string filename = getProperty("DetCalFilename"); std::fstream outfile; outfile.open(filename.c_str(), std::ios::out); if (detList.size() > 1) { outfile << "#\n"; outfile << "# Mantid Optimized .DetCal file for SNAP with TWO detector " "panels\n"; outfile << "# Old Panel, nominal size and distance at -90 degrees.\n"; outfile << "# New Panel, nominal size and distance at +90 degrees.\n"; outfile << "#\n"; outfile << "# Lengths are in centimeters.\n"; outfile << "# Base and up give directions of unit vectors for a local\n"; outfile << "# x,y coordinate system on the face of the detector.\n"; outfile << "#\n"; outfile << "# " << DateAndTime::getCurrentTime().toFormattedString("%c") << "\n"; outfile << "#\n"; outfile << "6 L1 T0_SHIFT\n"; IComponent_const_sptr source = inst->getSource(); IComponent_const_sptr sample = inst->getSample(); outfile << "7 " << source->getDistance(*sample) * 100 << " 0\n"; outfile << "4 DETNUM NROWS NCOLS WIDTH HEIGHT DEPTH DETD " "CenterX CenterY CenterZ BaseX BaseY BaseZ " "UpX UpY UpZ\n"; } Progress prog(this, 0.0, 1.0, detList.size()); for (int det = 0; det < static_cast<int>(detList.size()); det++) { std::string par[6]; par[0] = detList[det]->getName(); par[1] = inname; par[2] = outname; std::ostringstream strpeakOpt; strpeakOpt << peakOpt; par[3] = strpeakOpt.str(); par[4] = rb_params; // --- Create a GroupingWorkspace for this detector name ------ CPUTimer tim; IAlgorithm_sptr alg2 = AlgorithmFactory::Instance().create("CreateGroupingWorkspace", 1); alg2->initialize(); alg2->setProperty("InputWorkspace", inputW); alg2->setPropertyValue("GroupNames", detList[det]->getName()); std::string groupWSName = "group_" + detList[det]->getName(); alg2->setPropertyValue("OutputWorkspace", groupWSName); alg2->executeAsChildAlg(); par[5] = groupWSName; std::cout << tim << " to CreateGroupingWorkspace\n"; const gsl_multimin_fminimizer_type *T = gsl_multimin_fminimizer_nmsimplex; gsl_multimin_fminimizer *s = nullptr; gsl_vector *ss, *x; gsl_multimin_function minex_func; // finally do the fitting int nopt = 6; int iter = 0; int status = 0; /* Starting point */ x = gsl_vector_alloc(nopt); gsl_vector_set(x, 0, 0.0); gsl_vector_set(x, 1, 0.0); gsl_vector_set(x, 2, 0.0); gsl_vector_set(x, 3, 0.0); gsl_vector_set(x, 4, 0.0); gsl_vector_set(x, 5, 0.0); /* Set initial step sizes to 0.1 */ ss = gsl_vector_alloc(nopt); gsl_vector_set_all(ss, 0.1); /* Initialize method and iterate */ minex_func.n = nopt; minex_func.f = &Mantid::Algorithms::gsl_costFunction; minex_func.params = ∥ s = gsl_multimin_fminimizer_alloc(T, nopt); gsl_multimin_fminimizer_set(s, &minex_func, x, ss); do { iter++; status = gsl_multimin_fminimizer_iterate(s); if (status) break; double size = gsl_multimin_fminimizer_size(s); status = gsl_multimin_test_size(size, 1e-2); } while (status == GSL_CONTINUE && iter < maxIterations && s->fval != -0.000); // Output summary to log file if (s->fval != -0.000) movedetector(gsl_vector_get(s->x, 0), gsl_vector_get(s->x, 1), gsl_vector_get(s->x, 2), gsl_vector_get(s->x, 3), gsl_vector_get(s->x, 4), gsl_vector_get(s->x, 5), par[0], getProperty("InputWorkspace")); else { gsl_vector_set(s->x, 0, 0.0); gsl_vector_set(s->x, 1, 0.0); gsl_vector_set(s->x, 2, 0.0); gsl_vector_set(s->x, 3, 0.0); gsl_vector_set(s->x, 4, 0.0); gsl_vector_set(s->x, 5, 0.0); } std::string reportOfDiffractionEventCalibrateDetectors = gsl_strerror(status); if (s->fval == -0.000) reportOfDiffractionEventCalibrateDetectors = "No events"; g_log.information() << "Detector = " << det << "\n" << "Method used = " << "Simplex" << "\n" << "Iteration = " << iter << "\n" << "Status = " << reportOfDiffractionEventCalibrateDetectors << "\n" << "Minimize PeakLoc-" << peakOpt << " = " << s->fval << "\n"; // Move in cm for small shifts g_log.information() << "Move (X) = " << gsl_vector_get(s->x, 0) * 0.01 << " \n"; g_log.information() << "Move (Y) = " << gsl_vector_get(s->x, 1) * 0.01 << " \n"; g_log.information() << "Move (Z) = " << gsl_vector_get(s->x, 2) * 0.01 << " \n"; g_log.information() << "Rotate (X) = " << gsl_vector_get(s->x, 3) << " \n"; g_log.information() << "Rotate (Y) = " << gsl_vector_get(s->x, 4) << " \n"; g_log.information() << "Rotate (Z) = " << gsl_vector_get(s->x, 5) << " \n"; Kernel::V3D CalCenter = V3D(gsl_vector_get(s->x, 0) * 0.01, gsl_vector_get(s->x, 1) * 0.01, gsl_vector_get(s->x, 2) * 0.01); Kernel::V3D Center = detList[det]->getPos() + CalCenter; int pixmax = detList[det]->xpixels() - 1; int pixmid = (detList[det]->ypixels() - 1) / 2; BoundingBox box; detList[det]->getAtXY(pixmax, pixmid)->getBoundingBox(box); double baseX = box.xMax(); double baseY = box.yMax(); double baseZ = box.zMax(); Kernel::V3D Base = V3D(baseX, baseY, baseZ) + CalCenter; pixmid = (detList[det]->xpixels() - 1) / 2; pixmax = detList[det]->ypixels() - 1; detList[det]->getAtXY(pixmid, pixmax)->getBoundingBox(box); double upX = box.xMax(); double upY = box.yMax(); double upZ = box.zMax(); Kernel::V3D Up = V3D(upX, upY, upZ) + CalCenter; Base -= Center; Up -= Center; // Rotate around x baseX = Base[0]; baseY = Base[1]; baseZ = Base[2]; double deg2rad = M_PI / 180.0; double angle = gsl_vector_get(s->x, 3) * deg2rad; Base = V3D(baseX, baseY * cos(angle) - baseZ * sin(angle), baseY * sin(angle) + baseZ * cos(angle)); upX = Up[0]; upY = Up[1]; upZ = Up[2]; Up = V3D(upX, upY * cos(angle) - upZ * sin(angle), upY * sin(angle) + upZ * cos(angle)); // Rotate around y baseX = Base[0]; baseY = Base[1]; baseZ = Base[2]; angle = gsl_vector_get(s->x, 4) * deg2rad; Base = V3D(baseZ * sin(angle) + baseX * cos(angle), baseY, baseZ * cos(angle) - baseX * sin(angle)); upX = Up[0]; upY = Up[1]; upZ = Up[2]; Up = V3D(upZ * cos(angle) - upX * sin(angle), upY, upZ * sin(angle) + upX * cos(angle)); // Rotate around z baseX = Base[0]; baseY = Base[1]; baseZ = Base[2]; angle = gsl_vector_get(s->x, 5) * deg2rad; Base = V3D(baseX * cos(angle) - baseY * sin(angle), baseX * sin(angle) + baseY * cos(angle), baseZ); upX = Up[0]; upY = Up[1]; upZ = Up[2]; Up = V3D(upX * cos(angle) - upY * sin(angle), upX * sin(angle) + upY * cos(angle), upZ); Base.normalize(); Up.normalize(); Center *= 100.0; // << det+1 << " " outfile << "5 " << detList[det]->getName().substr(4) << " " << detList[det]->xpixels() << " " << detList[det]->ypixels() << " " << 100.0 * detList[det]->xsize() << " " << 100.0 * detList[det]->ysize() << " " << "0.2000" << " " << Center.norm() << " "; Center.write(outfile); outfile << " "; Base.write(outfile); outfile << " "; Up.write(outfile); outfile << "\n"; // clean up dynamically allocated gsl stuff gsl_vector_free(x); gsl_vector_free(ss); gsl_multimin_fminimizer_free(s); // Remove the now-unneeded grouping workspace AnalysisDataService::Instance().remove(groupWSName); prog.report(detList[det]->getName()); } // Closing outfile.close(); }
/** Executes the algorithm * @throw Exception::FileError If the grouping file cannot be opened or read * successfully * @throw runtime_error If unable to run one of the Child Algorithms * successfully */ void AlignAndFocusPowder::exec() { // retrieve the properties m_inputW = getProperty("InputWorkspace"); m_inputEW = boost::dynamic_pointer_cast<EventWorkspace>(m_inputW); m_instName = m_inputW->getInstrument()->getName(); m_instName = Kernel::ConfigService::Instance().getInstrument(m_instName).shortName(); std::string calFilename = getPropertyValue("CalFileName"); std::string groupFilename = getPropertyValue("GroupFilename"); m_calibrationWS = getProperty("CalibrationWorkspace"); m_maskWS = getProperty("MaskWorkspace"); m_groupWS = getProperty("GroupingWorkspace"); DataObjects::TableWorkspace_sptr maskBinTableWS = getProperty("MaskBinTable"); m_l1 = getProperty("PrimaryFlightPath"); specids = getProperty("SpectrumIDs"); l2s = getProperty("L2"); tths = getProperty("Polar"); phis = getProperty("Azimuthal"); m_params = getProperty("Params"); dspace = getProperty("DSpacing"); auto dmin = getVecPropertyFromPmOrSelf("DMin", m_dmins); auto dmax = getVecPropertyFromPmOrSelf("DMax", m_dmaxs); LRef = getProperty("UnwrapRef"); DIFCref = getProperty("LowResRef"); minwl = getProperty("CropWavelengthMin"); maxwl = getProperty("CropWavelengthMax"); if (maxwl == 0.) maxwl = EMPTY_DBL(); // python can only specify 0 for unused tmin = getProperty("TMin"); tmax = getProperty("TMax"); m_preserveEvents = getProperty("PreserveEvents"); m_resampleX = getProperty("ResampleX"); // determine some bits about d-space and binning if (m_resampleX != 0) { m_params.clear(); // ignore the normal rebin parameters } else if (m_params.size() == 1) { if (dmax > 0.) dspace = true; else dspace = false; } if (dspace) { if (m_params.size() == 1 && dmax > 0) { double step = m_params[0]; m_params.clear(); if (step > 0 || dmin > 0) { m_params.push_back(dmin); m_params.push_back(step); m_params.push_back(dmax); g_log.information() << "d-Spacing Binning: " << m_params[0] << " " << m_params[1] << " " << m_params[2] << "\n"; } } } else { if (m_params.size() == 1 && tmax > 0) { double step = m_params[0]; if (step > 0 || tmin > 0) { m_params[0] = tmin; m_params.push_back(step); m_params.push_back(tmax); g_log.information() << "TOF Binning: " << m_params[0] << " " << m_params[1] << " " << m_params[2] << "\n"; } } } xmin = 0.; xmax = 0.; if (tmin > 0.) { xmin = tmin; } if (tmax > 0.) { xmax = tmax; } if (!dspace && m_params.size() == 3) { xmin = m_params[0]; xmax = m_params[2]; } // Low resolution int lowresoffset = getProperty("LowResSpectrumOffset"); if (lowresoffset < 0) { m_processLowResTOF = false; } else { m_processLowResTOF = true; m_lowResSpecOffset = static_cast<size_t>(lowresoffset); } loadCalFile(calFilename, groupFilename); // Now setup the output workspace m_outputW = getProperty("OutputWorkspace"); if (m_inputEW) { if (m_outputW != m_inputW) { m_outputEW = m_inputEW->clone(); } m_outputEW = boost::dynamic_pointer_cast<EventWorkspace>(m_outputW); } else { if (m_outputW != m_inputW) { m_outputW = WorkspaceFactory::Instance().create(m_inputW); } } if (m_processLowResTOF) { if (!m_inputEW) { throw std::runtime_error( "Input workspace is not EventWorkspace. It is not supported now."); } else { // Make a brand new EventWorkspace m_lowResEW = boost::dynamic_pointer_cast<EventWorkspace>( WorkspaceFactory::Instance().create( "EventWorkspace", m_inputEW->getNumberHistograms(), 2, 1)); // Cast to the matrixOutputWS and save it m_lowResW = boost::dynamic_pointer_cast<MatrixWorkspace>(m_lowResEW); // m_lowResW->setName(lowreswsname); } } // set up a progress bar with the "correct" number of steps m_progress = new Progress(this, 0., 1., 22); if (m_inputEW) { double tolerance = getProperty("CompressTolerance"); if (tolerance > 0.) { g_log.information() << "running CompressEvents(Tolerance=" << tolerance << ") started at " << Kernel::DateAndTime::getCurrentTime() << "\n"; API::IAlgorithm_sptr compressAlg = createChildAlgorithm("CompressEvents"); compressAlg->setProperty("InputWorkspace", m_outputEW); compressAlg->setProperty("OutputWorkspace", m_outputEW); compressAlg->setProperty("OutputWorkspace", m_outputEW); compressAlg->setProperty("Tolerance", tolerance); compressAlg->executeAsChildAlg(); m_outputEW = compressAlg->getProperty("OutputWorkspace"); m_outputW = boost::dynamic_pointer_cast<MatrixWorkspace>(m_outputEW); } else { g_log.information() << "Not compressing event list\n"; doSortEvents(m_outputW); // still sort to help some thing out } } m_progress->report(); if (xmin > 0. || xmax > 0.) { double tempmin; double tempmax; m_outputW->getXMinMax(tempmin, tempmax); g_log.information() << "running CropWorkspace(TOFmin=" << xmin << ", TOFmax=" << xmax << ") started at " << Kernel::DateAndTime::getCurrentTime() << "\n"; API::IAlgorithm_sptr cropAlg = createChildAlgorithm("CropWorkspace"); cropAlg->setProperty("InputWorkspace", m_outputW); cropAlg->setProperty("OutputWorkspace", m_outputW); if ((xmin > 0.) && (xmin > tempmin)) cropAlg->setProperty("Xmin", xmin); if ((xmax > 0.) && (xmax < tempmax)) cropAlg->setProperty("Xmax", xmax); cropAlg->executeAsChildAlg(); m_outputW = cropAlg->getProperty("OutputWorkspace"); m_outputEW = boost::dynamic_pointer_cast<EventWorkspace>(m_outputW); } m_progress->report(); // filter the input events if appropriate double removePromptPulseWidth = getProperty("RemovePromptPulseWidth"); if (removePromptPulseWidth > 0.) { m_outputEW = boost::dynamic_pointer_cast<EventWorkspace>(m_outputW); if (m_outputEW->getNumberEvents() > 0) { g_log.information() << "running RemovePromptPulse(Width=" << removePromptPulseWidth << ") started at " << Kernel::DateAndTime::getCurrentTime() << "\n"; API::IAlgorithm_sptr filterPAlg = createChildAlgorithm("RemovePromptPulse"); filterPAlg->setProperty("InputWorkspace", m_outputW); filterPAlg->setProperty("OutputWorkspace", m_outputW); filterPAlg->setProperty("Width", removePromptPulseWidth); filterPAlg->executeAsChildAlg(); m_outputW = filterPAlg->getProperty("OutputWorkspace"); m_outputEW = boost::dynamic_pointer_cast<EventWorkspace>(m_outputW); } else { g_log.information("skipping RemovePromptPulse on empty EventWorkspace"); } } m_progress->report(); if (maskBinTableWS) { g_log.information() << "running MaskBinsFromTable started at " << Kernel::DateAndTime::getCurrentTime() << "\n"; API::IAlgorithm_sptr alg = createChildAlgorithm("MaskBinsFromTable"); alg->setProperty("InputWorkspace", m_outputW); alg->setProperty("OutputWorkspace", m_outputW); alg->setProperty("MaskingInformation", maskBinTableWS); alg->executeAsChildAlg(); m_outputW = alg->getProperty("OutputWorkspace"); m_outputEW = boost::dynamic_pointer_cast<EventWorkspace>(m_outputW); } m_progress->report(); if (m_maskWS) { g_log.information() << "running MaskDetectors started at " << Kernel::DateAndTime::getCurrentTime() << "\n"; API::IAlgorithm_sptr maskAlg = createChildAlgorithm("MaskDetectors"); maskAlg->setProperty("Workspace", m_outputW); maskAlg->setProperty("MaskedWorkspace", m_maskWS); maskAlg->executeAsChildAlg(); Workspace_sptr tmpW = maskAlg->getProperty("Workspace"); m_outputW = boost::dynamic_pointer_cast<MatrixWorkspace>(tmpW); m_outputEW = boost::dynamic_pointer_cast<EventWorkspace>(m_outputW); } m_progress->report(); if (!dspace) m_outputW = rebin(m_outputW); m_progress->report(); if (m_calibrationWS) { g_log.information() << "running AlignDetectors started at " << Kernel::DateAndTime::getCurrentTime() << "\n"; API::IAlgorithm_sptr alignAlg = createChildAlgorithm("AlignDetectors"); alignAlg->setProperty("InputWorkspace", m_outputW); alignAlg->setProperty("OutputWorkspace", m_outputW); alignAlg->setProperty("CalibrationWorkspace", m_calibrationWS); alignAlg->executeAsChildAlg(); m_outputW = alignAlg->getProperty("OutputWorkspace"); } else { m_outputW = convertUnits(m_outputW, "dSpacing"); } m_progress->report(); if (LRef > 0. || minwl > 0. || DIFCref > 0. || (!isEmpty(maxwl))) { m_outputW = convertUnits(m_outputW, "TOF"); } m_progress->report(); // Beyond this point, low resolution TOF workspace is considered. if (LRef > 0.) { g_log.information() << "running UnwrapSNS(LRef=" << LRef << ",Tmin=" << tmin << ",Tmax=" << tmax << ") started at " << Kernel::DateAndTime::getCurrentTime() << "\n"; API::IAlgorithm_sptr removeAlg = createChildAlgorithm("UnwrapSNS"); removeAlg->setProperty("InputWorkspace", m_outputW); removeAlg->setProperty("OutputWorkspace", m_outputW); removeAlg->setProperty("LRef", LRef); if (tmin > 0.) removeAlg->setProperty("Tmin", tmin); if (tmax > tmin) removeAlg->setProperty("Tmax", tmax); removeAlg->executeAsChildAlg(); m_outputW = removeAlg->getProperty("OutputWorkspace"); } m_progress->report(); if (minwl > 0. || (!isEmpty(maxwl))) { // just crop the worksapce // turn off the low res stuff m_processLowResTOF = false; EventWorkspace_sptr ews = boost::dynamic_pointer_cast<EventWorkspace>(m_outputW); if (ews) g_log.information() << "Number of events = " << ews->getNumberEvents() << ". "; g_log.information("\n"); m_outputW = convertUnits(m_outputW, "Wavelength"); g_log.information() << "running CropWorkspace(WavelengthMin=" << minwl; if (!isEmpty(maxwl)) g_log.information() << ", WavelengthMax=" << maxwl; g_log.information() << ") started at " << Kernel::DateAndTime::getCurrentTime() << "\n"; API::IAlgorithm_sptr removeAlg = createChildAlgorithm("CropWorkspace"); removeAlg->setProperty("InputWorkspace", m_outputW); removeAlg->setProperty("OutputWorkspace", m_outputW); removeAlg->setProperty("XMin", minwl); removeAlg->setProperty("XMax", maxwl); removeAlg->executeAsChildAlg(); m_outputW = removeAlg->getProperty("OutputWorkspace"); if (ews) g_log.information() << "Number of events = " << ews->getNumberEvents() << ".\n"; } else if (DIFCref > 0.) { g_log.information() << "running RemoveLowResTof(RefDIFC=" << DIFCref << ",K=3.22) started at " << Kernel::DateAndTime::getCurrentTime() << "\n"; EventWorkspace_sptr ews = boost::dynamic_pointer_cast<EventWorkspace>(m_outputW); if (ews) g_log.information() << "Number of events = " << ews->getNumberEvents() << ". "; g_log.information("\n"); API::IAlgorithm_sptr removeAlg = createChildAlgorithm("RemoveLowResTOF"); removeAlg->setProperty("InputWorkspace", m_outputW); removeAlg->setProperty("OutputWorkspace", m_outputW); removeAlg->setProperty("ReferenceDIFC", DIFCref); removeAlg->setProperty("K", 3.22); if (tmin > 0.) removeAlg->setProperty("Tmin", tmin); if (m_processLowResTOF) removeAlg->setProperty("LowResTOFWorkspace", m_lowResW); removeAlg->executeAsChildAlg(); m_outputW = removeAlg->getProperty("OutputWorkspace"); if (m_processLowResTOF) m_lowResW = removeAlg->getProperty("LowResTOFWorkspace"); } m_progress->report(); EventWorkspace_sptr ews = boost::dynamic_pointer_cast<EventWorkspace>(m_outputW); if (ews) { size_t numhighevents = ews->getNumberEvents(); if (m_processLowResTOF) { EventWorkspace_sptr lowes = boost::dynamic_pointer_cast<EventWorkspace>(m_lowResW); size_t numlowevents = lowes->getNumberEvents(); g_log.information() << "Number of high TOF events = " << numhighevents << "; " << "Number of low TOF events = " << numlowevents << ".\n"; } } m_progress->report(); // Convert units if (LRef > 0. || minwl > 0. || DIFCref > 0. || (!isEmpty(maxwl))) { m_outputW = convertUnits(m_outputW, "dSpacing"); if (m_processLowResTOF) m_lowResW = convertUnits(m_lowResW, "dSpacing"); } m_progress->report(); if (dspace) { m_outputW = rebin(m_outputW); if (m_processLowResTOF) m_lowResW = rebin(m_lowResW); } m_progress->report(); doSortEvents(m_outputW); if (m_processLowResTOF) doSortEvents(m_lowResW); m_progress->report(); // Diffraction focus m_outputW = diffractionFocus(m_outputW); if (m_processLowResTOF) m_lowResW = diffractionFocus(m_lowResW); m_progress->report(); doSortEvents(m_outputW); if (m_processLowResTOF) doSortEvents(m_lowResW); m_progress->report(); // this next call should probably be in for rebin as well // but it changes the system tests if (dspace && m_resampleX != 0) { m_outputW = rebin(m_outputW); if (m_processLowResTOF) m_lowResW = rebin(m_lowResW); } m_progress->report(); // edit the instrument geometry if (m_groupWS && (m_l1 > 0 || !tths.empty() || !l2s.empty() || !phis.empty())) { size_t numreg = m_outputW->getNumberHistograms(); try { // set up the vectors for doing everything auto specidsSplit = splitVectors(specids, numreg, "specids"); auto tthsSplit = splitVectors(tths, numreg, "two-theta"); auto l2sSplit = splitVectors(l2s, numreg, "L2"); auto phisSplit = splitVectors(phis, numreg, "phi"); // Edit instrument m_outputW = editInstrument(m_outputW, tthsSplit.reg, specidsSplit.reg, l2sSplit.reg, phisSplit.reg); if (m_processLowResTOF) { m_lowResW = editInstrument(m_lowResW, tthsSplit.low, specidsSplit.low, l2sSplit.low, phisSplit.low); } } catch (std::runtime_error &e) { g_log.warning("Not editing instrument geometry:"); g_log.warning(e.what()); } } m_progress->report(); // Conjoin 2 workspaces if there is low resolution if (m_processLowResTOF) { m_outputW = conjoinWorkspaces(m_outputW, m_lowResW, m_lowResSpecOffset); } m_progress->report(); // Convert units to TOF m_outputW = convertUnits(m_outputW, "TOF"); m_progress->report(); // compress again if appropriate double tolerance = getProperty("CompressTolerance"); m_outputEW = boost::dynamic_pointer_cast<EventWorkspace>(m_outputW); if ((m_outputEW) && (tolerance > 0.)) { g_log.information() << "running CompressEvents(Tolerance=" << tolerance << ") started at " << Kernel::DateAndTime::getCurrentTime() << "\n"; API::IAlgorithm_sptr compressAlg = createChildAlgorithm("CompressEvents"); compressAlg->setProperty("InputWorkspace", m_outputEW); compressAlg->setProperty("OutputWorkspace", m_outputEW); compressAlg->setProperty("OutputWorkspace", m_outputEW); compressAlg->setProperty("Tolerance", tolerance); compressAlg->executeAsChildAlg(); m_outputEW = compressAlg->getProperty("OutputWorkspace"); m_outputW = boost::dynamic_pointer_cast<MatrixWorkspace>(m_outputEW); } m_progress->report(); if ((!m_params.empty()) && (m_params.size() != 1)) { m_params.erase(m_params.begin()); m_params.pop_back(); } if (!m_dmins.empty()) m_dmins.clear(); if (!m_dmaxs.empty()) m_dmaxs.clear(); m_outputW = rebin(m_outputW); m_progress->report(); // return the output workspace setProperty("OutputWorkspace", m_outputW); }
/** Execute the algorithm */ void LoadEventPreNexus::exec() { // Check 'chunk' properties are valid, if set const int chunks = getProperty("TotalChunks"); if (!isEmpty(chunks) && int(getProperty("ChunkNumber")) > chunks) { throw std::out_of_range("ChunkNumber cannot be larger than TotalChunks"); } prog = new Progress(this, 0.0, 1.0, 100); // what spectra (pixel ID's) to load this->spectra_list = this->getProperty(PID_PARAM); // the event file is needed in case the pulseid fileanme is empty string event_filename = this->getPropertyValue(EVENT_PARAM); string pulseid_filename = this->getPropertyValue(PULSEID_PARAM); bool throwError = true; if (pulseid_filename.empty()) { pulseid_filename = generatePulseidName(event_filename); if (!pulseid_filename.empty()) { if (Poco::File(pulseid_filename).exists()) { this->g_log.information() << "Found pulseid file " << pulseid_filename << std::endl; throwError = false; } else { pulseid_filename = ""; } } } prog->report("Loading Pulse ID file"); this->readPulseidFile(pulseid_filename, throwError); this->openEventFile(event_filename); prog->report("Creating output workspace"); // prep the output workspace EventWorkspace_sptr localWorkspace = EventWorkspace_sptr(new EventWorkspace()); // Make sure to initialize. // We can use dummy numbers for arguments, for event workspace it doesn't // matter localWorkspace->initialize(1, 1, 1); // Set the units localWorkspace->getAxis(0)->unit() = UnitFactory::Instance().create("TOF"); localWorkspace->setYUnit("Counts"); // TODO localWorkspace->setTitle(title); // Add the run_start property // Use the first pulse as the run_start time. if (this->num_pulses > 0) { // add the start of the run as a ISO8601 date/time string. The start = the // first pulse. // (this is used in LoadInstrument to find the right instrument file to // use). localWorkspace->mutableRun().addProperty( "run_start", pulsetimes[0].toISO8601String(), true); } // determine the run number and add it to the run object localWorkspace->mutableRun().addProperty("run_number", getRunnumber(event_filename)); // Get the instrument! prog->report("Loading Instrument"); this->runLoadInstrument(event_filename, localWorkspace); // load the mapping file prog->report("Loading Mapping File"); string mapping_filename = this->getPropertyValue(MAP_PARAM); if (mapping_filename.empty()) { mapping_filename = generateMappingfileName(localWorkspace); if (!mapping_filename.empty()) this->g_log.information() << "Found mapping file \"" << mapping_filename << "\"" << std::endl; } this->loadPixelMap(mapping_filename); // Process the events into pixels this->procEvents(localWorkspace); // Save output this->setProperty<IEventWorkspace_sptr>(OUT_PARAM, localWorkspace); // Cleanup delete prog; }