Commit b5bd1bf4 authored by Karl Palmen's avatar Karl Palmen
Browse files

Merge branch 'master' of github.com:mantidproject/mantid

parents 11ccd43c cd7d0a04
......@@ -6,6 +6,11 @@
# project settings should be included in the relevant CMakeLists.txt file
# for that project.
# Get the GCC version
EXEC_PROGRAM(${CMAKE_CXX_COMPILER} ARGS --version OUTPUT_VARIABLE _compiler_output)
STRING(REGEX REPLACE ".*([0-9]\\.[0-9]\\.[0-9]).*" "\\1" GCC_COMPILER_VERSION ${_compiler_output})
MESSAGE(STATUS "gcc version: ${GCC_COMPILER_VERSION}")
# Global warning flags.
set( GNUFLAGS "-Wall -Wextra -Wconversion -Winit-self -Wpointer-arith -Wcast-qual -Wcast-align -Woverloaded-virtual -fno-common" )
# Disable some warnings about deprecated headers and type conversions that
......@@ -13,7 +18,12 @@ set( GNUFLAGS "-Wall -Wextra -Wconversion -Winit-self -Wpointer-arith -Wcast-qua
# -Wno-deprecated: Do not warn about use of deprecated headers.
# -Wno-write-strings: Do not warn about deprecated conversions of char*->const char*
# -Wno-unused-result: Do not warn about unused return values in some C functions
set( GNUFLAGS "${GNUFLAGS} -Wno-deprecated -Wno-write-strings -Wno-unused-result")
set( GNUFLAGS "${GNUFLAGS} -Wno-deprecated -Wno-write-strings")
# Check if we have a new enough version for this flag
IF (GCC_COMPILER_VERSION VERSION_GREATER "4.3")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-result")
ENDIF (GCC_COMPILER_VERSION VERSION_GREATER "4.3")
# Add some options for debug build to help the Zoom profiler
set( CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -fno-omit-frame-pointer" )
......
diff --git a/pyport.h b/pyport.h
--- a/pyport.h
+++ b/pyport.h
@@ -657,6 +657,9 @@
#endif
#ifdef _PY_PORT_CTYPE_UTF8_ISSUE
+
+#ifndef __cplusplus
+
#include <ctype.h>
#include <wctype.h>
#undef isalnum
@@ -673,7 +676,11 @@
#define tolower(c) towlower(btowc(c))
#undef toupper
#define toupper(c) towupper(btowc(c))
-#endif
+
+#endif /* !__cplusplus */
+
+
+#endif /* _PY_PORT_CTYPE_UTF8_ISSUE */
/* Declarations for symbol visibility.
......@@ -81,30 +81,33 @@ class DLLExport AnalysisDataServiceImpl : public Kernel::DataService<API::Worksp
//@}
public:
/// Overwridden add member to attach the name to the workspace when a workspace object is added to the service
virtual void add( const std::string& name, const boost::shared_ptr<API::Workspace>& workspace)
{
//Attach the name to the workspace
if( workspace.get() ) workspace->setName(name);
Kernel::DataService<API::Workspace>::add(name, workspace);
}
/// Overwridden addOrReplace member to attach the name to the workspace when a workspace object is added to the service
virtual void addOrReplace( const std::string& name, const boost::shared_ptr<API::Workspace>& workspace)
{
//Attach the name to the workspace
if( workspace.get() ) workspace->setName(name);
Kernel::DataService<API::Workspace>::addOrReplace(name, workspace);
}
/// Return the list of illegal characters as one string
const std::string & illegalCharacters() const;
/// Set the list of illegal characeters
void setIllegalCharacterList(const std::string &);
/// Is the given name a valid name for an object in the ADS
const std::string isValid(const std::string & name) const;
/// Overwridden add member to attach the name to the workspace when a workspace object is added to the service
virtual void add( const std::string& name, const boost::shared_ptr<API::Workspace>& workspace);
/// Overwridden addOrReplace member to attach the name to the workspace when a workspace object is added to the service
virtual void addOrReplace( const std::string& name, const boost::shared_ptr<API::Workspace>& workspace);
private:
/// Checks the name is valid, throwing if not
void verifyName(const std::string & name);
friend struct Mantid::Kernel::CreateUsingNew<AnalysisDataServiceImpl>;
// Constructors
/// Constructor
AnalysisDataServiceImpl();
/// Private, unimplemented copy constructor
AnalysisDataServiceImpl(const AnalysisDataServiceImpl&);
/// Private, unimplemented copy assignment operator
AnalysisDataServiceImpl& operator=(const AnalysisDataServiceImpl&);
/// Private destructor
virtual ~AnalysisDataServiceImpl();
/// The string of illegal characters
std::string m_illegalChars;
};
///Forward declaration of a specialisation of SingletonHolder for AnalysisDataServiceImpl (needed for dllexport/dllimport) and a typedef for it.
......
......@@ -96,11 +96,11 @@ namespace Mantid
/// Build and populate the NearestNeighbours object
void buildNearestNeighbours(const bool ignoreMaskedDetectors=false) const;
/// Query the NearestNeighbours object for a detector
std::map<specid_t, double> getNeighbours(const Mantid::Geometry::IDetector *comp, const double radius = 0.0, const bool ignoreMaskedDetectors=false) const;
std::map<specid_t, Mantid::Kernel::V3D> getNeighbours(const Mantid::Geometry::IDetector *comp, const double radius = 0.0, const bool ignoreMaskedDetectors=false) const;
/// Query the NearestNeighbours object for a given spectrum index using a search radius
std::map<specid_t, double> getNeighbours(specid_t spec, const double radius, const bool ignoreMaskedDetectors=false) const;
std::map<specid_t, Mantid::Kernel::V3D> getNeighbours(specid_t spec, const double radius, const bool ignoreMaskedDetectors=false) const;
/// Query the NearestNeighbours object for a given spectrum index using the direct number of nearest neighbours
std::map<specid_t, double> getNeighboursExact(specid_t spec, const int nNeighbours, const bool ignoreMaskedDetectors=false) const;
std::map<specid_t, Mantid::Kernel::V3D> getNeighboursExact(specid_t spec, const int nNeighbours, const bool ignoreMaskedDetectors=false) const;
//@}
/// Const access to the spectra-detector map
......
......@@ -372,25 +372,24 @@ namespace Mantid
}
/** Checks whether the entered output workspace is valid.
* To be valid the only thing it needs is a name.
* To be valid the only thing it needs is a name that is allowed by the ADS, @see AnalysisDataServiceImpl
* @returns A user level description of the problem or "" if it is valid.
*/
std::string isValidOutputWs() const
{
if ( !this->value().empty() )
std::string error("");
const std::string value = this->value();
if( !value.empty() )
{
//it has a name and that is enough so return the success
return "";
// Will the ADS accept it
error = AnalysisDataService::Instance().isValid(value);
}
else
{
std::string error;
if( m_optional ) return "";
//Return a user level error
error = "Enter a name for the Output workspace";
return error;
if( m_optional ) error = ""; // Optional ones don't need a name
else error = "Enter a name for the Output workspace";
}
return error;
}
/** Checks whether the entered workspace (that by this point we've found is not in the ADS)
......
#include "MantidAPI/AnalysisDataService.h"
#include "MantidAPI/WorkspaceTracer.h"
#include "MantidKernel/Strings.h"
namespace Mantid
{
namespace API
{
AnalysisDataServiceImpl::AnalysisDataServiceImpl()
:Mantid::Kernel::DataService<Mantid::API::Workspace>("AnalysisDataService")
{
}
AnalysisDataServiceImpl::~AnalysisDataServiceImpl()
{
}
namespace API
{
//-------------------------------------------------------------------------
// Public methods
//-------------------------------------------------------------------------
/**
* Is the given name a valid name for an object in the ADS
* @param name A string containing a possible name for an object in the ADS
* @return An empty string if the name is valid or an error message stating the problem
* if the name is unacceptable.
*/
const std::string AnalysisDataServiceImpl::isValid(const std::string & name) const
{
std::string error("");
const std::string & illegal = illegalCharacters();
if( illegal.empty() ) return error; //Quick route out.
const size_t length = name.size();
for(size_t i = 0; i < length; ++i)
{
if( illegal.find_first_of(name[i]) != std::string::npos )
{
std::ostringstream strm;
strm << "Invalid object name '" << name << "'. Names cannot contain any of the following characters: " << illegal;
error = strm.str();
break;
}
}
return error;
}
/**
* Overwridden add member to attach the name to the workspace when a workspace object is added to the service
* If the name already exists then this throws a std::runtime_error
* @param name The name of the object
* @param workspace The shared pointer to the workspace to store
*/
void AnalysisDataServiceImpl::add( const std::string& name, const boost::shared_ptr<API::Workspace>& workspace)
{
verifyName(name);
//Attach the name to the workspace
if( workspace ) workspace->setName(name);
Kernel::DataService<API::Workspace>::add(name, workspace);
}
/**
* Overwridden addOrReplace member to attach the name to the workspace when a workspace object is added to the service.
* This will overwrite one of the same name
* @param name The name of the object
* @param workspace The shared pointer to the workspace to store
*/
void AnalysisDataServiceImpl::addOrReplace( const std::string& name, const boost::shared_ptr<API::Workspace>& workspace)
{
verifyName(name);
//Attach the name to the workspace
if( workspace ) workspace->setName(name);
Kernel::DataService<API::Workspace>::addOrReplace(name, workspace);
}
//-------------------------------------------------------------------------
// Private methods
//-------------------------------------------------------------------------
/**
* Constructor
*/
AnalysisDataServiceImpl::AnalysisDataServiceImpl()
:Mantid::Kernel::DataService<Mantid::API::Workspace>("AnalysisDataService"), m_illegalChars()
{
}
/**
* Destructor
*/
AnalysisDataServiceImpl::~AnalysisDataServiceImpl()
{
}
/**
* Return a string containing the characters not allowed in names objects within ADS
* @returns A n array of c strings containing the following characters: " +-/*\%<>&|^~=!@()[]{},:.`$?"
*/
const std::string & AnalysisDataServiceImpl::illegalCharacters() const
{
return m_illegalChars;
}
/**
* Set the list of illegal characeters
* @param A string containing the characters, as one long string, that are not to be accepted by the ADS
* NOTE: This only affects further additions to the ADS
*/
void AnalysisDataServiceImpl::setIllegalCharacterList(const std::string & illegalChars)
{
m_illegalChars = illegalChars;
}
/**
* Checks the name is valid
* @param name A string containing the name to check. If the name is invalid a std::invalid_argument is thrown
*/
void AnalysisDataServiceImpl::verifyName(const std::string & name)
{
const std::string error = isValid(name);
if( !error.empty() )
{
throw std::invalid_argument(error);
}
}
} // Namespace API
} // Namespace API
} // Namespace Mantid
......@@ -355,7 +355,7 @@ namespace Mantid
* @param ignoreMaskedDetectors :: flag indicating that masked detectors should be ignored. True to ignore detectors.
* @return map of DetectorID to distance for the nearest neighbours
*/
std::map<specid_t, double> MatrixWorkspace::getNeighbours(const IDetector *comp, const double radius, const bool ignoreMaskedDetectors) const
std::map<specid_t, V3D> MatrixWorkspace::getNeighbours(const IDetector *comp, const double radius, const bool ignoreMaskedDetectors) const
{
if ( !m_nearestNeighbours )
{
......@@ -368,7 +368,7 @@ namespace Mantid
{
throw Kernel::Exception::NotFoundError("MatrixWorkspace::getNeighbours - Cannot find spectrum number for detector", comp->getID());
}
std::map<specid_t, double> neighbours = m_nearestNeighbours->neighbours(spectra[0], radius);
std::map<specid_t, V3D> neighbours = m_nearestNeighbours->neighbours(spectra[0], radius);
return neighbours;
}
......@@ -381,13 +381,13 @@ namespace Mantid
* @param ignoreMaskedDetectors :: flag indicating that masked detectors should be ignored. True to ignore detectors.
* @return map of DetectorID to distance for the nearest neighbours
*/
std::map<specid_t, double> MatrixWorkspace::getNeighbours(specid_t spec, const double radius, bool ignoreMaskedDetectors) const
std::map<specid_t, V3D> MatrixWorkspace::getNeighbours(specid_t spec, const double radius, bool ignoreMaskedDetectors) const
{
if ( !m_nearestNeighbours )
{
m_nearestNeighbours.reset(m_nearestNeighboursFactory->create(this->getInstrument(), *m_spectraMap, ignoreMaskedDetectors));
}
std::map<specid_t, double> neighbours = m_nearestNeighbours->neighbours(spec, radius);
std::map<specid_t, V3D> neighbours = m_nearestNeighbours->neighbours(spec, radius);
return neighbours;
}
......@@ -399,13 +399,13 @@ namespace Mantid
* @param ignoreMaskedDetectors :: flag indicating that masked detectors should be ignored. True to ignore detectors.
* @return map of DetectorID to distance for the nearest neighbours
*/
std::map<specid_t, double> MatrixWorkspace::getNeighboursExact(specid_t spec, const int nNeighbours, bool ignoreMaskedDetectors) const
std::map<specid_t, V3D> MatrixWorkspace::getNeighboursExact(specid_t spec, const int nNeighbours, bool ignoreMaskedDetectors) const
{
if ( !m_nearestNeighbours )
{
m_nearestNeighbours.reset(m_nearestNeighboursFactory->create(this->getInstrument(), *m_spectraMap, ignoreMaskedDetectors));
}
std::map<specid_t, double> neighbours = m_nearestNeighbours->neighbours(spec, false, nNeighbours);
std::map<specid_t, V3D> neighbours = m_nearestNeighbours->neighbours(spec, false, nNeighbours);
return neighbours;
}
......
......@@ -12,45 +12,165 @@ class AnalysisDataServiceTest : public CxxTest::TestSuite
{
public:
void testAdd()
void test_IsValid_Returns_An_Empty_String_For_A_Valid_Name_When_All_CharsAre_Allowed()
{
Workspace_sptr space;
TS_ASSERT_THROWS_NOTHING( AnalysisDataService::Instance().add("MySpace",space));
Workspace_sptr space2;
TS_ASSERT_THROWS( AnalysisDataService::Instance().add("MySpace",space2),std::runtime_error);
//clean up the ADS for other tests
AnalysisDataService::Instance().remove("MySpace");
AnalysisDataServiceImpl & ads = AnalysisDataService::Instance();
TS_ASSERT_EQUALS(ads.isValid("CamelCase"), "");
TS_ASSERT_EQUALS(ads.isValid("_Has_Underscore"), "");
TS_ASSERT_EQUALS(ads.isValid("alllowercase"), "");
TS_ASSERT_EQUALS(ads.isValid("ALLUPPERCASE"), "");
}
void testAddOrReplace()
void test_IsValid_Returns_An_Error_String_For_A_Invalid_Name()
{
Workspace_sptr space;
TS_ASSERT_THROWS_NOTHING(AnalysisDataService::Instance().add("MySpaceAddOrReplace",space));
TS_ASSERT_THROWS(AnalysisDataService::Instance().add("MySpaceAddOrReplace",space),std::runtime_error);
TS_ASSERT_THROWS_NOTHING(AnalysisDataService::Instance().addOrReplace("MySpaceAddOrReplace",space));
//clean up the ADS for other tests
AnalysisDataService::Instance().remove("MySpaceAddOrReplace");
AnalysisDataServiceImpl & ads = AnalysisDataService::Instance();
const std::string illegalChars = " +-/*\\%<>&|^~=!@()[]{},:.`$'\"?";
ads.setIllegalCharacterList(illegalChars);
const size_t nchars(illegalChars.size());
for( size_t i = 0; i < nchars; ++i )
{
std::ostringstream name;
name << "NotAllowed" << illegalChars[i];
std::ostringstream expectedError;
expectedError << "Invalid object name '" << name.str() << "'. Names cannot contain any of the following characters: " << illegalChars;
TS_ASSERT_EQUALS(ads.isValid(name.str()), expectedError.str());
}
// Clean up
ads.setIllegalCharacterList("");
}
void test_Add_With_Name_That_Has_No_Special_Chars_Is_Accpeted()
{
const std::string name = "MySpace";
TS_ASSERT_THROWS_NOTHING(addToADS(name));
TS_ASSERT(isInADS(name));
TS_ASSERT_THROWS_NOTHING(removeFromADS(name));
}
void test_Adding_A_Second_Item_Of_Same_Name_Throws_Runtime_Error()
{
const std::string name = "SameName";
TS_ASSERT_THROWS_NOTHING(addToADS(name));
// Adding again will throw
TS_ASSERT_THROWS(addToADS(name), std::runtime_error);
TS_ASSERT_THROWS_NOTHING(removeFromADS(name));
}
void test_Add_With_Name_Containing_Special_Chars_Throws_Invalid_Argument()
{
this->doAddingOnInvalidNameTests(false/*Don't use replace*/);
}
void test_AddOrReplace_With_Name_Containing_Special_Chars_Throws_Invalid_Argument()
{
this->doAddingOnInvalidNameTests(true/*Use replace*/);
}
void test_Add_Then_Changing_Illegal_Char_List_Only_Affects_Future_Additions()
{
// The ADS shouldcurrently accept anything
const std::string illegalChar(".");
std::string name = "ContainsIllegal" + illegalChar;
TS_ASSERT_THROWS_NOTHING(addToADS(name));
// Ban period characters
AnalysisDataService::Instance().setIllegalCharacterList(illegalChar);
// Check we still have the original one
TS_ASSERT_EQUALS(isInADS(name), true);
std::string banned = "Also.Contains.Illegal";
// This should not be allowed now.
TS_ASSERT_THROWS(addToADS(banned), std::invalid_argument);
AnalysisDataService::Instance().remove(name);
// Clear up
AnalysisDataService::Instance().setIllegalCharacterList("");
}
void test_AddOrReplace_Does_Not_Throw_When_Adding_Object_That_Has_A_Name_That_Already_Exists()
{
const std::string name("MySpaceAddOrReplace");
TS_ASSERT_THROWS_NOTHING(addOrReplaceToADS(name));
TS_ASSERT_THROWS(addToADS(name),std::runtime_error);
TS_ASSERT_THROWS_NOTHING(addOrReplaceToADS(name));
TS_ASSERT_THROWS_NOTHING(removeFromADS(name));
}
void testRemove()
{
Workspace_sptr space;
AnalysisDataService::Instance().add("MySpace",space);
TS_ASSERT_THROWS_NOTHING(AnalysisDataService::Instance().remove("MySpace"));
TS_ASSERT_THROWS(AnalysisDataService::Instance().retrieve("MySpace"),std::runtime_error);
const std::string name("MySpace");
addToADS(name);
TS_ASSERT_THROWS_NOTHING(removeFromADS(name));
TS_ASSERT_THROWS(AnalysisDataService::Instance().retrieve(name),std::runtime_error);
// Remove should not throw but give a warning in the log file, changed by LCC 05/2008
TS_ASSERT_THROWS_NOTHING(AnalysisDataService::Instance().remove("ttttt"));
TS_ASSERT_THROWS_NOTHING(removeFromADS("ttttt"));
}
void testRetrieve()
{
Workspace_sptr work;
AnalysisDataService::Instance().add("MySpace", work);
const std::string name("MySpace");
Workspace_sptr work = addToADS(name);
Workspace_sptr workBack;
TS_ASSERT_THROWS_NOTHING(workBack = AnalysisDataService::Instance().retrieve("MySpace"));
TS_ASSERT_THROWS_NOTHING(workBack = AnalysisDataService::Instance().retrieve(name));
TS_ASSERT_EQUALS(work, workBack);
//clean up the ADS for other tests
AnalysisDataService::Instance().remove("MySpace");
removeFromADS(name);
}
private:
/// If replace=true then usea addOrReplace
void doAddingOnInvalidNameTests(bool replace)
{
const std::string illegalChars = " +-/*\\%<>&|^~=!@()[]{},:.`$'\"?";
AnalysisDataService::Instance().setIllegalCharacterList(illegalChars);
const size_t nchars(illegalChars.size());
const std::string allowed("WsName");
for( int i = 0; i < nchars; ++i )
{
//Build illegal name
std::ostringstream name;
name << allowed << illegalChars[i] << allowed << illegalChars[i] << allowed;
// Add it
std::ostringstream errorMsg;
errorMsg << "Name containing illegal character " << illegalChars[i] << " is not allowed but ADS did not throw.";
if( replace )
{
TSM_ASSERT_THROWS(errorMsg.str(), addToADS(name.str()), std::invalid_argument);
}
else
{
TSM_ASSERT_THROWS(errorMsg.str(), addOrReplaceToADS(name.str()), std::invalid_argument);
}
bool stored = isInADS(name.str());
TS_ASSERT_EQUALS(stored, false);
if( stored ) removeFromADS(name.str()); // Clear up if the test fails so that it dones't impact on others.
}
// Clean up
AnalysisDataService::Instance().setIllegalCharacterList("");
}
/// Add a ptr to the ADS with the given name
Workspace_sptr addToADS(const std::string & name)
{
Workspace_sptr space = Workspace_sptr();
AnalysisDataService::Instance().add(name, space);
return space;
}
/// Add or replace the given name
void addOrReplaceToADS(const std::string & name)
{
AnalysisDataService::Instance().addOrReplace(name, Workspace_sptr());
}
void removeFromADS(const std::string & name)
{
AnalysisDataService::Instance().remove(name);
}
bool isInADS(const std::string & name)
{
return AnalysisDataService::Instance().doesExist(name);
}
};
......
......@@ -45,6 +45,7 @@ public:
// Two optional properties of different types
wsp4 = new WorkspaceProperty<Workspace>("workspace4","",Direction::Input, true);
wsp5 = new WorkspaceProperty<WorkspaceTester2>("workspace5","",Direction::Input, true);
wsp6 = new WorkspaceProperty<Workspace>("InvalidNameTest","",Direction::Output);
}
~WorkspacePropertyTest()
......@@ -54,6 +55,7 @@ public:
delete wsp3;
delete wsp4;
delete wsp5;
delete wsp6;
}
void testConstructor()
......@@ -96,10 +98,18 @@ public:
TS_ASSERT_EQUALS( wsp2->isValid(), "Enter a name for the Output workspace" );
TS_ASSERT_EQUALS( wsp3->isValid(), "Workspace \"ws3\" was not found in the Analysis Data Service" );
TS_ASSERT_EQUALS( wsp4->isValid(), "");
TS_ASSERT_EQUALS( wsp6->isValid(), "Enter a name for the Output workspace");
// Setting the workspace name should make wsp2 (an output workspace) valid
// Setting a valid workspace name should make wsp2 (an output workspace) valid
TS_ASSERT_EQUALS( wsp2->setValue("ws2"), "" );
TS_ASSERT_EQUALS( wsp2->isValid(), "" );
// Setting an invalid name should make wsp6 invalid
const std::string illegalChars = " +-/*\\%<>&|^~=!@()[]{},:.`$'\"?";
AnalysisDataService::Instance().setIllegalCharacterList(illegalChars);
std::string error = "Invalid object name 'ws6-1'. Names cannot contain any of the following characters: " + illegalChars;
TS_ASSERT_EQUALS( wsp6->setValue("ws6-1"), error);
TS_ASSERT_EQUALS( wsp6->isValid(), error);
AnalysisDataService::Instance().setIllegalCharacterList("");
WorkspaceFactory::Instance().subscribe<WorkspaceTester1>("WorkspacePropertyTest");
WorkspaceFactory::Instance().subscribe<WorkspaceTester2>("WorkspacePropertyTest2");
......@@ -231,6 +241,7 @@ private:
WorkspaceProperty<WorkspaceTester2> *wsp3;
WorkspaceProperty<Workspace> *wsp4;
WorkspaceProperty<WorkspaceTester2> *wsp5;
WorkspaceProperty<Workspace> *wsp6;
};
#endif /*WORKSPACEPROPERTYTEST_H_*/
......@@ -64,7 +64,7 @@ public:
/// Virtual destructor
virtual ~AbsorptionCorrection() {}
/// Algorithm's category for identification
virtual const std::string category() const { return "Absorption Corrections"; }
virtual const std::string category() const { return "CorrectionFunctions\\AbsorptionCorrections"; }
protected:
/** A virtual function in which additional properties of an algorithm should be declared.
......