From e3343f72952185ab985a0b4da018816cdaa0fe80 Mon Sep 17 00:00:00 2001
From: Gagik Vardanyan <vardanyan@ill.fr>
Date: Thu, 29 Nov 2018 13:40:25 +0100
Subject: [PATCH] Re #24124 new algorithm parallax correction

---
 Framework/Algorithms/CMakeLists.txt           |   3 +
 .../inc/MantidAlgorithms/ParallaxCorrection.h |  34 ++++
 .../Algorithms/src/ParallaxCorrection.cpp     | 188 ++++++++++++++++++
 .../Algorithms/test/ParallaxCorrectionTest.h  | 149 ++++++++++++++
 .../algorithms/ParallaxCorrection-v1.rst      |  54 +++++
 docs/source/release/v3.14.0/framework.rst     |   1 +
 instrument/D22_Parameters.xml                 |  32 ++-
 instrument/D22lr_Parameters.xml               |  35 +++-
 instrument/D33_Parameters.xml                 |  85 ++++++--
 9 files changed, 542 insertions(+), 39 deletions(-)
 create mode 100644 Framework/Algorithms/inc/MantidAlgorithms/ParallaxCorrection.h
 create mode 100644 Framework/Algorithms/src/ParallaxCorrection.cpp
 create mode 100644 Framework/Algorithms/test/ParallaxCorrectionTest.h
 create mode 100644 docs/source/algorithms/ParallaxCorrection-v1.rst

