1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
|
// ************************************************************************************************
//
// BornAgain: simulate and fit reflection and scattering
//
//! @file GUI/View/Device/ScanEditor.cpp
//! @brief Defines class ScanEditor.
//!
//! @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/View/Device/ScanEditor.h"
#include "Base/Axis/Frame.h"
#include "Base/Const/Units.h"
#include "GUI/Model/Axis/PointwiseAxisItem.h"
#include "GUI/Model/Beam/BeamDistributionItem.h"
#include "GUI/Model/Beam/SourceItems.h"
#include "GUI/Model/Project/ProjectDocument.h"
#include "GUI/Model/Sim/InstrumentsSet.h"
#include "GUI/View/Base/LayoutUtil.h"
#include "GUI/View/Device/AxisScanEditor.h"
#include "GUI/View/Device/DistributionEditor.h"
#include "GUI/View/Device/FootprintForm.h"
#include "GUI/View/Numeric/ComboUtil.h"
#include "GUI/View/Numeric/DSpinBox.h"
#include "GUI/View/Numeric/NumWidgetUtil.h"
ScanEditor::ScanEditor(QWidget* parent, InstrumentItem* instr_item, ScanItem* item, bool allow_phi,
bool allow_footprint, bool allow_distr)
: CollapsibleGroupBox("Beam and scan parameters", parent, item->expandBeamParameters)
, m_scan_item(item)
, m_instr_item(instr_item)
{
auto* layout = new QGridLayout(body());
layout->setAlignment(Qt::AlignTop);
//... Scan type
auto* scan_form = new QFormLayout;
scan_form->setFieldGrowthPolicy(QFormLayout::FieldsStayAtSizeHint);
layout->addLayout(scan_form, 0, 0);
ASSERT(item->scanTypeSelection().certainItem());
auto* typeCombo = GUI::Util::createComboBoxFromPolyPtr(
item->scanTypeSelection(),
[this, allow_phi, allow_footprint, allow_distr](int) {
updateScanWidgets(allow_phi, allow_footprint, allow_distr);
},
true);
scan_form->addRow("Scan type:", typeCombo);
// Hide non-physical scans (qz scan) from Offspecular instrument combo.
if (dynamic_cast<const OffspecInstrumentItem*>(m_instr_item))
for (int i = typeCombo->count() - 1; i >= 0; i--)
for (const auto type : ScanTypeCatalog::nonPhysicalTypes())
if (typeCombo->itemText(i) == ScanTypeCatalog::uiInfo(type).menuEntry)
typeCombo->removeItem(i);
//... Intensity
auto* form = new QFormLayout;
layout->addLayout(form, 1, 0);
form->setFieldGrowthPolicy(QFormLayout::FieldsStayAtSizeHint);
auto* intensity_spinbox = GUI::Util::addDoubleSpinBoxRow(form, item->intensity());
intensity_spinbox->setToolTip("Correction factor for normalized intensity");
//... Scan unit (deg vs 1/nm)
// TODO
m_beam_layout = new QHBoxLayout;
layout->addLayout(m_beam_layout, 2, 0);
updateScanWidgets(allow_phi, allow_footprint, allow_distr);
}
void ScanEditor::updateScanWidgets(bool allow_phi, bool allow_footprint, bool allow_distr)
{
GUI::Util::Layout::clearLayout(m_beam_layout);
ScanTypeItem* type = m_scan_item->scanTypeSelection().certainItem();
DistributionEditor* beamDistributionEditor = nullptr;
AxisScanEditor* scanEditor = nullptr;
auto upd_indicators = [this](AxisScanEditor* scanEditor) {
ASSERT(scanEditor);
if (auto* iiI = dynamic_cast<const SpecularInstrumentItem*>(m_instr_item))
if (auto* pw = dynamic_cast<PointwiseAxisItem*>(iiI->scanItem()->currentAxisItem()))
pw->updateAxIndicators(m_instr_item->makeFrame());
scanEditor->updateIndicators();
gDoc->setModified();
};
if (dynamic_cast<const QzScanTypeItem*>(type)) {
//... Qz scan
m_scan_item->scanDistributionItem()->setScaleFactor(1.);
m_scan_item->currentAxisItem()->axis().setProperties("1/nm", RealLimits::nonnegative());
scanEditor = new AxisScanEditor(this, m_scan_item, "Qz values", allow_distr);
m_beam_layout->addWidget(scanEditor);
upd_indicators(scanEditor);
return; // Important to leave the method and not create forms related to physical scans!
} else if (dynamic_cast<const AlphaScanTypeItem*>(type)) {
//... Wavelength
beamDistributionEditor =
new DistributionEditor("Wavelength", true, DistributionSelector::Category::All, this,
m_scan_item->wavelengthItem(), allow_distr);
m_beam_layout->addWidget(beamDistributionEditor);
//... Grazing angle scan
m_scan_item->scanDistributionItem()->setScaleFactor(Units::deg);
m_scan_item->currentAxisItem()->axis().setProperties("deg", RealLimits::limited(0, 90));
scanEditor = new AxisScanEditor(this, m_scan_item, "Grazing angles", allow_distr);
m_beam_layout->addWidget(scanEditor);
} else if (dynamic_cast<const LambdaScanTypeItem*>(type)) {
//... Wavelength scan
m_scan_item->scanDistributionItem()->setScaleFactor(1.);
m_scan_item->currentAxisItem()->axis().setProperties("nm", RealLimits::nonnegative());
scanEditor = new AxisScanEditor(this, m_scan_item, "Wavelengths", allow_distr);
m_beam_layout->addWidget(scanEditor);
//... Grazing angle
beamDistributionEditor =
new DistributionEditor("Grazing angle", true, DistributionSelector::Category::All, this,
m_scan_item->grazingAngleItem(), allow_distr);
m_beam_layout->addWidget(beamDistributionEditor);
} else
ASSERT_NEVER;
//... Azimuthal angle
if (allow_phi) {
auto* azimuthalEditor =
new DistributionEditor("Azimuthal angle", true, DistributionSelector::Category::All,
this, m_scan_item->azimuthalAngleItem(), allow_distr);
m_beam_layout->addWidget(azimuthalEditor);
}
//... Footprint
if (allow_footprint) {
auto* footprintEditor = new FootprintForm(this, m_scan_item);
m_beam_layout->addWidget(footprintEditor);
}
// Couple beam distribution and scan. Indicators have to be recalculated first, then updated.
ASSERT(beamDistributionEditor);
ASSERT(scanEditor);
connect(beamDistributionEditor, &DistributionEditor::distributionChanged,
[scanEditor, upd_indicators] {
// Update values in pointwise axis after a change of the distribution mean.
upd_indicators(scanEditor);
});
upd_indicators(scanEditor);
}
|