KaliVeda  1.12/06
Heavy-Ion Analysis Toolkit
KVINDRAGroupReconstructor.cpp
Go to the documentation of this file.
1 //Created by KVClassFactory on Wed Feb 21 13:42:47 2018
2 //Author: John Frankland,,,
3 
5 #include <KVIDGCsI.h>
6 #include <KVIDINDRACsI.h>
7 #include <KVINDRADetector.h>
8 
10 
11 
12 
27 {
28  // \param traj trajectory currently being scanned
29  // \param node current detector on trajectory to test
30  // \returns pointer to a new reconstructed particle added to this group's event; nullptr if nothing is to be done
31  //
32  // Specialised particle reconstruction for INDRA data.
33  //
34  // If the fired detector in question is a CsI we check, if identification is available, whether
35  // this corresponds to a 'gamma'. If so we count it (event parameter "INDRA_GAMMA_MULT")
36  // and add the name of the detector to the parameter "INDRA_GAMMA_DETS"
37  // but do not begin the reconstruction of a particle. This allows to continue along the trajectory and
38  // directly reconstruct any charged particle which may stop in the Si detector in coincidence with
39  // a 'gamma' in the CsI.
40 
41  if (node->GetDetector()->IsType("CSI")) {
42 
43  if (node->GetDetector()->Fired(GetPartSeedCond())) {
44 
45  ++nfireddets;
46  KVIDINDRACsI* idt = (KVIDINDRACsI*)traj->GetIDTelescopes()->FindObjectByType("CSI_R_L");
47  if (idt) {
48 
50  if (idt->IsReadyForID()) {
51 
52  idt->Identify(&idr);
53  if (idr.IDOK && (idr.IDcode == KVINDRA::IDCodes::ID_GAMMA || idr.IDquality == KVIDGCsI::kICODE10)) { // gamma in CsI
54  GetEventFragment()->GetParameters()->IncrementValue("INDRA_GAMMA_MULT", 1);
55  GetEventFragment()->GetParameters()->IncrementValue("INDRA_GAMMA_DETS", node->GetName());
56  node->GetDetector()->SetAnalysed();
57  return nullptr;
58  }
59 
60  // if we arrive here, CSI_R_L identification for the particle has been performed and
61  // the result is not a gamma (which are rejected; no particle is reconstructed).
62  // as the coordinates in the identification map are randomized (KVACQParamSignal),
63  // we do not want to perform a second identification attempt in KVINDRAGroupReconstructor::IdentifyParticle:
64  // the results may not be the same, and for particles close to the threshold a charged particle
65  // identified here may be subsequently identified as a gamma in a second identification attempt,
66  // leading to the incoherency that there are gamma particles (IDcode=KVINDRA::IDCodes::ID_GAMMA)
67  // in the final reconstructed event.
68  // therefore in this case we add a new particle to the event, and copy the results of this
69  // first identification into the particle, with IDR->IDattempted=true, so that in
70  // KVINDRAGroupReconstructor::IdentifyParticle the CSI identification will not be redone.
71 
72  auto new_part = GetEventFragment()->AddParticle();
73  *(new_part->GetIdentificationResult(1)) = idr;
74  return new_part;
75  }
76  }
77  return GetEventFragment()->AddParticle();
78  }
79  return nullptr;
80  }
82 }
83 
84 
85 
87 
89 {
90  static int i = 0;
92  for (KVEvent::Iterator it = GetEventFragment()->begin(); it != GetEventFragment()->end(); ++it) {
93 
94  KVReconstructedNucleus* d = it.get_pointer<KVReconstructedNucleus>();
95 
96  if (!d->IsIdentified()) d->SetIDCode(KVINDRA::IDCodes::NO_IDENTIFICATION); // unidentifiable particle
97  else {
98  if (d->GetIDCode() == KVINDRA::IDCodes::ID_CSI_PSA && d->GetZ() == 0) {
99  ++i;
100  std::cout << "\n\n";
101  std::cout << " GAMMA #" << i << "\n\n";
102  d->Print();
103  std::cout << "\n\n";
104  auto traj = (KVGeoDNTrajectory*)d->GetStoppingDetector()->GetNode()->GetTrajectories()->First();
105  KVIDINDRACsI* idt = (KVIDINDRACsI*)traj->GetIDTelescopes()->FindObjectByType("CSI_R_L");
106  std::cout << idt << std::endl;
107  std::cout << "Type: " << d->GetStoppingDetector()->GetType() << std::endl;
108  std::cout << "Fired: " << d->GetStoppingDetector()->Fired(GetPartSeedCond()) << std::endl;
109  std::cout << "ReadyforID: " << d->GetIdentifyingTelescope()->IsReadyForID() << std::endl;
110  std::cout << "\n\n";
111  exit(1);
112  }
113  }
114  }
115 }
116 
117 
118 
137 
139 {
140  // INDRA-specific particle identification.
141  // Here we attribute the Veda6-style general identification codes depending on the
142  // result of KVReconstructedNucleus::Identify and the subcodes from the different
143  // identification algorithms:
144  // If the particle's mass A was NOT measured, we make sure that it is calculated
145  // from the measured Z using the mass formula defined by default
146  //
147  //IDENTIFIED PARTICLES
148  //Identified particles with ID code = 2 with subcodes 4 & 5
149  //(masse hors limite superieure/inferieure) are relabelled
150  //with kIDCode10 (identification entre les lignes CsI)
151  //
152  //UNIDENTIFIED PARTICLES
153  //Unidentified particles receive the general ID code for non-identified particles (kIDCode14)
154  //EXCEPT if their identification in CsI R-L gave subcodes 6 or 7
155  //(Zmin) then they are relabelled "Identified" with IDcode = 9 (ident. incomplete dans CsI ou Phoswich (Z.min))
156  //Their "identifying" telescope is set to the CsI ID telescope
157 
159  // if a successful identification has occured, identifying_telescope & partID are now set
160  // and the particle has IsIdentified()=true
161 
162  // INDRA coherency treatment
163  PART.SetParameter("Coherent", kTRUE);
164  PART.SetParameter("Pileup", kFALSE);
165  PART.SetParameter("UseFullChIoEnergyForCalib", kTRUE);
166  Bool_t ok = DoCoherencyAnalysis(PART);
167 
168  if (ok) { // identification may change here due to coherency analysis
169  PART.SetIsIdentified();
171  } // if not ok, do we need to unset any previously identified particle?
172 
173  if (PART.IsIdentified()) {
174 
175  /******* IDENTIFIED PARTICLES *******/
176  if (partID.IsType("CSI_R_L")) { /**** CSI R-L IDENTIFICATION ****/
177 
178  //Identified particles with ID code = 2 with subcodes 4 & 5
179  //(masse hors limite superieure/inferieure) are relabelled
180  //with kIDCode10 (identification entre les lignes CsI)
181 
182  Int_t grid_code = partID.IDquality;
183  if (grid_code == KVIDGCsI::kICODE4 || grid_code == KVIDGCsI::kICODE5) {
184  partID.IDcode = KVINDRA::IDCodes::ID_CSI_MASS_OUT_OF_RANGE;
186  }
187 
188  }
189 
190  }
191  else {
192 
193  /******* UNIDENTIFIED PARTICLES *******/
194 
195  /*** general ID code for non-identified particles ***/
196  PART.SetIDCode(KVINDRA::IDCodes::NO_IDENTIFICATION);
197 #ifndef WITH_CPP11
198  std::map<std::string, KVIdentificationResult*>::iterator csirl = id_by_type.find("CSI_R_L");
199 #else
200  auto csirl = id_by_type.find("CSI_R_L");
201 #endif
202  if (csirl != id_by_type.end()) {
203  //Particles remaining unidentified are checked: if their identification in CsI R-L gave subcodes 6 or 7
204  //(Zmin) then they are relabelled "Identified" with IDcode = 9 (ident. incomplete dans CsI ou Phoswich (Z.min))
205  //
206  //Particles with ID code = 2 with subcodes 4 & 5 (masse hors limite superieure/inferieure) are relabelled
207  //with kIDCode10 (identification entre les lignes CsI)
208  //
209  //Their "identifying" telescope is set to the CsI ID telescope
210  if (csirl->second->IDattempted) {
211  if (csirl->second->IDquality == KVIDGCsI::kICODE6 || csirl->second->IDquality == KVIDGCsI::kICODE7) {
212  PART.SetIsIdentified();
213  csirl->second->IDcode = KVINDRA::IDCodes::ID_CSI_FRAGMENT;
214  partID = *(csirl->second);
217  }
218  else if (csirl->second->IDquality == KVIDGCsI::kICODE4 || csirl->second->IDquality == KVIDGCsI::kICODE5) {
219  PART.SetIsIdentified();
220  csirl->second->IDcode = KVINDRA::IDCodes::ID_CSI_MASS_OUT_OF_RANGE;
221  partID = *(csirl->second);
224  }
225  }
226  }
227 
228  }
229 }
230 
231 
232 
239 
241 {
242  // calculate fEChIo from residual energy
243  //
244  // returns kFALSE if it doesn't work, and sets particle bad calibration status
245  //
246  // returns kTRUE if it works, and sets calib status to SOME_ENERGY_LOSSES_CALCULATED
247 
248  Double_t e0 = theChio->GetDeltaEFromERes(n->GetZ(), n->GetA(), ERES);
251  if (fEChIo <= 0) {
253  fEChIo = 0;
254  return kFALSE;
255  }
257  n->SetECode(KVINDRA::ECodes::SOME_ENERGY_LOSSES_CALCULATED);
258  return kTRUE;
259 }
260 
261 
262 
268 
270 {
271  // Calculate and set the energy of a (previously identified) reconstructed particle
272  //
273  // This is only possible for correctly identified particles.
274  // We exclude IDCODE9 particles (Zmin in CsI-RL)
275 
276  fEChIo = fESi = fECsI = 0;
277 
278  print_part = false;
279 
281 
282  if (PART->GetIDCode() != KVINDRA::IDCodes::ID_CSI_FRAGMENT && PART->GetIDCode() != KVINDRA::IDCodes::ID_CSI_MASS_OUT_OF_RANGE) {
283  // this status may be modified depending on what happens in DoCalibration
284  SetCalibrationStatus(*PART, KVINDRA::ECodes::NORMAL_CALIBRATION);
285  DoCalibration(PART);
286  }
287 
288  PART->SetParameter("INDRA.ECHIO", fEChIo);
289  PART->SetParameter("INDRA.ESI", fESi);
290  PART->SetParameter("INDRA.ECSI", fECsI);
291  //add correction for target energy loss - moving charged particles only!
292  Double_t E_targ = 0.;
293  if (PART->GetZ() && PART->GetEnergy() > 0) {
294  E_targ = GetTargetEnergyLossCorrection(PART);
295  PART->SetTargetEnergyLoss(E_targ);
296  }
297  Double_t E_tot = PART->GetEnergy() + E_targ;
298  PART->SetEnergy(E_tot);
299  // set particle momentum from telescope dimensions (random)
301  CheckCsIEnergy(PART);
302 
303  //if(print_part) PART->Print();
304 }
305 
306 
307 
313 
315 {
316  // Beryllium-8 = 2 alpha particles of same energy
317  // We halve the total light output of the CsI to calculate the energy of 1 alpha
318  // Then multiply resulting energy by 2
319  // Note: fECsI is -ve, because energy is calculated not measured
320 
321  auto csi = GetCsI(n);
322  Double_t half_light = csi->GetDetectorSignalValue("TotLight") * 0.5;
323  KVNucleus tmp(2, 4);
324  double ecsi = 2.*csi->GetCorrectedEnergy(&tmp, half_light, kFALSE);
325  if (ecsi > 0) {
326  SetCalibrationStatus(*n, KVINDRA::ECodes::SOME_ENERGY_LOSSES_CALCULATED);
327  // calculated energy returned as negative value
328  return -ecsi;
329  }
331  return 0;
332 }
333 
334 
335 
342 
344 {
345  // Check calculated CsI energy loss of particle.
346  // If it is greater than the maximum theoretical energy loss
347  // (depending on the length of CsI, the Z & A of the particle)
348  // we set the energy calibration code to 3 (historical VEDA code
349  // for particles with E_csi > E_max_csi)
350 
351  KVDetector* csi = GetCsI(n);
352  if (csi && (n->GetZ() > 0) && (n->GetZ() < 3) && (csi->GetDetectorSignalValue("Energy", Form("Z=%d,A=%d", n->GetZ(), n->GetA())) > csi->GetMaxDeltaE(n->GetZ(), n->GetA()))) {
353  n->SetECode(KVINDRA::ECodes::WARNING_CSI_MAX_ENERGY);
354  }
355 }
356 
357 
358 
int Int_t
ClassImp(KVPartitionList) void KVPartitionList
Initialisation.
#define d(i)
const Bool_t kFALSE
bool Bool_t
double Double_t
const Bool_t kTRUE
char * Form(const char *fmt,...)
virtual Bool_t IsType(const Char_t *typ) const
Definition: KVBase.h:178
Base class for detector geometry description, interface to energy-loss calculations.
Definition: KVDetector.h:121
virtual Double_t GetMaxDeltaE(Int_t Z, Int_t A)
Double_t GetDetectorSignalValue(const TString &type, const KVNameValueList &params="") const
Definition: KVDetector.h:426
virtual void SetEResAfterDetector(Double_t e)
Definition: KVDetector.h:576
virtual Double_t GetDeltaEFromERes(Int_t Z, Int_t A, Double_t Eres)
virtual Double_t GetCorrectedEnergy(KVNucleus *, Double_t e=-1., Bool_t transmission=kTRUE)
Definition: KVDetector.cpp:949
Iterator end() const
Definition: KVEvent.h:428
Path taken by particles through multidetector geometry.
const KVSeqCollection * GetIDTelescopes() const
Information on relative positions of detectors & particle trajectories.
virtual KVReconstructedNucleus * ReconstructTrajectory(const KVGeoDNTrajectory *traj, const KVGeoDetectorNode *node)
KVIDTelescope * identifying_telescope
telescope which identified current particle
std::unordered_map< std::string, KVIdentificationResult * > id_by_type
identification results by type for current particle
KVReconstructedEvent * GetEventFragment() const
virtual void IdentifyParticle(KVReconstructedNucleus &PART)
Double_t GetTargetEnergyLossCorrection(KVReconstructedNucleus *ion)
void SetCalibrationStatus(KVReconstructedNucleus &PART, UShort_t code)
TString GetPartSeedCond() const
KVIdentificationResult partID
identification to be applied to current particle
virtual Bool_t Identify(KVIdentificationResult *, Double_t x=-1., Double_t y=-1.)
Base class for all detectors or associations of detectors in array which can identify charged particl...
Definition: KVIDTelescope.h:88
virtual Bool_t IsReadyForID()
Reconstruct particles in INDRA groups.
void SetNoCalibrationStatus(KVReconstructedNucleus *n)
virtual void DoCalibration(KVReconstructedNucleus *)=0
void IdentifyParticle(KVReconstructedNucleus &PART)
Bool_t CalculateChIoDEFromResidualEnergy(KVReconstructedNucleus *n, Double_t ERES)
double DoBeryllium8Calibration(KVReconstructedNucleus *n)
virtual bool DoCoherencyAnalysis(KVReconstructedNucleus &)=0
void CalibrateParticle(KVReconstructedNucleus *PART)
void CheckCsIEnergy(KVReconstructedNucleus *n)
KVDetector * GetCsI(KVReconstructedNucleus *n)
void SetBadCalibrationStatus(KVReconstructedNucleus *n)
KVDetector * theChio
the ChIo of the group
Full result of one attempted particle identification.
Bool_t IDOK
general quality of identification, =kTRUE if acceptable identification made
Int_t IDquality
specific quality code returned by identification procedure
Int_t IDcode
a general identification code for this type of identification
Description of properties and kinematics of atomic nuclei.
Definition: KVNucleus.h:125
Int_t GetZ() const
Return the number of proton / atomic number.
Definition: KVNucleus.cpp:770
Double_t GetEnergy() const
Definition: KVParticle.h:582
void SetParameter(const Char_t *name, ValType value) const
Definition: KVParticle.h:739
void SetEnergy(Double_t e)
Definition: KVParticle.h:560
Nuclei reconstructed from data measured by a detector array ,.
const KVReconNucTrajectory * GetReconstructionTrajectory() const
void SetIdentification(KVIdentificationResult *, KVIDTelescope *)
virtual Int_t GetIDCode() const
virtual void SetTargetEnergyLoss(Double_t e)
virtual void GetAnglesFromReconstructionTrajectory(Option_t *opt="random")
virtual TObject * FindObjectByType(const Char_t *) const
const Int_t n
Double_t Abs(Double_t d)