2#include "TRestRawPeaksFinderProcess.h"
20 if (fReadoutMetadata ==
nullptr) {
21 fReadoutMetadata = fInputEvent->GetReadoutMetadata();
24 if (fReadoutMetadata ==
nullptr && !fChannelTypes.empty()) {
25 cerr <<
"TRestRawPeaksFinderProcess::ProcessEvent: readout metadata is null, cannot filter "
26 "the process by signal type"
31 vector<tuple<UShort_t, UShort_t, double, double>>
35 double BaseLineMean = 0.0;
36 double BaseLineSigmaMean = 0.0;
37 unsigned int countTPC = 0;
39 for (
int signalIndex = 0; signalIndex < fInputEvent->GetNumberOfSignals(); signalIndex++) {
40 const auto signal = fInputEvent->GetSignal(signalIndex);
43 const string channelType = fReadoutMetadata->GetTypeForChannelDaqId(signalId);
44 const string channelName = fReadoutMetadata->GetNameForChannelDaqId(signalId);
47 if (fChannelTypes.find(channelType) == fChannelTypes.end()) {
52 if (channelType ==
"tpc") {
55 BaseLineMean += signal->GetBaseLine();
56 BaseLineSigmaMean += signal->GetBaseLineSigma();
63 BaseLineMean /= countTPC;
64 BaseLineSigmaMean /= countTPC;
67 for (
int signalIndex = 0; signalIndex < fInputEvent->GetNumberOfSignals(); signalIndex++) {
68 const auto signal = fInputEvent->GetSignal(signalIndex);
71 const string channelType = fReadoutMetadata->GetTypeForChannelDaqId(signalId);
72 const string channelName = fReadoutMetadata->GetNameForChannelDaqId(signalId);
75 if (fChannelTypes.find(channelType) == fChannelTypes.end()) {
80 if (channelType ==
"tpc") {
82 double signalBaseLine = signal->GetBaseLine();
86 cerr <<
"TRestRawPeaksFinderProcess::ProcessEvent: TPC count is 0 in TPC loop, this should "
93 const auto peaks = signal->GetPeaks(threshold,
fDistance, signalBaseLine);
95 for (
const auto& [time, amplitude, amplitudeBaseLineCorrected] : peaks) {
96 eventPeaks.emplace_back(signalId, time, amplitude, amplitudeBaseLineCorrected);
98 }
else if (channelType ==
"veto") {
101 signal->CalculateBaseLine(0, 511,
"OUTLIERS");
102 double signalBaseLine = signal->GetBaseLine();
107 for (
const auto& [time, amplitude, amplitudeBaseLineCorrected] : peaks) {
108 eventPeaks.emplace_back(signalId, time, amplitude, amplitudeBaseLineCorrected);
114 sort(eventPeaks.begin(), eventPeaks.end(),
115 [](
const tuple<UShort_t, UShort_t, double, double>& a,
116 const tuple<UShort_t, UShort_t, double, double>& b) {
117 return tie(get<1>(a), get<0>(a)) < tie(get<1>(b), get<0>(b));
120 vector<UShort_t> peaksChannelId;
121 vector<UShort_t> peaksTime;
122 vector<double> peaksAmplitude;
123 vector<double> peaksAmplitudeBaseLineCorrected;
125 double peaksEnergy = 0.0;
126 double peaksEnergyBaseLineCorrected = 0.0;
127 UShort_t peaksCount = 0;
128 UShort_t peaksCountUnique = 0;
130 set<UShort_t> uniquePeaks;
131 for (
const auto& [channelId, time, amplitude, amplitudeBaseLineCorrected] : eventPeaks) {
132 peaksChannelId.push_back(channelId);
133 peaksTime.push_back(time);
134 peaksAmplitude.push_back(amplitude);
135 peaksAmplitudeBaseLineCorrected.push_back(amplitudeBaseLineCorrected);
137 peaksEnergy += amplitude;
138 peaksEnergyBaseLineCorrected += amplitudeBaseLineCorrected;
141 if (uniquePeaks.find(channelId) == uniquePeaks.end()) {
142 uniquePeaks.insert(channelId);
150 SetObservableValue(
"peaksAmplitudeBaseLineCorrectedADC", peaksAmplitudeBaseLineCorrected);
153 SetObservableValue(
"peaksAmplitudeBaseLineCorrectedADCSum", peaksEnergyBaseLineCorrected);
157 vector<UShort_t> windowPeakIndex(eventPeaks.size(), std::numeric_limits<UShort_t>::max());
158 vector<UShort_t> windowPeakCenter(eventPeaks.size(), 0);
159 vector<UShort_t> windowPeakMultiplicity(eventPeaks.size(), 0);
161 UShort_t window_index = 0;
162 for (
size_t peakIndex = 0; peakIndex < eventPeaks.size(); peakIndex++) {
163 const auto& [channelId, time, amplitude, amplitudeBaseLineCorrected] = eventPeaks[peakIndex];
164 const auto windowTimeStart = time -
fWindow / 2;
165 const auto windowTimeEnd = time +
fWindow / 2;
168 if (windowPeakIndex[peakIndex] != std::numeric_limits<UShort_t>::max()) {
172 UShort_t window_center_time = time;
174 set<UShort_t> windowPeaksIndex;
177 windowPeaksIndex.insert(peakIndex);
180 for (
size_t otherPeakIndex = peakIndex + 1; otherPeakIndex < eventPeaks.size(); otherPeakIndex++) {
181 const auto& [otherChannelId, otherTime, otherAmplitude, otherAmplitudeBaseLineCorrected] =
182 eventPeaks[otherPeakIndex];
184 if (otherTime < windowTimeStart) {
188 if (otherTime > windowTimeEnd) {
192 windowPeaksIndex.insert(otherPeakIndex);
195 for (
const auto& index : windowPeaksIndex) {
196 windowPeakIndex[index] = window_index;
197 windowPeakCenter[index] = window_center_time;
198 windowPeakMultiplicity[index] = windowPeaksIndex.size();
208 vector<UShort_t> windowCenter;
209 vector<UShort_t> windowMultiplicity;
211 set<UShort_t> windowPeaksIndexInserted;
212 for (
size_t peakIndex = 0; peakIndex < eventPeaks.size(); peakIndex++) {
213 const auto& window_peak_index = windowPeakIndex[peakIndex];
214 if (windowPeaksIndexInserted.find(window_peak_index) != windowPeaksIndexInserted.end()) {
218 windowPeaksIndexInserted.insert(window_peak_index);
220 windowCenter.push_back(windowPeakCenter[peakIndex]);
221 windowMultiplicity.push_back(windowPeakMultiplicity[peakIndex]);
227 if (fTimeBinToTimeFactorMultiplier != 0.0) {
228 vector<Double_t> windowCenterTime(windowCenter.size(), 0.0);
229 vector<Double_t> windowPeakCenterTime(windowPeakCenter.size(), 0.0);
230 vector<Double_t> peaksTimePhysical(peaksTime.size(), 0.0);
233 auto timeBinToTime = [
this](UShort_t timeBin) {
234 if (!fTimeConversionElectronics) {
235 return fTimeBinToTimeFactorMultiplier * timeBin - fTimeBinToTimeFactorOffset;
238 double zero = -1 + (512 * fTimeBinToTimeFactorMultiplier - fTimeBinToTimeFactorOffset -
239 fTimeBinToTimeFactorOffsetTCM) /
240 fTimeBinToTimeFactorMultiplier;
241 return fTimeBinToTimeFactorMultiplier * (timeBin - zero);
245 for (
size_t i = 0; i < windowCenter.size(); i++) {
246 windowCenterTime[i] = timeBinToTime(windowCenter[i]);
249 for (
size_t i = 0; i < windowPeakCenter.size(); i++) {
250 windowPeakCenterTime[i] = timeBinToTime(windowPeakCenter[i]);
253 for (
size_t i = 0; i < peaksTime.size(); i++) {
254 peaksTimePhysical[i] = timeBinToTime(peaksTime[i]);
262 if (fADCtoEnergyFactor != 0.0 || !fChannelIDToADCtoEnergyFactor.empty()) {
263 vector<Double_t> peaksEnergyPhysical(peaksAmplitudeBaseLineCorrected.size(), 0.0);
264 Double_t peaksEnergySum = 0.0;
266 if (fADCtoEnergyFactor != 0.0) {
268 for (
size_t i = 0; i < peaksAmplitude.size(); i++) {
269 peaksEnergyPhysical[i] = peaksAmplitudeBaseLineCorrected[i] * fADCtoEnergyFactor;
270 peaksEnergySum += peaksEnergyPhysical[i];
274 for (
size_t i = 0; i < peaksAmplitude.size(); i++) {
275 const auto channelId = peaksChannelId[i];
277 if (fChannelIDToADCtoEnergyFactor.find(channelId) == fChannelIDToADCtoEnergyFactor.end()) {
278 cerr <<
"TRestRawPeaksFinderProcess::ProcessEvent: channel id " << channelId
279 <<
" not found in the map of ADC to energy factors" << endl;
282 const auto factor = fChannelIDToADCtoEnergyFactor[channelId];
284 peaksEnergyPhysical[i] = peaksAmplitudeBaseLineCorrected[i] * factor;
285 peaksEnergySum += peaksEnergyPhysical[i];
295 set<UShort_t> peakSignalIds;
296 for (
const auto& [channelId, time, amplitude, amplitudeBaseLineCorrected] : eventPeaks) {
297 peakSignalIds.insert(channelId);
300 vector<UShort_t> signalsToRemove;
301 for (
int signalIndex = 0; signalIndex < fInputEvent->GetNumberOfSignals(); signalIndex++) {
302 const auto signal = fInputEvent->GetSignal(signalIndex);
304 const string signalType = fReadoutMetadata->GetTypeForChannelDaqId(signalId);
306 if (signalType ==
"veto" && peakSignalIds.find(signalId) == peakSignalIds.end()) {
307 signalsToRemove.push_back(signalId);
312 for (
const auto& signalId : signalsToRemove) {
313 fInputEvent->RemoveSignalWithId(signalId);
319 vector<UShort_t> signalsToRemove;
320 for (
int signalIndex = 0; signalIndex < fInputEvent->GetNumberOfSignals(); signalIndex++) {
321 const auto signal = fInputEvent->GetSignal(signalIndex);
323 const string signalType = fReadoutMetadata->GetTypeForChannelDaqId(signalId);
325 if (signalType ==
"veto") {
326 signalsToRemove.push_back(signalId);
331 for (
const auto& signalId : signalsToRemove) {
332 fInputEvent->RemoveSignalWithId(signalId);
339std::map<UShort_t, double> parseStringToMap(
const std::string& input) {
340 std::map<UShort_t, double> my_map;
341 std::string cleaned_input;
344 for (
char c : input) {
345 if (!std::isspace(c) && c !=
'{' && c !=
'}') {
351 std::stringstream ss(cleaned_input);
353 while (std::getline(ss, pair,
',')) {
355 size_t colon_pos = pair.find(
':');
356 if (colon_pos != std::string::npos) {
358 int key = std::stoi(pair.substr(0, colon_pos));
359 double value = std::stod(pair.substr(colon_pos + 1));
368 const auto filterType =
GetParameter(
"channelType",
"");
369 if (!filterType.empty()) {
370 fChannelTypes.insert(filterType);
373 if (fChannelTypes.empty()) {
385 fTimeBinToTimeFactorMultiplier = GetDblParameterWithUnits(
"sampling", fTimeBinToTimeFactorMultiplier);
386 fTimeBinToTimeFactorOffset = GetDblParameterWithUnits(
"trigDelay", fTimeBinToTimeFactorOffset);
387 fTimeBinToTimeFactorOffsetTCM = GetDblParameterWithUnits(
"trigDelayTCM", fTimeBinToTimeFactorOffsetTCM);
388 fTimeConversionElectronics =
389 StringToBool(
GetParameter(
"trigDelayElectronics", fTimeConversionElectronics));
391 fADCtoEnergyFactor = GetDblParameterWithUnits(
"adcToEnergyFactor", fADCtoEnergyFactor);
392 const string fChannelIDToADCtoEnergyFactorAsString =
GetParameter(
"channelIDToADCtoEnergyFactor",
"");
393 if (!fChannelIDToADCtoEnergyFactorAsString.empty()) {
396 fChannelIDToADCtoEnergyFactor = parseStringToMap(fChannelIDToADCtoEnergyFactorAsString);
399 if (fADCtoEnergyFactor != 0 && !fChannelIDToADCtoEnergyFactor.empty()) {
400 cerr <<
"TRestRawPeaksFinderProcess::InitFromConfigFile: both adcToEnergyFactor and "
401 "channelIDToADCtoEnergyFactor are defined. Please, remove one of them."
407 cerr <<
"TRestRawPeaksFinderProcess::InitProcess: baseline range is not sorted or < 0" << endl;
412 cerr <<
"TRestRawPeaksFinderProcess::InitProcess: threshold over baseline is < 0" << endl;
417 cerr <<
"TRestRawPeaksFinderProcess::InitProcess: sigma over baseline is < 0" << endl;
422 cerr <<
"TRestRawPeaksFinderProcess::InitProcess: distance is < 0" << endl;
427 cerr <<
"TRestRawPeaksFinderProcess::InitProcess: window is < 0" << endl;
432 cerr <<
"TRestRawPeaksFinderProcess::InitProcess: removing veto signals only makes sense when the "
433 "process is applied to veto signals. Remove \"removePeaklessVetoes\" parameter"
442 RESTMetadata <<
"Applying process to channel types: ";
443 for (
const auto& type : fChannelTypes) {
444 RESTMetadata << type <<
" ";
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.
virtual void InitializeReferences(TRestRun *run)
Initialize dynamical references when loading the event from a root file.
Double_t fSigmaOverBaseline
choose times the sigma of the baseline must be overcome to consider a peak
UShort_t fDistance
distance between two peaks to consider them as different (ADC units)
void InitFromConfigFile() override
To make settings from rml file. This method must be implemented in the derived class.
Bool_t fRemovePeaklessVetoes
option to remove peak-less veto signals after finding the peaks
Double_t fThresholdOverBaseline
threshold over baseline to consider a peak
UShort_t fWindow
window size to calculate the peak amplitude (time bins)
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.
Bool_t fRemoveAllVetoes
option to remove all veto signals after finding the peaks
An event container for time rawdata signals with fixed length.
Int_t GetSignalID() const
Returns the value of signal ID.