KaliVeda  1.12/06
Heavy-Ion Analysis Toolkit
KVGroupReconstructor.cpp
Go to the documentation of this file.
1 #include "KVGroupReconstructor.h"
2 #include "KVMultiDetArray.h"
3 #include "KVTarget.h"
4 
5 #include <TPluginManager.h>
6 using std::cout;
7 using 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 
32 {
33  // Destructor
34 
36 }
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 
63  if (!fGrpEvent) fGrpEvent = (KVReconstructedEvent*)c->New();
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  return GetEventFragment()->AddParticle();
215  }
216  return nullptr;
217 }
218 
219 
220 
232 
234 {
235  // Reconstruction of a detected nucleus from the successive energy losses
236  // measured in a series of detectors/telescopes along a given trajectory.
237  //
238  // The particle is associated with a reconstruction trajectory which starts from the detector in
239  // which the particle stopped and leads up through the detection layers towards the target.
240  // These can be accessed in later analysis using the two methods
241  // - KVReconstructedNucleus::GetStoppingDetector()
242  // - KVReconstructedNucleus::GetReconstructionTrajectory()
243  //
244  // \sa KVReconNucTrajectory
245 
247  part->SetReconstructionTrajectory(Rtraj);
248  part->SetParameter("ARRAY", GetGroup()->GetArray()->GetName());
249 
250  Rtraj->IterateFrom();// iterate over trajectory
252  while ((n = Rtraj->GetNextNode())) {
253 
254  KVDetector* d = n->GetDetector();
255  d->AddHit(part); // add particle to list of particles hitting detector
256 
257  }
258 
259 }
260 
261 
262 
271 
273 {
274  // Analyse and set status of reconstructed particles in group, to decide whether they can be identified
275  // and further treated straight away.
276  //
277  // If there is more than one reconstructed particle in the group on different trajectories which
278  // have a detector in common, then it may be necessary to identify one of the particles before the
279  // others in order to try to subtract its contribution from the common detector and allow the
280  // identification of the other particles.
281 
282  if (GetNUnidentifiedInGroup() > 1) { //if there is more than one unidentified particle in the group
283 
284  Int_t n_nseg_1 = 0;
285  //loop over particles counting up different cases
286  for (KVEvent::Iterator it = GetEventFragment()->begin(); it != GetEventFragment()->end(); ++it) {
287  KVReconstructedNucleus* nuc = it.get_pointer<KVReconstructedNucleus>();
288  //ignore identified particles
289  if (nuc->IsIdentified())
290  continue;
291  // The condition for a particle to be identifiable straight away is that the first
292  // identification method that will be used must be independent
293  //if (nuc->GetNSegDet() >= 1) {
295  && ((KVIDTelescope*)nuc->GetReconstructionTrajectory()->GetIDTelescopes()->First())->IsIndependent()) {
296  //all particles whose first identification telescope is independent are fine
298  }
300  //no independent identification telescope => depends on what's in the rest of the group
301  ++n_nseg_1;
302  }
303  else {
304  //no identification available
306  }
307  }
308  //loop again, setting status
309  for (KVEvent::Iterator it = GetEventFragment()->begin(); it != GetEventFragment()->end(); ++it) {
310  KVReconstructedNucleus* nuc = it.get_pointer<KVReconstructedNucleus>();
311  if (nuc->IsIdentified())
312  continue; //ignore identified particles
313 
315  && ((KVIDTelescope*)nuc->GetReconstructionTrajectory()->GetIDTelescopes()->First())->IsIndependent())
317  //particles with no independent identification possibility
318  if (n_nseg_1 == 1) {
319  //just the one ? then we can get it no problem
320  //after identifying the others and subtracting their calculated
321  //energy losses from the other detectors
323  }
324  else {
325  //more than one ? then we can make some wild guess by sharing the
326  //contribution between them, but I wouldn't trust it as far as I can spit
328  }
329  //one possibility remains: the particle may actually have stopped e.g.
330  //in the DE detector of a DE-E telescope
332  //no ID telescopes with which to identify particle
334  }
335  }
336  }
337  }
338  else if (GetNUnidentifiedInGroup() == 1) {
339  //only one unidentified particle in group: just need an idtelescope which works
340 
341  //loop over particles looking for the unidentified one
342  KVReconstructedNucleus* nuc(nullptr);
343  for (KVEvent::Iterator it = GetEventFragment()->begin(); it != GetEventFragment()->end(); ++it) {
344  nuc = it.get_pointer<KVReconstructedNucleus>();
345  if (!nuc->IsIdentified()) break;
346  }
347  //cout << "nuc->GetNSegDet()=" << nuc->GetNSegDet() << endl;
349  //OK no problem
351  }
352  else {
353  //dead in the water
355  }
356  }
357 }
358 
359 
360 
377 
379 {
380  // Try to identify this nucleus by calling the KVIDTelescope::Identify() method of each
381  // identification telescope on its reconstruction trajectory, starting with the telescope
382  // where the particle stopped (i.e. containing its stopping detector), in order.
383  //
384  // Only identifications which have been correctly initialised for the current run are used,
385  // i.e. those for which KVIDTelescope::IsReadyForID() returns kTRUE.
386  //
387  // Note that *all* identifications along the trajectory are tried, even those far in front
388  // of the detector where the particle stopped. The results of all identifications (KVIdentificationResult)
389  // are stored with the particle (they can be retrieved later using KVReconstructedNucleus::GetIdentificationResult() ).
390  // They are later used for consistency checks ("coherency") between the identifications in the different
391  // stages.
392  //
393  // The first successful identification obtained in this way, if one exists, for a KVIDTelescope which includes
394  // the detector where the particle stopped is then attributed to the particle (see KVReconstructedNucleus::SetIdentification()).
395 
396  const KVSeqCollection* idt_list = PART.GetReconstructionTrajectory()->GetIDTelescopes();
397  identifying_telescope = nullptr;
398  id_by_type.clear();
399 
400  if (idt_list->GetEntries() > 0) {
401 
402  KVIDTelescope* idt;
403  TIter next(idt_list);
404  Int_t idnumber = 1;
405  Int_t n_success_id = 0;//number of successful identifications
406  while ((idt = (KVIDTelescope*) next())) {
407  KVIdentificationResult* IDR = PART.GetIdentificationResult(idnumber++);
408 
409  if (idt->IsReadyForID()) { // is telescope able to identify for this run ?
410  id_by_type[idt->GetType()] = IDR;// map contains only attempted identifications
411  if (!IDR->IDattempted) { // the identification may already have been attempted, e.g. in gamma particle
412  // rejection in CSI: see KVINDRAGroupReconstructor::ReconstructTrajectory
413  idt->Identify(IDR);
414  }
415  if (IDR->IDOK) n_success_id++;
416  }
417  else
418  IDR->IDattempted = kFALSE;
419 
420  if (n_success_id < 1 &&
421  ((!IDR->IDattempted) || (IDR->IDattempted && !IDR->IDOK))) {
422  // the particle is less identifiable than initially thought
423  // we may have to wait for secondary identification
424  Int_t nseg = PART.GetNSegDet();
425  PART.SetNSegDet(TMath::Max(nseg - 1, 0));
426  //if there are other unidentified particles in the group and NSegDet is < 1
427  //then exact status depends on segmentation of the other particles : reanalyse
428  if (PART.GetNSegDet() < 1 && GetNUnidentifiedInGroup() > 1) {
430  return;
431  }
432  //if NSegDet = 0 it's hopeless
433  if (!PART.GetNSegDet()) {
435  return;
436  }
437  }
438 
439  }
440  // set first successful identification as particle identification
441  // as long as the id telescope concerned contains the stopping detector!
442  Int_t id_no = 1;
443  Bool_t ok = kFALSE;
445  next.Reset();
446  idt = (KVIDTelescope*)next();
447  while (idt->HasDetector(PART.GetStoppingDetector())) {
448  if (pid->IDattempted && pid->IDOK) {
449  ok = kTRUE;
450  partID = *pid;
451  identifying_telescope = idt;
452  break;
453  }
454  ++id_no;
455  pid = PART.GetIdentificationResult(id_no);
456  idt = (KVIDTelescope*)next();
457  }
458  if (ok) {
459  PART.SetIsIdentified();
461  }
462 
463  }
464 
465 }
466 
467 
468 
469 
473 
475 {
476  // particles stopped in first member of a telescope
477  // estimation of Z (minimum) from energy loss (if detector is calibrated)
478  Int_t zmin = d.GetStoppingDetector()->FindZmin(-1., d.GetMassFormula());
479  if (zmin) {
481  idr.Z = zmin;
482  idr.IDcode = ((KVMultiDetArray*)GetGroup()->GetArray())->GetIDCodeForParticlesStoppingInFirstStageOfTelescopes();
483  idr.Zident = false;
484  idr.Aident = false;
485  idr.PID = zmin;
486  d.SetIsIdentified();
487  KVGeoDNTrajectory* t = (KVGeoDNTrajectory*)d.GetStoppingDetector()->GetNode()->GetTrajectories()->First();
488  d.SetIdentification(&idr, (KVIDTelescope*) t->GetIDTelescopes()->Last());
489  }
490 }
491 
492 
493 
503 
505 {
506  // Identify all particles reconstructed so far in this group which
507  // may be identified independently of all other particles in the group according to the 1st
508  // order coherency analysis (see AnalyseParticles() ). This is done by calling the method
509  // IdentifyParticle() for each particle in turn.
510  //
511  // Particles stopping in the first member of a telescope will
512  // have their Z estimated from the energy loss in the detector (if calibrated):
513  // in this case the Z is a minimum value.
514 
515  for (KVEvent::Iterator it = GetEventFragment()->begin(); it != GetEventFragment()->end(); ++it) {
516  KVReconstructedNucleus& d = it.get_reference<KVReconstructedNucleus>();
517  if (!d.IsIdentified()) {
518  if (d.GetStatus() == KVReconstructedNucleus::kStatusOK) {
519  // identifiable particles
521  }
522  else if (d.GetStatus() == KVReconstructedNucleus::kStatusStopFirstStage) {
523  // particles stopped in first member of a telescope
524  // estimation of Z (minimum) from energy loss (if detector is calibrated)
526  }
527  }
528  }
529 }
530 
531 
532 
533 
536 
538 {
539  // Calculate and set energies of all identified but uncalibrated particles in event.
540 
542 
543  while ((d = GetEventFragment()->GetNextParticle())) {
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
ClassImp(KVPartitionList) void KVPartitionList
Initialisation.
#define SafeDelete(p)
#define d(i)
#define c(i)
const Bool_t kFALSE
bool Bool_t
double Double_t
const Bool_t kTRUE
Base class for KaliVeda framework.
Definition: KVBase.h:135
const Char_t * GetType() const
Definition: KVBase.h:170
static TPluginHandler * LoadPlugin(const Char_t *base, const Char_t *uri="0")
Definition: KVBase.cpp:756
Base class for detector geometry description, interface to energy-loss calculations.
Definition: KVDetector.h:121
virtual Bool_t Fired(Option_t *opt="any") const
Definition: KVDetector.h:796
Iterator begin() const
Definition: KVEvent.h:423
Iterator end() const
Definition: KVEvent.h:428
Path taken by particles through multidetector geometry.
KVGeoDetectorNode * GetNextNode() const
void IterateFrom(const KVGeoDetectorNode *node0=nullptr) const
Int_t GetNumberOfIdentifications() const
const KVSeqCollection * GetIDTelescopes() const
KVGeoDetectorNode * GetNodeInFront(const KVGeoDetectorNode *n) 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)
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)
KVGroup * GetGroup() const
std::unordered_map< std::string, KVIdentificationResult * > id_by_type
identification results by type for current particle
KVReconstructedEvent * GetEventFragment() const
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 void IdentifyParticle(KVReconstructedNucleus &PART)
virtual ~KVGroupReconstructor()
Destructor.
TString fPartSeedCond
condition for seeding reconstructed particles
Double_t GetTargetEnergyLossCorrection(KVReconstructedNucleus *ion)
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:19
KVGeoStrucElement * GetArray() const
Definition: KVGroup.h:44
const KVGeoDNTrajectory * GetTrajectoryForReconstruction(const KVGeoDNTrajectory *t, const KVGeoDetectorNode *n) const
Definition: KVGroup.h:103
Base class for all detectors or associations of detectors in array which can identify charged particl...
Definition: KVIDTelescope.h:88
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:582
void SetParameter(const Char_t *name, ValType value) const
Definition: KVParticle.h:739
Path through detector array used to reconstruct detected particle.
Physical event reconstructed from data measured with a detector array using implemented identificatio...
KVReconstructedNucleus * AddParticle()
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)
const KVReconNucTrajectory * GetReconstructionTrajectory() const
void SetIdentification(KVIdentificationResult *, KVIDTelescope *)
KVDetector * GetStoppingDetector() const
void SetDetector(int i, KVDetector *);
@ 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
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:963
virtual Int_t GetEntries() const
void Reset()
virtual const char * GetName() const
Longptr_t ExecPlugin(int nargs, const T &... params)
const Int_t n
const long double g
masses
Definition: KVUnits.h:72
Double_t Max(Double_t a, Double_t b)