MDT is a C++ library designed to post-process simulation output from WCSim (Water Cherenkov Simulator). Its primary function is to bridge the gap between "True Hits" (Monte Carlo photoelectrons) and "Digitized Hits" (ADC counts and timestamps representing electronic readout).
The system is architected around three main phases:
- Merging: Combining true hits from multiple sources (e.g., neutrino interactions + beam background) and adding intrinsic PMT noise (Dark Rate).
- Digitizing: Simulating the PMT and electronics response to convert photoelectrons (PE) into digital time and charge.
- Triggering: Applying detector trigger logic to select events of interest.
The core logic resides in cpp/src and cpp/include. The architecture relies heavily on polymorphism to handle different PMT types and digitization models.
The PMTResponse class hierarchy defines how a specific PMT behaves physically (Quantum Efficiency, Transit Time Spread, Gain).
- Base Class:
PMTResponse(Abstract)- Interface:
GetRawSPE(...): Returns the charge of a Single Photoelectron (SPE), typically drawn from a distribution, for standardHitDigitizer.HitTimeSmearing(Q): Returns the time jitter (resolution) based on chargeQ, for standardHitDigitizer.ApplyDE(...): Determines if a photon is detected based on angular efficiency.
- Interface:
- Generic Implementation:
GenericPMTResponse- Handles loading standard configuration files:
- SPE CDF: Cumulative Distribution Function for charge generation.
- PMTDE: mPMT_ID-dependent angular efficiency maps.
- PMTTime: PMT-specific timing offsets.
- Handles loading standard configuration files:
- Specific Implementations:
ResponseBoxandLine20inchHQE: Implements a specific time smearing model usingksig_paramandklambda_param.Response3inchR14374_WCTE: Uses aTGraph(gTResol) to interpolate timing resolution as a function of charge.
The HitDigitizer class is responsible for converting a collection of True Hits on a single PMT into Digitized Hits.
- Base Class:
HitDigitizer- Standard Algorithm (
DigitizeTube):- Sorts true hits by time.
- Iterates through hits using an Integration Window (
fIntegWindow). - Sums charge of all hits within the window.
- Applies
HitTimeSmearingfrom thePMTResponseobject. - Applies
ApplyThresholdto simulate DAQ efficiency/thresholds. - Truncates values to simulate electronics precision (
fPrecisionTiming,fPrecisionCharge).
- Standard Algorithm (
- Waveform Digitizer:
HitDigitizer_mPMT- Purpose: Simulates the full voltage waveform for multi-PMT (mPMT) setups or advanced analysis.
- Workflow:
BuildWavetrain: Superimposes SPE pulse shapes (loaded fromWaveformFile) onto a histogram based on true hit times. The SPE amplitude is sampled from a Gaussian distribution of widthfAmplitudeSigma.FitWavetrain: Analyzes the generated waveform to extract hits.- Hit Finding: Looks for local maxima exceeding
fAmplitudeThreshold. - Time: Uses Linear Interpolation (CFD-like) to find the zero-crossing point.
- Charge: Integrates samples around the peak (
fChargeWindowBefore,fChargeWindowAfter).
- Hit Finding: Looks for local maxima exceeding
- Dark Noise:
GenerateDarkNoise: Calculates the number of noise hits using a Poisson distribution based onfDarkRateand the time window.AddPhotoElectrons: Injects these noise hits into theHitTubeCollectionas if they were true photons.
- Afterpulsing:
AddAfterpulse: Iterates through digitized hits. If a hit triggers an afterpulse (probabilistic), a new hit is generated with a time delay and charge, then added to the digitizer.
The library implements a trigger simulation via the TriggerAlgo class to determine if an event should be recorded, mimicking the Data Acquisition (DAQ) logic. Results are stored in TriggerInfo.
-
Classes:
TriggerAlgo: Handles the trigger logic. Configured viaMDTParFile.TriggerInfo: Container for trigger results (Trigger Time, Readout Window Start/End, Number of Hits, Trigger Type).
-
Algorithms:
- NDigits (
TriggerType = NDigits):- Collects and sorts all digitized hit times from the
HitTubeCollection. - Slides a time window of width
NDigitsWindowwith stepNDigitsStepSize. - Condition: Fires if hit count >
NDigitsThreshold. - Readout: Saves hits within [
TrigTime+PreTriggerWindow,TrigTime+PostTriggerWindow]. - Overlap: Adjusts the start of the readout window if it overlaps with a previous trigger to avoid duplication.
- Failure: If no trigger is found, a "Failure" trigger is recorded (typically with a specific failure time and window).
- Collects and sorts all digitized hit times from the
- NoTrig (
TriggerType = NoTrig):- Forces a trigger at T=0. Useful for saving fixed windows or debugging.
- NDigits (
-
Usage in MDTManager:
DoTrigger(pmtType): InvokesTriggerAlgo::DoTrigger.GetTriggerInfo(pmtType): Returns the populatedTriggerInfoobject.
The app/ directory contains executable applications that utilize the core library to process WCSim files.
Most applications follow this sequence:
- Configuration: Read parameters (Singleton
Configurationclass). - Initialization: Instantiate
MDTManagerand register PMT types. - Event Loop:
- Read
wcsimrootevent(True Hits). - AddTrueHits: Pass hits to MDT.
- DoAddDark: Add noise.
- DoDigitize: Convert to DigiHits.
- DoTrigger: Run trigger logic (e.g.,
MDT->DoTrigger(pmtType)). - Write: Retrieve trigger info (
MDT->GetTriggerInfo) and save DigiHits to output ROOT file.
- Read
appGenPileUpSpill:- Purpose: Generates "spills" containing multiple neutrino interactions and beam background events (e.g., for T2K/Hyper-K).
- Logic:
- Uses
WCRootDataIDNuIntandWCRootDataBeamBkgto manage input files. - Uses
BeamTimingto distribute events in time according to beam bunch structure. - Merges hits from all interactions into a single
MDTManagerinstance before digitizing.
- Uses
appWCTESingleEvent/appIWCDSingleEvent:- Purpose: Standard processing for single-event simulations (1 input event = 1 output event).
- Difference:
WCTEuses specific PMT model (Response3inchR14374_WCTE), whileIWCDsupports hybrid ID+OD configurations.
graph TD
App["Application (e.g., appWCTESingleEvent)"] --> Config[Configuration]
App -- Read --> Input[WCRootData Input]
App --> MDT[MDTManager]
MDT -- Register --> PMTType[PMTType]
PMTType --> Tubes[HitTubeCollection]
PMTType --> Noise[PMTNoise]
PMTType --> PMTResponse
PMTType --> Digi[HitDigitizer]
PMTType --> Trig[TriggerAlgo]
Input -- Add TrueHits --> Tubes
Input -- Use --> PMTResponse
Noise -- Add Dark Hits --> Tubes
Digi -- Use --> PMTResponse
Tubes -- Digitize --> Digi
Tubes -- Pass DigiHits --> Trig
Trig -- Generate --> TrigInfo[TriggerInfo]
TrigInfo --> Output[WCRootData Output]
Tubes -- Write --> Output
To add a new PMT model (e.g., a new 3-inch PMT):
- Create Header/Source: Create
PMTResponseNewType.hand.cc. - Inherit: Inherit from
GenericPMTResponse. - Implement:
Initialize(): Load specific parameters.HitTimeSmearing(float Q): Define the timing resolution function.
- Register: In your application (e.g.,
app/application/MyApp.cc), include the header and register it:MDT->RegisterPMTType("PMTNewType", new PMTResponseNewType());
To change how waveforms are processed:
- Modify
HitDigitizer_mPMT:- Update
BuildWavetrainif the pulse superposition logic changes. - Update
FitWavetrainto implement new hit-finding algorithms (e.g., changing from CFD to a fixed threshold or template fitting).
- Update
- Configuration: Ensure
DigitizerTypeis set correctly in the parameter file, andWaveformFilepoints to the correct SPE pulse shape.
- Implement logic in
TriggerAlgothat scansHitTubeCollectionforDigiHitsmeeting coincidence criteria (e.g., NDigits). - Ensure
TriggerInfois populated with the correct trigger time and readout window.
The system is driven by text-based parameter files. Key parameters include:
DigitizerType: Selects between standard (WCSim) or waveform digitizer.WaveformFile: Path to the text file containing the waveform pulse shape (Time vs Voltage).
DarkRate: PMT dark noise rate in kHz.PMTDE: Path to PMT angular efficiency file.- Trigger Parameters:
TriggerType:NDigitsorNoTrig.NDigitsWindow: Width of the sliding window (ns).NDigitsThreshold: Minimum number of hits to fire a trigger.