Skip to content

Commit

Permalink
re #9420 working for GroupingWS
Browse files Browse the repository at this point in the history
  • Loading branch information
NickDraper committed May 8, 2014
1 parent 9d76192 commit a87d018
Show file tree
Hide file tree
Showing 3 changed files with 235 additions and 4 deletions.
Expand Up @@ -8,6 +8,7 @@
#include "MantidKernel/System.h"
#include <climits>
#include "MantidDataObjects/EventWorkspace.h"
#include "MantidDataObjects/GroupingWorkspace.h"
#include <map>
#ifdef HAS_UNORDERED_MAP_H
#include <tr1/unordered_map>
Expand Down Expand Up @@ -157,6 +158,8 @@ typedef std::tr1::unordered_map<specid_t, std::vector<size_t> > storage_map;
/// gets groupings from XML file
void processXMLFile(std::string fname, API::MatrixWorkspace_const_sptr workspace,
std::vector<int64_t> &unUsedSpec);
void processGroupingWorkspace(DataObjects::GroupingWorkspace_const_sptr groupWS,
API::MatrixWorkspace_const_sptr workspace, std::vector<int64_t> &unUsedSpec);
/// used while reading the file turns the string into an integer number (if possible), white space and # comments ignored
int readInt(std::string line);

Expand Down
109 changes: 105 additions & 4 deletions Code/Mantid/Framework/DataHandling/src/GroupDetectors2.cpp
Expand Up @@ -77,6 +77,7 @@ The set of spectra to be grouped can be given as a list of either spectrum numbe
#include "MantidAPI/FileProperty.h"
#include "MantidKernel/Exception.h"
#include "MantidKernel/ListValidator.h"
#include "MantidGeometry/Instrument/DetectorGroup.h"
#include "MantidDataHandling/LoadDetectorsGroupingFile.h"


Expand Down Expand Up @@ -160,6 +161,10 @@ void GroupDetectors2::init()
"Whether to sum or average the values when grouping detectors.");
// Are we preserving event workspaces?
declareProperty("PreserveEvents", true, "Keep the output workspace as an EventWorkspace, if the input has events.");
declareProperty(new WorkspaceProperty<MatrixWorkspace>("CopyGroupingFromWorkspace","",Direction::Input,PropertyMode::Optional),"The name of a workspace to copy the grouping from.\n "
"This can be either a normal workspace or a grouping workspace, but they must be from the same instrument.\n"
"Detector ids are used to match up the spectra to be grouped.\n"
"If this option is selected all file and list options will be ignored.");
}

