REST-for-Physics  v2.3
Rare Event Searches ToolKit for Physics
TRestDetectorHitsReadoutAnalysisProcess.cxx
1//
2// Created by lobis on 03-Sep-23.
3//
4
5#include "TRestDetectorHitsReadoutAnalysisProcess.h"
6
7#include <numeric>
8
9using namespace std;
10
12 fInputHitsEvent = (TRestDetectorHitsEvent*)inputEvent;
13
14 vector<TVector3> hitPosition;
15 vector<double> hitEnergy;
16 double energyInFiducial = 0;
17
18 for (int hitIndex = 0; hitIndex < static_cast<int>(fInputHitsEvent->GetNumberOfHits()); hitIndex++) {
19 const auto position = fInputHitsEvent->GetPosition(hitIndex);
20 const auto energy = fInputHitsEvent->GetEnergy(hitIndex);
21 const auto time = fInputHitsEvent->GetTime(hitIndex);
22 const auto type = fInputHitsEvent->GetType(hitIndex);
23
24 if (energy == 0) {
25 continue;
26 } else if (energy < 0) {
27 // This should never happen. Why does it happen?
28 cerr << "TRestDetectorHitsReadoutAnalysisProcess::ProcessEvent() : "
29 << "Negative energy found in hit " << hitIndex << ". Energy (keV): " << energy << endl;
30 // exit(1);
31 continue; // We should error, but for now we just skip the hit
32 }
33 // when working with hits derived from experimental data, only relative z is available, so it cannot
34 // be used to check if a position is inside the readout. We use z=0 in this case which in most cases
35 // is inside.
36 const auto daqId =
37 fReadout->GetDaqId({position.X(), position.Y(), fIgnoreZ ? 0 : position.Z()}, false);
38 const auto channelType = fReadout->GetTypeForChannelDaqId(daqId);
39 const bool isValidHit = channelType == fChannelType;
40
41 // we need to add all hits to preserve the input event
42 fOutputHitsEvent->AddHit(position, energy, time, type);
43
44 if (!isValidHit) {
45 continue;
46 }
47
48 hitPosition.push_back(position);
49 hitEnergy.push_back(energy);
50
51 if (fFiducialDiameter > 0) {
52 TVector3 relativePosition = position - fFiducialPosition;
53 relativePosition.SetZ(0); // TODO: this should be relative to readout normal
54 const double distance = relativePosition.Mag();
55 if (distance > fFiducialDiameter / 2) {
56 continue;
57 }
58 energyInFiducial += energy;
59 }
60 }
61
62 const double readoutEnergy = accumulate(hitEnergy.begin(), hitEnergy.end(), 0.0);
63
64 if (fRemoveZeroEnergyEvents && readoutEnergy <= 0) {
65 // events not depositing any energy in the readout are removed
66 return nullptr;
67 }
68
69 TVector3 positionAverage;
70 for (size_t i = 0; i < hitPosition.size(); i++) {
71 positionAverage += hitPosition[i] * hitEnergy[i];
72 }
73 positionAverage *= 1.0 / readoutEnergy;
74
75 // standard deviation weighted with energy
76 TVector3 positionSigma;
77 for (size_t i = 0; i < hitPosition.size(); i++) {
78 TVector3 diff2 = hitPosition[i] - positionAverage;
79 diff2.SetX(diff2.X() * diff2.X());
80 diff2.SetY(diff2.Y() * diff2.Y());
81 diff2.SetZ(diff2.Z() * diff2.Z());
82 positionSigma += diff2 * hitEnergy[i];
83 }
84 positionSigma *= 1.0 / readoutEnergy;
85 positionSigma.SetX(sqrt(positionSigma.X()));
86 positionSigma.SetY(sqrt(positionSigma.Y()));
87 positionSigma.SetZ(sqrt(positionSigma.Z()));
88
89 const auto positionSigmaXY =
90 sqrt(positionSigma.X() * positionSigma.X() + positionSigma.Y() * positionSigma.Y());
91 const auto positionSigmaXYBalance =
92 (positionSigma.X() - positionSigma.Y()) / (positionSigma.X() + positionSigma.Y());
93
94 TVector3 positionSkewness;
95 for (size_t i = 0; i < hitPosition.size(); i++) {
96 TVector3 diff3 = hitPosition[i] - positionAverage;
97 diff3.SetX(diff3.X() * diff3.X() * diff3.X());
98 diff3.SetY(diff3.Y() * diff3.Y() * diff3.Y());
99 diff3.SetZ(diff3.Z() * diff3.Z() * diff3.Z());
100 positionSkewness += diff3 * hitEnergy[i];
101 }
102 positionSkewness *= 1.0 / readoutEnergy;
103 const auto positionSkewnessXY =
104 (positionSkewness.X() + positionSkewness.Y()) / (positionSigmaXY * positionSigmaXY * positionSigmaXY);
105 positionSkewness.SetX(positionSkewness.X() / (positionSigma.X() * positionSigma.X() * positionSigma.X()));
106 positionSkewness.SetY(positionSkewness.Y() / (positionSigma.Y() * positionSigma.Y() * positionSigma.Y()));
107 positionSkewness.SetZ(positionSkewness.Z() / (positionSigma.Z() * positionSigma.Z() * positionSigma.Z()));
108
109 SetObservableValue("readoutEnergy", readoutEnergy);
110 SetObservableValue("readoutNumberOfHits", hitEnergy.size());
111
112 SetObservableValue("readoutAveragePositionX", positionAverage.X());
113 SetObservableValue("readoutAveragePositionY", positionAverage.Y());
114 SetObservableValue("readoutAveragePositionZ", positionAverage.Z());
115
116 SetObservableValue("readoutSigmaPositionX", positionSigma.X());
117 SetObservableValue("readoutSigmaPositionY", positionSigma.Y());
118 SetObservableValue("readoutSigmaPositionZ", positionSigma.Z());
119 SetObservableValue("readoutSigmaPositionXY", positionSigmaXY);
120
121 SetObservableValue("readoutSigmaPositionXYBalance", positionSigmaXYBalance);
122
123 SetObservableValue("readoutSkewnessPositionX", positionSkewness.X());
124 SetObservableValue("readoutSkewnessPositionY", positionSkewness.Y());
125 SetObservableValue("readoutSkewnessPositionZ", positionSkewness.Z());
126 SetObservableValue("readoutSkewnessPositionXY", positionSkewnessXY);
127
128 SetObservableValue("readoutEnergyInFiducial", energyInFiducial);
129
130 return fOutputHitsEvent;
131}
132
134 fReadout = dynamic_cast<TRestDetectorReadout*>(fRunInfo->GetMetadataClass("TRestDetectorReadout"));
135 if (!fReadout) {
136 cerr << "TRestDetectorHitsReadoutAnalysisProcess::InitProcess() : "
137 << "TRestDetectorReadout not found" << endl;
138 exit(1);
139 }
140
141 if (fChannelType.empty()) {
142 cerr << "TRestDetectorHitsReadoutAnalysisProcess::InitProcess() : "
143 << "Channel type not defined" << endl;
144 exit(1);
145 }
146}
147
149
152
153 RESTMetadata << "Channel type : " << fChannelType << RESTendl;
154 RESTMetadata << "Fiducial position : (" << fFiducialPosition.X() << " , " << fFiducialPosition.Y()
155 << " , " << fFiducialPosition.Z() << ")" << RESTendl;
156 RESTMetadata << "Fiducial diameter : " << fFiducialDiameter << RESTendl;
157
158 EndPrintProcess();
159}
160
162 fRemoveZeroEnergyEvents = StringToBool(GetParameter("removeZeroEnergyEvents", "false"));
163 fIgnoreZ = StringToBool(GetParameter("ignoreZ", "false"));
164 fChannelType = GetParameter("channelType", fChannelType);
165 fFiducialPosition = Get3DVectorParameterWithUnits("fiducialPosition", fFiducialPosition);
166 fFiducialDiameter = GetDblParameterWithUnits("fiducialDiameter", fFiducialDiameter);
167}
168
170 SetSectionName(this->ClassName());
171 SetLibraryVersion(LIBRARY_VERSION);
172
173 fInputHitsEvent = nullptr;
174 fOutputHitsEvent = new TRestDetectorHitsEvent();
175}
void AddHit(Double_t x, Double_t y, Double_t z, Double_t en, Double_t t=0, REST_HitType type=XYZ)
Adds a new hit to this event.
void InitProcess() override
To be executed at the beginning of the run (outside event loop)
TRestEvent * ProcessEvent(TRestEvent *inputEvent) override
Process one event.
std::string fChannelType
This process will only work on hits corresponding to this channel type (using readout)
void PrintMetadata() override
Implemented it in the derived metadata class to print out specific metadata information.
bool fIgnoreZ
If true, the Z coordinate will be ignored when checking if a position is inside the readout....
void InitFromConfigFile() override
To make settings from rml file. This method must be implemented in the derived class.
void EndProcess() override
To be executed at the end of the run (outside event loop)
A metadata class to generate/store a readout description.
Int_t GetDaqId(const TVector3 &position, bool check=true)
Returns the DaqID of the channel for position. If no channel is found returns -1.
void BeginPrintProcess()
[name, cut range]
TRestRun * fRunInfo
< Pointer to TRestRun object where to find metadata.
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
endl_t RESTendl
Termination flag object for TRestStringOutput.
void SetLibraryVersion(TString version)
Set the library version of this metadata class.
void SetSectionName(std::string sName)
set the section name, clear the section content
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.