Skip to content

Conversation

@S81D
Copy link
Collaborator

@S81D S81D commented Oct 7, 2025

Describe your changes

Builds upon PR #359. PrintADCTraces is a tool that makes it easier to fetch the ADC traces from ProcessedData for analyzers.

Historically, if someone wanted to investigate the raw waveforms / pulses there wasn't a straightforward way to obtain them (they would need to re-run the event builder to store the raw waveforms to the ProcessedData). Following PR #359, the ADCPulse class is expanded to include the "stitched out" trace. That trace is saved in the ProcessedData and is easily accessible via the store. Therefore, after event building, the ProcessedData can be fully utilized by all users for analysis or calibration studies. This tool will read the trace information and save it to an output root file where the pulses can be analyzed. This can be used for:

  • Pulse template fitting for the waveform simulator
  • Assessing the stability of the PMTs (noise and pulse shape) over time
  • Serve as a template for other tools to fetch the ADC traces and do some analysis.

See the README for the structure of the output root file and for details on configuration.

Checklist before submitting your PR

  • This PR implements a single change (one new/modified Tool, or a set of changes to implement one new/modified feature)
  • This PR alters the minimum number of files to affect this change
  • If this PR includes a new Tool, a README and minimal demonstration ToolChain is provided
  • If a new Tool/ToolChain requires model or configuration files, their paths are not hard-coded, and means of generating those files is described in the readme, with examples provided on /pnfs/annie/persistent
  • For every new usage, there is a reason the data must be on the heap
  • For every new there is a delete, unless I explicitly know why (e.g. ROOT or a BoostStore takes ownership)

Additional Material

Runtime and filesizes per waveform generated are detailed in the README.

Here are some examples of the output root file. The traces are stored relative to their starting time (so they start at 0ns) and are baseline-subtracted (y = 0 = calculated baseline). This makes it easy to compare pulses.

Screenshot 2025-10-07 at 11 16 05 AM Screenshot 2025-10-07 at 11 17 02 AM Screenshot 2025-10-07 at 11 17 13 AM Screenshot 2025-10-07 at 11 17 18 AM

@S81D
Copy link
Collaborator Author

S81D commented Oct 7, 2025

Note that the compilation will FAIL since this relies on PR #359 to be merged first.

@S81D S81D added the on hold label Oct 7, 2025
@S81D
Copy link
Collaborator Author

S81D commented Oct 7, 2025

An example of the output root file can be found here:

/pnfs/annie/persistent/users/doran/datasets/R4695_p0_p9_ADCTraces.root (some laser data)

Copy link
Collaborator

@jminock jminock 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! Will remove "on hold" tag upon successful compilation

if (xpts.empty() || ypts.empty()) continue;

// create and write to TGraph
TGraph gr(xpts.size());
Copy link
Collaborator

Choose a reason for hiding this comment

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

you can do

TGraph gr(xpts.size(), xpts.data(), ypts.data());

to skip the need to loop and call SetPoint for each

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Sweet, added it to the code 👍🏼

for (size_t i = 0; i < std::min(xpts.size(), ypts.size()); ++i) {
gr.SetPoint(i, xpts[i], ypts[i]);
}
gr.SetTitle(grTitle.str().c_str());
Copy link
Collaborator

Choose a reason for hiding this comment

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

i'm not sure how transferrable this is to how these files are expected to be used, but from a quick test if one does

TFile f("testg.root","RECREATE");
TGraph g;
g.SetTitle("testgraph")
g.Write();
f.Close();

then

TFile f("testg.root","READ");
TGraph* g=(TGraph*)f.Get("testgraph");

then g will be nullptr because the TGraph name isn't set. It's always seemed odd to me that it's not part of the constructor, but i tend to always set both name and title for TGraphs.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Also added. The names of the graphs are currently just "Graph;N" within the root file and aren't used in my analysis. Going forward I will be sure to set the name of the TGraph, as well as the title.

if (fTraceSummaryTree) { // write summary to root file
fOutFile->cd();
fTraceSummaryTree->Write();
delete fTraceSummaryTree; // clean up clean up everybody do your share
Copy link
Collaborator

Choose a reason for hiding this comment

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

i believe fTraceSummaryTree will be owned by fOutFile so this would constitute a double delete.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Good catch. I was paranoid about new / delete so added this to be safe. It has been removed.

- condensed some code
- added a name to the TGraph
- removed the double delete
@S81D
Copy link
Collaborator Author

S81D commented Oct 22, 2025

All recommendations implemented! Also now compiled successfully since ADCPulses has been updated.

@marc1uk
Copy link
Collaborator

marc1uk commented Oct 30, 2025

Many thanks 👍

@marc1uk marc1uk merged commit 49a9530 into ANNIEsoft:Application Oct 30, 2025
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants