BornAgain  1.18.0
Simulate and fit neutron and x-ray scattering at grazing incidence
SampleToPython Class Reference
Collaboration diagram for SampleToPython:

Public Member Functions

 SampleToPython ()
 
 ~SampleToPython ()
 
std::string generateSampleCode (const MultiLayer &multilayer)
 

Private Member Functions

void initLabels (const MultiLayer &multilayer)
 
std::string defineGetSample () const
 
std::string defineMaterials () const
 
std::string defineLayers () const
 
std::string defineFormFactors () const
 
std::string defineParticles () const
 
std::string defineCoreShellParticles () const
 
std::string defineParticleDistributions () const
 
std::string defineParticleCompositions () const
 
std::string defineLattices () const
 
std::string defineCrystals () const
 
std::string defineMesoCrystals () const
 
std::string defineInterferenceFunctions () const
 
std::string defineParticleLayouts () const
 
std::string defineRoughnesses () const
 
std::string addLayoutsToLayers () const
 
std::string defineMultiLayers () const
 
std::string indent () const
 
void setRotationInformation (const IParticle *particle, std::string particle_name, std::ostringstream &result) const
 
void setPositionInformation (const IParticle *particle, std::string particle_name, std::ostringstream &result) const
 

Private Attributes

std::unique_ptr< SampleLabelHandlerm_label
 

Detailed Description

Generates Python code snippet from domain (C++) objects representing sample construction.

Definition at line 27 of file SampleToPython.h.

Constructor & Destructor Documentation

◆ SampleToPython()

SampleToPython::SampleToPython ( )
default

◆ ~SampleToPython()

SampleToPython::~SampleToPython ( )
default

Member Function Documentation

◆ generateSampleCode()

std::string SampleToPython::generateSampleCode ( const MultiLayer multilayer)

Definition at line 37 of file SampleToPython.cpp.

38 {
39  initLabels(multilayer);
40  return defineGetSample();
41 }
std::string defineGetSample() const
void initLabels(const MultiLayer &multilayer)

References defineGetSample(), and initLabels().

Referenced by ExportToPython::generateSampleCode(), and SimulationToPython::generateSimulationCode().

Here is the call graph for this function:

◆ initLabels()

void SampleToPython::initLabels ( const MultiLayer multilayer)
private

Definition at line 43 of file SampleToPython.cpp.

44 {
45  m_label.reset(new SampleLabelHandler());
46 
47  m_label->insertMultiLayer(&multilayer);
48 
49  for (auto x : multilayer.containedMaterials())
50  m_label->insertMaterial(x);
51  for (auto x : INodeUtils::AllDescendantsOfType<Layer>(multilayer))
52  m_label->insertLayer(x);
53  for (auto x : INodeUtils::AllDescendantsOfType<LayerRoughness>(multilayer))
54  m_label->insertRoughness(x);
55  for (auto x : INodeUtils::AllDescendantsOfType<IFormFactor>(multilayer))
56  m_label->insertFormFactor(x);
57  for (auto x : INodeUtils::AllDescendantsOfType<ILayout>(multilayer))
58  m_label->insertLayout(x);
59  for (auto x : INodeUtils::AllDescendantsOfType<IInterferenceFunction>(multilayer))
60  m_label->insertInterferenceFunction(x);
61  for (auto x : INodeUtils::AllDescendantsOfType<Particle>(multilayer))
62  m_label->insertParticle(x);
63  for (auto x : INodeUtils::AllDescendantsOfType<ParticleCoreShell>(multilayer))
64  m_label->insertParticleCoreShell(x);
65  for (auto x : INodeUtils::AllDescendantsOfType<ParticleComposition>(multilayer))
66  m_label->insertParticleComposition(x);
67  for (auto x : INodeUtils::AllDescendantsOfType<ParticleDistribution>(multilayer))
68  m_label->insertParticleDistribution(x);
69  for (auto x : INodeUtils::AllDescendantsOfType<Lattice>(multilayer))
70  m_label->insertLattice(x);
71  for (auto x : INodeUtils::AllDescendantsOfType<Crystal>(multilayer))
72  m_label->insertCrystal(x);
73  for (auto x : INodeUtils::AllDescendantsOfType<MesoCrystal>(multilayer))
74  m_label->insertMesoCrystal(x);
75  for (auto x : INodeUtils::AllDescendantsOfType<IRotation>(multilayer))
76  m_label->insertRotation(x);
77 }
std::vector< const Material * > containedMaterials() const
Returns set of unique materials contained in this ISample.
Definition: ISample.cpp:23
The handler which construct labels for sample variables during python script generation.
std::unique_ptr< SampleLabelHandler > m_label

References ISample::containedMaterials(), and m_label.

Referenced by generateSampleCode().

Here is the call graph for this function:

◆ defineGetSample()

std::string SampleToPython::defineGetSample ( ) const
private

Definition at line 83 of file SampleToPython.cpp.

84 {
85  return "def " + pyfmt::getSampleFunctionName() + "():\n" + defineMaterials() + defineLayers()
90  + defineMultiLayers() + "\n\n";
91 }
std::string defineLayers() const
std::string defineFormFactors() const
std::string defineMaterials() const
std::string defineMesoCrystals() const
std::string defineCrystals() const
std::string defineParticles() const
std::string defineParticleCompositions() const
std::string defineParticleDistributions() const
std::string addLayoutsToLayers() const
std::string defineParticleLayouts() const
std::string defineLattices() const
std::string defineCoreShellParticles() const
std::string defineInterferenceFunctions() const
std::string defineMultiLayers() const
std::string defineRoughnesses() const
std::string getSampleFunctionName()
Definition: PyFmt.cpp:33

