From 1ebe98564932599978e6965fb80fb5fbf1d42ef1 Mon Sep 17 00:00:00 2001
From: Ricardo Leal <ricardo.leal@ill.fr>
Date: Fri, 22 Nov 2013 11:06:24 +0100
Subject: [PATCH] Re #8365 Move instrument is not working yet

---
 .../inc/MantidDataHandling/LoadILLAscii.h     |   2 +
 .../MantidDataHandling/LoadILLAsciiHelper.h   |   3 +-
 .../DataHandling/src/LoadILLAscii.cpp         | 128 ++++++++++++------
 .../DataHandling/src/LoadILLAsciiHelper.cpp   |  54 ++++++--
 .../DataHandling/test/LoadILLAsciiTest.h      |   4 +-
 Code/Mantid/instrument/D2B_Definition.xml     |   4 +-
 6 files changed, 139 insertions(+), 56 deletions(-)

diff --git a/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadILLAscii.h b/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadILLAscii.h
index 014dc356d39..1a9475a0451 100644
--- a/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadILLAscii.h
+++ b/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadILLAscii.h
@@ -56,6 +56,8 @@ private:
 	void loadInstrumentName(ILLParser &);
 	void loadInstrumentDetails(ILLParser &p);
 	void loadIDF(API::MatrixWorkspace_sptr &workspace);
+	void loadsDataIntoTheWS(API::MatrixWorkspace_sptr &, const std::vector<int> &);
+	void moveDetector(API::MatrixWorkspace_sptr &, double angle);
 	//LoadHelper m_loader;
 	std::string m_instrumentName; ///< Name of the instrument
 	double m_wavelength;
diff --git a/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadILLAsciiHelper.h b/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadILLAsciiHelper.h
index 0f4d162c39a..6c07e7a4571 100644
--- a/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadILLAsciiHelper.h
+++ b/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadILLAsciiHelper.h
@@ -47,7 +47,8 @@ public:
 	std::string getInstrumentName();
 	std::vector< std::vector<int> > getSpectraList() const {return spectraList;}
 	std::vector<std::map<std::string, std::string> > getSpectraHeaderList() const {return spectraHeaders;}
-	template<typename T> T getValueFromHeader(const std::string &field);
+	template<typename T> T getValueFromHeader(const std::string &);
+	template<typename T> T getValue(const std::string &, const std::map<std::string, std::string> &);
 private:
 	void parseFieldR();
 	void parseFieldA();
diff --git a/Code/Mantid/Framework/DataHandling/src/LoadILLAscii.cpp b/Code/Mantid/Framework/DataHandling/src/LoadILLAscii.cpp
index f905bed9ee3..d65e988fc04 100644
--- a/Code/Mantid/Framework/DataHandling/src/LoadILLAscii.cpp
+++ b/Code/Mantid/Framework/DataHandling/src/LoadILLAscii.cpp
@@ -9,9 +9,11 @@
 
 #include "MantidDataHandling/LoadILLAscii.h"
 #include "MantidAPI/FileProperty.h"
+#include "MantidGeometry/Instrument/ComponentHelper.h"
 #include "MantidAPI/RegisterFileLoader.h"
 #include "MantidDataHandling/LoadILLAsciiHelper.h"
 #include "MantidKernel/UnitFactory.h"
+#include "MantidKernel/System.h"
 
 #include <algorithm>
 
