Skip to content

Conversation

@andpet1324
Copy link
Contributor

set_toa sets TOA_VREF for a specified channel. A small charge injection is sent to the channel, and the TOA_VREF is scanned. The first threshold with a toa efficiency of 1 is selected the "correct" toa for calibration as described in José González Martínez's "Design and characterization of readout ASICs for SiPM detectors in pico-second timing measurements for the CMS HGCAL experiment" on page 99.

The function returns a parameter handle with the TOA_VREF for the specified channel.
Example of calling the function:
auto toa_handle = set_toa(tgt, roc, channel);

@andpet1324 andpet1324 mentioned this pull request Jul 10, 2025
@andpet1324
Copy link
Contributor Author

Please let me know if you think of a better name for the subclass. You have to run cmake again for the new class to be recognized

Comment on lines 46 to 59
/**
* Subclass for implementation
*
*/
class DecodeAndBufferToRead : public DecodeAndBuffer {
public:
DecodeAndBufferToRead(int nevents);
virtual ~DecodeAndBufferToRead() = default;
virtual void write_event(const pflib::packing::SingleROCEventPacket& ep) override {
DecodeAndBuffer::write_event(ep);
};
/// Read out buffer
std::vector<pflib::packing::SingleROCEventPacket> read_buffer();
};
Copy link
Member

Choose a reason for hiding this comment

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

Why do you have the extra subclass? I don't think it would be necessary...

* of every event.
*
*/
class DecodeAndBuffer : public Target::DAQRunConsumer {
Copy link
Member

Choose a reason for hiding this comment

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

I think we can use the decoding already done and instead of writing to a file we write to a buffer.

  • inherit from DecodeAndWrite
  • add constructor which sets the size and reserves space
  • override write_event to push_back into buffer after checking size
  • add get_buffer() function

Then I don't think the secondary subclass is necessary.

Copy link
Member

Choose a reason for hiding this comment

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

I guess what I'm saying is to have your old implementation in its own files and #include "pflib/DecodeAndWrite.h" since its needed.

/// Buffer for event packets
std::vector<pflib::packing::SingleROCEventPacket> ep_buffer_;
/// Capacity of the buffer
int buffer_size_;
Copy link
Member

Choose a reason for hiding this comment

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

Instead of storing our own member for buffer_size_, we can use the std::vector::capacity() function. This returns the total capacity of the vector which we control directly when we call reserve.

This was linked to issues Jul 11, 2025
@taylorjcolaizzi
Copy link
Contributor

A quick comment here, I hope not to intrude or disturb the process here!

When we are trying to calibrate for TOA_VREF, should we use pedestals or charge injection? I had discussed with my advisor Cristina that we might want use pedestals for TOA_VREF and then charge injection for TRIM_TOA. What do you guys think?

The idea is that TOA_VREF should be set right above the pedestals, so that TOA can be sensitive to triggering off of even very small incoming signals. And then TRIM_TOA uses charge injection so we can send identical signals into each channel and then calibrate the TOA reading to be the same for each of them.

@taylorjcolaizzi
Copy link
Contributor

I want to add that I really appreciate what you guys are doing and have been very excited to see this work! Thank you!

@tomeichlersmith
Copy link
Member

I'm unsure what the best process is. We definitely don't want the TOA to trigger on any pedestals, so that could be a criteria we add to this set_toa function i.e. use charge injection with a small amplitude to find a reasonable TOA threshold and then check that pedestals never fire the TOA.

I haven't read the source that @andpet1324 cites and so maybe that is being done there and this is just the first step.

The TOA threshold is probably the most complicated one to tune since it has the most complicated criteria. TOT is a bit easier since we just want it to trigger "early enough" to take over before ADC reaches saturation. TOA needs to never trigger on pedestals and be as low as possible so we can get timing information for weaker signals.

@taylorjcolaizzi
Copy link
Contributor

I agree with you. Perhaps it is best to use both the pedestals and charge injection like that! I'll go see if I can find a definitive answer in my sources. I have access to some CMS and LDMX documents, so I'll report back on what they say.

@tomeichlersmith tomeichlersmith removed a link to an issue Jul 14, 2025
@taylorjcolaizzi
Copy link
Contributor

Update on the toa analysis: There seems to be variation on how to go about the pedestal alignment. Here's some data I pulled from the CMS collaboration, so thanks to Cristina for helping me find these resources!

A group from University of Maryland that worked on "TileBoard Quality Control" for CMS said that the first step in TOA threshold alignment is to set toa_vref without injection (using pedestals) so that the global threshold is above pedestal variations. Then, use low range charge injection to fix the trim_toa. Finally, they use linear regression to fit the trim_toa values for each channel.

Additionally, I looked at some toa analysis code from the TileBoard Quality Control team, and their code does exactly what they said to do (check toa_vref with pedestals, then trim_toa with charge injections). Additionally, their code suggests to add 10 to the calculated toa_vref, so that you can account for small variations in both pedestal fluctuations and the calculated toa_vref.

However, when we look at the paper Andreas recommended earlier by González Martínez, he recommends injecting a small charge into each channel to calibrate the TOA threshold. Then, after setting the trim_toa, you do another scan of toa_vref without charge injection (pedestal). So in this case, he's using both charge injection and pedestals to set the toa_vref threshold.

So, it looks like we can do it both ways!

- update documentation with advice on how to use buffer
- return const refs to avoid copying data
- drop unnecessary members now that we are inheriting from
  DecodeAndWrite
Copy link
Member

@tomeichlersmith tomeichlersmith left a comment

Choose a reason for hiding this comment

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

Looks good :) thank you, I just did some final cleanup

@tomeichlersmith tomeichlersmith merged commit a683431 into main Jul 15, 2025
@tomeichlersmith tomeichlersmith deleted the TOALund branch July 15, 2025 17:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

DAQRunConsumer that buffers events from latest run

4 participants