KaliVeda
Toolkit for HIC analysis
KVDetector.cpp
1 #include "KVDetector.h"
2 #include "Riostream.h"
3 #include "TROOT.h"
4 #include "TRandom3.h"
5 #include "TBuffer.h"
6 #include "KVUnits.h"
7 #include "KVTelescope.h"
8 #include "KVGroup.h"
9 #include "KVCalibrator.h"
10 #include "TPluginManager.h"
11 #include "TObjString.h"
12 #include "TClass.h"
13 /*** geometry ***/
14 #include "TGeoVolume.h"
15 #include "TGeoManager.h"
16 #include "TGeoMatrix.h"
17 #include "TGeoBBox.h"
18 #include "TGeoArb8.h"
19 #include "TGeoTube.h"
20 #include "KVCalibratedSignal.h"
21 #include "KVDetectorSignalExpression.h"
22 #include "KVZDependentCalibratedSignal.h"
23 
24 #include <TGeoPhysicalNode.h>
25 #include <TGraph.h>
26 
27 using namespace std;
28 
30 
31 
33 
34 
37 
39 {
40  //default initialisations
41  fCalibrators = 0;
42  fParticles = 0;
43  fCalWarning = 0;
44  fAbsorbers = new KVList;
45  fActiveLayer = nullptr;
46  fIDTelescopes = new KVList(kFALSE);
47  fIDTelescopes->SetCleanup(kTRUE);
48  fIDTelAlign = new KVList(kFALSE);
49  fIDTelAlign->SetCleanup(kTRUE);
50  fIDTele4Ident = 0;
51  fIdentP = fUnidentP = 0;
52  fTotThickness = 0.;
53  fDepthInTelescope = 0.;
54  fELossF = fEResF = fRangeF = 0;
55  fEResforEinc = -1.;
56  fAlignedDetectors[0] = 0;
57  fAlignedDetectors[1] = 0;
58  fSimMode = kFALSE;
59  fPresent = kTRUE;
60  fDetecting = kTRUE;
61  fParentStrucList.SetCleanup();
62  fSingleLayer = kTRUE;
63  fNode.SetDetector(this);
64  // detector owns any signals which are defined for it
65  fDetSignals.SetOwner();
66  // adding a new signal with the same name as an existing one
67  // will delete the existing signal and replace it
68  fDetSignals.ReplaceObjects();
69 }
70 
71 
72 
75 
77 {
78 //default ctor
79  init();
80  fDetCounter++;
81  SetName(Form("Det_%d", fDetCounter));
82 }
83 
84 
85 
88 
90  const Float_t thick): KVMaterial()
91 {
92  // Create a new detector of a given material and thickness in centimetres (default value = 0.0)
93 
94  init();
95  SetType("DET");
96  fDetCounter++;
97  SetName(Form("Det_%d", fDetCounter));
98  AddAbsorber(new KVMaterial(type, thick));
99 }
100 
101 
102 
105 
107 {
108 //copy ctor
109  init();
110  fDetCounter++;
111  SetName(Form("Det_%d", fDetCounter));
112 #if ROOT_VERSION_CODE >= ROOT_VERSION(3,4,0)
113  obj.Copy(*this);
114 #else
115  ((KVDetector&) obj).Copy(*this);
116 #endif
117 }
118 
119 
120 #if ROOT_VERSION_CODE >= ROOT_VERSION(3,4,0)
121 
126 
127 void KVDetector::Copy(TObject& obj) const
128 #else
129 void KVDetector::Copy(TObject& obj)
130 #endif
131 {
132  //copy 'this' to 'obj'
133  //The structure of the detector is copied, with new cloned objects for
134  //each absorber layer. The active layer is set in the new detector.
135 
136  TIter next(fAbsorbers);
137  KVMaterial* mat;
138  while ((mat = (KVMaterial*) next())) {
139  ((KVDetector&) obj).AddAbsorber((KVMaterial*) mat->Clone());
140  }
141  //set active layer
142  Int_t in_actif = fAbsorbers->IndexOf(fActiveLayer);
143  ((KVDetector&) obj).SetActiveLayer(((KVDetector&)obj).GetAbsorber(in_actif));
144 }
145 
146 
147 
148 
150 
151 KVDetector::~KVDetector()
152 {
153  fIDTelescopes->Clear();
157  delete fAbsorbers;
161  fIDTelAlign->Clear();
164  if (fAlignedDetectors[0]) fAlignedDetectors[0]->Clear("nodelete");
166  if (fAlignedDetectors[1]) fAlignedDetectors[1]->Clear("nodelete");
168 }
169 
170 
171 
176 
178 {
179  // Set material of active layer.
180  // If no absorbers have been added to the detector, create and add
181  // one (active layer by default)
182 
183  if (!GetActiveLayer())
185  else
187 }
188 
189 
190 
202 
204 {
205  //Calculate the energy loss of a charged particle traversing the detector,
206  //the particle is slowed down, it is added to the list of all particles hitting the
207  //detector. The apparent energy loss of the particle in the active layer of the
208  //detector is set.
209  //Do nothing if particle has zero (or -ve) energy.
210  //
211  //If the optional argument 'norm' is given, it is supposed to be a vector
212  //normal to the detector, oriented from the origin towards the detector.
213  //In this case the effective thicknesses of the detector's absorbers 'seen' by the particle
214  //depending on its direction of motion is used for the calculation.
215 
216  if (kvp->GetKE() <= 0.)
217  return;
218 
219  AddHit(kvp); //add nucleus to list of particles hitting detector in the event
220  //set flag to say that particle has been slowed down
221  kvp->SetIsDetected();
222  //If this is the first absorber that the particle crosses, we set a "reminder" of its
223  //initial energy
224  if (!kvp->GetPInitial())
225  kvp->SetE0();
226 
227  std::vector<Double_t> thickness;
228  if (norm) {
229  // modify thicknesses of all layers according to orientation,
230  // and store original thicknesses in array
231  TVector3 p = kvp->GetMomentum();
232  thickness.reserve(fAbsorbers->GetEntries());
233  KVMaterial* abs;
234  int i = 0;
235  TIter next(fAbsorbers);
236  while ((abs = (KVMaterial*) next())) {
237  thickness[i++] = abs->GetThickness();
238  Double_t T = abs->GetEffectiveThickness((*norm), p);
239  abs->SetThickness(T);
240  }
241  }
242  Double_t eloss = GetTotalDeltaE(kvp->GetZ(), kvp->GetA(), kvp->GetEnergy());
243  Double_t dE = GetDeltaE(kvp->GetZ(), kvp->GetA(), kvp->GetEnergy());
244  if (norm) {
245  // reset thicknesses of absorbers
246  KVMaterial* abs;
247  int i = 0;
248  TIter next(fAbsorbers);
249  while ((abs = (KVMaterial*) next())) {
250  abs->SetThickness(thickness[i++]);
251  }
252  }
253  Double_t epart = kvp->GetEnergy() - eloss;
254  if (epart < 1e-3) {
255  //printf("%s, pb d arrondi on met l energie de la particule a 0\n",GetName());
256  epart = 0.0;
257  }
258  kvp->SetEnergy(epart);
259  Double_t eloss_old = GetEnergyLoss();
260  SetEnergyLoss(eloss_old + dE);
261 }
262 
263 
264 
265 
275 
277 {
278  //Calculate the total energy loss of a charged particle traversing the detector.
279  //This does not affect the "stored" energy loss value of the detector,
280  //nor its ACQData, nor the energy of the particle.
281  //
282  //If the optional argument 'norm' is given, it is supposed to be a vector
283  //normal to the detector, oriented from the origin towards the detector.
284  //In this case the effective thicknesses of the detector's absorbers 'seen' by the particle
285  //depending on its direction of motion is used for the calculation.
286 
287  std::vector<Double_t> thickness;
288  if (norm) {
289  // modify thicknesses of all layers according to orientation,
290  // and store original thicknesses in array
291  TVector3 p = kvp->GetMomentum();
292  thickness.reserve(fAbsorbers->GetEntries());
293  KVMaterial* abs;
294  int i = 0;
295  TIter next(fAbsorbers);
296  while ((abs = (KVMaterial*) next())) {
297  thickness[i++] = abs->GetThickness();
298  Double_t T = abs->GetEffectiveThickness((*norm), p);
299  abs->SetThickness(T);
300  }
301  }
302  Double_t eloss = GetTotalDeltaE(kvp->GetZ(), kvp->GetA(), kvp->GetEnergy());
303  if (norm) {
304  // reset thicknesses of absorbers
305  KVMaterial* abs;
306  int i = 0;
307  TIter next(fAbsorbers);
308  while ((abs = (KVMaterial*) next())) {
309  abs->SetThickness(thickness[i++]);
310  }
311  }
312  return eloss;
313 }
314 
315 
316 
317 
327 
329 {
330  //Calculate the energy of particle 'kvn' before its passage through the detector,
331  //based on the current kinetic energy, Z & A of nucleus 'kvn', supposed to be
332  //after passing through the detector.
333  //
334  //If the optional argument 'norm' is given, it is supposed to be a vector
335  //normal to the detector, oriented from the origin towards the detector.
336  //In this case the effective thicknesses of the detector's absorbers 'seen' by the particle
337  //depending on its direction of motion is used for the calculation.
338 
339  Double_t Einc = 0.0;
340  //make 'clone' of particle
341  KVNucleus clone_part(kvp->GetZ(), kvp->GetA());
342  clone_part.SetMomentum(kvp->GetMomentum());
343  //composite detector - calculate losses in all layers
344  KVMaterial* abs;
345  TIter next(fAbsorbers, kIterBackward); //work through list backwards
346  while ((abs = (KVMaterial*) next())) {
347 
348  //calculate energy of particle before current absorber
349  Einc = abs->GetParticleEIncFromERes(&clone_part, norm);
350 
351  //set new energy of particle
352  clone_part.SetKE(Einc);
353  }
354  return Einc;
355 }
356 
357 
358 
359 
363 
364 void KVDetector::Print(Option_t* opt) const
365 {
366  //Print info on this detector
367  //if option="data" the energy loss and raw data are displayed
368 
369  if (!strcmp(opt, "data")) {
370  cout << GetName() << " -- ";
371  // print raw data signals
372  KVDetectorSignal* sig;
374  while ((sig = (KVDetectorSignal*)it())) {
375  if (sig->IsRaw()) {
376  std::cout << sig->GetName() << "=" << sig->GetValue() << " | ";
377  }
378  }
379  // print calibrated data
380  it.Reset();
381  while ((sig = (KVDetectorSignal*)it())) {
382  if (!sig->IsRaw() && !sig->GetValueNeedsExtraParameters()) {
383  std::cout << sig->GetName() << "=" << sig->GetValue() << " | ";
384  }
385  }
386  cout << " ";
388  cout << "(Belongs to an unidentified particle)";
389  cout << endl;
390  }
391  else if (!strcmp(opt, "all")) {
392  //Give full details of detector
393  //
394  TString option(" ");
395  cout << option << ClassName() << " : " << ((KVDetector*) this)->
396  GetName() << endl;
397  //composite detector - print all layers
398  KVMaterial* abs;
399  TIter next(fAbsorbers);
400  while ((abs = (KVMaterial*) next())) {
401  if (GetActiveLayer() == abs)
402  cout << " ### ACTIVE LAYER ### " << endl;
403  cout << option << option;
404  abs->Print();
405  if (GetActiveLayer() == abs)
406  cout << " #################### " << endl;
407  }
408  if (fParticles) {
409  cout << option << " --- Detected particles:" << endl;
410  fParticles->Print();
411  }
412  if (fIDTelescopes) {
413  cout << option << " --- Detector belongs to the following Identification Telescopes:" << endl;
414  fIDTelescopes->ls();
415  }
416  }
417  else {
418  //just print name
419  cout << ClassName() << ": " << ((KVDetector*) this)->
420  GetName() << endl;
421  }
422 }
423 
424 
425 
426 
427 
438 
440 {
441  // This method is called by KVASMultiDetArray::MakeListOfDetectors
442  // after the array geometry has been defined (i.e. all detectors have
443  // been placed in the array). The string returned by this method
444  // is used to set the name of the detector.
445  //
446  // Override this method in child classes in order to define a naming
447  // convention for specific detectors of the array.
448  //
449  // By default we return the same name as KVDetector::GetName
450 
451  fFName = GetName();
452  return fFName.Data();
453 }
454 
455 
456 
477 
479 {
480  // Associate a calibration with this detector.
481  //
482  // This will add a new signal to the list of the detector's signals.
483  //
484  // Also sets calibrator's name to `[detname]_[caltype]` where `caltype` is the type of the KVCalibration object.
485  //
486  // \param[in] cal pointer to KVCalibrator object (must be on heap, i.e. created with new: detector handles deletion)
487  // \param[in] opts
488  // \parblock
489  // can be used to pass any extra parameters/options needed by the calibrator.
490  //
491  // For example, if it contains a parameter `ZRange`, e.g. `ZRange=1-10`
492  // then the calibrator will be handled by a KVZDependentCalibratedSignal (handles several
493  // calibrators which provide the same output signal, each one is used for a specific range
494  // of atomic numbers)
495  // \endparblock
496  //
497  // \returns kFALSE in case of problems (non-existent input signal for calibrator, output signal not defined for calibrator),
498  // otherwise kTRUE
499 
500  if (!cal) return kFALSE;
501  // look for input signal
503  // input signal must exist
504  if (!in) {
505  Error("AddCalibrator", "Detector:%s has no signal %s, required as input by calibrator %s to provide output %s",
506  GetName(), cal->GetInputSignalType().Data(), cal->GetType(), cal->GetOutputSignalType().Data());
507  return kFALSE;
508  }
509  if (!fCalibrators)
510  fCalibrators = new KVList();
511 
512  cal->SetDetector(this);
513  fCalibrators->Add(cal);
514  cal->SetName(Form("%s_%s", GetName(), cal->GetType()));
515 
516  if (cal->GetOutputSignalType() == "") {
517  Warning("AddCalibrator", "%s : output signal not defined for calibrator %s. No output signal created.",
518  GetName(), cal->GetType());
519  }
520  else {
521  KVDetectorSignal* new_cal_sig(nullptr);
522  if (opts.HasParameter("ZRange")) {
523  // If 'ZRange' parameter is given we need to find the KVZDependentCalibratedSignal
524  // and add a new signal to it.
526  if (!sig) {
527  new_cal_sig = sig = new KVZDependentCalibratedSignal(in, cal->GetOutputSignalType());
528  }
529  dynamic_cast<KVZDependentCalibratedSignal*>(sig)->AddSignal(new KVCalibratedSignal(in, cal), opts.GetStringValue("ZRange"));
530  }
531  else {
532  new_cal_sig = new KVCalibratedSignal(in, cal);
533  }
534  if (new_cal_sig) fDetSignals.Add(new_cal_sig);
535  }
536  return kTRUE;
537 }
538 
539 
540 
551 
553 {
554  // Replace calibrator of given type with the given calibrator object
555  // The calibrator object should not be shared with any other detectors: it now belongs
556  // to this detector, which will delete it when necessary.
557  // If an exising calibrator with the same type is already defined, it will be
558  // deleted and removed from the detector's calibrator list
559  //
560  // Returns kFALSE in case of problems.
561  //
562  // The (optional) KVNameValueList argument can be used to pass any extra parameters/options.
563 
564  KVCalibrator* old_cal = GetCalibrator(type);
565  if (old_cal) {
566  fCalibrators->Remove(old_cal);
568  delete old_cal;
569  }
570  return AddCalibrator(cal, opts);
571 }
572 
573 
574 
579 
581 {
582  // A detector is considered to be calibrated if it has
583  // a signal "Energy" available and if depending on the supplied parameters
584  // this signal can be calculated
585 
586  KVCalibratedSignal* e_sig = dynamic_cast<KVCalibratedSignal*>(GetDetectorSignal("Energy"));
587  return (e_sig && e_sig->IsAvailableFor(params) && IsOK());
588 }
589 
590 
591 
592 
596 
598 {
599  //Set energy loss(es) etc. to zero
600  //If opt="N" we do not reset acquisition parameters/raw detector signals
601 
603  fIdentP = fUnidentP = 0;
606  if (strncmp(opt, "N", 1)) {
608  KVDetectorSignal* ds;
609  while ((ds = (KVDetectorSignal*)it())) {
610  if (ds->IsRaw() && !ds->IsExpression()) ds->Reset();
611  }
612  }
613  ClearHits();
614  //reset all layers in detector
615  KVMaterial* mat;
616  TIter next(fAbsorbers);
617  while ((mat = (KVMaterial*) next())) {
618  mat->Clear();
619  }
620  fEResforEinc = -1.;
621 }
622 
623 
624 
629 
631 {
632  // Add a layer of absorber material to the detector
633  // By default, the first layer added is set as the "Active" layer.
634  // Call SetActiveLayer to change this.
635  fAbsorbers->Add(mat);
636  if (!TestBit(kActiveSet))
637  SetActiveLayer(mat);
638  if (fAbsorbers->GetSize() > 1) fSingleLayer = kFALSE;
639 }
640 
641 
642 
645 
647 {
648  //Returns pointer to the i-th absorber in the detector (i=0 first absorber, i=1 second, etc.)
649 
650  if (i < 0) {
651  //special case of reading old detectors
652  //no warning
653  return 0;
654  }
655  if (!fAbsorbers) {
656  Error("GetAbsorber", "No absorber list");
657  return 0;
658  }
659  if (fAbsorbers->GetSize() < 1) {
660  Error("GetAbsorber", "Nothing in absorber list");
661  return 0;
662  }
663  if (i >= fAbsorbers->GetSize()) {
664  Error("GetAbsorber", "i=%d but only %d absorbers in list", i,
665  fAbsorbers->GetSize());
666  return 0;
667  }
668 
669  return (KVMaterial*) fAbsorbers->At(i);
670 }
671 
672 
673 
677 
679 {
680  // Used when a calibrator object is removed or replaced
681  // We remove and delete the corresponding output signal from the list of detector signals
682 
683  if (K->GetOutputSignalType() != "") {
684  KVDetectorSignal* ds = GetDetectorSignal(K->GetOutputSignalType());
685  if (ds) {
686  fDetSignals.Remove(ds);
687  delete ds;
688  }
689  }
690 }
691 
692 
693 
699 
701 {
702  // Removes all calibrations associated to this detector: in other words, we delete all
703  // the KVCalibrator objects in list fCalibrators.
704  //
705  // We also destroy all signals provided by these calibrators
706 
707  if (fCalibrators) {
708  KVCalibrator* K;
709  TIter it(fCalibrators);
710  while ((K = (KVCalibrator*)it())) {
712  }
713  fCalibrators->Delete();
714  }
715 }
716 
717 
718 
719 
722 
724 {
725  //Add ID telescope to list of telescopes to which detector belongs
726  fIDTelescopes->Add(idt);
727 }
728 
729 
730 
736 
738 {
739  // Return list of all ID telescopes containing detectors placed in front of
740  // this one.
741 
742  // temporary kludge during transition to trajectory-based reconstruction
743  // ROOT-geometry-based detectors will not have fIDTelAlign filled
744  if (ROOTGeo() && !fIDTelAlign->GetEntries()) {
746  (KVGeoDNTrajectory*)GetNode()->GetTrajectories()->First(),
747  GetNode()
748  );
749  if (Rtr) fIDTelAlign->AddAll(Rtr->GetIDTelescopes());
750  }
751  return fIDTelAlign;
752 }
753 
754 
755 
756 
761 
763 {
764  //Returns list of identification telescopes to be used in order to try to identify
765  //particles stopping in this detector. This is the same as GetAlignedIDTelescopes
766  //but only including the telescopes of which this detector is a member.
767  if (fIDTele4Ident) return fIDTele4Ident;
768  if (!fIDTelescopes || !fIDTelAlign) return 0;
769  fIDTele4Ident = new TList;
771  TObject* idt;
772  while ((idt = next())) {
773  if (fIDTelescopes->FindObject(idt)) fIDTele4Ident->Add(idt);
774  }
775  return fIDTele4Ident;
776 }
777 
778 
779 
780 
781 
810 
812 {
813  // Returns the total energy loss in the detector for a given nucleus
814  // including inactive absorber layers.
815  // e = energy loss in active layer (if not given, we use current value)
816  // transmission = kTRUE (default): the particle is assumed to emerge with
817  // a non-zero residual energy Eres after the detector.
818  // = kFALSE: the particle is assumed to stop in the detector.
819  //
820  // WARNING: if transmission=kTRUE, and if the residual energy after the detector
821  // is known (i.e. measured in a detector placed after this one), you should
822  // first call
823  // SetEResAfterDetector(Eres);
824  // before calling this method. Otherwise, especially for heavy ions, the
825  // correction may be false for particles which are just above the punch-through energy.
826  //
827  // WARNING 2: if measured energy loss in detector active layer is greater than
828  // maximum possible theoretical value for given nucleus' Z & A, this may be because
829  // the A was not measured but calculated from Z and hence could be false, or perhaps
830  // there was an (undetected) pile-up of two or more particles in the detector.
831  // In this case we return the uncorrected energy measured in the active layer
832  // and we add the following parameters to the particle (in nuc->GetParameters()):
833  //
834  // GetCorrectedEnergy.Warning = 1
835  // GetCorrectedEnergy.Detector = [name]
836  // GetCorrectedEnergy.MeasuredDE = [value]
837  // GetCorrectedEnergy.MaxDE = [value]
838  // GetCorrectedEnergy.Transmission = 0 or 1
839  // GetCorrectedEnergy.ERES = [value]
840 
841  Int_t z = nuc->GetZ();
842  Int_t a = nuc->GetA();
843 
844  if (e < 0.) e = GetEnergy();
845  if (e <= 0) {
847  return 0;
848  }
849 
850  enum SolType solution = kEmax;
851  if (!transmission) solution = kEmin;
852 
853  // check that apparent energy loss in detector is compatible with a & z
854  Double_t maxDE = GetMaxDeltaE(z, a);
855  Double_t EINC, ERES = GetEResAfterDetector();
856  if (e > maxDE) {
857  nuc->GetParameters()->SetValue("GetCorrectedEnergy.Warning", 1);
858  nuc->GetParameters()->SetValue("GetCorrectedEnergy.Detector", GetName());
859  nuc->GetParameters()->SetValue("GetCorrectedEnergy.MeasuredDE", e);
860  nuc->GetParameters()->SetValue("GetCorrectedEnergy.MaxDE", maxDE);
861  nuc->GetParameters()->SetValue("GetCorrectedEnergy.Transmission", (Int_t)transmission);
862  nuc->GetParameters()->SetValue("GetCorrectedEnergy.ERES", ERES);
863  return e;
864 
865  }
866  if (transmission && ERES > 0.) {
867  // if residual energy is known we use it to calculate EINC.
868  // if EINC < max of dE curve, we change solution
869  EINC = GetIncidentEnergyFromERes(z, a, ERES);
870  if (EINC < GetEIncOfMaxDeltaE(z, a)) solution = kEmin;
871  // we could keep the EINC value calculated using ERES, but then
872  // the corrected dE of this detector would not depend on the
873  // measured dE !
874  }
875  EINC = GetIncidentEnergy(z, a, e, solution);
876  if (EINC < 0) {
878  return EINC;
879  }
880  ERES = GetERes(z, a, EINC);
881 
883  return (EINC - ERES);
884 }
885 
886 
887 
888 
906 
908 {
909  //For particles which stop in the first stage of an identification telescope,
910  //we can at least estimate a minimum Z value based on the energy lost in this
911  //detector.
912  //
913  //This is based on the KVMaterial::GetMaxDeltaE method, giving the maximum
914  //energy loss in the active layer of the detector for a given nucleus (A,Z).
915  //
916  //The "Zmin" is the Z of the particle which gives a maximum energy loss just greater
917  //than that measured in the detector. Particles with Z<Zmin could not lose as much
918  //energy and so are excluded.
919  //
920  //If ELOSS is not given, we use the current value of GetEnergy()
921  //Use 'mass_formula' to change the formula used to calculate the A of the nucleus
922  //from its Z. Default is valley of stability value. (see KVNucleus::GetAFromZ).
923  //
924  //If the value of ELOSS or GetEnergy() is <=0 we return Zmin=0
925 
926  ELOSS = (ELOSS < 0. ? GetEnergy() : ELOSS);
927  if (ELOSS <= 0) return 0;
928 
929  UInt_t z = 40;
930  UInt_t zmin, zmax;
931  zmin = 1;
932  zmax = 92;
933  Double_t difference;
934  UInt_t last_positive_difference_z = 1;
935  KVNucleus particle;
936  if (mass_formula > -1)
937  particle.SetMassFormula((UChar_t)mass_formula);
938 
939  difference = 0.;
940 
941  while (zmax > zmin + 1) {
942 
943  particle.SetZ(z);
944 
945  difference = GetMaxDeltaE(z, particle.GetA()) - ELOSS;
946  //if difference < 0 the z is too small
947  if (difference < 0.0) {
948 
949  zmin = z;
950  z += (UInt_t)((zmax - z) / 2 + 0.5);
951 
952  }
953  else {
954 
955  zmax = z;
956  last_positive_difference_z = z;
957  z -= (UInt_t)((z - zmin) / 2 + 0.5);
958 
959  }
960  }
961  if (difference < 0) {
962  //if the last z we tried actually made the difference become negative again
963  //(i.e. z too small) we return the last z which gave a +ve difference
964  z = last_positive_difference_z;
965  }
966  return z;
967 }
968 
969 
970 
971 
980 
982 {
983  // Calculates energy loss (in MeV) in active layer of detector, taking into account preceding layers
984  //
985  // Arguments are:
986  // x[0] is incident energy in MeV
987  // Parameters are:
988  // par[0] Z of ion
989  // par[1] A of ion
990 
991  Double_t e = x[0];
992  TIter next(fAbsorbers);
993  KVMaterial* mat;
994  mat = (KVMaterial*)next();
995  while (fActiveLayer != mat) {
996  // calculate energy losses in absorbers before active layer
997  e = mat->GetERes(par[0], par[1], e); //residual energy after layer
998  if (e <= 0.)
999  return 0.; // return 0 if particle stops in layers before active layer
1000  mat = (KVMaterial*)next();
1001  }
1002  //calculate energy loss in active layer
1003  return mat->GetDeltaE(par[0], par[1], e);
1004 }
1005 
1006 
1007 
1008 
1018 
1020 {
1021  // Calculates range (in centimetres) of ions in detector as a function of incident energy (in MeV),
1022  // taking into account all layers of the detector.
1023  //
1024  // Arguments are:
1025  // x[0] = incident energy in MeV
1026  // Parameters are:
1027  // par[0] = Z of ion
1028  // par[1] = A of ion
1029 
1030  Double_t Einc = x[0];
1031  Int_t Z = (Int_t)par[0];
1032  Int_t A = (Int_t)par[1];
1033  Double_t range = 0.;
1034  TIter next(fAbsorbers);
1035  KVMaterial* mat = (KVMaterial*)next();
1036  if (!mat) return 0.;
1037  do {
1038  // range in this layer
1039  Double_t this_range = mat->GetLinearRange(Z, A, Einc);
1040  KVMaterial* next_mat = (KVMaterial*)next();
1041  if (this_range > mat->GetThickness()) {
1042  // particle traverses layer.
1043  if (next_mat)
1044  range += mat->GetThickness();
1045  else // if this is last layer, the range continues to increase beyond size of detector
1046  range += this_range;
1047  // calculate incident energy for next layer (i.e. residual energy after this layer)
1048  Einc = mat->GetERes(Z, A, Einc);
1049  }
1050  else {
1051  // particle stops in layer
1052  range += this_range;
1053  return range;
1054  }
1055  mat = next_mat;
1056  }
1057  while (mat);
1058  // particle traverses detector
1059  return range;
1060 }
1061 
1062 
1063 
1064 
1074 
1076 {
1077  // Calculates residual energy (in MeV) of particle after traversing all layers of detector.
1078  // Returned value is -1000 if particle stops in one of the layers of the detector.
1079  //
1080  // Arguments are:
1081  // x[0] is incident energy in MeV
1082  // Parameters are:
1083  // par[0] Z of ion
1084  // par[1] A of ion
1085 
1086  Double_t e = x[0];
1087  TIter next(fAbsorbers);
1088  KVMaterial* mat;
1089  while ((mat = (KVMaterial*)next())) {
1090  Double_t eres = mat->GetERes(par[0], par[1], e); //residual energy after layer
1091  if (eres <= 0.)
1092  return -1000.; // return -1000 if particle stops in layers before active layer
1093  e = eres;
1094  }
1095  return e;
1096 }
1097 
1098 
1099 
1100 
1115 
1117 {
1118  //Static function which will create an instance of the KVDetector-derived class
1119  //corresponding to 'name'
1120  //These are defined as 'Plugin' objects in the file $KVROOT/KVFiles/.kvrootrc :
1121  // [name_of_dataset].detector_type
1122  // detector_type
1123  // To use the dataset-dependent plugin, call this method with
1124  // name = "[name_of_dataset].detector_type"
1125  // If not, the default plugin will be used
1126  //first we check if there is a special plugin for the DataSet
1127  //if not we take the default one
1128  //
1129  //'thickness' is passed as argument to the constructor for the detector plugin
1130 
1131  //check and load plugin library
1132  TPluginHandler* ph = nullptr;
1133  KVString nom(name);
1134  if (!nom.Contains(".") && !(ph = LoadPlugin("KVDetector", name))) return nullptr;
1135  if (nom.Contains(".")) {
1136  // name format like [dataset].[det_type]
1137  // in case dataset name contains "." we parse string to find detector type: assumed after the last "."
1138  nom.RBegin(".");
1139  KVString det_type = nom.RNext();
1140  if (!(ph = LoadPlugin("KVDetector", name))) {
1141  if (!(ph = LoadPlugin("KVDetector", det_type))) {
1142  return nullptr;
1143  }
1144  }
1145  }
1146 
1147  //execute constructor/macro for detector
1148  return (KVDetector*) ph->ExecPlugin(1, thickness);
1149 }
1150 
1151 
1152 
1153 
1165 
1166 void KVDetector::GetVerticesInOwnFrame(TVector3* corners, Double_t depth, Double_t layer_thickness)
1167 {
1168  // This will fill the array corners[8] with the coordinates of the vertices of the
1169  // front (corners[0],...,corners[3]) & back (corners[4],...,corners[7]) sides of the volume
1170  // representing either a single absorber or the whole detector.
1171  //
1172  // depth = depth of detector/absorber inside the KVTelescope it belongs to (in centimetres)
1173  // layer_thickness = thickness of absorber/detector (in centimetres)
1174  //
1175  // Positioning information is taken from the KVTelescope to which this detector
1176  // belongs; if this is not the case, nothing will be done.
1177 
1178  // relative distance to back of detector
1179  Double_t dist_to_back = depth + layer_thickness;
1180 
1181  // get coordinates
1182  KVTelescope* fTelescope = (KVTelescope*)GetParentStructure("TELESCOPE");
1183  if (fTelescope) {
1184  fTelescope->GetCornerCoordinatesInOwnFrame(corners, depth);
1185  fTelescope->GetCornerCoordinatesInOwnFrame(&corners[4], dist_to_back);
1186  }
1187  else {
1188  GetCornerCoordinatesInOwnFrame(corners, depth);
1189  GetCornerCoordinatesInOwnFrame(&corners[4], dist_to_back);
1190  }
1191 }
1192 
1193 
1194 
1195 
1210 
1212 {
1213  // Construct a TGeoVolume shape to represent this detector in the current
1214  // geometry managed by gGeoManager.
1215  //
1216  // Making the volume requires:
1217  // - to construct a 'mother' volume (TGeoArb8) defined by the (theta-min/max, phi-min/max)
1218  // and the total thickness of the detector (all layers)
1219  // - to construct and position volumes (TGeoArb8) for each layer of the detector inside the
1220  // 'mother' volume. Each layer is represented by a TGeoArb8 whose two parallel faces correspond
1221  // to the front and back surfaces of the layer.
1222  //
1223  // If the detector is composed of a single absorber, we do not create a superfluous "mother" volume.
1224  //
1225  // gGeoManager must point to current instance of geometry manager.
1226 
1227  if (!gGeoManager) return NULL;
1228 
1229  if (fTotThickness == 0) GetTotalThicknessInCM(); // calculate sum of absorber thicknesses in centimetres
1230  // get from telescope info on relative depth of detector i.e. depth inside telescope
1231 
1232  KVTelescope* fTelescope = (KVTelescope*)GetParentStructure("TELESCOPE");
1233  if (fTelescope && fDepthInTelescope == 0)
1234  fDepthInTelescope = fTelescope->GetDepthInCM(fTelescope->GetDetectorRank(this));
1235 
1236  TVector3 coords[8];
1237  Double_t vertices[16];
1238  Double_t tot_thick_det = fTotThickness;
1239  TGeoMedium* med;
1240  TGeoVolume* mother_vol = 0;
1241 
1242  Bool_t multi_layer = fAbsorbers->GetSize() > 1;
1243 
1244  if (multi_layer) {
1245  mother_vol = gGeoManager->MakeVolumeAssembly(Form("%s_DET", GetName()));
1246  }
1247 
1248  /**** BUILD & ADD ABSORBER VOLUMES ****/
1249  TIter next(fAbsorbers);
1250  KVMaterial* abs;
1251  Double_t depth_in_det = 0.;
1252  Int_t no_abs = 1;
1253  while ((abs = (KVMaterial*)next())) {
1254  // get medium for absorber
1255  med = abs->GetGeoMedium();
1256  Double_t thick = abs->GetThickness();
1257  // do not include layers with zero thickness
1258  if (thick == 0.0) continue;
1259  GetVerticesInOwnFrame(coords, fDepthInTelescope + depth_in_det, thick);
1260  for (int i = 0; i < 8; i++) {
1261  vertices[2 * i] = coords[i].X();
1262  vertices[2 * i + 1] = coords[i].Y();
1263  }
1264  Double_t dz = thick / 2.;
1265  TString vol_name;
1266  if (abs == GetActiveLayer()) vol_name = GetName();
1267  else vol_name = Form("%s_%d_%s", GetName(), no_abs, abs->GetType());
1268  TGeoVolume* vol =
1269  gGeoManager->MakeArb8(vol_name.Data(), med, dz, vertices);
1270  vol->SetLineColor(med->GetMaterial()->GetDefaultColor());
1271  if (multi_layer) {
1272  /*** position absorber in mother ***/
1273  Double_t trans_z = -tot_thick_det / 2. + depth_in_det + dz; // (note: reference is CENTRE of absorber)
1274  TGeoTranslation* tr = new TGeoTranslation(0., 0., trans_z);
1275  mother_vol->AddNode(vol, 1, tr);
1276  }
1277  else {
1278  // single absorber: mother is absorber is detector is mother is ...
1279  mother_vol = vol;
1280  }
1281  depth_in_det += thick;
1282  no_abs++;
1283  }
1284 
1285  return mother_vol;
1286 }
1287 
1288 
1289 
1290 
1303 
1305 {
1306  // Construct and position a TGeoVolume shape to represent this detector in the current
1307  // geometry managed by gGeoManager.
1308  //
1309  // Adding the detector to the geometry requires:
1310  // - to construct a 'mother' volume (TGeoArb8) defined by the (theta-min/max, phi-min/max)
1311  // and the total thickness of the detector (all layers)
1312  // - to construct and position volumes (TGeoArb8) for each layer of the detector inside the
1313  // 'mother' volume
1314  // - to position 'mother' inside the top-level geometry
1315  //
1316  // gGeoManager must point to current instance of geometry manager.
1317 
1318  if (!gGeoManager) return;
1319 
1320  // get volume for detector
1321  TGeoVolume* vol = GetGeoVolume();
1322 
1323  // rotate detector to orientation corresponding to (theta,phi)
1324  Double_t theta = GetTheta();
1325  Double_t phi = GetPhi();
1326  TGeoRotation rot1, rot2;
1327  rot2.SetAngles(phi + 90., theta, 0.);
1328  rot1.SetAngles(-90., 0., 0.);
1329  // distance to detector centre = distance to telescope + depth of detector in telescope + half total thickness of detector
1330  KVTelescope* fTelescope = (KVTelescope*)GetParentStructure("TELESCOPE");
1331  Double_t dist_telescope = (fTelescope ? fTelescope->GetDistance() : 0.);
1332  Double_t dist = dist_telescope + fDepthInTelescope + fTotThickness / 2.;
1333  // translate detector to correct distance from target (note: reference is CENTRE of detector)
1334  Double_t trans_z = dist;
1335 
1336  TGeoTranslation tran(0, 0, trans_z);
1337  TGeoHMatrix h = rot2 * tran * rot1;
1338  TGeoHMatrix* ph = new TGeoHMatrix(h);
1339 
1340  // add detector volume to geometry
1341  gGeoManager->GetTopVolume()->AddNode(vol, 1, ph);
1342 }
1343 
1344 
1345 #ifndef WITH_CPP11
1346 
1348 
1349 void printvec(const TVector3& v)
1350 {
1351  cout << "(" << v.X() << "," << v.Y() << "," << v.Z() << ")";
1352 };
1353 
1354 #endif
1355 
1356 
1359 
1361 {
1362  // Return surface area of first layer of detector in cm2.
1363 
1364  if (ROOTGeo()) {
1365  if (!GetEntranceWindow().GetShape()->InheritsFrom("TGeoArb8")) {
1366  // simple shape area
1367  return GetEntranceWindow().GetShape()->GetFacetArea(1);
1368  }
1369  // Monte Carlo calculation for TGeoArb8 shapes
1370  return GetEntranceWindow().GetSurfaceArea();
1371  }
1372 
1373  KVTelescope* fTelescope = (KVTelescope*)GetParentStructure("TELESCOPE");
1374  if (fTelescope && fDepthInTelescope == 0)
1375  fDepthInTelescope = fTelescope->GetDepthInCM(fTelescope->GetDetectorRank(this));
1376 
1377  TVector3 coords[4];
1378 #ifdef WITH_CPP11
1379  auto printvec = [](const TVector3 & v) {
1380  cout << "(" << v.X() << "," << v.Y() << "," << v.Z() << ")";
1381  };
1382 #endif
1383 
1384  if (fTelescope) fTelescope->GetCornerCoordinates(coords, fDepthInTelescope);
1385  else GetCornerCoordinates(coords, 0);
1386  cout << "DETECTOR COORDINATES (in cm):" << endl;
1387  cout << "=================================" << endl;
1388  cout << " A : ";
1389  printvec(coords[0]);
1390  cout << endl;
1391  cout << " B : ";
1392  printvec(coords[1]);
1393  cout << endl;
1394  cout << " C : ";
1395  printvec(coords[2]);
1396  cout << endl;
1397  cout << " D : ";
1398  printvec(coords[3]);
1399  cout << endl;
1400 
1401  cout << "DETECTOR DIMENSIONS (in cm):" << endl;
1402  cout << "================================" << endl;
1403  Double_t c = (coords[0] - coords[1]).Mag();
1404  Double_t b = (coords[1] - coords[2]).Mag();
1405  Double_t d = (coords[2] - coords[3]).Mag();
1406  Double_t a = (coords[0] - coords[3]).Mag();
1407  cout << " AB = " << c << endl;
1408  cout << " BC = " << b << endl;
1409  cout << " CD = " << d << endl;
1410  cout << " AD = " << a << endl;
1411 
1412  cout << "DETECTOR SURFACE AREA = ";
1413  Double_t surf = pow((a + b), 2.0) * (a - b + 2.0 * c) * (b - a + 2.0 * c);
1414  surf = sqrt(surf) / 400.0;
1415  cout << surf << " cm2" << endl;
1416 
1417  return surf;
1418 }
1419 
1420 
1421 
1426 
1428 {
1429  // Return pointer toTF1 giving residual energy after detector as function of incident energy,
1430  // for a given nucleus (Z,A).
1431  // The TF1::fNpx parameter is taken from environment variable KVDetector.ResidualEnergy.Npx
1432 
1433  if (!fEResF) {
1434  fEResF = new TF1(Form("KVDetector:%s:ERes", GetName()), this, &KVDetector::EResDet,
1435  0., 1.e+04, 2, "KVDetector", "EResDet");
1436  fEResF->SetNpx(gEnv->GetValue("KVDetector.ResidualEnergy.Npx", 20));
1437  }
1439  fEResF->SetRange(0., GetSmallestEmaxValid(Z, A));
1440  fEResF->SetTitle(Form("Residual energy [MeV] after detector %s for Z=%d A=%d", GetName(), Z, A));
1441 
1442  return fEResF;
1443 }
1444 
1445 
1446 
1451 
1453 {
1454  // Return pointer toTF1 giving range (in centimetres) in detector as function of incident energy,
1455  // for a given nucleus (Z,A).
1456  // The TF1::fNpx parameter is taken from environment variable KVDetector.Range.Npx
1457 
1458  if (!fRangeF) {
1459  fRangeF = new TF1(Form("KVDetector:%s:Range", GetName()), this, &KVDetector::RangeDet,
1460  0., 1.e+04, 2, "KVDetector", "RangeDet");
1461  fRangeF->SetNpx(gEnv->GetValue("KVDetector.Range.Npx", 20));
1462  }
1465  fRangeF->SetTitle(Form("Range [cm] in detector %s for Z=%d A=%d", GetName(), Z, A));
1466 
1467  return fRangeF;
1468 }
1469 
1470 
1471 
1476 
1478 {
1479  // Return pointer to TF1 giving energy loss in active layer of detector as function of incident energy,
1480  // for a given nucleus (Z,A).
1481  // The TF1::fNpx parameter is taken from environment variable KVDetector.EnergyLoss.Npx
1482 
1483  if (!fELossF) {
1484  fELossF = new TF1(Form("KVDetector:%s:ELossActive", GetName()), this, &KVDetector::ELossActive,
1485  0., 1.e+04, 2, "KVDetector", "ELossActive");
1486  fELossF->SetNpx(gEnv->GetValue("KVDetector.EnergyLoss.Npx", 20));
1487  }
1490  fELossF->SetTitle(Form("Energy loss [MeV] in detector %s for Z=%d A=%d", GetName(), Z, A));
1491  return fELossF;
1492 }
1493 
1494 
1495 
1500 
1502 {
1503  // Overrides KVMaterial::GetEIncOfMaxDeltaE
1504  // Returns incident energy corresponding to maximum energy loss in the
1505  // active layer of the detector, for a given nucleus.
1506 
1507  return GetELossFunction(Z, A)->GetMaximumX();
1508 }
1509 
1510 
1511 
1516 
1518 {
1519  // Overrides KVMaterial::GetMaxDeltaE
1520  // Returns maximum energy loss in the
1521  // active layer of the detector, for a given nucleus.
1522 
1523  return GetELossFunction(Z, A)->GetMaximum();
1524 }
1525 
1526 
1527 
1532 
1534 {
1535  // Overrides KVMaterial::GetDeltaE
1536  // Returns energy loss of given nucleus in the active layer of the detector.
1537 
1538  // optimization for single-layer detectors
1539  if (fSingleLayer) {
1540  return fActiveLayer->GetDeltaE(Z, A, Einc);
1541  }
1542  return GetELossFunction(Z, A)->Eval(Einc);
1543 }
1544 
1545 
1546 
1550 
1552 {
1553  // Returns calculated total energy loss of ion in ALL layers of the detector.
1554  // This is just (Einc - GetERes(Z,A,Einc))
1555 
1556  return Einc - GetERes(Z, A, Einc);
1557 }
1558 
1559 
1560 
1565 
1567 {
1568  // Overrides KVMaterial::GetERes
1569  // Returns residual energy of given nucleus after the detector.
1570  // Returns 0 if Einc<=0
1571 
1572  if (Einc <= 0.) return 0.;
1573  Double_t eres = GetEResFunction(Z, A)->Eval(Einc);
1574  // Eres function returns -1000 when particle stops in detector,
1575  // in order for function inversion (GetEIncFromEres) to work
1576  if (eres < 0.) eres = 0.;
1577  return eres;
1578 }
1579 
1580 
1581 
1604 
1606 {
1607  // Overrides KVMaterial::GetIncidentEnergy
1608  // Returns incident energy corresponding to energy loss delta_e in active layer of detector for a given nucleus.
1609  // If delta_e is not given, the current energy loss in the active layer is used.
1610  //
1611  // By default the solution corresponding to the highest incident energy is returned
1612  // This is the solution found for Einc greater than the maximum of the dE(Einc) curve.
1613  // If you want the low energy solution set SolType = KVIonRangeTable::kEmin.
1614  //
1615  // WARNING: calculating the incident energy of a particle using only the dE in a detector
1616  // is ambiguous, as in general (and especially for very heavy ions) the maximum of the dE
1617  // curve occurs for Einc greater than the punch-through energy, therefore it is not always
1618  // true to assume that if the particle does not stop in the detector the required solution
1619  // is that for type=KVIonRangeTable::kEmax. For a range of energies between punch-through
1620  // and dE_max, the required solution is still that for type=KVIonRangeTable::kEmin.
1621  // If the residual energy of the particle is unknown, there is no way to know which is the
1622  // correct solution.
1623  //
1624  // WARNING 2
1625  // If the given energy loss in the active layer is greater than the maximum theoretical dE
1626  // for given Z & A, (dE > GetMaxDeltaE(Z,A)) then we return a NEGATIVE incident energy
1627  // corresponding to the maximum, GetEIncOfMaxDeltaE(Z,A)
1628 
1629  if (Z < 1) return 0.;
1630 
1631  Double_t DE = (delta_e > 0 ? delta_e : GetEnergyLoss());
1632 
1633  // If the given energy loss in the active layer is greater than the maximum theoretical dE
1634  // for given Z & A, (dE > GetMaxDeltaE(Z,A)) then we return a NEGATIVE incident energy
1635  // corresponding to the maximum, GetEIncOfMaxDeltaE(Z,A)
1636  if (DE > GetMaxDeltaE(Z, A)) return -GetEIncOfMaxDeltaE(Z, A);
1637 
1638  TF1* dE = GetELossFunction(Z, A);
1639  Double_t e1, e2;
1640  dE->GetRange(e1, e2);
1641  switch (type) {
1642  case kEmin:
1643  e2 = GetEIncOfMaxDeltaE(Z, A);
1644  break;
1645  case kEmax:
1646  e1 = GetEIncOfMaxDeltaE(Z, A);
1647  break;
1648  }
1649  int status;
1650  Double_t EINC = ProtectedGetX(dE, DE, status, e1, e2);
1651  if (status != 0) {
1652 // Warning("GetIncidentEnergy",
1653 // "In %s : Called for Z=%d A=%d with dE=%f sol_type %d",
1654 // GetName(), Z, A, DE, type);
1655 // Warning("GetIncidentEnergy",
1656 // "Max DeltaE in this case is %f MeV",
1657 // GetMaxDeltaE(Z, A));
1658 // Warning("GetIncidentEnergy",
1659 // "Between Einc limits [%f,%f] no solution found",
1660 // e1,e2);
1661 // Warning("GetIncidentEnergy",
1662 // "Returned value is -Einc for %s dE, %f",
1663 // (status>0 ? "maximum" : "minimum"), EINC);
1664  return -EINC;
1665  }
1666  return EINC;
1667 }
1668 
1669 
1670 
1676 
1678 {
1679  // Overrides KVMaterial::GetDeltaEFromERes
1680  //
1681  // Calculate energy loss in active layer of detGetAlignedDetector for nucleus (Z,A)
1682  // having a residual kinetic energy Eres (MeV)
1683 
1684  if (Z < 1 || Eres <= 0.) return 0.;
1685  Double_t Einc = GetIncidentEnergyFromERes(Z, A, Eres);
1686  if (Einc <= 0.) return 0.;
1687  return GetELossFunction(Z, A)->Eval(Einc);
1688 }
1689 
1690 
1691 
1698 
1700 {
1701  // Overrides KVMaterial::GetIncidentEnergyFromERes
1702  //
1703  // Calculate incident energy of nucleus from residual energy.
1704  //
1705  // Returns -1 if Eres is out of defined range of values
1706 
1707  if (Z < 1 || Eres <= 0.) return 0.;
1708  //return GetEResFunction(Z, A)->GetX(Eres);
1709  Int_t status;
1710  Double_t einc = KVBase::ProtectedGetX(GetEResFunction(Z, A), Eres, status);
1711  if (status != 0) {
1712  // problem with inversion - value out of defined range of function
1713  return -1;
1714  }
1715  return einc;
1716 }
1717 
1718 
1719 
1723 
1725 {
1726  // Returns the smallest maximum energy for which range tables are valid
1727  // for all absorbers in the detector, and given ion (Z,A)
1728 
1729  Double_t maxmin = -1.;
1730  TIter next(fAbsorbers);
1731  KVMaterial* abs;
1732  while ((abs = (KVMaterial*)next())) {
1733  if (maxmin < 0.) maxmin = abs->GetEmaxValid(Z, A);
1734  else {
1735  if (abs->GetEmaxValid(Z, A) < maxmin) maxmin = abs->GetEmaxValid(Z, A);
1736  }
1737  }
1738  return maxmin;
1739 }
1740 
1741 
1742 
1760 
1762 {
1763  // Create detector from text file in 'TEnv' format.
1764  //
1765  // Example:
1766  // ========
1767  //
1768  // Layer: Gold
1769  // Gold.Material: Au
1770  // Gold.AreaDensity: 200.*KVUnits::ug
1771  // +Layer: Gas1
1772  // Gas1.Material: C3F8
1773  // Gas1.Thickness: 5.*KVUnits::cm
1774  // Gas1.Pressure: 50.*KVUnits::mbar
1775  // Gas1.Active: yes
1776  // +Layer: Si1
1777  // Si1.Material: Si
1778  // Si1.Thickness: 300.*KVUnits::um
1779 
1780  TEnv fEnvFile(envrc);
1781 
1782  KVString layers(fEnvFile.GetValue("Layer", ""));
1783  layers.Begin(" ");
1784  while (!layers.End()) {
1785  KVString layer = layers.Next();
1786  KVString mat = fEnvFile.GetValue(Form("%s.Material", layer.Data()), "");
1787  KVString tS = fEnvFile.GetValue(Form("%s.Thickness", layer.Data()), "");
1788  KVString pS = fEnvFile.GetValue(Form("%s.Pressure", layer.Data()), "");
1789  KVString dS = fEnvFile.GetValue(Form("%s.AreaDensity", layer.Data()), "");
1790  Double_t thick, dens, press;
1791  thick = dens = press = 0.;
1792  KVMaterial* M = 0;
1793  if (pS != "" && tS != "") {
1794  press = (Double_t)gROOT->ProcessLineFast(Form("%s*1.e+12", pS.Data()));
1795  press /= 1.e+12;
1796  thick = (Double_t)gROOT->ProcessLineFast(Form("%s*1.e+12", tS.Data()));
1797  thick /= 1.e+12;
1798  M = new KVMaterial(mat.Data(), thick, press);
1799  }
1800  else if (tS != "") {
1801  thick = (Double_t)gROOT->ProcessLineFast(Form("%s*1.e+12", tS.Data()));
1802  thick /= 1.e+12;
1803  M = new KVMaterial(mat.Data(), thick);
1804  }
1805  else if (dS != "") {
1806  dens = (Double_t)gROOT->ProcessLineFast(Form("%s*1.e+12", dS.Data()));
1807  dens /= 1.e+12;
1808  M = new KVMaterial(dens, mat.Data());
1809  }
1810  if (M) {
1811  AddAbsorber(M);
1812  if (fEnvFile.GetValue(Form("%s.Active", layer.Data()), kFALSE)) SetActiveLayer(M);
1813  }
1814  }
1815 }
1816 
1817 
1818 
1819 
1837 
1839 {
1840  // Returns list of detectors (including this one) which are in geometrical aligment
1841  // with respect to the target position (assuming this detector is part of a multidetector
1842  // array described by KVMultiDetArray).
1843  //
1844  // By default the list is in the order starting from this detector and going towards the target
1845  // (direction=KVGroup::kBackwards).
1846  // Call with argument direction=KVGroup::kForwards to have the list of detectors in the order
1847  // "seen" by a particle flying out from the target and arriving in this detector.
1848  //
1849  // If this detector is not part of a KVMultiDetArray (i.e. we have no information on
1850  // its geometrical relation to other detectors), we return 0x0.
1851  //
1852  // The list pointers are stored in member variable fAlignedDetectors[] for rapid retrieval,
1853  // the lists will be deleted with this detector.
1854  //
1855  // See KVGroup::GetAlignedDetectors for more details.
1856 
1857  if (!GetGroup() || direction > 1) return 0x0;
1858  if (fAlignedDetectors[direction]) return fAlignedDetectors[direction];
1859  return (fAlignedDetectors[direction] = GetGroup()->GetAlignedDetectors(this, direction));
1860 }
1861 
1862 
1863 
1864 
1866 
1868 {
1869  if (!GetGroup() || direction > 1) return;
1870  if (fAlignedDetectors[direction]) fAlignedDetectors[direction] = 0;
1871 }
1872 
1873 
1874 
1878 
1880 {
1881  // WARNING: SAME AS KVDetector::GetLinearRange
1882  // Only linear range in centimetres is calculated for detectors!
1883  return GetLinearRange(Z, A, Einc);
1884 }
1885 
1886 
1887 
1893 
1895 {
1896  // Returns range of ion in centimetres in this detector,
1897  // taking into account all layers.
1898  // Note that for Einc > punch through energy, this range is no longer correct
1899  // (but still > total thickness of detector).
1900  return GetRangeFunction(Z, A)->Eval(Einc);
1901 }
1902 
1903 
1904 
1908 
1910 {
1911  // Returns energy (in MeV) necessary for ion (Z,A) to punch through all
1912  // layers of this detector
1913 
1914  if (fSingleLayer) {
1915  // Optimize calculation time for single-layer detector
1916  return fActiveLayer->GetPunchThroughEnergy(Z, A);
1917  }
1918  return GetRangeFunction(Z, A)->GetX(GetTotalThicknessInCM());
1919 }
1920 
1921 
1922 
1923 
1928 
1930 {
1931  // Creates and fills a TGraph with the punch through energy in MeV vs. Z for the given detector,
1932  // for Z=1-92. The mass of each nucleus is calculated according to the given mass formula
1933  // (see KVNucleus).
1934 
1935  TGraph* punch = new TGraph(92);
1936  punch->SetName(Form("KVDetpunchthrough_%s_mass%d", GetName(), massform));
1937  punch->SetTitle(Form("Simple Punch-through %s (MeV) (mass formula %d)", GetName(), massform));
1938  KVNucleus nuc;
1939  nuc.SetMassFormula(massform);
1940  for (int Z = 1; Z <= 92; Z++) {
1941  nuc.SetZ(Z);
1942  punch->SetPoint(Z - 1, Z, GetPunchThroughEnergy(nuc.GetZ(), nuc.GetA()));
1943  }
1944  return punch;
1945 }
1946 
1947 
1948 
1953 
1955 {
1956  // Creates and fills a TGraph with the punch through energy in MeV/nucleon vs. Z for the given detector,
1957  // for Z=1-92. The mass of each nucleus is calculated according to the given mass formula
1958  // (see KVNucleus).
1959 
1960  TGraph* punch = new TGraph(92);
1961  punch->SetName(Form("KVDetpunchthroughEsurA_%s_mass%d", GetName(), massform));
1962  punch->SetTitle(Form("Simple Punch-through %s (AMeV) (mass formula %d)", GetName(), massform));
1963  KVNucleus nuc;
1964  nuc.SetMassFormula(massform);
1965  for (int Z = 1; Z <= 92; Z++) {
1966  nuc.SetZ(Z);
1967  punch->SetPoint(Z - 1, Z, GetPunchThroughEnergy(nuc.GetZ(), nuc.GetA()) / nuc.GetA());
1968  }
1969  return punch;
1970 }
1971 
1972 
1973 
1974 
1976 
1978 {
1979  return (KVGroup*)GetParentStructure("GROUP");
1980 }
1981 
1982 
1983 
1985 
1987 {
1988  return (GetGroup() ? GetGroup()->GetNumber() : 0);
1989 }
1990 
1991 
1992 
1994 
1996 {
1997  fParentStrucList.Add(elem);
1998 }
1999 
2000 
2001 
2003 
2005 {
2006  fParentStrucList.Remove(elem);
2007 }
2008 
2009 
2010 
2014 
2016 {
2017  // Get parent geometry structure element of given type.
2018  // Give unique name of structure if more than one element of same type is possible.
2019  KVGeoStrucElement* el = 0;
2020  if (strcmp(name, "")) {
2022  el = (KVGeoStrucElement*)strucs->FindObject(name);
2023  delete strucs;
2024  }
2025  else
2027  return el;
2028 }
2029 
2030 
2031 
2034 
2036 {
2037  // Set ROOT geometry global matrix transformation to coordinate frame of active layer volume
2038  SetMatrix(m);
2039 }
2040 
2041 
2042 
2045 
2047 {
2048  // Set ROOT geometry shape of active layer volume
2049  SetShape(s);
2050 }
2051 
2052 
2053 
2056 
2058 {
2059  // Set ROOT geometry global matrix transformation to coordinate frame of entrance window
2061 }
2062 
2063 
2064 
2067 
2069 {
2070  // Set ROOT geometry shape of entrance window
2071  fEWPosition.SetShape(s);
2072 }
2073 
2074 
2075 
2083 
2085 {
2086  // Overrides KVMaterial::SetThickness
2087  //
2088  // If ROOT geometry is defined, we modify the DZ thickness of the volume representing
2089  // this detector in accordance with the new thickness.
2090  //
2091  // This is only implemented for single-layer detectors with a simple shape.
2092 
2093  if (ROOTGeo() && fSingleLayer) {
2096  TGeoBBox* shape = (TGeoBBox*)pn->GetShape();
2097  TGeoShape* newshape = nullptr;
2098  // bad kludge - is there no better way to clone a shape and change its dZ?
2099  if (shape->IsA() == TGeoBBox::Class()) {
2100  newshape = new TGeoBBox(shape->GetDX(), shape->GetDY(), 0.5 * thick);
2101  }
2102  else if (shape->IsA() == TGeoTube::Class()) {
2103  TGeoTube* oldtube = static_cast<TGeoTube*>(shape);
2104  newshape = new TGeoTube(oldtube->GetRmin(), oldtube->GetRmax(), 0.5 * thick);
2105  }
2106  else {
2107  Error("SetThickness", "No implementation for %s (%s)", shape->IsA()->GetName(), GetName());
2108  }
2109  if (newshape) {
2110  pn->Align(nullptr, newshape);
2111  //Info("SetThickness", "Modified ROOT geometry for %s: new thickness=%g cm", GetName(), thick);
2113  }
2114  }
2115  KVMaterial::SetThickness(thick);
2116 }
2117 
2118 
2119 
2125 
2127 {
2128  // Return kTRUE if the two detectors have the same internal structure, i.e.
2129  // - the same number of absorber layers
2130  // - in the same order
2131  // - with the same material & thickness
2132 
2133  int nabs = GetNumberOfAbsorberLayers();
2134  if (other->GetNumberOfAbsorberLayers() != nabs) return kFALSE;
2135  bool same = true;
2136  for (int iabs = 0; iabs < nabs; ++iabs) {
2137  KVMaterial* this_abs = GetAbsorber(iabs);
2138  KVMaterial* other_abs = other->GetAbsorber(iabs);
2139  if (!this_abs->IsType(other_abs->GetType())
2140  || this_abs->GetMass() != other_abs->GetMass()
2141  || this_abs->GetThickness() != other_abs->GetThickness())
2142  same = false;
2143  }
2144  return same;
2145 }
2146 
2147 
2148 
2156 
2158 {
2159  // Add a new KVDetectorSignalExpression to this detector
2160  //
2161  // \param[in] type the name/type of the new signal
2162  // \param[in] _expr mathematical expression using any of the known signals of the detector
2163  //
2164  // \note If the expression is not valid, no signal will be created and method returns kFALSE.
2165 
2167  if (!ds->IsValid()) {
2168  delete ds;
2169  ds = nullptr;
2170  }
2171  else
2172  AddDetectorSignal(ds);
2173  return (ds != nullptr);
2174 }
2175 
2176 
int Int_t
unsigned int UInt_t
#define SafeDelete(p)
#define d(i)
#define c(i)
#define e(i)
bool Bool_t
unsigned char UChar_t
char Char_t
float Float_t
constexpr Bool_t kFALSE
double Double_t
constexpr Bool_t kTRUE
const char Option_t
const Bool_t kIterBackward
R__EXTERN TEnv * gEnv
winID h TVirtualViewer3D TVirtualGLPainter p
Option_t Option_t option
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t b
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t type
char name[80]
R__EXTERN TGeoManager * gGeoManager
#define gROOT
char * Form(const char *fmt,...)
virtual const Char_t * GetType() const
Definition: KVBase.h:177
virtual Bool_t IsType(const Char_t *typ) const
Definition: KVBase.h:185
virtual void SetType(const Char_t *str)
Definition: KVBase.h:173
Double_t ProtectedGetX(const TF1 *func, Double_t val, int &status, Double_t xmin=0.0, Double_t xmax=0.0) const
Definition: KVBase.cpp:1691
static TPluginHandler * LoadPlugin(const Char_t *base, const Char_t *uri="0")
Definition: KVBase.cpp:793
UInt_t GetNumber() const
Definition: KVBase.h:220
Output signal from detector obtained by calibration.
virtual Bool_t IsAvailableFor(const KVNameValueList &params) const
Base class for all detector calibrations.
Definition: KVCalibrator.h:99
TString GetInputSignalType() const
Definition: KVCalibrator.h:224
void SetDetector(KVDetector *d)
Definition: KVCalibrator.h:232
TString GetOutputSignalType() const
Definition: KVCalibrator.h:228
Signal output from a mathematical combination of other signals.
Base class for output signal data produced by a detector.
virtual Bool_t IsExpression() const
virtual Bool_t IsRaw() const
virtual Bool_t GetValueNeedsExtraParameters() const
virtual Double_t GetValue(const KVNameValueList &params="") const
virtual void Reset()
Base class for detector geometry description.
Definition: KVDetector.h:160
static KVDetector * MakeDetector(const Char_t *name, Float_t thick)
virtual const Char_t * GetArrayName()
Definition: KVDetector.cpp:439
virtual Bool_t IsOK() const
Definition: KVDetector.h:682
void SetMatrix(const TGeoHMatrix *m)
Definition: KVDetector.h:186
KVPosition fEWPosition
position of entrance window i.e. first volume in detector geometry
Definition: KVDetector.h:163
virtual Double_t GetMaxDeltaE(Int_t Z, Int_t A)
@ kIdentifiedParticle
Definition: KVDetector.h:177
@ kUnidentifiedParticle
Definition: KVDetector.h:176
KVUniqueNameList fParentStrucList
list of geometry structures which directly contain this detector
Definition: KVDetector.h:164
Int_t GetNumberOfAbsorberLayers() const
Definition: KVDetector.h:305
virtual void GetVerticesInOwnFrame(TVector3 *, Double_t, Double_t)
virtual Double_t GetERes(Int_t Z, Int_t A, Double_t Einc)
virtual Double_t GetELostByParticle(KVNucleus *, TVector3 *norm=0)
Definition: KVDetector.cpp:276
Double_t ELossActive(Double_t *x, Double_t *par)
Definition: KVDetector.cpp:981
TList * GetTelescopesForIdentification()
Definition: KVDetector.cpp:762
virtual void AddIDTelescope(TObject *idt)
Add ID telescope to list of telescopes to which detector belongs.
Definition: KVDetector.cpp:723
KVList * GetAlignedIDTelescopes()
Definition: KVDetector.cpp:737
KVList * fCalibrators
list of associated calibrator objects
Definition: KVDetector.h:234
KVGeoStrucElement * GetParentStructure(const Char_t *type, const Char_t *name="") const
KVGroup * GetGroup() const
void AddDetectorSignal(KVDetectorSignal *ds)
Definition: KVDetector.h:261
virtual Double_t GetRange(Int_t Z, Int_t A, Double_t Einc)
virtual void SetEnergyLoss(Double_t e) const
Definition: KVDetector.h:373
Bool_t ReplaceCalibrator(const Char_t *type, KVCalibrator *cal, const KVNameValueList &opts="")
Definition: KVDetector.cpp:552
virtual Double_t GetTotalDeltaE(Int_t Z, Int_t A, Double_t Einc)
virtual TGeoVolume * GetGeoVolume()
virtual Double_t GetEnergy() const
Definition: KVDetector.h:349
virtual TF1 * GetEResFunction(Int_t Z, Int_t A)
virtual Double_t GetEIncOfMaxDeltaE(Int_t Z, Int_t A)
virtual TGraph * DrawPunchThroughEsurAVsZ(Int_t massform=KVNucleus::kBetaMass)
static Int_t fDetCounter
Definition: KVDetector.h:166
void AddAbsorber(KVMaterial *)
Definition: KVDetector.cpp:630
virtual Double_t GetEnergyLoss() const
Definition: KVDetector.h:369
virtual Double_t GetEResAfterDetector() const
Definition: KVDetector.h:634
KVList * fIDTelescopes
list of ID telescopes to which detector belongs
Definition: KVDetector.h:168
void SetShape(TGeoBBox *s)
Definition: KVDetector.h:190
void AddParentStructure(KVGeoStrucElement *elem)
Double_t GetTheta() const
Definition: KVDetector.h:744
Double_t fEResforEinc
used by GetIncidentEnergy & GetCorrectedEnergy
Definition: KVDetector.h:252
KVList * fIDTelAlign
list of ID telescopes made of this detector and all aligned detectors placed in front of it
Definition: KVDetector.h:169
virtual Int_t FindZmin(Double_t ELOSS=-1., Char_t mass_formula=-1)
Definition: KVDetector.cpp:907
TF1 * fELossF
parametric function dE in active layer vs. incident energy
Definition: KVDetector.h:248
TList * fAlignedDetectors[2]
stores lists of aligned detectors in both directions
Definition: KVDetector.h:253
virtual void Clear(Option_t *opt="")
Definition: KVDetector.cpp:597
const KVPosition & GetEntranceWindow() const
Definition: KVDetector.h:701
KVMaterial * GetAbsorber(Int_t i) const
Returns pointer to the i-th absorber in the detector (i=0 first absorber, i=1 second,...
Definition: KVDetector.cpp:646
void ClearHits()
Definition: KVDetector.h:430
void remove_signal_for_calibrator(KVCalibrator *K)
Definition: KVDetector.cpp:678
KVList * fAbsorbers
list of absorbers making up the detector
Definition: KVDetector.h:236
TList * fIDTele4Ident
list of ID telescopes used for particle ID
Definition: KVDetector.h:170
TF1 * fEResF
parametric function Eres residual energy after all layers of detector
Definition: KVDetector.h:249
virtual Double_t GetSmallestEmaxValid(Int_t Z, Int_t A)
Bool_t HasSameStructureAs(const KVDetector *) const
void SetThickness(Double_t thick)
virtual void AddToGeometry()
UInt_t GetGroupNumber()
virtual Double_t GetIncidentEnergy(Int_t Z, Int_t A, Double_t delta_e=-1.0, enum SolType type=kEmax)
virtual KVDetectorSignal * GetDetectorSignal(const KVString &type) const
Definition: KVDetector.h:533
virtual void ReadDefinitionFromFile(const Char_t *)
Double_t GetTotalThicknessInCM()
Definition: KVDetector.h:315
Bool_t IsCalibrated() const
Definition: KVDetector.h:390
virtual TF1 * GetELossFunction(Int_t Z, Int_t A)
void SetActiveLayer(KVMaterial *actif)
Definition: KVDetector.h:285
KVDetector()
default ctor
Definition: KVDetector.cpp:76
Bool_t BelongsToUnidentifiedParticle() const
Definition: KVDetector.h:571
Double_t RangeDet(Double_t *x, Double_t *par)
KVMaterial * GetActiveLayer() const
Definition: KVDetector.h:290
virtual void RemoveCalibrators()
Definition: KVDetector.cpp:700
virtual Double_t GetEntranceWindowSurfaceArea()
Return surface area of first layer of detector in cm2.
virtual TGraph * DrawPunchThroughEnergyVsZ(Int_t massform=KVNucleus::kBetaMass)
KVUniqueNameList fDetSignals
list of signals associated with detector
Definition: KVDetector.h:227
Double_t GetPhi() const
Definition: KVDetector.h:762
virtual Double_t GetPunchThroughEnergy(Int_t Z, Int_t A)
Int_t fUnidentP
temporary counters, determine state of identified/unidentified particle flags
Definition: KVDetector.h:181
TF1 * fRangeF
parametric function range of particles in detector
Definition: KVDetector.h:250
Bool_t AddDetectorSignalExpression(const KVString &type, const KVString &_expr)
virtual Double_t GetParticleEIncFromERes(KVNucleus *, TVector3 *norm=0)
Definition: KVDetector.cpp:328
virtual void SetEResAfterDetector(Double_t e)
Definition: KVDetector.h:630
void SetActiveLayerMatrix(const TGeoHMatrix *)
Set ROOT geometry global matrix transformation to coordinate frame of active layer volume.
virtual void Copy(TObject &obj) const
Definition: KVDetector.cpp:127
void RemoveParentStructure(KVGeoStrucElement *elem)
const KVSeqCollection & GetListOfDetectorSignals() const
Definition: KVDetector.h:786
KVList * fParticles
list of particles hitting detector in an event
Definition: KVDetector.h:235
virtual TList * GetAlignedDetectors(UInt_t direction=1)
KVGeoDetectorNode * GetNode()
Definition: KVDetector.h:326
void SetEntranceWindowMatrix(const TGeoHMatrix *)
Set ROOT geometry global matrix transformation to coordinate frame of entrance window.
virtual Double_t GetDeltaE(Int_t Z, Int_t A, Double_t Einc)
Double_t EResDet(Double_t *x, Double_t *par)
Double_t fDepthInTelescope
used to store depth of detector in parent telescope
Definition: KVDetector.h:242
KVMaterial * fActiveLayer
The active absorber in the detector.
Definition: KVDetector.h:167
void AddHit(KVNucleus *part)
Definition: KVDetector.h:405
KVCalibrator * GetCalibrator(const Char_t *name, const Char_t *type) const
Definition: KVDetector.h:815
virtual Double_t GetIncidentEnergyFromERes(Int_t Z, Int_t A, Double_t Eres)
Int_t fIdentP
temporary counters, determine state of identified/unidentified particle flags
Definition: KVDetector.h:180
virtual Double_t GetDeltaEFromERes(Int_t Z, Int_t A, Double_t Eres)
void SetEntranceWindowShape(TGeoBBox *)
Set ROOT geometry shape of entrance window.
void ResetAlignedDetectors(UInt_t direction=1)
virtual void DetectParticle(KVNucleus *, TVector3 *norm=0)
Definition: KVDetector.cpp:203
void SetActiveLayerShape(TGeoBBox *)
Set ROOT geometry shape of active layer volume.
void SetAnalysed(Bool_t b=kTRUE)
Definition: KVDetector.h:447
TString fFName
dynamically generated full name of detector
Definition: KVDetector.h:233
virtual void Print(Option_t *option="") const
Definition: KVDetector.cpp:364
Bool_t fSingleLayer
=kTRUE if detector has a single absorber layer
Definition: KVDetector.h:259
virtual Double_t GetLinearRange(Int_t Z, Int_t A, Double_t Einc)
virtual TF1 * GetRangeFunction(Int_t Z, Int_t A)
virtual Double_t GetCorrectedEnergy(KVNucleus *, Double_t e=-1., Bool_t transmission=kTRUE)
Definition: KVDetector.cpp:811
void init()
default initialisations
Definition: KVDetector.cpp:38
Bool_t AddCalibrator(KVCalibrator *cal, const KVNameValueList &opts="")
Definition: KVDetector.cpp:478
Double_t fTotThickness
used to store value calculated by GetTotalThicknessInCM
Definition: KVDetector.h:241
TGeoBBox * GetShape() const
Definition: KVDetector.h:198
virtual void SetMaterial(const Char_t *type)
Definition: KVDetector.cpp:177
Path taken by particles through multidetector geometry.
const KVSeqCollection * GetIDTelescopes() const
const Char_t * GetFullPathToNode() const
Base class describing elements of array geometry.
Group of detectors which can be treated independently of all others in array.
Definition: KVGroup.h:20
const KVGeoDNTrajectory * GetTrajectoryForReconstruction(const KVGeoDNTrajectory *t, const KVGeoDetectorNode *n) const
Definition: KVGroup.h:104
Extended TList class which owns its objects by default.
Definition: KVList.h:28
Description of physical materials used to construct detectors & targets; interface to range tables.
Definition: KVMaterial.h:94
virtual void SetThickness(Double_t thick)
Definition: KVMaterial.cpp:454
virtual Double_t GetThickness() const
Definition: KVMaterial.cpp:487
virtual Double_t GetPunchThroughEnergy(Int_t Z, Int_t A)
virtual void SetMaterial(const Char_t *type)
Definition: KVMaterial.cpp:225
virtual Double_t GetERes(Int_t Z, Int_t A, Double_t Einc)
virtual Double_t GetDeltaE(Int_t Z, Int_t A, Double_t Einc)
Definition: KVMaterial.cpp:835
virtual void Clear(Option_t *opt="")
Reset absorber - set stored energy lost by particles in absorber to zero.
KVMaterial()
default ctor
Definition: KVMaterial.cpp:77
virtual Double_t GetLinearRange(Int_t Z, Int_t A, Double_t Einc)
Definition: KVMaterial.cpp:902
Double_t GetMass() const
Definition: KVMaterial.cpp:305
Handles lists of named parameters with different types, a list of KVNamedParameter objects.
void SetValue(const Char_t *name, value_type value)
const Char_t * GetStringValue(const Char_t *name) const
Bool_t HasParameter(const Char_t *name) const
Description of properties and kinematics of atomic nuclei.
Definition: KVNucleus.h:126
Int_t GetA() const
Definition: KVNucleus.cpp:802
void SetZ(Int_t z, Char_t mt=-1)
Definition: KVNucleus.cpp:707
void SetMassFormula(UChar_t mt)
Definition: KVNucleus.h:345
Int_t GetZ() const
Return the number of proton / atomic number.
Definition: KVNucleus.cpp:773
TVector3 * GetPInitial() const
Definition: KVParticle.h:726
TVector3 GetMomentum() const
Definition: KVParticle.h:604
KVNameValueList * GetParameters() const
Definition: KVParticle.h:815
Double_t GetEnergy() const
Definition: KVParticle.h:621
void SetKE(Double_t ecin)
Definition: KVParticle.cpp:230
void SetMomentum(const TVector3 *v)
Definition: KVParticle.h:542
void SetE0(TVector3 *e=0)
Definition: KVParticle.h:715
void SetIsDetected()
Definition: KVParticle.h:730
Double_t GetKE() const
Definition: KVParticle.h:614
void SetEnergy(Double_t e)
Definition: KVParticle.h:599
Base class used for handling geometry in a multidetector array.
Definition: KVPosition.h:91
virtual void SetShape(TGeoBBox *)
Definition: KVPosition.cpp:743
Bool_t ROOTGeo() const
Returns kTRUE if ROOT geometry is used, kFALSE if not.
Definition: KVPosition.cpp:598
void GetCornerCoordinates(TVector3 *, Double_t=0)
Definition: KVPosition.cpp:496
virtual Double_t GetDistance(void) const
Definition: KVPosition.h:190
virtual Double_t GetSurfaceArea(int npoints=100000) const
Definition: KVPosition.cpp:974
virtual void SetMatrix(const TGeoHMatrix *)
Definition: KVPosition.cpp:702
virtual TGeoBBox * GetShape() const
Definition: KVPosition.cpp:790
void GetCornerCoordinatesInOwnFrame(TVector3 *, Double_t=0)
Definition: KVPosition.cpp:544
KaliVeda extensions to ROOT collection classes.
virtual void Clear(Option_t *option="")
virtual Int_t GetSize() const
virtual TObject * At(Int_t idx) const
KVSeqCollection * GetSubListWithType(const Char_t *retvalue) const
virtual TObject * FindObjectByType(const Char_t *) const
virtual void Add(TObject *obj)
virtual TObject * Remove(TObject *obj)
Remove object from list.
virtual void Delete(Option_t *option="")
virtual TObject * FindObject(const char *name) const
Extension of ROOT TString class which allows backwards compatibility with ROOT v3....
Definition: KVString.h:73
void Begin(TString delim) const
Definition: KVString.cpp:565
void RBegin(TString delim) const
Definition: KVString.cpp:768
Bool_t End() const
Definition: KVString.cpp:634
KVString Next(Bool_t strip_whitespace=kFALSE) const
Definition: KVString.cpp:695
KVString RNext(Bool_t strip_whitespace=kFALSE) const
Definition: KVString.cpp:841
Associates two detectors placed one behind the other.
Definition: KVTelescope.h:36
Int_t GetDetectorRank(KVDetector *kvd)
returns position (1=front, 2=next, etc.) detector in the telescope structure
Double_t GetDepthInCM(Int_t ndet) const
Definition: KVTelescope.h:74
virtual void Add(TObject *obj)
Handle several calibrations valid for different Z ranges.
virtual void Print(Option_t *option, const char *wildcard, Int_t recurse=1) const
void ls(Option_t *option="") const override
virtual void AddAll(const TCollection *col)
virtual Int_t GetEntries() const
virtual const char * GetValue(const char *name, const char *dflt) const
virtual void SetRange(Double_t xmin, Double_t xmax)
void SetTitle(const char *title="") override
virtual void SetNpx(Int_t npx=100)
virtual Double_t GetX(Double_t y, Double_t xmin=0, Double_t xmax=0, Double_t epsilon=1.E-10, Int_t maxiter=100, Bool_t logx=false) const
virtual void GetRange(Double_t &xmin, Double_t &xmax) const
virtual void SetParameters(const Double_t *params)
virtual Double_t Eval(Double_t x, Double_t y=0, Double_t z=0, Double_t t=0) const
virtual Double_t GetMaximum(Double_t xmin=0, Double_t xmax=0, Double_t epsilon=1.E-10, Int_t maxiter=100, Bool_t logx=false) const
virtual Double_t GetMaximumX(Double_t xmin=0, Double_t xmax=0, Double_t epsilon=1.E-10, Int_t maxiter=100, Bool_t logx=false) const
virtual Double_t GetDX() const
virtual Double_t GetFacetArea(Int_t index=0) const
virtual Double_t GetDY() const
static TClass * Class()
TClass * IsA() const override
TGeoVolume * MakeArb8(const char *name, TGeoMedium *medium, Double_t dz, Double_t *vertices=nullptr)
void RefreshPhysicalNodes(Bool_t lock=kTRUE)
TGeoPhysicalNode * MakePhysicalNode(const char *path=nullptr)
TGeoVolumeAssembly * MakeVolumeAssembly(const char *name)
TGeoVolume * GetTopVolume() const
TObjArray * GetListOfPhysicalNodes()
virtual Int_t GetDefaultColor() const
TGeoMaterial * GetMaterial() const
Bool_t Align(TGeoMatrix *newmat=nullptr, TGeoShape *newshape=nullptr, Bool_t check=kFALSE, Double_t ovlp=0.001)
TGeoShape * GetShape(Int_t level=-1) const
void SetAngles(Double_t phi, Double_t theta, Double_t psi)
virtual Double_t GetRmin() const
static TClass * Class()
virtual Double_t GetRmax() const
virtual TGeoNode * AddNode(TGeoVolume *vol, Int_t copy_no, TGeoMatrix *mat=nullptr, Option_t *option="")
void SetLineColor(Color_t lcolor) override
virtual void SetPoint(Int_t i, Double_t x, Double_t y)
void SetName(const char *name="") override
void SetTitle(const char *title="") override
void Reset()
void Clear(Option_t *option="") override
void Add(TObject *obj) override
TObject * Clone(const char *newname="") const override
const char * GetName() const override
virtual void SetName(const char *name)
TObject * FindObject(const char *name) const override
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) const
virtual const char * ClassName() const
virtual void Warning(const char *method, const char *msgfmt,...) const
virtual Bool_t InheritsFrom(const char *classname) const
virtual void Error(const char *method, const char *msgfmt,...) const
void ResetBit(UInt_t f)
Longptr_t ExecPlugin(int nargs)
const char * Data() const
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
Double_t Y() const
Double_t X() const
Expr< UnaryOp< Sqrt< T >, SMatrix< T, D, D2, R >, T >, T, D, D2, R > sqrt(const SMatrix< T, D, D2, R > &rhs)
T Mag(const SVector< T, D > &rhs)
RVec< PromoteType< T > > abs(const RVec< T > &v)
RVec< PromoteTypes< T0, T1 > > pow(const T0 &x, const RVec< T1 > &v)
Double_t x[n]
gr SetName("gr")
TH1 * h
double T(double x)
double dist(AxisAngle const &r1, AxisAngle const &r2)
void init()
constexpr Double_t K()
v
TMarker m
TArc a
ClassImp(TPyArg)