From 3f146be3d1ba21b7c915dd16fb529521b0fe015d Mon Sep 17 00:00:00 2001 From: Matthias Puchner <github@mpuchner.de> Date: Wed, 22 Dec 2021 06:33:05 +0100 Subject: [PATCH] complete parameter tree builder --- GUI/Model/Job/ParameterTreeUtils.cpp | 226 ++++++++++++++++++--------- GUI/Model/Job/ParameterTreeUtils.h | 11 +- 2 files changed, 160 insertions(+), 77 deletions(-) diff --git a/GUI/Model/Job/ParameterTreeUtils.cpp b/GUI/Model/Job/ParameterTreeUtils.cpp index 94135cc3020..0ea7c68acc2 100644 --- a/GUI/Model/Job/ParameterTreeUtils.cpp +++ b/GUI/Model/Job/ParameterTreeUtils.cpp @@ -19,21 +19,24 @@ #include "GUI/Model/Instrument/InstrumentItems.h" #include "GUI/Model/Job/JobItem.h" #include "GUI/Model/Material/MaterialItem.h" +#include "GUI/Model/Sample/FTDecayFunctionItemCatalogs.h" +#include "GUI/Model/Sample/FTDistributionItemCatalogs.h" #include "GUI/Model/Sample/FTDistributionItems.h" +#include "GUI/Model/Sample/FormFactorItemCatalog.h" #include "GUI/Model/Sample/InterferenceItemCatalog.h" #include "GUI/Model/Sample/InterferenceItems.h" +#include "GUI/Model/Sample/ItemWithParticlesCatalog.h" +#include "GUI/Model/Sample/Lattice2DItemCatalog.h" #include "GUI/Model/Sample/Lattice2DItems.h" #include "GUI/Model/Sample/LayerItem.h" +#include "GUI/Model/Sample/MesoCrystalItem.h" #include "GUI/Model/Sample/MultiLayerItem.h" +#include "GUI/Model/Sample/ParticleCompositionItem.h" #include "GUI/Model/Sample/ParticleCoreShellItem.h" #include "GUI/Model/Sample/ParticleItem.h" #include "GUI/Model/Sample/ParticleLayoutItem.h" +#include "GUI/Model/Sample/RotationItemCatalog.h" #include "GUI/Model/Types/VectorDescriptor.h" -#include "GUI/Util/Error.h" -#include <QStack> -#include <boost/polymorphic_cast.hpp> - -using boost::polymorphic_downcast; namespace { @@ -43,7 +46,7 @@ QString labelWithUnit(const QString& label, variant<QString, Unit> unit) : unitAsString(std::get<Unit>(unit)); if (!s.isEmpty()) - return label + "[" + s + "]"; + return label + " [" + s + "]"; return label; } @@ -88,6 +91,21 @@ void handleItem(ParameterContainerItem* container, QObject* tree, SessionItem* s } } +template <typename Catalog> +ParameterLabelItem* addLabel(ParameterLabelItem* parent, const QString& category, + const typename Catalog::CatalogedType* p) +{ + const auto title = category + " (" + Catalog::uiInfo(Catalog::type(p)).menuEntry + ")"; + return new ParameterLabelItem(title, parent); +} + +template <typename Catalog> +ParameterLabelItem* addLabel(ParameterLabelItem* parent, const typename Catalog::CatalogedType* p) +{ + const auto title = Catalog::uiInfo(Catalog::type(p)).menuEntry; + return new ParameterLabelItem(title, parent); +} + } // namespace ParameterTreeBuilder::ParameterTreeBuilder(JobItem* jobItem, bool recreateBackupValues) @@ -154,7 +172,7 @@ void ParameterTreeBuilder::addSample() addInterference(layoutLabel, layout); for (auto* p : layout->particles()) - addParticle(layoutLabel, p); + addParticle(layoutLabel, p, true); } } } @@ -166,7 +184,7 @@ void ParameterTreeBuilder::addInstrument() m_recreateBackupValues); } -void ParameterTreeBuilder::addParameterItem(ParameterLabelItem* parent, DoubleDescriptor d) +void ParameterTreeBuilder::addParameterItem(ParameterLabelItem* parent, const DoubleDescriptor& d) { auto* parameterItem = new ParameterItem(parent); parameterItem->setTitle(labelWithUnit(d.label, d.unit)); @@ -175,11 +193,12 @@ void ParameterTreeBuilder::addParameterItem(ParameterLabelItem* parent, DoubleDe m_jobItem->parameterContainerItem()->setBackupValue(parameterItem->link(), d.get()); } -void ParameterTreeBuilder::addParameterItem(ParameterLabelItem* parent, VectorDescriptor d) +void ParameterTreeBuilder::addParameterItem(ParameterLabelItem* parent, const VectorDescriptor& d) { - addParameterItem(parent, d.x); - addParameterItem(parent, d.y); - addParameterItem(parent, d.z); + auto* label = new ParameterLabelItem(d.label, parent); + addParameterItem(label, d.x); + addParameterItem(label, d.y); + addParameterItem(label, d.z); } ParameterContainerItem* ParameterTreeBuilder::parameterContainer() @@ -196,73 +215,132 @@ bool ParameterTreeBuilder::allowMagneticFields() const void ParameterTreeBuilder::addInterference(ParameterLabelItem* layoutLabel, const ParticleLayoutItem* layout) { - if (!layout->interference().currentItem()) + const auto* interference = layout->interference().currentItem(); + if (!interference) return; - const auto itfType = InterferenceItemCatalog::type(layout->interference().currentItem()); + const auto itfType = InterferenceItemCatalog::type(interference); const QString title = InterferenceItemCatalog::uiInfo(itfType).menuEntry; - auto* itfLabel = new ParameterLabelItem(title, layoutLabel); - - Q_UNUSED(itfLabel); // temporary - // later in handleItems the rotation of an interference may have to be ignored. - // #baMigration implement the following! - // if (auto* c = dynamic_cast<Interference2DAbstractLatticeItem*>(child)) - // if (c->latticeType().currentItem()) - // c->latticeType().currentItem()->enableRotationAngle(!c->xiIntegration()); - - // #baMigration see the following! - // if PDF1 and PDF2 are of same type, add a number to the name - // if (auto* itf = dynamic_cast<Interference2DParaCrystalItem*>( - // layout->interference().currentItem())) { - // SessionItem* pdf1 = itf->probabilityDistribution1().currentItem(); - // SessionItem* pdf2 = itf->probabilityDistribution2().currentItem(); - // - // if (pdf1 && pdf2) { - // if (pdf1->modelType() == pdf2->modelType()) { - // pdf1->setDisplayName(pdf1->modelType() + "0"); - // pdf2->setDisplayName(pdf2->modelType() + "1"); - // } else { - // pdf1->setDisplayName(pdf1->modelType()); - // pdf2->setDisplayName(pdf2->modelType()); - // } - // } - //} - - throw std::logic_error("The method or operation is not implemented."); + auto* itfLabel = new ParameterLabelItem("Interference (" + title + ")", layoutLabel); + + + if (const auto* itf = dynamic_cast<const InterferenceRadialParaCrystalItem*>(interference)) { + addParameterItem(itfLabel, itf->positionVariance()); + addParameterItem(itfLabel, itf->peakDistance()); + addParameterItem(itfLabel, itf->dampingLength()); + addParameterItem(itfLabel, itf->domainSize()); + addParameterItem(itfLabel, itf->kappa()); + + const auto* pdf = itf->probabilityDistribution().currentItem(); + auto* pdfLabel = addLabel<FTDistribution1DItemCatalog>(itfLabel, "PDF", pdf); + for (const auto& d : pdf->valueDescriptors()) + addParameterItem(pdfLabel, d); + } else if (const auto* itf = dynamic_cast<const Interference2DParaCrystalItem*>(interference)) { + addParameterItem(itfLabel, itf->positionVariance()); + addParameterItem(itfLabel, itf->dampingLength()); + addParameterItem(itfLabel, itf->domainSize1()); + addParameterItem(itfLabel, itf->domainSize2()); + addLattice(itfLabel, itf); + + const auto* pdf1 = itf->probabilityDistribution1().currentItem(); + const auto* pdf2 = itf->probabilityDistribution2().currentItem(); + const bool samePdfTypes = + FTDistribution2DItemCatalog::type(pdf1) == FTDistribution2DItemCatalog::type(pdf2); + auto* pdf1Label = + addLabel<FTDistribution2DItemCatalog>(itfLabel, samePdfTypes ? "PDF1" : "PDF", pdf1); + for (const auto& d : pdf1->valueDescriptors()) + addParameterItem(pdf1Label, d); + auto* pdf2Label = + addLabel<FTDistribution2DItemCatalog>(itfLabel, samePdfTypes ? "PDF2" : "PDF", pdf2); + for (const auto& d : pdf2->valueDescriptors()) + addParameterItem(pdf2Label, d); + } else if (const auto* itf = dynamic_cast<const Interference1DLatticeItem*>(interference)) { + addParameterItem(itfLabel, itf->positionVariance()); + addParameterItem(itfLabel, itf->length()); + addParameterItem(itfLabel, itf->rotationAngle()); + + const auto* df = itf->decayFunction().currentItem(); + auto* dfLabel = addLabel<FTDecayFunction1DItemCatalog>(itfLabel, "Decay function", df); + for (const auto& d : df->valueDescriptors()) + addParameterItem(dfLabel, d); + } else if (const auto* itf = dynamic_cast<const Interference2DLatticeItem*>(interference)) { + addParameterItem(itfLabel, itf->positionVariance()); + addLattice(itfLabel, itf); + + const auto* df = itf->decayFunction().currentItem(); + auto* dfLabel = addLabel<FTDecayFunction2DItemCatalog>(itfLabel, "Decay function", df); + for (const auto& d : df->valueDescriptors()) + addParameterItem(dfLabel, d); + } else if (const auto* itf = + dynamic_cast<const InterferenceFinite2DLatticeItem*>(interference)) { + // domainSize1 and domainSize2 are of type UInt (not matching the double approach for tuning + // and fitting). In BornAgain 1.18 these values have not been added to the tuning tree, and + // also not to the fitting parameters. Maybe this should be necessary, but for now this + // stays the same and the two sizes are not added + addParameterItem(itfLabel, itf->positionVariance()); + addLattice(itfLabel, itf); + } else if (const auto* itf = dynamic_cast<const InterferenceHardDiskItem*>(interference)) { + addParameterItem(itfLabel, itf->positionVariance()); + addParameterItem(itfLabel, itf->radius()); + addParameterItem(itfLabel, itf->density()); + } } -void ParameterTreeBuilder::addParticle(ParameterLabelItem* parentLabel, ItemWithParticles* p) +void ParameterTreeBuilder::addParticle(ParameterLabelItem* parentLabel, ItemWithParticles* p, + bool enableAbundance, bool enablePosition) { - Q_UNUSED(parentLabel); // temporary - Q_UNUSED(p); // temporary - // #baMigration implement the following! - // if (auto* c = dynamic_cast<ItemWithParticles*>(child)) - // c->enableAbundance(!c->parentHasOwnAbundance()); - // - // function was: - // - // bool ItemWithParticles::parentHasOwnAbundance() const - // { - // return dynamic_cast<ParticleCoreShellItem*>(parent()) - // || dynamic_cast<ParticleCompositionItem*>(parent()) - // || dynamic_cast<MesoCrystalItem*>(parent()); - // } - - - // - // later in handleItems the position of a shell particle has to be ignored. - // #baMigration implement the following! - // if (auto* c = dynamic_cast<ParticleCoreShellItem*>(child)) - // if (c->shell()) - // c->shell()->positionItem()->setEnabled(false); - - // later in handleItems the rotation of an interference may have to be ignored. - // #baMigration implement the following! - // if (auto* c = dynamic_cast<Interference2DAbstractLatticeItem*>(child)) - // if (c->latticeType().currentItem()) - // c->latticeType().currentItem()->enableRotationAngle(!c->xiIntegration()); - - - throw std::logic_error("The method or operation is not implemented."); + auto* particleLabel = addLabel<ItemWithParticlesCatalog>(parentLabel, p); + + if (enableAbundance) + addParameterItem(particleLabel, p->abundance()); + if (enablePosition) + addParameterItem(particleLabel, p->positionVector()); + addRotation(particleLabel, p); + + if (const auto* particle = dynamic_cast<const ParticleItem*>(p)) { + const auto* formFactor = particle->formfactor(); + auto* ffLabel = addLabel<FormFactorItemCatalog>(particleLabel, "Formfactor", formFactor); + for (const auto& d : formFactor->geometryValues()) + addParameterItem(ffLabel, d); + } else if (const auto* particleComposition = dynamic_cast<const ParticleCompositionItem*>(p)) { + for (auto* p : particleComposition->particles()) + addParticle(particleLabel, p, false); + } else if (const auto* coreShell = dynamic_cast<const ParticleCoreShellItem*>(p)) { + // #baMigration improve: add "Core"/"Shell" to label title + addParticle(particleLabel, coreShell->core(), false); + addParticle(particleLabel, coreShell->shell(), false, false); + } else if (const auto* meso = dynamic_cast<const MesoCrystalItem*>(p)) { + addParameterItem(particleLabel, meso->vectorA()); + addParameterItem(particleLabel, meso->vectorB()); + addParameterItem(particleLabel, meso->vectorC()); + + const auto* outerShape = meso->outerShape().currentItem(); + auto* ffLabel = addLabel<FormFactorItemCatalog>(particleLabel, "Outer shape", outerShape); + for (const auto& d : outerShape->geometryValues()) + addParameterItem(ffLabel, d); + + // #baMigration improve: add "Basisparticle" to label title + addParticle(particleLabel, meso->basisParticle(), false); + } +} + +void ParameterTreeBuilder::addLattice(ParameterLabelItem* parentLabel, + const Interference2DAbstractLatticeItem* itf) +{ + const auto* lattice = itf->latticeType().currentItem(); + auto* latticeLabel = addLabel<Lattice2DItemCatalog>(parentLabel, "Lattice", lattice); + for (const auto& d : lattice->geometryValues(!itf->xiIntegration())) + addParameterItem(latticeLabel, d); +} + +void ParameterTreeBuilder::addRotation(ParameterLabelItem* parentLabel, ItemWithParticles* p) +{ + const auto* r = p->rotationMethod().currentItem(); + if (!r) + return; + + auto* label = addLabel<RotationItemCatalog>(parentLabel, "Rotation", r); + for (const auto& d : r->rotationValues()) + addParameterItem(label, d); } diff --git a/GUI/Model/Job/ParameterTreeUtils.h b/GUI/Model/Job/ParameterTreeUtils.h index 1ba47e89df7..d708ce92ebc 100644 --- a/GUI/Model/Job/ParameterTreeUtils.h +++ b/GUI/Model/Job/ParameterTreeUtils.h @@ -27,6 +27,7 @@ class DoubleDescriptor; class VectorDescriptor; class ParticleLayoutItem; class ItemWithParticles; +class Interference2DAbstractLatticeItem; //! The ParameterTreeBuilder contains helper functions to create container //! with ParameterItems. The ParameterItem appears in RealTimeView and provides real @@ -45,13 +46,17 @@ private: //! add the job's sample void addSample(); void addInstrument(); - void addParameterItem(ParameterLabelItem* parent, DoubleDescriptor d); - void addParameterItem(ParameterLabelItem* parent, VectorDescriptor d); + void addParameterItem(ParameterLabelItem* parent, const DoubleDescriptor& d); + void addParameterItem(ParameterLabelItem* parent, const VectorDescriptor& d); ParameterContainerItem* parameterContainer(); bool allowMagneticFields() const; void addInterference(ParameterLabelItem* layoutLabel, const ParticleLayoutItem* layout); - void addParticle(ParameterLabelItem* parentLabel, ItemWithParticles* p); + void addParticle(ParameterLabelItem* parentLabel, ItemWithParticles* p, bool enableAbundance, + bool enablePosition = true); + void addLattice(ParameterLabelItem* parentLabel, const Interference2DAbstractLatticeItem* itf); + void addRotation(ParameterLabelItem* parentLabel, ItemWithParticles* p); + private: JobItem* m_jobItem; -- GitLab