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 "Riostream.h"
20 #include "TBuffer.h"
21 #include "TEnv.h"
22 #include "KVDataSet.h"
23 #include "KVINDRAReconNuc.h"
24 #include "KVList.h"
25 #include "KVGroup.h"
26 #include "KVLayer.h"
27 #include "KVINDRA.h"
28 #include "KVTelescope.h"
29 #include "KVIDTelescope.h"
30 #include "TCollection.h"
31 #include "KVChIo.h"
32 #include "KVEBYEDAT_ACQParam.h"
33 #include "KVSilicon.h"
34 #include "KVCsI.h"
35 /******* for Identify **********/
36 #include "KVIDGCsI.h"
37 #include "KVIDChIoSi.h"
38 #include "KVIDCsI.h"
39 
40 #include <KVIDGChIoSi.h>
41 
42 using namespace std;
43 
45 
46 
47 
48 
51 
53 {
54  //default initialisations
55  if (gDataSet)
56  SetMassFormula(UChar_t(gDataSet->GetDataSetEnv("KVINDRAReconNuc.MassFormula", Double_t(kEALMass))));
57  fCoherent = kTRUE;
58  fPileup = kFALSE;
59  fUseFullChIoEnergyForCalib = kTRUE;
60  fECsI = fESi = fEChIo = fESi75 = fESiLi = 0.;
61  fCorrectCalib = kFALSE;
62  fPileupChIo = kFALSE;
63  fPileupSi75 = kFALSE;
64  fPileupSiLi = kFALSE;
65  fIncludeEtalonsInCalibration = kFALSE;
66 }
67 
68 
69 
72 
74 {
75  //default ctor
76  init();
77 }
78 
79 
80 
83 
85  KVReconstructedNucleus(), fCodes()
86 {
87  //copy ctor
88  init();
89 #if ROOT_VERSION_CODE >= ROOT_VERSION(3,4,0)
90  obj.Copy(*this);
91 #else
92  ((KVINDRAReconNuc&) obj).Copy(*this);
93 #endif
94 }
95 
96 
97 
100 
101 KVINDRAReconNuc::~KVINDRAReconNuc()
102 {
103  //dtor
104  init();
105  fCodes.Clear();
106 }
107 
108 
109 #if ROOT_VERSION_CODE >= ROOT_VERSION(3,4,0)
110 
112 
114 #else
116 #endif
117 {
118  KVINDRAReconNuc& robj = (KVINDRAReconNuc&)obj;
119  fCodes.Copy(robj.fCodes);
120  robj.fCoherent = fCoherent;
121  robj.fPileup = fPileup;
122  robj.fUseFullChIoEnergyForCalib = fUseFullChIoEnergyForCalib;
123  robj.fECsI = fECsI;
124  robj.fESi = fESi;
125  robj.fEChIo = fEChIo;
126  robj.fESi75 = fESi75;
127  robj.fESiLi = fESiLi;
128  robj.fCorrectCalib = fCorrectCalib;
130  robj.fPileupChIo = fPileupChIo;
131  robj.fPileupSiLi = fPileupSiLi;
132  robj.fPileupSi75 = fPileupSi75;
133  robj.fIncludeEtalonsInCalibration = fIncludeEtalonsInCalibration;
135 }
136 
137 
138 
139 
141 
142 void KVINDRAReconNuc::Print(Option_t* option) const
143 {
144 
146 
147  cout << "KVINDRAReconNuc: fRing=" << GetRingNumber() << " fModule=" <<
148  GetModuleNumber() << endl;
149  if (IsIdentified()) {
150  if (GetRingNumber() < 10) {
151  cout << " -- RESULTS OF COHERENCY TESTS (RINGS 1-9) -- " << endl;
152  if (fCoherent) cout << " CsI-R/L & Si-CsI identifications COHERENT" << endl;
153  else cout << " CsI-R/L & Si-CsI identifications NOT COHERENT" << endl;
154  if (fPileup) cout << " Si energy loss indicates PILEUP" << endl;
155  else cout << " Si energy loss indicates single particle" << endl;
156  if (GetRingNumber() > 1) {
157  if (fUseFullChIoEnergyForCalib) cout << " ChIo-Si identification indicates single particle" << endl;
158  else cout << " ChIo-Si identification indicates MULTIPLE CHIO CONTRIBUTIONS" << endl;
159  }
160  cout << endl;
161  }
162  else {
163  cout << " -- RESULTS OF COHERENCY TESTS (RINGS 10-17) -- " << endl;
164  if (fIncludeEtalonsInCalibration) cout << " WITH Etalon telescopes included in particle trajectory" << endl;
165  else cout << " WITHOUT etalon telescopes included in particle trajectory" << endl;
166  if (fPileupChIo) {
167  cout << " Analysis indicates PILEUP in ChIo" << endl;
168  }
169  if (fPileupSi75) {
170  cout << " Analysis indicates PILEUP in Si75" << endl;
171  }
172  if (fPileupSiLi) {
173  cout << " Analysis indicates PILEUP in SiLi" << endl;
174  }
175  if (fUseFullChIoEnergyForCalib) cout << " ChIo energy assumed due solely to this particle" << endl;
176  else cout << " ChIo energy contribution calculated assuming MULTIPLE CHIO CONTRIBUTIONS" << endl;
177  }
178  cout << " =======> ";
179  cout << " Z=" << GetZ() << " A=" << ((KVINDRAReconNuc*) this)->
180  GetA();
181  if (((KVINDRAReconNuc*) this)->IsAMeasured()) cout << " Areal=" << ((KVINDRAReconNuc*) this)->GetRealA();
182  else cout << " Zreal=" << GetRealZ();
183  cout << endl << " Identification code = " << ((KVINDRAReconNuc*) this)->
184  GetCodes().GetIDStatus() << endl;
185  }
186  else {
187  cout << "(unidentified)" << endl;
188  }
189  if (IsCalibrated()) {
190  cout << " Total Energy = " << GetEnergy() << " MeV, Theta=" << GetTheta() << " Phi=" << GetPhi() << endl;
191  if (GetRingNumber() < 10) {
192  if (GetRingNumber() > 1) {
193  cout << " EChIo = " << TMath::Abs(fEChIo) << " MeV";
194  if (fEChIo < 0) cout << " (calculated)";
195  cout << endl;
196  }
197  cout << " ESi = " << TMath::Abs(fESi) << " MeV";
198  if (fESi < 0) cout << " (calculated)";
199  cout << endl;
200  cout << " ECsI = " << TMath::Abs(fECsI) << " MeV";
201  if (fECsI < 0) cout << " (calculated)";
202  cout << endl;
203  }
204  else {
205  cout << " EChIo = " << TMath::Abs(fEChIo) << " MeV";
206  if (fEChIo < 0) cout << " (calculated)";
207  cout << endl;
209  cout << " ESi75 = " << TMath::Abs(fESi75) << " MeV";
210  if (fESi75 < 0) cout << " (calculated)";
211  cout << endl;
212  cout << " ESiLi = " << TMath::Abs(fESiLi) << " MeV";
213  if (fESiLi < 0) cout << " (calculated)";
214  cout << endl;
215  }
216  cout << " ECsI = " << TMath::Abs(fECsI) << " MeV";
217  if (fECsI < 0) cout << " (calculated)";
218  cout << endl;
219  }
220  cout << " Target energy loss correction : " << GetTargetEnergyLoss() << " MeV" << endl;
221  cout << " Calibration code = " << ((KVINDRAReconNuc*) this)->
222  GetCodes().GetEStatus() << endl;
223  }
224  else {
225  cout << "(uncalibrated)" << endl;
226  }
227 // if (!IsIdentified()) {
228  cout << "Analysis : ";
229  switch (GetStatus()) {
230  case 0:
231  cout <<
232  "Particle alone in group, or identification independently of other"
233  << endl;
234  cout << "particles in group is directly possible." << endl;
235  break;
236 
237  case 1:
238  cout <<
239  "Particle reconstructed after identification of others in group"
240  << endl;
241  cout <<
242  "and subtraction of their calculated energy losses in ChIo."
243  << endl;
244  break;
245 
246  case 2:
247  cout <<
248  "Particle identification estimated after arbitrary sharing of"
249  << endl;
250  cout <<
251  "energy lost in ChIo between several reconstructed particles."
252  << endl;
253  break;
254 
255  case 3:
256  cout <<
257  "Particle stopped in first stage of telescope. Estimation of minimum Z."
258  << endl;
259  break;
260 
261  default:
262  cout << GetStatus() << endl;
263  break;
264  }
265  //}
266  cout <<
267  "-------------------------------------------------------------------------------"
268  << endl;
269 }
270 
271 
272 
273 
276 
278 {
279  //reset nucleus' properties
281  init();
282  fCodes.Clear();
283 }
284 
285 
286 
290 
292 {
293  //Return pointer to the ChIo the particle passed through.
294  //Pointer is null if not.
295  KVChIo* chio = (KVChIo*) GetDetector("CI");
296  return chio;
297 }
298 
299 
300 
304 
306 {
307  //Return pointer to the Silicon the particle passed through.
308  //Pointer is null if not.
309  KVSilicon* chio =
310  (KVSilicon*) GetDetector("SI");
311  return chio;
312 }
313 
314 
315 
319 
321 {
322  //Return pointer to the Silicon-75 the particle passed through.
323  //Pointer is null if not.
324  KVSi75* chio =
325  (KVSi75*) GetDetector("SI75");
326  return chio;
327 }
328 
329 
330 
334 
336 {
337  //Return pointer to the Silicon-Lithium the particle passed through.
338  //Pointer is null if not.
339  KVSiLi* chio =
340  (KVSiLi*) GetDetector("SILI");
341  return chio;
342 }
343 
344 
345 
349 
351 {
352  //Return pointer to the CsI the particle passed through.
353  //Pointer is null if not.
354  KVCsI* csi = (KVCsI*) GetDetector("CSI");
355  return csi;
356 }
357 
358 
359 
360 
363 
365 {
366  //Returns kTRUE if particle stopped in ChIo detector
367 
368  if (!strcmp(GetStoppingDetector()->GetType(), "CI")) {
369  return kTRUE;
370  }
371  else {
372  return kFALSE;
373  }
374 }
375 
376 
377 
380 
382 {
383  //Returns kTRUE if particle stopped in Si detector
384 
385  if (!strcmp(GetStoppingDetector()->GetType(), "SI")) {
386  return kTRUE;
387  }
388  else {
389  return kFALSE;
390  }
391 }
392 
393 
396 
398 {
399  //Returns kTRUE if particle stopped in Si75 detector
400 
401  if (!strcmp(GetStoppingDetector()->GetType(), "SI75")) {
402  return kTRUE;
403  }
404  else {
405  return kFALSE;
406  }
407 }
408 
409 
412 
414 {
415  //Returns kTRUE if particle stopped in Si detector
416 
417  if (!strcmp(GetStoppingDetector()->GetType(), "SILI")) {
418  return kTRUE;
419  }
420  else {
421  return kFALSE;
422  }
423 }
424 
425 
426 
429 
431 {
432  //Returns kTRUE if particle stopped in CsI detector
433 
434  if (!strcmp(GetStoppingDetector()->GetType(), "CSI")) {
435  return kTRUE;
436  }
437  else {
438  return kFALSE;
439  }
440 }
441 
442 
443 
461 
462 Int_t KVINDRAReconNuc::GetIDSubCode(const Char_t* id_tel_type) const
463 {
464  //Returns subcode/status code from identification performed in ID telescope of given type.
465  //i.e. to obtain CsI R-L subcode use GetIDSubCode("CSI_R_L").
466  //
467  //The meaning of the subcodes is defined in the corresponding KVIDTelescope class description
468  //i.e. for CsI R-L, look at KVIDCsI.
469  //
470  //The subcode is set for any attempted identification, not necessarily that which eventually
471  //leads to the definitive identification of the particle.
472  //i.e. in the example of the CsI R-L subcode, the particle in question may in fact be identified
473  //by a Si-CsI telescope, because the CsI identification routine returned e.g. KVIDGCsI::kICODE7
474  //(a gauche de la ligne fragment, Z est alors un Zmin et le plus probable).
475  //
476  //calling GetIDSubCode() with no type returns the identification subcode corresponding
477  //to the identifying telescope (whose pointer is given by GetIdentifyingTelescope()).
478  //
479  //If no subcode exists (identification in given telescope type was not attempted, etc.) value returned is -1
480 
481  KVIdentificationResult* ir = 0;
482  if (strcmp(id_tel_type, "")) ir = GetIdentificationResult(id_tel_type);
484  if (!ir) return -1;
485  return ir->IDquality;
486  //return GetIDSubCode(id_tel_type,const_cast <KVINDRAReconNuc *>(this)->GetCodes().GetSubCodes());
487 }
488 
489 
490 
504 
506  id_tel_type) const
507 {
508  //Returns explanatory message concerning identification performed in ID telescope of given type.
509  //(see GetIDSubCode())
510  //
511  //The subcode is set for any attempted identification, not necessarily that which eventually
512  //leads to the definitive identification of the particle.
513  //
514  //calling GetIDSubCodeString() with no type returns the identification subcode message corresponding
515  //to the identifying telescope (whose pointer is given by GetIdentifyingTelescope()).
516  //
517  //In case of problems:
518  // no ID telescope of type 'id_tel_type' : "No identification attempted in id_tel_type"
519  // particle not identified : "Particle unidentified. Identifying telescope not set."
520 
521  KVIdentificationResult* ir = 0;
522  if (strcmp(id_tel_type, "")) ir = GetIdentificationResult(id_tel_type);
524  if (!ir) {
525  if (strcmp(id_tel_type, ""))
526  return Form("No identification attempted in %s", id_tel_type);
527  else
528  return
529  Form("Particle unidentified. Identifying telescope not set.");
530  }
531  return ir->GetComment();
532 }
533 
534 
535 
536 
545 
547 {
548  // we check that the ChIo contribution is sane:
549  // if no other particles hit this group, the Z given by the ChIoSi
550  // must be <= the Z found from Si-CsI or CsI-RL identification
551  //
552  // in this case the measured energy loss of the ChIo can be solely attributed to this particle
553  // and we return kTRUE;
554 
555  // ChIo was hit by more than one particle in group
556  if (GetChIo() && GetChIo()->GetNHits() > 1) {
557  return kFALSE;
558  }
559 
561  if (!IDchiosi->IDattempted) {
562  // no ChIo-Si identification ? assume coherency ?
563  return kTRUE;
564  }
565 
566  // if we have a successful ChIo-Si id with a Z > Z given by CsI or Si-CsI id,
567  // then we consider that there is a pile-up in the ChIo
568  // note that we consider Z_ChIoSi = 1 to mean the ChIo is in the pedestal i.e. nothing seen
569  // we also require the chio-si identification to be above the punch-through line
570  if (IDchiosi->IDOK && IDchiosi->Z > 1 && IDchiosi->IDquality != KVIDGChIoSi::k_BelowPunchThrough && IDchiosi->Z > theID.Z) {
571  return kFALSE;
572  }
573 
574  return kTRUE;
575 }
576 
577 
578 
579 
592 
594 {
595  // Called by Identify() for particles stopping in CsI detectors on rings 1-9,
596  // which have a Silicon detector just in front of them.
597  //
598  // coherent = kFALSE if CsI-R/L and Si-CsI identifications are not coherent.
599  // this is a warning, the CsI identification is kept, either the Si signal
600  // was not good (particle hitting dead zone), or it actually corresponds
601  // to two particles reaching the CsI at the same time
602  // pileup = kTRUE means that the particle identified in CsI-R/L is correct,
603  // and there is probably a second particle which stopped in the silicon
604  // detector at the same time, to be identified in ChIo-Si after
605  // subtraction of the Silicon contribution
606 
609  fCoherent = kTRUE;
610  fPileup = kFALSE;
611 
612  // Unsuccessful/no CsI id attempt with successful Si-CsI id ?
613  // Then use Si-CsI identification result
614  if (IDsicsi->IDOK && !IDcsi->IDOK) {
615  theID = *IDsicsi;
616  return kTRUE;
617  }
618 
619  // check coherency of CsI-R/L and Si-CsI identifications
620  if (IDcsi->IDOK) {
621  // gammas
622  if (IDcsi->IDcode == KVINDRACodeMask::kIDCode0) {
623  theID = *IDcsi;
624  return kTRUE;
625  }
626  // Neutrons have no energy loss in Si detector (pedestal), have a reaction in the CsI and create a Z=1
627  // or Z=2 which is identified in CsI R-L, while they show up in Si-CsI maps as a horizontal
628  // band around the Si pedestal for low energies (energies where proton dE is significantly larger than
629  // the pedestal).
630  if ((IDcsi->Z == 1 || IDcsi->Z == 2) && GetSi()) {
632  // no explicit treatment of 'neutron-like' particles with a cut in Si-CsI id grid
633  // First we check that we are in the domain where proton dE can be distinguished from pedestal.
634  // If so, if the measured dE is below [ped + factor*(dE_exp - ped)], then we label the particle as a neutron.
635  // 'factor' depends on the Si-CsI telescope: if it has mass identification, factor=0.3; if not, factor=0.1
636  // (these empirical values correspond to 5th campaign data)
638  if (idt) {
639  Double_t ped = idt->GetPedestalY();
640  Int_t status;
641  Double_t dE_exp = idt->GetMeanDEFromID(status, 1, 1);
642  if (status == KVIDTelescope::kMeanDE_OK) { // proton/Z=1 line exists, and we are in its energy range
643  if (dE_exp > ped + 5.) { // arbitrary choice, must have expected dE at least 5 channels above pedestal
644 
645  // if Si-CsI has no isotopic identification, reduce factor
646  Double_t factor = (idt->HasMassID() ? 0.3 : 0.1);
647  if (idt->GetIDMapY() < (ped + factor * (dE_exp - ped))) {
648  theID = *IDsicsi;
649  theID.IDOK = kTRUE;
650  theID.Zident = kTRUE;
651  theID.Aident = kTRUE;
652  theID.Z = 0;
653  theID.A = 1;
654  theID.IDcode = KVINDRACodeMask::kIDCode1; // general code for neutrons
655  return kTRUE;
656  }
657  }
658  }
659  }
660  }
662  // explicit treatment of 'neutron-like' particles with a cut in Si-CsI id grid
663  theID = *IDsicsi;
664  theID.IDOK = kTRUE;
665  theID.Zident = kTRUE;
666  theID.Aident = kTRUE;
667  theID.Z = 0;
668  theID.A = 1;
669  theID.IDcode = KVINDRACodeMask::kIDCode1; // general code for neutrons
670  return kTRUE;
671  }
672  }
673 
674  // We check the coherency of the mass and charge identifications
675  // If a successful Si-CsI identification is available we check:
676  // if Si-CsI gives A & Z - must have same Z, A within +/-1 unit
677  // if Z or A smaller => incoherency : pile-up of two particles in CsI ?
678  // or bad signal from Si detector (dead zones) ?
679  // if Z or A larger, CsI identification is good,
680  // assume another particle stopped in Si (identify in ChIo-Si)
681  // if Si-CsI gives just Z - must have same Z
682  // if Z smaller => incoherency : pile-up of two particles in CsI ?
683  // or bad signal from Si detector (dead zones) ?
684  // if Z larger => CsI identification is good,
685  // assume another particle stopped in Si (identify in ChIo-Si)
686  //
687  // If CsI identification gives code KVIDGCsI::kICode1 ou KVIDGCsI::kICode3 and the
688  // Si-CsI gives the same Z but A = Acsi + 1, we use the Si-CsI identification.
689  //
690  // If CsI identification gives code KVIDGCsI::kICode2 ou KVIDGCsI::kICode3 and the
691  // Si-CsI gives the same Z but A = Acsi - 1, we use the Si-CsI identification.
692  //
693  // N.B. if CsI-R/L identification gives "8Be" (2 alpha particles) then there are two correct possibilities:
694  // 1) Si-CsI identification gives 7Li => CsI identification is correct ("8Be")
695  // 2) Si-CsI identification gives 8He => the particle is 8He (falls on same R/L line as 2*alpha)
696  // Seeing the very low statistics for 8He compared to 8Be/2alpha, we assume that if Si-CsI id
697  // gives something above 8He it is either incoherent (below 7Li) or 8Be + something else in ChIo-Si
698  // (above 7Li).
699  if (IDsicsi->IDOK) {
700  theID = *IDcsi;
701  Int_t Zref = IDcsi->Z;
702  Int_t Aref = IDcsi->A;
703  if (IDsicsi->Aident) { // Si-CsI provides mass identification
704 
705  if (IDcsi->Z == 4 && IDcsi->A == 8) {
706  // traitement special 8Be
707  // if sicsi => 7Li, it is 8Be (2alpha)
708  // if sicsi => 8He, it is 8He
709  if (IDsicsi->Z < 2 || (IDsicsi->Z == 2 && IDsicsi->A < 7)) {
710  fCoherent = kFALSE;
711  IDsicsi->SetComment("CsI-R/L & Si-CsI identifications not coherent");
712  return kTRUE;
713  }
714  else if (IDsicsi->Z == 2 && IDsicsi->A > 6 && IDsicsi->A < 10) {
715  // accept helium-7,8,9 as 8He
716  theID = *IDsicsi;
717  return kTRUE;
718  }
719  else if ((IDsicsi->Z == 2 && IDsicsi->A > 9) || (IDsicsi->Z == 3 && IDsicsi->A < 6)) {
720  fCoherent = kFALSE;
721  IDsicsi->SetComment("CsI-R/L & Si-CsI identifications not coherent");
722  return kTRUE;
723  }
724  else if (IDsicsi->Z == 3 && IDsicsi->A > 5 && IDsicsi->A < 9) {
725  // accept lithium-6,7,8 as 7Li
726  return kTRUE;
727  }
728  else if ((IDsicsi->Z == 3 && IDsicsi->A > 8) || IDsicsi->Z > 3) {
729  fPileup = kTRUE;
730  IDsicsi->SetComment("Second particle stopping in Si, identification ChIo-Si required");
731  return kTRUE;
732  }
733  }
734  // if CsI says A could be bigger and Si-CsI gives same Z and A+1, use Si-CsI
735  if ((IDsicsi->Z == Zref) && (IDsicsi->A == (Aref + 1))
736  && (IDcsi->IDquality == KVIDGCsI::kICODE1 || IDcsi->IDquality == KVIDGCsI::kICODE3)) {
737  theID = *IDsicsi;
738  return kTRUE;
739  }
740  // if CsI says A could be smaller and Si-CsI gives same Z and A-1, use Si-CsI
741  if ((IDsicsi->Z == Zref) && (IDsicsi->A == (Aref - 1))
742  && (IDcsi->IDquality == KVIDGCsI::kICODE2 || IDcsi->IDquality == KVIDGCsI::kICODE3)) {
743  theID = *IDsicsi;
744  return kTRUE;
745  }
746  // everything else - Z must be same, A +/- 1 unit
747  if (IDsicsi->Z == Zref && TMath::Abs(IDsicsi->A - Aref) < 2) {
748  return kTRUE;
749  }
750  else if (IDsicsi->Z < Zref || (IDsicsi->Z == Zref && IDsicsi->A < (Aref - 1))) {
751  fCoherent = kFALSE;
752  IDsicsi->SetComment("CsI-R/L & Si-CsI identifications not coherent");
753  return kTRUE;
754  }
755  else if (IDsicsi->Z > Zref || (IDsicsi->Z == Zref && IDsicsi->A > (Aref + 1))) {
756  fPileup = kTRUE;
757  IDsicsi->SetComment("Second particle stopping in Si, identification ChIo-Si required");
758  return kTRUE;
759  }
760  }
761  else { // only Z identification from Si-CsI
762  if (IDcsi->Z == 4 && IDcsi->A == 8) {
763  // traitement special 8Be
764  // we ask for Z to be equal 3 in SiCsI, but with no mass identification
765  // we do not try for 8He identification
766  if (IDsicsi->Z < 3) {
767  fCoherent = kFALSE;
768  IDsicsi->SetComment("CsI-R/L & Si-CsI identifications not coherent");
769  return kTRUE;
770  }
771  else if (IDsicsi->Z == 3) {
772  return kTRUE;
773  }
774  else {
775  fPileup = kTRUE;
776  IDsicsi->SetComment("Second particle stopping in Si, identification ChIo-Si required");
777  return kTRUE;
778  }
779  }
780  // everything else
781  if (IDsicsi->Z == Zref) {
782  return kTRUE;
783  }
784  else if (IDsicsi->Z < Zref) {
785  fCoherent = kFALSE;
786  IDsicsi->SetComment("CsI-R/L & Si-CsI identifications not coherent");
787  return kTRUE;
788  }
789  else {
790  fPileup = kTRUE;
791 
792  IDsicsi->SetComment("Second particle stopping in Si, identification ChIo-Si required");
793  return kTRUE;
794  }
795  }
796  }
797  // in all other cases accept CsI identification
798  theID = *IDcsi;
799  return kTRUE;
800  }
801  return kFALSE;
802 }
803 
804 
805 
806 
815 
817 {
818  // Called by Identify() for particles stopping in CsI detectors on rings 10-17,
819  // which have a ChIo detector just in front of them.
820  //
821  // fPileupChIo = kTRUE if ChIo-CsI identification gives Z >> CsI-R/L identification
822  // this means that the particle identified in CsI-R/L is correct,
823  // and there is probably a second particle which stopped in the ChIo
824  // detector at the same time (will be added as a Zmin/code5)
825 
827  KVIdentificationResult* IDcicsi = GetIdentificationResult("CI_CSI");
828 
831 
832  // Unsuccessful/no CsI id attempt with successful ChIo-CsI id ?
833  // Then use ChIo-CsI identification result
834  if (IDcsi && !IDcsi->IDOK) {
835  if (IDcicsi && IDcicsi->IDOK) {
836  theID = *IDcicsi;
837  return kTRUE;
838  }
839  }
840 
841  // check coherency of CsI-R/L and ChIo-CsI identifications
842  if (IDcsi && IDcsi->IDOK) {
843  // gammas
844  if (IDcsi->IDcode == KVINDRACodeMask::kIDCode0) {
845  theID = *IDcsi;
846  return kTRUE;
847  }
848 
849  // We check the coherency of the identifications
850  // Because ChIo-Csi identification is not of very high quality (compared to CsI R-L),
851  // we only check that the Z given by ChIo-CsI is < Zref+1
852  // If not, we can suspect the presence of another particle in the ChIo
853 
854  if (IDcicsi && IDcicsi->IDOK) {
855  Int_t Zref = IDcsi->Z;
856  if (IDcicsi->Z > (Zref + 1) && fUseFullChIoEnergyForCalib
857  && !fPileupSi75) { // do not add pile-up if one already suspected in Si75
858  fPileupChIo = kTRUE;
859  IDcicsi->SetComment("Possible pile-up in ChIo");
860  }
861  }
862 
863  // in all other cases accept CsI identification
864  theID = *IDcsi;
865  return kTRUE;
866  }
867  return kFALSE;
868 }
869 
870 
871 
874 
876 {
877  // Called by Identify() for particles stopping in etalon modules of Rings 10-17.
878 
879  KVIdentificationResult* IDcsi, *IDsilicsi, *IDsi75sili, *IDcisi75, *IDcicsi;
880  IDcsi = IDsilicsi = IDsi75sili = IDcisi75 = IDcicsi = 0;
881  if (StoppedInCsI()) {
882  IDcsi = GetIdentificationResult("CSI_R_L");
883  IDcicsi = GetIdentificationResult("CI_CSI");
884  IDsilicsi = GetIdentificationResult("SILI_CSI");
885  }
886  IDsi75sili = GetIdentificationResult("SI75_SILI");
887  IDcisi75 = GetIdentificationResult("CI_SI75");
890 
891  Bool_t haveCsI = IDcsi && IDcsi->IDOK;
892  Bool_t haveSiLiCsI = IDsilicsi && IDsilicsi->IDOK;
893  Bool_t haveChIoCsI = IDcicsi && IDcicsi->IDOK;
894  Bool_t haveSi75SiLi = IDsi75sili && IDsi75sili->IDOK;
895  Bool_t haveChIoSi75 = IDcisi75 && IDcisi75->IDOK;
896 
897  // Etalon telescope Si75/SiLi not concerned, only ChIo and CsI.
898  // Use standard coherency for rings 10-17
899  if ((!GetSiLi() || !GetSiLi()->Fired("Pany")) && (!GetSi75() || !GetSi75()->Fired("Pany")))
900  return CoherencyChIoCsI(theID);
901  if (haveCsI && !haveSiLiCsI && !haveSi75SiLi)
902  return CoherencyChIoCsI(theID);
903 
904  // Treat cases where particle hit etalon telescope
905  if (StoppedInCsI()) {
906  if (haveCsI) {
907  // gammas
908  if (IDcsi->IDcode == KVINDRACodeMask::kIDCode0) {
909  theID = *IDcsi;
910  return kTRUE;
911  }
912 
913  // successful CsI identification
914  // check (again) if particle passed through SiLi
915  // if SiLi did not fire but Si75 did, then we assume this particle
916  // just passed through ChIo-CsI while another particle stopped in Si75
917  if (!GetSiLi()->Fired("Pany") && GetSi75()->Fired("all")) {
918  fPileupSi75 = kTRUE; // need to create particle in ChIo-Si75
919  fUseFullChIoEnergyForCalib = kFALSE; // calculate ChIo energy for this particle
920  return CoherencyChIoCsI(theID);
921  }
922  theID = *IDcsi;
923  if (haveSi75SiLi) {
924  // check for heavy fragment in Si75-SiLi
925  if (IDsi75sili->Z > theID.Z) {
926  if (haveChIoSi75) {
927  // check we don't have a better identification in ChIo-Si75
928  if (IDcisi75->IDquality < IDsi75sili->IDquality && IDcisi75->Z > theID.Z) {
929  fPileupSi75 = kTRUE;
930  IDcisi75->SetComment("CsI identification with another particle stopped in Si75");
931  fUseFullChIoEnergyForCalib = kFALSE; // calculate ChIo energy for this particle
932  }
933  else {
934  fPileupSiLi = kTRUE;
935  IDsi75sili->SetComment("CsI identification with another particle stopped in SiLi");
936  fUseFullChIoEnergyForCalib = kFALSE; // calculate ChIo energy for this particle
937  }
938  }
939  }
940  }
941  else if (haveChIoSi75) {
942  // check for heavy fragment in ChIo-Si75
943  if (IDcisi75->Z > theID.Z) {
944  fPileupSi75 = kTRUE;
945  IDcisi75->SetComment("CsI identification with another particle stopped in Si75");
946  fUseFullChIoEnergyForCalib = kFALSE; // calculate ChIo energy for this particle
947  }
948  }
949  return kTRUE;
950  }
951  else if (haveSiLiCsI) {
952  theID = *IDsilicsi;
953  if (haveChIoSi75) {
954  // check for heavy fragment in ChIo-Si75
955  if (IDcisi75->Z > theID.Z) {
956  fPileupSi75 = kTRUE;
957  IDcisi75->SetComment("CsI identification with another particle stopped in Si75");
958  fUseFullChIoEnergyForCalib = kFALSE; // calculate ChIo energy for this particle
959  }
960  }
961  return kTRUE;
962  }
963  else if (haveChIoCsI) {
964  theID = *IDcicsi;
965  // fragment identified in ChIo-CsI
966  // therefore it did not cross the etalon telescopes
967  // (only Z=1 & 2 pass through SiLi)
969  return kTRUE;
970  }
971  }
972  else if (StoppedInSiLi()) {
973  if (haveSi75SiLi) {
974  theID = *IDsi75sili;
975  // check ChIo-Si75 id is coherent (either no id or Z<=this one)
976  if (haveChIoSi75) {
977  if (IDcisi75->Z > theID.Z) fPileupChIo = kTRUE;
978  }
979  return kTRUE;
980  }
981  else if (haveChIoSi75) {
982  theID = *IDcisi75;
983  return kTRUE;
984  }
985  }
986  else if (StoppedInSi75()) { // MFR march 2014 SiLi is not the real stopping detector
987  if (haveChIoSi75) {
988  theID = *IDcisi75;
989  return kTRUE;
990  } // end MFR march 2014
991  }
992 
993  return kFALSE;
994 }
995 
996 
997 
1016 
1018 {
1019  // INDRA-specific particle identification.
1020  // Here we attribute the Veda6-style general identification codes depending on the
1021  // result of KVReconstructedNucleus::Identify and the subcodes from the different
1022  // identification algorithms:
1023  // If the particle's mass A was NOT measured, we make sure that it is calculated
1024  // from the measured Z using the mass formula defined by default
1025  //
1026  //IDENTIFIED PARTICLES
1027  //Identified particles with ID code = 2 with subcodes 4 & 5
1028  //(masse hors limite superieure/inferieure) are relabelled
1029  //with kIDCode10 (identification entre les lignes CsI)
1030  //
1031  //UNIDENTIFIED PARTICLES
1032  //Unidentified particles receive the general ID code for non-identified particles (kIDCode14)
1033  //EXCEPT if their identification in CsI R-L gave subcodes 6 or 7
1034  //(Zmin) then they are relabelled "Identified" with IDcode = 9 (ident. incomplete dans CsI ou Phoswich (Z.min))
1035  //Their "identifying" telescope is set to the CsI ID telescope
1036 
1037  Obsolete("Identify", "1.13", "1.15");
1038 
1039 // KVReconstructedNucleus::Identify();
1040 
1041 // KVIdentificationResult partID;
1042 // Bool_t ok = kFALSE;
1043 
1044 // // INDRA coherency treatment
1045 // if (GetRingNumber() < 10) {
1046 // if (StoppedInCsI()) {
1047 // // particles stopping in CsI detectors on rings 1-9
1048 // // check coherency of CsI-R/L and Si-CsI identifications
1049 // ok = CoherencySiCsI(partID);
1050 // // we check that the ChIo contribution is sane:
1051 // // if no other particles hit this group, the Z given by the ChIoSi
1052 // // must be <= the Z found from Si-CsI or CsI-RL identification
1053 
1054 // //if(fCoherent && !fPileup)
1055 // fUseFullChIoEnergyForCalib = CoherencyChIoSiCsI(partID);
1056 // }
1057 // else {
1058 // // particle stopped in Si (=> ChIo-Si) or ChIo (=> Zmin)
1059 // Int_t id_no = 1;
1060 // KVIdentificationResult* pid = GetIdentificationResult(id_no);
1061 // while (pid->IDattempted) {
1062 // if (pid->IDOK) {
1063 // ok = kTRUE;
1064 // partID = *pid;
1065 // break;
1066 // }
1067 // ++id_no;
1068 // pid = GetIdentificationResult(id_no);
1069 // }
1070 // fUseFullChIoEnergyForCalib = !(GetChIo() && GetChIo()->GetNHits() > 1);
1071 // }
1072 // }
1073 // else {
1074 // //identification couronne 10 a 17
1075 // //Arret dans les CsI, coherence entre identification CsI RL et ChIo CsI
1076 
1077 // // if particle is alone in group, we can in principle attribute the ChIo energy
1078 // // to the energy lost by this particle alone
1079 // fUseFullChIoEnergyForCalib = !(GetChIo() && GetChIo()->GetNHits() > 1);
1080 // if (StoppedInCsI()) {
1081 
1082 // if (GetSiLi() || GetSi75()) /* etalon module */
1083 // ok = CoherencyEtalons(partID);
1084 // else
1085 // ok = CoherencyChIoCsI(partID);
1086 
1087 // }
1088 // else if (StoppedInChIo()) {
1089 // // particle stopped in ChIo (=> Zmin)
1090 // Int_t id_no = 1;
1091 // KVIdentificationResult* pid = GetIdentificationResult(id_no);
1092 // while (pid->IDattempted) {
1093 // if (pid->IDOK) {
1094 // ok = kTRUE;
1095 // partID = *pid;
1096 // break;
1097 // }
1098 // ++id_no;
1099 // pid = GetIdentificationResult(id_no);
1100 // }
1101 // partID.Print();
1102 // }
1103 // else {
1104 // // particle stopped in SiLi or Si75 (etalon modules)
1105 // ok = CoherencyEtalons(partID);
1106 // }
1107 
1108 // }
1109 // if (ok) {
1110 // SetIsIdentified();
1111 // KVIDTelescope* idt = (KVIDTelescope*)GetIDTelescopes()->FindObjectByType(partID.GetType());
1112 // if (!idt) {
1113 // Warning("Identify", "cannot find ID telescope with type %s", partID.GetType());
1114 // GetIDTelescopes()->ls();
1115 // partID.Print();
1116 // }
1117 // SetIdentifyingTelescope(idt);
1118 // SetIdentification(&partID);
1119 // }
1120 
1121 // if (IsIdentified()) {
1122 
1123 // /******* IDENTIFIED PARTICLES *******/
1124 // if (GetIdentifyingTelescope()->InheritsFrom("KVIDCsI")) { /**** CSI R-L IDENTIFICATION ****/
1125 
1126 // //Identified particles with ID code = 2 with subcodes 4 & 5
1127 // //(masse hors limite superieure/inferieure) are relabelled
1128 // //with kIDCode10 (identification entre les lignes CsI)
1129 
1130 // Int_t csi_subid = GetIDSubCode();
1131 // if (csi_subid == KVIDGCsI::kICODE4 || csi_subid == KVIDGCsI::kICODE5) {
1132 // SetIDCode(kIDCode10);
1133 // }
1134 
1135 // }
1136 
1137 // }
1138 // else {
1139 
1140 // /******* UNIDENTIFIED PARTICLES *******/
1141 
1142 // /*** general ID code for non-identified particles ***/
1143 // SetIDCode(kIDCode14);
1144 
1145 // KVIDCsI* idtel = (KVIDCsI*)GetIDTelescopes()->FindObjectByType("CSI_R_L");
1146 // if (idtel) {
1147 // //Particles remaining unidentified are checked: if their identification in CsI R-L gave subcodes 6 or 7
1148 // //(Zmin) then they are relabelled "Identified" with IDcode = 9 (ident. incomplete dans CsI ou Phoswich (Z.min))
1149 // //Their "identifying" telescope is set to the CsI ID telescope
1150 // Int_t csi_subid = GetIDSubCode("CSI_R_L");
1151 // if (csi_subid == KVIDGCsI::kICODE6 || csi_subid == KVIDGCsI::kICODE7) {
1152 // SetIsIdentified();
1153 // SetIDCode(kIDCode9);
1154 // SetIdentifyingTelescope(idtel);
1155 // }
1156 // }
1157 
1158 // }
1159 }
1160 
1161 
1162 
1163 
1169 
1171 {
1172  // Calculate and set the energy of a (previously identified) reconstructed particle.
1173  // For particles in rings 10-17
1174  // For particles in rings 1-9, we use the results of the ChIo-Si-CsI coherency tests in order
1175  // to calculate their energy.
1176 
1177 
1178  if (GetRingNumber() <= 9)
1180  else
1182 
1183 
1184  SetIsCalibrated();
1185  //add correction for target energy loss - moving charged particles only!
1186  Double_t E_targ = 0.;
1187  if (GetZ() && GetEnergy() > 0) {
1188  E_targ = gMultiDetArray->GetTargetEnergyLossCorrection(this);
1189  SetTargetEnergyLoss(E_targ);
1190  }
1191  Double_t E_tot = GetEnergy() + E_targ;
1192  SetEnergy(E_tot);
1193  // set particle momentum from telescope dimensions (random)
1195  CheckCsIEnergy();
1196 
1197 }
1198 
1199 
1200 
1203 
1205 {
1206  // no calibration is performed for gammas
1208  return;
1209 }
1210 
1211 
1212 
1216 
1218 {
1219  // use energy of CsI calculated using the Z & A of the CsI identification
1220  // to calculate the energy deposited by the neutron
1222  KVNucleus tmp(IDcsi->Z, IDcsi->A);
1223  if (GetCsI() && GetCsI()->IsCalibrated()) {
1224  fECsI = GetCsI()->GetCorrectedEnergy(&tmp, -1., kFALSE);
1225  SetEnergy(fECsI);
1226  SetECode(KVINDRACodeMask::kECode2); // not a real energy measure
1227  }
1228  else {
1230  }
1231 }
1232 
1233 
1234 
1240 
1242 {
1243  // Beryllium-8 = 2 alpha particles of same energy
1244  // We halve the total light output of the CsI to calculate the energy of 1 alpha
1245  // Then multiply resulting energy by 2
1246  // Note: fECsI is -ve, because energy is calculated not measured
1247  Double_t half_light = GetCsI()->GetDetectorSignalValue("TotLight") * 0.5;
1248  KVNucleus tmp(2, 4);
1249  fECsI = -2.*GetCsI()->GetCorrectedEnergy(&tmp, half_light, kFALSE);
1251 }
1252 
1253 
1254 
1258 
1260 {
1261  // calculate fESi from fECsI
1262  // returns kTRUE if OK
1265  fESi = GetSi()->GetCorrectedEnergy(this, e0);
1266  if (fESi <= 0) {
1267  // can't calculate fESi from CsI energy - bad
1269  return kFALSE;
1270  }
1271  else {
1272  // calculated energy: negative
1273  fESi = -TMath::Abs(fESi);
1275  }
1276  return kTRUE;
1277 }
1278 
1279 
1280 
1314 
1316 {
1317  // Special calibration for particles in rings 1 to 9
1318  // We set the energy calibration code for the particle here
1319  // kECode0 = no calibration (e.g. gammas)
1320  // kECode1 = everything OK
1321  // kECode2 = small warning, for example if energy loss in a detector is calculated
1322  // kECode15 = bad, calibration is no good
1323  // The contributions from ChIo, Si, and CsI are stored in member variables fEChIo, fESi, fECsI
1324  // If the contribution is calculated rather than measured (see below), it is stored as a negative value.
1325  // NOTE: in no case do we ever calculate an energy for uncalibrated detector using measured energy
1326  // loss in the detector placed in front (i.e. calculate ECsI from deSi, or calculate ESi
1327  // from deChIo) as this gives wildly varying (mostly false) results.
1328  //
1329  // For gammas (IDCODE=0): no calibration performed, energy will be zero, ECODE=kECode0
1330  // For neutrons (IDCODE=1): if CsI is calibrated, we use the CsI light response to calculate
1331  // the equivalent energy for a proton.
1332  // For particles stopping in the CsI detector (IDCODE=2 or 3):
1333  // - for "8Be" we use half the CsI light output to calculate 4He kinetic energy which is then doubled
1334  // (we assume two 4He of identical energy), and ECODE=kECode2 (calculated)
1335  // - if no calibration exists for the CsI, we cannot calibrate the particle (ECODE=kECode0)
1336  // - if calibrated CsI energy is bizarre (<=0), we cannot calibrate the particle (ECODE=kECode15)
1337  // - if the Silicon detector is not calibrated, or if coherency analysis indicates a pile-up
1338  // in the silicon or other inconsistency, the Silicon energy is calculated from the calibrated
1339  // CsI energy (ECODE=kECode2)
1340  // - if the Ionisation Chamber is not calibrated, or if coherency analysis indicates a pile-up
1341  // in the ChIo or other inconsistency, this contribution is calculated using the total
1342  // cumulated energy measured in the CsI and/or Silicon detectors (ECODE=kECode2)
1343  //
1344  // For particles stopping in the Silicon detector (IDCODE=3, 4 or 5):
1345  // - if no calibration exists for the Silicon, we cannot calibrate the particle (ECODE=kECode0)
1346  // - if the Ionisation Chamber is not calibrated, or if coherency analysis indicates a pile-up
1347  // in the ChIo or other inconsistency, this contribution is calculated using the total
1348  // cumulated energy measured in the CsI and/or Silicon detectors (ECODE=kECode2)
1349 
1350  fECsI = fESi = fEChIo = 0;
1351 
1352  if (GetCodes().TestIDCode(KVINDRACodeMask::kIDCode_Gamma)) {
1354  return;
1355  }
1356  if (GetCodes().TestIDCode(KVINDRACodeMask::kIDCode_Neutron)) {
1358  return;
1359  }
1360 
1362 
1363  Bool_t stopped_in_silicon = kTRUE;
1364 
1365  if (GetCsI()) {
1366  stopped_in_silicon = kFALSE;
1367  if (GetCsI()->IsCalibrated()) {
1368  /* CSI ENERGY CALIBRATION */
1369  if (GetCodes().TestIDCode(KVINDRACodeMask::kIDCode_CsI) && GetZ() == 4 && GetA() == 8) {
1371  }
1372  else
1373  fECsI = GetCsI()->GetCorrectedEnergy(this, -1., kFALSE);
1374  }
1375  else {
1376  SetNoCalibrationStatus();// no CsI calibration - no calibration performed
1377  return;
1378  }
1379  if (GetCodes().TestECode(KVINDRACodeMask::kECode1) && fECsI <= 0) { // for kECode2, fECsI is always <0
1380  //Info("Calib", "ECsI = %f",fECsI);
1381  SetBadCalibrationStatus();// problem with CsI energy - no calibration
1382  return;
1383  }
1384  }
1385  if (GetSi()) {
1386  /* SILICIUM ENERGY CONTRIBUTION */
1387  // if fPileup = kTRUE, the Silicon energy appears to include a contribution from another particle
1388  // therefore we have to estimate the silicon energy for this particle using the CsI energy
1389  // if fCoherent = kFALSE, the Silicon energy is too small to be consistent with the CsI identification,
1390  // therefore we have to estimate the silicon energy for this particle using the CsI energy
1391 
1392  if (!fPileup && fCoherent && GetSi()->IsCalibrated()) {
1393  // all is apparently well. use full energy deposited in silicon.
1394  Bool_t si_transmission = kTRUE;
1395  if (stopped_in_silicon) {
1396  si_transmission = kFALSE;
1397  }
1398  else {
1400  }
1401  fESi = GetSi()->GetCorrectedEnergy(this, -1., si_transmission);
1402  if (fESi <= 0) {
1403  // problem with silicon calibration
1404  if (!stopped_in_silicon && (TMath::Abs(fECsI) > 0.0)) {
1405  if (!CalculateSiliconDEFromResidualEnergy()) return;
1406  }
1407  else {
1408  // stopped in Si with bad Si calibration - no good
1410  return;
1411  }
1412  }
1413  }
1414  else {
1415  if (!stopped_in_silicon) {
1416  if (!CalculateSiliconDEFromResidualEnergy()) return;
1417  }
1418  else {
1419  // cannot calibrate particle stopping in silicon in this case
1421  return;
1422  }
1423  }
1424 
1425  }
1426  if (GetChIo()) {
1427  /* CHIO ENERGY CONTRIBUTION */
1428  // if fUseFullChIoEnergyForCalib = kFALSE, we have to estimate the ChIo energy for this particle
1431  // all is apparently well
1432  if (!StoppedInChIo()) {
1433  GetChIo()->SetEResAfterDetector(ERES);
1434  fEChIo = GetChIo()->GetCorrectedEnergy(this);
1435  }
1436  else {
1437  // particle stopped in chio, not in transmission
1438  fEChIo = GetChIo()->GetCorrectedEnergy(this, -1., kFALSE);
1439  }
1440  if (fEChIo < 0.) {
1441  // bad chio calibration
1442  if (!StoppedInChIo() && (ERES > 0.0)) {
1444  }
1445  }
1446  }
1447  else {
1448  if (!StoppedInChIo()) {
1450  }
1451  else {
1452  // particle stopped in ChIo, no calibration available
1454  return;
1455  }
1456  }
1457  }
1459 }
1460 
1461 
1462 
1466 
1468 {
1469  // Etalon modules
1470  // calculate fESiLi from residual CsI energy
1471  Double_t e0 = GetSiLi()->GetDeltaEFromERes(GetZ(), GetA(), ERES);
1472  GetSiLi()->SetEResAfterDetector(ERES);
1473  fESiLi = GetSiLi()->GetCorrectedEnergy(this, e0);
1474  fESiLi = -TMath::Abs(fESiLi);
1476 }
1477 
1478 
1479 
1483 
1485 {
1486  // Etalon modules
1487  // calculate fESi75 from residual CsI+SiLi energy
1488  Double_t e0 = GetSi75()->GetDeltaEFromERes(GetZ(), GetA(), ERES);
1489  GetSi75()->SetEResAfterDetector(ERES);
1490  fESi75 = GetSi75()->GetCorrectedEnergy(this, e0);
1491  fESi75 = -TMath::Abs(fESi75);
1493 }
1494 
1495 
1496 
1499 
1501 {
1502  // calculate fEChIo from residual energy
1503  Double_t e0 = GetChIo()->GetDeltaEFromERes(GetZ(), GetA(), ERES);
1504  GetChIo()->SetEResAfterDetector(ERES);
1505  fEChIo = GetChIo()->GetCorrectedEnergy(this, e0);
1506  fEChIo = -TMath::Abs(fEChIo);
1508 }
1509 
1510 
1511 
1521 
1523 {
1524  // Special calibration for particles in rings 10 to 17
1525  // We set the energy calibration code for the particle here
1526  // kECode0 = no calibration (e.g. gammas)
1527  // kECode1 = everything OK
1528  // kECode2 = small warning, for example if energy loss in a detector is calculated
1529  // kECode15 = bad, calibration is no good
1530  // The contributions from ChIo & CsI are stored in member variables fEChIo, fECsI
1531  // If the contribution is calculated rather than measured, it is stored as a negative value
1532 
1533  fECsI = fEChIo = fESi75 = fESiLi = 0;
1534  if (GetCodes().TestIDCode(KVINDRACodeMask::kIDCode_Gamma)) {
1536  return;
1537  }
1538  // change fUseFullChioenergyforcalib for "coherency" particles
1539  // we assume they are calibrated after all other particles in group have
1540  // been identified, calibrated, and their energy contributions removed
1541  // from the ChIo
1542  if (GetCodes().TestIDCode(KVINDRACodeMask::kIDCode6) || GetCodes().TestIDCode(KVINDRACodeMask::kIDCode7) || GetCodes().TestIDCode(KVINDRACodeMask::kIDCode8))
1544 
1546  Bool_t stopped_in_chio = kTRUE;
1547  if (GetCsI()) {
1548  stopped_in_chio = kFALSE;
1549  /* CSI ENERGY CALIBRATION */
1550  if (GetCodes().TestIDCode(KVINDRACodeMask::kIDCode_CsI) && GetZ() == 4 && GetA() == 8) {
1552  }
1553  else
1554  fECsI = GetCsI()->GetCorrectedEnergy(this, -1., kFALSE);
1555 
1556  if (fECsI <= 0) {
1557  SetBadCalibrationStatus();// bad - no CsI energy
1558  return;
1559  }
1560  }
1562  if (GetSiLi()) {
1563  Double_t ERES = fECsI;
1564  if (!fPileupSiLi && GetSiLi()->IsCalibrated()) {
1565  Bool_t si_transmission = kTRUE;
1566  if (StoppedInSiLi()) {
1567  si_transmission = kFALSE;
1568  }
1569  else {
1570  GetSiLi()->SetEResAfterDetector(ERES);
1571  }
1572  fESiLi = GetSiLi()->GetCorrectedEnergy(this, -1., si_transmission);
1573  if (fESiLi <= 0) {
1574  if (!StoppedInSiLi() && ERES > 0.0) {
1576  }
1577  else {
1579  return;
1580  }
1581  }
1582  }
1583  else {
1585  }
1586  }
1587  if (GetSi75()) {
1588  Double_t ERES = fECsI + TMath::Abs(fESiLi);
1589  if (!fPileupSi75 && !fPileupSiLi && GetSi75()->IsCalibrated()) {
1590  Bool_t si_transmission = kTRUE;
1591  if (StoppedInSi75()) {
1592  si_transmission = kFALSE;
1593  }
1594  else {
1595  GetSi75()->SetEResAfterDetector(ERES);
1596  }
1597  fESi75 = GetSi75()->GetCorrectedEnergy(this, -1., si_transmission);
1598  if (fESi75 <= 0) {
1599  if (!StoppedInSi75() && ERES > 0.0) {
1601  }
1602  else {
1604  return;
1605  }
1606  }
1607  }
1608  else {
1610  }
1611  }
1612  }
1613  if (GetChIo()) {
1614  /* IONISATION CHAMBER ENERGY CONTRIBUTION */
1615  // if fUseFullChIoEnergyForCalib = kFALSE, ChIo was hit by other particles in group
1616  // therefore we have to estimate the ChIo energy for this particle using the CsI energy
1617  // if fPileupChIo = kTRUE, there appears to be another particle stopped in the ChIo
1618  // therefore we have to estimate the ChIo energy for this particle using the CsI energy
1621  // all is apparently well
1622  Bool_t ci_transmission = kTRUE;
1623  if (stopped_in_chio) {
1624  ci_transmission = kFALSE;
1625  }
1626  else {
1627  GetChIo()->SetEResAfterDetector(ERES);
1628  }
1629  fEChIo = GetChIo()->GetCorrectedEnergy(this, -1., ci_transmission);
1630  if (fEChIo <= 0) {
1631  if (!stopped_in_chio && ERES > 0) {
1633  }
1634  }
1635  }
1636  else {
1637  if (!stopped_in_chio && ERES > 0) {
1639  }
1640  }
1641  }
1642 
1643 
1645 }
1646 
1647 
1648 
1649 
1656 
1658 {
1659  // Check calculated CsI energy loss of particle.
1660  // If it is greater than the maximum theoretical energy loss
1661  // (depending on the length of CsI, the Z & A of the particle)
1662  // we set the energy calibration code to kECode3 (historical VEDA code
1663  // for particles with E_csi > E_max_csi)
1664 
1665  KVDetector* csi = GetCsI();
1666  if (csi && GetZ() > 0 && GetZ() < 3 && (csi->GetEnergy() > csi->GetMaxDeltaE(GetZ(), GetA()))) SetECode(KVINDRACodeMask::kECode3);
1667 }
1668 
1669 
1670 
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:177
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)
void SetACQParams();
Definition: KVCsI.cpp:87
const Char_t * GetDataSetEnv(const Char_t *type, const Char_t *defval="") const
Definition: KVDataSet.cpp:767
Base class for detector geometry description.
Definition: KVDetector.h:160
virtual Double_t GetMaxDeltaE(Int_t Z, Int_t A)
virtual Double_t GetEnergy() const
Definition: KVDetector.h:349
Double_t GetDetectorSignalValue(const KVString &type, const KVNameValueList &params="") const
Definition: KVDetector.h:493
virtual void SetEResAfterDetector(Double_t e)
Definition: KVDetector.h:630
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:811
@ 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="")
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.
Bool_t StoppedInChIo()
Returns kTRUE if particle stopped in ChIo detector.
void CalculateSi75DEFromResidualEnergy(Double_t ERES)
virtual Bool_t CoherencyEtalons(KVIdentificationResult &theID)
Called by Identify() for particles stopping in etalon modules of Rings 10-17.
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
UInt_t GetRingNumber(void) const
virtual void Clear(Option_t *t="")
reset nucleus' properties
virtual void Copy(TObject &) const
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.
void Print(Option_t *option="") const
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()
UInt_t GetModuleNumber(void) const
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
void SetECode(UChar_t code_mask)
Float_t fESi75
si75 contribution to energy
Bool_t StoppedInSiLi()
Returns kTRUE if particle stopped in Si detector.
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:126
Int_t GetA() const
Definition: KVNucleus.cpp:802
Int_t GetZ() const
Return the number of proton / atomic number.
Definition: KVNucleus.cpp:773
Double_t GetTheta() const
Definition: KVParticle.h:680
Double_t GetEnergy() const
Definition: KVParticle.h:621
Double_t GetPhi() const
Definition: KVParticle.h:688
void SetEnergy(Double_t e)
Definition: KVParticle.h:599
Nuclei reconstructed from data measured by a detector array .
KVDetector * GetDetector(const TString &label) const
virtual Double_t GetTargetEnergyLoss() const
virtual void Print(Option_t *option="") const
virtual void Copy(TObject &) const
KVIdentificationResult * GetIdentificationResult(Int_t i)
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")
virtual void Clear(Option_t *option="")
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:61
2mm + 40um dead zone Si(Li) detector for INDRA etalon telescopes
Definition: KVSilicon.h:79
Silicon detectors of the INDRA array.
Definition: KVSilicon.h:19
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)