void GroupDetectors2::exec()
Expand Down Expand Up @@ -303,6 +308,24 @@ void GroupDetectors2::getGroups(API::MatrixWorkspace_const_sptr workspace,
m_GroupSpecInds.clear();

// There are several properties that may contain the user data go through them in order of precedence
// copy grouping from a workspace
const MatrixWorkspace_const_sptr groupingWS_sptr = getProperty("CopyGroupingFromWorkspace");
if( groupingWS_sptr )
{
DataObjects::GroupingWorkspace_const_sptr groupWS = boost::dynamic_pointer_cast<const DataObjects::GroupingWorkspace>(groupingWS_sptr);
if (groupWS)
{
g_log.debug() << "Extracting grouping from GroupingWorkspace (" << groupWS->name() << ")" << std::endl;
processGroupingWorkspace(groupWS, workspace, unUsedSpec);
}
else
{
//processWorkspace(groupingWS_sptr, workspace, unUsedSpec);
}
return;
}

// grouping described in a file
const std::string filename = getProperty("MapFile");
if ( ! filename.empty() )
{// The file property has been set so try to load the file
Expand All @@ -328,6 +351,8 @@ void GroupDetectors2::getGroups(API::MatrixWorkspace_const_sptr workspace,
}
return;
}

//manually specified grouping
const std::vector<specid_t> spectraList = getProperty("SpectraList");
const std::vector<detid_t> detectorList = getProperty("DetectorList");
const std::vector<size_t> indexList = getProperty("WorkspaceIndexList");
Expand Down Expand Up @@ -523,9 +548,9 @@ void GroupDetectors2::processXMLFile(std::string fname,
{
size_t wsid = ind->second;
wsindexes.push_back(wsid);
if ( unUsedSpec[wsid] != ( 1000 - INT_MAX ) )
if ( unUsedSpec[wsid] != ( USED ) )
{
unUsedSpec[wsid] = ( 1000 - INT_MAX );
unUsedSpec[wsid] = ( USED );
}
}
else
Expand Down Expand Up @@ -557,9 +582,9 @@ void GroupDetectors2::processXMLFile(std::string fname,
{
size_t wsid = ind->second;
wsindexes.push_back(wsid);
if ( unUsedSpec[wsid] != ( 1000 - INT_MAX ) )
if ( unUsedSpec[wsid] != ( USED ) )
{
unUsedSpec[wsid] = ( 1000 - INT_MAX );
unUsedSpec[wsid] = ( USED );
}
}
else
Expand All @@ -572,6 +597,82 @@ void GroupDetectors2::processXMLFile(std::string fname,
return;
}

/** Get groupings from XML file
* @param fname :: the full path name of the file to open
* @param workspace :: a pointer to the input workspace, used to get spectra indexes from numbers
* @param unUsedSpec :: the list of spectra indexes that have been not included in a group (so far)
*/
void GroupDetectors2::processGroupingWorkspace(GroupingWorkspace_const_sptr groupWS,
API::MatrixWorkspace_const_sptr workspace, std::vector<int64_t> &unUsedSpec)
{
//fill unUsedspectra with every target spectrum for now
const size_t nspecTarget=workspace->getNumberHistograms();

detid2index_map detIdToWiMap = workspace->getDetectorIDToWorkspaceIndexMap();


typedef std::map<size_t,std::set<size_t>> Group2SetMapType;
Group2SetMapType group2WSIndexSetmap;

const size_t nspec=groupWS->getNumberHistograms();
for (size_t i=0;i<nspec;++i)
{
//read spectra from groupingws
size_t groupid = static_cast<int> (groupWS->readY(i)[0]);
//group 0 is are unused spectra - don't process them
if (groupid > 0)
{
if (group2WSIndexSetmap.find(groupid) == group2WSIndexSetmap.end())
{
//not found - create an empty set
group2WSIndexSetmap.insert(std::make_pair(groupid, std::set<size_t>()));
}
//get a reference to the set
std::set<size_t>& targetWSIndexSet = group2WSIndexSetmap[groupid];

//translate to detectors
std::vector<detid_t> det_ids;
const Geometry::IDetector_const_sptr det = groupWS->getDetector(i);
Geometry::DetectorGroup_const_sptr detGroup = boost::dynamic_pointer_cast<const Geometry::DetectorGroup>(det);
if (detGroup)
{
det_ids = detGroup->getDetectorIDs();

}
else
{
det_ids.push_back(det->getID());
}

for (auto dit = det_ids.begin(); dit != det_ids.end(); ++ dit)
{
//translate detectors to target det ws indexes
detid_t det_id= *dit;
size_t targetWSIndex = detIdToWiMap[det_id];
targetWSIndexSet.insert(targetWSIndex);
//mark as used
if ( unUsedSpec[targetWSIndex] != ( USED ) )
{
unUsedSpec[targetWSIndex] = ( USED );
}
}
}
}

//Build m_GroupSpecInds (group -> list of ws indices)
for (auto dit = group2WSIndexSetmap.begin(); dit != group2WSIndexSetmap.end(); ++ dit)
{
size_t groupid = dit->first;
std::set<size_t>& targetWSIndexSet = dit->second;
std::vector<size_t> tempv;
tempv.assign( targetWSIndexSet.begin(), targetWSIndexSet.end() );
m_GroupSpecInds.insert(std::make_pair(groupid, tempv));
}

return;
}


/** The function expects that the string passed to it contains an integer number,
* it reads the number and returns it
* @param line :: a line read from the file, we'll interpret this
Expand Down
127 changes: 127 additions & 0 deletions Code/Mantid/Framework/DataHandling/test/GroupDetectors2Test.h
Expand Up @@ -536,6 +536,133 @@ class GroupDetectors2Test : public CxxTest::TestSuite
AnalysisDataService::Instance().remove("GDEventsOut");
}


void test_GroupingWorkspace_ThreeGroup_NoUngrouped_dontPreserveEvents_inplace()
{
dotestGroupingWorkspace(3, false, false,true,false);
}

void test_GroupingWorkspace_TwoGroup_Ungrouped_dontPreserveEvents_inplace()
{
dotestGroupingWorkspace(2, true, true,true,false);
}

void test_GroupingWorkspace_ThreeGroup_NoUngrouped_PreserveEvents_inplace()
{
dotestGroupingWorkspace(3, false, false,true,true);
}

void test_GroupingWorkspace_TwoGroup_Ungrouped_PreserveEvents_inplace()
{
dotestGroupingWorkspace(2, false, false,true,true);
}

void test_GroupingWorkspace_FourGroup_Ungrouped_PreserveEvents_Notinplace()
{
dotestGroupingWorkspace(4, true, true,true,false);
}

void dotestGroupingWorkspace(size_t numgroups=3, bool includeUngroupedDets =true, bool includeUngroupedDetsSetting=true, bool inplace = true, bool preserveEvents = true, int bankWidthInPixels=8 )
{
std::string nxsWSname("GroupDetectors2TestTarget_ws");
std::string groupWSName(nxsWSname + "_GROUP");
std::string outputws = nxsWSname + "_grouped";

// Create the fake event workspace
EventWorkspace_sptr inputW = WorkspaceCreationHelper::createEventWorkspaceWithFullInstrument(static_cast<int>(numgroups), bankWidthInPixels);
AnalysisDataService::Instance().addOrReplace(nxsWSname, inputW);


//-------- Check on the input workspace ---------------
TS_ASSERT(inputW);
if (!inputW) return;

//Create an axis for each pixel.
for (size_t pix=0; pix < inputW->getNumberHistograms(); pix++)
{
cow_ptr<Mantid::MantidVec> axis;
Mantid::MantidVec& xRef = axis.access();
xRef.resize(5);
for (int i = 0; i < 5; ++i)
xRef[i] = static_cast<double>(1) + i*1.0;
xRef[4] = 1e6;
//Set an X-axis
inputW->setX(pix, axis);
inputW->getEventList(pix).addEventQuickly( TofEvent(1000.0) );
}

// ------------ Create a grouping workspace to match -------------
auto groupW = boost::make_shared<GroupingWorkspace>(inputW->getInstrument());
AnalysisDataService::Instance().addOrReplace(nxsWSname + "_GROUP", groupW);
//fill in some groups
size_t startingGroupNo= 1;
size_t targetGroupNo = numgroups;
size_t targetSpectraCount = numgroups;
if (includeUngroupedDets)
{
--startingGroupNo;
++targetGroupNo;
}
size_t pixPerGroup = 0;
if (numgroups > 0)
{
pixPerGroup = groupW->getNumberHistograms()/targetGroupNo;
}
if (includeUngroupedDets)
{
targetSpectraCount += includeUngroupedDetsSetting?pixPerGroup+1:0;
}
for (size_t pix=0; pix < groupW->getNumberHistograms(); pix++)
{
size_t groupNo = startingGroupNo + (pix/pixPerGroup);
groupW->dataY(pix)[0] = groupNo;
}

// ------------ Create a grouping workspace by name -------------
GroupDetectors2 groupAlg;
groupAlg.initialize();
TS_ASSERT_THROWS_NOTHING( groupAlg.setPropertyValue("InputWorkspace", nxsWSname) );
if (inplace) outputws = nxsWSname;
TS_ASSERT_THROWS_NOTHING( groupAlg.setPropertyValue("OutputWorkspace", outputws) );

//This fake calibration file was generated using DiffractiongroupAlgsing2Test_helper.py
TS_ASSERT_THROWS_NOTHING( groupAlg.setPropertyValue("CopyGroupingFromWorkspace", groupWSName) );

TS_ASSERT_THROWS_NOTHING( groupAlg.setProperty("KeepUngroupedSpectra", includeUngroupedDetsSetting));
TS_ASSERT_THROWS_NOTHING( groupAlg.setProperty("PreserveEvents", preserveEvents) );
//OK, run the algorithm
TS_ASSERT_THROWS_NOTHING( groupAlg.execute(); );
TS_ASSERT( groupAlg.isExecuted() );

MatrixWorkspace_const_sptr output;
TS_ASSERT_THROWS_NOTHING( output = AnalysisDataService::Instance().retrieveWS<const MatrixWorkspace>(outputws) );
if (!output) return;

// ---- Did we keep the event workspace ----
EventWorkspace_const_sptr outputEvent;
TS_ASSERT_THROWS_NOTHING( outputEvent = boost::dynamic_pointer_cast<const EventWorkspace>(output) );
if (preserveEvents)
{
TS_ASSERT( outputEvent );
if (!outputEvent) return;
}
else
{
TS_ASSERT( !outputEvent );
}


TS_ASSERT_EQUALS( output->getNumberHistograms(), targetSpectraCount);

AnalysisDataService::Instance().remove(nxsWSname);
AnalysisDataService::Instance().remove(groupWSName);
if (!inplace) AnalysisDataService::Instance().remove(outputws);

}




private:
const std::string inputWS, outputBase, inputFile;
enum constants { NHIST = 6, NBINS = 4 };
Expand Down

0 comments on commit a87d018

Please sign in to comment.