Mantid
Loading...
Searching...
No Matches
CrystalFieldControl.cpp
Go to the documentation of this file.
1// Mantid Repository : https://github.com/mantidproject/mantid
2//
3// Copyright © 2018 ISIS Rutherford Appleton Laboratory UKRI,
4// NScD Oak Ridge National Laboratory, European Spallation Source,
5// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
6// SPDX - License - Identifier: GPL - 3.0 +
12
14
15using namespace API;
16
18 const bool quotedString = true;
19 // A comma-separated list of ion names
20 declareAttribute("Ions", Attribute("", quotedString));
21 // A comma-separated list of symmetry names
22 declareAttribute("Symmetries", Attribute("", quotedString));
23 // Temperature values for each spectrum.
24 declareAttribute("Temperatures", Attribute(std::vector<double>()));
25 // Default widths for peaks in each spectrum. If given it must have
26 // the same size as Temperatures or size == 1 in which case it's used
27 // for all spectra.
28 declareAttribute("FWHMs", Attribute(std::vector<double>()));
29 // Variation in FWHM of peaks when with model is used (FWHMX and FWHMY)
30 declareAttribute("FWHMVariation", Attribute(0.1));
31 // Definition of the background function
32 declareAttribute("Background", Attribute("", quotedString));
33 // Name of a IPeakFunction to use for peaks
34 declareAttribute("PeakShape", Attribute("Lorentzian"));
35 // Energy tolerance in crystal field calculations
36 declareAttribute("ToleranceEnergy", Attribute(1.0e-10));
37 // Intensity tolerance in crystal field calculations
38 declareAttribute("ToleranceIntensity", Attribute(1.0e-1));
39 // A comma-separated list of physical properties
40 declareAttribute("PhysicalProperties", Attribute(""));
41 declareAttribute("NPeaks", Attribute(0));
42 declareAttribute("FixAllPeaks", Attribute(false));
43}
44
46void CrystalFieldControl::setAttribute(const std::string &name, const API::IFunction::Attribute &attr) {
47 if (name == "Ions") {
49 } else if (name == "Symmetries") {
51 } else if (name == "PhysicalProperties") {
52 parseStringListAttribute("PhysicalProperties", attr.asString(), m_physProps);
54 } else {
55 if (name == "Temperatures") {
56 m_temperatures = attr.asVector();
58 } else if (name == "FWHMs") {
59 const size_t nSpec = m_temperatures.size();
60 m_FWHMs = attr.asVector();
61 auto frontValue = m_FWHMs.front();
62 if (m_FWHMs.size() == 1 && m_FWHMs.size() != nSpec) {
63 m_FWHMs.assign(nSpec, frontValue);
64 }
65 if (!m_FWHMs.empty()) {
66 m_fwhmX.resize(nSpec);
67 m_fwhmY.resize(nSpec);
68 for (size_t i = 0; i < nSpec; ++i) {
69 m_fwhmX[i].clear();
70 m_fwhmY[i].clear();
71 if (nSpec > 1) {
72 auto &control = *getFunction(i);
73 control.setAttributeValue("FWHMX", std::vector<double>());
74 control.setAttributeValue("FWHMY", std::vector<double>());
75 } else {
76 API::IFunction::setAttributeValue("FWHMX", std::vector<double>());
77 API::IFunction::setAttributeValue("FWHMY", std::vector<double>());
78 }
79 }
80 }
81 } else if ((name.compare(0, 5, "FWHMX") == 0 || name.compare(0, 5, "FWHMY") == 0) && !attr.asVector().empty()) {
82 m_FWHMs.clear();
83 }
85 }
86}
87
92void CrystalFieldControl::parseStringListAttribute(const std::string &attName, const std::string &value,
93 std::vector<std::string> &cache) {
94 // Split the attribute value into separate names, white spaces removed
96 cache.clear();
97 cache.insert(cache.end(), tokenizer.begin(), tokenizer.end());
98 auto attrValue = Kernel::Strings::join(cache.begin(), cache.end(), ",");
99 // Store back the trimmed names - we can't use setAttributeValue as it will
100 // call this setAttribute
101 auto attrCopy = getAttribute(attName);
102 attrCopy.setString(attrValue);
103 API::IFunction::setAttribute(attName, attrCopy);
104}
105
108 const auto nSpec = m_temperatures.size();
109 m_fwhmX.clear();
110 m_fwhmY.clear();
111 if (nSpec == 1) {
112 auto fwhmX = getAttribute("FWHMX").asVector();
113 auto fwhmY = getAttribute("FWHMY").asVector();
114 m_fwhmX.emplace_back(fwhmX);
115 m_fwhmY.emplace_back(fwhmY);
116 } else {
117 for (size_t i = 0; i < nSpec; ++i) {
118 auto &control = *getFunction(i);
119 auto fwhmX = control.getAttribute("FWHMX").asVector();
120 auto fwhmY = control.getAttribute("FWHMY").asVector();
121 m_fwhmX.emplace_back(fwhmX);
122 m_fwhmY.emplace_back(fwhmY);
123 }
124 }
125}
126
129 if (m_ions.empty()) {
130 throw std::runtime_error("No ions are set.");
131 }
132 if (m_ions.size() != m_symmetries.size()) {
133 throw std::runtime_error("Number of ions is different from number of symmetries.");
134 }
135 if (!m_temperatures.empty()) {
136 // If temperatures are given then there will be spectra with peaks
137 // and peaks need some width information. It comes either from
138 // FWHMs attribute or FWHMX and FWHMY attributes of the spectrum
139 // control functions.
140 const auto nSpec = m_temperatures.size();
141 if (nSpec > 1 && nSpec > nFunctions()) {
142 // Some of the member control funtions must be spectra
143 throw std::logic_error("Too few spectrum functions.");
144 }
145 // Check if the FWHMX and FWHMY attributes of the spectrum
146 // control functions are set and if they are they have equal lengths
147 bool allXYEmpty = true;
148 bool someXYEmpty = false;
149 for (size_t i = 0; i < nSpec; ++i) {
150 if (nSpec > 1) {
151 auto specFun = getFunction(i).get();
152 if (!dynamic_cast<CrystalFieldSpectrumControl *>(specFun)) {
153 throw std::logic_error("CrystalFieldSpectrumControl function expected");
154 }
155 }
156 if (m_fwhmX[i].size() != m_fwhmY[i].size()) {
157 throw std::runtime_error("Vectors in each pair of (FWHMX, FWHMY) "
158 "attributes must have the same size");
159 }
160 someXYEmpty = someXYEmpty || m_fwhmX[i].empty() || m_fwhmY[i].empty();
161 allXYEmpty = allXYEmpty && m_fwhmX[i].empty() && m_fwhmY[i].empty();
162 }
163 if (m_FWHMs.empty()) {
164 if (allXYEmpty) {
165 // No width information given
166 throw std::runtime_error("No peak width settings (FWHMs and FWHMX and "
167 "FWHMY attributes not set).");
168 } else if (someXYEmpty) {
169 // If given they all must be given
170 throw std::runtime_error("FWHMX, FWHMY attributes are not given for all spectra.");
171 }
172 } else if (m_FWHMs.size() != nSpec) {
173 if (m_FWHMs.size() == 1) {
174 // If single value then use it for all spectra
175 m_FWHMs.assign(nSpec, m_FWHMs.front());
176 } else {
177 // Otherwise it's an error
178 throw std::runtime_error("Vector of FWHMs must either have same size as "
179 "Temperatures (" +
180 std::to_string(nSpec) + ") or have size 1.");
181 }
182 } else if (!allXYEmpty) {
183 // Conflicting width attributes
184 throw std::runtime_error("Either FWHMs or (FWHMX and FWHMY) can be set but not all.");
185 }
186 } else if (physProps().empty()) {
187 throw std::runtime_error("No temperatures are set.");
188 }
189}
190
191const std::vector<double> &CrystalFieldControl::temperatures() const { return m_temperatures; }
192
193const std::vector<double> &CrystalFieldControl::FWHMs() const { return m_FWHMs; }
194
195const std::vector<std::string> &CrystalFieldControl::physProps() const { return m_physProps; }
196
199 const auto nSpec = m_temperatures.size();
200 if (nSpec == 1) {
201 declareAttribute("FWHMX", Attribute(std::vector<double>()));
202 declareAttribute("FWHMY", Attribute(std::vector<double>()));
203 } else {
204 for (size_t i = 0; i < nSpec; ++i) {
206 }
207 }
208}
209
212 const auto nSpec = m_temperatures.size();
213 if (nSpec == 1) {
215 }
216}
217
220bool CrystalFieldControl::isMultiSite() const { return m_ions.size() > 1; }
221
222bool CrystalFieldControl::isMultiSpectrum() const { return m_temperatures.size() > 1 || !m_physProps.empty(); }
223
225bool CrystalFieldControl::hasPeaks() const { return !m_temperatures.empty(); }
226
229
234 if (isMultiSite()) {
235 return buildMultiSite();
236 } else {
237 return buildSingleSite();
238 }
239}
240
243 if (isMultiSpectrum()) {
245 } else {
247 }
248}
249
252 if (isMultiSpectrum()) {
254 } else {
256 }
257}
258
261 if (m_temperatures.empty()) {
262 throw std::runtime_error("No tmperature was set.");
263 }
264 auto source = IFunction_sptr(new CrystalFieldPeaks);
265 source->setAttributeValue("Ion", m_ions[0]);
266 source->setAttributeValue("Symmetry", m_symmetries[0]);
267 source->setAttribute("ToleranceEnergy", IFunction::getAttribute("ToleranceEnergy"));
268 source->setAttribute("ToleranceIntensity", IFunction::getAttribute("ToleranceIntensity"));
269 source->setAttributeValue("Temperature", m_temperatures[0]);
270 return source;
271}
272
275 auto source = IFunction_sptr(new CrystalFieldPeaksBaseImpl);
276 source->setAttributeValue("Ion", m_ions[0]);
277 source->setAttributeValue("Symmetry", m_symmetries[0]);
278 source->setAttribute("ToleranceEnergy", IFunction::getAttribute("ToleranceEnergy"));
279 source->setAttribute("ToleranceIntensity", IFunction::getAttribute("ToleranceIntensity"));
280 return source;
281}
282
285 auto source = CompositeFunction_sptr(new CompositeFunction);
286 auto nSites = m_ions.size();
287 auto temperatures = getAttribute("Temperatures").asVector();
288 auto temperature = temperatures[0];
289 for (size_t i = 0; i < nSites; ++i) {
290 auto peakSource = IFunction_sptr(new CrystalFieldPeaks);
291 source->addFunction(peakSource);
292 peakSource->setAttributeValue("Ion", m_ions[i]);
293 peakSource->setAttributeValue("Symmetry", m_symmetries[i]);
294 peakSource->setAttribute("ToleranceEnergy", IFunction::getAttribute("ToleranceEnergy"));
295 peakSource->setAttribute("ToleranceIntensity", IFunction::getAttribute("ToleranceIntensity"));
296 peakSource->setAttributeValue("Temperature", temperature);
297 }
298 return source;
299}
300
303 auto source = CompositeFunction_sptr(new CompositeFunction);
304 auto nSites = m_ions.size();
305 for (size_t i = 0; i < nSites; ++i) {
306 auto peakSource = IFunction_sptr(new CrystalFieldPeaks);
307 source->addFunction(peakSource);
308 peakSource->setAttributeValue("Ion", m_ions[i]);
309 peakSource->setAttributeValue("Symmetry", m_symmetries[i]);
310 peakSource->setAttribute("ToleranceEnergy", IFunction::getAttribute("ToleranceEnergy"));
311 peakSource->setAttribute("ToleranceIntensity", IFunction::getAttribute("ToleranceIntensity"));
312 }
313 return source;
314}
315
316// -----------------------------------------------------------------------------------
317// //
318
320 declareAttribute("FWHMX", Attribute(std::vector<double>()));
321 declareAttribute("FWHMY", Attribute(std::vector<double>()));
322 declareParameter("IntensityScaling", 1.0, "Scales intensities of peaks in a spectrum.");
323}
324
325std::string CrystalFieldSpectrumControl::name() const { return "CrystalFieldSpectrumControl"; }
326
328 API::FunctionValues & /*values*/) const {
329 throw Kernel::Exception::NotImplementedError("This method is intentionally not implemented.");
330}
331
332// -----------------------------------------------------------------------------------
333// //
334
336
337std::string CrystalFieldPhysPropControl::name() const { return "CrystalFieldPhysPropControl"; }
338
340 API::FunctionValues & /*values*/) const {
341 throw Kernel::Exception::NotImplementedError("This method is intentionally not implemented.");
342}
343
344} // namespace Mantid::CurveFitting::Functions
double value
The value of the point.
Definition: FitMW.cpp:51
A composite function is a function containing other functions.
virtual size_t addFunction(IFunction_sptr f)
Add a function at the back of the internal function list.
void declareAttribute(const std::string &name, const API::IFunction::Attribute &defaultValue)
Declare a single attribute.
std::size_t nFunctions() const override
Number of functions.
Attribute getAttribute(const std::string &name) const override
Return a value of attribute attName.
std::string name() const override
Returns the function's name.
IFunction_sptr getFunction(std::size_t i) const override
Returns the pointer to i-th function.
Base class that represents the domain of a function.
A class to store values calculated by a function.
Attribute is a non-fitting parameter.
Definition: IFunction.h:282
std::string asUnquotedString() const
Returns a string value that is guarenteed to be unquoted.
Definition: IFunction.cpp:702
std::vector< double > asVector() const
Returns vector<double> if attribute is vector<double>, throws exception otherwise.
Definition: IFunction.cpp:765
std::string asString() const
Returns string value if attribute is a string, throws exception otherwise.
Definition: IFunction.cpp:660
virtual Attribute getAttribute(const std::string &name) const
Return a value of attribute attName.
Definition: IFunction.cpp:1394
void declareAttribute(const std::string &name, const API::IFunction::Attribute &defaultValue)
Declare a single attribute.
Definition: IFunction.cpp:1418
virtual void setAttribute(const std::string &name, const Attribute &)
Set a value to attribute attName.
Definition: IFunction.cpp:1409
void setAttributeValue(const std::string &attName, const T &value)
Set an attribute value.
Definition: IFunction.h:597
Implements the part of IFunction interface dealing with parameters.
Definition: ParamFunction.h:33
void declareParameter(const std::string &name, double initValue=0, const std::string &description="") override
Declare a new parameter.
void setAttribute(const std::string &name, const Attribute &) override
Set a value to attribute.
API::IFunction_sptr buildSingleSiteSingleSpectrum()
Build the source function in a single site - single spectrum case.
const std::vector< double > & temperatures() const
void buildPhysPropControls()
Build control functions for phys properties.
API::IFunction_sptr buildSource()
Build the source function.
std::vector< std::string > m_physProps
The physical properties.
void checkConsistent()
Check that everything is consistent.
API::IFunction_sptr buildMultiSiteSingleSpectrum()
Build the source function in a multi site - single spectrum case.
API::IFunction_sptr buildSingleSiteMultiSpectrum()
Build the source function in a single site - multi spectrum case.
void buildControls()
Build control functions for individual spectra.
const std::vector< std::string > & physProps() const
API::IFunction_sptr buildSingleSite()
Build the source function in a single site case.
std::vector< double > m_temperatures
The temperatures.
void parseStringListAttribute(const std::string &attName, const std::string &value, std::vector< std::string > &cache)
Parse a comma-separated list attribute.
API::IFunction_sptr buildMultiSiteMultiSpectrum()
Build the source function in a multi site - multi spectrum case.
bool hasPhysProperties() const
Check if there are any phys. properties.
bool isMultiSpectrum() const
Is it a multi-spectrum case?
std::vector< double > m_FWHMs
Cache the default peak FWHMs.
std::vector< std::string > m_symmetries
The symmetries.
API::IFunction_sptr buildMultiSite()
Build the source function in a multi site case.
std::vector< std::vector< double > > m_fwhmX
Caches of the width functions.
CrystalFieldPeaks is a function that calculates crystal field peak positions and intensities.
std::string name() const override
Returns the function's name.
void function(const API::FunctionDomain &, API::FunctionValues &) const override
Evaluates the function for all arguments in the domain.
void function(const API::FunctionDomain &, API::FunctionValues &) const override
Evaluates the function for all arguments in the domain.
std::string name() const override
Returns the function's name.
Marks code as not implemented yet.
Definition: Exception.h:138
Iterator begin()
Iterator referring to first element in the container.
@ TOK_TRIM
remove leading and trailing whitespace from tokens
Iterator end()
Iterator referring to the past-the-end element in the container.
std::shared_ptr< IFunction > IFunction_sptr
shared pointer to the function base class
Definition: IFunction.h:732
Mantid::Kernel::StringTokenizer tokenizer
Definition: Expression.cpp:17
std::shared_ptr< CompositeFunction > CompositeFunction_sptr
shared pointer to the composite function base class
DLLExport std::string join(ITERATOR_TYPE begin, ITERATOR_TYPE end, const std::string &separator, typename std::enable_if<!(std::is_same< typename std::iterator_traits< ITERATOR_TYPE >::iterator_category, std::random_access_iterator_tag >::value)>::type *=nullptr)
Join a set or vector of (something that turns into a string) together into one string,...
Definition: Strings.h:84
std::string to_string(const wide_integer< Bits, Signed > &n)