References addLayoutsToLayers(), defineCoreShellParticles(), defineCrystals(), defineFormFactors(), defineInterferenceFunctions(), defineLattices(), defineLayers(), defineMaterials(), defineMesoCrystals(), defineMultiLayers(), defineParticleCompositions(), defineParticleDistributions(), defineParticleLayouts(), defineParticles(), defineRoughnesses(), and pyfmt::getSampleFunctionName().

Referenced by generateSampleCode().

Here is the call graph for this function:

◆ defineMaterials()

std::string SampleToPython::defineMaterials ( ) const
private

Definition at line 97 of file SampleToPython.cpp.

98 {
99  const LabelMap<const Material*>* themap = m_label->materialMap();
100  if (themap->empty())
101  return "# No Materials.\n\n";
102  std::ostringstream result;
103  result << std::setprecision(12);
104  result << indent() << "# Defining Materials\n";
105  std::set<std::string> visitedMaterials;
106  for (auto it = themap->begin(); it != themap->end(); ++it) {
107  if (visitedMaterials.find(it->second) != visitedMaterials.end())
108  continue;
109  visitedMaterials.insert(it->second);
110  const Material* p_material = it->first;
111  const auto factory_name = factory_names.find(p_material->typeID());
112  if (factory_name == factory_names.cend())
113  throw std::runtime_error(
114  "Error in ExportToPython::defineMaterials(): unknown material type");
115  const complex_t& material_data = p_material->materialData();
116  if (p_material->isScalarMaterial()) {
117  result << indent() << m_label->labelMaterial(p_material) << " = ba."
118  << factory_name->second << "(\"" << p_material->getName() << "\", "
119  << pyfmt::printDouble(material_data.real()) << ", "
120  << pyfmt::printDouble(material_data.imag()) << ")\n";
121  } else {
122  kvector_t magnetic_field = p_material->magnetization();
123  result << indent() << "magnetic_field = kvector_t(" << magnetic_field.x() << ", "
124  << magnetic_field.y() << ", " << magnetic_field.z() << ")\n";
125  result << indent() << m_label->labelMaterial(p_material) << " = ba."
126  << factory_name->second << "(\"" << p_material->getName();
127  result << "\", " << pyfmt::printDouble(material_data.real()) << ", "
128  << pyfmt::printDouble(material_data.imag()) << ", "
129  << "magnetic_field)\n";
130  }
131  }
132  return result.str();
133 }
std::complex< double > complex_t
Definition: Complex.h:20
const std::map< MATERIAL_TYPES, std::string > factory_names
T z() const
Returns z-component in cartesian coordinate system.
Definition: BasicVector3D.h:68
T y() const
Returns y-component in cartesian coordinate system.
Definition: BasicVector3D.h:66
T x() const
Returns x-component in cartesian coordinate system.
Definition: BasicVector3D.h:64
A wrapper for underlying material implementation.
Definition: Material.h:29
kvector_t magnetization() const
Get the magnetization (in A/m)
Definition: Material.cpp:79
bool isScalarMaterial() const
Indicates whether the interaction with the material is scalar.
Definition: Material.cpp:59
std::string getName() const
Returns the name of material.
Definition: Material.cpp:69
MATERIAL_TYPES typeID() const
Returns the type of underlying material implementation.
Definition: Material.cpp:74
complex_t materialData() const
Returns underlying material data.
Definition: Material.cpp:84
const_iterator end() const
Definition: OrderedMap.h:47
bool empty() const
Definition: OrderedMap.h:56
const_iterator begin() const
Definition: OrderedMap.h:46
std::string indent() const
std::string printDouble(double input)
Definition: PyFmt.cpp:43

References OrderedMap< Key, Object >::begin(), OrderedMap< Key, Object >::empty(), OrderedMap< Key, Object >::end(), factory_names, Material::getName(), indent(), Material::isScalarMaterial(), m_label, Material::magnetization(), Material::materialData(), pyfmt::printDouble(), Material::typeID(), BasicVector3D< T >::x(), BasicVector3D< T >::y(), and BasicVector3D< T >::z().

Referenced by defineGetSample().

Here is the call graph for this function:

◆ defineLayers()

std::string SampleToPython::defineLayers ( ) const
private

Definition at line 135 of file SampleToPython.cpp.

136 {
137  const auto themap = m_label->layerMap();
138  if (themap->empty())
139  return "# No Layers.\n\n";
140  std::ostringstream result;
141  result << std::setprecision(12);
142  result << "\n" << indent() << "# Defining Layers\n";
143  for (auto it = themap->begin(); it != themap->end(); ++it) {
144  const Layer* layer = it->first;
145  result << indent() << it->second << " = ba.Layer("
146  << m_label->labelMaterial(layer->material());
147  if (layer->thickness() != 0)
148  result << ", " << layer->thickness();
149  result << ")\n";
150  if (layer->numberOfSlices() != 1)
151  result << indent() << it->second << ".setNumberOfSlices(" << layer->numberOfSlices()
152  << ")\n";
153  }
154  return result.str();
155 }
A layer, with thickness (in nanometer) and material.
Definition: Layer.h:28
double thickness() const
Definition: Layer.h:39
const Material * material() const override final
Returns nullptr, unless overwritten to return a specific material.
Definition: Layer.h:41
unsigned int numberOfSlices() const
Definition: Layer.h:53

