double DgsReduction::getParameter(std::string algParam, MatrixWorkspace_sptr ws, std::string altParam) { double param = this->getProperty(algParam); if (EMPTY_DBL() == param) { param = ws->getInstrument()->getNumberParameter(altParam)[0]; } return param; }
/** Get a pointer to an instrument in one of 3 ways: InputWorkspace, * InstrumentName, InstrumentFilename * @param alg :: algorithm from which to get the property values. * */ Geometry::Instrument_const_sptr LoadCalFile::getInstrument3Ways(Algorithm *alg) { MatrixWorkspace_sptr inWS = alg->getProperty("InputWorkspace"); std::string InstrumentName = alg->getPropertyValue("InstrumentName"); std::string InstrumentFilename = alg->getPropertyValue("InstrumentFilename"); // Some validation int numParams = 0; if (inWS) numParams++; if (!InstrumentName.empty()) numParams++; if (!InstrumentFilename.empty()) numParams++; if (numParams > 1) throw std::invalid_argument("You must specify exactly ONE way to get an " "instrument (workspace, instrument name, or " "IDF file). You specified more than one."); if (numParams == 0) throw std::invalid_argument("You must specify exactly ONE way to get an " "instrument (workspace, instrument name, or " "IDF file). You specified none."); // ---------- Get the instrument one of 3 ways --------------------------- Instrument_const_sptr inst; if (inWS) { inst = inWS->getInstrument(); } else { Algorithm_sptr childAlg = alg->createChildAlgorithm("LoadInstrument", 0.0, 0.2); MatrixWorkspace_sptr tempWS = boost::make_shared<Workspace2D>(); childAlg->setProperty<MatrixWorkspace_sptr>("Workspace", tempWS); childAlg->setPropertyValue("Filename", InstrumentFilename); childAlg->setPropertyValue("InstrumentName", InstrumentName); childAlg->setProperty("RewriteSpectraMap", Mantid::Kernel::OptionalBool(false)); childAlg->executeAsChildAlg(); inst = tempWS->getInstrument(); } return inst; }
/** Checks that the input workspace all exist, that they are the same size, have * the same units * and the same instrument name. Will throw if they don't. * @param inputWorkspaces The names of the input workspaces * @return A list of pointers to the input workspace, ordered by increasing * frame starting point * @throw Exception::NotFoundError If an input workspace doesn't exist * @throw std::invalid_argument If the input workspaces are not compatible */ std::list<API::MatrixWorkspace_sptr> MergeRuns::validateInputs(const std::vector<std::string> &inputWorkspaces) { std::list<MatrixWorkspace_sptr> inWS; std::string xUnitID; std::string YUnit; bool dist(false); // 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) { MatrixWorkspace_sptr ws; // Fetch the next input workspace - throw an error if it's not there try { ws = AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>( inputWorkspaces[i]); if (!ws) { g_log.error() << "Input workspace " << inputWorkspaces[i] << " not found.\n"; throw Kernel::Exception::NotFoundError("Data Object", inputWorkspaces[i]); } inWS.push_back(ws); } catch (Exception::NotFoundError &) { g_log.error() << "Input workspace " << inputWorkspaces[i] << " not found.\n"; throw; } // Check that it has common binning if (!WorkspaceHelpers::commonBoundaries(inWS.back())) { g_log.error("Input workspaces must have common binning for all spectra"); throw std::invalid_argument( "Input workspaces must have common binning for all spectra"); } // 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); } } // Order the workspaces by ascending frame (X) starting point inWS.sort(compare); return inWS; }
/** Sets the properties of the reference (usually first) workspace, * to later check the compatibility of the others with the reference * @param ref : the reference workspace */ void RunCombinationHelper::setReferenceProperties(MatrixWorkspace_sptr ref) { m_numberSpectra = ref->getNumberHistograms(); m_numberDetectors = ref->detectorInfo().size(); m_xUnit = ref->getAxis(0)->unit()->unitID(); m_spectrumAxisUnit = ref->getAxis(1)->unit()->unitID(); m_yUnit = ref->YUnit(); m_isHistogramData = ref->isHistogramData(); m_isScanning = ref->detectorInfo().isScanning(); m_instrumentName = ref->getInstrument()->getName(); if (m_numberSpectra) { m_hasDx.reserve(m_numberSpectra); for (unsigned int i = 0; i < m_numberSpectra; ++i) m_hasDx.push_back(ref->hasDx(i)); } }
/** * Get the detector component. Use the name provided as a property as the basis *for the lookup as a priority. * * Throws if the name is invalid. * @param workspace : Workspace from instrument with detectors * @param isPointDetector : True if this is a point detector. Used to guess a *name. * @return The component : The component object found. */ boost::shared_ptr<const Mantid::Geometry::IComponent> SpecularReflectionAlgorithm::getDetectorComponent( MatrixWorkspace_sptr workspace, const bool isPointDetector) const { boost::shared_ptr<const IComponent> searchResult; if (!isPropertyDefault("SpectrumNumbersOfDetectors")) { const std::vector<int> spectrumNumbers = this->getProperty("SpectrumNumbersOfDetectors"); const bool strictSpectrumChecking = this->getProperty("StrictSpectrumChecking"); checkSpectrumNumbers(spectrumNumbers, strictSpectrumChecking, g_log); auto specToWorkspaceIndex = workspace->getSpectrumToWorkspaceIndexMap(); DetectorGroup_sptr allDetectors = boost::make_shared<DetectorGroup>(); const auto &spectrumInfo = workspace->spectrumInfo(); for (auto index : spectrumNumbers) { const size_t spectrumNumber{static_cast<size_t>(index)}; auto it = specToWorkspaceIndex.find(index); if (it == specToWorkspaceIndex.end()) { std::stringstream message; message << "Spectrum number " << spectrumNumber << " does not exist in the InputWorkspace"; throw std::invalid_argument(message.str()); } const size_t workspaceIndex = it->second; auto detector = workspace->getDetector(workspaceIndex); if (spectrumInfo.isMasked(workspaceIndex)) g_log.warning() << "Adding a detector (ID:" << detector->getID() << ") that is flagged as masked.\n"; allDetectors->addDetector(detector); } searchResult = allDetectors; } else { Mantid::Geometry::Instrument_const_sptr inst = workspace->getInstrument(); std::string componentToCorrect = isPointDetector ? "point-detector" : "linedetector"; if (!isPropertyDefault("DetectorComponentName")) { componentToCorrect = this->getPropertyValue("DetectorComponentName"); } searchResult = inst->getComponentByName(componentToCorrect); if (searchResult == nullptr) { throw std::invalid_argument(componentToCorrect + " does not exist. Check input properties."); } } return searchResult; }
/** Execute the algorithm. */ void CreatePeaksWorkspace::exec() { MatrixWorkspace_sptr instWS = getProperty("InstrumentWorkspace"); PeaksWorkspace_sptr out(new PeaksWorkspace()); setProperty("OutputWorkspace", out); int NumberOfPeaks = getProperty("NumberOfPeaks"); if (instWS) { out->setInstrument(instWS->getInstrument()); // Create some default peaks for (int i=0; i < NumberOfPeaks; i++) { out->addPeak( Peak(out->getInstrument(), out->getInstrument()->getDetectorIDs(true)[0], 1.0) ); } } }
/** * Update the list of analysers based on an instrument workspace. * * @param ws Instrument workspace * @return If the workspace contained valid analysers */ bool IndirectInstrumentConfig::updateAnalysersList(MatrixWorkspace_sptr ws) { if(!ws) return false; QList<QPair<QString, QString>> instrumentModes; Instrument_const_sptr instrument = ws->getInstrument(); std::vector<std::string> ipfAnalysers = instrument->getStringParameter("analysers"); QStringList analysers; if(ipfAnalysers.size() > 0) analysers = QString::fromStdString(ipfAnalysers[0]).split(","); // Do not try to display analysers if there are none if(analysers.size() == 0) return false; for(auto it = analysers.begin(); it != analysers.end(); ++it) { QString analyser = *it; std::string ipfReflections = instrument->getStringParameter("refl-" + analyser.toStdString())[0]; QStringList reflections = QString::fromStdString(ipfReflections).split(","); if(m_removeDiffraction && analyser == "diffraction") continue; if(m_forceDiffraction && analyser != "diffraction") continue; if(reflections.size() > 0) { QVariant data = QVariant(reflections); m_uiForm.cbAnalyser->addItem(analyser, data); } else { m_uiForm.cbAnalyser->addItem(analyser); } } return true; }
/** Loads the parameters from the Nexus file if possible, else from a parameter *file * into the specified workspace * @param nxfile :: open NeXus file * @param localWorkspace :: workspace into which loading occurs * * @throw FileError Thrown if unable to parse XML file */ void LoadIDFFromNexus::LoadParameters( ::NeXus::File *nxfile, const MatrixWorkspace_sptr localWorkspace) { std::string parameterString; // First attempt to load parameters from nexus file. nxfile->openGroup("instrument", "NXinstrument"); localWorkspace->loadInstrumentParametersNexus(nxfile, parameterString); nxfile->closeGroup(); // loadInstrumentParametersNexus does not populate any instrument params // so we do it here. localWorkspace->populateInstrumentParameters(); if (parameterString.empty()) { // No parameters have been found in Nexus file, so we look for them in a // parameter file. std::vector<std::string> directoryNames = ConfigService::Instance().getInstrumentDirectories(); const std::string instrumentName = localWorkspace->getInstrument()->getName(); for (const auto &directoryName : directoryNames) { // This will iterate around the directories from user ->etc ->install, and // find the first appropriate file const std::string paramFile = directoryName + instrumentName + "_Parameters.xml"; // Attempt to load specified file, if successful, use file and stop // search. if (loadParameterFile(paramFile, localWorkspace)) break; } } else { // We do have parameters from the Nexus file g_log.notice() << "Found Instrument parameter map entry in Nexus file, " "which is loaded.\n\n"; // process parameterString into parameters in workspace localWorkspace->readParameterMap(parameterString); } }
void SmoothNeighboursDialog::inputWorkspaceChanged(const QString& pName) { UNUSED_ARG(pName); m_propertiesWidget->m_groupWidgets[RECTANGULAR_GROUP]->setVisible(false); m_propertiesWidget->m_groupWidgets[NON_UNIFORM_GROUP]->setVisible(false); std::string inWsName = INPUT_WORKSPACE.toStdString(); // Workspace should have been set by PropertyWidget before emitting valueChanged MatrixWorkspace_sptr inWs = this->getAlgorithm()->getProperty(inWsName); if(!inWs) { // Workspace groups are NOT returned by IWP->getWorkspace(), as they are not MatrixWorkspace, // so check the ADS for the GroupWorkspace with the same name std::string inWsValue = this->getAlgorithm()->getPointerToProperty(inWsName)->value(); // If it really doesn't exist, don't do anything if(!AnalysisDataService::Instance().doesExist(inWsValue)) return; WorkspaceGroup_sptr inGroupWs = AnalysisDataService::Instance().retrieveWS<WorkspaceGroup>(inWsValue); if(inGroupWs) // If is a group workspace, use the first workspace to determine the instrument type, // as most of the times it will be the same for all the workspaces inWs = boost::dynamic_pointer_cast<MatrixWorkspace>(inGroupWs->getItem(0)); else // If is not a GroupWorkspace as well, do nothing return; } Instrument::ContainsState containsRectDetectors = inWs->getInstrument()->containsRectDetectors(); if(containsRectDetectors == Instrument::ContainsState::Full) m_propertiesWidget->m_groupWidgets[RECTANGULAR_GROUP]->setVisible(true); else m_propertiesWidget->m_groupWidgets[NON_UNIFORM_GROUP]->setVisible(true); }
/** Execute the algorithm. */ void SpecularReflectionPositionCorrect::exec() { MatrixWorkspace_sptr inWS = this->getProperty("InputWorkspace"); const std::string analysisMode = this->getProperty("AnalysisMode"); auto cloneWS = this->createChildAlgorithm("CloneWorkspace"); cloneWS->initialize(); cloneWS->setProperty("InputWorkspace", inWS); cloneWS->execute(); Workspace_sptr tmp = cloneWS->getProperty("OutputWorkspace"); MatrixWorkspace_sptr outWS = boost::dynamic_pointer_cast<MatrixWorkspace>(tmp); const double twoThetaIn = this->getProperty("TwoThetaIn"); auto instrument = outWS->getInstrument(); IComponent_const_sptr detector = this->getDetectorComponent(outWS, analysisMode == pointDetectorAnalysis); IComponent_const_sptr sample = this->getSurfaceSampleComponent(instrument); correctPosition(outWS, twoThetaIn, sample, detector); setProperty("OutputWorkspace", outWS); }
/** * Determine the instrument from the various input parameters. * * @return The correct instrument. */ Instrument_const_sptr CreateChunkingFromInstrument::getInstrument() { // try the input workspace MatrixWorkspace_sptr inWS = getProperty(PARAM_IN_WKSP); if (inWS) { return inWS->getInstrument(); } // temporary workspace to hang everything else off of MatrixWorkspace_sptr tempWS(new Workspace2D()); // name of the instrument string instName = getPropertyValue(PARAM_INST_NAME); // see if there is an input file string filename = getPropertyValue(PARAM_IN_FILE); if (!filename.empty()) { string top_entry_name("entry"); // TODO make more flexible // get the instrument name from the filename size_t n = filename.rfind('/'); if (n != std::string::npos) { std::string temp = filename.substr(n + 1, filename.size() - n - 1); n = temp.find('_'); if (n != std::string::npos && n > 0) { instName = temp.substr(0, n); } } // read information from the nexus file itself try { NeXus::File nxsfile(filename); // get the run start time string start_time; nxsfile.openGroup(top_entry_name, "NXentry"); nxsfile.readData("start_time", start_time); tempWS->mutableRun().addProperty( "run_start", DateAndTime(start_time).toISO8601String(), true); // get the instrument name nxsfile.openGroup("instrument", "NXinstrument"); nxsfile.readData("name", instName); nxsfile.closeGroup(); // Test if IDF exists in file, move on quickly if not nxsfile.openPath("instrument/instrument_xml"); nxsfile.close(); IAlgorithm_sptr loadInst = createChildAlgorithm("LoadIDFFromNexus", 0.0, 0.2); // Now execute the Child Algorithm. Catch and log any error, but don't // stop. try { loadInst->setPropertyValue("Filename", filename); loadInst->setProperty<MatrixWorkspace_sptr>("Workspace", tempWS); loadInst->setPropertyValue("InstrumentParentPath", top_entry_name); loadInst->execute(); } catch (std::invalid_argument &) { g_log.error("Invalid argument to LoadIDFFromNexus Child Algorithm "); } catch (std::runtime_error &) { g_log.debug("No instrument definition found in " + filename + " at " + top_entry_name + "/instrument"); } if (loadInst->isExecuted()) return tempWS->getInstrument(); else g_log.information("No IDF loaded from Nexus file."); } catch (::NeXus::Exception &) { g_log.information("No instrument definition found in " + filename + " at " + top_entry_name + "/instrument"); } } // run LoadInstrument if other methods have not run string instFilename = getPropertyValue(PARAM_INST_FILE); Algorithm_sptr childAlg = createChildAlgorithm("LoadInstrument", 0.0, 0.2); childAlg->setProperty<MatrixWorkspace_sptr>("Workspace", tempWS); childAlg->setPropertyValue("Filename", instFilename); childAlg->setPropertyValue("InstrumentName", instName); childAlg->executeAsChildAlg(); return tempWS->getInstrument(); }
/** * Handles setting default spectra range when an instrument configuration is *selected. * * @param instrumentName Name of selected instrument * @param analyserName Name of selected analyser (should always be *"diffraction") * @param reflectionName Name of diffraction mode selected */ void IndirectDiffractionReduction::instrumentSelected( const QString &instrumentName, const QString &analyserName, const QString &reflectionName) { UNUSED_ARG(analyserName); // Set the search instrument for runs m_uiForm.rfSampleFiles->setInstrumentOverride(instrumentName); m_uiForm.rfCanFiles->setInstrumentOverride(instrumentName); MatrixWorkspace_sptr instWorkspace = loadInstrument( instrumentName.toStdString(), reflectionName.toStdString()); Instrument_const_sptr instrument = instWorkspace->getInstrument(); // Get default spectra range double specMin = instrument->getNumberParameter("spectra-min")[0]; double specMax = instrument->getNumberParameter("spectra-max")[0]; m_uiForm.spSpecMin->setValue(static_cast<int>(specMin)); m_uiForm.spSpecMax->setValue(static_cast<int>(specMax)); // Determine whether we need vanadium input std::vector<std::string> correctionVector = instrument->getStringParameter("Workflow.Diffraction.Correction"); bool vanadiumNeeded = false; bool calibNeeded = false; if (correctionVector.size() > 0) { vanadiumNeeded = (correctionVector[0] == "Vanadium"); calibNeeded = (correctionVector[0] == "Calibration"); } if (vanadiumNeeded) m_uiForm.swVanadium->setCurrentIndex(0); else if (calibNeeded) m_uiForm.swVanadium->setCurrentIndex(1); else m_uiForm.swVanadium->setCurrentIndex(2); // Hide options that the current instrument config cannot process if (instrumentName == "OSIRIS" && reflectionName == "diffonly") { // Disable individual grouping m_uiForm.ckIndividualGrouping->setToolTip( "OSIRIS cannot group detectors individually in diffonly mode"); m_uiForm.ckIndividualGrouping->setEnabled(false); m_uiForm.ckIndividualGrouping->setChecked(false); // Disable sum files m_uiForm.ckSumFiles->setToolTip("OSIRIS cannot sum files in diffonly mode"); m_uiForm.ckSumFiles->setEnabled(false); m_uiForm.ckSumFiles->setChecked(false); } else { // Re-enable sum files m_uiForm.ckSumFiles->setToolTip(""); m_uiForm.ckSumFiles->setEnabled(true); m_uiForm.ckSumFiles->setChecked(true); // Re-enable individual grouping m_uiForm.ckIndividualGrouping->setToolTip(""); m_uiForm.ckIndividualGrouping->setEnabled(true); // Re-enable spectra range m_uiForm.spSpecMin->setEnabled(true); m_uiForm.spSpecMax->setEnabled(true); } }
/** Execute the algorithm. */ void DgsReduction::exec() { // Reduction property manager const std::string reductionManagerName = this->getProperty("ReductionProperties"); if (reductionManagerName.empty()) { g_log.error() << "ERROR: Reduction Property Manager name is empty" << std::endl; return; } this->reductionManager = boost::make_shared<PropertyManager>(); PropertyManagerDataService::Instance().addOrReplace(reductionManagerName, this->reductionManager); // Put all properties except input files/workspaces into property manager. const std::vector<Property *> props = this->getProperties(); std::vector<Property *>::const_iterator iter = props.begin(); for (; iter != props.end(); ++iter) { if (!boost::contains((*iter)->name(), "Input")) { this->reductionManager->declareProperty((*iter)->clone()); } } // Determine the default facility const FacilityInfo defaultFacility = ConfigService::Instance().getFacility(); // Need to load data to get certain bits of information. Workspace_sptr sampleWS = this->loadInputData("Sample"); MatrixWorkspace_sptr WS = boost::dynamic_pointer_cast<MatrixWorkspace>(sampleWS); this->reductionManager->declareProperty(new PropertyWithValue<std::string>( "InstrumentName", WS->getInstrument()->getName())); // Check the facility for the loaded file and make sure it's the // same as the default. const InstrumentInfo info = ConfigService::Instance().getInstrument(WS->getInstrument()->getName()); if (defaultFacility.name() != info.facility().name()) { std::ostringstream mess; mess << "Default facility must be set to " << info.facility().name(); mess << " in order for reduction to work!"; throw std::runtime_error(mess.str()); } MatrixWorkspace_sptr sampleMonWS = this->getProperty("SampleInputMonitorWorkspace"); const bool showIntermedWS = this->getProperty("ShowIntermediateWorkspaces"); // Get output workspace pointer and name MatrixWorkspace_sptr outputWS = this->getProperty("OutputWorkspace"); std::string outputWsName = this->getPropertyValue("OutputWorkspace"); if (boost::ends_with(outputWsName, "_spe")) { boost::erase_all(outputWsName, "_spe"); } // Load the hard mask if available MatrixWorkspace_sptr hardMaskWS = this->loadHardMask(); if (hardMaskWS && showIntermedWS) { std::string hardMaskName = outputWsName + "_hardmask"; this->declareProperty(new WorkspaceProperty<>("ReductionHardMask", hardMaskName, Direction::Output)); this->setProperty("ReductionHardMask", hardMaskWS); } // Load the grouping file if available MatrixWorkspace_sptr groupingWS = this->loadGroupingFile(""); if (groupingWS && showIntermedWS) { std::string groupName = outputWsName + "_grouping"; this->declareProperty(new WorkspaceProperty<>("ReductionGrouping", groupName, Direction::Output)); this->setProperty("ReductionGrouping", groupingWS); } // This will be diagnostic mask if DgsDiagnose is run and hard mask if not. MatrixWorkspace_sptr maskWS; // Process the sample detector vanadium if present Workspace_sptr detVanWS = this->loadInputData("DetectorVanadium", false); MatrixWorkspace_sptr detVanMonWS = this->getProperty("DetectorVanadiumInputMonitorWorkspace"); bool isProcessedDetVan = this->getProperty("UseProcessedDetVan"); // Process a comparison detector vanadium if present Workspace_sptr detVan2WS = this->loadInputData("DetectorVanadium2", false); MatrixWorkspace_sptr detVan2MonWS = this->getProperty("DetectorVanadium2InputMonitorWorkspace"); IAlgorithm_sptr detVan; Workspace_sptr idetVanWS; if (detVanWS && !isProcessedDetVan) { std::string detVanMaskName = outputWsName + "_diagmask"; IAlgorithm_sptr diag = this->createChildAlgorithm("DgsDiagnose"); diag->setProperty("DetVanWorkspace", detVanWS); diag->setProperty("DetVanMonitorWorkspace", detVanMonWS); diag->setProperty("DetVanCompWorkspace", detVan2WS); diag->setProperty("DetVanCompMonitorWorkspace", detVan2MonWS); diag->setProperty("SampleWorkspace", sampleWS); diag->setProperty("SampleMonitorWorkspace", sampleMonWS); diag->setProperty("HardMaskWorkspace", hardMaskWS); diag->setProperty("ReductionProperties", reductionManagerName); diag->executeAsChildAlg(); maskWS = diag->getProperty("OutputWorkspace"); if (showIntermedWS) { this->declareProperty(new WorkspaceProperty<>("SampleDetVanDiagMask", detVanMaskName, Direction::Output)); this->setProperty("SampleDetVanDiagMask", maskWS); } detVan = this->createChildAlgorithm("DgsProcessDetectorVanadium"); detVan->setProperty("InputWorkspace", detVanWS); detVan->setProperty("InputMonitorWorkspace", detVanMonWS); detVan->setProperty("MaskWorkspace", maskWS); std::string idetVanName = outputWsName + "_idetvan"; detVan->setProperty("ReductionProperties", reductionManagerName); detVan->executeAsChildAlg(); MatrixWorkspace_sptr oWS = detVan->getProperty("OutputWorkspace"); idetVanWS = boost::dynamic_pointer_cast<Workspace>(oWS); if (showIntermedWS) { this->declareProperty(new WorkspaceProperty<>("IntegratedNormWorkspace", idetVanName, Direction::Output)); this->setProperty("IntegratedNormWorkspace", idetVanWS); } } else { idetVanWS = detVanWS; maskWS = boost::dynamic_pointer_cast<MatrixWorkspace>(idetVanWS); detVanWS.reset(); } IAlgorithm_sptr etConv = this->createChildAlgorithm("DgsConvertToEnergyTransfer"); etConv->setProperty("InputWorkspace", sampleWS); etConv->setProperty("InputMonitorWorkspace", sampleMonWS); etConv->setProperty("IntegratedDetectorVanadium", idetVanWS); const double ei = this->getProperty("IncidentEnergyGuess"); etConv->setProperty("IncidentEnergyGuess", ei); if (!maskWS && hardMaskWS) { maskWS = hardMaskWS; } etConv->setProperty("MaskWorkspace", maskWS); if (groupingWS) { etConv->setProperty("GroupingWorkspace", groupingWS); } etConv->setProperty("ReductionProperties", reductionManagerName); std::string tibWsName = this->getPropertyValue("OutputWorkspace") + "_tib"; etConv->executeAsChildAlg(); outputWS = etConv->getProperty("OutputWorkspace"); MatrixWorkspace_sptr tibWS = etConv->getProperty("OutputTibWorkspace"); if (tibWS && showIntermedWS) { this->declareProperty(new WorkspaceProperty<>("SampleTibWorkspace", tibWsName, Direction::Output)); this->setProperty("SampleTibWorkspace", tibWS); } Workspace_sptr absSampleWS = this->loadInputData("AbsUnitsSample", false); // Perform absolute normalisation if necessary if (absSampleWS) { std::string absWsName = outputWsName + "_absunits"; // Collect the other workspaces first. MatrixWorkspace_sptr absSampleMonWS = this->getProperty("AbsUnitsSampleInputMonitorWorkspace"); Workspace_sptr absDetVanWS = this->loadInputData("AbsUnitsDetectorVanadium", false); MatrixWorkspace_sptr absDetVanMonWS = this->getProperty("AbsUnitsDetectorVanadiumInputMonitorWorkspace"); MatrixWorkspace_sptr absGroupingWS = this->loadGroupingFile("AbsUnits"); // Run the absolute normalisation reduction IAlgorithm_sptr absUnitsRed = this->createChildAlgorithm("DgsAbsoluteUnitsReduction"); absUnitsRed->setProperty("InputWorkspace", absSampleWS); absUnitsRed->setProperty("InputMonitorWorkspace", absSampleMonWS); absUnitsRed->setProperty("DetectorVanadiumWorkspace", absDetVanWS); absUnitsRed->setProperty("DetectorVanadiumMonitorWorkspace", absDetVanMonWS); absUnitsRed->setProperty("GroupingWorkspace", absGroupingWS); absUnitsRed->setProperty("MaskWorkspace", maskWS); absUnitsRed->setProperty("ReductionProperties", reductionManagerName); absUnitsRed->executeAsChildAlg(); MatrixWorkspace_sptr absUnitsWS = absUnitsRed->getProperty("OutputWorkspace"); //!!! There is Property outputMaskWorkspace to get masks? It looks like one is using wrong property for masks MatrixWorkspace_sptr absMaskWS = absUnitsRed->getProperty("OutputWorkspace"); IAlgorithm_sptr mask = this->createChildAlgorithm("MaskDetectors"); mask->setProperty("Workspace", outputWS); mask->setProperty("MaskedWorkspace", absMaskWS); mask->executeAsChildAlg(); outputWS = mask->getProperty("Workspace"); // Do absolute normalisation outputWS = divide(outputWS, absUnitsWS); if (showIntermedWS) { this->declareProperty(new WorkspaceProperty<>("AbsUnitsWorkspace", absWsName, Direction::Output)); this->setProperty("AbsUnitsWorkspace", absUnitsWS); this->declareProperty(new WorkspaceProperty<>("AbsUnitsDiagMask", outputWsName+"_absunits_diagmask", Direction::Output)); this->setProperty("AbsUnitsDiagMask", absMaskWS); } } // Convert from DeltaE to powder S(Q,W) const bool doPowderConvert = this->getProperty("DoPowderDataConversion"); if (doPowderConvert) { g_log.notice() << "Converting to powder S(Q,W)" << std::endl; // Collect information std::string sqwWsName = outputWsName + "_pd_sqw"; std::vector<double> qBinning = this->getProperty("PowderMomTransferRange"); const double initialEnergy = boost::lexical_cast<double>(outputWS->run().getProperty("Ei")->value()); IAlgorithm_sptr sofqw = this->createChildAlgorithm("SofQW3"); sofqw->setProperty("InputWorkspace", outputWS); sofqw->setProperty("QAxisBinning", qBinning); sofqw->setProperty("EMode", "Direct"); sofqw->setProperty("EFixed", initialEnergy); sofqw->executeAsChildAlg(); MatrixWorkspace_sptr sqwWS = sofqw->getProperty("OutputWorkspace"); this->declareProperty(new WorkspaceProperty<>("PowderSqwWorkspace", sqwWsName, Direction::Output)); this->setProperty("PowderSqwWorkspace", sqwWS); const bool saveProcNexus = this->getProperty("SavePowderNexusFile"); if (saveProcNexus) { std::string saveProcNexusFilename = this->getProperty("SavePowderNexusFilename"); if (saveProcNexusFilename.empty()) { saveProcNexusFilename = sqwWsName + ".nxs"; } IAlgorithm_sptr saveNxs = this->createChildAlgorithm("SaveNexus"); saveNxs->setProperty("InputWorkspace", sqwWS); saveNxs->setProperty("Filename", saveProcNexusFilename); saveNxs->executeAsChildAlg(); } } this->setProperty("OutputWorkspace", outputWS); }
/** Executes the algorithm. * * @throw std::runtime_error Thrown with Workspace problems */ void RotateInstrumentComponent::exec() { // Get the workspace MatrixWorkspace_sptr WS = getProperty("Workspace"); const std::string ComponentName = getProperty("ComponentName"); const int DetID = getProperty("DetectorID"); const double X = getProperty("X"); const double Y = getProperty("Y"); const double Z = getProperty("Z"); const double angle = getProperty("Angle"); const bool RelativeRotation = getProperty("RelativeRotation"); if (X + Y + Z == 0.0) throw std::invalid_argument("The rotation axis must not be a zero vector"); Instrument_const_sptr inst = WS->getInstrument(); IComponent_const_sptr comp; // Find the component to move if (DetID != -1) { comp = inst->getDetector(DetID); if (comp == 0) { std::ostringstream mess; mess<<"Detector with ID "<<DetID<<" was not found."; g_log.error(mess.str()); throw std::runtime_error(mess.str()); } } else if (!ComponentName.empty()) { comp = inst->getComponentByName(ComponentName); if (comp == 0) { std::ostringstream mess; mess<<"Component with name "<<ComponentName<<" was not found."; g_log.error(mess.str()); throw std::runtime_error(mess.str()); } } else { g_log.error("DetectorID or ComponentName must be given."); throw std::invalid_argument("DetectorID or ComponentName must be given."); } // First set new relative or absolute rotation Quat Rot; if (RelativeRotation) { Quat Rot0 = comp->getRelativeRot(); Rot = Rot0 * Quat(angle,V3D(X,Y,Z)); } else { Rot = Quat(angle,V3D(X,Y,Z)); // Then find the corresponding relative position boost::shared_ptr<const IComponent> parent = comp->getParent(); if (parent) { Quat rot0 = parent->getRelativeRot(); rot0.inverse(); Rot = Rot * rot0; } } //Need to get the address to the base instrument component Geometry::ParameterMap& pmap = WS->instrumentParameters(); // Add a parameter for the new rotation pmap.addQuat(comp.get(), "rot", Rot); return; }
void SavePAR::exec() { // Get the input workspace MatrixWorkspace_sptr inputWorkspace = getProperty("InputWorkspace"); // Get the sample position const Kernel::V3D samplePos = inputWorkspace->getInstrument()->getSample()->getPos(); // Retrieve the filename from the properties const std::string filename = getProperty("Filename"); // Get a pointer to the sample IObjComponent_const_sptr sample = inputWorkspace->getInstrument()->getSample(); std::ofstream outPAR_file(filename.c_str()); if (!outPAR_file) { g_log.error("Failed to open (PAR) file:" + filename); throw Kernel::Exception::FileError("Failed to open (PAR) file:", filename); } // execute the subalgorithm to calculate the detector's parameters; IAlgorithm_sptr spCalcDetPar = this->createSubAlgorithm("FindDetectorsPar", 0, 1, true, 1); spCalcDetPar->initialize(); spCalcDetPar->setPropertyValue("InputWorkspace", inputWorkspace->getName()); // calculate linear rather then angular detector's sizes; spCalcDetPar->setPropertyValue("ReturnLinearRanges", "1"); // in test mode, request the subalgortithm to create output workspace and add it to dataservice if(!det_par_ws_name.empty()){ spCalcDetPar->setPropertyValue("OutputParTable",det_par_ws_name); } // let's not do this for the time being /* std::string parFileName = this->getPropertyValue("ParFile"); if(!(parFileName.empty()||parFileName=="not_used.par")){ spCalcDetPar->setPropertyValue("ParFile",parFileName); }*/ spCalcDetPar->execute(); // FindDetectorsPar * pCalcDetPar = dynamic_cast<FindDetectorsPar *>(spCalcDetPar.get()); if(!pCalcDetPar){ // "can not get pointer to FindDetectorsPar algorithm" throw(std::bad_cast()); } const std::vector<double> & azimuthal = pCalcDetPar->getAzimuthal(); const std::vector<double> & polar = pCalcDetPar->getPolar(); const std::vector<double> & azimuthal_width = pCalcDetPar->getAzimWidth(); const std::vector<double> & polar_width = pCalcDetPar->getPolarWidth(); const std::vector<double> & secondary_flightpath= pCalcDetPar->getFlightPath(); const std::vector<size_t> & det_ID = pCalcDetPar->getDetID(); size_t nDetectors = pCalcDetPar->getNDetectors(); // Write the number of detectors to the file. outPAR_file <<" "<< nDetectors << std::endl; for (size_t i = 0; i < nDetectors; ++i) { // verify if no detector defined; volatile double NanID = azimuthal[i]; if(NanID !=azimuthal[i] )continue; // skip NaN -s // Now write all the detector info. outPAR_file << std::fixed << std::setprecision(3); outPAR_file.width(10); outPAR_file <<secondary_flightpath[i]; outPAR_file.width(10); outPAR_file<< polar[i]; outPAR_file.width(10); outPAR_file << (-azimuthal[i]); outPAR_file.width(10); outPAR_file << polar_width[i]; outPAR_file.width(10); outPAR_file << azimuthal_width[i]; outPAR_file.width(10); outPAR_file << det_ID[i] << std::endl; } // Close the file outPAR_file.close(); }
/** Execute the algorithm. */ void ConvertToDetectorFaceMD::exec() { // TODO convert matrix to event as needed MatrixWorkspace_sptr mws = this->getProperty("InputWorkspace"); in_ws = boost::dynamic_pointer_cast<EventWorkspace>(mws); if (!in_ws) throw std::runtime_error("InputWorkspace is not an EventWorkspace"); // Fill the map, throw if there are grouped pixels. m_detID_to_WI = in_ws->getDetectorIDToWorkspaceIndexVector(m_detID_to_WI_offset, true); // Get the map of the banks we'll display std::map<int, RectangularDetector_const_sptr> banks = this->getBanks(); // Find the size in the TOF dimension double tof_min, tof_max; Axis *ax0 = in_ws->getAxis(0); in_ws->getXMinMax(tof_min, tof_max); if (ax0->getValue(0) < tof_min) tof_min = ax0->getValue(0); if (ax0->getValue(ax0->length() - 1) > tof_max) tof_max = ax0->getValue(ax0->length() - 1); // Get MDFrame of General Frame type Mantid::Geometry::GeneralFrame framePixel( Mantid::Geometry::GeneralFrame::GeneralFrameName, "pixel"); Mantid::Geometry::GeneralFrame frameTOF( Mantid::Geometry::GeneralFrame::GeneralFrameName, ax0->unit()->label()); // ------------------ Build all the dimensions ---------------------------- MDHistoDimension_sptr dimX( new MDHistoDimension("x", "x", framePixel, static_cast<coord_t>(0), static_cast<coord_t>(m_numXPixels), m_numXPixels)); MDHistoDimension_sptr dimY( new MDHistoDimension("y", "y", framePixel, static_cast<coord_t>(0), static_cast<coord_t>(m_numYPixels), m_numYPixels)); std::string TOFname = ax0->title(); if (TOFname.empty()) TOFname = ax0->unit()->unitID(); MDHistoDimension_sptr dimTOF(new MDHistoDimension( TOFname, TOFname, frameTOF, static_cast<coord_t>(tof_min), static_cast<coord_t>(tof_max), ax0->length())); std::vector<IMDDimension_sptr> dims{dimX, dimY, dimTOF}; if (banks.size() > 1) { Mantid::Geometry::GeneralFrame frameNumber( Mantid::Geometry::GeneralFrame::GeneralFrameName, "number"); int min = banks.begin()->first; int max = banks.rbegin()->first + 1; MDHistoDimension_sptr dimBanks(new MDHistoDimension( "bank", "bank", frameNumber, static_cast<coord_t>(min), static_cast<coord_t>(max), max - min)); dims.push_back(dimBanks); } // --------- Create the workspace with the right number of dimensions // ---------- size_t nd = dims.size(); IMDEventWorkspace_sptr outWS = MDEventFactory::CreateMDWorkspace(nd, "MDEvent"); outWS->initGeometry(dims); outWS->initialize(); this->setBoxController(outWS->getBoxController(), mws->getInstrument()); outWS->splitBox(); MDEventWorkspace3::sptr outWS3 = boost::dynamic_pointer_cast<MDEventWorkspace3>(outWS); MDEventWorkspace4::sptr outWS4 = boost::dynamic_pointer_cast<MDEventWorkspace4>(outWS); // Copy ExperimentInfo (instrument, run, sample) to the output WS ExperimentInfo_sptr ei(in_ws->cloneExperimentInfo()); uint16_t runIndex = outWS->addExperimentInfo(ei); // ---------------- Convert each bank -------------------------------------- for (auto &bank : banks) { int bankNum = bank.first; RectangularDetector_const_sptr det = bank.second; for (int x = 0; x < det->xpixels(); x++) for (int y = 0; y < det->ypixels(); y++) { // Find the workspace index for this pixel coordinate detid_t detID = det->getDetectorIDAtXY(x, y); size_t wi = m_detID_to_WI[detID + m_detID_to_WI_offset]; if (wi >= in_ws->getNumberHistograms()) throw std::runtime_error("Invalid workspace index found in bank " + det->getName() + "!"); coord_t xPos = static_cast<coord_t>(x); coord_t yPos = static_cast<coord_t>(y); coord_t bankPos = static_cast<coord_t>(bankNum); EventList &el = in_ws->getSpectrum(wi); // We want to bind to the right templated function, so we have to know // the type of TofEvent contained in the EventList. boost::function<void()> func; switch (el.getEventType()) { case TOF: if (nd == 3) this->convertEventList<TofEvent, MDEvent<3>, 3>( outWS3, wi, xPos, yPos, bankPos, runIndex, detID); else if (nd == 4) this->convertEventList<TofEvent, MDEvent<4>, 4>( outWS4, wi, xPos, yPos, bankPos, runIndex, detID); break; case WEIGHTED: if (nd == 3) this->convertEventList<WeightedEvent, MDEvent<3>, 3>( outWS3, wi, xPos, yPos, bankPos, runIndex, detID); else if (nd == 4) this->convertEventList<WeightedEvent, MDEvent<4>, 4>( outWS4, wi, xPos, yPos, bankPos, runIndex, detID); break; case WEIGHTED_NOTIME: if (nd == 3) this->convertEventList<WeightedEventNoTime, MDEvent<3>, 3>( outWS3, wi, xPos, yPos, bankPos, runIndex, detID); else if (nd == 4) this->convertEventList<WeightedEventNoTime, MDEvent<4>, 4>( outWS4, wi, xPos, yPos, bankPos, runIndex, detID); break; default: throw std::runtime_error("EventList had an unexpected data type!"); } } } // ---------------------- Perform all box splitting --------------- ThreadScheduler *ts = new ThreadSchedulerLargestCost(); ThreadPool tp(ts); outWS->splitAllIfNeeded(ts); tp.joinAll(); outWS->refreshCache(); // Save the output workspace this->setProperty("OutputWorkspace", outWS); }
/** * Mask edges of a RectangularDetector * @param ws :: Input workspace * @param left :: number of columns to mask left * @param right :: number of columns to mask right * @param high :: number of rows to mask top * @param low :: number of rows to mask Bottom * @param componentName :: Must be a RectangularDetector */ void CalculateEfficiency::maskEdges(MatrixWorkspace_sptr ws, int left, int right, int high, int low, const std::string &componentName) { auto instrument = ws->getInstrument(); boost::shared_ptr<Mantid::Geometry::RectangularDetector> component; try { component = boost::const_pointer_cast<Mantid::Geometry::RectangularDetector>( boost::dynamic_pointer_cast< const Mantid::Geometry::RectangularDetector>( instrument->getComponentByName(componentName))); } catch (std::exception &) { g_log.warning("Expecting the component " + componentName + " to be a RectangularDetector. maskEdges not executed."); return; } if (!component) { g_log.warning("Component " + componentName + " is not a RectangularDetector. MaskEdges not executed."); return; } std::vector<int> IDs; int i = 0; while (i < left * component->idstep()) { IDs.push_back(component->idstart() + i); i += 1; } // right i = component->maxDetectorID() - right * component->idstep(); while (i < component->maxDetectorID()) { IDs.push_back(i); i += 1; } // low: 0,256,512,768,..,1,257,513 for (int row = 0; row < low; row++) { i = row + component->idstart(); while (i < component->nelements() * component->idstep() - component->idstep() + low + component->idstart()) { IDs.push_back(i); i += component->idstep(); } } // high # 255, 511, 767.. for (int row = 0; row < high; row++) { i = component->idstep() + component->idstart() - row - 1; while (i < component->nelements() * component->idstep() + component->idstart()) { IDs.push_back(i); i += component->idstep(); } } g_log.debug() << "CalculateEfficiency::maskEdges Detector Ids to Mask:" << std::endl; for (auto id : IDs) { g_log.debug() << id << " "; } g_log.debug() << std::endl; IAlgorithm_sptr maskAlg = createChildAlgorithm("MaskDetectors"); maskAlg->setChild(true); maskAlg->setProperty("Workspace", ws); maskAlg->setProperty("DetectorList", IDs); maskAlg->execute(); }
/** Reads the header of a .peaks file * @param outWS :: the workspace in which to place the information * @param in :: stream of the input file * @param T0 :: Time offset * @return the first word on the next line */ std::string LoadIsawPeaks::readHeader( PeaksWorkspace_sptr outWS, std::ifstream& in, double &T0 ) { std::string tag; std::string r = getWord( in , false ); if( r.length() < 1 ) throw std::logic_error( std::string( "No first line of Peaks file" ) ); if( r.compare( std::string( "Version:" ) ) != 0 ) throw std::logic_error( std::string( "No Version: on first line of Peaks file" ) ); std::string C_version = getWord( in , false ); if( C_version.length() < 1 ) throw std::logic_error( std::string( "No Version for Peaks file" ) ); getWord( in , false ); //tag // cppcheck-suppress unreadVariable std::string C_Facility = getWord( in , false ); getWord( in , false ); //tag std::string C_Instrument = getWord( in , false ); if( C_Instrument.length() < 1 ) throw std::logic_error( std::string( "No Instrument for Peaks file" ) ); // Date: use the current date/time if not found Kernel::DateAndTime C_experimentDate; std::string date; tag = getWord( in , false ); if(tag.empty()) date = Kernel::DateAndTime::getCurrentTime().toISO8601String(); else if(tag == "Date:") date = getWord( in , false ); readToEndOfLine( in , true ); // Now we load the instrument using the name and date MatrixWorkspace_sptr tempWS = WorkspaceFactory::Instance().create("Workspace2D", 1, 1, 1); tempWS->mutableRun().addProperty<std::string>("run_start", date); IAlgorithm_sptr loadInst= createChildAlgorithm("LoadInstrument"); loadInst->setPropertyValue("InstrumentName", C_Instrument); loadInst->setProperty<MatrixWorkspace_sptr> ("Workspace", tempWS); loadInst->executeAsChildAlg(); // Populate the instrument parameters in this workspace - this works around a bug tempWS->populateInstrumentParameters(); Geometry::Instrument_const_sptr instr_old = tempWS->getInstrument() ; boost::shared_ptr< ParameterMap > map(new ParameterMap()); Geometry::Instrument_const_sptr instr ( new Geometry::Instrument(instr_old->baseInstrument(), map )); //std::string s; std::string s = ApplyCalibInfo(in, "", instr_old, instr, T0); outWS->setInstrument( instr); // Now skip all lines on L1, detector banks, etc. until we get to a block of peaks. They start with 0. // readToEndOfLine( in , true ); // readToEndOfLine( in , true ); // s = getWord(in, false); while (s != "0" && in.good()) { readToEndOfLine( in , true ); s = getWord(in, false); } return s; }
void ModeratorTzero::exec() { m_tolTOF = getProperty("tolTOF"); //Tolerance in the calculation of the emission time, in microseconds m_niter=getProperty("Niter"); // number of iterations const MatrixWorkspace_sptr inputWS = getProperty("InputWorkspace"); m_instrument = inputWS->getInstrument(); // pointer to the instrument //deltaE-mode (should be "indirect") std::vector<std::string> Emode=m_instrument->getStringParameter("deltaE-mode"); if(Emode.empty()) throw Exception::InstrumentDefinitionError("Unable to retrieve instrument geometry (direct or indirect) parameter", inputWS->getTitle()); if(Emode[0]!= "indirect") throw Exception::InstrumentDefinitionError("Instrument geometry must be of type indirect."); // extract formula from instrument parameters std::vector<std::string> t0_formula=m_instrument->getStringParameter("t0_formula"); if(t0_formula.empty()) throw Exception::InstrumentDefinitionError("Unable to retrieve t0_formula among instrument parameters"); m_formula=t0_formula[0]; //Run execEvent if eventWorkSpace EventWorkspace_const_sptr eventWS = boost::dynamic_pointer_cast<const EventWorkspace>(inputWS); if (eventWS != NULL) { execEvent(); return; } MatrixWorkspace_sptr outputWS = getProperty("OutputWorkspace"); //Check whether input == output to see whether a new workspace is required. if ( outputWS != inputWS ) { //Create new workspace for output from old outputWS = WorkspaceFactory::Instance().create(inputWS); } const size_t numHists = static_cast<size_t>(inputWS->getNumberHistograms()); Progress prog(this,0.0,1.0,numHists); //report progress of algorithm PARALLEL_FOR2(inputWS, outputWS) // iterate over the spectra for (int i=0; i < static_cast<int>(numHists); ++i) { PARALLEL_START_INTERUPT_REGION size_t wsIndex = static_cast<size_t>(i); double L1=CalculateL1(inputWS, wsIndex); // distance from source to sample or monitor double t2=CalculateT2(inputWS, wsIndex); // time from sample to detector // shift the time of flights by the emission time from the moderator if(t2 >= 0) //t2 < 0 when no detector info is available { double E1; mu::Parser parser; parser.DefineVar("incidentEnergy", &E1); // associate 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 MantidVec &inbins = inputWS->dataX(i); MantidVec &outbins = outputWS->dataX(i); // iterate over the time-of-flight values for(unsigned int ibin=0; ibin < inbins.size(); ibin++) { double tof=inbins[ibin]; // current time-of-flight if(tof<m_t1min+t2) tof-=min_t0_next; else tof-=CalculateT0(tof, L1, t2, E1, parser); outbins[ibin] = tof; } } else { outputWS->dataX(i) = inputWS->dataX(i); } //Copy y and e data outputWS->dataY(i) = inputWS->dataY(i); outputWS->dataE(i) = inputWS->dataE(i); prog.report(); PARALLEL_END_INTERUPT_REGION } PARALLEL_CHECK_INTERUPT_REGION // Copy units if (inputWS->getAxis(0)->unit().get()) { outputWS->getAxis(0)->unit() = inputWS->getAxis(0)->unit(); } try { if(inputWS->getAxis(1)->unit().get()) { outputWS->getAxis(1)->unit() = inputWS->getAxis(1)->unit(); } } catch(Exception::IndexError &) { // OK, so this isn't a Workspace2D } // Assign it to the output workspace property setProperty("OutputWorkspace",outputWS); }
/** Execute the algorithm. */ void CreateGroupingWorkspace::exec() { MatrixWorkspace_sptr inWS = getProperty("InputWorkspace"); std::string InstrumentName = getPropertyValue("InstrumentName"); std::string InstrumentFilename = getPropertyValue("InstrumentFilename"); std::string OldCalFilename = getPropertyValue("OldCalFilename"); std::string GroupNames = getPropertyValue("GroupNames"); std::string grouping = getPropertyValue("GroupDetectorsBy"); int numGroups = getProperty("FixedGroupCount"); std::string componentName = getPropertyValue("ComponentName"); // Some validation int numParams = 0; if (inWS) numParams++; if (!InstrumentName.empty()) numParams++; if (!InstrumentFilename.empty()) numParams++; if (numParams > 1) throw std::invalid_argument("You must specify exactly ONE way to get an " "instrument (workspace, instrument name, or " "IDF file). You specified more than one."); if (numParams == 0) throw std::invalid_argument("You must specify exactly ONE way to get an " "instrument (workspace, instrument name, or " "IDF file). You specified none."); if (!OldCalFilename.empty() && !GroupNames.empty()) throw std::invalid_argument("You must specify either to use the " "OldCalFilename parameter OR GroupNames but " "not both!"); bool sortnames = false; // ---------- Get the instrument one of 3 ways --------------------------- Instrument_const_sptr inst; if (inWS) { inst = inWS->getInstrument(); } else { Algorithm_sptr childAlg = createChildAlgorithm("LoadInstrument", 0.0, 0.2); MatrixWorkspace_sptr tempWS = boost::make_shared<Workspace2D>(); childAlg->setProperty<MatrixWorkspace_sptr>("Workspace", tempWS); childAlg->setPropertyValue("Filename", InstrumentFilename); childAlg->setProperty("RewriteSpectraMap", Mantid::Kernel::OptionalBool(true)); childAlg->setPropertyValue("InstrumentName", InstrumentName); childAlg->executeAsChildAlg(); inst = tempWS->getInstrument(); } if (GroupNames.empty() && OldCalFilename.empty()) { if (grouping.compare("All") == 0) { GroupNames = inst->getName(); } else if (inst->getName().compare("SNAP") == 0 && grouping.compare("Group") == 0) { GroupNames = "East,West"; } else { sortnames = true; GroupNames = ""; int maxRecurseDepth = this->getProperty("MaxRecursionDepth"); // cppcheck-suppress syntaxError PRAGMA_OMP(parallel for schedule(dynamic, 1) ) for (int num = 0; num < 300; ++num) { PARALLEL_START_INTERUPT_REGION std::ostringstream mess; mess << grouping << num; IComponent_const_sptr comp = inst->getComponentByName(mess.str(), maxRecurseDepth); PARALLEL_CRITICAL(GroupNames) if (comp) GroupNames += mess.str() + ","; PARALLEL_END_INTERUPT_REGION } PARALLEL_CHECK_INTERUPT_REGION } } // --------------------------- Create the output -------------------------- auto outWS = boost::make_shared<GroupingWorkspace>(inst); this->setProperty("OutputWorkspace", outWS); // This will get the grouping std::map<detid_t, int> detIDtoGroup; Progress prog(this, 0.2, 1.0, outWS->getNumberHistograms()); // Make the grouping one of three ways: if (!GroupNames.empty()) detIDtoGroup = makeGroupingByNames(GroupNames, inst, prog, sortnames); else if (!OldCalFilename.empty()) detIDtoGroup = readGroupingFile(OldCalFilename, prog); else if ((numGroups > 0) && !componentName.empty()) detIDtoGroup = makeGroupingByNumGroups(componentName, numGroups, inst, prog); g_log.information() << detIDtoGroup.size() << " entries in the detectorID-to-group map.\n"; setProperty("NumberGroupedSpectraResult", static_cast<int>(detIDtoGroup.size())); if (detIDtoGroup.empty()) { g_log.warning() << "Creating empty group workspace\n"; setProperty("NumberGroupsResult", static_cast<int>(0)); } else { size_t numNotFound = 0; // Make the groups, if any std::map<detid_t, int>::const_iterator it_end = detIDtoGroup.end(); std::map<detid_t, int>::const_iterator it; std::unordered_set<int> groupCount; for (it = detIDtoGroup.begin(); it != it_end; ++it) { int detID = it->first; int group = it->second; groupCount.insert(group); try { outWS->setValue(detID, double(group)); } catch (std::invalid_argument &) { numNotFound++; } } setProperty("NumberGroupsResult", static_cast<int>(groupCount.size())); if (numNotFound > 0) g_log.warning() << numNotFound << " detector IDs (out of " << detIDtoGroup.size() << ") were not found in the instrument\n."; } }
void TOFSANSResolutionByPixel::exec() { MatrixWorkspace_sptr inWS = getProperty("InputWorkspace"); double deltaR = getProperty("DeltaR"); double R1 = getProperty("SourceApertureRadius"); double R2 = getProperty("SampleApertureRadius"); const bool doGravity = getProperty("AccountForGravity"); // Check the input checkInput(inWS); // Setup outputworkspace auto outWS = setupOutputWorkspace(inWS); // Convert to meters deltaR /= 1000.0; R1 /= 1000.0; R2 /= 1000.0; // The moderator workspace needs to match the data workspace // in terms of wavelength binning const MatrixWorkspace_sptr sigmaModeratorVSwavelength = getModeratorWorkspace(inWS); // create interpolation table from sigmaModeratorVSwavelength Kernel::Interpolation lookUpTable; const auto &xInterpolate = sigmaModeratorVSwavelength->points(0); const auto &yInterpolate = sigmaModeratorVSwavelength->y(0); // prefer the input to be a pointworkspace and create interpolation function if (sigmaModeratorVSwavelength->isHistogramData()) { g_log.notice() << "mid-points of SigmaModerator histogram bins will be " "used for interpolation."; } for (size_t i = 0; i < xInterpolate.size(); ++i) { lookUpTable.addPoint(xInterpolate[i], yInterpolate[i]); } // Calculate the L1 distance const V3D samplePos = inWS->getInstrument()->getSample()->getPos(); const V3D sourcePos = inWS->getInstrument()->getSource()->getPos(); const V3D SSD = samplePos - sourcePos; const double L1 = SSD.norm(); // Get the collimation length double LCollim = getProperty("CollimationLength"); if (LCollim == 0.0) { auto collimationLengthEstimator = SANSCollimationLengthEstimator(); LCollim = collimationLengthEstimator.provideCollimationLength(inWS); g_log.information() << "No collimation length was specified. A default " "collimation length was estimated to be " << LCollim << '\n'; } else { g_log.information() << "The collimation length is " << LCollim << '\n'; } const int numberOfSpectra = static_cast<int>(inWS->getNumberHistograms()); Progress progress(this, 0.0, 1.0, numberOfSpectra); const auto &spectrumInfo = inWS->spectrumInfo(); for (int i = 0; i < numberOfSpectra; i++) { IDetector_const_sptr det; if (!spectrumInfo.hasDetectors(i)) { g_log.information() << "Workspace index " << i << " has no detector assigned to it - discarding\n"; continue; } // If no detector found or if it's masked or a monitor, skip onto the next // spectrum if (spectrumInfo.isMonitor(i) || spectrumInfo.isMasked(i)) continue; const double L2 = spectrumInfo.l2(i); TOFSANSResolutionByPixelCalculator calculator; const double waveLengthIndependentFactor = calculator.getWavelengthIndependentFactor(R1, R2, deltaR, LCollim, L2); // Multiplicative factor to go from lambda to Q // Don't get fooled by the function name... const double theta = spectrumInfo.twoTheta(i); double sinTheta = sin(0.5 * theta); double factor = 4.0 * M_PI * sinTheta; const auto &xIn = inWS->x(i); const size_t xLength = xIn.size(); // Gravity correction std::unique_ptr<GravitySANSHelper> grav; if (doGravity) { grav = Kernel::make_unique<GravitySANSHelper>(spectrumInfo, i, getProperty("ExtraLength")); } // Get handles on the outputWorkspace auto &yOut = outWS->mutableY(i); // for each wavelenght bin of each pixel calculate a q-resolution for (size_t j = 0; j < xLength - 1; j++) { // use the midpoint of each bin const double wl = (xIn[j + 1] + xIn[j]) / 2.0; // Calculate q. Alternatively q could be calculated using ConvertUnit // If we include a gravity correction we need to adjust sinTheta // for each wavelength (in Angstrom) if (doGravity) { double sinThetaGrav = grav->calcSinTheta(wl); factor = 4.0 * M_PI * sinThetaGrav; } const double q = factor / wl; // wavelenght spread from bin assumed to be const double sigmaSpreadFromBin = xIn[j + 1] - xIn[j]; // Get the uncertainty in Q auto sigmaQ = calculator.getSigmaQValue(lookUpTable.value(wl), waveLengthIndependentFactor, q, wl, sigmaSpreadFromBin, L1, L2); // Insert the Q value and the Q resolution into the outputworkspace yOut[j] = sigmaQ; } progress.report("Computing Q resolution"); } // Set the y axis label outWS->setYUnitLabel("QResolution"); setProperty("OutputWorkspace", outWS); }
/** * This extraction strategy gets applied when guides are used to calculate the * collimation length. The instrument * parameter file contains the information about the number of guides to use. * The guide data itself is fetched * from the sample logs. * @param inOutWS: a matrix workspace * @param L1: the distance between sample and source * @param collimationLengthCorrection: The correction to get the collimation * length */ double SANSCollimationLengthEstimator::getCollimationLengthWithGuides( MatrixWorkspace_sptr inOutWS, const double L1, const double collimationLengthCorrection) const { auto lCollim = L1 - collimationLengthCorrection; // Make sure we have guide cutoffs if (!inOutWS->getInstrument()->hasParameter("guide-cutoff")) { throw std::invalid_argument("TOFSANSResolutionByPixel: Could not get a " "GuideCutoff from the instrument"); } // Make sure we have a defined number of guidess if (!inOutWS->getInstrument()->hasParameter("number-of-guides")) { throw std::invalid_argument( "TOFSANSResolutionByPixel: Could not get the number of guides."); } // Make sure we have a guide increment specified if (!inOutWS->getInstrument()->hasParameter( "guide-collimation-length-increment")) { throw std::invalid_argument( "TOFSANSResolutionByPixel: Could not find a guide increment."); } auto numberOfGuides = static_cast<unsigned int>( inOutWS->getInstrument()->getNumberParameter("number-of-guides")[0]); auto guideIncrement = inOutWS->getInstrument()->getNumberParameter( "guide-collimation-length-increment")[0]; // Make sure that all guides are there. They are labelled as Guide1, Guide2, // Guide3, ... // The entry is a numeric TimeSeriesProperty or a numeric entry, if something // else then default std::vector<double> guideValues; for (unsigned int i = 1; i <= numberOfGuides; i++) { auto guideName = "Guide" + boost::lexical_cast<std::string>(i); if (inOutWS->run().hasProperty(guideName)) { auto guideValue = getGuideValue(inOutWS->run().getProperty(guideName)); guideValues.push_back(guideValue); } else { throw std::invalid_argument("TOFSANSResolutionByPixel: Mismatch between " "specified number of Guides and actual " "Guides."); } } auto guideCutoff = inOutWS->getInstrument()->getNumberParameter("guide-cutoff")[0]; // Go through the guides and check in an alternate manner if the guide is // smaller // or larger than the cut off value. We start at the last guide and check that // it is // larger than the cutoff, the next one has to be smaller and so on. For // example in pseudocode // If Guide5 > 130: LCollim+=2.0 else break; // If Guide4 < 130: LCollim+=2.0 else break; // If Guide3 > 130: LCollim+=2.0 else break; // ... unsigned int largerSmallerCounter = 0; for (auto it = guideValues.rbegin(); it != guideValues.rend(); ++it) { bool guideIsLarger = largerSmallerCounter % 2 == 0; if (guideIsLarger && (*it > guideCutoff)) { lCollim += guideIncrement; } else if (!guideIsLarger && (*it < guideCutoff)) { lCollim += guideIncrement; } else { break; } largerSmallerCounter++; } return lCollim; }
/** Convert a SPICE 2D Det MatrixWorkspace to MDEvents and append to an * MDEventWorkspace * It is optional to use a virtual instrument or copy from input data workspace * @brief ConvertCWSDExpToMomentum::convertSpiceMatrixToMomentumMDEvents * @param dataws :: data matrix workspace * @param usevirtual :: boolean flag to use virtual instrument * @param startdetid :: starting detid for detectors from this workspace mapping * to virtual instrument in MDEventWorkspace * @param runnumber :: run number for all MDEvents created from this matrix * workspace */ void ConvertCWSDExpToMomentum::convertSpiceMatrixToMomentumMDEvents( MatrixWorkspace_sptr dataws, bool usevirtual, const detid_t &startdetid, const int runnumber) { // Create transformation matrix from which the transformation is Kernel::DblMatrix rotationMatrix; setupTransferMatrix(dataws, rotationMatrix); g_log.information() << "Before insert new event, output workspace has " << m_outputWS->getNEvents() << "Events.\n"; // Creates a new instance of the MDEventInserte to output workspace MDEventWorkspace<MDEvent<3>, 3>::sptr mdws_mdevt_3 = boost::dynamic_pointer_cast<MDEventWorkspace<MDEvent<3>, 3>>(m_outputWS); MDEventInserter<MDEventWorkspace<MDEvent<3>, 3>::sptr> inserter(mdws_mdevt_3); // Calcualte k_i: it is assumed that all k_i are same for one Pt. // number, i.e., one 2D XML file Kernel::V3D sourcePos = dataws->getInstrument()->getSource()->getPos(); Kernel::V3D samplePos = dataws->getInstrument()->getSample()->getPos(); if (dataws->readX(0).size() != 2) throw std::runtime_error( "Input matrix workspace has wrong dimension in X-axis."); double momentum = 0.5 * (dataws->readX(0)[0] + dataws->readX(0)[1]); Kernel::V3D ki = (samplePos - sourcePos) * (momentum / sourcePos.norm()); g_log.debug() << "Source at " << sourcePos.toString() << ", Norm = " << sourcePos.norm() << ", momentum = " << momentum << "\n" << "k_i = " << ki.toString() << "\n"; // Go though each spectrum to conver to MDEvent size_t numspec = dataws->getNumberHistograms(); double maxsignal = 0; size_t nummdevents = 0; for (size_t iws = 0; iws < numspec; ++iws) { // Get detector positions and signal double signal = dataws->readY(iws)[0]; // Skip event with 0 signal if (signal < 0.001) continue; double error = dataws->readE(iws)[0]; Kernel::V3D detpos = dataws->getDetector(iws)->getPos(); std::vector<Mantid::coord_t> q_sample(3); // Calculate Q-sample and new detector ID in virtual instrument. Kernel::V3D qlab = convertToQSample(samplePos, ki, detpos, momentum, q_sample, rotationMatrix); detid_t native_detid = dataws->getDetector(iws)->getID(); detid_t detid = native_detid + startdetid; // Insert inserter.insertMDEvent( static_cast<float>(signal), static_cast<float>(error * error), static_cast<uint16_t>(runnumber), detid, q_sample.data()); updateQRange(q_sample); g_log.debug() << "Q-lab = " << qlab.toString() << "\n"; g_log.debug() << "Insert DetID " << detid << ", signal = " << signal << ", with q_sample = " << q_sample[0] << ", " << q_sample[1] << ", " << q_sample[2] << "\n"; // Update some statistical inforamtion if (signal > maxsignal) maxsignal = signal; ++nummdevents; } g_log.information() << "Imported Matrixworkspace: Max. Signal = " << maxsignal << ", Add " << nummdevents << " MDEvents " << "\n"; // Add experiment info including instrument, goniometer and run number ExperimentInfo_sptr expinfo = boost::make_shared<ExperimentInfo>(); if (usevirtual) expinfo->setInstrument(m_virtualInstrument); else { Geometry::Instrument_const_sptr tmp_inst = dataws->getInstrument(); expinfo->setInstrument(tmp_inst); } expinfo->mutableRun().setGoniometer(dataws->run().getGoniometer(), false); expinfo->mutableRun().addProperty("run_number", runnumber); // Add all the other propertys from original data workspace const std::vector<Kernel::Property *> vec_property = dataws->run().getProperties(); for (auto property : vec_property) { expinfo->mutableRun().addProperty(property->clone()); } m_outputWS->addExperimentInfo(expinfo); return; }
void TOFSANSResolutionByPixel::exec() { MatrixWorkspace_sptr inOutWS = getProperty("InputWorkspace"); double deltaR = getProperty("DeltaR"); double R1 = getProperty("SourceApertureRadius"); double R2 = getProperty("SampleApertureRadius"); // Convert to meters deltaR /= 1000.0; R1 /= 1000.0; R2 /= 1000.0; const double sigmaModeratorMicroSec = getProperty("SigmaModerator"); const V3D samplePos = inOutWS->getInstrument()->getSample()->getPos(); const V3D sourcePos = inOutWS->getInstrument()->getSource()->getPos(); const V3D SSD = samplePos - sourcePos; const double L1 = SSD.norm(); const int numberOfSpectra = static_cast<int>(inOutWS->getNumberHistograms()); Progress progress(this,0.0,1.0,numberOfSpectra); //PARALLEL_FOR1(inOutWS) for (int i = 0; i < numberOfSpectra; i++) { //PARALLEL_START_INTERUPT_REGION IDetector_const_sptr det; try { det = inOutWS->getDetector(i); } catch (Exception::NotFoundError&) { g_log.information() << "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 scatteredFlightPathV3D = det->getPos() - samplePos; const double L2 = scatteredFlightPathV3D.norm(); const double Lsum = L1+L2; // calculate part that is wavelenght independent const double dTheta2 = (4.0 * M_PI * M_PI / 12.0) * ( 3.0*R1*R1/(L1*L1) + 3.0*R2*R2*Lsum*Lsum/(L1*L1*L2*L2) + (deltaR*deltaR)/(L2*L2) ); // Multiplicative factor to go from lambda to Q // Don't get fooled by the function name... const double theta = inOutWS->detectorTwoTheta(det); const double factor = 4.0 * M_PI * sin( theta/2.0 ); const MantidVec& xIn = inOutWS->readX(i); MantidVec& yIn = inOutWS->dataY(i); const size_t xLength = xIn.size(); for ( size_t j = 0; j < xLength-1; j++) { // Calculate q. Alternatively q could be calculated using ConvertUnit const double wl = (xIn[j+1]+xIn[j])/2.0; const double q = factor/wl; // calculate wavelenght resolution from moderator and histogram time bin width and // convert to from unit of micro-seconds to Aangstrom const double sigmaLambda = sigmaModeratorMicroSec*3.9560/(1000.0*Lsum); // calculate sigmaQ for a given lambda and pixel const double sigmaOverLambdaTimesQ = q*sigmaLambda/wl; const double sigmaQ = std::sqrt(dTheta2/(wl*wl)+sigmaOverLambdaTimesQ*sigmaOverLambdaTimesQ); // update inout workspace with this sigmaQ yIn[j] = sigmaQ; } progress.report("Computing Q resolution"); //PARALLEL_END_INTERUPT_REGION } }
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]; } } }
void TOFSANSResolutionByPixel::exec() { MatrixWorkspace_sptr inOutWS = getProperty("Workspace"); double deltaR = getProperty("DeltaR"); double R1 = getProperty("SourceApertureRadius"); double R2 = getProperty("SampleApertureRadius"); // Convert to meters deltaR /= 1000.0; R1 /= 1000.0; R2 /= 1000.0; const MatrixWorkspace_sptr sigmaModeratorVSwavelength = getProperty("SigmaModerator"); // create interpolation table from sigmaModeratorVSwavelength Kernel::Interpolation lookUpTable; const MantidVec xInterpolate = sigmaModeratorVSwavelength->readX(0); const MantidVec yInterpolate = sigmaModeratorVSwavelength->readY(0); // prefer the input to be a pointworkspace and create interpolation function if (sigmaModeratorVSwavelength->isHistogramData()) { g_log.notice() << "mid-points of SigmaModerator histogram bins will be " "used for interpolation."; for (size_t i = 0; i < xInterpolate.size() - 1; ++i) { const double midpoint = xInterpolate[i + 1] - xInterpolate[i]; lookUpTable.addPoint(midpoint, yInterpolate[i]); } } else { for (size_t i = 0; i < xInterpolate.size(); ++i) { lookUpTable.addPoint(xInterpolate[i], yInterpolate[i]); } } const V3D samplePos = inOutWS->getInstrument()->getSample()->getPos(); const V3D sourcePos = inOutWS->getInstrument()->getSource()->getPos(); const V3D SSD = samplePos - sourcePos; const double L1 = SSD.norm(); const int numberOfSpectra = static_cast<int>(inOutWS->getNumberHistograms()); Progress progress(this, 0.0, 1.0, numberOfSpectra); for (int i = 0; i < numberOfSpectra; i++) { IDetector_const_sptr det; try { det = inOutWS->getDetector(i); } catch (Exception::NotFoundError &) { g_log.information() << "Spectrum index " << i << " has no detector assigned to it - discarding" << std::endl; } // 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 scatteredFlightPathV3D = det->getPos() - samplePos; const double L2 = scatteredFlightPathV3D.norm(); const double Lsum = L1 + L2; // calculate part that is wavelenght independent const double dTheta2 = (4.0 * M_PI * M_PI / 12.0) * (3.0 * R1 * R1 / (L1 * L1) + 3.0 * R2 * R2 * Lsum * Lsum / (L1 * L1 * L2 * L2) + (deltaR * deltaR) / (L2 * L2)); // Multiplicative factor to go from lambda to Q // Don't get fooled by the function name... const double theta = inOutWS->detectorTwoTheta(det); const double factor = 4.0 * M_PI * sin(theta / 2.0); const MantidVec &xIn = inOutWS->readX(i); MantidVec &yIn = inOutWS->dataY(i); const size_t xLength = xIn.size(); // for each wavelenght bin of each pixel calculate a q-resolution for (size_t j = 0; j < xLength - 1; j++) { // use the midpoint of each bin const double wl = (xIn[j + 1] + xIn[j]) / 2.0; // Calculate q. Alternatively q could be calculated using ConvertUnit const double q = factor / wl; // wavelenght spread from bin assumed to be const double sigmaSpreadFromBin = xIn[j + 1] - xIn[j]; // wavelenght spread from moderatorm, converted from microseconds to // wavelengths const double sigmaModerator = lookUpTable.value(wl) * 3.9560 / (1000.0 * Lsum); // calculate wavelenght resolution from moderator and histogram time bin const double sigmaLambda = std::sqrt(sigmaSpreadFromBin * sigmaSpreadFromBin / 12.0 + sigmaModerator * sigmaModerator); // calculate sigmaQ for a given lambda and pixel const double sigmaOverLambdaTimesQ = q * sigmaLambda / wl; const double sigmaQ = std::sqrt( dTheta2 / (wl * wl) + sigmaOverLambdaTimesQ * sigmaOverLambdaTimesQ); // update inout workspace with this sigmaQ yIn[j] = sigmaQ; } progress.report("Computing Q resolution"); } }
/** Executes the algorithm. Reading in the file and creating and populating * the output workspace * * @throw std::runtime_error If the instrument cannot be loaded by the LoadInstrument ChildAlgorithm * @throw InstrumentDefinitionError Thrown if issues with the content of XML instrument file not covered by LoadInstrument * @throw std::invalid_argument If the optional properties are set to invalid values */ void LoadEmptyInstrument::exec() { // Get other properties const double detector_value = getProperty("DetectorValue"); const double monitor_value = getProperty("MonitorValue"); // load the instrument into this workspace MatrixWorkspace_sptr ws = this->runLoadInstrument(); Instrument_const_sptr instrument = ws->getInstrument(); // Get number of detectors stored in instrument const size_t number_spectra = instrument->getNumberDetectors(); // Check that we have some spectra for the workspace if( number_spectra == 0){ g_log.error("Instrument has no detectors, unable to create workspace for it"); throw Kernel::Exception::InstrumentDefinitionError("No detectors found in instrument"); } bool MakeEventWorkspace = getProperty("MakeEventWorkspace"); MatrixWorkspace_sptr outWS; if (MakeEventWorkspace) { //Make a brand new EventWorkspace EventWorkspace_sptr localWorkspace = boost::dynamic_pointer_cast<EventWorkspace>( API::WorkspaceFactory::Instance().create("EventWorkspace", number_spectra, 2, 1)); //Copy geometry over. API::WorkspaceFactory::Instance().initializeFromParent(ws, localWorkspace, true); // Cast to matrix WS outWS = boost::dynamic_pointer_cast<MatrixWorkspace>(localWorkspace); } else { // Now create the outputworkspace and copy over the instrument object DataObjects::Workspace2D_sptr localWorkspace = boost::dynamic_pointer_cast<DataObjects::Workspace2D>(WorkspaceFactory::Instance().create(ws,number_spectra,2,1)); outWS = boost::dynamic_pointer_cast<MatrixWorkspace>(localWorkspace); } outWS->rebuildSpectraMapping( true /* include monitors */); // ---- Set the values ---------- if (!MakeEventWorkspace) { MantidVecPtr x,v,v_monitor; x.access().resize(2); x.access()[0]=1.0; x.access()[1]=2.0; v.access().resize(1); v.access()[0]=detector_value; v_monitor.access().resize(1); v_monitor.access()[0]=monitor_value; for (size_t i=0; i < outWS->getNumberHistograms(); i++) { IDetector_const_sptr det = outWS->getDetector(i); if ( det->isMonitor() ) outWS->setData(i, v_monitor, v_monitor); else outWS->setData(i, v, v); } } // Save in output this->setProperty("OutputWorkspace", outWS); }
/** * Execute the algorithm. */ void SofQW3::exec() { MatrixWorkspace_sptr inputWS = getProperty("InputWorkspace"); // Do the full check for common binning if( !WorkspaceHelpers::commonBoundaries(inputWS) ) { throw std::invalid_argument("The input workspace must have common binning across all spectra"); } RebinnedOutput_sptr outputWS = this->setUpOutputWorkspace(inputWS, getProperty("QAxisBinning"), m_Qout); g_log.debug() << "Workspace type: " << outputWS->id() << std::endl; setProperty("OutputWorkspace", outputWS); const size_t nEnergyBins = inputWS->blocksize(); const size_t nHistos = inputWS->getNumberHistograms(); // Progress reports & cancellation const size_t nreports(nHistos * nEnergyBins); m_progress = boost::shared_ptr<API::Progress>(new API::Progress(this, 0.0, 1.0, nreports)); // Compute input caches this->initCachedValues(inputWS); std::vector<double> par = inputWS->getInstrument()->getNumberParameter("detector-neighbour-offset"); if (par.empty()) { // Index theta cache this->initThetaCache(inputWS); } else { g_log.debug() << "Offset: " << par[0] << std::endl; this->m_detNeighbourOffset = static_cast<int>(par[0]); this->getValuesAndWidths(inputWS); } const MantidVec & X = inputWS->readX(0); PARALLEL_FOR2(inputWS, outputWS) for (int64_t i = 0; i < static_cast<int64_t>(nHistos); ++i) // signed for openmp { PARALLEL_START_INTERUPT_REGION DetConstPtr detector = inputWS->getDetector(i); if (detector->isMasked() || detector->isMonitor()) { continue; } double theta = this->m_theta[i]; double phi = 0.0; double thetaWidth = 0.0; double phiWidth = 0.0; // Non-PSD mode if (par.empty()) { thetaWidth = this->m_thetaWidth; } // PSD mode else { phi = this->m_phi[i]; thetaWidth = this->m_thetaWidths[i]; phiWidth = this->m_phiWidths[i]; } double thetaHalfWidth = 0.5 * thetaWidth; double phiHalfWidth = 0.5 * phiWidth; const double thetaLower = theta - thetaHalfWidth; const double thetaUpper = theta + thetaHalfWidth; const double phiLower = phi - phiHalfWidth; const double phiUpper = phi + phiHalfWidth; const double efixed = this->getEFixed(detector); for(size_t j = 0; j < nEnergyBins; ++j) { m_progress->report("Computing polygon intersections"); // For each input polygon test where it intersects with // the output grid and assign the appropriate weights of Y/E const double dE_j = X[j]; const double dE_jp1 = X[j+1]; const V2D ll(dE_j, this->calculateQ(efixed, dE_j, thetaLower, phiLower)); const V2D lr(dE_jp1, this->calculateQ(efixed, dE_jp1, thetaLower, phiLower)); const V2D ur(dE_jp1, this->calculateQ(efixed, dE_jp1, thetaUpper, phiUpper)); const V2D ul(dE_j, this->calculateQ(efixed, dE_j, thetaUpper, phiUpper)); Quadrilateral inputQ = Quadrilateral(ll, lr, ur, ul); this->rebinToFractionalOutput(inputQ, inputWS, i, j, outputWS, m_Qout); } PARALLEL_END_INTERUPT_REGION } PARALLEL_CHECK_INTERUPT_REGION outputWS->finalize(); this->normaliseOutput(outputWS, inputWS); }
/** Execute the algorithm. */ void EditInstrumentGeometry::exec() { // Lots of things have to do with the input workspace MatrixWorkspace_sptr workspace = getProperty("Workspace"); Geometry::Instrument_const_sptr originstrument = workspace->getInstrument(); // Get and check the primary flight path double l1 = this->getProperty("PrimaryFlightPath"); if (isEmpty(l1)) { // Use the original L1 if (!originstrument) { std::string errmsg( "It is not supported that L1 is not given, ", "while there is no instrument associated to input workspace."); g_log.error(errmsg); throw std::runtime_error(errmsg); } Geometry::IComponent_const_sptr source = originstrument->getSource(); Geometry::IComponent_const_sptr sample = originstrument->getSample(); l1 = source->getDistance(*sample); g_log.information() << "Retrieve L1 from input data workspace. \n"; } g_log.information() << "Using L1 = " << l1 << "\n"; // Get spectra number in case they are in a funny order std::vector<int32_t> specids = this->getProperty("SpectrumIDs"); if (specids.empty()) // they are using the order of the input workspace { size_t numHist = workspace->getNumberHistograms(); for (size_t i = 0; i < numHist; ++i) { specids.push_back(workspace->getSpectrum(i).getSpectrumNo()); g_log.information() << "Add spectrum " << workspace->getSpectrum(i).getSpectrumNo() << ".\n"; } } // Get the detector ids - empsy means ignore it const vector<int> vec_detids = getProperty("DetectorIDs"); const bool renameDetID(!vec_detids.empty()); // Get individual detector geometries ordered by input spectrum Numbers const std::vector<double> l2s = this->getProperty("L2"); const std::vector<double> tths = this->getProperty("Polar"); std::vector<double> phis = this->getProperty("Azimuthal"); // empty list of L2 and 2-theta is not allowed if (l2s.empty()) { throw std::runtime_error("User must specify L2 for all spectra. "); } if (tths.empty()) { throw std::runtime_error("User must specify 2theta for all spectra."); } // empty list of phi means that they are all zero if (phis.empty()) { phis.assign(l2s.size(), 0.); } // Validate for (size_t ib = 0; ib < l2s.size(); ib++) { g_log.information() << "Detector " << specids[ib] << " L2 = " << l2s[ib] << " 2Theta = " << tths[ib] << '\n'; if (specids[ib] < 0) { // Invalid spectrum Number : less than 0. stringstream errmsgss; errmsgss << "Detector ID = " << specids[ib] << " cannot be less than 0."; throw std::invalid_argument(errmsgss.str()); } if (l2s[ib] <= 0.0) { throw std::invalid_argument("L2 cannot be less or equal to 0"); } } // Keep original instrument and set the new instrument, if necessary const auto spec2indexmap = workspace->getSpectrumToWorkspaceIndexMap(); // ??? Condition: spectrum has 1 and only 1 detector size_t nspec = workspace->getNumberHistograms(); // Initialize another set of L2/2-theta/Phi/DetectorIDs vector ordered by // workspace index std::vector<double> storL2s(nspec, 0.); std::vector<double> stor2Thetas(nspec, 0.); std::vector<double> storPhis(nspec, 0.); vector<int> storDetIDs(nspec, 0); // Map the properties from spectrum Number to workspace index for (size_t i = 0; i < specids.size(); i++) { // Find spectrum's workspace index auto it = spec2indexmap.find(specids[i]); if (it == spec2indexmap.end()) { stringstream errss; errss << "Spectrum Number " << specids[i] << " is not found. " << "Instrument won't be edited for this spectrum. \n"; g_log.error(errss.str()); throw std::runtime_error(errss.str()); } // Store and set value size_t workspaceindex = it->second; storL2s[workspaceindex] = l2s[i]; stor2Thetas[workspaceindex] = tths[i]; storPhis[workspaceindex] = phis[i]; if (renameDetID) storDetIDs[workspaceindex] = vec_detids[i]; g_log.debug() << "workspace index = " << workspaceindex << " is for Spectrum " << specids[i] << '\n'; } // Generate a new instrument // Name of the new instrument std::string name = std::string(getProperty("InstrumentName")); if (name.empty()) { // Use the original L1 if (!originstrument) { std::string errmsg( "It is not supported that InstrumentName is not given, ", "while there is no instrument associated to input workspace."); g_log.error(errmsg); throw std::runtime_error(errmsg); } name = originstrument->getName(); } // Create a new instrument from scratch any way. auto instrument = boost::make_shared<Geometry::Instrument>(name); if (!bool(instrument)) { stringstream errss; errss << "Trying to use a Parametrized Instrument as an Instrument."; g_log.error(errss.str()); throw std::runtime_error(errss.str()); } // Set up source and sample information Geometry::ObjComponent *samplepos = new Geometry::ObjComponent("Sample", instrument.get()); instrument->add(samplepos); instrument->markAsSamplePos(samplepos); samplepos->setPos(0.0, 0.0, 0.0); Geometry::ObjComponent *source = new Geometry::ObjComponent("Source", instrument.get()); instrument->add(source); instrument->markAsSource(source); source->setPos(0.0, 0.0, -1.0 * l1); // Add/copy detector information auto indexInfo = workspace->indexInfo(); std::vector<detid_t> detIDs; for (size_t i = 0; i < workspace->getNumberHistograms(); i++) { // Create a new detector. // (Instrument will take ownership of pointer so no need to delete.) detid_t newdetid; if (renameDetID) newdetid = storDetIDs[i]; else newdetid = detid_t(i) + 100; Geometry::Detector *detector = new Geometry::Detector("det", newdetid, samplepos); // Set up new detector parameters related to new instrument double l2 = storL2s[i]; double tth = stor2Thetas[i]; double phi = storPhis[i]; Kernel::V3D pos; pos.spherical(l2, tth, phi); detector->setPos(pos); // Add new detector to spectrum and instrument // Good and do some debug output g_log.debug() << "Orignal spectrum " << indexInfo.spectrumNumber(i) << "has " << indexInfo.detectorIDs(i).size() << " detectors. \n"; detIDs.push_back(newdetid); instrument->add(detector); instrument->markAsDetector(detector); } // ENDFOR workspace index indexInfo.setDetectorIDs(std::move(detIDs)); workspace->setIndexInfo(indexInfo); // Add the new instrument workspace->setInstrument(instrument); }
void Iqt::plotInput(const QString& wsname) { MatrixWorkspace_sptr workspace; try { workspace = Mantid::API::AnalysisDataService::Instance().retrieveWS<MatrixWorkspace>(wsname.toStdString()); } catch(Mantid::Kernel::Exception::NotFoundError&) { showMessageBox(QString("Unable to retrieve workspace: " + wsname)); return; } m_uiForm.ppPlot->clear(); m_uiForm.ppPlot->addSpectrum("Sample", workspace, 0); auto xRangeSelector = m_uiForm.ppPlot->getRangeSelector("FuryRange"); try { QPair<double, double> range = m_uiForm.ppPlot->getCurveRange("Sample"); double rounded_min(range.first); double rounded_max(range.second); const std::string instrName(workspace->getInstrument()->getName()); if(instrName == "BASIS") { xRangeSelector->setRange(range.first, range.second); m_dblManager->setValue(m_properties["ELow"], rounded_min); m_dblManager->setValue(m_properties["EHigh"], rounded_max); m_dblManager->setValue(m_properties["EWidth"], 0.0004); m_dblManager->setValue(m_properties["SampleBinning"], 1); } else { rounded_min = floor(rounded_min * 10 + 0.5) / 10.0; rounded_max = floor(rounded_max * 10 + 0.5) / 10.0; //corrections for if nearest value is outside of range if (rounded_max > range.second) { rounded_max -= 0.1; } if(rounded_min < range.first) { rounded_min += 0.1; } //check incase we have a really small range if (fabs(rounded_min) > 0 && fabs(rounded_max) > 0) { xRangeSelector->setRange(rounded_min, rounded_max); m_dblManager->setValue(m_properties["ELow"], rounded_min); m_dblManager->setValue(m_properties["EHigh"], rounded_max); } else { xRangeSelector->setRange(range.first, range.second); m_dblManager->setValue(m_properties["ELow"], range.first); m_dblManager->setValue(m_properties["EHigh"], range.second); } //set default value for width m_dblManager->setValue(m_properties["EWidth"], 0.005); } } catch(std::invalid_argument & exc) { showMessageBox(exc.what()); } calculateBinning(); }