10#include <klm/modules/KLMDigitizer/KLMDigitizerModule.h>
13#include <klm/dataobjects/KLMChannelIndex.h>
14#include <klm/dataobjects/KLMScintillatorFirmwareFitResult.h>
15#include <klm/simulation/ScintillatorSimulator.h>
18#include <framework/dataobjects/BackgroundMetaData.h>
19#include <mdst/dataobjects/MCParticle.h>
51 m_ChannelSpecificSimulation(false),
52 m_EfficiencyMode(c_Plane),
55 setDescription(
"KLM digitization module: create KLMDigits from KLMSimHits.");
58 "Simulation mode (\"Generic\" or \"ChannelSpecific\").",
59 std::string(
"Generic"));
65 "Initial digitization time in CTIME periods.", -5);
66 addParam(
"SaveFPGAFit",
m_SaveFPGAFit,
"Save FPGA fit data and set a relation with KLMDigits.",
false);
68 "Efficiency determination mode (\"Strip\" or \"Plane\").",
69 std::string(
"Plane"));
71 "Whether to create multi-strip digits in Run 1 data (not used for Run 2+).",
true);
73 "Debug mode (generates additional output files with histograms).",
110 klmChannel.getSector(), klmChannel.getLayer(),
111 klmChannel.getPlane(), klmChannel.getStrip());
113 if (FEEData ==
nullptr)
114 B2FATAL(
"Incomplete scintillator FEE data.");
116 B2ERROR(
"Non-positive photoelectron amplitude. The requested "
117 "channel-specific simulation is impossible. "
118 "KLMDigitizer is switched to the generic mode."
119 <<
LogVar(
"Section", klmChannel.getSection())
120 <<
LogVar(
"Layer", klmChannel.getLayer())
121 <<
LogVar(
"Sector", klmChannel.getSector())
122 <<
LogVar(
"Plane", klmChannel.getPlane())
123 <<
LogVar(
"Strip", klmChannel.getStrip()));
133 B2FATAL(
"KLM scintillator digitization parameters are not available.");
135 B2FATAL(
"KLM scintillator FEE parameters are not available.");
137 B2FATAL(
"KLM channel status data are not available.");
139 B2FATAL(
"KLM strip efficiency data are not available.");
141 B2FATAL(
"KLM scintillator firmware version is not available.");
166 B2FATAL(
"Incomplete KLM channel status data.");
172 if (std::isnan(efficiency))
173 B2FATAL(
"Incomplete KLM efficiency data.");
174 double selection = gRandom->Uniform();
175 return (selection < efficiency);
180 std::multimap<KLMChannelNumber, const KLMSimHit*>::iterator
181 it, it2, lowerBound, upperBound;
187 if (not lowerBound->second->inRPC())
188 B2FATAL(
"KLMDigitizer::digitizeRPC is trying to process a scintillator hit.");
198 const KLMSimHit* hit = lowerBound->second;
199 double time = hit->getTime();
201 while (it2 != upperBound) {
202 if (it2->second->getTime() < time) {
203 time = it2->second->getTime();
210 while (it2 != upperBound) {
224 std::multimap<KLMChannelNumber, const KLMSimHit*>::iterator
225 it, lowerBound, upperBound;
226 for (
int i = 0; i < KLM::c_NChannelsAsic; ++i)
233 if (lowerBound->second->inRPC())
234 B2FATAL(
"KLMDigitizer::digitizeScintillator is trying to process a RPC hit.");
235 const KLMSimHit* simHit = lowerBound->second;
242 FEEData =
m_FEEPar->getFEEData(lowerBound->first);
243 if (FEEData ==
nullptr)
244 B2FATAL(
"Incomplete KLM scintillator FEE data.");
247 simulator.
simulate(lowerBound, upperBound);
252 int channel = (electronicsChannel->
getChannel() - 1) %
253 KLM::c_NChannelsAsic;
263 KLM::c_ScintillatorFirmwareSuccessfulFit) {
276 KLM::c_ScintillatorFirmwareSuccessfulFit)) {
286 std::multimap<KLMElectronicsChannel, const KLMSimHit*>::iterator
288 std::multimap<KLMChannelNumber, const KLMSimHit*>::iterator it3;
293 for (it2 = it; it2 != upperBound; ++it2) {
297 hit->getSubdetector(), hit->getSection(), hit->getSector(),
298 hit->getLayer(), hit->getPlane(), hit->getStrip());
300 std::pair<KLMChannelNumber, const KLMSimHit*>(channel, hit));
305 for (
int i = 0; i < KLM::c_NChannelsAsic; ++i) {
309 bool multiStripMode = (nDigits >= 2);
311 while (i < KLM::c_NChannelsAsic) {
313 if (digit ==
nullptr) {
320 int minGroupChannel = 1;
321 int maxGroupChannel = KLM::c_NChannelsAsic;
325 bool connectedChannelFound =
false;
326 int minStrip, maxStrip;
327 for (
int j = minGroupChannel; j <= maxGroupChannel; ++j) {
328 electronicsChannel.
setChannel(KLM::c_NChannelsAsic * asic + j);
331 if (detectorChannel !=
nullptr) {
332 int subdetector, section, sector, layer, plane, strip;
334 *detectorChannel, &subdetector, §ion, §or, &layer,
336 if (!connectedChannelFound) {
337 connectedChannelFound =
true;
341 if (strip < minStrip)
343 if (strip > maxStrip)
349 if (!connectedChannelFound)
350 B2FATAL(
"Cannot find connected electronics channels.");
351 if (multiStripMode) {
355 for (
int j = i; j < maxGroupChannel; ++j) {
365 for (i = 0; i < KLM::c_NChannelsAsic; ++i) {
370 for (
int i = 0; i < KLM::c_NChannelsAsic; ++i) {
372 if (digit ==
nullptr)
394 for (i = 0; i <
m_SimHits.getEntries(); i++) {
397 if (hit->getStrip() <= 0)
405 if (particle !=
nullptr) {
408 hit->getSubdetector(), hit->getSection(), hit->getSector(),
409 hit->getLayer(), hit->getPlane());
411 std::pair<KLMPlaneNumber, const KLMSimHit*>(plane, hit));
413 B2ASSERT(
"The KLMSimHit is not related to any MCParticle and "
414 "it is also not a beam background hit.",
418 hit->getSubdetector(), hit->getSection(), hit->getSector(),
419 hit->getLayer(), hit->getPlane(), hit->getStrip());
421 bool rpc = hit->inRPC();
423 m_MapChannelSimHit.insert(std::pair<KLMChannelNumber, const KLMSimHit*>(channel, hit));
427 if (electronicsChannel ==
nullptr)
428 B2FATAL(
"Incomplete electronics map.");
430 m_MapAsicSimHit.insert(std::pair<KLMElectronicsChannel, const KLMSimHit*>(asic, hit));
435 std::multimap<KLMPlaneNumber, const KLMSimHit*>::iterator it, it2;
443 std::multimap<const MCParticle*, const KLMSimHit*>::iterator
444 itParticle, it2Particle;
447 particleHitMap.clear();
452 particleHitMap.insert(
453 std::pair<const MCParticle*, const KLMSimHit*>(particle, hit));
457 if (it2->first != it->first)
460 itParticle = particleHitMap.begin();
461 while (itParticle != particleHitMap.end()) {
462 it2Particle = itParticle;
463 const KLMSimHit* hit = it2Particle->second;
466 hit->getSubdetector(), hit->getSection(), hit->getSector(),
467 hit->getLayer(), hit->getPlane(), hit->getStrip());
471 hit = it2Particle->second;
472 bool rpc = hit->inRPC();
474 for (
int s = hit->getStrip(); s <= hit->getLastStrip(); ++s) {
477 hit->getSubdetector(), hit->getSection(), hit->getSector(),
478 hit->getLayer(), hit->getPlane(), s);
483 std::pair<KLMChannelNumber, const KLMSimHit*>(channel, hit));
487 if (electronicsChannel ==
nullptr)
488 B2FATAL(
"Incomplete electronics map.");
491 std::pair<KLMElectronicsChannel, const KLMSimHit*>(
497 if (it2Particle == particleHitMap.end())
499 if (it2Particle->first != itParticle->first)
502 itParticle = it2Particle;
507 for (i = 0; i <
m_SimHits.getEntries(); i++) {
510 if (hit->getStrip() <= 0)
512 for (
int s = hit->getStrip(); s <= hit->getLastStrip(); ++s) {
514 hit->getSection(), hit->getSector(), hit->getLayer(),
518 std::pair<KLMChannelNumber, const KLMSimHit*>(channel, hit));
523 hit->getSubdetector(), hit->getSection(), hit->getSector(),
524 hit->getLayer(), hit->getPlane(), hit->getStrip());
528 if (electronicsChannel ==
nullptr)
529 B2FATAL(
"Incomplete electronics map.");
532 std::pair<KLMElectronicsChannel, const KLMSimHit*>(asic, hit));
static int getStripByModule(int module)
Get strip number by module identifier.
ChannelStatus
Channel status.
@ c_Dead
Dead channel (no signal).
@ c_Unknown
Unknown status (no data).
KLM digit (class representing a digitized hit in RPCs or scintillators).
void setMCTime(float time)
Set MC time.
void setNGeneratedPhotoelectrons(int nPhotoelectrons)
Set generated number of photoelectrons.
void setLastStrip(int lastStrip)
Set last strip number (for multi-strip digits).
void setSiPMMCTime(float time)
Set SiPM MC time.
void setEnergyDeposit(float eDep)
Set energy deposit.
void setNPhotoelectrons(float nPhotoelectrons)
Set number of photoelectrons.
void setStrip(int strip)
Set strip number.
void setTime(float time)
Set hit time.
void setTDC(uint16_t tdc)
Set TDC.
void setFitStatus(int s)
Set fit status.
void setCharge(uint16_t charge)
Set charge.
std::multimap< KLMElectronicsChannel, const KLMSimHit * > m_MapAsicSimHit
Simulation hit map (by ASIC).
std::multimap< KLMPlaneNumber, const KLMSimHit * > m_MapPlaneSimHit
Simulation hit map (by plane).
KLMDigit * m_AsicDigits[KLM::c_NChannelsAsic]
Digits corresponding to ASIC channels.
EfficiencyMode m_EfficiencyMode
Efficiency determination mode (converted from the string parameter).
StoreArray< KLMDigit > m_Digits
KLM digits.
DBObjPtr< KLMChannelStatus > m_ChannelStatus
Channel status.
DBObjPtr< KLMScintillatorFEEParameters > m_FEEPar
Scintillator FEE parameters.
void initialize() override
Initializer.
bool m_CreateMultiStripDigitsByRun
Whether to create multi-strip digits for one particular run.
bool efficiencyCorrection(float efficiency)
Efficiency correction.
void event() override
This method is called for each event.
const KLMElementNumbers * m_ElementNumbers
Element numbers.
bool m_SaveFPGAFit
Save FPGA fit data (KLMScintillatorFirmwareFitResult).
bool checkActive(KLMChannelNumber channel)
Check if channel is active (status is not KLMChannelStatus::c_Dead).
void endRun() override
This method is called if the current run ends.
DBObjPtr< KLMScintillatorDigitizationParameters > m_DigPar
Scintillator digitization parameters.
std::multimap< KLMChannelNumber, const KLMSimHit * > m_MapChannelSimHit
Simulation hit map (by channel).
void terminate() override
This method is called at the end of the event processing.
bool m_Debug
Use debug mode in EKLM::ScintillatorSimulator or not.
StoreArray< KLMSimHit > m_SimHits
Simulation hits.
void digitizeRPC()
Digitization in RPCs.
int m_DigitizationInitialTime
Initial digitization time in CTIME periods.
std::multimap< KLMChannelNumber, constKLMSimHit * >::iterator m_AsicDigitSimHitsUpperBound[KLM::c_NChannelsAsic]
Simulation hits upper bound for ASIC digit.
void digitizeScintillator()
Digitization in scintillators.
void checkScintillatorFEEParameters()
Check scintillator FEE parameters for channel-specific simulation.
std::string m_Efficiency
Efficiency determination mode ("Strip" or "Plane").
void beginRun() override
Called when entering a new run.
DBObjPtr< KLMScintillatorFirmware > m_ScintillatorFirmware
Scintillator FEE firmware version.
DBObjPtr< KLMElectronicsMap > m_ElectronicsMap
Electronics map.
std::multimap< KLMChannelNumber, constKLMSimHit * >::iterator m_AsicDigitSimHitsLowerBound[KLM::c_NChannelsAsic]
Simulation hits lower bound for ASIC digit.
KLMDigitizerModule()
Constructor.
void digitizeAsic()
Digitization in ASIC.
~KLMDigitizerModule()
Destructor.
StoreArray< KLMScintillatorFirmwareFitResult > m_FPGAFits
FPGA fits.
bool m_ChannelSpecificSimulation
Whether the simulation is channel-specific.
KLMTime * m_Time
Time conversion.
bool m_CreateMultiStripDigits
Whether to create multi-strip digits.
DBObjPtr< KLMStripEfficiency > m_StripEfficiency
Strip efficiency.
KLM::ScintillatorFirmware * m_Fitter
FPGA fitter.
std::string m_SimulationMode
Simulation mode.
BKLM electronics channel.
int getChannel() const
Get channel.
KLMElectronicsChannel getAsic() const
Get ASIC.
void setChannel(int channel)
Set channel.
KLMChannelNumber channelNumberBKLM(int section, int sector, int layer, int plane, int strip) const
Get channel number for BKLM.
KLMChannelNumber channelNumber(int subdetector, int section, int sector, int layer, int plane, int strip) const
Get channel number.
KLMPlaneNumber planeNumber(int subdetector, int section, int sector, int layer, int plane) const
Get plane number.
void channelNumberToElementNumbers(KLMChannelNumber channel, int *subdetector, int *section, int *sector, int *layer, int *plane, int *strip) const
Get element numbers by channel number.
int localChannelNumberBKLM(KLMChannelNumber channel) const
Get local BKLM channel number.
float getPhotoelectronAmplitude() const
Get photoelectron amplitude.
FPGA fit simulation data.
int getMinimalAmplitude() const
Get minimal amplitude (ADC output).
int getStartTime() const
Get signal start time (in TDC counts).
FirmwareVersion
Enumerator for the scintillator firmware version.
@ c_Invalid
Flag for marking an invalid version.
@ c_Run1
Flag for Run 1 (from 2019a to 2022b)
@ c_Phase2
Flag for Phase 2 version.
double getCTimePeriod() const
Get CTIME period.
double getTimeSimulation(int tdc, bool scintillator) const
Get time for simulation.
void updateConstants()
Update constants from database objects.
Digitize EKLMSim2Hits to get EKLM StripHits.
float getSiPMMCTime() const
Get SiPM MC time.
void setFEEData(const KLMScintillatorFEEData *FEEData)
Set FEE data.
enum ScintillatorFirmwareFitStatus getFitStatus() const
Get fit status.
double getEnergy()
Get total energy deposited in the strip (sum over ssimulation hits).
double getNPhotoelectrons()
Get number of photoelectrons (fit result).
KLMScintillatorFirmwareFitResult * getFPGAFit()
Get fit data.
float getMCTime() const
Get MC time.
int getNGeneratedPhotoelectrons()
Get generated number of photoelectrons.
void simulate(const std::multimap< KLMChannelNumber, const KLMSimHit * >::iterator &firstHit, const std::multimap< KLMChannelNumber, const KLMSimHit * >::iterator &end)
Simulate a strip.
A Class to store the Monte Carlo particle information.
int getIndex() const
Get 1-based index of the particle in the corresponding MCParticle list.
void setDescription(const std::string &description)
Sets the description of the module.
void setPropertyFlags(unsigned int propertyFlags)
Sets the flags for the module properties.
@ c_ParallelProcessingCertified
This module can be run in parallel processing mode safely (All I/O must be done through the data stor...
void addRelationTo(const RelationsInterface< BASE > *object, float weight=1.0, const std::string &namedRelation="") const
Add a relation from this object to another object (with caching).
Comparison of MCParticles by index.
bool operator()(const MCParticle *particle1, const MCParticle *particle2) const
Compare MCParticles by index.
Class to store variables with their name which were sent to the logging service.
void addParam(const std::string &name, T ¶mVariable, const std::string &description, const T &defaultValue)
Adds a new parameter to the module.
#define REG_MODULE(moduleName)
Register the given module (without 'Module' suffix) with the framework.
uint16_t KLMChannelNumber
Channel number.
uint16_t KLMPlaneNumber
Plane number.
Abstract base class for different kinds of events.