Commit 54501509 authored by Janik Zikovsky's avatar Janik Zikovsky
Browse files

Fixes #3842: Merged changes from Branch Iteration31 to trunk.

parent e17c7245
......@@ -20,6 +20,7 @@ set ( SRC_FILES
src/CoordTransform.cpp
src/CostFunctionFactory.cpp
src/DeprecatedAlgorithm.cpp
src/EnabledWhenWorkspaceIsType.cpp
src/ExperimentInfo.cpp
src/Expression.cpp
src/FileFinder.cpp
......@@ -113,6 +114,7 @@ set ( INC_FILES
inc/MantidAPI/DeclareUserAlg.h
inc/MantidAPI/DeprecatedAlgorithm.h
inc/MantidAPI/DllConfig.h
inc/MantidAPI/EnabledWhenWorkspaceIsType.h
inc/MantidAPI/ExperimentInfo.h
inc/MantidAPI/Expression.h
inc/MantidAPI/FileFinder.h
......@@ -205,6 +207,7 @@ set ( TEST_FILES
test/CompositeFunctionTest.h
test/CoordTransformTest.h
test/CostFunctionFactoryTest.h
test/EnabledWhenWorkspaceIsTypeTest.h
test/ExperimentInfoTest.h
test/ExpressionTest.h
test/FileFinderTest.h
......
#ifndef MANTID_API_ENABLEDWHENWORKSPACEISTYPE_H_
#define MANTID_API_ENABLEDWHENWORKSPACEISTYPE_H_
#include "MantidKernel/System.h"
#include "MantidKernel/IPropertySettings.h"
#include "MantidKernel/DataService.h"
#include "MantidKernel/SingletonHolder.h"
#include "MantidKernel/Exception.h"
#include "MantidAPI/Workspace.h"
#include "MantidKernel/IPropertyManager.h"
#include "MantidAPI/AnalysisDataService.h"
namespace Mantid
{
namespace API
{
/** Show a property as enabled when the workspace pointed to by another
* is of a given type
@author Janik Zikovsky
@date 2011-09-21
Copyright © 2011 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://svn.mantidproject.org/mantid/trunk/Code/Mantid>
Code Documentation is available at: <http://doxygen.mantidproject.org>
*/
template <typename T>
class DLLExport EnabledWhenWorkspaceIsType : public Kernel::IPropertySettings
{
public:
//--------------------------------------------------------------------------------------------
/** Constructor
* @param algo :: ptr to the calling Algorithm (type IPropertyManager)
* @param otherPropName :: Name of the OTHER property that we will check.
* @param enabledSetting :: Set Enabled on this property to this value when the workspace is of type T. Default true.
*/
EnabledWhenWorkspaceIsType(const Mantid::Kernel::IPropertyManager * algo, std::string otherPropName,
bool enabledSetting = true)
: IPropertySettings(algo),
m_otherPropName(otherPropName), m_enabledSetting(enabledSetting)
{
}
/// Destructor
virtual ~EnabledWhenWorkspaceIsType()
{}
//--------------------------------------------------------------------------------------------
/** Does the validator fulfill the criterion based on the
* other property values?
* @return true if fulfilled or if any problem was found (missing property, e.g.).
*/
virtual bool fulfillsCriterion() const
{
// Find the property
if (this->m_propertyManager == NULL) return true;
Mantid::Kernel::Property * prop = NULL;
try
{
prop = this->m_propertyManager->getPointerToProperty(m_otherPropName);
}
catch (Mantid::Kernel::Exception::NotFoundError&)
{
return true; //Property not found. Ignore
}
if (!prop) return true;
// Value of the other property
std::string propValue = prop->value();
if (propValue.empty())
return true;
Workspace_sptr ws;
try
{
ws = Mantid::API::AnalysisDataService::Instance().retrieve(propValue);
}
catch (...)
{
return true;
}
// Does it cast to the desired type?
boost::shared_ptr<T> castWS = boost::dynamic_pointer_cast<T>(ws);
if (castWS)
return m_enabledSetting;
else
return !m_enabledSetting;
}
//--------------------------------------------------------------------------------------------
/// Return true/false based on whether the other property satisfies the criterion
virtual bool isEnabled() const
{
return fulfillsCriterion();
}
//--------------------------------------------------------------------------------------------
/// Return true always
virtual bool isVisible() const
{
return true;
}
//--------------------------------------------------------------------------------------------
/// Make a copy of the present type of validator
virtual IPropertySettings * clone()
{
EnabledWhenWorkspaceIsType * out = new EnabledWhenWorkspaceIsType<T>(this->m_propertyManager, m_otherPropName, m_enabledSetting);
return out;
}
protected:
/// Name of the OTHER property that we will check.
std::string m_otherPropName;
/// Set Enabled to this.
bool m_enabledSetting;
};
} // namespace API
} // namespace Mantid
#endif /* MANTID_API_ENABLEDWHENWORKSPACEISTYPE_H_ */
......@@ -45,6 +45,7 @@ namespace API
virtual Mantid::Kernel::V3D getQLabFrame() const = 0;
virtual Mantid::Kernel::V3D getQSampleFrame() const = 0;
virtual bool findDetector() = 0;
virtual void setQSampleFrame(Mantid::Kernel::V3D QSampleFrame, double detectorDistance=1.0) = 0;
virtual void setQLabFrame(Mantid::Kernel::V3D QLabFrame, double detectorDistance=1.0) = 0;
......
#include "MantidAPI/EnabledWhenWorkspaceIsType.h"
#include "MantidKernel/System.h"
using namespace Mantid::Kernel;
using namespace Mantid::API;
namespace Mantid
{
namespace API
{
} // namespace Mantid
} // namespace API
#ifndef MANTID_API_ENABLEDWHENWORKSPACEISTYPETEST_H_
#define MANTID_API_ENABLEDWHENWORKSPACEISTYPETEST_H_
#include <cxxtest/TestSuite.h>
#include "MantidKernel/Timer.h"
#include "MantidKernel/System.h"
#include <iostream>
#include <iomanip>
#include "MantidAPI/EnabledWhenWorkspaceIsType.h"
#include "MantidKernel/PropertyManagerOwner.h"
#include "MantidKernel/EnabledWhenProperty.h"
#include "FakeObjects.h"
#include "MantidAPI/WorkspaceProperty.h"
using namespace Mantid;
using namespace Mantid::Kernel;
using namespace Mantid::API;
class EnabledWhenWorkspaceIsTypeTest : 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 EnabledWhenWorkspaceIsTypeTest *createSuite() { return new EnabledWhenWorkspaceIsTypeTest(); }
static void destroySuite( EnabledWhenWorkspaceIsTypeTest *suite ) { delete suite; }
class WorkspaceTesterSubClass: public WorkspaceTester
{
public:
int m_someMember;
};
void test_enable_disable()
{
boost::shared_ptr<WorkspaceTester> ws1(new WorkspaceTester);
boost::shared_ptr<WorkspaceTesterSubClass> ws2(new WorkspaceTesterSubClass);
AnalysisDataService::Instance().addOrReplace("tester", ws1);
AnalysisDataService::Instance().addOrReplace("testersub", ws2);
PropertyManagerOwner alg;
// Start with a regular property
alg.declareProperty(new WorkspaceProperty<>("InputWorkspace","",Direction::Input));
// Make a property with its validator. Will be enabled when that other one is NOT the default
alg.declareProperty("MyValidatorProp", 456);
alg.setPropertySettings("MyValidatorProp", new EnabledWhenWorkspaceIsType<WorkspaceTesterSubClass>(&alg, "InputWorkspace", true));
alg.declareProperty("MyValidatorProp2", 456);
alg.setPropertySettings("MyValidatorProp2", new EnabledWhenWorkspaceIsType<WorkspaceTesterSubClass>(&alg, "InputWorkspace", false));
Property * prop = alg.getPointerToProperty("MyValidatorProp");
Property * prop2 = alg.getPointerToProperty("MyValidatorProp2");
TS_ASSERT(prop); if (!prop) return;
TSM_ASSERT( "Property always returns visible.", prop->isVisible() )
TSM_ASSERT( "Property always returns valid.", prop->isValid().empty() )
TSM_ASSERT( "Starts off enabled because empty", prop->isEnabled());
alg.setProperty("InputWorkspace", "tester");
TSM_ASSERT( "Becomes disabled when the workspace is the wrong type", !prop->isEnabled());
alg.setProperty("InputWorkspace", "testersub");
TSM_ASSERT( "Becomes enabled when the workspace is correct type", prop->isEnabled());
TSM_ASSERT( "Starts disabled when the workspace is correct type", !prop2->isEnabled());
alg.setProperty("InputWorkspace", "tester");
TSM_ASSERT( "Becomes enabled when the workspace is the wrong type", prop2->isEnabled());
}
};
#endif /* MANTID_API_ENABLEDWHENWORKSPACEISTYPETEST_H_ */
......@@ -419,7 +419,6 @@ set ( TEST_FILES
test/LogarithmTest.h
test/MaskBinsTest.h
test/MedianDetectorTestTest.h
test/MemoryLeakTest.h
test/MergeRunsTest.h
test/MinusTest.h
test/MonteCarloAbsorptionTest.h
......
......@@ -22,8 +22,8 @@ DECLARE_ALGORITHM(GeneratePythonScript)
/// Sets documentation strings for this algorithm
void GeneratePythonScript::initDocs()
{
this->setWikiSummary("An Algorithm to generate a Python script file to reproduce the history of a workspace.");
this->setOptionalMessage("An Algorithm to generate a Python script file to reproduce the history of a workspace.");
this->setWikiSummary("An Algorithm to generate a Python script file to reproduce the history of a workspace.");
this->setOptionalMessage("An Algorithm to generate a Python script file to reproduce the history of a workspace.");
}
//----------------------------------------------------------------------------------------------
......@@ -31,13 +31,13 @@ void GeneratePythonScript::initDocs()
*/
void GeneratePythonScript::init()
{
declareProperty(new WorkspaceProperty<Workspace>("InputWorkspace","",Direction::Input), "An input workspace.");
declareProperty(new WorkspaceProperty<Workspace>("InputWorkspace","",Direction::Input), "An input workspace.");
std::vector<std::string> exts;
exts.push_back(".py");
std::vector<std::string> exts;
exts.push_back(".py");
declareProperty(new API::FileProperty("Filename","", API::FileProperty::Save, exts),
"The file into which the Python script will be generated.");
declareProperty(new API::FileProperty("Filename","", API::FileProperty::Save, exts),
"The file into which the Python script will be generated.");
}
//----------------------------------------------------------------------------------------------
......@@ -45,48 +45,48 @@ void GeneratePythonScript::init()
*/
void GeneratePythonScript::exec()
{
const Workspace_const_sptr ws = getProperty("InputWorkspace");
const std::string filename = getPropertyValue("Filename");
std::ofstream file(filename.c_str(), std::ofstream::trunc);
if (NULL == file)
{
g_log.error("Unable to create file: " + filename);
throw Exception::FileError("Unable to create file: " , filename);
}
// Get the algorithm histories of the workspace.
const WorkspaceHistory wsHistory = ws->getHistory();
// Cycle through the AlgorithHistory objects of the workspace, create a string for each one,
// and then add them to the list.
std::vector<AlgorithmHistory> algHistories = wsHistory.getAlgorithmHistories();
std::vector<AlgorithmHistory>::iterator algHistIter = algHistories.begin();
std::vector<std::string> orderedHists;
for( ; algHistIter != algHistories.end(); ++algHistIter)
{
orderedHists.push_back(
genAlgString(*algHistIter)
);
}
// Generate the python script from each of the Algorith strings, then write to file.
std::string generatedScript = "";
generatedScript += "######################################################################\n";
generatedScript += "#Python Script Generated by GeneratePythonScript Algorithm\n";
generatedScript += "######################################################################\n";
std::vector<std::string>::iterator m3_pIter;
for (m3_pIter=orderedHists.begin( );m3_pIter!=orderedHists.end( );m3_pIter++)
{
generatedScript += *m3_pIter + "\n";
}
file << generatedScript;
file.flush();
file.close();
const Workspace_const_sptr ws = getProperty("InputWorkspace");
const std::string filename = getPropertyValue("Filename");
std::ofstream file(filename.c_str(), std::ofstream::trunc);
if (NULL == file)
{
g_log.error("Unable to create file: " + filename);
throw Exception::FileError("Unable to create file: " , filename);
}
// Get the algorithm histories of the workspace.
const WorkspaceHistory wsHistory = ws->getHistory();
// Cycle through the AlgorithHistory objects of the workspace, create a string for each one,
// and then add them along with their order to a map.
std::vector<AlgorithmHistory> algHistories = wsHistory.getAlgorithmHistories();
std::vector<AlgorithmHistory>::iterator algHistIter = algHistories.begin();
std::map<size_t,std::string> orderedHistMap;
for( ; algHistIter != algHistories.end(); ++algHistIter)
{
orderedHistMap.insert(std::map<size_t,std::string>::value_type(
algHistIter->execCount(),
genAlgString(*algHistIter)
));
}
// Generate the python script from each of the Algorith strings, then write to file.
std::string generatedScript = "";
generatedScript += "######################################################################\n";
generatedScript += "#Python Script Generated by GeneratePythonScript Algorithm\n";
generatedScript += "######################################################################\n";
std::map<size_t,std::string>::iterator m3_pIter;
for (m3_pIter=orderedHistMap.begin( );m3_pIter!=orderedHistMap.end( );m3_pIter++)
{
generatedScript += m3_pIter->second + "\n";
}
file << generatedScript;
file.flush();
file.close();
}
//----------------------------------------------------------------------------------------------
/** Generate the line of script corresponding to the given AlgorithmHistory
......@@ -94,42 +94,42 @@ void GeneratePythonScript::exec()
* @param algHist :: AlgorithmHistory to generate a line in the script for.
* @returns - the generated string for the given algorithm.
*/
std::string GeneratePythonScript::genAlgString(const API::AlgorithmHistory &algHist)
std::string GeneratePythonScript::genAlgString(const API::AlgorithmHistory &algHist)
{
std::string algString = "";
// Get the details of this algorithm history.
const std::string name = algHist.name();
const int version = algHist.version();
// Create an unmanaged version of the algorithm, with witch we can compare the parameters later.
const IAlgorithm_sptr ialg_Sptr = AlgorithmManager::Instance().createUnmanaged(name,version);
if(ialg_Sptr)
{
ialg_Sptr->initialize();
}
// Get the properties of this algorithm history, loop through them, and generate
// a string with the appropriate parameters.
std::vector<Kernel::PropertyHistory> props = algHist.getProperties();
std::vector<Kernel::PropertyHistory>::iterator propsIter = props.begin();
for( ; propsIter != props.end(); ++propsIter)
{
std::string paramString = genParamString(*propsIter, ialg_Sptr, name);
// Miss out parameters that are empty.
if(paramString.length() != 0)
std::string algString = "";
// Get the details of this algorithm history.
const std::string name = algHist.name();
const int version = algHist.version();
// Create an unmanaged version of the algorithm, with with we can compare the parameters later.
const IAlgorithm_sptr ialg_Sptr = AlgorithmManager::Instance().createUnmanaged(name,version);
if(ialg_Sptr)
{
if(algString.length() != 0)
{
algString += ",";
}
algString += paramString;
ialg_Sptr->initialize();
}
}
return name + "(" + algString + ")";
// Get the properties of this algorithm history, loop through them, and generate
// a string with the appropriate parameters.
std::vector<Kernel::PropertyHistory> props = algHist.getProperties();
std::vector<Kernel::PropertyHistory>::iterator propsIter = props.begin();
for( ; propsIter != props.end(); ++propsIter)
{
std::string paramString = genParamString(*propsIter, ialg_Sptr, name);
// Miss out parameters that are empty.
if(paramString.length() != 0)
{
if(algString.length() != 0)
{
algString += ",";
}
algString += paramString;
}
}
return name + "(" + algString + ")";
}
//----------------------------------------------------------------------------------------------
/** Generate the parameter string (of format "[name]='[value]'") for the given PropertyHistory.
......@@ -140,64 +140,64 @@ std::string GeneratePythonScript::genAlgString(const API::AlgorithmHistory &algH
* @returns - the generated string for the given parameter.
*/
std::string GeneratePythonScript::genParamString(
const Kernel::PropertyHistory &propHist,
const API::IAlgorithm_sptr ialg_Sptr,
const std::string algHistName)
const Kernel::PropertyHistory &propHist,
const API::IAlgorithm_sptr ialg_Sptr,
const std::string algHistName)
{
std::string params = "";
const std::string name = propHist.name();
const std::string value = propHist.value();
const unsigned int direction = propHist.direction();
// See if the the property is an Output workspace.
bool outputWkspace = false;
if( ialg_Sptr->existsProperty(name) && direction == Mantid::Kernel::Direction::Output )
{
Property *p = ialg_Sptr->getProperty(name);
if( dynamic_cast<IWorkspaceProperty*>(p) ) outputWkspace = true;
}
// Only non-default properties should be included in the paramter list.
if(!propHist.isDefault())
{
// If the property name occurs in the unmanaged version of the Algorithm, then
// we should include it in the parameter list.
if( (algHistName == "Load" || ialg_Sptr->existsProperty(name) ) &&
(direction == Direction::Input || direction == Direction::InOut || outputWkspace) )
std::string params = "";
const std::string name = propHist.name();
const std::string value = propHist.value();
const unsigned int direction = propHist.direction();
// See if the the property is an Output workspace.
bool outputWkspace = false;
if( ialg_Sptr->existsProperty(name) && direction == Mantid::Kernel::Direction::Output )
{
if(params.length() != 0)
{
params += ",";
}
Property *p = ialg_Sptr->getProperty(name);
if( dynamic_cast<IWorkspaceProperty*>(p) ) outputWkspace = true;
}
params += sanitizePropertyName(name) + "='" + value + "'";
// Only non-default properties should be included in the paramter list.
if(!propHist.isDefault())
{
// If the property name occurs in the unmanaged version of the Algorithm, then
// we should include it in the parameter list.
if( (algHistName == "Load" || ialg_Sptr->existsProperty(name) ) &&
(direction == Direction::Input || direction == Direction::InOut || outputWkspace) )
{
if(params.length() != 0)
{
params += ",";
}
params += sanitizePropertyName(name) + "='" + value + "'";
}
}
}
return params;
return params;
}
//----------------------------------------------------------------------------------------------
/** Sanitises the property name.
*/
std::string GeneratePythonScript::sanitizePropertyName(const std::string & name)
{
std::string arg;
std::string::const_iterator sIter = name.begin();
std::string::const_iterator sEnd = name.end();
std::string arg;
std::string::const_iterator sIter = name.begin();
std::string::const_iterator sEnd = name.end();
for( ; sIter != sEnd; ++sIter )
{
int letter = (int)(*sIter);
if( (letter >= 48 && letter <= 57) || (letter >= 97 && letter <= 122) ||
(letter >= 65 && letter <= 90) )
for( ; sIter != sEnd; ++sIter )
{
arg.push_back(*sIter);
int letter = (int)(*sIter);
if( (letter >= 48 && letter <= 57) || (letter >= 97 && letter <= 122) ||
(letter >= 65 && letter <= 90) )
{
arg.push_back(*sIter);
}
}
}
return arg;
return arg;
}
} // namespace Algorithms
......