Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/feature/9364_CopyInstrumentPar'
Browse files Browse the repository at this point in the history
  • Loading branch information
NickDraper committed May 30, 2014
2 parents 17c8685 + 275e709 commit 1669e65
Show file tree
Hide file tree
Showing 8 changed files with 310 additions and 42 deletions.
2 changes: 2 additions & 0 deletions Code/Mantid/Framework/API/inc/MantidAPI/ExperimentInfo.h
Expand Up @@ -73,6 +73,8 @@ namespace API

/// Replaces current parameter map with copy of given map
void replaceInstrumentParameters(const Geometry::ParameterMap & pmap);
/// exchange contents of current parameter map with contents of other map)
void swapInstrumentParameters(Geometry::ParameterMap & pmap);

/// Cache a lookup of grouped detIDs to member IDs
void cacheDetectorGroupings(const det2group_map & mapping);
Expand Down
10 changes: 10 additions & 0 deletions Code/Mantid/Framework/API/src/ExperimentInfo.cpp
Expand Up @@ -316,6 +316,16 @@ namespace API
{
this->m_parmap.reset(new ParameterMap(pmap));
}
//---------------------------------------------------------------------------------------
/**
* exchanges contents of current parameter map with contents of other map)
* @ pmap reference to parameter map which would exchange its contents with current map
*/
void ExperimentInfo::swapInstrumentParameters(Geometry::ParameterMap & pmap)
{
this->m_parmap->swap(pmap);
}


//---------------------------------------------------------------------------------------
/**
Expand Down
32 changes: 11 additions & 21 deletions Code/Mantid/Framework/Algorithms/src/CopyInstrumentParameters.cpp
@@ -1,11 +1,12 @@
/*WIKI*
Transfer an instrument from a giving workspace to a receiving workspace for the same instrument.
Transfer an instrument parameters from a giving workspace to a receiving workspace.
The instrument in of the receiving workspace is replaced by a copy of the instrument in the giving workspace
and so gains any manipulations such as calibration done to the instrument in the giving workspace.
The two workspaces can have spectra allocated to their detectors differently.
The instrument parameters in the receiving workspace are REPLACED (despite you can assume from the name of the algorithm)
by a copy of the instrument parameters in the giving workspace
so gaining any manipulations such as calibration done to the instrument in the giving workspace.
Does not work on workspaces with grouped detectors if some of the detectors were calibrated.
*WIKI*/
//----------------------------------------------------------------------
Expand Down Expand Up @@ -76,19 +77,6 @@ void CopyInstrumentParameters::exec()

Geometry::ParameterMap targMap;

//// vector of all components contained in the target instrument
//std::vector<IComponent_const_sptr> targComponents;
//// flattens instrument definition tree
//inst2->getChildren(targComponents,true);
//// multimap of existing instrument parameters
//std::multimap<std::string,IComponent const *> existingComponents;
//for(size_t i=0;i<targComponents.size();i++)
//{
// if (dynamic_cast<IDetector const *>(targComponents[i].get()))
// continue;
// existingComponents.insert(std::pair<std::string,IComponent const *>(targComponents[i]->getFullName(),targComponents[i].get()));
//}

auto it = givParams.begin();
for(;it!= givParams.end(); it++)
{
Expand Down Expand Up @@ -122,14 +110,16 @@ void CopyInstrumentParameters::exec()
}
targComp = spTargComp->getBaseComponent();
}
// merge maps for existing target component
auto param = it->second.get();
targMap.add(param->type(),targComp,param->name(),param->asString());

// create shared pointer to independent copy of original parameter. Would be easy and nice to have cow_pointer instead of shared_ptr in the parameter map.
auto param = Parameter_sptr(it->second->clone());
// add new parameter to the maps for existing target component
targMap.add(targComp, param);

}

// changed parameters
m_receivingWorkspace->replaceInstrumentParameters( targMap );
m_receivingWorkspace->swapInstrumentParameters(targMap);

}
else
Expand Down
109 changes: 109 additions & 0 deletions Code/Mantid/Framework/Algorithms/test/CopyInstrumentParametersTest.h
Expand Up @@ -21,6 +21,7 @@
#include "MantidGeometry/Instrument/ComponentHelper.h"
#include <stdexcept>


