REST-for-Physics  v2.3
Rare Event Searches ToolKit for Physics
TRestRawPeaksFinderProcess.cxx
1
2#include "TRestRawPeaksFinderProcess.h"
3
4#include <utility>
5
7
8using namespace std;
9
11
13 fInputEvent = dynamic_cast<TRestRawSignalEvent*>(inputEvent);
14
15 const auto run = GetRunInfo();
16 if (run != nullptr) {
17 fInputEvent->InitializeReferences(run);
18 }
19
20 auto event = fInputEvent->GetSignalEventForTypes(fChannelTypes, fReadoutMetadata);
21
22 if (fReadoutMetadata == nullptr) {
23 fReadoutMetadata = fInputEvent->GetReadoutMetadata();
24 }
25
26 if (fReadoutMetadata == nullptr && !fChannelTypes.empty()) {
27 cerr << "TRestRawPeaksFinderProcess::ProcessEvent: readout metadata is null, cannot filter "
28 "the process by signal type"
29 << endl;
30 exit(1);
31 }
32
33 vector<tuple<UShort_t, UShort_t, double>> eventPeaks;
34
35 for (int signalIndex = 0; signalIndex < event.GetNumberOfSignals(); signalIndex++) {
36 const auto signal = event.GetSignal(signalIndex);
37 const UShort_t signalId = signal->GetSignalID();
38
39 const string channelType = fReadoutMetadata->GetTypeForChannelDaqId(signalId);
40 const string channelName = fReadoutMetadata->GetNameForChannelDaqId(signalId);
41
42 // check if channel type is in the list of selected channel types
43 if (fChannelTypes.find(channelType) == fChannelTypes.end()) {
44 continue;
45 }
46
47 signal->CalculateBaseLine(0, 5);
48 const auto peaks = signal->GetPeaks(signal->GetBaseLine() + 1.0, fDistance);
49
50 for (const auto& [time, amplitude] : peaks) {
51 eventPeaks.emplace_back(signalId, time, amplitude);
52 }
53 /*
54 cout << "Signal ID: " << channelId << " Name: " << channelName << endl;
55 for (const auto& [time, amplitude] : peaks) {
56 cout << " - Peak at " << time << " with amplitude " << amplitude << endl;
57 }
58 */
59 }
60
61 // sort eventPeaks by time, then signal id
62 sort(eventPeaks.begin(), eventPeaks.end(),
63 [](const tuple<UShort_t, UShort_t, double>& a, const tuple<UShort_t, UShort_t, double>& b) {
64 return tie(get<1>(a), get<0>(a)) < tie(get<1>(b), get<0>(b));
65 });
66
67 // SetObservableValue("peaks", eventPeaks); // problems with dictionaries
68 vector<UShort_t> peaksChannelId;
69 vector<UShort_t> peaksTime;
70 vector<double> peaksAmplitude;
71
72 for (const auto& [channelId, time, amplitude] : eventPeaks) {
73 peaksChannelId.push_back(channelId);
74 peaksTime.push_back(time);
75 peaksAmplitude.push_back(amplitude);
76 }
77
78 SetObservableValue("peaksChannelId", peaksChannelId);
79 SetObservableValue("peaksTime", peaksTime);
80 SetObservableValue("peaksAmplitude", peaksAmplitude);
81
82 vector<UShort_t> windowIndex(eventPeaks.size(), 0); // Initialize with zeros
83 vector<UShort_t> windowCenter; // for each different window, the center of the window
84
85 for (size_t peakIndex = 0; peakIndex < eventPeaks.size(); peakIndex++) {
86 const auto& [channelId, time, amplitude] = eventPeaks[peakIndex];
87 const auto windowTime = time - fWindow / 2;
88 const auto windowEnd = time + fWindow / 2;
89
90 // check if the peak is already in a window
91 if (windowIndex[peakIndex] != 0) {
92 continue;
93 }
94
95 // create a new window
96 windowCenter.push_back(time);
97
98 // add the peak to the window
99 windowIndex[peakIndex] = windowCenter.size();
100
101 // add the peaks that are in the window
102 for (size_t otherPeakIndex = peakIndex + 1; otherPeakIndex < eventPeaks.size(); otherPeakIndex++) {
103 const auto& [otherChannelId, otherTime, otherAmplitude] = eventPeaks[otherPeakIndex];
104
105 if (otherTime < windowTime) {
106 continue;
107 }
108
109 if (otherTime > windowEnd) {
110 break;
111 }
112
113 windowIndex[otherPeakIndex] = windowCenter.size();
114 }
115 }
116
117 // subtract 1 from windowIndex so it starts on 0
118 for (auto& index : windowIndex) {
119 index--;
120 }
121
122 // validation
123 // check only values from 0 ... windowCenter.size() -1 are in windowIndex
124 // ALL values in this range should appear at least once
125 for (size_t index = 0; index < windowCenter.size(); index++) {
126 bool found = false;
127 for (const auto& window : windowIndex) {
128 if (window == index) {
129 found = true;
130 break;
131 }
132 }
133 if (!found) {
134 cerr << "TRestRawPeaksFinderProcess::ProcessEvent: window index " << index << " not found"
135 << endl;
136 exit(1);
137 }
138 }
139
140 SetObservableValue("windowIndex", windowIndex);
141 SetObservableValue("windowCenter", windowCenter);
142
143 return inputEvent;
144}
145
147 const auto filterType = GetParameter("channelType", "");
148 if (!filterType.empty()) {
149 fChannelTypes.insert(filterType);
150 }
151
152 if (fChannelTypes.empty()) {
153 // if no channel type is specified, use all channel types
154 }
155
157 fBaselineRange = Get2DVectorParameterWithUnits("baselineRange", fBaselineRange);
160
161 if (fBaselineRange.X() > fBaselineRange.Y() || fBaselineRange.X() < 0 || fBaselineRange.Y() < 0) {
162 cerr << "TRestRawPeaksFinderProcess::InitProcess: baseline range is not sorted or < 0" << endl;
163 exit(1);
164 }
165
166 if (fThresholdOverBaseline < 0) {
167 cerr << "TRestRawPeaksFinderProcess::InitProcess: threshold over baseline is < 0" << endl;
168 exit(1);
169 }
170
171 if (fDistance <= 0) {
172 cerr << "TRestRawPeaksFinderProcess::InitProcess: distance is < 0" << endl;
173 exit(1);
174 }
175
176 if (fWindow <= 0) {
177 cerr << "TRestRawPeaksFinderProcess::InitProcess: window is < 0" << endl;
178 exit(1);
179 }
180}
181
184
185 RESTMetadata << "Applying process to channel types: ";
186 for (const auto& type : fChannelTypes) {
187 RESTMetadata << type << " ";
188 }
189 RESTMetadata << RESTendl;
190
191 RESTMetadata << "Threshold over baseline: " << fThresholdOverBaseline << RESTendl;
192 RESTMetadata << "Baseline range: " << fBaselineRange.X() << " - " << fBaselineRange.Y() << RESTendl;
193
194 RESTMetadata << "Distance: " << fDistance << RESTendl;
195 RESTMetadata << "Window: " << fWindow << RESTendl;
196
197 EndPrintProcess();
198}
TRestRun * GetRunInfo() const
Return the pointer of the hosting TRestRun object.
void BeginPrintProcess()
[name, cut range]
void SetObservableValue(const std::string &name, const T &value)
Set observable value for AnalysisTree.
A base class for any REST event.
Definition: TRestEvent.h:38
virtual void InitializeReferences(TRestRun *run)
Initialize dynamical references when loading the event from a root file.
Definition: TRestEvent.cxx:175
endl_t RESTendl
Termination flag object for TRestStringOutput.
std::string GetParameter(std::string parName, TiXmlElement *e, TString defaultValue=PARAMETER_NOT_FOUND_STR)
Returns the value for the parameter named parName in the given section.
UShort_t fDistance
distance between two peaks to consider them as different
void InitFromConfigFile() override
To make settings from rml file. This method must be implemented in the derived class.
Double_t fThresholdOverBaseline
threshold over baseline to consider a peak
UShort_t fWindow
window size to calculate the peak amplitude
void InitProcess() override
To be executed at the beginning of the run (outside event loop)
TRestEvent * ProcessEvent(TRestEvent *inputEvent) override
Process one event.
TVector2 fBaselineRange
range of samples to calculate baseline for peak finding
void PrintMetadata() override
Implemented it in the derived metadata class to print out specific metadata information.
An event container for time rawdata signals with fixed length.
Double_t StringToDouble(std::string in)
Gets a double from a string.