References indent(), m_label, Layer::material(), Layer::numberOfSlices(), and Layer::thickness().

Referenced by defineGetSample().

Here is the call graph for this function:

◆ defineFormFactors()

std::string SampleToPython::defineFormFactors ( ) const
private

Definition at line 157 of file SampleToPython.cpp.

158 {
159  const auto themap = m_label->formFactorMap();
160  if (themap->empty())
161  return "";
162  std::ostringstream result;
163  result << std::setprecision(12);
164  result << "\n" << indent() << "# Defining Form Factors\n";
165  for (auto it = themap->begin(); it != themap->end(); ++it) {
166  const IFormFactor* p_ff = it->first;
167  result << indent() << it->second << " = ba.FormFactor" << p_ff->getName() << "("
168  << pyfmt2::argumentList(p_ff) << ")\n";
169  }
170  return result.str();
171 }
Pure virtual base class for all form factors.
Definition: IFormFactor.h:40
const std::string & getName() const
std::string argumentList(const IParameterized *ip)
Returns comma-separated list of parameter values, including unit multiplicator (like "* nm").
Definition: PyFmt2.cpp:106

References pyfmt2::argumentList(), IParameterized::getName(), indent(), and m_label.

Referenced by defineGetSample().

Here is the call graph for this function:

◆ defineParticles()

std::string SampleToPython::defineParticles ( ) const
private

Definition at line 173 of file SampleToPython.cpp.

174 {
175  const auto themap = m_label->particleMap();
176  if (themap->empty())
177  return "";
178  std::ostringstream result;
179  result << std::setprecision(12);
180  result << "\n" << indent() << "# Defining Particles\n";
181  for (auto it = themap->begin(); it != themap->end(); ++it) {
182  const Particle* p_particle = it->first;
183  std::string particle_name = it->second;
184  auto p_ff = INodeUtils::OnlyChildOfType<IFormFactor>(*p_particle);
185  if (!p_ff)
186  continue;
187  result << indent() << particle_name << " = ba.Particle("
188  << m_label->labelMaterial(p_particle->material()) << ", "
189  << m_label->labelFormFactor(p_ff) << ")\n";
190  setRotationInformation(p_particle, particle_name, result);
191  setPositionInformation(p_particle, particle_name, result);
192  }
193  return result.str();
194 }
A particle with a form factor and refractive index.
Definition: Particle.h:26
const Material * material() const override final
Returns nullptr, unless overwritten to return a specific material.
Definition: Particle.h:40
void setRotationInformation(const IParticle *particle, std::string particle_name, std::ostringstream &result) const
void setPositionInformation(const IParticle *particle, std::string particle_name, std::ostringstream &result) const

References indent(), m_label, Particle::material(), setPositionInformation(), and setRotationInformation().

Referenced by defineGetSample().

Here is the call graph for this function:

◆ defineCoreShellParticles()

std::string SampleToPython::defineCoreShellParticles ( ) const
private

Definition at line 196 of file SampleToPython.cpp.

197 {
198  const auto themap = m_label->particleCoreShellMap();
199  if (themap->empty())
200  return "";
201  std::ostringstream result;
202  result << std::setprecision(12);
203  result << "\n" << indent() << "# Defining Core Shell Particles\n";
204  for (auto it = themap->begin(); it != themap->end(); ++it) {
205  const ParticleCoreShell* p_coreshell = it->first;
206  result << "\n"
207  << indent() << it->second << " = ba.ParticleCoreShell("
208  << m_label->labelParticle(p_coreshell->shellParticle()) << ", "
209  << m_label->labelParticle(p_coreshell->coreParticle()) << ")\n";
210  std::string core_shell_name = it->second;
211  setRotationInformation(p_coreshell, core_shell_name, result);
212  setPositionInformation(p_coreshell, core_shell_name, result);
213  }
214  return result.str();
215 }
A particle with a core/shell geometry.
const Particle * shellParticle() const
const Particle * coreParticle() const

References ParticleCoreShell::coreParticle(), indent(), m_label, setPositionInformation(), setRotationInformation(), and ParticleCoreShell::shellParticle().

Referenced by defineGetSample().

Here is the call graph for this function:

◆ defineParticleDistributions()

std::string SampleToPython::defineParticleDistributions ( ) const
private

Definition at line 217 of file SampleToPython.cpp.

