Skip to content

Commit

Permalink
Add LoadCanSAS1D2 the second version
Browse files Browse the repository at this point in the history
it allows to load cansas version 1.1

re #6839
  • Loading branch information
gesnerpassos committed Apr 15, 2013
1 parent d09ac84 commit 621e3ab
Show file tree
Hide file tree
Showing 4 changed files with 347 additions and 4 deletions.
2 changes: 2 additions & 0 deletions Code/Mantid/Framework/DataHandling/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ set ( SRC_FILES
src/LoadAscii.cpp
src/LoadCalFile.cpp
src/LoadCanSAS1D.cpp
src/LoadCanSAS1D2.cpp
src/LoadDAE.cpp
src/LoadDAE/idc.cpp
src/LoadDAE/idc.h
Expand Down Expand Up @@ -173,6 +174,7 @@ set ( INC_FILES
inc/MantidDataHandling/LoadAscii.h
inc/MantidDataHandling/LoadCalFile.h
inc/MantidDataHandling/LoadCanSAS1D.h
inc/MantidDataHandling/LoadCanSAS1D2.h
inc/MantidDataHandling/LoadDAE.h
inc/MantidDataHandling/LoadDaveGrp.h
inc/MantidDataHandling/LoadDetectorInfo.h
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ namespace Mantid
///default constructor
LoadCanSAS1D();
/// destructor
~LoadCanSAS1D();
virtual ~LoadCanSAS1D();
/// Algorithm's name for identification overriding a virtual method
virtual const std::string name() const { return "LoadCanSAS1D"; }
/// Algorithm's version for identification overriding a virtual method
Expand All @@ -73,7 +73,7 @@ namespace Mantid
/// check the structure of the file and return a value between 0 and 100 of how much this file can be loaded
virtual int fileCheck(const std::string& filePath);

private:
protected:
/// Sets documentation strings for this algorithm
virtual void initDocs();
/// If a workspace group is created this is set from empty to the root name of the members, the name of the workspace group members up to and including the _
Expand All @@ -82,12 +82,12 @@ namespace Mantid
int m_groupNumber;

/// Overwrites Algorithm method.
void init();
virtual void init();
/// Overwrites Algorithm method
void exec();

/// Loads an individual SASentry element into a new workspace
API::MatrixWorkspace_sptr loadEntry(Poco::XML::Node * const workspaceData, std::string & runName);
virtual API::MatrixWorkspace_sptr loadEntry(Poco::XML::Node * const workspaceData, std::string & runName);
/// Checks if the pointer to the loaded data is not null or throws if it is
void check(const Poco::XML::Element* const toCheck, const std::string & name) const;
/// Appends the new data workspace creating a workspace group if there was existing data
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
#ifndef MANTID_DATAHANDLING_LoadCanSAS1D2_H
#define MANTID_DATAHANDLING_LoadCanSAS1D2_H

//----------------------------------------------------------------------
// Includes
//----------------------------------------------------------------------
#include "LoadCanSAS1D.h"
#include "MantidDataObjects/Workspace2D.h"
#include "MantidAPI/IDataFileChecker.h"
#include <Poco/DOM/Element.h>
#include <Poco/DOM/Node.h>
//----------------------------------------------------------------------

namespace Poco {
namespace XML {
class Element;
}
}

namespace Mantid
{
namespace DataHandling
{
/** @class LoadCanSAS1D2 DataHandling/LoadCanSAS1D2.h
This algorithm loads 1 CanSAS1d xml file into a workspace.
It implements the CanSAS - version 1.1 standard
(http://www.cansas.org/svn/1dwg/tags/v1.1/cansas1d.xsd).
The main difference between the CanSAS1D version 1.0 (implemented at
version 1 of this algorithm (LoadCanSAS1D) and the version 1.1 is
that the later version introduced the element SAStransmission_spectrum.
This means that right now, a file may have the reduced data, as well as
some spectra related to the transmission. In order not to break the
signature proposed on LoadCanSAS1D version 1.0, a new Property will be
introduced:
- LoadTransmission - boolean flag with default False.
If the user let the LoadTransmissionData false, than the signature will be:
- OutputWs = LoadCanSAS1D(filename)
If the user set the LoadTransmission, than, it will receive the output in this
way:
- OutputWs, TransWs, TransCanWs = LoadCanSAS1D(filename,LoadTransmission)
The values of TransWs and TransCanWs may be None if the related data was not found
at filename.
@author Gesner Passos, Rutherford Appleton Laboratory
@date 12/04/2013
Copyright &copy; 2007-10 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 LoadCanSAS1D2 : public LoadCanSAS1D
{
public:
///default constructor
LoadCanSAS1D2();
/// destructor
virtual ~LoadCanSAS1D2();
/// Algorithm's version for identification overriding a virtual method
virtual int version() const { return 2; }

protected:
/// Overwrites Algorithm method. Extend to create the LoadTransmission flag.
virtual void init();

virtual void exec();
/// Extends the LoadEntry to deal with the possibility of Transmission data.
virtual API::MatrixWorkspace_sptr loadEntry(Poco::XML::Node * const workspaceData, std::string & runName);
/// Add new method to deal with loading the transmission related data.
API::MatrixWorkspace_sptr loadTransEntry(Poco::XML::Node * const workspaceData, std::string & runName,
std::string trans_name);

std::vector<API::MatrixWorkspace_sptr> trans_gp, trans_can_gp;

private:
void processTransmission(std::vector<API::MatrixWorkspace_sptr>& trans_gp, const std::string & name, const std::string & output_name);
};

}
}
#endif // MANTID_DATAHANDLING_LoadCanSAS1D2_H
240 changes: 240 additions & 0 deletions Code/Mantid/Framework/DataHandling/src/LoadCanSAS1D2.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,240 @@
/*WIKI*
Loads the given file, which should be in the CanSAS1d format specified by canSAS 1D Data Formats Working
Group schema http://svn.smallangles.net/svn/canSAS/1dwg/trunk/cansas1d.xsd and creates output workspace.
CANSAS has a Wiki page at http://www.smallangles.net/wgwiki/index.php/canSAS_Working_Groups
If the file contains mulitple SASentry elements a workspace group will be created and each SASentry will be one workspace in the group. Loading multiple SASdata elements is not supported.
*WIKI*/
//----------------------------------------------------------------------
// Includes
//----------------------------------------------------------------------
#include "MantidDataHandling/LoadCanSAS1D2.h"
#include "MantidAPI/FileProperty.h"
#include "MantidAPI/WorkspaceGroup.h"
#include "MantidAPI/WorkspaceFactory.h"
#include "MantidKernel/UnitFactory.h"
#include "MantidKernel/ConfigService.h"
#include "MantidAPI/AlgorithmFactory.h"
#include "MantidAPI/LoadAlgorithmFactory.h"
#include "MantidDataObjects/Workspace2D.h"
#include <Poco/Path.h>
#include <Poco/DOM/DOMParser.h>
#include <Poco/DOM/Document.h>
#include <Poco/DOM/NodeList.h>
#include <Poco/DOM/Text.h>

#include <boost/lexical_cast.hpp>
//-----------------------------------------------------------------------

using Poco::XML::DOMParser;
using Poco::XML::Document;
using Poco::XML::Element;
using Poco::XML::NodeList;
using Poco::XML::Node;
using Poco::XML::Text;

using namespace Mantid::Kernel;
using namespace Mantid::API;
using namespace Mantid::DataObjects;

namespace Mantid
{
namespace DataHandling
{

// Register the algorithm into the AlgorithmFactory
DECLARE_ALGORITHM(LoadCanSAS1D2)

//register the algorithm into loadalgorithm factory
DECLARE_LOADALGORITHM(LoadCanSAS1D2)

/// constructor
LoadCanSAS1D2::LoadCanSAS1D2() : LoadCanSAS1D()
{}

/// destructor
LoadCanSAS1D2::~LoadCanSAS1D2()
{}

/// Overwrites Algorithm Init method.
void LoadCanSAS1D2::init()
{
LoadCanSAS1D::init();
declareProperty(
new PropertyWithValue<bool>("LoadTransmission", false, Direction::Input),
"Load the transmission related data from the file if it is present (optional, default False).");
}

void LoadCanSAS1D2::exec(){
LoadCanSAS1D::exec();
bool loadTrans = getProperty("LoadTransmission");
if (!loadTrans)
return; // all done. It is not to load the transmission, nor check if it exists.
if (trans_gp.size() == 0 && trans_can_gp.size() == 0){
return; // all done, not transmission inside
}

std::string out_wsname = this->getProperty("OutputWorkspace");
processTransmission(trans_gp, "sample",out_wsname);
processTransmission(trans_can_gp, "can",out_wsname);
}

/**
Process the Transmission workspaces in order to output them to Mantid.
@param trans_gp: A vector with the pointers to the workspaces related to the transmission
@param name: Name of the transmission. Only two names are allowed: sample/can.
@param output_name: The name of the OutputWorkspace, in order to create the workspaces with similar names.
*/
void LoadCanSAS1D2::processTransmission(std::vector<MatrixWorkspace_sptr>& trans_gp, const std::string & name, const std::string & output_name){

std::string trans_wsname = std::string(output_name).append("_trans_").append(name);
const std::string fileName = getPropertyValue("Filename");

std::string propertyWS;
if (name == "sample")
propertyWS = "TransmissionWorkspace";
else
propertyWS = "TransmissionCanWorkspace";
const std::string doc = "The transmission workspace";


if (trans_gp.size() == 1){
MatrixWorkspace_sptr WS = trans_gp[0];
WS->mutableRun().addProperty("Filename",fileName);
declareProperty(new WorkspaceProperty<MatrixWorkspace>
(propertyWS,trans_wsname,Direction::Output),
doc);

setProperty(propertyWS,WS);
}else if (trans_gp.size() > 1){
WorkspaceGroup_sptr group(new WorkspaceGroup);
for (unsigned int i =0; i< trans_gp.size(); i++){
MatrixWorkspace_sptr newWork = trans_gp[i];

newWork->mutableRun().addProperty("Filename",fileName);
std::stringstream pname;
std::stringstream name;
pname << propertyWS << i;
name << trans_wsname << i;
declareProperty(new WorkspaceProperty<MatrixWorkspace>
(pname.str(), name.str(), Direction::Output),
doc);
setProperty(pname.str(), newWork);
group->addWorkspace(newWork);
}
std::string pname = std::string(propertyWS).append("GP");
declareProperty(new WorkspaceProperty<WorkspaceGroup>
(pname, trans_wsname, Direction::Output),
doc);
setProperty(pname,group);
}
}


/** Load an individual "<SASentry>" element into a new workspace. It extends the LoadCanSAS1D
* in the direction of loading the SAStransmission_spectrum as well. (which was introduced in version 1.1)
*
* @param[in] workspaceData points to a "<SASentry>" element
* @param[out] runName the name this workspace should take
* @return dataWS this workspace will be filled with data
* @throw NotFoundError if any expected elements couldn't be read
* @throw NotImplementedError if the entry doesn't contain exactly one run
*/
MatrixWorkspace_sptr LoadCanSAS1D2::loadEntry(Poco::XML::Node * const workspaceData, std::string & runName)
{
MatrixWorkspace_sptr main_out = LoadCanSAS1D::loadEntry(workspaceData, runName);
bool loadTrans = getProperty("LoadTransmission");
if (!loadTrans)
return main_out; // all done. It is not to load the transmission, nor check if it exists.

Element *workspaceElem = dynamic_cast<Element*>(workspaceData);
// check(workspaceElem, "<SASentry>"); // already done at LoadCanSAS1D::loadEntry
NodeList * sasTransList = workspaceElem->getElementsByTagName("SAStransmission_spectrum");
if (!sasTransList->length()){
//sasTransList->release();
g_log.warning() << "There is no transmission data for this file " << getPropertyValue("Filename") << std::endl;
return main_out;
}

for (unsigned short trans_index = 0; trans_index < sasTransList->length();
trans_index++){
// foreach SAStransmission_spectrum
Node* idataElem = sasTransList->item(trans_index);
Element* sasTrasElem =dynamic_cast<Element*> (idataElem);
if (!sasTrasElem)
continue;
std::vector<API::MatrixWorkspace_sptr> & group = (sasTrasElem->getAttribute("name") == "sample")? trans_gp : trans_can_gp;

// getting number of Tdata elements in the xml file
NodeList* tdataElemList = sasTrasElem->getElementsByTagName("Tdata");
size_t nBins = tdataElemList->length();

MatrixWorkspace_sptr dataWS =
WorkspaceFactory::Instance().create("Workspace2D", 1, nBins, nBins);

createLogs(workspaceElem, dataWS);

std::string title = main_out->getTitle();
title += ":trans";
title += sasTrasElem->getAttribute("name");
dataWS->setTitle(title);
dataWS->isDistribution(true);
dataWS->setYUnit("");

//load workspace data
MantidVec& X = dataWS->dataX(0);
MantidVec& Y = dataWS->dataY(0);
MantidVec& E = dataWS->dataE(0);
int vecindex = 0;
//iterate through each Tdata element and get the values of "Lambda",
//"T" and "Tdev" text nodes and fill X,Y,E vectors
for (unsigned long index = 0; index < nBins; ++index)
{
Node* idataElem = tdataElemList->item(index);
Element* elem = dynamic_cast<Element*> (idataElem);
if (elem)
{
//setting X vector
std::string nodeVal;
Element*qElem = elem->getChildElement("Lambda");
check(qElem, "Lambda");
nodeVal = qElem->innerText();
std::stringstream x(nodeVal);
double d;
x >> d;
X[vecindex] = d;

//setting Y vector
Element*iElem = elem->getChildElement("T");
check(qElem, "T");
nodeVal = iElem->innerText();
std::stringstream y(nodeVal);
y >> d;
Y[vecindex] = d;

//setting the error vector
Element*idevElem = elem->getChildElement("Tdev");
check(qElem, "Tdev");
nodeVal = idevElem->innerText();
std::stringstream e(nodeVal);
e >> d;
E[vecindex] = d;
++vecindex;
}
}

runLoadInstrument(main_out->getInstrument()->getName(), dataWS);
tdataElemList->release();
dataWS->getAxis(0)->setUnit("Wavelength");

// add to group
group.push_back(dataWS);
}
return main_out;
}


}
}

0 comments on commit 621e3ab

Please sign in to comment.