Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Hcal tot digitization #1475

Draft
wants to merge 5 commits into
base: trunk
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Binary file added .DS_Store
Binary file not shown.
Binary file added Hcal/.DS_Store
Binary file not shown.
4 changes: 2 additions & 2 deletions Hcal/python/digi.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ def __init__(self, instance_name = 'hcalDigis') :

# avg parameters
self.avgReadoutThreshold = 4. #ADCs - noise config only
self.avgGain = 1.2 #noise config only
self.avgGain = 5100./1023. #noise config only
self.avgPedestal = 1. #noise config only
# avg noise set to 0.02PE
self.avgNoiseRMS = self.hgcroc.calculateVoltageHcal(0.02)/self.avgGain
Expand Down Expand Up @@ -151,7 +151,7 @@ def __init__(self, instance_name = 'hcalRecon') :

# avg parameters
self.avgToaThreshold = 1.6 # mV - correction config only
self.avgGain = 1.2 # correction config only
self.avgGain = 5100./1023. # correction config only
self.avgPedestal = 1. #noise config only

class HcalSingleEndRecProducer(Producer) :
Expand Down
14 changes: 7 additions & 7 deletions Hcal/python/hcal_hardcoded_conditions.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
HcalTrigPrimConditionsHardcode.validForAllRows([ 1 , # ADC_PEDESTAL -- should match value from HgcrocEmulator
5 , # ADC_THRESHOLD -- current noise is
1, # TOT_PEDESTAL -- currently set to match ADC pedestal
10000, # TOT_THRESHOLD -- rather large value...
5100., # TOT_THRESHOLD
# Rounding because trigger primitives shouldn't represent floating point operations.
# See https://github.com/LDMX-Software/Hcal/issues/66#issuecomment-1719663799
round(2.5) ] # TOT_GAIN, ratio of recon TOT gain over recon ADC gain
Expand Down Expand Up @@ -59,13 +59,13 @@

HcalHgcrocConditionsHardcode.validForAllRows([
1. , #PEDESTAL
0.02*5/1.2, #NOISE - 0.02 PE with 1 PE ~ 5mV and gain = 1.2
0.02*5/(5100./1023.), #NOISE - 0.02 PE with 1 PE ~ 5mV and gain = 5100./1023.
12.5, #MEAS_TIME - ns - clock_cycle/2 - defines the point in the BX where an in-time (time=0 in times vector) hit would arrive
20., #PAD_CAPACITANCE - pF
13/5.1, #PAD_CAPACITANCE - pF
200., #TOT_MAX - ns - maximum time chip would be in TOT mode
10240. / 200., #DRAIN_RATE - fC/ns - dummy value for now
1.2, #GAIN - large ADC gain for now - conversion from ADC to mV
320000./200., #DRAIN_RATE - fC/ns - to drain maximum charge of 320000fC in 200ns
5100./1023., #GAIN - take 160 fC - 13 pC to be the linear range of ADC -> V_{adc_max} = 13pC/13/5.1pF = 5100mV
1. + 4., #READOUT_THRESHOLD - 4 ADC counts above pedestal
1.*1.2 + 1*5, #TOA_THRESHOLD - mV - 1 PE above pedestal ( 1 PE - 5 mV conversion)
10000., #TOT_THRESHOLD - mV - very large for now
1.*(5100./1023.) + 1*5, #TOA_THRESHOLD - mV - 1 PE above pedestal ( 1 PE - 5 mV conversion)
5100., #TOT_THRESHOLD - mV - TOT begins at V_{adc_max}
])
Binary file added Hcal/src/.DS_Store
Binary file not shown.
89 changes: 87 additions & 2 deletions Hcal/src/Hcal/HcalDigiProducer.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,10 @@

#include "Hcal/HcalDigiProducer.h"

#include <fstream>

#include "Framework/RandomNumberSeedService.h"
#include "Tools/PulseRecord.h"

namespace hcal {

Expand Down Expand Up @@ -130,6 +133,10 @@ void HcalDigiProducer::produce(framework::Event& event) {
std::vector<std::pair<double, double>> pulses_posend;
std::vector<std::pair<double, double>> pulses_negend;

// For plotting purposes
std::vector<std::tuple<double, int, int>> DigiToPlot;
DigiToPlot.clear();

for (auto psimHit : simBar.second) {
const ldmx::SimCalorimeterHit& simHit = *psimHit;

Expand Down Expand Up @@ -213,6 +220,10 @@ void HcalDigiProducer::produce(framework::Event& event) {
for (int iContrib = 0; iContrib < simHit.getNumberOfContribs();
iContrib++) {
double voltage = simHit.getContrib(iContrib).edep * MeV_;

std::cout << " Energy deposited: " << simHit.getContrib(iContrib).edep
<< std::endl;

double time =
simHit.getContrib(iContrib).time; // global time (t=0ns at target)
time -= position.at(2) /
Expand Down Expand Up @@ -246,7 +257,44 @@ void HcalDigiProducer::produce(framework::Event& event) {
hgcroc_->digitize(negendID.raw(), pulses_negend, digiToAddNegend)) {
hcalDigis.addDigi(posendID.raw(), digiToAddPosend);
hcalDigis.addDigi(negendID.raw(), digiToAddNegend);
} // Back Hcal needs to digitize both pulses or none

// for(const auto& digi: hcalDigis){
// std::cout << " DEBUG PRINT 2: " << digi.at(2) << std::endl;
// }
}

// Recording digitized pulses in PulseRecord
// Since two pulses are digitized, using existing loop is bit untidy.
// Access PulseRecord
if (hgcroc_->digitize(posendID.raw(), pulses_posend, digiToAddPosend) &&
hgcroc_->digitize(negendID.raw(), pulses_negend, digiToAddNegend)) {
const auto& pulseRecord = hgcroc_->getPulseRecord();

for (const auto& record : pulseRecord) {
DigiToPlot.emplace_back(record.getVolts(), record.getADC(),
record.getTOT());
}
}

if (hgcroc_->digitize(posendID.raw(), pulses_negend, digiToAddNegend) &&
hgcroc_->digitize(posendID.raw(), pulses_posend, digiToAddPosend)) {
const auto& pulseRecord = hgcroc_->getPulseRecord();

for (const auto& record : pulseRecord) {
DigiToPlot.emplace_back(record.getVolts(), record.getADC(),
record.getTOT());
}
Comment on lines +283 to +286
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One of the code blocks that could be skipped if the user doesn't want to save the digi emulation detailed information.

}

// Print Voltages, adc/tot values to the same txt file
std::ofstream dataFile("Voltage_ADC_TOT.txt", std::ios::app);
for (const auto& entry : DigiToPlot) {
dataFile << std::get<0>(entry) << " " << std::get<1>(entry) << " "
<< std::get<2>(entry) << "\n";
}
dataFile.close();
Comment on lines +289 to +295
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This chunk of code (and the others like it) is incredibly helpful for you the developer when tuning the digitization parameters; however, most people running this producer will not be tuning the parameters and creating an extra txt file would at best be confusing and at worst cause extra issues.

My request here is to put these code blocks behind a configuration parameter such that the user can choose whether to save the digitization information. Maybe a digi_emulation_file parameter that is the file to save the information to? (e.g. it could be "Voltage_ADC_TOT.txt") and when it is empty, nothing is saved.


// Back Hcal needs to digitize both pulses or none
} else {
bool is_posend = false;
std::vector<ldmx::HgcrocDigiCollection::Sample> digiToAdd;
Expand All @@ -262,18 +310,54 @@ void HcalDigiProducer::produce(framework::Event& event) {
if (hgcroc_->digitize(digiID.raw(), pulses_posend, digiToAdd)) {
hcalDigis.addDigi(digiID.raw(), digiToAdd);
}
// Recording digitized pulses in PulseRecord
// Access PulseRecord
const auto& pulseRecord = hgcroc_->getPulseRecord();

for (const auto& record : pulseRecord) {
DigiToPlot.emplace_back(record.getVolts(), record.getADC(),
record.getTOT());
}

// Print Voltages, adc/tot values to the same txt file
std::ofstream dataFile("Voltage_ADC_TOT.txt", std::ios::app);
for (const auto& entry : DigiToPlot) {
dataFile << std::get<0>(entry) << " " << std::get<1>(entry) << " "
<< std::get<2>(entry) << "\n";
}
dataFile.close();

Comment on lines +313 to +329
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One of the code blocks that could be skipped if the user doesn't want to save the digi emulation detailed information.

} else {
ldmx::HcalDigiID digiID(section, layer, strip, 1);
if (hgcroc_->digitize(digiID.raw(), pulses_negend, digiToAdd)) {
hcalDigis.addDigi(digiID.raw(), digiToAdd);
}

// Recording digitized pulses in PulseRecord
// Access PulseRecord
const auto& pulseRecord = hgcroc_->getPulseRecord();

for (const auto& record : pulseRecord) {
DigiToPlot.emplace_back(record.getVolts(), record.getADC(),
record.getTOT());
}

// Print Voltages, adc/tot values to the same txt file
std::ofstream dataFile("Voltage_ADC_TOT.txt", std::ios::app);
for (const auto& entry : DigiToPlot) {
dataFile << std::get<0>(entry) << " " << std::get<1>(entry) << " "
<< std::get<2>(entry) << "\n";
}
dataFile.close();
Comment on lines +335 to +351
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One of the code blocks that could be skipped if the user doesn't want to save the digi emulation detailed information.

}
}
}

/******************************************************************************************
* Noise Simulation on Empty Channels
*****************************************************************************************/
// bool noise_ = false;
// std::cout << " noise: " << noise_ << std::endl;
if (noise_) {
int numChannels = 0;
for (int section = 0; section < hcalGeometry.getNumSections(); section++) {
Expand Down Expand Up @@ -349,7 +433,8 @@ void HcalDigiProducer::produce(framework::Event& event) {
}
}
} // loop over noise amplitudes
} // if we should add noise

} // if we should add noise

event.add(digiCollName_, hcalDigis);

Expand Down
Binary file added Tools/.DS_Store
Binary file not shown.
Binary file added Tools/include/.DS_Store
Binary file not shown.
9 changes: 9 additions & 0 deletions Tools/include/Tools/HgcrocEmulator.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "Recon/Event/HgcrocDigiCollection.h"
#include "SimCore/Event/SimCalorimeterHit.h"
#include "Tools/NoiseGenerator.h"
#include "Tools/PulseRecord.h"

//----------//
// ROOT //
Expand Down Expand Up @@ -441,6 +442,14 @@ class HgcrocEmulator {
*/
mutable TF1 pulseFunc_;

mutable std::vector<ldmx::PulseRecord> pulseRecord_;

// Getter to access pulseRecord_
public:
const std::vector<ldmx::PulseRecord>& getPulseRecord() const {
return pulseRecord_;
}

}; // HgcrocEmulator

} // namespace ldmx
Expand Down
26 changes: 26 additions & 0 deletions Tools/include/Tools/PulseRecord.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#ifndef TOOLS_PULSERECORD_H_
#define TOOLS_PULSERECORD_H_