diff --git a/Framework/Algorithms/CMakeLists.txt b/Framework/Algorithms/CMakeLists.txt
index d513840a134..4bd7e03cf3a 100644
--- a/Framework/Algorithms/CMakeLists.txt
+++ b/Framework/Algorithms/CMakeLists.txt
@@ -215,6 +215,7 @@ set ( SRC_FILES
 	src/PDDetermineCharacterizations.cpp
 	src/PDFFourierTransform.cpp
 	src/PaddingAndApodization.cpp
+	src/ParallaxCorrection.cpp
 	src/Pause.cpp
 	src/PerformIndexOperations.cpp
 	src/Plus.cpp
@@ -554,6 +555,7 @@ set ( INC_FILES
 	inc/MantidAlgorithms/PDDetermineCharacterizations.h
 	inc/MantidAlgorithms/PDFFourierTransform.h
 	inc/MantidAlgorithms/PaddingAndApodization.h
+	inc/MantidAlgorithms/ParallaxCorrection.h
 	inc/MantidAlgorithms/Pause.h
 	inc/MantidAlgorithms/PerformIndexOperations.h
 	inc/MantidAlgorithms/Plus.h
@@ -896,6 +898,7 @@ set ( TEST_FILES
 	PDDetermineCharacterizationsTest.h
 	PDFFourierTransformTest.h
 	PaddingAndApodizationTest.h
+	ParallaxCorrectionTest.h
 	PauseTest.h
 	PerformIndexOperationsTest.h
 	PlusTest.h
diff --git a/Framework/Algorithms/inc/MantidAlgorithms/ParallaxCorrection.h b/Framework/Algorithms/inc/MantidAlgorithms/ParallaxCorrection.h
new file mode 100644
index 00000000000..7824a713506
--- /dev/null
+++ b/Framework/Algorithms/inc/MantidAlgorithms/ParallaxCorrection.h
@@ -0,0 +1,34 @@
+// Mantid Repository : https://github.com/mantidproject/mantid
+//
+// Copyright &copy; 2018 ISIS Rutherford Appleton Laboratory UKRI,
+//     NScD Oak Ridge National Laboratory, European Spallation Source
+//     & Institut Laue - Langevin
+// SPDX - License - Identifier: GPL - 3.0 +
+#ifndef MANTID_ALGORITHMS_PARALLAXCORRECTION_H_
+#define MANTID_ALGORITHMS_PARALLAXCORRECTION_H_
+
+#include "MantidAlgorithms/DllConfig.h"
+#include "MantidAPI/Algorithm.h"
+
+namespace Mantid {
+namespace Algorithms {
+
+/** ParallaxCorrection : Performs geometrical correction for parallax effect in
+ * tube based SANS instruments.
+ */
+class MANTID_ALGORITHMS_DLL ParallaxCorrection : public API::Algorithm {
+public:
+  const std::string name() const override;
+  int version() const override;
+  const std::string category() const override;
+  const std::string summary() const override;
+
+private:
+  void init() override;
+  void exec() override;
+};
+
+} // namespace Algorithms
+} // namespace Mantid
+
+#endif /* MANTID_ALGORITHMS_PARALLAXCORRECTION_H_ */
diff --git a/Framework/Algorithms/src/ParallaxCorrection.cpp b/Framework/Algorithms/src/ParallaxCorrection.cpp
new file mode 100644
index 00000000000..06021a77f72
--- /dev/null
+++ b/Framework/Algorithms/src/ParallaxCorrection.cpp
@@ -0,0 +1,188 @@
+// Mantid Repository : https://github.com/mantidproject/mantid
+//
+// Copyright &copy; 2018 ISIS Rutherford Appleton Laboratory UKRI,
+//     NScD Oak Ridge National Laboratory, European Spallation Source
+//     & Institut Laue - Langevin
+// SPDX - License - Identifier: GPL - 3.0 +
+#include "MantidAlgorithms/ParallaxCorrection.h"
+#include "MantidAPI/InstrumentValidator.h"
+#include "MantidAPI/MatrixWorkspace.h"
+#include "MantidAPI/Progress.h"
+#include "MantidAPI/WorkspaceUnitValidator.h"
+#include "MantidGeometry/Instrument.h"
+#include "MantidGeometry/Instrument/DetectorInfo.h"
+#include "MantidHistogramData/HistogramMath.h"
+#include "MantidKernel/ArrayLengthValidator.h"
+#include "MantidKernel/ArrayProperty.h"
+#include "MantidKernel/CompositeValidator.h"
+
+#include <math.h>
+#include <muParser.h>
+
+namespace {
+static const std::string PARALLAX_PARAMETER = "parallax";
+static const std::string DIRECTION_PARAMETER = "direction";
+
+/**
+ * @brief validateFormula Checks if the formula is evaluable
+ * @param parallax : formula
+ * @param direction : x or y
+ * @return empty string if valid, error message otherwise
+ */
+std::string validateFormula(const std::string &parallax,
+                            const std::string &direction) {
+  if (direction != "x" && direction != "y") {
+    return "Direction must be x or y";
+  }
+  mu::Parser muParser;
+  double t = 0.;
+  muParser.DefineVar("t", &t);
+  muParser.SetExpr(parallax);
+  try {
+    muParser.Eval();
+  } catch (mu::Parser::exception_type &e) {
+    return e.GetMsg();
+  }
+  return "";
+}
+} // namespace
+
+namespace Mantid {
+namespace Algorithms {
+
+// Register the algorithm into the AlgorithmFactory
+DECLARE_ALGORITHM(ParallaxCorrection)
+
+//----------------------------------------------------------------------------------------------
+
+/// Algorithms name for identification. @see Algorithm::name
+const std::string ParallaxCorrection::name() const {
+  return "ParallaxCorrection";
+}
+
+/// Algorithm's version for identification. @see Algorithm::version
+int ParallaxCorrection::version() const { return 1; }
+
+/// Algorithm's category for identification. @see Algorithm::category
+const std::string ParallaxCorrection::category() const { return "SANS"; }
+
+/// Algorithm's summary for use in the GUI and help. @see Algorithm::summary
+const std::string ParallaxCorrection::summary() const {
+  return "Performs parallax correction for tube based SANS instruments.";
+}
+
+//----------------------------------------------------------------------------------------------
+/** Initialize the algorithm's properties.
+ */
+void ParallaxCorrection::init() {
+  auto validator = boost::make_shared<Kernel::CompositeValidator>();
+  validator->add(Kernel::make_unique<API::InstrumentValidator>());
+  validator->add(
+      Kernel::make_unique<API::WorkspaceUnitValidator>("Wavelength"));
+  auto lengthValidator =
+      boost::make_shared<Kernel::ArrayLengthValidator<std::string>>();
+  lengthValidator->setLengthMin(1);
+  declareProperty(
+      Kernel::make_unique<API::WorkspaceProperty<API::MatrixWorkspace>>(
+          "InputWorkspace", "", Kernel::Direction::Input, validator),
+      "An input workspace.");
+  declareProperty(
+      Kernel::make_unique<Kernel::ArrayProperty<std::string>>("ComponentNames",
+                                                              lengthValidator),
+      "List of instrument components to perform the corrections for.");
+  declareProperty(
+      Kernel::make_unique<API::WorkspaceProperty<API::MatrixWorkspace>>(
+          "OutputWorkspace", "", Kernel::Direction::Output),
+      "An output workspace.");
+}
+
+//----------------------------------------------------------------------------------------------
+/** Execute the algorithm.
+ */
+void ParallaxCorrection::exec() {
+  API::MatrixWorkspace_const_sptr inputWorkspace =
+      getProperty("InputWorkspace");
+  API::MatrixWorkspace_sptr outputWorkspace = getProperty("OutputWorkspace");
+  if (inputWorkspace != outputWorkspace) {
+    outputWorkspace = inputWorkspace->clone();
+  }
+  const std::vector<std::string> componentNames = getProperty("ComponentNames");
+  const auto &instrument = inputWorkspace->getInstrument();
+  const auto &detectorInfo = inputWorkspace->detectorInfo();
+  auto progress =
+      Kernel::make_unique<API::Progress>(this, 0., 1., componentNames.size());
+  for (const auto &componentName : componentNames) {
+    progress->report("Performing parallax correction for component " +
+                     componentName);
+    const auto component = instrument->getComponentByName(componentName);
+    if (!component) {
+      g_log.error() << "No component defined with name " << componentName
+                    << "\n";
+      continue;
+    }
+    if (!component->hasParameter(PARALLAX_PARAMETER) ||
+        !component->hasParameter(DIRECTION_PARAMETER)) {
+      g_log.error() << "No parallax correction defined in IPF for component "
+                    << componentName << "\n";
+      continue;
+    }
+    std::vector<detid_t> detIDs;
+    std::vector<Geometry::IDetector_const_sptr> dets;
+    instrument->getDetectorsInBank(dets, componentName);
+    if (dets.empty()) {
+      const auto det =
+          boost::dynamic_pointer_cast<const Geometry::IDetector>(component);
+      if (!det) {
+        g_log.error() << "No detectors found in component " << componentName
+                      << "\n";
+        continue;
+      }
+      dets.emplace_back(det);
+    }
+    if (!dets.empty()) {
+      detIDs.reserve(dets.size());
+      for (const auto &det : dets) {
+        detIDs.emplace_back(det->getID());
+      }
+      const auto indices = inputWorkspace->getIndicesFromDetectorIDs(detIDs);
+      const std::string parallax =
+          component->getStringParameter(PARALLAX_PARAMETER)[0];
+      const std::string direction =
+          component->getStringParameter(DIRECTION_PARAMETER)[0];
+      const auto valid = validateFormula(parallax, direction);
+      if (!valid.empty()) {
+        g_log.error() << "Unable to parse the parallax formula and direction "
+                         "for component "
+                      << componentName << ". Reason: " << valid << "\n";
+        continue;
+      }
+      double t;
+      mu::Parser muParser;
+      muParser.DefineVar("t", &t);
+      muParser.SetExpr(parallax);
+      // note that this is intenionally serial
+      for (auto wsIndex : indices) {
+        const Kernel::V3D pos = detectorInfo.position(wsIndex);
+        if (direction == "y") {
+          t = std::fabs(std::atan2(pos.X(), pos.Z()));
+        } else {
+          t = std::fabs(std::atan2(pos.Y(), pos.Z()));
+        }
+        const double correction = muParser.Eval();
+        if (correction > 0.) {
+          auto &spectrum = outputWorkspace->mutableY(wsIndex);
+          auto &errors = outputWorkspace->mutableE(wsIndex);
+          spectrum /= correction;
+          errors /= correction;
+        } else {
+          g_log.warning() << "Correction is <=0 for workspace index " << wsIndex
+                          << ". Skipping the correction.\n";
+        }
+      }
+    }
+  }
+  setProperty("OutputWorkspace", outputWorkspace);
+}
+
+} // namespace Algorithms
+} // namespace Mantid
diff --git a/Framework/Algorithms/test/ParallaxCorrectionTest.h b/Framework/Algorithms/test/ParallaxCorrectionTest.h
new file mode 100644
index 00000000000..e807fa14ea6
--- /dev/null
+++ b/Framework/Algorithms/test/ParallaxCorrectionTest.h
@@ -0,0 +1,149 @@
+// Mantid Repository : https://github.com/mantidproject/mantid
+//
+// Copyright &copy; 2018 ISIS Rutherford Appleton Laboratory UKRI,
+//     NScD Oak Ridge National Laboratory, European Spallation Source
+//     & Institut Laue - Langevin
+// SPDX - License - Identifier: GPL - 3.0 +
+#ifndef MANTID_ALGORITHMS_PARALLAXCORRECTIONTEST_H_
+#define MANTID_ALGORITHMS_PARALLAXCORRECTIONTEST_H_
+
+#include <cxxtest/TestSuite.h>
+
+#include "MantidAPI/FrameworkManager.h"
+#include "MantidAPI/MatrixWorkspace_fwd.h"
+#include "MantidAlgorithms/CreateSampleWorkspace.h"
+#include "MantidAlgorithms/ParallaxCorrection.h"
+#include "MantidAlgorithms/SetInstrumentParameter.h"
+#include "MantidGeometry/Instrument/DetectorInfo.h"
+#include "MantidKernel/V3D.h"
+
+using Mantid::Algorithms::CreateSampleWorkspace;
+using Mantid::Algorithms::ParallaxCorrection;
+using Mantid::Algorithms::SetInstrumentParameter;
+using Mantid::API::FrameworkManager;
+using Mantid::API::MatrixWorkspace_sptr;
+using Mantid::Geometry::DetectorInfo;
+using Mantid::Kernel::V3D;
+
+namespace {
+MatrixWorkspace_sptr createWorkspace(const int nPixelsPerBank = 3,
+                                     const int nBins = 2) {
+  CreateSampleWorkspace creator;
+  creator.initialize();
+  creator.setChild(true);
+  creator.setAlwaysStoreInADS(false);
+  creator.setProperty("NumBanks", 1);
+  creator.setProperty("XMin", 1.);
+  creator.setProperty("XMax", 2.);
+  creator.setProperty("BinWidth", 1. / nBins);
+  creator.setProperty("BankPixelWidth", nPixelsPerBank);
+  creator.setProperty("Function", "One Peak");
+  creator.setProperty("XUnit", "Wavelength");
+  creator.setPropertyValue("OutputWorkspace", "__unused");
+  creator.execute();
+
+  MatrixWorkspace_sptr in = creator.getProperty("OutputWorkspace");
+
+  SetInstrumentParameter setter;
+  setter.initialize();
+  setter.setChild(true);
+  setter.setAlwaysStoreInADS(false);
+
+  setter.setProperty("Workspace", in);
+  setter.setProperty("ParameterName", "direction");
+  setter.setProperty("ParameterType", "String");
+  setter.setProperty("ComponentName", "bank1");
+  setter.setProperty("Value", "y");
+  setter.execute();
+
+  setter.setProperty("Workspace", in);
+  setter.setProperty("ParameterName", "parallax");
+  setter.setProperty("ParameterType", "String");
+  setter.setProperty("ComponentName", "bank1");
+  setter.setProperty("Value", "1 + 0.1 * t");
+  setter.execute();
+
+  return in;
+}
+} // namespace
+
+class ParallaxCorrectionTest : public CxxTest::TestSuite {
+public:
+  // This pair of boilerplate methods prevent the suite being created statically
+  // This means the constructor isn't called when running other tests
+  static ParallaxCorrectionTest *createSuite() {
+    return new ParallaxCorrectionTest();
+  }
+  static void destroySuite(ParallaxCorrectionTest *suite) { delete suite; }
+
+  ParallaxCorrectionTest() { FrameworkManager::Instance(); }
+
+  void test_init() {
+    ParallaxCorrection alg;
+    TS_ASSERT_THROWS_NOTHING(alg.initialize())
+    TS_ASSERT(alg.isInitialized())
+  }
+
+  void test_exec() {
+
+    MatrixWorkspace_sptr in = createWorkspace();
+    const std::vector<std::string> components = {"bank1"};
+
+    ParallaxCorrection alg;
+    alg.setChild(true);
+    alg.setAlwaysStoreInADS(false);
+    alg.initialize();
+    alg.isInitialized();
+    alg.setRethrows(true);
+    TS_ASSERT_THROWS_NOTHING(alg.setProperty("InputWorkspace", in));
+    TS_ASSERT_THROWS_NOTHING(alg.setProperty("ComponentNames", components));
+    TS_ASSERT_THROWS_NOTHING(
+        alg.setPropertyValue("OutputWorkspace", "__unused"));
+    TS_ASSERT_THROWS_NOTHING(alg.execute());
+    TS_ASSERT(alg.isExecuted());
+
+    MatrixWorkspace_sptr out = alg.getProperty("OutputWorkspace");
+    TS_ASSERT(out);
+    // Divide the input with the output to get just the correction
+    in /= out;
+
+    auto &detectorInfo = in->detectorInfo();
+    for (size_t index = 0; index < in->getNumberHistograms(); ++index) {
+      const V3D pos = detectorInfo.position(index);
+      const double expectation =
+          1. + 0.1 * std::abs(std::atan2(pos.X(), pos.Z()));
+      const double reality = in->y(index)[0];
+      TS_ASSERT_DELTA(expectation, reality, 1E-5);
+    }
+  }
+};
+
+class ParallaxCorrectionTestPerformance : public CxxTest::TestSuite {
+public:
+  static ParallaxCorrectionTestPerformance *createSuite() {
+    return new ParallaxCorrectionTestPerformance();
+  }
+  static void destroySuite(ParallaxCorrectionTestPerformance *suite) {
+    delete suite;
+  }
+
+  void setUp() override {
+    FrameworkManager::Instance();
+    m_alg.initialize();
+    m_alg.setChild(true);
+    m_alg.setAlwaysStoreInADS(false);
+    m_alg.setRethrows(true);
+    MatrixWorkspace_sptr in = createWorkspace(1000, 100);
+    const std::vector<std::string> components = {"bank1"};
+    m_alg.setProperty("InputWorkspace", in);
+    m_alg.setProperty("ComponentNames", components);
+    m_alg.setProperty("OutputWorkspace", "__out");
+  }
+
+  void test_performance() { TS_ASSERT_THROWS_NOTHING(m_alg.execute()) }
+
+private:
+  ParallaxCorrection m_alg;
+};
+
+#endif /* MANTID_ALGORITHMS_PARALLAXCORRECTIONTEST_H_ */
diff --git a/docs/source/algorithms/ParallaxCorrection-v1.rst b/docs/source/algorithms/ParallaxCorrection-v1.rst
new file mode 100644
index 00000000000..5f6375c3cc0
--- /dev/null
+++ b/docs/source/algorithms/ParallaxCorrection-v1.rst
@@ -0,0 +1,54 @@
+
+.. algorithm::
+
+.. summary::
+
+.. relatedalgorithms::
+
+.. properties::
+
+Description
+-----------
+
+This algorithm performs a geometrical correction for the so-called parallax effect in tube based SANS instruments.
+
+The correction formula must be specified in the :ref:`IPF <InstrumentParameterFile>` as follows:
+
+- A string parameter named **direction** must hold **x** or **y** which is the direction of the tubes in the detector.
+
+- A string parameter named **parallax** must hold the `muparser <http://beltoforion.de/article.php?a=muparser>`_ expression, where **t** is reserved for the parallax angle:
+
+:math:`t = \arctan(\frac{x}{z})` if direction is **y**, and :math:`t = \arctan(\frac{y}{z})` if direction is **x**.
+
+:math:`x, y, z` are the coordinates of the detector pixel in the system where sample is at :math:`0,0,0` and :math:`z` is the beam axis.
+:math:`t \in (0,\frac{\pi}{2})` in radians.
+
+The correction will be calculated for each pixel and the input data will be divided by the correction and stored in the output.
+
+The instrument parameters must be defined for detector components and without loss of generality, different components can have different formulae.
+
+At least one component name must be given as input.
+
+Usage
+-----
+
+**Example - ParallaxCorrection**
+
+.. testcode:: ParallaxCorrectionExample
+
+    CreateSampleWorkspace(NumBanks=1, XMin=1, XMax=2, BinWidth=1, BankPixelWidth=100, Function="One Peak", XUnit="Wavelength", OutputWorkspace="in")
+    SetInstrumentParameter(Workspace="in", ParameterName="direction", ComponentName="bank1", ParameterType="String", Value="y")
+    SetInstrumentParameter(Workspace="in", ParameterName="parallax", ComponentName="bank1", ParameterType="String", Value="1+0.1*t")
+    ParallaxCorrection(InputWorkspace="in", ComponentNames="bank1", OutputWorkspace="out")
+    Divide(LHSWorkspace="in", RHSWorkspace="out", OutputWorkspace="corr")
+    print("The correction is {0:.4f} for the spectrum {1}".format(mtd["corr"].readY(1000)[0], 1000))
+
+Output:
+
+.. testoutput:: ParallaxCorrectionExample
+
+  The correction is 1.0016 for the spectrum 1000
+
+.. categories::
+
+.. sourcelink::
diff --git a/docs/source/release/v3.14.0/framework.rst b/docs/source/release/v3.14.0/framework.rst
index 2ddcd7ddd01..035f3164cbb 100644
--- a/docs/source/release/v3.14.0/framework.rst
+++ b/docs/source/release/v3.14.0/framework.rst
@@ -49,6 +49,7 @@ New Algorithms
 - :ref:`MatchSpectra <algm-MatchSpectra>` is an algorithm that calculates factors to match all spectra to a reference spectrum.
 - :ref:`MaskBinsIf <algm-MaskBinsIf>` is an algorithm to mask bins according to criteria specified as a muparser expression.
 - :ref:`MaskNonOverlappingBins <algm-MaskNonOverlappingBins>` masks the bins that do not overlap with another workspace.
+- :ref:`ParallaxCorrection <algm-ParallaxCorrection>` will perform a geometric correction for the so-called parallax effect in tube based SANS detectors.
 
 Improvements
 ############
diff --git a/instrument/D22_Parameters.xml b/instrument/D22_Parameters.xml
index df9e8746287..7017ad3d8af 100644
--- a/instrument/D22_Parameters.xml
+++ b/instrument/D22_Parameters.xml
@@ -1,16 +1,32 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <parameter-file instrument = "D22" valid-from="2017-10-01 23:59:59">
 
+
+    <!-- This should be removed when the new way of correction is in the workflow-->
     <component-link name="D22">
 
-    <!-- This is the formula to model the theta dependency of the
-    detector sensitivities because of varying path lengths in the
-    detector volume. This is evaluated with python eval.
-    Note that the np stands for the numpy, p must be the parallax:
-    p = arctan(x/l2) [in radians], where x is the coordinate of the
-    detector pixel, l2 is the sample to detector distance. -->
-		<parameter name="parallax" type="string">
-		  <value val="1+0.14*np.exp(-4*np.log(2.)*((np.abs(p)-0.588)/0.414)**2)"/>
+      <!-- This is the formula to model the theta dependency of the
+      detector sensitivities because of varying path lengths in the
+      detector volume. This is evaluated with python eval.
+      Note that the np stands for the numpy, p must be the parallax:
+      p = arctan(x/l2) [in radians], where x is the coordinate of the
+      detector pixel, l2 is the sample to detector distance. -->
+      <parameter name="parallax" type="string">
+        <value val="1+0.14*np.exp(-4*np.log(2.)*((np.abs(p)-0.588)/0.414)**2)"/>
+      </parameter>
+
+    </component-link>
+
+    <!-- These parameters are used in ParallaxCorrection algorithm -->
+
+    <component-link name="detector">
+
+    <parameter name="parallax" type="string">
+		  <value val="1+0.14*exp(-4*log(2.)*((t-0.588)/0.414)^2)"/>
+		</parameter>
+
+    <parameter name="direction" type="string">
+		  <value val="y"/>
 		</parameter>
 
     </component-link>
diff --git a/instrument/D22lr_Parameters.xml b/instrument/D22lr_Parameters.xml
index b6fc8c44aaf..50d8da17a02 100644
--- a/instrument/D22lr_Parameters.xml
+++ b/instrument/D22lr_Parameters.xml
@@ -1,16 +1,31 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <parameter-file instrument = "D22lr" valid-from="2017-10-01 23:59:59">
 
-    <component-link name="D22lr">
-
-    <!-- This is the formula to model the theta dependency of the
-    detector sensitivities because of varying path lengths in the
-    detector volume. This is evaluated with python eval.
-    Note that the np stands for the numpy, p must be the parallax:
-    p = arctan(x/l2) [in radians], where x is the coordinate of the
-    detector pixel, l2 is the sample to detector distance. -->
-		<parameter name="parallax" type="string">
-		  <value val="1+0.14*np.exp(-4*np.log(2.)*((np.abs(p)-0.588)/0.414)**2)"/>
+    <!-- This should be removed when the new way of correction is in the workflow-->
+    <component-link name="D22">
+
+      <!-- This is the formula to model the theta dependency of the
+      detector sensitivities because of varying path lengths in the
+      detector volume. This is evaluated with python eval.
+      Note that the np stands for the numpy, p must be the parallax:
+      p = arctan(x/l2) [in radians], where x is the coordinate of the
+      detector pixel, l2 is the sample to detector distance. -->
+      <parameter name="parallax" type="string">
+        <value val="1+0.14*np.exp(-4*np.log(2.)*((np.abs(p)-0.588)/0.414)**2)"/>
+      </parameter>
+
+    </component-link>
+
+    <!-- These parameters are used in ParallaxCorrection algorithm -->
+
+    <component-link name="detector">
+
+    <parameter name="parallax" type="string">
+		  <value val="1+0.14*exp(-4*log(2.)*((abs(t)-0.588)/0.414)^2)"/>
+		</parameter>
+
+    <parameter name="direction" type="string">
+		  <value val="y"/>
 		</parameter>
 
     </component-link>
diff --git a/instrument/D33_Parameters.xml b/instrument/D33_Parameters.xml
index 4cafda254fd..e4e753af62f 100644
--- a/instrument/D33_Parameters.xml
+++ b/instrument/D33_Parameters.xml
@@ -1,23 +1,66 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <parameter-file instrument = "D33" valid-from = "20th May 2010">
-    
-    <component-link name="D33">
-		
-		<parameter name="number-of-x-pixels">
-		  <value val="256"/>
-		</parameter>
-
-		<parameter name="number-of-y-pixels">
-		  <value val="128"/>
-		</parameter>
-
-		<parameter name="x-pixel-size">
-		  <value val="5.5"/>
-		</parameter>
-		
-		<parameter name="y-pixel-size">
-		  <value val="4.297"/>
-		</parameter>
-
-    </component-link>
-</parameter-file>    
+
+  <!-- These parameters are used in ParallaxCorrection algorithm -->
+
+  <component-link name="back_detector">
+
+    <parameter name="parallax" type="string">
+      <value val="(t * 180 / 3.14 &lt; 10) ? (1 + t * 180 / 3.14 * 0.0081615 / 1.0273) : (1 + 10 * 0.0081615 / 1.0273)"/>
+    </parameter>
+
+    <parameter name="direction" type="string">
+      <value val="x"/>
+    </parameter>
+
+  </component-link>
+
+  <component-link name="front_detector_right">
+
+    <parameter name="parallax" type="string">
+      <value val="(t * 180 / 3.14 &lt; 10) ? (1 + t * 180 / 3.14 * 0.005026 / 0.90814) : (1 + 10 * 0.005026 / 0.90814)"/>
+    </parameter>
+
+    <parameter name="direction" type="string">
+      <value val="y"/>
+    </parameter>
+
+  </component-link>
+
+  <component-link name="front_detector_left">
+
+    <parameter name="parallax" type="string">
+      <value val="(t * 180 / 3.14 &lt; 10) ? (1 + t * 180 / 3.14 * 0.005026 / 0.90814) : (1 + 10 * 0.005026 / 0.90814)"/>
+    </parameter>
+
+    <parameter name="direction" type="string">
+      <value val="y"/>
+    </parameter>
+
+  </component-link>
+
+  <component-link name="front_detector_top">
+
+    <parameter name="parallax" type="string">
+      <value val="(t * 180 / 3.14 &lt; 10) ? (1 + t * 180 / 3.14 * 0.0058296 / 0.98876) : (1 + 10 * 0.0058296 / 0.98876)"/>
+    </parameter>
+
+    <parameter name="direction" type="string">
+      <value val="x"/>
+    </parameter>
+
+  </component-link>
+
+  <component-link name="front_detector_bottom">
+
+    <parameter name="parallax" type="string">
+      <value val="(t * 180 / 3.14 &lt; 10) ? (1 + t * 180 / 3.14 * 0.0058296 / 0.98876) : (1 + 10 * 0.0058296 / 0.98876)"/>
+    </parameter>
+
+    <parameter name="direction" type="string">
+      <value val="x"/>
+    </parameter>
+
+  </component-link>
+
+</parameter-file>
-- 
GitLab