From fb5eea97709f1c6f223602b94261da8e09e20469 Mon Sep 17 00:00:00 2001
From: John Hill <john.r.hill@stfc.ac.uk>
Date: Wed, 6 Aug 2014 16:28:05 +0100
Subject: [PATCH] Refs #10061 added files for loader

---
 .../Framework/DataHandling/CMakeLists.txt     |   8 +-
 .../inc/MantidDataHandling/LoadFITS.h         |  96 ++++++
 .../Framework/DataHandling/src/LoadFITS.cpp   | 294 ++++++++++++++++++
 .../docs/source/algorithms/LoadFITS-v1.rst    |  14 +
 4 files changed, 409 insertions(+), 3 deletions(-)
 create mode 100644 Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadFITS.h
 create mode 100644 Code/Mantid/Framework/DataHandling/src/LoadFITS.cpp
 create mode 100644 Code/Mantid/docs/source/algorithms/LoadFITS-v1.rst

diff --git a/Code/Mantid/Framework/DataHandling/CMakeLists.txt b/Code/Mantid/Framework/DataHandling/CMakeLists.txt
index 8edcfd12003..5527225abe3 100644
--- a/Code/Mantid/Framework/DataHandling/CMakeLists.txt
+++ b/Code/Mantid/Framework/DataHandling/CMakeLists.txt
@@ -22,7 +22,7 @@ set ( SRC_FILES
 	src/Load.cpp
 	src/LoadAscii.cpp
 	src/LoadAscii2.cpp
-        src/LoadBBY.cpp
+    src/LoadBBY.cpp
 	src/LoadCalFile.cpp
 	src/LoadCanSAS1D.cpp
 	src/LoadCanSAS1D2.cpp
@@ -34,6 +34,7 @@ set ( SRC_FILES
 	src/LoadEventNexus.cpp
 	src/LoadEventPreNexus.cpp
 	src/LoadEventPreNexus2.cpp
+	src/LoadFITS.cpp
 	src/LoadFullprofResolution.cpp
 	src/LoadGSASInstrumentFile.cpp
 	src/LoadGSS.cpp
@@ -163,7 +164,7 @@ set ( INC_FILES
 	inc/MantidDataHandling/Load.h
 	inc/MantidDataHandling/LoadAscii.h
 	inc/MantidDataHandling/LoadAscii2.h
-        inc/MantidDataHandling/LoadBBY.h
+    inc/MantidDataHandling/LoadBBY.h
 	inc/MantidDataHandling/LoadCalFile.h
 	inc/MantidDataHandling/LoadCanSAS1D.h
 	inc/MantidDataHandling/LoadCanSAS1D2.h
@@ -175,6 +176,7 @@ set ( INC_FILES
 	inc/MantidDataHandling/LoadEventNexus.h
 	inc/MantidDataHandling/LoadEventPreNexus.h
 	inc/MantidDataHandling/LoadEventPreNexus2.h
+	inc/MantidDataHandling/LoadFITS.h
 	inc/MantidDataHandling/LoadFullprofResolution.h
 	inc/MantidDataHandling/LoadGSASInstrumentFile.h
 	inc/MantidDataHandling/LoadGSS.h
@@ -226,7 +228,7 @@ set ( INC_FILES
 	inc/MantidDataHandling/LoadSassena.h
 	inc/MantidDataHandling/LoadSpec.h
 	inc/MantidDataHandling/LoadSpice2D.h
-	inc/MantidDataHandling/LoadTOFRawNexus.h
+	inc/MantidDataHandling/LoadTOFRawNexus.h	
 	inc/MantidDataHandling/MaskDetectors.h
 	inc/MantidDataHandling/MaskDetectorsInShape.h
 	inc/MantidDataHandling/MergeLogs.h
diff --git a/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadFITS.h b/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadFITS.h
new file mode 100644
index 00000000000..06ee83f0b03
--- /dev/null
+++ b/Code/Mantid/Framework/DataHandling/inc/MantidDataHandling/LoadFITS.h
@@ -0,0 +1,96 @@
+#ifndef MANTID_DATAHANDLING_LOADFITS_H_
+#define MANTID_DATAHANDLING_LOADFITS_H_
+
+#include "MantidAPI/IFileLoader.h"
+
+
+namespace Mantid
+{
+namespace DataHandling
+{
+  /** LoadFITS : Load FITS files to TableWorkspace(s)
+    
+    Copyright &copy; 2014 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://github.com/mantidproject/mantid>
+    Code Documentation is available at: <http://doxygen.mantidproject.org>
+  */
+
+  class DLLExport LoadFITS : public API::IFileLoader<Kernel::FileDescriptor>
+  {
+  public:
+    LoadFITS() {}
+    virtual ~LoadFITS() {}
+
+    /// Algorithm's name for identification overriding a virtual method
+    virtual const std::string name() const { return "LoadFITS" ;}
+
+    ///Summary of algorithms purpose
+    virtual const std::string summary() const {return "Load data from FITS files.";}
+
+    /// Algorithm's version for identification overriding a virtual method
+    virtual int version() const { return 1 ;}
+
+    /// Algorithm's category for identification overriding a virtual method
+    virtual const std::string category() const { return "DataHandling";}
+
+    /// Returns a confidence value that this algorithm can load a file
+    virtual int confidence(Kernel::FileDescriptor & descriptor) const;
+
+  private:
+    /// Initialisation code
+    void init();
+    /// Execution code
+    void exec();
+    
+    ///// Implement abstract Algorithm methods
+    //void init();
+    ///// Implement abstract Algorithm methods
+    //void exec();
+
+    ///// Load file to a vector of strings
+    //void loadFile(std::string filename, std::vector<std::string>& lines);
+
+    ///// Get Histogram type
+    //std::string getHistogramType(const std::vector<std::string>& lines);
+
+    ///// Get Number of banks
+    //size_t getNumberOfBanks(const std::vector<std::string>& lines);
+
+    ///// Scan imported file for bank information
+    //void scanBanks(const std::vector<std::string>& lines, std::vector<size_t>& bankStartIndex );
+
+    ///// Parse bank in file to a map
+    //void parseBank(std::map<std::string, double>& parammap, const std::vector<std::string>& lines, size_t bankid, size_t startlineindex, int nProf);
+
+    ///// Find first INS line at or after lineIndex
+    //size_t findINSLine(const std::vector<std::string>& lines, size_t lineIndex);
+
+    ///// Generate output workspace
+    //DataObjects::TableWorkspace_sptr genTableWorkspace(std::map<size_t, std::map<std::string, double> > bankparammap);
+
+
+  };
+
+
+
+
+} // namespace DataHandling
+} // namespace Mantid
+
+#endif // MANTID_DATAHANDLING_LOADFITS_H_
diff --git a/Code/Mantid/Framework/DataHandling/src/LoadFITS.cpp b/Code/Mantid/Framework/DataHandling/src/LoadFITS.cpp
new file mode 100644
index 00000000000..2275a68b869
--- /dev/null
+++ b/Code/Mantid/Framework/DataHandling/src/LoadFITS.cpp
@@ -0,0 +1,294 @@
+#include "MantidDataHandling/LoadFITS.h"
+
+#include "MantidDataObjects/EventWorkspace.h"
+#include "MantidAPI/FileProperty.h"
+#include "MantidAPI/RegisterFileLoader.h"
+//#include "MantidAPI/WorkspaceValidators.h"
+//#include "MantidKernel/UnitFactory.h"
+//#include "MantidGeometry/Instrument.h"
+//#include "MantidGeometry/Instrument/RectangularDetector.h"
+//#include "MantidGeometry/Objects/ShapeFactory.h"
+//
+//#include "MantidNexus/NexusClasses.h"
+//
+//#include <boost/math/special_functions/fpclassify.hpp>
+//#include <Poco/File.h>
+//#include <iostream>
+//#include <fstream>
+//#include <iomanip>
+
+using namespace Mantid::DataHandling;
+using namespace Mantid::API;
+using namespace Mantid::Kernel;
+
+namespace Mantid
+{
+namespace DataHandling
+{
+  // Register the algorithm into the AlgorithmFactory
+  DECLARE_FILELOADER_ALGORITHM(LoadFITS);
+
+  int LoadFITS::confidence(Kernel::FileDescriptor & descriptor) const
+  {
+      return (descriptor.extension() == ".fits" || descriptor.extension() == ".fit") ? 80 : 0; 
+  }
+
+  /**
+  * Execute the algorithm.
+  */
+  void LoadFITS::exec()
+  {
+    // Delete the output workspace name if it existed
+    std::string outName = getPropertyValue("OutputWorkspace");
+    if (AnalysisDataService::Instance().doesExist(outName))
+      AnalysisDataService::Instance().remove(outName);
+
+    // Get the name of the file.
+    std::string filenameBin = getPropertyValue("Filename");
+      
+    size_t nBins  = 1;
+    double tofMinBoundary = 5;
+    double tofMaxBoundary = 5;
+      
+    //// 100 for "loading neutron counts", 100 for "creating neutron event lists", 100 for "loading neutron events"
+    //Progress prog(this, 0.0, 1.0, 100 + 100 + 100);
+    //prog.doReport("creating instrument");
+
+    // Create a workspace
+    DataObjects::EventWorkspace_sptr eventWS(new DataObjects::EventWorkspace());
+
+    eventWS->initialize(
+        nHist,
+        nBins + 1,  // number of TOF bin boundaries
+        nBins);
+
+    // Set the units
+    eventWS->getAxis(0)->unit() = UnitFactory::Instance().create("TOF");
+    eventWS->setYUnit("Counts");
+
+    // ???
+    //eventWS->setYUnitLabel("Counts");      
+
+    eventWS->setTitle("my title");
+    eventWS->mutableRun().addProperty("Filename", filenameBin);
+    //eventWS->mutableRun().addProperty("run_number", 1);
+    //eventWS->mutableRun().addProperty("run_start", "1991-01-01T00:00:00", true );
+    //eventWS->mutableRun().addProperty("duration", duration[0], units);
+
+    // Build instrument geometry
+
+    // Create a new instrument and set its name
+    std::string instrumentname = "BILBY";
+    Geometry::Instrument_sptr instrument(new Geometry::Instrument(instrumentname));
+    eventWS->setInstrument(instrument);
+
+    // Add dummy source and samplepos to instrument
+
+    // Create an instrument component wich will represent the sample position.
+    Geometry::ObjComponent *samplepos = new Geometry::ObjComponent("Sample",instrument.get());
+    instrument->add(samplepos);
+    instrument->markAsSamplePos(samplepos);
+    // Put the sample in the centre of the coordinate system
+    samplepos->setPos(0.0,0.0,0.0);
+
+    // Create a component to represent the source
+    Geometry::ObjComponent *source = new Geometry::ObjComponent("Source",instrument.get());
+    instrument->add(source);
+    instrument->markAsSource(source);
+
+    // Read in the L1 value and place the source at (0,0,-L1)
+    double l1 = 3949.1824;
+    source->setPos(0.0,0.0,-1.0*l1);
+
+    // Create a component for the detector.
+      
+    size_t xPixelCount = HISTO_BINS_X / 6;
+    size_t yPixelCount = HISTO_BINS_Y;
+    size_t pixelCount = xPixelCount * yPixelCount;
+      
+    // We assumed that these are the dimensions of the detector, and height is in y direction and width is in x direction
+    double width  = 0.4; // meters
+    double height = 1.0;
+
+    // We assumed that individual pixels have the same size and shape of a cuboid with dimensions:
+    double pixel_width  = width  / static_cast<double>(xPixelCount);
+    double pixel_height = height / static_cast<double>(yPixelCount);
+
+    // Create size strings for shape creation
+    std::string pixel_width_str  = boost::lexical_cast<std::string>(pixel_width / 2);
+    std::string pixel_height_str = boost::lexical_cast<std::string>(pixel_height / 2);
+    std::string pixel_depth_str  = "0.00001"; // Set the depth of a pixel to a very small number
+
+    // Define shape of a pixel as an XML string. See http://www.mantidproject.org/HowToDefineGeometricShape for details
+    // on shapes in Mantid.
+    std::string detXML =
+      "<cuboid id=\"pixel\">"
+        "<left-front-bottom-point   x=\"+"+pixel_width_str+"\" y=\"-"+pixel_height_str+"\" z=\"0\"  />"
+        "<left-front-top-point      x=\"+"+pixel_width_str+"\" y=\"-"+pixel_height_str+"\" z=\""+pixel_depth_str+"\"  />"
+        "<left-back-bottom-point    x=\"-"+pixel_width_str+"\" y=\"-"+pixel_height_str+"\" z=\"0\"  />"
+        "<right-front-bottom-point  x=\"+"+pixel_width_str+"\" y=\"+"+pixel_height_str+"\" z=\"0\"  />"
+      "</cuboid>";
+
+    // Create a shape object which will be shared by all pixels.
+    Geometry::Object_sptr shape = Geometry::ShapeFactory().createShape(detXML);
+      
+    double detectorZ =  5;
+    double angle     = 10;
+
+    double curtZOffset = width / 2 * sin(angle * 3.14159265359 / 180);
+
+    if (!filenameHdf.empty()) {
+      NeXus::NXRoot root(filenameHdf);
+      NeXus::NXEntry entry = root.openFirstEntry();
+     
+    }
+
+    // 6 detector banks are available
+
+    // curtain 1
+    AddDetectorBank(
+      instrument,
+      xPixelCount,
+      yPixelCount,
+      0 * pixelCount,
+      shape,
+      width,
+      height,
+      Kernel::V3D(+(width + height) / 2, 0, detectorZ - curtZOffset),
+      Kernel::Quat(  0, Kernel::V3D(0, 0, 1)) * Kernel::Quat(angle, Kernel::V3D(0, 1, 0)));
+      
+    // curtain 2
+    AddDetectorBank(
+      instrument,
+      xPixelCount,
+      yPixelCount,
+      1 * pixelCount,
+      shape,
+      width,
+      height,
+      Kernel::V3D(-(width + height) / 2, 0, detectorZ - curtZOffset),
+      Kernel::Quat(180, Kernel::V3D(0, 0, 1)) * Kernel::Quat(angle, Kernel::V3D(0, 1, 0)));
+      
+    // curtain 3
+    AddDetectorBank(
+      instrument,
+      xPixelCount,
+      yPixelCount,
+      2 * pixelCount,
+      shape,
+      width,
+      height,
+      Kernel::V3D(0, +(width + height) / 2, detectorZ - curtZOffset),
+      Kernel::Quat( 90, Kernel::V3D(0, 0, 1)) * Kernel::Quat(angle, Kernel::V3D(0, 1, 0)));
+      
+    // curtain 4
+    AddDetectorBank(
+      instrument,
+      xPixelCount,
+      yPixelCount,
+      3 * pixelCount,
+      shape,
+      width,
+      height,
+      Kernel::V3D(0, -(width + height) / 2, detectorZ - curtZOffset),
+      Kernel::Quat(-90, Kernel::V3D(0, 0, 1)) * Kernel::Quat(angle, Kernel::V3D(0, 1, 0)));
+      
+    // back 1
+    AddDetectorBank(
+      instrument,
+      xPixelCount,
+      yPixelCount,
+      4 * pixelCount,
+      shape,
+      width,
+      height,
+      Kernel::V3D(-width / 2 - 0.05, 0, detectorZ),
+      Kernel::Quat(180, Kernel::V3D(0, 0, 1)));
+      
+    // back 2
+    AddDetectorBank(
+      instrument,
+      xPixelCount,
+      yPixelCount,
+      5 * pixelCount,
+      shape,
+      width,
+      height,
+      Kernel::V3D(+width / 2 + 0.05, 0, detectorZ),
+      Kernel::Quat(  0, Kernel::V3D(0, 0, 1)));
+
+    // load events
+                  
+    size_t numberHistograms = eventWS->getNumberHistograms();
+
+    std::vector<EventVector_pt> eventVectors(numberHistograms, NULL);
+    std::vector<size_t> eventCounts(numberHistograms, 0);
+		std::vector<detid_t> detIDs = instrument->getDetectorIDs();
+
+    // count total events per pixel to reserve necessary memory
+    LoadFile_Counts(prog, filenameBin, HISTO_BINS_X, HISTO_BINS_Y, tofMinBoundary, tofMaxBoundary, eventCounts);
+      
+    // for progress notifications
+    size_t progCount = 100;
+    size_t progStep  = numberHistograms / progCount;
+    size_t progNext  = progStep;
+      
+    auto progMsg = "creating neutron event lists";
+    prog.doReport(progMsg);
+    for (size_t i = 0; i != numberHistograms; ++i) {
+      DataObjects::EventList& eventList = eventWS->getEventList(i);
+
+      eventList.setSortOrder(DataObjects::PULSETIME_SORT); // why not PULSETIME[TOF]_SORT ?
+      eventList.reserve(eventCounts[i]);
+      eventList.setDetectorID(detIDs[i]);
+			eventList.setSpectrumNo(detIDs[i]);  
+
+      DataObjects::getEventsFrom(eventList, eventVectors[i]);
+
+      if ((progNext <= i) && (progCount != 0)) {
+        prog.report(progMsg);
+        progNext += progStep;
+        progCount--;
+      }
+    }
+    if (progCount != 0)
+      prog.reportIncrement(progCount, progMsg);
+      
+    double shortest_tof(0.0), longest_tof(0.0);
+    LoadFile_Events(prog, filenameBin, HISTO_BINS_X, HISTO_BINS_Y, tofMinBoundary, tofMaxBoundary, eventVectors, shortest_tof, longest_tof);
+
+    cow_ptr<MantidVec> axis;
+    MantidVec& xRef = axis.access();
+    xRef.resize(2, 0.0);
+    if (longest_tof != 0.0) {
+      xRef[0] = std::max(0.0, shortest_tof - 1); // just to make sure the bins hold it all
+      xRef[1] = longest_tof + 1;
+    }
+    eventWS->setAllX(axis);
+
+    setProperty("OutputWorkspace", eventWS);
+  }
+
+  /**
+  * Initialise the algorithm. Declare properties which can be set before execution (input) or 
+  * read from after the execution (output).
+  */
+  void LoadFITS::init()
+  {
+    // Specify file extensions which can be associated with a BBY file.
+    std::vector<std::string> exts;
+
+    // Declare the Filename algorithm property. Mandatory. Sets the path to the file to load.
+    exts.clear();
+    exts.push_back(".fit");  
+    declareProperty(
+    new API::FileProperty("Filename", "", API::FileProperty::Load, exts),
+    "The input filename of the stored data");
+      
+    declareProperty(
+    new API::WorkspaceProperty<API::IEventWorkspace>("OutputWorkspace", "", Kernel::Direction::Output));
+  }
+
+
+}
+}
\ No newline at end of file
diff --git a/Code/Mantid/docs/source/algorithms/LoadFITS-v1.rst b/Code/Mantid/docs/source/algorithms/LoadFITS-v1.rst
new file mode 100644
index 00000000000..557447bc10f
--- /dev/null
+++ b/Code/Mantid/docs/source/algorithms/LoadFITS-v1.rst
@@ -0,0 +1,14 @@
+.. algorithm::
+
+.. summary::
+
+.. alias::
+
+.. properties::
+
+Description
+-----------
+
+Load data from FITS files
+
+.. categories::
-- 
GitLab