Skip to content
Snippets Groups Projects
Commit 0e97cf77 authored by Wuttke, Joachim's avatar Wuttke, Joachim
Browse files

[j.mask131] restore display of masked pixels (lightbulb button) ()

Merging branch 'j.mask131'  into 'main'.

See merge request !2269
parents 848d2733 61798ffb
No related branches found
No related tags found
1 merge request!2269restore display of masked pixels (lightbulb button)
Pipeline #125029 passed
......@@ -228,12 +228,12 @@ std::vector<size_t> IDetector::activeIndices() const
void IDetector::addMask(const IShape2D& shape, bool mask_value)
{
m_mask->maskToStack(shape, mask_value, false);
m_mask->pushMask(shape, mask_value, false);
}
void IDetector::addBinMask(const IShape2D& shape, bool mask_value)
{
m_mask->maskToStack(shape, mask_value, true);
m_mask->pushMask(shape, mask_value, true);
}
void IDetector::maskAll()
......
......@@ -50,7 +50,7 @@ MaskStack::MaskStack() = default;
MaskStack::MaskStack(const MaskStack&) = default;
MaskStack::~MaskStack() = default;
void MaskStack::maskToStack(const IShape2D& shape, bool mask_value, bool in_bins)
void MaskStack::pushMask(const IShape2D& shape, bool mask_value, bool in_bins)
{
m_stack.emplace_back(new MaskPattern(shape.clone(), mask_value, in_bins));
}
......
......@@ -34,7 +34,7 @@ public:
~MaskStack();
//! Add mask to the stack of detector masks.
//! Argument mask_value=true means that the area will be excluded from the analysis.
void maskToStack(const IShape2D& shape, bool mask_value, bool in_bins);
void pushMask(const IShape2D& shape, bool mask_value, bool in_bins);
bool isMasked(size_t i_flat, const Frame& frame) const;
......
......@@ -66,6 +66,8 @@ digraph maskClasses
#SpecularPlot->ScientificPlot[arrowhead=onormal];
Data2DItem->MaskList;
Data2DItem->MaskeditorListmodel[style=dotted color=magenta];
MaskList->MaskItem;
EllipseOverlay->EllipseItem;
......
......@@ -17,8 +17,11 @@
#include "Base/Axis/Scale.h"
#include "Base/Util/Assert.h"
#include "Device/Data/Datafield.h"
#include "Device/Mask/IShape2D.h"
#include "Device/Mask/MaskStack.h"
#include "GUI/Model/Axis/AmplitudeAxisItem.h"
#include "GUI/Model/Axis/BasicAxisItem.h"
#include "GUI/Model/Mask/MaskItems.h"
#include "GUI/Model/Mask/MaskeditorListmodel.h"
#include "GUI/Model/Mask/ProjectionList.h"
#include "GUI/Support/Style/QCP_Util.h"
......@@ -365,6 +368,37 @@ MaskeditorListmodel* Data2DItem::getOrCreateMaskModel()
return m_mask_model.get();
}
Datafield* Data2DItem::createMaskedField() const
{
// Requesting mask information
std::unique_ptr<IShape2D> roi;
Datafield* result = c_field()->clone();
MaskStack detectorMask;
const QVector<const MaskItem*> maskItems = maskContainerItem()->maskItems();
for (auto maskIter = maskItems.rbegin(); maskIter != maskItems.rend(); maskIter++)
if ((*maskIter)->isVisible()) {
if (auto* roiItem = dynamic_cast<const RegionOfInterestItem*>((*maskIter)))
roi = roiItem->createShape();
else {
std::unique_ptr<IShape2D> shape((*maskIter)->createShape());
detectorMask.pushMask(*shape, (*maskIter)->maskValue(), false);
}
}
// ROI mask has to be the last one, it can not be "unmasked" by other shapes
if (roi)
detectorMask.pushMask(*roi, true, false);
if (!detectorMask.hasMasks())
return nullptr;
for (size_t i = 0; i < result->size(); ++i)
if (detectorMask.isMasked(i, result->frame()))
(*result)[i] = 0;
return result;
}
ProjectionList* Data2DItem::projectionContainerItem()
{
return m_proj_model ? m_proj_model->projnItem() : nullptr;
......
......@@ -78,6 +78,7 @@ public:
MaskList* maskContainerItem();
const MaskList* maskContainerItem() const;
MaskeditorListmodel* getOrCreateMaskModel();
Datafield* createMaskedField() const;
ProjectionList* projectionContainerItem();
const ProjectionList* projectionContainerItem() const;
......
// ************************************************************************************************
//
// BornAgain: simulate and fit reflection and scattering
//
//! @file GUI/Model/Data/MaskResultsPresenter.cpp
//! @brief Implements class MaskResultsPresenter.
//!
//! @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/Data/MaskResultsPresenter.h"
#include "Device/Data/Datafield.h"
#include "Device/Mask/IShape2D.h"
#include "Device/Mask/MaskStack.h"
#include "GUI/Model/Data/Data2DItem.h"
#include "GUI/Model/Mask/MaskItems.h"
#include "GUI/Model/Mask/MaskList.h"
namespace {
//! Constructs Datafield which contains original intensity data except masked areas,
//! and areas outside of ROI, where bin content is set to zero.
Datafield* createMaskPresentation(Data2DItem* data2DItem)
{
// Requesting mask information
std::unique_ptr<IShape2D> roi;
Datafield* result = data2DItem->c_field()->clone();
MaskStack detectorMask;
const QVector<const MaskItem*> maskItems = data2DItem->maskContainerItem()->maskItems();
for (auto maskIter = maskItems.rbegin(); maskIter != maskItems.rend(); maskIter++)
if ((*maskIter)->isVisible()) {
if (auto* roiItem = dynamic_cast<const RegionOfInterestItem*>((*maskIter)))
roi = roiItem->createShape();
else {
std::unique_ptr<IShape2D> shape((*maskIter)->createShape());
detectorMask.maskToStack(*shape, (*maskIter)->maskValue(), false);
}
}
// ROI mask has to be the last one, it can not be "unmasked" by other shapes
if (roi)
detectorMask.maskToStack(*roi, true, false);
if (!detectorMask.hasMasks())
return nullptr;
for (size_t i = 0; i < result->size(); ++i)
if (detectorMask.isMasked(i, result->frame()))
(*result)[i] = 0;
return result;
}
} // namespace
MaskResultsPresenter::MaskResultsPresenter() = default;
MaskResultsPresenter::~MaskResultsPresenter() = default;
void MaskResultsPresenter::updateMaskResults(Data2DItem* data2DItem)
{
m_data2DItem = data2DItem;
}
void MaskResultsPresenter::updatePresenter(bool pixelized)
{
ASSERT(m_data2DItem);
if (pixelized) {
if (Datafield* maskedData = ::createMaskPresentation(m_data2DItem)) {
// store data backup
m_backup_data.reset(m_data2DItem->c_field()->clone());
m_backup_interpolated = m_data2DItem->isInterpolated();
m_data2DItem->setDatafield(*maskedData);
m_data2DItem->setInterpolated(false);
} else {
m_backup_data.reset();
}
} else {
if (m_backup_data) {
m_data2DItem->setDatafield(*m_backup_data);
m_data2DItem->setInterpolated(m_backup_interpolated);
}
}
}
// ************************************************************************************************
//
// BornAgain: simulate and fit reflection and scattering
//
//! @file GUI/Model/Data/MaskResultsPresenter.h
//! @brief Defines class MaskResultsPresenter.
//!
//! @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)
//
// ************************************************************************************************
#ifndef BORNAGAIN_GUI_MODEL_DATA_MASKRESULTSPRESENTER_H
#define BORNAGAIN_GUI_MODEL_DATA_MASKRESULTSPRESENTER_H
#include <memory>
class Data2DItem;
class Datafield;
//! Updates bin values inside IntensityData to display current mask state.
class MaskResultsPresenter {
public:
MaskResultsPresenter();
~MaskResultsPresenter();
void updateMaskResults(Data2DItem* data2DItem);
void updatePresenter(bool pixelized);
private:
Data2DItem* m_data2DItem;
std::unique_ptr<Datafield> m_backup_data;
bool m_backup_interpolated = false;
};
#endif // BORNAGAIN_GUI_MODEL_DATA_MASKRESULTSPRESENTER_H
......@@ -13,8 +13,8 @@
// ************************************************************************************************
#include "GUI/View/Canvas/MaskEditorCanvas.h"
#include "Device/Data/Datafield.h"
#include "GUI/Model/Data/Data2DItem.h"
#include "GUI/Model/Data/MaskResultsPresenter.h"
#include "GUI/Model/Mask/MaskItems.h"
#include "GUI/Model/Mask/MaskList.h"
#include "GUI/Model/Project/ProjectDocument.h"
......@@ -31,7 +31,6 @@ MaskEditorCanvas::MaskEditorCanvas(QWidget* parent)
, m_view(new MaskGraphicsView(m_scene))
, m_data2DItem(nullptr)
, m_statusLabel(new PlotStatusLabel(nullptr, this))
, m_resultsPresenter(new MaskResultsPresenter)
{
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
......@@ -48,12 +47,12 @@ MaskEditorCanvas::MaskEditorCanvas(QWidget* parent)
&MaskEditorCanvas::deleteSelectedRequest);
}
MaskEditorCanvas::~MaskEditorCanvas() = default;
void MaskEditorCanvas::updateMaskCanvas(Data2DItem* data2DItem, QItemSelectionModel* selModel)
{
m_data2DItem = data2DItem;
m_resultsPresenter->updateMaskResults(data2DItem);
m_scene->updateSize(m_view->size());
m_scene->associateItems(data2DItem, data2DItem->getOrCreateMaskModel(), selModel);
......@@ -70,7 +69,28 @@ void MaskEditorCanvas::resetMaskCanvas()
void MaskEditorCanvas::onPresentationChange(bool pixelized)
{
m_scene->clearSelection(); // important to avoid crash (unsubscribe while calling subscribers)
m_resultsPresenter->updatePresenter(pixelized);
ASSERT(m_data2DItem);
if (pixelized) {
if (Datafield* maskedData = m_data2DItem->createMaskedField()) {
// store data backup
m_backup_data.reset(m_data2DItem->c_field()->clone());
m_backup_interpolated = m_data2DItem->isInterpolated();
m_data2DItem->setDatafield(*maskedData);
m_data2DItem->setInterpolated(false);
} else {
m_backup_data.reset();
}
} else {
if (m_backup_data) {
m_data2DItem->setDatafield(*m_backup_data);
m_data2DItem->setInterpolated(m_backup_interpolated);
}
}
m_scene->updateSize(m_view->size()); // TODO replace by proper repaint command
if (auto* container = m_data2DItem->maskContainerItem())
for (MaskItem* mask : container->modifiableMaskItems())
......
......@@ -19,11 +19,12 @@
#include <QItemSelectionModel>
#include <QModelIndex>
#include <QWidget>
#include <memory>
class Data2DItem;
class Datafield;
class MaskGraphicsScene;
class MaskGraphicsView;
class MaskResultsPresenter;
class PlotStatusLabel;
//! Painting widget for MaskEditor, contains graphics scene and graphics view
......@@ -32,6 +33,7 @@ class MaskEditorCanvas : public QWidget {
Q_OBJECT
public:
MaskEditorCanvas(QWidget* parent = nullptr);
~MaskEditorCanvas();
void updateMaskCanvas(Data2DItem* data2DItem, QItemSelectionModel* selModel);
......@@ -55,7 +57,8 @@ private:
MaskGraphicsView* m_view;
Data2DItem* m_data2DItem;
PlotStatusLabel* m_statusLabel;
MaskResultsPresenter* m_resultsPresenter;
std::unique_ptr<Datafield> m_backup_data;
bool m_backup_interpolated = false;
};
#endif // BORNAGAIN_GUI_VIEW_CANVAS_MASKEDITORCANVAS_H
......@@ -204,10 +204,11 @@ void MaskPanel::addMaskCheckBox(const QString& title, std::function<bool()> gett
gDoc->setModified();
});
connect(m_currentMaskItem, &MaskItem::maskVisibilityChanged, [check_box, getter] {
QSignalBlocker b(check_box);
check_box->setChecked(getter());
});
// TODO reconsider
// connect(m_currentMaskItem, &MaskItem::maskVisibilityChanged, [check_box, getter] {
// QSignalBlocker b(check_box);
// check_box->setChecked(getter());
// });
m_editor_layout->addRow(check_box);
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment