KaliVeda
Toolkit for HIC analysis
Loading...
Searching...
No Matches
KVGroupReconstructor.cpp
1#include "KVGroupReconstructor.h"
2#include "KVMultiDetArray.h"
3#include "KVTarget.h"
4
5#include <TPluginManager.h>
6using std::cout;
7using std::endl;
8
10
13
14
17
19 : KVBase("KVGroupReconstructor", "Reconstruction of particles in detector groups"),
20 fGroup(nullptr), fGrpEvent(nullptr)
21{
22 // Default constructor
23
24}
25
26
27
30
37
38
39
44
46{
47 // Set the group to be reconstructed
48 //
49 // Set condition for seeding reconstructed particles
50 fGroup = g;
52}
53
54
55
58
60{
61 // Instantiate event fragment object
62
64}
65
66
67
72
74{
75 // Create a new object of a class derived from KVGroupReconstructor defined by a plugin
76 //
77 // If plugin="" this is just a new KVGroupReconstructor instance
78
79 if (plugin == "") return new KVGroupReconstructor;
80 TPluginHandler* ph = LoadPlugin("KVGroupReconstructor", plugin);
81 if (ph) {
82 return (KVGroupReconstructor*)ph->ExecPlugin(0);
83 }
84 return nullptr;
85}
86
87
88
96
98{
99 // Perform full reconstruction of particles detected in group.
100 //
101 // This will call in order Reconstruct(), Identify(), Calibrate() and AddCoherencyParticles()
102 //
103 // - identification can be inhibited (for all groups) by calling KVGroupReconstructor::SetDoIdentification(false);
104 // - calibration can be inhibited (for all groups) by calling KVGroupReconstructor::SetDoCalibration(false);
105
106 nfireddets = 0;
107 coherency_particles.clear();
108 Reconstruct();
109 if (GetEventFragment()->GetMult() == 0) {
110 return;
111 }
113 if (fDoCalibration) {
114 Calibrate();
116 }
117}
118
119
120
129
131{
132 // Reconstruct the particles in the group from hit trajectories
133 //
134 // We work our way along each trajectory, starting from the furthest detector from the target,
135 // and start reconstruction of a new detected particle depending on decision made in ReconstructTrajectory()
136 // for each detector we try (normally just the first fired detector we find).
137 //
138 // The reconstruction is then handled by ReconstructParticle().
139
140 TIter nxt_traj(GetGroup()->GetTrajectories());
141 KVGeoDNTrajectory* traj;
142
143 // loop over trajectories
144 while ((traj = (KVGeoDNTrajectory*)nxt_traj())) {
145
146 // Work our way along the trajectory, starting from furthest detector from target,
147 // start reconstruction of new detected particle from first fired detector.
148 traj->IterateFrom();
149 KVGeoDetectorNode* node;
150 while ((node = traj->GetNextNode())) {
151
153 if ((kvdp = ReconstructTrajectory(traj, node))) {
154 ReconstructParticle(kvdp, traj, node);
155 break; //start next trajectory
156 }
157
158 }
159
160 }
161
162 if (GetEventFragment()->GetMult()) {
165 }
166}
167
168
169
174
176{
177 // This method will be called after reconstruction and first-order coherency analysis
178 // of all particles in the group (if there are any reconstructed particles).
179 // By default it does nothing.
180}
181
182
183
193
195{
196 // \param traj trajectory currently being scanned
197 // \param node current detector on trajectory to test
198 // \returns pointer to a new reconstructed particle added to this group's event; nullptr if nothing is to be done
199 //
200 // The condition which must be fulfilled for us to begin the reconstruction of a new particle starting from
201 // a fired detector on the trajectory is either:
202 // - the trajectory is the only one which passes through this detector; or
203 // - the detector directly in front of this one on this trajectory also fired.
204
205 KVDetector* d = node->GetDetector();
206 nfireddets += d->Fired();
207 // if d has fired and is either independent (only one trajectory passes through it)
208 // or, if several trajectories pass through it,
209 // only if the detector directly in front of it on this trajectory fired also
210 if (!d->IsAnalysed() && d->Fired(fPartSeedCond)
211 && (node->GetNTraj() == 1 ||
212 (traj->GetNodeInFront(node) &&
213 traj->GetNodeInFront(node)->GetDetector()->Fired()))) {
214
215 return GetEventFragment()->AddParticle();
216 }
217
218 return nullptr;
219}
220
221
222
234
236{
237 // Reconstruction of a detected nucleus from the successive energy losses
238 // measured in a series of detectors/telescopes along a given trajectory.
239 //
240 // The particle is associated with a reconstruction trajectory which starts from the detector in
241 // which the particle stopped and leads up through the detection layers towards the target.
242 // These can be accessed in later analysis using the two methods
243 // - KVReconstructedNucleus::GetStoppingDetector()
244 // - KVReconstructedNucleus::GetReconstructionTrajectory()
245 //
246 // \sa KVReconNucTrajectory
247
249 part->SetReconstructionTrajectory(Rtraj);
250 part->SetParameter("ARRAY", GetGroup()->GetArray()->GetName());
251
252 Rtraj->IterateFrom();// iterate over trajectory
254 while ((n = Rtraj->GetNextNode())) {
255
256 KVDetector* d = n->GetDetector();
257 d->AddHit(part); // add particle to list of particles hitting detector
258
259 }
260
261}
262
263
264
273
275{
276 // Analyse and set status of reconstructed particles in group, to decide whether they can be identified
277 // and further treated straight away.
278 //
279 // If there is more than one reconstructed particle in the group on different trajectories which
280 // have a detector in common, then it may be necessary to identify one of the particles before the
281 // others in order to try to subtract its contribution from the common detector and allow the
282 // identification of the other particles.
283
284 if (GetNUnidentifiedInGroup() > 1) { //if there is more than one unidentified particle in the group
285
286 Int_t n_nseg_1 = 0;
287 //loop over particles counting up different cases
288 for (KVReconstructedEvent::Iterator it = GetEventFragment()->begin(); it != GetEventFragment()->end(); ++it) {
289 KVReconstructedNucleus* nuc = it.get_pointer();
290 //ignore identified particles
291 if (nuc->IsIdentified())
292 continue;
293 // The condition for a particle to be identifiable straight away is that the first
294 // identification method that will be used must be independent
295 //if (nuc->GetNSegDet() >= 1) {
297 && ((KVIDTelescope*)nuc->GetReconstructionTrajectory()->GetIDTelescopes()->First())->IsIndependent()) {
298 //all particles whose first identification telescope is independent are fine
300 }
302 //no independent identification telescope => depends on what's in the rest of the group
303 ++n_nseg_1;
304 }
305 else {
306 //no identification available
308 }
309 }
310 //loop again, setting status
311 for (KVReconstructedEvent::Iterator it = GetEventFragment()->begin(); it != GetEventFragment()->end(); ++it) {
312 KVReconstructedNucleus* nuc = it.get_pointer();
313 if (nuc->IsIdentified())
314 continue; //ignore identified particles
315
317 && ((KVIDTelescope*)nuc->GetReconstructionTrajectory()->GetIDTelescopes()->First())->IsIndependent())
319 //particles with no independent identification possibility
320 if (n_nseg_1 == 1) {
321 //just the one ? then we can get it no problem
322 //after identifying the others and subtracting their calculated
323 //energy losses from the other detectors
325 }
326 else {
327 //more than one ? then we can make some wild guess by sharing the
328 //contribution between them, but I wouldn't trust it as far as I can spit
330 }
331 //one possibility remains: the particle may actually have stopped e.g.
332 //in the DE detector of a DE-E telescope
334 //no ID telescopes with which to identify particle
336 }
337 }
338 }
339 }
340 else if (GetNUnidentifiedInGroup() == 1) {
341 //only one unidentified particle in group: just need an idtelescope which works
342
343 //loop over particles looking for the unidentified one
344 KVReconstructedNucleus* nuc(nullptr);
345 for (KVReconstructedEvent::Iterator it = GetEventFragment()->begin(); it != GetEventFragment()->end(); ++it) {
346 nuc = it.get_pointer();
347 if (!nuc->IsIdentified()) break;
348 }
349 //cout << "nuc->GetNSegDet()=" << nuc->GetNSegDet() << endl;
351 //OK no problem
353 }
354 else {
355 //dead in the water
357 }
358 }
359}
360
361
362
379
381{
382 // Try to identify this nucleus by calling the KVIDTelescope::Identify() method of each
383 // identification telescope on its reconstruction trajectory, starting with the telescope
384 // where the particle stopped (i.e. containing its stopping detector), in order.
385 //
386 // Only identifications which have been correctly initialised for the current run are used,
387 // i.e. those for which KVIDTelescope::IsReadyForID() returns kTRUE.
388 //
389 // Note that *all* identifications along the trajectory are tried, even those far in front
390 // of the detector where the particle stopped. The results of all identifications (KVIdentificationResult)
391 // are stored with the particle (they can be retrieved later using KVReconstructedNucleus::GetIdentificationResult() ).
392 // They are later used for consistency checks ("coherency") between the identifications in the different
393 // stages.
394 //
395 // The first successful identification obtained in this way, if one exists, for a KVIDTelescope which includes
396 // the detector where the particle stopped is then attributed to the particle (see KVReconstructedNucleus::SetIdentification()).
397
399 identifying_telescope = nullptr;
400 id_by_type.clear();
401
402 if (idt_list->GetEntries() > 0) {
403
404 KVIDTelescope* idt;
405 TIter next(idt_list);
406 Int_t idnumber = 1;
407 Int_t n_success_id = 0;//number of successful identifications
408 while ((idt = (KVIDTelescope*) next())) {
409 KVIdentificationResult* IDR = PART.GetIdentificationResult(idnumber++);
410
411 if (idt->IsReadyForID()) { // is telescope able to identify for this run ?
412 id_by_type[idt->GetType()] = IDR;// map contains only attempted identifications
413 if (!IDR->IDattempted) { // the identification may already have been attempted, e.g. in gamma particle
414 // rejection in CSI: see KVINDRAGroupReconstructor::ReconstructTrajectory
415 idt->Identify(IDR);
416 }
417 if (IDR->IDOK) n_success_id++;
418 }
419 else
420 IDR->IDattempted = kFALSE;
421
422 if (n_success_id < 1 &&
423 ((!IDR->IDattempted) || (IDR->IDattempted && !IDR->IDOK))) {
424 // the particle is less identifiable than initially thought
425 // we may have to wait for secondary identification
426 Int_t nseg = PART.GetNSegDet();
427 PART.SetNSegDet(TMath::Max(nseg - 1, 0));
428 //if there are other unidentified particles in the group and NSegDet is < 1
429 //then exact status depends on segmentation of the other particles : reanalyse
430 if (PART.GetNSegDet() < 1 && GetNUnidentifiedInGroup() > 1) {
432 return;
433 }
434 //if NSegDet = 0 it's hopeless
435 if (!PART.GetNSegDet()) {
437 return;
438 }
439 }
440
441 }
442 // set first successful identification as particle identification
443 // as long as the id telescope concerned contains the stopping detector!
444 Int_t id_no = 1;
445 Bool_t ok = kFALSE;
447 next.Reset();
448 idt = (KVIDTelescope*)next();
449 while (idt->HasDetector(PART.GetStoppingDetector())) {
450 if (pid->IDattempted && pid->IDOK) {
451 ok = kTRUE;
452 partID = *pid;
454 break;
455 }
456 ++id_no;
457 pid = PART.GetIdentificationResult(id_no);
458 idt = (KVIDTelescope*)next();
459 }
460 if (ok) {
461 PART.SetIsIdentified();
463 }
464
465 }
466
467}
468
469
470
471
475
477{
478 // particles stopped in first member of a telescope
479 // estimation of Z (minimum) from energy loss (if detector is calibrated)
480 Int_t zmin = d.GetStoppingDetector()->FindZmin(-1., d.GetMassFormula());
481 if (zmin) {
483 idr.Z = zmin;
484 idr.IDcode = ((KVMultiDetArray*)GetGroup()->GetArray())->GetIDCodeForParticlesStoppingInFirstStageOfTelescopes();
485 idr.Zident = false;
486 idr.Aident = false;
487 idr.PID = zmin;
488 d.SetIsIdentified();
489 KVGeoDNTrajectory* t = (KVGeoDNTrajectory*)d.GetStoppingDetector()->GetNode()->GetTrajectories()->First();
490 d.SetIdentification(&idr, (KVIDTelescope*) t->GetIDTelescopes()->Last());
491 }
492}
493
494
495
505
507{
508 // Identify all particles reconstructed so far in this group which
509 // may be identified independently of all other particles in the group according to the 1st
510 // order coherency analysis (see AnalyseParticles() ). This is done by calling the method
511 // IdentifyParticle() for each particle in turn.
512 //
513 // Particles stopping in the first member of a telescope will
514 // have their Z estimated from the energy loss in the detector (if calibrated):
515 // in this case the Z is a minimum value.
516
517 for (KVReconstructedEvent::Iterator it = GetEventFragment()->begin(); it != GetEventFragment()->end(); ++it) {
518 KVReconstructedNucleus& d = it.get_reference();
519 if (!d.IsIdentified()) {
520 if (d.GetStatus() == KVReconstructedNucleus::kStatusOK) {
521 // identifiable particles
523 }
524 else if (d.GetStatus() == KVReconstructedNucleus::kStatusStopFirstStage) {
525 // particles stopped in first member of a telescope
526 // estimation of Z (minimum) from energy loss (if detector is calibrated)
528 }
529 }
530 }
531}
532
533
534
535
538
540{
541 // Calculate and set energies of all identified but uncalibrated particles in event.
542
543 for (auto& d : ReconEventIterator(GetEventFragment())) {
544
545 if (d.IsIdentified() && !d.IsCalibrated()) {
547 }
548
549 }
550
551}
552
553
554
570
572{
573 // Calculate the energy loss in the current target of the multidetector
574 // for the reconstructed charged particle 'ion', assuming that the current
575 // energy and momentum of this particle correspond to its state on
576 // leaving the target.
577 //
578 // WARNING: for this correction to work, the target must be in the right 'state':
579 //
580 // gMultiDetArray->GetTarget()->SetIncoming(kFALSE);
581 // gMultiDetArray->GetTarget()->SetOutgoing(kTRUE);
582 //
583 // (see KVTarget::GetParticleEIncFromERes).
584 //
585 // The returned value is the energy lost in the target in MeV.
586 // The energy/momentum of 'ion' are not affected.
587
589 if (!array->GetTarget() || !ion) return 0.0;
590 return (array->GetTarget()->GetParticleEIncFromERes(ion) - ion->GetEnergy());
591}
592
593
594
int Int_t
#define SafeDelete(p)
#define d(i)
#define c(i)
bool Bool_t
constexpr Bool_t kFALSE
double Double_t
constexpr Bool_t kTRUE
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t g
Base class for KaliVeda framework.
Definition KVBase.h:142
virtual const Char_t * GetType() const
Definition KVBase.h:177
static TPluginHandler * LoadPlugin(const Char_t *base, const Char_t *uri="0")
Definition KVBase.cpp:793
Base class for detector geometry description.
Definition KVDetector.h:160
virtual Bool_t Fired(Option_t *opt="any") const
Definition KVDetector.h:451
Path taken by particles through multidetector geometry.
KVGeoDetectorNode * GetNodeInFront(const KVGeoDetectorNode *n) const
const KVSeqCollection * GetIDTelescopes() const
void IterateFrom(const KVGeoDetectorNode *node0=nullptr) const
Int_t GetNumberOfIdentifications() const
KVGeoDetectorNode * GetNextNode() const
Information on relative positions of detectors & particle trajectories.
KVDetector * GetDetector() const
Int_t GetNTraj() const
Returns number of trajectories passing through this node.
Base class for particle reconstruction in one group of a detector array.
virtual KVReconstructedNucleus * ReconstructTrajectory(const KVGeoDNTrajectory *traj, const KVGeoDetectorNode *node)
KVGroup * GetGroup() const
KVReconstructedEvent * fGrpEvent
event containing particles reconstructed in this group
KVIDTelescope * identifying_telescope
telescope which identified current particle
void ReconstructParticle(KVReconstructedNucleus *part, const KVGeoDNTrajectory *traj, const KVGeoDetectorNode *node)
std::unordered_map< std::string, KVIdentificationResult * > id_by_type
identification results by type for current particle
virtual void CalibrateParticle(KVReconstructedNucleus *)
virtual void AddCoherencyParticles()
int nfireddets
number of fired detectors in group for current event
KVGroup * fGroup
the group where we are reconstructing
void Calibrate()
Calculate and set energies of all identified but uncalibrated particles in event.
virtual ~KVGroupReconstructor()
Destructor.
KVReconstructedEvent * GetEventFragment() const
TString fPartSeedCond
condition for seeding reconstructed particles
Double_t GetTargetEnergyLossCorrection(KVReconstructedNucleus *ion)
virtual void IdentifyParticle(KVReconstructedNucleus &)
void SetReconEventClass(TClass *c)
Instantiate event fragment object.
TString GetPartSeedCond() const
KVIdentificationResult partID
identification to be applied to current particle
KVGroupReconstructor()
Default constructor.
void TreatStatusStopFirstStage(KVReconstructedNucleus &)
virtual void PostReconstructionProcessing()
static KVGroupReconstructor * Factory(const TString &plugin="")
virtual void SetGroup(KVGroup *g)
std::vector< particle_to_add_from_coherency_analysis > coherency_particles
Group of detectors which can be treated independently of all others in array.
Definition KVGroup.h:20
const KVGeoDNTrajectory * GetTrajectoryForReconstruction(const KVGeoDNTrajectory *t, const KVGeoDetectorNode *n) const
Definition KVGroup.h:104
KVGeoStrucElement * GetArray() const
Definition KVGroup.h:45
Base class for all detectors or associations of detectors in array which can identify charged particl...
virtual Bool_t IsReadyForID()
virtual Bool_t Identify(KVIdentificationResult *, Double_t x=-1., Double_t y=-1.)
Bool_t HasDetector(const KVDetector *d) const
Full result of one attempted particle identification.
Bool_t IDattempted
=kTRUE if identification was attempted
Bool_t IDOK
general quality of identification, =kTRUE if acceptable identification made
Bool_t Aident
= kTRUE if A of particle established
Double_t PID
= "real" Z if Zident==kTRUE and Aident==kFALSE, "real" A if Zident==Aident==kTRUE
Int_t Z
Z of particle found (if Zident==kTRUE)
Int_t IDcode
a general identification code for this type of identification
Bool_t Zident
=kTRUE if Z of particle established
Base class for describing the geometry of a detector array.
KVTarget * GetTarget()
Double_t GetEnergy() const
Definition KVParticle.h:621
void SetParameter(const Char_t *name, ValType value) const
Definition KVParticle.h:819
Path through detector array used to reconstruct detected particle.
Event containing KVReconstructedNucleus nuclei reconstructed from hits in detectors.
Nuclei reconstructed from data measured by a detector array .
void SetReconstructionTrajectory(const KVReconNucTrajectory *t)
Method called in initial reconstruction of particle.
KVIdentificationResult * GetIdentificationResult(Int_t i)
KVDetector * GetStoppingDetector() const
void SetDetector(int i, KVDetector *);
void SetIdentification(KVIdentificationResult *, KVIDTelescope *)
@ kStatusOKafterShare
of energy losses of other particles in the same group which have Status=0
@ kStatusStopFirstStage
(arbitrarily) between this and the other particle(s) with Status=2
const KVReconNucTrajectory * GetReconstructionTrajectory() const
KaliVeda extensions to ROOT collection classes.
virtual TObject * Last() const
virtual TObject * First() const
virtual Double_t GetParticleEIncFromERes(KVNucleus *, TVector3 *norm=0)
Definition KVTarget.cpp:957
Iterator begin() const
Particle * AddParticle()
Iterator end() const
Wrapper class for iterating over nuclei in KVReconstructedEvent accessed through base pointer or refe...
virtual Int_t GetEntries() const
void Reset()
const char * GetName() const override
Longptr_t ExecPlugin(int nargs)
const Int_t n
Double_t Max(Double_t a, Double_t b)
ClassImp(TPyArg)