diff --git a/Core/Fitting/SimDataPair.cpp b/Core/Fitting/SimDataPair.cpp
index 61cc94f5711373aefd3aa65114eaf40712e6e762..37da617e529cd72129c7df8f78a3652eb1b4cd8c 100644
--- a/Core/Fitting/SimDataPair.cpp
+++ b/Core/Fitting/SimDataPair.cpp
@@ -14,8 +14,9 @@
 
 #include "Core/Fitting/SimDataPair.h"
 #include "Base/Math/Numeric.h"
-#include "Core/Scan/CoordSystem1D.h"
-#include "Core/Simulation/includeSimulations.h"
+#include "Device/Coord/CoordSystem1D.h"
+#include "Core/Scan/ISpecularScan.h"
+#include "Core/Simulation/ISimulation.h"
 #include "Device/Data/DataUtils.h"
 #include "Device/Instrument/CoordSystem2D.h"
 
@@ -48,23 +49,6 @@ bool detHasSameDimensions(const IDetector& detector, const OutputData<double>& d
     return true;
 }
 
-std::unique_ptr<ICoordSystem> createConverter(const ISimulation& simulation)
-{
-    if (auto gisas = dynamic_cast<const GISASSimulation*>(&simulation))
-        return CoordSystem2D::createConverterForGISAS(gisas->instrument());
-
-    if (auto spec = dynamic_cast<const SpecularSimulation*>(&simulation))
-        return CoordSystem1D::createCoordSystem(*spec->dataHandler());
-
-    if (auto probe = dynamic_cast<const DepthProbeSimulation*>(&simulation))
-        return probe->createCoordSystem();
-
-    if (auto off_spec = dynamic_cast<const OffSpecularSimulation*>(&simulation))
-        return off_spec->createCoordSystem();
-
-    ASSERT(0);
-}
-
 //! Convert user data to SimulationResult object for later drawing in various axes units.
 //! User data will be cropped to the ROI defined in the simulation, amplitudes in areas
 //! corresponding to the masked areas of the detector will be set to zero.
@@ -72,7 +56,7 @@ std::unique_ptr<ICoordSystem> createConverter(const ISimulation& simulation)
 SimulationResult convertData(const ISimulation& simulation, const OutputData<double>& data,
                              bool put_masked_areas_to_zero)
 {
-    auto converter = createConverter(simulation);
+    const ICoordSystem* converter = simulation.createCoordSystem();
     auto roi_data = converter->createOutputData(converter->defaultUnits());
 
     if (roi_data->hasSameDimensions(data)) {
@@ -95,12 +79,11 @@ SimulationResult convertData(const ISimulation& simulation, const OutputData<dou
             },
             /*visit_masked*/ !put_masked_areas_to_zero);
 
-    } else {
-        throw std::runtime_error("FitObject::init_dataset() -> Error. Detector and exp data have "
-                                 "different shape.");
-    }
+    } else
+        throw std::runtime_error(
+            "FitObject::init_dataset: Detector and experimental data have different shape");
 
-    return SimulationResult(*roi_data, *converter);
+    return SimulationResult(*roi_data, std::move(converter));
 }
 
 } // namespace
diff --git a/Core/Scan/AngularSpecScan.cpp b/Core/Scan/AngularSpecScan.cpp
index fc1b35f896cf2f75615a662594db364f87f3d570..846cb1c359ae87d0eab564bcaf1eaaec37ceca7c 100644
--- a/Core/Scan/AngularSpecScan.cpp
+++ b/Core/Scan/AngularSpecScan.cpp
@@ -16,6 +16,7 @@
 #include "Base/Axis/FixedBinAxis.h"
 #include "Base/Axis/PointwiseAxis.h"
 #include "Core/Element/SpecularSimulationElement.h"
+#include "Device/Coord/CoordSystem1D.h"
 #include "Device/Beam/IFootprintFactor.h"
 #include "Device/Resolution/ScanResolution.h"
 #include "Param/Distrib/RangedDistributions.h"
@@ -225,6 +226,11 @@ size_t AngularSpecScan::numberOfSimulationElements() const
     return m_inc_angle->size() * m_wl_resolution->nSamples() * m_inc_resolution->nSamples();
 }
 
+CoordSystem1D* AngularSpecScan::createCoordSystem() const
+{
+    return new AngularReflectometryCoordinates(wavelength(), *coordinateAxis());
+}
+
 std::vector<double>
 AngularSpecScan::createIntensities(const std::vector<SpecularSimulationElement>& sim_elements) const
 {
diff --git a/Core/Scan/AngularSpecScan.h b/Core/Scan/AngularSpecScan.h
index 7167f928fb13f9036ae15fb844329b9e6b540a37..330bae3f6ab6cda86101b01ce43b9ae061e3f1bf 100644
--- a/Core/Scan/AngularSpecScan.h
+++ b/Core/Scan/AngularSpecScan.h
@@ -55,6 +55,8 @@ public:
     //! Returns the number of simulation elements
     size_t numberOfSimulationElements() const override;
 
+    CoordSystem1D* createCoordSystem() const override;
+
     //! Returns intensity vector corresponding to convolution of given simulation elements
     std::vector<double>
     createIntensities(const std::vector<SpecularSimulationElement>& sim_elements) const override;
diff --git a/Core/Scan/ISpecularScan.h b/Core/Scan/ISpecularScan.h
index cc5b8f6274d4fdd7e0a04da03973e6eadce47499..5a587696fd4541d4cbee81caa5bbcb63713ea359 100644
--- a/Core/Scan/ISpecularScan.h
+++ b/Core/Scan/ISpecularScan.h
@@ -22,6 +22,7 @@
 #include <string>
 #include <vector>
 
+class CoordSystem1D;
 class IAxis;
 class IFootprintFactor;
 class Instrument;
@@ -51,6 +52,8 @@ public:
     //! Returns the number of simulation elements
     virtual size_t numberOfSimulationElements() const = 0;
 
+    virtual CoordSystem1D* createCoordSystem() const = 0;
+
     //! Returns intensity vector corresponding to convolution of given simulation elements
     virtual std::vector<double>
     createIntensities(const std::vector<SpecularSimulationElement>& sim_elements) const = 0;
diff --git a/Core/Scan/QSpecScan.cpp b/Core/Scan/QSpecScan.cpp
index 7e6b16b61e6f07c00651a080da75aef79048160d..015f48c50c4cf21c494454e5bd0d6e93b112aaf8 100644
--- a/Core/Scan/QSpecScan.cpp
+++ b/Core/Scan/QSpecScan.cpp
@@ -15,6 +15,7 @@
 #include "Core/Scan/QSpecScan.h"
 #include "Base/Axis/FixedBinAxis.h"
 #include "Base/Axis/PointwiseAxis.h"
+#include "Device/Coord/CoordSystem1D.h"
 #include "Core/Element/SpecularSimulationElement.h"
 #include "Device/Resolution/ScanResolution.h"
 #include "Param/Distrib/RangedDistributions.h"
@@ -78,6 +79,11 @@ size_t QSpecScan::numberOfSimulationElements() const
     return m_qs->size() * m_resolution->nSamples();
 }
 
+CoordSystem1D* QSpecScan::createCoordSystem() const
+{
+    return new WavenumberReflectometryCoordinates(coordinateAxis()->clone());
+}
+
 std::vector<double>
 QSpecScan::createIntensities(const std::vector<SpecularSimulationElement>& sim_elements) const
 {
diff --git a/Core/Scan/QSpecScan.h b/Core/Scan/QSpecScan.h
index e4a5d1178d396ec1d8658bfc4c85dee7fe00e491..b3edbb4c66e63eb44a47e83e0307e578edd93c7c 100644
--- a/Core/Scan/QSpecScan.h
+++ b/Core/Scan/QSpecScan.h
@@ -59,6 +59,8 @@ public:
     //! Returns the number of simulation elements
     size_t numberOfSimulationElements() const override;
 
+    CoordSystem1D* createCoordSystem() const override;
+
     //! Returns intensity vector corresponding to convolution of given simulation elements
     std::vector<double>
     createIntensities(const std::vector<SpecularSimulationElement>& sim_elements) const override;
diff --git a/Core/Simulation/DepthProbeSimulation.cpp b/Core/Simulation/DepthProbeSimulation.cpp
index 7b48eaf11a7ad247641e5486466c620d38baa603..d907ade3aca473a93b7574acfa6f3908cd5f3a1c 100644
--- a/Core/Simulation/DepthProbeSimulation.cpp
+++ b/Core/Simulation/DepthProbeSimulation.cpp
@@ -50,7 +50,7 @@ SimulationResult DepthProbeSimulation::result() const
 {
     validityCheck();
     auto data = createIntensityData();
-    return SimulationResult(*data, *createCoordSystem());
+    return SimulationResult(*data, createCoordSystem());
 }
 
 void DepthProbeSimulation::setBeamParameters(double lambda, int nbins, double alpha_i_min,
@@ -92,10 +92,12 @@ size_t DepthProbeSimulation::intensityMapSize() const
     return m_z_axis->size() * m_alpha_axis->size();
 }
 
-std::unique_ptr<ICoordSystem> DepthProbeSimulation::createCoordSystem() const
+#ifndef SWIG
+ICoordSystem* DepthProbeSimulation::createCoordSystem() const
 {
-    return std::make_unique<DepthProbeConverter>(beam(), *m_alpha_axis, *m_z_axis);
+    return new DepthProbeCoordinates(beam(), *m_alpha_axis, *m_z_axis);
 }
+#endif
 
 DepthProbeSimulation::DepthProbeSimulation(const DepthProbeSimulation& other)
     : ISimulation(other), m_sim_elements(other.m_sim_elements), m_cache(other.m_cache)
diff --git a/Core/Simulation/DepthProbeSimulation.h b/Core/Simulation/DepthProbeSimulation.h
index b1b2b9481023e501bb5923517a99dc340950db67..c1ce4a43a66bfcb4d2791d35c249c002a52870e1 100644
--- a/Core/Simulation/DepthProbeSimulation.h
+++ b/Core/Simulation/DepthProbeSimulation.h
@@ -61,7 +61,7 @@ public:
     size_t intensityMapSize() const override;
 
 #ifndef SWIG
-    std::unique_ptr<ICoordSystem> createCoordSystem() const;
+    ICoordSystem* createCoordSystem() const override;
 #endif
 
 private:
diff --git a/Core/Simulation/GISASSimulation.cpp b/Core/Simulation/GISASSimulation.cpp
index e0fa3a5dc65fad05930a27ac485a4869c4114ff6..d59751b7e5affdec1bc769993bae7bc6b08255df 100644
--- a/Core/Simulation/GISASSimulation.cpp
+++ b/Core/Simulation/GISASSimulation.cpp
@@ -57,10 +57,10 @@ void GISASSimulation::prepareSimulation()
 
 SimulationResult GISASSimulation::result() const
 {
-    const auto converter = CoordSystem2D::createConverterForGISAS(instrument());
+    const auto coordsys = instrument().createScatteringCoords();
     const std::unique_ptr<OutputData<double>> data(
         detector().createDetectorIntensity(m_sim_elements));
-    return SimulationResult(*data, *converter);
+    return SimulationResult(*data, *coordsys);
 }
 
 void GISASSimulation::setBeamParameters(double wavelength, double alpha_i, double phi_i)
@@ -78,6 +78,13 @@ size_t GISASSimulation::intensityMapSize() const
     return result;
 }
 
+#ifndef SWIG
+ICoordSystem* GISASSimulation::createCoordSystem() const
+{
+    return instrument().createScatteringCoords();
+}
+#endif
+
 void GISASSimulation::initSimulationElementVector()
 {
     m_sim_elements = generateSimulationElements(beam());
diff --git a/Core/Simulation/GISASSimulation.h b/Core/Simulation/GISASSimulation.h
index 071df23111aa630be4200189b525e4025c92f704..65a6ad0746b48e2655a934602173b5c2e95c5eb7 100644
--- a/Core/Simulation/GISASSimulation.h
+++ b/Core/Simulation/GISASSimulation.h
@@ -50,6 +50,10 @@ public:
     //! Returns the total number of the intensity values in the simulation result
     size_t intensityMapSize() const override;
 
+#ifndef SWIG
+    ICoordSystem* createCoordSystem() const override;
+#endif // SWIG
+
 private:
     GISASSimulation(const GISASSimulation& other);
 
diff --git a/Core/Simulation/ISimulation.h b/Core/Simulation/ISimulation.h
index f4ee6aaebcb941a95b452bd09ad082040006c5cc..41c927caefa0b7360fa2251c5fdb8ea34569a2e6 100644
--- a/Core/Simulation/ISimulation.h
+++ b/Core/Simulation/ISimulation.h
@@ -97,6 +97,7 @@ public:
 #ifndef SWIG
     ISimulation(const Beam& beam, const IDetector& detector);
     void setInstrument(const Instrument& instrument_);
+    virtual ICoordSystem* createCoordSystem() const = 0;
 #endif // SWIG
 
 protected:
diff --git a/Core/Simulation/OffSpecularSimulation.cpp b/Core/Simulation/OffSpecularSimulation.cpp
index 6f833fa9f2bc620b2b06abdec0e3a5c7ca7b0eab..37f572e229211db7739b1b48aeac5728568ec312 100644
--- a/Core/Simulation/OffSpecularSimulation.cpp
+++ b/Core/Simulation/OffSpecularSimulation.cpp
@@ -45,7 +45,7 @@ size_t OffSpecularSimulation::numberOfSimulationElements() const
 SimulationResult OffSpecularSimulation::result() const
 {
     auto data = std::unique_ptr<OutputData<double>>(m_intensity_map.clone());
-    OffSpecularConverter converter(detector2D(), beam(), *m_alpha_i_axis);
+    OffSpecularCoordinates converter(detector2D(), beam(), *m_alpha_i_axis);
     return SimulationResult(*data, converter);
 }
 
@@ -66,14 +66,16 @@ const IAxis* OffSpecularSimulation::beamAxis() const
     return m_alpha_i_axis.get();
 }
 
-std::unique_ptr<ICoordSystem> OffSpecularSimulation::createCoordSystem() const
+#ifndef SWIG
+ICoordSystem* OffSpecularSimulation::createCoordSystem() const
 {
     const IAxis* axis = beamAxis();
     if (!axis)
         throw std::runtime_error("Error in OffSpecularSimulation::createCoordSystem:"
                                  " missing inclination angle axis");
-    return std::make_unique<OffSpecularConverter>(detector2D(), beam(), *axis);
+    return new OffSpecularCoordinates(detector2D(), beam(), *axis);
 }
+#endif
 
 size_t OffSpecularSimulation::intensityMapSize() const
 {
diff --git a/Core/Simulation/OffSpecularSimulation.h b/Core/Simulation/OffSpecularSimulation.h
index 82188cfd85e17784d27d40f9076d154d3cb48bc7..dd8a38dc93bccc70b7013c38749c1255fa415d94 100644
--- a/Core/Simulation/OffSpecularSimulation.h
+++ b/Core/Simulation/OffSpecularSimulation.h
@@ -47,7 +47,7 @@ public:
     const IAxis* beamAxis() const;
 
 #ifndef SWIG
-    std::unique_ptr<ICoordSystem> createCoordSystem() const;
+    ICoordSystem* createCoordSystem() const override;
 #endif
 
     //! Returns the total number of the intensity values in the simulation result
diff --git a/Core/Simulation/SpecularSimulation.cpp b/Core/Simulation/SpecularSimulation.cpp
index 3f81a58fce9d097b182115a4110774bfed6dc7e3..10043a8953faf27366724f147f26145e04714f01 100644
--- a/Core/Simulation/SpecularSimulation.cpp
+++ b/Core/Simulation/SpecularSimulation.cpp
@@ -18,7 +18,7 @@
 #include "Core/Computation/SpecularComputation.h"
 #include "Core/Element/SpecularSimulationElement.h"
 #include "Core/Scan/AngularSpecScan.h"
-#include "Core/Scan/CoordSystem1D.h"
+#include "Device/Coord/CoordSystem1D.h"
 #include "Device/Beam/IFootprintFactor.h"
 #include "Device/Detector/SpecularDetector1D.h"
 #include "Param/Base/ParameterPool.h"
@@ -105,8 +105,7 @@ SimulationResult SpecularSimulation::result() const
     else
         data.setAllTo(0.0);
 
-    auto converter = CoordSystem1D::createCoordSystem(*m_scan);
-    return SimulationResult(data, *converter);
+    return SimulationResult(data, createCoordSystem());
 }
 
 void SpecularSimulation::setScan(const ISpecularScan& scan)
@@ -149,6 +148,14 @@ size_t SpecularSimulation::intensityMapSize() const
     return m_scan->coordinateAxis()->size();
 }
 
+#ifndef SWIG
+ICoordSystem* SpecularSimulation::createCoordSystem() const
+{
+    ASSERT(m_scan);
+    return m_scan->createCoordSystem();
+}
+#endif
+
 void SpecularSimulation::initSimulationElementVector()
 {
     if (!m_scan)
diff --git a/Core/Simulation/SpecularSimulation.h b/Core/Simulation/SpecularSimulation.h
index 39debc1a9affd3b81a60059089f48bdc0156c831..c9df1351a5233a82cffd7f82b62da3daff9c5ff8 100644
--- a/Core/Simulation/SpecularSimulation.h
+++ b/Core/Simulation/SpecularSimulation.h
@@ -59,6 +59,7 @@ public:
     size_t intensityMapSize() const override;
 
 #ifndef SWIG
+    ICoordSystem* createCoordSystem() const override;
     //! Returns internal data handler
     const ISpecularScan* dataHandler() const { return m_scan.get(); }
 #endif // USER_API
diff --git a/Device/Unit/Axes.h b/Device/Coord/Axes.h
similarity index 96%
rename from Device/Unit/Axes.h
rename to Device/Coord/Axes.h
index dc379a419cb1c2c35f2951993267b792281cd7d7..891dd25f3c694ce900ac3b40290cf2bfab66b120 100644
--- a/Device/Unit/Axes.h
+++ b/Device/Coord/Axes.h
@@ -2,7 +2,7 @@
 //
 //  BornAgain: simulate and fit reflection and scattering
 //
-//! @file      Device/Unit/Axes.h
+//! @file      Device/Coord/Axes.h
 //! @brief     Defines enum Axis::Units.
 //!
 //! @homepage  http://www.bornagainproject.org
diff --git a/Device/Unit/AxisNames.cpp b/Device/Coord/AxisNames.cpp
similarity index 97%
rename from Device/Unit/AxisNames.cpp
rename to Device/Coord/AxisNames.cpp
index fdcb9ac747bddd2a42418d5cfb87f9d82e21a7e2..9134649cd0e14d1921fd5e6834acf2c2e6eb7c9b 100644
--- a/Device/Unit/AxisNames.cpp
+++ b/Device/Coord/AxisNames.cpp
@@ -2,7 +2,7 @@
 //
 //  BornAgain: simulate and fit reflection and scattering
 //
-//! @file      Device/Unit/AxisNames.cpp
+//! @file      Device/Coord/AxisNames.cpp
 //! @brief     Implements functions in namespace AxisNames.
 //!
 //! @homepage  http://www.bornagainproject.org
@@ -12,7 +12,7 @@
 //
 //  ************************************************************************************************
 
-#include "Device/Unit/AxisNames.h"
+#include "Device/Coord/AxisNames.h"
 #include <map>
 
 namespace AxisNames {
diff --git a/Device/Unit/AxisNames.h b/Device/Coord/AxisNames.h
similarity index 97%
rename from Device/Unit/AxisNames.h
rename to Device/Coord/AxisNames.h
index d6a3a49ff79f4658aaef8b69bb5976604fb3f05c..18e49abcb902545b4d398968f4f798537ce5221c 100644
--- a/Device/Unit/AxisNames.h
+++ b/Device/Coord/AxisNames.h
@@ -2,7 +2,7 @@
 //
 //  BornAgain: simulate and fit reflection and scattering
 //
-//! @file      Device/Unit/AxisNames.h
+//! @file      Device/Coord/AxisNames.h
 //! @brief     Defines axisUnitLabel and maps in namespace AxisNames.
 //!
 //! @homepage  http://www.bornagainproject.org
@@ -20,7 +20,7 @@
 #ifndef BORNAGAIN_DEVICE_UNIT_AXISNAMES_H
 #define BORNAGAIN_DEVICE_UNIT_AXISNAMES_H
 
-#include "Device/Unit/Axes.h"
+#include "Device/Coord/Axes.h"
 #include "Wrap/WinDllMacros.h"
 #include <map>
 #include <string>
diff --git a/Core/Scan/CoordSystem1D.cpp b/Device/Coord/CoordSystem1D.cpp
similarity index 63%
rename from Core/Scan/CoordSystem1D.cpp
rename to Device/Coord/CoordSystem1D.cpp
index 7fd7f2cb3794949fcb33574916309e618af3175b..d5374d9618396e64f89f3d4d561e8b195754f6ff 100644
--- a/Core/Scan/CoordSystem1D.cpp
+++ b/Device/Coord/CoordSystem1D.cpp
@@ -2,7 +2,7 @@
 //
 //  BornAgain: simulate and fit reflection and scattering
 //
-//! @file      Core/Scan/CoordSystem1D.cpp
+//! @file      Device/Coord/CoordSystem1D.cpp
 //! @brief     Implements CoordSystem1D class and derived classes.
 //!
 //! @homepage  http://www.bornagainproject.org
@@ -12,15 +12,12 @@
 //
 //  ************************************************************************************************
 
-#include "Core/Scan/CoordSystem1D.h"
+#include "Device/Coord/CoordSystem1D.h"
 #include "Base/Axis/PointwiseAxis.h"
 #include "Base/Const/Units.h"
 #include "Base/Math/Constants.h"
-#include "Core/Scan/AngularSpecScan.h"
-#include "Core/Scan/QSpecScan.h"
-#include "Device/Beam/Beam.h"
+#include "Device/Coord/AxisNames.h"
 #include "Device/Data/OutputData.h"
-#include "Device/Unit/AxisNames.h"
 
 namespace {
 
@@ -44,6 +41,39 @@ createTranslatedAxis(const IAxis& axis, std::function<double(double)> translator
     return std::make_unique<PointwiseAxis>(name, coordinates);
 }
 
+double backTransform(double value, Axes::Coords coords, double wavelength)
+{
+    switch (coords) {
+    case Axes::Coords::RADIANS:
+        return value;
+    case Axes::Coords::DEGREES:
+        return Units::deg2rad(value);
+    case Axes::Coords::QSPACE:
+        return getInvQ(wavelength, value);
+    default:
+        throw std::runtime_error("CoordSystem1D/backTransform: invalid coord system");
+    }
+}
+
+std::string angularAxisName(const Axes::Coords units)
+{
+    const auto& name_map = AxisNames::specAxis;
+    const auto& it = name_map.find(
+        units == Axes::Coords::UNDEFINED ? Axes::Coords::DEGREES : units);
+    ASSERT(it != name_map.cend());
+    return it->second;
+}
+
+PointwiseAxis* createAxisFrom(const IAxis& axis, Axes::Coords coords, const std::string& name,
+                              double wavelength)
+{
+    std::vector<double> ret;
+    ret.reserve(axis.size());
+    for (const double value : axis.binCenters())
+        ret.emplace_back(backTransform(value, coords, wavelength));
+    return new PointwiseAxis(name, ret);
+}
+
 } // namespace
 
 
@@ -51,16 +81,7 @@ createTranslatedAxis(const IAxis& axis, std::function<double(double)> translator
 //  class CoordSystem1D
 //  ************************************************************************************************
 
-std::unique_ptr<CoordSystem1D> CoordSystem1D::createCoordSystem(const ISpecularScan& scan)
-{
-    if (const auto* aScan = dynamic_cast<const AngularSpecScan*>(&scan))
-        return std::make_unique<AngularReflectometryConverter>(*aScan);
-
-    if (const auto* qScan = dynamic_cast<const QSpecScan*>(&scan))
-        return std::make_unique<WavenumberReflectometryConverter>(*qScan);
-
-    throw std::runtime_error("Bug in CoordSystem1D::createCoordSystem: invalid case");
-}
+CoordSystem1D::CoordSystem1D(const IAxis*&& axis) : m_axis(std::move(axis)) {}
 
 //! Returns the size of underlying axis.
 size_t CoordSystem1D::axisSize(size_t i_axis) const
@@ -122,67 +143,46 @@ CoordSystem1D::createConvertedData(const OutputData<double>& data, Axes::Coords
 
 
 //  ************************************************************************************************
-//  class AngularReflectometryConverter
+//  class AngularReflectometryCoordinates
 //  ************************************************************************************************
 
-AngularReflectometryConverter::AngularReflectometryConverter(const Beam& beam, const IAxis& axis,
-                                                             Axes::Coords axis_units)
-    : m_wavelength(beam.wavelength())
-    , m_axis(createTranslatedAxis(axis, getTraslatorFrom(axis_units), axisName(0, axis_units)))
-
+AngularReflectometryCoordinates::AngularReflectometryCoordinates(double wavelength,
+                                                                 const IAxis& axis,
+                                                                 Axes::Coords axis_units)
+    : CoordSystem1D(createAxisFrom(axis, axis_units, angularAxisName(axis_units), wavelength))
+    , m_wavelength(wavelength)
 {
     if (m_axis->lowerBound() < 0 || m_axis->upperBound() > M_PI_2)
         throw std::runtime_error("Error in CoordSystem1D: input axis range is out of bounds");
 }
 
-AngularReflectometryConverter::AngularReflectometryConverter(const AngularSpecScan& handler)
-    : m_wavelength(handler.wavelength()), m_axis(handler.coordinateAxis()->clone())
+AngularReflectometryCoordinates::AngularReflectometryCoordinates(
+    const AngularReflectometryCoordinates& other)
+    : CoordSystem1D(other.m_axis->clone()), m_wavelength(other.m_wavelength)
 {
 }
 
-AngularReflectometryConverter::~AngularReflectometryConverter() = default;
+AngularReflectometryCoordinates::~AngularReflectometryCoordinates() = default;
 
-AngularReflectometryConverter* AngularReflectometryConverter::clone() const
+AngularReflectometryCoordinates* AngularReflectometryCoordinates::clone() const
 {
-    return new AngularReflectometryConverter(*this);
+    return new AngularReflectometryCoordinates(*this);
 }
 
-std::vector<Axes::Coords> AngularReflectometryConverter::availableUnits() const
+std::vector<Axes::Coords> AngularReflectometryCoordinates::availableUnits() const
 {
     return {Axes::Coords::NBINS, Axes::Coords::RADIANS, Axes::Coords::DEGREES, Axes::Coords::QSPACE,
             Axes::Coords::RQ4};
 }
 
-AngularReflectometryConverter::AngularReflectometryConverter(
-    const AngularReflectometryConverter& other)
-    : m_wavelength(other.m_wavelength), m_axis(other.m_axis->clone())
-{
-}
-
 std::vector<std::map<Axes::Coords, std::string>>
-AngularReflectometryConverter::createNameMaps() const
+AngularReflectometryCoordinates::createNameMaps() const
 {
     return {AxisNames::specAxis};
 }
 
 std::function<double(double)>
-AngularReflectometryConverter::getTraslatorFrom(Axes::Coords units) const
-{
-    switch (units) {
-    case Axes::Coords::RADIANS:
-        return [](double value) { return value; };
-    case Axes::Coords::DEGREES:
-        return [](double value) { return Units::deg2rad(value); };
-    case Axes::Coords::QSPACE:
-        return [this](double value) { return getInvQ(m_wavelength, value); };
-    default:
-        throwUnitsError("AngularReflectometryConverter::getTraslatorFrom",
-                        {Axes::Coords::RADIANS, Axes::Coords::DEGREES, Axes::Coords::QSPACE});
-    }
-}
-
-std::function<double(double)>
-AngularReflectometryConverter::getTraslatorTo(Axes::Coords units) const
+AngularReflectometryCoordinates::getTraslatorTo(Axes::Coords units) const
 {
     switch (units) {
     case Axes::Coords::RADIANS:
@@ -194,49 +194,49 @@ AngularReflectometryConverter::getTraslatorTo(Axes::Coords units) const
     case Axes::Coords::RQ4:
         return [wl = m_wavelength](double value) { return getQ(wl, value); };
     default:
-        throwUnitsError("AngularReflectometryConverter::getTraslatorTo", availableUnits());
+        throwUnitsError("AngularReflectometryCoordinates::getTraslatorTo", availableUnits());
     }
 }
 
 
 //  ************************************************************************************************
-//  class WavenumberReflectometryConverter
+//  class WavenumberReflectometryCoordinates
 //  ************************************************************************************************
 
-WavenumberReflectometryConverter::WavenumberReflectometryConverter(const QSpecScan& handler)
-    : m_axis(handler.coordinateAxis()->clone())
+WavenumberReflectometryCoordinates::WavenumberReflectometryCoordinates(const IAxis*&& axis)
+    : CoordSystem1D(std::move(axis))
 {
 }
 
-WavenumberReflectometryConverter::~WavenumberReflectometryConverter() = default;
-
-WavenumberReflectometryConverter* WavenumberReflectometryConverter::clone() const
+WavenumberReflectometryCoordinates::WavenumberReflectometryCoordinates(
+    const WavenumberReflectometryCoordinates& other)
+    : CoordSystem1D(other.coordinateAxis()->clone())
 {
-    return new WavenumberReflectometryConverter(*this);
 }
 
-//! Returns the list of all available units
-std::vector<Axes::Coords> WavenumberReflectometryConverter::availableUnits() const
+WavenumberReflectometryCoordinates::~WavenumberReflectometryCoordinates() = default;
+
+WavenumberReflectometryCoordinates* WavenumberReflectometryCoordinates::clone() const
 {
-    return {Axes::Coords::NBINS, Axes::Coords::QSPACE, Axes::Coords::RQ4};
+    return new WavenumberReflectometryCoordinates(*this);
 }
 
-WavenumberReflectometryConverter::WavenumberReflectometryConverter(
-    const WavenumberReflectometryConverter& other)
-    : m_axis(std::unique_ptr<const IAxis>(other.coordinateAxis()->clone()))
+//! Returns the list of all available units
+std::vector<Axes::Coords> WavenumberReflectometryCoordinates::availableUnits() const
 {
+    return {Axes::Coords::NBINS, Axes::Coords::QSPACE, Axes::Coords::RQ4};
 }
 
 //! Creates name map for axis in various units
 std::vector<std::map<Axes::Coords, std::string>>
-WavenumberReflectometryConverter::createNameMaps() const
+WavenumberReflectometryCoordinates::createNameMaps() const
 {
     return {AxisNames::specAxisQ};
 }
 
 //! Returns translating functional (inv. nm --> desired units)
 std::function<double(double)>
-WavenumberReflectometryConverter::getTraslatorTo(Axes::Coords units) const
+WavenumberReflectometryCoordinates::getTraslatorTo(Axes::Coords units) const
 {
     switch (units) {
     case Axes::Coords::QSPACE:
@@ -244,6 +244,6 @@ WavenumberReflectometryConverter::getTraslatorTo(Axes::Coords units) const
     case Axes::Coords::RQ4:
         return [](double value) { return value; };
     default:
-        throwUnitsError("WavenumberReflectometryConverter::getTraslatorTo", availableUnits());
+        throwUnitsError("WavenumberReflectometryCoordinates::getTraslatorTo", availableUnits());
     }
 }
diff --git a/Core/Scan/CoordSystem1D.h b/Device/Coord/CoordSystem1D.h
similarity index 66%
rename from Core/Scan/CoordSystem1D.h
rename to Device/Coord/CoordSystem1D.h
index c32570c8163245b3f2862d6fe7e17adbebbef38e..cf203d137ae8bc0e4b7ff1bd72c22dd5702424f8 100644
--- a/Core/Scan/CoordSystem1D.h
+++ b/Device/Coord/CoordSystem1D.h
@@ -2,7 +2,7 @@
 //
 //  BornAgain: simulate and fit reflection and scattering
 //
-//! @file      Core/Scan/CoordSystem1D.h
+//! @file      Device/Coord/CoordSystem1D.h
 //! @brief     Defines CoordSystem1D class and derived classes.
 //!
 //! @homepage  http://www.bornagainproject.org
@@ -20,24 +20,20 @@
 #ifndef BORNAGAIN_CORE_SCAN_COORDSYSTEM1D_H
 #define BORNAGAIN_CORE_SCAN_COORDSYSTEM1D_H
 
-#include "Device/Unit/ICoordSystem.h"
+#include "Device/Coord/ICoordSystem.h"
 
 #include <functional>
 
-class Beam;
 class ISpecularScan;
-class AngularSpecScan;
-class QSpecScan;
 
 
 //! Abstract base class to support coordinate transforms and axis labels for 1D scans.
-//! Inherited by AngularReflectometryConverter and WavenumberReflectometryConverter.
+//! Inherited by AngularReflectometryCoordinates and WavenumberReflectometryCoordinates.
 
 class CoordSystem1D : public ICoordSystem {
 public:
-    //! Factory function to create unit converter for particular type of specular data
-    static std::unique_ptr<CoordSystem1D> createCoordSystem(const ISpecularScan& handler);
-
+    CoordSystem1D() = delete;
+    CoordSystem1D(const IAxis*&& axis); //!< Takes ownership of axis
     ~CoordSystem1D() override = default;
 
     CoordSystem1D* clone() const override = 0;
@@ -66,20 +62,21 @@ protected:
     //! Returns translating functional (rads --> output units)
     virtual std::function<double(double)> getTraslatorTo(Axes::Coords units) const = 0;
 
-    virtual const IAxis* coordinateAxis() const = 0;
+    const IAxis* coordinateAxis() const { return m_axis.get(); }
+
+    std::unique_ptr<const IAxis> m_axis; //!< semantics depends on subclass
 };
 
 
 //! Conversion of axis units for the case of conventional (angle-based) reflectometry.
-class AngularReflectometryConverter : public CoordSystem1D {
+class AngularReflectometryCoordinates : public CoordSystem1D {
 public:
     //! Constructs the object for unit conversion.
-    AngularReflectometryConverter(const Beam& beam, const IAxis& axis,
-                                  Axes::Coords axis_units = Axes::Coords::RADIANS);
-    AngularReflectometryConverter(const AngularSpecScan& handler);
-    ~AngularReflectometryConverter() override;
+    AngularReflectometryCoordinates(double wavelength, const IAxis& axis,
+                                    Axes::Coords axis_units = Axes::Coords::RADIANS);
+    ~AngularReflectometryCoordinates() override;
 
-    AngularReflectometryConverter* clone() const override;
+    AngularReflectometryCoordinates* clone() const override;
 
     //! Returns the list of all available units
     std::vector<Axes::Coords> availableUnits() const override;
@@ -89,31 +86,25 @@ public:
 
 
 private:
-    AngularReflectometryConverter(const AngularReflectometryConverter& other);
+    AngularReflectometryCoordinates(const AngularReflectometryCoordinates& other);
 
     //! Creates name map for axis in various units
     std::vector<std::map<Axes::Coords, std::string>> createNameMaps() const override;
 
-    //! Returns translating functional (input units --> rads)
-    std::function<double(double)> getTraslatorFrom(Axes::Coords units) const;
-
     //! Returns translating functional (rads --> desired units)
     std::function<double(double)> getTraslatorTo(Axes::Coords units) const override;
 
-    const IAxis* coordinateAxis() const override { return m_axis.get(); }
-
-    double m_wavelength;                 //!< basic wavelength in nm (for translation to q-space).
-    std::unique_ptr<const IAxis> m_axis; //!< basic inclination angles (in rads).
+    double m_wavelength; //!< basic wavelength in nm (for translation to q-space).
 };
 
 
 //! Conversion of axis units for the case of q-defined reflectometry.
-class WavenumberReflectometryConverter : public CoordSystem1D {
+class WavenumberReflectometryCoordinates : public CoordSystem1D {
 public:
-    WavenumberReflectometryConverter(const QSpecScan& handler);
-    ~WavenumberReflectometryConverter() override;
+    WavenumberReflectometryCoordinates(const IAxis*&& axis);
+    ~WavenumberReflectometryCoordinates() override;
 
-    WavenumberReflectometryConverter* clone() const override;
+    WavenumberReflectometryCoordinates* clone() const override;
 
     //! Returns the list of all available units
     std::vector<Axes::Coords> availableUnits() const override;
@@ -122,17 +113,13 @@ public:
     Axes::Coords defaultUnits() const override { return Axes::Coords::QSPACE; }
 
 private:
-    WavenumberReflectometryConverter(const WavenumberReflectometryConverter& other);
+    WavenumberReflectometryCoordinates(const WavenumberReflectometryCoordinates& other);
 
     //! Creates name map for axis in various units
     std::vector<std::map<Axes::Coords, std::string>> createNameMaps() const override;
 
     //! Returns translating functional (inv. nm --> desired units)
     std::function<double(double)> getTraslatorTo(Axes::Coords units) const override;
-
-    const IAxis* coordinateAxis() const override { return m_axis.get(); }
-
-    std::unique_ptr<const IAxis> m_axis; //!< qz values (in inv. nm).
 };
 
 #endif // BORNAGAIN_CORE_SCAN_COORDSYSTEM1D_H
diff --git a/Device/Unit/ICoordSystem.cpp b/Device/Coord/ICoordSystem.cpp
similarity index 94%
rename from Device/Unit/ICoordSystem.cpp
rename to Device/Coord/ICoordSystem.cpp
index 732025f220d3086d68695c817a8147fbcffa08f8..34cf5c3d8f1c85e90b2d65891aeee498574aa7d9 100644
--- a/Device/Unit/ICoordSystem.cpp
+++ b/Device/Coord/ICoordSystem.cpp
@@ -2,7 +2,7 @@
 //
 //  BornAgain: simulate and fit reflection and scattering
 //
-//! @file      Device/Unit/ICoordSystem.cpp
+//! @file      Device/Coord/ICoordSystem.cpp
 //! @brief     Implements ICoordSystem class.
 //!
 //! @homepage  http://www.bornagainproject.org
@@ -12,9 +12,9 @@
 //
 //  ************************************************************************************************
 
-#include "Device/Unit/ICoordSystem.h"
+#include "Device/Coord/ICoordSystem.h"
+#include "Device/Coord/AxisNames.h"
 #include "Device/Data/OutputData.h"
-#include "Device/Unit/AxisNames.h"
 
 
 ICoordSystem::~ICoordSystem() = default;
diff --git a/Device/Unit/ICoordSystem.h b/Device/Coord/ICoordSystem.h
similarity index 97%
rename from Device/Unit/ICoordSystem.h
rename to Device/Coord/ICoordSystem.h
index 94324934ed7960b42d9ad9cdf7cb1fe16001dc89..0b553502d29e7a20a279ea89b30460f7d65407f6 100644
--- a/Device/Unit/ICoordSystem.h
+++ b/Device/Coord/ICoordSystem.h
@@ -2,7 +2,7 @@
 //
 //  BornAgain: simulate and fit reflection and scattering
 //
-//! @file      Device/Unit/ICoordSystem.h
+//! @file      Device/Coord/ICoordSystem.h
 //! @brief     Defines interface ICoordSystem and possible axis units.
 //!
 //! @homepage  http://www.bornagainproject.org
@@ -21,7 +21,7 @@
 #define BORNAGAIN_DEVICE_UNIT_ICOORDSYSTEM_H
 
 #include "Base/Types/ICloneable.h"
-#include "Device/Unit/Axes.h"
+#include "Device/Coord/Axes.h"
 #include <map>
 #include <memory>
 #include <string>
diff --git a/Device/Detector/IDetector.h b/Device/Detector/IDetector.h
index be110b3f41f990d45d0407c4489b6a54bb8e47e9..00c03190677973ad39f1c34d141c5c716bfb91a4 100644
--- a/Device/Detector/IDetector.h
+++ b/Device/Detector/IDetector.h
@@ -18,9 +18,9 @@
 
 #include "Base/Types/CloneableVector.h"
 #include "Base/Types/ICloneable.h"
+#include "Device/Coord/Axes.h"
 #include "Device/Detector/SimulationAreaIterator.h"
 #include "Device/ProDetector/DetectionProperties.h"
-#include "Device/Unit/Axes.h"
 
 class Beam;
 class DetectorMask;
diff --git a/Device/Histo/SimulationResult.cpp b/Device/Histo/SimulationResult.cpp
index 6ecb30b54015c7f0d258b66b93a6c4f8267eb76d..db3cfe5f5f009d91b6666d7dfe8782a4c243cfd1 100644
--- a/Device/Histo/SimulationResult.cpp
+++ b/Device/Histo/SimulationResult.cpp
@@ -16,8 +16,15 @@
 #include "Device/Histo/Histogram2D.h"
 
 SimulationResult::SimulationResult(const OutputData<double>& data,
-                                   const ICoordSystem& unit_converter)
-    : m_data(data.clone()), m_coordsys(unit_converter.clone())
+                                   const ICoordSystem& coords)
+    : m_data(data.clone()), m_coordsys(coords.clone())
+{
+    checkDimensions();
+}
+
+SimulationResult::SimulationResult(const OutputData<double>& data,
+                                   const ICoordSystem*&& coords)
+    : m_data(data.clone()), m_coordsys(std::move(coords))
 {
     checkDimensions();
 }
diff --git a/Device/Histo/SimulationResult.h b/Device/Histo/SimulationResult.h
index fb546a7aae2624b5df34d69a013a1dbeacb6121c..5292c89456c6ba8ed71e942d2f719339560ed6b7 100644
--- a/Device/Histo/SimulationResult.h
+++ b/Device/Histo/SimulationResult.h
@@ -16,7 +16,7 @@
 #define BORNAGAIN_DEVICE_HISTO_SIMULATIONRESULT_H
 
 #include "Base/Py/PyObject.h"
-#include "Device/Unit/ICoordSystem.h"
+#include "Device/Coord/ICoordSystem.h"
 #include <memory>
 #include <vector>
 
@@ -40,7 +40,8 @@ struct AxisInfo {
 class SimulationResult {
 public:
     SimulationResult() = default;
-    SimulationResult(const OutputData<double>& data, const ICoordSystem& unit_converter);
+    SimulationResult(const OutputData<double>& data, const ICoordSystem& coords); //TODO rm
+    SimulationResult(const OutputData<double>& data, const ICoordSystem*&& coords);
 
     SimulationResult(const SimulationResult& other);
     SimulationResult(SimulationResult&& other);
@@ -83,7 +84,7 @@ private:
     void checkDimensions() const;
 
     std::unique_ptr<OutputData<double>> m_data;
-    std::unique_ptr<ICoordSystem> m_coordsys;
+    std::unique_ptr<const ICoordSystem> m_coordsys;
 };
 
 #endif // BORNAGAIN_DEVICE_HISTO_SIMULATIONRESULT_H
diff --git a/Device/Instrument/CoordSystem2D.cpp b/Device/Instrument/CoordSystem2D.cpp
index 161240117d073a11ac34bf747ae63408d273eddd..20668ae5ad6cae0e4a073402ab1784aa71a0ac48 100644
--- a/Device/Instrument/CoordSystem2D.cpp
+++ b/Device/Instrument/CoordSystem2D.cpp
@@ -16,11 +16,11 @@
 #include "Base/Const/Units.h"
 #include "Base/Math/Constants.h"
 #include "Base/Pixel/RectangularPixel.h"
+#include "Device/Beam/Beam.h"
+#include "Device/Coord/AxisNames.h"
 #include "Device/Detector/RectangularDetector.h"
 #include "Device/Detector/SphericalDetector.h"
-#include "Device/Instrument/Instrument.h"
 #include "Device/ProDetector/RegionOfInterest.h"
-#include "Device/Unit/AxisNames.h"
 #include <algorithm>
 #include <cmath>
 #include <stdexcept>
@@ -56,7 +56,7 @@ CoordSystem2D::CoordSystem2D(const Beam& beam)
 }
 
 CoordSystem2D::CoordSystem2D(const CoordSystem2D& other)
-    : m_axis_data_table(other.m_axis_data_table)
+    : m_axes(other.m_axes)
     , m_wavelength(other.m_wavelength)
     , m_alpha_i(other.m_alpha_i)
     , m_phi_i(other.m_phi_i)
@@ -66,14 +66,14 @@ CoordSystem2D::CoordSystem2D(const CoordSystem2D& other)
 void CoordSystem2D::addAxisData(std::string name, double min, double max,
                                 Axes::Coords default_units, size_t nbins)
 {
-    m_axis_data_table.emplace_back(AxisData{name, min, max, default_units, nbins});
+    m_axes.emplace_back(AxisData{name, min, max, default_units, nbins});
 }
 
 double CoordSystem2D::calculateMin(size_t i_axis, Axes::Coords units) const
 {
     ASSERT(i_axis < dimension());
     units = substituteDefaultUnits(units);
-    const auto& axis_data = m_axis_data_table[i_axis];
+    const auto& axis_data = m_axes[i_axis];
     if (units == Axes::Coords::NBINS)
         return 0.0;
     return calculateValue(i_axis, units, axis_data.min);
@@ -83,7 +83,7 @@ double CoordSystem2D::calculateMax(size_t i_axis, Axes::Coords units) const
 {
     ASSERT(i_axis < dimension());
     units = substituteDefaultUnits(units);
-    const auto& axis_data = m_axis_data_table[i_axis];
+    const auto& axis_data = m_axes[i_axis];
     if (units == Axes::Coords::NBINS)
         return static_cast<double>(axis_data.nbins);
     return calculateValue(i_axis, units, axis_data.max);
@@ -92,7 +92,7 @@ double CoordSystem2D::calculateMax(size_t i_axis, Axes::Coords units) const
 size_t CoordSystem2D::axisSize(size_t i_axis) const
 {
     ASSERT(i_axis < dimension());
-    return m_axis_data_table[i_axis].nbins;
+    return m_axes[i_axis].nbins;
 }
 
 std::vector<Axes::Coords> CoordSystem2D::availableUnits() const
@@ -124,25 +124,12 @@ void CoordSystem2D::addDetectorAxis(const IDetector& detector, size_t i_axis)
                 roi_axis->size());
 }
 
-std::unique_ptr<CoordSystem2D> CoordSystem2D::createConverterForGISAS(const Instrument& instrument)
-{
-    const IDetector* const detector = instrument.getDetector();
-
-    if (const auto* const det = dynamic_cast<const SphericalDetector*>(detector))
-        return std::make_unique<SphericalConverter>(*det, instrument.beam());
-
-    if (const auto* const det = dynamic_cast<const RectangularDetector*>(detector))
-        return std::make_unique<RectangularConverter>(*det, instrument.beam());
-
-    throw std::runtime_error("Error in createConverterForGISAS: wrong or absent detector type");
-}
-
 
 //  ************************************************************************************************
-//  class SphericalConverter
+//  class SphericalCoords
 //  ************************************************************************************************
 
-SphericalConverter::SphericalConverter(const SphericalDetector& detector, const Beam& beam)
+SphericalCoords::SphericalCoords(const SphericalDetector& detector, const Beam& beam)
     : CoordSystem2D(beam)
 {
     ASSERT(detector.dimension() == 2);
@@ -150,23 +137,23 @@ SphericalConverter::SphericalConverter(const SphericalDetector& detector, const
     addDetectorAxis(detector, 1);
 }
 
-SphericalConverter::SphericalConverter(const SphericalConverter& other) : CoordSystem2D(other) {}
+SphericalCoords::SphericalCoords(const SphericalCoords& other) : CoordSystem2D(other) {}
 
-SphericalConverter::~SphericalConverter() = default;
+SphericalCoords::~SphericalCoords() = default;
 
-SphericalConverter* SphericalConverter::clone() const
+SphericalCoords* SphericalCoords::clone() const
 {
-    return new SphericalConverter(*this);
+    return new SphericalCoords(*this);
 }
 
-std::vector<Axes::Coords> SphericalConverter::availableUnits() const
+std::vector<Axes::Coords> SphericalCoords::availableUnits() const
 {
     auto result = CoordSystem2D::availableUnits();
     result.push_back(Axes::Coords::QSPACE);
     return result;
 }
 
-double SphericalConverter::calculateValue(size_t i_axis, Axes::Coords units, double value) const
+double SphericalCoords::calculateValue(size_t i_axis, Axes::Coords units, double value) const
 {
     switch (units) {
     case Axes::Coords::RADIANS:
@@ -182,7 +169,7 @@ double SphericalConverter::calculateValue(size_t i_axis, Axes::Coords units, dou
             const auto k_f = vecOfLambdaAlphaPhi(m_wavelength, value, 0.0);
             return (k_f - k_i).z();
         }
-        throw std::runtime_error("Error in SphericalConverter::calculateValue: "
+        throw std::runtime_error("Error in SphericalCoords::calculateValue: "
                                  "incorrect axis index: "
                                  + std::to_string(static_cast<int>(i_axis)));
     }
@@ -195,26 +182,26 @@ double SphericalConverter::calculateValue(size_t i_axis, Axes::Coords units, dou
             const auto k_f = vecOfLambdaAlphaPhi(m_wavelength, value, 0.0);
             return (k_f - k_i).x();
         }
-        throw std::runtime_error("Error in SphericalConverter::calculateValue: "
+        throw std::runtime_error("Error in SphericalCoords::calculateValue: "
                                  "incorrect axis index: "
                                  + std::to_string(static_cast<int>(i_axis)));
     }
     default:
-        throwUnitsError("SphericalConverter::calculateValue", availableUnits());
+        throwUnitsError("SphericalCoords::calculateValue", availableUnits());
     }
 }
 
-std::vector<std::map<Axes::Coords, std::string>> SphericalConverter::createNameMaps() const
+std::vector<std::map<Axes::Coords, std::string>> SphericalCoords::createNameMaps() const
 {
     return {AxisNames::sphericalAxis0, AxisNames::sphericalAxis1};
 }
 
 
 //  ************************************************************************************************
-//  class RectangularConverter
+//  class ImageCoords
 //  ************************************************************************************************
 
-RectangularConverter::RectangularConverter(const RectangularDetector& detector, const Beam& beam)
+ImageCoords::ImageCoords(const RectangularDetector& detector, const Beam& beam)
     : CoordSystem2D(beam)
 {
     ASSERT(detector.dimension() == 2);
@@ -223,19 +210,19 @@ RectangularConverter::RectangularConverter(const RectangularDetector& detector,
     m_detector_pixel.reset(detector.regionOfInterestPixel());
 }
 
-RectangularConverter::RectangularConverter(const RectangularConverter& other)
+ImageCoords::ImageCoords(const ImageCoords& other)
     : CoordSystem2D(other), m_detector_pixel(other.m_detector_pixel->clone())
 {
 }
 
-RectangularConverter::~RectangularConverter() = default;
+ImageCoords::~ImageCoords() = default;
 
-RectangularConverter* RectangularConverter::clone() const
+ImageCoords* ImageCoords::clone() const
 {
-    return new RectangularConverter(*this);
+    return new ImageCoords(*this);
 }
 
-std::vector<Axes::Coords> RectangularConverter::availableUnits() const
+std::vector<Axes::Coords> ImageCoords::availableUnits() const
 {
     auto result = CoordSystem2D::availableUnits();
     result.push_back(Axes::Coords::QSPACE);
@@ -243,7 +230,7 @@ std::vector<Axes::Coords> RectangularConverter::availableUnits() const
     return result;
 }
 
-double RectangularConverter::calculateValue(size_t i_axis, Axes::Coords units, double value) const
+double ImageCoords::calculateValue(size_t i_axis, Axes::Coords units, double value) const
 {
     ASSERT(m_wavelength > 0);
     if (units == Axes::Coords::MM)
@@ -252,7 +239,7 @@ double RectangularConverter::calculateValue(size_t i_axis, Axes::Coords units, d
     const auto k01 = m_detector_pixel->getPosition(0.0, 1.0);
     const auto k10 = m_detector_pixel->getPosition(1.0, 0.0);
     const auto& max_pos = i_axis == 0 ? k10 : k01; // position of max along given axis
-    const double shift = value - m_axis_data_table[i_axis].min;
+    const double shift = value - m_axes[i_axis].min;
     const kvector_t out_dir = k00 + shift * (max_pos - k00).unit();
     const kvector_t k_f = out_dir.unit() * M_TWOPI / m_wavelength;
 
@@ -276,23 +263,23 @@ double RectangularConverter::calculateValue(size_t i_axis, Axes::Coords units, d
             return (k_f - k_i).x();
     }
     default:
-        throwUnitsError("RectangularConverter::calculateValue", availableUnits());
+        throwUnitsError("ImageCoords::calculateValue", availableUnits());
     }
     ASSERT(0);
 }
 
-std::vector<std::map<Axes::Coords, std::string>> RectangularConverter::createNameMaps() const
+std::vector<std::map<Axes::Coords, std::string>> ImageCoords::createNameMaps() const
 {
     return {AxisNames::rectangularAxis0, AxisNames::rectangularAxis1};
 }
 
 
 //  ************************************************************************************************
-//  class OffSpecularConverter
+//  class OffSpecularCoordinates
 //  ************************************************************************************************
 
-OffSpecularConverter::OffSpecularConverter(const IDetector2D& detector, const Beam& beam,
-                                           const IAxis& alpha_axis)
+OffSpecularCoordinates::OffSpecularCoordinates(const IDetector2D& detector, const Beam& beam,
+                                               const IAxis& alpha_axis)
     : CoordSystem2D(beam)
 {
     ASSERT(detector.dimension() == 2);
@@ -301,23 +288,24 @@ OffSpecularConverter::OffSpecularConverter(const IDetector2D& detector, const Be
     addDetectorYAxis(detector);
 }
 
-OffSpecularConverter::OffSpecularConverter(const OffSpecularConverter& other) : CoordSystem2D(other)
+OffSpecularCoordinates::OffSpecularCoordinates(const OffSpecularCoordinates& other)
+    : CoordSystem2D(other)
 {
 }
 
-OffSpecularConverter::~OffSpecularConverter() = default;
+OffSpecularCoordinates::~OffSpecularCoordinates() = default;
 
-OffSpecularConverter* OffSpecularConverter::clone() const
+OffSpecularCoordinates* OffSpecularCoordinates::clone() const
 {
-    return new OffSpecularConverter(*this);
+    return new OffSpecularCoordinates(*this);
 }
 
-Axes::Coords OffSpecularConverter::defaultUnits() const
+Axes::Coords OffSpecularCoordinates::defaultUnits() const
 {
     return Axes::Coords::DEGREES;
 }
 
-double OffSpecularConverter::calculateValue(size_t, Axes::Coords units, double value) const
+double OffSpecularCoordinates::calculateValue(size_t, Axes::Coords units, double value) const
 {
     switch (units) {
     case Axes::Coords::RADIANS:
@@ -325,16 +313,16 @@ double OffSpecularConverter::calculateValue(size_t, Axes::Coords units, double v
     case Axes::Coords::DEGREES:
         return Units::rad2deg(value);
     default:
-        throwUnitsError("OffSpecularConverter::calculateValue", availableUnits());
+        throwUnitsError("OffSpecularCoordinates::calculateValue", availableUnits());
     }
 }
 
-std::vector<std::map<Axes::Coords, std::string>> OffSpecularConverter::createNameMaps() const
+std::vector<std::map<Axes::Coords, std::string>> OffSpecularCoordinates::createNameMaps() const
 {
     return {AxisNames::offSpecularAxis0, AxisNames::offSpecularAxis1};
 }
 
-void OffSpecularConverter::addDetectorYAxis(const IDetector2D& detector)
+void OffSpecularCoordinates::addDetectorYAxis(const IDetector2D& detector)
 {
     const auto& axis = detector.axis(1);
     const auto* roi = detector.regionOfInterest();
@@ -363,13 +351,13 @@ void OffSpecularConverter::addDetectorYAxis(const IDetector2D& detector)
 
 
 //  ************************************************************************************************
-//  class DepthProbeConverter
+//  class DepthProbeCoordinates
 //  ************************************************************************************************
 
 const std::string z_axis_name = "Position [nm]";
 
-DepthProbeConverter::DepthProbeConverter(const Beam& beam, const IAxis& alpha_axis,
-                                         const IAxis& z_axis)
+DepthProbeCoordinates::DepthProbeCoordinates(const Beam& beam, const IAxis& alpha_axis,
+                                             const IAxis& z_axis)
     : CoordSystem2D(beam)
 {
     const auto& alpha_axis_name = axisName(0);
@@ -380,27 +368,30 @@ DepthProbeConverter::DepthProbeConverter(const Beam& beam, const IAxis& alpha_ax
                 z_axis.size());
 }
 
-DepthProbeConverter::DepthProbeConverter(const DepthProbeConverter& other) : CoordSystem2D(other) {}
+DepthProbeCoordinates::DepthProbeCoordinates(const DepthProbeCoordinates& other)
+    : CoordSystem2D(other)
+{
+}
 
-DepthProbeConverter::~DepthProbeConverter() = default;
+DepthProbeCoordinates::~DepthProbeCoordinates() = default;
 
-DepthProbeConverter* DepthProbeConverter::clone() const
+DepthProbeCoordinates* DepthProbeCoordinates::clone() const
 {
-    return new DepthProbeConverter(*this);
+    return new DepthProbeCoordinates(*this);
 }
 
-std::vector<Axes::Coords> DepthProbeConverter::availableUnits() const
+std::vector<Axes::Coords> DepthProbeCoordinates::availableUnits() const
 {
     auto result = CoordSystem2D::availableUnits();
     result.push_back(Axes::Coords::QSPACE);
     return result;
 }
 
-double DepthProbeConverter::calculateValue(size_t i_axis, Axes::Coords units, double value) const
+double DepthProbeCoordinates::calculateValue(size_t i_axis, Axes::Coords units, double value) const
 {
     const auto& available_units = availableUnits();
     if (std::find(available_units.begin(), available_units.end(), units) == available_units.cend())
-        throwUnitsError("DepthProbeConverter::checkUnits", available_units);
+        throwUnitsError("DepthProbeCoordinates::checkUnits", available_units);
 
     if (i_axis == 1)
         return value; // unit conversions are not applied to sample position axis
@@ -414,7 +405,7 @@ double DepthProbeConverter::calculateValue(size_t i_axis, Axes::Coords units, do
     }
 }
 
-std::vector<std::map<Axes::Coords, std::string>> DepthProbeConverter::createNameMaps() const
+std::vector<std::map<Axes::Coords, std::string>> DepthProbeCoordinates::createNameMaps() const
 {
     return {AxisNames::specAxis, AxisNames::sampleDepthAxis};
 }
diff --git a/Device/Instrument/CoordSystem2D.h b/Device/Instrument/CoordSystem2D.h
index 0e4caa5ab25560546042805d1fb8d71c775493e6..56c8ac07cba983b0345cb53282e0dc21e8306154 100644
--- a/Device/Instrument/CoordSystem2D.h
+++ b/Device/Instrument/CoordSystem2D.h
@@ -21,12 +21,11 @@
 #define BORNAGAIN_DEVICE_INSTRUMENT_COORDSYSTEM2D_H
 
 #include "Base/Vector/Vectors3D.h"
-#include "Device/Unit/ICoordSystem.h"
+#include "Device/Coord/ICoordSystem.h"
 
 class Beam;
 class IDetector;
 class IDetector2D;
-class Instrument;
 class RectangularDetector;
 class RectangularPixel;
 class SphericalDetector;
@@ -39,7 +38,7 @@ public:
     CoordSystem2D(const Beam& beam);
     ~CoordSystem2D() override = default;
 
-    virtual size_t dimension() const override { return m_axis_data_table.size(); }
+    virtual size_t dimension() const override { return m_axes.size(); }
 
     double calculateMin(size_t i_axis, Axes::Coords units) const override;
     double calculateMax(size_t i_axis, Axes::Coords units) const override;
@@ -52,10 +51,6 @@ public:
     std::unique_ptr<const IAxis> createConvertedAxis(size_t i_axis,
                                                      Axes::Coords units) const override;
 
-    //! Helper factory function to use in GISASSimulation. Depending on the type of detector,
-    //! returns either RectangularConverter or SphericalConverter.
-    static std::unique_ptr<CoordSystem2D> createConverterForGISAS(const Instrument& instrument);
-
 protected:
     CoordSystem2D(const CoordSystem2D& other);
     void addDetectorAxis(const IDetector& detector, size_t i_axis);
@@ -70,7 +65,7 @@ protected:
         Axes::Coords default_units;
         size_t nbins;
     };
-    std::vector<AxisData> m_axis_data_table;
+    std::vector<AxisData> m_axes;
 #endif
     double m_wavelength;
     double m_alpha_i;
@@ -85,13 +80,13 @@ private:
 //! Its default units are radians for both axes
 //! @ingroup simulation_internal
 
-class SphericalConverter : public CoordSystem2D {
+class SphericalCoords : public CoordSystem2D {
 public:
-    SphericalConverter() = delete;
-    SphericalConverter(const SphericalDetector& detector, const Beam& beam);
-    ~SphericalConverter() override;
+    SphericalCoords() = delete;
+    SphericalCoords(const SphericalDetector& detector, const Beam& beam);
+    ~SphericalCoords() override;
 
-    SphericalConverter* clone() const override;
+    SphericalCoords* clone() const override;
 
     //! Returns the list of all available units
     std::vector<Axes::Coords> availableUnits() const override;
@@ -99,7 +94,7 @@ public:
     Axes::Coords defaultUnits() const override { return Axes::Coords::DEGREES; }
 
 private:
-    SphericalConverter(const SphericalConverter& other); //!< used by clone()
+    SphericalCoords(const SphericalCoords& other); //!< used by clone()
     double calculateValue(size_t i_axis, Axes::Coords units, double value) const override;
     std::vector<std::map<Axes::Coords, std::string>> createNameMaps() const override;
 };
@@ -109,13 +104,13 @@ private:
 //! Its default units are mm for both axes
 //! @ingroup simulation_internal
 
-class RectangularConverter : public CoordSystem2D {
+class ImageCoords : public CoordSystem2D {
 public:
-    RectangularConverter() = delete;
-    RectangularConverter(const RectangularDetector& detector, const Beam& beam);
-    ~RectangularConverter() override;
+    ImageCoords() = delete;
+    ImageCoords(const RectangularDetector& detector, const Beam& beam);
+    ~ImageCoords() override;
 
-    RectangularConverter* clone() const override;
+    ImageCoords* clone() const override;
 
     //! Returns the list of all available units
     std::vector<Axes::Coords> availableUnits() const override;
@@ -123,7 +118,7 @@ public:
     Axes::Coords defaultUnits() const override { return Axes::Coords::MM; }
 
 private:
-    RectangularConverter(const RectangularConverter& other); //!< used by clone()
+    ImageCoords(const ImageCoords& other); //!< used by clone()
     double calculateValue(size_t i_axis, Axes::Coords units, double value) const override;
     std::vector<std::map<Axes::Coords, std::string>> createNameMaps() const override;
 
@@ -136,18 +131,18 @@ private:
 //! Its default units are radians for both axes
 //! @ingroup simulation_internal
 
-class OffSpecularConverter : public CoordSystem2D {
+class OffSpecularCoordinates : public CoordSystem2D {
 public:
-    OffSpecularConverter() = delete;
-    OffSpecularConverter(const IDetector2D& detector, const Beam& beam, const IAxis& alpha_axis);
-    ~OffSpecularConverter() override;
+    OffSpecularCoordinates() = delete;
+    OffSpecularCoordinates(const IDetector2D& detector, const Beam& beam, const IAxis& alpha_axis);
+    ~OffSpecularCoordinates() override;
 
-    OffSpecularConverter* clone() const override;
+    OffSpecularCoordinates* clone() const override;
 
     Axes::Coords defaultUnits() const override;
 
 private:
-    OffSpecularConverter(const OffSpecularConverter& other); //!< used by clone()
+    OffSpecularCoordinates(const OffSpecularCoordinates& other); //!< used by clone()
     double calculateValue(size_t i_axis, Axes::Coords units, double value) const override;
     std::vector<std::map<Axes::Coords, std::string>> createNameMaps() const override;
 
@@ -155,17 +150,17 @@ private:
 };
 
 
-//! DepthProbeConverter class handles the unit translations for depth probe simulations
+//! DepthProbeCoordinates class handles the unit translations for depth probe simulations
 //! Its default units are radians for x-axis and nm for y-axis
 //! @ingroup simulation_internal
 
-class DepthProbeConverter : public CoordSystem2D {
+class DepthProbeCoordinates : public CoordSystem2D {
 public:
-    DepthProbeConverter() = delete;
-    DepthProbeConverter(const Beam& beam, const IAxis& alpha_axis, const IAxis& z_axis);
-    ~DepthProbeConverter() override;
+    DepthProbeCoordinates() = delete;
+    DepthProbeCoordinates(const Beam& beam, const IAxis& alpha_axis, const IAxis& z_axis);
+    ~DepthProbeCoordinates() override;
 
-    DepthProbeConverter* clone() const override;
+    DepthProbeCoordinates* clone() const override;
 
     //! Returns the list of all available units
     std::vector<Axes::Coords> availableUnits() const override;
@@ -173,7 +168,7 @@ public:
     Axes::Coords defaultUnits() const override { return Axes::Coords::DEGREES; }
 
 private:
-    DepthProbeConverter(const DepthProbeConverter& other); //!< used by clone()
+    DepthProbeCoordinates(const DepthProbeCoordinates& other); //!< used by clone()
     double calculateValue(size_t, Axes::Coords units, double value) const override;
     std::vector<std::map<Axes::Coords, std::string>> createNameMaps() const override;
 };
diff --git a/Device/Instrument/Instrument.cpp b/Device/Instrument/Instrument.cpp
index 221ad24d6cffbff0b0704f171c246afd44e381aa..fa81d528d906019d34d5304555ba217ea7c47019 100644
--- a/Device/Instrument/Instrument.cpp
+++ b/Device/Instrument/Instrument.cpp
@@ -13,8 +13,10 @@
 //  ************************************************************************************************
 
 #include "Device/Instrument/Instrument.h"
+#include "Device/Detector/RectangularDetector.h"
 #include "Device/Detector/SphericalDetector.h"
 #include "Device/Histo/Histogram2D.h"
+#include "Device/Instrument/CoordSystem2D.h"
 #include "Device/Resolution/IResolutionFunction2D.h"
 
 Instrument::Instrument(const Beam& beam, const IDetector& detector)
@@ -109,3 +111,17 @@ IDetector& Instrument::detector()
     ASSERT(m_detector);
     return *m_detector;
 }
+
+CoordSystem2D* Instrument::createScatteringCoords() const
+{
+    const IDetector* const detector = getDetector();
+
+    // TODO: use virtual fcts in detector classes instead of dynamic casts here
+    if (const auto* const det = dynamic_cast<const SphericalDetector*>(detector))
+        return new SphericalCoords(*det, beam());
+
+    if (const auto* const det = dynamic_cast<const RectangularDetector*>(detector))
+        return new ImageCoords(*det, beam());
+
+    ASSERT(0);
+}
diff --git a/Device/Instrument/Instrument.h b/Device/Instrument/Instrument.h
index 3ee6f560badb44810ba67e89e5e875b9e315f10d..aa168caf1e76c4978b0e5f3763dc5795589939bc 100644
--- a/Device/Instrument/Instrument.h
+++ b/Device/Instrument/Instrument.h
@@ -23,6 +23,7 @@
 #include "Device/Beam/Beam.h"
 #include <memory>
 
+class CoordSystem2D;
 class IDetector;
 class IDetector2D;
 
@@ -60,6 +61,8 @@ public:
 
     std::vector<const INode*> getChildren() const override;
 
+    CoordSystem2D* createScatteringCoords() const;
+
 protected:
     Beam m_beam;
     std::unique_ptr<IDetector> m_detector;
diff --git a/GUI/coregui/DataLoaders/QREDataLoader.cpp b/GUI/coregui/DataLoaders/QREDataLoader.cpp
index 8d782926838d516b4b121aaf155f65d2599fa95f..f9b4d4b6a1fd1292416acb4dcb7e03ce0e8c9694 100644
--- a/GUI/coregui/DataLoaders/QREDataLoader.cpp
+++ b/GUI/coregui/DataLoaders/QREDataLoader.cpp
@@ -14,9 +14,9 @@
 
 #include "GUI/coregui/DataLoaders/QREDataLoader.h"
 #include "Base/Axis/PointwiseAxis.h"
+#include "Device/Coord/AxisNames.h"
 #include "Device/Histo/IntensityDataIOFactory.h"
 #include "Device/InputOutput/DataFormatUtils.h"
-#include "Device/Unit/AxisNames.h"
 #include "GUI/coregui/DataLoaders/QREDataLoaderProperties.h"
 #include "GUI/coregui/DataLoaders/QREDataLoaderResultModel.h"
 #include "GUI/coregui/Models/DataItem.h"
diff --git a/GUI/coregui/Models/DataViewUtils.cpp b/GUI/coregui/Models/DataViewUtils.cpp
index d2370881bc58c83438ab574940ea0cf212e35773..4621cf0652168b09a16068a40938d9c3702c205a 100644
--- a/GUI/coregui/Models/DataViewUtils.cpp
+++ b/GUI/coregui/Models/DataViewUtils.cpp
@@ -13,7 +13,7 @@
 //  ************************************************************************************************
 
 #include "GUI/coregui/Models/DataViewUtils.h"
-#include "Device/Unit/ICoordSystem.h"
+#include "Device/Coord/ICoordSystem.h"
 #include "GUI/coregui/Models/Data1DViewItem.h"
 #include "GUI/coregui/Models/DataItem.h"
 #include "GUI/coregui/Models/DataPropertyContainer.h"
@@ -24,7 +24,7 @@
 
 namespace {
 
-std::unique_ptr<ICoordSystem> getConverter(Data1DViewItem* view_item)
+ICoordSystem* getConverter(Data1DViewItem* view_item)
 {
     auto job_item = view_item->jobItem();
     ASSERT(job_item->instrumentItem());
@@ -44,7 +44,7 @@ Axes::Coords selectedUnits(Data1DViewItem* view_item)
 
 void DataViewUtils::updateAxesTitle(Data1DViewItem* view_item)
 {
-    auto converter = getConverter(view_item);
+    std::unique_ptr<ICoordSystem> converter{getConverter(view_item)};
     if (!converter)
         return;
     auto current_units = selectedUnits(view_item);
diff --git a/GUI/coregui/Models/DomainObjectBuilder.cpp b/GUI/coregui/Models/DomainObjectBuilder.cpp
index 46b5c51bf9f046c948b0e481021120ce54cfccad..059d7ac01791f6b87c66e09ee1ea0db7e4b006ba 100644
--- a/GUI/coregui/Models/DomainObjectBuilder.cpp
+++ b/GUI/coregui/Models/DomainObjectBuilder.cpp
@@ -14,7 +14,7 @@
 
 #include "GUI/coregui/Models/DomainObjectBuilder.h"
 #include "Base/Const/Units.h"
-#include "Core/Scan/CoordSystem1D.h"
+#include "Device/Coord/CoordSystem1D.h"
 #include "Device/Detector/IDetector2D.h"
 #include "Device/Instrument/CoordSystem2D.h"
 #include "GUI/coregui/Models/AxesItems.h"
diff --git a/GUI/coregui/Models/InstrumentItems.cpp b/GUI/coregui/Models/InstrumentItems.cpp
index ca7cb63b56a9ec74755cdd2a7d05eeafbf608f71..21227971ef818819d6182768cdae57717b977daa 100644
--- a/GUI/coregui/Models/InstrumentItems.cpp
+++ b/GUI/coregui/Models/InstrumentItems.cpp
@@ -14,7 +14,7 @@
 
 #include "GUI/coregui/Models/InstrumentItems.h"
 #include "Base/Const/Units.h"
-#include "Core/Scan/CoordSystem1D.h"
+#include "Device/Coord/CoordSystem1D.h"
 #include "Core/Simulation/DepthProbeSimulation.h"
 #include "Device/Instrument/CoordSystem2D.h"
 #include "Device/Instrument/Instrument.h"
@@ -202,7 +202,7 @@ bool SpecularInstrumentItem::alignedWith(const RealDataItem* item) const
     }
 }
 
-std::unique_ptr<ICoordSystem> SpecularInstrumentItem::createCoordSystem() const
+ICoordSystem* SpecularInstrumentItem::createCoordSystem() const
 {
     const auto instrument = createInstrument();
     auto axis_item = beamItem()->currentInclinationAxisItem();
@@ -210,11 +210,12 @@ std::unique_ptr<ICoordSystem> SpecularInstrumentItem::createCoordSystem() const
         if (!pointwise_axis->containsNonXMLData()) // workaround for loading project
             return nullptr;
         Axes::Coords native_units = JobItemUtils::coordsFromName(pointwise_axis->getUnitsLabel());
-        return std::make_unique<AngularReflectometryConverter>(
-            instrument->beam(), *pointwise_axis->axis(), native_units);
-    } else
-        return std::make_unique<AngularReflectometryConverter>(
-            instrument->beam(), *axis_item->createAxis(1.0), Axes::Coords::DEGREES);
+        return new AngularReflectometryCoordinates(
+            instrument->beam().wavelength(), *pointwise_axis->axis(), native_units);
+    }
+
+    return new AngularReflectometryCoordinates(
+        instrument->beam().wavelength(), *axis_item->createAxis(1.0), Axes::Coords::DEGREES);
 }
 
 QString SpecularInstrumentItem::defaultName() const
@@ -304,11 +305,11 @@ QString GISASInstrumentItem::defaultName() const
     return "GISAS";
 }
 
-std::unique_ptr<ICoordSystem> GISASInstrumentItem::createCoordSystem() const
+ICoordSystem* GISASInstrumentItem::createCoordSystem() const
 {
     const auto instrument = createInstrument();
     instrument->initDetector();
-    return CoordSystem2D::createConverterForGISAS(*instrument);
+    return instrument->createScatteringCoords();
 }
 
 //  ************************************************************************************************
@@ -355,14 +356,14 @@ QString OffSpecularInstrumentItem::defaultName() const
     return "OffSpecular";
 }
 
-std::unique_ptr<ICoordSystem> OffSpecularInstrumentItem::createCoordSystem() const
+ICoordSystem* OffSpecularInstrumentItem::createCoordSystem() const
 {
     const auto instrument = createInstrument();
     instrument->initDetector();
     auto axis_item = item<BasicAxisItem>(OffSpecularInstrumentItem::P_ALPHA_AXIS);
     const auto detector2d = dynamic_cast<const IDetector2D*>(instrument->getDetector());
-    return std::make_unique<OffSpecularConverter>(*detector2d, instrument->beam(),
-                                                  *axis_item->createAxis(Units::deg));
+    return new OffSpecularCoordinates(*detector2d, instrument->beam(),
+                                      *axis_item->createAxis(Units::deg));
 }
 
 //  ************************************************************************************************
@@ -447,7 +448,7 @@ std::unique_ptr<DepthProbeSimulation> DepthProbeInstrumentItem::createSimulation
     return simulation;
 }
 
-std::unique_ptr<ICoordSystem> DepthProbeInstrumentItem::createCoordSystem() const
+ICoordSystem* DepthProbeInstrumentItem::createCoordSystem() const
 {
     return createSimulation()->createCoordSystem();
 }
diff --git a/GUI/coregui/Models/InstrumentItems.h b/GUI/coregui/Models/InstrumentItems.h
index 0dcfe22eb92be2382f43965e6aa453afef377a53..2a1f2f6533eb68d96709992395402987edd28910 100644
--- a/GUI/coregui/Models/InstrumentItems.h
+++ b/GUI/coregui/Models/InstrumentItems.h
@@ -62,7 +62,7 @@ public:
     //! The default user visible name when creating an instrument
     virtual QString defaultName() const = 0;
 
-    virtual std::unique_ptr<ICoordSystem> createCoordSystem() const = 0;
+    virtual ICoordSystem* createCoordSystem() const = 0;
 
 protected:
     explicit InstrumentItem(const QString& modelType);
@@ -84,7 +84,7 @@ public:
     bool alignedWith(const RealDataItem* item) const override;
     virtual QString defaultName() const override;
 
-    std::unique_ptr<ICoordSystem> createCoordSystem() const override;
+    ICoordSystem* createCoordSystem() const override;
 };
 
 
@@ -116,7 +116,7 @@ public:
     void updateToRealData(const RealDataItem* item) override;
     virtual QString defaultName() const override;
 
-    std::unique_ptr<ICoordSystem> createCoordSystem() const override;
+    ICoordSystem* createCoordSystem() const override;
 };
 
 
@@ -129,7 +129,7 @@ public:
     void updateToRealData(const RealDataItem* item) override;
     virtual QString defaultName() const override;
 
-    std::unique_ptr<ICoordSystem> createCoordSystem() const override;
+    ICoordSystem* createCoordSystem() const override;
 };
 
 
@@ -151,7 +151,7 @@ public:
     // after ISimulation gets createCoordSystem method
     std::unique_ptr<DepthProbeSimulation> createSimulation() const;
 
-    std::unique_ptr<ICoordSystem> createCoordSystem() const override;
+    ICoordSystem* createCoordSystem() const override;
 };
 
 #endif // BORNAGAIN_GUI_COREGUI_MODELS_INSTRUMENTITEMS_H
diff --git a/GUI/coregui/Models/JobModelFunctions.cpp b/GUI/coregui/Models/JobModelFunctions.cpp
index 3f2104e6242d7b4b03f91ef0b6cece99cc1ec22f..823bb7b136e5ec495f891d5fdda85b2eb3a4627e 100644
--- a/GUI/coregui/Models/JobModelFunctions.cpp
+++ b/GUI/coregui/Models/JobModelFunctions.cpp
@@ -13,9 +13,9 @@
 //  ************************************************************************************************
 
 #include "GUI/coregui/Models/JobModelFunctions.h"
+#include "Device/Coord/ICoordSystem.h"
 #include "Device/Detector/IDetector2D.h"
 #include "Device/Instrument/Instrument.h"
-#include "Device/Unit/ICoordSystem.h"
 #include "GUI/coregui/Models/Data1DViewItem.h"
 #include "GUI/coregui/Models/DataPropertyContainer.h"
 #include "GUI/coregui/Models/DetectorItems.h"
diff --git a/GUI/coregui/Models/PointwiseAxisItem.cpp b/GUI/coregui/Models/PointwiseAxisItem.cpp
index 646d707fb93924481eea01482a11d93d355d4c82..7827fd367fe41bd2a5906b407c613241b8e069a8 100644
--- a/GUI/coregui/Models/PointwiseAxisItem.cpp
+++ b/GUI/coregui/Models/PointwiseAxisItem.cpp
@@ -14,9 +14,9 @@
 
 #include "GUI/coregui/Models/PointwiseAxisItem.h"
 #include "Base/Axis/PointwiseAxis.h"
+#include "Device/Coord/ICoordSystem.h"
 #include "Device/Data/OutputData.h"
 #include "Device/Histo/IntensityDataIOFactory.h"
-#include "Device/Unit/ICoordSystem.h"
 #include "GUI/coregui/Models/InstrumentItems.h"
 
 namespace {
diff --git a/GUI/coregui/Views/ImportDataWidgets/CsvImportAssistant/CsvDataColumn.h b/GUI/coregui/Views/ImportDataWidgets/CsvImportAssistant/CsvDataColumn.h
index 103e7c43df0bfee62feb22368b44f6dc5795d98a..4626f7c3e02005bb358d7f635fd4d5a1f805f97b 100644
--- a/GUI/coregui/Views/ImportDataWidgets/CsvImportAssistant/CsvDataColumn.h
+++ b/GUI/coregui/Views/ImportDataWidgets/CsvImportAssistant/CsvDataColumn.h
@@ -15,7 +15,7 @@
 #ifndef BORNAGAIN_GUI_COREGUI_VIEWS_IMPORTDATAWIDGETS_CSVIMPORTASSISTANT_CSVDATACOLUMN_H
 #define BORNAGAIN_GUI_COREGUI_VIEWS_IMPORTDATAWIDGETS_CSVIMPORTASSISTANT_CSVDATACOLUMN_H
 
-#include "Device/Unit/Axes.h"
+#include "Device/Coord/Axes.h"
 #include "GUI/coregui/Views/ImportDataWidgets/CsvImportAssistant/CsvNamespace.h"
 
 class CsvIntensityColumn {
diff --git a/GUI/coregui/Views/ImportDataWidgets/CsvImportAssistant/CsvImportAssistant.cpp b/GUI/coregui/Views/ImportDataWidgets/CsvImportAssistant/CsvImportAssistant.cpp
index e2a607bdf54846e1470a2d967f0f5676841764d7..cb5de41d711b30e59362fefe605fbe49a7a78057 100644
--- a/GUI/coregui/Views/ImportDataWidgets/CsvImportAssistant/CsvImportAssistant.cpp
+++ b/GUI/coregui/Views/ImportDataWidgets/CsvImportAssistant/CsvImportAssistant.cpp
@@ -13,8 +13,8 @@
 //  ************************************************************************************************
 
 #include "Base/Axis/PointwiseAxis.h"
+#include "Device/Coord/AxisNames.h"
 #include "Device/Data/OutputData.h"
-#include "Device/Unit/AxisNames.h"
 #include "GUI/coregui/Views/ImportDataWidgets/CsvImportAssistant/DataSelector.h"
 #include "GUI/coregui/mainwindow/mainwindow_constants.h"
 #include "GUI/coregui/utils/StyleUtils.h"
diff --git a/GUI/coregui/Views/ImportDataWidgets/CsvImportAssistant/CsvImportTable.cpp b/GUI/coregui/Views/ImportDataWidgets/CsvImportAssistant/CsvImportTable.cpp
index 5883fe4184a09f0bb44bd718649438fe4a638698..8112e9ba403d4ed24ec046c04f4e12e633e179d0 100644
--- a/GUI/coregui/Views/ImportDataWidgets/CsvImportAssistant/CsvImportTable.cpp
+++ b/GUI/coregui/Views/ImportDataWidgets/CsvImportAssistant/CsvImportTable.cpp
@@ -13,7 +13,7 @@
 //  ************************************************************************************************
 
 #include "GUI/coregui/Views/ImportDataWidgets/CsvImportAssistant/CsvImportTable.h"
-#include "Device/Unit/AxisNames.h"
+#include "Device/Coord/AxisNames.h"
 #include "GUI/coregui/Views/JobWidgets/ScientificSpinBox.h"
 
 namespace {
diff --git a/GUI/coregui/Views/ImportDataWidgets/CsvImportAssistant/DataSelector.cpp b/GUI/coregui/Views/ImportDataWidgets/CsvImportAssistant/DataSelector.cpp
index d7fb7ad8292abdb615d0730cef529a8867cc54b3..5b2cccb8b8bc60feffd9bc1c7bffea0667c54983 100644
--- a/GUI/coregui/Views/ImportDataWidgets/CsvImportAssistant/DataSelector.cpp
+++ b/GUI/coregui/Views/ImportDataWidgets/CsvImportAssistant/DataSelector.cpp
@@ -13,7 +13,7 @@
 //  ************************************************************************************************
 
 #include "GUI/coregui/Views/ImportDataWidgets/CsvImportAssistant/DataSelector.h"
-#include "Device/Unit/AxisNames.h"
+#include "Device/Coord/AxisNames.h"
 #include "GUI/coregui/Views/ImportDataWidgets/CsvImportAssistant/TableContextMenu.h"
 #include "GUI/coregui/mainwindow/mainwindow_constants.h"
 #include "GUI/coregui/utils/StyleUtils.h"
diff --git a/GUI/coregui/utils/ImportDataInfo.cpp b/GUI/coregui/utils/ImportDataInfo.cpp
index ee23833020295d6129ac3cb068a6900349da8f5e..9a6fdbba7a328609b963c61b2662ad36199f8b81 100644
--- a/GUI/coregui/utils/ImportDataInfo.cpp
+++ b/GUI/coregui/utils/ImportDataInfo.cpp
@@ -12,8 +12,8 @@
 //
 //  ************************************************************************************************
 
+#include "Device/Coord/AxisNames.h"
 #include "Device/Data/OutputData.h"
-#include "Device/Unit/AxisNames.h"
 #include "GUI/coregui/Models/JobItemUtils.h"
 #include "GUI/coregui/Views/ImportDataWidgets/ImportDataUtils.h"
 #include "GUI/coregui/utils/GUIHelpers.h"
diff --git a/GUI/coregui/utils/ImportDataInfo.h b/GUI/coregui/utils/ImportDataInfo.h
index bd4489e727bf1bc3af81ef62fc382b3b538ed169..903f1b3361da3e52fa3d9df2231c57d2b8c5ca36 100644
--- a/GUI/coregui/utils/ImportDataInfo.h
+++ b/GUI/coregui/utils/ImportDataInfo.h
@@ -15,7 +15,7 @@
 #ifndef BORNAGAIN_GUI_COREGUI_UTILS_IMPORTDATAINFO_H
 #define BORNAGAIN_GUI_COREGUI_UTILS_IMPORTDATAINFO_H
 
-#include "Device/Unit/Axes.h"
+#include "Device/Coord/Axes.h"
 #include <QString>
 #include <memory>
 
diff --git a/Tests/UnitTests/Core/Axes/CoordSystem1DTest.cpp b/Tests/UnitTests/Core/Axes/CoordSystem1DTest.cpp
index 1855737568a1cfd6ab68553843a055cd5df1722b..948e333d949aaa0320004c8097509a467c52d9a2 100644
--- a/Tests/UnitTests/Core/Axes/CoordSystem1DTest.cpp
+++ b/Tests/UnitTests/Core/Axes/CoordSystem1DTest.cpp
@@ -1,4 +1,4 @@
-#include "Core/Scan/CoordSystem1D.h"
+#include "Device/Coord/CoordSystem1D.h"
 #include "Base/Axis/PointwiseAxis.h"
 #include "Base/Axis/VariableBinAxis.h"
 #include "Base/Const/Units.h"
@@ -182,13 +182,13 @@ void CoordSystem1DTest::checkQSpecConverter(const CoordSystem1D& test_object)
 
 TEST_F(CoordSystem1DTest, MainFunctionality)
 {
-    checkConventionalConverter(AngularReflectometryConverter(m_beam, m_axis));
-    checkQSpecConverter(WavenumberReflectometryConverter(m_qscan));
+    checkConventionalConverter(AngularReflectometryCoordinates(m_beam.wavelength(), m_axis));
+    checkQSpecConverter(WavenumberReflectometryCoordinates(m_qscan.coordinateAxis()->clone()));
 }
 
 TEST_F(CoordSystem1DTest, Exceptions)
 {
-    AngularReflectometryConverter converter(m_beam, m_axis);
+    AngularReflectometryCoordinates converter(m_beam.wavelength(), m_axis);
 
     EXPECT_THROW(converter.calculateMin(0, Axes::Coords::MM), std::runtime_error);
     EXPECT_THROW(converter.calculateMin(1, Axes::Coords::RADIANS), std::runtime_error);
@@ -200,9 +200,10 @@ TEST_F(CoordSystem1DTest, Exceptions)
     EXPECT_THROW(converter.createConvertedAxis(1, Axes::Coords::UNDEFINED), std::runtime_error);
 
     FixedBinAxis axis("Angles", 100, 0.0, 2.0 * M_PI);
-    EXPECT_THROW(AngularReflectometryConverter converter2(m_beam, axis), std::runtime_error);
+    EXPECT_THROW(AngularReflectometryCoordinates converter2(m_beam.wavelength(), axis),
+                 std::runtime_error);
 
-    WavenumberReflectometryConverter converter2(m_qscan);
+    WavenumberReflectometryCoordinates converter2(m_qscan.coordinateAxis()->clone());
     // wrong units
     EXPECT_THROW(converter2.calculateMin(0, Axes::Coords::MM), std::runtime_error);
     EXPECT_THROW(converter2.calculateMin(0, Axes::Coords::RADIANS), std::runtime_error);
@@ -220,11 +221,11 @@ TEST_F(CoordSystem1DTest, Exceptions)
 
 TEST_F(CoordSystem1DTest, Clone)
 {
-    AngularReflectometryConverter converter(m_beam, m_axis);
+    AngularReflectometryCoordinates converter(m_beam.wavelength(), m_axis);
     std::unique_ptr<CoordSystem1D> converter_clone(converter.clone());
     checkConventionalConverter(*converter_clone);
 
-    WavenumberReflectometryConverter converterQ(m_qscan);
+    WavenumberReflectometryCoordinates converterQ(m_qscan.coordinateAxis()->clone());
     std::unique_ptr<CoordSystem1D> converterQ_clone(converterQ.clone());
     checkQSpecConverter(*converterQ_clone);
 }
@@ -233,10 +234,10 @@ TEST_F(CoordSystem1DTest, NonDefaultUnitsInInput)
 {
     PointwiseAxis axis("x", std::vector<double>{0.0, 0.5, 1.0});
 
-    EXPECT_THROW(AngularReflectometryConverter(m_beam, axis, Axes::Coords::NBINS),
+    EXPECT_THROW(AngularReflectometryCoordinates(m_beam.wavelength(), axis, Axes::Coords::NBINS),
                  std::runtime_error);
 
-    AngularReflectometryConverter converter(m_beam, axis, Axes::Coords::DEGREES);
+    AngularReflectometryCoordinates converter(m_beam.wavelength(), axis, Axes::Coords::DEGREES);
     auto axis_deg_output = converter.createConvertedAxis(0, Axes::Coords::DEGREES);
     EXPECT_TRUE(axis.size() == axis_deg_output->size());
     EXPECT_DOUBLE_EQ(axis[0], (*axis_deg_output)[0]);
@@ -246,13 +247,13 @@ TEST_F(CoordSystem1DTest, NonDefaultUnitsInInput)
     auto values = axis.binCenters();
     std::for_each(values.begin(), values.end(), [this](double& value) { value = getQ(value); });
     PointwiseAxis q_axis("q", values);
-    AngularReflectometryConverter converter2(m_beam, q_axis, Axes::Coords::QSPACE);
+    AngularReflectometryCoordinates converter2(m_beam.wavelength(), q_axis, Axes::Coords::QSPACE);
     auto axis_rad_output = converter2.createConvertedAxis(0, Axes::Coords::RADIANS);
     EXPECT_TRUE(axis.size() == axis_rad_output->size());
     EXPECT_DOUBLE_EQ(axis[0], (*axis_rad_output)[0]);
     EXPECT_DOUBLE_EQ(axis[1], (*axis_rad_output)[1]);
     EXPECT_DOUBLE_EQ(axis[2], (*axis_rad_output)[2]);
 
-    EXPECT_THROW(AngularReflectometryConverter(m_beam, q_axis, Axes::Coords::RQ4),
+    EXPECT_THROW(AngularReflectometryCoordinates(m_beam.wavelength(), q_axis, Axes::Coords::RQ4),
                  std::runtime_error);
 }
diff --git a/Tests/UnitTests/Core/Core/DepthProbeConverterTest.cpp b/Tests/UnitTests/Core/Core/DepthProbeConverterTest.cpp
index cf92a8018d1a563ccc2424e87795c7f49378b0d7..55e66b413dfc9e84ef005f04c6bdabc2972f3b56 100644
--- a/Tests/UnitTests/Core/Core/DepthProbeConverterTest.cpp
+++ b/Tests/UnitTests/Core/Core/DepthProbeConverterTest.cpp
@@ -5,13 +5,13 @@
 #include "Device/Instrument/CoordSystem2D.h"
 #include "Tests/GTestWrapper/google_test.h"
 
-class DepthProbeConverterTest : public ::testing::Test {
+class DepthProbeCoordinatesTest : public ::testing::Test {
 protected:
-    DepthProbeConverterTest();
+    DepthProbeCoordinatesTest();
 
-    void checkMainFunctionality(const DepthProbeConverter& test_object);
-    void checkAlphaAxis(Axes::Coords units, const DepthProbeConverter& test_object);
-    void checkZAxis(Axes::Coords units, const DepthProbeConverter& test_object);
+    void checkMainFunctionality(const DepthProbeCoordinates& test_object);
+    void checkAlphaAxis(Axes::Coords units, const DepthProbeCoordinates& test_object);
+    void checkZAxis(Axes::Coords units, const DepthProbeCoordinates& test_object);
     const double m_alpha_start = 0.5; // first axis value in rads
     const double m_alpha_end = 1.0;   // last axis value in rads
     const double m_z_start = -30.0;
@@ -22,14 +22,14 @@ protected:
     Beam m_beam;
 };
 
-DepthProbeConverterTest::DepthProbeConverterTest()
+DepthProbeCoordinatesTest::DepthProbeCoordinatesTest()
     : m_inclination_axis("Angles", m_nbins, m_alpha_start, m_alpha_end) // angles in radians
     , m_z_axis("Positions", m_nbins, m_z_start, m_z_end)                // z positions in nm
     , m_beam(Beam::horizontalBeam())
 {
 }
 
-void DepthProbeConverterTest::checkMainFunctionality(const DepthProbeConverter& test_object)
+void DepthProbeCoordinatesTest::checkMainFunctionality(const DepthProbeCoordinates& test_object)
 {
     EXPECT_EQ(test_object.dimension(), 2u);
 
@@ -65,8 +65,8 @@ void DepthProbeConverterTest::checkMainFunctionality(const DepthProbeConverter&
     checkZAxis(Axes::Coords::NBINS, test_object);
 }
 
-void DepthProbeConverterTest::checkAlphaAxis(Axes::Coords units,
-                                             const DepthProbeConverter& test_object)
+void DepthProbeCoordinatesTest::checkAlphaAxis(Axes::Coords units,
+                                               const DepthProbeCoordinates& test_object)
 {
     auto axis = test_object.createConvertedAxis(0, units);
     EXPECT_TRUE(dynamic_cast<const FixedBinAxis*>(axis.get()));
@@ -76,7 +76,8 @@ void DepthProbeConverterTest::checkAlphaAxis(Axes::Coords units,
     EXPECT_EQ(axis->upperBound(), test_object.calculateMax(0, units));
 }
 
-void DepthProbeConverterTest::checkZAxis(Axes::Coords units, const DepthProbeConverter& test_object)
+void DepthProbeCoordinatesTest::checkZAxis(Axes::Coords units,
+                                           const DepthProbeCoordinates& test_object)
 {
     auto axis = test_object.createConvertedAxis(1, units);
     EXPECT_TRUE(dynamic_cast<const FixedBinAxis*>(axis.get()));
@@ -92,15 +93,15 @@ void DepthProbeConverterTest::checkZAxis(Axes::Coords units, const DepthProbeCon
     EXPECT_NEAR(axis->upperBound(), test_max, std::abs(test_max) * 1e-10);
 }
 
-TEST_F(DepthProbeConverterTest, DepthProbeConverter)
+TEST_F(DepthProbeCoordinatesTest, DepthProbeCoordinates)
 {
-    DepthProbeConverter converter(m_beam, m_inclination_axis, m_z_axis);
+    DepthProbeCoordinates converter(m_beam, m_inclination_axis, m_z_axis);
     checkMainFunctionality(converter);
 }
 
-TEST_F(DepthProbeConverterTest, DepthProbeConverterExceptions)
+TEST_F(DepthProbeCoordinatesTest, DepthProbeCoordinatesExceptions)
 {
-    DepthProbeConverter converter(m_beam, m_inclination_axis, m_z_axis);
+    DepthProbeCoordinates converter(m_beam, m_inclination_axis, m_z_axis);
 
     EXPECT_THROW(converter.axisName(0, Axes::Coords::MM), std::runtime_error);
     EXPECT_THROW(converter.axisName(1, Axes::Coords::MM), std::runtime_error);
@@ -119,9 +120,9 @@ TEST_F(DepthProbeConverterTest, DepthProbeConverterExceptions)
     EXPECT_THROW(converter.createConvertedAxis(2, Axes::Coords::UNDEFINED), std::runtime_error);
 }
 
-TEST_F(DepthProbeConverterTest, DepthProbeConverterClone)
+TEST_F(DepthProbeCoordinatesTest, DepthProbeCoordinatesClone)
 {
-    DepthProbeConverter converter(m_beam, m_inclination_axis, m_z_axis);
-    std::unique_ptr<DepthProbeConverter> converter_clone(converter.clone());
+    DepthProbeCoordinates converter(m_beam, m_inclination_axis, m_z_axis);
+    std::unique_ptr<DepthProbeCoordinates> converter_clone(converter.clone());
     checkMainFunctionality(*converter_clone);
 }
diff --git a/Tests/UnitTests/Core/Instrument/OffSpecularConverterTest.cpp b/Tests/UnitTests/Core/Instrument/OffSpecularConverterTest.cpp
index 6f768aa41e98d64afa964c1d7be8b4592619473b..1ffad75272ea0cd47ea6c4e648a361826227680a 100644
--- a/Tests/UnitTests/Core/Instrument/OffSpecularConverterTest.cpp
+++ b/Tests/UnitTests/Core/Instrument/OffSpecularConverterTest.cpp
@@ -4,9 +4,9 @@
 #include "Device/Instrument/CoordSystem2D.h"
 #include "Tests/GTestWrapper/google_test.h"
 
-class OffSpecularConverterTest : public ::testing::Test {
+class OffSpecularCoordinatesTest : public ::testing::Test {
 public:
-    OffSpecularConverterTest();
+    OffSpecularCoordinatesTest();
 
 protected:
     SphericalDetector m_detector;
@@ -14,16 +14,16 @@ protected:
     Beam m_beam;
 };
 
-OffSpecularConverterTest::OffSpecularConverterTest()
+OffSpecularCoordinatesTest::OffSpecularCoordinatesTest()
     : m_detector(100, 0.0, 5.0 * Units::deg, 70, -2.0 * Units::deg, 1.5)
     , m_alpha_i_axis("alpha_i", 51, 0.0, 7.0 * Units::deg)
     , m_beam(1.0, 1.0, {1.0 * Units::deg, 0.0})
 {
 }
 
-TEST_F(OffSpecularConverterTest, OffSpecularConverter)
+TEST_F(OffSpecularCoordinatesTest, OffSpecularCoordinates)
 {
-    OffSpecularConverter converter(m_detector, m_beam, m_alpha_i_axis);
+    OffSpecularCoordinates converter(m_detector, m_beam, m_alpha_i_axis);
 
     EXPECT_EQ(converter.dimension(), 2u);
 
@@ -74,10 +74,10 @@ TEST_F(OffSpecularConverterTest, OffSpecularConverter)
     EXPECT_THROW(converter.createConvertedAxis(1, Axes::Coords::QSPACE), std::runtime_error);
 }
 
-TEST_F(OffSpecularConverterTest, OffSpecularConverterClone)
+TEST_F(OffSpecularCoordinatesTest, OffSpecularCoordinatesClone)
 {
-    OffSpecularConverter converter(m_detector, m_beam, m_alpha_i_axis);
-    std::unique_ptr<OffSpecularConverter> P_clone(converter.clone());
+    OffSpecularCoordinates converter(m_detector, m_beam, m_alpha_i_axis);
+    std::unique_ptr<OffSpecularCoordinates> P_clone(converter.clone());
 
     EXPECT_EQ(P_clone->dimension(), 2u);
 
diff --git a/Tests/UnitTests/Core/Instrument/RectangularConverterTest.cpp b/Tests/UnitTests/Core/Instrument/RectangularConverterTest.cpp
index 4028d89d8e4de2f47eb07468118021ff95f0b09a..f3cfcbf42412f7813bc54003db7fc74f981e650c 100644
--- a/Tests/UnitTests/Core/Instrument/RectangularConverterTest.cpp
+++ b/Tests/UnitTests/Core/Instrument/RectangularConverterTest.cpp
@@ -13,9 +13,9 @@ const size_t det_nx = 100u;
 const size_t det_ny = 70u;
 } // namespace
 
-class RectangularConverterTest : public ::testing::Test {
+class ImageCoordsTest : public ::testing::Test {
 public:
-    RectangularConverterTest();
+    ImageCoordsTest();
 
 protected:
     RectangularDetector m_detector;
@@ -24,7 +24,7 @@ protected:
     double m_kiz, m_kfy, m_kfz;
 };
 
-RectangularConverterTest::RectangularConverterTest()
+ImageCoordsTest::ImageCoordsTest()
     : m_detector(det_nx, det_width, det_ny, det_height), m_beam(1.0, 1.0, {1 * Units::deg, 0})
 {
     m_detector.setPerpendicularToSampleX(det_distance, det_width / 2.0, 0.0);
@@ -38,9 +38,9 @@ RectangularConverterTest::RectangularConverterTest()
     m_kfz = K * std::sin(m_alpha);
 }
 
-TEST_F(RectangularConverterTest, RectangularConverter)
+TEST_F(ImageCoordsTest, ImageCoords)
 {
-    RectangularConverter converter(m_detector, m_beam);
+    ImageCoords converter(m_detector, m_beam);
 
     EXPECT_EQ(converter.dimension(), 2u);
 
@@ -96,10 +96,10 @@ TEST_F(RectangularConverterTest, RectangularConverter)
     EXPECT_THROW(converter.createConvertedAxis(2, Axes::Coords::UNDEFINED), std::runtime_error);
 }
 
-TEST_F(RectangularConverterTest, RectangularConverterClone)
+TEST_F(ImageCoordsTest, ImageCoordsClone)
 {
-    RectangularConverter converter(m_detector, m_beam);
-    std::unique_ptr<RectangularConverter> P_clone(converter.clone());
+    ImageCoords converter(m_detector, m_beam);
+    std::unique_ptr<ImageCoords> P_clone(converter.clone());
 
     EXPECT_EQ(P_clone->dimension(), 2u);
 
@@ -141,7 +141,7 @@ TEST_F(RectangularConverterTest, RectangularConverterClone)
     EXPECT_THROW(P_clone->calculateMax(2, Axes::Coords::UNDEFINED), std::runtime_error);
 }
 
-TEST_F(RectangularConverterTest, RectangularConverterWithROI)
+TEST_F(ImageCoordsTest, ImageCoordsWithROI)
 {
     const double roi_xmin = 100;
     const double roi_xmax = 150; // xmax in roi will be 152 due to binning
@@ -149,7 +149,7 @@ TEST_F(RectangularConverterTest, RectangularConverterWithROI)
     const double roi_ymax = 100; // ymax in roi will be 102 due to binning
 
     m_detector.setRegionOfInterest(roi_xmin, roi_ymin, roi_xmax, roi_ymax);
-    RectangularConverter converter(m_detector, m_beam);
+    ImageCoords converter(m_detector, m_beam);
 
     EXPECT_EQ(converter.calculateMin(0, Axes::Coords::UNDEFINED), 100);
     EXPECT_EQ(converter.calculateMax(0, Axes::Coords::UNDEFINED), 152);
diff --git a/Tests/UnitTests/Core/Instrument/SphericalConverterTest.cpp b/Tests/UnitTests/Core/Instrument/SphericalConverterTest.cpp
index 6986971be51e63b3abbd3a2dd39e4e06206b4b69..d4e390f1d35014d9ec26e7f2489a4882ea8ba76a 100644
--- a/Tests/UnitTests/Core/Instrument/SphericalConverterTest.cpp
+++ b/Tests/UnitTests/Core/Instrument/SphericalConverterTest.cpp
@@ -4,9 +4,9 @@
 #include "Device/Instrument/CoordSystem2D.h"
 #include "Tests/GTestWrapper/google_test.h"
 
-class SphericalConverterTest : public ::testing::Test {
+class SphericalCoordsTest : public ::testing::Test {
 public:
-    SphericalConverterTest();
+    SphericalCoordsTest();
 
 protected:
     SphericalDetector m_detector;
@@ -14,7 +14,7 @@ protected:
     double m_kiz, m_kfy, m_kfz1, m_kfz2;
 };
 
-SphericalConverterTest::SphericalConverterTest()
+SphericalCoordsTest::SphericalCoordsTest()
     : m_detector(100, 0.0, 5.0 * Units::deg, 70, -2.0 * Units::deg, 1.5)
     , m_beam(1.0, 1.0, {1 * Units::deg, 0})
 {
@@ -26,9 +26,9 @@ SphericalConverterTest::SphericalConverterTest()
     m_kfz2 = K * std::sin(1.5);
 }
 
-TEST_F(SphericalConverterTest, SphericalConverter)
+TEST_F(SphericalCoordsTest, SphericalCoords)
 {
-    SphericalConverter converter(m_detector, m_beam);
+    SphericalCoords converter(m_detector, m_beam);
 
     EXPECT_EQ(converter.dimension(), 2u);
 
@@ -78,10 +78,10 @@ TEST_F(SphericalConverterTest, SphericalConverter)
     EXPECT_THROW(converter.createConvertedAxis(2, Axes::Coords::UNDEFINED), std::runtime_error);
 }
 
-TEST_F(SphericalConverterTest, SphericalConverterClone)
+TEST_F(SphericalCoordsTest, SphericalCoordsClone)
 {
-    SphericalConverter converter(m_detector, m_beam);
-    std::unique_ptr<SphericalConverter> P_clone(converter.clone());
+    SphericalCoords converter(m_detector, m_beam);
+    std::unique_ptr<SphericalCoords> P_clone(converter.clone());
 
     EXPECT_EQ(P_clone->dimension(), 2u);
 
diff --git a/Wrap/Swig/libBornAgainDevice.i b/Wrap/Swig/libBornAgainDevice.i
index 245a312a5bb2d91bf2777f10487117d3fea1b520..6fcda79fec617dbd055a1b4e8474da6f66bd607c 100644
--- a/Wrap/Swig/libBornAgainDevice.i
+++ b/Wrap/Swig/libBornAgainDevice.i
@@ -98,7 +98,7 @@
 %include "Device/Resolution/ResolutionFunction2DGaussian.h"
 %include "Device/Resolution/ScanResolution.h"
 
-%include "Device/Unit/Axes.h"
+%include "Device/Coord/Axes.h"
 
 %include "Device/ProDetector/DetectorMask.h"
 %include "Device/Detector/IDetector.h"
diff --git a/auto/Wrap/doxygenCore.i b/auto/Wrap/doxygenCore.i
index 8b92f1fef3aeddf5cbd5ae787c9d12af6a246590..b5e97ac621f79e7e565332f2b84981b4f08883a0 100644
--- a/auto/Wrap/doxygenCore.i
+++ b/auto/Wrap/doxygenCore.i
@@ -1,34 +1,31 @@
 
 // File: index.xml
 
-// File: classAngularReflectometryConverter.xml
-%feature("docstring") AngularReflectometryConverter "
+// File: classAngularReflectometryCoordinates.xml
+%feature("docstring") AngularReflectometryCoordinates "
 
 Conversion of axis units for the case of conventional (angle-based) reflectometry.
 
 C++ includes: CoordSystem1D.h
 ";
 
-%feature("docstring")  AngularReflectometryConverter::AngularReflectometryConverter "AngularReflectometryConverter::AngularReflectometryConverter(const Beam &beam, const IAxis &axis, Axes::Coords axis_units=Axes::Coords::RADIANS)
+%feature("docstring")  AngularReflectometryCoordinates::AngularReflectometryCoordinates "AngularReflectometryCoordinates::AngularReflectometryCoordinates(double wavelength, const IAxis &axis, Axes::Coords axis_units=Axes::Coords::RADIANS)
 
 Constructs the object for unit conversion. 
 ";
 
-%feature("docstring")  AngularReflectometryConverter::AngularReflectometryConverter "AngularReflectometryConverter::AngularReflectometryConverter(const AngularSpecScan &handler)
+%feature("docstring")  AngularReflectometryCoordinates::~AngularReflectometryCoordinates "AngularReflectometryCoordinates::~AngularReflectometryCoordinates() override
 ";
 
-%feature("docstring")  AngularReflectometryConverter::~AngularReflectometryConverter "AngularReflectometryConverter::~AngularReflectometryConverter() override
+%feature("docstring")  AngularReflectometryCoordinates::clone "AngularReflectometryCoordinates * AngularReflectometryCoordinates::clone() const override
 ";
 
-%feature("docstring")  AngularReflectometryConverter::clone "AngularReflectometryConverter * AngularReflectometryConverter::clone() const override
-";
-
-%feature("docstring")  AngularReflectometryConverter::availableUnits "std::vector< Axes::Coords > AngularReflectometryConverter::availableUnits() const override
+%feature("docstring")  AngularReflectometryCoordinates::availableUnits "std::vector< Axes::Coords > AngularReflectometryCoordinates::availableUnits() const override
 
 Returns the list of all available units. 
 ";
 
-%feature("docstring")  AngularReflectometryConverter::defaultUnits "Axes::Coords AngularReflectometryConverter::defaultUnits() const override
+%feature("docstring")  AngularReflectometryCoordinates::defaultUnits "Axes::Coords AngularReflectometryCoordinates::defaultUnits() const override
 
 Returns default units to convert to. 
 ";
@@ -84,6 +81,9 @@ Returns footprint correction factor for a range of simulation elements of size
 Returns the number of simulation elements. 
 ";
 
+%feature("docstring")  AngularSpecScan::createCoordSystem "CoordSystem1D * AngularSpecScan::createCoordSystem() const override
+";
+
 %feature("docstring")  AngularSpecScan::createIntensities "std::vector< double > AngularSpecScan::createIntensities(const std::vector< SpecularSimulationElement > &sim_elements) const override
 
 Returns intensity vector corresponding to convolution of given simulation elements. 
@@ -312,11 +312,19 @@ C++ includes: ConstantBackground.h
 // File: classCoordSystem1D.xml
 %feature("docstring") CoordSystem1D "
 
-Abstract base class to support coordinate transforms and axis labels for 1D scans. Inherited by  AngularReflectometryConverter and  WavenumberReflectometryConverter.
+Abstract base class to support coordinate transforms and axis labels for 1D scans. Inherited by  AngularReflectometryCoordinates and  WavenumberReflectometryCoordinates.
 
 C++ includes: CoordSystem1D.h
 ";
 
+%feature("docstring")  CoordSystem1D::CoordSystem1D "CoordSystem1D::CoordSystem1D()=delete
+";
+
+%feature("docstring")  CoordSystem1D::CoordSystem1D "CoordSystem1D::CoordSystem1D(const IAxis *&&axis)
+
+Takes ownership of axis. 
+";
+
 %feature("docstring")  CoordSystem1D::~CoordSystem1D "CoordSystem1D::~CoordSystem1D() override=default
 ";
 
@@ -480,7 +488,7 @@ Returns a pointer to z-position axis.
 Returns the total number of the intensity values in the simulation result. 
 ";
 
-%feature("docstring")  DepthProbeSimulation::createCoordSystem "std::unique_ptr< ICoordSystem > DepthProbeSimulation::createCoordSystem() const
+%feature("docstring")  DepthProbeSimulation::createCoordSystem "ICoordSystem * DepthProbeSimulation::createCoordSystem() const override
 ";
 
 
@@ -884,6 +892,9 @@ Sets beam parameters from here (forwarded to Instrument)
 Returns the total number of the intensity values in the simulation result. 
 ";
 
+%feature("docstring")  GISASSimulation::createCoordSystem "ICoordSystem * GISASSimulation::createCoordSystem() const override
+";
+
 
 // File: classGISASSpecularComputation.xml
 %feature("docstring") GISASSpecularComputation "
@@ -1165,6 +1176,9 @@ Initializes a progress monitor that prints to stdout.
 %feature("docstring")  ISimulation::setInstrument "void ISimulation::setInstrument(const Instrument &instrument_)
 ";
 
+%feature("docstring")  ISimulation::createCoordSystem "virtual ICoordSystem* ISimulation::createCoordSystem() const =0
+";
+
 
 // File: classISimulation2D.xml
 %feature("docstring") ISimulation2D "
@@ -1292,6 +1306,9 @@ Returns footprint correction factor for a range of simulation elements of size
 Returns the number of simulation elements. 
 ";
 
+%feature("docstring")  ISpecularScan::createCoordSystem "virtual CoordSystem1D* ISpecularScan::createCoordSystem() const =0
+";
+
 %feature("docstring")  ISpecularScan::createIntensities "virtual std::vector<double> ISpecularScan::createIntensities(const std::vector< SpecularSimulationElement > &sim_elements) const =0
 
 Returns intensity vector corresponding to convolution of given simulation elements. 
@@ -1560,7 +1577,7 @@ Sets beam parameters from here (forwarded to Instrument)
 Returns axis of the beam. 
 ";
 
-%feature("docstring")  OffSpecularSimulation::createCoordSystem "std::unique_ptr< ICoordSystem > OffSpecularSimulation::createCoordSystem() const
+%feature("docstring")  OffSpecularSimulation::createCoordSystem "ICoordSystem * OffSpecularSimulation::createCoordSystem() const override
 ";
 
 %feature("docstring")  OffSpecularSimulation::intensityMapSize "size_t OffSpecularSimulation::intensityMapSize() const override
@@ -1777,6 +1794,9 @@ Returns footprint correction factor for a range of simulation elements of size
 Returns the number of simulation elements. 
 ";
 
+%feature("docstring")  QSpecScan::createCoordSystem "CoordSystem1D * QSpecScan::createCoordSystem() const override
+";
+
 %feature("docstring")  QSpecScan::createIntensities "std::vector< double > QSpecScan::createIntensities(const std::vector< SpecularSimulationElement > &sim_elements) const override
 
 Returns intensity vector corresponding to convolution of given simulation elements. 
@@ -2173,6 +2193,9 @@ Returns a pointer to footprint factor holder.
 Returns the total number of the intensity values in the simulation result. 
 ";
 
+%feature("docstring")  SpecularSimulation::createCoordSystem "ICoordSystem * SpecularSimulation::createCoordSystem() const override
+";
+
 %feature("docstring")  SpecularSimulation::dataHandler "const ISpecularScan* SpecularSimulation::dataHandler() const
 
 Returns internal data handler. 
@@ -2257,29 +2280,29 @@ C++ includes: VarianceFunctions.h
 ";
 
 
-// File: classWavenumberReflectometryConverter.xml
-%feature("docstring") WavenumberReflectometryConverter "
+// File: classWavenumberReflectometryCoordinates.xml
+%feature("docstring") WavenumberReflectometryCoordinates "
 
 Conversion of axis units for the case of q-defined reflectometry.
 
 C++ includes: CoordSystem1D.h
 ";
 
-%feature("docstring")  WavenumberReflectometryConverter::WavenumberReflectometryConverter "WavenumberReflectometryConverter::WavenumberReflectometryConverter(const QSpecScan &handler)
+%feature("docstring")  WavenumberReflectometryCoordinates::WavenumberReflectometryCoordinates "WavenumberReflectometryCoordinates::WavenumberReflectometryCoordinates(const IAxis *&&axis)
 ";
 
-%feature("docstring")  WavenumberReflectometryConverter::~WavenumberReflectometryConverter "WavenumberReflectometryConverter::~WavenumberReflectometryConverter() override
+%feature("docstring")  WavenumberReflectometryCoordinates::~WavenumberReflectometryCoordinates "WavenumberReflectometryCoordinates::~WavenumberReflectometryCoordinates() override
 ";
 
-%feature("docstring")  WavenumberReflectometryConverter::clone "WavenumberReflectometryConverter * WavenumberReflectometryConverter::clone() const override
+%feature("docstring")  WavenumberReflectometryCoordinates::clone "WavenumberReflectometryCoordinates * WavenumberReflectometryCoordinates::clone() const override
 ";
 
-%feature("docstring")  WavenumberReflectometryConverter::availableUnits "std::vector< Axes::Coords > WavenumberReflectometryConverter::availableUnits() const override
+%feature("docstring")  WavenumberReflectometryCoordinates::availableUnits "std::vector< Axes::Coords > WavenumberReflectometryCoordinates::availableUnits() const override
 
 Returns the list of all available units. 
 ";
 
-%feature("docstring")  WavenumberReflectometryConverter::defaultUnits "Axes::Coords WavenumberReflectometryConverter::defaultUnits() const override
+%feature("docstring")  WavenumberReflectometryCoordinates::defaultUnits "Axes::Coords WavenumberReflectometryCoordinates::defaultUnits() const override
 
 Returns default units to convert to. 
 ";
diff --git a/auto/Wrap/doxygenDevice.i b/auto/Wrap/doxygenDevice.i
index 61bbcee00adc7e764e57732ad1890832b5fa5375..2a09f4b8397261f0dbdf0453ab218d1b744c87a0 100644
--- a/auto/Wrap/doxygenDevice.i
+++ b/auto/Wrap/doxygenDevice.i
@@ -1,6 +1,36 @@
 
 // File: index.xml
 
+// File: classAngularReflectometryCoordinates.xml
+%feature("docstring") AngularReflectometryCoordinates "
+
+Conversion of axis units for the case of conventional (angle-based) reflectometry.
+
+C++ includes: CoordSystem1D.h
+";
+
+%feature("docstring")  AngularReflectometryCoordinates::AngularReflectometryCoordinates "AngularReflectometryCoordinates::AngularReflectometryCoordinates(double wavelength, const IAxis &axis, Axes::Coords axis_units=Axes::Coords::RADIANS)
+
+Constructs the object for unit conversion. 
+";
+
+%feature("docstring")  AngularReflectometryCoordinates::~AngularReflectometryCoordinates "AngularReflectometryCoordinates::~AngularReflectometryCoordinates() override
+";
+
+%feature("docstring")  AngularReflectometryCoordinates::clone "AngularReflectometryCoordinates * AngularReflectometryCoordinates::clone() const override
+";
+
+%feature("docstring")  AngularReflectometryCoordinates::availableUnits "std::vector< Axes::Coords > AngularReflectometryCoordinates::availableUnits() const override
+
+Returns the list of all available units. 
+";
+
+%feature("docstring")  AngularReflectometryCoordinates::defaultUnits "Axes::Coords AngularReflectometryCoordinates::defaultUnits() const override
+
+Returns default units to convert to. 
+";
+
+
 // File: classAxes.xml
 %feature("docstring") Axes "
 
@@ -182,6 +212,59 @@ Sets convolution mode.
 ";
 
 
+// File: classCoordSystem1D.xml
+%feature("docstring") CoordSystem1D "
+
+Abstract base class to support coordinate transforms and axis labels for 1D scans. Inherited by  AngularReflectometryCoordinates and  WavenumberReflectometryCoordinates.
+
+C++ includes: CoordSystem1D.h
+";
+
+%feature("docstring")  CoordSystem1D::CoordSystem1D "CoordSystem1D::CoordSystem1D()=delete
+";
+
+%feature("docstring")  CoordSystem1D::CoordSystem1D "CoordSystem1D::CoordSystem1D(const IAxis *&&axis)
+
+Takes ownership of axis. 
+";
+
+%feature("docstring")  CoordSystem1D::~CoordSystem1D "CoordSystem1D::~CoordSystem1D() override=default
+";
+
+%feature("docstring")  CoordSystem1D::clone "CoordSystem1D* CoordSystem1D::clone() const override=0
+";
+
+%feature("docstring")  CoordSystem1D::dimension "size_t CoordSystem1D::dimension() const override
+
+Returns dimensionality of converted canvas. 
+";
+
+%feature("docstring")  CoordSystem1D::axisSize "size_t CoordSystem1D::axisSize(size_t i_axis) const override
+
+Returns the size of underlying axis. 
+";
+
+%feature("docstring")  CoordSystem1D::calculateMin "double CoordSystem1D::calculateMin(size_t i_axis, Axes::Coords units) const override
+
+Calculates minimum on-axis value in given units. 
+";
+
+%feature("docstring")  CoordSystem1D::calculateMax "double CoordSystem1D::calculateMax(size_t i_axis, Axes::Coords units) const override
+
+Calculates maximum on-axis value in given units. 
+";
+
+%feature("docstring")  CoordSystem1D::createConvertedAxis "std::unique_ptr< const IAxis > CoordSystem1D::createConvertedAxis(size_t i_axis, Axes::Coords units) const override
+
+Creates axis in converted units. 
+";
+
+%feature("docstring")  CoordSystem1D::createConvertedData "std::unique_ptr< OutputData< double > > CoordSystem1D::createConvertedData(const OutputData< double > &data, Axes::Coords units) const override
+
+Creates  OutputData array in converter units. 
+";
+
+
 // File: classCoordSystem2D.xml
 %feature("docstring") CoordSystem2D "
 
@@ -254,32 +337,32 @@ C++ includes: CumulativeValue.h
 ";
 
 
-// File: classDepthProbeConverter.xml
-%feature("docstring") DepthProbeConverter "
+// File: classDepthProbeCoordinates.xml
+%feature("docstring") DepthProbeCoordinates "
 
-DepthProbeConverter class handles the unit translations for depth probe simulations Its default units are radians for x-axis and nm for y-axis
+DepthProbeCoordinates class handles the unit translations for depth probe simulations Its default units are radians for x-axis and nm for y-axis
 
 C++ includes: CoordSystem2D.h
 ";
 
-%feature("docstring")  DepthProbeConverter::DepthProbeConverter "DepthProbeConverter::DepthProbeConverter()=delete
+%feature("docstring")  DepthProbeCoordinates::DepthProbeCoordinates "DepthProbeCoordinates::DepthProbeCoordinates()=delete
 ";
 
-%feature("docstring")  DepthProbeConverter::DepthProbeConverter "DepthProbeConverter::DepthProbeConverter(const Beam &beam, const IAxis &alpha_axis, const IAxis &z_axis)
+%feature("docstring")  DepthProbeCoordinates::DepthProbeCoordinates "DepthProbeCoordinates::DepthProbeCoordinates(const Beam &beam, const IAxis &alpha_axis, const IAxis &z_axis)
 ";
 
-%feature("docstring")  DepthProbeConverter::~DepthProbeConverter "DepthProbeConverter::~DepthProbeConverter() override
+%feature("docstring")  DepthProbeCoordinates::~DepthProbeCoordinates "DepthProbeCoordinates::~DepthProbeCoordinates() override
 ";
 
-%feature("docstring")  DepthProbeConverter::clone "DepthProbeConverter * DepthProbeConverter::clone() const override
+%feature("docstring")  DepthProbeCoordinates::clone "DepthProbeCoordinates * DepthProbeCoordinates::clone() const override
 ";
 
-%feature("docstring")  DepthProbeConverter::availableUnits "std::vector< Axes::Coords > DepthProbeConverter::availableUnits() const override
+%feature("docstring")  DepthProbeCoordinates::availableUnits "std::vector< Axes::Coords > DepthProbeCoordinates::availableUnits() const override
 
 Returns the list of all available units. 
 ";
 
-%feature("docstring")  DepthProbeConverter::defaultUnits "Axes::Coords DepthProbeConverter::defaultUnits() const override
+%feature("docstring")  DepthProbeCoordinates::defaultUnits "Axes::Coords DepthProbeCoordinates::defaultUnits() const override
 ";
 
 
@@ -1370,6 +1453,35 @@ Loads histogram from file, the shape of array in file should match Following for
 ";
 
 
+// File: classImageCoords.xml
+%feature("docstring") ImageCoords "
+
+ICoordSystem class that handles the unit translations for rectangular detectors Its default units are mm for both axes
+
+C++ includes: CoordSystem2D.h
+";
+
+%feature("docstring")  ImageCoords::ImageCoords "ImageCoords::ImageCoords()=delete
+";
+
+%feature("docstring")  ImageCoords::ImageCoords "ImageCoords::ImageCoords(const RectangularDetector &detector, const Beam &beam)
+";
+
+%feature("docstring")  ImageCoords::~ImageCoords "ImageCoords::~ImageCoords() override
+";
+
+%feature("docstring")  ImageCoords::clone "ImageCoords * ImageCoords::clone() const override
+";
+
+%feature("docstring")  ImageCoords::availableUnits "std::vector< Axes::Coords > ImageCoords::availableUnits() const override
+
+Returns the list of all available units. 
+";
+
+%feature("docstring")  ImageCoords::defaultUnits "Axes::Coords ImageCoords::defaultUnits() const override
+";
+
+
 // File: classInfinitePlane.xml
 %feature("docstring") InfinitePlane "
 
@@ -1457,6 +1569,9 @@ init detector with beam settings
 %feature("docstring")  Instrument::getChildren "std::vector< const INode * > Instrument::getChildren() const override
 ";
 
+%feature("docstring")  Instrument::createScatteringCoords "CoordSystem2D * Instrument::createScatteringCoords() const
+";
+
 
 // File: classIntensityDataIOFactory.xml
 %feature("docstring") IntensityDataIOFactory "
@@ -1612,27 +1727,27 @@ C++ includes: LLData.h
 // File: structArrayUtils_1_1CreateDataImpl_1_1nDim_3_01std_1_1vector_3_01T_00_01A_01_4_01_4.xml
 
 
-// File: classOffSpecularConverter.xml
-%feature("docstring") OffSpecularConverter "
+// File: classOffSpecularCoordinates.xml
+%feature("docstring") OffSpecularCoordinates "
 
 ICoordSystem class that handles the unit translations for off-specular simulations with a spherical detector Its default units are radians for both axes
 
 C++ includes: CoordSystem2D.h
 ";
 
-%feature("docstring")  OffSpecularConverter::OffSpecularConverter "OffSpecularConverter::OffSpecularConverter()=delete
+%feature("docstring")  OffSpecularCoordinates::OffSpecularCoordinates "OffSpecularCoordinates::OffSpecularCoordinates()=delete
 ";
 
-%feature("docstring")  OffSpecularConverter::OffSpecularConverter "OffSpecularConverter::OffSpecularConverter(const IDetector2D &detector, const Beam &beam, const IAxis &alpha_axis)
+%feature("docstring")  OffSpecularCoordinates::OffSpecularCoordinates "OffSpecularCoordinates::OffSpecularCoordinates(const IDetector2D &detector, const Beam &beam, const IAxis &alpha_axis)
 ";
 
-%feature("docstring")  OffSpecularConverter::~OffSpecularConverter "OffSpecularConverter::~OffSpecularConverter() override
+%feature("docstring")  OffSpecularCoordinates::~OffSpecularCoordinates "OffSpecularCoordinates::~OffSpecularCoordinates() override
 ";
 
-%feature("docstring")  OffSpecularConverter::clone "OffSpecularConverter * OffSpecularConverter::clone() const override
+%feature("docstring")  OffSpecularCoordinates::clone "OffSpecularCoordinates * OffSpecularCoordinates::clone() const override
 ";
 
-%feature("docstring")  OffSpecularConverter::defaultUnits "Axes::Coords OffSpecularConverter::defaultUnits() const override
+%feature("docstring")  OffSpecularCoordinates::defaultUnits "Axes::Coords OffSpecularCoordinates::defaultUnits() const override
 ";
 
 
@@ -2179,35 +2294,6 @@ Returns true if area defined by two bins is inside or on border of polygon (more
 ";
 
 
-// File: classRectangularConverter.xml
-%feature("docstring") RectangularConverter "
-
-ICoordSystem class that handles the unit translations for rectangular detectors Its default units are mm for both axes
-
-C++ includes: CoordSystem2D.h
-";
-
-%feature("docstring")  RectangularConverter::RectangularConverter "RectangularConverter::RectangularConverter()=delete
-";
-
-%feature("docstring")  RectangularConverter::RectangularConverter "RectangularConverter::RectangularConverter(const RectangularDetector &detector, const Beam &beam)
-";
-
-%feature("docstring")  RectangularConverter::~RectangularConverter "RectangularConverter::~RectangularConverter() override
-";
-
-%feature("docstring")  RectangularConverter::clone "RectangularConverter * RectangularConverter::clone() const override
-";
-
-%feature("docstring")  RectangularConverter::availableUnits "std::vector< Axes::Coords > RectangularConverter::availableUnits() const override
-
-Returns the list of all available units. 
-";
-
-%feature("docstring")  RectangularConverter::defaultUnits "Axes::Coords RectangularConverter::defaultUnits() const override
-";
-
-
 // File: classRectangularDetector.xml
 %feature("docstring") RectangularDetector "
 
@@ -2512,7 +2598,10 @@ C++ includes: SimulationResult.h
 %feature("docstring")  SimulationResult::SimulationResult "SimulationResult::SimulationResult()=default
 ";
 
-%feature("docstring")  SimulationResult::SimulationResult "SimulationResult::SimulationResult(const OutputData< double > &data, const ICoordSystem &unit_converter)
+%feature("docstring")  SimulationResult::SimulationResult "SimulationResult::SimulationResult(const OutputData< double > &data, const ICoordSystem &coords)
+";
+
+%feature("docstring")  SimulationResult::SimulationResult "SimulationResult::SimulationResult(const OutputData< double > &data, const ICoordSystem *&&coords)
 ";
 
 %feature("docstring")  SimulationResult::SimulationResult "SimulationResult::SimulationResult(const SimulationResult &other)
@@ -2624,32 +2713,32 @@ Return default axes units.
 ";
 
 
-// File: classSphericalConverter.xml
-%feature("docstring") SphericalConverter "
+// File: classSphericalCoords.xml
+%feature("docstring") SphericalCoords "
 
 ICoordSystem class that handles the unit translations for spherical detectors Its default units are radians for both axes
 
 C++ includes: CoordSystem2D.h
 ";
 
-%feature("docstring")  SphericalConverter::SphericalConverter "SphericalConverter::SphericalConverter()=delete
+%feature("docstring")  SphericalCoords::SphericalCoords "SphericalCoords::SphericalCoords()=delete
 ";
 
-%feature("docstring")  SphericalConverter::SphericalConverter "SphericalConverter::SphericalConverter(const SphericalDetector &detector, const Beam &beam)
+%feature("docstring")  SphericalCoords::SphericalCoords "SphericalCoords::SphericalCoords(const SphericalDetector &detector, const Beam &beam)
 ";
 
-%feature("docstring")  SphericalConverter::~SphericalConverter "SphericalConverter::~SphericalConverter() override
+%feature("docstring")  SphericalCoords::~SphericalCoords "SphericalCoords::~SphericalCoords() override
 ";
 
-%feature("docstring")  SphericalConverter::clone "SphericalConverter * SphericalConverter::clone() const override
+%feature("docstring")  SphericalCoords::clone "SphericalCoords * SphericalCoords::clone() const override
 ";
 
-%feature("docstring")  SphericalConverter::availableUnits "std::vector< Axes::Coords > SphericalConverter::availableUnits() const override
+%feature("docstring")  SphericalCoords::availableUnits "std::vector< Axes::Coords > SphericalCoords::availableUnits() const override
 
 Returns the list of all available units. 
 ";
 
-%feature("docstring")  SphericalConverter::defaultUnits "Axes::Coords SphericalConverter::defaultUnits() const override
+%feature("docstring")  SphericalCoords::defaultUnits "Axes::Coords SphericalCoords::defaultUnits() const override
 ";
 
 
@@ -2762,22 +2851,53 @@ Returns true if area defined by two bins is inside or on border of polygon (more
 ";
 
 
+// File: classWavenumberReflectometryCoordinates.xml
+%feature("docstring") WavenumberReflectometryCoordinates "
+
+Conversion of axis units for the case of q-defined reflectometry.
+
+C++ includes: CoordSystem1D.h
+";
+
+%feature("docstring")  WavenumberReflectometryCoordinates::WavenumberReflectometryCoordinates "WavenumberReflectometryCoordinates::WavenumberReflectometryCoordinates(const IAxis *&&axis)
+";
+
+%feature("docstring")  WavenumberReflectometryCoordinates::~WavenumberReflectometryCoordinates "WavenumberReflectometryCoordinates::~WavenumberReflectometryCoordinates() override
+";
+
+%feature("docstring")  WavenumberReflectometryCoordinates::clone "WavenumberReflectometryCoordinates * WavenumberReflectometryCoordinates::clone() const override
+";
+
+%feature("docstring")  WavenumberReflectometryCoordinates::availableUnits "std::vector< Axes::Coords > WavenumberReflectometryCoordinates::availableUnits() const override
+
+Returns the list of all available units. 
+";
+
+%feature("docstring")  WavenumberReflectometryCoordinates::defaultUnits "Axes::Coords WavenumberReflectometryCoordinates::defaultUnits() const override
+
+Returns default units to convert to. 
+";
+
+
 // File: classConvolve_1_1Workspace.xml
 
 
 // File: namespace_0d11.xml
 
 
-// File: namespace_0d49.xml
+// File: namespace_0d18.xml
+
 
+// File: namespace_0d56.xml
 
-// File: namespace_0d57.xml
 
+// File: namespace_0d64.xml
 
-// File: namespace_0d61.xml
 
+// File: namespace_0d68.xml
 
-// File: namespace_0d90.xml
+
+// File: namespace_0d97.xml
 
 
 // File: namespaceArrayUtils.xml
@@ -2983,6 +3103,27 @@ Returns true if SimulatioResult agrees with data from reference file.
 // File: IFootprintFactor_8h.xml
 
 
+// File: Axes_8h.xml
+
+
+// File: AxisNames_8cpp.xml
+
+
+// File: AxisNames_8h.xml
+
+
+// File: CoordSystem1D_8cpp.xml
+
+
+// File: CoordSystem1D_8h.xml
+
+
+// File: ICoordSystem_8cpp.xml
+
+
+// File: ICoordSystem_8h.xml
+
+
 // File: ArrayUtils_8h.xml
 
 
@@ -3241,27 +3382,15 @@ make Swappable
 // File: ScanResolution_8h.xml
 
 
-// File: Axes_8h.xml
-
-
-// File: AxisNames_8cpp.xml
-
-
-// File: AxisNames_8h.xml
-
-
-// File: ICoordSystem_8cpp.xml
-
-
-// File: ICoordSystem_8h.xml
-
-
 // File: deprecated.xml
 
 
 // File: dir_045b2146c1496d64c013dbede5cfb743.xml
 
 
+// File: dir_0bb3c1d1d7b9ebf51620a7778682f6fa.xml
+
+
 // File: dir_dda0c63858d3307626c38e9d5a1e4058.xml
 
 
@@ -3288,6 +3417,3 @@ make Swappable
 
 // File: dir_aa6451b5aab7f40a79bc1a0dc7cac3c6.xml
 
-
-// File: dir_1129f0bc4b0b28573da786f6a995b6c2.xml
-
diff --git a/auto/Wrap/libBornAgainDevice.py b/auto/Wrap/libBornAgainDevice.py
index 0092723c19f30f1809eaec1900a155563cd91a52..2942d922feb12bd2fd3c204a2c30c71fd4d66380 100644
--- a/auto/Wrap/libBornAgainDevice.py
+++ b/auto/Wrap/libBornAgainDevice.py
@@ -5412,7 +5412,8 @@ class SimulationResult(object):
     def __init__(self, *args):
         r"""
         __init__(SimulationResult self) -> SimulationResult
-        __init__(SimulationResult self, IntensityData data, ICoordSystem const & unit_converter) -> SimulationResult
+        __init__(SimulationResult self, IntensityData data, ICoordSystem const & coords) -> SimulationResult
+        __init__(SimulationResult self, IntensityData data, ICoordSystem const *&& coords) -> SimulationResult
         __init__(SimulationResult self, SimulationResult other) -> SimulationResult
         __init__(SimulationResult self, SimulationResult other) -> SimulationResult
         SimulationResult::SimulationResult(SimulationResult &&other)
diff --git a/auto/Wrap/libBornAgainDevice_wrap.cpp b/auto/Wrap/libBornAgainDevice_wrap.cpp
index bf9a2f14c5be8a3247b1fb7ba604a2db99ffe38f..6fa73d859b9c66d463ed375d45dae00beaeaeb6f 100644
--- a/auto/Wrap/libBornAgainDevice_wrap.cpp
+++ b/auto/Wrap/libBornAgainDevice_wrap.cpp
@@ -3164,52 +3164,53 @@ namespace Swig {
 #define SWIGTYPE_p_key_type swig_types[64]
 #define SWIGTYPE_p_long_long swig_types[65]
 #define SWIGTYPE_p_mapped_type swig_types[66]
-#define SWIGTYPE_p_p_PyObject swig_types[67]
-#define SWIGTYPE_p_parameters_t swig_types[68]
-#define SWIGTYPE_p_second_type swig_types[69]
-#define SWIGTYPE_p_short swig_types[70]
-#define SWIGTYPE_p_signed_char swig_types[71]
-#define SWIGTYPE_p_size_type swig_types[72]
-#define SWIGTYPE_p_std__allocatorT_BasicVector3DT_double_t_t swig_types[73]
-#define SWIGTYPE_p_std__allocatorT_BasicVector3DT_std__complexT_double_t_t_t swig_types[74]
-#define SWIGTYPE_p_std__allocatorT_double_t swig_types[75]
-#define SWIGTYPE_p_std__allocatorT_int_t swig_types[76]
-#define SWIGTYPE_p_std__allocatorT_std__complexT_double_t_t swig_types[77]
-#define SWIGTYPE_p_std__allocatorT_std__pairT_double_double_t_t swig_types[78]
-#define SWIGTYPE_p_std__allocatorT_std__pairT_std__string_const_double_t_t swig_types[79]
-#define SWIGTYPE_p_std__allocatorT_std__string_t swig_types[80]
-#define SWIGTYPE_p_std__allocatorT_std__vectorT_double_std__allocatorT_double_t_t_t swig_types[81]
-#define SWIGTYPE_p_std__allocatorT_std__vectorT_int_std__allocatorT_int_t_t_t swig_types[82]
-#define SWIGTYPE_p_std__allocatorT_unsigned_long_t swig_types[83]
-#define SWIGTYPE_p_std__complexT_double_t swig_types[84]
-#define SWIGTYPE_p_std__functionT_void_fSimulationAreaIterator_const_RF_t swig_types[85]
-#define SWIGTYPE_p_std__invalid_argument swig_types[86]
-#define SWIGTYPE_p_std__lessT_std__string_t swig_types[87]
-#define SWIGTYPE_p_std__mapT_std__string_double_std__lessT_std__string_t_std__allocatorT_std__pairT_std__string_const_double_t_t_t swig_types[88]
-#define SWIGTYPE_p_std__pairT_double_double_t swig_types[89]
-#define SWIGTYPE_p_std__vectorT_AxisInfo_std__allocatorT_AxisInfo_t_t swig_types[90]
-#define SWIGTYPE_p_std__vectorT_BasicVector3DT_double_t_std__allocatorT_BasicVector3DT_double_t_t_t swig_types[91]
-#define SWIGTYPE_p_std__vectorT_BasicVector3DT_std__complexT_double_t_t_std__allocatorT_BasicVector3DT_std__complexT_double_t_t_t_t swig_types[92]
-#define SWIGTYPE_p_std__vectorT_INode_const_p_std__allocatorT_INode_const_p_t_t swig_types[93]
-#define SWIGTYPE_p_std__vectorT_SimulationElement_std__allocatorT_SimulationElement_t_t swig_types[94]
-#define SWIGTYPE_p_std__vectorT_double_std__allocatorT_double_t_t swig_types[95]
-#define SWIGTYPE_p_std__vectorT_int_std__allocatorT_int_t_t swig_types[96]
-#define SWIGTYPE_p_std__vectorT_size_t_std__allocatorT_size_t_t_t swig_types[97]
-#define SWIGTYPE_p_std__vectorT_std__complexT_double_t_std__allocatorT_std__complexT_double_t_t_t swig_types[98]
-#define SWIGTYPE_p_std__vectorT_std__pairT_double_double_t_std__allocatorT_std__pairT_double_double_t_t_t swig_types[99]
-#define SWIGTYPE_p_std__vectorT_std__string_std__allocatorT_std__string_t_t swig_types[100]
-#define SWIGTYPE_p_std__vectorT_std__vectorT_double_std__allocatorT_double_t_t_std__allocatorT_std__vectorT_double_std__allocatorT_double_t_t_t_t swig_types[101]
-#define SWIGTYPE_p_std__vectorT_std__vectorT_int_std__allocatorT_int_t_t_std__allocatorT_std__vectorT_int_std__allocatorT_int_t_t_t_t swig_types[102]
-#define SWIGTYPE_p_std__vectorT_unsigned_int_std__allocatorT_unsigned_int_t_t swig_types[103]
-#define SWIGTYPE_p_std__vectorT_unsigned_long_std__allocatorT_unsigned_long_t_t swig_types[104]
-#define SWIGTYPE_p_swig__SwigPyIterator swig_types[105]
-#define SWIGTYPE_p_unsigned_char swig_types[106]
-#define SWIGTYPE_p_unsigned_int swig_types[107]
-#define SWIGTYPE_p_unsigned_long_long swig_types[108]
-#define SWIGTYPE_p_unsigned_short swig_types[109]
-#define SWIGTYPE_p_value_type swig_types[110]
-static swig_type_info *swig_types[112];
-static swig_module_info swig_module = {swig_types, 111, 0, 0, 0, 0};
+#define SWIGTYPE_p_p_ICoordSystem swig_types[67]
+#define SWIGTYPE_p_p_PyObject swig_types[68]
+#define SWIGTYPE_p_parameters_t swig_types[69]
+#define SWIGTYPE_p_second_type swig_types[70]
+#define SWIGTYPE_p_short swig_types[71]
+#define SWIGTYPE_p_signed_char swig_types[72]
+#define SWIGTYPE_p_size_type swig_types[73]
+#define SWIGTYPE_p_std__allocatorT_BasicVector3DT_double_t_t swig_types[74]
+#define SWIGTYPE_p_std__allocatorT_BasicVector3DT_std__complexT_double_t_t_t swig_types[75]
+#define SWIGTYPE_p_std__allocatorT_double_t swig_types[76]
+#define SWIGTYPE_p_std__allocatorT_int_t swig_types[77]
+#define SWIGTYPE_p_std__allocatorT_std__complexT_double_t_t swig_types[78]
+#define SWIGTYPE_p_std__allocatorT_std__pairT_double_double_t_t swig_types[79]
+#define SWIGTYPE_p_std__allocatorT_std__pairT_std__string_const_double_t_t swig_types[80]
+#define SWIGTYPE_p_std__allocatorT_std__string_t swig_types[81]
+#define SWIGTYPE_p_std__allocatorT_std__vectorT_double_std__allocatorT_double_t_t_t swig_types[82]
+#define SWIGTYPE_p_std__allocatorT_std__vectorT_int_std__allocatorT_int_t_t_t swig_types[83]
+#define SWIGTYPE_p_std__allocatorT_unsigned_long_t swig_types[84]
+#define SWIGTYPE_p_std__complexT_double_t swig_types[85]
+#define SWIGTYPE_p_std__functionT_void_fSimulationAreaIterator_const_RF_t swig_types[86]
+#define SWIGTYPE_p_std__invalid_argument swig_types[87]
+#define SWIGTYPE_p_std__lessT_std__string_t swig_types[88]
+#define SWIGTYPE_p_std__mapT_std__string_double_std__lessT_std__string_t_std__allocatorT_std__pairT_std__string_const_double_t_t_t swig_types[89]
+#define SWIGTYPE_p_std__pairT_double_double_t swig_types[90]
+#define SWIGTYPE_p_std__vectorT_AxisInfo_std__allocatorT_AxisInfo_t_t swig_types[91]
+#define SWIGTYPE_p_std__vectorT_BasicVector3DT_double_t_std__allocatorT_BasicVector3DT_double_t_t_t swig_types[92]
+#define SWIGTYPE_p_std__vectorT_BasicVector3DT_std__complexT_double_t_t_std__allocatorT_BasicVector3DT_std__complexT_double_t_t_t_t swig_types[93]
+#define SWIGTYPE_p_std__vectorT_INode_const_p_std__allocatorT_INode_const_p_t_t swig_types[94]
+#define SWIGTYPE_p_std__vectorT_SimulationElement_std__allocatorT_SimulationElement_t_t swig_types[95]
+#define SWIGTYPE_p_std__vectorT_double_std__allocatorT_double_t_t swig_types[96]
+#define SWIGTYPE_p_std__vectorT_int_std__allocatorT_int_t_t swig_types[97]
+#define SWIGTYPE_p_std__vectorT_size_t_std__allocatorT_size_t_t_t swig_types[98]
+#define SWIGTYPE_p_std__vectorT_std__complexT_double_t_std__allocatorT_std__complexT_double_t_t_t swig_types[99]
+#define SWIGTYPE_p_std__vectorT_std__pairT_double_double_t_std__allocatorT_std__pairT_double_double_t_t_t swig_types[100]
+#define SWIGTYPE_p_std__vectorT_std__string_std__allocatorT_std__string_t_t swig_types[101]
+#define SWIGTYPE_p_std__vectorT_std__vectorT_double_std__allocatorT_double_t_t_std__allocatorT_std__vectorT_double_std__allocatorT_double_t_t_t_t swig_types[102]
+#define SWIGTYPE_p_std__vectorT_std__vectorT_int_std__allocatorT_int_t_t_std__allocatorT_std__vectorT_int_std__allocatorT_int_t_t_t_t swig_types[103]
+#define SWIGTYPE_p_std__vectorT_unsigned_int_std__allocatorT_unsigned_int_t_t swig_types[104]
+#define SWIGTYPE_p_std__vectorT_unsigned_long_std__allocatorT_unsigned_long_t_t swig_types[105]
+#define SWIGTYPE_p_swig__SwigPyIterator swig_types[106]
+#define SWIGTYPE_p_unsigned_char swig_types[107]
+#define SWIGTYPE_p_unsigned_int swig_types[108]
+#define SWIGTYPE_p_unsigned_long_long swig_types[109]
+#define SWIGTYPE_p_unsigned_short swig_types[110]
+#define SWIGTYPE_p_value_type swig_types[111]
+static swig_type_info *swig_types[113];
+static swig_module_info swig_module = {swig_types, 112, 0, 0, 0, 0};
 #define SWIG_TypeQuery(name) SWIG_TypeQueryModule(&swig_module, &swig_module, name)
 #define SWIG_MangledTypeQuery(name) SWIG_MangledTypeQueryModule(&swig_module, &swig_module, name)
 
@@ -42605,6 +42606,41 @@ fail:
 
 
 SWIGINTERN PyObject *_wrap_new_SimulationResult__SWIG_2(PyObject *SWIGUNUSEDPARM(self), Py_ssize_t nobjs, PyObject **swig_obj) {
+  PyObject *resultobj = 0;
+  OutputData< double > *arg1 = 0 ;
+  ICoordSystem **arg2 = 0 ;
+  void *argp1 = 0 ;
+  int res1 = 0 ;
+  void *argp2 = 0 ;
+  int res2 = 0 ;
+  SimulationResult *result = 0 ;
+  
+  if ((nobjs < 2) || (nobjs > 2)) SWIG_fail;
+  res1 = SWIG_ConvertPtr(swig_obj[0], &argp1, SWIGTYPE_p_OutputDataT_double_t,  0  | 0);
+  if (!SWIG_IsOK(res1)) {
+    SWIG_exception_fail(SWIG_ArgError(res1), "in method '" "new_SimulationResult" "', argument " "1"" of type '" "OutputData< double > const &""'"); 
+  }
+  if (!argp1) {
+    SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "new_SimulationResult" "', argument " "1"" of type '" "OutputData< double > const &""'"); 
+  }
+  arg1 = reinterpret_cast< OutputData< double > * >(argp1);
+  res2 = SWIG_ConvertPtr(swig_obj[1], &argp2, SWIGTYPE_p_p_ICoordSystem,  0 );
+  if (!SWIG_IsOK(res2)) {
+    SWIG_exception_fail(SWIG_ArgError(res2), "in method '" "new_SimulationResult" "', argument " "2"" of type '" "ICoordSystem const *&&""'"); 
+  }
+  if (!argp2) {
+    SWIG_exception_fail(SWIG_ValueError, "invalid null reference " "in method '" "new_SimulationResult" "', argument " "2"" of type '" "ICoordSystem const *&&""'"); 
+  }
+  arg2 = reinterpret_cast< ICoordSystem ** >(argp2);
+  result = (SimulationResult *)new SimulationResult((OutputData< double > const &)*arg1,(ICoordSystem const *&&)*arg2);
+  resultobj = SWIG_NewPointerObj(SWIG_as_voidptr(result), SWIGTYPE_p_SimulationResult, SWIG_POINTER_NEW |  0 );
+  return resultobj;
+fail:
+  return NULL;
+}
+
+
+SWIGINTERN PyObject *_wrap_new_SimulationResult__SWIG_3(PyObject *SWIGUNUSEDPARM(self), Py_ssize_t nobjs, PyObject **swig_obj) {
   PyObject *resultobj = 0;
   SimulationResult *arg1 = 0 ;
   void *argp1 = 0 ;
@@ -42628,7 +42664,7 @@ fail:
 }
 
 
-SWIGINTERN PyObject *_wrap_new_SimulationResult__SWIG_3(PyObject *SWIGUNUSEDPARM(self), Py_ssize_t nobjs, PyObject **swig_obj) {
+SWIGINTERN PyObject *_wrap_new_SimulationResult__SWIG_4(PyObject *SWIGUNUSEDPARM(self), Py_ssize_t nobjs, PyObject **swig_obj) {
   PyObject *resultobj = 0;
   SimulationResult *arg1 = 0 ;
   void *argp1 = 0 ;
@@ -42668,7 +42704,7 @@ SWIGINTERN PyObject *_wrap_new_SimulationResult(PyObject *self, PyObject *args)
     int res = SWIG_ConvertPtr(argv[0], 0, SWIGTYPE_p_SimulationResult, SWIG_POINTER_NO_NULL | 0);
     _v = SWIG_CheckState(res);
     if (_v) {
-      return _wrap_new_SimulationResult__SWIG_2(self, argc, argv);
+      return _wrap_new_SimulationResult__SWIG_3(self, argc, argv);
     }
   }
   if (argc == 1) {
@@ -42677,7 +42713,7 @@ SWIGINTERN PyObject *_wrap_new_SimulationResult(PyObject *self, PyObject *args)
     int res = SWIG_ConvertPtr(argv[0], &vptr, SWIGTYPE_p_SimulationResult, SWIG_POINTER_NO_NULL);
     _v = SWIG_CheckState(res);
     if (_v) {
-      return _wrap_new_SimulationResult__SWIG_3(self, argc, argv);
+      return _wrap_new_SimulationResult__SWIG_4(self, argc, argv);
     }
   }
   if (argc == 2) {
@@ -42692,12 +42728,26 @@ SWIGINTERN PyObject *_wrap_new_SimulationResult(PyObject *self, PyObject *args)
       }
     }
   }
+  if (argc == 2) {
+    int _v;
+    int res = SWIG_ConvertPtr(argv[0], 0, SWIGTYPE_p_OutputDataT_double_t, SWIG_POINTER_NO_NULL | 0);
+    _v = SWIG_CheckState(res);
+    if (_v) {
+      void *vptr = 0;
+      int res = SWIG_ConvertPtr(argv[1], &vptr, SWIGTYPE_p_p_ICoordSystem, SWIG_POINTER_NO_NULL);
+      _v = SWIG_CheckState(res);
+      if (_v) {
+        return _wrap_new_SimulationResult__SWIG_2(self, argc, argv);
+      }
+    }
+  }
   
 fail:
   SWIG_Python_RaiseOrModifyTypeError("Wrong number or type of arguments for overloaded function 'new_SimulationResult'.\n"
     "  Possible C/C++ prototypes are:\n"
     "    SimulationResult::SimulationResult()\n"
     "    SimulationResult::SimulationResult(OutputData< double > const &,ICoordSystem const &)\n"
+    "    SimulationResult::SimulationResult(OutputData< double > const &,ICoordSystem const *&&)\n"
     "    SimulationResult::SimulationResult(SimulationResult const &)\n"
     "    SimulationResult::SimulationResult(SimulationResult &&)\n");
   return 0;
@@ -46021,7 +46071,8 @@ static PyMethodDef SwigMethods[] = {
 	 { "AxisInfo_swiginit", AxisInfo_swiginit, METH_VARARGS, NULL},
 	 { "new_SimulationResult", _wrap_new_SimulationResult, METH_VARARGS, "\n"
 		"SimulationResult()\n"
-		"SimulationResult(IntensityData data, ICoordSystem const & unit_converter)\n"
+		"SimulationResult(IntensityData data, ICoordSystem const & coords)\n"
+		"SimulationResult(IntensityData data, ICoordSystem const *&& coords)\n"
 		"SimulationResult(SimulationResult other)\n"
 		"new_SimulationResult(SimulationResult other) -> SimulationResult\n"
 		"SimulationResult::SimulationResult(SimulationResult &&other)\n"
@@ -46398,6 +46449,7 @@ static swig_type_info _swigt__p_iterator = {"_p_iterator", "iterator *", 0, 0, (
 static swig_type_info _swigt__p_key_type = {"_p_key_type", "key_type *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_long_long = {"_p_long_long", "int_least64_t *|int_fast64_t *|int64_t *|long long *|intmax_t *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_mapped_type = {"_p_mapped_type", "mapped_type *", 0, 0, (void*)0, 0};
+static swig_type_info _swigt__p_p_ICoordSystem = {"_p_p_ICoordSystem", "ICoordSystem **", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_p_PyObject = {"_p_p_PyObject", "PyObject **", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_parameters_t = {"_p_parameters_t", "parameters_t *", 0, 0, (void*)0, 0};
 static swig_type_info _swigt__p_second_type = {"_p_second_type", "second_type *", 0, 0, (void*)0, 0};
@@ -46511,6 +46563,7 @@ static swig_type_info *swig_type_initial[] = {
   &_swigt__p_key_type,
   &_swigt__p_long_long,
   &_swigt__p_mapped_type,
+  &_swigt__p_p_ICoordSystem,
   &_swigt__p_p_PyObject,
   &_swigt__p_parameters_t,
   &_swigt__p_second_type,
@@ -46624,6 +46677,7 @@ static swig_cast_info _swigc__p_iterator[] = {  {&_swigt__p_iterator, 0, 0, 0},{
 static swig_cast_info _swigc__p_key_type[] = {  {&_swigt__p_key_type, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_long_long[] = {  {&_swigt__p_long_long, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_mapped_type[] = {  {&_swigt__p_mapped_type, 0, 0, 0},{0, 0, 0, 0}};
+static swig_cast_info _swigc__p_p_ICoordSystem[] = {  {&_swigt__p_p_ICoordSystem, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_p_PyObject[] = {  {&_swigt__p_p_PyObject, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_parameters_t[] = {  {&_swigt__p_parameters_t, 0, 0, 0},{0, 0, 0, 0}};
 static swig_cast_info _swigc__p_second_type[] = {  {&_swigt__p_second_type, 0, 0, 0},{0, 0, 0, 0}};
@@ -46737,6 +46791,7 @@ static swig_cast_info *swig_cast_initial[] = {
   _swigc__p_key_type,
   _swigc__p_long_long,
   _swigc__p_mapped_type,
+  _swigc__p_p_ICoordSystem,
   _swigc__p_p_PyObject,
   _swigc__p_parameters_t,
   _swigc__p_second_type,