KaliVeda
Toolkit for HIC analysis
KVINDRAReconNuc.cpp
1 /***************************************************************************
2 $Id: KVINDRAReconNuc.cpp,v 1.61 2009/04/03 14:28:37 franklan Exp $
3  kvdetectedparticle.cpp - description
4  -------------------
5  begin : Thu Oct 10 2002
6  copyright : (C) 2002 by J.D. Frankland
7  email : frankland@ganil.fr
8  ***************************************************************************/
9 
10 /***************************************************************************
11  * *
12  * This program is free software; you can redistribute it and/or modify *
13  * it under the terms of the GNU General Public License as published by *
14  * the Free Software Foundation; either version 2 of the License, or *
15  * (at your option) any later version. *
16  * *
17  ***************************************************************************/
18 
19 #include "KVDataSet.h"
20 #include "KVINDRAReconNuc.h"
21 #include "KVIDTelescope.h"
22 #include "KVChIo.h"
23 #include "KVMultiDetArray.h"
24 #include "KVSilicon.h"
25 #include "KVCsI.h"
26 /******* for Identify **********/
27 #include "KVIDGCsI.h"
28 
29 #include <KVIDGChIoSi.h>
30 
31 #include <KVIDGChIoSi.h>
32 
33 using namespace std;
34 
36 
37 
38 
39 
42 
44 {
45  //default initialisations
46  if (gDataSet)
47  SetMassFormula(UChar_t(gDataSet->GetDataSetEnv("KVINDRAReconNuc.MassFormula", Double_t(kEALMass))));
48  fCoherent = kTRUE;
49  fPileup = kFALSE;
50  fUseFullChIoEnergyForCalib = kTRUE;
51  fECsI = fESi = fEChIo = fESi75 = fESiLi = 0.;
52  fCorrectCalib = kFALSE;
53  fPileupChIo = kFALSE;
54  fPileupSi75 = kFALSE;
55  fPileupSiLi = kFALSE;
56  fIncludeEtalonsInCalibration = kFALSE;
57 }
58 
59 
60 
63 
65 {
66  //default ctor
67  init();
68 }
69 
70 
71 
74 
76  KVReconstructedNucleus(), fCodes()
77 {
78  //copy ctor
79  init();
80 #if ROOT_VERSION_CODE >= ROOT_VERSION(3,4,0)
81  obj.Copy(*this);
82 #else
83  ((KVINDRAReconNuc&) obj).Copy(*this);
84 #endif
85 }
86 
87 
88 
91 
92 KVINDRAReconNuc::~KVINDRAReconNuc()
93 {
94  //dtor
95  init();
96  fCodes.Clear();
97 }
98 
99 
100 #if ROOT_VERSION_CODE >= ROOT_VERSION(3,4,0)
101 
103 
105 #else
107 #endif
108 {
109  KVINDRAReconNuc& robj = (KVINDRAReconNuc&)obj;
110  fCodes.Copy(robj.fCodes);
111  robj.fCoherent = fCoherent;
112  robj.fPileup = fPileup;
113  robj.fUseFullChIoEnergyForCalib = fUseFullChIoEnergyForCalib;
114  robj.fECsI = fECsI;
115  robj.fESi = fESi;
116  robj.fEChIo = fEChIo;
117  robj.fESi75 = fESi75;
118  robj.fESiLi = fESiLi;
119  robj.fCorrectCalib = fCorrectCalib;
121  robj.fPileupChIo = fPileupChIo;
122  robj.fPileupSiLi = fPileupSiLi;
123  robj.fPileupSi75 = fPileupSi75;
124  robj.fIncludeEtalonsInCalibration = fIncludeEtalonsInCalibration;
126 }
127 
128 
129 
130 
132 
133 void KVINDRAReconNuc::Print(Option_t* option) const
134 {
135 
137 
138  cout << "KVINDRAReconNuc: fRing=" << GetRingNumber() << " fModule=" <<
139  GetModuleNumber() << endl;
140  if (IsIdentified()) {
141  if (GetRingNumber() < 10) {
142  cout << " -- RESULTS OF COHERENCY TESTS (RINGS 1-9) -- " << endl;
143  if (fCoherent) cout << " CsI-R/L & Si-CsI identifications COHERENT" << endl;
144  else cout << " CsI-R/L & Si-CsI identifications NOT COHERENT" << endl;
145  if (fPileup) cout << " Si energy loss indicates PILEUP" << endl;
146  else cout << " Si energy loss indicates single particle" << endl;
147  if (GetRingNumber() > 1) {
148  if (fUseFullChIoEnergyForCalib) cout << " ChIo-Si identification indicates single particle" << endl;
149  else cout << " ChIo-Si identification indicates MULTIPLE CHIO CONTRIBUTIONS" << endl;
150  }
151  cout << endl;
152  }
153  else {
154  cout << " -- RESULTS OF COHERENCY TESTS (RINGS 10-17) -- " << endl;
155  if (fIncludeEtalonsInCalibration) cout << " WITH Etalon telescopes included in particle trajectory" << endl;
156  else cout << " WITHOUT etalon telescopes included in particle trajectory" << endl;
157  if (fPileupChIo) {
158  cout << " Analysis indicates PILEUP in ChIo" << endl;
159  }
160  if (fPileupSi75) {
161  cout << " Analysis indicates PILEUP in Si75" << endl;
162  }
163  if (fPileupSiLi) {
164  cout << " Analysis indicates PILEUP in SiLi" << endl;
165  }
166  if (fUseFullChIoEnergyForCalib) cout << " ChIo energy assumed due solely to this particle" << endl;
167  else cout << " ChIo energy contribution calculated assuming MULTIPLE CHIO CONTRIBUTIONS" << endl;
168  }
169  cout << " =======> ";
170  cout << " Z=" << GetZ() << " A=" << ((KVINDRAReconNuc*) this)->
171  GetA();
172  if (((KVINDRAReconNuc*) this)->IsAMeasured()) cout << " Areal=" << ((KVINDRAReconNuc*) this)->GetRealA();
173  else cout << " Zreal=" << GetRealZ();
174  cout << endl << " Identification code = " << ((KVINDRAReconNuc*) this)->
175  GetCodes().GetIDStatus() << endl;
176  }
177  else {
178  cout << "(unidentified)" << endl;
179  }
180  if (IsCalibrated()) {
181  cout << " Total Energy = " << GetEnergy() << " MeV, Theta=" << GetTheta() << " Phi=" << GetPhi() << endl;
182  if (GetRingNumber() < 10) {
183  if (GetRingNumber() > 1) {
184  cout << " EChIo = " << TMath::Abs(fEChIo) << " MeV";
185  if (fEChIo < 0) cout << " (calculated)";
186  cout << endl;
187  }
188  cout << " ESi = " << TMath::Abs(fESi) << " MeV";
189  if (fESi < 0) cout << " (calculated)";
190  cout << endl;
191  cout << " ECsI = " << TMath::Abs(fECsI) << " MeV";
192  if (fECsI < 0) cout << " (calculated)";
193  cout << endl;
194  }
195  else {
196  cout << " EChIo = " << TMath::Abs(fEChIo) << " MeV";
197  if (fEChIo < 0) cout << " (calculated)";
198  cout << endl;
200  cout << " ESi75 = " << TMath::Abs(fESi75) << " MeV";
201  if (fESi75 < 0) cout << " (calculated)";
202  cout << endl;
203  cout << " ESiLi = " << TMath::Abs(fESiLi) << " MeV";
204  if (fESiLi < 0) cout << " (calculated)";
205  cout << endl;
206  }
207  cout << " ECsI = " << TMath::Abs(fECsI) << " MeV";
208  if (fECsI < 0) cout << " (calculated)";
209  cout << endl;
210  }
211  cout << " Target energy loss correction : " << GetTargetEnergyLoss() << " MeV" << endl;
212  cout << " Calibration code = " << ((KVINDRAReconNuc*) this)->
213  GetCodes().GetEStatus() << endl;
214  }
215  else {
216  cout << "(uncalibrated)" << endl;
217  }
218 // if (!IsIdentified()) {
219  cout << "Analysis : ";
220  switch (GetStatus()) {
221  case 0:
222  cout <<
223  "Particle alone in group, or identification independently of other"
224  << endl;
225  cout << "particles in group is directly possible." << endl;
226  break;
227 
228  case 1:
229  cout <<
230  "Particle reconstructed after identification of others in group"
231  << endl;
232  cout <<
233  "and subtraction of their calculated energy losses in ChIo."
234  << endl;
235  break;
236 
237  case 2:
238  cout <<
239  "Particle identification estimated after arbitrary sharing of"
240  << endl;
241  cout <<
242  "energy lost in ChIo between several reconstructed particles."
243  << endl;
244  break;
245 
246  case 3:
247  cout <<
248  "Particle stopped in first stage of telescope. Estimation of minimum Z."
249  << endl;
250  break;
251 
252  default:
253  cout << GetStatus() << endl;
254  break;
255  }
256  //}
257  cout <<
258  "-------------------------------------------------------------------------------"
259  << endl;
260 }
261 
262 
263 
264 
267 
269 {
270  //reset nucleus' properties
272  init();
273  fCodes.Clear();
274 }
275 
276 
277 
281 
283 {
284  //Return pointer to the ChIo the particle passed through.
285  //Pointer is null if not.
286  KVChIo* chio = (KVChIo*) GetDetector("CI");
287  return chio;
288 }
289 
290 
291 
295 
297 {
298  //Return pointer to the Silicon the particle passed through.
299  //Pointer is null if not.
300  KVSilicon* chio =
301  (KVSilicon*) GetDetector("SI");
302  return chio;
303 }
304 
305 
306 
310 
312 {
313  //Return pointer to the Silicon-75 the particle passed through.
314  //Pointer is null if not.
315  KVSi75* chio =
316  (KVSi75*) GetDetector("SI75");
317  return chio;
318 }
319 
320 
321 
325 
327 {
328  //Return pointer to the Silicon-Lithium the particle passed through.
329  //Pointer is null if not.
330  KVSiLi* chio =
331  (KVSiLi*) GetDetector("SILI");
332  return chio;
333 }
334 
335 
336 
340 
342 {
343  //Return pointer to the CsI the particle passed through.
344  //Pointer is null if not.
345  KVCsI* csi = (KVCsI*) GetDetector("CSI");
346  return csi;
347 }
348 
349 
350 
351 
354 
356 {
357  //Returns kTRUE if particle stopped in ChIo detector
358 
359  if (!strcmp(GetStoppingDetector()->GetType(), "CI")) {
360  return kTRUE;
361  }
362  else {
363  return kFALSE;
364  }
365 }
366 
367 
368 
371 
373 {
374  //Returns kTRUE if particle stopped in Si detector
375 
376  if (!strcmp(GetStoppingDetector()->GetType(), "SI")) {
377  return kTRUE;
378  }
379  else {
380  return kFALSE;
381  }
382 }
383 
384 
387 
389 {
390  //Returns kTRUE if particle stopped in Si75 detector
391 
392  if (!strcmp(GetStoppingDetector()->GetType(), "SI75")) {
393  return kTRUE;
394  }
395  else {
396  return kFALSE;
397  }
398 }
399 
400 
403 
405 {
406  //Returns kTRUE if particle stopped in Si detector
407 
408  if (!strcmp(GetStoppingDetector()->GetType(), "SILI")) {
409  return kTRUE;
410  }
411  else {
412  return kFALSE;
413  }
414 }
415 
416 
417 
420 
422 {
423  //Returns kTRUE if particle stopped in CsI detector
424 
425  if (!strcmp(GetStoppingDetector()->GetType(), "CSI")) {
426  return kTRUE;
427  }
428  else {
429  return kFALSE;
430  }
431 }
432 
433 
434 
452 
453 Int_t KVINDRAReconNuc::GetIDSubCode(const Char_t* id_tel_type) const
454 {
455  //Returns subcode/status code from identification performed in ID telescope of given type.
456  //i.e. to obtain CsI R-L subcode use GetIDSubCode("CSI_R_L").
457  //
458  //The meaning of the subcodes is defined in the corresponding KVIDTelescope class description
459  //i.e. for CsI R-L, look at KVIDCsI.
460  //
461  //The subcode is set for any attempted identification, not necessarily that which eventually
462  //leads to the definitive identification of the particle.
463  //i.e. in the example of the CsI R-L subcode, the particle in question may in fact be identified
464  //by a Si-CsI telescope, because the CsI identification routine returned e.g. KVIDGCsI::kICODE7
465  //(a gauche de la ligne fragment, Z est alors un Zmin et le plus probable).
466  //
467  //calling GetIDSubCode() with no type returns the identification subcode corresponding
468  //to the identifying telescope (whose pointer is given by GetIdentifyingTelescope()).
469  //
470  //If no subcode exists (identification in given telescope type was not attempted, etc.) value returned is -1
471 
472  KVIdentificationResult* ir = 0;
473  if (strcmp(id_tel_type, "")) ir = GetIdentificationResult(id_tel_type);
475  if (!ir) return -1;
476  return ir->IDquality;
477  //return GetIDSubCode(id_tel_type,const_cast <KVINDRAReconNuc *>(this)->GetCodes().GetSubCodes());
478 }
479 
480 
481 
495 
497  id_tel_type) const
498 {
499  //Returns explanatory message concerning identification performed in ID telescope of given type.
500  //(see GetIDSubCode())
501  //
502  //The subcode is set for any attempted identification, not necessarily that which eventually
503  //leads to the definitive identification of the particle.
504  //
505  //calling GetIDSubCodeString() with no type returns the identification subcode message corresponding
506  //to the identifying telescope (whose pointer is given by GetIdentifyingTelescope()).
507  //
508  //In case of problems:
509  // no ID telescope of type 'id_tel_type' : "No identification attempted in id_tel_type"
510  // particle not identified : "Particle unidentified. Identifying telescope not set."
511 
512  KVIdentificationResult* ir = 0;
513  if (strcmp(id_tel_type, "")) ir = GetIdentificationResult(id_tel_type);
515  if (!ir) {
516  if (strcmp(id_tel_type, ""))
517  return Form("No identification attempted in %s", id_tel_type);
518  else
519  return
520  Form("Particle unidentified. Identifying telescope not set.");
521  }
522  return ir->GetComment();
523 }
524 
525 
526 
527 
536 
538 {
539  // we check that the ChIo contribution is sane:
540  // if no other particles hit this group, the Z given by the ChIoSi
541  // must be <= the Z found from Si-CsI or CsI-RL identification
542  //
543  // in this case the measured energy loss of the ChIo can be solely attributed to this particle
544  // and we return kTRUE;
545 
546  // ChIo was hit by more than one particle in group
547  if (GetChIo() && GetChIo()->GetNHits() > 1) {
548  return kFALSE;
549  }
550 
552  if (!IDchiosi->IDattempted) {
553  // no ChIo-Si identification ? assume coherency ?
554  return kTRUE;
555  }
556 
557  // if we have a successful ChIo-Si id with a Z > Z given by CsI or Si-CsI id,
558  // then we consider that there is a pile-up in the ChIo
559  // note that we consider Z_ChIoSi = 1 to mean the ChIo is in the pedestal i.e. nothing seen
560  // we also require the chio-si identification to be above the punch-through line
561  if (IDchiosi->IDOK && IDchiosi->Z > 1 && IDchiosi->IDquality != KVIDGChIoSi::k_BelowPunchThrough && IDchiosi->Z > theID.Z) {
562  return kFALSE;
563  }
564 
565  return kTRUE;
566 }
567 
568 
569 
570 
583 
585 {
586  // Called by Identify() for particles stopping in CsI detectors on rings 1-9,
587  // which have a Silicon detector just in front of them.
588  //
589  // coherent = kFALSE if CsI-R/L and Si-CsI identifications are not coherent.
590  // this is a warning, the CsI identification is kept, either the Si signal
591  // was not good (particle hitting dead zone), or it actually corresponds
592  // to two particles reaching the CsI at the same time
593  // pileup = kTRUE means that the particle identified in CsI-R/L is correct,
594  // and there is probably a second particle which stopped in the silicon
595  // detector at the same time, to be identified in ChIo-Si after
596  // subtraction of the Silicon contribution
597 
600  fCoherent = kTRUE;
601  fPileup = kFALSE;
602 
603  // Unsuccessful/no CsI id attempt with successful Si-CsI id ?
604  // Then use Si-CsI identification result
605  if (IDsicsi->IDOK && !IDcsi->IDOK) {
606  theID = *IDsicsi;
607  return kTRUE;
608  }
609 
610  // check coherency of CsI-R/L and Si-CsI identifications
611  if (IDcsi->IDOK) {
612  // gammas
613  if (IDcsi->IDcode == KVINDRACodeMask::kIDCode0) {
614  theID = *IDcsi;
615  return kTRUE;
616  }
617  // Neutrons have no energy loss in Si detector (pedestal), have a reaction in the CsI and create a Z=1
618  // or Z=2 which is identified in CsI R-L, while they show up in Si-CsI maps as a horizontal
619  // band around the Si pedestal for low energies (energies where proton dE is significantly larger than
620  // the pedestal).
621  if ((IDcsi->Z == 1 || IDcsi->Z == 2) && GetSi()) {
623  // no explicit treatment of 'neutron-like' particles with a cut in Si-CsI id grid
624  // First we check that we are in the domain where proton dE can be distinguished from pedestal.
625  // If so, if the measured dE is below [ped + factor*(dE_exp - ped)], then we label the particle as a neutron.
626  // 'factor' depends on the Si-CsI telescope: if it has mass identification, factor=0.3; if not, factor=0.1
627  // (these empirical values correspond to 5th campaign data)
629  if (idt) {
630  Double_t ped = idt->GetPedestalY();
631  Int_t status;
632  Double_t dE_exp = idt->GetMeanDEFromID(status, 1, 1);
633  if (status == KVIDTelescope::kMeanDE_OK) { // proton/Z=1 line exists, and we are in its energy range
634  if (dE_exp > ped + 5.) { // arbitrary choice, must have expected dE at least 5 channels above pedestal
635 
636  // if Si-CsI has no isotopic identification, reduce factor
637  Double_t factor = (idt->HasMassID() ? 0.3 : 0.1);
638  if (idt->GetIDMapY() < (ped + factor * (dE_exp - ped))) {
639  theID = *IDsicsi;
640  theID.IDOK = kTRUE;
641  theID.Zident = kTRUE;
642  theID.Aident = kTRUE;
643  theID.Z = 0;
644  theID.A = 1;
645  theID.IDcode = KVINDRACodeMask::kIDCode1; // general code for neutrons
646  return kTRUE;
647  }
648  }
649  }
650  }
651  }
653  // explicit treatment of 'neutron-like' particles with a cut in Si-CsI id grid
654  theID = *IDsicsi;
655  theID.IDOK = kTRUE;
656  theID.Zident = kTRUE;
657  theID.Aident = kTRUE;
658  theID.Z = 0;
659  theID.A = 1;
660  theID.IDcode = KVINDRACodeMask::kIDCode1; // general code for neutrons
661  return kTRUE;
662  }
663  }
664 
665  // We check the coherency of the mass and charge identifications
666  // If a successful Si-CsI identification is available we check:
667  // if Si-CsI gives A & Z - must have same Z, A within +/-1 unit
668  // if Z or A smaller => incoherency : pile-up of two particles in CsI ?
669  // or bad signal from Si detector (dead zones) ?
670  // if Z or A larger, CsI identification is good,
671  // assume another particle stopped in Si (identify in ChIo-Si)
672  // if Si-CsI gives just Z - must have same Z
673  // if Z smaller => incoherency : pile-up of two particles in CsI ?
674  // or bad signal from Si detector (dead zones) ?
675  // if Z larger => CsI identification is good,
676  // assume another particle stopped in Si (identify in ChIo-Si)
677  //
678  // If CsI identification gives code KVIDGCsI::kICode1 ou KVIDGCsI::kICode3 and the
679  // Si-CsI gives the same Z but A = Acsi + 1, we use the Si-CsI identification.
680  //
681  // If CsI identification gives code KVIDGCsI::kICode2 ou KVIDGCsI::kICode3 and the
682  // Si-CsI gives the same Z but A = Acsi - 1, we use the Si-CsI identification.
683  //
684  // N.B. if CsI-R/L identification gives "8Be" (2 alpha particles) then there are two correct possibilities:
685  // 1) Si-CsI identification gives 7Li => CsI identification is correct ("8Be")
686  // 2) Si-CsI identification gives 8He => the particle is 8He (falls on same R/L line as 2*alpha)
687  // Seeing the very low statistics for 8He compared to 8Be/2alpha, we assume that if Si-CsI id
688  // gives something above 8He it is either incoherent (below 7Li) or 8Be + something else in ChIo-Si
689  // (above 7Li).
690  if (IDsicsi->IDOK) {
691  theID = *IDcsi;
692  Int_t Zref = IDcsi->Z;
693  Int_t Aref = IDcsi->A;
694  if (IDsicsi->Aident) { // Si-CsI provides mass identification
695 
696  if (IDcsi->Z == 4 && IDcsi->A == 8) {
697  // traitement special 8Be
698  // if sicsi => 7Li, it is 8Be (2alpha)
699  // if sicsi => 8He, it is 8He
700  if (IDsicsi->Z < 2 || (IDsicsi->Z == 2 && IDsicsi->A < 7)) {
701  fCoherent = kFALSE;
702  IDsicsi->SetComment("CsI-R/L & Si-CsI identifications not coherent");
703  return kTRUE;
704  }
705  else if (IDsicsi->Z == 2 && IDsicsi->A > 6 && IDsicsi->A < 10) {
706  // accept helium-7,8,9 as 8He
707  theID = *IDsicsi;
708  return kTRUE;
709  }
710  else if ((IDsicsi->Z == 2 && IDsicsi->A > 9) || (IDsicsi->Z == 3 && IDsicsi->A < 6)) {
711  fCoherent = kFALSE;
712  IDsicsi->SetComment("CsI-R/L & Si-CsI identifications not coherent");
713  return kTRUE;
714  }
715  else if (IDsicsi->Z == 3 && IDsicsi->A > 5 && IDsicsi->A < 9) {
716  // accept lithium-6,7,8 as 7Li
717  return kTRUE;
718  }
719  else if ((IDsicsi->Z == 3 && IDsicsi->A > 8) || IDsicsi->Z > 3) {
720  fPileup = kTRUE;
721  IDsicsi->SetComment("Second particle stopping in Si, identification ChIo-Si required");
722  return kTRUE;
723  }
724  }
725  // if CsI says A could be bigger and Si-CsI gives same Z and A+1, use Si-CsI
726  if ((IDsicsi->Z == Zref) && (IDsicsi->A == (Aref + 1))
727  && (IDcsi->IDquality == KVIDGCsI::kICODE1 || IDcsi->IDquality == KVIDGCsI::kICODE3)) {
728  theID = *IDsicsi;
729  return kTRUE;
730  }
731  // if CsI says A could be smaller and Si-CsI gives same Z and A-1, use Si-CsI
732  if ((IDsicsi->Z == Zref) && (IDsicsi->A == (Aref - 1))
733  && (IDcsi->IDquality == KVIDGCsI::kICODE2 || IDcsi->IDquality == KVIDGCsI::kICODE3)) {
734  theID = *IDsicsi;
735  return kTRUE;
736  }
737  // everything else - Z must be same, A +/- 1 unit
738  if (IDsicsi->Z == Zref && TMath::Abs(IDsicsi->A - Aref) < 2) {
739  return kTRUE;
740  }
741  else if (IDsicsi->Z < Zref || (IDsicsi->Z == Zref && IDsicsi->A < (Aref - 1))) {
742  fCoherent = kFALSE;
743  IDsicsi->SetComment("CsI-R/L & Si-CsI identifications not coherent");
744  return kTRUE;
745  }
746  else if (IDsicsi->Z > Zref || (IDsicsi->Z == Zref && IDsicsi->A > (Aref + 1))) {
747  fPileup = kTRUE;
748  IDsicsi->SetComment("Second particle stopping in Si, identification ChIo-Si required");
749  return kTRUE;
750  }
751  }
752  else { // only Z identification from Si-CsI
753  if (IDcsi->Z == 4 && IDcsi->A == 8) {
754  // traitement special 8Be
755  // we ask for Z to be equal 3 in SiCsI, but with no mass identification
756  // we do not try for 8He identification
757  if (IDsicsi->Z < 3) {
758  fCoherent = kFALSE;
759  IDsicsi->SetComment("CsI-R/L & Si-CsI identifications not coherent");
760  return kTRUE;
761  }
762  else if (IDsicsi->Z == 3) {
763  return kTRUE;
764  }
765  else {
766  fPileup = kTRUE;
767  IDsicsi->SetComment("Second particle stopping in Si, identification ChIo-Si required");
768  return kTRUE;
769  }
770  }
771  // everything else
772  if (IDsicsi->Z == Zref) {
773  return kTRUE;
774  }
775  else if (IDsicsi->Z < Zref) {
776  fCoherent = kFALSE;
777  IDsicsi->SetComment("CsI-R/L & Si-CsI identifications not coherent");
778  return kTRUE;
779  }
780  else {
781  fPileup = kTRUE;
782 
783  IDsicsi->SetComment("Second particle stopping in Si, identification ChIo-Si required");
784  return kTRUE;
785  }
786  }
787  }
788  // in all other cases accept CsI identification
789  theID = *IDcsi;
790  return kTRUE;
791  }
792  return kFALSE;
793 }
794 
795 
796 
797 
806 
808 {
809  // Called by Identify() for particles stopping in CsI detectors on rings 10-17,
810  // which have a ChIo detector just in front of them.
811  //
812  // fPileupChIo = kTRUE if ChIo-CsI identification gives Z >> CsI-R/L identification
813  // this means that the particle identified in CsI-R/L is correct,
814  // and there is probably a second particle which stopped in the ChIo
815  // detector at the same time (will be added as a Zmin/code5)
816 
818  KVIdentificationResult* IDcicsi = GetIdentificationResult("CI_CSI");
819 
822 
823  // Unsuccessful/no CsI id attempt with successful ChIo-CsI id ?
824  // Then use ChIo-CsI identification result
825  if (IDcsi && !IDcsi->IDOK) {
826  if (IDcicsi && IDcicsi->IDOK) {
827  theID = *IDcicsi;
828  return kTRUE;
829  }
830  }
831 
832  // check coherency of CsI-R/L and ChIo-CsI identifications
833  if (IDcsi && IDcsi->IDOK) {
834  // gammas
835  if (IDcsi->IDcode == KVINDRACodeMask::kIDCode0) {
836  theID = *IDcsi;
837  return kTRUE;
838  }
839 
840  // We check the coherency of the identifications
841  // Because ChIo-Csi identification is not of very high quality (compared to CsI R-L),
842  // we only check that the Z given by ChIo-CsI is < Zref+1
843  // If not, we can suspect the presence of another particle in the ChIo
844 
845  if (IDcicsi && IDcicsi->IDOK) {
846  Int_t Zref = IDcsi->Z;
847  if (IDcicsi->Z > (Zref + 1) && fUseFullChIoEnergyForCalib
848  && !fPileupSi75) { // do not add pile-up if one already suspected in Si75
849  fPileupChIo = kTRUE;
850  IDcicsi->SetComment("Possible pile-up in ChIo");
851  }
852  }
853 
854  // in all other cases accept CsI identification
855  theID = *IDcsi;
856  return kTRUE;
857  }
858  return kFALSE;
859 }
860 
861 
862 
865 
867 {
868  // Called by Identify() for particles stopping in etalon modules of Rings 10-17.
869 
870  KVIdentificationResult* IDcsi, *IDsilicsi, *IDsi75sili, *IDcisi75, *IDcicsi;
871  IDcsi = IDsilicsi = IDsi75sili = IDcisi75 = IDcicsi = 0;
872  if (StoppedInCsI()) {
873  IDcsi = GetIdentificationResult("CSI_R_L");
874  IDcicsi = GetIdentificationResult("CI_CSI");
875  IDsilicsi = GetIdentificationResult("SILI_CSI");
876  }
877  IDsi75sili = GetIdentificationResult("SI75_SILI");
878  IDcisi75 = GetIdentificationResult("CI_SI75");
881 
882  Bool_t haveCsI = IDcsi && IDcsi->IDOK;
883  Bool_t haveSiLiCsI = IDsilicsi && IDsilicsi->IDOK;
884  Bool_t haveChIoCsI = IDcicsi && IDcicsi->IDOK;
885  Bool_t haveSi75SiLi = IDsi75sili && IDsi75sili->IDOK;
886  Bool_t haveChIoSi75 = IDcisi75 && IDcisi75->IDOK;
887 
888  // Etalon telescope Si75/SiLi not concerned, only ChIo and CsI.
889  // Use standard coherency for rings 10-17
890  if ((!GetSiLi() || !GetSiLi()->Fired("Pany")) && (!GetSi75() || !GetSi75()->Fired("Pany")))
891  return CoherencyChIoCsI(theID);
892  if (haveCsI && !haveSiLiCsI && !haveSi75SiLi)
893  return CoherencyChIoCsI(theID);
894 
895  // Treat cases where particle hit etalon telescope
896  if (StoppedInCsI()) {
897  if (haveCsI) {
898  // gammas
899  if (IDcsi->IDcode == KVINDRACodeMask::kIDCode0) {
900  theID = *IDcsi;
901  return kTRUE;
902  }
903 
904  // successful CsI identification
905  // check (again) if particle passed through SiLi
906  // if SiLi did not fire but Si75 did, then we assume this particle
907  // just passed through ChIo-CsI while another particle stopped in Si75
908  if (!GetSiLi()->Fired("Pany") && GetSi75()->Fired("all")) {
909  fPileupSi75 = kTRUE; // need to create particle in ChIo-Si75
910  fUseFullChIoEnergyForCalib = kFALSE; // calculate ChIo energy for this particle
911  return CoherencyChIoCsI(theID);
912  }
913  theID = *IDcsi;
914  if (haveSi75SiLi) {
915  // check for heavy fragment in Si75-SiLi
916  if (IDsi75sili->Z > theID.Z) {
917  if (haveChIoSi75) {
918  // check we don't have a better identification in ChIo-Si75
919  if (IDcisi75->IDquality < IDsi75sili->IDquality && IDcisi75->Z > theID.Z) {
920  fPileupSi75 = kTRUE;
921  IDcisi75->SetComment("CsI identification with another particle stopped in Si75");
922  fUseFullChIoEnergyForCalib = kFALSE; // calculate ChIo energy for this particle
923  }
924  else {
925  fPileupSiLi = kTRUE;
926  IDsi75sili->SetComment("CsI identification with another particle stopped in SiLi");
927  fUseFullChIoEnergyForCalib = kFALSE; // calculate ChIo energy for this particle
928  }
929  }
930  }
931  }
932  else if (haveChIoSi75) {
933  // check for heavy fragment in ChIo-Si75
934  if (IDcisi75->Z > theID.Z) {
935  fPileupSi75 = kTRUE;
936  IDcisi75->SetComment("CsI identification with another particle stopped in Si75");
937  fUseFullChIoEnergyForCalib = kFALSE; // calculate ChIo energy for this particle
938  }
939  }
940  return kTRUE;
941  }
942  else if (haveSiLiCsI) {
943  theID = *IDsilicsi;
944  if (haveChIoSi75) {
945  // check for heavy fragment in ChIo-Si75
946  if (IDcisi75->Z > theID.Z) {
947  fPileupSi75 = kTRUE;
948  IDcisi75->SetComment("CsI identification with another particle stopped in Si75");
949  fUseFullChIoEnergyForCalib = kFALSE; // calculate ChIo energy for this particle
950  }
951  }
952  return kTRUE;
953  }
954  else if (haveChIoCsI) {
955  theID = *IDcicsi;
956  // fragment identified in ChIo-CsI
957  // therefore it did not cross the etalon telescopes
958  // (only Z=1 & 2 pass through SiLi)
960  return kTRUE;
961  }
962  }
963  else if (StoppedInSiLi()) {
964  if (haveSi75SiLi) {
965  theID = *IDsi75sili;
966  // check ChIo-Si75 id is coherent (either no id or Z<=this one)
967  if (haveChIoSi75) {
968  if (IDcisi75->Z > theID.Z) fPileupChIo = kTRUE;
969  }
970  return kTRUE;
971  }
972  else if (haveChIoSi75) {
973  theID = *IDcisi75;
974  return kTRUE;
975  }
976  }
977  else if (StoppedInSi75()) { // MFR march 2014 SiLi is not the real stopping detector
978  if (haveChIoSi75) {
979  theID = *IDcisi75;
980  return kTRUE;
981  } // end MFR march 2014
982  }
983 
984  return kFALSE;
985 }
986 
987 
988 
1007 
1009 {
1010  // INDRA-specific particle identification.
1011  // Here we attribute the Veda6-style general identification codes depending on the
1012  // result of KVReconstructedNucleus::Identify and the subcodes from the different
1013  // identification algorithms:
1014  // If the particle's mass A was NOT measured, we make sure that it is calculated
1015  // from the measured Z using the mass formula defined by default
1016  //
1017  //IDENTIFIED PARTICLES
1018  //Identified particles with ID code = 2 with subcodes 4 & 5
1019  //(masse hors limite superieure/inferieure) are relabelled
1020  //with kIDCode10 (identification entre les lignes CsI)
1021  //
1022  //UNIDENTIFIED PARTICLES
1023  //Unidentified particles receive the general ID code for non-identified particles (kIDCode14)
1024  //EXCEPT if their identification in CsI R-L gave subcodes 6 or 7
1025  //(Zmin) then they are relabelled "Identified" with IDcode = 9 (ident. incomplete dans CsI ou Phoswich (Z.min))
1026  //Their "identifying" telescope is set to the CsI ID telescope
1027 
1028  Obsolete("Identify", "1.13", "1.15");
1029 
1030 // KVReconstructedNucleus::Identify();
1031 
1032 // KVIdentificationResult partID;
1033 // Bool_t ok = kFALSE;
1034 
1035 // // INDRA coherency treatment
1036 // if (GetRingNumber() < 10) {
1037 // if (StoppedInCsI()) {
1038 // // particles stopping in CsI detectors on rings 1-9
1039 // // check coherency of CsI-R/L and Si-CsI identifications
1040 // ok = CoherencySiCsI(partID);
1041 // // we check that the ChIo contribution is sane:
1042 // // if no other particles hit this group, the Z given by the ChIoSi
1043 // // must be <= the Z found from Si-CsI or CsI-RL identification
1044 
1045 // //if(fCoherent && !fPileup)
1046 // fUseFullChIoEnergyForCalib = CoherencyChIoSiCsI(partID);
1047 // }
1048 // else {
1049 // // particle stopped in Si (=> ChIo-Si) or ChIo (=> Zmin)
1050 // Int_t id_no = 1;
1051 // KVIdentificationResult* pid = GetIdentificationResult(id_no);
1052 // while (pid->IDattempted) {
1053 // if (pid->IDOK) {
1054 // ok = kTRUE;
1055 // partID = *pid;
1056 // break;
1057 // }
1058 // ++id_no;
1059 // pid = GetIdentificationResult(id_no);
1060 // }
1061 // fUseFullChIoEnergyForCalib = !(GetChIo() && GetChIo()->GetNHits() > 1);
1062 // }
1063 // }
1064 // else {
1065 // //identification couronne 10 a 17
1066 // //Arret dans les CsI, coherence entre identification CsI RL et ChIo CsI
1067 
1068 // // if particle is alone in group, we can in principle attribute the ChIo energy
1069 // // to the energy lost by this particle alone
1070 // fUseFullChIoEnergyForCalib = !(GetChIo() && GetChIo()->GetNHits() > 1);
1071 // if (StoppedInCsI()) {
1072 
1073 // if (GetSiLi() || GetSi75()) /* etalon module */
1074 // ok = CoherencyEtalons(partID);
1075 // else
1076 // ok = CoherencyChIoCsI(partID);
1077 
1078 // }
1079 // else if (StoppedInChIo()) {
1080 // // particle stopped in ChIo (=> Zmin)
1081 // Int_t id_no = 1;
1082 // KVIdentificationResult* pid = GetIdentificationResult(id_no);
1083 // while (pid->IDattempted) {
1084 // if (pid->IDOK) {
1085 // ok = kTRUE;
1086 // partID = *pid;
1087 // break;
1088 // }
1089 // ++id_no;
1090 // pid = GetIdentificationResult(id_no);
1091 // }
1092 // partID.Print();
1093 // }
1094 // else {
1095 // // particle stopped in SiLi or Si75 (etalon modules)
1096 // ok = CoherencyEtalons(partID);
1097 // }
1098 
1099 // }
1100 // if (ok) {
1101 // SetIsIdentified();
1102 // KVIDTelescope* idt = (KVIDTelescope*)GetIDTelescopes()->FindObjectByType(partID.GetType());
1103 // if (!idt) {
1104 // Warning("Identify", "cannot find ID telescope with type %s", partID.GetType());
1105 // GetIDTelescopes()->ls();
1106 // partID.Print();
1107 // }
1108 // SetIdentifyingTelescope(idt);
1109 // SetIdentification(&partID);
1110 // }
1111 
1112 // if (IsIdentified()) {
1113 
1114 // /******* IDENTIFIED PARTICLES *******/
1115 // if (GetIdentifyingTelescope()->InheritsFrom("KVIDCsI")) { /**** CSI R-L IDENTIFICATION ****/
1116 
1117 // //Identified particles with ID code = 2 with subcodes 4 & 5
1118 // //(masse hors limite superieure/inferieure) are relabelled
1119 // //with kIDCode10 (identification entre les lignes CsI)
1120 
1121 // Int_t csi_subid = GetIDSubCode();
1122 // if (csi_subid == KVIDGCsI::kICODE4 || csi_subid == KVIDGCsI::kICODE5) {
1123 // SetIDCode(kIDCode10);
1124 // }
1125 
1126 // }
1127 
1128 // }
1129 // else {
1130 
1131 // /******* UNIDENTIFIED PARTICLES *******/
1132 
1133 // /*** general ID code for non-identified particles ***/
1134 // SetIDCode(kIDCode14);
1135 
1136 // KVIDCsI* idtel = (KVIDCsI*)GetIDTelescopes()->FindObjectByType("CSI_R_L");
1137 // if (idtel) {
1138 // //Particles remaining unidentified are checked: if their identification in CsI R-L gave subcodes 6 or 7
1139 // //(Zmin) then they are relabelled "Identified" with IDcode = 9 (ident. incomplete dans CsI ou Phoswich (Z.min))
1140 // //Their "identifying" telescope is set to the CsI ID telescope
1141 // Int_t csi_subid = GetIDSubCode("CSI_R_L");
1142 // if (csi_subid == KVIDGCsI::kICODE6 || csi_subid == KVIDGCsI::kICODE7) {
1143 // SetIsIdentified();
1144 // SetIDCode(kIDCode9);
1145 // SetIdentifyingTelescope(idtel);
1146 // }
1147 // }
1148 
1149 // }
1150 }
1151 
1152 
1153 
1154 
1160 
1162 {
1163  // Calculate and set the energy of a (previously identified) reconstructed particle.
1164  // For particles in rings 10-17
1165  // For particles in rings 1-9, we use the results of the ChIo-Si-CsI coherency tests in order
1166  // to calculate their energy.
1167 
1168 
1169  if (GetRingNumber() <= 9)
1171  else
1173 
1174 
1175  SetIsCalibrated();
1176  //add correction for target energy loss - moving charged particles only!
1177  Double_t E_targ = 0.;
1178  if (GetZ() && GetEnergy() > 0) {
1179  E_targ = gMultiDetArray->GetTargetEnergyLossCorrection(this);
1180  SetTargetEnergyLoss(E_targ);
1181  }
1182  Double_t E_tot = GetEnergy() + E_targ;
1183  SetEnergy(E_tot);
1184  // set particle momentum from telescope dimensions (random)
1186  CheckCsIEnergy();
1187 
1188 }
1189 
1190 
1191 
1194 
1196 {
1197  // no calibration is performed for gammas
1199  return;
1200 }
1201 
1202 
1203 
1207 
1209 {
1210  // use energy of CsI calculated using the Z & A of the CsI identification
1211  // to calculate the energy deposited by the neutron
1213  KVNucleus tmp(IDcsi->Z, IDcsi->A);
1214  if (GetCsI() && GetCsI()->IsCalibrated()) {
1215  fECsI = GetCsI()->GetCorrectedEnergy(&tmp, -1., kFALSE);
1216  SetEnergy(fECsI);
1217  SetECode(KVINDRACodeMask::kECode2); // not a real energy measure
1218  }
1219  else {
1221  }
1222 }
1223 
1224 
1225 
1231 
1233 {
1234  // Beryllium-8 = 2 alpha particles of same energy
1235  // We halve the total light output of the CsI to calculate the energy of 1 alpha
1236  // Then multiply resulting energy by 2
1237  // Note: fECsI is -ve, because energy is calculated not measured
1238  Double_t half_light = GetCsI()->GetDetectorSignalValue("TotLight") * 0.5;
1239  KVNucleus tmp(2, 4);
1240  fECsI = -2.*GetCsI()->GetCorrectedEnergy(&tmp, half_light, kFALSE);
1242 }
1243 
1244 
1245 
1249 
1251 {
1252  // calculate fESi from fECsI
1253  // returns kTRUE if OK
1254  Double_t e0 = GetSi()->GetDeltaEFromERes(GetZ(), GetA(), TMath::Abs(fECsI));
1255  GetSi()->SetEResAfterDetector(TMath::Abs(fECsI));
1256  fESi = GetSi()->GetCorrectedEnergy(this, e0);
1257  if (fESi <= 0) {
1258  // can't calculate fESi from CsI energy - bad
1260  return kFALSE;
1261  }
1262  else {
1263  // calculated energy: negative
1264  fESi = -TMath::Abs(fESi);
1266  }
1267  return kTRUE;
1268 }
1269 
1270 
1271 
1305 
1307 {
1308  // Special calibration for particles in rings 1 to 9
1309  // We set the energy calibration code for the particle here
1310  // kECode0 = no calibration (e.g. gammas)
1311  // kECode1 = everything OK
1312  // kECode2 = small warning, for example if energy loss in a detector is calculated
1313  // kECode15 = bad, calibration is no good
1314  // The contributions from ChIo, Si, and CsI are stored in member variables fEChIo, fESi, fECsI
1315  // If the contribution is calculated rather than measured (see below), it is stored as a negative value.
1316  // NOTE: in no case do we ever calculate an energy for uncalibrated detector using measured energy
1317  // loss in the detector placed in front (i.e. calculate ECsI from deSi, or calculate ESi
1318  // from deChIo) as this gives wildly varying (mostly false) results.
1319  //
1320  // For gammas (IDCODE=0): no calibration performed, energy will be zero, ECODE=kECode0
1321  // For neutrons (IDCODE=1): if CsI is calibrated, we use the CsI light response to calculate
1322  // the equivalent energy for a proton.
1323  // For particles stopping in the CsI detector (IDCODE=2 or 3):
1324  // - for "8Be" we use half the CsI light output to calculate 4He kinetic energy which is then doubled
1325  // (we assume two 4He of identical energy), and ECODE=kECode2 (calculated)
1326  // - if no calibration exists for the CsI, we cannot calibrate the particle (ECODE=kECode0)
1327  // - if calibrated CsI energy is bizarre (<=0), we cannot calibrate the particle (ECODE=kECode15)
1328  // - if the Silicon detector is not calibrated, or if coherency analysis indicates a pile-up
1329  // in the silicon or other inconsistency, the Silicon energy is calculated from the calibrated
1330  // CsI energy (ECODE=kECode2)
1331  // - if the Ionisation Chamber is not calibrated, or if coherency analysis indicates a pile-up
1332  // in the ChIo or other inconsistency, this contribution is calculated using the total
1333  // cumulated energy measured in the CsI and/or Silicon detectors (ECODE=kECode2)
1334  //
1335  // For particles stopping in the Silicon detector (IDCODE=3, 4 or 5):
1336  // - if no calibration exists for the Silicon, we cannot calibrate the particle (ECODE=kECode0)
1337  // - if the Ionisation Chamber is not calibrated, or if coherency analysis indicates a pile-up
1338  // in the ChIo or other inconsistency, this contribution is calculated using the total
1339  // cumulated energy measured in the CsI and/or Silicon detectors (ECODE=kECode2)
1340 
1341  fECsI = fESi = fEChIo = 0;
1342 
1343  if (GetCodes().TestIDCode(KVINDRACodeMask::kIDCode_Gamma)) {
1345  return;
1346  }
1347  if (GetCodes().TestIDCode(KVINDRACodeMask::kIDCode_Neutron)) {
1349  return;
1350  }
1351 
1353 
1354  Bool_t stopped_in_silicon = kTRUE;
1355 
1356  if (GetCsI()) {
1357  stopped_in_silicon = kFALSE;
1358  if (GetCsI()->IsCalibrated()) {
1359  /* CSI ENERGY CALIBRATION */
1360  if (GetCodes().TestIDCode(KVINDRACodeMask::kIDCode_CsI) && GetZ() == 4 && GetA() == 8) {
1362  }
1363  else
1364  fECsI = GetCsI()->GetCorrectedEnergy(this, -1., kFALSE);
1365  }
1366  else {
1367  SetNoCalibrationStatus();// no CsI calibration - no calibration performed
1368  return;
1369  }
1370  if (GetCodes().TestECode(KVINDRACodeMask::kECode1) && fECsI <= 0) { // for kECode2, fECsI is always <0
1371  //Info("Calib", "ECsI = %f",fECsI);
1372  SetBadCalibrationStatus();// problem with CsI energy - no calibration
1373  return;
1374  }
1375  }
1376  if (GetSi()) {
1377  /* SILICIUM ENERGY CONTRIBUTION */
1378  // if fPileup = kTRUE, the Silicon energy appears to include a contribution from another particle
1379  // therefore we have to estimate the silicon energy for this particle using the CsI energy
1380  // if fCoherent = kFALSE, the Silicon energy is too small to be consistent with the CsI identification,
1381  // therefore we have to estimate the silicon energy for this particle using the CsI energy
1382 
1383  if (!fPileup && fCoherent && GetSi()->IsCalibrated()) {
1384  // all is apparently well. use full energy deposited in silicon.
1385  Bool_t si_transmission = kTRUE;
1386  if (stopped_in_silicon) {
1387  si_transmission = kFALSE;
1388  }
1389  else {
1390  GetSi()->SetEResAfterDetector(TMath::Abs(fECsI));
1391  }
1392  fESi = GetSi()->GetCorrectedEnergy(this, -1., si_transmission);
1393  if (fESi <= 0) {
1394  // problem with silicon calibration
1395  if (!stopped_in_silicon && (TMath::Abs(fECsI) > 0.0)) {
1396  if (!CalculateSiliconDEFromResidualEnergy()) return;
1397  }
1398  else {
1399  // stopped in Si with bad Si calibration - no good
1401  return;
1402  }
1403  }
1404  }
1405  else {
1406  if (!stopped_in_silicon) {
1407  if (!CalculateSiliconDEFromResidualEnergy()) return;
1408  }
1409  else {
1410  // cannot calibrate particle stopping in silicon in this case
1412  return;
1413  }
1414  }
1415 
1416  }
1417  if (GetChIo()) {
1418  /* CHIO ENERGY CONTRIBUTION */
1419  // if fUseFullChIoEnergyForCalib = kFALSE, we have to estimate the ChIo energy for this particle
1422  // all is apparently well
1423  if (!StoppedInChIo()) {
1424  GetChIo()->SetEResAfterDetector(ERES);
1425  fEChIo = GetChIo()->GetCorrectedEnergy(this);
1426  }
1427  else {
1428  // particle stopped in chio, not in transmission
1429  fEChIo = GetChIo()->GetCorrectedEnergy(this, -1., kFALSE);
1430  }
1431  if (fEChIo < 0.) {
1432  // bad chio calibration
1433  if (!StoppedInChIo() && (ERES > 0.0)) {
1435  }
1436  }
1437  }
1438  else {
1439  if (!StoppedInChIo()) {
1441  }
1442  else {
1443  // particle stopped in ChIo, no calibration available
1445  return;
1446  }
1447  }
1448  }
1450 }
1451 
1452 
1453 
1457 
1459 {
1460  // Etalon modules
1461  // calculate fESiLi from residual CsI energy
1462  Double_t e0 = GetSiLi()->GetDeltaEFromERes(GetZ(), GetA(), ERES);
1463  GetSiLi()->SetEResAfterDetector(ERES);
1464  fESiLi = GetSiLi()->GetCorrectedEnergy(this, e0);
1465  fESiLi = -TMath::Abs(fESiLi);
1467 }
1468 
1469 
1470 
1474 
1476 {
1477  // Etalon modules
1478  // calculate fESi75 from residual CsI+SiLi energy
1479  Double_t e0 = GetSi75()->GetDeltaEFromERes(GetZ(), GetA(), ERES);
1480  GetSi75()->SetEResAfterDetector(ERES);
1481  fESi75 = GetSi75()->GetCorrectedEnergy(this, e0);
1482  fESi75 = -TMath::Abs(fESi75);
1484 }
1485 
1486 
1487 
1490 
1492 {
1493  // calculate fEChIo from residual energy
1494  Double_t e0 = GetChIo()->GetDeltaEFromERes(GetZ(), GetA(), ERES);
1495  GetChIo()->SetEResAfterDetector(ERES);
1496  fEChIo = GetChIo()->GetCorrectedEnergy(this, e0);
1497  fEChIo = -TMath::Abs(fEChIo);
1499 }
1500 
1501 
1502 
1512 
1514 {
1515  // Special calibration for particles in rings 10 to 17
1516  // We set the energy calibration code for the particle here
1517  // kECode0 = no calibration (e.g. gammas)
1518  // kECode1 = everything OK
1519  // kECode2 = small warning, for example if energy loss in a detector is calculated
1520  // kECode15 = bad, calibration is no good
1521  // The contributions from ChIo & CsI are stored in member variables fEChIo, fECsI
1522  // If the contribution is calculated rather than measured, it is stored as a negative value
1523 
1524  fECsI = fEChIo = fESi75 = fESiLi = 0;
1525  if (GetCodes().TestIDCode(KVINDRACodeMask::kIDCode_Gamma)) {
1527  return;
1528  }
1529  // change fUseFullChioenergyforcalib for "coherency" particles
1530  // we assume they are calibrated after all other particles in group have
1531  // been identified, calibrated, and their energy contributions removed
1532  // from the ChIo
1533  if (GetCodes().TestIDCode(KVINDRACodeMask::kIDCode6) || GetCodes().TestIDCode(KVINDRACodeMask::kIDCode7) || GetCodes().TestIDCode(KVINDRACodeMask::kIDCode8))
1535 
1537  Bool_t stopped_in_chio = kTRUE;
1538  if (GetCsI()) {
1539  stopped_in_chio = kFALSE;
1540  /* CSI ENERGY CALIBRATION */
1541  if (GetCodes().TestIDCode(KVINDRACodeMask::kIDCode_CsI) && GetZ() == 4 && GetA() == 8) {
1543  }
1544  else
1545  fECsI = GetCsI()->GetCorrectedEnergy(this, -1., kFALSE);
1546 
1547  if (fECsI <= 0) {
1548  SetBadCalibrationStatus();// bad - no CsI energy
1549  return;
1550  }
1551  }
1553  if (GetSiLi()) {
1554  Double_t ERES = fECsI;
1555  if (!fPileupSiLi && GetSiLi()->IsCalibrated()) {
1556  Bool_t si_transmission = kTRUE;
1557  if (StoppedInSiLi()) {
1558  si_transmission = kFALSE;
1559  }
1560  else {
1561  GetSiLi()->SetEResAfterDetector(ERES);
1562  }
1563  fESiLi = GetSiLi()->GetCorrectedEnergy(this, -1., si_transmission);
1564  if (fESiLi <= 0) {
1565  if (!StoppedInSiLi() && ERES > 0.0) {
1567  }
1568  else {
1570  return;
1571  }
1572  }
1573  }
1574  else {
1576  }
1577  }
1578  if (GetSi75()) {
1579  Double_t ERES = fECsI + TMath::Abs(fESiLi);
1580  if (!fPileupSi75 && !fPileupSiLi && GetSi75()->IsCalibrated()) {
1581  Bool_t si_transmission = kTRUE;
1582  if (StoppedInSi75()) {
1583  si_transmission = kFALSE;
1584  }
1585  else {
1586  GetSi75()->SetEResAfterDetector(ERES);
1587  }
1588  fESi75 = GetSi75()->GetCorrectedEnergy(this, -1., si_transmission);
1589  if (fESi75 <= 0) {
1590  if (!StoppedInSi75() && ERES > 0.0) {
1592  }
1593  else {
1595  return;
1596  }
1597  }
1598  }
1599  else {
1601  }
1602  }
1603  }
1604  if (GetChIo()) {
1605  /* IONISATION CHAMBER ENERGY CONTRIBUTION */
1606  // if fUseFullChIoEnergyForCalib = kFALSE, ChIo was hit by other particles in group
1607  // therefore we have to estimate the ChIo energy for this particle using the CsI energy
1608  // if fPileupChIo = kTRUE, there appears to be another particle stopped in the ChIo
1609  // therefore we have to estimate the ChIo energy for this particle using the CsI energy
1612  // all is apparently well
1613  Bool_t ci_transmission = kTRUE;
1614  if (stopped_in_chio) {
1615  ci_transmission = kFALSE;
1616  }
1617  else {
1618  GetChIo()->SetEResAfterDetector(ERES);
1619  }
1620  fEChIo = GetChIo()->GetCorrectedEnergy(this, -1., ci_transmission);
1621  if (fEChIo <= 0) {
1622  if (!stopped_in_chio && ERES > 0) {
1624  }
1625  }
1626  }
1627  else {
1628  if (!stopped_in_chio && ERES > 0) {
1630  }
1631  }
1632  }
1633 
1634 
1636 }
1637 
1638 
1639 
1640 
1647 
1649 {
1650  // Check calculated CsI energy loss of particle.
1651  // If it is greater than the maximum theoretical energy loss
1652  // (depending on the length of CsI, the Z & A of the particle)
1653  // we set the energy calibration code to kECode3 (historical VEDA code
1654  // for particles with E_csi > E_max_csi)
1655 
1656  KVDetector* csi = GetCsI();
1657  if (csi && GetZ() > 0 && GetZ() < 3 && (csi->GetEnergy() > csi->GetMaxDeltaE(GetZ(), GetA()))) SetECode(KVINDRACodeMask::kECode3);
1658 }
1659 
1660 
1661 
int Int_t
bool Bool_t
unsigned char UChar_t
char Char_t
constexpr Bool_t kFALSE
double Double_t
constexpr Bool_t kTRUE
const char Option_t
Option_t Option_t option
char * Form(const char *fmt,...)
virtual const Char_t * GetType() const
Definition: KVBase.h:176
Ionisation chamber detectors of the INDRA multidetector array.
Definition: KVChIo.h:30
CsI(Tl) scintillation detectors of the INDRA multidetector array.
Definition: KVCsI.h:16
Double_t GetCorrectedEnergy(KVNucleus *, Double_t lum=-1., Bool_t transmission=kTRUE) override
Definition: KVCsI.cpp:16
KVString GetDataSetEnv(const Char_t *type, const Char_t *defval="") const
Definition: KVDataSet.cpp:784
@ k_BelowPunchThrough
Definition: KVIDGChIoSi.h:77
Base class for all detectors or associations of detectors in array which can identify charged particl...
Definition: KVIDTelescope.h:84
virtual Double_t GetIDMapY(Option_t *opt="")
virtual Double_t GetPedestalY(Option_t *opt="")
Bool_t HasMassID() const
virtual Double_t GetMeanDEFromID(Int_t &status, Int_t Z, Int_t A=-1, Double_t Eres=-1.0)
const Char_t * GetEStatus()
Give an explanation for the calibration code.
void Clear(Option_t *opt="") override
resets all id subcodes.
const Char_t * GetIDStatus()
Give an explanation for the ID code.
Nuclei reconstructed from data measured in the INDRA array.
Bool_t StoppedInSi()
Returns kTRUE if particle stopped in Si detector.
int GetModuleNumber() const
Bool_t StoppedInChIo()
Returns kTRUE if particle stopped in ChIo detector.
int GetRingNumber() const
void CalculateSi75DEFromResidualEnergy(Double_t ERES)
virtual Bool_t CoherencyEtalons(KVIdentificationResult &theID)
Called by Identify() for particles stopping in etalon modules of Rings 10-17.
void SetECode(UChar_t code_mask) override
void Copy(TObject &) const override
void Clear(Option_t *t="") override
reset nucleus' properties
Bool_t fCorrectCalib
set to kTRUE in Streamer if calibration needs correction
virtual void Identify()
Bool_t fCoherentSi75SiLiCsI
coherency of Si75-SiLi and SiLi-CsI/CsI identifications
const Char_t * GetIDSubCodeString(const Char_t *id_tel_type="") const
Float_t fESi
si contribution to energy
Bool_t fPileupChIo
apparent pileup in ChIo, revealed by inconsistency between CsI & ChIo-CsI identifications
KVSilicon * GetSi()
KVINDRACodes fCodes
VEDA6-style calibration and identification codes.
virtual Bool_t CoherencySiCsI(KVIdentificationResult &theID)
Bool_t fPileupSi75
apparent pileup in Si75, revealed by inconsistency between CsI/SiLi-CsI & ChIo-Si75 identifications
void DoGammaCalibration()
no calibration is performed for gammas
void SetBadCalibrationStatus()
void CalculateSiLiDEFromResidualEnergy(Double_t ERES)
Float_t fECsI
csi contribution to energy
Bool_t StoppedInCsI()
Returns kTRUE if particle stopped in CsI detector.
virtual void Calibrate()
virtual Bool_t CoherencyChIoCsI(KVIdentificationResult &theID)
void init()
default initialisations
KVINDRACodes & GetCodes() const
Bool_t fPileupSiLi
apparent pileup in SiLi, revealed by inconsistency between CsI & Si75-SiLi identifications
Bool_t StoppedInSi75()
Returns kTRUE if particle stopped in Si75 detector.
virtual void CalibrateRings1To9()
KVINDRAReconNuc()
default ctor
Bool_t CalculateSiliconDEFromResidualEnergy()
Bool_t fUseFullChIoEnergyForCalib
decided by coherency analysis
Int_t GetIDSubCode(const Char_t *id_tel_type="") const
Float_t fESiLi
sili contribution to energy
virtual void CalibrateRings10To17()
void SetNoCalibrationStatus()
Bool_t fPileup
apparent pileup in Si, revealed by inconsistency between CsI & Si-CsI identifications
Float_t fEChIo
chio contribution to energy
virtual Bool_t CoherencyChIoSiCsI(KVIdentificationResult)
void CalculateChIoDEFromResidualEnergy(Double_t ERES)
calculate fEChIo from residual energy
Bool_t fIncludeEtalonsInCalibration
for etalon modules:particle passed through Si75/SiLi
Bool_t fCoherent
coherency of CsI & Si-CsI identifications
Float_t fESi75
si75 contribution to energy
Bool_t StoppedInSiLi()
Returns kTRUE if particle stopped in Si detector.
void Print(Option_t *option="") const override
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)
Bool_t Aident
= kTRUE if A of particle established
Int_t deltaEpedestal
special code for handling particles which give no signal in deltaE
const Char_t * GetComment() const
Int_t A
A of particle found (if Aident==kTRUE)
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 Zident
=kTRUE if Z of particle established
virtual Double_t GetTargetEnergyLossCorrection(KVReconstructedNucleus *)
Description of properties and kinematics of atomic nuclei.
Definition: KVNucleus.h:123
Int_t GetA() const
Definition: KVNucleus.cpp:792
Int_t GetZ() const
Return the number of proton / atomic number.
Definition: KVNucleus.cpp:763
Double_t GetTheta() const
Definition: KVParticle.h:683
Double_t GetEnergy() const
Definition: KVParticle.h:624
Double_t GetPhi() const
Definition: KVParticle.h:691
void SetEnergy(Double_t e)
Definition: KVParticle.h:602
Nuclei reconstructed from data measured by a detector array .
KVDetector * GetDetector(const TString &label) const
virtual Double_t GetTargetEnergyLoss() const
KVIdentificationResult * GetIdentificationResult(Int_t i)
void Copy(TObject &) const override
void Clear(Option_t *option="") override
const KVSeqCollection * GetIDTelescopes() const
KVDetector * GetStoppingDetector() const
void SetDetector(int i, KVDetector *);
virtual void SetTargetEnergyLoss(Double_t e)
virtual void GetAnglesFromReconstructionTrajectory(Option_t *opt="random")
void Print(Option_t *option="") const override
KVIDTelescope * GetIdentifyingTelescope() const
virtual Bool_t IsAMeasured() const
virtual TObject * FindObjectByType(const Char_t *) const
80um silicon detector for INDRA etalon telescopes
Definition: KVSilicon.h:48
2mm + 40um dead zone Si(Li) detector for INDRA etalon telescopes
Definition: KVSilicon.h:69
Silicon detectors of the INDRA array.
Definition: KVSilicon.h:16
virtual void Copy(TObject &object) const
void Obsolete(const char *method, const char *asOfVers, const char *removedFromVers) const
Type GetType(const std::string &Name)
Double_t Abs(Double_t d)
ClassImp(TPyArg)