Commit cc4f478a authored by Gigg, Martyn Anthony's avatar Gigg, Martyn Anthony
Browse files

Refs #2898. Merged changes from iteration 29 branch back to the trunk.

parent 19ee13f6
...@@ -216,7 +216,7 @@ set ( GMOCK_TEST_FILES ...@@ -216,7 +216,7 @@ set ( GMOCK_TEST_FILES
if(UNITY_BUILD) if(UNITY_BUILD)
include(UnityBuild) include(UnityBuild)
enable_unity_build(API SRC_FILES SRC_UNITY_IGNORE_FILES 1000) enable_unity_build(API SRC_FILES SRC_UNITY_IGNORE_FILES 10)
endif(UNITY_BUILD) endif(UNITY_BUILD)
# Have to link to winsock library on Windows # Have to link to winsock library on Windows
......
...@@ -78,6 +78,7 @@ namespace Mantid ...@@ -78,6 +78,7 @@ namespace Mantid
// The Workspace Factory create-from-parent method needs direct access to the axes. // The Workspace Factory create-from-parent method needs direct access to the axes.
friend class WorkspaceFactoryImpl; friend class WorkspaceFactoryImpl;
/// Typedef for the workspace_iterator to use with a Workspace /// Typedef for the workspace_iterator to use with a Workspace
typedef workspace_iterator<LocatedDataRef, MatrixWorkspace> iterator; typedef workspace_iterator<LocatedDataRef, MatrixWorkspace> iterator;
/// Typedef for the const workspace_iterator to use with a Workspace /// Typedef for the const workspace_iterator to use with a Workspace
...@@ -301,12 +302,14 @@ namespace Mantid ...@@ -301,12 +302,14 @@ namespace Mantid
/// The instrument used for this experiment /// The instrument used for this experiment
boost::shared_ptr<Geometry::Instrument> sptr_instrument; boost::shared_ptr<Geometry::Instrument> sptr_instrument;
protected:
/// The SpectraDetector table used for this experiment. Inside a copy-on-write pointer. /// The SpectraDetector table used for this experiment. Inside a copy-on-write pointer.
Kernel::cow_ptr<SpectraDetectorMap> m_spectramap; Kernel::cow_ptr<SpectraDetectorMap> m_spectramap;
/// The information on the sample environment /// The information on the sample environment
Kernel::cow_ptr<Sample> m_sample; Kernel::cow_ptr<Sample> m_sample;
protected:
/// The run information /// The run information
Kernel::cow_ptr<Run> m_run; Kernel::cow_ptr<Run> m_run;
......
...@@ -97,8 +97,6 @@ public: ...@@ -97,8 +97,6 @@ public:
private: private:
/// Copy Contructor /// Copy Contructor
SpectraDetectorMap(const SpectraDetectorMap& copy); SpectraDetectorMap(const SpectraDetectorMap& copy);
/// Assignment operator
SpectraDetectorMap& operator=(const SpectraDetectorMap& rhs);
/// internal spectra detector map instance /// internal spectra detector map instance
smap m_s2dmap; smap m_s2dmap;
......
...@@ -19,6 +19,14 @@ namespace Mantid ...@@ -19,6 +19,14 @@ namespace Mantid
SpectraDetectorMap::~SpectraDetectorMap() SpectraDetectorMap::~SpectraDetectorMap()
{} {}
//------------------------------------------------------------------------------------------------
/** Populate the map with 2 arrays; one detector per spectrum
*
* @param _spectable :: bare vector of the spectrum numbers
* @param _udettable :: bare vector of the detector ids (same length as spectable)
* @param nentries :: number of entries in the vectors
*/
void SpectraDetectorMap::populate(const int* _spectable, const int* _udettable, int nentries) void SpectraDetectorMap::populate(const int* _spectable, const int* _udettable, int nentries)
{ {
m_s2dmap.clear(); m_s2dmap.clear();
...@@ -38,6 +46,12 @@ namespace Mantid ...@@ -38,6 +46,12 @@ namespace Mantid
return; return;
} }
//------------------------------------------------------------------------------------------------
/** Populate a simple spectrum-to-detector map, with a 1:1 correspondence
*
* @param start :: first spectrum number
* @param end :: last spectrum number (not inclusive)
*/
void SpectraDetectorMap::populateSimple(const int start, const int end) void SpectraDetectorMap::populateSimple(const int start, const int end)
{ {
m_s2dmap.clear(); m_s2dmap.clear();
...@@ -55,11 +69,11 @@ namespace Mantid ...@@ -55,11 +69,11 @@ namespace Mantid
} }
//------------------------------------------------------------------------------------------------
/** Fill the SpectraDetectorMap with a simple list of pixel ids, /** Fill the SpectraDetectorMap with a simple list of pixel ids,
* where the nth entry in the vector has a single detector, specified * where the nth entry in the vector has a single detector, specified
* by the value at that entry in the vector. * by the value at that entry in the vector.
* @param udetList list of ints where the index = spectrum number; value = pixel ID. * @param udetList list of ints where the index = spectrum number; value = pixel ID.
*/ */
void SpectraDetectorMap::populateWithVector(const std::vector<int>& udetList) void SpectraDetectorMap::populateWithVector(const std::vector<int>& udetList)
{ {
...@@ -69,6 +83,7 @@ namespace Mantid ...@@ -69,6 +83,7 @@ namespace Mantid
} }
} }
//------------------------------------------------------------------------------------------------
/** Links a list of UDETs to the given spectrum. /** Links a list of UDETs to the given spectrum.
* THIS METHOD SHOULD BE USED WITH CARE - IT CAN LEAD TO AN INCONSISTENT MAP * THIS METHOD SHOULD BE USED WITH CARE - IT CAN LEAD TO AN INCONSISTENT MAP
* @param spectrum :: The spectrum number to which detectors should be added * @param spectrum :: The spectrum number to which detectors should be added
...@@ -84,6 +99,7 @@ namespace Mantid ...@@ -84,6 +99,7 @@ namespace Mantid
} }
//------------------------------------------------------------------------------------------------
/** Links a SET of detector IDs to the given spectrum. /** Links a SET of detector IDs to the given spectrum.
* THIS METHOD SHOULD BE USED WITH CARE - IT CAN LEAD TO AN INCONSISTENT MAP * THIS METHOD SHOULD BE USED WITH CARE - IT CAN LEAD TO AN INCONSISTENT MAP
* @param spectrum :: The spectrum number to which detectors should be added * @param spectrum :: The spectrum number to which detectors should be added
...@@ -98,6 +114,7 @@ namespace Mantid ...@@ -98,6 +114,7 @@ namespace Mantid
} }
} }
//------------------------------------------------------------------------------------------------
/** Moves all detectors assigned to a particular spectrum number to a different one. /** Moves all detectors assigned to a particular spectrum number to a different one.
* Does nothing if the oldSpectrum number does not exist in the map. * Does nothing if the oldSpectrum number does not exist in the map.
* @param oldSpectrum :: The spectrum number to be removed and have its detectors reassigned * @param oldSpectrum :: The spectrum number to be removed and have its detectors reassigned
...@@ -126,17 +143,22 @@ namespace Mantid ...@@ -126,17 +143,22 @@ namespace Mantid
m_s2dmap.erase(oldSpectrum); m_s2dmap.erase(oldSpectrum);
} }
//------------------------------------------------------------------------------------------------
/// Empties the map - use with care! /// Empties the map - use with care!
void SpectraDetectorMap::clear() void SpectraDetectorMap::clear()
{ {
m_s2dmap.clear(); m_s2dmap.clear();
} }
//------------------------------------------------------------------------------------------------
/** Return the number of detectors for the given spectrum number
* @param spectrum_number :: which spectrum number */
int SpectraDetectorMap::ndet(const int spectrum_number) const int SpectraDetectorMap::ndet(const int spectrum_number) const
{ {
return m_s2dmap.count(spectrum_number); return m_s2dmap.count(spectrum_number);
} }
//------------------------------------------------------------------------------------------------
/** Get a vector of detectors ids contributing to a spectrum /** Get a vector of detectors ids contributing to a spectrum
* @param spectrum_number :: The # of the spectrum you are looking for. * @param spectrum_number :: The # of the spectrum you are looking for.
* @return list of detector ids in map * @return list of detector ids in map
...@@ -159,6 +181,7 @@ namespace Mantid ...@@ -159,6 +181,7 @@ namespace Mantid
return detectors; return detectors;
} }
//------------------------------------------------------------------------------------------------
/** Gets a list of spectra corresponding to a list of detector numbers. /** Gets a list of spectra corresponding to a list of detector numbers.
* @param detectorList :: A list of detector Ids * @param detectorList :: A list of detector Ids
* @return A vector where matching indices correspond to the relevant spectra id * @return A vector where matching indices correspond to the relevant spectra id
...@@ -194,6 +217,7 @@ namespace Mantid ...@@ -194,6 +217,7 @@ namespace Mantid
return spectraList; return spectraList;
} }
//------------------------------------------------------------------------------------------------
/** Tests whether the present map matches another /** Tests whether the present map matches another
* @param other The other map against which to test * @param other The other map against which to test
* @return True if the maps match * @return True if the maps match
...@@ -203,6 +227,7 @@ namespace Mantid ...@@ -203,6 +227,7 @@ namespace Mantid
return ( m_s2dmap == other.m_s2dmap ); return ( m_s2dmap == other.m_s2dmap );
} }
//------------------------------------------------------------------------------------------------
/** Tests whether the present map does not match another /** Tests whether the present map does not match another
* @param other The other map against which to test * @param other The other map against which to test
* @return True if the maps do not match * @return True if the maps do not match
......
...@@ -27,6 +27,7 @@ set ( SRC_FILES ...@@ -27,6 +27,7 @@ set ( SRC_FILES
src/CorrectToFile.cpp src/CorrectToFile.cpp
src/CreateCalFileByNames.cpp src/CreateCalFileByNames.cpp
src/CreateDummyCalFile.cpp src/CreateDummyCalFile.cpp
src/CreateGroupingWorkspace.cpp
src/CreatePSDBleedMask.cpp src/CreatePSDBleedMask.cpp
src/CreatePeaksWorkspace.cpp src/CreatePeaksWorkspace.cpp
src/CreateSingleValuedWorkspace.cpp src/CreateSingleValuedWorkspace.cpp
...@@ -174,6 +175,7 @@ set ( INC_FILES ...@@ -174,6 +175,7 @@ set ( INC_FILES
inc/MantidAlgorithms/CorrectToFile.h inc/MantidAlgorithms/CorrectToFile.h
inc/MantidAlgorithms/CreateCalFileByNames.h inc/MantidAlgorithms/CreateCalFileByNames.h
inc/MantidAlgorithms/CreateDummyCalFile.h inc/MantidAlgorithms/CreateDummyCalFile.h
inc/MantidAlgorithms/CreateGroupingWorkspace.h
inc/MantidAlgorithms/CreatePSDBleedMask.h inc/MantidAlgorithms/CreatePSDBleedMask.h
inc/MantidAlgorithms/CreatePeaksWorkspace.h inc/MantidAlgorithms/CreatePeaksWorkspace.h
inc/MantidAlgorithms/CreateSingleValuedWorkspace.h inc/MantidAlgorithms/CreateSingleValuedWorkspace.h
...@@ -322,6 +324,7 @@ set ( TEST_FILES ...@@ -322,6 +324,7 @@ set ( TEST_FILES
test/CorrectToFileTest.h test/CorrectToFileTest.h
test/CreateCalFileByNamesTest.h test/CreateCalFileByNamesTest.h
test/CreateDummyCalFileTest.h test/CreateDummyCalFileTest.h
test/CreateGroupingWorkspaceTest.h
test/CreatePSDBleedMaskTest.h test/CreatePSDBleedMaskTest.h
test/CreatePeaksWorkspaceTest.h test/CreatePeaksWorkspaceTest.h
test/CreateSingleValuedWorkspaceTest.h test/CreateSingleValuedWorkspaceTest.h
...@@ -434,7 +437,7 @@ set(SRC_UNITY_IGNORE_FILES src/AlignDetectors.cpp ...@@ -434,7 +437,7 @@ set(SRC_UNITY_IGNORE_FILES src/AlignDetectors.cpp
if(UNITY_BUILD) if(UNITY_BUILD)
include(UnityBuild) include(UnityBuild)
enable_unity_build(Algorithms SRC_FILES SRC_UNITY_IGNORE_FILES 1000) enable_unity_build(Algorithms SRC_FILES SRC_UNITY_IGNORE_FILES 10)
endif(UNITY_BUILD) endif(UNITY_BUILD)
# Add the target for this directory # Add the target for this directory
......
#ifndef MANTID_ALGORITHMS_CREATEGROUPINGWORKSPACE_H_
#define MANTID_ALGORITHMS_CREATEGROUPINGWORKSPACE_H_
#include "MantidKernel/System.h"
#include "MantidAPI/Algorithm.h"
namespace Mantid
{
namespace Algorithms
{
/** Creates a new GroupingWorkspace using an instrument from one of:
* an input workspace,
* an instrument name,
* or an instrument IDF file.
*
* Optionally uses bank names to create the groups.");
*
* @author Janik Zikovsky
* @date 2011-05-02
*/
class DLLExport CreateGroupingWorkspace : public API::Algorithm
{
public:
CreateGroupingWorkspace();
~CreateGroupingWorkspace();
/// Algorithm's name for identification
virtual const std::string name() const { return "CreateGroupingWorkspace";};
/// Algorithm's version for identification
virtual int version() const { return 1;};
/// Algorithm's category for identification
virtual const std::string category() const { return "General";}
private:
/// Sets documentation strings for this algorithm
virtual void initDocs();
/// Initialise the properties
void init();
/// Run the algorithm
void exec();
};
} // namespace Mantid
} // namespace Algorithms
#endif /* MANTID_ALGORITHMS_CREATEGROUPINGWORKSPACE_H_ */
#include "MantidAlgorithms/CreateGroupingWorkspace.h"
#include "MantidAPI/MatrixWorkspace.h"
#include "MantidDataObjects/GroupingWorkspace.h"
#include "MantidGeometry/IDetector.h"
#include "MantidKernel/Strings.h"
#include "MantidKernel/System.h"
#include <boost/algorithm/string/detail/classification.hpp>
#include <boost/algorithm/string/split.hpp>
#include <queue>
#include <fstream>
#include "MantidAPI/FileProperty.h"
namespace Mantid
{
namespace Algorithms
{
// Register the algorithm into the AlgorithmFactory
DECLARE_ALGORITHM(CreateGroupingWorkspace)
using namespace Mantid::Kernel;
using namespace Mantid::API;
using namespace Mantid::Geometry;
using namespace Mantid::DataObjects;
//----------------------------------------------------------------------------------------------
/** Constructor
*/
CreateGroupingWorkspace::CreateGroupingWorkspace()
{
}
//----------------------------------------------------------------------------------------------
/** Destructor
*/
CreateGroupingWorkspace::~CreateGroupingWorkspace()
{
}
//----------------------------------------------------------------------------------------------
/// Sets documentation strings for this algorithm
void CreateGroupingWorkspace::initDocs()
{
this->setWikiSummary("Creates a new GroupingWorkspace using an instrument from one of: an input workspace, an instrument name, or an instrument IDF file.\nOptionally uses bank names to create the groups.");
this->setOptionalMessage("Creates a new GroupingWorkspace using an instrument from one of: an input workspace, an instrument name, or an instrument IDF file.\Optionally uses bank names to create the groups.");
}
//----------------------------------------------------------------------------------------------
/** Initialize the algorithm's properties.
*/
void CreateGroupingWorkspace::init()
{
declareProperty(new WorkspaceProperty<>("InputWorkspace","",Direction::Input, true),
"Optional: An input workspace with the instrument we want to use.");
declareProperty(new PropertyWithValue<std::string>("InstrumentName","",Direction::Input),
"Optional: Name of the instrument to base the GroupingWorkspace on which to base the GroupingWorkspace.");
declareProperty(new FileProperty("InstrumentFilename", "", FileProperty::OptionalLoad, ".xml"),
"Optional: Path to the instrument definition file on which to base the GroupingWorkspace.");
declareProperty(new FileProperty("OldCalFilename", "", FileProperty::OptionalLoad, ".cal"),
"Optional: Path to the old-style .cal grouping/calibration file (multi-column ASCII). You must also specify the instrument.");
declareProperty("GroupNames","",
"Optional: A string of the instrument component names to use as separate groups.\n"
"Use / or , to separate multiple groups.\n"
"If empty, then an empty GroupingWorkspace will be created.");
declareProperty(new WorkspaceProperty<GroupingWorkspace>("OutputWorkspace","",Direction::Output),
"An output GroupingWorkspace.");
}
//------------------------------------------------------------------------------------------------
/** Read old-style .cal file to get the grouping
*
* @param groupingFileName :: path to .cal multi-col ascii
* @param detIDtoGroup :: map of key=detectorID, value=group number.
* @param prog :: progress reporter
*/
void readGroupingFile(const std::string& groupingFileName, IndexToIndexMap & detIDtoGroup, Progress & prog )
{
std::ifstream grFile(groupingFileName.c_str());
if (!grFile.is_open())
{
throw Exception::FileError("Error reading .cal file",groupingFileName);
}
detIDtoGroup.clear();
std::string str;
while(getline(grFile,str))
{
//Comment
if (str.empty() || str[0] == '#') continue;
std::istringstream istr(str);
int n,udet,sel,group;
double offset;
istr >> n >> udet >> offset >> sel >> group;
if ((sel) && (group>0))
{
detIDtoGroup[udet]=group; //Register this detector id
}
prog.report();
}
grFile.close();
return;
}
//------------------------------------------------------------------------------------------------
/** Use bank names to build grouping
*
* @param GroupNames :: comma-sep list of bank names
* @param inst :: instrument
* @param detIDtoGroup :: output: map of detID: to group number
* @param prog :: progress report
*/
void makeGroupingByNames(std::string GroupNames, IInstrument_sptr inst, IndexToIndexMap & detIDtoGroup, Progress & prog)
{
// Split the names of the group and insert in a vector
std::vector<std::string> vgroups;
boost::split( vgroups, GroupNames, boost::algorithm::detail::is_any_ofF<char>(",/*"));
// Assign incremental number to each group
std::map<std::string,int> group_map;
int index=0;
for (std::vector<std::string>::const_iterator it=vgroups.begin();it!=vgroups.end();it++)
group_map[(*it)]=++index;
// Find Detectors that belong to groups
if (group_map.size() > 0)
{
// Find Detectors that belong to groups
typedef boost::shared_ptr<Geometry::ICompAssembly> sptr_ICompAss;
typedef boost::shared_ptr<Geometry::IComponent> sptr_IComp;
typedef boost::shared_ptr<Geometry::IDetector> sptr_IDet;
std::queue< std::pair<sptr_ICompAss,int> > assemblies;
sptr_ICompAss current=boost::dynamic_pointer_cast<Geometry::ICompAssembly>(inst);
sptr_IDet currentDet;
sptr_IComp currentIComp;
sptr_ICompAss currentchild;
int top_group, child_group;
if (current.get())
{
top_group=group_map[current->getName()]; // Return 0 if not in map
assemblies.push(std::make_pair<sptr_ICompAss,int>(current,top_group));
}
prog.setNumSteps( int(assemblies.size()) );
while(!assemblies.empty()) //Travel the tree from the instrument point
{
current=assemblies.front().first;
top_group=assemblies.front().second;
assemblies.pop();
int nchilds=current->nelements();
if (nchilds!=0)
{
for (int i=0;i<nchilds;++i)
{
currentIComp=(*(current.get()))[i]; // Get child
currentDet=boost::dynamic_pointer_cast<Geometry::IDetector>(currentIComp);
if (currentDet.get())// Is detector
{
if (top_group > 0)
{
detIDtoGroup[currentDet->getID()] = top_group;
}
}
else // Is an assembly, push in the queue
{
currentchild=boost::dynamic_pointer_cast<Geometry::ICompAssembly>(currentIComp);
if (currentchild.get())
{
child_group=group_map[currentchild->getName()];
if (child_group==0)
child_group=top_group;
assemblies.push(std::make_pair<sptr_ICompAss,int>(currentchild,child_group));
}
}
}
}
prog.report();
}
return;
}
}
//----------------------------------------------------------------------------------------------
/** Execute the algorithm.
*/
void CreateGroupingWorkspace::exec()
{
std::string InputWorkspace = getPropertyValue("InputWorkspace");
std::string InstrumentName = getPropertyValue("InstrumentName");
std::string InstrumentFilename = getPropertyValue("InstrumentFilename");
std::string OldCalFilename = getPropertyValue("OldCalFilename");
std::string GroupNames = getPropertyValue("GroupNames");
// Some validation
int numParams = 0;
if (!InputWorkspace.empty()) numParams++;
if (!InstrumentName.empty()) numParams++;
if (!InstrumentFilename.empty()) numParams++;
if (numParams != 1)
throw std::invalid_argument("You must specify exactly ONE way to get an instrument (workspace, instrument name, or IDF file).");
if (!OldCalFilename.empty() && !GroupNames.empty())
throw std::invalid_argument("You must specify either to use the OldCalFilename parameter OR GroupNames but not both!");
// ---------- Get the instrument one of 3 ways ---------------------------
IInstrument_sptr inst;
if (!InputWorkspace.empty())
{
MatrixWorkspace_sptr inWS = getProperty("InputWorkspace");
inst = inWS->getInstrument();
}
else
{
Algorithm_sptr childAlg = createSubAlgorithm("LoadInstrument",0.0,0.2);
MatrixWorkspace_sptr tempWS(new Workspace2D());
childAlg->setProperty<MatrixWorkspace_sptr>("Workspace", tempWS);
childAlg->setPropertyValue("Filename", InstrumentFilename);
childAlg->setPropertyValue("InstrumentName", InstrumentName);
childAlg->executeAsSubAlg();
inst = tempWS->getInstrument();
}
// --------------------------- Create the output --------------------------
GroupingWorkspace_sptr outWS(new GroupingWorkspace(inst));
this->setProperty("OutputWorkspace", outWS);
// This will get the grouping
IndexToIndexMap detIDtoGroup;
Progress prog(this,0.2,1.0, outWS->getNumberHistograms() );
// Make the grouping one of two ways:
if (GroupNames != "")
makeGroupingByNames(GroupNames, inst, detIDtoGroup, prog);
else if (OldCalFilename != "")
readGroupingFile(OldCalFilename, detIDtoGroup, prog);
if (detIDtoGroup.size() != 0)
{
// Make the groups, if any
// To put a detector ID with a workspace index
IndexToIndexMap * detID_to_WI_ptr = outWS->getDetectorIDToWorkspaceIndexMap(true);
IndexToIndexMap & detID_to_WI = *detID_to_WI_ptr;
// Now go through the map of results and put them in the workspace
IndexToIndexMap::const_iterator it_end = detIDtoGroup.end();
IndexToIndexMap::const_iterator it2_end = detID_to_WI.end();
for (IndexToIndexMap::const_iterator it = detIDtoGroup.begin(); it != it_end; ++it)
{