/** * Execute the algorithm. */ void LoadSassena::exec() { // auto // gws=boost::dynamic_pointer_cast<API::WorkspaceGroup>(getProperty("OutputWorkspace")); // API::WorkspaceGroup_sptr gws=getProperty("OutputWorkspace"); API::Workspace_sptr ows = getProperty("OutputWorkspace"); API::WorkspaceGroup_sptr gws = boost::dynamic_pointer_cast<API::WorkspaceGroup>(ows); if (gws && API::AnalysisDataService::Instance().doesExist(gws->name())) { // gws->deepRemoveAll(); // remove workspace members API::AnalysisDataService::Instance().deepRemoveGroup(gws->name()); } else { gws = boost::make_shared<API::WorkspaceGroup>(); setProperty("OutputWorkspace", boost::dynamic_pointer_cast<API::Workspace>(gws)); } // populate m_validSets int nvalidSets = 4; const char *validSets[] = {"fq", "fq0", "fq2", "fqt"}; for (int iSet = 0; iSet < nvalidSets; iSet++) this->m_validSets.push_back(validSets[iSet]); // open the HDF5 file for reading m_filename = this->getPropertyValue("Filename"); hid_t h5file = H5Fopen(m_filename.c_str(), H5F_ACC_RDONLY, H5P_DEFAULT); if (h5file < 0) { this->g_log.error("Cannot open " + m_filename); throw Kernel::Exception::FileError("Unable to open:", m_filename); } // find out the sassena version used char cversion[16]; if (H5LTget_attribute_string(h5file, "/", "sassena_version", cversion) < 0) { this->g_log.error("Unable to read Sassena version"); } // const std::string version(cversion); // determine which loader protocol to use based on the version // to be done at a later time, maybe implement a Version class std::vector<int> sorting_indexes; const MantidVec qvmod = this->loadQvectors(h5file, gws, sorting_indexes); // iterate over the valid sets std::string setName; for (std::vector<std::string>::const_iterator it = this->m_validSets.begin(); it != this->m_validSets.end(); ++it) { setName = *it; if (H5LTfind_dataset(h5file, setName.c_str()) == 1) { if (setName == "fq" || setName == "fq0" || setName == "fq2") this->loadFQ(h5file, gws, setName, qvmod, sorting_indexes); else if (setName == "fqt") this->loadFQT(h5file, gws, setName, qvmod, sorting_indexes); } else this->g_log.information("Dataset " + setName + " not present in file"); } // end of iterate over the valid sets H5Fclose(h5file); } // end of LoadSassena::exec()
/** * Create the output workspace group. * @param baseName :: The base name for the output workspace. Suffix "Workspace" * will be added to it. * @param function :: A function to calculate the values. Must be of the * MultiDomainFunction type. * @param domain :: Domain created earlier with this creator (unused) * @param values :: Values created earlier with this creator (unused) * @param outputWorkspacePropertyName :: Name for the property to hold the * output workspace. If * empty the property won't be created. * @return A shared pointer to the created workspace. */ boost::shared_ptr<API::Workspace> MultiDomainCreator::createOutputWorkspace( const std::string &baseName, API::IFunction_sptr function, boost::shared_ptr<API::FunctionDomain> domain, boost::shared_ptr<API::FunctionValues> values, const std::string &outputWorkspacePropertyName) { UNUSED_ARG(domain); UNUSED_ARG(values); auto mdFunction = boost::dynamic_pointer_cast<API::MultiDomainFunction>(function); if (!mdFunction) { throw std::runtime_error("A MultiDomainFunction is expected to be used " "with MultiDomainCreator."); } // split the function into independent parts std::vector<API::IFunction_sptr> functions = mdFunction->createEquivalentFunctions(); // there must be as many parts as there are domains if (functions.size() != m_creators.size()) { throw std::runtime_error("Number of functions and domains don't match"); } API::WorkspaceGroup_sptr outWS = API::WorkspaceGroup_sptr(new API::WorkspaceGroup()); for (size_t i = 0; i < functions.size(); ++i) { std::string localName = baseName + "Workspace_" + boost::lexical_cast<std::string>(i); auto fun = functions[i]; auto creator = m_creators[i]; boost::shared_ptr<API::FunctionDomain> localDomain; boost::shared_ptr<API::FunctionValues> localValues; fun->setUpForFit(); creator->createDomain(localDomain, localValues); creator->initFunction(fun); auto ws = creator->createOutputWorkspace(localName, fun, localDomain, localValues, ""); API::AnalysisDataService::Instance().addOrReplace(localName, ws); outWS->addWorkspace(ws); } if (!outputWorkspacePropertyName.empty()) { declareProperty( new API::WorkspaceProperty<API::WorkspaceGroup>( outputWorkspacePropertyName, "", Kernel::Direction::Output), "Name of the output Workspace holding resulting simulated spectrum"); m_manager->setPropertyValue(outputWorkspacePropertyName, baseName + "Workspaces"); m_manager->setProperty(outputWorkspacePropertyName, outWS); } return outWS; }
/** * Register a workspace in the Analysis Data Service and add it to the * groupWorkspace * @param gws pointer to WorkspaceGroup being filled * @param wsName name of workspace to be added and registered * @param ws pointer to workspace to be added and registered * @param description */ void LoadSassena::registerWorkspace(API::WorkspaceGroup_sptr gws, const std::string wsName, DataObjects::Workspace2D_sptr ws, const std::string &description) { UNUSED_ARG(description); API::AnalysisDataService::Instance().add(wsName, ws); gws->addWorkspace(ws); }
/** Fits each spectrum in the workspace to f(x) = A * sin( w * x + p) * @param ws :: [input] The workspace to fit * @param freq :: [input] Hint for the frequency (w) * @param groupName :: [input] The name of the output workspace group * @param resTab :: [output] Table workspace storing the asymmetries and phases * @param resGroup :: [output] Workspace group storing the fitting results */ void CalMuonDetectorPhases::fitWorkspace(const API::MatrixWorkspace_sptr &ws, double freq, std::string groupName, API::ITableWorkspace_sptr &resTab, API::WorkspaceGroup_sptr &resGroup) { int nhist = static_cast<int>(ws->getNumberHistograms()); // Create the fitting function f(x) = A * sin ( w * x + p ) // The same function and initial parameters are used for each fit std::string funcStr = createFittingFunction(freq, true); // Set up results table resTab->addColumn("int", "Spectrum number"); resTab->addColumn("double", "Asymmetry"); resTab->addColumn("double", "Phase"); // Loop through fitting all spectra individually const static std::string success = "success"; for (int wsIndex = 0; wsIndex < nhist; wsIndex++) { reportProgress(wsIndex, nhist); auto fit = createChildAlgorithm("Fit"); fit->initialize(); fit->setPropertyValue("Function", funcStr); fit->setProperty("InputWorkspace", ws); fit->setProperty("WorkspaceIndex", wsIndex); fit->setProperty("CreateOutput", true); fit->setPropertyValue("Output", groupName); fit->execute(); std::string status = fit->getProperty("OutputStatus"); if (!fit->isExecuted() || status != success) { std::ostringstream error; error << "Fit failed for spectrum at workspace index " << wsIndex; error << ": " << status; throw std::runtime_error(error.str()); } API::MatrixWorkspace_sptr fitOut = fit->getProperty("OutputWorkspace"); resGroup->addWorkspace(fitOut); API::ITableWorkspace_sptr tab = fit->getProperty("OutputParameters"); // Now we have our fitting results stored in tab // but we need to extract the relevant information, i.e. // the detector phases (parameter 'p') and asymmetries ('A') const auto &spectrum = ws->getSpectrum(static_cast<size_t>(wsIndex)); extractDetectorInfo(tab, resTab, spectrum.getSpectrumNo()); } }
void Load::loadMultipleFiles() { // allFilenames contains "rows" of filenames. If the row has more than 1 file // in it // then that row is to be summed across each file in the row const std::vector<std::vector<std::string>> allFilenames = getProperty("Filename"); std::string outputWsName = getProperty("OutputWorkspace"); std::vector<std::string> wsNames(allFilenames.size()); std::transform(allFilenames.begin(), allFilenames.end(), wsNames.begin(), generateWsNameFromFileNames); auto wsName = wsNames.cbegin(); assert(allFilenames.size() == wsNames.size()); std::vector<API::Workspace_sptr> loadedWsList; loadedWsList.reserve(allFilenames.size()); Workspace_sptr tempWs; // Cycle through the filenames and wsNames. for (auto filenames = allFilenames.cbegin(); filenames != allFilenames.cend(); ++filenames, ++wsName) { auto filename = filenames->cbegin(); Workspace_sptr sumWS = loadFileToWs(*filename, *wsName); ++filename; for (; filename != filenames->cend(); ++filename) { tempWs = loadFileToWs(*filename, "__@loadsum_temp@"); sumWS = plusWs(sumWS, tempWs); } API::WorkspaceGroup_sptr group = boost::dynamic_pointer_cast<WorkspaceGroup>(sumWS); if (group) { std::vector<std::string> childWsNames = group->getNames(); auto childWsName = childWsNames.begin(); size_t count = 1; for (; childWsName != childWsNames.end(); ++childWsName, ++count) { Workspace_sptr childWs = group->getItem(*childWsName); const std::string childName = group->getName() + "_" + std::to_string(count); API::AnalysisDataService::Instance().addOrReplace(childName, childWs); // childWs->setName(group->getName() + "_" + // boost::lexical_cast<std::string>(count)); } } // Add the sum to the list of loaded workspace names. loadedWsList.push_back(sumWS); } // If we only have one loaded ws, set it as the output. if (loadedWsList.size() == 1) { setProperty("OutputWorkspace", loadedWsList[0]); AnalysisDataService::Instance().rename(loadedWsList[0]->getName(), outputWsName); } // Else we have multiple loaded workspaces - group them and set the group as // output. else { API::WorkspaceGroup_sptr group = groupWsList(loadedWsList); setProperty("OutputWorkspace", group); std::vector<std::string> childWsNames = group->getNames(); size_t count = 1; for (auto &childWsName : childWsNames) { if (childWsName == outputWsName) { Mantid::API::Workspace_sptr child = group->getItem(childWsName); // child->setName(child->getName() + "_" + // boost::lexical_cast<std::string>(count)); const std::string childName = child->getName() + "_" + std::to_string(count); API::AnalysisDataService::Instance().addOrReplace(childName, child); count++; } } childWsNames = group->getNames(); count = 1; for (auto &childWsName : childWsNames) { Workspace_sptr childWs = group->getItem(childWsName); std::string outWsPropName = "OutputWorkspace_" + std::to_string(count); ++count; declareProperty(Kernel::make_unique<WorkspaceProperty<Workspace>>( outWsPropName, childWsName, Direction::Output)); setProperty(outWsPropName, childWs); } } // Clean up. if (tempWs) { Algorithm_sptr alg = AlgorithmManager::Instance().createUnmanaged("DeleteWorkspace"); alg->initialize(); alg->setChild(true); alg->setProperty("Workspace", tempWs); alg->execute(); } }
/** Fits each spectrum in the workspace to f(x) = A * sin( w * x + p) * @param ws :: [input] The workspace to fit * @param freq :: [input] Hint for the frequency (w) * @param groupName :: [input] The name of the output workspace group * @param resTab :: [output] Table workspace storing the asymmetries and phases * @param resGroup :: [output] Workspace group storing the fitting results */ void CalMuonDetectorPhases::fitWorkspace(const API::MatrixWorkspace_sptr &ws, double freq, std::string groupName, API::ITableWorkspace_sptr resTab, API::WorkspaceGroup_sptr &resGroup) { int nhist = static_cast<int>(ws->getNumberHistograms()); // Create the fitting function f(x) = A * sin ( w * x + p ) // The same function and initial parameters are used for each fit std::string funcStr = createFittingFunction(freq, true); // Set up results table resTab->addColumn("int", "Spectrum number"); resTab->addColumn("double", "Asymmetry"); resTab->addColumn("double", "Phase"); const auto &indexInfo = ws->indexInfo(); // Loop through fitting all spectra individually const static std::string success = "success"; for (int wsIndex = 0; wsIndex < nhist; wsIndex++) { reportProgress(wsIndex, nhist); const auto &yValues = ws->y(wsIndex); auto emptySpectrum = std::all_of(yValues.begin(), yValues.end(), [](double value) { return value == 0.; }); if (emptySpectrum) { g_log.warning("Spectrum " + std::to_string(wsIndex) + " is empty"); TableWorkspace_sptr tab = boost::make_shared<TableWorkspace>(); tab->addColumn("str", "Name"); tab->addColumn("double", "Value"); tab->addColumn("double", "Error"); for (int j = 0; j < 4; j++) { API::TableRow row = tab->appendRow(); if (j == PHASE_ROW) { row << "dummy" << 0.0 << 0.0; } else { row << "dummy" << ASYMM_ERROR << 0.0; } } extractDetectorInfo(*tab, *resTab, indexInfo.spectrumNumber(wsIndex)); } else { auto fit = createChildAlgorithm("Fit"); fit->initialize(); fit->setPropertyValue("Function", funcStr); fit->setProperty("InputWorkspace", ws); fit->setProperty("WorkspaceIndex", wsIndex); fit->setProperty("CreateOutput", true); fit->setPropertyValue("Output", groupName); fit->execute(); std::string status = fit->getProperty("OutputStatus"); if (!fit->isExecuted()) { std::ostringstream error; error << "Fit failed for spectrum at workspace index " << wsIndex; error << ": " << status; throw std::runtime_error(error.str()); } else if (status != success) { g_log.warning("Fit failed for spectrum at workspace index " + std::to_string(wsIndex) + ": " + status); } API::MatrixWorkspace_sptr fitOut = fit->getProperty("OutputWorkspace"); resGroup->addWorkspace(fitOut); API::ITableWorkspace_sptr tab = fit->getProperty("OutputParameters"); // Now we have our fitting results stored in tab // but we need to extract the relevant information, i.e. // the detector phases (parameter 'p') and asymmetries ('A') extractDetectorInfo(*tab, *resTab, indexInfo.spectrumNumber(wsIndex)); } } }
/// Create a list of input workspace names std::vector<PlotPeakByLogValue::InputData> PlotPeakByLogValue::makeNames()const { std::vector<InputData> nameList; std::string inputList = getPropertyValue("Input"); int default_wi = getProperty("WorkspaceIndex"); int default_spec = getProperty("Spectrum"); double start = 0; double end = 0; typedef Poco::StringTokenizer tokenizer; tokenizer names(inputList, ";", tokenizer::TOK_IGNORE_EMPTY | tokenizer::TOK_TRIM); for (tokenizer::Iterator it = names.begin(); it != names.end(); ++it) { tokenizer params(*it, ",", tokenizer::TOK_TRIM); std::string name = params[0]; int wi = default_wi; int spec = default_spec; if (params.count() > 1) { std::string index = params[1]; // spectrum or workspace index with a prefix if (index.size() > 2 && index.substr(0,2) == "sp") {// spectrum number spec = boost::lexical_cast<int>(index.substr(2)); wi = -1; // undefined yet } else if (index.size() > 1 && index[0] == 'i') {// workspace index wi = boost::lexical_cast<int>(index.substr(1)); spec = -1; // undefined yet } else if (index.size() > 0 && index[0] == 'v') { if (index.size() > 1) {// there is some text after 'v' tokenizer range(index.substr(1), ":", tokenizer::TOK_IGNORE_EMPTY | tokenizer::TOK_TRIM); if (range.count() < 1) { wi = -2; // means use the whole range } else if (range.count() == 1) { start = boost::lexical_cast<double>(range[0]); end = start; wi = -1; spec = -1; } else if (range.count() > 1) { start = boost::lexical_cast<double>(range[0]); end = boost::lexical_cast<double>(range[1]); if (start > end) std::swap(start,end); wi = -1; spec = -1; } } else { wi = -2; } } else {// error //throw std::invalid_argument("Malformed spectrum identifier ("+index+"). " // "It must be either \"sp\" followed by a number for a spectrum number or" // "\"i\" followed by a number for a workspace index."); wi = default_wi; } } int period = (params.count() > 2)? boost::lexical_cast<int>(params[2]) : 1; if (API::AnalysisDataService::Instance().doesExist(name)) { API::Workspace_sptr ws = API::AnalysisDataService::Instance().retrieve(name); API::WorkspaceGroup_sptr wsg = boost::dynamic_pointer_cast<API::WorkspaceGroup>(ws); if (wsg) { std::vector<std::string> wsNames = wsg->getNames(); for(std::vector<std::string>::iterator i=wsNames.begin();i!=wsNames.end();++i) { nameList.push_back(InputData(*i,wi,-1,period,start,end)); } continue; } } nameList.push_back(InputData(name,wi,spec,period,start,end)); } return nameList; }
/** Get a workspace identified by an InputData structure. * @param data :: InputData with name and either spec or i fields defined. * @return InputData structure with the ws field set if everything was OK. */ PlotPeakByLogValue::InputData PlotPeakByLogValue::getWorkspace(const InputData& data) { InputData out(data); if (API::AnalysisDataService::Instance().doesExist(data.name)) { DataObjects::Workspace2D_sptr ws = boost::dynamic_pointer_cast<DataObjects::Workspace2D>( API::AnalysisDataService::Instance().retrieve(data.name)); if (ws) { out.ws = ws; } else { return data; } } else { std::ifstream fil(data.name.c_str()); if (!fil) { g_log.warning() << "File "<<data.name<<" does not exist\n"; return data; } fil.close(); std::string::size_type i = data.name.find_last_of('.'); if (i == std::string::npos) { g_log.warning() << "Cannot open file "<<data.name<<"\n"; return data; } std::string ext = data.name.substr(i); try { API::IAlgorithm_sptr load = createSubAlgorithm("Load"); load->initialize(); load->setPropertyValue("FileName",data.name); load->execute(); if (load->isExecuted()) { API::Workspace_sptr rws = load->getProperty("OutputWorkspace"); if (rws) { DataObjects::Workspace2D_sptr ws = boost::dynamic_pointer_cast<DataObjects::Workspace2D>(rws); if (ws) { out.ws = ws; } else { API::WorkspaceGroup_sptr gws = boost::dynamic_pointer_cast<API::WorkspaceGroup>(rws); if (gws) { std::vector<std::string> wsNames = gws->getNames(); std::string propName = "OUTPUTWORKSPACE_" + boost::lexical_cast<std::string>(data.period); if (load->existsProperty(propName)) { Workspace_sptr rws1 = load->getProperty(propName); out.ws = boost::dynamic_pointer_cast<DataObjects::Workspace2D>(rws1); } } } } } } catch(std::exception& e) { g_log.error(e.what()); return data; } } if (!out.ws) return data; API::Axis* axis = out.ws->getAxis(1); if (axis->isSpectra()) {// spectra axis if (out.spec < 0) { if (out.i >= 0) { out.spec = axis->spectraNo(out.i); } else {// i < 0 && spec < 0 => use start and end for(size_t i=0;i<axis->length();++i) { double s = double(axis->spectraNo(i)); if (s >= out.start && s <= out.end) { out.indx.push_back(static_cast<int>(i)); } } } } else { for(size_t i=0;i<axis->length();++i) { int j = axis->spectraNo(i); if (j == out.spec) { out.i = static_cast<int>(i); break; } } } if (out.i < 0 && out.indx.empty()) { return data; } } else {// numeric axis out.spec = -1; if (out.i >= 0) { out.indx.clear(); } else { if (out.i < -1) { out.start = (*axis)(0); out.end = (*axis)(axis->length()-1); } for(size_t i=0;i<axis->length();++i) { double s = (*axis)(i); if (s >= out.start && s <= out.end) { out.indx.push_back(static_cast<int>(i)); } } } } return out; }
/// Execute the algorithm void SassenaFFT::exec() { const std::string gwsName = this->getPropertyValue("InputWorkspace"); API::WorkspaceGroup_sptr gws = this->getProperty("InputWorkspace"); const std::string ftqReName = gwsName + "_fqt.Re"; const std::string ftqImName = gwsName + "_fqt.Im"; // Make sure the intermediate structure factor is there if(!gws->contains(ftqReName) ) { const std::string errMessg = "workspace "+gwsName+" does not contain an intermediate structure factor"; this->g_log.error(errMessg); throw Kernel::Exception::NotFoundError("group workspace does not contain",ftqReName); } // Retrieve the real and imaginary parts of the intermediate scattering function DataObjects::Workspace2D_sptr fqtRe = boost::dynamic_pointer_cast<DataObjects::Workspace2D>( gws->getItem( ftqReName ) ); DataObjects::Workspace2D_sptr fqtIm = boost::dynamic_pointer_cast<DataObjects::Workspace2D>( gws->getItem( ftqImName ) ); // Calculate the FFT for all spectra, retaining only the real part since F(q,-t) = F*(q,t) int part=3; // extract the real part of the transform, assuming I(Q,t) is real const std::string sqwName = gwsName + "_sqw"; API::IAlgorithm_sptr fft = this->createChildAlgorithm("ExtractFFTSpectrum"); fft->setProperty<DataObjects::Workspace2D_sptr>("InputWorkspace", fqtRe); if( !this->getProperty("FFTonlyRealPart") ) { part=0; // extract the real part of the transform, assuming I(Q,t) is complex fft->setProperty<DataObjects::Workspace2D_sptr>("InputImagWorkspace", fqtIm); } fft->setPropertyValue("OutputWorkspace", sqwName ); fft->setProperty<int>("FFTPart",part); // extract the real part fft->executeAsChildAlg(); API::MatrixWorkspace_sptr sqw0 = fft->getProperty("OutputWorkspace"); DataObjects::Workspace2D_sptr sqw = boost::dynamic_pointer_cast<DataObjects::Workspace2D>( sqw0 ); API::AnalysisDataService::Instance().addOrReplace( sqwName, sqw ); // Transform the X-axis to appropriate dimensions // We assume the units of the intermediate scattering function are in picoseconds // The resulting frequency unit is in mili-eV, thus use m_ps2meV API::IAlgorithm_sptr scaleX = this->createChildAlgorithm("ScaleX"); scaleX->setProperty<DataObjects::Workspace2D_sptr>("InputWorkspace",sqw); scaleX->setProperty<double>("Factor", m_ps2meV); scaleX->setProperty<DataObjects::Workspace2D_sptr>("OutputWorkspace", sqw); scaleX->executeAsChildAlg(); //Do we apply the detailed balance condition exp(E/(2*kT)) ? if( this->getProperty("DetailedBalance") ) { double T = this->getProperty("Temp"); // The ExponentialCorrection algorithm assumes the form C0*exp(-C1*x). Note the explicit minus in the exponent API::IAlgorithm_sptr ec = this->createChildAlgorithm("ExponentialCorrection"); ec->setProperty<DataObjects::Workspace2D_sptr>("InputWorkspace", sqw); ec->setProperty<DataObjects::Workspace2D_sptr>("OutputWorkspace", sqw); ec->setProperty<double>("C0",1.0); ec->setProperty<double>("C1",-1.0/(2.0*T*m_T2ueV)); // Temperature in units of ueV ec->setPropertyValue("Operation","Multiply"); ec->executeAsChildAlg(); } // Set the Energy unit for the X-axis sqw->getAxis(0)->unit() = Kernel::UnitFactory::Instance().create("DeltaE"); // Add to group workspace, except if we are replacing the workspace. In this case, the group workspace // is already notified of the changes by the analysis data service. if(!gws->contains(sqwName)) { gws->add( sqwName ); } else { this->g_log.information("Workspace "+sqwName+" replaced with new contents"); } }