diff --git a/include/GeantParser/JPetGeantParser/JPetGeantParser.h b/include/GeantParser/JPetGeantParser/JPetGeantParser.h index 5f05b5465..ead954430 100644 --- a/include/GeantParser/JPetGeantParser/JPetGeantParser.h +++ b/include/GeantParser/JPetGeantParser/JPetGeantParser.h @@ -60,6 +60,16 @@ class JPetGeantParser : public JPetUserTask double fExperimentalThreshold = 10; //< in keV unsigned long fSeed = 0.; + bool fUseDefaultZSmearing = false; + bool fUseDefaultTimeSmearing = false; + bool fUseDefaultEnergySmearing = false; + + float fDefaultZSmearingSigma = 3.0; + float fDefaultTimeSmearingSigma = 220.0; + float fDefaultTimeSmearingThresholdEnergy = 200.0; + float fDefaultTimeSmearingReferenceEnergy = 270.0; + float fDefaultEnergySmearingFraction = 0.044; + JPetHitExperimentalParametrizer fExperimentalParametrizer; // internal variables @@ -83,6 +93,17 @@ class JPetGeantParser : public JPetUserTask const std::string kZPositionSmearingFunctionParamKey = "GeantParser_ZPositionSmearingFunction_std::string"; const std::string kZPositionSmearingFunctionLimitsParamKey = "GeantParser_ZPositionSmearingFunctionLimits_std::vector"; + const std::string kUseDefaultZSmearingKey = "GeantParser_UseDefaultZSmearing_bool"; + const std::string kDefaultZSmearingSigmaKey = "GeantParser_DefaultZSmearingSigma_double"; + + const std::string kUseDefaultTimeSmearingKey = "GeantParser_UseDefaultTimeSmearing_bool"; + const std::string kDefaultTimeSmearingSigmaKey = "GeantParser_DefaultTimeSmearingSigma_double"; + const std::string kDefaultTimeSmearingThresholdEnergyKey = "GeantParser_DefaultTimeSmearingThresholdEnergy_double"; + const std::string kDefaultTimeSmearingReferenceEnergyKey = "GeantParser_DefaultTimeSmearingReferenceEnergy_double"; + + const std::string kUseDefaultEnergySmearingKey = "GeantParser_UseDefaultEnergySmearing_bool"; + const std::string kDefaultEnergySmearingFractionKey = "GeantParser_DefaultEnergySmearingFraction_double"; + const std::string kSeedParamKey = "GeantParser_Seed_int"; long fExpectedNumberOfEvents = 0; diff --git a/include/GeantParser/JPetGeantParser/JPetGeantParserTools.h b/include/GeantParser/JPetGeantParser/JPetGeantParserTools.h index 55c253919..876024c47 100644 --- a/include/GeantParser/JPetGeantParser/JPetGeantParserTools.h +++ b/include/GeantParser/JPetGeantParser/JPetGeantParserTools.h @@ -34,9 +34,9 @@ class JPetGeantParserTools { public: - static JPetMCHit createJPetMCHit(JPetGeantScinHits* geantHit, const JPetParamBank& paramBank); + static JPetMCHit createJPetMCHit(JPetGeantScinHits* geantHit, const JPetParamBank& paramBank, const float timeShift); - static JPetHit reconstructHit(JPetMCHit& hit, const JPetParamBank& paramBank, const float timeShift, JPetHitExperimentalParametrizer& parametrizer); + static JPetHit reconstructHit(JPetMCHit& hit, const JPetParamBank& paramBank, JPetHitExperimentalParametrizer& parametrizer); static bool isHitReconstructed(JPetHit& hit, const float th); diff --git a/include/GeantParser/JPetSmearingFunctions/JPetSmearingFunctions.h b/include/GeantParser/JPetSmearingFunctions/JPetSmearingFunctions.h index 533daf68d..5fd9d7bf7 100644 --- a/include/GeantParser/JPetSmearingFunctions/JPetSmearingFunctions.h +++ b/include/GeantParser/JPetSmearingFunctions/JPetSmearingFunctions.h @@ -79,9 +79,49 @@ class JPetHitExperimentalParametrizer void setSmearingFunctionLimits(const std::vector>& limits); + void setShouldUseDefaultSmearing(bool defaultZ, bool defaultTime, bool defaultEnergy){ + fUseDefaultZSmearing = defaultZ; + fUseDefaultTimeSmearing = defaultTime; + fUseDefaultEnergySmearing = defaultEnergy; + } + + void setDefaultZSmearingSigma(double sigma){ + fDefaultZSmearingSigma = sigma; + } + + void setDefaultTimeSmearingSigma(double sigma){ + fDefaultTimeSmearingSigma = sigma; + } + + void setDefaultTimeSmearingThresholdEnergy(double thresholdEnergy){ + fDefaultTimeSmearingThresholdEnergy = thresholdEnergy; + } + + void setDefaultTimeSmearingReferenceEnergy(double referenceEnergy){ + fDefaultTimeSmearingReferenceEnergy = referenceEnergy; + } + + void setDefaultEnergySmearingFraction(double fraction){ + fDefaultEnergySmearingFraction = fraction; + } + private: + double defaultTimeSmearing(double zIn, double eneIn, double timeIn); + double defaultEnergySmearing(double zIn, double eneIn, double timeIn); + double defaultZHitSmearing(double zIn, double eneIn, double timeIn); + std::map fSmearingFunctions; std::map fFunctionLimits{{kTime, {-300, 300}}, {kEnergy, {-100, 100}}, {kZPosition, {-5, 5}}}; + + bool fUseDefaultZSmearing = false; + bool fUseDefaultTimeSmearing = false; + bool fUseDefaultEnergySmearing = false; + + double fDefaultZSmearingSigma = 3.0; // cm + double fDefaultTimeSmearingSigma = 220.0; // ps + double fDefaultTimeSmearingThresholdEnergy = 200.0; // keV + double fDefaultTimeSmearingReferenceEnergy = 270.0; // keV + double fDefaultEnergySmearingFraction = 0.044; }; #endif diff --git a/src/GeantParser/JPetGeantParser/JPetGeantParser.cpp b/src/GeantParser/JPetGeantParser/JPetGeantParser.cpp index 54aaf237d..c4d1e144c 100644 --- a/src/GeantParser/JPetGeantParser/JPetGeantParser.cpp +++ b/src/GeantParser/JPetGeantParser/JPetGeantParser.cpp @@ -144,11 +144,52 @@ void JPetGeantParser::loadSmearingOptionsAndSetupExperimentalParametrizer() } std::vector zPositionSmearingLimits; + if (isOptionSet(fParams.getOptions(), kZPositionSmearingFunctionLimitsParamKey)) { zPositionSmearingLimits = getOptionAsVectorOfDoubles(fParams.getOptions(), kZPositionSmearingFunctionLimitsParamKey); } + if (isOptionSet(fParams.getOptions(), kUseDefaultZSmearingKey)) + { + fUseDefaultZSmearing = getOptionAsDouble(fParams.getOptions(), kUseDefaultZSmearingKey); + } + + if (isOptionSet(fParams.getOptions(), kUseDefaultTimeSmearingKey)) + { + fUseDefaultTimeSmearing = getOptionAsDouble(fParams.getOptions(), kUseDefaultTimeSmearingKey); + } + + if (isOptionSet(fParams.getOptions(), kUseDefaultEnergySmearingKey)) + { + fUseDefaultEnergySmearing = getOptionAsDouble(fParams.getOptions(), kUseDefaultEnergySmearingKey); + } + + if (isOptionSet(fParams.getOptions(), kDefaultZSmearingSigmaKey)) + { + fDefaultZSmearingSigma = getOptionAsDouble(fParams.getOptions(), kDefaultZSmearingSigmaKey); + } + + if (isOptionSet(fParams.getOptions(), kDefaultTimeSmearingSigmaKey)) + { + fDefaultTimeSmearingSigma = getOptionAsDouble(fParams.getOptions(), kDefaultTimeSmearingSigmaKey); + } + + if (isOptionSet(fParams.getOptions(), kDefaultTimeSmearingThresholdEnergyKey)) + { + fDefaultTimeSmearingThresholdEnergy = getOptionAsDouble(fParams.getOptions(), kDefaultTimeSmearingThresholdEnergyKey); + } + + if (isOptionSet(fParams.getOptions(), kDefaultTimeSmearingReferenceEnergyKey)) + { + fDefaultTimeSmearingReferenceEnergy = getOptionAsDouble(fParams.getOptions(), kDefaultTimeSmearingReferenceEnergyKey); + } + + if (isOptionSet(fParams.getOptions(), kDefaultEnergySmearingFractionKey)) + { + fDefaultEnergySmearingFraction = getOptionAsDouble(fParams.getOptions(), kDefaultEnergySmearingFractionKey); + } + fExperimentalParametrizer.setSmearingFunctions({{timeSmearingFormula, timeSmearingParameters}, {energySmearingFormula, energySmearingParameters}, {zPositionSmearingFormula, zPositionSmearingParameters}}); @@ -183,6 +224,22 @@ void JPetGeantParser::loadSmearingOptionsAndSetupExperimentalParametrizer() } fExperimentalParametrizer.setSmearingFunctionLimits(limits); + + fExperimentalParametrizer.setShouldUseDefaultSmearing(fUseDefaultZSmearing, fUseDefaultTimeSmearing, fUseDefaultEnergySmearing); + + if(fUseDefaultZSmearing){ + fExperimentalParametrizer.setDefaultZSmearingSigma(fDefaultZSmearingSigma); + } + + if(fUseDefaultTimeSmearing){ + fExperimentalParametrizer.setDefaultTimeSmearingSigma(fDefaultTimeSmearingSigma); + fExperimentalParametrizer.setDefaultTimeSmearingReferenceEnergy(fDefaultTimeSmearingReferenceEnergy); + fExperimentalParametrizer.setDefaultTimeSmearingThresholdEnergy(fDefaultTimeSmearingThresholdEnergy); + } + + if(fUseDefaultEnergySmearing){ + fExperimentalParametrizer.setDefaultEnergySmearingFraction(fDefaultEnergySmearingFraction); + } } bool JPetGeantParser::exec() @@ -258,12 +315,12 @@ void JPetGeantParser::processMCEvent(JPetGeantEventPack* evPack) { // translate geantHit -> JPetMCHit - JPetMCHit mcHit = JPetGeantParserTools::createJPetMCHit(evPack->GetHit(i), getParamBank()); + JPetMCHit mcHit = JPetGeantParserTools::createJPetMCHit(evPack->GetHit(i), getParamBank(), timeShift); if (fMakeHisto) fillHistoMCGen(mcHit); // create reconstructed hit and add all smearings - JPetHit recHit = JPetGeantParserTools::reconstructHit(mcHit, getParamBank(), timeShift, fExperimentalParametrizer); + JPetHit recHit = JPetGeantParserTools::reconstructHit(mcHit, getParamBank(), fExperimentalParametrizer); // add criteria for possible rejection of reconstructed events (e.g. E>50 keV) if (JPetGeantParserTools::isHitReconstructed(recHit, fExperimentalThreshold)) diff --git a/src/GeantParser/JPetGeantParser/JPetGeantParserTools.cpp b/src/GeantParser/JPetGeantParser/JPetGeantParserTools.cpp index 4e1e664c9..29376a217 100644 --- a/src/GeantParser/JPetGeantParser/JPetGeantParserTools.cpp +++ b/src/GeantParser/JPetGeantParser/JPetGeantParserTools.cpp @@ -1,5 +1,5 @@ /** - * @copyright Copyright 2018 The J-PET Framework Authors. All rights reserved. + * @copyright Copyright 2022 The J-PET Framework Authors. All rights reserved. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may find a copy of the License in the LICENCE file. @@ -13,17 +13,17 @@ * @file JPetGeantParserTools.cpp */ -#include "JPetGeantParser/JPetGeantParserTools.h" #include "JPetSmearingFunctions/JPetSmearingFunctions.h" +#include "JPetGeantParser/JPetGeantParserTools.h" #include -JPetMCHit JPetGeantParserTools::createJPetMCHit(JPetGeantScinHits* geantHit, const JPetParamBank& paramBank) +JPetMCHit JPetGeantParserTools::createJPetMCHit(JPetGeantScinHits* geantHit, const JPetParamBank& paramBank, const float timeShift) { - JPetMCHit mcHit = JPetMCHit(0, // UInt_t MCDecayTreeIndex, - geantHit->GetEvtID(), // UInt_t MCVtxIndex, - geantHit->GetEneDepos(), // keV - geantHit->GetTime(), // ps + JPetMCHit mcHit = JPetMCHit(0, // UInt_t MCDecayTreeIndex, + geantHit->GetEvtID(), // UInt_t MCVtxIndex, + geantHit->GetEneDepos(), // keV + geantHit->GetTime() + timeShift, // ps geantHit->GetHitPosition(), geantHit->GetPolarizationIn(), geantHit->GetMomentumIn()); JPetScin& scin = paramBank.getScintillator(geantHit->GetScinID()); @@ -33,15 +33,14 @@ JPetMCHit JPetGeantParserTools::createJPetMCHit(JPetGeantScinHits* geantHit, con return mcHit; } -JPetHit JPetGeantParserTools::reconstructHit(JPetMCHit& mcHit, const JPetParamBank& paramBank, const float timeShift, - JPetHitExperimentalParametrizer& parametrizer) +JPetHit JPetGeantParserTools::reconstructHit(JPetMCHit& mcHit, const JPetParamBank& paramBank, JPetHitExperimentalParametrizer& parametrizer) { JPetHit hit = dynamic_cast(mcHit); /// Nonsmeared values auto scinID = mcHit.getScintillator().getID(); auto posZ = mcHit.getPosZ(); auto energy = mcHit.getEnergy(); - auto time = mcHit.getTime() + timeShift; + auto time = mcHit.getTime(); hit.setEnergy(parametrizer.addEnergySmearing(scinID, posZ, energy, time)); // adjust to time window and smear @@ -93,6 +92,12 @@ std::tuple, std::vector> JPetGeantParserTools::getTime float timeShift = estimateNextDecayTimeExp(activityMBq); float nextTime = timeWindowMin + timeShift; + // checking if the draw time is not outside the timewindow -> Fix to the low activity issue + if (nextTime > timeWindowMax) { + float timeWindowSize = timeWindowMax - timeWindowMin; + nextTime = timeWindowMin + fmod(nextTime, timeWindowSize); + } + while (nextTime < timeWindowMax) { fTimeDistroOfDecays.push_back(nextTime); diff --git a/src/GeantParser/JPetSmearingFunctions/JPetSmearingFunctions.cpp b/src/GeantParser/JPetSmearingFunctions/JPetSmearingFunctions.cpp index 77355a7d0..54fa105a0 100644 --- a/src/GeantParser/JPetSmearingFunctions/JPetSmearingFunctions.cpp +++ b/src/GeantParser/JPetSmearingFunctions/JPetSmearingFunctions.cpp @@ -17,6 +17,8 @@ #include #include +#include +#include using SmearingType = JPetHitExperimentalParametrizer::SmearingType; using SmearingFunctionLimits = JPetHitExperimentalParametrizer::SmearingFunctionLimits; @@ -24,7 +26,8 @@ using SmearingFunctionLimits = JPetHitExperimentalParametrizer::SmearingFunction JPetHitExperimentalParametrizer::JPetHitExperimentalParametrizer() { - auto timeSmearingF = [&](double* x, double* p) -> double { + auto timeSmearingF = [&](double* x, double* p) -> double + { // p[0] = scinID // p[1] = zIn // p[2] = eneIn @@ -57,7 +60,8 @@ JPetHitExperimentalParametrizer::JPetHitExperimentalParametrizer() fSmearingFunctions[kTime]->SetParameter(5, kEnergyThreshold); fSmearingFunctions[kTime]->SetParameter(6, kReferenceEnergy); - auto energySmearingF = [&](double* x, double* p) -> double { + auto energySmearingF = [&](double* x, double* p) -> double + { // p[0] = scinID // p[1] = zIn // p[2] = eneIn @@ -71,7 +75,8 @@ JPetHitExperimentalParametrizer::JPetHitExperimentalParametrizer() fSmearingFunctions.emplace(kEnergy, std::make_unique("funEnergySmearing", energySmearingF, -200., 200., 4)); - auto zPositionSmearingF = [&](double* x, double* p) -> double { + auto zPositionSmearingF = [&](double* x, double* p) -> double + { // p[0] = scinID // p[1] = zIn // p[2] = eneIn @@ -217,6 +222,9 @@ std::map JPetHitExperimentalParametrizer:: /// function is randomize in the range [lowLim + timeIn, highLim + timeIn] double JPetHitExperimentalParametrizer::addTimeSmearing(int scinID, double zIn, double eneIn, double timeIn) { + if(fUseDefaultTimeSmearing) { + return defaultTimeSmearing(zIn, eneIn, timeIn); + } /// We cannot use setParameters(...) cause if there are more then 4 parameters /// It would set it all to 0. fSmearingFunctions[kTime]->SetParameter(0, double(scinID)); @@ -230,6 +238,10 @@ double JPetHitExperimentalParametrizer::addTimeSmearing(int scinID, double zIn, /// function is randomize in the range [lowLim + eneIn, highLim + eneIn] double JPetHitExperimentalParametrizer::addEnergySmearing(int scinID, double zIn, double eneIn, double timeIn) { + if(fUseDefaultEnergySmearing) { + return defaultEnergySmearing(zIn, eneIn, timeIn); + } + fSmearingFunctions[kEnergy]->SetParameter(0, double(scinID)); fSmearingFunctions[kEnergy]->SetParameter(1, zIn); fSmearingFunctions[kEnergy]->SetParameter(2, eneIn); @@ -241,6 +253,10 @@ double JPetHitExperimentalParametrizer::addEnergySmearing(int scinID, double zIn /// function is randomize in the range [lowLim + zIn, highLim + zIn] double JPetHitExperimentalParametrizer::addZHitSmearing(int scinID, double zIn, double eneIn, double timeIn) { + if(fUseDefaultZSmearing) { + return defaultZHitSmearing(zIn, eneIn, timeIn); + } + /// We cannot use setParameters(...) cause if there are more then 4 parameters /// It would set it all to 0. fSmearingFunctions[kZPosition]->SetParameter(0, double(scinID)); @@ -250,3 +266,27 @@ double JPetHitExperimentalParametrizer::addZHitSmearing(int scinID, double zIn, fSmearingFunctions[kZPosition]->SetRange(zIn + fFunctionLimits[kZPosition].first, zIn + fFunctionLimits[kZPosition].second); return fSmearingFunctions[kZPosition]->GetRandom(); } + +double JPetHitExperimentalParametrizer::defaultTimeSmearing(double /* zIn */, double eneIn, double timeIn) +{ + double random_norm_gaus = gRandom->Gaus(0.0, 1.0); + double sigma = fDefaultTimeSmearingSigma; + if (eneIn < fDefaultTimeSmearingThresholdEnergy){ + sigma /= sqrt(eneIn / fDefaultTimeSmearingReferenceEnergy); + } + return timeIn + random_norm_gaus * sigma; +} + +double JPetHitExperimentalParametrizer::defaultEnergySmearing(double /* zIn */, double eneIn, double /* timeIn */) +{ + double random_norm_gaus = gRandom->Gaus(0.0, 1.0); + double sigma = fDefaultEnergySmearingFraction * eneIn / sqrt(eneIn / 1000.); + return eneIn + random_norm_gaus * sigma; +} + +double JPetHitExperimentalParametrizer::defaultZHitSmearing(double zIn, double /* eneIn */, double /* timeIn */) +{ + double random_norm_gaus = gRandom->Gaus(0.0, 1.0); + double sigma = fDefaultZSmearingSigma; + return zIn + random_norm_gaus * sigma; +} diff --git a/tests/Core/JPetTask/JPetTaskTest.cpp b/tests/Core/JPetTask/JPetTaskTest.cpp index b396053d0..b08f986b2 100644 --- a/tests/Core/JPetTask/JPetTaskTest.cpp +++ b/tests/Core/JPetTask/JPetTaskTest.cpp @@ -1,5 +1,5 @@ /** - * @copyright Copyright 2018 The J-PET Framework Authors. All rights reserved. + * @copyright Copyright 2022 The J-PET Framework Authors. All rights reserved. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may find a copy of the License in the LICENCE file. @@ -19,8 +19,44 @@ #include +class TestTask : public JPetTask +{ +public: + explicit TestTask(const char* name = "") : JPetTask(name) {} + bool init(const JPetParams&) override { return true; } + bool run(const JPetDataInterface&) override { return true; } + bool terminate(JPetParams&) override { return true; } +}; + BOOST_AUTO_TEST_SUITE(JPetTaskTestSuite) -BOOST_AUTO_TEST_CASE(my_test) {} +BOOST_AUTO_TEST_CASE(constructor_test) +{ + TestTask task; + BOOST_REQUIRE_EQUAL(task.getName(), ""); + BOOST_REQUIRE_EQUAL(task.getSubTasks().size(), 0); +} + +BOOST_AUTO_TEST_CASE(task_name_test) +{ + TestTask task("the_task"); + BOOST_REQUIRE_EQUAL(task.getName(), "the_task"); + task.setName("same_task"); + BOOST_REQUIRE_EQUAL(task.getName(), "same_task"); +} + +BOOST_AUTO_TEST_CASE(subtask_test) +{ + TestTask task("task"); + + std::unique_ptr pTask1; + std::unique_ptr pTask2; + std::unique_ptr pTask3; + task.addSubTask(std::move(pTask1)); + task.addSubTask(std::move(pTask2)); + task.addSubTask(std::move(pTask3)); + + BOOST_REQUIRE_EQUAL(task.getSubTasks().size(), 3); +} BOOST_AUTO_TEST_SUITE_END()