diff --git a/cmake/BuildDynamicSmearcepter.in b/cmake/BuildDynamicSmearcepter.in new file mode 100644 index 0000000..0936923 --- /dev/null +++ b/cmake/BuildDynamicSmearcepter.in @@ -0,0 +1,88 @@ +# Copyright 2016 L. Pickering, P Stowell, R. Terri, C. Wilkinson, C. Wret + +################################################################################ +# This file is part of NUISANCE. +# +# NUISANCE 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. +# +# NUISANCE 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 NUISANCE. If not, see . +################################################################################ + +#!/bin/bash + +if [ ! "${1}" ] || [ ! -e ${1} ] || [ ! "${2}" ]; then + echo "[USAGE]: ${0} input.cxx outputLibName.so [classname]" + exit 1 +fi + +if [ ! "${3}" ]; then + CN=$(grep "class .*" $1 | sed "s/^class \([0-9a-zA-Z]\+\).*$/\1/g") +else + CN=${3} +fi + +if [ ! "${CN}" ]; then + echo "[ERROR]: Couldn't find class name -- Expected to find a line like: \"class XXXX : public ISmearcepter\" in \"$1\". You can also forcibly specify your classes name by passing a third argument to this script." + exit 1 +fi + +if [ ! -e compile.tmp ]; then + mkdir compile.tmp +fi + +cat $1 > compile.tmp/$1 + +echo -e "static char const * SmearceptorNames[] = {\"${CN}\"};\n"\ +"static int const NSmearceptors = 1;\n"\ +"\n"\ +"extern \"C\" {\n"\ +"int DSF_NSmearceptors() { return NSmearceptors; }\n"\ +"char const* DSF_GetSmearceptorName(int i) {\n"\ +" if (i < NSmearceptors) {\n"\ +" return SmearceptorNames[i];\n"\ +" }\n"\ +" return 0;\n"\ +"}\n"\ +"ISmearcepter* DSF_GetSmearceptor(int i, void* smearceptorkey) {\n"\ +" nuiskey* sk = reinterpret_cast(smearceptorkey);\n"\ +" if (!sk) {\n"\ +" return 0;\n"\ +" }\n"\ +"\n"\ +" if (sk->GetS(\"name\") != DSF_GetSmearceptorName(i)) {\n"\ +" std::cout\n"\ +" << \"[ERROR]: When instantiating dynamic smearceptor. Smearceptorkey named: \"\n"\ +" << sk->GetS(\"name\") << \", but requested smearceptor named: \"\n"\ +" << DSF_GetSmearceptorName(i)\n"\ +" << \". It is possible that the nuiskey object is lost in translation. \"\n"\ +" \"Was NUISANCE and this dynamic smearceptor manifest built with the same \"\n"\ +" \"environment and compiler?\"\n"\ +" << std::endl;\n"\ +" }\n"\ +"\n"\ +" if (i == 0) {\n"\ +" ISmearcepter* sm = new ${CN}();\n"\ +" sm->Setup(*sk);\n"\ +" }\n"\ +" return 0;\n"\ +"}\n"\ +"void DSF_DestroySmearceptor(ISmearcepter* mb) { delete mb; }\n"\ +"}" >> compile.tmp/$1 + +echo "g++ ${DYNSAMPLE_EXTRA_BUILD_FLAGS} compile.tmp/$1 -shared -o $2 -fPIC @CMAKE_CXX_FLAGS@ -I. -I@ALL_INCLUDES_STR@ -L@CMAKE_INSTALL_PREFIX@/lib -l@ALL_MODULETARGETS_STR@ @CMAKE_LINK_FLAGS@ @CMAKE_DEPENDLIB_FLAGS@" + +if ! g++ ${DYNSAMPLE_EXTRA_BUILD_FLAGS} compile.tmp/$1 -shared -o $2 -fPIC @CMAKE_CXX_FLAGS@ -I. -I@ALL_INCLUDES_STR@ -L@CMAKE_INSTALL_PREFIX@/lib -l@ALL_MODULETARGETS_STR@ @CMAKE_LINK_FLAGS@ @CMAKE_DEPENDLIB_FLAGS@; then + echo "[ERROR]: Failed to compile $1. Generated code can be found in ./compile.tmp/$1" +else + rm -r compile.tmp + echo "Successfully build: $2." +fi diff --git a/src/Electron/CLAS6-EG2_Accepter.cxx b/src/Electron/CLAS6-EG2_Accepter.cxx new file mode 100644 index 0000000..d2c4307 --- /dev/null +++ b/src/Electron/CLAS6-EG2_Accepter.cxx @@ -0,0 +1,177 @@ +#include "ISmearcepter.h" + +#include "TH3D.h" +#include "TRandom3.h" + +#include + +#define DEBUG_CLASACCEPT + +class CLASAccepter : public ISmearcepter { + TRandom3 rand; + // Maps a particle PDG to the relevant generated and accepted histograms from + // the input map. + std::map > Acceptance; + + public: + CLASAccepter() { ElementName = "CLASAccepter"; } + + void SpecifcSetup(nuiskey &nk) { + rand.~TRandom3(); + new (&rand) TRandom3(); + + InstanceName = nk.GetS("name"); + + std::string const &mapfile = nk.GetS("map"); + + if (!mapfile.length()) { + std::cout << "[ERROR]: No input file specified by \"map\" attribute." + << std::endl; + exit(1); + } + + TFile *f = new TFile(mapfile.c_str()); + + if (!f || !f->IsOpen()) { + std::cout << "[ERROR]: Could not open root file specified by \"map\" " + "attribute: \"" + << mapfile << "\"" << std::endl; + exit(1); + } + + std::vector accepts = nk.GetListOfChildNodes("accept"); + for (auto &acc : accepts) { + std::string const &genStr = acc.GetS("generated"); + std::string const &accStr = acc.GetS("accepted"); + + if (!genStr.length() || !accStr.length()) { + std::cout << "[ERROR]: expected accept node to contain both " + "\"generated\" and \"accepted\" attributes." + << std::endl; + exit(1); + } + + std::string const &pdgs_s = acc.GetS("PDG"); + std::vector pdgs_i = GeneralUtils::ParseToInt(pdgs_s, ","); + + if (!pdgs_i.size()) { + std::cout + << "[ERROR]: Could not find any applicable particle PDG codes." + << std::endl; + exit(1); + } + + std::pair genacc; + + genacc.first = dynamic_cast(f->Get(accStr.c_str())); + genacc.second = dynamic_cast(f->Get(genStr.c_str())); + + if (!genacc.first) { + std::cout << "[ERROR]: Could not retrieve \"accepted\" histogram: \"" + << accStr << "\" from file: \"" << mapfile << "\"." + << std::endl; + exit(1); + } + if (!genacc.second) { + std::cout << "[ERROR]: Could not retrieve \"accepted\" histogram: \"" + << genStr << "\" from file: \"" << mapfile << "\"." + << std::endl; + exit(1); + } + + genacc.first = static_cast(genacc.first->Clone()); + genacc.first->SetDirectory(NULL); + genacc.second = static_cast(genacc.second->Clone()); + genacc.second->SetDirectory(NULL); + + for (size_t pdg_it = 0; pdg_it < pdgs_i.size(); ++pdg_it) { + if (Acceptance.count(pdgs_i[pdg_it])) { + std::cout + << "[WARN]: Acceptance map already contains acceptance for PDG: " + << pdgs_i[pdg_it] << ". Overwriting..." << std::endl; + } + Acceptance[pdgs_i[pdg_it]] = genacc; + } + } + + std::cout << "Loaded " << Acceptance.size() + << " particle acceptance definitions." << std::endl; + f->Close(); + delete f; + } + + RecoInfo *Smearcept(FitEvent *fe) { + RecoInfo *ri = new RecoInfo(); + + for (size_t p_it = 0; p_it < fe->NParticles(); ++p_it) { + FitParticle *fp = fe->GetParticle(p_it); + + int PDG = fp->PDG(); + double p = fp->P3().Mag(); + double cost = fp->P3().CosTheta(); + double phi = fp->P3().Phi(); + +#ifdef DEBUG_CLASACCEPT + std::cout << std::endl; + std::cout << "[" << p_it << "]: " << PDG << ", " << fp->Status() << ", " + << fp->E() << " -- KE:" << fp->KE() << " Mom: " << p + << std::flush; +#endif + + if (fp->Status() != kFinalState) { +#ifdef DEBUG_CLASACCEPT + std::cout << " -- Not final state." << std::flush; +#endif + continue; + } + + if (!Acceptance.count(PDG)) { +#ifdef DEBUG_CLASACCEPT + std::cout << " -- Unknown acceptance." << std::flush; +#endif + + continue; + } + + std::pair acc = Acceptance[PDG]; + + // For a bin in phase space defined by p, cost, phi: + // Find number of generated events + Int_t pbin = acc.second->GetXaxis()->FindBin(p); + Int_t tbin = acc.second->GetYaxis()->FindBin(cost); + Int_t phibin = acc.second->GetZaxis()->FindBin(phi); + double num_gen = acc.second->GetBinContent(pbin, tbin, phibin); + // Find number of accepted events + pbin = acc.first->GetXaxis()->FindBin(p); + tbin = acc.first->GetYaxis()->FindBin(cost); + phibin = acc.first->GetZaxis()->FindBin(phi); + double num_acc = acc.first->GetBinContent(pbin, tbin, phibin); + double acc_ratio = double(num_acc) / double(num_gen); + + bool accepted = (rand.Uniform() < acc_ratio); + if (accepted) { +#ifdef DEBUG_CLASACCEPT + std::cout << " -- Reconstructed with probability: " << acc_ratio + << std::flush; +#endif + ri->RecObjMom.push_back(fp->P3()); + ri->RecObjClass.push_back(fp->PDG()); + + continue; + } + +#ifdef DEBUG_CLASACCEPT + std::cout << " -- Rejected with probability: " << acc_ratio << std::flush; +#endif +#ifdef DEBUG_CLASACCEPT + std::cout << std::endl; +#endif + } + +#ifdef DEBUG_CLASACCEPT + std::cout << "Reconstructed " << ri->RecObjMom.size() << " particles. " + << std::endl; +#endif + return ri; + } +}; diff --git a/src/Smearceptance/Smearcepterton.cxx b/src/Smearceptance/Smearcepterton.cxx index 17ff95d..1dbf868 100644 --- a/src/Smearceptance/Smearcepterton.cxx +++ b/src/Smearceptance/Smearcepterton.cxx @@ -1,78 +1,334 @@ // Copyright 2016 L. Pickering, P Stowell, R. Terri, C. Wilkinson, C. Wret /******************************************************************************* * This file is part of NUISANCE. * * NUISANCE 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. * * NUISANCE 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 NUISANCE. If not, see . *******************************************************************************/ #include "Smearcepterton.h" #include "EfficiencyApplicator.h" #include "GaussianSmearer.h" #include "MetaSimpleSmearcepter.h" #include "ThresholdAccepter.h" #include "TrackedMomentumMatrixSmearer.h" #include "VisECoalescer.h" #include +#ifdef __USE_DYNSAMPLES__ + +#include "TRegexp.h" + +#include + +// linux +#include + +DynamicSmearceptorFactory::DynamicSmearceptorFactory() + : NSmearceptors(0), NManifests(0) { + LoadPlugins(); + QLOG(FIT, "Loaded " << NSmearceptors << " from " << NManifests + << " shared object libraries."); +} +DynamicSmearceptorFactory* DynamicSmearceptorFactory::glblDSF = NULL; +DynamicSmearceptorFactory::PluginManifest::~PluginManifest() { + for (size_t i_it = 0; i_it < Instances.size(); ++i_it) { + (*(DSF_DestroySmearceptor))(Instances[i_it]); + } +} +std::string EnsureTrailingSlash(std::string const& inp) { + if (!inp.length()) { + return "/"; + } + if (inp[inp.length() - 1] == '/') { + return inp; + } + return inp + "/"; +} +void DynamicSmearceptorFactory::LoadPlugins() { + std::vector SearchDirectories; + + if (Config::HasPar("dynamic_smearceptor.path")) { + SearchDirectories = GeneralUtils::ParseToStr( + Config::GetParS("dynamic_smearceptor.path"), ":"); + } + + char const* envPath = getenv("NUISANCE_DS_PATH"); + if (envPath) { + std::vector envPaths = GeneralUtils::ParseToStr(envPath, ":"); + for (size_t ep_it = 0; ep_it < envPaths.size(); ++ep_it) { + SearchDirectories.push_back(envPaths[ep_it]); + } + } + + if (!SearchDirectories.size()) { + char const* pwdPath = getenv("PWD"); + if (pwdPath) { + SearchDirectories.push_back(pwdPath); + } + } + + for (size_t sp_it = 0; sp_it < SearchDirectories.size(); ++sp_it) { + std::string dirpath = EnsureTrailingSlash(SearchDirectories[sp_it]); + + QLOG(FIT, "Searching for dynamic smearceptor manifests in: " << dirpath); + + Ssiz_t len = 0; + DIR* dir; + struct dirent* ent; + dir = opendir(dirpath.c_str()); + if (dir != NULL) { + TRegexp matchExp("*.so", true); + while ((ent = readdir(dir)) != NULL) { + if (matchExp.Index(TString(ent->d_name), &len) != Ssiz_t(-1)) { + QLOG(FIT, "\tFound shared object: " + << ent->d_name << " checking for relevant methods..."); + + void* dlobj = + dlopen((dirpath + ent->d_name).c_str(), RTLD_NOW | RTLD_GLOBAL); + char const* dlerr_cstr = dlerror(); + std::string dlerr; + if (dlerr_cstr) { + dlerr = dlerr_cstr; + } + + if (dlerr.length()) { + ERROR(WRN, "\tDL Load Error: " << dlerr); + continue; + } + + PluginManifest plgManif; + plgManif.dllib = dlobj; + plgManif.soloc = (dirpath + ent->d_name); + + plgManif.DSF_NSmearceptors = reinterpret_cast( + dlsym(dlobj, "DSF_NSmearceptors")); + + dlerr = ""; + dlerr_cstr = dlerror(); + if (dlerr_cstr) { + dlerr = dlerr_cstr; + } + + if (dlerr.length()) { + ERROR(WRN, "\tFailed to load symbol \"DSF_NSmearceptors\" from " + << (dirpath + ent->d_name) << ": " << dlerr); + dlclose(dlobj); + continue; + } + + plgManif.DSF_GetSmearceptorName = + reinterpret_cast( + dlsym(dlobj, "DSF_GetSmearceptorName")); + + dlerr = ""; + dlerr_cstr = dlerror(); + if (dlerr_cstr) { + dlerr = dlerr_cstr; + } + + if (dlerr.length()) { + ERROR(WRN, + "\tFailed to load symbol \"DSF_GetSmearceptorName\" from " + << (dirpath + ent->d_name) << ": " << dlerr); + dlclose(dlobj); + continue; + } + + plgManif.DSF_GetSmearceptor = + reinterpret_cast( + dlsym(dlobj, "DSF_GetSmearceptor")); + + dlerr = ""; + dlerr_cstr = dlerror(); + if (dlerr_cstr) { + dlerr = dlerr_cstr; + } + + if (dlerr.length()) { + ERROR(WRN, "\tFailed to load symbol \"DSF_GetSmearceptor\" from " + << (dirpath + ent->d_name) << ": " << dlerr); + dlclose(dlobj); + continue; + } + + plgManif.DSF_DestroySmearceptor = + reinterpret_cast( + dlsym(dlobj, "DSF_DestroySmearceptor")); + + dlerr = ""; + dlerr_cstr = dlerror(); + if (dlerr_cstr) { + dlerr = dlerr_cstr; + } + + if (dlerr.length()) { + ERROR(WRN, "Failed to load symbol \"DSF_DestroySmearceptor\" from " + << (dirpath + ent->d_name) << ": " << dlerr); + dlclose(dlobj); + continue; + } + + plgManif.NSmearceptors = (*(plgManif.DSF_NSmearceptors))(); + QLOG(FIT, "\tSuccessfully loaded dynamic smearceptor manifest: " + << plgManif.soloc << ". Contains " + << plgManif.NSmearceptors << " smearceptors."); + + for (size_t smp_it = 0; smp_it < plgManif.NSmearceptors; ++smp_it) { + char const* smp_name = (*(plgManif.DSF_GetSmearceptorName))(smp_it); + if (!smp_name) { + THROW("Could not load smearceptor " + << smp_it << " / " << plgManif.NSmearceptors << " from " + << plgManif.soloc); + } + + if (Smearceptors.count(smp_name)) { + ERROR(WRN, "Already loaded a smearceptor named: \"" + << smp_name << "\". cannot load duplciates. This " + "smearceptor will be skipped."); + continue; + } + + plgManif.SmearceptorsProvided.push_back(smp_name); + Smearceptors[smp_name] = std::make_pair(plgManif.soloc, smp_it); + QLOG(FIT, "\t\t" << smp_name); + } + + if (plgManif.SmearceptorsProvided.size()) { + Manifests[plgManif.soloc] = plgManif; + + NSmearceptors += plgManif.SmearceptorsProvided.size(); + NManifests++; + } else { + dlclose(dlobj); + } + } + } + closedir(dir); + } else { + ERROR(WRN, "Tried to open non-existant directory."); + } + } +} +DynamicSmearceptorFactory& DynamicSmearceptorFactory::Get() { + if (!glblDSF) { + glblDSF = new DynamicSmearceptorFactory(); + } + return *glblDSF; +} +void DynamicSmearceptorFactory::Print() { + std::map > ManifestSmearceptors; + + for (std::map >::iterator smp_it = + Smearceptors.begin(); + smp_it != Smearceptors.end(); ++smp_it) { + if (!ManifestSmearceptors.count(smp_it->second.first)) { + ManifestSmearceptors[smp_it->second.first] = std::vector(); + } + ManifestSmearceptors[smp_it->second.first].push_back(smp_it->first); + } + + QLOG(FIT, "Dynamic smearceptor manifest: "); + for (std::map >::iterator m_it = + ManifestSmearceptors.begin(); + m_it != ManifestSmearceptors.end(); ++m_it) { + QLOG(FIT, "\tLibrary " << m_it->first << " contains: "); + for (size_t s_it = 0; s_it < m_it->second.size(); ++s_it) { + QLOG(FIT, "\t\t" << m_it->second[s_it]); + } + } +} +bool DynamicSmearceptorFactory::HasSmearceptor(std::string const& name) { + return Smearceptors.count(name); +} +bool DynamicSmearceptorFactory::HasSmearceptor(nuiskey& smearceptorkey) { + return HasSmearceptor(smearceptorkey.GetS("name")); +} +ISmearcepter* DynamicSmearceptorFactory::CreateSmearceptor( + nuiskey& smearceptorkey) { + if (!HasSmearceptor(smearceptorkey)) { + ERROR(WRN, "Asked to load unknown smearceptor: \"" + << smearceptorkey.GetS("name") << "\"."); + return NULL; + } + + std::pair smearceptor = + Smearceptors[smearceptorkey.GetS("name")]; + QLOG(SAM, "\tLoading smearceptor " << smearceptor.second << " from " + << smearceptor.first); + + ISmearcepter* smear = (*(Manifests[smearceptor.first].DSF_GetSmearceptor))( + smearceptor.second, &smearceptorkey); + return smear; +} + +DynamicSmearceptorFactory::~DynamicSmearceptorFactory() { Manifests.clear(); } + +#endif + Smearcepterton* Smearcepterton::_inst = NULL; Smearcepterton& Smearcepterton::Get() { if (!_inst) { _inst = new Smearcepterton(); } return *_inst; } Smearcepterton::Smearcepterton() { InitialiserSmearcepters(); } void Smearcepterton::InitialiserSmearcepters() { // hard coded list of tag name -> smearcepter factories, add here to add your // own. std::map factories; factories["ThresholdAccepter"] = &BuildSmearcepter; factories["EfficiencyApplicator"] = &BuildSmearcepter; factories["GaussianSmearer"] = &BuildSmearcepter; factories["TrackedMomentumMatrixSmearer"] = &BuildSmearcepter; factories["VisECoalescer"] = &BuildSmearcepter; factories["MetaSimpleSmearcepter"] = &BuildSmearcepter; std::vector smearcepterBlocks = Config::QueryKeys("smearcepters"); for (size_t smearB_it = 0; smearB_it < smearcepterBlocks.size(); ++smearB_it) { std::vector smearcepters = smearcepterBlocks[smearB_it].GetListOfChildNodes(); for (size_t smear_it = 0; smear_it < smearcepters.size(); ++smear_it) { std::string const& smearType = smearcepters[smear_it].GetElementName(); - if (!factories.count(smearType)) { - ERROR(WRN, "No known smearer accepts elements named: \"" << smearType - << "\""); - continue; + ISmearcepter* smearer = NULL; + if (DynamicSmearceptorFactory::Get().HasSmearceptor(smearType)) { + smearer = DynamicSmearceptorFactory::Get().CreateSmearceptor( + smearcepters[smear_it]); + } else { + if (!factories.count(smearType)) { + ERROR(WRN, "No known smearer accepts elements named: \"" << smearType + << "\""); + continue; + } + smearer = factories[smearType](smearcepters[smear_it]); } - ISmearcepter* smearer = factories[smearType](smearcepters[smear_it]); - Smearcepters[smearer->GetName()] = smearer; QLOG(FIT, "Configured smearer named: " << smearer->GetName() << " of type: " << smearer->GetElementName()); } } } diff --git a/src/Smearceptance/Smearcepterton.h b/src/Smearceptance/Smearcepterton.h index 5196d7f..f5c6fc5 100644 --- a/src/Smearceptance/Smearcepterton.h +++ b/src/Smearceptance/Smearcepterton.h @@ -1,57 +1,112 @@ // Copyright 2016 L. Pickering, P Stowell, R. Terri, C. Wilkinson, C. Wret /******************************************************************************* * This file is part of NUISANCE. * * NUISANCE 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. * * NUISANCE 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 NUISANCE. If not, see . *******************************************************************************/ #ifndef SMEARCEPTERTON_HXX_SEEN #define SMEARCEPTERTON_HXX_SEEN #include "FitLogger.h" #include "ISmearcepter.h" #include #include + +#ifdef __USE_DYNSAMPLES__ +/// Expect each .so containing smearceptors to supply 4 c-style methods. +/// int DSF_NSmearceptors(); +/// char const * DSF_GetSmearceptorName(int); +/// ISmearcepter* DSF_GetSmearceptor(int, nuiskey *); +/// void DSF_DestroySmearceptor(ISmearcepter *); +class DynamicSmearceptorFactory { + size_t NSmearceptors; + size_t NManifests; + + DynamicSmearceptorFactory(); + + static DynamicSmearceptorFactory* glblDSF; + + typedef int (*DSF_NSmearceptors_ptr)(void); + typedef char const* (*DSF_GetSmearceptorName_ptr)(int); + typedef ISmearcepter* (*DSF_GetSmearceptor_ptr)(int, nuiskey *); + typedef void (*DSF_DestroySmearceptor_ptr)(ISmearcepter*); + + struct PluginManifest { + void* dllib; + + DSF_NSmearceptors_ptr DSF_NSmearceptors; + DSF_GetSmearceptorName_ptr DSF_GetSmearceptorName; + DSF_GetSmearceptor_ptr DSF_GetSmearceptor; + DSF_DestroySmearceptor_ptr DSF_DestroySmearceptor; + + std::string soloc; + std::vector Instances; + std::vector SmearceptorsProvided; + size_t NSmearceptors; + ~PluginManifest(); + }; + + std::map Manifests; + std::map > Smearceptors; + + void LoadPlugins(); + + public: + static DynamicSmearceptorFactory& Get(); + + void Print(); + + bool HasSmearceptor(std::string const& name); + bool HasSmearceptor(nuiskey& smearceptorkey); + + ISmearcepter* CreateSmearceptor(nuiskey& smearceptorkey); + + ~DynamicSmearceptorFactory(); +}; + +#endif + /// Singleton handling the loading and configuring of known smearcepters. class Smearcepterton { Smearcepterton(); void InitialiserSmearcepters(); static Smearcepterton *_inst; std::map Smearcepters; public: static Smearcepterton &Get(); ISmearcepter &GetSmearcepter(std::string const &name) { if (!Smearcepters.count(name) || !Smearcepters[name]) { ERROR(FTL, "Known smearcepters:"); for (std::map::iterator sm_it = Smearcepters.begin(); sm_it != Smearcepters.end(); ++sm_it) { ERROR(FTL, "\t" << sm_it->first); } THROW("No smearcepter named: \"" << name << "\" defined."); } return *Smearcepters[name]; } }; #endif