using namespace Mantid::Algorithms;
using namespace Mantid::API;
using namespace Mantid::Kernel;
Expand Down Expand Up @@ -191,6 +192,114 @@ class CopyInstrumentParametersTest : public CxxTest::TestSuite
CopyInstrumentParameters copyInstParam;


};


class CopyInstrumentParametersTestPerformance : public CxxTest::TestSuite
{
public:
// This pair of boilerplate methods prevent the suite being created statically
// This means the constructor isn't called when running other tests
static CopyInstrumentParametersTestPerformance *createSuite() { return new CopyInstrumentParametersTestPerformance(); }
static void destroySuite( CopyInstrumentParametersTestPerformance *suite ) { delete suite; }


CopyInstrumentParametersTestPerformance():
m_SourceWSName("SourceWS"),m_TargetWSName("TargWS")
{
size_t n_detectors=44327;
size_t n_Parameters=200;
// Create input workspace with parameterized instrument and put into data store
MatrixWorkspace_sptr ws1 = WorkspaceCreationHelper::create2DWorkspaceWithFullInstrument(static_cast<int>(n_detectors+2), 10, true,false,true,"Instr_calibrated");
AnalysisDataServiceImpl & dataStore = AnalysisDataService::Instance();
dataStore.add(m_SourceWSName, ws1);


Geometry::Instrument_const_sptr instrument = ws1->getInstrument();
Geometry::ParameterMap *pmap;
pmap = &(ws1->instrumentParameters());
for(size_t i=0;i<n_Parameters;i++)
{
// add auxiliary instrument parameters
pmap->addDouble(instrument.get(),"Param-"+boost::lexical_cast<std::string>(i),static_cast<double>(i*10));
}
// calibrate detectors;
for(size_t i=0;i<n_detectors;i++)
{
IComponent_const_sptr det =instrument->getDetector(static_cast<Mantid::detid_t>(i+1));
Geometry::ComponentHelper::moveComponent(*det, *pmap, V3D(sin(3.1415926*double(i)),cos(3.1415926*double(i/500)),7), Absolute );
}

// Create output workspace with another parameterized instrument and put into data store
MatrixWorkspace_sptr ws2 = WorkspaceCreationHelper::create2DWorkspaceWithFullInstrument(static_cast<int>(n_detectors), 10, true,false,true,"Instr_base");
dataStore.add(m_TargetWSName, ws2);


copyInstParam.initialize();

}

public:

void test_copy_performance()
{

// Set properties
TS_ASSERT_THROWS_NOTHING(copyInstParam.setPropertyValue("InputWorkspace", m_SourceWSName ));
TS_ASSERT_THROWS_NOTHING(copyInstParam.setPropertyValue("OutputWorkspace", m_TargetWSName ));


// Execute Algorithm, should warn but proceed
copyInstParam.setRethrows(true);

clock_t t_start = clock();
TS_ASSERT(copyInstParam.execute());
clock_t t_end = clock();

double seconds=static_cast<double>(t_end-t_start)/static_cast<double>(CLOCKS_PER_SEC);
std::cout<<" Time to copy all parameters is: "<<seconds<<" sec\n";

TS_ASSERT( copyInstParam.isExecuted() );
TS_ASSERT(copyInstParam.isInstrumentDifferent());

AnalysisDataServiceImpl & dataStore = AnalysisDataService::Instance();
MatrixWorkspace_sptr ws2 =dataStore.retrieveWS<API::MatrixWorkspace>(m_TargetWSName);
auto instr2=ws2->getInstrument();


std::set<std::string> param_names = instr2->getParameterNames();

for(auto it =param_names.begin(); it!=param_names.end();it++)
{
auto name = *it;
double num = boost::lexical_cast<double>(name.substr(6,name.size()-6));
double val = instr2->getNumberParameter(name)[0];
TS_ASSERT_DELTA(num*10,val,1.e-8);
}

// new detector allocation applied
size_t nDetectors = ws2->getNumberHistograms();
for(size_t i=0;i<nDetectors;i++)
{
IDetector_const_sptr deto1 = ws2->getDetector(i);
int id = deto1->getID();
V3D newPos1 = deto1->getPos();
TS_ASSERT_EQUALS( id, i+1);
TS_ASSERT_DELTA( newPos1.X() ,sin(3.1415926*double(i)), 0.0001);
TS_ASSERT_DELTA( newPos1.Y() ,cos(3.1415926*double(i/500)), 0.0001);
TS_ASSERT_DELTA( newPos1.Z() , 7, 1.e-6);

}

dataStore.remove(m_SourceWSName);
dataStore.remove(m_TargetWSName);

}
private:
CopyInstrumentParameters copyInstParam;
const std::string m_SourceWSName,m_TargetWSName;


};

