REST-for-Physics  v2.3
Rare Event Searches ToolKit for Physics
TRestGeant4EventViewer.cxx
1
14
15#include "TRestGeant4EventViewer.h"
16
17#include <TEveStraightLineSet.h>
18#include <TRestStringOutput.h>
19
20using namespace std;
21
23
24TRestGeant4EventViewer::TRestGeant4EventViewer() { Initialize(); }
25
26TRestGeant4EventViewer::~TRestGeant4EventViewer() {
27 // TRestGeant4EventViewer destructor
28}
29
30void TRestGeant4EventViewer::Initialize() {
31 fG4Event = new TRestGeant4Event();
32 fEvent = fG4Event;
33
34 fHitConnectors.clear();
35 fHitConnectors.push_back(nullptr);
36}
37
38void TRestGeant4EventViewer::DeleteCurrentEvent() {
39 TRestEveEventViewer::DeleteCurrentEvent();
40 fG4Metadata = nullptr;
41
42 fHitConnectors.clear();
43 fHitConnectors.push_back(nullptr);
44}
45
47 Color_t fColor = kWhite;
48 Style_t fLineStyle = 1;
49 Width_t fLineWidth = 4.0;
50};
51
52TrackVisualConfiguration GetTrackVisualConfiguration(const TRestGeant4Track& track) {
53 auto config = TrackVisualConfiguration();
54 // special particles
55 const auto particleName = track.GetParticleName();
56 if (particleName == "geantino") {
57 config.fColor = kRed;
58 config.fLineStyle = 9;
59 config.fLineWidth = 2;
60 return config;
61 }
62 // color based on charge
63 if (particleName.Contains('-')) {
64 config.fColor = kMagenta; // red
65 } else if (particleName.Contains('+')) {
66 config.fColor = kAzure;
67 }
68 // color based on particle (overrides charge color)
69 if (particleName == "neutron") {
70 config.fColor = kOrange; // white
71 } else if (particleName == "gamma") {
72 config.fColor = kGreen; // green
73 } else if (particleName == "e-") {
74 config.fColor = kRed; // red
75 } else if (particleName == "mu-") {
76 config.fColor = kGray; // red
77 } else if (particleName == "alpha") {
78 config.fColor = kYellow; // red
79 }
80
81 // width
82 Width_t width = TMath::Log10(track.GetInitialKineticEnergy() / 100);
83 width = (width > 10 ? 10 : width);
84 width = (width < 1 ? 1 : width);
85 config.fLineWidth = TMath::Log10(track.GetInitialKineticEnergy() / 10);
86
87 // line style
88
89 if (track.GetCreatorProcess() == "nCapture") {
90 config.fLineStyle = 2;
91 }
92
93 return config;
94}
95
96TEveStraightLineSet* GetTrackEveDrawable(const TRestGeant4Track& track) {
97 auto lineSet = new TEveStraightLineSet(
98 TString::Format("ID %d | %s | Created by %s | KE: %s", //
99 track.GetTrackID(), track.GetParticleName().Data(), track.GetCreatorProcess().Data(),
100 ToEnergyString(track.GetInitialKineticEnergy()).c_str()));
101
102 const auto& hits = track.GetHits();
103 for (unsigned int i = 0; i < hits.GetNumberOfHits() - 1; i++) {
104 lineSet->AddLine({static_cast<float>(GEOM_SCALE * hits.GetPosition(i).x()),
105 static_cast<float>(GEOM_SCALE * hits.GetPosition(i).y()),
106 static_cast<float>(GEOM_SCALE * hits.GetPosition(i).z())}, //
107 {static_cast<float>(GEOM_SCALE * hits.GetPosition(i + 1).x()),
108 static_cast<float>(GEOM_SCALE * hits.GetPosition(i + 1).y()),
109 static_cast<float>(GEOM_SCALE * hits.GetPosition(i + 1).z())});
110
111 const auto config = GetTrackVisualConfiguration(track);
112 lineSet->SetMainColor(config.fColor);
113 lineSet->SetLineColor(config.fColor);
114 lineSet->SetLineStyle(config.fLineStyle);
115 lineSet->SetLineWidth(config.fLineWidth);
116 }
117
118 return lineSet;
119}
120
122 Color_t fColor = kBlack;
123 Style_t fMarkerStyle = 1;
124 Size_t fMarkerSize = 1.0;
125};
126
127HitsVisualConfiguration GetHitsVisualConfiguration(const TString& processNameOrType) {
128 auto config = HitsVisualConfiguration();
129 // based on particle type
130 if (processNameOrType.EqualTo("Electromagnetic")) {
131 config.fColor = kRed;
132 } else if (processNameOrType.EqualTo("Init")) {
133 // custom process (not Geant4)
134 config.fColor = kWhite;
135 }
136
137 // based on particle name
138 if (processNameOrType.EqualTo("Transportation")) {
139 config.fColor = kWhite;
140 } else if (processNameOrType.EqualTo("Init")) {
141 // custom process (not Geant4)
142 config.fColor = kWhite;
143 } else if (processNameOrType.EqualTo("hadElastic")) {
144 config.fColor = kOrange;
145 } else if (processNameOrType.EqualTo("neutronInelastic")) {
146 config.fColor = kGreen;
147 config.fMarkerStyle = 4;
148 } else if (processNameOrType.EqualTo("nCapture")) {
149 config.fColor = kBlue;
150 config.fMarkerStyle = 2;
151 config.fMarkerSize = 4.0;
152 }
153 return config;
154}
155
156void TRestGeant4EventViewer::AddEvent(TRestEvent* event) {
157 DeleteCurrentEvent();
158
159 fG4Event = (TRestGeant4Event*)event;
160 fG4Metadata = fG4Event->GetGeant4Metadata();
161 if (fG4Metadata == nullptr) {
162 cerr << "TRestGeant4EventViewer::Initialize. No TRestGeant4Metadata found in TRestGeant4Event"
163 << endl;
164 exit(1);
165 }
166
167 size_t trackCounter = 0;
168 size_t hitsCounter = 0;
169
170 map<Int_t, TEveStraightLineSet*> linesSet;
171 map<TString, TEvePointSet*> hitsPoints;
172 map<TString, TEveElementList*> hitsType;
173
174 auto trackList = new TEveElementList("Tracks");
175 gEve->AddElement(trackList);
176 auto hitsList = new TEveElementList("Hits");
177 gEve->AddElement(hitsList);
178
179 const auto& physicsInfo = fG4Metadata->GetGeant4PhysicsInfo();
180
181 for (const auto& track : fG4Event->GetTracks()) {
182 if (track.GetInitialKineticEnergy() < 1.0 || track.GetLength() < 0.1) {
183 continue;
184 }
185
186 auto line = GetTrackEveDrawable(track);
187 linesSet[track.GetTrackID()] = line;
188 TEveElement* parentLine = trackList;
189 if (linesSet.count(track.GetParentID())) {
190 parentLine = linesSet.at(track.GetParentID());
191 }
192 gEve->AddElement(line, parentLine);
193 trackCounter++;
194
195 const auto& hits = track.GetHits();
196 for (unsigned int i = 0; i < hits.GetNumberOfHits(); i++) {
197 const auto& processName = physicsInfo.GetProcessName(hits.GetProcess(i));
198 const auto& processType = physicsInfo.GetProcessType(processName);
199 const auto& position = hits.GetPosition(i);
200
201 if (hitsType.count(processType) == 0) {
202 hitsType[processType] = new TEveElementList(processType);
203 gEve->AddElement(hitsType[processType], hitsList);
204 }
205 if (hitsPoints.count(processName) == 0) {
206 hitsPoints[processName] = new TEvePointSet(processName);
207 auto hitPoints = hitsPoints.at(processName);
208 auto hitsVisualConfig = GetHitsVisualConfiguration(processName);
209 hitPoints->SetMarkerColor(hitsVisualConfig.fColor);
210 hitPoints->SetMarkerStyle(hitsVisualConfig.fMarkerStyle);
211 hitPoints->SetMarkerSize(hitsVisualConfig.fMarkerSize);
212
213 gEve->AddElement(hitPoints, hitsType[processType]);
214 }
215 hitsPoints.at(processName)
216 ->SetNextPoint(GEOM_SCALE * position.X(), GEOM_SCALE * position.Y(),
217 GEOM_SCALE * position.Z());
218 hitsCounter++;
219 }
220 }
221
222 // Add event text
223 const auto& firstTrack = fG4Event->GetTracks().front();
224 TVector3 position = {firstTrack.GetInitialPosition().X(), firstTrack.GetInitialPosition().Y(),
225 firstTrack.GetInitialPosition().Z()};
226 AddText(
227 TString::Format(
228 "Event ID: %d%s | Primary origin: (%4.2lf, %4.2lf, %4.2lf) mm", fG4Event->GetID(),
229 (fG4Event->GetSubID() > 0 ? TString::Format(" (SubID: %d)", fG4Event->GetSubID()) : "").Data(),
230 position.X(), position.Y(), position.Z()),
231 position);
232
233 Update();
234}
235
236void TRestGeant4EventViewer::AddText(TString text, TVector3 at) {
237 TEveText* evText = new TEveText(text);
238 evText->SetName("Event title");
239 evText->SetFontSize(12);
240 evText->RefMainTrans().SetPos((at.X() + 15) * GEOM_SCALE, (at.Y() + 15) * GEOM_SCALE,
241 (at.Z() + 15) * GEOM_SCALE);
242
243 gEve->AddElement(evText);
244}
245
246void TRestGeant4EventViewer::AddMarker(Int_t trkID, TVector3 at, TString name) {
247 TEvePointSet* marker = new TEvePointSet(1);
248 marker->SetName(name);
249 marker->SetMarkerColor(kMagenta);
250 marker->SetMarkerStyle(3);
251 marker->SetPoint(0, at.X() * GEOM_SCALE, at.Y() * GEOM_SCALE, at.Z() * GEOM_SCALE);
252 marker->SetMarkerSize(0.4);
253 fHitConnectors[trkID]->AddElement(marker);
254}
255
256void TRestGeant4EventViewer::NextTrackVertex(Int_t trkID, TVector3 to) {
257 fHitConnectors[trkID]->SetNextPoint(to.X() * GEOM_SCALE, to.Y() * GEOM_SCALE, to.Z() * GEOM_SCALE);
258}
259
260void TRestGeant4EventViewer::AddTrack(Int_t trkID, Int_t parentID, TVector3 from, TString name) {
261 TEveLine* evLine = new TEveLine();
262 evLine->SetName(name);
263 fHitConnectors.push_back(evLine);
264
265 fHitConnectors[trkID]->SetMainColor(kWhite);
266 fHitConnectors[trkID]->SetLineWidth(4);
267
268 if (name.Contains("gamma")) fHitConnectors[trkID]->SetMainColor(kGreen);
269 if (name.Contains("e-")) fHitConnectors[trkID]->SetMainColor(kRed);
270 if (name.Contains("mu-")) fHitConnectors[trkID]->SetMainColor(kGray);
271 if (name.Contains("alpha")) fHitConnectors[trkID]->SetMainColor(kYellow);
272 if (name.Contains("neutron")) fHitConnectors[trkID]->SetMainColor(kBlue);
273
274 fHitConnectors[trkID]->SetNextPoint(from.X() * GEOM_SCALE, from.Y() * GEOM_SCALE, from.Z() * GEOM_SCALE);
275
276 if (parentID >= 0 && fHitConnectors.size() > (unsigned int)parentID)
277 fHitConnectors[parentID]->AddElement(fHitConnectors[trkID]);
278 else {
279 RESTWarning << "Parent ID: " << parentID << " of track " << trkID << " was not found!" << RESTendl;
280 RESTWarning << "This might be solved by enabling TRestGeant4Metadata::fRegisterEmptyTracks"
281 << RESTendl;
282 }
283}
284
285void TRestGeant4EventViewer::AddParentTrack(Int_t trkID, TVector3 from, TString name) {
286 TEveLine* evLine = new TEveLine();
287 evLine->SetName(name);
288 fHitConnectors.push_back(evLine);
289
290 fHitConnectors[trkID]->SetMainColor(kWhite);
291 fHitConnectors[trkID]->SetLineWidth(4);
292 fHitConnectors[trkID]->SetNextPoint(from.X() * GEOM_SCALE, from.Y() * GEOM_SCALE, from.Z() * GEOM_SCALE);
293
294 gEve->AddElement(fHitConnectors[trkID]);
295}
A base class for any REST event.
Definition: TRestEvent.h:38
An event class to store geant4 generated event information.
const TRestGeant4PhysicsInfo & GetGeant4PhysicsInfo() const
Returns an immutable reference to the physics info.