Commit 05032fb9 authored by Tim Martin's avatar Tim Martin Committed by Walter Lampl
Browse files

Add extra type checking to TrigComposite. Allow casting to generic...

Add extra type checking to TrigComposite. Allow casting to generic IParticleContainer interface. TODO add explicit check on cast
parent 4b3b8ed9
......@@ -18,6 +18,7 @@ atlas_depends_on_subdirs(
Control/AthContainersInterfaces
Control/AthLinks
Event/xAOD/xAODCore
Event/xAOD/xAODBase
Trigger/TrigConfiguration/TrigConfHLTData
Trigger/TrigEvent/TrigNavStructure
${extra_deps} )
......@@ -27,7 +28,7 @@ atlas_add_library( xAODTrigger
xAODTrigger/*.h xAODTrigger/versions/*.h xAODTrigger/versions/*.icc
Root/*.cxx
PUBLIC_HEADERS xAODTrigger
LINK_LIBRARIES AthContainers AthLinks xAODCore TrigConfHLTData TrigNavStructure ${extra_libs} )
LINK_LIBRARIES AthContainers AthLinks xAODCore xAODBase TrigConfHLTData TrigNavStructure ${extra_libs} )
atlas_add_dictionary( xAODTriggerDict
xAODTrigger/xAODTriggerDict.h
......
......@@ -160,25 +160,43 @@ namespace xAOD {
// Implementation for the link accessor functions
//
bool TrigComposite_v1::hasObjectLink( const std::string& name ) const {
bool TrigComposite_v1::hasObjectLink( const std::string& name, const CLID clid ) const {
// Since this function shouldn't throw exceptions too easily,
// let's be super careful here...
static Accessor< std::vector< std::string > > accNames( "linkColNames" );
if( ! accNames.isAvailable( *this ) ) {
static ConstAccessor< std::vector< std::string > > accNames( "linkColNames" );
static ConstAccessor< std::vector< uint32_t > > accCLIDs( "linkColClids" );
if( ! (accNames.isAvailable( *this ) || accCLIDs.isAvailable( *this) ) ) {
return false;
}
// The check itself is pretty simple:
const std::vector< std::string >& names = accNames( *this );
return ( std::find( names.begin(), names.end(), name ) != names.end() );
const std::vector< uint32_t >& clids = accCLIDs( *this );
std::vector<std::string>::const_iterator vecIt = std::find( names.begin(), names.end(), name );
if (vecIt == names.end()) {
return false; // Could not find name
}
if (clid != CLID_NULL) { // Also check against clid
const uint32_t storedCLID = clids.at( std::distance( names.begin(), vecIt ) );
if (clid == ClassID_traits< xAOD::IParticleContainer >::ID()) {
return derivesFromIParticle(storedCLID);
} else if (storedCLID != clid) { // Otherwise we require the ID to match
return false; // Type missmatch
}
}
return true; // Satisfied
}
bool TrigComposite_v1::hasObjectCollectionLinks( const std::string& collectionName ) const {
bool TrigComposite_v1::hasObjectCollectionLinks( const std::string& collectionName, const CLID clid ) const {
const std::string mangledName = collectionName + s_collectionSuffix;
return hasObjectLink( mangledName );
return hasObjectLink( mangledName, clid );
}
bool TrigComposite_v1::hasObjectLinkExact(const std::string& name, const uint32_t key, const uint16_t index, const uint32_t clid) const {
for (size_t i = 0; i < this->linkColNames().size(); ++i) {
if (this->linkColNames().at(i) != name) continue;
......@@ -190,6 +208,11 @@ namespace xAOD {
return false;
}
bool TrigComposite_v1::derivesFromIParticle(const CLID /*clid*/) const {
// It would be nice to include some logic here.
return true;
}
AUXSTORE_OBJECT_GETTER( TrigComposite_v1, std::vector< std::string >,
linkColNames )
AUXSTORE_OBJECT_GETTER( TrigComposite_v1, std::vector< uint32_t >,
......@@ -308,7 +331,7 @@ std::ostream& operator<<(std::ostream& os, const xAOD::TrigComposite_v1& tc) {
if (i != tc.linkColNames().size() - 1) os << std::endl;
}
if (tc.decisions().size()) {
os << std::endl << " N Decisions: '" << tc.decisions().size() << std::endl << " ";
os << std::endl << " N Decisions:" << tc.decisions().size() << std::endl << " ";
for (const TrigCompositeUtils::DecisionID id : tc.decisions()) os << id << ", ";
}
return os;
......
......@@ -25,7 +25,7 @@ namespace xAOD {
/// Auxiliary store for TrigComposite containers
///
/// This v2 changes the base class from ByteStreamAuxContainer_v1 to AuxContainerBase
/// for Run 3. Otherwise, it is the same.
/// for Run 3. It additionally adds "decisions" as a static member. Otherwise, it is the same.
///
/// $Date: 2019-01-23 $
///
......
......@@ -20,6 +20,7 @@ extern "C" {
#include "AthContainers/AuxElement.h"
#include "AthLinks/ElementLink.h"
#include "AthLinks/ElementLinkVector.h"
#include "xAODBase/IParticleContainer.h"
namespace TrigCompositeUtils{
typedef unsigned int DecisionID;
......@@ -95,8 +96,8 @@ namespace xAOD {
template< class CONTAINER >
bool setObjectLink( const std::string& name,
const ElementLink< CONTAINER >& link );
/// Check if a link to an object with a given name exists
bool hasObjectLink( const std::string& name ) const;
/// Check if a link to an object with a given name and type exists. CLID_NULL to not check type.
bool hasObjectLink( const std::string& name, const CLID clid = CLID_NULL ) const;
/// Get the link with the requested name
template< class CONTAINER >
ElementLink< CONTAINER >
......@@ -113,8 +114,8 @@ namespace xAOD {
template< class CONTAINER >
bool addObjectCollectionLinks( const std::string& collectionName,
const ElementLinkVector< CONTAINER >& links );
/// Check if links exist to a collection of objects with given name
bool hasObjectCollectionLinks( const std::string& collectionName ) const;
/// Check if links exist to a collection of objects with given name and type. CLID_NULL to not check type.
bool hasObjectCollectionLinks( const std::string& collectionName, const CLID clid = CLID_NULL) const;
/// Get a vector of all element links from the collection
template< class CONTAINER >
ElementLinkVector< CONTAINER >
......@@ -206,6 +207,14 @@ namespace xAOD {
/// Helper function, copy one link into this object
void copyLinkInternal(const xAOD::TrigComposite_v1& other, const size_t index, const std::string& newName);
/// Helper function. Check if the requested type can be down cast to an IParticle transient interface
bool derivesFromIParticle(const CLID clid) const;
/// Helper function. Contains type logic check for use during actual link retrieval. Throws on error.
template< class CONTAINER >
void checkTypes(const CLID storedCLID, const std::string& name) const;
static const std::string s_collectionSuffix;
}; // class TrigComposite_v1
......
......@@ -109,7 +109,7 @@ namespace xAOD {
return true;
}
}
template< class CONTAINER >
ElementLink< CONTAINER >
TrigComposite_v1::objectLink( const std::string& name ) const {
......@@ -118,14 +118,7 @@ namespace xAOD {
const std::vector< std::string >& names = linkColNames();
for( size_t i = 0; i < names.size(); ++i ) {
if( names[ i ] != name ) continue;
// Check that it is of the right type:
if( linkColClids()[ i ] != ClassID_traits< CONTAINER >::ID() ) {
const std::string typeName =
SG::normalizedTypeinfoName( typeid( CONTAINER ) );
throw std::runtime_error( "xAOD::TrigComposite::objectLink: "
"Wrong type (" + typeName + ") requested "
"for name \"" + name + "\"" );
}
checkTypes< CONTAINER >(linkColClids()[ i ], name);
// Construct the link:
return ElementLink< CONTAINER >( linkColKeys()[ i ],
linkColIndices()[ i ] );
......@@ -150,16 +143,7 @@ namespace xAOD {
for( size_t i = 0; i < names.size(); ++i ) {
if( names[ i ] != name ) continue;
// Check that it is of the right type:
if( linkColClids()[ i ] !=
ClassID_traits< DataVector< OBJECT > >::ID() ) {
const std::string typeName =
SG::normalizedTypeinfoName( typeid( OBJECT ) );
std::cerr << "xAOD::TrigComposite_v1::object WARNING Wrong type ("
<< typeName << ") requested for CLID "
<< linkColClids()[ i ] << " and name \"" << name
<< std::endl;
return 0;
}
checkTypes< DataVector< OBJECT > >(linkColClids()[ i ], name);
// Create a temporary ElementLink:
ElementLink< DataVector< OBJECT > > link( linkColKeys()[ i ],
linkColIndices()[ i ] );
......@@ -215,14 +199,8 @@ namespace xAOD {
const std::vector< std::string >& names = linkColNames();
for( size_t i = 0; i < names.size(); ++i ) {
if( names[ i ] != mangledName ) continue;
// Check that it is of the right type:
if( linkColClids()[ i ] != ClassID_traits< CONTAINER >::ID() ) {
const std::string typeName =
SG::normalizedTypeinfoName( typeid( CONTAINER ) );
throw std::runtime_error( "xAOD::TrigComposite::objectCollectionLinks: "
"Wrong type (" + typeName + ") requested "
"for collection name \"" + collectionName + "\"" );
}
// Check that it is of the right type:
checkTypes< CONTAINER >(linkColClids()[ i ], collectionName);
// Construct and add the link:
links.push_back( ElementLink< CONTAINER >(linkColKeys()[ i ],
linkColIndices()[ i ]) );
......@@ -230,6 +208,21 @@ namespace xAOD {
return links;
}
template<class CONTAINER>
void TrigComposite_v1::checkTypes(const uint32_t storedCLID, const std::string& name) const {
if (ClassID_traits< CONTAINER >::ID() == ClassID_traits< xAOD::IParticleContainer >::ID()) {
if (!derivesFromIParticle(storedCLID)) {
throw std::runtime_error( "xAOD::TrigComposite::checkTypes: "
"Cannot retrieve \"" + name + "\" as an IParticle");
}
} else if (ClassID_traits< CONTAINER >::ID() != storedCLID) {
const std::string typeName = SG::normalizedTypeinfoName( typeid( CONTAINER ) );
throw std::runtime_error( "xAOD::TrigComposite::checkTypes: "
"Wrong type (" + typeName + ") requested "
"for name \"" + name + "\"" );
}
}
} // namespace xAOD
#endif // XAODTRIGGER_VERSIONS_TRIGCOMPOSITE_V1_ICC
......@@ -72,6 +72,8 @@ StatusCode TrigDecisionMakerMT::finalize()
StatusCode TrigDecisionMakerMT::execute(const EventContext& context) const
{
using namespace TrigCompositeUtils;
// increment event counter
m_nEvents++;
......@@ -84,7 +86,7 @@ StatusCode TrigDecisionMakerMT::execute(const EventContext& context) const
}
}
const TrigCompositeUtils::DecisionContainer* hltResult = nullptr;
const DecisionContainer* hltResult = nullptr;
if (m_doHLT) {
ATH_CHECK(getHLTResult(hltResult, context));
}
......@@ -112,24 +114,43 @@ StatusCode TrigDecisionMakerMT::execute(const EventContext& context) const
outputVectors.insert( &hltRerunBits );
if (hltResult) {
ATH_MSG_DEBUG("Got a DecisionContainer '" << m_HLTSummaryKeyIn.key() << "' of size " << hltResult->size() << " (typically expect size=3)");
TrigCompositeUtils::DecisionIDContainer passRawInput; //!< The chains which returned a positive decision
TrigCompositeUtils::DecisionIDContainer prescaledInput; //!< The chains which did not run due to being prescaled out
TrigCompositeUtils::DecisionIDContainer rerunInput; //!< The chains which were activate only in the rerun (not physics decisions)
ATH_MSG_DEBUG("Got a DecisionContainer '" << m_HLTSummaryKeyIn.key() << "' of size " << hltResult->size());
const Decision* HLTPassRaw = nullptr;
const Decision* HLTPrescaled = nullptr;
const Decision* HLTRerun = nullptr;
DecisionIDContainer passRawInput; //!< The chains which returned a positive decision
DecisionIDContainer prescaledInput; //!< The chains which did not run due to being prescaled out
DecisionIDContainer rerunInput; //!< The chains which were activate only in the rerun (not physics decisions)
// Read the sets of chain IDs
for (const TrigCompositeUtils::Decision* decisionObject : *hltResult) {
for (const Decision* decisionObject : *hltResult) {
// Collect all decisions (IDs of passed/prescaled/rerun chains) from named decisionObjects
if (decisionObject->name() == "HLTPassRaw") {
TrigCompositeUtils::decisionIDs(decisionObject, passRawInput);
HLTPassRaw = decisionObject;
} else if (decisionObject->name() == "HLTPrescaled") {
TrigCompositeUtils::decisionIDs(decisionObject, prescaledInput);
HLTPrescaled = decisionObject;
} else if (decisionObject->name() == "HLTRerun") {
TrigCompositeUtils::decisionIDs(decisionObject, rerunInput);
} else {
ATH_MSG_WARNING("TrigDecisionMakerMT encountered an unknown set of decisions with name '" << decisionObject->name() << "'");
HLTRerun = decisionObject;
}
if (HLTPassRaw && HLTPrescaled && HLTRerun) {
break;
}
}
ATH_CHECK(HLTPassRaw != nullptr);
ATH_CHECK(HLTPrescaled != nullptr);
ATH_CHECK(HLTRerun != nullptr);
// Get all passed IDs.
decisionIDs(HLTPassRaw, passRawInput);
// Simpler structure for prescaled.
decisionIDs(HLTPrescaled, prescaledInput);
// Get all passed IDs.
decisionIDs(HLTRerun, rerunInput);
if (passRawInput.size()) {
++m_hltPassed;
}
......
......@@ -60,6 +60,7 @@ else()
Trigger/TrigEvent/TrigNavStructure
Trigger/TrigEvent/TrigNavigation
Trigger/TrigEvent/TrigStorageDefinitions
Trigger/TrigSteer/DecisionHandling
PRIVATE
Control/AthenaBaseComps
Control/AthenaKernel
......@@ -102,7 +103,7 @@ else()
xAODTrigger GaudiKernel AnalysisTriggerEvent TrigConfHLTData
TrigConfL1Data TrigDecisionEvent TrigMuonEvent TrigNavStructure
TrigStorageDefinitions StoreGateLib TrigNavigationLib
TrigRoiConversionLib
TrigRoiConversionLib DecisionHandlingLib
PRIVATE_LINK_LIBRARIES ${ROOT_LIBRARIES} AthenaBaseComps
TrigSteeringEvent AthenaKernel )
endif()
......
......@@ -723,7 +723,6 @@ namespace ChainGroup_impl {
}
}// eof namespace
const Trig::FeatureContainer
Trig::ChainGroup::features(unsigned int condition) const {
using namespace ChainGroup_impl;
......
......@@ -31,7 +31,7 @@
#include "TrigDecisionTool/FeatureContainer.h"
#include "TrigDecisionTool/Logger.h"
#include "TrigSteeringEvent/Enums.h"
#include "DecisionHandling/TrigCompositeUtils.h"
namespace HLT {
class Chain;
......@@ -114,7 +114,18 @@ namespace Trig {
* Note: This does not yet work for L1_FJ..., i.e. no features are returned for these items.
**/
const FeatureContainer features(unsigned int condition = TrigDefs::Physics) const;
/**
* @brief returns typed features related to given chain group of HLT chains or L1 items
* Note: This is a RUN 3 (and on) function.
* @param[in] eventStore Event store pointer. To migrate to readHandles with the rest of the TDT soon
* @param[in] condition Condition requirement. Only physics currently supported.
* @param[in] oneFeaturePerLeg If true, only collects the final feature from each object which passed the event for the Chain Group.
* @return ElementLinkVector with one entry per located feature for the ChainGroup's chain(s)
**/
template<class CONTAINER>
const ElementLinkVector<CONTAINER> features(EventPtr_t eventStore, unsigned int condition = TrigDefs::Physics, const bool oneFeaturePerLeg = true) const;
//
const std::vector< std::string >& patterns() const {return m_patterns;}
private:
......@@ -194,4 +205,6 @@ namespace Trig {
};
} // End of namespace
#include "ChainGroup.icc"
#endif
template<class CONTAINER>
const ElementLinkVector<CONTAINER> Trig::ChainGroup::features(EventPtr_t eventStore, unsigned int condition, const bool oneFeaturePerLeg) const {
// Proper adherence to the condition bits in Run 3 is to follow.
bool errState = false;
if ( !(condition & TrigDefs::Physics) ) {
ATH_MSG_ERROR("Only TrigDefs::Physics is currently supported for Run 3 feature retrieval");
errState = true;
}
if ( condition & TrigDefs::allowResurrectedDecision ) {
ATH_MSG_ERROR("TrigDefs::allowResurrectedDecision is not yet supported for feature retrieval for Run 3");
errState = true;
}
// TODO when we decide what happens to CacheGlobalMemory - this needs to be updated to use a ReadHandle
const TrigCompositeUtils::DecisionContainer* navigationSummaryContainer = nullptr;
if (eventStore->retrieve(navigationSummaryContainer, "HLTSummary").isFailure() || navigationSummaryContainer == nullptr) {
ATH_MSG_ERROR("Unable to read Run 3 trigger navigation. Cannot retrieve features.");
errState = true;
}
// We just support Physics decision for now
const TrigCompositeUtils::Decision* terminusNode = nullptr;
if (!errState) {
for (const TrigCompositeUtils::Decision* decision : *navigationSummaryContainer) {
if (decision->name() == "HLTPassRaw") {
terminusNode = decision;
break;
}
}
if (terminusNode == nullptr) {
ATH_MSG_ERROR("Unable to locate HLTPassRaw element of HLTSummary");
errState = true;
}
}
if (errState) {
return ElementLinkVector<CONTAINER>();
}
// For each chain, collect Navigation information
std::vector< ElementLinkVector<TrigCompositeUtils::DecisionContainer> > allLinearNavigationPaths;
// Loop over HLT chains
std::set<const TrigConf::HLTChain*>::const_iterator chIt;
for (chIt=conf_chain_begin(); chIt != conf_chain_end(); ++chIt) {
const HLT::Chain* fchain = cgm()->chain(**chIt);
if (fchain) {
TrigCompositeUtils::recursiveGetDecisions(terminusNode, allLinearNavigationPaths, fchain->getChainHashId());
}
}
return TrigCompositeUtils::getFeaturesOfType<CONTAINER>(allLinearNavigationPaths, oneFeaturePerLeg);
}
......@@ -94,17 +94,31 @@ namespace Trig {
char getBGCode() const;
/**
* @brief returns all features related to given chain group
* @brief Runs 1, 2. Returns all features related to given chain group
**/
FeatureContainer features(const ChainGroup* group,
FeatureContainer features(const Trig::ChainGroup* group,
unsigned int condition = TrigDefs::Physics) const;
/**
* @brief returns features related to given chain
* @brief Runs 1, 2. Returns features related to given chain
**/
FeatureContainer features(const std::string& chainName = "EF_.*",
unsigned int condition = TrigDefs::Physics) const;
/**
* @brief Runs 3+. Returns all features related to given chain group
**/
template<class CONTAINER>
const ElementLinkVector<CONTAINER> features(const Trig::ChainGroup* group,
unsigned int condition = TrigDefs::Physics) const;
/**
* @brief Runs 3+. Returns features related to given chain
**/
template<class CONTAINER>
const ElementLinkVector<CONTAINER> features(const std::string& chainName = "HLT_.*",
unsigned int condition = TrigDefs::Physics) const;
/**
* @brief gives back feature matching (by seeding relation)
* @param te - is trigger element to start with, not that thanks to conversion operators
......@@ -140,54 +154,6 @@ namespace Trig {
};
} // End of namespace
#if defined(ASGTOOL_ATHENA) && !defined(XAOD_ANALYSIS)
template<class T>
const Trig::Feature<T> Trig::DecisionAccess::ancestor(const HLT::TriggerElement* te, std::string label) const {
Trig::Feature<T> f;
std::vector<Trig::Feature<T> > data;
FeatureAccessImpl::collect<T>(te, data, label, TrigDefs::alsoDeactivateTEs, "", const_cast<HLT::TrigNavStructure*>(cgm()->navigation()));
BOOST_FOREACH( Feature<T>& f, data ) {
if ( f.owned() ) {
cgm()->deleteAtTheEndOfEvent( const_cast<T*>( f.cptr() ) );
}
}
if (data.size() == 1)
f = data[0];
return f;
}
template<class T>
const std::vector<Trig::Feature<T> > Trig::DecisionAccess::ancestors(const HLT::TriggerElement* te, std::string label, unsigned int condition, const std::string& teName) const {
std::vector<Trig::Feature<T> > data;
FeatureAccessImpl::collect<T>(te, data, label, condition, teName, const_cast<HLT::TrigNavStructure*>(cgm()->navigation()));
BOOST_FOREACH( Feature<T>& f, data ) {
if ( f.owned() ) {
cgm()->deleteAtTheEndOfEvent(const_cast<T*>( f.cptr() ));
}
}
return data;
}
#else
template<class T>
const Trig::Feature<T> Trig::DecisionAccess::ancestor(const HLT::TriggerElement* /*te*/, std::string /*label*/) const {
ATH_MSG_WARNING("DecisionAccess::ancestor not implemented in Standalone mode, since it needs compile-time type information. Returning empty Feature");
return Trig::Feature<T>();
}
template<class T>
const std::vector<Trig::Feature<T> > Trig::DecisionAccess::ancestors(const HLT::TriggerElement* /*te*/, std::string /*label*/, unsigned int /*condition*/, const std::string& /*teName*/) const {
ATH_MSG_WARNING("DecisionAccess::ancestor not implemented in Standalone mode, since it needs compile-time type information. Returning empty vector");
return std::vector<Trig::Feature<T> >();
}
#endif
#include "DecisionAccess.icc"
#endif
#if defined(ASGTOOL_ATHENA) && !defined(XAOD_ANALYSIS)
template<class T>
const Trig::Feature<T> Trig::DecisionAccess::ancestor(const HLT::TriggerElement* te, std::string label) const {
Trig::Feature<T> f;
std::vector<Trig::Feature<T> > data;
FeatureAccessImpl::collect<T>(te, data, label, TrigDefs::alsoDeactivateTEs, "", const_cast<HLT::TrigNavStructure*>(cgm()->navigation()));
BOOST_FOREACH( Feature<T>& f, data ) {
if ( f.owned() ) {
cgm()->deleteAtTheEndOfEvent( const_cast<T*>( f.cptr() ) );
}
}
if (data.size() == 1)
f = data[0];
return f;
}
template<class T>
const std::vector<Trig::Feature<T> > Trig::DecisionAccess::ancestors(const HLT::TriggerElement* te, std::string label, unsigned int condition, const std::string& teName) const {
std::vector<Trig::Feature<T> > data;
FeatureAccessImpl::collect<T>(te, data, label, condition, teName, const_cast<HLT::TrigNavStructure*>(cgm()->navigation()));
BOOST_FOREACH( Feature<T>& f, data ) {
if ( f.owned() ) {
cgm()->deleteAtTheEndOfEvent(const_cast<T*>( f.cptr() ));
}
}
return data;
}
#else
template<class T>
const Trig::Feature<T> Trig::DecisionAccess::ancestor(const HLT::TriggerElement* /*te*/, std::string /*label*/) const {
ATH_MSG_WARNING("DecisionAccess::ancestor not implemented in Standalone mode, since it needs compile-time type information. Returning empty Feature");
return Trig::Feature<T>();
}
template<class T>
const std::vector<Trig::Feature<T> > Trig::DecisionAccess::ancestors(const HLT::TriggerElement* /*te*/, std::string /*label*/, unsigned int /*condition*/, const std::string& /*teName*/) const {
ATH_MSG_WARNING("DecisionAccess::ancestor not implemented in Standalone mode, since it needs compile-time type information. Returning empty vector");
return std::vector<Trig::Feature<T> >();
}
#endif // ASGTOOL_ATHENA
template<class CONTAINER>
const ElementLinkVector<CONTAINER> Trig::DecisionAccess::features(const Trig::ChainGroup* group,
unsigned int condition) const {
return group->features<CONTAINER>(cgm()->store(), condition, /*one feature per leg*/ true);
}
template<class CONTAINER>
const ElementLinkVector<CONTAINER> Trig::DecisionAccess::features(const std::string& chainName,
unsigned int condition) const {
const Trig::ChainGroup *g = cgm()->createChainGroup(Trig::convertStringToVector(chainName));
return features<CONTAINER>(g,condition);
}
\ No newline at end of file
......@@ -119,28 +119,33 @@ HLTConfigSvc::initialize() {
//////////////////////////////////////////////////////////////
// BEGIN RUN-3 TESTING BLOCK - THIS SHOULD BE TEMPORARY
//////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////
string s(boost::to_lower_copy(m_configSourceString)); // lower case