From a61daffb3f2d8aed554fc574d1046959b360a38b Mon Sep 17 00:00:00 2001
From: Wenduo Zhou <zhouw@ornl.gov>
Date: Mon, 23 Jul 2012 17:30:45 -0400
Subject: [PATCH] Start new LeBailFit version 2.  Refs #5306.

---
 .../Framework/CurveFitting/CMakeLists.txt     |   3 +
 .../inc/MantidCurveFitting/LeBailFit2.h       |  92 +++++
 .../ThermalNeutronBk2BkExpConvPV.h            |   4 +-
 .../Framework/CurveFitting/src/LeBailFit2.cpp | 269 ++++++++++++++
 .../CurveFitting/test/LeBailFit2Test.h        | 343 ++++++++++++++++++
 5 files changed, 710 insertions(+), 1 deletion(-)
 create mode 100644 Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/LeBailFit2.h
 create mode 100644 Code/Mantid/Framework/CurveFitting/src/LeBailFit2.cpp
 create mode 100644 Code/Mantid/Framework/CurveFitting/test/LeBailFit2Test.h

diff --git a/Code/Mantid/Framework/CurveFitting/CMakeLists.txt b/Code/Mantid/Framework/CurveFitting/CMakeLists.txt
index 773c698090e..3c0b17ba898 100644
--- a/Code/Mantid/Framework/CurveFitting/CMakeLists.txt
+++ b/Code/Mantid/Framework/CurveFitting/CMakeLists.txt
@@ -38,6 +38,7 @@ set ( SRC_FILES
 	src/IFuncMinimizer.cpp
 	src/IkedaCarpenterPV.cpp
 	src/LeBailFit.cpp
+	src/LeBailFit2.cpp
 	src/LeBailFunction.cpp
 	src/LevenbergMarquardtMDMinimizer.cpp
 	src/LevenbergMarquardtMinimizer.cpp
@@ -120,6 +121,7 @@ set ( INC_FILES
 	inc/MantidCurveFitting/IkedaCarpenterPV.h
 	inc/MantidCurveFitting/Jacobian.h
 	inc/MantidCurveFitting/LeBailFit.h
+	inc/MantidCurveFitting/LeBailFit2.h
 	inc/MantidCurveFitting/LeBailFunction.h
 	inc/MantidCurveFitting/LevenbergMarquardtMDMinimizer.h
 	inc/MantidCurveFitting/LevenbergMarquardtMinimizer.h
@@ -183,6 +185,7 @@ set ( TEST_FILES
 	test/GaussianTest.h
 	test/HighOrderPolynomialBackgroundTest.h
 	test/IkedaCarpenterPVTest.h
+	test/LeBailFit2Test.h
 	test/LeBailFitTest.h
 	test/LeBailFunctionTest.h
 	test/LeastSquaresTest.h
diff --git a/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/LeBailFit2.h b/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/LeBailFit2.h
new file mode 100644
index 00000000000..54d95cb7085
--- /dev/null
+++ b/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/LeBailFit2.h
@@ -0,0 +1,92 @@
+#ifndef MANTID_CURVEFITTING_LEBAILFIT2_H_
+#define MANTID_CURVEFITTING_LEBAILFIT2_H_
+
+#include "MantidKernel/System.h"
+#include "MantidAPI/Algorithm.h"
+#include "MantidDataObjects/TableWorkspace.h"
+#include "MantidDataObjects/Workspace2D.h"
+#include "MantidAPI/MatrixWorkspace.h"
+#include "MantidCurveFitting/ThermalNeutronBk2BkExpConvPV.h"
+#include "MantidAPI/CompositeFunction.h"
+
+
+using namespace Mantid;
+using namespace Mantid::Kernel;
+
+namespace Mantid
+{
+namespace CurveFitting
+{
+
+  /** LeBailFit2 : Algorithm to do Le Bail Fit.
+    The workflow and architecture of this algorithm is different from LeBailFit,
+    though they hold the same interface to users.
+    
+    Copyright &copy; 2012 ISIS Rutherford Appleton Laboratory & NScD Oak Ridge National Laboratory
+
+    This file is part of Mantid.
+
+    Mantid is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 3 of the License, or
+    (at your option) any later version.
+
+    Mantid is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+    File change history is stored at: <https://svn.mantidproject.org/mantid/trunk/Code/Mantid>
+    Code Documentation is available at: <http://doxygen.mantidproject.org>
+  */
+  class DLLExport LeBailFit2 : public API::Algorithm
+  {
+  public:
+    LeBailFit2();
+    virtual ~LeBailFit2();
+
+    /// Algorithm's name for identification overriding a virtual method
+    virtual const std::string name() const { return "LeBailFit";}
+    /// Algorithm's version for identification overriding a virtual method
+    virtual int version() const { return 2;}
+    /// Algorithm's category for identification overriding a virtual method
+    virtual const std::string category() const { return "Diffraction";}
+
+  private:
+    /// Sets documentation strings for this algorithm
+    virtual void initDocs();
+    // Implement abstract Algorithm methods
+    void init();
+    // Implement abstract Algorithm methods
+    void exec();
+
+    /// Import peak parameters
+    void importParametersTable();
+    /// Import Miller Indices (HKL)
+    void importReflections();
+
+    /// Create a list of peaks
+    void generatePeaksFromInput();
+
+
+    API::MatrixWorkspace_sptr dataWS;
+    DataObjects::TableWorkspace_sptr parameterWS;
+    DataObjects::TableWorkspace_sptr reflectionWS;
+
+    std::vector<std::vector<int> > mPeakHKLs;
+    API::CompositeFunction_sptr mLeBailFunction;
+
+    std::map<std::string, std::pair<double, char> > mFuncParameters; // char = f: fit... = t: tie to value
+
+    std::vector<CurveFitting::ThermalNeutronBk2BkExpConvPV_sptr> mPeaks;
+    
+  };
+
+
+} // namespace CurveFitting
+} // namespace Mantid
+
+#endif  /* MANTID_CURVEFITTING_LEBAILFIT2_H_ */
diff --git a/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/ThermalNeutronBk2BkExpConvPV.h b/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/ThermalNeutronBk2BkExpConvPV.h
index a6ca9ddf5bb..20c63d6e396 100644
--- a/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/ThermalNeutronBk2BkExpConvPV.h
+++ b/Code/Mantid/Framework/CurveFitting/inc/MantidCurveFitting/ThermalNeutronBk2BkExpConvPV.h
@@ -51,7 +51,7 @@ class DLLExport ThermalNeutronBk2BkExpConvPV : virtual public API::IPeakFunction
     virtual void setHeight(const double h);
 
     /// overwrite IFunction base class methods
-    std::string name()const{return "Bk2BkExpConvPV";}
+    std::string name()const{return "ThermalNeutronBk2BkExpConvPV";}
     virtual const std::string category() const { return "Peak";}
 
     /// Set up the range of peak calculation for higher efficiency
@@ -106,6 +106,8 @@ class DLLExport ThermalNeutronBk2BkExpConvPV : virtual public API::IPeakFunction
     
 };
 
+/// Shared pointer to ThermalNeutronBk2BkExpConvPV peak/function
+typedef boost::shared_ptr<ThermalNeutronBk2BkExpConvPV> ThermalNeutronBk2BkExpConvPV_sptr;
 
 } // namespace CurveFitting
 } // namespace Mantid