// new class PulseRecord for plotting purposes

namespace ldmx {

class PulseRecord {
public:
// Constructor to initialize Voltage, ADC, and TOT
PulseRecord(double volts, int adc, int tot)
: volts_(volts), adc_(adc), tot_(tot) {}

// Getters for the recorded data
double getVolts() const { return volts_; }
int getADC() const { return adc_; }
int getTOT() const { return tot_; }

private:
double volts_;
int adc_;
int tot_;
};
} // namespace ldmx

#endif
Binary file added Tools/src/.DS_Store
Binary file not shown.
35 changes: 31 additions & 4 deletions Tools/src/Tools/HgcrocEmulator.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ bool HgcrocEmulator::digitize(
std::vector<ldmx::HgcrocDigiCollection::Sample> &digiToAdd) const {
// step 0: prepare ourselves for emulation

digiToAdd.clear(); // make sure it is clean
digiToAdd.clear(); // make sure it is clean
pulseRecord_.clear(); // clear pulseRecord

// Configure chip settings based off of table (that may have been passed)
double totMax = getCondition(channelID, "TOT_MAX");
Expand Down Expand Up @@ -101,8 +102,20 @@ bool HgcrocEmulator::digitize(
continue; // if this hit wasn't in the current BX, continue...

double vpeak = pulse(hit.second);
double bxvolts = pulse((iADC - iSOI_) * clockCycle_);

// std::cout << "DEBUG PRINT - COMPARE IN COMING VOLTAGE AND PULSE FUNC
// VOLTAGE" << std::endl; std::cout << " Incoming peak Voltage: " <<
// vpeak << std::endl; std::cout << " Pulse func Voltage: " << bxvolts
// << std::endl; std::cout << " " << std::endl;

// if (vpeak > totThreshold){
// startTOT = true;
// if (toverTOT < hit.second)
// toverTOT = hit.second; // use the latest time in the window
//}

if (vpeak > totThreshold) {
if (bxvolts > totThreshold) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the part that I am worried about effecting the ECal digi emulation as well. This is a substantial change and could affect things there and, while the change is well motivated, I would like to understand what the results are.

startTOT = true;
if (toverTOT < hit.second)
toverTOT = hit.second; // use the latest time in the window
Expand Down Expand Up @@ -134,6 +147,8 @@ bool HgcrocEmulator::digitize(
double charge_deposited =
(pulse(toverTOT) - gain * pedestal) * padCapacitance;

double voltaGe = (pulse(toverTOT) - gain * pedestal);

// Measure Time Over Threshold (TOT) by using the drain rate.
// 1. Use drain rate to see how long it takes for the charge to drain off
// 2. Translate this into DIGI samples
Expand All @@ -153,7 +168,7 @@ bool HgcrocEmulator::digitize(
// to measure a maximum of tot Max [ns]
int tdc_counts = int(tot * 4096 / totMax) + pedestal;

// were we already over TOA? TOT is reported in BX where TOA went over
// were we already over TOnA? TOT is reported in BX where TOA went over
// threshold...
int toa{0};
if (wasTOA) {
Expand All @@ -176,14 +191,19 @@ bool HgcrocEmulator::digitize(
toa // TOA is third measurement
);

// Record in PulseRecord
pulseRecord_.clear();
pulseRecord_.emplace_back(voltaGe, 0, tdc_counts);

// TODO: properly handle saturation and recovery, eventually.
// Now just kill everything...
while (digiToAdd.size() < nADCs_) {
digiToAdd.emplace_back(true, false, // flags to mark type of sample
0x3FF, 0x3FF, 0);
}

return true; // always readout
for (const auto &digi : digiToAdd) return true; // always readout

Comment on lines -186 to +206
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You don't need the for loop. It will exit on the first entry in the for loop anyways.

Suggested change
return true; // always readout
for (const auto &digi : digiToAdd) return true; // always readout
return true; // always readout

} else {
// determine the voltage at the sampling time
double bxvolts = pulse((iADC - iSOI_) * clockCycle_);
Expand All @@ -194,6 +214,12 @@ bool HgcrocEmulator::digitize(
if (adc < 0) adc = 0;
if (adc > 1023) adc = 1023;

// Record in PulseRecord
if (adc >= readoutThreshold) {
// pulseRecord_.clear();
pulseRecord_.emplace_back(bxvolts, adc, 0);
}

// check for TOA
int toa(0);
if (pulse(startBX) < toaThreshold && overTOA) {
Expand All @@ -214,6 +240,7 @@ bool HgcrocEmulator::digitize(
adc, // ADC[t] is the second field
toa // TOA is third measurement
);

} // TOT or ADC Mode
} // sampling baskets

Expand Down
Loading