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