218 {
219  const auto themap = m_label->particleDistributionsMap();
220  if (themap->empty())
221  return "";
222 
223  std::ostringstream result;
224  result << std::setprecision(12);
225  result << "\n" << indent() << "# Defining particles with parameter following a distribution\n";
226 
227  int index(1);
228  for (auto it = themap->begin(); it != themap->end(); ++it) {
229  const ParticleDistribution* p_particle_distr = it->first;
230 
231  const std::string units = p_particle_distr->mainUnits();
232 
233  ParameterDistribution par_distr = p_particle_distr->parameterDistribution();
234 
235  // building distribution functions
236  std::string s_distr = "distr_" + std::to_string(index);
237  result << indent() << s_distr << " = "
238  << pyfmt2::printDistribution(*par_distr.getDistribution(), units) << "\n";
239 
240  // building parameter distribution
241  std::string s_par_distr = "par_distr_" + std::to_string(index);
242 
243  result << indent() << s_par_distr << " = "
244  << pyfmt2::printParameterDistribution(par_distr, s_distr, units) << "\n";
245 
246  // linked parameters
247  std::vector<std::string> linked_pars = par_distr.getLinkedParameterNames();
248  if (!linked_pars.empty()) {
249  result << indent() << s_par_distr;
250  for (size_t i = 0; i < linked_pars.size(); ++i)
251  result << ".linkParameter(\"" << linked_pars[i] << "\")";
252  result << "\n";
253  }
254 
255  auto p_particle = INodeUtils::OnlyChildOfType<IParticle>(*p_particle_distr);
256  if (!p_particle)
257  continue;
258  result << indent() << it->second << " = ba.ParticleDistribution("
259  << m_label->labelParticle(p_particle) << ", " << s_par_distr << ")\n";
260  index++;
261  }
262  return result.str();
263 }
A parametric distribution function, for use with any model parameter.
const IDistribution1D * getDistribution() const
std::vector< std::string > getLinkedParameterNames() const
get list of linked parameter names
A particle type that is a parametric distribution of IParticle's.
ParameterDistribution parameterDistribution() const
Returns the distributed parameter data.
std::string mainUnits() const
std::string printParameterDistribution(const ParameterDistribution &par_distr, const std::string &distVarName, const std::string &units)
Definition: PyFmt2.cpp:127
std::string printDistribution(const IDistribution1D &par_distr, const std::string &units)
Prints distribution with constructor parameters in given units.
Definition: PyFmt2.cpp:117

References ParameterDistribution::getDistribution(), ParameterDistribution::getLinkedParameterNames(), indent(), m_label, ParticleDistribution::mainUnits(), ParticleDistribution::parameterDistribution(), pyfmt2::printDistribution(), and pyfmt2::printParameterDistribution().

Referenced by defineGetSample().

Here is the call graph for this function:

◆ defineParticleCompositions()

std::string SampleToPython::defineParticleCompositions ( ) const
private

Definition at line 265 of file SampleToPython.cpp.

266 {
267  const auto themap = m_label->particleCompositionMap();
268  if (themap->empty())
269  return "";
270  std::ostringstream result;
271  result << std::setprecision(12);
272  result << "\n" << indent() << "# Defining composition of particles at specific positions\n";
273  for (auto it = themap->begin(); it != themap->end(); ++it) {
274  const ParticleComposition* p_particle_composition = it->first;
275  std::string particle_composition_name = it->second;
276  result << indent() << particle_composition_name << " = ba.ParticleComposition()\n";
277  auto particle_list = INodeUtils::ChildNodesOfType<IParticle>(*p_particle_composition);
278  for (auto p_particle : particle_list) {
279  result << indent() << particle_composition_name << ".addParticle("
280  << m_label->labelParticle(p_particle) << ")\n";
281  }
282  setRotationInformation(p_particle_composition, particle_composition_name, result);
283  setPositionInformation(p_particle_composition, particle_composition_name, result);
284  }
285  return result.str();
286 }
A composition of particles at fixed positions.

References indent(), m_label, setPositionInformation(), and setRotationInformation().

Referenced by defineGetSample().

Here is the call graph for this function:

◆ defineLattices()

std::string SampleToPython::defineLattices ( ) const
private

Definition at line 288 of file SampleToPython.cpp.

289 {
290  const auto themap = m_label->latticeMap();
291  if (themap->empty())
292  return "";
293  std::ostringstream result;
294  result << std::setprecision(12);
295  result << "\n" << indent() << "# Defining 3D lattices\n";
296  for (auto it = themap->begin(); it != themap->end(); ++it) {
297  const Lattice* p_lattice = it->first;
298  std::string lattice_name = it->second;
299  kvector_t bas_a = p_lattice->getBasisVectorA();
300  kvector_t bas_b = p_lattice->getBasisVectorB();
301  kvector_t bas_c = p_lattice->getBasisVectorC();
302  result << indent() << lattice_name << " = ba.Lattice(\n";
303  result << indent() << indent() << "ba.kvector_t(" << pyfmt::printNm(bas_a.x()) << ", "
304  << pyfmt::printNm(bas_a.y()) << ", " << pyfmt::printNm(bas_a.z()) << "),\n";
305  result << indent() << indent() << "ba.kvector_t(" << pyfmt::printNm(bas_b.x()) << ", "
306  << pyfmt::printNm(bas_b.y()) << ", " << pyfmt::printNm(bas_b.z()) << "),\n";
307  result << indent() << indent() << "ba.kvector_t(" << pyfmt::printNm(bas_c.x()) << ", "
308  << pyfmt::printNm(bas_c.y()) << ", " << pyfmt::printNm(bas_c.z()) << "))\n";
309  }
310  return result.str();
311 }
A lattice with three basis vectors.
Definition: Lattice.h:28
kvector_t getBasisVectorB() const
Returns basis vector b.
Definition: Lattice.h:47
kvector_t getBasisVectorC() const
Returns basis vector c.
Definition: Lattice.h:50
kvector_t getBasisVectorA() const
Returns basis vector a.
Definition: Lattice.h:44
std::string printNm(double input)
Definition: PyFmt.cpp:57