#endif /*COPYINSTRUMENTPARAMETERSTEST_H_*/
Expand Up @@ -81,6 +81,9 @@ namespace Mantid
const std::string& name() const { return m_name; }
/// Parameter name
const char* nameAsCString() const{ return m_name.c_str(); }

/// type-independent clone method;
virtual Parameter * clone()const=0;

/// Returns the value of the property as a string
virtual std::string asString() const{return m_str_value;}
Expand Down Expand Up @@ -137,6 +140,8 @@ namespace Mantid
/// Get the value of the parameter
inline const Type& operator()()const{ return m_value; }

Parameter * clone()const
{ return new ParameterType(*this);}
private:
friend class ParameterMap;
friend class Parameter;
Expand Down
Expand Up @@ -59,6 +59,16 @@ namespace Geometry
File change history is stored at: <https://github.com/mantidproject/mantid>.
Code Documentation is available at: <http://doxygen.mantidproject.org>
*/
#ifndef HAS_UNORDERED_MAP_H
/// Parameter map iterator typedef
typedef std::multimap<const ComponentID,boost::shared_ptr<Parameter> >::iterator component_map_it;
typedef std::multimap<const ComponentID,boost::shared_ptr<Parameter> >::const_iterator component_map_cit;
#else
/// Parameter map iterator typedef
typedef std::tr1::unordered_multimap<const ComponentID,boost::shared_ptr<Parameter> >::iterator component_map_it;
typedef std::tr1::unordered_multimap<const ComponentID,boost::shared_ptr<Parameter> >::const_iterator component_map_cit;
#endif

class MANTID_GEOMETRY_DLL ParameterMap
{
public:
Expand Down Expand Up @@ -110,6 +120,12 @@ namespace Geometry
m_map.clear();
clearPositionSensitiveCaches();
}
/// method swaps two parameter maps contents each other. All caches contents is nullified (TO DO: it can be efficiently swapped too)
void swap(ParameterMap &other)
{
m_map.swap(other.m_map);
clearPositionSensitiveCaches();
}
/// Clear any parameters with the given name
void clearParametersByName(const std::string & name);

Expand Down Expand Up @@ -148,6 +164,8 @@ namespace Geometry
}
}
}
/// Method for adding a parameter providing shared pointer to it. The class stores share pointer and increment ref count to it
void add(const IComponent* comp,const boost::shared_ptr<Parameter> &param);
/** @name Helper methods for adding and updating parameter types */
/// Create or adjust "pos" parameter for a component
void addPositionCoordinate(const IComponent* comp,const std::string& name, const double value);
Expand Down Expand Up @@ -285,6 +303,11 @@ namespace Geometry
/// Retrieve a parameter by either creating a new one of getting an existing one
Parameter_sptr retrieveParameter(bool &created, const std::string & type, const IComponent* comp,
const std::string & name);
/// internal function to get position of the parameter in the parameter map
component_map_it getMapPlace(const IComponent* comp,const char *name, const char * type);
///const version of the internal function to get position of the parameter in the parameter map
component_map_cit getMapPlace(const IComponent* comp,const char *name, const char * type)const;


/// internal parameter map instance
pmap m_map;
Expand Down

0 comments on commit 1669e65

Please sign in to comment.