/** Determine in the WorkspaceGroup is multiperiod. * @return True if the WorkspaceGroup instance is multiperiod. */ bool WorkspaceGroup::isMultiperiod() const { std::lock_guard<std::recursive_mutex> _lock(m_mutex); if (m_workspaces.empty()) { g_log.debug("Not a multiperiod-group with < 1 nested workspace."); return false; } // Loop through all inner workspaces, checking each one in turn. for (const auto &workspace : m_workspaces) { if (MatrixWorkspace_sptr ws = boost::dynamic_pointer_cast<MatrixWorkspace>(workspace)) { try { Kernel::Property *nPeriodsProp = ws->run().getLogData("nperiods"); int num = -1; Kernel::Strings::convert(nPeriodsProp->value(), num); if (num < 1) { g_log.debug("Not a multiperiod-group with nperiods log < 1."); return false; } } catch (Kernel::Exception::NotFoundError &) { g_log.debug("Not a multiperiod-group without nperiods log on all " "nested workspaces."); return false; } } else { g_log.debug("Not a multiperiod-group unless all inner workspaces are " "Matrix Workspaces."); return false; } } return true; }
/** Loads and checks the values passed to the algorithm * * @throw invalid_argument if there is an incapatible property value so the algorithm can't continue */ void DetectorEfficiencyCor::retrieveProperties() { // these first three properties are fully checked by validators m_inputWS = getProperty("InputWorkspace"); m_paraMap = &(m_inputWS->instrumentParameters()); m_Ei = getProperty("IncidentEnergy"); // If we're not given an Ei, see if one has been set. if( m_Ei == EMPTY_DBL() ) { if( m_inputWS->run().hasProperty("Ei") ) { Kernel::Property* eiprop = m_inputWS->run().getProperty("Ei"); m_Ei = boost::lexical_cast<double>(eiprop->value()); g_log.debug() << "Using stored Ei value " << m_Ei << "\n"; } else { throw std::invalid_argument("No Ei value has been set or stored within the run information."); } } m_outputWS = getProperty("OutputWorkspace"); // If input and output workspaces are not the same, create a new workspace for the output if (m_outputWS != m_inputWS ) { m_outputWS = WorkspaceFactory::Instance().create(m_inputWS); } }
/** * Set up starting values for cached variables */ void MDNormDirectSC::cacheInputs() { m_inputWS = getProperty("InputWorkspace"); bool skipCheck = getProperty("SkipSafetyCheck"); if (!skipCheck && (inputEnergyMode() != "Direct")) { throw std::invalid_argument("Invalid energy transfer mode. Algorithm only " "supports direct geometry spectrometers."); } // Min/max dimension values const auto hdim(m_inputWS->getDimension(0)), kdim(m_inputWS->getDimension(1)), ldim(m_inputWS->getDimension(2)), edim(m_inputWS->getDimension(3)); m_hmin = hdim->getMinimum(); m_kmin = kdim->getMinimum(); m_lmin = ldim->getMinimum(); m_dEmin = edim->getMinimum(); m_hmax = hdim->getMaximum(); m_kmax = kdim->getMaximum(); m_lmax = ldim->getMaximum(); m_dEmax = edim->getMaximum(); const auto &exptInfoZero = *(m_inputWS->getExperimentInfo(0)); auto source = exptInfoZero.getInstrument()->getSource(); auto sample = exptInfoZero.getInstrument()->getSample(); if (source == nullptr || sample == nullptr) { throw Kernel::Exception::InstrumentDefinitionError( "Instrument not sufficiently defined: failed to get source and/or " "sample"); } m_samplePos = sample->getPos(); m_beamDir = m_samplePos - source->getPos(); m_beamDir.normalize(); double originaldEmin = exptInfoZero.run().getBinBoundaries().front(); double originaldEmax = exptInfoZero.run().getBinBoundaries().back(); if (exptInfoZero.run().hasProperty("Ei")) { Kernel::Property *eiprop = exptInfoZero.run().getProperty("Ei"); m_Ei = boost::lexical_cast<double>(eiprop->value()); if (m_Ei <= 0) { throw std::invalid_argument("Ei stored in the workspace is not positive"); } } else { throw std::invalid_argument("Could not find Ei value in the workspace."); } double eps = 1e-7; if (m_Ei - originaldEmin < eps) { originaldEmin = m_Ei - eps; } if (m_Ei - originaldEmax < eps) { originaldEmax = m_Ei - 1e-7; } if (originaldEmin == originaldEmax) { throw std::runtime_error("The limits of the original workspace used in " "ConvertToMD are incorrect"); } const double energyToK = 8.0 * M_PI * M_PI * PhysicalConstants::NeutronMass * PhysicalConstants::meV * 1e-20 / (PhysicalConstants::h * PhysicalConstants::h); m_ki = std::sqrt(energyToK * m_Ei); m_kfmin = std::sqrt(energyToK * (m_Ei - originaldEmin)); m_kfmax = std::sqrt(energyToK * (m_Ei - originaldEmax)); }
T ConvertEmptyToTof::getPropertyFromRun(API::MatrixWorkspace_const_sptr inputWS, const std::string &propertyName) { if (inputWS->run().hasProperty(propertyName)) { Kernel::Property *prop = inputWS->run().getProperty(propertyName); return boost::lexical_cast<T>(prop->value()); } else { std::string mesg = "No '" + propertyName + "' property found in the input workspace...."; throw std::runtime_error(mesg); } }
std::string AlgorithmHasProperty::checkValidity( const boost::shared_ptr<IAlgorithm> &value) const { std::string message; if (value->existsProperty(m_propName)) { Kernel::Property *p = value->getProperty(m_propName); if (!p->isValid().empty()) { message = "Algorithm object contains the required property \"" + m_propName + "\" but it has an invalid value: " + p->value(); } } else { message = "Algorithm object does not have the required property \"" + m_propName + "\""; } return message; }
TimeAtSampleStrategy *FilterEvents::setupDirectTOFCorrection() const { // Get incident energy Ei double ei = 0.; if (m_eventWS->run().hasProperty("Ei")) { Kernel::Property *eiprop = m_eventWS->run().getProperty("Ei"); ei = boost::lexical_cast<double>(eiprop->value()); g_log.debug() << "Using stored Ei value " << ei << "\n"; } else { ei = getProperty("IncidentEnergy"); if (isEmpty(ei)) throw std::invalid_argument( "No Ei value has been set or stored within the run information."); g_log.debug() << "Using user-input Ei value " << ei << "\n"; } return new TimeAtSampleStrategyDirect(m_eventWS, ei); }
/** This method creates an XML element named "Run" * @param sasRun :: string for run element in the xml */ void SaveCanSAS1D::createSASRunElement(std::string& sasRun) { //initialise the run number to an empty string, this may or may not be changed later std::string run; if( m_workspace->run().hasProperty("run_number") ) { Kernel::Property *logP = m_workspace->run().getLogData("run_number"); run = logP->value(); } else { g_log.debug() << "Didn't find RunNumber log in workspace. Writing <Run></Run> to the CANSAS file\n"; } searchandreplaceSpecialChars(run); sasRun="\n\t\t<Run>"; sasRun+=run; sasRun+="</Run>"; }
/** Write value from a RunInfo property (i.e., log) to a stream */ void writeLogValue(std::ostream &os, const Run &runinfo, const std::string &name, const std::string &defValue = "UNKNOWN") { // Return without property exists if (!runinfo.hasProperty(name)) { os << defValue; return; } // Get handler of property Kernel::Property *prop = runinfo.getProperty(name); // Return without a valid pointer to property if (prop == NULL) { os << defValue; return; } // Get value Kernel::TimeSeriesProperty<double> *log = dynamic_cast<Kernel::TimeSeriesProperty<double> *>(prop); if (log) { // Time series to get mean os << log->getStatistics().mean; } else { // None time series os << prop->value(); } // Unit std::string units = prop->units(); if (!units.empty()) os << " " << units; return; }
/** Execute the algorithm. */ void ConvertToDiffractionMDWorkspace::exec() { Timer tim, timtotal; CPUTimer cputim, cputimtotal; // ---------------------- Extract properties // -------------------------------------- ClearInputWorkspace = getProperty("ClearInputWorkspace"); Append = getProperty("Append"); std::string OutputDimensions = getPropertyValue("OutputDimensions"); LorentzCorrection = getProperty("LorentzCorrection"); OneEventPerBin = getProperty("OneEventPerBin"); // -------- Input workspace -> convert to Event // ------------------------------------ m_inWS = getProperty("InputWorkspace"); Workspace2D_sptr m_InWS2D = boost::dynamic_pointer_cast<Workspace2D>(m_inWS); if (LorentzCorrection) { API::Run &run = m_inWS->mutableRun(); if (run.hasProperty("LorentzCorrection")) { Kernel::Property *prop = run.getProperty("LorentzCorrection"); bool lorentzDone = boost::lexical_cast<bool, std::string>(prop->value()); if (lorentzDone) { LorentzCorrection = false; g_log.warning() << "Lorentz Correction was already done for this " "workspace. LorentzCorrection was changed to false." << std::endl; } } } m_inEventWS = boost::dynamic_pointer_cast<EventWorkspace>(m_inWS); // check the input units if (m_inWS->getAxis(0)->unit()->unitID() != "TOF") throw std::invalid_argument( "Input event workspace's X axis must be in TOF units."); // Try to get the output workspace IMDEventWorkspace_sptr i_out = getProperty("OutputWorkspace"); ws = boost::dynamic_pointer_cast< DataObjects::MDEventWorkspace<DataObjects::MDLeanEvent<3>, 3>>(i_out); // Initalize the matrix to 3x3 identity mat = Kernel::Matrix<double>(3, 3, true); // ----------------- Handle the type of output // ------------------------------------- std::string dimensionNames[3] = {"Q_lab_x", "Q_lab_y", "Q_lab_z"}; Mantid::Kernel::SpecialCoordinateSystem coordinateSystem = Mantid::Kernel::QLab; // Setup the MDFrame auto frameFactory = makeMDFrameFactoryChain(); Mantid::Geometry::MDFrame_uptr frame; if (OutputDimensions == "Q (sample frame)") { // Set the matrix based on goniometer angles mat = m_inWS->mutableRun().getGoniometerMatrix(); // But we need to invert it, since we want to get the Q in the sample frame. mat.Invert(); // Names dimensionNames[0] = "Q_sample_x"; dimensionNames[1] = "Q_sample_y"; dimensionNames[2] = "Q_sample_z"; coordinateSystem = Mantid::Kernel::QSample; // Frame MDFrameArgument frameArgQSample(QSample::QSampleName, ""); frame = frameFactory->create(frameArgQSample); } else if (OutputDimensions == "HKL") { // Set the matrix based on UB etc. Kernel::Matrix<double> ub = m_inWS->mutableSample().getOrientedLattice().getUB(); Kernel::Matrix<double> gon = m_inWS->mutableRun().getGoniometerMatrix(); // As per Busing and Levy 1967, q_lab_frame = 2pi * Goniometer * UB * HKL // Therefore, HKL = (2*pi * Goniometer * UB)^-1 * q_lab_frame mat = gon * ub; mat.Invert(); // Divide by 2 PI to account for our new convention, |Q| = 2pi / wl // (December 2011, JZ) mat /= (2 * M_PI); dimensionNames[0] = "H"; dimensionNames[1] = "K"; dimensionNames[2] = "L"; coordinateSystem = Mantid::Kernel::HKL; MDFrameArgument frameArgQLab(HKL::HKLName, Units::Symbol::RLU.ascii()); frame = frameFactory->create(frameArgQLab); } else { MDFrameArgument frameArgQLab(QLab::QLabName, ""); frame = frameFactory->create(frameArgQLab); } // Q in the lab frame is the default, so nothing special to do. if (ws && Append) { // Check that existing workspace dimensions make sense with the desired one // (using the name) if (ws->getDimension(0)->getName() != dimensionNames[0]) throw std::runtime_error("The existing MDEventWorkspace " + ws->getName() + " has different dimensions than were requested! " "Either give a different name for the output, " "or change the OutputDimensions parameter."); } // ------------------- Create the output workspace if needed // ------------------------ if (!ws || !Append) { // Create an output workspace with 3 dimensions. size_t nd = 3; i_out = DataObjects::MDEventFactory::CreateMDWorkspace(nd, "MDLeanEvent"); ws = boost::dynamic_pointer_cast<DataObjects::MDEventWorkspace3Lean>(i_out); // ---------------- Get the extents ------------- std::vector<double> extents = getProperty("Extents"); // Replicate a single min,max into several if (extents.size() == 2) { for (size_t d = 1; d < nd; d++) { extents.push_back(extents[0]); extents.push_back(extents[1]); } } if (extents.size() != nd * 2) throw std::invalid_argument( "You must specify either 2 or 6 extents (min,max)."); // Give all the dimensions for (size_t d = 0; d < nd; d++) { MDHistoDimension *dim = new MDHistoDimension(dimensionNames[d], dimensionNames[d], *frame, static_cast<coord_t>(extents[d * 2]), static_cast<coord_t>(extents[d * 2 + 1]), 10); ws->addDimension(MDHistoDimension_sptr(dim)); } ws->initialize(); // Build up the box controller, using the properties in // BoxControllerSettingsAlgorithm BoxController_sptr bc = ws->getBoxController(); this->setBoxController(bc, m_inWS->getInstrument()); // We always want the box to be split (it will reject bad ones) ws->splitBox(); // Perform minimum recursion depth splitting int minDepth = this->getProperty("MinRecursionDepth"); int maxDepth = this->getProperty("MaxRecursionDepth"); if (minDepth > maxDepth) throw std::invalid_argument( "MinRecursionDepth must be <= MaxRecursionDepth "); ws->setMinRecursionDepth(size_t(minDepth)); } ws->splitBox(); if (!ws) throw std::runtime_error("Error creating a 3D MDEventWorkspace!"); BoxController_sptr bc = ws->getBoxController(); if (!bc) throw std::runtime_error( "Output MDEventWorkspace does not have a BoxController!"); // Cache the extents for speed. m_extentsMin = new coord_t[3]; m_extentsMax = new coord_t[3]; for (size_t d = 0; d < 3; d++) { m_extentsMin[d] = ws->getDimension(d)->getMinimum(); m_extentsMax[d] = ws->getDimension(d)->getMaximum(); } // Copy ExperimentInfo (instrument, run, sample) to the output WS ExperimentInfo_sptr ei(m_inWS->cloneExperimentInfo()); uint16_t runIndex = ws->addExperimentInfo(ei); UNUSED_ARG(runIndex); // ------------------- Cache values that are common for all // --------------------------- // Extract some parameters global to the instrument m_inWS->getInstrument()->getInstrumentParameters(l1, beamline, beamline_norm, samplePos); beamline_norm = beamline.norm(); beamDir = beamline / beamline.norm(); // To get all the detector ID's m_inWS->getInstrument()->getDetectors(allDetectors); // Estimate the number of events in the final workspace size_t totalEvents = m_inWS->size(); if (m_inEventWS && !OneEventPerBin) totalEvents = m_inEventWS->getNumberEvents(); prog = boost::make_shared<Progress>(this, 0, 1.0, totalEvents); // Is the addition of events thread-safe? bool MultiThreadedAdding = m_inWS->threadSafe(); // Create the thread pool that will run all of these. ThreadScheduler *ts = new ThreadSchedulerFIFO(); ThreadPool tp(ts, 0); // To track when to split up boxes this->failedDetectorLookupCount = 0; size_t eventsAdded = 0; size_t approxEventsInOutput = 0; size_t lastNumBoxes = ws->getBoxController()->getTotalNumMDBoxes(); if (DODEBUG) g_log.information() << cputim << ": initial setup. There are " << lastNumBoxes << " MDBoxes.\n"; for (size_t wi = 0; wi < m_inWS->getNumberHistograms(); wi++) { // Get an idea of how many events we'll be adding size_t eventsAdding = m_inWS->blocksize(); if (m_inEventWS && !OneEventPerBin) eventsAdding = m_inEventWS->getEventList(wi).getNumberEvents(); if (MultiThreadedAdding) { // Equivalent to calling "this->convertSpectrum(wi)" boost::function<void()> func = boost::bind(&ConvertToDiffractionMDWorkspace::convertSpectrum, &*this, static_cast<int>(wi)); // Give this task to the scheduler double cost = static_cast<double>(eventsAdding); ts->push(new FunctionTask(func, cost)); } else { // Not thread-safe. Just add right now this->convertSpectrum(static_cast<int>(wi)); } // Keep a running total of how many events we've added eventsAdded += eventsAdding; approxEventsInOutput += eventsAdding; if (bc->shouldSplitBoxes(approxEventsInOutput, eventsAdded, lastNumBoxes)) { if (DODEBUG) g_log.information() << cputim << ": Added tasks worth " << eventsAdded << " events. WorkspaceIndex " << wi << std::endl; // Do all the adding tasks tp.joinAll(); if (DODEBUG) g_log.information() << cputim << ": Performing the addition of these events.\n"; // Now do all the splitting tasks ws->splitAllIfNeeded(ts); if (ts->size() > 0) prog->doReport("Splitting Boxes"); tp.joinAll(); // Count the new # of boxes. lastNumBoxes = ws->getBoxController()->getTotalNumMDBoxes(); if (DODEBUG) g_log.information() << cputim << ": Performing the splitting. There are now " << lastNumBoxes << " boxes.\n"; eventsAdded = 0; } } if (this->failedDetectorLookupCount > 0) { if (this->failedDetectorLookupCount == 1) g_log.warning() << "Unable to find a detector for " << this->failedDetectorLookupCount << " spectrum. It has been skipped." << std::endl; else g_log.warning() << "Unable to find detectors for " << this->failedDetectorLookupCount << " spectra. They have been skipped." << std::endl; } if (DODEBUG) g_log.information() << cputim << ": We've added tasks worth " << eventsAdded << " events.\n"; tp.joinAll(); if (DODEBUG) g_log.information() << cputim << ": Performing the FINAL addition of these events.\n"; // Do a final splitting of everything ws->splitAllIfNeeded(ts); tp.joinAll(); if (DODEBUG) g_log.information() << cputim << ": Performing the FINAL splitting of boxes. There are now " << ws->getBoxController()->getTotalNumMDBoxes() << " boxes\n"; // Recount totals at the end. cputim.reset(); ws->refreshCache(); if (DODEBUG) g_log.information() << cputim << ": Performing the refreshCache().\n"; // TODO: Centroid in parallel, maybe? // ws->getBox()->refreshCentroid(NULL); // if (DODEBUG) g_log.information() << cputim << ": Performing the // refreshCentroid().\n"; if (DODEBUG) { g_log.information() << "Workspace has " << ws->getNPoints() << " events. This took " << cputimtotal << " in total.\n"; std::vector<std::string> stats = ws->getBoxControllerStats(); for (auto &stat : stats) g_log.information() << stat << "\n"; g_log.information() << std::endl; } // Set the special coordinate system. ws->setCoordinateSystem(coordinateSystem); // Save the output setProperty("OutputWorkspace", boost::dynamic_pointer_cast<IMDEventWorkspace>(ws)); // Clean up delete[] m_extentsMin; delete[] m_extentsMax; }
/** Write the header information, which is independent of bank, from the given * workspace * @param format :: The string containing the header formatting * @param os :: The stream to use to write the information * @param primaryflightpath :: Value for the moderator to sample distance */ void SaveGSS::writeHeaders(const std::string &format, std::stringstream &os, double primaryflightpath) const { const Run &runinfo = inputWS->run(); // Run number if (format.compare(SLOG) == 0) { os << "Sample Run: "; writeLogValue(os, runinfo, "run_number"); os << " Vanadium Run: "; writeLogValue(os, runinfo, "van_number"); os << " Wavelength: "; writeLogValue(os, runinfo, "LambdaRequest"); os << "\n"; } if (this->getProperty("ExtendedHeader")) { // the instrument parameter file if (runinfo.hasProperty("iparm_file")) { Kernel::Property *prop = runinfo.getProperty("iparm_file"); if (prop != NULL && (!prop->value().empty())) { std::stringstream line; line << "#Instrument parameter file: " << prop->value(); os << std::setw(80) << std::left << line.str() << "\n"; } } // write out the gsas monitor counts os << "Monitor: "; if (runinfo.hasProperty("gsas_monitor")) { writeLogValue(os, runinfo, "gsas_monitor"); } else { writeLogValue(os, runinfo, "gd_prtn_chrg", "1"); } os << "\n"; } if (format.compare(SLOG) == 0) { os << "# "; // make the next line a comment } os << inputWS->getTitle() << "\n"; os << "# " << inputWS->getNumberHistograms() << " Histograms\n"; os << "# File generated by Mantid:\n"; os << "# Instrument: " << inputWS->getInstrument()->getName() << "\n"; os << "# From workspace named : " << inputWS->getName() << "\n"; if (getProperty("MultiplyByBinWidth")) os << "# with Y multiplied by the bin widths.\n"; os << "# Primary flight path " << primaryflightpath << "m \n"; if (format.compare(SLOG) == 0) { os << "# Sample Temperature: "; writeLogValue(os, runinfo, "SampleTemp"); os << " Freq: "; writeLogValue(os, runinfo, "SpeedRequest1"); os << " Guide: "; writeLogValue(os, runinfo, "guide"); os << "\n"; // print whether it is normalized by monitor or pcharge bool norm_by_current = false; bool norm_by_monitor = false; const Mantid::API::AlgorithmHistories &algohist = inputWS->getHistory().getAlgorithmHistories(); for (Mantid::API::AlgorithmHistories::const_iterator it = algohist.begin(); it != algohist.end(); ++it) { if ((*it)->name().compare("NormaliseByCurrent") == 0) norm_by_current = true; if ((*it)->name().compare("NormaliseToMonitor") == 0) norm_by_monitor = true; } os << "#"; if (norm_by_current) os << " Normalised to pCharge"; if (norm_by_monitor) os << " Normalised to monitor"; os << "\n"; } return; }
void CorrectKiKf::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); } const std::string emodeStr = getProperty("EMode"); double efixedProp = getProperty("EFixed"),efixed; if( efixedProp == EMPTY_DBL() ) { if (emodeStr == "Direct") { // Check if it has been store on the run object for this workspace if( this->inputWS->run().hasProperty("Ei")) { Kernel::Property* eiprop = this->inputWS->run().getProperty("Ei"); efixedProp = boost::lexical_cast<double>(eiprop->value()); g_log.debug() << "Using stored Ei value " << efixedProp << "\n"; } else { throw std::invalid_argument("No Ei value has been set or stored within the run information."); } } else { // If not specified, will try to get Ef from the parameter file for indirect geometry, // but it will be done for each spectrum separately, in case of different analyzer crystals } } // Get the parameter map const ParameterMap& pmap = outputWS->constInstrumentParameters(); 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 double Efi = 0; // Now get the detector object for this histogram to check if monitor // or to get Ef for indirect geometry if (emodeStr == "Indirect") { if ( efixedProp != EMPTY_DBL()) Efi = efixedProp; else try { IDetector_const_sptr det = inputWS->getDetector(i); if (!det->isMonitor()) { try { Parameter_sptr par = pmap.getRecursive(det.get(),"Efixed"); if (par) { Efi = par->value<double>(); g_log.debug() << "Detector: " << det->getID() << " EFixed: " << Efi << "\n"; } } catch (std::runtime_error&) { /* Throws if a DetectorGroup, use single provided value */ } } } catch(std::runtime_error&) { g_log.information() << "Workspace Index " << i << ": cannot find detector" << "\n"; } } if (emodeStr == "Indirect") efixed=Efi; else efixed=efixedProp; //Do the correction EventList *evlist=outputWS->getEventListPtr(i); switch (evlist->getEventType()) { case TOF: //Switch to weights if needed. evlist->switchTo(WEIGHTED); /* no break */ // Fall through case WEIGHTED: correctKiKfEventHelper(evlist->getWeightedEvents(), efixed,emodeStr); break; case WEIGHTED_NOTIME: correctKiKfEventHelper(evlist->getWeightedEventsNoTime(), efixed,emodeStr); break; } prog.report(); PARALLEL_END_INTERUPT_REGION } PARALLEL_CHECK_INTERUPT_REGION outputWS->clearMRU(); if (inputWS->getNumberEvents( ) != outputWS->getNumberEvents( )) { g_log.information() <<"Ef <= 0 or Ei <= 0 for "<<inputWS->getNumberEvents( )-outputWS->getNumberEvents( )<<" events, out of "<<inputWS->getNumberEvents( )<<std::endl; if ( efixedProp == EMPTY_DBL()) g_log.information()<<"Try to set fixed energy"<<std::endl ; } }
void ModeratorTzero::execEvent(const std::string &emode) { 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 pointers to sample and source IComponent_const_sptr source = m_instrument->getSource(); IComponent_const_sptr sample = m_instrument->getSample(); double Lss = source->getDistance(*sample); // distance from source to sample // calculate tof shift once for all neutrons if emode==Direct double t0_direct(-1); if (emode == "Direct") { Kernel::Property *eiprop = inputWS->run().getProperty("Ei"); double Ei = boost::lexical_cast<double>(eiprop->value()); mu::Parser parser; parser.DefineVar("incidentEnergy", &Ei); // associate E1 to this parser parser.SetExpr(m_formula); t0_direct = parser.Eval(); } // 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 { IDetector_const_sptr det; double L1(Lss); // distance from source to sample double L2(-1); // distance from sample to detector try { det = inputWS->getDetector(i); if (det->isMonitor()) { // redefine the sample as the monitor L1 = source->getDistance(*det); L2 = 0; } else { L2 = sample->getDistance(*det); } } catch (Exception::NotFoundError &) { g_log.error() << "Unable to calculate distances to/from detector" << i << std::endl; } if (L2 >= 0) { // One parser for each parallel processor needed (except Edirect mode) double E1; mu::Parser parser; parser.DefineVar("incidentEnergy", &E1); // associate E1 to this parser parser.SetExpr(m_formula); // fast neutrons are shifted by min_t0_next, irrespective of tof double v1_max = L1 / m_t1min; E1 = m_convfactor * v1_max * v1_max; double min_t0_next = parser.Eval(); if (emode == "Indirect") { double t2(-1.0); // time from sample to detector. (-1) signals error if (det->isMonitor()) { t2 = 0.0; } else { static const double convFact = 1.0e-6 * sqrt(2 * PhysicalConstants::meV / PhysicalConstants::NeutronMass); std::vector<double> wsProp = det->getNumberParameter("Efixed"); if (!wsProp.empty()) { double E2 = wsProp.at(0); //[E2]=meV double v2 = convFact * sqrt(E2); //[v2]=meter/microsec t2 = L2 / v2; } else { // t2 is kept to -1 if no Efixed is found g_log.debug() << "Efixed not found for detector " << i << std::endl; } } if (t2 >= 0) // t2 < 0 when no detector info is available { // fix the histogram bins MantidVec &x = evlist.dataX(); for (double &tof : x) { if (tof < m_t1min + t2) tof -= min_t0_next; else tof -= CalculateT0indirect(tof, L1, t2, E1, parser); } MantidVec tofs = evlist.getTofs(); for (double &tof : tofs) { if (tof < m_t1min + t2) tof -= min_t0_next; else tof -= CalculateT0indirect(tof, L1, t2, E1, parser); } evlist.setTofs(tofs); evlist.setSortOrder(Mantid::DataObjects::EventSortType::UNSORTED); } // end of if( t2>= 0) } // end of if(emode=="Indirect") else if (emode == "Elastic") { // Apply t0 correction to histogram bins MantidVec &x = evlist.dataX(); for (double &tof : x) { if (tof < m_t1min * (L1 + L2) / L1) tof -= min_t0_next; else tof -= CalculateT0elastic(tof, L1 + L2, E1, parser); } MantidVec tofs = evlist.getTofs(); for (double &tof : tofs) { // add a [-0.1,0.1] microsecond noise to avoid artifacts // resulting from original tof data if (tof < m_t1min * (L1 + L2) / L1) tof -= min_t0_next; else tof -= CalculateT0elastic(tof, L1 + L2, E1, parser); } evlist.setTofs(tofs); evlist.setSortOrder(Mantid::DataObjects::EventSortType::UNSORTED); MantidVec tofs_b = evlist.getTofs(); MantidVec xarray = evlist.readX(); } // end of else if(emode=="Elastic") else if (emode == "Direct") { // fix the histogram bins MantidVec &x = evlist.dataX(); for (double &tof : x) { tof -= t0_direct; } MantidVec tofs = evlist.getTofs(); for (double &tof : tofs) { tof -= t0_direct; } evlist.setTofs(tofs); evlist.setSortOrder(Mantid::DataObjects::EventSortType::UNSORTED); } // end of else if(emode=="Direct") } // end of if(L2 >= 0) } // end of if (evlist.getNumberEvents() > 0) prog.report(); PARALLEL_END_INTERUPT_REGION } // end of for (int i = 0; i < static_cast<int>(numHists); ++i) PARALLEL_CHECK_INTERUPT_REGION outputWS->clearMRU(); // Clears the Most Recent Used lists */ } // end of void ModeratorTzero::execEvent()
void ModeratorTzero::execEvent(const std::string &emode) { g_log.information("Processing event workspace"); const MatrixWorkspace_const_sptr matrixInputWS = getProperty("InputWorkspace"); // generate the output workspace pointer API::MatrixWorkspace_sptr matrixOutputWS = getProperty("OutputWorkspace"); if (matrixOutputWS != matrixInputWS) { matrixOutputWS = matrixInputWS->clone(); setProperty("OutputWorkspace", matrixOutputWS); } auto outputWS = boost::dynamic_pointer_cast<EventWorkspace>(matrixOutputWS); // calculate tof shift once for all neutrons if emode==Direct double t0_direct(-1); if (emode == "Direct") { Kernel::Property *eiprop = outputWS->run().getProperty("Ei"); double Ei = boost::lexical_cast<double>(eiprop->value()); mu::Parser parser; parser.DefineVar("incidentEnergy", &Ei); // associate E1 to this parser parser.SetExpr(m_formula); t0_direct = parser.Eval(); } const auto &spectrumInfo = outputWS->spectrumInfo(); const double Lss = spectrumInfo.l1(); // Loop over the spectra const size_t numHists = static_cast<size_t>(outputWS->getNumberHistograms()); Progress prog(this, 0.0, 1.0, numHists); // report progress of algorithm PARALLEL_FOR_IF(Kernel::threadSafe(*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->getSpectrum(wsIndex); if (evlist.getNumberEvents() > 0) // don't bother with empty lists { double L1(Lss); // distance from source to sample double L2(-1); // distance from sample to detector if (spectrumInfo.hasDetectors(i)) { if (spectrumInfo.isMonitor(i)) { // redefine the sample as the monitor L1 = Lss + spectrumInfo.l2(i); // L2 in SpectrumInfo defined negative L2 = 0; } else { L2 = spectrumInfo.l2(i); } } else { g_log.error() << "Unable to calculate distances to/from detector" << i << '\n'; } if (L2 >= 0) { // One parser for each parallel processor needed (except Edirect mode) double E1; mu::Parser parser; parser.DefineVar("incidentEnergy", &E1); // associate E1 to this parser parser.SetExpr(m_formula); // fast neutrons are shifted by min_t0_next, irrespective of tof double v1_max = L1 / m_t1min; E1 = m_convfactor * v1_max * v1_max; double min_t0_next = parser.Eval(); if (emode == "Indirect") { double t2(-1.0); // time from sample to detector. (-1) signals error if (spectrumInfo.isMonitor(i)) { t2 = 0.0; } else { static const double convFact = 1.0e-6 * sqrt(2 * PhysicalConstants::meV / PhysicalConstants::NeutronMass); std::vector<double> wsProp = spectrumInfo.detector(i).getNumberParameter("Efixed"); if (!wsProp.empty()) { double E2 = wsProp.at(0); //[E2]=meV double v2 = convFact * sqrt(E2); //[v2]=meter/microsec t2 = L2 / v2; } else { // t2 is kept to -1 if no Efixed is found g_log.debug() << "Efixed not found for detector " << i << '\n'; } } if (t2 >= 0) // t2 < 0 when no detector info is available { // fix the histogram bins auto &x = evlist.mutableX(); for (double &tof : x) { if (tof < m_t1min + t2) tof -= min_t0_next; else tof -= CalculateT0indirect(tof, L1, t2, E1, parser); } MantidVec tofs = evlist.getTofs(); for (double &tof : tofs) { if (tof < m_t1min + t2) tof -= min_t0_next; else tof -= CalculateT0indirect(tof, L1, t2, E1, parser); } evlist.setTofs(tofs); evlist.setSortOrder(Mantid::DataObjects::EventSortType::UNSORTED); } // end of if( t2>= 0) } // end of if(emode=="Indirect") else if (emode == "Elastic") { // Apply t0 correction to histogram bins auto &x = evlist.mutableX(); for (double &tof : x) { if (tof < m_t1min * (L1 + L2) / L1) tof -= min_t0_next; else tof -= CalculateT0elastic(tof, L1 + L2, E1, parser); } MantidVec tofs = evlist.getTofs(); for (double &tof : tofs) { // add a [-0.1,0.1] microsecond noise to avoid artifacts // resulting from original tof data if (tof < m_t1min * (L1 + L2) / L1) tof -= min_t0_next; else tof -= CalculateT0elastic(tof, L1 + L2, E1, parser); } evlist.setTofs(tofs); evlist.setSortOrder(Mantid::DataObjects::EventSortType::UNSORTED); } // end of else if(emode=="Elastic") else if (emode == "Direct") { // fix the histogram bins evlist.mutableX() -= t0_direct; MantidVec tofs = evlist.getTofs(); for (double &tof : tofs) { tof -= t0_direct; } evlist.setTofs(tofs); evlist.setSortOrder(Mantid::DataObjects::EventSortType::UNSORTED); } // end of else if(emode=="Direct") } // end of if(L2 >= 0) } // end of if (evlist.getNumberEvents() > 0) prog.report(); PARALLEL_END_INTERUPT_REGION } // end of for (int i = 0; i < static_cast<int>(numHists); ++i) PARALLEL_CHECK_INTERUPT_REGION outputWS->clearMRU(); // Clears the Most Recent Used lists */ } // end of void ModeratorTzero::execEvent()
void CorrectKiKf::exec() { // Get the workspaces this->inputWS = this->getProperty("InputWorkspace"); this->outputWS = this->getProperty("OutputWorkspace"); // If input and output workspaces are not the same, create a new workspace for the output if (this->outputWS != this->inputWS) { this->outputWS = API::WorkspaceFactory::Instance().create(this->inputWS); } //Check if it is an event workspace EventWorkspace_const_sptr eventW = boost::dynamic_pointer_cast<const EventWorkspace>(inputWS); if (eventW != NULL) { this->execEvent(); return; } const size_t size = this->inputWS->blocksize(); // Calculate the number of spectra in this workspace const int numberOfSpectra = static_cast<int>(this->inputWS->size() / size); API::Progress prog(this,0.0,1.0,numberOfSpectra); const bool histogram = this->inputWS->isHistogramData(); bool negativeEnergyWarning = false; const std::string emodeStr = getProperty("EMode"); double efixedProp = getProperty("EFixed"); if( efixedProp == EMPTY_DBL() ) { if (emodeStr == "Direct") { // Check if it has been store on the run object for this workspace if( this->inputWS->run().hasProperty("Ei")) { Kernel::Property* eiprop = this->inputWS->run().getProperty("Ei"); efixedProp = boost::lexical_cast<double>(eiprop->value()); g_log.debug() << "Using stored Ei value " << efixedProp << "\n"; } else { throw std::invalid_argument("No Ei value has been set or stored within the run information."); } } else { // If not specified, will try to get Ef from the parameter file for indirect geometry, // but it will be done for each spectrum separately, in case of different analyzer crystals } } PARALLEL_FOR2(inputWS,outputWS) for (int64_t i = 0; i < int64_t(numberOfSpectra); ++i) { PARALLEL_START_INTERUPT_REGION double Efi = 0; // Now get the detector object for this histogram to check if monitor // or to get Ef for indirect geometry if (emodeStr == "Indirect") { if ( efixedProp != EMPTY_DBL()) Efi = efixedProp; else try { IDetector_const_sptr det = inputWS->getDetector(i); if (!det->isMonitor()) { std::vector< double > wsProp=det->getNumberParameter("Efixed"); if ( wsProp.size() > 0 ) { Efi=wsProp.at(0); g_log.debug() << i << " Ef: "<< Efi<<" (from parameter file)\n"; } else { g_log.information() <<"Ef not found for spectrum "<< i << std::endl; throw std::invalid_argument("No Ef value has been set or found."); } } } catch(std::runtime_error&) { g_log.information() << "Spectrum " << i << ": cannot find detector" << "\n"; } } MantidVec& yOut = outputWS->dataY(i); MantidVec& eOut = outputWS->dataE(i); const MantidVec& xIn = inputWS->readX(i); const MantidVec& yIn = inputWS->readY(i); const MantidVec& eIn = inputWS->readE(i); //Copy the energy transfer axis outputWS->setX( i, inputWS->refX(i) ); for (unsigned int j = 0; j < size; ++j) { const double deltaE = histogram ? 0.5*(xIn[j]+xIn[j+1]) : xIn[j]; double Ei=0.; double Ef=0.; double kioverkf = 1.; if (emodeStr == "Direct") //Ei=Efixed { Ei = efixedProp; Ef = Ei - deltaE; } else //Ef=Efixed { Ef = Efi; Ei = Efi + deltaE; } // if Ei or Ef is negative, it should be a warning // however, if the intensity is 0 (histogram goes to energy transfer higher than Ei) it is still ok, so no warning. if ((Ei <= 0)||(Ef <= 0)) { kioverkf=0.; if (yIn[j]!=0) negativeEnergyWarning=true; } else kioverkf = std::sqrt( Ei / Ef ); yOut[j] = yIn[j]*kioverkf; eOut[j] = eIn[j]*kioverkf; } prog.report(); PARALLEL_END_INTERUPT_REGION }//end for i PARALLEL_CHECK_INTERUPT_REGION if (negativeEnergyWarning) g_log.information() <<"Ef <= 0 or Ei <= 0 in at least one spectrum!!!!"<<std::endl; if ((negativeEnergyWarning) && ( efixedProp == EMPTY_DBL())) g_log.information()<<"Try to set fixed energy"<<std::endl ; this->setProperty("OutputWorkspace",this->outputWS); return; }
/** * Clear the vector of strings and then add pairs of strings giving information * about the specified point, x, y. The first string in a pair should * generally be a string describing the value being presented and the second * string should contain the value. * * @param x The x-coordinate of the point of interest in the data. * @param y The y-coordinate of the point of interest in the data. * @param list Vector that will be filled out with the information strings. */ void MatrixWSDataSource::getInfoList( double x, double y, std::vector<std::string> &list ) { // First get the info that is always available for any matrix workspace list.clear(); int row = (int)y; restrictRow( row ); const ISpectrum* spec = m_matWs->getSpectrum( row ); double spec_num = spec->getSpectrumNo(); SVUtils::PushNameValue( "Spec Num", 8, 0, spec_num, list ); std::string x_label = ""; Unit_sptr& old_unit = m_matWs->getAxis(0)->unit(); if ( old_unit != 0 ) { x_label = old_unit->caption(); SVUtils::PushNameValue( x_label, 8, 3, x, list ); } std::set<detid_t> ids = spec->getDetectorIDs(); if ( !ids.empty() ) { list.push_back("Det ID"); const int64_t id = static_cast<int64_t>(*(ids.begin())); list.push_back(boost::lexical_cast<std::string>(id)); } /* Now try to do various unit conversions to get equivalent info */ /* first make sure we can get the needed information */ if ( !(m_instrument && m_source && m_sample) ) { return; } try { if ( old_unit == 0 ) { g_log.debug("No UNITS on MatrixWorkspace X-axis"); return; } auto det = m_matWs->getDetector( row ); if ( det == 0 ) { g_log.debug() << "No DETECTOR for row " << row << " in MatrixWorkspace" << std::endl; return; } double l1 = m_source->getDistance(*m_sample); double l2 = 0.0; double two_theta = 0.0; double azi = 0.0; if ( det->isMonitor() ) { l2 = det->getDistance(*m_source); l2 = l2-l1; } else { l2 = det->getDistance(*m_sample); two_theta = m_matWs->detectorTwoTheta(det); azi = det->getPhi(); } SVUtils::PushNameValue( "L2", 8, 4, l2, list ); SVUtils::PushNameValue( "TwoTheta", 8, 2, two_theta*180./M_PI, list ); SVUtils::PushNameValue( "Azimuthal", 8, 2, azi*180./M_PI, list ); /* For now, only support diffractometers and monitors. */ /* We need a portable way to determine emode and */ /* and efixed that will work for any matrix workspace! */ int emode = 0; double efixed = 0.0; double delta = 0.0; // First try to get emode & efixed from the user if ( m_emodeHandler != NULL ) { efixed = m_emodeHandler->getEFixed(); if ( efixed != 0 ) { emode = m_emodeHandler->getEMode(); if ( emode == 0 ) { g_log.information("EMode invalid, spectrometer needed if emode != 0"); g_log.information("Assuming Direct Geometry Spectrometer...."); emode = 1; } } } // Did NOT get emode & efixed from user, try getting direct geometry information from the run object if ( efixed == 0 ) { const API::Run & run = m_matWs->run(); if ( run.hasProperty("Ei") ) { Kernel::Property* prop = run.getProperty("Ei"); efixed = boost::lexical_cast<double,std::string>(prop->value()); emode = 1; // only correct if direct geometry } else if ( run.hasProperty("EnergyRequested") ) { Kernel::Property* prop = run.getProperty("EnergyRequested"); efixed = boost::lexical_cast<double,std::string>(prop->value()); emode = 1; } else if ( run.hasProperty("EnergyEstimate") ) { Kernel::Property* prop = run.getProperty("EnergyEstimate"); efixed = boost::lexical_cast<double,std::string>(prop->value()); emode = 1; } } // Finally, try getting indirect geometry information from the detector object if ( efixed == 0 ) { if ( !(det->isMonitor() && det->hasParameter("Efixed"))) { try { const ParameterMap& pmap = m_matWs->constInstrumentParameters(); Parameter_sptr par = pmap.getRecursive(det.get(),"Efixed"); if (par) { efixed = par->value<double>(); emode = 2; } } catch ( std::runtime_error& ) { g_log.debug() << "Failed to get Efixed from detector ID: " << det->getID() << " in MatrixWSDataSource" << std::endl; efixed = 0; } } } if ( efixed == 0 ) emode = 0; if ( m_emodeHandler != NULL ) { m_emodeHandler -> setEFixed( efixed ); m_emodeHandler -> setEMode ( emode ); } double tof = old_unit->convertSingleToTOF( x, l1, l2, two_theta, emode, efixed, delta ); if ( ! (x_label == "Time-of-flight") ) SVUtils::PushNameValue( "Time-of-flight", 8, 1, tof, list ); if ( ! (x_label == "Wavelength") ) { const Unit_sptr& wl_unit = UnitFactory::Instance().create("Wavelength"); double wavelength = wl_unit->convertSingleFromTOF( tof, l1, l2, two_theta, emode, efixed, delta ); SVUtils::PushNameValue( "Wavelength", 8, 4, wavelength, list ); } if ( ! (x_label == "Energy") ) { const Unit_sptr& e_unit = UnitFactory::Instance().create("Energy"); double energy = e_unit->convertSingleFromTOF( tof, l1, l2, two_theta, emode, efixed, delta ); SVUtils::PushNameValue( "Energy", 8, 4, energy, list ); } if ( (! (x_label == "d-Spacing")) && (two_theta != 0.0) && ( emode == 0 ) ) { const Unit_sptr& d_unit = UnitFactory::Instance().create("dSpacing"); double d_spacing = d_unit->convertSingleFromTOF( tof, l1, l2, two_theta, emode, efixed, delta ); SVUtils::PushNameValue( "d-Spacing", 8, 4, d_spacing, list ); } if ( (! (x_label == "q")) && (two_theta != 0.0) ) { const Unit_sptr& q_unit=UnitFactory::Instance().create("MomentumTransfer"); double mag_q = q_unit->convertSingleFromTOF( tof, l1, l2, two_theta, emode, efixed, delta ); SVUtils::PushNameValue( "|Q|", 8, 4, mag_q, list ); } if ( (! (x_label == "DeltaE")) && (two_theta != 0.0) && ( emode != 0 ) ) { const Unit_sptr& deltaE_unit=UnitFactory::Instance().create("DeltaE"); double delta_E = deltaE_unit->convertSingleFromTOF( tof, l1, l2, two_theta, emode, efixed, delta ); SVUtils::PushNameValue( "DeltaE", 8, 4, delta_E, list ); } } catch (std::exception & e) { g_log.debug() << "Failed to get information from Workspace:" << e.what() << std::endl; } }