BornAgain  1.19.0
Simulate and fit neutron and x-ray scattering at grazing incidence
ParticleDistributionItem.cpp
Go to the documentation of this file.
1 // ************************************************************************************************
2 //
3 // BornAgain: simulate and fit reflection and scattering
4 //
5 //! @file GUI/coregui/Models/ParticleDistributionItem.cpp
6 //! @brief Implements class ParticleDistributionItem
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/Const/Units.h"
26 
27 namespace {
28 const QString abundance_tooltip = "Proportion of this type of particles normalized to the \n"
29  "total number of particles in the layout";
30 }
31 
32 const QString ParticleDistributionItem::P_DISTRIBUTED_PARAMETER = "Distributed parameter";
33 const QString ParticleDistributionItem::P_LINKED_PARAMETER = "Linked parameter";
34 const QString ParticleDistributionItem::P_DISTRIBUTION = "Distribution";
35 const QString ParticleDistributionItem::NO_SELECTION = "None";
36 const QString ParticleDistributionItem::T_PARTICLES = "Particle Tag";
37 
39 {
40  setToolTip("Collection of particles obtained via parametric distribution "
41  "of particle prototype");
42 
44  ->setLimits(RealLimits::limited(0.0, 1.0))
45  .setDecimals(3)
46  .setToolTip(abundance_tooltip);
47 
48  addGroupProperty(P_DISTRIBUTION, "Distribution group")
49  ->setToolTip("Distribution to apply to the specified parameter");
50 
52  QStringList() << "Particle"
53  << "ParticleCoreShell"
54  << "ParticleComposition"
55  << "MesoCrystal");
57 
58  ComboProperty par_prop;
59  addProperty(P_DISTRIBUTED_PARAMETER, par_prop.variant())->setToolTip("Parameter to distribute");
60 
62  ->setToolTip("Linked parameter")
63  .setEditorType("MultiSelectionComboEditor");
64 
66 
68  // prevent infinit loop when item changes its own properties
69  if (item && item->modelType() == "Property" && item->parent() == this)
70  return;
72  });
73 
74  mapper()->setOnPropertyChange([this](const QString& name) {
77  });
78 }
79 
80 std::unique_ptr<ParticleDistribution> ParticleDistributionItem::createParticleDistribution() const
81 {
82  if (children().empty())
83  return nullptr;
84  std::unique_ptr<IParticle> P_particle = TransformToDomain::createIParticle(*getItem());
85  if (!P_particle)
86  throw GUIHelpers::Error("DomainObjectBuilder::buildParticleDistribution()"
87  " -> Error! No correct particle defined");
88  auto& distr_item = groupItem<DistributionItem>(ParticleDistributionItem::P_DISTRIBUTION);
89 
90  std::string domain_par = domainMainParameter();
91 
92  double scale = ParameterUtils::isAngleRelated(domain_par) ? Units::deg : 1.0;
93  auto P_distribution = distr_item.createDistribution(scale);
94 
96  if (distr_item.isTag(DistributionItem::P_LIMITS)) {
97  auto& limitsItem = distr_item.groupItem<RealLimitsItem>(DistributionItem::P_LIMITS);
98  limits = limitsItem.createRealLimits(scale);
99  }
100 
101  int nbr_samples = distr_item.getItemValue(DistributionItem::P_NUMBER_OF_SAMPLES).toInt();
102  double sigma_factor = distr_item.isTag(DistributionItem::P_SIGMA_FACTOR)
103  ? distr_item.getItemValue(DistributionItem::P_SIGMA_FACTOR).toDouble()
104  : 0.0;
105  ParameterDistribution par_distr(domain_par, *P_distribution, static_cast<size_t>(nbr_samples),
106  sigma_factor, limits);
107 
108  for (auto name : domainLinkedParameters())
109  par_distr.linkParameter(name);
110 
111  auto result = std::make_unique<ParticleDistribution>(*P_particle, par_distr);
112  double abundance = getItemValue(ParticleItem::P_ABUNDANCE).toDouble();
113  result->setAbundance(abundance);
114  return result;
115 }
116 
117 void ParticleDistributionItem::setDomainCacheNames(const QString& name, const QStringList& linked)
118 {
120  m_linked_names = linked;
121 }
122 
124 {
126  return;
127 
128  QString currentValue = getItemValue(P_DISTRIBUTED_PARAMETER).value<ComboProperty>().getValue();
129 
130  if (!m_domain_cache_name.isEmpty() && childParticle()) {
132  if (!guiName.isEmpty()) { // might be empty because item was not fully constructed yet
133  currentValue = guiName;
134  m_domain_cache_name.clear();
135  }
136  }
137 
138  QStringList par_names = QStringList() << NO_SELECTION << childParameterNames();
139  ComboProperty newProp = ComboProperty::fromList(par_names, NO_SELECTION);
140 
141  if (newProp.getValues().contains(currentValue))
142  newProp.setValue(currentValue);
143 
145 }
146 
148 {
150  return;
151 
152  QString mainValue = getItemValue(P_DISTRIBUTED_PARAMETER).value<ComboProperty>().getValue();
153 
154  QStringList par_names = childParameterNames();
155  par_names.removeAll(mainValue);
156 
158  QStringList currentValues = linkedProp.selectedValues();
159 
160  if (!m_linked_names.isEmpty() && childParticle()) {
161  QStringList domainValues;
162  for (auto par : m_linked_names) {
163  QString guiName = translateParameterNameToGUI(par);
164  if (!guiName.isEmpty())
165  domainValues.append(guiName);
166  }
167  if (!domainValues.isEmpty()) {
168  currentValues = domainValues;
169  m_linked_names.clear();
170  }
171  }
172 
173  ComboProperty newProp = ComboProperty::fromList(par_names);
174  for (auto name : currentValues)
175  newProp.setSelected(name, true);
176 
178 }
179 
181 {
182  if (auto child = childParticle()) {
183  auto result = ParameterTreeUtils::parameterTreeNames(child);
184  result.removeAll(ParticleItem::P_ABUNDANCE);
185  return result;
186  }
187 
188  return {};
189 }
190 
192 {
193  if (auto child = childParticle())
194  return ParameterTreeUtils::domainNameToParameterName(domainName, child);
195  return {};
196 }
197 
199 {
200  if (getItems(T_PARTICLES).empty())
201  return nullptr;
202 
203  ASSERT(getItems(T_PARTICLES).size() == 1);
204  return getItems(T_PARTICLES).front();
205 }
206 
208 {
209  auto par_name = getItemValue(P_DISTRIBUTED_PARAMETER).value<ComboProperty>().getValue();
210  return ParameterTreeUtils::parameterNameToDomainName(par_name, childParticle()).toStdString();
211 }
212 
213 std::vector<std::string> ParticleDistributionItem::domainLinkedParameters() const
214 {
215  std::vector<std::string> result;
216  auto linked_names = getItemValue(P_LINKED_PARAMETER).value<ComboProperty>().selectedValues();
217  for (auto name : linked_names) {
219  if (!translated.isEmpty())
220  result.push_back(translated.toStdString());
221  }
222  return result;
223 }
#define ASSERT(condition)
Definition: Assert.h:31
Defines class ComboProperty.
Defines class DistributionItem and several subclasses.
Defines class GUIHelpers functions.
Defines ParameterTreeUtils namespace.
Defines namespace ParameterUtils.
Defines class ParticleDistributionItem.
Defines class ParticleItem.
Defines RealLimitsItems's classes.
Defines namespace TransformFromDomain.
Defines class TransformToDomain.
Defines some unit conversion factors and other constants in namespace Units.
Custom property to define list of string values with multiple selections.
Definition: ComboProperty.h:25
QStringList getValues() const
static ComboProperty fromList(const QStringList &values, const QString &current_value="")
QVariant variant() const
Constructs variant enclosing given ComboProperty.
void setSelected(int index, bool value=true)
Sets given index selection flag.
void setValue(const QString &name)
QStringList selectedValues() const
Returns list of string with selected values;.
static const QString P_LIMITS
static const QString P_NUMBER_OF_SAMPLES
static const QString P_SIGMA_FACTOR
void setOnAnyChildChange(std::function< void(SessionItem *)> f, const void *caller=0)
Calls back on any change in children (number of children or their properties), reports childItem.
Definition: ModelMapper.cpp:82
void setOnPropertyChange(std::function< void(QString)> f, const void *caller=0)
Definition: ModelMapper.cpp:35
A parametric distribution function, for use with any model parameter.
ParameterDistribution & linkParameter(std::string par_name)
const SessionItem * childParticle() const
std::unique_ptr< ParticleDistribution > createParticleDistribution() const
static const QString NO_SELECTION
QString translateParameterNameToGUI(const QString &domainName)
static const QString P_DISTRIBUTION
static const QString T_PARTICLES
void setDomainCacheNames(const QString &name, const QStringList &linked)
static const QString P_DISTRIBUTED_PARAMETER
std::vector< std::string > domainLinkedParameters() const
static const QString P_LINKED_PARAMETER
static const QString P_ABUNDANCE
Definition: ParticleItem.h:26
Limits for a real fit parameter.
Definition: RealLimits.h:24
static RealLimits limitless()
Creates an object withoud bounds (default)
Definition: RealLimits.cpp:130
static RealLimits limited(double left_bound_value, double right_bound_value)
Creates an object bounded from the left and right.
Definition: RealLimits.cpp:125
bool isTag(const QString &name) const
Returns true if tag is available.
SessionItem * addProperty(const QString &name, const QVariant &variant)
Add new property item and register new tag.
SessionItem & setDecimals(int n)
bool registerTag(const QString &name, int min=0, int max=-1, QStringList modelTypes={})
Add new tag to this item with given name, min, max and types.
QVector< SessionItem * > getItems(const QString &tag="") const
Returns vector of all items of given tag.
SessionItem & setEditorType(const QString &editorType)
QVariant getItemValue(const QString &tag) const
Directly access value of item under given tag.
SessionItem * addGroupProperty(const QString &groupTag, const QString &groupType)
Creates new group item and register new tag, returns GroupItem.
ModelMapper * mapper()
Returns the current model mapper of this item. Creates new one if necessary.
void setDefaultTag(const QString &tag)
Set default tag.
T * item(const QString &tag) const
Definition: SessionItem.h:151
void setItemValue(const QString &tag, const QVariant &variant)
Directly set value of item under given tag.
QVector< SessionItem * > children() const
Returns vector of all children.
RealLimits limits() const
SessionItem & setToolTip(const QString &tooltip)
SessionItem * getItem(const QString &tag="", int row=0) const
Returns item in given row of given tag.
SessionItem & setLimits(const RealLimits &value)
QString domainNameToParameterName(const QString &domainName, const SessionItem *source)
Converts domain name to parameterItem name.
QStringList parameterTreeNames(const SessionItem *source)
Creates list with parameter names of source item.
QString parameterNameToDomainName(const QString &parName, const SessionItem *source)
Converts parameter name to domain name.
bool isAngleRelated(const std::string &par_name)
Returns true if given parameter name is related to angles.
QString const & name(EShape k)
Definition: particles.cpp:21
std::unique_ptr< IParticle > createIParticle(const SessionItem &item)
static constexpr double deg
Definition: Units.h:46