KaliVeda  1.12/06
Heavy-Ion Analysis Toolkit
KVMultiDetArray.cpp
Go to the documentation of this file.
1 //Created by KVClassFactory on Tue Apr 16 09:45:50 2013
2 //Author: John Frankland,,,
3 
4 #include "KVMultiDetArray.h"
5 #include "Riostream.h"
6 #include "TROOT.h"
7 #include "KVDetector.h"
8 #include "KVDetectorEvent.h"
9 #include "KVReconstructedEvent.h"
10 #include "KVReconstructedNucleus.h"
11 #include "KVACQParam.h"
12 #include "KVRList.h"
13 #include "KVLayer.h"
14 #include "KVEvent.h"
15 #include "KVNucleus.h"
16 #include "KVGroup.h"
17 #include "KVRing.h"
18 #include "KVTelescope.h"
19 #include "KVMaterial.h"
20 #include "KVTarget.h"
21 #include "KVIDTelescope.h"
22 #include "KV2Body.h"
23 #include <KVString.h>
24 #include <TObjString.h>
25 #include <TObjArray.h>
26 #include <KVIDGridManager.h>
27 #include <KVDataSetManager.h>
28 #include <KVUpDater.h>
29 #include "TPluginManager.h"
30 #include "KVDataSet.h"
31 #include "TGeoManager.h"
32 #include "TGeoMedium.h"
33 #include "TGeoMaterial.h"
34 #include "KVHashList.h"
35 #include "KVNameValueList.h"
36 #include "KVUniqueNameList.h"
37 #include "KVIonRangeTable.h"
39 #include <KVDataAnalyser.h>
40 #include <KVNamedParameter.h>
41 #include <KVCalibrator.h>
42 #include <KVDBParameterSet.h>
43 #ifdef WITH_OPENGL
44 #include <TGLViewer.h>
45 #include <TVirtualPad.h>
46 #endif
47 #ifdef WITH_BUILTIN_GRU
48 #include "KVGANILDataReader.h"
49 #else
50 #include "KVRawDataReader.h"
51 #endif
52 #ifdef WITH_MFM
53 #include "KVMFMDataFileReader.h"
54 #include "MFMEbyedatFrame.h"
55 #endif
56 #ifdef WITH_PROTOBUF
57 #include "KVProtobufDataReader.h"
58 #endif
59 using namespace std;
60 
62 
66 
68 
69 
70 
74  : KVGeoStrucElement(), fTrajectories(kTRUE)
75 {
76  // Default constructor
77  init();
78  gMultiDetArray = this;
79 }
80 
81 
82 
85 
87  : KVGeoStrucElement(name, type), fTrajectories(kTRUE)
88 {
89  // Constructor with name and optional type
90  init();
91  gMultiDetArray = this;
92 }
93 
94 
95 
112 
114 {
115  //Basic initialisation called by constructor.
116  //Creates detectors list fDetectors,
117  //groups list fGroups, identification telescopes list
118  //fIDTelescopes
119  //
120  //Cleanups
121  //The fDetectors and fACQParams lists contain references to objects which are
122  //referenced & owned by other objects. We use the ROOT automatic garbage collection
123  //to make sure that any object deleted elsewhere is removed automatically from these lists.
124  //
125  //The fGroups & fIDTelescopes lists contain objects owned by the multidetector array,
126  //but which may be deleted by other objects (or as a result of the deletion of other
127  //objects: i.e. if all the detectors in a group are deleted, the group itself is destroyed).
128  //We use the ROOT automatic garbage collection to make sure that any object deleted
129  //elsewhere is removed automatically from these lists.
130 
131  fIDTelescopes = new KVHashList();
132  fIDTelescopes->SetOwner(kTRUE); // owns its objects
134 
135  fHitGroups = 0;
136 
137  fACQParams = 0;
138  fTarget = 0;
139  fCurrentRun = 0;
140 
142  fCalibStatusDets = 0;
143  fSimMode = kFALSE;
144 
145  fROOTGeometry = gEnv->GetValue("KVMultiDetArray.ROOTGeometry", kTRUE);
147 
148 // fGeoManager = 0;
149  fNavigator = 0;
150  fUpDater = 0;
151 
153 
154  // all trajectories belong to us
156 
157  //all detectors belong to us
159 
160  fHandledRawData = false;
161 }
162 
163 
164 
167 
169 {
170  //destroy (delete) the MDA and all the associated structure, detectors etc.
171 
173  //destroy all identification telescopes
176  delete fIDTelescopes;
177  }
178  fIDTelescopes = 0;
179 
180  //clear list of acquisition parameters
182  fACQParams->Clear();
183  delete fACQParams;
184  }
185  fACQParams = 0;
186 
187  if (fTarget) {
188  delete fTarget;
189  fTarget = 0;
190  }
191  if (gMultiDetArray == this)
192  gMultiDetArray = nullptr;
193 
194  if (fStatusIDTelescopes) {
196  delete fStatusIDTelescopes;
198  }
199  if (fCalibStatusDets) {
201  delete fCalibStatusDets;
202  fCalibStatusDets = 0;
203  }
204 
205  if (fNavigator) {
206  if (gGeoManager) {
207  delete gGeoManager;
208  gGeoManager = nullptr;
209  }
210  delete fNavigator;
211  fNavigator = nullptr;
212  }
214 }
215 
216 
217 
218 
219 
221 
223 {
224 
225 
226 
227 }
228 
229 
230 
231 
253 
255 {
256  // Create one or more KVIDTelescope particle-identification objects from the two detectors
257  //
258  // The different ID telescopes are defined as 'Plugin' objects in the file $KVROOT/KVFiles/.kvrootrc :
259  // # The KVMultiDetArray::GetIDTelescopes(KVDetector*de, KVDetector*e) method uses these plugins to
260  // # create KVIDTelescope instances adapted to the specific array geometry and detector types.
261  // # For each pair of detectors we look for a plugin with one of the following names:
262  // # [name_of_dataset].array_name.de_detector_type[de detector thickness]-e_detector_type[de detector thickness]
263  // # Each characteristic in [] brackets may or may not be present in the name; first we test for names
264  // # with these characteristics, then all combinations where one or other of the characteristics is not present.
265  // # In addition, we first test all combinations which begin with [name_of_dataset].
266  // # The first plugin found in this order will be used.
267  // # In addition, if for one of the two detectors there is a plugin called
268  // # [name_of_dataset].array_name.de_detector_type[de detector thickness]
269  // # [name_of_dataset].array_name.e_detector_type[e detector thickness]
270  // # then we add also an instance of this 1-detector identification telescope.
271  //
272  // This method is called by DeduceIdentificationTelescopesFromGeometry
273  // in order to set up all ID telescopes of the array.
274  //
275  // Returns number of ID telescopes created
276 
277  Int_t ntels = 0;
278  // if both detectors are not OK then stop
279  if (!de->IsOK() && !e->IsOK()) return ntels;
280 
281  if (fDataSet == "" && gDataSet) fDataSet = gDataSet->GetName();
282 
283  //look for ID telescopes starting from furthest from target
284  if (e->IsOK()) ntels += try_all_singleID_telescopes(e, list);
285  if (de != e) {
286  if (e->IsOK() && de->IsOK()) ntels += try_all_doubleID_telescopes(de, e, list);
287  if (de->IsOK()) ntels += try_all_singleID_telescopes(de, list);
288  }
289 
290  return ntels;
291 }
292 
293 
294 
312 
314 {
315  // Attempt to find a plugin KVIDTelescope class for making a single-detector
316  // ID telescope from detector *d
317  // We look for plugins with the following signatures (uri):
318  //
319  // [array name].[type]
320  // [array_name].[type][thickness]
321  //
322  // where 'type' is the type of the detector in UPPER or lowercase letters
323  // 'thickness' is the nearest-integer thickness of the detector as returned by d->GetThickness()
324  // In addition, if a dataset is set (gDataSet!=nullptr) we try also for dataset-specific
325  // plugins:
326  //
327  // [dataset].[array name].[type]
328  // [dataset].[array name].[type][thickness]
329  //
330  // Returns number of generated telescopes
331 
332  TString uri = Form("%s.%s", GetName(), d->GetType());
333  Int_t ntels = 0;
334  if (!(ntels += try_upper_and_lower_singleIDtelescope(uri, d, l))) {
335  Int_t d_thick = TMath::Nint(d->GetThickness());
336  uri += d_thick;
337  ntels += try_upper_and_lower_singleIDtelescope(uri, d, l);
338  }
339  return ntels;
340 }
341 
342 
343 
344 
367 
369 {
370  // Attempt to find a plugin KVIDTelescope class for making an ID telescope from detectors de & e.
371  // We look for plugins with the following signatures (uri):
372  //
373  // [array name].[de-type]-[e-type]
374  // [array name].[de-type][thickness]-[e-type]
375  // [array name].[de-type]-[e-type][thickness]
376  // [array name].[de-type][thickness]-[e-type][thickness]
377  //
378  // where 'type' is the type of the detector in UPPER or lowercase letters
379  // 'thickness' is the nearest-integer thickness of the detector.
380  // In addition, if a dataset is set (gDataSet!=nullptr) we try also for dataset-specific
381  // plugins:
382  //
383  // [dataset].[array name].[de-type][thickness]-[e-type][thickness]
384  // [dataset].[array name].[de-type][thickness]-[e-type]
385  // [dataset].[array name].[de-type]-[e-type][thickness]
386  // [dataset].[array name].[de-type]-[e-type]
387  //
388  // if no plugin is found, we return a KVIDTelescope base class object
389  //
390  // Returns 1 (we always generate exactly one telescope)
391 
392  TString de_type = de->GetType();
393  TString e_type = e->GetType();
394  TString de_thick = Form("%d", TMath::Nint(de->GetThickness()));
395  TString e_thick = Form("%d", TMath::Nint(e->GetThickness()));
396 
397  TString uri = de_type + de_thick + "-" + e_type + e_thick;
398  uri.Prepend(Form("%s.", GetName()));
399  if (try_upper_and_lower_doubleIDtelescope(uri, de, e, l)) return 1;
400 
401  uri = de_type + de_thick + "-" + e_type;
402  uri.Prepend(Form("%s.", GetName()));
403  if (try_upper_and_lower_doubleIDtelescope(uri, de, e, l)) return 1;
404 
405  uri = de_type + "-" + e_type + e_thick;
406  uri.Prepend(Form("%s.", GetName()));
407  if (try_upper_and_lower_doubleIDtelescope(uri, de, e, l)) return 1;
408 
409  uri = de_type + "-" + e_type;
410  uri.Prepend(Form("%s.", GetName()));
411  if (try_upper_and_lower_doubleIDtelescope(uri, de, e, l)) return 1;
412 
413  // default id telescope object
414  KVIDTelescope* idt = new KVIDTelescope;
415  uri = de_type + "-" + e_type;
416  idt->SetLabel(uri);
417  // set type as "[DEtype]-[Etype]" where "[*type]" is type of DE/E detectors
418  idt->SetType(Form("%s-%s", de_type.Data(), e_type.Data()));
419  set_up_telescope(de, e, idt, l);
420 
421  return 1;
422 }
423 
424 
425 
433 
435 {
436  // Attempt to find a plugin KVIDTelescope class for making a single-detector
437  // ID telescope from detector *d with the given signature/uri
438  // Both original & all-upper-case versions of uri are tried.
439  // uri is tried both with & without prepended dataset name (if set)
440  // Returns true if successful (the new ID telescope will be added to internal
441  // list fIDTelescopes and also to TCollection* l)
442 
443  if (try_a_singleIDtelescope(uri, d, l)) return true;
444  uri.ToUpper();
445  return try_a_singleIDtelescope(uri, d, l);
446 }
447 
448 
449 
456 
458 {
459  // Attempt to find a plugin KVIDTelescope class for making an ID telescope with the given signature/uri
460  // Both original & all-upper-case versions of uri are tried.
461  // uri is tried both with & without prepended dataset name (if set)
462  // Returns true if successful (the new ID telescope will be added to internal
463  // list fIDTelescopes and also to TCollection* l)
464 
465  if (try_a_doubleIDtelescope(uri, de, e, l)) return true;
466  uri.ToUpper();
467  return try_a_doubleIDtelescope(uri, de, e, l);
468 }
469 
470 
471 
480 
482 {
483  // Attempt to find a plugin KVIDTelescope class for making a single-detector
484  // ID telescope from detector *d with the given signature/uri
485  // Both original & all-upper-case versions of uri are tried.
486  // uri is tried both with & without prepended dataset name (if set)
487  // Returns true if successful (the new ID telescope will be added to internal
488  // list fIDTelescopes and also to TCollection* l)
489 
490  // dataset-specific version takes precedence over default
491  TString duri = uri;
492  if (gDataSet) {
493  // try with dataset name
494  duri.Prepend(Form("%s.", fDataSet.Data()));
495  KVIDTelescope* idt;
496  if ((idt = KVIDTelescope::MakeIDTelescope(duri))) {
498  return true;
499  }
500  }
501 
502  // look for default version
503  KVIDTelescope* idt;
504  if ((idt = KVIDTelescope::MakeIDTelescope(uri))) {
506  return true;
507  }
508 
509  return false;
510 }
511 
512 
513 
520 
522 {
523  // Attempt to find a plugin KVIDTelescope class for making an ID telescope with the given signature/uri
524  // uri is tried both with & without prepended dataset name (if set)
525  // Returns true if successful (the new ID telescope will be added to internal
526  // list fIDTelescopes and also to TCollection* l)
527 
528  // dataset-specific version takes precedence over default
529  TString duri = uri;
530  if (gDataSet) {
531  // try with dataset name
532  duri.Prepend(Form("%s.", fDataSet.Data()));
533  KVIDTelescope* idt;
534  if ((idt = KVIDTelescope::MakeIDTelescope(duri))) {
535  set_up_telescope(de, e, idt, l);
536  return true;
537  }
538  }
539  // look for default version
540  KVIDTelescope* idt;
541  if ((idt = KVIDTelescope::MakeIDTelescope(uri))) {
542  set_up_telescope(de, e, idt, l);
543  return true;
544  }
545 
546  return false;
547 }
548 
549 
550 
553 
555 {
556  // Set up detectors in de-e identification telescope and add to fIDTelescopes and to l
557 
558  idt->AddDetector(de);
559  idt->AddDetector(e);
560  if (de->GetGroup()) {
561  idt->SetGroup(de->GetGroup());
562  }
563  else {
564  idt->SetGroup(e->GetGroup());
565  }
566  // if telescope already exists, we delete this new version and add a reference to
567  // the original into list l
569  if (p) {
570  l->Add(p);
571  delete idt;
572  }
573  else {
574  fIDTelescopes->Add(idt);
575  l->Add(idt);
576  }
577 }
578 
579 
580 
583 
585 {
586  // Set up detector in single-stage identification telescope and add to fIDTelescopes and to l
587 
588  idt->AddDetector(det);
589  idt->SetGroup(det->GetGroup());
590  // if telescope already exists, we delete this new version and add a reference to
591  // the original into list l
593  if (p) {
594  l->Add(p);
595  delete idt;
596  }
597  else {
598  fIDTelescopes->Add(idt);
599  l->Add(idt);
600  }
601 }
602 
603 
605 
607 {
608  fIDTelescopes->Delete(); // clear out (delete) old identification telescopes
609  KVGroup* grp;
610  unique_ptr<KVSeqCollection> fGroups(GetStructures()->GetSubListWithType("GROUP"));
611  TIter ngrp(fGroups.get());
612  while ((grp = (KVGroup*) ngrp())) {
614  }
615 }
616 
617 
618 
619 
623 
625 {
626  //Number groups according to position in list fGroups and set fGr counter to the number
627  //of groups in the list
628  Int_t fGr = 0;
629  KVGroup* g = 0;
630  KVSeqCollection* fGroups = GetStructures()->GetSubListWithType("GROUP");
631  TIter next(fGroups);
632  while ((g = (KVGroup*) next())) {
633  g->SetNumber(++fGr);
634  }
635  delete fGroups;
636 }
637 
638 
639 
640 
646 
648 {
649  // Perform multi-hit and coherency analysis of filtered event.
650  // round=1,2,... depending on number of times method has been called
651  // Returns number of particles whose status were changed.
652  // When this becomes zero, the coherency analysis is finished
653 
654  Int_t nchanged = 0;
655  KVReconstructedNucleus* recon_nuc;
656 
657  while ((recon_nuc = rec_event->GetNextParticle())) {
658  if (!recon_nuc->IsIdentified()) {
659  int dethits = recon_nuc->GetStoppingDetector()->GetHits()->GetEntries() ;
661  Bool_t pileup = kFALSE;
662  if (dethits > 1) {
663  // if any of the other particles also stopped in the same detector, we assume identification
664  // will be so false as to reject particle
665  for (int j = 0; j < dethits; j++) {
667  if (n != recon_nuc && n->GetStoppingDetector() == recon_nuc->GetStoppingDetector()) pileup = kTRUE;
668  }
669  }
670  if (pileup) {
671  nchanged++;
672  recon_nuc->SetIsIdentified();//to stop looking anymore & to allow identification of other particles in same group
673  if (idtelstop) recon_nuc->SetIDCode(GetBadIDCode());// idtelstop->SetIDCode(recon_nuc, idtelstop->GetBadIDCode());
674  else recon_nuc->SetIsOK(kFALSE);
675  }
676  else if (recon_nuc->GetStatus() == 3) {
677  //stopped in first member
678  recon_nuc->SetIsIdentified();
679  nchanged++;
680  }
681  else if (recon_nuc->GetStatus() == 2) {
682  // pile-up in first stage of telescopes
683  recon_nuc->SetIsIdentified();
684  if (idtelstop && idtelstop->IsReadyForID()) recon_nuc->SetIDCode(GetMultiHitFirstStageIDCode());//idtelstop->SetIDCode(recon_nuc, idtelstop->GetMultiHitFirstStageIDCode());
685  else recon_nuc->SetIsOK(kFALSE);
686  nchanged++;
687  }
688  else if (recon_nuc->GetStatus() == 0) {
689  // try to "identify" the particle
691  idtelstop = (KVIDTelescope*)nxtidt();
692  while (idtelstop) {
693  if (idtelstop->IsReadyForID() && idtelstop->CanIdentify(recon_nuc->GetZ(), recon_nuc->GetA())
694  && idtelstop->CheckTheoreticalIdentificationThreshold(recon_nuc)) { // make sure we are above identification threshold
695  nchanged++;
696  // if this is not the first round, this particle has been 'identified' after
697  // dealing with other particles in the group
698  if (round > 1) recon_nuc->SetIDCode(GetCoherencyIDCode());//idtelstop->SetIDCode(recon_nuc, idtelstop->GetCoherencyIDCode());
699  recon_nuc->SetIsIdentified();
700  recon_nuc->SetIsCalibrated();
701  idtelstop->SetIdentificationStatus(recon_nuc);
702  break;
703  }
704  else {
705  Int_t nseg = recon_nuc->GetNSegDet();
706  recon_nuc->SetNSegDet(TMath::Max(nseg - 1, 0));
707  //if there are other unidentified particles in the group and NSegDet is < 2
708  //then exact status depends on segmentation of the other particles : reanalyse
709  if (recon_nuc->GetNSegDet() < 2 &&
711  nchanged++;
712  break;
713  }
714  //if NSegDet = 0 it's hopeless
715  if (!recon_nuc->GetNSegDet()) {
716  nchanged++;
717  break;
718  }
719  }
720  idtelstop = (KVIDTelescope*)nxtidt();
721  }
722  }
723  }
724  }
725  return nchanged;
726 }
727 
728 
729 
815 
816 void KVMultiDetArray::DetectEvent(KVEvent* event, KVReconstructedEvent* rec_event, const Char_t* detection_frame)
817 {
818  //Simulate detection of event by multidetector array.
819  //
820  // optional argument detection_frame(="" by default) can be used to give name of
821  // inertial reference frame (defined for all particles of 'event') to be used.
822  // e.g. if the simulated event's default reference frame is the centre of mass frame, before calling this method
823  // you should create the 'laboratory' or 'detector' frame with KVEvent::SetFrame(...), and then give the
824  // name of the 'LAB' or 'DET' frame as 3rd argument here.
825  //
826  //For each particle in the event we calculate first its energy loss in the target (if the target has been defined, see KVMultiDetArray::SetTarget).
827  //By default these energy losses are calculated from a point half-way along the beam-direction through the target (taking into account the orientation
828  //of the target), if you want random depths for each event call GetTarget()->SetRandomized() before using DetectEvent().
829  //
830  //If the particle escapes the target then we look for the group in the array that it will hit. If there is one, then the detection of this particle by the
831  //different members of the group is simulated. The actual geometry and algorithms used to calculate the particle's trajectory depend on the
832  //value of fROOTGeometry (modify with SetROOTGeometry(kTRUE/kFALSE):
833  // if kTRUE: we use the ROOT TGeo description of the array generated by CreateGeoManager(). In this case, CreateGeoManager()
834  // must be called once in order to set up the geometry.
835  // if kFALSE: we use the simplistic KaliVeda geometry, i.e. detectors are only defined by min/max polar & azimuthal angles.
836  //
837  //The detectors concerned have their fEloss members set to the energy lost by the particle when it crosses them.
838  //
839  //Give tags to the simulated particles via KVNucleus::AddGroup() method
840  //Two general tags :
841  // - DETECTED : cross at least one active layer of one detector
842  // - UNDETECTED : go through dead zone or stopped in target
843  //We add also different sub group :
844  // - For UNDETECTED particles : "NO HIT", "NEUTRON", "DEAD ZONE", "STOPPED IN TARGET" and "THRESHOLD", the last one concerned particle
845  //go through the first detection stage of the multidetector array but stopped in an absorber (ie an inactive layer)
846  // - For DETECTED particles :
847  // "PUNCH THROUGH" corrresponds to particle which cross all the materials in front of it
848  // (high energy particle punh through), or which miss some detectors due to a non perfect
849  // overlap between defined telescope,
850  // "INCOMPLETE" corresponds to particles which stopped in the first detection stage of the multidetector
851  // in a detector which can not give alone a clear identification,
852  // this correponds to status=3 or idcode=5 in INDRA data
853  //
854  //After the filtered process, a reconstructed event are obtain from the fired groups corresponding
855  //to detection group where at least one detector havec an active layer energy loss greater than zero
856  //this reconstructed event are available for the user in the KVReconstructedEvent* rec_event argument
857  //This pointer is cleared and also the multidet array at the beginning of the method
858  //
859  //INFO to the user :
860  // - at this point the different PILE-UP, several particles going through same telescope, detector
861  // are only taken into account for filter type KVMultiDetArray::kFilterType_Full
862  // - specific cases correponding specific multi detectors are to be implemented in the child class
863  //
864  // === FILTER TYPES ===
865  // Use gMultiDetArray->SetFilterType(...) with one of the following values:
866  // KVMultiDetArray::kFilterType_Geo geometric filter only, particles are kept if they hit detector in the array
867  // energy losses are not calculated, particle energies are irrelevant
868  // KVMultiDetArray::kFilterType_GeoThresh particles are kept if they have enough energy to leave the target,
869  // and enough energy to cross at least one detector of the array
870  // ---> for these two cases, accepted particles are copied into the 'reconstructed' event with their
871  // original simulated energy, charge and mass, although angles are randomized to reflect detector granularity
872  //
873  // KVMultiDetArray::kFilterType_Full full simulation of detection of particles by the array. the calibration parameters
874  // for the chosen run (call to gMultiDetArray->SetParameters(...)) are inverted in order
875  // to calculate pseudo-raw data from the calculated energy losses. the resulting pseudo-raw
876  //
877  // SIMULATED EVENT PARAMETERS
878  // ==========================
879  // The event given as input to the method may contain extra information in its parameter
880  // list concerning the simulation. The parameter list of the event is copied into that of the
881  // reconstructed event, therefore these informations can be accessed from the reconstructed
882  // event using the method
883  // rec_event->GetParameters()
884  //
885  // SIMULATED PARTICLE PARAMETERS
886  // ==========================
887  // For filter types KVMultiDetArray::kFilterType_Geo and KVMultiDetArray::kFilterType_GeoThresh,
888  // for which there is a 1-to-1 correspondance between simulated and reconstructed particles,
889  // we copy the list of parameters associated to each input particle into the output particle.
890  // Note that this list contains full informations on the detection of each particle
891  // (see Users Guide chapter on Filtering)
892  //
893  // TRACKING (only with ROOT geometries)
894  // ====================================
895  // You can visualise the trajectories of particles for individual events in the 3D OpenGL viewer.
896  // To enable this:
897  // gMultiDetArray->GetNavigator()->SetTracking(kTRUE)
898  // Then you can do:
899  // gMultiDetArray->DetectEvent(...)
900  // gMultiDetArray->Draw("tracks")
901  // The geometry of the array with the tracks overlaid will be displayed.
902 
903  if (!event) {
904  Error("DetectEvent", "the KVEvent object pointer has to be valid");
905  return;
906  }
907  if (!rec_event) {
908  Error("DetectEvent", "the KVReconstructedEvent object pointer has to be valid");
909  return;
910  }
911 
912  if (IsROOTGeometry()) {
913  if (!gGeoManager) {
914  Error("DetectEvent", "ROOT geometry is requested, but has not been set: gGeoManager=0x0");
915  return;
916  }
917  if (!fNavigator) {
918  Error("DetectEvent", "Using ROOT geometry, but no navigator exists");
919  return;
920  }
921  if (fNavigator->IsTracking()) {
922  // clear any tracks created by last event
925  }
926  }
927 
928  //Clear the KVReconstructed pointer before a new filter process
929  rec_event->Clear();
930  //Copy any parameters associated with simulated event into the reconstructed event
931  event->GetParameters()->Copy(*(rec_event->GetParameters()));
932  if (!fHitGroups) {
933  //Create the list where fired groups will be stored
934  //for reconstruction
935  fHitGroups = new KVDetectorEvent;
936  }
937  else {
938  //Clear the multidetector before a new filter process
939  fHitGroups->Clear();
940  }
941 
942  // iterate through list of particles
943  KVNucleus* part, *_part;
944  KVNameValueList det_stat;
945  KVNameValueList* nvl = 0;
946  KVNameValueList un;
947 
948  Int_t part_index = 0; //index of particle in event
949  while ((part = event->GetNextParticle())) { // loop over particles
950  ++part_index;
951  TList* lidtel = 0;
952 
953 #ifdef KV_DEBUG
954  cout << "DetectEvent(): looking at particle---->" << endl;
955  part->Print();
956 #endif
957  if (strcmp(detection_frame, "")) _part = (KVNucleus*)part->GetFrame(detection_frame);
958  else _part = (KVNucleus*)part;
959  _part->SetE0();
960  det_stat.Clear();
961  Double_t eLostInTarget = 0;
962  KVDetector* last_det = 0;
963 
964  if (part->GetZ() && !fNavigator->CheckIonForRangeTable(part->GetZ(), part->GetA())) {
965  // ignore charged particles which range table cannot handle
966  det_stat.SetValue("UNDETECTED", Form("Z=%d", part->GetZ()));
967 
968  part->AddGroup("UNDETECTED");
969  part->AddGroup("SUPERHEAVY");
970  }
971  else if (!fNavigator->IsTracking() && (part->GetZ() == 0)) {
972  // when tracking is activated, we follow neutron trajectories
973  // if not, we don't even bother trying
974  det_stat.SetValue("UNDETECTED", "NEUTRON");
975 
976  part->AddGroup("UNDETECTED");
977  part->AddGroup("NEUTRON");
978  }
979  else if (_part->GetKE() < 1.e-3) {
980  det_stat.SetValue("UNDETECTED", "NO ENERGY");
981 
982  part->AddGroup("UNDETECTED");
983  part->AddGroup("NO ENERGY");
984  }
985  else {
986 
987  //Double_t eLostInTarget=0;
988  if (fTarget && part->GetZ()) {
990  //simulate passage through target material
991  Double_t ebef = _part->GetKE();
993  eLostInTarget = ebef - _part->GetKE();
994  if (_part->GetKE() < 1.e-3) {
995  det_stat.SetValue("UNDETECTED", "STOPPED IN TARGET");
996 
997  part->AddGroup("UNDETECTED");
998  part->AddGroup("STOPPED IN TARGET");
999  }
1001  }
1002 
1003  if ((fFilterType != kFilterType_Geo) && _part->GetKE() < 1.e-3) {
1004  // unless we are doing a simple geometric filter, particles which
1005  // do not have the energy to leave the target are not detected
1006  }
1007  else {
1008  if (!(nvl = DetectParticle(_part))) {
1009  if (part->GetZ() == 0) {
1010  // tracking
1011  det_stat.SetValue("UNDETECTED", "NEUTRON");
1012 
1013  part->AddGroup("UNDETECTED");
1014  part->AddGroup("NEUTRON");
1015  }
1016  else {
1017  det_stat.SetValue("UNDETECTED", "NO HIT");
1018 
1019  part->AddGroup("UNDETECTED");
1020  part->AddGroup("NO HIT");
1021  }
1022 
1023  }
1024  else if (nvl->GetNpar() == 0) {
1025 
1026  if (part->GetZ() == 0) {
1027  // tracking
1028  det_stat.SetValue("UNDETECTED", "NEUTRON");
1029 
1030  part->AddGroup("UNDETECTED");
1031  part->AddGroup("NEUTRON");
1032  }
1033  else {
1034  part->AddGroup("UNDETECTED");
1035  part->AddGroup("DEAD ZONE");
1036 
1037  det_stat.SetValue("UNDETECTED", "DEAD ZONE");
1038  }
1039  delete nvl;
1040  nvl = 0;
1041  }
1042  else {
1043  Int_t nbre_nvl = nvl->GetNpar();
1044  KVString LastDet(nvl->GetNameAt(nbre_nvl - 1));
1045  last_det = GetDetector(LastDet.Data());
1046  TList* ldet = last_det->GetAlignedDetectors();
1047  TIter it1(ldet);
1048 
1049  Int_t ntrav = 0;
1050  KVDetector* dd = 0;
1051  if (!IsROOTGeometry()) {
1052  //Test de la trajectoire coherente
1053  while ((dd = (KVDetector*)it1.Next())) {
1054  if (dd->GetHits()) {
1055  if (dd->GetHits()->FindObject(_part))
1056  ntrav += 1;
1057  else if (dd->IsSmallerThan(last_det))
1058  ntrav += 1;
1059  }
1060  else {
1061  if (dd->IsSmallerThan(last_det))
1062  ntrav += 1;
1063  }
1064  }
1065  }
1066  else {
1067  ntrav = ldet->GetEntries();
1068  }
1069 
1070  if (ntrav != ldet->GetEntries()) {
1071 
1072  // la particule a une trajectoire
1073  // incoherente, elle a loupe un detecteur avec une ouverture
1074  // plus large que ceux a la suite ou la particule est passe
1075  // (ceci peut etre du a un pb de definition de zone morte autour de certains detecteur)
1076  //
1077  // on retire la particule sur tout les detecteurs
1078  // ou elle est enregistree et on retire egalement
1079  // sa contribution en energie
1080  //
1081  // on assimile en fait ces particules a
1082  // des particules arretes dans les zones mortes
1083  // non detectees
1084  it1.Reset();
1085  //Warning("DetectEvent","trajectoire incoherente ...");
1086  while ((dd = (KVDetector*)it1.Next()))
1087  if (dd->GetHits() && dd->GetHits()->FindObject(_part)) {
1088  if (nvl->HasParameter(dd->GetName())) {
1089  Double_t el = dd->GetEnergy();
1090  el -= nvl->GetDoubleValue(dd->GetName());
1091  dd->SetEnergyLoss(el);
1092  if (dd->GetNHits() == 1)
1093  dd->SetEnergyLoss(0);
1094  }
1095  dd->GetHits()->Remove(_part);
1096  }
1097  det_stat.SetValue("UNDETECTED", "GEOMETRY INCOHERENCY");
1098 
1099  part->AddGroup("UNDETECTED");
1100  part->AddGroup("GEOMETRY INCOHERENCY");
1101  }
1102  else {
1103 
1104  //On recupere les telescopes d identification
1105  //associe au dernier detecteur touche
1106  lidtel = last_det->GetTelescopesForIdentification();
1107  if (lidtel->GetEntries() == 0 && last_det->GetEnergy() <= 0) {
1108  //Arret dans un absorbeur
1109  det_stat.SetValue("UNDETECTED", "THRESHOLD");
1110 
1111  part->AddGroup("UNDETECTED");
1112  part->AddGroup("THRESHOLD");
1113 
1114  //On retire la particule du detecteur considere
1115  //
1116  last_det->GetHits()->Remove(_part);
1117  //Warning("DetectEvent","threshold ...");
1118  }
1119  else {
1120  part->AddGroup("DETECTED");
1121  det_stat.SetValue("DETECTED", "OK");
1122  fHitGroups->AddGroup(last_det->GetGroup());
1123 
1124  if (lidtel->GetEntries() > 0) {
1125  //Il y a possibilite d identification
1126  }
1127  else if (last_det->GetEnergy() > 0) {
1128  //Il n'y a pas de possibilite d'identification
1129  //arret dans le premier etage de detection
1130  det_stat.SetValue("DETECTED", "INCOMPLETE");
1131  part->AddGroup("INCOMPLETE");
1132  }
1133  else {
1134  Warning("DetectEvent", "Cas non prevu ....");
1135  printf("last_det->GetName()=%s, lidtel->GetEntries()=%d, last_det->GetEnergy()=%lf\n",
1136  last_det->GetName(),
1137  lidtel->GetEntries(),
1138  last_det->GetEnergy()
1139  );
1140  }
1141 
1142  //Test d'une energie residuelle non nulle
1143  //La particule n a pas ete arrete par le detecteur
1144  if (_part->GetKE() > 1.e-3) {
1145  //Pour ces deux cas
1146  //on a une information incomplete
1147  //pour la particule
1148  if (nbre_nvl != Int_t(last_det->GetGroup()->GetNumberOfDetectorLayers())) {
1149  //----
1150  // Fuite,
1151  // la particule a loupe des detecteurs normalement aligne
1152  // avec le dernier par laquelle elle est passee
1153  // (ceci peut etre du a un pb de definition de la geometrie)
1154  part->RemoveGroup("DETECTED");
1155  det_stat.RemoveParameter("DETECTED");
1156 
1157  det_stat.SetValue("UNDETECTED", "GEOMETRY INCOHERENCY");
1158  part->AddGroup("UNDETECTED");
1159  part->AddGroup("GEOMETRY INCOHERENCY");
1160  //Warning("DetectEvent","Fuite ......");
1161  }
1162  else if (nbre_nvl) {
1163  //----
1164  // Punch Through,
1165  // La particule est trop energetique, elle a traversee
1166  // tout l'appareillage de detection
1167  //Warning("DetectEvent","Punch Through ......");
1168  part->AddGroup("PUNCH THROUGH");
1169  det_stat.SetValue("DETECTED", "PUNCH THROUGH");
1170  //Warning("DetectEvent","Punch Through ......");
1171  }
1172  } //fin du cas ou la particule avait encore de l energie apres avoir traverser l ensemble du detecteur
1173  } //fin du cas ou la particule a laisse de l energie dans un detecteur
1174  } //fin du cas ou la trajectoire est coherente avec la geometrie
1175  } //fin du cas ou la particule a touche un detecteur au sens large
1176  } //fin de la condition (FilterType == kFilterType_Geo) || _part->GetKE()>1.e-3
1177  } // end case where particle with a non-zero KE left the target
1178 
1179  //On enregistre l eventuelle perte dans la cible
1180  if (fTarget)
1181  part->GetParameters()->SetValue("TARGET Out", eLostInTarget);
1182  //On enregistre le detecteur ou la particule s'arrete
1183  if (last_det)
1184  part->GetParameters()->SetValue("STOPPING DETECTOR", last_det->GetName());
1185  //On enregistre le telescope d'identification
1186  if (lidtel && lidtel->GetEntries()) {
1187  KVIDTelescope* theIDT = 0;
1188  TIter nextIDT(lidtel);
1189  while ((theIDT = (KVIDTelescope*)nextIDT())) {
1190  // make sure particle passed through telescope's detectors
1191  Int_t ndet = theIDT->GetSize();
1192  Int_t ntouche = 0;
1193  for (int i = 1; i <= ndet; i++) {
1194  if (nvl && nvl->HasParameter(Form("%s", theIDT->GetDetector(i)->GetName())))
1195  ntouche++;
1196  }
1197  if (ntouche < ndet) continue;
1198  if (fFilterType == kFilterType_Geo ||
1199  (theIDT->IsReadyForID() && theIDT->CanIdentify(part->GetZ(), part->GetA()))) {
1200  part->GetParameters()->SetValue("IDENTIFYING TELESCOPE", theIDT->GetName());
1201  break;
1202  }
1203  }
1204  }
1205  //On enregistre le statut de detection
1206  //dans l objet KVNucleus
1207  for (Int_t ii = 0; ii < det_stat.GetNpar(); ii += 1) {
1208  part->GetParameters()->SetValue(det_stat.GetNameAt(ii), det_stat.GetStringValue(ii));
1209  }
1210  //On enregistre les differentes pertes d'energie dans les detecteurs
1211  //dans l objet KVNucleus
1212  if (nvl) {
1213 
1214  for (Int_t ii = 0; ii < nvl->GetNpar(); ii += 1) {
1215  TString detname = nvl->GetNameAt(ii);
1216  part->GetParameters()->SetValue(detname, nvl->GetDoubleValue(ii));
1217  // For fFilterType == kFilterType_Full:
1218  // for each detector hit we record the index of each particle hitting the detector
1219  // [detector]="13" => detector hit by particle 13
1220  // if more than one we have
1221  // [detector]="1 6" => detector hit by particles 1 & 6
1222  if (fFilterType == kFilterType_Full) {
1223  if (un.HasParameter(detname)) {
1224  KVNumberList ppp(un.GetStringValue(detname));
1225  ppp.Add(part_index);
1226  un.SetValue(detname, ppp.AsString());
1227  }
1228  else {
1229  un.SetValue(detname, Form("%d", part_index));
1230  }
1231  }
1232  }
1233  delete nvl;
1234  nvl = 0;
1235  }
1236 
1237  _part->SetMomentum(*_part->GetPInitial());
1238 
1239  } //fin de loop over particles
1240 
1241  // Info("DetectEvent", "Finished filtering event. Event status now:");
1242  // event->Print();
1243 
1244  // EVENT RECONSTRUCTION FOR SIMPLE GEOMETRIC FILTER
1245  /*
1246  We keep all particles EXCEPT those belonging to groups
1247  "NO HIT" "DEAD ZONE" or "GEOMETRY INCOHERENCY"
1248  */
1249  if (fFilterType == kFilterType_Geo) {
1250 
1251  KVGroup* grp_tch;
1252  TIter nxt_grp(fHitGroups->GetGroups());
1253  while ((grp_tch = (KVGroup*) nxt_grp())) {
1254  grp_tch->ClearHitDetectors();
1255  }
1256  while ((part = event->GetNextParticle())) {
1257  if (part->BelongsToGroup("DETECTED") ||
1258  (part->BelongsToGroup("UNDETECTED") &&
1259  !part->BelongsToGroup("NO HIT") &&
1260  !part->BelongsToGroup("DEAD ZONE") &&
1261  !part->BelongsToGroup("GEOMETRY INCOHERENCY") &&
1262  !part->BelongsToGroup("NEUTRON") &&
1263  !part->BelongsToGroup("NO ENERGY"))
1264  ) {
1265  KVDetector* last_det = 0;
1266  if (part->GetParameters()->HasParameter("STOPPING DETECTOR"))
1267  last_det = GetDetector(part->GetParameters()->GetStringValue("STOPPING DETECTOR"));
1268  if (!last_det) continue;
1269  KVReconstructedNucleus* recon_nuc = (KVReconstructedNucleus*)rec_event->AddParticle();
1270  // copy parameter list
1271  part->GetParameters()->Copy(*(recon_nuc->GetParameters()));
1272  recon_nuc->Reconstruct(last_det);
1273  recon_nuc->SetZandA(part->GetZ(), part->GetA());
1274  recon_nuc->SetE(part->GetFrame(detection_frame, kFALSE)->GetE());
1275  if (part->GetParameters()->HasParameter("IDENTIFYING TELESCOPE")) {
1276  KVIDTelescope* idt = GetIDTelescope(part->GetParameters()->GetStringValue("IDENTIFYING TELESCOPE"));
1277  if (idt) {
1278  recon_nuc->SetIdentifyingTelescope(idt);
1279  recon_nuc->SetIDCode(idt->GetIDCode());//idt->SetIDCode(recon_nuc, idt->GetIDCode());
1280  recon_nuc->SetECode(GetNormalCalibrationCode());//recon_nuc->SetECode(idt->GetECode());
1281  }
1282  }
1284  }
1285  }
1286 
1287  // analyse all groups & particles
1288  nxt_grp.Reset();
1289  while ((grp_tch = (KVGroup*) nxt_grp())) {
1291  }
1292  KVReconstructedNucleus* recon_nuc;
1293  while ((recon_nuc = rec_event->GetNextParticle())) {
1294  // check for undetectable pile-ups
1295  if (recon_nuc->GetStatus() == KVReconstructedNucleus::kStatusOK) {
1296  if (recon_nuc->GetStoppingDetector()->GetNHits() > 1)
1298  else {
1299  KVIDTelescope* idt = recon_nuc->GetIdentifyingTelescope();
1300  if (idt) {
1301  KVDetector* de_det = idt->GetDetector(1);
1302  if (de_det->GetNHits() > 1) recon_nuc->SetStatus(KVReconstructedNucleus::kStatusPileupDE);
1303  }
1304  }
1305  }
1306  recon_nuc->SetIsOK(kFALSE);
1308  recon_nuc->SetIsIdentified();
1309  recon_nuc->SetIsCalibrated();
1310  recon_nuc->SetIsOK();
1311  recon_nuc->SetZMeasured();
1312  recon_nuc->SetAMeasured();
1313  }
1314  }
1315  return;
1316  }
1317  // EVENT RECONSTRUCTION FOR SIMPLE GEOMETRIC FILTER WITH THRESHOLDS
1318  /*
1319  We keep all particles belonging to "DETECTED" group
1320  Those in "INCOMPLETE" group are treated as Zmin particles
1321  */
1323  // before reconstruction we have to clear the list of 'hits' of each detector
1324  // (they currently hold the addresses of the simulated particles which were detected)
1325  // which will be filled with the reconstructed particles, otherwise the number of hits
1326  // in each detector will be 2x the real value, and coherency analysis of the reconstructed
1327  // events will not work
1328  KVGroup* grp_tch;
1329  TIter nxt_grp(fHitGroups->GetGroups());
1330  while ((grp_tch = (KVGroup*) nxt_grp())) grp_tch->ClearHitDetectors();
1331  KVReconstructedNucleus* recon_nuc;
1332  while ((part = event->GetNextParticle())) {
1333  if (part->BelongsToGroup("DETECTED")) {
1334  KVDetector* last_det = 0;
1335  if (part->GetParameters()->HasParameter("STOPPING DETECTOR"))
1336  last_det = GetDetector(part->GetParameters()->GetStringValue("STOPPING DETECTOR"));
1337  if (!last_det || !(last_det->IsOK())) continue;
1338 
1339  recon_nuc = (KVReconstructedNucleus*)rec_event->AddParticle();
1340  // copy parameter list
1341  part->GetParameters()->Copy(*(recon_nuc->GetParameters()));
1342  recon_nuc->Reconstruct(last_det);
1343  recon_nuc->SetZandA(part->GetZ(), part->GetA());
1344  recon_nuc->SetE(part->GetFrame(detection_frame, kFALSE)->GetE());
1345 
1346  if (part->GetParameters()->HasParameter("IDENTIFYING TELESCOPE")) {
1347  KVIDTelescope* idt = GetIDTelescope(part->GetParameters()->GetStringValue("IDENTIFYING TELESCOPE"));
1348  if (idt) {
1349  recon_nuc->SetIdentifyingTelescope(idt);
1350  // for particles which are apprently well-identified, we
1351  // check that they are in fact sufficiently energetic to be identified
1352  if (!part->BelongsToGroup("INCOMPLETE")
1353  && !idt->CheckTheoreticalIdentificationThreshold((KVNucleus*)part->GetFrame(detection_frame, kFALSE)))
1354  part->AddGroup("INCOMPLETE");
1355  if (!part->BelongsToGroup("INCOMPLETE")) {
1356  recon_nuc->SetIDCode(idt->GetIDCode());//idt->SetIDCode(recon_nuc, idt->GetIDCode());
1357  idt->SetIdentificationStatus(recon_nuc);
1358  }
1359  else {
1360  recon_nuc->SetIDCode(GetZminCode());//idt->SetIDCode(recon_nuc, idt->GetZminCode());
1361  }
1362  recon_nuc->SetECode(GetNormalCalibrationCode());//recon_nuc->SetECode(idt->GetECode());
1363  //recon_nuc->SetIsIdentified();
1364  //recon_nuc->SetIsCalibrated();
1365  }
1366  }
1367  else { /*if(part->BelongsToGroup("INCOMPLETE"))*/
1368  // for particles stopping in 1st member of a telescope, there is no "identifying telescope"
1369  //KVIDTelescope* idt = (KVIDTelescope*)last_det->GetIDTelescopes()->First();
1370  //if (idt) idt->SetIDCode(recon_nuc, idt->GetZminCode());
1371  recon_nuc->SetIDCode(GetZminCode());
1372  }
1374  }
1375  }
1376  // analyse all groups & particles
1377  nxt_grp.Reset();
1378  while ((grp_tch = (KVGroup*) nxt_grp())) {
1380  }
1381 
1382  // now perform mult-hit/coherency analysis until no further changes take place
1383  Int_t round = 1, nchanged;
1384  //cout << "SIM: " << event->GetMult() << " REC: " << rec_event->GetMult() << endl;
1385  //for(int i=1;i<=rec_event->GetMult();i++) cout << i << " Z=" << rec_event->GetParticle(i)->GetZ()<<" status="<<rec_event->GetParticle(i)->GetStatus() <<endl;
1386  do {
1387  nchanged = FilteredEventCoherencyAnalysis(round++, rec_event);
1388  //cout << "Round = " << round-1 << " : nchanged = " << nchanged << endl;
1389  nxt_grp.Reset();
1390  while ((grp_tch = (KVGroup*) nxt_grp())) {
1392  }
1393  //for(int i=1;i<=rec_event->GetMult();i++) cout << i << " Z=" << rec_event->GetParticle(i)->GetZ()<<" status="<<rec_event->GetParticle(i)->GetStatus() <<endl;
1394  }
1395  while (nchanged);
1396 
1397  return;
1398  }
1399 
1400  if (fFilterType == kFilterType_Full) {
1401  // Calculate acquisition parameters, taking into account pile-up
1402  KVDetector* det = 0;
1403  for (Int_t nn = 0; nn < un.GetNpar(); nn += 1) {
1404  det = GetDetector(un.GetNameAt(nn));
1405  KVNumberList ppp(un.GetStringValue(nn));
1406  det->DeduceACQParameters(event, ppp);
1407  }
1408 
1409  // before reconstruction we have to clear the list of 'hits' of each detector
1410  // (they currently hold the addresses of the simulated particles which were detected)
1411  // which will be filled with the reconstructed particles, otherwise the number of hits
1412  // in each detector will be 2x the real value, and coherency analysis of the reconstructed
1413  // events will not work
1414  KVGroup* grp_tch;
1415  TIter nxt_grp(fHitGroups->GetGroups());
1416  while ((grp_tch = (KVGroup*) nxt_grp())) {
1417  grp_tch->ClearHitDetectors();
1418  }
1419  // Info("DetectEvent", "Multidetector status before event reconstruction:");
1420  // fHitGroups->Print();
1421 
1422  // reconstruct & identify the event
1423  ReconstructEvent(rec_event, fHitGroups);
1424  rec_event->IdentifyEvent();
1425  // calculate particle energies
1426  rec_event->CalibrateEvent();
1427  // 'coherency'
1428  rec_event->SecondaryIdentCalib();
1429  return;
1430  }
1431 
1432 }
1433 
1434 
1448 
1450 {
1451  // Use ROOT geometry to propagate particle through the array,
1452  // calculating its energy losses in all absorbers, and setting the
1453  // energy loss members of the active detectors on the way.
1454  //
1455  // It is assumed that the ROOT geometry has been generated and is
1456  // pointed to by gGeoManager.
1457  //
1458  // Returns a list (KVNameValueList pointer) of the crossed detectors with their name and energy loss
1459  // if particle hits detector in array, 0 if not (i.e. particle
1460  // in beam pipe or dead zone of the multidetector)
1461  // INFO User has to delete the KVNameValueList after its use
1462 
1463  // list of energy losses in active layers of detectors
1464  KVNameValueList* NVL = 0;
1465  if (!fNavigator) {
1466  Error("DetectParticle_TGEO", "No existing navigator ...");
1467  return 0;
1468  }
1470 
1471  // particle missed all detectors
1472  if (!part->GetParameters()->GetNpar()) return NVL;
1473  else {
1474  // find detectors in array hit by particle
1475  // and set their energies
1476  TIter next(part->GetParameters()->GetList());
1477  KVNamedParameter* param;
1478  while ((param = (KVNamedParameter*)next())) {
1479  KVString pname(param->GetName());
1480  pname.Begin(":");
1481  KVString pn2 = pname.Next();
1482  KVString pn3 = pname.Next();
1483  if (pn2 == "DE") {
1484  pn3.Begin("/");
1485  KVString det_name = pn3.Next();
1486  if (pn3.End() || pn3.Next().BeginsWith("ACTIVE")) {
1487  // energy loss in active layer of detector
1488  KVDetector* curDet = GetDetector(det_name);
1489  if (curDet) {
1490  Double_t de = param->GetDouble();
1491  if (!NVL) NVL = new KVNameValueList;
1492  NVL->SetValue(curDet->GetName(), de);
1493  }
1494  }
1495  }
1496  }
1497  }
1498  return NVL;
1499 }
1500 
1501 
1502 
1518 
1520  KVDetector*)
1521 {
1522  //Replace (and destroy) the named detector in the array with a detector based on the prototype
1523  //given by the pointer new_kvd.
1524 
1525 // KVDetector *kvd = GetDetector(name);
1526 // if (!kvd) {
1527 // Warning("ReplaceDetector", "Detector %s not found", name);
1528 // return;
1529 // }
1530 // //get telescope of detector, so we know where to put the replacement
1531 // KVTelescope *tel = kvd->GetTelescope();
1532 // if (!tel) {
1533 // Error("ReplaceDetector", "Detector %s is not in a telescope", name);
1534 // return;
1535 // }
1536 // tel->ReplaceDetector(kvd, new_kvd);
1537  Warning("ReplaceDetector", "Needs reimplementing");
1538 }
1539 
1540 
1541 
1542 
1545 
1547 {
1548  // Return pointer to telescope in array with name given by "name"
1549  return 0;
1550 }
1551 
1552 
1553 
1556 
1558 {
1559  //Return pointer to DeltaE-E ID Telescope with "name"
1560 
1561  return (KVIDTelescope*) fIDTelescopes->FindObject(name);
1562 }
1563 
1564 
1565 
1566 
1567 
1571 
1573 {
1574  //return pointer to group in array which contains detector or telescope
1575  //with name "name"
1576 
1577  KVTelescope* tel = 0;
1578  KVDetector* det = 0;
1579  KVGroup* grp = 0;
1580  if ((tel = GetTelescope(name))) {
1581  grp = (KVGroup*)tel->GetParentStructure("GROUP");
1582  return grp;
1583  }
1584  if ((det = GetDetector(name))) {
1585  grp = det->GetGroup();
1586  }
1587  return grp;
1588 }
1589 
1590 
1591 
1594 
1596 {
1597  // Return pointer to group with name
1598  return (KVGroup*)GetStructure("GROUP", name);
1599 }
1600 
1601 
1602 
1603 
1604 
1606 
1608 {
1609  AbstractMethod("MakeListOfDetectors");
1610 }
1611 
1612 
1613 
1618 
1620 {
1621  //Reset all groups (lists of detected particles etc.)
1622  //and detectors in groups (energy losses, ACQparams etc. etc.)
1623  //and the target if there is one
1624 
1625  unique_ptr<KVSeqCollection> fGroups(GetStructures()->GetSubListWithType("GROUP"));
1626 
1627  TIter next(fGroups.get());
1628  KVGroup* grp;
1629  while ((grp = (KVGroup*) next())) {
1630  grp->Reset();
1631  }
1632  if (GetTarget())
1633  GetTarget()->Clear();
1634 }
1635 
1636 
1637 
1644 
1646 {
1647  //Add an acquisition parameter corresponding to a detector of the array.
1648  //The fACQParams list is added to the list of cleanups (gROOT->GetListOfCleanups).
1649  //Each acq-param has its kMustCleanup bit set.
1650  //Thus, if the acq-param is deleted (e.g. by the detector which owns it), it is
1651  //automatically removed from the fACQParams list by ROOT.
1652 
1653  if (!fACQParams) {
1654  fACQParams = new KVHashList;
1655  fACQParams->SetName(Form("List of acquisition parameters for multidetector array %s", GetName()));
1658  }
1659  if (par) {
1660  fACQParams->Add(par);
1661  }
1662  else
1663  Warning("AddACQParam", "Null pointer passed as argument");
1664 }
1665 
1666 
1667 
1668 
1692 
1694 {
1695  // Set up acquisition parameters in all detectors of the array + any acquisition parameters which are not
1696  // directly related to a detector.
1697  //
1698  // Override the method SetArrayACQParams() in order to add any acquisition parameters not directly
1699  // related to a detector.
1700  //
1701  // For the detector acquisition parameters, we loop over all detectors of the array and call each detector's
1702  // SetACQParams() method, if it has not already been done (i.e. if the detector has no associated parameters).
1703  // Each specific implementation of a KVDetector class should redefine the KVDetector::SetACQParams()
1704  // method in order to give the detector in question the necessary acquisition parameters (KVACQParam objects).
1705  //
1706  // The list of acquisition parameters of each detector is then used to
1707  // 1) add to fACQParams list of all acquisition parameters of the array
1708  // 2) set as "not working" the acquisition parameters for which environment variables such as
1709  // [dataset name].KVACQParam.[acq par name].Working: NO
1710  // are set in a .kvrootrc file.
1711  // 3) set bitmask for each detector used to determine which acquisition parameters are
1712  // taken into account by KVDetector::Fired based on the environment variables
1713  // [classname].Fired.ACQParameterList.[type]: PG,GG,T
1714  // where [classname]=KVDetector by default, or the name of some class
1715  // derived from KVDetector which calls the method KVDetector::SetKVDetectorFiredACQParameterListFormatString()
1716  // in its constructor.
1717 
1718  if (fACQParams) {
1719  fACQParams->Clear();
1720  }
1721 
1723 
1724  TIter next(GetDetectors());
1725  KVDetector* det;
1726  while ((det = (KVDetector*) next())) {
1727  KVSeqCollection* l = det->GetACQParamList();
1728  if (!l) {
1729  //detector has no acq params
1730  //set up acqparams in detector
1731  det->SetACQParams();
1732  l = det->GetACQParamList();
1733  }
1734  //loop over acqparams and add them to fACQParams list, checking
1735  //their status (working or not working ?)
1736  TIter next_par(l);
1737  KVACQParam* par;
1738  while ((par = (KVACQParam*) next_par())) {
1739  AddACQParam(par);
1740  par->SetWorking(gDataSet->GetDataSetEnv(Form("KVACQParam.%s.Working", par->GetName()), kTRUE));
1741  }
1742  // set bitmask
1743  KVString inst;
1744  inst.Form(det->GetFiredACQParameterListFormatString(), det->GetType());
1745  KVString lpar = gDataSet->GetDataSetEnv(inst);
1746  det->SetFiredBitmask(lpar);
1747  }
1748 }
1749 
1750 
1751 
1752 
1757 
1759 {
1760  // Method called by SetACQParams() in order to define any acquisition parameters which are not
1761  // directly related to any detectors of the array.
1762  // This implementation does nothing: override it in derived classes if needed.
1763 }
1764 
1765 
1766 
1772 
1774 {
1775  // Sets up calibrators for all detectors with a defined calibration for run
1776  // Set parameters for all detectors with links to table "Calibrations" for run
1777  // If 'myname' is given, we look in "myname.Calibrations"
1778 
1779  //Reset all calibrators of all detectors first
1780  TIter next(GetDetectors());
1781  KVDetector* kvd;
1782  while ((kvd = (KVDetector*) next())) kvd->RemoveCalibrators();
1783 
1784  TString tabname = (myname != "" ? Form("%s.Calibrations", myname.Data()) : "Calibrations");
1785  Info("SetCalibratorParameters", "For array %s in table %s", GetName(), tabname.Data());
1786  KVRList* run_links = r->GetLinks(tabname);
1787  if (run_links) Info("SetCalibratorParameters", "Found %d calibrations for this run", run_links->GetEntries());
1788  else {
1789  Warning("SetCalibratorParameters", "Got no links for %s", tabname.Data());
1790  r->GetKeys()->ls();
1791  return;
1792  }
1793  TIter nxt_link(run_links);
1794  KVDBParameterSet* dbps;
1795  while ((dbps = (KVDBParameterSet*)nxt_link())) {
1796 
1797  KVDetector* det = GetDetector(dbps->GetName());
1798  if (!det) {
1799  Warning("SetCalibratorParameters", "Got parameters for unknown detector: %s", dbps->GetName());
1800  continue;
1801  }
1802 
1803  KVNameValueList class_options;
1804  KVString clop;
1805  if (dbps->HasParameter("CalibOptions")) clop = dbps->GetStringParameter("CalibOptions");
1806  if (clop != "") {
1807  clop.Begin(",");
1808  while (!clop.End()) {
1809  KVString clopp = clop.Next(true);
1810  clopp.Begin("=");
1811  KVString par(clopp.Next(true)), val(clopp.Next(true));
1812  class_options.SetValue(par, val);
1813  }
1814  }
1815  KVCalibrator* cal = KVCalibrator::MakeCalibrator(dbps->GetStringParameter("CalibClass"));
1816  cal->SetType(dbps->GetTitle());
1817  if (clop != "") {
1818  try {
1819  cal->SetOptions(class_options);
1820  }
1821  catch (std::exception& e) {
1822  Error("SetCalibratorParameters",
1823  "Problem for %s [%s] : %s", det->GetName(), cal->GetType(), e.what());
1824  delete cal;
1825  continue;
1826  }
1827  }
1828  cal->SetInputSignalType(dbps->GetStringParameter("SignalIn"));
1829  cal->SetOutputSignalType(dbps->GetStringParameter("SignalOut"));
1830  if (!det->AddCalibrator(cal, dbps->GetParameters())) {
1831  // Calibrator invalid - probably input signal is not defined for detector
1832  // N.B. 'cal' deleted by KVDetector::AddCalibrator
1833  continue;
1834  }
1835 
1836  if (dbps->GetParamNumber() > cal->GetNumberParams()) {
1837  Warning("SetCalibratorParameters", "Wrong number of parameters (%d) for calibrator %s for detector %s : should be %d",
1838  dbps->GetParamNumber(), dbps->GetTitle(), dbps->GetName(), cal->GetNumberParams());
1839  dbps->Print();
1840  continue;
1841  }
1842  for (int i = 0; i < dbps->GetParamNumber(); ++i) {
1843  if (i >= cal->GetNumberParams())
1844  cal->SetParameter(i, 0);
1845  else
1846  cal->SetParameter(i, dbps->GetParameter(i));
1847  }
1848  cal->SetStatus(true);
1849  }
1850 }
1851 
1852 
1853 
1865 
1866 void KVMultiDetArray::GetDetectorEvent(KVDetectorEvent* detev, const TSeqCollection* fired_params)
1867 {
1868  // First step in event reconstruction based on current status of detectors in array.
1869  // Fills the given KVDetectorEvent with the list of all groups which have fired.
1870  // i.e. loop over all groups of the array and test whether KVGroup::Fired() returns true or false.
1871  //
1872  // If the list of fired acquisition parameters 'fired_params' is given, then we use this list
1873  // to find, first, the associated fired detectors, then, the associated groups. If not given,
1874  // or if it is empty, we may use the internal fFiredACQParams list.
1875  //
1876  // Call method detev->Clear() before reading another event in order to reset all of the hit groups
1877  // (including all detectors etc.) and emptying the list.
1878 
1879  if (!fired_params || !fired_params->GetEntries()) {
1880  if (fFiredACQParams.GetEntries()) fired_params = &fFiredACQParams;
1881  }
1882  if (fired_params && fired_params->GetEntries()) {
1883  // list of fired acquisition parameters given
1884  TIter next_par(fired_params);
1885  KVACQParam* par = 0;
1886  KVDetector* det = 0;
1887  KVGroup* grp = 0;
1888  while ((par = (KVACQParam*)next_par())) {
1889  if ((det = par->GetDetector())) {
1890  if ((grp = det->GetGroup()) && grp->GetParents()->Contains(this)) detev->AddGroup(grp);
1891  }
1892  }
1893  }
1894  else {
1895  //loop over groups
1896  unique_ptr<KVSeqCollection> fGroups(GetStructures()->GetSubListWithType("GROUP"));
1897 
1898  TIter next_grp(fGroups.get());
1899  KVGroup* grp;
1900  while ((grp = (KVGroup*) next_grp())) {
1901  if (grp->Fired()) {
1902  //if (!fHitGroups->FindObject(grp))
1903  // grp->Print();
1904  //add new group to list of hit groups
1905  detev->AddGroup(grp);
1906  }
1907  }
1908  }
1909 }
1910 
1911 
1912 
1924 
1925 void KVMultiDetArray::ReconstructEvent(KVReconstructedEvent* recev, KVDetectorEvent* kvde)
1926 {
1927  // Use the KVDetectorEvent (list of hit groups) in order to fill the
1928  // KVReconstructedEvent with reconstructed nuclei
1929  //
1930  // Reconstruction of detected particles
1931  //
1932  // - loop over last stage of group telescopes
1933  // - if any detector is hit, construct "particle" from energy losses in all detectors
1934  // directly in front of it.
1935  // - loop over next to last stage...if any detector hit NOT ALREADY IN A "PARTICLE"
1936  // construct "particle" etc. etc.
1937 
1938  KVGroup* grp_tch;
1939  TIter nxt_grp(kvde->GetGroups());
1940  while ((grp_tch = (KVGroup*) nxt_grp())) {
1941  AnalyseGroupAndReconstructEvent(recev, grp_tch);
1942  }
1943 }
1944 
1945 
1946 
1947 
1951 
1953 {
1954  // Loop over detectors in group, starting from the furthest from the target,
1955  // and working inwards. Calls KVReconstructedEvent::AnalyseDetectors
1956 
1957  for (Int_t il = grp->GetNumberOfDetectorLayers(); il > 0; il--) {
1958  unique_ptr<TList> dets(grp->GetDetectorsInLayer(il));
1959  recev->AnalyseDetectors(dets.get());
1960  }
1961  //perform first-order coherency analysis (set fAnalStatus for each particle)
1963 }
1964 
1965 
1966 
1967 
1968 
1973 
1974 void KVMultiDetArray::SetTarget(const Char_t* material,
1975  const Float_t thickness)
1976 {
1977  //Define the target used for a given experimental set-up. For material names, see KVMaterial.
1978  //The thickness is in mg/cm2.
1979  //Use SetTarget(0) to remove the existing target.
1980 
1981  if (!material) {
1982  if (fTarget) {
1983  delete fTarget;
1984  fTarget = 0;
1985  }
1986  return;
1987  }
1988  if (!GetTarget())
1989  fTarget = new KVTarget(material, thickness);
1990 
1991 }
1992 
1993 
1994 
2001 
2003 {
2004  //Adopt KVTarget object for use as experimental target i.e. we make a clone of the object pointed to by 'targ'.
2005  //Therefore, any subsequent modifications to the target should be made to the object whose pointer is returned by GetTarget().
2006  //This object will be deleted with the detector array, or when the target is changed.
2007  //
2008  //Calling SetTarget(0) will remove any existing target.
2009 
2010  if (fTarget) {
2011  delete fTarget;
2012  fTarget = 0;
2013  }
2014  if (!targ)
2015  return;
2016  fTarget = (KVTarget*) targ->Clone();
2017 }
2018 
2019 
2020 
2024 
2026 {
2027  //Define the target material used for a given experimental set-up.
2028  //For material names, see KVDetector.
2029 
2030  if (!GetTarget())
2031  fTarget = new KVTarget(material, 0.0);
2032 }
2033 
2034 
2035 
2039 
2041 {
2042  //Define the target thickness (mg/cm2) used for a given experimental set-up.
2043  //Need to define material first
2044  if (GetTarget()) {
2045  if (GetTarget()->GetLayerByIndex(1))
2046  GetTarget()->GetLayerByIndex(1)->SetThickness(thickness);
2047  }
2048 }
2049 
2050 
2051 
2057 
2059 {
2060  //Remove (i.e. destroy) all the telescopes belonging to a given group
2061 // if (grp) {
2062 // grp->Destroy();
2063 // }
2064  Warning("RemoveGroup", "Needs reimplementing");
2065 }
2066 
2067 
2068 
2072 
2074 {
2075  //Remove (i.e. destroy) all the telescopes belonging to the group in array
2076  //which contains detector or telescope with name "name"
2077  KVGroup* grp = GetGroupWithDetector(name);
2078  if (grp) {
2079  RemoveGroup(grp);
2080  }
2081 }
2082 
2083 
2084 
2085 
2090 
2092  KVNucleus* kvp)
2093 {
2094  //Given the name of a detector, simulate detection of a given particle
2095  //by the complete corresponding group. The particle's theta and phi are set
2096  //at random within the limits of detector entrance window
2097 
2098  KVDetector* kvd = GetDetector(detname);
2099  if (kvd) {
2100  KVNameValueList* nvl = 0;
2101  kvp->SetMomentum(kvp->GetEnergy(), kvd->GetRandomDirection("random"));
2102  if ((nvl = DetectParticle(kvp))) delete nvl;
2103  }
2104  else {
2105  Error("DetectParticleIn", "Detector %s not found", detname);
2106  }
2107 }
2108 
2109 
2110 
2124 
2126 {
2127  //Static function which will create and 'Build' the multidetector object corresponding to
2128  //a given run of dataset 'dataset_name'. Any previously existing multidetector will be
2129  //deleted.
2130  //We first activate the given dataset if not already done
2131  //
2132  //Multidetector arrays are defined as 'Plugin' objects in the file $KVROOT/KVFiles/.kvrootrc :
2133  //
2134  //Plugin.KVMultiDet: [dataset_name] [classname] [library] "[constructor]()"
2135  //
2136  //The constructors/macros are always without arguments
2137  //
2138  //Dataset name is stored in fDataSet
2139 
2140  if (gDataSetManager && (!gDataSet || (gDataSet != gDataSetManager->GetDataSet(dataset_name)))) {
2141  printf("Info in <KVMultiDetArray::MakeMultiDetector>: Changing dataset\n");
2142  gDataSetManager->GetDataSet(dataset_name)->cd();
2143  }
2144 
2145  if (gMultiDetArray && gMultiDetArray->GetDataSet() != dataset_name) {
2146  printf("Info in <KVMultiDetArray::MakeMultiDetector>: Deleting existing array %s\n", gMultiDetArray->GetName());
2147  if (gIDGridManager) {
2148  delete gIDGridManager;
2149  gIDGridManager = nullptr;
2150  }
2151  delete gMultiDetArray;
2152  gMultiDetArray = nullptr;
2153  }
2154 
2155 
2156  // Creation of database when dataset is selected for first time may
2157  // include creation of multidetector array (by calling this method)
2158  KVMultiDetArray* mda = nullptr;
2159  if (!gMultiDetArray) {
2160  TPluginHandler* ph;
2161  if (!(ph = LoadPlugin(classname.Data(), dataset_name)))
2162  return nullptr;
2163 
2164  //execute constructor/macro for multidetector - assumed without arguments
2165  mda = (KVMultiDetArray*) ph->ExecPlugin(0);
2166  mda->fDataSet = dataset_name;
2167  mda->Build(run);
2168  // if ROOT geometry is not allowed ([dataset_name].KVMultiDetArray.ROOTGeometry = no
2169  // or KVMultiDetArray.ROOTGeometry = no), disable it
2170  mda->fROOTGeometry = GetDataSetEnv(dataset_name, "KVMultiDetArray.ROOTGeometry", kTRUE);
2171  if (mda->fROOTGeometry) mda->CheckROOTGeometry();
2172  // set dataset-dependent lists of acceptable ID/E codes for reconstructed nuclei
2173  KVString codes = GetDataSetEnv(dataset_name, Form("%s.ReconstructedNuclei.AcceptIDCodes", mda->GetName()), "");
2174  if (codes != "") mda->fAcceptIDCodes.Set(codes);
2175  codes = GetDataSetEnv(dataset_name, Form("%s.ReconstructedNuclei.AcceptECodes", mda->GetName()), "");
2176  if (codes != "") mda->fAcceptECodes.Set(codes);
2177  // set dataset-dependent condition for seeding reconstructed nuclei
2178  mda->SetPartSeedCond(GetDataSetEnv(dataset_name, Form("%s.ReconstructedNuclei.ParticleSeedCond", mda->GetName()), ""));
2179  }
2180  else {
2181  mda = gMultiDetArray;
2182  }
2183  // set parameters if required & allowed & not done yet
2184  if (fMakeMultiDetectorSetParameters && (run > -1)) mda->SetParameters(run);
2185  return mda;
2186 }
2187 
2188 
2189 
2201 
2203 {
2204  // Return pointer to KVUpDater defined by dataset for this multidetector, the class used
2205  // is defined as a plugin like this:
2206  //
2207  // # Plugin.KVUpDater: name_of_dataset name_of_class name_of_plugin_library constructor_to_call
2208  //
2209  // However, if a dataset defines a variable like this:
2210  //
2211  // [dataset].ExpSetUp.Updater.[multidetector name]: [name_of_dataset for plugin]
2212  //
2213  // then we use the updater plugin defined for the given dataset
2214 
2215  if (!fUpDater) {
2216  KVString alt_updater = KVBase::GetDataSetEnv(fDataSet, Form("ExpSetUp.Updater.%s", GetName()), "");
2217  if (alt_updater != "") fUpDater = KVUpDater::MakeUpDater(alt_updater, this);
2219  }
2220  Info("GetUpDater", "updater class for dataset %s: %s", fDataSet.Data(), fUpDater->IsA()->GetName());
2221  return fUpDater;
2222 }
2223 
2224 
2225 
2226 
2235 
2236 void KVMultiDetArray::SetParameters(UInt_t run, Bool_t physics_parameters_only)
2237 {
2238  // Set run-dependent parameters of the array.
2239  //
2240  // if physics_parameters_only==false, identification and calibration parameters are set.
2241  // if physics_parameters_only==true, just the minimum necessary for physics analysis of reduced data are set.
2242  //
2243  // This can only be done if gDataSet has been set i.e. a dataset has been chosen,
2244  // otherwise this just has the effect of setting the current run number
2245 
2246  fCurrentRun = run;
2247  KVDataSet* ds = gDataSet;
2248  if (!ds) {
2249  if (gDataSetManager)
2251  }
2252  if (ds) {
2253  GetUpDater()->SetParameters(run, physics_parameters_only);
2254  SetBit(kParamsSet);
2255  }
2256 }
2257 
2258 
2259 
2260 
2265 
2267 {
2268  //Set identification parameters for run.
2269  //This can only be done if gDataSet has been set i.e. a dataset has been chosen
2270  //Otherwise this just has the effect of setting the current run number
2271 
2272  fCurrentRun = run;
2273  KVDataSet* ds = gDataSet;
2274  if (!ds) {
2275  if (gDataSetManager)
2277  }
2278  if (ds) {
2281  }
2282 }
2283 
2284 
2285 
2286 
2291 
2293 {
2294  //Set calibration parameters for run.
2295  //This can only be done if gDataSet has been set i.e. a dataset has been chosen
2296  //Otherwise this just has the effect of setting the current run number
2297 
2298  fCurrentRun = run;
2299  KVDataSet* ds = gDataSet;
2300  if (!ds) {
2301  if (gDataSetManager)
2303  }
2304  if (ds) {
2307  }
2308 }
2309 
2310 
2311 
2312 
2329 
2331 {
2332  //Initialisation of all ACTIVE identification telescopes in the array, i.e. those appearing in a line
2333  //in the .kvrootrc file such as this:
2334  //
2335  //# [dataset name].ActiveIdentifications: [type1] [type2] ...
2336  //
2337  //The 'types' given correspond to the value given by KVIDTelescope::GetLabel(), these are the
2338  //identifiers used to retrieve the different plugin classes in GetIDTelescopes(KVDetector*,KVDetector*,KVList*).
2339  //
2340  //For each type of identification in the list, we retrieve the first identification telescope with this
2341  //label from the list of all ID telescopes, in order to call its KVIDTelescope::SetIdentificationParameters() method.
2342  //This method (when rederived in child classes of KVIDTelescope) initialises the identification objects
2343  //for ALL of the ID telescopes of the same type (class) in the array.
2344  //
2345  //Note that, in general, the parameters of the identifications for a given run are not
2346  //set until SetParameters or SetRunIdentificationParameters is called.
2347 
2348  KVString id_labels = GetDataSetEnv(fDataSet, "ActiveIdentifications", "");
2349  if (id_labels == "" || (gDataSet && !gDataSet->HasCalibIdentInfos())) {
2350  Info("SetIdentifications", "No active identifications");
2351  return;
2352  }
2353  //split list of labels
2354  id_labels.Begin(" ");
2355  int ok(0);
2356  //loop over labels/identification 'types'
2357  while (!id_labels.End()) {
2358 
2359  //get first telescope in list with right label
2361  //set ID parameters for all telescopes of this 'type'
2362  if (idt) {
2363  Info("SetIdentifications", "Initialising %s identifications...", idt->GetLabel());
2364  if (idt->SetIdentificationParameters(this))
2365  Info("SetIdentifications", "OK");
2366  ++ok;
2367  }
2368 
2369  }
2370  if (!ok) {
2371  // None of the labels in the list correspond to telescopes in the array
2372  Warning("SetIdentfications", "No telescopes found with labels given in %s.ActiveIdentifications list: %s",
2373  gDataSet->GetName(), id_labels.Data());
2374  }
2375 }
2376 
2377 
2378 
2379 
2386 
2388 {
2389  // Calls Initialize() method of each identification telescope (see KVIDTelescope
2390  // and derived classes) and sets the general identification code defined for each
2391  // telescope.
2392  //
2393  // Calling this method is essential before identification of particles is attempted.
2394 
2395  TIter next(fIDTelescopes);
2396  KVIDTelescope* idt;
2397  while ((idt = (KVIDTelescope*)next())) {
2398  idt->Initialize();
2400  }
2401 }
2402 
2403 
2404 
2415 
2417 {
2418  // Read all identification grids from the file and add them to the IDGridManager object
2419  // used by this array. This method sets up the links between each grid and the
2420  // IDtelescope(s) it is to be used for, unlike calling
2421  //
2422  // gIDGridManager->ReadAsciiFile(grids)
2423  //
2424  // which does not.
2425  //
2426  // Returns kFALSE if there is a problem reading the file
2427 
2428  if (gIDGridManager->ReadAsciiFile(grids)) {
2430  KVIDGraph* gr;
2431  while ((gr = (KVIDGraph*)next())) FillListOfIDTelescopes(gr);
2432  return kTRUE;
2433  }
2434  return kFALSE;
2435 }
2436 
2437 
2438 
2439 
2443 
2445 {
2446  // Print full status report on ID telescopes in array, using informations stored in
2447  // fStatusIDTelescopes (see GetStatusOfIDTelescopes).
2448 
2449  cout << endl << "-----STATUS OF IDENTIFICATION TELESCOPES";
2450  if (GetCurrentRunNumber()) cout << " FOR RUN "
2451  << GetCurrentRunNumber();
2452  cout << "------" << endl << endl;
2453  //get list of active telescopes
2454  KVString id_labels;
2455  if (gDataSet) id_labels = gDataSet->GetDataSetEnv("ActiveIdentifications");
2456  else {
2457  unique_ptr<KVUniqueNameList> typelist(GetIDTelescopeTypes());
2458  TIter it(typelist.get());
2459  TObjString* type;
2460  while ((type = (TObjString*)it())) {
2461  if (id_labels == "") id_labels += type->GetString().Data();
2462  else {
2463  id_labels += Form(" %s", type->GetString().Data());
2464  }
2465  }
2466  }
2467  if (id_labels == "") {
2468  cout << " *** No active identifications *** " << endl;
2469  return;
2470  }
2471  // iterate over labels
2472  unique_ptr<TObjArray> toks(id_labels.Tokenize(' '));
2473 
2474  //update status infos
2476 
2477  TIter next_type(fStatusIDTelescopes);
2478  TList* id_type_list = 0;
2479  while ((id_type_list = (TList*)next_type())) {
2480 
2481  cout << " *** " << id_type_list->GetName() << " Identifications -------------------" << endl;
2482  if (!toks->FindObject(id_type_list->GetName())) {
2483  cout << " [NOT ACTIVE]" << endl;
2484  }
2485  TList* ok_list = (TList*)id_type_list->FindObject("OK");
2486  TList* notok_list = (TList*)id_type_list->FindObject("NOT OK");
2487  TList* print_list = 0;
2488  Int_t Nok = ok_list->GetEntries();
2489  Int_t Notok = notok_list->GetEntries();
2490  if (Nok && Notok) {
2491  if (Nok < Notok) print_list = ok_list;
2492  else print_list = notok_list;
2493  }
2494  if (Nok && (!Notok)) cout << " ALL telescopes are OK" << endl;
2495  else if (Notok && (!Nok)) cout << " NO telescopes are OK" << endl;
2496  else {
2497  cout << " " << ok_list->GetEntries() << " telescopes are OK, "
2498  << notok_list->GetEntries() << " telescopes are NOT OK" << endl;
2499  cout << " " << print_list->GetName() << " :" << endl;
2500  TIter it(print_list);
2501  TObject* ob = it();
2502  cout << ob->GetName();
2503  while ((ob = it())) cout << "," << ob->GetName();
2504  cout << endl;
2505  }
2506  cout << endl;
2507 
2508  }
2509 }
2510 
2511 
2512 
2513 
2521 
2523 {
2524  // Fill and return pointer to list fStatusIDTelescopes which contains
2525  // a list for each type of ID telescope in the array, each list contains a list
2526  // "OK" with the ID telescopes which have IsReadyForID()=kTRUE, and
2527  // a list "NOT OK" with the others.
2528  //
2529  // The returned TList object must not be deleted (it belongs to the KVMultiDetArray).
2530 
2531  if (!fStatusIDTelescopes) {
2532  fStatusIDTelescopes = new TList;
2534  }
2535  else {
2537  }
2539  TIter next(fIDTelescopes);
2540  KVIDTelescope* idt = 0;
2541  while ((idt = (KVIDTelescope*)next())) {
2542 
2543  TString id_type = idt->GetLabel();
2544  TList* id_type_list = (TList*)fStatusIDTelescopes->FindObject(id_type.Data());
2545  if (!id_type_list) {
2546  id_type_list = new TList;
2547  id_type_list->SetOwner(kTRUE);
2548  id_type_list->SetName(id_type.Data());
2549  fStatusIDTelescopes->Add(id_type_list);
2550  id_type_list->Add(new TList);
2551  ((TList*)id_type_list->At(0))->SetName("OK");
2552  id_type_list->Add(new TList);
2553  ((TList*)id_type_list->At(1))->SetName("NOT OK");
2554  }
2555  if (idt->IsReadyForID())
2556  ((TList*)id_type_list->FindObject("OK"))->Add(idt);
2557  else
2558  ((TList*)id_type_list->FindObject("NOT OK"))->Add(idt);
2559  }
2560  return fStatusIDTelescopes;
2561 }
2562 
2563 
2564 
2565 
2571 
2573 {
2574  // Create, fill and return pointer to a list of TObjString containing the name of each type
2575  // of ID telescope (actually the label) in the array.
2576  //
2577  // Delete the list after use (it owns the TObjString objects)
2578 
2579  KVUniqueNameList* type_list = new KVUniqueNameList(kTRUE);
2580  type_list->SetOwner();
2581  if (!fIDTelescopes || !fIDTelescopes->GetEntries()) return type_list;
2582  TIter next(fIDTelescopes);
2583  KVIDTelescope* idt = 0;
2584  while ((idt = (KVIDTelescope*)next())) {
2585  type_list->Add(new TObjString(idt->GetLabel()));
2586  }
2587  return type_list;
2588 }
2589 
2590 
2591 
2592 
2600 
2602 {
2603  // Create, fill and return pointer to a list of KVIDTelescopes with
2604  // the given type (label) in the array.
2605  // WARNING! - check pointer is not zero (we return NULL if ID telescopes
2606  // list is not defined or empty)
2607  //
2608  // Delete the KVList after use (it does not own the KVIDTelescopes).
2609 
2610  if (!fIDTelescopes || !fIDTelescopes->GetEntries()) return NULL;
2612 }
2613 
2614 
2615 
2616 
2624 
2626 {
2627  // Fill and return pointer to list fCalibStatusDets which contains
2628  // a list for each type of detector in the array, each list contains a list
2629  // "OK" with the detectors which are calibrated, and
2630  // a list "NOT OK" with the others.
2631  //
2632  // The returned TList object must not be deleted (it belongs to the KVMultiDetArray).
2633 
2634  if (!fCalibStatusDets) {
2635  fCalibStatusDets = new TList;
2637  }
2638  else {
2640  }
2641  if (!GetDetectors()->GetEntries()) return fCalibStatusDets;
2642  TIter next(GetDetectors());
2643  KVDetector* det = 0;
2644  while ((det = (KVDetector*)next())) {
2645 
2646  TString type = det->GetType();
2647  TList* type_list = (TList*)fCalibStatusDets->FindObject(type.Data());
2648  if (!type_list) {
2649  type_list = new TList;
2650  type_list->SetOwner(kTRUE);
2651  type_list->SetName(type.Data());
2652  fCalibStatusDets->Add(type_list);
2653  type_list->Add(new TList);
2654  ((TList*)type_list->At(0))->SetName("OK");
2655  type_list->Add(new TList);
2656  ((TList*)type_list->At(1))->SetName("NOT OK");
2657  }
2658  if (det->IsCalibrated())
2659  ((TList*)type_list->FindObject("OK"))->Add(det);
2660  else
2661  ((TList*)type_list->FindObject("NOT OK"))->Add(det);
2662  }
2663  return fCalibStatusDets;
2664 }
2665 
2666 
2667 
2668 
2672 
2674 {
2675  // Print full status report on calibration of detectors in array, using informations stored in
2676  // fCalibStatusDets (see GetCalibrationStatusOfDetectors).
2677 
2678  if (!GetCurrentRunNumber()) {
2679  Info("PrintCalibStatusOfDetectors", "Cannot know status without knowing RUN NUMBER");
2680  return;
2681  }
2682 
2683  cout << endl << "-----------STATUS OF CALIBRATIONS FOR RUN "
2684  << GetCurrentRunNumber() << "------------" << endl << endl;
2685 
2686  //update status infos
2688 
2689  TIter next_type(fCalibStatusDets);
2690  TList* id_type_list = 0;
2691  while ((id_type_list = (TList*)next_type())) {
2692 
2693  cout << " *** " << id_type_list->GetName() << " Detectors -------------------" << endl;
2694  TList* ok_list = (TList*)id_type_list->FindObject("OK");
2695  TList* notok_list = (TList*)id_type_list->FindObject("NOT OK");
2696  TList* print_list = 0;
2697  Int_t Nok = ok_list->GetEntries();
2698  Int_t Notok = notok_list->GetEntries();
2699  if (Nok && Notok) {
2700  if (Nok < Notok) print_list = ok_list;
2701  else print_list = notok_list;
2702  }
2703  if (Nok && (!Notok)) cout << " ALL calibrations are OK" << endl;
2704  else if (Notok && (!Nok)) cout << " NO calibrations are OK" << endl;
2705  else {
2706  cout << " " << ok_list->GetEntries() << " calibrations are OK, "
2707  << notok_list->GetEntries() << " calibrations are NOT OK" << endl;
2708  cout << " " << print_list->GetName() << " :" << endl;
2709  TIter it(print_list);
2710  TObject* ob = it();
2711  cout << ob->GetName();
2712  while ((ob = it())) cout << "," << ob->GetName();
2713  cout << endl;
2714  }
2715  cout << endl;
2716 
2717  }
2718 }
2719 
2720 
2721 
2722 
2738 
2740 {
2741  // Calculate the energy loss in the current target of the multidetector
2742  // for the reconstructed charged particle 'ion', assuming that the current
2743  // energy and momentum of this particle correspond to its state on
2744  // leaving the target.
2745  //
2746  // WARNING: for this correction to work, the target must be in the right 'state':
2747  //
2748  // gMultiDetArray->GetTarget()->SetIncoming(kFALSE);
2749  // gMultiDetArray->GetTarget()->SetOutgoing(kTRUE);
2750  //
2751  // (see KVTarget::GetParticleEIncFromERes).
2752  //
2753  // The returned value is the energy lost in the target in MeV.
2754  // The energy/momentum of 'ion' are not affected.
2755 
2756  if (fTarget && ion) return (fTarget->GetParticleEIncFromERes(ion) - ion->GetEnergy());
2757  return 0;
2758 }
2759 
2760 
2761 
2762 
2765 
2767 {
2768  // Return pointer to the (ROOT) geometry of the array.
2769  return gGeoManager;
2770 }
2771 
2772 
2773 
2775 
2777 {
2778  return fNavigator;
2779 }
2780 
2781 
2782 
2807 
2809 {
2810  // Look for a file in the dataset directory with the name given by .kvrootrc variable:
2811  //
2812  // KVMultiDetArray.DetectorThicknesses:
2813  // or
2814  // dataset.KVMultiDetArray.DetectorThicknesses:
2815  //
2816  // and, if it exists, we use it to set the real thicknesses of the detectors.
2817  // Any detector which is not in the file will be left with its nominal thickness.
2818  //
2819  // EXAMPLE FILE:
2820  //
2821  //# thickness of detector DET01 in default units
2822  //DET01: 56.4627
2823  //
2824  //# DET03 has several layers
2825  //DET03.Abs0: 61.34
2826  //DET03.Abs1: 205.62
2827  //
2828  // !!! WARNING !!!
2829  // Single-layer detectors: The units are those defined by default for the detector's
2830  // Get/SetThickness methods.
2831  // Multi-layer: Each layer is a KVMaterial object. The thickness MUST be given in centimetres
2832  // (default thickness unit for KVMaterial).
2833 
2834  TString filename = GetDataSetEnv(fDataSet, "KVMultiDetArray.DetectorThicknesses", "");
2835  if (filename == "") {
2836  Error("SetDetectorThicknesses", "*.KVMultiDetArray.DetectorThicknesses not defined in .kvrootrc");
2837  return;
2838  }
2839  TString fullpath;
2840  if (gDataSet) fullpath = gDataSet->GetFullPathToDataSetFile(filename);
2841  if (fullpath == "") {
2842  Info("SetDetectorThicknesses", "File %s not found", filename.Data());
2843  return;
2844  }
2845  TEnv thickdat;
2846  if (thickdat.ReadFile(fullpath, kEnvUser) != 0) {
2847  Error("SetDetectorThicknesses", "Problem opening file %s", fullpath.Data());
2848  return;
2849  }
2850  Info("SetDetectorThicknesses", "Setting thicknesses of detectors from file %s", filename.Data());
2851  TIter next(GetDetectors());
2852  KVDetector* det;
2853  while ((det = (KVDetector*)next())) {
2854  if (thickdat.Defined(det->GetName())) {
2855  // simple single layer detector
2856  Double_t thick = thickdat.GetValue(det->GetName(), 0.0);
2857  det->SetThickness(thick);
2858  //Info("SetDetectorThicknesses", "Set thickness of %s to %f", det->GetName(), thick);
2859  }
2860  else {
2861  Char_t i = 0;
2862  TString absname;
2863  absname.Form("%s.Abs%d", det->GetName(), (Int_t)i);
2864  if (thickdat.Defined(absname.Data())) {
2865  // detector with several layers
2866  KVMaterial* abs = 0;
2867  while ((abs = det->GetAbsorber(i))) {
2868  Double_t thick = thickdat.GetValue(absname.Data(), 0.0);
2869  abs->SetThickness(thick);
2870  //Info("SetDetectorThicknesses", "Set thickness of %s.Abs%d to %f", det->GetName(), (Int_t)i, thick);
2871  i++;
2872  absname.Form("%s.Abs%d", det->GetName(), (Int_t)i);
2873  if (!thickdat.Defined(absname.Data())) break;
2874  }
2875  }
2876  }
2877  }
2878 }
2879 
2880 
2881 
2887 
2889 {
2890  // Define the geometry of the array with a valid ROOT geometry (TGeoManager instance)
2891  // If no name and/or title are defined for the array, the name and title of the TGeoManager
2892  // object will be used for the array.
2893  // ROOT geometry will be used by default from now on.
2894 
2895  if (!strcmp(GetName(), "")) SetName(g->GetName());
2896  if (!strcmp(GetTitle(), "")) SetTitle(g->GetTitle());
2897  SetROOTGeometry();
2898 }
2899 
2900 
2901 
2905 
2907 {
2908  // Calculate incident energy of particle (Z,A) required to punch through given detector,
2909  // taking into account any detectors which the particle must first cross in order to reach it.
2910 
2911  KVDetector* theDet = GetDetector(detector);
2912  if (!theDet) {
2913  Error("GetPunchThroughEnergy", "Detector %s not found in array", detector);
2914  return -1.0;
2915  }
2916  Double_t E0 = theDet->GetPunchThroughEnergy(Z, A);
2917  TIter alDets(theDet->GetAlignedDetectors());
2918  // first detector in list is theDet
2919  alDets.Next();
2920  KVDetector* D;
2921  while ((D = (KVDetector*)alDets.Next())) {
2922  Double_t E1 = D->GetIncidentEnergyFromERes(Z, A, E0);
2923  E0 = E1;
2924  }
2925  return E0;
2926 }
2927 
2928 
2929 
2934 
2936 {
2937  // Creates and fills a TGraph with the punch through energy in MeV vs. Z for the given detector,
2938  // for Z=1-92. The mass of each nucleus is calculated according to the given mass formula
2939  // (see KVNucleus).
2940 
2941  TGraph* punch = new TGraph(92);
2942  punch->SetName(Form("KVMultiDetpunchthrough_%s_mass%d", detector, massform));
2943  punch->SetTitle(Form("Array Punch-through %s (MeV) (mass formula %d)", detector, massform));
2944  KVNucleus nuc;
2945  nuc.SetMassFormula(massform);
2946  for (int Z = 1; Z <= 92; Z++) {
2947  nuc.SetZ(Z);
2948  punch->SetPoint(Z - 1, Z, GetPunchThroughEnergy(detector, nuc.GetZ(), nuc.GetA()));
2949  }
2950  return punch;
2951 }
2952 
2953 
2954 
2959 
2961 {
2962  // Creates and fills a TGraph with the punch through energy in MeV/nucleon vs. Z for the given detector,
2963  // for Z=1-92. The mass of each nucleus is calculated according to the given mass formula
2964  // (see KVNucleus).
2965 
2966  TGraph* punch = new TGraph(92);
2967  punch->SetName(Form("KVMultiDetpunchthroughEsurA_%s_mass%d", detector, massform));
2968  punch->SetTitle(Form("Array Punch-through %s (AMeV) (mass formula %d)", detector, massform));
2969  KVNucleus nuc;
2970  nuc.SetMassFormula(massform);
2971  for (int Z = 1; Z <= 92; Z++) {
2972  nuc.SetZ(Z);
2973  punch->SetPoint(Z - 1, Z, GetPunchThroughEnergy(detector, nuc.GetZ(), nuc.GetA()) / nuc.GetA());
2974  }
2975  return punch;
2976 }
2977 
2978 
2979 
2985 
2987 {
2988  // Creates and fills a TGraph with the Z vs. the punch-through velocity paralllel to the beam
2989  // direction in cm/ns for the given detector,
2990  // for Z=1-92. The mass of each nucleus is calculated according to the given mass formula
2991  // (see KVNucleus).
2992 
2993  TGraph* punch = new TGraph(92);
2994  punch->SetName(Form("KVMultiDetpunchthroughV_%s_mass%d", detector, massform));
2995  punch->SetTitle(Form("Array Punch-through %s (cm/ns) (mass formula %d)", detector, massform));
2996  KVNucleus nuc;
2997  nuc.SetMassFormula(massform);
2998  for (int Z = 1; Z <= 92; Z++) {
2999  nuc.SetZ(Z);
3000  nuc.SetE(GetPunchThroughEnergy(detector, nuc.GetZ(), nuc.GetA()));
3001  nuc.SetTheta(GetDetector(detector)->GetTheta());
3002  punch->SetPoint(Z - 1, nuc.GetVpar(), Z);
3003  }
3004  return punch;
3005 }
3006 
3007 
3008 
3012 
3014 {
3015  // Call with on=kTRUE if array uses ROOT geometry for tracking
3016  // Call SetGeometry(TGeoManager*) first with a valid geometry.
3017 
3018  fROOTGeometry = on;
3019  if (on && !gGeoManager) {
3020  Error("SetROOTGeometry", "ROOT geometry is requested, but has not been set: gGeoManager=0x0,\n Call CreateGeoManager() method first");
3021  return;
3022  }
3023 
3024  // set up geometry navigator
3026  else if (!on) SafeDelete(fNavigator);
3027 }
3028 
3029 
3030 
3059 
3061 {
3062  // Method for positioning volumes in detector geometries
3063  //
3064  // Given:
3065  //
3066  // distance [cm] = distance from target (origin) to the CENTRE of the volume in position
3067  // theta [deg] = polar angle of vector from target to centre of volume in position
3068  // phi [deg] = azimuthal angle of vector
3069  //
3070  // this method generates the matrix which is required to position the volume as required
3071  // while also turning the volume so that the side nearest the target (i.e. the entrance
3072  // window of the detector) remains perpendicular to the vector joining the origin and
3073  // the centre of the volume.
3074  //
3075  // If required, a further translation can be given which will be applied to the volume after
3076  // it has been placed with the required orientation at the nominal distance. This can be used
3077  // e.g. for detector misalignment, when detectors are in a structure which guarantees their line
3078  // of sight to be orthogonal to their surface at a nominal distance, but the nominal distance
3079  // is not respected.
3080  //
3081  // Example of use:
3082  //
3083  //~~~~~~~~~~~~
3084  // TGeoVolume* vol;// volume to be positioned
3085  // double depth = vol->GetShape()->GetDZ(); // half-width of volume in direction of target
3086  // // place front of volume at 100cm, with theta=45 deg. and phi=60 deg.
3087  // gGeoManager->GetTopVolume()->AddNode(vol, 1, KVMultiDetArray::GetVolumePositioningMatrix(100+depth,45,60));
3088  //~~~~~~~~~~~~
3089 
3090  TGeoRotation rot1, rot2;
3091  TGeoTranslation trans;
3092  phi += 90;
3093  rot1.SetAngles(-phi, 0, 0) ;
3094  rot2.SetAngles(phi, theta, 0) ;
3095  trans.SetDz(distance) ;
3096  TGeoHMatrix h;
3097  if (postTrans) h = (*postTrans) * rot2 * trans * rot1 ;
3098  else h = rot2 * trans * rot1;
3099  TGeoHMatrix* ph = new TGeoHMatrix(h);
3100  return ph;
3101 }
3102 
3103 
3104 
3112 
3114 {
3115  // *** Set 'segmentation' index of detectors ***
3116  // This is essential for particle reconstruction, judging whether particles can be identified
3117  // independently of any others in the same group etc.
3118  // Basically, any detector with >1 detector placed directly behind it has a seg. index = 0
3119  // if <=1 detector is directly behind, the seg. index = 1
3120  // This method is used for arrays imported from ROOT geometries.
3121 
3122  TIter next(GetDetectors());
3123  KVDetector* d;
3124  while ((d = (KVDetector*)next())) {
3125  if (d->GetNode()->GetNDetsBehind() > 1) d->SetSegment(0);
3126  else d->SetSegment(1);
3127  }
3128 }
3129 
3130 
3131 
3132 
3139 
3141 {
3142  //Create and add to list all ID telescopes made of this detector
3143  //and the aligned detectors placed in front of it.
3144  //
3145  //If list=0 then we store pointers to the ALREADY EXISTING ID telescopes
3146  //in det->fIDTelAlign. (first clear det->fIDTelAlign)
3147 
3148  if (!(det->IsOK())) return;
3149 
3150  TList* aligned = det->GetAlignedDetectors();
3151 
3152  Bool_t list_zero = kFALSE;
3153 
3154  if (!list) {
3155  list_zero = kTRUE;
3156  //the IDTelescopes created will be destroyed at the end,
3157  //once we have used their names to find pointers to the corresponding
3158  //telescopes in gMultiDetArray
3159  list = new KVList;
3160  //clear any existing list of aligned telescopes
3161  det->GetAlignedIDTelescopes()->Clear();
3162  }
3163 
3164  if (aligned->GetSize() > 1) {
3165  //pairwise looping through list
3166  for (int i = 0; i < (aligned->GetSize() - 1); i++) {
3167  KVDetector* det1 = (KVDetector*) aligned->At(i + 1);
3168  KVDetector* det2 = (KVDetector*) aligned->At(i);
3169 
3170  GetIDTelescopes(det1, det2, list);
3171  }
3172  }
3173  else {
3174  //The following line is in case there are no detectors aligned
3175  //with 'det', but 'det' acts as an IDTelescope all by itself.
3176  //In this case we expect KVMultiDetArray::GetIDTelescopes
3177  //to define the appropriate ID telescope whenever one of the
3178  //two detector arguments (or both!) corresponds to 'det''s type.
3179  GetIDTelescopes(det, det, list);
3180  }
3181 
3182  if (list_zero) {
3183  //now we use the created ID telescopes to find pointers to the already
3184  //existing identical telescopes in gMultiDetArray, stock them in
3185  //det->fIDTelAlign
3186  TIter next_tel(list);
3187  KVIDTelescope* tel;
3188  while ((tel = (KVIDTelescope*) next_tel())) {
3189  KVIDTelescope* trash = GetIDTelescope(tel->GetName());
3190  if (trash) {
3191  det->GetAlignedIDTelescopes()->Add(trash);
3192  }
3193  }
3194  //destroy the superfluous copy telescopes we just created
3195  list->Delete();
3196  delete list;
3197  }
3198 
3199 }
3200 
3201 
3202 
3216 
3218 {
3219  //Identify all the ways of identifying particles possible from the detectors
3220  //in the group, create the appropriate KVIDTelescope objects and add them to
3221  //the list pointed to by tel_list.
3222  //USER'S RESPONSIBILITY TO DELETE CONTENTS OF LIST!!
3223  //
3224  //Starting from each detector in the group,
3225  //we build ID telescopes from all pairs of aligned detectors.
3226  //
3227  //For each pair of detectors, it is KVMultiDetArray::GetIDTelescopes
3228  //which determines which KVIDTelescope class to use (specialise this method
3229  //in KVMultiDetArray child classes). It must also make sure that
3230  //each IDTelescope is added only once (i.e. check it is not already in the list).
3231 
3232  TIter next_det(grp->GetDetectors());
3233  KVDetector* det;
3234 
3235  while ((det = (KVDetector*) next_det())) {
3236  if (det->IsOK()) {
3237  //1st call: create ID telescopes, they will be added to the
3238  //gMultiDetArray list of IDTelescopes
3239  GetAlignedIDTelescopesForDetector(det, tel_list);
3240  //2nd call: set up in the detector a list of pointers to the
3241  //ID telescopes made up of it and all aligned detectors in front
3242  //of it
3244  }
3245  }
3246 }
3247 
3248 
3249 
3259 
3261 {
3262  //Casse tous les liens entre les detecteurs d un meme groupe
3263  //Retire de la liste gMultiDetArray->GetListOfIDTelescopes() les
3264  //telescopes associes et les efface apres les avoir
3265  //retires des grilles auxquelles ils etaient associees
3266  //pour preparer l ajout ou le retrait d un detecteur
3267  //voir KVDetector::SetPresent()
3268  //
3269  //
3270  KVNameValueList nv;
3271 
3272  KVDetector* det = 0;
3273  KVIDTelescope* id = 0;
3274 
3275  const KVSeqCollection* lgrdet = grp->GetDetectors();
3276  TIter nextdet(lgrdet);
3277  while ((det = (KVDetector*)nextdet())) {
3278  //Info("PrepareModif","On retire les detecteurs alignes pour %s",det->GetName());
3281  Int_t ntel = det->GetIDTelescopes()->GetEntries();
3282  for (Int_t ii = 0; ii < ntel; ii += 1) {
3283  id = (KVIDTelescope*)det->GetIDTelescopes()->At(0);
3284  if (id->GetDetectors()->FindObject(dd)) {
3285  nv.SetValue(id->GetName(), "");
3286  det->GetIDTelescopes()->RemoveAt(0);
3287  }
3288  }
3289  }
3290 
3292  for (Int_t ii = 0; ii < nv.GetEntries(); ii += 1) {
3293  id = (KVIDTelescope*)lidtel->FindObject(nv.GetNameAt(ii));
3294  //Info("PrepareModif","On retire et on detruit l'ID tel %s",id->GetName());
3295 
3296  if (id->GetListOfIDGrids()) {
3297  KVIDGraph* idg = 0;
3298  for (Int_t kk = 0; kk < id->GetListOfIDGrids()->GetEntries(); kk += 1) {
3299  idg = (KVIDGraph*)id->GetListOfIDGrids()->At(kk);
3300  idg->RemoveIDTelescope(id);
3301  }
3302  }
3303 
3304  //Info("PrepareModif","Je retire et j efface le idtel %s %s",id->GetName(),id->ClassName());
3305  delete lidtel->Remove(id);
3306  }
3307  nv.Clear();
3308 
3309 }
3310 
3311 
3312 
3325 
3327 {
3328  //
3329  // If present=kTRUE (default), detector is present
3330  // If present=kFALSE, detector has been removed
3331  // This method does nothing is required state is already current state.
3332  //
3333  // Methode applicable seulement pour un detecteur
3334  // etant le seul dans un telescope
3335  // ex les ChIo pour Indra
3336  //
3337  // This method as always to be call before
3338  // call the SetDetecting() method
3339 
3340  if (present == det->IsPresent())
3341  return;
3342 
3343  det->SetPresent(present);
3344 
3345  //On passe l etat d un detecteur de present a absent
3346  //
3347  KVTelescope* fTelescope = (KVTelescope*)det->GetParentStructure("TELESCOPE");
3348  if (!det->IsPresent()) {
3349 
3350  //Le detecteur etait l unique d un KVTelescope
3351  //on retire directement le KVTelescope
3352  if (fTelescope->GetDetectors()->GetEntries() == 1) {
3353  KVGroup* gr = (KVGroup*)fTelescope->GetParentStructure("GROUP");
3354 
3355  PrepareModifGroup(gr, det);
3356 
3357  gr->Remove(fTelescope);
3358  gr->Remove(det);
3360 
3361  }
3362  else {
3363  Warning("SetPresent", "Method implemented only in case detector is alone in telescope");
3364  }
3365  }
3366  //On remet le detecteur dans le groupe auquel il appartenait
3367  else {
3368 
3369  if (!det->GetGroup()) {
3370  KVGroup* gr = GetGroupWithAngles(det->GetTheta(), det->GetPhi());
3371 
3372  PrepareModifGroup(gr, det);
3373 
3374  gr->Add(fTelescope);
3375  gr->Add(det);
3376  gr->Sort();
3377  gr->CountLayers();
3379 
3380  }
3381 
3382  }
3383 
3384 }
3385 
3386 
3387 
3396 
3398 {
3399 
3400  // This method has effect only if detector is present
3401  //
3402  // If detecting=kTRUE (default), detector is detecting
3403  // If detecting=kFALSE, detector has been switch off or no gas or just dead
3404  // Does nothing if:
3405  // - detector already marked as absent
3406  // - required state is already current state
3407 
3408  if (!det->IsPresent())
3409  return;
3410 
3411  if (detecting == det->IsDetecting())
3412  return;
3413 
3414  det->SetDetecting(detecting);
3415  if (!det->IsDetecting()) {
3416  KVGroup* gr = det->GetGroup();
3417  PrepareModifGroup(gr, det);
3419  }
3420  else {
3421  KVGroup* gr = GetGroupWithAngles(det->GetTheta(), det->GetPhi());
3422  PrepareModifGroup(gr, det);
3424  }
3425 
3426 }
3427 
3428 
3429 
3433 
3435 {
3436  // For each grid which is valid for this run, we call the KVIDTelescope::SetIDGrid method
3437  // of each associated ID telescope.
3438  TIter next(gIDGridManager->GetGrids());
3439  KVIDGraph* gr = 0;
3440  while ((gr = (KVIDGraph*) next())) {
3441  if (gr->GetRuns().Contains((Int_t) run)) {
3442 
3443  TIter nxtid(gr->GetIDTelescopes());
3444  KVIDTelescope* idt;
3445  while ((idt = (KVIDTelescope*) nxtid())) {
3446  idt->SetIDGrid(gr);
3447  }
3448  }
3449  }
3450 }
3451 
3452 
3456 
3458 {
3459  // Fill list of ID telescopes with which this grid is associated
3460  // from list of names read from ascii file.
3461 
3462  gr->ClearListOfTelescopes();
3463  if (gr->GetParameters()->HasParameter("IDTelescopes")) {
3464  KVString tel_list = gr->GetParameters()->GetStringValue("IDTelescopes");
3465  tel_list.Begin(",");
3466  while (!tel_list.End()) {
3467  TString tel_name = tel_list.Next();
3468  KVIDTelescope* idt = GetIDTelescope(tel_name.Data()) ;
3469  if (idt) gr->AddIDTelescope(idt);
3470  }
3471  }
3472 }
3473 
3474 
3475 
3485 
3487 {
3488  // Use OpenGL viewer to view multidetector geometry (only for ROOT geometries)
3489  //
3490  // If option="tracks" we draw any tracks corresponding to the last simulated
3491  // event whose detection was simulated with DetectEvent
3492  // If option="tracks:[numberlist]" with a list of numbers,
3493  // it will be interpreted as a KVNumberList containing the Z of tracks to be drawn
3494  // e.g. option="tracks:1-92" draw only tracks with 1<=Z<=92 (no neutrons)
3495  // option="tracks:2" draw only helium isotopes
3496  if (IsROOTGeometry()) {
3497  GetGeometry()->GetTopVolume()->Draw("ogl");
3498  KVString opt(option);
3499  opt.Begin(":");
3500  if (opt.Next() == "tracks") {
3501  if (!opt.End()) {
3502  KVNumberList zlist(opt.Next());
3503  GetNavigator()->DrawTracks(&zlist);
3504  }
3505  else
3506  GetNavigator()->DrawTracks();
3507  }
3508 #ifdef WITH_OPENGL
3509  TGLViewer* view = (TGLViewer*)gPad->GetViewer3D();
3512  view->SetSmoothLines(kTRUE);
3513  view->SetSmoothPoints(kTRUE);
3514 #endif
3515  }
3516  else Error("Draw", "Only ROOT geometries can be viewed");
3517 
3518 }
3519 
3520 
3521 
3523 
3525 {
3527 }
3528 
3529 
3530 
3535 
3537 {
3538  // Create TH2F histograms for all IDTelescopes of the array
3539  // They will be added to the list
3540  // histograms will have resolution of dimension*dimension
3541 
3543  KVIDTelescope* idt;
3544  while ((idt = (KVIDTelescope*)it())) {
3545  TString name(idt->GetName());
3546  name.ReplaceAll("-", "_");
3547  list->Add(new TH2F(name, Form("Hits in %s", idt->GetName()), dimension, 0., 0., dimension, 0., 0.));
3548  }
3549 }
3550 
3551 
3552 
3555 
3557 {
3558  // Fill TH2F histograms for all IDTelescopes of the array
3559 
3561  KVIDTelescope* idt;
3562  while ((idt = (KVIDTelescope*)it())) {
3563  TString name(idt->GetName());
3564  name.ReplaceAll("-", "_");
3565  TH2F* h = (TH2F*)list->FindObject(name);
3566  if (h) h->Fill(idt->GetIDMapX(), idt->GetIDMapY());
3567  }
3568 }
3569 
3570 
3571 
3574 
3576 {
3577  // Modify the transparency of detector volumes in OpenGL view
3578 
3579  TIter itV(GetGeometry()->GetListOfVolumes());
3580  TGeoVolume* vol;
3581  while ((vol = (TGeoVolume*)itV())) vol->SetTransparency(t);
3582 }
3583 
3584 
3585 
3589 
3591 {
3592  // Calculate all possible (sub-)trajectories
3593  // for particle reconstruction (GetReconTrajectories())
3594 
3595  unique_ptr<KVSeqCollection> groups(GetStructureTypeList("GROUP"));
3596  TIter it(groups.get());
3597  KVGroup* group;
3598  Int_t ntr = 0;
3599  Info("CalculateReconstructionTrajectories", "Calculating trajectories for particle reconstruction:");
3601  std::cout << "\xd" << " -- calculated " << ntr << " reconstruction trajectories" << std::flush;
3602  while ((group = (KVGroup*)it())) {
3603  ntr += group->CalculateReconstructionTrajectories();
3605  std::cout << "\xd" << " -- calculated " << ntr << " reconstruction trajectories" << std::flush;
3606  }
3608  std::cout << " -- calculated " << ntr << " reconstruction trajectories" << std::endl;
3609  else
3610  std::cout << std::endl;
3611 }
3612 
3613 
3614 
3621 
3623 {
3624  // Track over all possible particle trajectories calling
3625  // GetIDTelescopes(KVDetector*,KVDetector*)
3626  // for each pair of (present & functioning) detectors.
3627  // This will create all possible KVIDTelescope identification
3628  // objects and put them in list fIDTelescopes
3629 
3630  fIDTelescopes->Delete();
3631  TIter next_traj(GetTrajectories());
3632  KVGeoDNTrajectory* traj;
3633  Int_t count = 0;
3634  Info("DeduceIdentificationTelescopesFromGeometry", "Calculating...");
3636  std::cout << "\xd" << " -- created " << count << " telescopes" << std::flush;
3637  while ((traj = (KVGeoDNTrajectory*)next_traj())) { // loop over all trajectories
3638 
3639  traj->IterateFrom(); // from furthest-out to closest-in detector
3640 
3642  while ((N = traj->GetNextNode())) {
3643  KVGeoDetectorNode* Nplus1 = traj->GetNodeInFront(N);
3644 
3645  if (Nplus1) {
3646  count += GetIDTelescopes(Nplus1->GetDetector(), N->GetDetector(), traj->AccessIDTelescopeList());
3648  std::cout << "\xd" << " -- created " << count << " telescopes" << std::flush;
3649  }
3650  }
3651  }
3653  std::cout << " -- created " << count << " telescopes" << std::endl;
3654  else
3655  std::cout << std::endl;
3656 }
3657 
3658 
3659 
3663 
3665 {
3666  // Eliminate any trajectories which are just sub-trajectories of others
3667  // For each trajectory in list fTrajectories, we add a reference to the trajectory to each node on the trajectory
3668 
3669  TIter it(&fTrajectories);
3670  KVGeoDNTrajectory* tr;
3671  KVList duplicates;
3672  // look for duplicate sub-trajectories
3673  while ((tr = (KVGeoDNTrajectory*)it())) {
3674  int len_tr = tr->GetN();
3675  TIter it2(&fTrajectories);
3676  KVGeoDNTrajectory* tr2;
3677  while ((tr2 = (KVGeoDNTrajectory*)it2())) {
3678  if ((tr2 != tr) && (len_tr < tr2->GetN()) && (tr2->ContainsPath(tr))) {
3679  duplicates.Add(tr);
3680  break;
3681  }
3682  }
3683  }
3684  // remove duplicates
3685  if (duplicates.GetEntries()) {
3686  TIter it_dup(&duplicates);
3687  while ((tr = (KVGeoDNTrajectory*)it_dup())) {
3688  fTrajectories.Remove(tr);
3689  }
3690  Info("AssociateTrajectoriesAndNodes", "Removed %d duplicated sub-trajectories", duplicates.GetEntries());
3691  }
3692  Info("AssociateTrajectoriesAndNodes", "Calculated %d particle trajectories", fTrajectories.GetEntries());
3693  it.Reset();
3694  while ((tr = (KVGeoDNTrajectory*)it())) {
3695  tr->AddToNodes();
3696  }
3697 }
3698 
3699 
3700 
3702 
3704 {
3705  if (N->GetNTraj() > 1) {
3706  if (!multitraj_nodes.FindObject(N)) { // look for any detectors which are on multiple trajectories
3707  //cout << "multitraj node found: " << N->GetName() << " (" << N->GetNTraj() << ")" << endl;
3708  multitraj_nodes.Add(N);
3709  TIter tr(N->GetTrajectories());
3710  KVGeoDNTrajectory* traj;
3711  while ((traj = (KVGeoDNTrajectory*)tr())) { // for each trajectory associated with detector
3712  if (tried_trajectories.FindObject(traj)) continue; // trajectory already used
3713  tried_trajectories.Add(traj);
3714  traj->IterateFrom();
3715  KVGeoDetectorNode* node;
3716  while ((node = traj->GetNextNode())) { // store names of all detectors on trajectory
3717  detectors_of_group.Add(node);
3718  RecursiveTrajectoryClustering(node, tried_trajectories, multitraj_nodes, detectors_of_group);
3719  }
3720  }
3721  }
3722  }
3723  else if (N->GetNTraj() == 1) {
3724  // single-trajectory node.
3725  // work along trajectory adding nodes to group
3726  KVGeoDNTrajectory* traj = (KVGeoDNTrajectory*)N->GetTrajectories()->First();
3727  if (tried_trajectories.FindObject(traj)) return; // trajectory already used
3728  tried_trajectories.Add(traj);
3729  traj->IterateFrom();
3730  KVGeoDetectorNode* node;
3731  while ((node = traj->GetNextNode())) { // store names of all detectors on trajectory
3732  detectors_of_group.Add(node);
3733  RecursiveTrajectoryClustering(node, tried_trajectories, multitraj_nodes, detectors_of_group);
3734  }
3735  }
3736  else {
3737  // orphan node? single-detector array?
3738  detectors_of_group.Add(N);
3739  }
3740 }
3741 
3742 
3743 
3750 
3752 {
3753  // Create and return pointer to new KVGroupReconstructor for reconstructing particles
3754  // in the given group. Returns nullptr if group is not part of this array.
3755  //
3756  // Plugins for specific arrays can be defined as plugins using the name of the array:
3757  // +Plugin.KVGroupReconstructor: my_array my_group_reconstructor my_lib "my_group_reconstructor()"
3758 
3759  KVGroupReconstructor* gr(nullptr);
3760  if (GetGroup(g->GetName())) {
3761  // look for plugin
3763  if (!gr) gr = new KVGroupReconstructor;
3764  }
3765  return gr;
3766 }
3767 
3768 
3769 
3773 
3775 {
3776  // Call this method just after opening a raw data file in order to perform any
3777  // necessary initialisations, depending on the type of data
3778 
3779 #ifdef WITH_BUILTIN_GRU
3780  if (r->GetDataFormat() == "EBYEDAT") dynamic_cast<KVGANILDataReader*>(r)->ConnectRawDataParameters(GetACQParams());
3781 #endif
3782 }
3783 
3784 
3785 
3790 
3792 {
3793  // Deduce the "groups" in the array from the trajectories
3794  // Any trajectories with 1 or more common detectors define a group.
3795  // The group is constituted of all detectors belonging to the trajectories of the group.
3796 
3797  Info("DeduceGroupsFromTrajectories", "Deducing groups of detectors from trajectories");
3798  Int_t number_of_groups = 0;
3799  TIter next_det(GetDetectors());
3800  unique_ptr<KVSeqCollection> stl(GetStructureTypeList("GROUP"));
3801  if (stl.get() && stl->GetEntries()) {
3802  Info("DeduceGroupsFromTrajectories", "Deleting existing %d groups in array", stl->GetEntries());
3803  ClearStructures("GROUP");
3804  Info("DeduceGroupsFromTrajectories", "Done");
3805  }
3806  KVDetector* det;
3807  KVUniqueNameList tried_trajectories;//avoid double-counting/infinite loops
3808  KVUniqueNameList multitraj_nodes;//avoid double-counting/infinite loops
3809  while ((det = (KVDetector*) next_det())) {
3810  if (det->GetGroup()) continue; // group assignment already done
3811  KVUniqueNameList detectors_of_group;
3812  RecursiveTrajectoryClustering(det->GetNode(), tried_trajectories, multitraj_nodes, detectors_of_group);
3813  if (!detectors_of_group.GetEntries()) continue;
3814  KVGroup* Group = new KVGroup;
3815  Group->SetNumber(++number_of_groups);
3816  Add(Group);
3817  TIter next_node(&detectors_of_group);
3819  while ((d = (KVGeoDetectorNode*)next_node())) Group->Add(d->GetDetector());
3820  }
3821  TIter tr(&fTrajectories);
3822  KVGeoDNTrajectory* t;
3823  Info("DeduceGroupsFromTrajectories", "Filling group trajectory lists");
3824  while ((t = (KVGeoDNTrajectory*)tr())) {
3825  if (t->GetNodeAt(0)->GetDetector()->GetGroup())
3826  t->GetNodeAt(0)->GetDetector()->GetGroup()->AddTrajectory(t);
3827  else {
3828  t->Print();
3829  t->GetNodeAt(0)->GetDetector()->Print();
3830  }
3831  }
3832 }
3833 
3834 
3835 
3839 
3841 {
3842  // Called when required to fill KVReconstructedNucleus::fDetList with pointers to
3843  // the detectors whose names are stored in KVReconstructedNucleus::fDetNames.
3844 
3845  DetList->Clear();
3846  DetNames.Begin("/");
3847  while (!DetNames.End()) {
3848  KVDetector* det = GetDetector(DetNames.Next(kTRUE));
3849  if (det) DetList->Add(det);
3850  }
3851 }
3852 
3853 
3854 
3865 
3867 {
3868  // Set status (IsOK) of particle by comparing its identification/calibration codes
3869  // with those set as acceptable in fAcceptIDCodes and fAcceptECodes.
3870  // The default lists are defined in variables of the form
3871  // [DataSet].[name].ReconstructedNuclei.AcceptIDCodes: [list]
3872  // [DataSet].[name].ReconstructedNuclei.AcceptECodes: [list]
3873  // where DataSet is an optional dataset name for dataset-specific lists
3874  // name is the name of the multidetector array
3875  // list is a numeric list (KVNumberList format)
3876  // If either list is empty, no selection is made for the corresponding code
3877 
3878  Bool_t ok = kTRUE;
3880  if (!fAcceptECodes.IsEmpty()) ok = ok && fAcceptECodes.Contains(NUC->GetECode());
3881  NUC->SetIsOK(ok);
3882 }
3883 
3884 
3885 
3892 
3894 {
3895  // Set the minimum number of particles which are "OK" in the event
3896  // (usually a KVReconstructedEvent) for it to be retained for analysis.
3897  // This could, for example, depend on the experimental multiplicity trigger
3898  // used during the run.
3899  // This default version sets a minimum of 1 "OK" particle
3900  e->SetMinimumOKMultiplicity(1);
3901 }
3902 
3903 
3904 #ifdef WITH_BUILTIN_GRU
3905 
3909 
3911 {
3912  // General method for reading raw data in old GANIL ebyedat format
3913  // Values of all KVACQParam objects appearing in the event are updated
3914  AbstractMethod("handle_raw_data_event_ebyedat");
3915  return kFALSE;
3916 }
3917 
3918 #endif
3919 
3920 
3923 
3925 {
3926  // reset acquisition parameters etc. before reading new raw data event
3927  TIter it(&fFiredACQParams);
3928  TObject* obj;
3929  while ((obj = it())) obj->Clear();
3932  fHandledRawData = false;
3933 }
3934 
3935 
3936 
3944 
3946 {
3947  // Perform any operations to finalise the description of the multidetector
3948  // which can only be done once the geometry is closed, e.g. use KVGeoImport
3949  // to set up nodes, trajectories, detectors, idtelescopes, etc.
3950  // This has to be kept separate for use with KVExpSetUp which first fills
3951  // a single ROOT geometry with all component KVMultiDetArray geometries,
3952  // then closes the geometry only when all have been built.
3953 }
3954 
3955 
3956 
3959 
3961 {
3962  // Copy any parameters in fReconParameters in to the reconstructed event parameter list
3963  *(e->GetParameters()) += fReconParameters;
3964 }
3965 
3966 
3967 
3969 
3971 {
3973  TObject* o;
3974  while ((o = it())) {
3975  if (o->InheritsFrom("KVACQParam") && GetACQParam(o->GetName())) {
3976  fReconParameters.SetValue(Form("ACQPAR.%s.%s", GetName(), o->GetName()), (Int_t)((KVACQParam*)o)->GetCoderData());
3977  }
3978  }
3979 }
3980 
3981 
3982 
3991 
3993 {
3994  // Update array according to last event read using the KVRawDataReader object
3995  // (it is assumed that KVRawDataReader::GetNextEvent() was called before calling this method)
3996  //
3997  // Return kTRUE if raw data was treated
3998  //
3999  // All fired acquisition parameters are written in the fReconParameters list,
4000  // ready to be copied to the reconstructed event
4001 
4003  if (rawdata->GetDataFormat() == "MFM") {
4004 #ifdef WITH_MFM
4006 #endif
4007  }
4008  else if (rawdata->GetDataFormat() == "PROTOBUF") {
4009 #ifdef WITH_PROTOBUF
4011 #endif
4012  }
4013  else if (rawdata->GetDataFormat() == "EBYEDAT") {
4014 #ifdef WITH_BUILTIN_GRU
4016 #endif
4017  }
4018  if (fHandledRawData) {
4020  }
4021  return fHandledRawData;
4022 }
4023 
4024 
4025 #ifdef WITH_MFM
4026 
4035 
4037 {
4038  // Update array according to last event read from MFM buffer
4039  // (it is assumed that MFMBufferReader::ReadNextFrame() was called before calling this method)
4040  //
4041  // Return kTRUE if raw data was treated
4042  //
4043  // All fired acquisition parameters are written in the fReconParameters list,
4044  // ready to be copied to the reconstructed event
4045 
4047  bool ok = false;
4048  ok = handle_raw_data_event_mfmfile(bufrdr);
4049  if (ok) {
4051  }
4052  return ok;
4053 }
4054 
4055 #endif
4056 
4057 
4061 
4063 {
4064  // Take values 'ACQPAR.[array_name].[par_name]' in the parameter list and use them to set
4065  // values of raw acquisition parameters (EBYEDAT)
4066 
4067  int N = l.GetNpar();
4068  for (int i = 0; i < N; ++i) {
4069  KVNamedParameter* np = l.GetParameter(i);
4070  KVString name(np->GetName());
4071  name.Begin(".");
4072  if (name.Next() == "ACQPAR") {
4073  if (name.Next() == GetName()) {
4074  KVACQParam* par = GetACQParam(name.Next());
4075  if (par) par->SetData((UShort_t)np->GetInt());
4076  }
4077  }
4078  }
4079 }
4080 
4081 
4082 
4098 
4100 {
4101  // We first look for a file with the name given by
4102  //
4103  // [dataset].[name].OoODetectors: [name.OoODetectors.dat]
4104  //
4105  // which should contain the runlists for each malfunctioning detector.
4106  // If found we add to the experiment database a table '[name].OoO Detectors' where [name] is the name of this array.
4107  //
4108  // Then we look for a file with the name given by
4109  //
4110  // [dataset].[name].CalibrationFiles: [CalibrationFiles.dat]
4111  //
4112  // which should contain the names of files to read with each type of calibration
4113  // If found we add to the experiment database a table '[name].Calibrations' where [name] is the name of this array,
4114  // containing all calibrations as KVDBParameterSet objects with the name of the detector concerned.
4115 
4116  ReadOoODetectors(db);
4118 }
4119 
4120 
4121 
4123 
4125 {
4126  TString basic_name = db->GetCalibFileName(keyw);
4127  if (basic_name == "") {
4128  Info(meth, "No name found for \"%s\" file", keyw);
4129  return "";
4130  }
4131  Info(meth, "Search for %s for dataset %s ...", basic_name.Data(), fDataSet.Data());
4132  TString fp;
4133  SearchKVFile(basic_name.Data(), fp, fDataSet);
4134  if (fp == "") {
4135  Info(meth, "\tNo file found ...");
4136  }
4137  return fp;
4138 }
4139 
4140 
4141 
4143 
4144 unique_ptr<KVFileReader> KVMultiDetArray::GetKVFileReader(KVExpDB* db, const Char_t* meth, const Char_t* keyw)
4145 {
4146 
4147  TString fp = GetFileName(db, meth, keyw);
4148  if (fp == "")
4149  return unique_ptr<KVFileReader>();
4150 
4151  unique_ptr<KVFileReader> fr(new KVFileReader());
4152  if (!fr->OpenFileToRead(fp.Data())) {
4153  Error(meth, "Error in opening file %s", fp.Data());
4154  fr.reset(nullptr);
4155  }
4156  else
4157  Info(meth, "Reading %s file", fp.Data());
4158  return fr;
4159 }
4160 
4161 
4162 
4164 
4166 {
4167 
4168  unique_ptr<KVFileReader> fr = GetKVFileReader(db, "ReadCalibrationFiles()", "CalibrationFiles");
4169  if (!fr.get())
4170  return;
4171 
4172  KVDBTable* calib_table = db->AddTable(Form("%s.Calibrations", GetName()), Form("Calibrations for %s", GetName()));
4173  while (fr->IsOK()) {
4174  fr->ReadLine(0);
4175  if (fr->GetCurrentLine().BeginsWith("#") || fr->GetCurrentLine() == "") {}
4176  else {
4177  ReadCalibFile(fr->GetCurrentLine().Data(), db, calib_table);
4178  }
4179  }
4180  fr->CloseFile();
4181 }
4182 
4183 
4184 
4225 
4226 void KVMultiDetArray::ReadCalibFile(const Char_t* filename, KVExpDB* db, KVDBTable* calib_table)
4227 {
4228  // Read a calibration file with the format
4229  //
4230  //~~~~~~~~~~~~~
4231  // RunList: 1546-7485
4232  // SignalIn: PG
4233  // SignalOut: Volts
4234  // CalibType: ChannelVolt
4235  // CalibOptions: func=pol3,min=0,max=1
4236  // ZRange: 2-92
4237  // [detector1]: 0.0,0.261829,0.0
4238  // [detector2]: 0.1,0.539535,1.2
4239  //~~~~~~~~~~~~~
4240  //
4241  //The `[RunList]` is optional: if not given, the calibration will be applied to all runs in the database.
4242  //
4243  //If different parameters are required for different sets of runs, they should be written in different
4244  //files (all of which are listed in `CalibrationFiles.dat` or `[array].CalibrationFiles.dat`).
4245  //
4246  //The `[CalibClass]`, if given, must correspond to a KVCalibrator plugin name. The list of plugin names and the corresponding
4247  //classes can be retrieved with
4248  //
4249  //~~~~~~~~~~~
4250  //KVBase::GetListOfPlugins("KVCalibrator")
4251  //KVBase::GetListOfPluginURIs("KVCalibrator")
4252  //~~~~~~~~~~~
4253  //
4254  //KVCalibrator objects are added to detectors as required by the contents of calibration files.
4255  //If any detector has an existing calibrator of type `[CalibType]` which is not of the given class
4256  //it will be replaced with a new calibrator corresponding to the plugin.
4257  //
4258  //The `[CalibOptions]` is optional: list in `[CalibOptions]` will be used
4259  //to complete set-up of any new calibrator objects by calling the KVCalibrator::SetOptions()
4260  //method.
4261  //
4262  //`[CalibOptions]` should hold a comma-separated list of `parameter=value` pairs which will be used
4263  //to fill a KVNameValueList for the method call. See the KVCalibrator::SetOptions() method.
4264  //
4265  //`[ZRange]` is an option if several calibrations need to be used to provide the same signal
4266  //for certain detectors depending on the atomic number Z of the particle detected.
4267 
4268 
4269  TString fullpath = "";
4270  if (!SearchKVFile(filename, fullpath, fDataSet)) {
4271  Info("ReadCalibFile", "%s does not exist or not found", filename);
4272  return;
4273  }
4274 
4275  Info("ReadCalibFile", "file : %s found", fullpath.Data());
4276  TEnv env;
4277  env.ReadFile(fullpath, kEnvAll);
4278 
4279  // read options from file
4280  KVNameValueList options;
4281  KVString opt_list = "RunList SignalIn SignalOut CalibType CalibClass CalibOptions ZRange";
4282  opt_list.Begin(" ");
4283  while (!opt_list.End()) {
4284  KVString opt = opt_list.Next();
4285  KVString opt_val = env.GetValue(opt, "");
4286  opt_val.Remove(TString::kBoth, ' ');
4287  options.SetValue(opt, opt_val.Data());
4288  }
4289 
4290  if (options.GetTStringValue("SignalIn") == "") {
4291  Error("ReadCalibFile", "No input signal defined : SignalIn");
4292  return;
4293  }
4294  if (options.GetTStringValue("SignalOut") == "") {
4295  Error("ReadCalibFile", "No output signal defined : SignalOut");
4296  return;
4297  }
4298  if (options.GetTStringValue("CalibType") == "") {
4299  Error("ReadCalibFile", "No calibration type defined : CalibType");
4300  return;
4301  }
4302  Bool_t check_class(options.GetTStringValue("CalibClass") != "");
4303  TString calibrator_class;
4304  if (check_class) {
4305  TPluginHandler* ph = LoadPlugin("KVCalibrator", options.GetStringValue("CalibClass"));
4306  if (ph) calibrator_class = ph->GetClass();
4307  else {
4308  Error("ReadCalibFile", "No calibrator plugin of type %s", options.GetStringValue("CalibClass"));
4309  return;
4310  }
4311  }
4312 
4313  KVString clop;
4314  if (options.HasParameter("CalibOptions")) clop = options.GetStringValue("CalibOptions");
4315 
4316  KVString zrange;
4317  if (options.HasParameter("ZRange")) zrange = options.GetStringValue("ZRange");
4318 
4319  KVNumberList run_list = db->GetRunList();
4320  if (options.GetTStringValue("RunList") != "")
4321  run_list.Set(options.GetTStringValue("RunList"));
4322 
4323  TIter next(env.GetTable());
4324  TEnvRec* rec = 0;
4325  KVDBParameterSet* par = 0;
4326 
4327  while ((rec = (TEnvRec*)next())) {
4328 
4329  TString sname(rec->GetName());
4330  KVDetector* det = GetDetector(sname);
4331  if (!det) continue;
4332 
4333  KVString lval(rec->GetValue());
4334  par = new KVDBParameterSet(sname.Data(), options.GetStringValue("CalibType"), lval.GetNValues(","));
4335  par->SetParameter("SignalIn", options.GetStringValue("SignalIn"));
4336  par->SetParameter("SignalOut", options.GetStringValue("SignalOut"));
4337  // put infos on required calibrator class into database so that it can be replaced
4338  // as needed in SetCalibratorParameters
4339  par->SetParameter("CalibClass", options.GetStringValue("CalibClass"));
4340  if (clop != "") par->SetParameter("CalibOptions", clop);
4341  if (zrange != "") par->SetParameter("ZRange", zrange);
4342  Int_t np = 0;
4343  lval.Begin(",");
4344  while (!lval.End()) {
4345  par->SetParameter(np++, lval.Next().Atof());
4346  }
4347  calib_table->AddRecord(par);
4348  db->LinkRecordToRunRange(par, run_list);
4349 
4350  }
4351 }
4352 
4353 
4354 #ifdef WITH_MFM
4355 
4361 
4363 {
4364  // Update array according to last event read using the KVMFMDataFileReader object
4365  // (it is assumed that KVRawDataReader::GetNextEvent() was called before calling this method)
4366  //
4367  // Return kTRUE if raw data was treated
4368 
4369  if (mfmreader.IsFrameReadMerge()) {
4370  return handle_raw_data_event_mfmmergeframe(mfmreader.GetMergeManager());
4371  }
4372  else {
4373  return handle_raw_data_event_mfmframe(mfmreader.GetFrameRead());
4374  }
4375  return kFALSE;
4376 }
4377 
4378 
4379 
4383 
4384 Bool_t KVMultiDetArray::handle_raw_data_event_mfmmergeframe(const MFMMergeFrameManager& mergeframe)
4385 {
4386  // Method used to handle merged MFM frames
4387  // We call handle_raw_data_event_mfmframe() for each frame contained in the merge
4388 
4389  Bool_t ok = false;
4390  while (mergeframe.ReadNextFrame()) {
4391  Bool_t me = handle_raw_data_event_mfmframe(mergeframe.GetFrameRead());
4392  ok = (ok || me);
4393  }
4394  return ok;
4395 }
4396 
4397 
4398 
4406 
4408 {
4409  // Method used to treat raw data in MFM format read by KVMFMDataFileReader
4410  // A generic method is provided to treat MFM-encapsulated ebyedat data
4411  // - see handle_raw_data_event_mfmframe_ebyedat(const MFMEbyedatFrame&)
4412  // Treatment of other frame types will need to be implemented in child classes.
4413  //
4414  // Return kTRUE if raw data was treated
4415 
4416  if (!fACQParams) return kFALSE;// no (ebyedat) acquisition parameters defined for array
4417 
4418  if (mfmframe.GetFrameType() == MFM_EBY_EN_FRAME_TYPE
4419  || mfmframe.GetFrameType() == MFM_EBY_TS_FRAME_TYPE
4420  || mfmframe.GetFrameType() == MFM_EBY_EN_TS_FRAME_TYPE)
4421  return handle_raw_data_event_mfmframe_ebyedat((const MFMEbyedatFrame&)mfmframe);
4422 
4423  return kFALSE;
4424 }
4425 
4426 
4427 
4437 
4439 {
4440  // General method for reading raw data in MFM-encapsulated ebyedat format
4441  // Values of all KVACQParam objects appearing in the event are updated
4442  // Fills list of hit acquisition parameters.
4443  // Returns kTRUE if at least one parameter belonging to the array is present.
4444  //
4445  // Any unknown parameters in the event (i.e. ones for which no KVACQParam object
4446  // has been defined) are written in the fReconParameters list with names
4447  // "ACQPAR.[array name].[parameter name]"
4448 
4449  uint16_t val;
4450  string lab;
4451  KVACQParam* acqpar;
4452  Bool_t ok = false;
4453 
4454  for (int i = 0; i < ebyframe.GetNbItems(); ++i) {
4455  ebyframe.GetDataItem(i, lab, val);
4456  if ((acqpar = GetACQParam(lab.c_str()))) {
4457  acqpar->SetData(val);
4458  fFiredACQParams.Add(acqpar);
4459  ok = kTRUE;
4460  }
4461  else
4462  fReconParameters.SetValue(Form("ACQPAR.%s.%s", GetName(), lab.c_str()), val);
4463  }
4464 
4465  return ok;
4466 }
4467 
4468 #endif
4469 
4470 #ifdef WITH_PROTOBUF
4471 
4473 
4475 {
4476  AbstractMethod("handle_raw_data_event_protobuf");
4477  return kFALSE;
4478 }
4479 
4480 #endif
4481 
4482 
4485 
4487 {
4488  // For each IDtelescope in array, calculate an identification grid
4489 
4490  TIter nxtid(GetListOfIDTelescopes());
4491  KVIDTelescope* idt;
4492  while ((idt = (KVIDTelescope*) nxtid())) {
4493  idt->CalculateDeltaE_EGrid("1-92", 0, 20);
4494  }
4495 }
4496 
4497 
4498 
4503 
4505 {
4506  // Sets status of detectors (KVDetector::IsPresent() and KVDetector::IsWorking()) for a given run of a dataset.
4507  //
4508  // If 'myname' is given, we look in database table "myname.OoODets"
4509 
4510  KVRList* absdet = (myname != "" ? kvrun->GetLinks(Form("%s.Absent Detectors", myname.Data())) : kvrun->GetLinks("Absent Detectors"));
4511  KVRList* ooodet = (myname != "" ? kvrun->GetLinks(Form("%s.OoO Detectors", myname.Data())) : kvrun->GetLinks("OoO Detectors"));
4512 
4513  TIter next(GetDetectors());
4514  KVDetector* det;
4515 
4516  Int_t ndet_absent = 0;
4517  Int_t ndet_ooo = 0;
4518  TString absent_dets, ooo_dets;
4519 
4520  while ((det = (KVDetector*)next())) {
4521  //Test de la presence ou non du detecteur
4522  if (!absdet) {
4523  det->SetPresent();
4524  }
4525  else {
4526  if (absdet->FindObject(det->GetName(), "Absent Detector")) {
4527  det->SetPresent(kFALSE);
4528  if (ndet_absent) absent_dets += ",";
4529  absent_dets += det->GetName();
4530  ndet_absent += 1;
4531  }
4532  else {
4533  det->SetPresent();
4534  }
4535  }
4536  if (det->IsPresent()) {
4537  //Test du bon fonctionnement ou non du detecteur
4538  if (!ooodet) {
4539  det->SetDetecting();
4540  }
4541  else {
4542  if (ooodet->FindObject(det->GetName(), "OoO Detector")) {
4543  det->SetDetecting(kFALSE);
4544  if (ndet_ooo) ooo_dets += ",";
4545  ooo_dets += det->GetName();
4546  ndet_ooo += 1;
4547  }
4548  else {
4549  det->SetDetecting();
4550  }
4551  }
4552  }
4553  }
4554 
4555  if (ndet_absent) Info("CheckStatusOfDetectors", "%d detectors absent during run : %s", ndet_absent, absent_dets.Data());
4556  else Info("CheckStatusOfDetectors", "All detectors present during run");
4557  if (ndet_ooo) Info("CheckStatusOfDetectors", "%d detectors malfunctioned during run : %s", ndet_ooo, ooo_dets.Data());
4558  else Info("CheckStatusOfDetectors", "All detectors functioning during run");
4559 }
4560 
4561 
4562 
4577 
4579 {
4580  // Read a file containing runlists for each temporarily non-functioning detector.
4581  //
4582  // The file should be in TEnv format like so:
4583  //
4584  //~~~~
4585  // DET_1: 100-122,541-1938
4586  // DET_2,DET_3: 91-765
4587  //~~~~
4588  //
4589  // i.e. more than one detector can be associated with the same runs (comma-separated list of
4590  // detector names) and the list of runs are given using KVNumberList syntax.
4591  //
4592  // The data is added to the database in a table '[name].OoO Detectors' with the name of this array.
4593 
4594  TString fullpath;
4595  if (!db->FindCalibFile("OoODet", fullpath)) return;
4596 
4597  Info("ReadOoODetectors()", "Reading lists of out-of-order detectors...");
4598  auto fOoODet = db->AddTable(Form("%s.OoO Detectors", GetName()), "Name of out of order detectors");
4599 
4600  KVDBRecord* dbrec = 0;
4601  TEnv env;
4602  TEnvRec* rec = 0;
4603  env.ReadFile(fullpath.Data(), kEnvAll);
4604  TIter it(env.GetTable());
4605 
4606  while ((rec = (TEnvRec*)it.Next())) {
4607  KVString srec(rec->GetName());
4608  KVNumberList nl(rec->GetValue());
4609  if (srec.Contains(",")) {
4610  srec.Begin(",");
4611  while (!srec.End()) {
4612  dbrec = new KVDBRecord(srec.Next(kTRUE), "OoO Detector");
4613  dbrec->AddKey("Runs", "List of Runs");
4614  fOoODet->AddRecord(dbrec);
4615  db->LinkRecordToRunRange(dbrec, nl);
4616  }
4617  }
4618  else {
4619  dbrec = new KVDBRecord(rec->GetName(), "OoO Detector");
4620  dbrec->AddKey("Runs", "List of Runs");
4621  fOoODet->AddRecord(dbrec);
4622  db->LinkRecordToRunRange(dbrec, nl);
4623  }
4624  }
4625 }
4626 
4627 
int Int_t
unsigned int UInt_t
KVDataSetManager * gDataSetManager
KVDataSet * gDataSet
Definition: KVDataSet.cpp:30
KVIDGridManager * gIDGridManager
KVMultiDetArray * gMultiDetArray
ClassImp(KVPartitionList) void KVPartitionList
Initialisation.
ROOT::R::TRInterface & r
#define SafeDelete(p)
#define d(i)
#define e(i)
unsigned short UShort_t
char Char_t
const Bool_t kFALSE
bool Bool_t
double Double_t
float Float_t
const Bool_t kTRUE
const char Option_t
R__EXTERN TEnv * gEnv
kEnvUser
kEnvAll
#define N
int type
R__EXTERN TGeoManager * gGeoManager
char * Form(const char *fmt,...)
#define gPad
GANIL VXI/VME acquisition parameter.
Definition: KVACQParam.h:15
void SetWorking(Bool_t on=kTRUE)
Definition: KVACQParam.h:130
KVDetector * GetDetector() const
Definition: KVACQParam.h:40
void SetData(UShort_t val)
Definition: KVACQParam.h:58
void SetLabel(const Char_t *lab)
Definition: KVBase.h:188
const Char_t * GetLabel() const
Definition: KVBase.h:192
const Char_t * GetType() const
Definition: KVBase.h:170
virtual void Print(Option_t *option="") const
Definition: KVBase.cpp:413
virtual void SetType(const Char_t *str)
Definition: KVBase.h:166
static const Char_t * GetDataSetEnv(const Char_t *dataset, const Char_t *type, const Char_t *defval)
Definition: KVBase.cpp:1582
static Bool_t SearchKVFile(const Char_t *name, TString &fullpath, const Char_t *kvsubdir="")
Definition: KVBase.cpp:541
static TPluginHandler * LoadPlugin(const Char_t *base, const Char_t *uri="0")
Definition: KVBase.cpp:756
Base class for all detector calibrations.
Definition: KVCalibrator.h:75
Int_t GetNumberParams() const
Definition: KVCalibrator.h:129
virtual void SetOptions(const KVNameValueList &)
void SetParameter(int i, Double_t par_val) const
Definition: KVCalibrator.h:134
void SetStatus(Bool_t ready)
Definition: KVCalibrator.h:142
void SetOutputSignalType(const TString &type)
Definition: KVCalibrator.h:196
void SetInputSignalType(const TString &type)
Definition: KVCalibrator.h:192
static KVCalibrator * MakeCalibrator(const Char_t *type)
To store calibration parameters in a database ,.
Bool_t HasParameter(const Char_t *name) const
TString GetStringParameter(const TString &name) const
Double_t GetParameter(UShort_t i=0) const
void Print(Option_t *option="") const
Int_t GetParamNumber() const
void SetParameter(UShort_t i, Double_t val)
const KVNameValueList & GetParameters() const
Record folder for the database.
Definition: KVDBRecord.h:42
virtual Bool_t AddKey(KVDBKey *key, Bool_t check=kTRUE)
Definition: KVDBRecord.cpp:65
virtual KVRList * GetLinks(const Char_t *key) const
Returns the list of records linked to this record in table "key".
Definition: KVDBRecord.cpp:206
Description of an experimental run in database ,.
Definition: KVDBRun.h:35
Table in a database.
Definition: KVDBTable.h:33
virtual Bool_t AddRecord(KVDBRecord *add)
Definition: KVDBTable.cpp:74
static Bool_t IsRunningBatchAnalysis()
virtual Bool_t AddTable(KVDBTable *table)
Definition: KVDataBase.cpp:84
KVDataSet * GetDataSet(Int_t) const
Return pointer to DataSet using index in list of all datasets, index>=0.
Manage an experimental dataset corresponding to a given experiment or campaign.
Definition: KVDataSet.h:207
Bool_t HasCalibIdentInfos() const
Definition: KVDataSet.h:396
const Char_t * GetDataSetEnv(const Char_t *type, const Char_t *defval="") const
Definition: KVDataSet.cpp:757
TString GetFullPathToDataSetFile(const Char_t *filename)
Definition: KVDataSet.cpp:1886
void cd() const
Definition: KVDataSet.cpp:735
Base class for detector geometry description, interface to energy-loss calculations.
Definition: KVDetector.h:121
virtual Bool_t IsOK() const
Definition: KVDetector.h:628
TList * GetTelescopesForIdentification()
Definition: KVDetector.cpp:900
KVList * GetAlignedIDTelescopes()
Definition: KVDetector.cpp:875
KVGeoStrucElement * GetParentStructure(const Char_t *type, const Char_t *name="") const
KVGroup * GetGroup() const
virtual void SetEnergyLoss(Double_t e) const
Definition: KVDetector.h:332
KVList * GetHits() const
Return the list of particles hitting this detector in an event.
Definition: KVDetector.h:395
virtual Double_t GetEnergy() const
Definition: KVDetector.h:308
Int_t GetNHits() const
Return the number of particles hitting this detector in an event.
Definition: KVDetector.h:405
virtual const Char_t * GetFiredACQParameterListFormatString() const
Definition: KVDetector.h:540
virtual void SetACQParams()
Definition: KVDetector.cpp:802
KVList * GetIDTelescopes()
Definition: KVDetector.h:478
Double_t GetTheta() const
Definition: KVDetector.h:690
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:769
virtual void DeduceACQParameters(KVEvent *, KVNumberList &)
Definition: KVDetector.h:634
void SetThickness(Double_t thick)
Bool_t IsCalibrated() const
Definition: KVDetector.h:359
void SetDetecting(Bool_t yes=kTRUE)
Definition: KVDetector.h:623
virtual void RemoveCalibrators()
Definition: KVDetector.cpp:838
Double_t GetPhi() const
Definition: KVDetector.h:708
virtual Double_t GetPunchThroughEnergy(Int_t Z, Int_t A)
virtual void SetFiredBitmask(KVString &)
virtual Bool_t IsDetecting() const
Definition: KVDetector.h:618
virtual TList * GetAlignedDetectors(UInt_t direction=1)
KVGeoDetectorNode * GetNode()
Definition: KVDetector.h:285
virtual Double_t GetIncidentEnergyFromERes(Int_t Z, Int_t A, Double_t Eres)
KVList * GetACQParamList() const
Definition: KVDetector.h:342
virtual Bool_t IsPresent() const
Definition: KVDetector.h:609
TVector3 GetRandomDirection(Option_t *t="isotropic")
Definition: KVDetector.h:666
void ResetAlignedDetectors(UInt_t direction=1)
virtual void Print(Option_t *option="") const
Definition: KVDetector.cpp:393
Bool_t AddCalibrator(KVCalibrator *cal, const KVNameValueList &opts="")
Definition: KVDetector.cpp:510
void SetPresent(Bool_t yes=kTRUE)
Definition: KVDetector.h:614
Base class container for multi-particle events.
Definition: KVEvent.h:176
KVNameValueList * GetParameters() const
Definition: KVEvent.h:391
virtual void Clear(Option_t *opt="")
Definition: KVEvent.cpp:200
Base class to describe database of an experiment ,.
Definition: KVExpDB.h:18
Bool_t FindCalibFile(const Char_t *type, TString &fullpath) const
Definition: KVExpDB.cpp:476
TString GetCalibFileName(const Char_t *type) const
Definition: KVExpDB.h:107
const KVNumberList & GetRunList() const
Definition: KVExpDB.h:78
virtual void LinkRecordToRunRange(KVDBRecord *rec, UInt_t first_run, UInt_t last_run)
Definition: KVExpDB.cpp:86
Handle reading text files.
Definition: KVFileReader.h:19
Reads GANIL acquisition files (EBYEDAT)
Path taken by particles through multidetector geometry.
KVGeoDetectorNode * GetNextNode() const
KVSeqCollection * AccessIDTelescopeList()
void AddToNodes()
Add reference to this trajectory to all nodes on it.
void IterateFrom(const KVGeoDetectorNode *node0=nullptr) const
Bool_t ContainsPath(KVGeoDNTrajectory *other)
KVGeoDetectorNode * GetNodeInFront(const KVGeoDetectorNode *n) const
KVGeoDetectorNode * GetNodeAt(Int_t i) const
Information on relative positions of detectors & particle trajectories.
KVDetector * GetDetector() const
Base class for propagation of particles through array geometry.
Bool_t IsTracking() const
void ResetTrackID(Int_t id=0)
void DrawTracks(KVNumberList *=nullptr)
Base class describing elements of array geometry.
virtual Bool_t Fired(Option_t *opt="any") const
void SetOwnsDetectors(Bool_t yes=kTRUE)
KVDetector * GetDetector(const Char_t *name) const
Return detector in this structure with given name.
const KVSeqCollection * GetDetectors() const
const KVSeqCollection * GetStructures() const
virtual void Add(KVBase *)
KVSeqCollection * GetStructureTypeList(const Char_t *type) const
KVGeoStrucElement * GetStructure(const Char_t *name) const
void ClearStructures(const Char_t *type="")
KVGeoStrucElement * GetParentStructure(const Char_t *type, const Char_t *name="") const
const KVSeqCollection * GetParents() const
Base class for particle reconstruction in one group of a detector array.
static KVGroupReconstructor * Factory(const TString &plugin="")
Group of detectors which can be treated independently of all others in array.
Definition: KVGroup.h:19
void AddTrajectory(KVGeoDNTrajectory *t)
Definition: KVGroup.h:82
void Reset(Option_t *opt="")
Definition: KVGroup.cpp:114
@ kBackwards
Definition: KVGroup.h:33
@ kForwards
Definition: KVGroup.h:32
virtual void SetNumber(UInt_t num)
Definition: KVGroup.h:38
virtual TList * GetDetectorsInLayer(UInt_t lay)
Definition: KVGroup.cpp:88
virtual UInt_t GetNumberOfDetectorLayers()
Definition: KVGroup.cpp:64
void ClearHitDetectors()
Definition: KVGroup.cpp:222
Extended version of ROOT THashList.
Definition: KVHashList.h:28
Base class for particle identification in a 2D map.
Definition: KVIDGraph.h:31
void RemoveIDTelescope(KVBase *t)
Definition: KVIDGraph.h:388
Handles a stock of identification grids to be used by one or more identification telescopes.
KVList * GetGrids()
Bool_t ReadAsciiFile(const Char_t *filename)
const TList * GetLastReadGrids() const
Base class for all detectors or associations of detectors in array which can identify charged particl...
Definition: KVIDTelescope.h:88
virtual Double_t GetIDMapY(Option_t *opt="")
virtual Bool_t IsReadyForID()
void SetGroup(KVGroup *kvg)
KVIDGrid * CalculateDeltaE_EGrid(const KVNumberList &Zrange, Int_t deltaMasse, Int_t npoints, Double_t lifetime=-10, UChar_t massformula=0, Double_t xfactor=1.)
virtual Double_t GetIDMapX(Option_t *opt="")
static KVIDTelescope * MakeIDTelescope(const Char_t *name)
virtual Bool_t SetIdentificationParameters(const KVMultiDetArray *)
void SetIDGrid(KVIDGraph *)
KVDetector * GetDetector(UInt_t n) const
virtual Bool_t CheckTheoreticalIdentificationThreshold(KVNucleus *, Double_t=0.0)
virtual Bool_t CanIdentify(Int_t Z, Int_t)
virtual void AddDetector(KVDetector *d)
const KVList * GetDetectors() const
virtual UShort_t GetIDCode()
virtual void Initialize(void)
virtual void SetIdentificationStatus(KVReconstructedNucleus *)
UInt_t GetSize() const
const KVList * GetListOfIDGrids() const
Extended TList class which owns its objects by default.
Definition: KVList.h:27
Read MFM format acquisition data.
Description of physical materials used to construct detectors; interface to range tables.
Definition: KVMaterial.h:41
virtual void SetThickness(Double_t thick)
Definition: KVMaterial.cpp:354
static KVIonRangeTable * GetRangeTable()
Definition: KVMaterial.cpp:153
Base class for describing the geometry of a detector array.
KVNumberList fAcceptECodes
list of acceptable calibration codes for reconstructed nuclei
virtual KVNameValueList * DetectParticle(KVNucleus *part)
Bool_t IsROOTGeometry() const
bool try_a_singleIDtelescope(TString uri, KVDetector *d, TCollection *l)
virtual KVGroup * GetGroupWithDetector(const Char_t *)
KVSeqCollection * GetListOfIDTelescopes() const
KVUniqueNameList * GetIDTelescopeTypes()
void FillListOfIDTelescopes(KVIDGraph *gr) const
virtual Bool_t handle_raw_data_event_mfmframe_ebyedat(const MFMEbyedatFrame &)
KVNumberList fAcceptIDCodes
list of acceptable identification codes for reconstructed nuclei
virtual void DetectEvent(KVEvent *event, KVReconstructedEvent *rec_event, const Char_t *detection_frame="")
virtual void SetDetectorThicknesses()
virtual void GetDetectorEvent(KVDetectorEvent *detev, const TSeqCollection *fired_params=0)
virtual Bool_t handle_raw_data_event_protobuf(KVProtobufDataReader &)
void MakeHistogramsForAllIDTelescopes(KVSeqCollection *list, Int_t dimension=100)
TList * GetStatusOfIDTelescopes()
int try_all_singleID_telescopes(KVDetector *d, TCollection *l)
virtual void GetIDTelescopesForGroup(KVGroup *grp, TCollection *tel_list)
static Bool_t fCloseGeometryNow
virtual KVGroup * GetGroup(const Char_t *) const
Return pointer to group with name.
const KVSeqCollection * GetACQParams() const
void DeduceIdentificationTelescopesFromGeometry()
unique_ptr< KVFileReader > GetKVFileReader(KVExpDB *db, const Char_t *meth, const Char_t *keyw)
virtual Double_t GetTargetEnergyLossCorrection(KVReconstructedNucleus *)
virtual Bool_t handle_raw_data_event_mfmmergeframe(const MFMMergeFrameManager &)
virtual Bool_t handle_raw_data_event_mfmfile(MFMBufferReader &)
void ReadOoODetectors(KVExpDB *db)
Bool_t fHandledRawData
set to true if multidetector handles data in last call to HandleRawData
KVSeqCollection * GetIDTelescopesWithType(const Char_t *type)
TList * fCalibStatusDets
used by GetStatusIDTelescopes
KVDetectorEvent * fHitGroups
list of hit groups in simulation
virtual UShort_t GetCoherencyIDCode()
KVTarget * GetTarget()
void RecursiveTrajectoryClustering(KVGeoDetectorNode *N, KVUniqueNameList &tried_trajectories, KVUniqueNameList &multitraj_nodes, KVUniqueNameList &detectors_of_group)
KVSeqCollection * fIDTelescopes
deltaE-E telescopes in groups
virtual Int_t FilteredEventCoherencyAnalysis(Int_t round, KVReconstructedEvent *rec_event)
virtual void SetMinimumOKMultiplicity(KVEvent *) const
UInt_t fCurrentRun
Number of the current run used to call SetParameters.
static Bool_t fMakeMultiDetectorSetParameters
void CalculateIdentificationGrids()
For each IDtelescope in array, calculate an identification grid.
virtual void prepare_to_handle_new_raw_data()
reset acquisition parameters etc. before reading new raw data event
virtual UChar_t GetNormalCalibrationCode()
int try_all_doubleID_telescopes(KVDetector *de, KVDetector *e, TCollection *l)
void FillHistogramsForAllIDTelescopes(KVSeqCollection *list)
Fill TH2F histograms for all IDTelescopes of the array.
virtual TGraph * DrawPunchThroughEsurAVsZ(const Char_t *detector, Int_t massform=KVNucleus::kBetaMass)
Bool_t ReadGridsFromAsciiFile(const Char_t *) const
void InitialiseRawDataReading(KVRawDataReader *)
virtual void SetParameters(UInt_t n, Bool_t physics_parameters_only=kFALSE)
KVSeqCollection * fACQParams
list of data acquisition parameters associated to detectors
virtual void SetDetecting(KVDetector *det, Bool_t detecting=kTRUE)
virtual void copy_fired_parameters_to_recon_param_list()
TString GetDataSet() const
virtual void SetPresent(KVDetector *det, Bool_t present=kTRUE)
void CalculateDetectorSegmentationIndex()
virtual void AnalyseGroupAndReconstructEvent(KVReconstructedEvent *recev, KVGroup *grp)
static TGeoHMatrix * GetVolumePositioningMatrix(Double_t distance, Double_t theta, Double_t phi, TGeoTranslation *postTrans=nullptr)
KVGeoNavigator * GetNavigator() const
void DetectParticleIn(const Char_t *detname, KVNucleus *kvp)
KVUpDater * fUpDater
used to set parameters for multidetector
void SetTarget(const Char_t *material, const Float_t thickness)
virtual Int_t GetIDTelescopes(KVDetector *, KVDetector *, TCollection *list)
void SetGeometry(TGeoManager *)
UShort_t GetZminCode()
virtual void MakeCalibrationTables(KVExpDB *)
virtual ~KVMultiDetArray()
destroy (delete) the MDA and all the associated structure, detectors etc.
KVUniqueNameList fFiredACQParams
list of fired acquisition parameters after reading raw data event
virtual void SetRunIdentificationParameters(UShort_t n)
Bool_t HandleRawDataBuffer(MFMBufferReader &)
TString GetFileName(KVExpDB *, const Char_t *meth, const Char_t *keyw)
virtual void Clear(Option_t *opt="")
virtual void CheckStatusOfDetectors(KVDBRun *, const TString &="")
virtual void SetArrayACQParams()
virtual void PerformClosedROOTGeometryOperations()
KVRangeTableGeoNavigator * fNavigator
for propagating particles through array geometry
UInt_t GetCurrentRunNumber() const
void SetDetectorTransparency(Char_t)
Modify the transparency of detector volumes in OpenGL view.
virtual KVGroupReconstructor * GetReconstructorForGroup(const KVGroup *) const
virtual void SetIdentifications()
void RemoveGroup(KVGroup *)
TList * fStatusIDTelescopes
used by GetStatusIDTelescopes
Bool_t fSimMode
=kTRUE in "simulation mode" (use for calculating response to simulated events)
virtual void Build(Int_t run=-1)
virtual void FillDetectorList(KVReconstructedNucleus *rnuc, KVHashList *DetList, const KVString &DetNames)
virtual UShort_t GetBadIDCode()
virtual Bool_t handle_raw_data_event_ebyedat(KVGANILDataReader &)
const TSeqCollection * GetTrajectories() const
virtual void MakeListOfDetectors()
void SetTargetMaterial(const Char_t *material)
static Bool_t fBuildTarget
KVTarget * fTarget
target used in experiment
virtual void set_up_telescope(KVDetector *de, KVDetector *e, KVIDTelescope *idt, TCollection *l)
Set up detectors in de-e identification telescope and add to fIDTelescopes and to l.
TList * GetCalibrationStatusOfDetectors()
void Draw(Option_t *option="")
bool try_upper_and_lower_singleIDtelescope(TString uri, KVDetector *d, TCollection *l)
void ReplaceDetector(const Char_t *name, KVDetector *new_kvd)
virtual Bool_t handle_raw_data_event_mfmframe(const MFMCommonFrame &)
TGeoManager * GetGeometry() const
Return pointer to the (ROOT) geometry of the array.
static KVMultiDetArray * MakeMultiDetector(const Char_t *dataset_name, Int_t run=-1, TString classname="KVMultiDetArray")
virtual void ReconstructEvent(KVReconstructedEvent *, KVDetectorEvent *)
virtual KVGroup * GetGroupWithAngles(Float_t, Float_t)
virtual void SetRawDataFromReconEvent(KVNameValueList &)
virtual TGraph * DrawPunchThroughZVsVpar(const Char_t *detector, Int_t massform=KVNucleus::kBetaMass)
Bool_t HandleRawDataEvent(KVRawDataReader *)
virtual Double_t GetPunchThroughEnergy(const Char_t *detector, Int_t Z, Int_t A)
virtual void InitializeIDTelescopes()
virtual void SetROOTGeometry(Bool_t on=kTRUE)
virtual void RenumberGroups()
virtual void SetRunCalibrationParameters(UShort_t n)
void PrintStatusOfIDTelescopes()
virtual void SetACQParams()
KVACQParam * GetACQParam(const Char_t *name) const
bool try_upper_and_lower_doubleIDtelescope(TString uri, KVDetector *de, KVDetector *e, TCollection *l)
void PrintCalibStatusOfDetectors()
virtual TGraph * DrawPunchThroughEnergyVsZ(const Char_t *detector, Int_t massform=KVNucleus::kBetaMass)
Bool_t fROOTGeometry
=kTRUE use ROOT geometry
void ReadCalibrationFiles(KVExpDB *db)
virtual UShort_t GetMultiHitFirstStageIDCode()
virtual void SetCalibratorParameters(KVDBRun *, const TString &="")
KVNameValueList * DetectParticle_TGEO(KVNucleus *part)
Int_t fFilterType
type of filtering (used by DetectEvent)
virtual void PrepareModifGroup(KVGroup *grp, KVDetector *dd)
virtual void SetPartSeedCond(const Char_t *cond)
virtual void SetGridsInTelescopes(UInt_t run)
KVIDTelescope * GetIDTelescope(const Char_t *name) const
Return pointer to DeltaE-E ID Telescope with "name".
void CalculateReconstructionTrajectories()
KVUniqueNameList fTrajectories
list of all possible trajectories through detectors of array
virtual void SetIDCodeForIDTelescope(KVIDTelescope *) const
virtual void SetReconParametersInEvent(KVReconstructedEvent *) const
Copy any parameters in fReconParameters in to the reconstructed event parameter list.
void AddACQParam(KVACQParam *)
KVNameValueList fReconParameters
general purpose list of parameters for storing information on data reconstruction
TString fDataSet
name of associated dataset, used with MakeMultiDetector()
void AssociateTrajectoriesAndNodes()
void SetTargetThickness(const Float_t thickness)
void ReadCalibFile(const Char_t *filename, KVExpDB *db, KVDBTable *calib_table)
virtual void AcceptParticleForAnalysis(KVReconstructedNucleus *) const
virtual KVTelescope * GetTelescope(const Char_t *name) const
Return pointer to telescope in array with name given by "name".
void SetNavigator(KVGeoNavigator *geo)
KVMultiDetArray()
Default constructor.
KVUpDater * GetUpDater()
void DeduceGroupsFromTrajectories()
virtual void set_up_single_stage_telescope(KVDetector *det, KVIDTelescope *idt, TCollection *l)
Set up detector in single-stage identification telescope and add to fIDTelescopes and to l.
bool try_a_doubleIDtelescope(TString uri, KVDetector *de, KVDetector *e, TCollection *l)
virtual void GetAlignedIDTelescopesForDetector(KVDetector *det, TCollection *list)
virtual void CreateIDTelescopesInGroups()
const KVSeqCollection * GetFiredDataParameters() const
Handles lists of named parameters with different types, a list of KVNamedParameter objects.
Double_t GetDoubleValue(const Char_t *name) const
void SetValue(const Char_t *name, value_type value)
void RemoveParameter(const Char_t *name)
virtual void Clear(Option_t *opt="")
const Char_t * GetNameAt(Int_t idx) const
Int_t GetNpar() const
return the number of stored parameters
Int_t GetEntries() const
const Char_t * GetStringValue(const Char_t *name) const
Bool_t HasParameter(const Char_t *name) const
KVHashList * GetList() const
TString GetTStringValue(const Char_t *name) const
void Copy(TObject &nvl) const
A generic named parameter storing values of different types.
Int_t GetInt() const
Double_t GetDouble() const
Description of properties and kinematics of atomic nuclei.
Definition: KVNucleus.h:125
virtual void Print(Option_t *t="") const
Display nucleus parameters.
Definition: KVNucleus.cpp:758
Int_t GetA() const
Definition: KVNucleus.cpp:799
void SetZ(Int_t z, Char_t mt=-1)
Definition: KVNucleus.cpp:704
void SetZandA(Int_t z, Int_t a)
Set atomic number and mass number.
Definition: KVNucleus.cpp:721
void SetMassFormula(UChar_t mt)
Definition: KVNucleus.h:347
Int_t GetZ() const
Return the number of proton / atomic number.
Definition: KVNucleus.cpp:770
Strings used to represent a set of ranges of values.
Definition: KVNumberList.h:83
Bool_t Contains(Int_t val) const
returns kTRUE if the value 'val' is contained in the ranges defined by the number list
const Char_t * AsString(Int_t maxchars=0) const
void Add(Int_t)
Add value 'n' to the list.
void Set(const TString &l)
Definition: KVNumberList.h:133
Bool_t IsEmpty() const
Definition: KVNumberList.h:173
void SetIsOK(Bool_t flag=kTRUE)
Definition: KVParticle.cpp:333
void SetTheta(Double_t theta)
Definition: KVParticle.h:654
TVector3 * GetPInitial() const
Definition: KVParticle.h:687
void RemoveGroup(const Char_t *groupname)
Definition: KVParticle.cpp:619
void AddGroup(const Char_t *groupname, const Char_t *from="")
Definition: KVParticle.cpp:485
KVNameValueList * GetParameters() const
Definition: KVParticle.h:735
void SetMomentum(const TVector3 &v)
Definition: KVParticle.h:535
Double_t GetEnergy() const
Definition: KVParticle.h:582
Double_t GetE() const
Definition: KVParticle.h:613
void SetE(Double_t a)
Definition: KVParticle.h:555
void SetE0(TVector3 *e=0)
Definition: KVParticle.h:676
Double_t GetKE() const
Definition: KVParticle.h:575
Double_t GetVpar() const
Definition: KVParticle.h:636
KVParticle const * GetFrame(const Char_t *frame, Bool_t warn_and_return_null_if_unknown=kTRUE) const
Definition: KVParticle.cpp:952
Bool_t BelongsToGroup(const Char_t *groupname) const
Definition: KVParticle.cpp:597
Bool_t IsSmallerThan(KVPosition *pos)
kTRUE if "this" is entirely contained within "pos"
Definition: KVPosition.cpp:379
Read Google Protobuf DAQ files.
Wrapper for TRefArray adding some functionality.
Definition: KVRList.h:36
virtual KVBase * FindObject(const Char_t *name, const Char_t *type) const
Definition: KVRList.cpp:106
Propagate particles through array geometry calculating energy losses.
Bool_t CheckIonForRangeTable(Int_t Z, Int_t A)
virtual void PropagateParticle(KVNucleus *, TVector3 *TheOrigin=0)
We start a new track to represent the particle's trajectory through the array.
Abstract base class for reading raw (DAQ) data.
virtual TString GetDataFormat() const =0
Physical event reconstructed from data measured with a detector array using implemented identificatio...
virtual Bool_t AnalyseDetectors(TList *kvtl)
KVReconstructedNucleus * AddParticle()
virtual void SecondaryIdentCalib()
KVReconstructedNucleus * GetNextParticle(Option_t *opt="")
Nuclei reconstructed from data measured by a detector array ,.
virtual void Reconstruct(KVDetector *kvd)
virtual void SetAMeasured(Bool_t yes=kTRUE)
virtual Int_t GetECode() const
static UInt_t GetNUnidentifiedInGroup(KVGroup *grp)
virtual Int_t GetIDCode() const
KVDetector * GetStoppingDetector() const
void SetDetector(int i, KVDetector *);
virtual void GetAnglesFromReconstructionTrajectory(Option_t *opt="random")
virtual void SetZMeasured(Bool_t yes=kTRUE)
KVIDTelescope * GetIdentifyingTelescope() const
static void AnalyseParticlesInGroup(KVGroup *grp)
@ kStatusPileupDE
telescope; a minimum Z could be estimated from the measured energy loss.
void SetIdentifyingTelescope(KVIDTelescope *i)
KaliVeda extensions to ROOT collection classes.
virtual TObject * FindObjectByLabel(const Char_t *) const
virtual void SetOwner(Bool_t enable=kTRUE)
virtual void Clear(Option_t *option="")
virtual TObject * At(Int_t idx) const
KVSeqCollection * GetSubListWithType(const Char_t *retvalue) const
virtual void SetCleanup(Bool_t enable=kTRUE)
virtual void Add(TObject *obj)
KVSeqCollection * GetSubListWithLabel(const Char_t *retvalue) const
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:72
void Begin(TString delim) const
Definition: KVString.cpp:562
Bool_t End() const
Definition: KVString.cpp:625
KVString Next(Bool_t strip_whitespace=kFALSE) const
Definition: KVString.cpp:675
Int_t GetNValues(TString delim) const
Definition: KVString.cpp:859
Calculation/correction of energy losses of particles through an experimental target.
Definition: KVTarget.h:126
virtual void DetectParticle(KVNucleus *, TVector3 *norm=0)
Definition: KVTarget.cpp:485
virtual Double_t GetParticleEIncFromERes(KVNucleus *, TVector3 *norm=0)
Definition: KVTarget.cpp:963
void Clear(Option_t *opt="")
Reset absorber - set energy lost by particles to zero.
Definition: KVTarget.cpp:753
void SetOutgoing(Bool_t r=kTRUE)
Definition: KVTarget.h:237
KVMaterial * GetLayerByIndex(Int_t ilayer) const
Definition: KVTarget.h:173
Associates two detectors placed one behind the other.
Definition: KVTelescope.h:35
Optimised list in which named objects can only be placed once.
virtual void Add(TObject *obj)
Abstract class implementing necessary methods for setting multidetector parameters for each run of th...
Definition: KVUpDater.h:24
virtual void SetParameters(UInt_t, Bool_t physics_parameters_only=kFALSE)
Definition: KVUpDater.cpp:91
static KVUpDater * MakeUpDater(const Char_t *uri, KVMultiDetArray *)
Definition: KVUpDater.cpp:59
virtual void SetCalibrationParameters(UInt_t)
Set calibration parameters for this run.
Definition: KVUpDater.cpp:198
virtual void SetIdentificationParameters(UInt_t)
Definition: KVUpDater.cpp:157
virtual const char * GetName() const
void SetName(const char *name)
virtual Int_t GetEntries() const
virtual void Delete(Option_t *option="")=0
virtual void SetOwner(Bool_t enable=kTRUE)
Bool_t Contains(const char *name) const
virtual Int_t GetSize() const
const char * GetName() const
const char * GetValue() const
virtual const char * GetValue(const char *name, const char *dflt) const
virtual Int_t ReadFile(const char *fname, EEnvLevel level)
Bool_t Defined(const char *name) const
THashList * GetTable() const
void SetStyle(Short_t st)
void SetCurrentCamera(ECameraType camera)
void SetSmoothPoints(Bool_t s)
void SetSmoothLines(Bool_t s)
TGeoVolume * GetTopVolume() const
void ClearTracks()
void SetAngles(Double_t phi, Double_t theta, Double_t psi)
virtual void SetDz(Double_t dz)
void SetTransparency(Char_t transparency=0)
virtual void Draw(Option_t *option="")
virtual void SetPoint(Int_t i, Double_t x, Double_t y)
virtual void SetName(const char *name="")
virtual void SetTitle(const char *title="")
virtual void Sort(Bool_t(*greater)(const TGraph *, Int_t, Int_t)=&TGraph::CompareX, Bool_t ascending=kTRUE, Int_t low=0, Int_t high=-1111)
virtual Int_t Fill(const char *name, Double_t w)
TObject * Next()
void Reset()
virtual void Add(TObject *obj)
virtual TObject * FindObject(const char *name) const
virtual TObject * At(Int_t idx) const
virtual void Delete(Option_t *option="")
virtual TObject * First() const
virtual const char * GetName() const
virtual void SetTitle(const char *title="")
virtual const char * GetTitle() const
virtual void SetName(const char *name)
virtual TObject * Clone(const char *newname="") const
void AbstractMethod(const char *method) const
virtual void Clear(Option_t *="")
virtual const char * GetName() const
void SetBit(UInt_t f)
R__ALWAYS_INLINE Bool_t TestBit(UInt_t f) 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
virtual void ls(Option_t *option="") const
virtual void Info(const char *method, const char *msgfmt,...) const
const char * GetClass() const
Longptr_t ExecPlugin(int nargs, const T &... params)
Int_t GetEntries() const
virtual TObject * RemoveAt(Int_t idx)
Double_t Atof() const
void ToUpper()
TObjArray * Tokenize(const TString &delim) const
Bool_t BeginsWith(const char *s, ECaseCompare cmp=kExact) const
const char * Data() const
TString & Prepend(char c, Ssiz_t rep=1)
void Form(const char *fmt,...)
TString & Remove(EStripType s, char c)
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
TString & ReplaceAll(const char *s1, const char *s2)
const Int_t n
TGraphErrors * gr
TH1 * h
const long double g
masses
Definition: KVUnits.h:72
Int_t Nint(T x)
Double_t Max(Double_t a, Double_t b)
auto * l