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
if(UNITY_BUILD)
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)
# Have to link to winsock library on Windows
......
......@@ -78,6 +78,7 @@ namespace Mantid
// The Workspace Factory create-from-parent method needs direct access to the axes.
friend class WorkspaceFactoryImpl;
/// Typedef for the workspace_iterator to use with a Workspace
typedef workspace_iterator<LocatedDataRef, MatrixWorkspace> iterator;
/// Typedef for the const workspace_iterator to use with a Workspace
......@@ -301,12 +302,14 @@ namespace Mantid
/// The instrument used for this experiment
boost::shared_ptr<Geometry::Instrument> sptr_instrument;
protected:
/// The SpectraDetector table used for this experiment. Inside a copy-on-write pointer.
Kernel::cow_ptr<SpectraDetectorMap> m_spectramap;
/// The information on the sample environment
Kernel::cow_ptr<Sample> m_sample;
protected:
/// The run information
Kernel::cow_ptr<Run> m_run;
......
......@@ -97,8 +97,6 @@ public:
private:
/// Copy Contructor
SpectraDetectorMap(const SpectraDetectorMap& copy);
/// Assignment operator
SpectraDetectorMap& operator=(const SpectraDetectorMap& rhs);
/// internal spectra detector map instance
smap m_s2dmap;
......
......@@ -19,6 +19,14 @@ namespace Mantid
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)
{
m_s2dmap.clear();
......@@ -38,6 +46,12 @@ namespace Mantid
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)
{
m_s2dmap.clear();
......@@ -55,11 +69,11 @@ namespace Mantid
}
//------------------------------------------------------------------------------------------------
/** Fill the SpectraDetectorMap with a simple list of pixel ids,
* where the nth entry in the vector has a single detector, specified
* by the value at that entry in the vector.
* @param udetList list of ints where the index = spectrum number; value = pixel ID.
*/
void SpectraDetectorMap::populateWithVector(const std::vector<int>& udetList)
{
......@@ -69,6 +83,7 @@ namespace Mantid
}
}
//------------------------------------------------------------------------------------------------
/** Links a list of UDETs to the given spectrum.
* 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
......@@ -84,6 +99,7 @@ namespace Mantid
}
//------------------------------------------------------------------------------------------------
/** Links a SET of detector IDs to the given spectrum.
* 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
......@@ -98,6 +114,7 @@ namespace Mantid
}
}
//------------------------------------------------------------------------------------------------
/** 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.
* @param oldSpectrum :: The spectrum number to be removed and have its detectors reassigned
......@@ -126,17 +143,22 @@ namespace Mantid
m_s2dmap.erase(oldSpectrum);
}
//------------------------------------------------------------------------------------------------
/// Empties the map - use with care!
void SpectraDetectorMap::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
{
return m_s2dmap.count(spectrum_number);
}
//------------------------------------------------------------------------------------------------
/** Get a vector of detectors ids contributing to a spectrum
* @param spectrum_number :: The # of the spectrum you are looking for.
* @return list of detector ids in map
......@@ -159,6 +181,7 @@ namespace Mantid
return detectors;
}
//------------------------------------------------------------------------------------------------
/** Gets a list of spectra corresponding to a list of detector numbers.
* @param detectorList :: A list of detector Ids
* @return A vector where matching indices correspond to the relevant spectra id
......@@ -194,6 +217,7 @@ namespace Mantid
return spectraList;
}
//------------------------------------------------------------------------------------------------
/** Tests whether the present map matches another
* @param other The other map against which to test
* @return True if the maps match
......@@ -203,6 +227,7 @@ namespace Mantid
return ( m_s2dmap == other.m_s2dmap );
}
//------------------------------------------------------------------------------------------------
/** Tests whether the present map does not match another
* @param other The other map against which to test
* @return True if the maps do not match
......
......@@ -27,6 +27,7 @@ set ( SRC_FILES
src/CorrectToFile.cpp
src/CreateCalFileByNames.cpp
src/CreateDummyCalFile.cpp
src/CreateGroupingWorkspace.cpp
src/CreatePSDBleedMask.cpp
src/CreatePeaksWorkspace.cpp
src/CreateSingleValuedWorkspace.cpp
......@@ -174,6 +175,7 @@ set ( INC_FILES
inc/MantidAlgorithms/CorrectToFile.h
inc/MantidAlgorithms/CreateCalFileByNames.h
inc/MantidAlgorithms/CreateDummyCalFile.h
inc/MantidAlgorithms/CreateGroupingWorkspace.h
inc/MantidAlgorithms/CreatePSDBleedMask.h
inc/MantidAlgorithms/CreatePeaksWorkspace.h
inc/MantidAlgorithms/CreateSingleValuedWorkspace.h
......@@ -322,6 +324,7 @@ set ( TEST_FILES
test/CorrectToFileTest.h
test/CreateCalFileByNamesTest.h
test/CreateDummyCalFileTest.h
test/CreateGroupingWorkspaceTest.h
test/CreatePSDBleedMaskTest.h
test/CreatePeaksWorkspaceTest.h
test/CreateSingleValuedWorkspaceTest.h
......@@ -434,7 +437,7 @@ set(SRC_UNITY_IGNORE_FILES src/AlignDetectors.cpp
if(UNITY_BUILD)
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)
# 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)
{
int detID = it->first;
int group = it->second;
IndexToIndexMap::const_iterator it2 = detID_to_WI.find(detID);
if (it2 != it2_end)
{
int wi = it2->second;
outWS->dataY(wi)[0] = double(group);
}
}
delete detID_to_WI_ptr;
}
}
} // namespace Mantid
} // namespace Algorithms
......@@ -2,22 +2,23 @@
// Includes
//----------------------------------------------------------------------
#include "MantidAlgorithms/DiffractionEventCalibrateDetectors.h"
#include "MantidGeometry/Instrument/RectangularDetector.h"
#include "MantidAPI/TableRow.h"
#include "MantidDataObjects/Workspace2D.h"
#include "MantidDataObjects/EventWorkspace.h"
#include "MantidDataObjects/EventList.h"
#include "MantidAlgorithms/GSLFunctions.h"
#include "MantidAPI/FileProperty.h"
#include "MantidAPI/TableRow.h"
#include "MantidAPI/TextAxis.h"
#include "MantidKernel/UnitFactory.h"
#include "MantidDataObjects/EventList.h"
#include "MantidDataObjects/EventWorkspace.h"
#include "MantidDataObjects/Workspace2D.h"
#include "MantidGeometry/Instrument/RectangularDetector.h"
#include "MantidKernel/ArrayProperty.h"
#include "MantidKernel/CPUTimer.h"
#include "MantidKernel/Exception.h"
#include "MantidAPI/FileProperty.h"
#include <Poco/File.h>
#include <sstream>
#include <numeric>
#include "MantidKernel/UnitFactory.h"
#include <cmath>
#include <iomanip>
#include <numeric>
#include <Poco/File.h>
#include <sstream>
namespace Mantid
{
......@@ -110,6 +111,7 @@ namespace Algorithms
throw std::runtime_error("Error while executing MoveInstrumentComponent as a sub algorithm.");
}
IAlgorithm_sptr algx = createSubAlgorithm("RotateInstrumentComponent");
algx->setProperty<MatrixWorkspace_sptr>("Workspace", inputW);
algx->setPropertyValue("ComponentName", detname);
......@@ -128,6 +130,7 @@ namespace Algorithms
throw std::runtime_error("Error while executing RotateInstrumentComponent as a sub algorithm.");
}
IAlgorithm_sptr algy = createSubAlgorithm("RotateInstrumentComponent");
algy->setProperty<MatrixWorkspace_sptr>("Workspace", inputW);
algy->setPropertyValue("ComponentName", detname);
......@@ -185,6 +188,9 @@ namespace Algorithms
MatrixWorkspace_sptr inputW = boost::dynamic_pointer_cast<MatrixWorkspace>
(AnalysisDataService::Instance().retrieve(inname));
bool debug = true;
CPUTimer tim;
movedetector(x, y, z, rotx, roty, rotz, detname, inputW);
IAlgorithm_sptr alg2 = createSubAlgorithm("CreateCalFileByNames");
alg2->setProperty<MatrixWorkspace_sptr>("InstrumentWorkspace", inputW);
......@@ -202,6 +208,8 @@ namespace Algorithms
throw std::runtime_error("Error while executing CreateCalFileByNames as a sub algorithm.");
}
if (debug) std::cout << tim << " to CreateCalFileByNames" << std::endl;
IAlgorithm_sptr alg3 = createSubAlgorithm("ConvertUnits");
alg3->setProperty<MatrixWorkspace_sptr>("InputWorkspace", inputW);
alg3->setPropertyValue("OutputWorkspace", outname);
......@@ -218,6 +226,8 @@ namespace Algorithms
}
MatrixWorkspace_sptr outputW=alg3->getProperty("OutputWorkspace");
if (debug) std::cout << tim << " to ConvertUnits" << std::endl;
IAlgorithm_sptr alg4 = createSubAlgorithm("DiffractionFocussing");
alg4->setProperty<MatrixWorkspace_sptr>("InputWorkspace", outputW);
alg4->setProperty<MatrixWorkspace_sptr>("OutputWorkspace", outputW);
......@@ -233,7 +243,10 @@ namespace Algorithms
}
outputW=alg4->getProperty("OutputWorkspace");