BornAgain  1.19.79
Simulate and fit neutron and x-ray scattering at grazing incidence
MaterialItem.cpp
Go to the documentation of this file.
1 // ************************************************************************************************
2 //
3 // BornAgain: simulate and fit reflection and scattering
4 //
5 //! @file GUI/Model/Sample/MaterialItem.cpp
6 //! @brief Implements class MaterialItem
7 //!
8 //! @homepage http://www.bornagainproject.org
9 //! @license GNU General Public License v3 or higher (see COPYING)
10 //! @copyright Forschungszentrum Jülich GmbH 2018
11 //! @authors Scientific Computing Group at MLZ (see CITATION, AUTHORS)
12 //
13 // ************************************************************************************************
14 
16 #include "Base/Util/Assert.h"
21 #include "Sample/Material/MaterialFactoryFuncs.h"
22 #include <QColor>
23 #include <QUuid>
24 #include <QXmlStreamReader>
25 
26 namespace {
27 
28 namespace Tags {
29 
30 const QString Color("Color");
31 const QString Id("Id");
32 const QString Name("Name");
33 const QString Delta("Delta");
34 const QString Beta("Beta");
35 const QString Sld("Sld");
36 const QString Magnetization("Magnetization");
37 
38 } // namespace Tags
39 
40 } // namespace
41 
42 #define m_delta std::get<Refractive>(m_data).delta
43 #define m_beta std::get<Refractive>(m_data).beta
44 
45 #define m_real std ::get<complex_t>(m_data).real()
46 #define m_imag std ::get<complex_t>(m_data).imag()
47 
49  : m_data(Refractive(0.0, 0.0))
50 {
51  m_color = Qt::red;
52  m_id = QUuid::createUuid().toString();
53 }
54 
56  : QObject()
57  , m_name(other.m_name)
58  , m_id(other.m_id)
59  , m_color(other.m_color)
60  , m_data(other.m_data)
61  , m_magnetization(other.m_magnetization)
62 {
63 }
64 
65 void MaterialItem::setRefractiveIndex(const double delta, const double beta)
66 {
67  const Refractive r(delta, beta);
68  if (hasRefractiveIndex() && std::get<Refractive>(m_data) == r)
69  return;
70 
71  m_data = r;
72  emit dataChanged();
73 }
74 
76 {
77  if (!hasRefractiveIndex() && std::get<complex_t>(m_data) == sld)
78  return;
79 
80  m_data = sld;
81  emit dataChanged();
82 }
83 
85 {
86  ASSERT(hasRefractiveIndex());
87  const auto setter = [=](double v) {
88  if (m_delta != v) {
89  m_delta = v;
90  emit dataChanged();
91  }
92  };
93 
95  "Delta", "Delta of refractive index (n = 1 - delta + i*beta)", 3, RealLimits::limitless(),
96  setter, [=] { return m_delta; }, Unit::unitless);
97  d.path = [=] { return uidForDescriptor("delta"); };
98  return d;
99 }
100 
102 {
103  ASSERT(hasRefractiveIndex());
104  const auto setter = [=](double v) {
105  if (m_beta != v) {
106  m_beta = v;
107  emit dataChanged();
108  }
109  };
110 
112  "Beta", "Beta of refractive index (n = 1 - delta + i*beta)", 3, RealLimits::limitless(),
113  setter, [=] { return m_beta; }, Unit::unitless);
114  d.path = [=] { return uidForDescriptor("beta"); };
115  return d;
116 }
117 
119 {
120  ASSERT(!hasRefractiveIndex());
121  const auto setter = [=](double v) {
122  if (m_real != v) {
123  std::get<complex_t>(m_data).real(v);
124  emit dataChanged();
125  }
126  };
127 
129  "SLD, real", "Real part of SLD (SLD = real - i*imag), AA^{-2}", 3, RealLimits::limitless(),
130  setter, [=] { return m_real; }, Unit::unitless);
131  d.path = [=] { return uidForDescriptor("re"); };
132  return d;
133 }
134 
136 {
137  ASSERT(!hasRefractiveIndex());
138  const auto setter = [=](double v) {
139  if (m_imag != v) {
140  std::get<complex_t>(m_data).imag(v);
141  emit dataChanged();
142  }
143  };
144 
146  "SLD, imaginary", "Imaginary part of SLD (SLD = real - i*imag), AA^{-2}", 3,
147  RealLimits::limitless(), setter, [=] { return m_imag; }, Unit::unitless);
148  d.path = [=] { return uidForDescriptor("im"); };
149  return d;
150 }
151 
153 {
154  VectorDescriptor d("Magnetization", "Magnetization (A/m)", "A/m");
155 
156  d.x.set = [=](double v) {
157  if (m_magnetization.x() != v) {
158  m_magnetization.setX(v);
159  emit dataChanged();
160  }
161  };
162  d.x.get = [=]() { return m_magnetization.x(); };
163  d.x.path = [=] { return uidForDescriptor("mx"); };
164 
165  d.y.set = [=](double v) {
166  if (m_magnetization.y() != v) {
167  m_magnetization.setY(v);
168  emit dataChanged();
169  }
170  };
171  d.y.get = [=]() { return m_magnetization.y(); };
172  d.y.path = [=] { return uidForDescriptor("my"); };
173 
174  d.z.set = [=](double v) {
175  if (m_magnetization.z() != v) {
176  m_magnetization.setZ(v);
177  emit dataChanged();
178  }
179  };
180  d.z.get = [=]() { return m_magnetization.z(); };
181  d.z.path = [=] { return uidForDescriptor("mz"); };
182  d.uid = [=] { return uidForDescriptor("magnetization"); };
183  return d;
184 }
185 
187 {
188  return std::holds_alternative<Refractive>(m_data);
189 }
190 
192 {
193  return m_name;
194 }
195 
196 void MaterialItem::setMatItemName(const QString& name)
197 {
198  if (m_name != name) {
199  m_name = name;
200  emit dataChanged();
201  }
202 }
203 
205 {
206  return m_id;
207 }
208 
209 void MaterialItem::setIdentifier(const QString& id)
210 {
211  m_id = id;
212  // no "emit dataChanged()" here
213 }
214 
216 {
217  m_id = QUuid::createUuid().toString();
218  // no "emit dataChanged()" here
219 }
220 
221 QColor MaterialItem::color() const
222 {
223  return m_color;
224 }
225 
226 void MaterialItem::setColor(const QColor& color)
227 {
228  if (m_color != color) {
229  m_color = color;
230  emit dataChanged();
231  }
232 }
233 
235 {
236  return m_magnetization;
237 }
238 
239 void MaterialItem::setMagnetization(const R3& magnetization)
240 {
243  emit dataChanged();
244  }
245 }
246 
247 std::unique_ptr<Material> MaterialItem::createMaterial() const
248 {
249  if (hasRefractiveIndex())
250  return std::make_unique<Material>(
251  RefractiveMaterial(matItemName().toStdString(), m_delta, m_beta, m_magnetization));
252 
253  return std::make_unique<Material>(
254  MaterialBySLD(matItemName().toStdString(), m_real, m_imag, m_magnetization));
255 }
256 
257 void MaterialItem::writeContentTo(QXmlStreamWriter* writer) const
258 {
260 
262  GUI::Session::XML::writeAttribute(writer, Tags::Color, m_color);
263  GUI::Session::XML::writeAttribute(writer, Tags::Name, m_name);
264  GUI::Session::XML::writeAttribute(writer, Tags::Magnetization, m_magnetization);
265 
266  if (hasRefractiveIndex()) {
267  GUI::Session::XML::writeAttribute(writer, Tags::Delta, m_delta);
268  GUI::Session::XML::writeAttribute(writer, Tags::Beta, m_beta);
269  } else
270  GUI::Session::XML::writeAttribute(writer, Tags::Sld, std::get<complex_t>(m_data));
271 }
272 
273 void MaterialItem::readContentFrom(QXmlStreamReader* reader)
274 {
275  const int version = reader->attributes().value(GUI::Session::XML::Version).toInt();
276 
277  if (version < 1)
279 
280  if (version > 1)
282 
284  GUI::Session::XML::readAttribute(reader, Tags::Color, &m_color);
285  GUI::Session::XML::readAttribute(reader, Tags::Name, &m_name);
286  GUI::Session::XML::readAttribute(reader, Tags::Magnetization, &m_magnetization);
287  if (reader->attributes().hasAttribute(Tags::Delta)) {
288  double d, b;
289  GUI::Session::XML::readAttribute(reader, Tags::Delta, &d);
290  GUI::Session::XML::readAttribute(reader, Tags::Beta, &b);
291  m_data = Refractive(d, b);
292  } else {
293  complex_t c;
294  GUI::Session::XML::readAttribute(reader, Tags::Sld, &c);
295  m_data = c;
296  }
297 }
298 
300 {
301  bool hasRefractive = hasRefractiveIndex();
302  double val1 = hasRefractiveIndex() ? delta() : sldRe();
303  double val2 = hasRefractiveIndex() ? beta() : sldIm();
304 
305  s.assertVersion(0);
306  Serialize::rwValue(s, "name", m_name);
307  Serialize::rwValue(s, "id", m_id);
308  Serialize::rwValue(s, "color", m_color);
309  Serialize::rwValue(s, "magnetization", m_magnetization);
310  Serialize::rwValue(s, "refr", hasRefractive);
311  Serialize::rwValue(s, "val1", val1);
312  Serialize::rwValue(s, "val2", val2);
313 
314  if (s.xmlReader()) {
315  if (hasRefractive)
316  m_data = Refractive(val1, val2);
317  else
318  m_data = complex_t(val1, val2);
319  }
320 }
321 
323 {
324  if (operator!=(other)) {
325  m_name = other.m_name;
326  m_color = other.m_color;
327  m_data = other.m_data;
328  m_magnetization = other.m_magnetization;
329  emit dataChanged();
330  }
331 }
332 
333 QString MaterialItem::uidForDescriptor(const QString& lastPart) const
334 {
335  return "material/" + identifier() + "/" + lastPart;
336 }
337 
338 bool MaterialItem::operator!=(const MaterialItem& other) const
339 {
340  return !operator==(other);
341 }
342 
343 bool MaterialItem::operator==(const MaterialItem& other) const
344 {
345  if (hasRefractiveIndex()) {
346  if (std::get<Refractive>(m_data) != std::get<Refractive>(other.m_data))
347  return false;
348  } else if (std::get<complex_t>(m_data) != std::get<complex_t>(other.m_data))
349  return false;
350 
351 
352  return (m_id == other.m_id) && (m_name == other.m_name) && (m_color == other.m_color)
353  && (m_magnetization == other.m_magnetization);
354 }
Defines class DeserializationException.
#define m_imag
#define m_delta
#define m_real
#define m_beta
Defines class MaterialItem.
Defines class Streamer.
@ other
The unit has no enum value defined in here (e.g. when defined as an explicit string)
@ unitless
Defines.
Defines class VectorDescriptor.
static DeserializationException tooOld()
static DeserializationException tooNew()
Describes properties of a double value which are necessary to allow GUI representation,...
function< void(double)> set
function to set the value
function< double()> get
function to get the current value
function< QString()> path
Path describing this value. Used e.g. for undo/redo.
QString m_id
Definition: MaterialItem.h:104
QString uidForDescriptor(const QString &lastPart) const
Returns a unique identifier for descriptors.
QColor m_color
Definition: MaterialItem.h:105
bool hasRefractiveIndex() const
void serialize(Streamer &s)
void createNewIdentifier()
QString m_name
Definition: MaterialItem.h:103
void setScatteringLengthDensity(complex_t sld)
Turns material into SLD based material.
DoubleDescriptor sldIm()
DoubleDescriptor beta()
void readContentFrom(QXmlStreamReader *reader)
bool operator!=(const MaterialItem &other) const
QString matItemName() const
QColor color() const
void setIdentifier(const QString &id)
R3 magnetization() const
std::variant< Refractive, complex_t > m_data
Definition: MaterialItem.h:119
void setMagnetization(const R3 &magnetization)
void updateFrom(const MaterialItem &other)
Updates content from the other material.
bool operator==(const MaterialItem &other) const
Compares all contents. The inactive contents (e.g. SLD in case of refractive) are not taken into acco...
QString identifier() const
void setRefractiveIndex(double delta, double beta)
Turns material into refractive index material.
std::unique_ptr< Material > createMaterial() const
DoubleDescriptor sldRe()
void setMatItemName(const QString &name)
DoubleDescriptor delta()
void dataChanged() const
VectorDescriptor magnetizationVector()
void setColor(const QColor &color)
void writeContentTo(QXmlStreamWriter *writer) const
Supports serialization to or deserialization from QXmlStream.
Definition: Streamer.h:36
QXmlStreamReader * xmlReader()
Returns stream reader or nullptr.
Definition: Streamer.h:48
void assertVersion(unsigned expectedVersion) const
As reader, throws DeserializationException unless the expected version is read. As writer,...
Definition: Streamer.cpp:26
Describes properties of a 3D vector, consisting of three double values.
DoubleDescriptor y
DoubleDescriptor x
function< QString()> uid
unique id describing this value. Used e.g. for undo/redo
DoubleDescriptor z
QString const & name(EShape k)
Definition: particles.cpp:20
void readAttribute(QXmlStreamReader *reader, const QString &attributeName, double *d)
Definition: UtilXML.cpp:193
constexpr auto Version("Version")
void writeAttribute(QXmlStreamWriter *writer, const QString &attributeName, const QVariant &variant)
Write the variant's value as an attribute.
Definition: UtilXML.cpp:65
void rwValue(Streamer &s, const QString &tag, bool &val)
Definition: Serialize.cpp:19
Definition: JobItem.cpp:33
constexpr auto Id("id")