diff --git a/GUI/Model/Mask/MaskUnitsConverter.cpp b/GUI/Model/Mask/MaskUnitsConverter.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..6ff5bb85b2ba60420a108c4581b23297cbd12150
--- /dev/null
+++ b/GUI/Model/Mask/MaskUnitsConverter.cpp
@@ -0,0 +1,118 @@
+//  ************************************************************************************************
+//
+//  BornAgain: simulate and fit reflection and scattering
+//
+//! @file      GUI/Model/Data/MaskUnitsConverter.cpp
+//! @brief     Implements class MaskUnitsConverter
+//!
+//! @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/Mask/MaskUnitsConverter.h"
+#include "Base/Axis/FrameUtil.h"
+#include "Device/Data/Datafield.h"
+#include "GUI/Model/Data/Data2DItem.h"
+#include "GUI/Model/Mask/MaskItems.h"
+#include "GUI/Model/Mask/ProjectionContainerItem.h"
+
+MaskUnitsConverter::MaskUnitsConverter()
+    : m_data(nullptr)
+    , m_direction(UNDEFINED)
+{
+}
+
+//! Converts all masks on board of IntensityDataItem into bin-fraction coordinates.
+
+void MaskUnitsConverter::convertToNbins(Data2DItem* intensityData)
+{
+    m_direction = TO_NBINS;
+    convertIntensityDataItem(intensityData);
+}
+
+//! Converts all masks on board of IntensityDataItem from bin-fraction coordinates to coordinates
+//! of axes currently defined in Datafield.
+
+void MaskUnitsConverter::convertFromNbins(Data2DItem* intensityData)
+{
+    m_direction = FROM_NBINS;
+    convertIntensityDataItem(intensityData);
+}
+
+//! Converts all masks on board of IntensityDataItem from/to bin-fraction coordinates
+
+void MaskUnitsConverter::convertIntensityDataItem(Data2DItem* intensityData)
+{
+    if (!intensityData || !intensityData->c_field())
+        return;
+
+    m_data = intensityData->c_field();
+
+    if (intensityData->maskContainerItem())
+        for (auto* maskItem : intensityData->maskContainerItem()->maskItems())
+            convertMask(maskItem);
+
+    if (intensityData->projectionContainerItem())
+        for (auto* maskItem : intensityData->projectionContainerItem()->maskItems())
+            convertMask(maskItem);
+}
+
+//! Converts single mask from/to bin-fraction coordinates
+
+void MaskUnitsConverter::convertMask(MaskItem* maskItem)
+{
+    if (auto* rectItem = dynamic_cast<RectangleItem*>(maskItem)) {
+        rectItem->setXLow(convert(rectItem->xLow(), Axis::X));
+        rectItem->setYLow(convert(rectItem->yLow(), Axis::Y));
+        rectItem->setXUp(convert(rectItem->xUp(), Axis::X));
+        rectItem->setYUp(convert(rectItem->yUp(), Axis::Y));
+    } else if (auto* poly = dynamic_cast<PolygonItem*>(maskItem)) {
+        for (PolygonPointItem* pointItem : poly->points()) {
+            pointItem->setPosX(convert(pointItem->posX(), Axis::X));
+            pointItem->setPosY(convert(pointItem->posY(), Axis::Y));
+        }
+    } else if (auto* vlineItem = dynamic_cast<VerticalLineItem*>(maskItem)) {
+        vlineItem->setPosX(convert(vlineItem->posX(), Axis::X));
+    } else if (auto* hlineItem = dynamic_cast<HorizontalLineItem*>(maskItem)) {
+        hlineItem->setPosY(convert(hlineItem->posY(), Axis::Y));
+    } else if (auto* ellItem = dynamic_cast<EllipseItem*>(maskItem)) {
+        double xc = ellItem->xCenter();
+        double yc = ellItem->yCenter();
+        double xR = ellItem->xRadius();
+        double yR = ellItem->yRadius();
+
+        double x2 = xc + xR;
+        double y2 = yc + yR;
+
+        if (m_direction == TO_NBINS) {
+            FrameUtil::coordinatesToBinf(xc, yc, m_data->frame());
+            FrameUtil::coordinatesToBinf(x2, y2, m_data->frame());
+        } else {
+            FrameUtil::coordinatesFromBinf(xc, yc, m_data->frame());
+            FrameUtil::coordinatesFromBinf(x2, y2, m_data->frame());
+        }
+        ellItem->setXCenter(xc);
+        ellItem->setYCenter(yc);
+        ellItem->setXRadius(x2 - xc);
+        ellItem->setYRadius(y2 - yc);
+    }
+}
+
+//! Convert value of axis from/to bin-fraction coordinates.
+
+double MaskUnitsConverter::convert(double value, Axis axis)
+{
+    auto axis_index = static_cast<size_t>(axis);
+
+    ASSERT(m_data);
+    ASSERT(axis_index == 0 || axis_index == 1);
+
+    if (m_direction == TO_NBINS)
+        return FrameUtil::coordinateToBinf(value, m_data->axis(axis_index));
+    if (m_direction == FROM_NBINS)
+        return FrameUtil::coordinateFromBinf(value, m_data->axis(axis_index));
+    ASSERT(false);
+}
diff --git a/GUI/Model/Mask/MaskUnitsConverter.h b/GUI/Model/Mask/MaskUnitsConverter.h
new file mode 100644
index 0000000000000000000000000000000000000000..12d2fd6008fd1d755a37d606f28c54b8c721f3e7
--- /dev/null
+++ b/GUI/Model/Mask/MaskUnitsConverter.h
@@ -0,0 +1,50 @@
+//  ************************************************************************************************
+//
+//  BornAgain: simulate and fit reflection and scattering
+//
+//! @file      GUI/Model/Data/MaskUnitsConverter.h
+//! @brief     Defines class MaskUnitsConverter
+//!
+//! @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_MASKUNITSCONVERTER_H
+#define BORNAGAIN_GUI_MODEL_DATA_MASKUNITSCONVERTER_H
+
+class Data2DItem;
+class Datafield;
+class MaskItem;
+
+//! The MaskUnitsConverter converts coordinates of all masks from one units to anoter.
+//! I.e. masks in 'mm' into masks in 'deg'. This is done in two steps.
+//! On first step masks are converted from native coordinates (as given by axes of Datafield)
+//! into bin-fraction coordinates.
+//! On second step masks are converted from bin-fraction coordinates into current axes of
+//! Datafield.
+
+class MaskUnitsConverter {
+public:
+    enum EConvertionDirection { TO_NBINS, FROM_NBINS, UNDEFINED };
+
+    MaskUnitsConverter();
+
+    void convertToNbins(Data2DItem* intensityData);
+    void convertFromNbins(Data2DItem* intensityData);
+
+private:
+    enum class Axis { X, Y };
+
+    void convertIntensityDataItem(Data2DItem* intensityData);
+    void convertMask(MaskItem* maskItem);
+
+    double convert(double value, Axis axis);
+
+    const Datafield* m_data;
+    EConvertionDirection m_direction;
+};
+
+#endif // BORNAGAIN_GUI_MODEL_DATA_MASKUNITSCONVERTER_H