-
Matthias Puchner authoredMatthias Puchner authored
MesoCrystalItem.cpp 7.42 KiB
// ************************************************************************************************
//
// BornAgain: simulate and fit reflection and scattering
//
//! @file GUI/coregui/Models/MesoCrystalItem.cpp
//! @brief Implements class MesoCrystalItem
//!
//! @homepage http://www.bornagainproject.org
//! @license GNU General Public License v3 or higher (see COPYING)
//! @copyright Forschungszentrum Jülich GmbH 2018
//! @authors Scientific Computing Group at MLZ (see CITATION, AUTHORS)
//
// ************************************************************************************************
#include "GUI/coregui/Models/MesoCrystalItem.h"
#include "GUI/coregui/Models/ComboProperty.h"
#include "GUI/coregui/Models/FormFactorItems.h"
#include "GUI/coregui/Models/ModelPath.h"
#include "GUI/coregui/Models/ParticleCompositionItem.h"
#include "GUI/coregui/Models/ParticleCoreShellItem.h"
#include "GUI/coregui/Models/ParticleItem.h"
#include "GUI/coregui/Models/SessionItemUtils.h"
#include "GUI/coregui/Models/TransformToDomain.h"
#include "GUI/coregui/Models/VectorItem.h"
#include "GUI/coregui/utils/GUIHelpers.h"
#include "Sample/Particle/Crystal.h"
#include "Sample/Particle/MesoCrystal.h"
#include "Sample/Particle/Particle.h"
#include "Sample/Particle/ParticleCoreShell.h"
#include "Sample/Scattering/IFormFactor.h"
namespace {
const QString abundance_tooltip = "Proportion of this type of mesocrystal normalized to the \n"
"total number of particles in the layout";
const QString lattice_vector1_tooltip = "Coordinates of the first lattice vector";
const QString lattice_vector2_tooltip = "Coordinates of the second lattice vector";
const QString lattice_vector3_tooltip = "Coordinates of the third lattice vector";
const QString position_tooltip = "Relative position of the mesocrystal's reference point \n"
"in the coordinate system of the parent (nm)";
const QString density_tooltip =
"Number of mesocrystals per square nanometer (particle surface density).\n "
"Should be defined for disordered and 1d-ordered particle collections.";
bool IsIParticleName(QString name)
{
return (name.startsWith("Particle") || name.startsWith("ParticleComposition")
|| name.startsWith("ParticleCoreShell") || name.startsWith("MesoCrystal"));
}
} // namespace
const QString MesoCrystalItem::P_OUTER_SHAPE = "Outer Shape";
const QString MesoCrystalItem::T_BASIS_PARTICLE = "Basis Particle";
const QString MesoCrystalItem::P_VECTOR_A = "First lattice vector";
const QString MesoCrystalItem::P_VECTOR_B = "Second lattice vector";
const QString MesoCrystalItem::P_VECTOR_C = "Third lattice vector";
// TODO make derived from ParticleItem
MesoCrystalItem::MesoCrystalItem() : SessionGraphicsItem("MesoCrystal")
{
setToolTip("A 3D crystal structure of nanoparticles");
addGroupProperty(P_OUTER_SHAPE, "Form Factor");
addProperty(ParticleItem::P_ABUNDANCE, 1.0)
->setLimits(RealLimits::limited(0.0, 1.0))
.setDecimals(3)
.setToolTip(abundance_tooltip);
addProperty<VectorItem>(P_VECTOR_A)->setToolTip(lattice_vector1_tooltip);
addProperty<VectorItem>(P_VECTOR_B)->setToolTip(lattice_vector2_tooltip);
addProperty<VectorItem>(P_VECTOR_C)->setToolTip(lattice_vector3_tooltip);
addProperty<VectorItem>(ParticleItem::P_POSITION)->setToolTip(position_tooltip);
registerTag(T_BASIS_PARTICLE, 0, 1,
QStringList() << "Particle"
<< "ParticleCoreShell"
<< "ParticleComposition"
<< "MesoCrystal");
setDefaultTag(T_BASIS_PARTICLE);
registerTag(ParticleItem::T_TRANSFORMATION, 0, 1, QStringList() << "Rotation");
addTranslator(VectorParameterTranslator(ParticleItem::P_POSITION, "Position"));
addTranslator(RotationTranslator());
QStringList additional_names{QString::fromStdString("Lattice"),
QString::fromStdString("Crystal")};
addTranslator(VectorParameterTranslator(P_VECTOR_A, "BasisA", additional_names));
addTranslator(VectorParameterTranslator(P_VECTOR_B, "BasisB", additional_names));
addTranslator(VectorParameterTranslator(P_VECTOR_C, "BasisC", additional_names));
mapper()->setOnParentChange([this](SessionItem* parent) {
if (SessionItemUtils::HasOwnAbundance(parent)) {
setItemValue(ParticleItem::P_ABUNDANCE, 1.0);
getItem(ParticleItem::P_ABUNDANCE)->setEnabled(false);
} else {
getItem(ParticleItem::P_ABUNDANCE)->setEnabled(true);
}
});
}
VectorItem* MesoCrystalItem::positionItem() const
{
return item<VectorItem>(ParticleItem::P_POSITION);
}
std::unique_ptr<MesoCrystal> MesoCrystalItem::createMesoCrystal() const
{
const Lattice3D& lattice = getLattice();
if (!(lattice.unitCellVolume() > 0.0))
throw GUIHelpers::Error("MesoCrystalItem::createMesoCrystal(): "
"Lattice volume not strictly positive");
std::unique_ptr<IParticle> basis = getBasis();
if (!basis)
throw GUIHelpers::Error("MesoCrystalItem::createMesoCrystal(): "
"No basis particle defined");
Crystal crystal(*basis, lattice);
std::unique_ptr<IFormFactor> ff = getOuterShape();
if (!ff)
throw GUIHelpers::Error("MesoCrystalItem::createMesoCrystal(): "
"No outer shape defined");
auto result = std::make_unique<MesoCrystal>(crystal, *ff);
TransformToDomain::setTransformationInfo(result.get(), *this);
return result;
}
QStringList MesoCrystalItem::translateList(const QStringList& list) const
{
QStringList result = list;
// Add CrystalType to path name of basis particle
if (IsIParticleName(list.back()))
result << QString::fromStdString("Crystal"); // this result is overwritten in any case with the next line
result = SessionItem::translateList(result);
return result;
}
Lattice3D MesoCrystalItem::getLattice() const
{
const kvector_t a1 = item<VectorItem>(P_VECTOR_A)->getVector();
const kvector_t a2 = item<VectorItem>(P_VECTOR_B)->getVector();
const kvector_t a3 = item<VectorItem>(P_VECTOR_C)->getVector();
return Lattice3D(a1, a2, a3);
}
std::unique_ptr<IParticle> MesoCrystalItem::getBasis() const
{
QVector<SessionItem*> childlist = children();
for (int i = 0; i < childlist.size(); ++i) {
if (childlist[i]->modelType() == "Particle") {
auto* particle_item = static_cast<ParticleItem*>(childlist[i]);
return particle_item->createParticle();
} else if (childlist[i]->modelType() == "ParticleCoreShell") {
auto* particle_coreshell_item = static_cast<ParticleCoreShellItem*>(childlist[i]);
return particle_coreshell_item->createParticleCoreShell();
} else if (childlist[i]->modelType() == "ParticleComposition") {
auto* particlecomposition_item = static_cast<ParticleCompositionItem*>(childlist[i]);
return particlecomposition_item->createParticleComposition();
} else if (childlist[i]->modelType() == "MesoCrystal") {
auto* mesocrystal_item = static_cast<MesoCrystalItem*>(childlist[i]);
return mesocrystal_item->createMesoCrystal();
}
}
return {};
}
std::unique_ptr<IFormFactor> MesoCrystalItem::getOuterShape() const
{
auto& ff_item = groupItem<FormFactorItem>(MesoCrystalItem::P_OUTER_SHAPE);
return ff_item.createFormFactor();
}