KaliVeda  1.12/06
Heavy-Ion Analysis Toolkit
KVINDRAEtalonGroupReconstructor.cpp
Go to the documentation of this file.
1 //Created by KVClassFactory on Wed Feb 21 13:43:10 2018
2 //Author: John Frankland,,,
3 
5 #include <string>
6 #include <unordered_map>
7 #include <iostream>
8 #include <KVSilicon.h>
9 #include "KVIDGCsI.h"
10 using namespace std;
11 
13 
14 
15 
16 
34 {
35  // \param traj trajectory currently being scanned
36  // \param node current detector on trajectory to test
37  // \returns pointer to a new reconstructed particle added to this group's event; nullptr if nothing is to be done
38  //
39  // Specialised particle reconstruction for INDRA groups with etalon telescopes (Rings 10-17).
40  //
41  // If node is a CsI detector with more than one trajectory passing through it (in front of it),
42  // we are behind the etalons Si(75)-Si(Li).
43  //
44  // As the Si(75)-Si(Li) coders are opened by every firing of the CsI directly behind them,
45  // their acquisition parameters are present in the event whether the particle went through them
46  // or passed directly from ChIo to CsI.
47  //
48  // The best way to choose the right reconstruction trajectory is to see if Si(Li)-CsI
49  // provides an identification, and if so is it coherent with that of the CsI.
50 
51  if (!node->GetDetector()->IsAnalysed() &&
52  node->GetDetector()->Fired(GetPartSeedCond()) &&
53  node->GetDetector()->IsType("CSI") &&
54  node->GetNTrajForwards() > 1) {
55  ++nfireddets;
56  const KVSeqCollection* idt_list = traj->GetIDTelescopes();
57  TIter next_idt(idt_list);
58  KVIDTelescope* idt;
59  bool with_etalon = (traj->GetN() == 4);
60 
61  std::unordered_map<std::string, KVIdentificationResult> IDR;
62  while ((idt = (KVIDTelescope*)next_idt())) {
63  if (idt->IsReadyForID()) { // is telescope able to identify for this run ?
64  idt->Identify(&IDR[idt->GetType()]);
65  }
66  }
67  // cases:
68  // gamma in CsI: * same as general INDRA reconstruction: count the gammmas, do not
69  // reconstruct a particle (but set CsI analysed state)
70  // particle identified in CsI:
71  // * if this is the long trajectory, check the SILI-CSI identification
72  // if SILI-CSI identification no good, then short trajectory should be used
73  // so we return nullptr
74  // * if this is the short trajectory, we accept it
75  KVIdentificationResult& idcsi = IDR["CSI_R_L"];
76  if (idcsi.IDattempted) {
77  if (idcsi.IDOK) {
78  if (idcsi.IDcode == KVINDRA::IDCodes::ID_GAMMA || idcsi.IDquality == KVIDGCsI::kICODE10) {
79  // gamma
80  //Info("ReconstructTrajectory","Gamma in CsI: with_etalon=%d",with_etalon);
81  GetEventFragment()->GetParameters()->IncrementValue("INDRA_GAMMA_MULT", 1);
82  GetEventFragment()->GetParameters()->IncrementValue("INDRA_GAMMA_DETS", node->GetName());
83  node->GetDetector()->SetAnalysed();
84  return nullptr;
85  }
86  else { // charged particle identified
87  //Info("ReconstructTrajectory","Charged particle in CsI: with_etalon=%d",with_etalon);
88  if (with_etalon) {
89  if (IDR["SILI_CSI"].IDattempted && IDR["SILI_CSI"].IDOK) {
90  //Info("ReconstructTrajectory","Charged particle in SILI too Zcsi=%d Zsili=%d",idcsi.Z,IDR["SILI_CSI"].Z);
91  return GetEventFragment()->AddParticle();
92  }
93  else return nullptr;
94  }
95  else
96  return GetEventFragment()->AddParticle();
97  }
98  }
99  }
100  return nullptr;
101  }
102  // standard non-etalon treatment
104 }
105 
106 
107 
112 
114 {
115  // Coherency analysis for etalon groups on rings 10-17 of INDRA
116  // Note that the treatment of all modules in the group except the one with the etalons
117  // is standard (KVINDRABackwardGroupReconstructor), but all modules will call here first
118 
119  if (!GetSi75(&PART) && !GetSiLi(&PART)) // => no etalons in particle trajectory
121 
122  PART.SetParameter("UseFullChIoEnergyForCalib", !(theChio && theChio->GetNHits() > 1));
123  bool ok = CoherencyEtalons(PART);
124 
125  return ok;
126 }
127 
128 
129 
132 
134 {
135  // Calibration of particle stopping in etalon modules
136 
137  fESiLi = fESi75 = 0;
138 
139  if (!GetSi75(PART) && !GetSiLi(PART)) // => no etalons in particle trajectory
141 
142  // change fUseFullChioenergyforcalib for "coherency" particles
143  // we assume they are calibrated after all other particles in group have
144  // been identified, calibrated, and their energy contributions removed
145  // from the ChIo
146  if (PART->GetIDCode() == KVINDRA::IDCodes::ID_CI_SI_COHERENCY
147  || PART->GetIDCode() == KVINDRA::IDCodes::ID_CI_COHERENCY
148  || PART->GetIDCode() == KVINDRA::IDCodes::ID_CI_MULTIHIT)
149  PART->SetParameter("UseFullChIoEnergyForCalib", kTRUE);
150 
151  Bool_t stopped_in_chio = kTRUE;
152  auto csi = GetCsI(PART);
153  if (csi) {
154  stopped_in_chio = kFALSE;
155  if (csi->IsCalibrated()) {
156  /* CSI ENERGY CALIBRATION */
157  if (PART->GetIDCode() == KVINDRA::IDCodes::ID_CSI_PSA && PART->IsIsotope(4, 8)) {
158  fECsI = DoBeryllium8Calibration(PART);
159  }
160  else
161  fECsI = csi->GetCorrectedEnergy(PART, -1., kFALSE);
162  }
163  else {
164  SetNoCalibrationStatus(PART);
165  return;
166  }
167  if (fECsI <= 0 && (PART->GetECode() != KVINDRA::ECodes::SOME_ENERGY_LOSSES_CALCULATED)) { // DoBeryllium8Calibration returns fECsI<0 with ECode=SOME_ENERGY_LOSSES_CALCULATED if OK
168  SetBadCalibrationStatus(PART);// problem with CsI energy - no calibration
169  return;
170  }
171  }
172  if (PART->GetParameters()->GetBoolValue("IncludeEtalonsInCalibration")) {
173  auto sili = GetSiLi(PART);
174  if (sili) {
175  bool stopped_in_sili = PART->GetStoppingDetector()->IsType("SILI");
176  Double_t ERES = TMath::Abs(fECsI);
177  if (!PART->GetParameters()->GetBoolValue("PileupSiLi") && sili->IsCalibrated()) {
178  Bool_t si_transmission = kTRUE;
179  if (stopped_in_sili) {
180  si_transmission = kFALSE;
181  }
182  else {
183  sili->SetEResAfterDetector(ERES);
184  }
185  fESiLi = sili->GetCorrectedEnergy(PART, -1., si_transmission);
186  if (fESiLi <= 0) {
187  if (!stopped_in_sili && ERES > 0.0) {
188  if (!CalculateSiLiDEFromResidualEnergy(ERES, sili, PART)) return;
189  }
190  else {
191  SetBadCalibrationStatus(PART);
192  return;
193  }
194  }
195  }
196  else {
197  if (!CalculateSiLiDEFromResidualEnergy(ERES, sili, PART)) return;
198  }
199  }
200  auto si75 = GetSi75(PART);
201  if (si75) {
202  bool stopped_in_si75 = PART->GetStoppingDetector()->IsType("SI75");
203  Double_t ERES = TMath::Abs(fECsI) + TMath::Abs(fESiLi);
204  if (!PART->GetParameters()->GetBoolValue("PileupSi75")
205  && !PART->GetParameters()->GetBoolValue("PileupSiLi")
206  && si75->IsCalibrated()) {
207  Bool_t si_transmission = kTRUE;
208  if (stopped_in_si75) {
209  si_transmission = kFALSE;
210  }
211  else {
212  si75->SetEResAfterDetector(ERES);
213  }
214  fESi75 = si75->GetCorrectedEnergy(PART, -1., si_transmission);
215  if (fESi75 <= 0) {
216  if (!stopped_in_si75 && ERES > 0.0) {
217  if (!CalculateSi75DEFromResidualEnergy(ERES, si75, PART)) return;
218  }
219  else {
220  SetBadCalibrationStatus(PART);
221  return;
222  }
223  }
224  }
225  else {
226  if (!CalculateSi75DEFromResidualEnergy(ERES, si75, PART)) return;
227  }
228  }
229  }
230  if (theChio) {
231  /* IONISATION CHAMBER ENERGY CONTRIBUTION */
232  // if fUseFullChIoEnergyForCalib = kFALSE, ChIo was hit by other particles in group
233  // therefore we have to estimate the ChIo energy for this particle using the CsI energy
234  // if fPileupChIo = kTRUE, there appears to be another particle stopped in the ChIo
235  // therefore we have to estimate the ChIo energy for this particle using the CsI energy
236  Double_t ERES = TMath::Abs(fECsI) + TMath::Abs(fESiLi) + TMath::Abs(fESi75);
237  if (!PART->GetParameters()->GetBoolValue("PileupChIo")
238  && PART->GetParameters()->GetBoolValue("UseFullChIoEnergyForCalib")
239  && theChio->IsCalibrated()) {
240  // all is apparently well
241  Bool_t ci_transmission = kTRUE;
242  if (stopped_in_chio) {
243  ci_transmission = kFALSE;
244  }
245  else {
246  theChio->SetEResAfterDetector(ERES);
247  }
248  fEChIo = theChio->GetCorrectedEnergy(PART, -1., ci_transmission);
249  if (fEChIo <= 0) {
250  if (!stopped_in_chio && ERES > 0) {
251  if (!CalculateChIoDEFromResidualEnergy(PART, ERES)) return;
252  }
253  }
254  }
255  else {
256  if (!stopped_in_chio && ERES > 0) {
257  if (!CalculateChIoDEFromResidualEnergy(PART, ERES)) return;
258  }
259  }
260  }
261 
262  PART->SetEnergy(TMath::Abs(fECsI) + TMath::Abs(fESiLi) + TMath::Abs(fESi75) + TMath::Abs(fEChIo));
263 }
264 
265 
266 
269 
271 {
272  // Called by Identify() for particles stopping in etalon modules of Rings 10-17.
273 
274  KVIdentificationResult* IDcsi, *IDsilicsi, *IDsi75sili, *IDcisi75, *IDcicsi;
275  IDcsi = IDsilicsi = IDsi75sili = IDcisi75 = IDcicsi = nullptr;
276  if (PART.GetStoppingDetector()->IsType("CSI")) {
277  IDcsi = PART.GetIdentificationResult("CSI_R_L");
278  IDcicsi = PART.GetIdentificationResult("CI_CSI");
279  IDsilicsi = PART.GetIdentificationResult("SILI_CSI");
280  }
281  IDsi75sili = PART.GetIdentificationResult("SI75_SILI");
282  IDcisi75 = PART.GetIdentificationResult("CI_SI75");
283 
284  PART.SetParameter("PileupChIo", kFALSE);
285  PART.SetParameter("IncludeEtalonsInCalibration", kTRUE);
286 
287  Bool_t haveCsI = IDcsi && IDcsi->IDOK;
288  Bool_t haveSiLiCsI = IDsilicsi && IDsilicsi->IDOK;
289  Bool_t haveSi75SiLi = IDsi75sili && IDsi75sili->IDOK;
290  Bool_t haveChIoSi75 = IDcisi75 && IDcisi75->IDOK;
291 
292  KVIDTelescope* idt_csi, *idt_silicsi, *idt_si75sili, *idt_cisi75, *idt_cicsi;
293  idt_csi = idt_silicsi = idt_si75sili = idt_cisi75 = idt_cicsi = nullptr;
294  if (PART.GetStoppingDetector()->IsType("CSI")) {
295  idt_csi =
297  idt_silicsi =
299  idt_cicsi =
301  }
302  idt_si75sili = (KVIDTelescope*)PART.GetReconstructionTrajectory()->GetIDTelescopes()->FindObjectByType(IDsi75sili->GetType());
304 
305  // Treat cases where particle hit etalon telescope
306  if (idt_csi) {
307  if (haveCsI) {
308 
309  partID = *IDcsi;
310  identifying_telescope = idt_csi;
311 
312  if (haveSi75SiLi) {
313  // check for heavy fragment in Si75-SiLi
314  if (IDsi75sili->Z > partID.Z) {
315  if (haveChIoSi75) {
316  // check we don't have a better identification in ChIo-Si75
317  if (IDcisi75->IDquality < IDsi75sili->IDquality && IDcisi75->Z > partID.Z) {
318  PART.SetParameter("PileupSi75", kTRUE);
319  IDcisi75->SetComment("CsI identification with another particle stopped in Si75");
320  PART.SetParameter("UseFullChIoEnergyForCalib", kFALSE); // calculate ChIo energy for this particle
321  }
322  else {
323  PART.SetParameter("PileupSiLi", kTRUE);
324  IDsi75sili->SetComment("CsI identification with another particle stopped in SiLi");
325  PART.SetParameter("UseFullChIoEnergyForCalib", kFALSE); // calculate ChIo energy for this particle
326  }
327  }
328  }
329  }
330  else if (haveChIoSi75) {
331  // check for heavy fragment in ChIo-Si75
332  if (IDcisi75->Z > partID.Z) {
333  PART.SetParameter("PileupSi75", kTRUE);
334  IDcisi75->SetComment("CsI identification with another particle stopped in Si75");
335  PART.SetParameter("UseFullChIoEnergyForCalib", kFALSE); // calculate ChIo energy for this particle
336  }
337  }
338  return kTRUE;
339  }
340  else if (haveSiLiCsI) {
341  partID = *IDsilicsi;
342  identifying_telescope = idt_silicsi;
343  if (haveChIoSi75) {
344  // check for heavy fragment in ChIo-Si75
345  if (IDcisi75->Z > partID.Z) {
346  PART.SetParameter("PileupSi75", kTRUE);
347  IDcisi75->SetComment("CsI identification with another particle stopped in Si75");
348  PART.SetParameter("UseFullChIoEnergyForCalib", kFALSE); // calculate ChIo energy for this particle
349  }
350  }
351  return kTRUE;
352  }
353  }
354  else if (PART.GetStoppingDetector()->IsType("SILI")) {
355  if (haveSi75SiLi) {
356  partID = *IDsi75sili;
357  identifying_telescope = idt_si75sili;
358  // check ChIo-Si75 id is coherent (either no id or Z<=this one)
359  if (haveChIoSi75) {
360  if (IDcisi75->Z > partID.Z) PART.SetParameter("PileupChIo", kTRUE);
361  }
362  return kTRUE;
363  }
364  else if (haveChIoSi75) {
365  partID = *IDcisi75;
366  identifying_telescope = idt_cisi75;
367  return kTRUE;
368  }
369  }
370  else if (PART.GetStoppingDetector()->IsType("SI75")) { // MFR march 2014 SiLi is not the real stopping detector
371  if (haveChIoSi75) {
372  partID = *IDcisi75;
373  identifying_telescope = idt_cisi75;
374  return kTRUE;
375  } // end MFR march 2014
376  }
377 
378  return kFALSE;
379 }
380 
381 
382 
386 
388 {
389  // Etalon modules
390  // calculate fESiLi from residual CsI energy
391  Double_t e0 = sili->GetDeltaEFromERes(n->GetZ(), n->GetA(), ERES);
392  sili->SetEResAfterDetector(ERES);
393  fESiLi = sili->GetCorrectedEnergy(n, e0);
394  if (fESiLi <= 0) {
395  fESiLi = 0;
396  SetBadCalibrationStatus(n);
397  return kFALSE;
398  }
399  fESiLi = -TMath::Abs(fESiLi);
400  SetCalibrationStatus(*n, KVINDRA::ECodes::SOME_ENERGY_LOSSES_CALCULATED);
401  return kTRUE;
402 }
403 
404 
405 
409 
411 {
412  // Etalon modules
413  // calculate fESi75 from residual CsI+SiLi energy
414  Double_t e0 = si75->GetDeltaEFromERes(n->GetZ(), n->GetA(), ERES);
415  si75->SetEResAfterDetector(ERES);
416  fESi75 = si75->GetCorrectedEnergy(n, e0);
417  if (fESi75 <= 0) {
418  fESi75 = 0;
419  SetBadCalibrationStatus(n);
420  return kFALSE;
421  }
422  fESi75 = -TMath::Abs(fESi75);
423  SetCalibrationStatus(*n, KVINDRA::ECodes::SOME_ENERGY_LOSSES_CALCULATED);
424  return kTRUE;
425 }
426 
427 
ClassImp(KVPartitionList) void KVPartitionList
Initialisation.
const Bool_t kFALSE
bool Bool_t
double Double_t
const Bool_t kTRUE
virtual Bool_t IsType(const Char_t *typ) const
Definition: KVBase.h:178
const Char_t * GetType() const
Definition: KVBase.h:170
Base class for detector geometry description, interface to energy-loss calculations.
Definition: KVDetector.h:121
virtual void SetEResAfterDetector(Double_t e)
Definition: KVDetector.h:576
virtual Double_t GetDeltaEFromERes(Int_t Z, Int_t A, Double_t Eres)
virtual Double_t GetCorrectedEnergy(KVNucleus *, Double_t e=-1., Bool_t transmission=kTRUE)
Definition: KVDetector.cpp:949
Path taken by particles through multidetector geometry.
const KVSeqCollection * GetIDTelescopes() const
Information on relative positions of detectors & particle trajectories.
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.)
void DoCalibration(KVReconstructedNucleus *PART)
bool DoCoherencyAnalysis(KVReconstructedNucleus &PART)
Coherency analysis for backward rings 10-17 of INDRA.
Reconstruct particles in INDRA groups with etalon telescopes.
Bool_t CoherencyEtalons(KVReconstructedNucleus &PART)
Called by Identify() for particles stopping in etalon modules of Rings 10-17.
void DoCalibration(KVReconstructedNucleus *PART)
Calibration of particle stopping in etalon modules.
Bool_t CalculateSi75DEFromResidualEnergy(Double_t ERES, KVDetector *si75, KVReconstructedNucleus *n)
Bool_t CalculateSiLiDEFromResidualEnergy(Double_t ERES, KVDetector *sili, KVReconstructedNucleus *n)
bool DoCoherencyAnalysis(KVReconstructedNucleus &PART)
KVReconstructedNucleus * ReconstructTrajectory(const KVGeoDNTrajectory *traj, const KVGeoDetectorNode *node)
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
void SetComment(const Char_t *c)
Int_t Z
Z of particle found (if Zident==kTRUE)
Int_t IDquality
specific quality code returned by identification procedure
Int_t IDcode
a general identification code for this type of identification
Bool_t GetBoolValue(const Char_t *name) const
Bool_t IsIsotope(Int_t Z, Int_t A) const
Definition: KVNucleus.h:336
KVNameValueList * GetParameters() const
Definition: KVParticle.h:735
void SetParameter(const Char_t *name, ValType value) const
Definition: KVParticle.h:739
void SetEnergy(Double_t e)
Definition: KVParticle.h:560
Nuclei reconstructed from data measured by a detector array ,.
virtual Int_t GetECode() const
KVIdentificationResult * GetIdentificationResult(Int_t i)
const KVReconNucTrajectory * GetReconstructionTrajectory() const
virtual Int_t GetIDCode() const
KVDetector * GetStoppingDetector() const
void SetDetector(int i, KVDetector *);
KaliVeda extensions to ROOT collection classes.
virtual TObject * FindObjectByType(const Char_t *) const
const Int_t n
Double_t Abs(Double_t d)