References Lattice::getBasisVectorA(), Lattice::getBasisVectorB(), Lattice::getBasisVectorC(), indent(), m_label, pyfmt::printNm(), BasicVector3D< T >::x(), BasicVector3D< T >::y(), and BasicVector3D< T >::z().

Referenced by defineGetSample().

Here is the call graph for this function:

◆ defineCrystals()

std::string SampleToPython::defineCrystals ( ) const
private

Definition at line 313 of file SampleToPython.cpp.

314 {
315  const auto themap = m_label->crystalMap();
316  if (themap->empty())
317  return "";
318  std::ostringstream result;
319  result << std::setprecision(12);
320  result << "\n" << indent() << "# Defining crystals: basis particle + lattice\n";
321  for (auto it = themap->begin(); it != themap->end(); ++it) {
322  const Crystal* p_crystal = it->first;
323  std::string crystal_name = it->second;
324  auto p_lattice = INodeUtils::OnlyChildOfType<Lattice>(*p_crystal);
325  auto p_basis = INodeUtils::OnlyChildOfType<IParticle>(*p_crystal);
326  if (!p_lattice || !p_basis)
327  continue;
328  result << indent() << crystal_name << " = ba.Crystal(";
329  result << m_label->labelParticle(p_basis) << ", ";
330  result << m_label->labelLattice(p_lattice) << ")\n";
331  }
332  return result.str();
333 }
A crystal structure with a ParticleComposition as a basis.
Definition: Crystal.h:26

References indent(), and m_label.

Referenced by defineGetSample().

Here is the call graph for this function:

◆ defineMesoCrystals()

std::string SampleToPython::defineMesoCrystals ( ) const
private

Definition at line 335 of file SampleToPython.cpp.

336 {
337  const auto themap = m_label->mesocrystalMap();
338  if (themap->empty())
339  return "";
340  std::ostringstream result;
341  result << std::setprecision(12);
342  result << "\n" << indent() << "# Defining mesocrystals\n";
343  for (auto it = themap->begin(); it != themap->end(); ++it) {
344  const MesoCrystal* p_mesocrystal = it->first;
345  std::string mesocrystal_name = it->second;
346  auto p_crystal = INodeUtils::OnlyChildOfType<Crystal>(*p_mesocrystal);
347  auto p_outer_shape = INodeUtils::OnlyChildOfType<IFormFactor>(*p_mesocrystal);
348  if (!p_crystal || !p_outer_shape)
349  continue;
350  result << indent() << mesocrystal_name << " = ba.MesoCrystal(";
351  result << m_label->labelCrystal(p_crystal) << ", ";
352  result << m_label->labelFormFactor(p_outer_shape) << ")\n";
353  setRotationInformation(p_mesocrystal, mesocrystal_name, result);
354  setPositionInformation(p_mesocrystal, mesocrystal_name, result);
355  }
356  return result.str();
357 }
A particle with an internal structure of smaller particles.
Definition: MesoCrystal.h:26

References indent(), m_label, setPositionInformation(), and setRotationInformation().

Referenced by defineGetSample().

Here is the call graph for this function:

◆ defineInterferenceFunctions()

std::string SampleToPython::defineInterferenceFunctions ( ) const
private

Definition at line 359 of file SampleToPython.cpp.

