// ************************************************************************************************ // // BornAgain: simulate and fit reflection and scattering // //! @file GUI/Model/Job/ParameterTreeUtils.cpp //! @brief Implements ParameterTreeUtils namespace //! //! @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/Model/Job/ParameterTreeUtils.h" #include "GUI/Model/Fit/ParameterTreeItems.h" #include "GUI/Model/Group/GroupItem.h" #include "GUI/Model/Group/PropertyItem.h" #include "GUI/Model/Instrument/InstrumentItems.h" #include "GUI/Model/Job/JobItem.h" #include "GUI/Model/Material/MaterialItem.h" #include "GUI/Model/Sample/InterferenceItems.h" #include "GUI/Model/Sample/Lattice2DItems.h" #include "GUI/Model/Sample/LayerItem.h" #include "GUI/Model/Sample/MultiLayerItem.h" #include "GUI/Model/Sample/ParticleCoreShellItem.h" #include "GUI/Model/Sample/ParticleItem.h" #include "GUI/Model/Sample/ParticleLayoutItem.h" #include "GUI/Model/Session/ModelPath.h" #include "GUI/Model/Types/VectorDescriptor.h" #include "GUI/Util/Error.h" #include <QStack> #include <boost/polymorphic_cast.hpp> using boost::polymorphic_downcast; namespace { void handleItem(ParameterContainerItem* container, SessionItem* tree, SessionItem* source, bool recreateBackupValues) { if (tree->hasModelType<ParameterLabelItem>()) tree->setDisplayName(source->itemName()); else if (tree->hasModelType<ParameterItem>()) { tree->setDisplayName(source->itemName()); const double sourceValue = source->value().toDouble(); tree->setValue(QVariant(sourceValue)); auto* parItem = polymorphic_downcast<ParameterItem*>(tree); parItem->linkToSessionItem(source); if (recreateBackupValues) container->setBackupValue(parItem->link(), sourceValue); return; } else return; for (SessionItem* child : source->children()) { // later in handleItems the position of a shell particle has to be ignored. 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. if (auto* c = dynamic_cast<Interference2DAbstractLatticeItem*>(child)) if (c->latticeType().currentItem()) c->latticeType().currentItem()->enableRotationAngle(!c->xiIntegration()); if (child->isVisible() && child->isEnabled()) { if (child->hasModelType<PropertyItem>()) { if (child->value().type() == QVariant::Double) { auto* branch = tree->model()->insertItem<ParameterItem>(tree); handleItem(container, branch, child, recreateBackupValues); } } else if (child->hasModelType<GroupItem>()) { SessionItem* currentItem = dynamic_cast<GroupItem*>(child)->currentItem(); if (currentItem && currentItem->numberOfChildren() > 0) { auto* branch = tree->model()->insertItem<ParameterLabelItem>(tree); handleItem(container, branch, currentItem, recreateBackupValues); } } else { auto* branch = tree->model()->insertItem<ParameterLabelItem>(tree); handleItem(container, branch, child, recreateBackupValues); } } } } //! Populates ParameterContainer with ParameterItem's corresponding to all properties found //! in a source item. void populateParameterContainer(ParameterContainerItem* container, SessionItem* source, bool recreateBackupValues) { auto* sourceLabel = container->model()->insertItem<ParameterLabelItem>(container); handleItem(container, sourceLabel, source, recreateBackupValues); } } // namespace void GUI::Model::ParameterTreeUtils::createParameterTree(JobItem* jobItem, bool recreateBackupValues) { auto* container = jobItem->parameterContainerItem(); if (!container) container = jobItem->createParameterContainerItem(); // add the job's materials auto* materialTopLabel = container->model()->insertItem<ParameterLabelItem>(container); materialTopLabel->setDisplayName("Materials"); for (auto* material : jobItem->materialItems().materialItems()) { auto* materialLabel = container->model()->insertItem<ParameterLabelItem>(container); materialLabel->setDisplayName(material->materialName()); DoubleDescriptors descriptors; if (material->hasRefractiveIndex()) descriptors << material->delta() << material->beta(); else descriptors << material->sldRe() << material->sldIm(); // TODO: remove when specular instrument is ready for magnetization if (!jobItem->isSpecularJob()) descriptors << material->magnetizationVector().x << material->magnetizationVector().y << material->magnetizationVector().z; for (const auto& d : descriptors) { auto* materialValue = materialLabel->model()->insertItem<ParameterItem>(materialLabel); materialValue->setDisplayName(d.label); materialValue->setValue(QVariant(d.get())); materialValue->linkToDescriptor(d); if (recreateBackupValues) container->setBackupValue(materialValue->link(), d.get()); } } // add sample. // #baMigration To ignore thickness/roughness, they are disabled. This has to be changed after // SessionModel migration. Compare also to handling in // LayerForm::updateLayerPositionDependentElements() // dto. for totalDensity of particle layout for (auto* layer : jobItem->sampleItem()->layers()) { const bool isFirstLayer = jobItem->sampleItem()->layers().first() == layer; const bool isLastLayer = jobItem->sampleItem()->layers().last() == layer; layer->setRoughnessEnabled(!isFirstLayer); layer->setThicknessEnabled(!isFirstLayer && !isLastLayer); for (auto* layout : layer->layouts()) layout->enableDensity(!layout->totalDensityIsDefinedByInterference()); } populateParameterContainer(container, jobItem->sampleItem(), recreateBackupValues); // add instrument populateParameterContainer(container, jobItem->instrumentItem(), recreateBackupValues); }