@@ -20,7 +22,6 @@ namespace DataHandling {
 
 using namespace Kernel;
 using namespace API;
-using namespace Mantid::Kernel;
 
 // Register the algorithm into the AlgorithmFactory
 DECLARE_FILELOADER_ALGORITHM(LoadILLAscii)
@@ -97,8 +98,9 @@ void LoadILLAscii::initDocs() {
 void LoadILLAscii::init() {
 	declareProperty(new FileProperty("Filename", "", FileProperty::Load, ""),
 			"Name of the data file to load.");
-	declareProperty("OutputWorkspacePrefix", "",
-			"Prefix for the workspaces created by the moving instrument.");
+	declareProperty(
+	        new WorkspaceProperty<>("OutputWorkspace", "", Direction::Output),
+	        "Name to use for the output workspace");
 
 }
 
@@ -108,76 +110,64 @@ void LoadILLAscii::init() {
 void LoadILLAscii::exec() {
 	// Init
 	std::string filename = getPropertyValue("Filename");
-	std::string prefix = getPropertyValue("OutputWorkspacePrefix");
-
 	ILLParser p(filename);
 	loadInstrumentName(p);
 	p.parse();
 	loadInstrumentDetails(p);
 
+	// get local references to the parsed file
 	const std::vector<std::vector<int> > &spectraList = p.getSpectraList();
 	const std::vector<std::map<std::string, std::string> > &spectraHeaderList =
 			p.getSpectraHeaderList();
 
+	std::vector<API::MatrixWorkspace_sptr> workspaceList;
+	workspaceList.reserve(spectraList.size());
+
+	// iterate parsed file
 	std::vector<std::vector<int> >::const_iterator iSpectra;
 	std::vector<std::map<std::string, std::string> >::const_iterator iSpectraHeader;
 
 	Progress progress(this, 0, 1, spectraList.size());
-	for (iSpectra = spectraList.begin(), iSpectraHeader =
-			spectraHeaderList.begin();
-			iSpectra < spectraList.end()
-					&& iSpectraHeader < spectraHeaderList.end();
+	for (iSpectra = spectraList.begin(), iSpectraHeader =spectraHeaderList.begin();
+			iSpectra < spectraList.end() && iSpectraHeader < spectraHeaderList.end();
 			++iSpectra, ++iSpectraHeader) {
 
-		g_log.debug() << "Reading sprectra: " << std::distance(spectraList.begin(),iSpectra) << std::endl;
+		g_log.debug() << "Reading Spectrum: " << std::distance(spectraList.begin(),iSpectra) << std::endl;
 
 		std::vector<int> thisSpectrum = *iSpectra;
 		API::MatrixWorkspace_sptr thisWorkspace = WorkspaceFactory::Instance().create("Workspace2D", thisSpectrum.size(),
 				2, 1);
-		g_log.debug() << "2" << std::endl;
+
 		thisWorkspace->getAxis(0)->unit() = UnitFactory::Instance().create(
 				"Wavelength");
-		g_log.debug() << "3" << std::endl;
-
 		thisWorkspace->setYUnitLabel("Counts");
 		loadIDF(thisWorkspace);
-		// todo : need to mobe instrument
-
+		// todo : need to move instrument
 
+		double currentPositionAngle = p.getValue<double>("angles*1000", *iSpectraHeader) / 1000;
+		moveDetector(thisWorkspace, currentPositionAngle);
 
-		thisWorkspace->dataX(0)[0] = m_wavelength - 0.001;
-		thisWorkspace->dataX(0)[1] = m_wavelength + 0.001;
 
+		//
+		loadsDataIntoTheWS(thisWorkspace,thisSpectrum);
+		loadIDF(thisWorkspace); // assigns data to the instrument
 
+		workspaceList.push_back(thisWorkspace);
 
-
-		size_t spec = 0;
-		for (size_t i = 0; i < thisSpectrum.size(); ++i) {
-
-			if (spec > 0) {
-				// just copy the time binning axis to every spectra
-				thisWorkspace->dataX(spec) = thisWorkspace->readX(0);
-			}
-			// Assign Y
-			thisWorkspace->dataY(spec)[0] = thisSpectrum[i];
-			// Assign Error
-			thisWorkspace->dataE(spec)[0] = thisSpectrum[i] * thisSpectrum[i];
-
-			++spec;
-		}
-
-		loadIDF(thisWorkspace); // assins data to the instrument
-
-		// Set the output workspace property : concatenate prefix with spectrum number
+		// JUUST TO SEE the WS in mantiplot
 		std::stringstream outWorkspaceNameStream;
-		outWorkspaceNameStream << prefix << std::distance(spectraList.begin(),iSpectra);
-
+		outWorkspaceNameStream << "test" << std::distance(spectraList.begin(),iSpectra);
 		AnalysisDataService::Instance().addOrReplace(outWorkspaceNameStream.str(), thisWorkspace);
 
 		progress.report();
 	}
 
-	p.showHeader();
+	//p.showHeader();
+
+	// TODO: Merge workspaces
+
+	// TODO : Correct (this is like this to work!)
+	setProperty("OutputWorkspace", WorkspaceFactory::Instance().create("Workspace2D", 128,2, 1));
 
 }
 
@@ -219,5 +209,65 @@ void LoadILLAscii::loadIDF(API::MatrixWorkspace_sptr &workspace) {
 		g_log.information("Cannot load the instrument definition.");
 	}
 }
+
+/**
+ * Loads the scan into the workspace
+ */
+void LoadILLAscii::loadsDataIntoTheWS(API::MatrixWorkspace_sptr &thisWorkspace,
+		const std::vector<int> &thisSpectrum) {
+
+	thisWorkspace->dataX(0)[0] = m_wavelength - 0.001;
+	thisWorkspace->dataX(0)[1] = m_wavelength + 0.001;
+
+	size_t spec = 0;
+	for (size_t i = 0; i < thisSpectrum.size(); ++i) {
+
+		if (spec > 0) {
+			// just copy the time binning axis to every spectra
+			thisWorkspace->dataX(spec) = thisWorkspace->readX(0);
+		}
+		// Assign Y
+		thisWorkspace->dataY(spec)[0] = thisSpectrum[i];
+		// Assign Error
+		thisWorkspace->dataE(spec)[0] = thisSpectrum[i] * thisSpectrum[i];
+
+		++spec;
+	}
+
+	loadIDF(thisWorkspace); // assigns data to the instrument
+
+}
+
+/**
+ * This is not working!!!
+ *
+ * Either I have to put a location in bank_uniq to move the whole detector
+ * or have to move every tube. To be done!
+ *
+ *
+ */
+void LoadILLAscii::moveDetector(API::MatrixWorkspace_sptr &ws, double angle){
+
+	// todo: put this as a constant somewhere?
+	const std::string componentName("bank_uniq");
+
+	// current position
+	Geometry::Instrument_const_sptr instrument = ws->getInstrument();
+	Geometry::IComponent_const_sptr component = instrument->getComponentByName(componentName);
+
+	// position - set all detector distance to constant l2
+	double r, theta, phi;
+	V3D oldPos = component->getPos();
+	oldPos.getSpherical(r, theta, phi);
+
+	V3D newPos;
+	newPos.spherical(r, angle, phi);
+
+	g_log.debug() << "Theta before = " << theta << " ; after = " << angle << "\n";
+	Geometry::ParameterMap& pmap = ws->instrumentParameters();
+	Geometry::ComponentHelper::moveComponent(*component, pmap, newPos,Geometry::ComponentHelper::Absolute);
+
+}
+
 } // namespace DataHandling
 } // namespace Mantid
diff --git a/Code/Mantid/Framework/DataHandling/src/LoadILLAsciiHelper.cpp b/Code/Mantid/Framework/DataHandling/src/LoadILLAsciiHelper.cpp
index 052be19f6b9..2dfc58627e1 100644
--- a/Code/Mantid/Framework/DataHandling/src/LoadILLAsciiHelper.cpp
+++ b/Code/Mantid/Framework/DataHandling/src/LoadILLAsciiHelper.cpp
@@ -148,8 +148,12 @@ RrAadIitddddddddddddddddAatdddddddFfttttttttddddddddddddddddddddddddddIitdd etc.
 namespace Mantid {
 namespace DataHandling {
 
-ILLParser::ILLParser(const std::string &filename) {
-	fin.open(filename);
+
+/*
+ * @param filepath for the raw file
+ */
+ILLParser::ILLParser(const std::string &filepath) {
+	fin.open(filepath);
 }
 
 ILLParser::~ILLParser() {
@@ -158,8 +162,9 @@ ILLParser::~ILLParser() {
 	}
 }
 
-/**
- * Main function
+/*
+ * Main function that parses the files a fills in the lists (see private
+ * attributes of this class)
  */
 void ILLParser::parse() {
 	std::string line;
@@ -190,11 +195,16 @@ void ILLParser::parse() {
 
 /**
  * Reads the instrument name from the file
- * This should be done before parsing the file!
+ * TODO:
+ * This must be done before parsing the file, otherwise doesn't work:
+ * fin.seekg(0, std::ios::beg) ; fin.clear();
+ * If the file was already parsed, those functions don't appear to put
+ * the get stream at the beginning. Needs to be fix.
  */
 std::string ILLParser::getInstrumentName() {
 
 	if (fin.tellg() != std::ios::beg) {
+		//TODO: this doesn't seem to work.
 		fin.seekg(0, std::ios::beg);
 		fin.clear();
 		//throw std::runtime_error("Must be called before reading the file!");
@@ -213,7 +223,7 @@ std::string ILLParser::getInstrumentName() {
 		lineRead += 1;
 	}
 
-	// Point to the begining again!
+	// Point to the beginning again!
 	fin.seekg(0, std::ios::beg);
 	fin.clear();
 	return instrumentName;
@@ -288,7 +298,7 @@ void ILLParser::parseFieldNumeric(std::map<std::string, std::string> &header,
 			index += 1;
 		}
 	}
-
+	// keep the pairs key=value in the header
 	std::vector<std::string>::const_iterator iKey;
 	std::vector<std::string>::const_iterator iValue;
 	for (iKey = keys.begin(), iValue = values.begin();
@@ -301,7 +311,7 @@ void ILLParser::parseFieldNumeric(std::map<std::string, std::string> &header,
 }
 
 /**
- * Parses the spectrum
+ * Parses the field I in the spectrum block
  */
 std::vector<int> ILLParser::parseFieldISpec(int fieldWith) {
 	std::string line;
@@ -317,6 +327,7 @@ std::vector<int> ILLParser::parseFieldISpec(int fieldWith) {
 				fieldWith);
 		nSpectraRead += static_cast<int>(s.size());
 		for (auto it = s.begin(); it != s.end(); ++it) {
+			// sscanf is much faster than lexical_cast / erase_spaces
 			sscanf(it->c_str(), "%d", &spectrumValues[index]);
 			index += 1;
 		}
@@ -325,7 +336,8 @@ std::vector<int> ILLParser::parseFieldISpec(int fieldWith) {
 }
 
 /**
- * Shows contents
+ * Shows contents of the headers
+ * Just for debug purposes.
  */
 void ILLParser::showHeader() {
 	std::cout << "* Global header" << '\n';
@@ -354,6 +366,9 @@ void ILLParser::showHeader() {
 
 }
 
+/**
+ * Parses the spectrum blocks. Called after the header has been parsed.
+ */
 void ILLParser::startParseSpectra() {
 	std::string line;
 	std::getline(fin, line);
@@ -399,6 +414,9 @@ std::vector<std::string> ILLParser::splitLineInFixedWithFields(
 	return outVec;
 }
 
+/**
+ * Evaluate the input string to a type <T>
+ */
 template<typename T>
 T ILLParser::evaluate(std::string field) {
 	boost::algorithm::erase_all(field, " ");
@@ -412,9 +430,21 @@ T ILLParser::evaluate(std::string field) {
 	return value;
 }
 
+/**
+ * Gets a value from the header.
+ */
 template<typename T> T ILLParser::getValueFromHeader(const std::string &field) {
+
+	return getValue<T>(field,header);
+}
+
+/*
+ * Get value type <T> from a map<strin,string>
+ */
+template<typename T> T ILLParser::getValue(const std::string &field,
+		const std::map<std::string, std::string> &thisHeader ) {
 	T ret;
-	for (auto it = header.begin(); it != header.end(); ++it) {
+	for (auto it = thisHeader.begin(); it != thisHeader.end(); ++it) {
 		//std::cout << it->first << "=>" << it->second << '\n';
 		std::size_t pos = it->first.find(field);
 		if (pos != std::string::npos) {
@@ -430,6 +460,8 @@ template<typename T> T ILLParser::getValueFromHeader(const std::string &field) {
 } // namespace DataHandling
 }// namespace Mantid
 
-// Concrete template instantiation:The other libraries can't see the template definition so it needs to be instantiated in API
+// Concrete template instantiation
+// The other libraries can't see the template definition so it needs to be instantiated in API
 template MANTID_KERNEL_DLL double Mantid::DataHandling::ILLParser::getValueFromHeader(const std::string &);
+template MANTID_KERNEL_DLL double Mantid::DataHandling::ILLParser::getValue(const std::string &,const std::map<std::string, std::string> &);
 
diff --git a/Code/Mantid/Framework/DataHandling/test/LoadILLAsciiTest.h b/Code/Mantid/Framework/DataHandling/test/LoadILLAsciiTest.h
index 044abb852c3..ae48269b873 100644
--- a/Code/Mantid/Framework/DataHandling/test/LoadILLAsciiTest.h
+++ b/Code/Mantid/Framework/DataHandling/test/LoadILLAsciiTest.h
@@ -30,14 +30,12 @@ public:
 	}
 
 	void test_exec() {
-		// Name of the output workspace.
-		std::string outWSName("LoadILLAsciiTest_OutputWS");
 
 		LoadILLAscii alg;
 		TS_ASSERT_THROWS_NOTHING(alg.initialize())
 		TS_ASSERT(alg.isInitialized())
 		TS_ASSERT_THROWS_NOTHING( alg.setPropertyValue("Filename", m_testFile));
-		TS_ASSERT_THROWS_NOTHING( alg.setPropertyValue("OutputWorkspacePrefix", "value"));
+		TS_ASSERT_THROWS_NOTHING( alg.setPropertyValue("OutputWorkspace", "outputWSName"));
 		TS_ASSERT_THROWS_NOTHING( alg.execute(); );
 		TS_ASSERT(alg.isExecuted( ));
 
diff --git a/Code/Mantid/instrument/D2B_Definition.xml b/Code/Mantid/instrument/D2B_Definition.xml
index 2c87272300c..ffcd7975230 100644
--- a/Code/Mantid/instrument/D2B_Definition.xml
+++ b/Code/Mantid/instrument/D2B_Definition.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!-- For help on the notation used to specify an Instrument Definition File see http://www.mantidproject.org/IDF -->
-<instrument name="D2B" valid-from="1900-01-31 23:59:59" valid-to="2100-01-31 23:59:59" last-modified="2013-11-05 13:11:35">
+<instrument name="D2B" valid-from="1900-01-31 23:59:59" valid-to="2100-01-31 23:59:59" last-modified="2013-11-22 09:57:44">
   <!-- Author: ricardo.leal@ill.fr -->
   <defaults>
     <length unit="meter" />
@@ -305,7 +305,7 @@
     <cylinder id="shape">
       <centre-of-bottom-base x="0.0" y="-0.006144" z="0.0" />
       <axis x="0.0" y="1.0" z="0.0" />
-      <radius val="0.0127" />
+      <radius val="0.00127" />
       <height val=".0114341328125" />
     </cylinder>
     <algebra val="shape" />
-- 
GitLab