diff --git a/GUI/Model/Device/InstrumentItems.cpp b/GUI/Model/Device/InstrumentItems.cpp index f7e45aa69ac4a855528898133caa98bdf3f0431a..181bd7ecf0cfa3de449278e190e195908f709a9a 100644 --- a/GUI/Model/Device/InstrumentItems.cpp +++ b/GUI/Model/Device/InstrumentItems.cpp @@ -284,7 +284,7 @@ Frame InstrumentItem::makeFrame() const } // ************************************************************************************************ -// class ScanningItem +// class ScanningFunctionality // ************************************************************************************************ ScanningFunctionality::ScanningFunctionality(double intensity) @@ -360,108 +360,83 @@ void ScanningFunctionality::readScanFrom(QXmlStreamReader* r) } } - // ************************************************************************************************ -// class SpecularInstrumentItem +// class GISASInstrumentItem // ************************************************************************************************ -SpecularInstrumentItem::SpecularInstrumentItem() - : ScanningFunctionality(1e6) -{ -} - -std::vector<int> SpecularInstrumentItem::axdims() const +GISASInstrumentItem::GISASInstrumentItem() { - return {scanItem()->inclinationAxisItem()->size()}; + m_detector_item = std::make_unique<DetectorItem>(); + m_beam_item = std::make_unique<BeamItem>(); } -void SpecularInstrumentItem::updateToRealData(const DatafileItem* dfileItem) +std::vector<int> GISASInstrumentItem::axdims() const { - if (axdims().size() != dfileItem->axdims().size()) - throw std::runtime_error("Specular instrument type is incompatible with passed data shape"); - - const auto& dataAxis = dfileItem->dataItem()->c_field()->axis(0); - scanItem()->updateToData(dataAxis); - scanItem()->grazingScanItem()->updateAxIndicators(makeFrame()); + ASSERT(detectorItem()); + return {(int)detectorItem()->phiAxis().nbins(), (int)detectorItem()->alphaAxis().nbins()}; } -bool SpecularInstrumentItem::alignedWith(const DatafileItem* dfileItem) const +void GISASInstrumentItem::updateToRealData(const DatafileItem* dfileItem) { - if (!dfileItem->holdsDimensionalData()) - return scanItem()->grazingScanItem()->uniformAlphaAxisSelected() - && axdims() == dfileItem->axdims(); - - if (!scanItem()->grazingScanItem()->pointwiseAlphaAxisSelected()) - return false; - - const auto* axisItem = - dynamic_cast<const PointwiseAxisItem*>(scanItem()->grazingScanItem()->alphaAxisItem()); - ASSERT(axisItem); - - const auto* instrumentAxis = axisItem->axis(); - if (!instrumentAxis) - return false; + if (!dfileItem) + return; - const auto& native_axis = dfileItem->dataItem()->c_field()->axis(0); - return *instrumentAxis == native_axis; + const auto data_shape = dfileItem->axdims(); + if (axdims().size() != data_shape.size()) + throw std::runtime_error("GISAS instrument type is incompatible with passed data shape."); + ASSERT(detectorItem()); + detectorItem()->phiAxis().setNbins(data_shape[0]); + detectorItem()->alphaAxis().setNbins(data_shape[1]); } -std::unique_ptr<Frame> SpecularInstrumentItem::createFrame() const +std::unique_ptr<Frame> GISASInstrumentItem::createFrame() const { - auto* axis_item = scanItem()->inclinationAxisItem(); - ASSERT(axis_item); - - if (auto* pointwise_axis = dynamic_cast<PointwiseAxisItem*>(axis_item)) { - const Scale* pAxis = pointwise_axis->axis(); - if (!pAxis) // workaround for loading project - return {}; - - if (pAxis->unit() == "1/nm") { - double lambda = scanItem()->wavelength(); - Scale ax = - pAxis->transformedScale(Coordinate("alpha_i", "rad").label(), [lambda](double qz) { - return std::asin(qz * lambda / 4 / pi); - }); - return std::make_unique<Frame>(ax.clone()); - } - return std::make_unique<Frame>(pAxis->clone()); - } - - Scale axis = axis_item->makeScale("alpha_i (rad)"); - return std::make_unique<Frame>(axis.clone()); + return std::make_unique<Frame>(normalDetector()->clippedFrame()); } -ISimulation* SpecularInstrumentItem::createSimulation(const MultiLayer& sample) const +ISimulation* GISASInstrumentItem::createSimulation(const MultiLayer& sample) const { - auto frame = createFrame(); - std::unique_ptr<BeamScan> scan = createScan(frame->axis(0)); + const auto beam = beamItem()->createBeam(); if (withPolarizer()) - scan->setPolarization(m_polarizer_bloch_vector); + beam->setPolarization(m_polarizer_bloch_vector); + const auto detector = detectorItem()->createDetector(); if (withAnalyzer()) - scan->setAnalyzer(m_analyzer_bloch_vector); - auto* result = new SpecularSimulation(*scan, sample); + detector->setAnalyzer(m_analyzer_bloch_vector); + auto* result = new ScatteringSimulation(*beam, sample, *detector); + + setBeamDistribution(ParameterDistribution::BeamWavelength, beamItem()->wavelengthItem(), + result); + setBeamDistribution(ParameterDistribution::BeamInclinationAngle, + beamItem()->beamDistributionItem(), result); + setBeamDistribution(ParameterDistribution::BeamAzimuthalAngle, beamItem()->azimuthalAngleItem(), + result); if (const auto background = backgroundItem()->createBackground()) result->setBackground(*background); return result; } -void SpecularInstrumentItem::writeTo(QXmlStreamWriter* w) const +void GISASInstrumentItem::writeTo(QXmlStreamWriter* w) const { XML::writeAttribute(w, XML::Attrib::version, uint(1)); - // instrument parameters from base class + // parameters from base class w->writeStartElement(Tag::BaseData); InstrumentItem::writeTo(w); w->writeEndElement(); - // scan parameters from base class - w->writeStartElement(Tag::ScanParameters); - ScanningFunctionality::writeScanTo(w); + // beam + w->writeStartElement(Tag::Beam); + m_beam_item->writeTo(w); + w->writeEndElement(); + + // detector + w->writeStartElement(Tag::Detector); + m_detector_item->writeTo(w); w->writeEndElement(); } -void SpecularInstrumentItem::readFrom(QXmlStreamReader* r) +void GISASInstrumentItem::readFrom(QXmlStreamReader* r) { const uint version = XML::readUIntAttribute(r, XML::Attrib::version); Q_UNUSED(version) @@ -469,14 +444,19 @@ void SpecularInstrumentItem::readFrom(QXmlStreamReader* r) while (r->readNextStartElement()) { QString tag = r->name().toString(); - // instrument parameters from base class + // parameters from base class if (tag == Tag::BaseData) { InstrumentItem::readFrom(r); XML::gotoEndElementOfTag(r, tag); - // scan parameters from base class - } else if (tag == Tag::ScanParameters) { - ScanningFunctionality::readScanFrom(r); + // beam + } else if (tag == Tag::Beam) { + m_beam_item->readFrom(r); + XML::gotoEndElementOfTag(r, tag); + + // detector + } else if (tag == Tag::Detector) { + m_detector_item->readFrom(r); XML::gotoEndElementOfTag(r, tag); } else @@ -484,51 +464,66 @@ void SpecularInstrumentItem::readFrom(QXmlStreamReader* r) } } +std::unique_ptr<IDetector> GISASInstrumentItem::normalDetector() const +{ + return detectorItem()->createDetector(); +} + // ************************************************************************************************ -// class DepthprobeInstrumentItem +// class OffspecInstrumentItem // ************************************************************************************************ -DepthprobeInstrumentItem::DepthprobeInstrumentItem() +OffspecInstrumentItem::OffspecInstrumentItem() : ScanningFunctionality(1e8) + , m_detector(new OffspecDetectorItem) { - auto* axisItem = scanItem()->inclinationAxisItem(); - axisItem->setMin(0.0); - axisItem->setMax(1.0); - axisItem->resize(500); - - m_z_axis.initMin("Min (nm)", "Starting value below sample horizon", -100.0, - RealLimits::limitless()); - m_z_axis.initMax("Max (nm)", "Ending value above sample horizon", 100.0, - RealLimits::limitless()); } -std::vector<int> DepthprobeInstrumentItem::axdims() const +std::vector<int> OffspecInstrumentItem::axdims() const { - return {}; // no certain shape to avoid linking to real data + return {scanItem()->grazingScanItem()->nBins(), detectorItem()->ySize()}; } -void DepthprobeInstrumentItem::updateToRealData(const DatafileItem*) +void OffspecInstrumentItem::updateToRealData(const DatafileItem* dfileItem) { - ASSERT_NEVER; + if (!dfileItem) + return; + + const auto data_shape = dfileItem->axdims(); + if (axdims().size() != data_shape.size()) + throw std::runtime_error("Offspec instrument type is incompatible with passed data shape"); + + throw std::runtime_error("OffspecInstrumentItem::updateToRealData not yet implemented"); + // ... set to data_shape[0] + + detectorItem()->setYSize(data_shape[1]); } -std::unique_ptr<Frame> DepthprobeInstrumentItem::createFrame() const +std::unique_ptr<Frame> OffspecInstrumentItem::createFrame() const { BasicAxisItem* const axis_item = scanItem()->inclinationAxisItem(); Scale xAxis = axis_item->makeScale("alpha_i (rad)"); - Scale zAxis = m_z_axis.createAxis("z (nm)"); - std::vector<const Scale*> axes{xAxis.clone(), zAxis.clone()}; - return std::make_unique<Frame>(axes); + return std::make_unique<Frame>(xAxis.clone(), + detectorItem()->createOffspecDetector()->axis(1).clone()); } -ISimulation* DepthprobeInstrumentItem::createSimulation(const MultiLayer& sample) const +ISimulation* OffspecInstrumentItem::createSimulation(const MultiLayer& sample) const { const Frame frame = makeFrame(); - std::unique_ptr<BeamScan> scan = createScan(frame.axis(0)); - return new DepthprobeSimulation(*scan, sample, frame.axis(1)); + const auto detector = detectorItem()->createOffspecDetector(); + std::unique_ptr<PhysicalScan> scan = createScan(frame.axis(0)); + if (withPolarizer()) + scan->setPolarization(m_polarizer_bloch_vector); + if (withAnalyzer()) + detector->setAnalyzer(m_analyzer_bloch_vector); // offspec uses detector analyzer, not scan + auto* result = new OffspecSimulation(*scan, sample, *detector); + + if (const auto background = backgroundItem()->createBackground()) + result->setBackground(*background); + return result; } -void DepthprobeInstrumentItem::writeTo(QXmlStreamWriter* w) const +void OffspecInstrumentItem::writeTo(QXmlStreamWriter* w) const { XML::writeAttribute(w, XML::Attrib::version, uint(1)); @@ -542,13 +537,13 @@ void DepthprobeInstrumentItem::writeTo(QXmlStreamWriter* w) const ScanningFunctionality::writeScanTo(w); w->writeEndElement(); - // z axis - w->writeStartElement(Tag::ZAxis); - m_z_axis.writeTo(w); + // detector + w->writeStartElement(Tag::Detector); + m_detector->writeTo(w); w->writeEndElement(); } -void DepthprobeInstrumentItem::readFrom(QXmlStreamReader* r) +void OffspecInstrumentItem::readFrom(QXmlStreamReader* r) { const uint version = XML::readUIntAttribute(r, XML::Attrib::version); Q_UNUSED(version) @@ -566,9 +561,9 @@ void DepthprobeInstrumentItem::readFrom(QXmlStreamReader* r) ScanningFunctionality::readScanFrom(r); XML::gotoEndElementOfTag(r, tag); - // z axis - } else if (tag == Tag::ZAxis) { - m_z_axis.readFrom(r); + // detector + } else if (tag == Tag::Detector) { + m_detector->readFrom(r); XML::gotoEndElementOfTag(r, tag); } else @@ -577,60 +572,91 @@ void DepthprobeInstrumentItem::readFrom(QXmlStreamReader* r) } // ************************************************************************************************ -// class OffspecInstrumentItem +// class SpecularInstrumentItem // ************************************************************************************************ -OffspecInstrumentItem::OffspecInstrumentItem() - : ScanningFunctionality(1e8) - , m_detector(new OffspecDetectorItem) +SpecularInstrumentItem::SpecularInstrumentItem() + : ScanningFunctionality(1e6) { } -std::vector<int> OffspecInstrumentItem::axdims() const +std::vector<int> SpecularInstrumentItem::axdims() const { - return {scanItem()->grazingScanItem()->nBins(), detectorItem()->ySize()}; + return {scanItem()->inclinationAxisItem()->size()}; } -void OffspecInstrumentItem::updateToRealData(const DatafileItem* dfileItem) +void SpecularInstrumentItem::updateToRealData(const DatafileItem* dfileItem) { - if (!dfileItem) - return; + if (axdims().size() != dfileItem->axdims().size()) + throw std::runtime_error("Specular instrument type is incompatible with passed data shape"); - const auto data_shape = dfileItem->axdims(); - if (axdims().size() != data_shape.size()) - throw std::runtime_error("Offspec instrument type is incompatible with passed data shape"); + const auto& dataAxis = dfileItem->dataItem()->c_field()->axis(0); + scanItem()->updateToData(dataAxis); + scanItem()->grazingScanItem()->updateAxIndicators(makeFrame()); +} - throw std::runtime_error("OffspecInstrumentItem::updateToRealData not yet implemented"); - // ... set to data_shape[0] +bool SpecularInstrumentItem::alignedWith(const DatafileItem* dfileItem) const +{ + if (!dfileItem->holdsDimensionalData()) + return scanItem()->grazingScanItem()->uniformAlphaAxisSelected() + && axdims() == dfileItem->axdims(); - detectorItem()->setYSize(data_shape[1]); + if (!scanItem()->grazingScanItem()->pointwiseAlphaAxisSelected()) + return false; + + const auto* axisItem = + dynamic_cast<const PointwiseAxisItem*>(scanItem()->grazingScanItem()->alphaAxisItem()); + ASSERT(axisItem); + + const auto* instrumentAxis = axisItem->axis(); + if (!instrumentAxis) + return false; + + const auto& native_axis = dfileItem->dataItem()->c_field()->axis(0); + return *instrumentAxis == native_axis; } -std::unique_ptr<Frame> OffspecInstrumentItem::createFrame() const +std::unique_ptr<Frame> SpecularInstrumentItem::createFrame() const { - BasicAxisItem* const axis_item = scanItem()->inclinationAxisItem(); - Scale xAxis = axis_item->makeScale("alpha_i (rad)"); - return std::make_unique<Frame>(xAxis.clone(), - detectorItem()->createOffspecDetector()->axis(1).clone()); + auto* axis_item = scanItem()->inclinationAxisItem(); + ASSERT(axis_item); + + if (auto* pointwise_axis = dynamic_cast<PointwiseAxisItem*>(axis_item)) { + const Scale* pAxis = pointwise_axis->axis(); + if (!pAxis) // workaround for loading project + return {}; + + if (pAxis->unit() == "1/nm") { + double lambda = scanItem()->wavelength(); + Scale ax = + pAxis->transformedScale(Coordinate("alpha_i", "rad").label(), [lambda](double qz) { + return std::asin(qz * lambda / 4 / pi); + }); + return std::make_unique<Frame>(ax.clone()); + } + return std::make_unique<Frame>(pAxis->clone()); + } + + Scale axis = axis_item->makeScale("alpha_i (rad)"); + return std::make_unique<Frame>(axis.clone()); } -ISimulation* OffspecInstrumentItem::createSimulation(const MultiLayer& sample) const +ISimulation* SpecularInstrumentItem::createSimulation(const MultiLayer& sample) const { - const Frame frame = makeFrame(); - const auto detector = detectorItem()->createOffspecDetector(); - std::unique_ptr<PhysicalScan> scan = createScan(frame.axis(0)); + auto frame = createFrame(); + std::unique_ptr<BeamScan> scan = createScan(frame->axis(0)); if (withPolarizer()) scan->setPolarization(m_polarizer_bloch_vector); if (withAnalyzer()) - detector->setAnalyzer(m_analyzer_bloch_vector); // offspec uses detector analyzer, not scan - auto* result = new OffspecSimulation(*scan, sample, *detector); + scan->setAnalyzer(m_analyzer_bloch_vector); + auto* result = new SpecularSimulation(*scan, sample); if (const auto background = backgroundItem()->createBackground()) result->setBackground(*background); return result; } -void OffspecInstrumentItem::writeTo(QXmlStreamWriter* w) const +void SpecularInstrumentItem::writeTo(QXmlStreamWriter* w) const { XML::writeAttribute(w, XML::Attrib::version, uint(1)); @@ -643,14 +669,9 @@ void OffspecInstrumentItem::writeTo(QXmlStreamWriter* w) const w->writeStartElement(Tag::ScanParameters); ScanningFunctionality::writeScanTo(w); w->writeEndElement(); - - // detector - w->writeStartElement(Tag::Detector); - m_detector->writeTo(w); - w->writeEndElement(); } -void OffspecInstrumentItem::readFrom(QXmlStreamReader* r) +void SpecularInstrumentItem::readFrom(QXmlStreamReader* r) { const uint version = XML::readUIntAttribute(r, XML::Attrib::version); Q_UNUSED(version) @@ -668,93 +689,76 @@ void OffspecInstrumentItem::readFrom(QXmlStreamReader* r) ScanningFunctionality::readScanFrom(r); XML::gotoEndElementOfTag(r, tag); - // detector - } else if (tag == Tag::Detector) { - m_detector->readFrom(r); - XML::gotoEndElementOfTag(r, tag); - } else r->skipCurrentElement(); } } // ************************************************************************************************ -// class GISASInstrumentItem +// class DepthprobeInstrumentItem // ************************************************************************************************ -GISASInstrumentItem::GISASInstrumentItem() +DepthprobeInstrumentItem::DepthprobeInstrumentItem() + : ScanningFunctionality(1e8) { - m_detector_item = std::make_unique<DetectorItem>(); - m_beam_item = std::make_unique<BeamItem>(); + auto* axisItem = scanItem()->inclinationAxisItem(); + axisItem->setMin(0.0); + axisItem->setMax(1.0); + axisItem->resize(500); + + m_z_axis.initMin("Min (nm)", "Starting value below sample horizon", -100.0, + RealLimits::limitless()); + m_z_axis.initMax("Max (nm)", "Ending value above sample horizon", 100.0, + RealLimits::limitless()); } -std::vector<int> GISASInstrumentItem::axdims() const +std::vector<int> DepthprobeInstrumentItem::axdims() const { - ASSERT(detectorItem()); - return {(int)detectorItem()->phiAxis().nbins(), (int)detectorItem()->alphaAxis().nbins()}; + return {}; // no certain shape to avoid linking to real data } -void GISASInstrumentItem::updateToRealData(const DatafileItem* dfileItem) +void DepthprobeInstrumentItem::updateToRealData(const DatafileItem*) { - if (!dfileItem) - return; - - const auto data_shape = dfileItem->axdims(); - if (axdims().size() != data_shape.size()) - throw std::runtime_error("GISAS instrument type is incompatible with passed data shape."); - ASSERT(detectorItem()); - detectorItem()->phiAxis().setNbins(data_shape[0]); - detectorItem()->alphaAxis().setNbins(data_shape[1]); + ASSERT_NEVER; } -std::unique_ptr<Frame> GISASInstrumentItem::createFrame() const +std::unique_ptr<Frame> DepthprobeInstrumentItem::createFrame() const { - return std::make_unique<Frame>(normalDetector()->clippedFrame()); + BasicAxisItem* const axis_item = scanItem()->inclinationAxisItem(); + Scale xAxis = axis_item->makeScale("alpha_i (rad)"); + Scale zAxis = m_z_axis.createAxis("z (nm)"); + std::vector<const Scale*> axes{xAxis.clone(), zAxis.clone()}; + return std::make_unique<Frame>(axes); } -ISimulation* GISASInstrumentItem::createSimulation(const MultiLayer& sample) const +ISimulation* DepthprobeInstrumentItem::createSimulation(const MultiLayer& sample) const { - const auto beam = beamItem()->createBeam(); - if (withPolarizer()) - beam->setPolarization(m_polarizer_bloch_vector); - const auto detector = detectorItem()->createDetector(); - if (withAnalyzer()) - detector->setAnalyzer(m_analyzer_bloch_vector); - auto* result = new ScatteringSimulation(*beam, sample, *detector); - - setBeamDistribution(ParameterDistribution::BeamWavelength, beamItem()->wavelengthItem(), - result); - setBeamDistribution(ParameterDistribution::BeamInclinationAngle, - beamItem()->beamDistributionItem(), result); - setBeamDistribution(ParameterDistribution::BeamAzimuthalAngle, beamItem()->azimuthalAngleItem(), - result); - - if (const auto background = backgroundItem()->createBackground()) - result->setBackground(*background); - return result; + const Frame frame = makeFrame(); + std::unique_ptr<BeamScan> scan = createScan(frame.axis(0)); + return new DepthprobeSimulation(*scan, sample, frame.axis(1)); } -void GISASInstrumentItem::writeTo(QXmlStreamWriter* w) const +void DepthprobeInstrumentItem::writeTo(QXmlStreamWriter* w) const { XML::writeAttribute(w, XML::Attrib::version, uint(1)); - // parameters from base class + // instrument parameters from base class w->writeStartElement(Tag::BaseData); InstrumentItem::writeTo(w); w->writeEndElement(); - // beam - w->writeStartElement(Tag::Beam); - m_beam_item->writeTo(w); + // scan parameters from base class + w->writeStartElement(Tag::ScanParameters); + ScanningFunctionality::writeScanTo(w); w->writeEndElement(); - // detector - w->writeStartElement(Tag::Detector); - m_detector_item->writeTo(w); + // z axis + w->writeStartElement(Tag::ZAxis); + m_z_axis.writeTo(w); w->writeEndElement(); } -void GISASInstrumentItem::readFrom(QXmlStreamReader* r) +void DepthprobeInstrumentItem::readFrom(QXmlStreamReader* r) { const uint version = XML::readUIntAttribute(r, XML::Attrib::version); Q_UNUSED(version) @@ -762,27 +766,22 @@ void GISASInstrumentItem::readFrom(QXmlStreamReader* r) while (r->readNextStartElement()) { QString tag = r->name().toString(); - // parameters from base class + // instrument parameters from base class if (tag == Tag::BaseData) { InstrumentItem::readFrom(r); XML::gotoEndElementOfTag(r, tag); - // beam - } else if (tag == Tag::Beam) { - m_beam_item->readFrom(r); + // scan parameters from base class + } else if (tag == Tag::ScanParameters) { + ScanningFunctionality::readScanFrom(r); XML::gotoEndElementOfTag(r, tag); - // detector - } else if (tag == Tag::Detector) { - m_detector_item->readFrom(r); + // z axis + } else if (tag == Tag::ZAxis) { + m_z_axis.readFrom(r); XML::gotoEndElementOfTag(r, tag); } else r->skipCurrentElement(); } } - -std::unique_ptr<IDetector> GISASInstrumentItem::normalDetector() const -{ - return detectorItem()->createDetector(); -} diff --git a/GUI/Model/Device/InstrumentItems.h b/GUI/Model/Device/InstrumentItems.h index b9662308e95ed352d584eff9d3d56d6c66f4314d..d85db407f577aabe95e776cbc917b02304c20dfb 100644 --- a/GUI/Model/Device/InstrumentItems.h +++ b/GUI/Model/Device/InstrumentItems.h @@ -126,27 +126,34 @@ private: }; -class SpecularInstrumentItem : public InstrumentItem, public ScanningFunctionality { +class GISASInstrumentItem : public InstrumentItem { public: - SpecularInstrumentItem(); - QString instrumentType() const override { return "Specular"; } + GISASInstrumentItem(); + QString instrumentType() const override { return "Scatter2D"; } std::vector<int> axdims() const override; void updateToRealData(const DatafileItem* dfileItem) override; - bool alignedWith(const DatafileItem* dfileItem) const override; std::unique_ptr<Frame> createFrame() const override; ISimulation* createSimulation(const MultiLayer& sample) const override; - void writeTo(QXmlStreamWriter* w) const override; void readFrom(QXmlStreamReader* r) override; + + BeamItem* beamItem() const { return m_beam_item.get(); } + DetectorItem* detectorItem() const { return m_detector_item.get(); } + + std::unique_ptr<IDetector> normalDetector() const; + +private: + std::unique_ptr<BeamItem> m_beam_item; + std::unique_ptr<DetectorItem> m_detector_item; }; -class DepthprobeInstrumentItem : public InstrumentItem, public ScanningFunctionality { +class OffspecInstrumentItem : public InstrumentItem, public ScanningFunctionality { public: - DepthprobeInstrumentItem(); + OffspecInstrumentItem(); - QString instrumentType() const override { return "Depthprobe"; } + QString instrumentType() const override { return "Offspecular"; } std::vector<int> axdims() const override; void updateToRealData(const DatafileItem* dfileItem) override; std::unique_ptr<Frame> createFrame() const override; @@ -154,37 +161,34 @@ public: void writeTo(QXmlStreamWriter* w) const override; void readFrom(QXmlStreamReader* r) override; - AxisProperty& zAxis() { return m_z_axis; } + OffspecDetectorItem* detectorItem() const { return m_detector.get(); } private: - AxisProperty m_z_axis; + std::unique_ptr<OffspecDetectorItem> m_detector; }; -class OffspecInstrumentItem : public InstrumentItem, public ScanningFunctionality { +class SpecularInstrumentItem : public InstrumentItem, public ScanningFunctionality { public: - OffspecInstrumentItem(); + SpecularInstrumentItem(); + QString instrumentType() const override { return "Specular"; } - QString instrumentType() const override { return "Offspecular"; } std::vector<int> axdims() const override; void updateToRealData(const DatafileItem* dfileItem) override; + bool alignedWith(const DatafileItem* dfileItem) const override; std::unique_ptr<Frame> createFrame() const override; ISimulation* createSimulation(const MultiLayer& sample) const override; + void writeTo(QXmlStreamWriter* w) const override; void readFrom(QXmlStreamReader* r) override; - - OffspecDetectorItem* detectorItem() const { return m_detector.get(); } - -private: - std::unique_ptr<OffspecDetectorItem> m_detector; }; -class GISASInstrumentItem : public InstrumentItem { +class DepthprobeInstrumentItem : public InstrumentItem, public ScanningFunctionality { public: - GISASInstrumentItem(); + DepthprobeInstrumentItem(); - QString instrumentType() const override { return "Scatter2D"; } + QString instrumentType() const override { return "Depthprobe"; } std::vector<int> axdims() const override; void updateToRealData(const DatafileItem* dfileItem) override; std::unique_ptr<Frame> createFrame() const override; @@ -192,14 +196,10 @@ public: void writeTo(QXmlStreamWriter* w) const override; void readFrom(QXmlStreamReader* r) override; - BeamItem* beamItem() const { return m_beam_item.get(); } - DetectorItem* detectorItem() const { return m_detector_item.get(); } - - std::unique_ptr<IDetector> normalDetector() const; + AxisProperty& zAxis() { return m_z_axis; } private: - std::unique_ptr<BeamItem> m_beam_item; - std::unique_ptr<DetectorItem> m_detector_item; + AxisProperty m_z_axis; };