360 {
361  const auto themap = m_label->interferenceFunctionMap();
362  if (themap->empty())
363  return "";
364  std::ostringstream result;
365  result << std::setprecision(12);
366  result << "\n" << indent() << "# Defining Interference Functions\n";
367  for (auto it = themap->begin(); it != themap->end(); ++it) {
368  const IInterferenceFunction* interference = it->first;
369 
370  if (dynamic_cast<const InterferenceFunctionNone*>(interference))
371  result << indent() << it->second << " = ba.InterferenceFunctionNone()\n";
372  else if (auto p_lattice_1d =
373  dynamic_cast<const InterferenceFunction1DLattice*>(interference)) {
374  result << indent() << it->second << " = ba.InterferenceFunction1DLattice("
375  << pyfmt::printNm(p_lattice_1d->getLength()) << ", "
376  << pyfmt::printDegrees(p_lattice_1d->getXi()) << ")\n";
377 
378  auto pdf = INodeUtils::OnlyChildOfType<IFTDecayFunction1D>(*p_lattice_1d);
379 
380  if (pdf->decayLength() != 0.0)
381  result << indent() << it->second << "_pdf = ba." << pdf->getName() << "("
382  << pyfmt2::argumentList(pdf) << ")\n"
383  << indent() << it->second << ".setDecayFunction(" << it->second << "_pdf)\n";
384  } else if (auto p_para_radial =
385  dynamic_cast<const InterferenceFunctionRadialParaCrystal*>(interference)) {
386  result << indent() << it->second << " = ba.InterferenceFunctionRadialParaCrystal("
387  << pyfmt::printNm(p_para_radial->peakDistance()) << ", "
388  << pyfmt::printNm(p_para_radial->dampingLength()) << ")\n";
389 
390  if (p_para_radial->kappa() != 0.0)
391  result << indent() << it->second << ".setKappa("
392  << pyfmt::printDouble(p_para_radial->kappa()) << ")\n";
393 
394  if (p_para_radial->domainSize() != 0.0)
395  result << indent() << it->second << ".setDomainSize("
396  << pyfmt::printDouble(p_para_radial->domainSize()) << ")\n";
397 
398  auto pdf = INodeUtils::OnlyChildOfType<IFTDistribution1D>(*p_para_radial);
399 
400  if (pdf->omega() != 0.0)
401  result << indent() << it->second << "_pdf = ba." << pdf->getName() << "("
402  << pyfmt2::argumentList(pdf) << ")\n"
403  << indent() << it->second << ".setProbabilityDistribution(" << it->second
404  << "_pdf)\n";
405  } else if (auto p_lattice_2d =
406  dynamic_cast<const InterferenceFunction2DLattice*>(interference)) {
407  const Lattice2D& lattice = p_lattice_2d->lattice();
408  result << indent() << it->second << " = ba.InterferenceFunction2DLattice("
409  << pyfmt::printNm(lattice.length1()) << ", " << pyfmt::printNm(lattice.length2())
410  << ", " << pyfmt::printDegrees(lattice.latticeAngle()) << ", "
411  << pyfmt::printDegrees(lattice.rotationAngle()) << ")\n";
412 
413  auto pdf = INodeUtils::OnlyChildOfType<IFTDecayFunction2D>(*p_lattice_2d);
414 
415  result << indent() << it->second << "_pdf = ba." << pdf->getName() << "("
416  << pyfmt2::argumentList(pdf) << ")\n"
417  << indent() << it->second << ".setDecayFunction(" << it->second << "_pdf)\n";
418 
419  if (p_lattice_2d->integrationOverXi() == true)
420  result << indent() << it->second << ".setIntegrationOverXi(True)\n";
421  } else if (auto p_lattice_2d =
422  dynamic_cast<const InterferenceFunctionFinite2DLattice*>(interference)) {
423  const Lattice2D& lattice = p_lattice_2d->lattice();
424  result << indent() << it->second << " = ba.InterferenceFunctionFinite2DLattice("
425  << pyfmt::printNm(lattice.length1()) << ", " << pyfmt::printNm(lattice.length2())
426  << ", " << pyfmt::printDegrees(lattice.latticeAngle()) << ", "
427  << pyfmt::printDegrees(lattice.rotationAngle()) << ", "
428  << p_lattice_2d->numberUnitCells1() << ", " << p_lattice_2d->numberUnitCells2()
429  << ")\n";
430 
431  if (p_lattice_2d->integrationOverXi() == true)
432  result << indent() << it->second << ".setIntegrationOverXi(True)\n";
433  } else if (auto p_para_2d =
434  dynamic_cast<const InterferenceFunction2DParaCrystal*>(interference)) {
435  std::vector<double> domainSize = p_para_2d->domainSizes();
436  const Lattice2D& lattice = p_para_2d->lattice();
437  result << indent() << it->second << " = ba.InterferenceFunction2DParaCrystal("
438  << pyfmt::printNm(lattice.length1()) << ", " << pyfmt::printNm(lattice.length2())
439  << ", " << pyfmt::printDegrees(lattice.latticeAngle()) << ", "
440  << pyfmt::printDegrees(lattice.rotationAngle()) << ", "
441  << pyfmt::printNm(p_para_2d->dampingLength()) << ")\n";
442 
443  if (domainSize[0] != 0.0 || domainSize[1] != 0.0)
444  result << indent() << it->second << ".setDomainSizes("
445  << pyfmt::printNm(domainSize[0]) << ", " << pyfmt::printNm(domainSize[1])
446  << ")\n";
447  if (p_para_2d->integrationOverXi() == true)
448  result << indent() << it->second << ".setIntegrationOverXi(True)\n";
449 
450  auto pdf_vector = INodeUtils::ChildNodesOfType<IFTDistribution2D>(*p_para_2d);
451  if (pdf_vector.size() != 2)
452  continue;
453  const IFTDistribution2D* pdf = pdf_vector[0];
454 
455  result << indent() << it->second << "_pdf_1 = ba." << pdf->getName() << "("
456  << pyfmt2::argumentList(pdf) << ")\n";
457 
458  pdf = pdf_vector[1];
459 
460  result << indent() << it->second << "_pdf_2 = ba." << pdf->getName() << "("
461  << pyfmt2::argumentList(pdf) << ")\n";
462  result << indent() << it->second << ".setProbabilityDistributions(" << it->second
463  << "_pdf_1, " << it->second << "_pdf_2)\n";
464  } else if (auto p_lattice_hd =
465  dynamic_cast<const InterferenceFunctionHardDisk*>(interference)) {
466  result << indent() << it->second << " = ba.InterferenceFunctionHardDisk("
467  << pyfmt::printNm(p_lattice_hd->radius()) << ", "
468  << pyfmt::printDouble(p_lattice_hd->density()) << ")\n";
469  } else
471  "Bug: ExportToPython::defineInterferenceFunctions() called with unexpected "
472  "IInterferenceFunction "
473  + interference->getName());
474  if (interference->positionVariance() > 0.0) {
475  result << indent() << it->second << ".setPositionVariance("
476  << pyfmt::printNm2(interference->positionVariance()) << ")\n";
477  }
478  }
479  return result.str();
480 }
Interface for two-dimensional distributions in Fourier space.
Pure virtual base class of interference functions.
double positionVariance() const
Returns the position variance.
Interference function of a 1D lattice.
Interference function of a 2D lattice.
Interference function of a 2D paracrystal.
Interference function of a finite 2D lattice.
Percus-Yevick hard disk interference function.
Default interference function (i.e.
Interference function of radial paracrystal.
double rotationAngle() const
Definition: Lattice2D.h:39
virtual double latticeAngle() const =0
virtual double length2() const =0
virtual double length1() const =0
std::string printNm2(double input)
Definition: PyFmt.cpp:65
std::string printDegrees(double input)
Definition: PyFmt.cpp:94

References pyfmt2::argumentList(), IParameterized::getName(), indent(), Lattice2D::latticeAngle(), Lattice2D::length1(), Lattice2D::length2(), m_label, IInterferenceFunction::positionVariance(), pyfmt::printDegrees(), pyfmt::printDouble(), pyfmt::printNm(), pyfmt::printNm2(), and Lattice2D::rotationAngle().

Referenced by defineGetSample().

Here is the call graph for this function:

◆ defineParticleLayouts()

std::string SampleToPython::defineParticleLayouts ( ) const
private

Definition at line 482 of file SampleToPython.cpp.

483 {
484  const auto themap = m_label->particleLayoutMap();
485  if (themap->empty())
486  return "";
487  std::ostringstream result;
488  result << std::setprecision(12);
489  result << "\n" << indent() << "# Defining Particle Layouts and adding Particles\n";
490  for (auto it = themap->begin(); it != themap->end(); ++it) {
491  const ILayout* iLayout = it->first;
492  if (const ParticleLayout* particleLayout = dynamic_cast<const ParticleLayout*>(iLayout)) {
493  result << indent() << it->second << " = ba.ParticleLayout()\n";
494  auto particles = INodeUtils::ChildNodesOfType<IAbstractParticle>(*particleLayout);
495 
496  for (auto p_particle : particles) {
497  double abundance = p_particle->abundance();
498  result << indent() << it->second << ".addParticle("
499  << m_label->labelParticle(p_particle) << ", "
500  << pyfmt::printDouble(abundance) << ")\n";
501  }
502  if (auto p_iff = INodeUtils::OnlyChildOfType<IInterferenceFunction>(*particleLayout))
503  result << indent() << it->second << ".setInterferenceFunction("
504  << m_label->labelInterferenceFunction(p_iff) << ")\n";
505  result << indent() << it->second << ".setWeight(" << particleLayout->weight() << ")\n";
506  result << indent() << it->second << ".setTotalParticleSurfaceDensity("
507  << particleLayout->totalParticleSurfaceDensity() << ")\n";
508  }
509  }
510  return result.str();
511 }
Pure virtual interface class to equip a sample layer with scattering properties.
Definition: ILayout.h:32
Decorator class that adds particles to ISample objects.

References indent(), m_label, and pyfmt::printDouble().

Referenced by defineGetSample().

Here is the call graph for this function:

◆ defineRoughnesses()

std::string SampleToPython::defineRoughnesses ( ) const
private

Definition at line 513 of file SampleToPython.cpp.

514 {
515  const auto themap = m_label->layerRoughnessMap();
516  if (themap->empty())
517  return "";
518  std::ostringstream result;
519  result << std::setprecision(12);
520  result << "\n" << indent() << "# Defining Roughness Parameters\n";
521  for (auto it = themap->begin(); it != themap->end(); ++it)
522  result << indent() << it->second << " = ba.LayerRoughness("
523  << pyfmt2::argumentList(it->first) << ")\n";
524  return result.str();
525 }

References pyfmt2::argumentList(), indent(), and m_label.

Referenced by defineGetSample().

Here is the call graph for this function:

◆ addLayoutsToLayers()

std::string SampleToPython::addLayoutsToLayers ( ) const
private

Definition at line 527 of file SampleToPython.cpp.

528 {
529  if (m_label->particleLayoutMap()->empty())
530  return "";
531  std::ostringstream result;
532  result << std::setprecision(12);
533  result << "\n" << indent() << "# Adding layouts to layers";
534  const auto layermap = m_label->layerMap();
535  for (auto it = layermap->begin(); it != layermap->end(); ++it) {
536  const Layer* layer = it->first;
537  for (auto p_layout : layer->layouts())
538  result << "\n"
539  << indent() << it->second << ".addLayout(" << m_label->labelLayout(p_layout)
540  << ")\n";
541  }
542  return result.str();
543 }
std::vector< const ILayout * > layouts() const
Definition: Layer.cpp:64

References indent(), Layer::layouts(), and m_label.

Referenced by defineGetSample().

Here is the call graph for this function:

◆ defineMultiLayers()

std::string SampleToPython::defineMultiLayers ( ) const
private

Definition at line 545 of file SampleToPython.cpp.

546 {
547  const auto themap = m_label->multiLayerMap();
548  if (themap->empty())
549  return "# No MultiLayers.\n\n";
550  std::ostringstream result;
551  result << std::setprecision(12);
552  result << "\n" << indent() << "# Defining Multilayers\n";
553  for (auto it = themap->begin(); it != themap->end(); ++it) {
554  result << indent() << it->second << " = ba.MultiLayer()\n";
555  double ccl = it->first->crossCorrLength();
556  if (ccl > 0.0)
557  result << indent() << it->second << ".setCrossCorrLength(" << ccl << ")\n";
558  auto external_field = it->first->externalField();
559  if (external_field.mag() > 0.0) {
560  std::string field_name = it->second + "_external_field";
561  result << indent() << field_name << " = kvector_t("
562  << pyfmt::printScientificDouble(external_field.x()) << ", "
563  << pyfmt::printScientificDouble(external_field.y()) << ", "
564  << pyfmt::printScientificDouble(external_field.z()) << ")\n";
565  result << indent() << it->second << ".setExternalField(" << field_name << ")\n";
566  }
567  size_t numberOfLayers = it->first->numberOfLayers();
568  if (numberOfLayers) {
569  result << indent() << it->second << ".addLayer("
570  << m_label->labelLayer(it->first->layer(0)) << ")\n";
571 
572  size_t layerIndex = 1;
573  while (layerIndex != numberOfLayers) {
574  const LayerInterface* layerInterface = it->first->layerInterface(layerIndex - 1);
575  if (m_label->layerRoughnessMap()->find(layerInterface->getRoughness())
576  == m_label->layerRoughnessMap()->end())
577  result << indent() << it->second << ".addLayer("
578  << m_label->labelLayer(it->first->layer(layerIndex)) << ")\n";
579  else
580  result << indent() << it->second << ".addLayerWithTopRoughness("
581  << m_label->labelLayer(it->first->layer(layerIndex)) << ", "
582  << m_label->labelRoughness(layerInterface->getRoughness()) << ")\n";
583  layerIndex++;
584  }
585  }
586  result << indent() << "return " << it->second << "\n";
587  }
588  return result.str();
589 }
Interface between two layers, possibly with roughness.
const LayerRoughness * getRoughness() const
Returns roughness of the interface.
std::string printScientificDouble(double input)
Definition: PyFmt.cpp:74

References LayerInterface::getRoughness(), indent(), m_label, and pyfmt::printScientificDouble().

Referenced by defineGetSample().

Here is the call graph for this function:

◆ indent()

◆ setRotationInformation()

void SampleToPython::setRotationInformation ( const IParticle particle,
std::string  particle_name,
std::ostringstream &  result 
) const
private

Definition at line 596 of file SampleToPython.cpp.

598 {
599  if (p_particle->rotation()) {
600  switch (p_particle->rotation()->getTransform3D().getRotationType()) {
601  case Transform3D::EULER: {
602  double alpha, beta, gamma;
603  p_particle->rotation()->getTransform3D().calculateEulerAngles(&alpha, &beta, &gamma);
604  result << indent() << name << "_rotation = ba.RotationEuler("
605  << pyfmt::printDegrees(alpha) << ", " << pyfmt::printDegrees(beta) << ", "
606  << pyfmt::printDegrees(gamma) << ")\n";
607  break;
608  }
609  case Transform3D::XAXIS: {
610  double alpha = p_particle->rotation()->getTransform3D().calculateRotateXAngle();
611  result << indent() << name << "_rotation = ba.RotationX(" << pyfmt::printDegrees(alpha)
612  << ")\n";
613  break;
614  }
615  case Transform3D::YAXIS: {
616  double alpha = p_particle->rotation()->getTransform3D().calculateRotateYAngle();
617  result << indent() << name << "_rotation = ba.RotationY(" << pyfmt::printDegrees(alpha)
618  << ")\n";
619  break;
620  }
621  case Transform3D::ZAXIS: {
622  double alpha = p_particle->rotation()->getTransform3D().calculateRotateZAngle();
623  result << indent() << name << "_rotation = ba.RotationZ(" << pyfmt::printDegrees(alpha)
624  << ")\n";
625  break;
626  }
627  }
628  result << indent() << name << ".setRotation(" << name << "_rotation)\n";
629  }
630 }

References Transform3D::calculateEulerAngles(), Transform3D::calculateRotateXAngle(), Transform3D::calculateRotateYAngle(), Transform3D::calculateRotateZAngle(), Transform3D::EULER, Transform3D::getRotationType(), IRotation::getTransform3D(), indent(), pyfmt::printDegrees(), IParticle::rotation(), Transform3D::XAXIS, Transform3D::YAXIS, and Transform3D::ZAXIS.

Referenced by defineCoreShellParticles(), defineMesoCrystals(), defineParticleCompositions(), and defineParticles().

Here is the call graph for this function:

◆ setPositionInformation()

void SampleToPython::setPositionInformation ( const IParticle particle,
std::string  particle_name,
std::ostringstream &  result 
) const
private

Definition at line 632 of file SampleToPython.cpp.

634 {
635  kvector_t pos = p_particle->position();
636  bool has_position_info = (pos != kvector_t());
637 
638  if (has_position_info) {
639  result << indent() << name << "_position = kvector_t(" << pyfmt::printNm(pos.x()) << ", "
640  << pyfmt::printNm(pos.y()) << ", " << pyfmt::printNm(pos.z()) << ")\n";
641 
642  result << indent() << name << ".setPosition(" << name << "_position)\n";
643  }
644 }
BasicVector3D< double > kvector_t
Definition: Vectors3D.h:21

References indent(), IParticle::position(), pyfmt::printNm(), BasicVector3D< T >::x(), BasicVector3D< T >::y(), and BasicVector3D< T >::z().

Referenced by defineCoreShellParticles(), defineMesoCrystals(), defineParticleCompositions(), and defineParticles().

Here is the call graph for this function:

Member Data Documentation

◆ m_label


The documentation for this class was generated from the following files: