diff --git a/Framework/Geometry/src/Instrument.cpp b/Framework/Geometry/src/Instrument.cpp
index d4465f5ffceb4a5c7867b65dad4ea57b7c8b2920..caa2d371f591101b426fa05e9aaaebc0b6ebf260 100644
--- a/Framework/Geometry/src/Instrument.cpp
+++ b/Framework/Geometry/src/Instrument.cpp
@@ -1266,36 +1266,51 @@ boost::shared_ptr<ParameterMap> Instrument::makeLegacyParameterMap() const {
   constexpr double L = 1000.0;
   constexpr double safety_factor = 2.0;
   const double imag_norm_max = sin(d_max / (2.0 * L * safety_factor));
+
+  const IComponent *oldParent{nullptr};
+  Eigen::Quaterniond invParentRot;
+  Eigen::Affine3d transformation;
   for (size_t i = 0; i < m_detectorInfo->size(); ++i) {
     const auto &det = std::get<1>(baseInstr.m_detectorCache[i]);
     if (m_detectorInfo->isMasked(i)) {
       pmap->forceUnsafeSetMasked(det.get(), true);
     }
 
-    // Compare detector position with position based on pmap. Note that we
-    // previously stripped the DetectorInfo from pmap so we do not get positions
-    // from the DetectorInfo but only those directly stored in pmap.
-    const auto parDet = ParComponentFactory::create(det, pmap.get());
-    auto relPos = m_detectorInfo->position(i);
-    auto relRot = m_detectorInfo->rotation(i);
-    if (const auto parent = parDet->getParent()) {
-      relPos -= toVector3d(parent->getPos());
-      const auto invParentRot =
-          toQuaterniond(parent->getRotation()).conjugate();
-      relPos = invParentRot * relPos;
-      // Note the unusual order, see Component.cpp
-      relRot = invParentRot * relRot;
+    // Obtain parent position/rotation/scale.
+    const auto parent = det->getParent();
+    if (parent.get() != oldParent) {
+      oldParent = parent.get();
+      const auto parParent = ParComponentFactory::create(parent, pmap.get());
+      const auto parentPos = toVector3d(parParent->getPos());
+      invParentRot = toQuaterniond(parParent->getRotation()).conjugate();
+      transformation = invParentRot;
+      transformation.translate(-parentPos);
+      // Special case: scaling for RectangularDetectorPixel
+      if (boost::dynamic_pointer_cast<const RectangularDetectorPixel>(det)) {
+        const auto *panel = det->getParent()->getParent().get();
+        Eigen::Vector3d scale(1, 1, 1);
+        if (auto scalex = pmap->get(panel, "scalex"))
+          scale[0] = 1.0 / scalex->value<double>();
+        if (auto scaley = pmap->get(panel, "scaley"))
+          scale[1] = 1.0 / scaley->value<double>();
+        transformation.prescale(scale);
+      }
     }
+
+    // Undo parent transformation to obtain relative position/rotation.
+    auto relPos = transformation * m_detectorInfo->position(i);
+    auto relRot = invParentRot * m_detectorInfo->rotation(i);
+
     // Tolerance 1e-9 m as in Beamline::DetectorInfo::isEquivalent.
-    if ((relPos - toVector3d(parDet->getRelativePos())).norm() >= 1e-9) {
-      if (boost::dynamic_pointer_cast<const RectangularDetectorPixel>(parDet))
+    if ((relPos - toVector3d(det->getRelativePos())).norm() >= 1e-9) {
+      if (boost::dynamic_pointer_cast<const RectangularDetectorPixel>(det))
         throw std::runtime_error("Cannot create legacy ParameterMap: Position "
                                  "parameters for RectangularDetectorPixel are "
                                  "not supported");
       pmap->addV3D(det->getComponentID(), ParameterMap::pos(), toV3D(relPos));
     }
 
-    if ((relRot * toQuaterniond(parDet->getRelativeRot()).conjugate())
+    if ((relRot * toQuaterniond(det->getRelativeRot()).conjugate())
             .vec()
             .norm() >= imag_norm_max)
       pmap->addQuat(det->getComponentID(), ParameterMap::rot(), toQuat(relRot));