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