diff --git a/Code/Mantid/Framework/CurveFitting/src/LeBailFit2.cpp b/Code/Mantid/Framework/CurveFitting/src/LeBailFit2.cpp
new file mode 100644
index 00000000000..e49908358c2
--- /dev/null
+++ b/Code/Mantid/Framework/CurveFitting/src/LeBailFit2.cpp
@@ -0,0 +1,269 @@
+#include "MantidCurveFitting/LeBailFit2.h"
+#include "MantidKernel/ListValidator.h"
+#include "MantidAPI/TableRow.h"
+
+namespace Mantid
+{
+namespace CurveFitting
+{
+
+DECLARE_ALGORITHM(LeBailFit2)
+
+//----------------------------------------------------------------------------------------------
+/** Constructor
+ */
+LeBailFit2::LeBailFit2()
+{
+}
+    
+//----------------------------------------------------------------------------------------------
+/** Destructor
+ */
+LeBailFit2::~LeBailFit2()
+{
+}
+  
+/*
+ * Sets documentation strings for this algorithm
+ */
+void LeBailFit2::initDocs()
+{
+    this->setWikiSummary("Do LeBail Fit to a spectrum of powder diffraction data.. ");
+    this->setOptionalMessage("Do LeBail Fit to a spectrum of powder diffraction data. ");
+}
+
+/*
+ * Define the input properties for this algorithm
+ */
+void LeBailFit2::init()
+{
+  this->declareProperty(new API::WorkspaceProperty<API::MatrixWorkspace>("InputWorkspace", "", Direction::Input),
+      "Input workspace containing the data to fit by LeBail algorithm.");
+  this->declareProperty(new API::WorkspaceProperty<DataObjects::TableWorkspace>("ParametersWorkspace", "", Direction::InOut),
+      "Input table workspace containing the parameters required by LeBail fit. ");
+  this->declareProperty(new API::WorkspaceProperty<DataObjects::TableWorkspace>("ReflectionsWorkspace", "", Direction::InOut),
+      "Input table workspace containing the list of reflections (HKL). ");
+  this->declareProperty("WorkspaceIndex", 0, "Workspace index of the spectrum to fit by LeBail.");
+
+  std::vector<std::string> functions;
+  functions.push_back("LeBailFit");
+  functions.push_back("Calculation");
+  functions.push_back("AutoSelectBackgroundPoints");
+  auto validator = boost::make_shared<Kernel::StringListValidator>(functions);
+  this->declareProperty("Function", "LeBailFit", validator, "Functionality");
+
+  this->declareProperty(new API::WorkspaceProperty<DataObjects::Workspace2D>("OutputWorkspace", "", Direction::Output),
+                        "Output workspace containing calculated pattern or calculated background. ");
+
+  return;
+}
+
+/*
+ * Implement abstract Algorithm methods
+ */
+void LeBailFit2::exec()
+{
+    // 1. Get input
+    dataWS = this->getProperty("InputWorkspace");
+    parameterWS = this->getProperty("ParametersWorkspace");
+    reflectionWS = this->getProperty("ReflectionsWorkspace");
+
+    int tempindex = this->getProperty("WorkspaceIndex");
+    if (tempindex < 0)
+        throw std::invalid_argument("Input workspace index cannot be negative.");
+    size_t workspaceindex = size_t(tempindex);
+
+    // 2. Determine Function
+    std::string function = this->getProperty("Function");
+    int functionmode = 0; // calculation
+    if (function.compare("Calculation") == 0)
+    {
+        // peak calculation
+        functionmode = 1;
+    }
+    else if (function.compare("AutoSelectBackgroundPoints") == 0)
+    {
+        // automatic background points selection
+        functionmode = 2;
+    }
+
+    // 3. Check and/or process inputs
+    if (workspaceindex >= dataWS->getNumberHistograms())
+    {
+        g_log.error() << "Input WorkspaceIndex " << workspaceindex << " is out of boundary [0, " <<
+                         dataWS->getNumberHistograms() << ")" << std::endl;
+        throw std::invalid_argument("Invalid input workspace index. ");
+    }
+
+    this->importParametersTable();
+    this->importReflections();
+
+    // 3. Create LeBail Function & initialize from input
+    generatePeaksFromInput();
+
+    // 4. Create CompositeFunction
+    API::CompositeFunction compfunction;
+    mLeBailFunction = boost::make_shared<API::CompositeFunction>(compfunction);
+
+    for (size_t ipk = 0; ipk < mPeaks.size(); ++ipk)
+    {
+        mLeBailFunction->addFunction(mPeaks[ipk]);
+    }
+    std::cout << "LeBail Composite Function: " << mLeBailFunction->asString() << std::endl;
+
+    // 5. Create output workspace
+    size_t nspec = 1;
+    size_t nbin = dataWS->dataX(workspaceindex).size();
+    DataObjects::Workspace2D_sptr outws =
+        boost::dynamic_pointer_cast<DataObjects::Workspace2D>(API::WorkspaceFactory::Instance().create("Workspace2D", nspec, nbin, nbin));
+    for (size_t i = 0; i < nbin; ++i)
+    {
+      outws->dataX(0)[i] = dataWS->readX(workspaceindex)[i];
+      outws->dataY(0)[i] = dataWS->readY(workspaceindex)[i];
+    }
+    outws->getAxis(0)->setUnit("TOF");
+
+    this->setProperty("OutputWorkspace", outws);
+
+    // 6. Real work
+    switch (functionmode)
+    {
+    case 0:
+        // LeBail Fit
+        g_log.notice() << "Do LeBail Fit." << std::endl;
+        g_log.error() << "To be implemented soon!" << std::endl;
+        break;
+
+    case 1:
+        // Calculation
+        g_log.notice() << "Pattern Calculation. It is not FINISHED yet. " << std::endl;
+        g_log.error() << "To be implemented soon!" << std::endl;
+        break;
+
+    case 2:
+        // Background
+        g_log.notice() << "Automatic background background selection. " << std::endl;
+        g_log.error() << "To be implemented soon!" << std::endl;
+        break;
+
+    default:
+        // Impossible
+        g_log.warning() << "FunctionMode = " << functionmode <<".  It is not possible" << std::endl;
+        break;
+    }
+
+  return;
+}
+
+/*
+ * Generate a list of peaks from input
+ */
+void LeBailFit2::generatePeaksFromInput()
+{
+    for (size_t ipk = 0; ipk < mPeakHKLs.size(); ++ipk)
+    {
+        CurveFitting::ThermalNeutronBk2BkExpConvPV tmppeak;
+        int h = mPeakHKLs[ipk][0];
+        int k = mPeakHKLs[ipk][1];
+        int l = mPeakHKLs[ipk][2];
+        tmppeak.setMillerIndex(h, k, l);
+        CurveFitting::ThermalNeutronBk2BkExpConvPV_sptr speak = boost::make_shared<CurveFitting::ThermalNeutronBk2BkExpConvPV>(tmppeak);
+
+        mPeaks.push_back(speak);
+    }
+
+    return;
+}
+
+/*
+ * Parse the input TableWorkspace to some maps for easy access
+ */
+void LeBailFit2::importParametersTable()
+{
+  // 1. Check column orders
+  std::vector<std::string> colnames = parameterWS->getColumnNames();
+  if (colnames.size() < 3)
+  {
+    g_log.error() << "Input parameter table workspace does not have enough number of columns. "
+        << " Number of columns = " << colnames.size() << " < 3 as required. " << std::endl;
+    throw std::runtime_error("Input parameter workspace is wrong. ");
+  }
+  if (colnames[0].compare("Name") != 0 ||
+      colnames[1].compare("Value") != 0 ||
+      colnames[2].compare("FitOrTie") != 0)
+  {
+    g_log.error() << "Input parameter table workspace does not have the columns in order.  "
+        << " It must be Name, Value, FitOrTie." << std::endl;
+    throw std::runtime_error("Input parameter workspace is wrong. ");
+  }
+
+  // 2. Import data to maps
+  std::string parname, fitortie;
+  double value;
+
+  size_t numrows = parameterWS->rowCount();
+
+  for (size_t ir = 0; ir < numrows; ++ir)
+  {
+    API::TableRow trow = parameterWS->getRow(ir);
+    trow >> parname >> value >> fitortie;
+    // fit or tie?
+    char tofit = 'f';
+    if (fitortie.length() > 0)
+    {
+      char fc = fitortie.c_str()[0];
+      if (fc == 't' || fc == 'T')
+      {
+        tofit = 't';
+      }
+    }
+    mFuncParameters.insert(std::make_pair(parname, std::make_pair(value, tofit)));
+  }
+
+  return;
+}
+
+/*
+ * Parse the reflections workspace to a list of reflections;
+ */
+void LeBailFit2::importReflections()
+{
+  // 1. Check column orders
+  std::vector<std::string> colnames = reflectionWS->getColumnNames();
+  if (colnames.size() < 3)
+  {
+    g_log.error() << "Input parameter table workspace does not have enough number of columns. "
+        << " Number of columns = " << colnames.size() << " < 3 as required. " << std::endl;
+    throw std::runtime_error("Input parameter workspace is wrong. ");
+  }
+  if (colnames[0].compare("H") != 0 ||
+      colnames[1].compare("K") != 0 ||
+      colnames[2].compare("L") != 0)
+  {
+    g_log.error() << "Input parameter table workspace does not have the columns in order.  "
+        << " It must be H, K, L." << std::endl;
+    throw std::runtime_error("Input parameter workspace is wrong. ");
+  }
+
+  // 2. Import data to maps
+  int h, k, l;
+
+  size_t numrows = reflectionWS->rowCount();
+  for (size_t ir = 0; ir < numrows; ++ir)
+  {
+    API::TableRow trow = reflectionWS->getRow(ir);
+    trow >> h >> k >> l;
+    std::vector<int> hkl;
+    hkl.push_back(h);
+    hkl.push_back(k);
+    hkl.push_back(l);
+
+    mPeakHKLs.push_back(hkl);
+  }
+
+  return;
+}
+
+
+} // namespace CurveFitting
+} // namespace Mantid
diff --git a/Code/Mantid/Framework/CurveFitting/test/LeBailFit2Test.h b/Code/Mantid/Framework/CurveFitting/test/LeBailFit2Test.h
new file mode 100644
index 00000000000..067f0e084bb
--- /dev/null
+++ b/Code/Mantid/Framework/CurveFitting/test/LeBailFit2Test.h
@@ -0,0 +1,343 @@
+#ifndef MANTID_CURVEFITTING_LEBAILFIT2TEST_H_
+#define MANTID_CURVEFITTING_LEBAILFIT2TEST_H_
+
+#include <cxxtest/TestSuite.h>
+#include "MantidKernel/Timer.h"
+#include "MantidKernel/System.h"
+#include <iostream>
+#include <iomanip>
+
+#include "MantidTestHelpers/WorkspaceCreationHelper.h"
+#include "MantidAPI/TableRow.h"
+#include "MantidAPI/WorkspaceFactory.h"
+
+#include "MantidCurveFitting/LeBailFit2.h"
+
+using namespace Mantid;
+using namespace Mantid::CurveFitting;
+using namespace Mantid::API;
+using namespace WorkspaceCreationHelper;
+
+using Mantid::CurveFitting::LeBailFit2;
+
+class LeBailFit2Test : 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 LeBailFit2Test *createSuite() { return new LeBailFit2Test(); }
+  static void destroySuite( LeBailFit2Test *suite ) { delete suite; }
+
+  /*
+   * Fundamental test to calcualte 2 peak w/o background
+   */
+  void test_cal2Peaks()
+  {
+      // 1. Create input workspace
+      API::MatrixWorkspace_sptr dataws;
+      DataObjects::TableWorkspace_sptr parameterws;
+      DataObjects::TableWorkspace_sptr hklws;
+
+      dataws = createInputDataWorkspace();
+      parameterws = createPeakParameterWorkspace();
+      hklws = createReflectionWorkspace();
+
+      AnalysisDataService::Instance().addOrReplace("Data", dataws);
+      AnalysisDataService::Instance().addOrReplace("PeakParameters", parameterws);
+      AnalysisDataService::Instance().addOrReplace("Reflections", hklws);
+
+      // 2. Initialize the algorithm
+      LeBailFit2 lbfit;
+
+      TS_ASSERT_THROWS_NOTHING(lbfit.initialize());
+      TS_ASSERT(lbfit.isInitialized());
+
+      // 3. Set properties
+      lbfit.setPropertyValue("InputWorkspace", "Data");
+      lbfit.setPropertyValue("ParametersWorkspace", "PeakParameters");
+      lbfit.setPropertyValue("ReflectionsWorkspace", "Reflections");
+      lbfit.setProperty("WorkspaceIndex", 0);
+      lbfit.setProperty("OutputWorkspace", "CalculatedPeaks");
+
+      // 4. Execute
+      TS_ASSERT_THROWS_NOTHING(lbfit.execute());
+
+      TS_ASSERT(lbfit.isExecuted());
+  }
+
+  /*
+   * Create parameter workspace for peak calculation
+   */
+  DataObjects::TableWorkspace_sptr createPeakParameterWorkspace()
+  {
+    DataObjects::TableWorkspace *tablews;
+
+    tablews = new DataObjects::TableWorkspace();
+    DataObjects::TableWorkspace_sptr parameterws(tablews);
+
+    tablews->addColumn("str", "Name");
+    tablews->addColumn("double", "Value");
+    tablews->addColumn("str", "FitOrTie");
+
+    API::TableRow newparam = parameterws->appendRow();
+    newparam << "Dtt1"  << 29671.7500 << "t";
+    newparam = parameterws->appendRow();
+    newparam << "Dtt2"  << 0.0 << "t";
+    newparam = parameterws->appendRow();
+    newparam << "Dtt1t" << 29671.750 << "t";
+    newparam = parameterws->appendRow();
+    newparam << "Dtt2t" << 0.30 << "t";
+    newparam = parameterws->appendRow();
+    newparam << "Zero"  << 0.0 << "f";
+    // newparam << "Zero"  << 50.0 << "f";
+    newparam = parameterws->appendRow();
+    newparam << "Zerot" << 33.70 << "t";
+    newparam = parameterws->appendRow();
+    newparam << "Alph0" << 4.026 << "t";
+    newparam = parameterws->appendRow();
+    newparam << "Alph1" << 7.362 << "t";
+    newparam = parameterws->appendRow();
+    newparam << "Beta0" << 3.489 << "t";
+    newparam = parameterws->appendRow();
+    newparam << "Beta1" << 19.535 << "t";
+    newparam = parameterws->appendRow();
+    newparam << "Alph0t"<< 60.683 << "t";
+    newparam = parameterws->appendRow();
+    newparam << "Alph1t"<< 39.730 << "t";
+    newparam = parameterws->appendRow();
+    newparam << "Beta0t"<< 96.864 << "t";
+    newparam = parameterws->appendRow();
+    newparam << "Beta1t"<< 96.864 << "t";
+    newparam = parameterws->appendRow();
+    newparam << "Sig2"  <<  11.380 << "t";
+    newparam = parameterws->appendRow();
+    newparam << "Sig1"  <<   9.901 << "t";
+    newparam = parameterws->appendRow();
+    newparam << "Sig0"  <<  17.370 << "t";
+    newparam = parameterws->appendRow();
+    newparam << "Width" << 1.0055 << "t";
+    newparam = parameterws->appendRow();
+    newparam << "Tcross"<< 0.4700 << "t";
+    newparam = parameterws->appendRow();
+    newparam << "Gam0"  << 0.0 << "t";
+    newparam = parameterws->appendRow();
+    newparam << "Gam1"  << 0.0 << "t";
+    newparam = parameterws->appendRow();
+    newparam << "Gam2"  << 0.0 << "t";
+    newparam = parameterws->appendRow();
+    newparam << "LatticeConstant" << 4.156890 << "t";
+
+    return parameterws;
+  }
+
+
+  /*
+   * Create reflection table workspaces
+   */
+  DataObjects::TableWorkspace_sptr createReflectionWorkspace()
+  {
+    DataObjects::TableWorkspace* tablews = new DataObjects::TableWorkspace();
+    DataObjects::TableWorkspace_sptr hklws = DataObjects::TableWorkspace_sptr(tablews);
+
+    tablews->addColumn("int", "H");
+    tablews->addColumn("int", "K");
+    tablews->addColumn("int", "L");
+
+    // a) Add reflection (111) and (110)
+    API::TableRow hkl = hklws->appendRow();
+    hkl << 1 << 1 << 0;
+    hkl = hklws->appendRow();
+    hkl << 1 << 1 << 1;
+
+    return hklws;
+  }
+
+  /*
+   * Create data workspace without background
+   */
+  API::MatrixWorkspace_sptr createInputDataWorkspace()
+  {
+    // 1. Import data
+    std::vector<double> vecX;
+    std::vector<double> vecY;
+    std::vector<double> vecE;
+    /*
+    std::string filename("/home/wzz/Mantid/mantid/Code/release/LB4917b1_unittest.dat");
+    importDataFromColumnFile(filename, vecX, vecY,  vecE);
+    */
+    generateData(vecX, vecY, vecE);
+
+    // 2. Get workspace
+    int64_t nHist = 1;
+    int64_t nBins = vecX.size();
+    std::set<int64_t> maskedWSIndices;
+
+    API::MatrixWorkspace_sptr dataws =
+        boost::dynamic_pointer_cast<API::MatrixWorkspace>(
+            API::WorkspaceFactory::Instance().create("Workspace2D", nHist, nBins, nBins));
+
+
+    // Mantid::DataObjects::Workspace2D_sptr  Create2DWorkspace(int nHist, int nBins);
+    // API::MatrixWorkspace_sptr dataws = boost::dynamic_pointer_cast<API::MatrixWorkspace>(Create2DWorkspaceWithValues(
+    // nHist, nBins, isHist, maskedWSIndices, xvalue, yvalue, evalue));
+
+    // 3. Input data
+    for (size_t i = 0; i < vecX.size(); ++i)
+    {
+      dataws->dataX(0)[i] = vecX[i];
+      dataws->dataY(0)[i] = vecY[i];
+      dataws->dataE(0)[i] = vecE[i];
+    }
+
+    return dataws;
+  }
+
+  /*
+   * Generate a set of powder diffraction data with 2 peaks w/o background
+   */
+  void generateData(std::vector<double>& vecX, std::vector<double>& vecY, std::vector<double>& vecE)
+  {
+    vecX.push_back(70931.750);    vecY.push_back(    0.0000000    );
+    vecX.push_back(70943.609);    vecY.push_back(    0.0000000    );
+    vecX.push_back(70955.477);    vecY.push_back(   0.69562334    );
+    vecX.push_back(70967.336);    vecY.push_back(   0.99016321    );
+    vecX.push_back(70979.203);    vecY.push_back(    1.4097446    );
+    vecX.push_back(70991.063);    vecY.push_back(    2.0066566    );
+    vecX.push_back(71002.930);    vecY.push_back(    2.8569770    );
+    vecX.push_back(71014.789);    vecY.push_back(    4.0666742    );
+    vecX.push_back(71026.656);    vecY.push_back(    5.7899261    );
+    vecX.push_back(71038.516);    vecY.push_back(    8.2414885    );
+    vecX.push_back(71050.383);    vecY.push_back(    11.733817    );
+    vecX.push_back(71062.242);    vecY.push_back(    16.702133    );
+    vecX.push_back(71074.109);    vecY.push_back(    23.779659    );
+    vecX.push_back(71085.969);    vecY.push_back(    33.848408    );
+    vecX.push_back(71097.836);    vecY.push_back(    48.191662    );
+    vecX.push_back(71109.695);    vecY.push_back(    68.596909    );
+    vecX.push_back(71121.563);    vecY.push_back(    97.664757    );
+    vecX.push_back(71133.430);    vecY.push_back(    139.04889    );
+    vecX.push_back(71145.289);    vecY.push_back(    197.90808    );
+    vecX.push_back(71157.156);    vecY.push_back(    281.60803    );
+    vecX.push_back(71169.016);    vecY.push_back(    399.65021    );
+    vecX.push_back(71180.883);    vecY.push_back(    562.42670    );
+    vecX.push_back(71192.742);    vecY.push_back(    773.34192    );
+    vecX.push_back(71204.609);    vecY.push_back(    1015.2813    );
+    vecX.push_back(71216.469);    vecY.push_back(    1238.3613    );
+    vecX.push_back(71228.336);    vecY.push_back(    1374.9380    );
+    vecX.push_back(71240.195);    vecY.push_back(    1380.5173    );
+    vecX.push_back(71252.063);    vecY.push_back(    1266.3978    );
+    vecX.push_back(71263.922);    vecY.push_back(    1086.2141    );
+    vecX.push_back(71275.789);    vecY.push_back(    894.75891    );
+    vecX.push_back(71287.648);    vecY.push_back(    723.46112    );
+    vecX.push_back(71299.516);    vecY.push_back(    581.04535    );
+    vecX.push_back(71311.375);    vecY.push_back(    465.93588    );
+    vecX.push_back(71323.242);    vecY.push_back(    373.45383    );
+    vecX.push_back(71335.102);    vecY.push_back(    299.35800    );
+    vecX.push_back(71346.969);    vecY.push_back(    239.92720    );
+    vecX.push_back(71358.836);    vecY.push_back(    192.29497    );
+    vecX.push_back(71370.695);    vecY.push_back(    154.14153    );
+    vecX.push_back(71382.563);    vecY.push_back(    123.54013    );
+    vecX.push_back(71394.422);    vecY.push_back(    99.028404    );
+    vecX.push_back(71406.289);    vecY.push_back(    79.368507    );
+    vecX.push_back(71418.148);    vecY.push_back(    63.620914    );
+    vecX.push_back(71430.016);    vecY.push_back(    50.990391    );
+    vecX.push_back(71441.875);    vecY.push_back(    40.873333    );
+    vecX.push_back(71453.742);    vecY.push_back(    32.758839    );
+    vecX.push_back(71465.602);    vecY.push_back(    26.259121    );
+    vecX.push_back(71477.469);    vecY.push_back(    21.045954    );
+    vecX.push_back(71489.328);    vecY.push_back(    16.870203    );
+    vecX.push_back(71501.195);    vecY.push_back(    13.520998    );
+    vecX.push_back(71513.055);    vecY.push_back(    10.838282    );
+    vecX.push_back(71524.922);    vecY.push_back(    8.6865807    );
+    vecX.push_back(71536.781);    vecY.push_back(    6.9630671    );
+    vecX.push_back(71548.648);    vecY.push_back(    5.5807042    );
+    vecX.push_back(71560.508);    vecY.push_back(    4.4734306    );
+    vecX.push_back(71572.375);    vecY.push_back(    3.5853302    );
+    vecX.push_back(71584.242);    vecY.push_back(    2.8735423    );
+    vecX.push_back(71596.102);    vecY.push_back(    2.3033996    );
+    vecX.push_back(71607.969);    vecY.push_back(    1.8461106    );
+    vecX.push_back(71619.828);    vecY.push_back(    0.0000000    );
+    vecX.push_back(86911.852);    vecY.push_back(   0.28651541    );
+    vecX.push_back(86923.719);    vecY.push_back(   0.39156997    );
+    vecX.push_back(86935.578);    vecY.push_back(   0.53503412    );
+    vecX.push_back(86947.445);    vecY.push_back(   0.73121130    );
+    vecX.push_back(86959.305);    vecY.push_back(   0.99911392    );
+    vecX.push_back(86971.172);    vecY.push_back(    1.3654519    );
+    vecX.push_back(86983.039);    vecY.push_back(    1.8661126    );
+    vecX.push_back(86994.898);    vecY.push_back(    2.5498226    );
+    vecX.push_back(87006.766);    vecY.push_back(    3.4847479    );
+    vecX.push_back(87018.625);    vecY.push_back(    4.7614965    );
+    vecX.push_back(87030.492);    vecY.push_back(    6.5073609    );
+    vecX.push_back(87042.352);    vecY.push_back(    8.8915405    );
+    vecX.push_back(87054.219);    vecY.push_back(    12.151738    );
+    vecX.push_back(87066.078);    vecY.push_back(    16.603910    );
+    vecX.push_back(87077.945);    vecY.push_back(    22.691912    );
+    vecX.push_back(87089.805);    vecY.push_back(    31.005537    );
+    vecX.push_back(87101.672);    vecY.push_back(    42.372311    );
+    vecX.push_back(87113.531);    vecY.push_back(    57.886639    );
+    vecX.push_back(87125.398);    vecY.push_back(    79.062233    );
+    vecX.push_back(87137.258);    vecY.push_back(    107.82082    );
+    vecX.push_back(87149.125);    vecY.push_back(    146.58661    );
+    vecX.push_back(87160.984);    vecY.push_back(    197.83006    );
+    vecX.push_back(87172.852);    vecY.push_back(    263.46185    );
+    vecX.push_back(87184.711);    vecY.push_back(    343.08966    );
+    vecX.push_back(87196.578);    vecY.push_back(    432.57846    );
+    vecX.push_back(87208.445);    vecY.push_back(    522.64124    );
+    vecX.push_back(87220.305);    vecY.push_back(    600.01373    );
+    vecX.push_back(87232.172);    vecY.push_back(    651.22260    );
+    vecX.push_back(87244.031);    vecY.push_back(    667.17743    );
+    vecX.push_back(87255.898);    vecY.push_back(    646.90039    );
+    vecX.push_back(87267.758);    vecY.push_back(    597.38873    );
+    vecX.push_back(87279.625);    vecY.push_back(    530.12573    );
+    vecX.push_back(87291.484);    vecY.push_back(    456.83890    );
+    vecX.push_back(87303.352);    vecY.push_back(    386.05295    );
+    vecX.push_back(87315.211);    vecY.push_back(    322.58456    );
+    vecX.push_back(87327.078);    vecY.push_back(    267.96231    );
+    vecX.push_back(87338.938);    vecY.push_back(    222.04863    );
+    vecX.push_back(87350.805);    vecY.push_back(    183.80043    );
+    vecX.push_back(87362.664);    vecY.push_back(    152.11101    );
+    vecX.push_back(87374.531);    vecY.push_back(    125.85820    );
+    vecX.push_back(87386.391);    vecY.push_back(    104.14707    );
+    vecX.push_back(87398.258);    vecY.push_back(    86.170067    );
+    vecX.push_back(87410.117);    vecY.push_back(    71.304932    );
+    vecX.push_back(87421.984);    vecY.push_back(    58.996807    );
+    vecX.push_back(87433.844);    vecY.push_back(    48.819309    );
+    vecX.push_back(87445.711);    vecY.push_back(    40.392483    );
+    vecX.push_back(87457.578);    vecY.push_back(    33.420235    );
+    vecX.push_back(87469.438);    vecY.push_back(    27.654932    );
+    vecX.push_back(87481.305);    vecY.push_back(    22.881344    );
+    vecX.push_back(87493.164);    vecY.push_back(    18.934097    );
+    vecX.push_back(87505.031);    vecY.push_back(    15.665835    );
+    vecX.push_back(87516.891);    vecY.push_back(    12.963332    );
+    vecX.push_back(87528.758);    vecY.push_back(    10.725698    );
+    vecX.push_back(87540.617);    vecY.push_back(    8.8754158    );
+    vecX.push_back(87552.484);    vecY.push_back(    7.3434072    );
+    vecX.push_back(87564.344);    vecY.push_back(    6.0766010    );
+    vecX.push_back(87576.211);    vecY.push_back(    5.0277033    );
+    vecX.push_back(87588.070);    vecY.push_back(    4.1603775    );
+    vecX.push_back(87599.938);    vecY.push_back(    3.4422443    );
+    vecX.push_back(87611.797);    vecY.push_back(    2.8484249    );
+    vecX.push_back(87623.664);    vecY.push_back(    2.3567512    );
+    vecX.push_back(87635.523);    vecY.push_back(    1.9501896    );
+    vecX.push_back(87647.391);    vecY.push_back(    1.6135623    );
+    vecX.push_back(87659.250);    vecY.push_back(    1.3352078    );
+    vecX.push_back(87671.117);    vecY.push_back(    1.1047342    );
+    vecX.push_back(87682.984);    vecY.push_back(   0.91404319    );
+    vecX.push_back(87694.844);    vecY.push_back(   0.75636220    );
+    vecX.push_back(87706.711);    vecY.push_back(    0.0000000    );
+
+    for (size_t i = 0; i < vecY.size(); ++i)
+    {
+      double e = 1.0;
+      if (vecY[i] > 1.0)
+        e = sqrt(vecY[i]);
+      vecE.push_back(e);
+    }
+
+    return;
+  }
+
+
+};
+
+
+#endif /* MANTID_CURVEFITTING_LEBAILFIT2TEST_H_ */
-- 
GitLab