KaliVeda
Toolkit for HIC analysis
KVMultiDetArray.cpp
1 //Created by KVClassFactory on Tue Apr 16 09:45:50 2013
2 //Author: John Frankland,,,
3 
4 #include "KVMultiDetArray.h"
5 #include "KVDetector.h"
6 #include "KVDetectorEvent.h"
7 #include "KVReconstructedEvent.h"
8 #include "KVReconstructedNucleus.h"
9 #include "KVRList.h"
10 #include "KVTemplateEvent.h"
11 #include "KVNucleus.h"
12 #include "KVGroup.h"
13 #include "KVTelescope.h"
14 #include "KVMaterial.h"
15 #include "KVTarget.h"
16 #include "KVIDTelescope.h"
17 #include <KVString.h>
18 #include <TObjString.h>
19 #include <TObjArray.h>
20 #include <KVIDGridManager.h>
21 #include <KVDataSetManager.h>
22 #include <KVUpDater.h>
23 #include "TPluginManager.h"
24 #include "KVDataSet.h"
25 #include "TGeoManager.h"
26 #include "KVHashList.h"
27 #include "KVNameValueList.h"
28 #include "KVUniqueNameList.h"
29 #include "KVIonRangeTable.h"
30 #include "KVRangeTableGeoNavigator.h"
31 #include <KVDataAnalyser.h>
32 #include <KVNamedParameter.h>
33 #include <KVCalibrator.h>
34 #include <KVDBParameterSet.h>
35 #ifdef WITH_RSQLITE
36 #include <KVSQLROOTIDGridManager.h>
37 #endif
38 #ifdef WITH_OPENGL
39 #include <TGLViewer.h>
40 #include <TVirtualPad.h>
41 #endif
42 #ifdef WITH_BUILTIN_GRU
43 #include "KVGANILDataReader.h"
44 #else
45 #include "KVRawDataReader.h"
46 #endif
47 #ifdef WITH_MFM
48 #include "KVMFMDataFileReader.h"
49 #include "MFMEbyedatFrame.h"
50 #endif
51 #ifdef WITH_PROTOBUF
52 #include "KVProtobufDataReader.h"
53 #endif
54 using namespace std;
55 
56 KVMultiDetArray* gMultiDetArray = nullptr;
57 
63 
65 
66 
67 
71  : KVGeoStrucElement(), fTrajectories(kTRUE)
72 {
73  // Default constructor
74  init();
75  gMultiDetArray = this;
76 }
77 
78 
79 
82 
84  : KVGeoStrucElement(name, type), fTrajectories(kTRUE)
85 {
86  // Constructor with name and optional type
87  init();
88  gMultiDetArray = this;
89 }
90 
91 
92 
104 
106 {
107  //Basic initialisation called by constructor.
108  //Creates detectors list fDetectors,
109  //groups list fGroups, identification telescopes list
110  //fIDTelescopes
111  //
112  //The fGroups & fIDTelescopes lists contain objects owned by the multidetector array,
113  //but which may be deleted by other objects (or as a result of the deletion of other
114  //objects: i.e. if all the detectors in a group are deleted, the group itself is destroyed).
115  //We use the ROOT automatic garbage collection to make sure that any object deleted
116  //elsewhere is removed automatically from these lists.
117 
118  fIDTelescopes = new KVHashList();
119  fIDTelescopes->SetOwner(kTRUE); // owns its objects
121 
122  fHitGroups = 0;
123 
124  fTarget = 0;
125  fCurrentRun = 0;
126 
128  fCalibStatusDets = 0;
129  fSimMode = kFALSE;
130 
131  fROOTGeometry = gEnv->GetValue("KVMultiDetArray.ROOTGeometry", kTRUE);
133 
134  fNavigator = 0;
135  fUpDater = 0;
136 
137  if (!gIDGridManager) new KVIDGridManager;
138 
139  // all trajectories belong to us
141 
142  //all detectors belong to us
144 
145  fRawDataReader = nullptr;
146  fHandledRawData = false;
147 
148  // any extra raw data signals created when reading data belong to us
150 }
151 
152 
153 
156 
158 {
159  //destroy (delete) the MDA and all the associated structure, detectors etc.
160 
162  //destroy all identification telescopes
165  delete fIDTelescopes;
166  }
167  fIDTelescopes = 0;
168 
169  if (gMultiDetArray == this)
170  gMultiDetArray = nullptr;
171 
172  if (fStatusIDTelescopes) {
174  delete fStatusIDTelescopes;
176  }
177  if (fCalibStatusDets) {
179  delete fCalibStatusDets;
180  fCalibStatusDets = 0;
181  }
182 
183  if (fNavigator) {
184  if (gGeoManager) {
185  delete gGeoManager;
186  gGeoManager = nullptr;
187  }
188  delete fNavigator;
189  fNavigator = nullptr;
190  }
192 }
193 
194 
195 
196 
197 
199 
201 {
202 
203 
204 
205 }
206 
207 
208 
209 
231 
233 {
234  // Create one or more KVIDTelescope particle-identification objects from the two detectors
235  //
236  // The different ID telescopes are defined as 'Plugin' objects in the file $KVROOT/KVFiles/.kvrootrc :
237  // # The KVMultiDetArray::GetIDTelescopes(KVDetector*de, KVDetector*e) method uses these plugins to
238  // # create KVIDTelescope instances adapted to the specific array geometry and detector types.
239  // # For each pair of detectors we look for a plugin with one of the following names:
240  // # [name_of_dataset].array_name.de_detector_type[de detector thickness]-e_detector_type[de detector thickness]
241  // # Each characteristic in [] brackets may or may not be present in the name; first we test for names
242  // # with these characteristics, then all combinations where one or other of the characteristics is not present.
243  // # In addition, we first test all combinations which begin with [name_of_dataset].
244  // # The first plugin found in this order will be used.
245  // # In addition, if for one of the two detectors there is a plugin called
246  // # [name_of_dataset].array_name.de_detector_type[de detector thickness]
247  // # [name_of_dataset].array_name.e_detector_type[e detector thickness]
248  // # then we add also an instance of this 1-detector identification telescope.
249  //
250  // This method is called by DeduceIdentificationTelescopesFromGeometry
251  // in order to set up all ID telescopes of the array.
252  //
253  // Returns number of ID telescopes created
254 
255  Int_t ntels = 0;
256  // if both detectors are not OK then stop
257  if (!de->IsOK() && !e->IsOK()) return ntels;
258 
259  if (fDataSet == "" && gDataSet) fDataSet = gDataSet->GetName();
260 
261  //look for ID telescopes starting from furthest from target
262  if (e->IsOK()) ntels += try_all_singleID_telescopes(e, list);
263  if (de != e) {
264  if (e->IsOK() && de->IsOK()) ntels += try_all_doubleID_telescopes(de, e, list);
265  if (de->IsOK()) ntels += try_all_singleID_telescopes(de, list);
266  }
267 
268  return ntels;
269 }
270 
271 
272 
290 
292 {
293  // Attempt to find a plugin KVIDTelescope class for making a single-detector
294  // ID telescope from detector *d
295  // We look for plugins with the following signatures (uri):
296  //
297  // [array name].[type]
298  // [array_name].[type][thickness]
299  //
300  // where 'type' is the type of the detector in UPPER or lowercase letters
301  // 'thickness' is the nearest-integer thickness of the detector as returned by d->GetThickness()
302  // In addition, if a dataset is set (gDataSet!=nullptr) we try also for dataset-specific
303  // plugins:
304  //
305  // [dataset].[array name].[type]
306  // [dataset].[array name].[type][thickness]
307  //
308  // Returns number of generated telescopes
309 
310  TString uri = Form("%s.%s", GetName(), d->GetType());
311  Int_t ntels = 0;
312  if (!(ntels += try_upper_and_lower_singleIDtelescope(uri, d, l))) {
313  Int_t d_thick = TMath::Nint(d->GetThickness());
314  uri += d_thick;
315  ntels += try_upper_and_lower_singleIDtelescope(uri, d, l);
316  }
317  return ntels;
318 }
319 
320 
321 
322 
345 
347 {
348  // Attempt to find a plugin KVIDTelescope class for making an ID telescope from detectors de & e.
349  // We look for plugins with the following signatures (uri):
350  //
351  // [array name].[de-type]-[e-type]
352  // [array name].[de-type][thickness]-[e-type]
353  // [array name].[de-type]-[e-type][thickness]
354  // [array name].[de-type][thickness]-[e-type][thickness]
355  //
356  // where 'type' is the type of the detector in UPPER or lowercase letters
357  // 'thickness' is the nearest-integer thickness of the detector.
358  // In addition, if a dataset is set (gDataSet!=nullptr) we try also for dataset-specific
359  // plugins:
360  //
361  // [dataset].[array name].[de-type][thickness]-[e-type][thickness]
362  // [dataset].[array name].[de-type][thickness]-[e-type]
363  // [dataset].[array name].[de-type]-[e-type][thickness]
364  // [dataset].[array name].[de-type]-[e-type]
365  //
366  // if no plugin is found, we return a KVIDTelescope base class object
367  //
368  // Returns 1 (we always generate exactly one telescope)
369 
370  TString de_type = de->GetType();
371  TString e_type = e->GetType();
372  TString de_thick = Form("%d", TMath::Nint(de->GetThickness()));
373  TString e_thick = Form("%d", TMath::Nint(e->GetThickness()));
374 
375  TString uri = de_type + de_thick + "-" + e_type + e_thick;
376  uri.Prepend(Form("%s.", GetName()));
377  if (try_upper_and_lower_doubleIDtelescope(uri, de, e, l)) return 1;
378 
379  uri = de_type + de_thick + "-" + e_type;
380  uri.Prepend(Form("%s.", GetName()));
381  if (try_upper_and_lower_doubleIDtelescope(uri, de, e, l)) return 1;
382 
383  uri = de_type + "-" + e_type + e_thick;
384  uri.Prepend(Form("%s.", GetName()));
385  if (try_upper_and_lower_doubleIDtelescope(uri, de, e, l)) return 1;
386 
387  uri = de_type + "-" + e_type;
388  uri.Prepend(Form("%s.", GetName()));
389  if (try_upper_and_lower_doubleIDtelescope(uri, de, e, l)) return 1;
390 
391  // default id telescope object
392  KVIDTelescope* idt = new KVIDTelescope;
393  uri = de_type + "-" + e_type;
394  idt->SetLabel(uri);
395  // set type as "[DEtype]-[Etype]" where "[*type]" is type of DE/E detectors
396  idt->SetType(Form("%s-%s", de_type.Data(), e_type.Data()));
397  set_up_telescope(de, e, idt, l);
398 
399  return 1;
400 }
401 
402 
403 
411 
413 {
414  // Attempt to find a plugin KVIDTelescope class for making a single-detector
415  // ID telescope from detector *d with the given signature/uri
416  // Both original & all-upper-case versions of uri are tried.
417  // uri is tried both with & without prepended dataset name (if set)
418  // Returns true if successful (the new ID telescope will be added to internal
419  // list fIDTelescopes and also to TCollection* l)
420 
421  if (try_a_singleIDtelescope(uri, d, l)) return true;
422  uri.ToUpper();
423  return try_a_singleIDtelescope(uri, d, l);
424 }
425 
426 
427 
434 
436 {
437  // Attempt to find a plugin KVIDTelescope class for making an ID telescope 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_doubleIDtelescope(uri, de, e, l)) return true;
444  uri.ToUpper();
445  return try_a_doubleIDtelescope(uri, de, e, l);
446 }
447 
448 
449 
458 
460 {
461  // Attempt to find a plugin KVIDTelescope class for making a single-detector
462  // ID telescope from detector *d with the given signature/uri
463  // Both original & all-upper-case versions of uri are tried.
464  // uri is tried both with & without prepended dataset name (if set)
465  // Returns true if successful (the new ID telescope will be added to internal
466  // list fIDTelescopes and also to TCollection* l)
467 
468  // dataset-specific version takes precedence over default
469  TString duri = uri;
470  if (gDataSet) {
471  // try with dataset name
472  duri.Prepend(Form("%s.", fDataSet.Data()));
473  KVIDTelescope* idt;
474  if ((idt = KVIDTelescope::MakeIDTelescope(duri))) {
476  return true;
477  }
478  }
479 
480  // look for default version
481  KVIDTelescope* idt;
482  if ((idt = KVIDTelescope::MakeIDTelescope(uri))) {
484  return true;
485  }
486 
487  return false;
488 }
489 
490 
491 
498 
500 {
501  // Attempt to find a plugin KVIDTelescope class for making an ID telescope with the given signature/uri
502  // uri is tried both with & without prepended dataset name (if set)
503  // Returns true if successful (the new ID telescope will be added to internal
504  // list fIDTelescopes and also to TCollection* l)
505 
506  // dataset-specific version takes precedence over default
507  TString duri = uri;
508  if (gDataSet) {
509  // try with dataset name
510  duri.Prepend(Form("%s.", fDataSet.Data()));
511  KVIDTelescope* idt;
512  if ((idt = KVIDTelescope::MakeIDTelescope(duri))) {
513  set_up_telescope(de, e, idt, l);
514  return true;
515  }
516  }
517  // look for default version
518  KVIDTelescope* idt;
519  if ((idt = KVIDTelescope::MakeIDTelescope(uri))) {
520  set_up_telescope(de, e, idt, l);
521  return true;
522  }
523 
524  return false;
525 }
526 
527 
528 
531 
533 {
534  // Set up detectors in de-e identification telescope and add to fIDTelescopes and to l
535 
536  idt->AddDetector(de);
537  idt->AddDetector(e);
538  if (de->GetGroup()) {
539  idt->SetGroup(de->GetGroup());
540  }
541  else {
542  idt->SetGroup(e->GetGroup());
543  }
544  // if telescope already exists, we delete this new version and add a reference to
545  // the original into list l
547  if (p) {
548  l->Add(p);
549  delete idt;
550  }
551  else {
552  fIDTelescopes->Add(idt);
553  l->Add(idt);
554  }
555 }
556 
557 
558 
561 
563 {
564  // Set up detector in single-stage identification telescope and add to fIDTelescopes and to l
565 
566  idt->AddDetector(det);
567  idt->SetGroup(det->GetGroup());
568  // if telescope already exists, we delete this new version and add a reference to
569  // the original into list l
571  if (p) {
572  l->Add(p);
573  delete idt;
574  }
575  else {
576  fIDTelescopes->Add(idt);
577  l->Add(idt);
578  }
579 }
580 
581 
583 
585 {
586  fIDTelescopes->Delete(); // clear out (delete) old identification telescopes
587  KVGroup* grp;
588  unique_ptr<KVSeqCollection> fGroups(GetStructures()->GetSubListWithType("GROUP"));
589  TIter ngrp(fGroups.get());
590  while ((grp = (KVGroup*) ngrp())) {
592  }
593 }
594 
595 
596 
597 
601 
603 {
604  //Number groups according to position in list fGroups and set fGr counter to the number
605  //of groups in the list
606  Int_t fGr = 0;
607  KVGroup* g = 0;
608  KVSeqCollection* fGroups = GetStructures()->GetSubListWithType("GROUP");
609  TIter next(fGroups);
610  while ((g = (KVGroup*) next())) {
611  g->SetNumber(++fGr);
612  }
613  delete fGroups;
614 }
615 
616 
617 
618 
624 
626 {
627  // Perform multi-hit and coherency analysis of filtered event.
628  // round=1,2,... depending on number of times method has been called
629  // Returns number of particles whose status were changed.
630  // When this becomes zero, the coherency analysis is finished
631 
632  Int_t nchanged = 0;
633  KVReconstructedNucleus* recon_nuc;
634 
635  while ((recon_nuc = rec_event->GetNextParticle())) {
636  if (!recon_nuc->IsIdentified()) {
637  int dethits = recon_nuc->GetStoppingDetector()->GetHits()->GetEntries() ;
639  Bool_t pileup = kFALSE;
640  if (dethits > 1) {
641  // if any of the other particles also stopped in the same detector, we assume identification
642  // will be so false as to reject particle
643  for (int j = 0; j < dethits; j++) {
645  if (n != recon_nuc && n->GetStoppingDetector() == recon_nuc->GetStoppingDetector()) pileup = kTRUE;
646  }
647  }
648  if (pileup) {
649  nchanged++;
650  recon_nuc->SetIsIdentified();//to stop looking anymore & to allow identification of other particles in same group
651  if (idtelstop) recon_nuc->SetIDCode(GetBadIDCode());// idtelstop->SetIDCode(recon_nuc, idtelstop->GetBadIDCode());
652  else recon_nuc->SetIsOK(kFALSE);
653  }
654  else if (recon_nuc->GetStatus() == 3) {
655  //stopped in first member
656  recon_nuc->SetIsIdentified();
657  nchanged++;
658  }
659  else if (recon_nuc->GetStatus() == 2) {
660  // pile-up in first stage of telescopes
661  recon_nuc->SetIsIdentified();
662  if (idtelstop && idtelstop->IsReadyForID()) recon_nuc->SetIDCode(GetMultiHitFirstStageIDCode());//idtelstop->SetIDCode(recon_nuc, idtelstop->GetMultiHitFirstStageIDCode());
663  else recon_nuc->SetIsOK(kFALSE);
664  nchanged++;
665  }
666  else if (recon_nuc->GetStatus() == 0) {
667  // try to "identify" the particle
669  idtelstop = (KVIDTelescope*)nxtidt();
670  while (idtelstop) {
671  if (idtelstop->IsReadyForID() && idtelstop->CanIdentify(recon_nuc->GetZ(), recon_nuc->GetA())
672  && idtelstop->CheckTheoreticalIdentificationThreshold(recon_nuc)) { // make sure we are above identification threshold
673  nchanged++;
674  // if this is not the first round, this particle has been 'identified' after
675  // dealing with other particles in the group
676  if (round > 1) recon_nuc->SetIDCode(GetCoherencyIDCode());//idtelstop->SetIDCode(recon_nuc, idtelstop->GetCoherencyIDCode());
677  recon_nuc->SetIsIdentified();
678  recon_nuc->SetIsCalibrated();
679  idtelstop->SetIdentificationStatus(recon_nuc);
680  break;
681  }
682  else {
683  Int_t nseg = recon_nuc->GetNSegDet();
684  recon_nuc->SetNSegDet(TMath::Max(nseg - 1, 0));
685  //if there are other unidentified particles in the group and NSegDet is < 2
686  //then exact status depends on segmentation of the other particles : reanalyse
687  if (recon_nuc->GetNSegDet() < 2 &&
689  nchanged++;
690  break;
691  }
692  //if NSegDet = 0 it's hopeless
693  if (!recon_nuc->GetNSegDet()) {
694  nchanged++;
695  break;
696  }
697  }
698  idtelstop = (KVIDTelescope*)nxtidt();
699  }
700  }
701  }
702  }
703  return nchanged;
704 }
705 
706 
707 
793 
794 void KVMultiDetArray::DetectEvent(KVEvent* event, KVReconstructedEvent* rec_event, const Char_t* detection_frame)
795 {
796  //Simulate detection of event by multidetector array.
797  //
798  // optional argument detection_frame(="" by default) can be used to give name of
799  // inertial reference frame (defined for all particles of 'event') to be used.
800  // e.g. if the simulated event's default reference frame is the centre of mass frame, before calling this method
801  // you should create the 'laboratory' or 'detector' frame with KVEvent::SetFrame(...), and then give the
802  // name of the 'LAB' or 'DET' frame as 3rd argument here.
803  //
804  //For each particle in the event we calculate first its energy loss in the target (if the target has been defined, see KVMultiDetArray::SetTarget).
805  //By default these energy losses are calculated from a point half-way along the beam-direction through the target (taking into account the orientation
806  //of the target), if you want random depths for each event call GetTarget()->SetRandomized() before using DetectEvent().
807  //
808  //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
809  //different members of the group is simulated. The actual geometry and algorithms used to calculate the particle's trajectory depend on the
810  //value of fROOTGeometry (modify with SetROOTGeometry(kTRUE/kFALSE):
811  // if kTRUE: we use the ROOT TGeo description of the array generated by CreateGeoManager(). In this case, CreateGeoManager()
812  // must be called once in order to set up the geometry.
813  // if kFALSE: we use the simplistic KaliVeda geometry, i.e. detectors are only defined by min/max polar & azimuthal angles.
814  //
815  //The detectors concerned have their fEloss members set to the energy lost by the particle when it crosses them.
816  //
817  //Give tags to the simulated particles via KVNucleus::AddGroup() method
818  //Two general tags :
819  // - DETECTED : cross at least one active layer of one detector
820  // - UNDETECTED : go through dead zone or stopped in target
821  //We add also different sub group :
822  // - For UNDETECTED particles : "NO HIT", "NEUTRON", "DEAD ZONE", "STOPPED IN TARGET" and "THRESHOLD", the last one concerned particle
823  //go through the first detection stage of the multidetector array but stopped in an absorber (ie an inactive layer)
824  // - For DETECTED particles :
825  // "PUNCH THROUGH" corrresponds to particle which cross all the materials in front of it
826  // (high energy particle punh through), or which miss some detectors due to a non perfect
827  // overlap between defined telescope,
828  // "INCOMPLETE" corresponds to particles which stopped in the first detection stage of the multidetector
829  // in a detector which can not give alone a clear identification,
830  // this correponds to status=3 or idcode=5 in INDRA data
831  //
832  //After the filtered process, a reconstructed event are obtain from the fired groups corresponding
833  //to detection group where at least one detector havec an active layer energy loss greater than zero
834  //this reconstructed event are available for the user in the KVReconstructedEvent* rec_event argument
835  //This pointer is cleared and also the multidet array at the beginning of the method
836  //
837  //INFO to the user :
838  // - at this point the different PILE-UP, several particles going through same telescope, detector
839  // are only taken into account for filter type KVMultiDetArray::kFilterType_Full
840  // - specific cases correponding specific multi detectors are to be implemented in the child class
841  //
842  // === FILTER TYPES ===
843  // Use gMultiDetArray->SetFilterType(...) with one of the following values:
844  // KVMultiDetArray::kFilterType_Geo geometric filter only, particles are kept if they hit detector in the array
845  // energy losses are not calculated, particle energies are irrelevant
846  // KVMultiDetArray::kFilterType_GeoThresh particles are kept if they have enough energy to leave the target,
847  // and enough energy to cross at least one detector of the array
848  // ---> for these two cases, accepted particles are copied into the 'reconstructed' event with their
849  // original simulated energy, charge and mass, although angles are randomized to reflect detector granularity
850  //
851  // KVMultiDetArray::kFilterType_Full full simulation of detection of particles by the array. the calibration parameters
852  // for the chosen run (call to gMultiDetArray->SetParameters(...)) are inverted in order
853  // to calculate pseudo-raw data from the calculated energy losses. the resulting pseudo-raw
854  //
855  // SIMULATED EVENT PARAMETERS
856  // ==========================
857  // The event given as input to the method may contain extra information in its parameter
858  // list concerning the simulation. The parameter list of the event is copied into that of the
859  // reconstructed event, therefore these informations can be accessed from the reconstructed
860  // event using the method
861  // rec_event->GetParameters()
862  //
863  // SIMULATED PARTICLE PARAMETERS
864  // ==========================
865  // For filter types KVMultiDetArray::kFilterType_Geo and KVMultiDetArray::kFilterType_GeoThresh,
866  // for which there is a 1-to-1 correspondance between simulated and reconstructed particles,
867  // we copy the list of parameters associated to each input particle into the output particle.
868  // Note that this list contains full informations on the detection of each particle
869  // (see Users Guide chapter on Filtering)
870  //
871  // TRACKING (only with ROOT geometries)
872  // ====================================
873  // You can visualise the trajectories of particles for individual events in the 3D OpenGL viewer.
874  // To enable this:
875  // gMultiDetArray->GetNavigator()->SetTracking(kTRUE)
876  // Then you can do:
877  // gMultiDetArray->DetectEvent(...)
878  // gMultiDetArray->Draw("tracks")
879  // The geometry of the array with the tracks overlaid will be displayed.
880 
881  if (!event) {
882  Error("DetectEvent", "the KVEvent object pointer has to be valid");
883  return;
884  }
885  if (!rec_event) {
886  Error("DetectEvent", "the KVReconstructedEvent object pointer has to be valid");
887  return;
888  }
889 
890  if (IsROOTGeometry()) {
891  if (!gGeoManager) {
892  Error("DetectEvent", "ROOT geometry is requested, but has not been set: gGeoManager=0x0");
893  return;
894  }
895  if (!fNavigator) {
896  Error("DetectEvent", "Using ROOT geometry, but no navigator exists");
897  return;
898  }
899  if (fNavigator->IsTracking()) {
900  // clear any tracks created by last event
903  }
904  }
905 
906  //Clear the KVReconstructed pointer before a new filter process
907  rec_event->Clear();
908  //Copy any parameters associated with simulated event into the reconstructed event
909  event->GetParameters()->Copy(*(rec_event->GetParameters()));
910  if (!fHitGroups) {
911  //Create the list where fired groups will be stored
912  //for reconstruction
914  }
915  else {
916  //Clear the multidetector before a new filter process
917  fHitGroups->Clear();
918  }
919 
920  // iterate through list of particles
921  KVNucleus* part, *_part;
922  KVNameValueList det_stat;
923  KVNameValueList* nvl = 0;
924  KVNameValueList un;
925 
926  Int_t part_index = 0; //index of particle in event
927  while ((part = event->GetNextNucleus())) { // loop over particles
928  ++part_index;
929  TList* lidtel = 0;
930 
931 #ifdef KV_DEBUG
932  cout << "DetectEvent(): looking at particle---->" << endl;
933  part->Print();
934 #endif
935  if (strcmp(detection_frame, "")) _part = (KVNucleus*)part->GetFrame(detection_frame);
936  else _part = (KVNucleus*)part;
937  _part->SetE0();
938  det_stat.Clear();
939  Double_t eLostInTarget = 0;
940  KVDetector* last_det = 0;
941 
942  if (part->GetZ() && !fNavigator->CheckIonForRangeTable(part->GetZ(), part->GetA())) {
943  // ignore charged particles which range table cannot handle
944  det_stat.SetValue("UNDETECTED", Form("Z=%d", part->GetZ()));
945 
946  part->AddGroup("UNDETECTED");
947  part->AddGroup("SUPERHEAVY");
948  }
949  else if (!fNavigator->IsTracking() && (part->GetZ() == 0)) {
950  // when tracking is activated, we follow neutron trajectories
951  // if not, we don't even bother trying
952  det_stat.SetValue("UNDETECTED", "NEUTRON");
953 
954  part->AddGroup("UNDETECTED");
955  part->AddGroup("NEUTRON");
956  }
957  else if (_part->GetKE() < 1.e-3) {
958  det_stat.SetValue("UNDETECTED", "NO ENERGY");
959 
960  part->AddGroup("UNDETECTED");
961  part->AddGroup("NO ENERGY");
962  }
963  else {
964 
965  //Double_t eLostInTarget=0;
966  if (fTarget && part->GetZ()) {
968  //simulate passage through target material
969  Double_t ebef = _part->GetKE();
971  eLostInTarget = ebef - _part->GetKE();
972  if (_part->GetKE() < 1.e-3) {
973  det_stat.SetValue("UNDETECTED", "STOPPED IN TARGET");
974 
975  part->AddGroup("UNDETECTED");
976  part->AddGroup("STOPPED IN TARGET");
977  }
979  }
980 
981  if ((fFilterType != kFilterType_Geo) && _part->GetKE() < 1.e-3) {
982  // unless we are doing a simple geometric filter, particles which
983  // do not have the energy to leave the target are not detected
984  }
985  else {
986  if (!(nvl = DetectParticle(_part))) {
987  if (part->GetZ() == 0) {
988  // tracking
989  det_stat.SetValue("UNDETECTED", "NEUTRON");
990 
991  part->AddGroup("UNDETECTED");
992  part->AddGroup("NEUTRON");
993  }
994  else {
995  det_stat.SetValue("UNDETECTED", "NO HIT");
996 
997  part->AddGroup("UNDETECTED");
998  part->AddGroup("NO HIT");
999  }
1000 
1001  }
1002  else if (nvl->GetNpar() == 0) {
1003 
1004  if (part->GetZ() == 0) {
1005  // tracking
1006  det_stat.SetValue("UNDETECTED", "NEUTRON");
1007 
1008  part->AddGroup("UNDETECTED");
1009  part->AddGroup("NEUTRON");
1010  }
1011  else {
1012  part->AddGroup("UNDETECTED");
1013  part->AddGroup("DEAD ZONE");
1014 
1015  det_stat.SetValue("UNDETECTED", "DEAD ZONE");
1016  }
1017  delete nvl;
1018  nvl = 0;
1019  }
1020  else {
1021  Int_t nbre_nvl = nvl->GetNpar();
1022  KVString LastDet(nvl->GetNameAt(nbre_nvl - 1));
1023  last_det = GetDetector(LastDet.Data());
1024  TList* ldet = last_det->GetAlignedDetectors();
1025  TIter it1(ldet);
1026 
1027  Int_t ntrav = 0;
1028  KVDetector* dd = 0;
1029  if (!IsROOTGeometry()) {
1030  //Test de la trajectoire coherente
1031  while ((dd = (KVDetector*)it1.Next())) {
1032  if (dd->GetHits()) {
1033  if (dd->GetHits()->FindObject(_part))
1034  ntrav += 1;
1035  else if (dd->IsSmallerThan(last_det))
1036  ntrav += 1;
1037  }
1038  else {
1039  if (dd->IsSmallerThan(last_det))
1040  ntrav += 1;
1041  }
1042  }
1043  }
1044  else {
1045  ntrav = ldet->GetEntries();
1046  }
1047 
1048  if (ntrav != ldet->GetEntries()) {
1049 
1050  // la particule a une trajectoire
1051  // incoherente, elle a loupe un detecteur avec une ouverture
1052  // plus large que ceux a la suite ou la particule est passe
1053  // (ceci peut etre du a un pb de definition de zone morte autour de certains detecteur)
1054  //
1055  // on retire la particule sur tout les detecteurs
1056  // ou elle est enregistree et on retire egalement
1057  // sa contribution en energie
1058  //
1059  // on assimile en fait ces particules a
1060  // des particules arretes dans les zones mortes
1061  // non detectees
1062  it1.Reset();
1063  //Warning("DetectEvent","trajectoire incoherente ...");
1064  while ((dd = (KVDetector*)it1.Next()))
1065  if (dd->GetHits() && dd->GetHits()->FindObject(_part)) {
1066  if (nvl->HasParameter(dd->GetName())) {
1067  Double_t el = dd->GetEnergy();
1068  el -= nvl->GetDoubleValue(dd->GetName());
1069  dd->SetEnergyLoss(el);
1070  if (dd->GetNHits() == 1)
1071  dd->SetEnergyLoss(0);
1072  }
1073  dd->GetHits()->Remove(_part);
1074  }
1075  det_stat.SetValue("UNDETECTED", "GEOMETRY INCOHERENCY");
1076 
1077  part->AddGroup("UNDETECTED");
1078  part->AddGroup("GEOMETRY INCOHERENCY");
1079  }
1080  else {
1081 
1082  //On recupere les telescopes d identification
1083  //associe au dernier detecteur touche
1084  lidtel = last_det->GetTelescopesForIdentification();
1085  if (lidtel->GetEntries() == 0 && last_det->GetEnergy() <= 0) {
1086  //Arret dans un absorbeur
1087  det_stat.SetValue("UNDETECTED", "THRESHOLD");
1088 
1089  part->AddGroup("UNDETECTED");
1090  part->AddGroup("THRESHOLD");
1091 
1092  //On retire la particule du detecteur considere
1093  //
1094  last_det->GetHits()->Remove(_part);
1095  //Warning("DetectEvent","threshold ...");
1096  }
1097  else {
1098  part->AddGroup("DETECTED");
1099  det_stat.SetValue("DETECTED", "OK");
1100  fHitGroups->AddGroup(last_det->GetGroup());
1101 
1102  if (lidtel->GetEntries() > 0) {
1103  //Il y a possibilite d identification
1104  }
1105  else if (last_det->GetEnergy() > 0) {
1106  //Il n'y a pas de possibilite d'identification
1107  //arret dans le premier etage de detection
1108  det_stat.SetValue("DETECTED", "INCOMPLETE");
1109  part->AddGroup("INCOMPLETE");
1110  }
1111  else {
1112  Warning("DetectEvent", "Cas non prevu ....");
1113  printf("last_det->GetName()=%s, lidtel->GetEntries()=%d, last_det->GetEnergy()=%lf\n",
1114  last_det->GetName(),
1115  lidtel->GetEntries(),
1116  last_det->GetEnergy()
1117  );
1118  }
1119 
1120  //Test d'une energie residuelle non nulle
1121  //La particule n a pas ete arrete par le detecteur
1122  if (_part->GetKE() > 1.e-3) {
1123  //Pour ces deux cas
1124  //on a une information incomplete
1125  //pour la particule
1126  if (nbre_nvl != Int_t(last_det->GetGroup()->GetNumberOfDetectorLayers())) {
1127  //----
1128  // Fuite,
1129  // la particule a loupe des detecteurs normalement aligne
1130  // avec le dernier par laquelle elle est passee
1131  // (ceci peut etre du a un pb de definition de la geometrie)
1132  part->RemoveGroup("DETECTED");
1133  det_stat.RemoveParameter("DETECTED");
1134 
1135  det_stat.SetValue("UNDETECTED", "GEOMETRY INCOHERENCY");
1136  part->AddGroup("UNDETECTED");
1137  part->AddGroup("GEOMETRY INCOHERENCY");
1138  //Warning("DetectEvent","Fuite ......");
1139  }
1140  else if (nbre_nvl) {
1141  //----
1142  // Punch Through,
1143  // La particule est trop energetique, elle a traversee
1144  // tout l'appareillage de detection
1145  //Warning("DetectEvent","Punch Through ......");
1146  part->AddGroup("PUNCH THROUGH");
1147  det_stat.SetValue("DETECTED", "PUNCH THROUGH");
1148  //Warning("DetectEvent","Punch Through ......");
1149  }
1150  } //fin du cas ou la particule avait encore de l energie apres avoir traverser l ensemble du detecteur
1151  } //fin du cas ou la particule a laisse de l energie dans un detecteur
1152  } //fin du cas ou la trajectoire est coherente avec la geometrie
1153  } //fin du cas ou la particule a touche un detecteur au sens large
1154  } //fin de la condition (FilterType == kFilterType_Geo) || _part->GetKE()>1.e-3
1155  } // end case where particle with a non-zero KE left the target
1156 
1157  //On enregistre l eventuelle perte dans la cible
1158  if (fTarget)
1159  part->GetParameters()->SetValue("TARGET Out", eLostInTarget);
1160  //On enregistre le detecteur ou la particule s'arrete
1161  if (last_det)
1162  part->GetParameters()->SetValue("STOPPING DETECTOR", last_det->GetName());
1163  //On enregistre le telescope d'identification
1164  if (lidtel && lidtel->GetEntries()) {
1165  KVIDTelescope* theIDT = 0;
1166  TIter nextIDT(lidtel);
1167  while ((theIDT = (KVIDTelescope*)nextIDT())) {
1168  // make sure particle passed through telescope's detectors
1169  Int_t ndet = theIDT->GetSize();
1170  Int_t ntouche = 0;
1171  for (int i = 1; i <= ndet; i++) {
1172  if (nvl && nvl->HasParameter(Form("%s", theIDT->GetDetector(i)->GetName())))
1173  ntouche++;
1174  }
1175  if (ntouche < ndet) continue;
1176  //Info("DetectEvent","about to check id in %s", theIDT->GetName());
1177  //Info("DetectEvent","ready=%d can identify(%d,%d)=%d", theIDT->IsReadyForID(),part->GetZ(),part->GetA(),theIDT->CanIdentify(part->GetZ(),part->GetA()));
1178  if (fFilterType == kFilterType_Geo ||
1179  (theIDT->IsReadyForID() && theIDT->CanIdentify(part->GetZ(), part->GetA()))) {
1180  //Info("DetectEvent","IDENTIFYING TELESCOPE = %s", theIDT->GetName());
1181  part->GetParameters()->SetValue("IDENTIFYING TELESCOPE", theIDT->GetName());
1182  break;
1183  }
1184  }
1185  }
1186  //On enregistre le statut de detection
1187  //dans l objet KVNucleus
1188  for (Int_t ii = 0; ii < det_stat.GetNpar(); ii += 1) {
1189  part->GetParameters()->SetValue(det_stat.GetNameAt(ii), det_stat.GetStringValue(ii));
1190  }
1191  //On enregistre les differentes pertes d'energie dans les detecteurs
1192  //dans l objet KVNucleus
1193  if (nvl) {
1194 
1195  for (Int_t ii = 0; ii < nvl->GetNpar(); ii += 1) {
1196  TString detname = nvl->GetNameAt(ii);
1197  part->GetParameters()->SetValue(detname, nvl->GetDoubleValue(ii));
1198  // For fFilterType == kFilterType_Full:
1199  // for each detector hit we record the index of each particle hitting the detector
1200  // [detector]="13" => detector hit by particle 13
1201  // if more than one we have
1202  // [detector]="1 6" => detector hit by particles 1 & 6
1203  if (fFilterType == kFilterType_Full) {
1204  if (un.HasParameter(detname)) {
1205  KVNumberList ppp(un.GetStringValue(detname));
1206  ppp.Add(part_index);
1207  un.SetValue(detname, ppp.AsString());
1208  }
1209  else {
1210  un.SetValue(detname, Form("%d", part_index));
1211  }
1212  }
1213  }
1214  delete nvl;
1215  nvl = 0;
1216  }
1217 
1218  _part->SetMomentum(*_part->GetPInitial());
1219 
1220  } //fin de loop over particles
1221 
1222  // Info("DetectEvent", "Finished filtering event. Event status now:");
1223  // event->Print();
1224 
1225  // EVENT RECONSTRUCTION FOR SIMPLE GEOMETRIC FILTER
1226  /*
1227  We keep all particles EXCEPT those belonging to groups
1228  "NO HIT" "DEAD ZONE" or "GEOMETRY INCOHERENCY"
1229  */
1230  if (fFilterType == kFilterType_Geo) {
1231 
1232  KVGroup* grp_tch;
1233  TIter nxt_grp(fHitGroups->GetGroups());
1234  while ((grp_tch = (KVGroup*) nxt_grp())) {
1235  grp_tch->ClearHitDetectors();
1236  }
1237  while ((part = event->GetNextNucleus())) {
1238  if (part->BelongsToGroup("DETECTED") ||
1239  (part->BelongsToGroup("UNDETECTED") &&
1240  !part->BelongsToGroup("NO HIT") &&
1241  !part->BelongsToGroup("DEAD ZONE") &&
1242  !part->BelongsToGroup("GEOMETRY INCOHERENCY") &&
1243  !part->BelongsToGroup("NEUTRON") &&
1244  !part->BelongsToGroup("NO ENERGY"))
1245  ) {
1246  KVDetector* last_det = 0;
1247  if (part->GetParameters()->HasParameter("STOPPING DETECTOR"))
1248  last_det = GetDetector(part->GetParameters()->GetStringValue("STOPPING DETECTOR"));
1249  if (!last_det) continue;
1250  KVReconstructedNucleus* recon_nuc = (KVReconstructedNucleus*)rec_event->AddParticle();
1251  // copy parameter list
1252  part->GetParameters()->Copy(*(recon_nuc->GetParameters()));
1253  recon_nuc->Reconstruct(last_det);
1254  recon_nuc->RebuildReconTraj(false);
1255  recon_nuc->SetZandA(part->GetZ(), part->GetA());
1256  recon_nuc->SetE(part->GetFrame(detection_frame, kFALSE)->GetE());
1257  if (part->GetParameters()->HasParameter("IDENTIFYING TELESCOPE")) {
1258  KVIDTelescope* idt = GetIDTelescope(part->GetParameters()->GetStringValue("IDENTIFYING TELESCOPE"));
1259  if (idt) {
1260  recon_nuc->SetIdentifyingTelescope(idt);
1261  recon_nuc->SetIDCode(idt->GetIDCode());//idt->SetIDCode(recon_nuc, idt->GetIDCode());
1262  recon_nuc->SetECode(GetNormalCalibrationCode());//recon_nuc->SetECode(idt->GetECode());
1263  }
1264  }
1266  }
1267  }
1268 
1269  // analyse all groups & particles
1270  nxt_grp.Reset();
1271  while ((grp_tch = (KVGroup*) nxt_grp())) {
1273  }
1274  KVReconstructedNucleus* recon_nuc;
1275  while ((recon_nuc = rec_event->GetNextParticle())) {
1276  // check for undetectable pile-ups
1277  if (recon_nuc->GetStatus() == KVReconstructedNucleus::kStatusOK) {
1278  if (recon_nuc->GetStoppingDetector()->GetNHits() > 1)
1280  else {
1281  KVIDTelescope* idt = recon_nuc->GetIdentifyingTelescope();
1282  if (idt) {
1283  KVDetector* de_det = idt->GetDetector(1);
1284  if (de_det->GetNHits() > 1) recon_nuc->SetStatus(KVReconstructedNucleus::kStatusPileupDE);
1285  }
1286  }
1287  }
1288  recon_nuc->SetIsOK(kFALSE);
1290  recon_nuc->SetIsIdentified();
1291  recon_nuc->SetIsCalibrated();
1292  recon_nuc->SetIsOK();
1293  recon_nuc->SetZMeasured();
1294  recon_nuc->SetAMeasured();
1295  }
1296  }
1297  return;
1298  }
1299  // EVENT RECONSTRUCTION FOR SIMPLE GEOMETRIC FILTER WITH THRESHOLDS
1300  /*
1301  We keep all particles belonging to "DETECTED" group
1302  Those in "INCOMPLETE" group are treated as Zmin particles
1303  */
1305  // before reconstruction we have to clear the list of 'hits' of each detector
1306  // (they currently hold the addresses of the simulated particles which were detected)
1307  // which will be filled with the reconstructed particles, otherwise the number of hits
1308  // in each detector will be 2x the real value, and coherency analysis of the reconstructed
1309  // events will not work
1310  KVGroup* grp_tch;
1311  TIter nxt_grp(fHitGroups->GetGroups());
1312  while ((grp_tch = (KVGroup*) nxt_grp())) grp_tch->ClearHitDetectors();
1313  KVReconstructedNucleus* recon_nuc;
1314  while ((part = event->GetNextNucleus())) {
1315  if (part->BelongsToGroup("DETECTED")) {
1316  KVDetector* last_det = 0;
1317  if (part->GetParameters()->HasParameter("STOPPING DETECTOR"))
1318  last_det = GetDetector(part->GetParameters()->GetStringValue("STOPPING DETECTOR"));
1319  if (!last_det || !(last_det->IsOK())) continue;
1320 
1321  recon_nuc = (KVReconstructedNucleus*)rec_event->AddParticle();
1322  // copy parameter list
1323  part->GetParameters()->Copy(*(recon_nuc->GetParameters()));
1324  recon_nuc->Reconstruct(last_det);
1325  recon_nuc->RebuildReconTraj(false);
1326  recon_nuc->SetZandA(part->GetZ(), part->GetA());
1327  recon_nuc->SetE(part->GetFrame(detection_frame, kFALSE)->GetE());
1328 
1329  if (part->GetParameters()->HasParameter("IDENTIFYING TELESCOPE")) {
1330  KVIDTelescope* idt = GetIDTelescope(part->GetParameters()->GetStringValue("IDENTIFYING TELESCOPE"));
1331  if (idt) {
1332  recon_nuc->SetIdentifyingTelescope(idt);
1333  // for particles which are apprently well-identified, we
1334  // check that they are in fact sufficiently energetic to be identified
1335  if (!part->BelongsToGroup("INCOMPLETE")
1336  && !idt->CheckTheoreticalIdentificationThreshold((KVNucleus*)part->GetFrame(detection_frame, kFALSE)))
1337  part->AddGroup("INCOMPLETE");
1338  if (!part->BelongsToGroup("INCOMPLETE")) {
1339  recon_nuc->SetIDCode(idt->GetIDCode());//idt->SetIDCode(recon_nuc, idt->GetIDCode());
1340  idt->SetIdentificationStatus(recon_nuc);
1341  }
1342  else {
1343  recon_nuc->SetIDCode(GetZminCode());//idt->SetIDCode(recon_nuc, idt->GetZminCode());
1344  }
1345  recon_nuc->SetECode(GetNormalCalibrationCode());
1346  //recon_nuc->SetIsIdentified();
1347  //recon_nuc->SetIsCalibrated();
1348  }
1349  }
1350  else { /*if(part->BelongsToGroup("INCOMPLETE"))*/
1351  // for particles stopping in 1st member of a telescope, there is no "identifying telescope"
1352  //KVIDTelescope* idt = (KVIDTelescope*)last_det->GetIDTelescopes()->First();
1353  //if (idt) idt->SetIDCode(recon_nuc, idt->GetZminCode());
1354  recon_nuc->SetIDCode(GetZminCode());
1355  }
1357  }
1358  }
1359  // analyse all groups & particles
1360  nxt_grp.Reset();
1361  while ((grp_tch = (KVGroup*) nxt_grp())) {
1363  }
1364 
1365  // now perform mult-hit/coherency analysis until no further changes take place
1366  Int_t round = 1, nchanged;
1367  //cout << "SIM: " << event->GetMult() << " REC: " << rec_event->GetMult() << endl;
1368  //for(int i=1;i<=rec_event->GetMult();i++) cout << i << " Z=" << rec_event->GetParticle(i)->GetZ()<<" status="<<rec_event->GetParticle(i)->GetStatus() <<endl;
1369  do {
1370  nchanged = FilteredEventCoherencyAnalysis(round++, rec_event);
1371  //cout << "Round = " << round-1 << " : nchanged = " << nchanged << endl;
1372  nxt_grp.Reset();
1373  while ((grp_tch = (KVGroup*) nxt_grp())) {
1375  }
1376  //for(int i=1;i<=rec_event->GetMult();i++) cout << i << " Z=" << rec_event->GetParticle(i)->GetZ()<<" status="<<rec_event->GetParticle(i)->GetStatus() <<endl;
1377  }
1378  while (nchanged);
1379 
1380  return;
1381  }
1382 
1383  if (fFilterType == kFilterType_Full) {
1384  // Calculate acquisition parameters, taking into account pile-up
1385  KVDetector* det = 0;
1386  for (Int_t nn = 0; nn < un.GetNpar(); nn += 1) {
1387  det = GetDetector(un.GetNameAt(nn));
1388  KVNumberList ppp(un.GetStringValue(nn));
1389  det->DeduceACQParameters(event, ppp);
1390  }
1391 
1392  // before reconstruction we have to clear the list of 'hits' of each detector
1393  // (they currently hold the addresses of the simulated particles which were detected)
1394  // which will be filled with the reconstructed particles, otherwise the number of hits
1395  // in each detector will be 2x the real value, and coherency analysis of the reconstructed
1396  // events will not work
1397  KVGroup* grp_tch;
1398  TIter nxt_grp(fHitGroups->GetGroups());
1399  while ((grp_tch = (KVGroup*) nxt_grp())) {
1400  grp_tch->ClearHitDetectors();
1401  }
1402  // Info("DetectEvent", "Multidetector status before event reconstruction:");
1403  // fHitGroups->Print();
1404 
1405  // reconstruct & identify the event
1406  ReconstructEvent(rec_event, fHitGroups);
1407  rec_event->IdentifyEvent();
1408  // calculate particle energies
1409  rec_event->CalibrateEvent();
1410  // 'coherency'
1411  rec_event->SecondaryIdentCalib();
1412  return;
1413  }
1414 
1415 }
1416 
1417 
1431 
1433 {
1434  // Use ROOT geometry to propagate particle through the array,
1435  // calculating its energy losses in all absorbers, and setting the
1436  // energy loss members of the active detectors on the way.
1437  //
1438  // It is assumed that the ROOT geometry has been generated and is
1439  // pointed to by gGeoManager.
1440  //
1441  // Returns a list (KVNameValueList pointer) of the crossed detectors with their name and energy loss
1442  // if particle hits detector in array, 0 if not (i.e. particle
1443  // in beam pipe or dead zone of the multidetector)
1444  // INFO User has to delete the KVNameValueList after its use
1445 
1446  // list of energy losses in active layers of detectors
1447  KVNameValueList* NVL = 0;
1448  if (!fNavigator) {
1449  Error("DetectParticle_TGEO", "No existing navigator ...");
1450  return 0;
1451  }
1453 
1454  // particle missed all detectors
1455  if (!part->GetParameters()->GetNpar()) return NVL;
1456  else {
1457  // find detectors in array hit by particle
1458  // and set their energies
1459  TIter next(part->GetParameters()->GetList());
1460  KVNamedParameter* param;
1461  while ((param = (KVNamedParameter*)next())) {
1462  KVString pname(param->GetName());
1463  pname.Begin(":");
1464  KVString pn2 = pname.Next();
1465  KVString pn3 = pname.Next();
1466  if (pn2 == "DE") {
1467  pn3.Begin("/");
1468  KVString det_name = pn3.Next();
1469  if (pn3.End() || pn3.Next().BeginsWith("ACTIVE")) {
1470  // energy loss in active layer of detector
1471  KVDetector* curDet = GetDetector(det_name);
1472  if (curDet) {
1473  Double_t de = param->GetDouble();
1474  if (!NVL) NVL = new KVNameValueList;
1475  NVL->SetValue(curDet->GetName(), de);
1476  }
1477  }
1478  }
1479  }
1480  }
1481  return NVL;
1482 }
1483 
1484 
1485 
1501 
1503  KVDetector*)
1504 {
1505  //Replace (and destroy) the named detector in the array with a detector based on the prototype
1506  //given by the pointer new_kvd.
1507 
1508 // KVDetector *kvd = GetDetector(name);
1509 // if (!kvd) {
1510 // Warning("ReplaceDetector", "Detector %s not found", name);
1511 // return;
1512 // }
1513 // //get telescope of detector, so we know where to put the replacement
1514 // KVTelescope *tel = kvd->GetTelescope();
1515 // if (!tel) {
1516 // Error("ReplaceDetector", "Detector %s is not in a telescope", name);
1517 // return;
1518 // }
1519 // tel->ReplaceDetector(kvd, new_kvd);
1520  Warning("ReplaceDetector", "Needs reimplementing");
1521 }
1522 
1523 
1524 
1525 
1528 
1530 {
1531  // Return pointer to telescope in array with name given by "name"
1532  return 0;
1533 }
1534 
1535 
1536 
1539 
1541 {
1542  //Return pointer to DeltaE-E ID Telescope with "name"
1543 
1545 }
1546 
1547 
1548 
1549 
1550 
1554 
1556 {
1557  //return pointer to group in array which contains detector or telescope
1558  //with name "name"
1559 
1560  KVTelescope* tel = 0;
1561  KVDetector* det = 0;
1562  KVGroup* grp = 0;
1563  if ((tel = GetTelescope(name))) {
1564  grp = (KVGroup*)tel->GetParentStructure("GROUP");
1565  return grp;
1566  }
1567  if ((det = GetDetector(name))) {
1568  grp = det->GetGroup();
1569  }
1570  return grp;
1571 }
1572 
1573 
1574 
1577 
1579 {
1580  // Return pointer to group with name
1581  return (KVGroup*)GetStructure("GROUP", name);
1582 }
1583 
1584 
1585 
1586 
1587 
1589 
1591 {
1592  AbstractMethod("MakeListOfDetectors");
1593 }
1594 
1595 
1596 
1601 
1603 {
1604  //Reset all groups (lists of detected particles etc.)
1605  //and detectors in groups (energy losses, ACQparams etc. etc.)
1606  //and the target if there is one
1607 
1608  unique_ptr<KVSeqCollection> fGroups(GetStructures()->GetSubListWithType("GROUP"));
1609 
1610  TIter next(fGroups.get());
1611  KVGroup* grp;
1612  while ((grp = (KVGroup*) next())) {
1613  grp->Reset();
1614  }
1615  if (GetTarget())
1616  GetTarget()->Clear();
1617 }
1618 
1619 
1620 //void KVMultiDetArray::AddACQParam(KVACQParam* par)
1621 //{
1622 // //Add an acquisition parameter corresponding to a detector of the array.
1623 // //The fACQParams list is added to the list of cleanups (gROOT->GetListOfCleanups).
1624 // //Each acq-param has its kMustCleanup bit set.
1625 // //Thus, if the acq-param is deleted (e.g. by the detector which owns it), it is
1626 // //automatically removed from the fACQParams list by ROOT.
1627 
1628 // if (!fACQParams) {
1629 // fACQParams = new KVHashList;
1630 // fACQParams->SetName(Form("List of acquisition parameters for multidetector array %s", GetName()));
1631 // fACQParams->SetOwner(kFALSE);
1632 // fACQParams->SetCleanup(kTRUE);
1633 // }
1634 // if (par) {
1635 // fACQParams->Add(par);
1636 // }
1637 // else
1638 // Warning("AddACQParam", "Null pointer passed as argument");
1639 //}
1640 
1641 
1642 //void KVMultiDetArray::SetACQParams()
1643 //{
1644 // // Set up acquisition parameters in all detectors of the array + any acquisition parameters which are not
1645 // // directly related to a detector.
1646 // //
1647 // // Override the method SetArrayACQParams() in order to add any acquisition parameters not directly
1648 // // related to a detector.
1649 // //
1650 // // For the detector acquisition parameters, we loop over all detectors of the array and call each detector's
1651 // // SetACQParams() method, if it has not already been done (i.e. if the detector has no associated parameters).
1652 // // Each specific implementation of a KVDetector class should redefine the KVDetector::SetACQParams()
1653 // // method in order to give the detector in question the necessary acquisition parameters (KVACQParam objects).
1654 // //
1655 // // The list of acquisition parameters of each detector is then used to
1656 // // 1) add to fACQParams list of all acquisition parameters of the array
1657 // // 2) set as "not working" the acquisition parameters for which environment variables such as
1658 // // [dataset name].KVACQParam.[acq par name].Working: NO
1659 // // are set in a .kvrootrc file.
1660 // // 3) set bitmask for each detector used to determine which acquisition parameters are
1661 // // taken into account by KVDetector::Fired based on the environment variables
1662 // // [classname].Fired.ACQParameterList.[type]: PG,GG,T
1663 // // where [classname]=KVDetector by default, or the name of some class
1664 // // derived from KVDetector which calls the method KVDetector::SetKVDetectorFiredACQParameterListFormatString()
1665 // // in its constructor.
1666 
1667 // if (fACQParams) {
1668 // fACQParams->Clear();
1669 // }
1670 
1671 // SetArrayACQParams();
1672 
1673 // TIter next(GetDetectors());
1674 // KVDetector* det;
1675 // while ((det = (KVDetector*) next())) {
1676 // KVSeqCollection* l = det->GetACQParamList();
1677 // if (!l) {
1678 // //detector has no acq params
1679 // //set up acqparams in detector
1680 // det->SetACQParams();
1681 // l = det->GetACQParamList();
1682 // }
1683 // //loop over acqparams and add them to fACQParams list, checking
1684 // //their status (working or not working ?)
1685 // TIter next_par(l);
1686 // KVACQParam* par;
1687 // while ((par = (KVACQParam*) next_par())) {
1688 // AddACQParam(par);
1689 // par->SetWorking(gDataSet->GetDataSetEnv(Form("KVACQParam.%s.Working", par->GetName()), kTRUE));
1690 // }
1691 // // set bitmask
1692 // KVString inst;
1693 // inst.Form(det->GetFiredACQParameterListFormatString(), det->GetType());
1694 // KVString lpar = gDataSet->GetDataSetEnv(inst);
1695 // det->SetFiredBitmask(lpar);
1696 // }
1697 //}
1698 
1699 
1700 //void KVMultiDetArray::SetArrayACQParams()
1701 //{
1702 // // Method called by SetACQParams() in order to define any acquisition parameters which are not
1703 // // directly related to any detectors of the array.
1704 // // This implementation does nothing: override it in derived classes if needed.
1705 //}
1706 
1707 
1713 
1715 {
1716  // Sets up calibrators for all detectors with a defined calibration for run
1717  // Set parameters for all detectors with links to table "Calibrations" for run
1718  // If 'myname' is given, we look in "myname.Calibrations"
1719 
1720  //Reset all calibrators of all detectors first
1721  TIter next(GetDetectors());
1722  KVDetector* kvd;
1723  while ((kvd = (KVDetector*) next())) kvd->RemoveCalibrators();
1724 
1725  TString tabname = (myname != "" ? Form("%s.Calibrations", myname.Data()) : "Calibrations");
1726  //Info("SetCalibratorParameters", "For array %s in table %s", GetName(), tabname.Data());
1727  KVRList* run_links = r->GetLinks(tabname);
1728  if (run_links) Info("SetCalibratorParameters", "Found %d calibrations for this run", run_links->GetEntries());
1729  else {
1730 // Warning("SetCalibratorParameters", "Got no links for %s", tabname.Data());
1731 // r->GetKeys()->ls();
1732  return;
1733  }
1734  TIter nxt_link(run_links);
1735  KVDBParameterSet* dbps;
1736  while ((dbps = (KVDBParameterSet*)nxt_link())) {
1737 
1738  KVDetector* det = GetDetector(dbps->GetName());
1739  if (!det) {
1740  Warning("SetCalibratorParameters", "Got parameters for unknown detector: %s", dbps->GetName());
1741  continue;
1742  }
1743 
1744  KVNameValueList class_options;
1745  KVString clop;
1746  if (dbps->HasParameter("CalibOptions")) clop = dbps->GetStringParameter("CalibOptions");
1747  if (clop != "") {
1748  clop.Begin(",");
1749  while (!clop.End()) {
1750  KVString clopp = clop.Next(true);
1751  clopp.Begin("=");
1752  KVString par(clopp.Next(true)), val(clopp.Next(true));
1753  class_options.SetValue(par, val);
1754  }
1755  }
1756  KVCalibrator* cal = KVCalibrator::MakeCalibrator(dbps->GetStringParameter("CalibClass"));
1757  cal->SetType(dbps->GetTitle());
1758  if (clop != "") {
1759  try {
1760  cal->SetOptions(class_options);
1761  }
1762  catch (std::exception& e) {
1763  Error("SetCalibratorParameters",
1764  "Problem for %s [%s] : %s", det->GetName(), cal->GetType(), e.what());
1765  delete cal;
1766  continue;
1767  }
1768  }
1769  cal->SetInputSignalType(dbps->GetStringParameter("SignalIn"));
1770  cal->SetOutputSignalType(dbps->GetStringParameter("SignalOut"));
1771  if (!det->AddCalibrator(cal, dbps->GetParameters())) {
1772  // Calibrator invalid - probably input signal is not defined for detector
1773  // N.B. 'cal' deleted by KVDetector::AddCalibrator
1774  continue;
1775  }
1776 
1777  if (dbps->GetParamNumber() > cal->GetNumberParams()) {
1778  Warning("SetCalibratorParameters", "Wrong number of parameters (%d) for calibrator %s for detector %s : should be %d",
1779  dbps->GetParamNumber(), dbps->GetTitle(), dbps->GetName(), cal->GetNumberParams());
1780  dbps->Print();
1781  continue;
1782  }
1783  for (int i = 0; i < dbps->GetParamNumber(); ++i) {
1784  if (i >= cal->GetNumberParams())
1785  cal->SetParameter(i, 0);
1786  else
1787  cal->SetParameter(i, dbps->GetParameter(i));
1788  }
1789  cal->SetStatus(true);
1790  }
1791 }
1792 
1793 
1794 
1812 
1814 {
1815  // Detector signals corresponding to raw data acquisition parameters are typically only created and
1816  // added to detectors when some raw data has been read including those parameters.
1817  //
1818  // However, when reconstructing data, we may define identification matrices or calibration formulae
1819  // which use these signals before starting to read data. Therefore we need to know beforehand what
1820  // detector signals are expected to be available once data has been read.
1821  //
1822  // These are defined, according to detector types, by variables of the form
1823  //
1824  //~~~~
1825  // [dataset].[array].[detector-type].ExpectedDetectorSignals: [comma-separated list of signal names]
1826  //~~~~
1827  //
1828  // where [dataset] is optionally used to provide dataset-specific definitions.
1829  //
1830  // Here we add a detector signal of each expected type to each detector of the array
1831 
1832  TIter it(GetDetectors());
1833  KVDetector* det;
1834  while ((det = (KVDetector*)it())) {
1835  KVString s = KVBase::GetDataSetEnv(fDataSet.Data(), Form("%s.%s.ExpectedDetectorSignals", GetName(), det->GetType()), "");
1836  if (s.IsNull()) continue;
1837  s.Begin(",");
1838  while (!s.End()) {
1839  det->AddDetectorSignal(s.Next(kTRUE));
1840  }
1841  }
1842 }
1843 
1844 
1845 
1856 
1858 {
1859  // First step in event reconstruction based on current status of detectors in array.
1860  // Fills the given KVDetectorEvent with the list of all groups which have fired.
1861  // i.e. loop over all groups of the array and test whether KVGroup::Fired() returns true or false.
1862  //
1863  // If the list of fired detectors 'fired_dets' is given, then we use this list
1864  // to find the associated groups. If not given, or if it is empty, we may use the internal fFiredDetectors list.
1865  //
1866  // Call method detev->Clear() before reading another event in order to reset all of the hit groups
1867  // (including all detectors etc.) and emptying the list.
1868 
1869  if (!fired_dets || !fired_dets->GetEntries()) {
1870  if (fFiredDetectors.GetEntries()) fired_dets = &fFiredDetectors;
1871  }
1872  if (fired_dets && fired_dets->GetEntries()) {
1873  // list of fired detectorsgiven
1874  TIter next_det(fired_dets);
1875  KVDetector* det = 0;
1876  KVGroup* grp = 0;
1877  while ((det = (KVDetector*)next_det())) {
1878  if ((grp = det->GetGroup()) && grp->GetParents()->Contains(this)) detev->AddGroup(grp);
1879  }
1880  }
1881  else {
1882  //loop over groups
1883  unique_ptr<KVSeqCollection> fGroups(GetStructures()->GetSubListWithType("GROUP"));
1884 
1885  TIter next_grp(fGroups.get());
1886  KVGroup* grp;
1887  while ((grp = (KVGroup*) next_grp())) {
1888  if (grp->Fired()) {
1889  //if (!fHitGroups->FindObject(grp))
1890  // grp->Print();
1891  //add new group to list of hit groups
1892  detev->AddGroup(grp);
1893  }
1894  }
1895  }
1896 }
1897 
1898 
1899 
1911 
1913 {
1914  // Use the KVDetectorEvent (list of hit groups) in order to fill the
1915  // KVReconstructedEvent with reconstructed nuclei
1916  //
1917  // Reconstruction of detected particles
1918  //
1919  // - loop over last stage of group telescopes
1920  // - if any detector is hit, construct "particle" from energy losses in all detectors
1921  // directly in front of it.
1922  // - loop over next to last stage...if any detector hit NOT ALREADY IN A "PARTICLE"
1923  // construct "particle" etc. etc.
1924 
1925  KVGroup* grp_tch;
1926  TIter nxt_grp(kvde->GetGroups());
1927  while ((grp_tch = (KVGroup*) nxt_grp())) {
1928  AnalyseGroupAndReconstructEvent(recev, grp_tch);
1929  }
1930 }
1931 
1932 
1933 
1934 
1938 
1940 {
1941  // Loop over detectors in group, starting from the furthest from the target,
1942  // and working inwards. Calls KVReconstructedEvent::AnalyseDetectors
1943 
1944  for (Int_t il = grp->GetNumberOfDetectorLayers(); il > 0; il--) {
1945  unique_ptr<TList> dets(grp->GetDetectorsInLayer(il));
1946  recev->AnalyseDetectors(dets.get());
1947  }
1948  //perform first-order coherency analysis (set fAnalStatus for each particle)
1950 }
1951 
1952 
1953 
1954 
1955 
1956 
1962 
1964 {
1965  //Remove (i.e. destroy) all the telescopes belonging to a given group
1966 // if (grp) {
1967 // grp->Destroy();
1968 // }
1969  Warning("RemoveGroup", "Needs reimplementing");
1970 }
1971 
1972 
1973 
1977 
1979 {
1980  //Remove (i.e. destroy) all the telescopes belonging to the group in array
1981  //which contains detector or telescope with name "name"
1983  if (grp) {
1984  RemoveGroup(grp);
1985  }
1986 }
1987 
1988 
1989 
1990 
1995 
1997  KVNucleus* kvp)
1998 {
1999  //Given the name of a detector, simulate detection of a given particle
2000  //by the complete corresponding group. The particle's theta and phi are set
2001  //at random within the limits of detector entrance window
2002 
2003  KVDetector* kvd = GetDetector(detname);
2004  if (kvd) {
2005  KVNameValueList* nvl = 0;
2006  kvp->SetMomentum(kvp->GetEnergy(), kvd->GetRandomDirection("random"));
2007  if ((nvl = DetectParticle(kvp))) delete nvl;
2008  }
2009  else {
2010  Error("DetectParticleIn", "Detector %s not found", detname);
2011  }
2012 }
2013 
2014 
2015 
2032 
2034 {
2035  //Static function which will create and 'Build' the multidetector object corresponding to
2036  //a given run of dataset 'dataset_name'. Any previously existing multidetector will be
2037  //deleted.
2038  //We first activate the given dataset if not already done
2039  //
2040  //Multidetector arrays are defined as 'Plugin' objects in the file $KVROOT/KVFiles/.kvrootrc :
2041  //
2042  //Plugin.KVMultiDet: [dataset_name] [classname] [library] "[constructor]()"
2043  //
2044  //The constructors/macros are always without arguments
2045  //
2046  //Dataset name is stored in fDataSet
2047 
2048  // store the run number (if given) so that if the dataset needs to update its database
2049  // (which requires building the multidetector by calling MakeMultiDetector()) then it
2050  // will build the correct geometry for the run
2051  if (run > 0) fMakeMultiDetectorRunNumber = run;
2053 
2054  if (gDataSetManager && (!gDataSet || (gDataSet != gDataSetManager->GetDataSet(dataset_name)))) {
2055  printf("Info in <KVMultiDetArray::MakeMultiDetector>: Changing dataset\n");
2056  gDataSetManager->GetDataSet(dataset_name)->cd();
2057  }
2058 
2059  if (gMultiDetArray && gMultiDetArray->GetDataSet() != dataset_name) {
2060  printf("Info in <KVMultiDetArray::MakeMultiDetector>: Deleting existing array %s\n", gMultiDetArray->GetName());
2061  if (gIDGridManager) {
2062  delete gIDGridManager;
2063  gIDGridManager = nullptr;
2064  }
2065  delete gMultiDetArray;
2066  gMultiDetArray = nullptr;
2067  }
2068 
2069 
2070  // Creation of database when dataset is selected for first time may
2071  // include creation of multidetector array (by calling this method)
2072  KVMultiDetArray* mda = nullptr;
2073  if (!gMultiDetArray) {
2074  TPluginHandler* ph;
2075  if (!(ph = LoadPlugin(classname.Data(), dataset_name)))
2076  return nullptr;
2077 
2078  //execute constructor/macro for multidetector - assumed without arguments
2079  mda = (KVMultiDetArray*) ph->ExecPlugin(0);
2080  mda->fDataSet = dataset_name;
2081  mda->Build(run);
2082  // if ROOT geometry is not allowed ([dataset_name].KVMultiDetArray.ROOTGeometry = no
2083  // or KVMultiDetArray.ROOTGeometry = no), disable it
2084  mda->fROOTGeometry = GetDataSetEnv(dataset_name, "KVMultiDetArray.ROOTGeometry", kTRUE);
2085  if (mda->fROOTGeometry) mda->CheckROOTGeometry();
2086  // set dataset-dependent lists of acceptable ID/E codes for reconstructed nuclei
2087  KVString codes = GetDataSetEnv(dataset_name, Form("%s.ReconstructedNuclei.AcceptIDCodes", mda->GetName()), "");
2088  if (codes != "") mda->fAcceptIDCodes.Set(codes);
2089  codes = GetDataSetEnv(dataset_name, Form("%s.ReconstructedNuclei.AcceptECodes", mda->GetName()), "");
2090  if (codes != "") mda->fAcceptECodes.Set(codes);
2091  // set dataset-dependent condition for seeding reconstructed nuclei
2092  mda->SetPartSeedCond(GetDataSetEnv(dataset_name, Form("%s.ReconstructedNuclei.ParticleSeedCond", mda->GetName()), ""));
2093 #ifdef WITH_RSQLITE
2094  // save contents of grid manager in an SQL-ROOT database if not already done
2095  if (fMakeMultiDetectorSetParameters && !gIDGridManager->IsSQLROOT()) {
2096  // 'if(fMakeMultiDetectorSetParameters...' ensures that we are not currently building a subarray
2097  // of a KVExpSetUp. Grids can only be saved once in a single file after all have been read.
2098  TString filepath;
2099  if (is_gnuinstall()) {
2100  // GNU-style install: use working directory $HOME/.kaliveda
2101  filepath = GetWORKDIRFilePath(gDataSet->GetName());
2102  }
2103  else
2104  filepath = gDataSet->GetDataSetDir();
2105 
2106  filepath += "/idgrids_DB";
2107 
2108  int n_grids_to_write = gIDGridManager->GetGrids()->GetEntries();
2109 
2110  if (n_grids_to_write) {
2111  KVSQLROOTFile f(filepath, "recreate");
2112 
2113  printf("Info in <KVMultiDetArray::MakeMultiDetector>: Saving %d grids in SQL-ROOT database file %s\n",
2114  n_grids_to_write, filepath.Data());
2115 
2116  TIter it(gIDGridManager->GetGrids());
2117  KVIDGraph* gr;
2118  while ((gr = (KVIDGraph*)it())) {
2119  f.WriteObject(gr, {
2120  {"IDLabel", gr->GetIDTelescopeLabel()},
2121  {"IDTelescopes", gr->GetParameters()->GetStringValue("IDTelescopes")},
2122  {"VarX", gr->GetVarX()},
2123  {"VarY", gr->GetVarY()},
2124  {"Runlist", gr->GetRunList()},
2125  }
2126  );
2127  --n_grids_to_write;
2128  if (!(n_grids_to_write % 1000)) printf("Info in <KVMultiDetArray::MakeMultiDetector>: ...%d grids left...\n",
2129  n_grids_to_write);
2130 
2131  }
2132  }
2133  }
2134 #endif
2135  }
2136  else {
2137  mda = gMultiDetArray;
2138  }
2139  // set parameters if required & allowed & not done yet
2141  return mda;
2142 }
2143 
2144 
2145 
2157 
2159 {
2160  // Return pointer to KVUpDater defined by dataset for this multidetector, the class used
2161  // is defined as a plugin like this:
2162  //
2163  // # Plugin.KVUpDater: name_of_dataset name_of_class name_of_plugin_library constructor_to_call
2164  //
2165  // However, if a dataset defines a variable like this:
2166  //
2167  // [dataset].ExpSetUp.Updater.[multidetector name]: [name_of_dataset for plugin]
2168  //
2169  // then we use the updater plugin defined for the given dataset
2170 
2171  if (!fUpDater) {
2172  KVString alt_updater = KVBase::GetDataSetEnv(fDataSet, Form("ExpSetUp.Updater.%s", GetName()), "");
2173  if (alt_updater != "") fUpDater = KVUpDater::MakeUpDater(alt_updater, this);
2175  }
2176  Info("GetUpDater", "updater class for dataset %s: %s", fDataSet.Data(), fUpDater->IsA()->GetName());
2177  return fUpDater;
2178 }
2179 
2180 
2181 
2182 
2191 
2192 void KVMultiDetArray::SetParameters(UInt_t run, Bool_t physics_parameters_only)
2193 {
2194  // Set run-dependent parameters of the array.
2195  //
2196  // if physics_parameters_only==false, identification and calibration parameters are set.
2197  // if physics_parameters_only==true, just the minimum necessary for physics analysis of reduced data are set.
2198  //
2199  // This can only be done if gDataSet has been set i.e. a dataset has been chosen,
2200  // otherwise this just has the effect of setting the current run number
2201 
2202  fCurrentRun = run;
2203  KVDataSet* ds = gDataSet;
2204  if (!ds) {
2205  if (gDataSetManager)
2206  ds = gDataSetManager->GetDataSet(fDataSet.Data());
2207  }
2208  if (ds) {
2209  GetUpDater()->SetParameters(run, physics_parameters_only);
2210  SetBit(kParamsSet);
2211  }
2212 }
2213 
2214 
2215 
2216 
2221 
2223 {
2224  //Set identification parameters for run.
2225  //This can only be done if gDataSet has been set i.e. a dataset has been chosen
2226  //Otherwise this just has the effect of setting the current run number
2227 
2228  fCurrentRun = run;
2229  KVDataSet* ds = gDataSet;
2230  if (!ds) {
2231  if (gDataSetManager)
2232  ds = gDataSetManager->GetDataSet(fDataSet.Data());
2233  }
2234  if (ds) {
2237  }
2238 }
2239 
2240 
2241 
2242 
2247 
2249 {
2250  //Set calibration parameters for run.
2251  //This can only be done if gDataSet has been set i.e. a dataset has been chosen
2252  //Otherwise this just has the effect of setting the current run number
2253 
2254  fCurrentRun = run;
2255  KVDataSet* ds = gDataSet;
2256  if (!ds) {
2257  if (gDataSetManager)
2258  ds = gDataSetManager->GetDataSet(fDataSet.Data());
2259  }
2260  if (ds) {
2263  }
2264 }
2265 
2266 
2267 
2268 
2285 
2287 {
2288  //Initialisation of all ACTIVE identification telescopes in the array, i.e. those appearing in a line
2289  //in the .kvrootrc file such as this:
2290  //
2291  //# [dataset name].ActiveIdentifications: [type1] [type2] ...
2292  //
2293  //The 'types' given correspond to the value given by KVIDTelescope::GetLabel(), these are the
2294  //identifiers used to retrieve the different plugin classes in GetIDTelescopes(KVDetector*,KVDetector*,KVList*).
2295  //
2296  //For each type of identification in the list, we retrieve the first identification telescope with this
2297  //label from the list of all ID telescopes, in order to call its KVIDTelescope::SetIdentificationParameters() method.
2298  //This method (when rederived in child classes of KVIDTelescope) initialises the identification objects
2299  //for ALL of the ID telescopes of the same type (class) in the array.
2300  //
2301  //Note that, in general, the parameters of the identifications for a given run are not
2302  //set until SetParameters or SetRunIdentificationParameters is called.
2303 
2304 #ifdef WITH_RSQLITE
2305  // if a KVSQLROOTFile has been filled with the dataset identification parameters we use it.
2306  if (gIDGridManager->IsSQLROOT()) {
2307  // nothing more to do
2308  return;
2309  }
2310  else if (!gDataSet->DataBaseUpdateInProgress())
2311  // the update of the database may have been caused by 1 or more identification files being modified
2312  // (even if they are not part of the database). in this case we read in all the grids again even
2313  // if it has already been done before.
2314  {
2315  TString filepath;
2316  if (is_gnuinstall()) {
2317  // GNU-style install: use working directory $HOME/.kaliveda
2318  filepath = GetWORKDIRFilePath(gDataSet->GetName());
2319  }
2320  else
2321  filepath = gDataSet->GetDataSetDir();
2322 
2323  filepath += "/idgrids_DB";
2324 
2325  if (SearchKVFile(filepath.Data(), filepath)) {
2326  delete gIDGridManager;
2327  gIDGridManager = new KVSQLROOTIDGridManager(filepath);
2328  return;
2329  }
2330  }
2331 #endif
2332 
2333  KVString id_labels = GetDataSetEnv(fDataSet, "ActiveIdentifications", "");
2334  if (id_labels == "" || (gDataSet && !gDataSet->HasCalibIdentInfos())) {
2335  Info("SetIdentifications", "No active identifications");
2336  return;
2337  }
2338  //split list of labels
2339  id_labels.Begin(" ");
2340  int ok(0);
2341  //loop over labels/identification 'types'
2342  while (!id_labels.End()) {
2343 
2344  //get first telescope in list with right label
2346  //set ID parameters for all telescopes of this 'type'
2347  if (idt) {
2348  Info("SetIdentifications", "Initialising %s identifications...", idt->GetLabel());
2349  if (idt->SetIdentificationParameters(this))
2350  Info("SetIdentifications", "OK");
2351  ++ok;
2352  }
2353 
2354  }
2355  if (!ok) {
2356  // None of the labels in the list correspond to telescopes in the array
2357  Warning("SetIdentfications", "No telescopes found with labels given in %s.ActiveIdentifications list: %s",
2358  gDataSet->GetName(), id_labels.Data());
2359  }
2360 }
2361 
2362 
2363 
2364 
2371 
2373 {
2374  // Calls Initialize() method of each identification telescope (see KVIDTelescope
2375  // and derived classes) and sets the general identification code defined for each
2376  // telescope.
2377  //
2378  // Calling this method is essential before identification of particles is attempted.
2379 
2380  TIter next(fIDTelescopes);
2381  KVIDTelescope* idt;
2382  while ((idt = (KVIDTelescope*)next())) {
2383  idt->Initialize();
2385  }
2386 }
2387 
2388 
2389 
2400 
2402 {
2403  // Read all identification grids from the file and add them to the IDGridManager object
2404  // used by this array. This method sets up the links between each grid and the
2405  // IDtelescope(s) it is to be used for, unlike calling
2406  //
2407  // gIDGridManager->ReadAsciiFile(grids)
2408  //
2409  // which does not.
2410  //
2411  // Returns kFALSE if there is a problem reading the file
2412 
2413  if (gIDGridManager->ReadAsciiFile(grids)) {
2414  TIter next(gIDGridManager->GetLastReadGrids());
2415  KVIDGraph* gr;
2416  while ((gr = (KVIDGraph*)next())) FillListOfIDTelescopes(gr);
2417  return kTRUE;
2418  }
2419  return kFALSE;
2420 }
2421 
2422 
2423 
2424 
2428 
2430 {
2431  // Print full status report on ID telescopes in array, using informations stored in
2432  // fStatusIDTelescopes (see GetStatusOfIDTelescopes).
2433 
2434  cout << endl << "-----STATUS OF IDENTIFICATION TELESCOPES";
2435  if (GetCurrentRunNumber()) cout << " FOR RUN "
2436  << GetCurrentRunNumber();
2437  cout << "------" << endl << endl;
2438  //get list of active telescopes
2439  KVString id_labels;
2440  if (gDataSet) id_labels = gDataSet->GetDataSetEnv("ActiveIdentifications");
2441  else {
2442  unique_ptr<KVUniqueNameList> typelist(GetIDTelescopeTypes());
2443  TIter it(typelist.get());
2444  TObjString* type;
2445  while ((type = (TObjString*)it())) {
2446  if (id_labels == "") id_labels += type->GetString().Data();
2447  else {
2448  id_labels += Form(" %s", type->GetString().Data());
2449  }
2450  }
2451  }
2452  if (id_labels == "") {
2453  cout << " *** No active identifications *** " << endl;
2454  return;
2455  }
2456  // iterate over labels
2457  unique_ptr<TObjArray> toks(id_labels.Tokenize(' '));
2458 
2459  //update status infos
2461 
2462  TIter next_type(fStatusIDTelescopes);
2463  TList* id_type_list = 0;
2464  while ((id_type_list = (TList*)next_type())) {
2465 
2466  cout << " *** " << id_type_list->GetName() << " Identifications -------------------" << endl;
2467  if (!toks->FindObject(id_type_list->GetName())) {
2468  cout << " [NOT ACTIVE]" << endl;
2469  }
2470  TList* ok_list = (TList*)id_type_list->FindObject("OK");
2471  TList* notok_list = (TList*)id_type_list->FindObject("NOT OK");
2472  TList* print_list = 0;
2473  Int_t Nok = ok_list->GetEntries();
2474  Int_t Notok = notok_list->GetEntries();
2475  if (Nok && Notok) {
2476  if (Nok < Notok) print_list = ok_list;
2477  else print_list = notok_list;
2478  }
2479  if (Nok && (!Notok)) cout << " ALL telescopes are OK" << endl;
2480  else if (Notok && (!Nok)) cout << " NO telescopes are OK" << endl;
2481  else {
2482  cout << " " << ok_list->GetEntries() << " telescopes are OK, "
2483  << notok_list->GetEntries() << " telescopes are NOT OK" << endl;
2484  cout << " " << print_list->GetName() << " :" << endl;
2485  TIter it(print_list);
2486  TObject* ob = it();
2487  cout << ob->GetName();
2488  while ((ob = it())) cout << "," << ob->GetName();
2489  cout << endl;
2490  }
2491  cout << endl;
2492 
2493  }
2494 }
2495 
2496 
2497 
2498 
2506 
2508 {
2509  // Fill and return pointer to list fStatusIDTelescopes which contains
2510  // a list for each type of ID telescope in the array, each list contains a list
2511  // "OK" with the ID telescopes which have IsReadyForID()=kTRUE, and
2512  // a list "NOT OK" with the others.
2513  //
2514  // The returned TList object must not be deleted (it belongs to the KVMultiDetArray).
2515 
2516  if (!fStatusIDTelescopes) {
2517  fStatusIDTelescopes = new TList;
2519  }
2520  else {
2522  }
2524  TIter next(fIDTelescopes);
2525  KVIDTelescope* idt = 0;
2526  while ((idt = (KVIDTelescope*)next())) {
2527 
2528  TString id_type = idt->GetLabel();
2529  TList* id_type_list = (TList*)fStatusIDTelescopes->FindObject(id_type.Data());
2530  if (!id_type_list) {
2531  id_type_list = new TList;
2532  id_type_list->SetOwner(kTRUE);
2533  id_type_list->SetName(id_type.Data());
2534  fStatusIDTelescopes->Add(id_type_list);
2535  id_type_list->Add(new TList);
2536  ((TList*)id_type_list->At(0))->SetName("OK");
2537  id_type_list->Add(new TList);
2538  ((TList*)id_type_list->At(1))->SetName("NOT OK");
2539  }
2540  if (idt->IsReadyForID())
2541  ((TList*)id_type_list->FindObject("OK"))->Add(idt);
2542  else
2543  ((TList*)id_type_list->FindObject("NOT OK"))->Add(idt);
2544  }
2545  return fStatusIDTelescopes;
2546 }
2547 
2548 
2549 
2550 
2556 
2558 {
2559  // Create, fill and return pointer to a list of TObjString containing the name of each type
2560  // of ID telescope (actually the label) in the array.
2561  //
2562  // Delete the list after use (it owns the TObjString objects)
2563 
2564  KVUniqueNameList* type_list = new KVUniqueNameList(kTRUE);
2565  type_list->SetOwner();
2566  if (!fIDTelescopes || !fIDTelescopes->GetEntries()) return type_list;
2567  TIter next(fIDTelescopes);
2568  KVIDTelescope* idt = 0;
2569  while ((idt = (KVIDTelescope*)next())) {
2570  type_list->Add(new TObjString(idt->GetLabel()));
2571  }
2572  return type_list;
2573 }
2574 
2575 
2576 
2577 
2585 
2587 {
2588  // Create, fill and return pointer to a list of KVIDTelescopes with
2589  // the given type (label) in the array.
2590  // WARNING! - check pointer is not zero (we return NULL if ID telescopes
2591  // list is not defined or empty)
2592  //
2593  // Delete the KVList after use (it does not own the KVIDTelescopes).
2594 
2595  if (!fIDTelescopes || !fIDTelescopes->GetEntries()) return NULL;
2597 }
2598 
2599 
2600 
2601 
2609 
2611 {
2612  // Fill and return pointer to list fCalibStatusDets which contains
2613  // a list for each type of detector in the array, each list contains a list
2614  // "OK" with the detectors which are calibrated, and
2615  // a list "NOT OK" with the others.
2616  //
2617  // The returned TList object must not be deleted (it belongs to the KVMultiDetArray).
2618 
2619  if (!fCalibStatusDets) {
2620  fCalibStatusDets = new TList;
2622  }
2623  else {
2625  }
2626  if (!GetDetectors()->GetEntries()) return fCalibStatusDets;
2627  TIter next(GetDetectors());
2628  KVDetector* det = 0;
2629  while ((det = (KVDetector*)next())) {
2630 
2631  TString type = det->GetType();
2632  TList* type_list = (TList*)fCalibStatusDets->FindObject(type.Data());
2633  if (!type_list) {
2634  type_list = new TList;
2635  type_list->SetOwner(kTRUE);
2636  type_list->SetName(type.Data());
2637  fCalibStatusDets->Add(type_list);
2638  type_list->Add(new TList);
2639  ((TList*)type_list->At(0))->SetName("OK");
2640  type_list->Add(new TList);
2641  ((TList*)type_list->At(1))->SetName("NOT OK");
2642  }
2643  if (det->IsCalibrated())
2644  ((TList*)type_list->FindObject("OK"))->Add(det);
2645  else
2646  ((TList*)type_list->FindObject("NOT OK"))->Add(det);
2647  }
2648  return fCalibStatusDets;
2649 }
2650 
2651 
2652 
2653 
2657 
2659 {
2660  // Print full status report on calibration of detectors in array, using informations stored in
2661  // fCalibStatusDets (see GetCalibrationStatusOfDetectors).
2662 
2663  if (!GetCurrentRunNumber()) {
2664  Info("PrintCalibStatusOfDetectors", "Cannot know status without knowing RUN NUMBER");
2665  return;
2666  }
2667 
2668  cout << endl << "-----------STATUS OF CALIBRATIONS FOR RUN "
2669  << GetCurrentRunNumber() << "------------" << endl << endl;
2670 
2671  //update status infos
2673 
2674  TIter next_type(fCalibStatusDets);
2675  TList* id_type_list = 0;
2676  while ((id_type_list = (TList*)next_type())) {
2677 
2678  cout << " *** " << id_type_list->GetName() << " Detectors -------------------" << endl;
2679  TList* ok_list = (TList*)id_type_list->FindObject("OK");
2680  TList* notok_list = (TList*)id_type_list->FindObject("NOT OK");
2681  TList* print_list = 0;
2682  Int_t Nok = ok_list->GetEntries();
2683  Int_t Notok = notok_list->GetEntries();
2684  if (Nok && Notok) {
2685  if (Nok < Notok) print_list = ok_list;
2686  else print_list = notok_list;
2687  }
2688  if (Nok && (!Notok)) cout << " ALL calibrations are OK" << endl;
2689  else if (Notok && (!Nok)) cout << " NO calibrations are OK" << endl;
2690  else {
2691  cout << " " << ok_list->GetEntries() << " calibrations are OK, "
2692  << notok_list->GetEntries() << " calibrations are NOT OK" << endl;
2693  cout << " " << print_list->GetName() << " :" << endl;
2694  TIter it(print_list);
2695  TObject* ob = it();
2696  cout << ob->GetName();
2697  while ((ob = it())) cout << "," << ob->GetName();
2698  cout << endl;
2699  }
2700  cout << endl;
2701 
2702  }
2703 }
2704 
2705 
2706 
2707 
2723 
2725 {
2726  // Calculate the energy loss in the current target of the multidetector
2727  // for the reconstructed charged particle 'ion', assuming that the current
2728  // energy and momentum of this particle correspond to its state on
2729  // leaving the target.
2730  //
2731  // WARNING: for this correction to work, the target must be in the right 'state':
2732  //
2733  // gMultiDetArray->GetTarget()->SetIncoming(kFALSE);
2734  // gMultiDetArray->GetTarget()->SetOutgoing(kTRUE);
2735  //
2736  // (see KVTarget::GetParticleEIncFromERes).
2737  //
2738  // The returned value is the energy lost in the target in MeV.
2739  // The energy/momentum of 'ion' are not affected.
2740 
2741  if (fTarget && ion) return (fTarget->GetParticleEIncFromERes(ion) - ion->GetEnergy());
2742  return 0;
2743 }
2744 
2745 
2746 
2747 
2750 
2752 {
2753  // Return pointer to the (ROOT) geometry of the array.
2754  return gGeoManager;
2755 }
2756 
2757 
2758 
2760 
2762 {
2763  return fNavigator;
2764 }
2765 
2766 
2767 
2793 
2795 {
2796  // Actual thicknesses of detectors can be given in one or more files associated with a dataset.
2797  //
2798  // If the variable
2799  //
2800  //~~~~
2801  //[dataset].DetectorThicknessesFile: toto.dat
2802  //~~~~
2803  //
2804  // is defined for the current dataset, we expect toto.dat to contain a list of files to be read in order
2805  // to set dectector thicknesses. Note that the same detector may appear several times in the files.
2806  // In this case it is the thickness in the last file (in the order listed in toto.dat) which will remain.
2807  //
2808  // Otherwise, we look for a single file in the dataset directory with the name given by one or other of
2809  // the variables
2810  //
2811  //~~~~
2812  //KVMultiDetArray.DetectorThicknesses:
2813  //[dataset].KVMultiDetArray.DetectorThicknesses:
2814  //~~~~
2815  //
2816  // and, if found, we use it to set the detector thicknesses.
2817  //
2818  // See set_detector_thicknesses() for details of the format of the individual thickness files.
2819 
2820  // look for list of files
2821  TString filename = GetDataSetEnv(fDataSet, "DetectorThicknessesFile", "");
2822  if (filename != "") {
2823  KVFileReader fr;
2825  if (fr.OpenFileToRead(fullpath)) {
2826  while (fr.IsOK()) {
2827  fr.ReadLine(0);
2828  if (fr.GetCurrentLine().BeginsWith("#") || fr.GetCurrentLine() == "") continue;
2830  }
2831  return;
2832  }
2833  else {
2834  Warning("SetDetectorThicknesses", "Could not open DetectorThicknessesFile %s...", fullpath.Data());
2835  }
2836  return;
2837  }
2838  // look for single file
2839  filename = GetDataSetEnv(fDataSet, "KVMultiDetArray.DetectorThicknesses", "");
2840  if (filename == "") {
2841  Error("SetDetectorThicknesses", "*.KVMultiDetArray.DetectorThicknesses not defined in .kvrootrc");
2842  return;
2843  }
2844  TString fullpath;
2846  if (fullpath == "") {
2847  Info("SetDetectorThicknesses", "File %s not found", filename.Data());
2848  return;
2849  }
2850  set_detector_thicknesses(fullpath);
2851 }
2852 
2853 
2854 
2873 
2875 {
2876  // Use file given by fullpath to set the real thicknesses of the detectors.
2877  // Any detector which is not in the file will be left with its nominal thickness.
2878  //
2879  // EXAMPLE FILE:
2880  //
2881  //# thickness of detector DET01 in default units
2882  //DET01: 56.4627
2883  //
2884  //# DET03 has several layers
2885  //DET03.Abs0: 61.34
2886  //DET03.Abs1: 205.62
2887  //
2888  // !!! WARNING !!!
2889  // Single-layer detectors: The units are those defined by default for the detector's
2890  // Get/SetThickness methods.
2891  // Multi-layer: Each layer is a KVMaterial object. The thickness MUST be given in centimetres
2892  // (default thickness unit for KVMaterial).
2893 
2894  TEnv thickdat;
2895  if (thickdat.ReadFile(fullpath, kEnvUser) != 0) {
2896  Error("SetDetectorThicknesses", "Problem opening file %s", fullpath.Data());
2897  return;
2898  }
2899  Info("SetDetectorThicknesses", "Setting thicknesses of detectors from file %s", fullpath.Data());
2900  TIter next(GetDetectors());
2901  KVDetector* det;
2902  while ((det = (KVDetector*)next())) {
2903  if (thickdat.Defined(det->GetName())) {
2904  // simple single layer detector
2905  Double_t thick = thickdat.GetValue(det->GetName(), 0.0);
2906  det->SetThickness(thick);
2907  //Info("SetDetectorThicknesses", "Set thickness of %s to %f", det->GetName(), thick);
2908  }
2909  else {
2910  Char_t i = 0;
2911  TString absname;
2912  absname.Form("%s.Abs%d", det->GetName(), (Int_t)i);
2913  if (thickdat.Defined(absname.Data())) {
2914  // detector with several layers
2915  KVMaterial* abs = 0;
2916  while ((abs = det->GetAbsorber(i))) {
2917  Double_t thick = thickdat.GetValue(absname.Data(), 0.0);
2918  abs->SetThickness(thick);
2919  //Info("SetDetectorThicknesses", "Set thickness of %s.Abs%d to %f", det->GetName(), (Int_t)i, thick);
2920  i++;
2921  absname.Form("%s.Abs%d", det->GetName(), (Int_t)i);
2922  if (!thickdat.Defined(absname.Data())) break;
2923  }
2924  }
2925  }
2926  }
2927 }
2928 
2929 
2930 
2936 
2938 {
2939  // Define the geometry of the array with a valid ROOT geometry (TGeoManager instance)
2940  // If no name and/or title are defined for the array, the name and title of the TGeoManager
2941  // object will be used for the array.
2942  // ROOT geometry will be used by default from now on.
2943 
2944  if (!strcmp(GetName(), "")) SetName(g->GetName());
2945  if (!strcmp(GetTitle(), "")) SetTitle(g->GetTitle());
2946  SetROOTGeometry();
2947 }
2948 
2949 
2950 
2954 
2956 {
2957  // Calculate incident energy of particle (Z,A) required to punch through given detector,
2958  // taking into account any detectors which the particle must first cross in order to reach it.
2959 
2960  KVDetector* theDet = GetDetector(detector);
2961  if (!theDet) {
2962  Error("GetPunchThroughEnergy", "Detector %s not found in array", detector);
2963  return -1.0;
2964  }
2965  Double_t E0 = theDet->GetPunchThroughEnergy(Z, A);
2966  TIter alDets(theDet->GetAlignedDetectors());
2967  // first detector in list is theDet
2968  alDets.Next();
2969  KVDetector* D;
2970  while ((D = (KVDetector*)alDets.Next())) {
2971  Double_t E1 = D->GetIncidentEnergyFromERes(Z, A, E0);
2972  E0 = E1;
2973  }
2974  return E0;
2975 }
2976 
2977 
2978 
2983 
2985 {
2986  // Creates and fills a TGraph with the punch through energy in MeV vs. Z for the given detector,
2987  // for Z=1-92. The mass of each nucleus is calculated according to the given mass formula
2988  // (see KVNucleus).
2989 
2990  TGraph* punch = new TGraph(92);
2991  punch->SetName(Form("KVMultiDetpunchthrough_%s_mass%d", detector, massform));
2992  punch->SetTitle(Form("Array Punch-through %s (MeV) (mass formula %d)", detector, massform));
2993  KVNucleus nuc;
2994  nuc.SetMassFormula(massform);
2995  for (int Z = 1; Z <= 92; Z++) {
2996  nuc.SetZ(Z);
2997  punch->SetPoint(Z - 1, Z, GetPunchThroughEnergy(detector, nuc.GetZ(), nuc.GetA()));
2998  }
2999  return punch;
3000 }
3001 
3002 
3003 
3008 
3010 {
3011  // Creates and fills a TGraph with the punch through energy in MeV/nucleon vs. Z for the given detector,
3012  // for Z=1-92. The mass of each nucleus is calculated according to the given mass formula
3013  // (see KVNucleus).
3014 
3015  TGraph* punch = new TGraph(92);
3016  punch->SetName(Form("KVMultiDetpunchthroughEsurA_%s_mass%d", detector, massform));
3017  punch->SetTitle(Form("Array Punch-through %s (AMeV) (mass formula %d)", detector, massform));
3018  KVNucleus nuc;
3019  nuc.SetMassFormula(massform);
3020  for (int Z = 1; Z <= 92; Z++) {
3021  nuc.SetZ(Z);
3022  punch->SetPoint(Z - 1, Z, GetPunchThroughEnergy(detector, nuc.GetZ(), nuc.GetA()) / nuc.GetA());
3023  }
3024  return punch;
3025 }
3026 
3027 
3028 
3034 
3036 {
3037  // Creates and fills a TGraph with the Z vs. the punch-through velocity paralllel to the beam
3038  // direction in cm/ns for the given detector,
3039  // for Z=1-92. The mass of each nucleus is calculated according to the given mass formula
3040  // (see KVNucleus).
3041 
3042  TGraph* punch = new TGraph(92);
3043  punch->SetName(Form("KVMultiDetpunchthroughV_%s_mass%d", detector, massform));
3044  punch->SetTitle(Form("Array Punch-through %s (cm/ns) (mass formula %d)", detector, massform));
3045  KVNucleus nuc;
3046  nuc.SetMassFormula(massform);
3047  for (int Z = 1; Z <= 92; Z++) {
3048  nuc.SetZ(Z);
3049  nuc.SetE(GetPunchThroughEnergy(detector, nuc.GetZ(), nuc.GetA()));
3050  nuc.SetTheta(GetDetector(detector)->GetTheta());
3051  punch->SetPoint(Z - 1, nuc.GetVpar(), Z);
3052  }
3053  return punch;
3054 }
3055 
3056 
3057 
3061 
3063 {
3064  // Call with on=kTRUE if array uses ROOT geometry for tracking
3065  // Call SetGeometry(TGeoManager*) first with a valid geometry.
3066 
3067  fROOTGeometry = on;
3068  if (on && !gGeoManager) {
3069  Error("SetROOTGeometry", "ROOT geometry is requested, but has not been set: gGeoManager=0x0,\n Call CreateGeoManager() method first");
3070  return;
3071  }
3072 
3073  // set up geometry navigator
3075  else if (!on) SafeDelete(fNavigator);
3076 }
3077 
3078 
3079 
3108 
3110 {
3111  // Method for positioning volumes in detector geometries
3112  //
3113  // Given:
3114  //
3115  // distance [cm] = distance from target (origin) to the CENTRE of the volume in position
3116  // theta [deg] = polar angle of vector from target to centre of volume in position
3117  // phi [deg] = azimuthal angle of vector
3118  //
3119  // this method generates the matrix which is required to position the volume as required
3120  // while also turning the volume so that the side nearest the target (i.e. the entrance
3121  // window of the detector) remains perpendicular to the vector joining the origin and
3122  // the centre of the volume.
3123  //
3124  // If required, a further translation can be given which will be applied to the volume after
3125  // it has been placed with the required orientation at the nominal distance. This can be used
3126  // e.g. for detector misalignment, when detectors are in a structure which guarantees their line
3127  // of sight to be orthogonal to their surface at a nominal distance, but the nominal distance
3128  // is not respected.
3129  //
3130  // Example of use:
3131  //
3132  //~~~~~~~~~~~~
3133  // TGeoVolume* vol;// volume to be positioned
3134  // double depth = vol->GetShape()->GetDZ(); // half-width of volume in direction of target
3135  // // place front of volume at 100cm, with theta=45 deg. and phi=60 deg.
3136  // gGeoManager->GetTopVolume()->AddNode(vol, 1, KVMultiDetArray::GetVolumePositioningMatrix(100+depth,45,60));
3137  //~~~~~~~~~~~~
3138 
3139  TGeoRotation rot1, rot2;
3140  TGeoTranslation trans;
3141  phi += 90;
3142  rot1.SetAngles(-phi, 0, 0) ;
3143  rot2.SetAngles(phi, theta, 0) ;
3144  trans.SetDz(distance) ;
3145  TGeoHMatrix h;
3146  if (postTrans) h = (*postTrans) * rot2 * trans * rot1 ;
3147  else h = rot2 * trans * rot1;
3148  TGeoHMatrix* ph = new TGeoHMatrix(h);
3149  return ph;
3150 }
3151 
3152 
3153 
3161 
3163 {
3164  // *** Set 'segmentation' index of detectors ***
3165  // This is essential for particle reconstruction, judging whether particles can be identified
3166  // independently of any others in the same group etc.
3167  // Basically, any detector with >1 detector placed directly behind it has a seg. index = 0
3168  // if <=1 detector is directly behind, the seg. index = 1
3169  // This method is used for arrays imported from ROOT geometries.
3170 
3171  TIter next(GetDetectors());
3172  KVDetector* d;
3173  while ((d = (KVDetector*)next())) {
3174  if (d->GetNode()->GetNDetsBehind() > 1) d->SetSegment(0);
3175  else d->SetSegment(1);
3176  }
3177 }
3178 
3179 
3180 
3181 
3188 
3190 {
3191  //Create and add to list all ID telescopes made of this detector
3192  //and the aligned detectors placed in front of it.
3193  //
3194  //If list=0 then we store pointers to the ALREADY EXISTING ID telescopes
3195  //in det->fIDTelAlign. (first clear det->fIDTelAlign)
3196 
3197  if (!(det->IsOK())) return;
3198 
3199  TList* aligned = det->GetAlignedDetectors();
3200 
3201  Bool_t list_zero = kFALSE;
3202 
3203  if (!list) {
3204  list_zero = kTRUE;
3205  //the IDTelescopes created will be destroyed at the end,
3206  //once we have used their names to find pointers to the corresponding
3207  //telescopes in gMultiDetArray
3208  list = new KVList;
3209  //clear any existing list of aligned telescopes
3210  det->GetAlignedIDTelescopes()->Clear();
3211  }
3212 
3213  if (aligned->GetSize() > 1) {
3214  //pairwise looping through list
3215  for (int i = 0; i < (aligned->GetSize() - 1); i++) {
3216  KVDetector* det1 = (KVDetector*) aligned->At(i + 1);
3217  KVDetector* det2 = (KVDetector*) aligned->At(i);
3218 
3219  GetIDTelescopes(det1, det2, list);
3220  }
3221  }
3222  else {
3223  //The following line is in case there are no detectors aligned
3224  //with 'det', but 'det' acts as an IDTelescope all by itself.
3225  //In this case we expect KVMultiDetArray::GetIDTelescopes
3226  //to define the appropriate ID telescope whenever one of the
3227  //two detector arguments (or both!) corresponds to 'det''s type.
3228  GetIDTelescopes(det, det, list);
3229  }
3230 
3231  if (list_zero) {
3232  //now we use the created ID telescopes to find pointers to the already
3233  //existing identical telescopes in gMultiDetArray, stock them in
3234  //det->fIDTelAlign
3235  TIter next_tel(list);
3236  KVIDTelescope* tel;
3237  while ((tel = (KVIDTelescope*) next_tel())) {
3238  KVIDTelescope* trash = GetIDTelescope(tel->GetName());
3239  if (trash) {
3240  det->GetAlignedIDTelescopes()->Add(trash);
3241  // if telescope contains detector, add to detector's list of telescopes it belongs to
3242  if (trash->HasDetector(det)) det->AddIDTelescope(trash);
3243  }
3244  }
3245  //destroy the superfluous copy telescopes we just created
3246  list->Delete();
3247  delete list;
3248  }
3249 
3250 }
3251 
3252 
3253 
3267 
3269 {
3270  //Identify all the ways of identifying particles possible from the detectors
3271  //in the group, create the appropriate KVIDTelescope objects and add them to
3272  //the list pointed to by tel_list.
3273  //USER'S RESPONSIBILITY TO DELETE CONTENTS OF LIST!!
3274  //
3275  //Starting from each detector in the group,
3276  //we build ID telescopes from all pairs of aligned detectors.
3277  //
3278  //For each pair of detectors, it is KVMultiDetArray::GetIDTelescopes
3279  //which determines which KVIDTelescope class to use (specialise this method
3280  //in KVMultiDetArray child classes). It must also make sure that
3281  //each IDTelescope is added only once (i.e. check it is not already in the list).
3282 
3283  TIter next_det(grp->GetDetectors());
3284  KVDetector* det;
3285 
3286  while ((det = (KVDetector*) next_det())) {
3287  if (det->IsOK()) {
3288  //1st call: create ID telescopes, they will be added to the
3289  //gMultiDetArray list of IDTelescopes
3290  GetAlignedIDTelescopesForDetector(det, tel_list);
3291  //2nd call: set up in the detector a list of pointers to the
3292  //ID telescopes made up of it and all aligned detectors in front
3293  //of it
3295  }
3296  }
3297 }
3298 
3299 
3300 
3310 
3312 {
3313  //Casse tous les liens entre les detecteurs d un meme groupe
3314  //Retire de la liste gMultiDetArray->GetListOfIDTelescopes() les
3315  //telescopes associes et les efface apres les avoir
3316  //retires des grilles auxquelles ils etaient associees
3317  //pour preparer l ajout ou le retrait d un detecteur
3318  //voir KVDetector::SetPresent()
3319  //
3320  //
3321  KVNameValueList nv;
3322 
3323  KVDetector* det = 0;
3324  KVIDTelescope* id = 0;
3325 
3326  const KVSeqCollection* lgrdet = grp->GetDetectors();
3327  TIter nextdet(lgrdet);
3328  while ((det = (KVDetector*)nextdet())) {
3329  //Info("PrepareModif","On retire les detecteurs alignes pour %s",det->GetName());
3332  Int_t ntel = det->GetIDTelescopes()->GetEntries();
3333  for (Int_t ii = 0; ii < ntel; ii += 1) {
3334  id = (KVIDTelescope*)det->GetIDTelescopes()->At(0);
3335  if (id->GetDetectors()->FindObject(dd)) {
3336  nv.SetValue(id->GetName(), "");
3337  det->GetIDTelescopes()->RemoveAt(0);
3338  }
3339  }
3340  }
3341 
3343  for (Int_t ii = 0; ii < nv.GetEntries(); ii += 1) {
3344  id = (KVIDTelescope*)lidtel->FindObject(nv.GetNameAt(ii));
3345  //Info("PrepareModif","On retire et on detruit l'ID tel %s",id->GetName());
3346 
3347  if (id->GetListOfIDGrids()) {
3348  KVIDGraph* idg = 0;
3349  for (Int_t kk = 0; kk < id->GetListOfIDGrids()->GetEntries(); kk += 1) {
3350  idg = (KVIDGraph*)id->GetListOfIDGrids()->At(kk);
3351  idg->RemoveIDTelescope(id);
3352  }
3353  }
3354 
3355  //Info("PrepareModif","Je retire et j efface le idtel %s %s",id->GetName(),id->ClassName());
3356  delete lidtel->Remove(id);
3357  }
3358  nv.Clear();
3359 
3360 }
3361 
3362 
3363 
3376 
3378 {
3379  //
3380  // If present=kTRUE (default), detector is present
3381  // If present=kFALSE, detector has been removed
3382  // This method does nothing is required state is already current state.
3383  //
3384  // Methode applicable seulement pour un detecteur
3385  // etant le seul dans un telescope
3386  // ex les ChIo pour Indra
3387  //
3388  // This method as always to be call before
3389  // call the SetDetecting() method
3390 
3391  if (present == det->IsPresent())
3392  return;
3393 
3394  det->SetPresent(present);
3395 
3396  //On passe l etat d un detecteur de present a absent
3397  //
3398  KVTelescope* fTelescope = (KVTelescope*)det->GetParentStructure("TELESCOPE");
3399  if (!det->IsPresent()) {
3400 
3401  //Le detecteur etait l unique d un KVTelescope
3402  //on retire directement le KVTelescope
3403  if (fTelescope->GetDetectors()->GetEntries() == 1) {
3404  KVGroup* gr = (KVGroup*)fTelescope->GetParentStructure("GROUP");
3405 
3406  PrepareModifGroup(gr, det);
3407 
3408  gr->Remove(fTelescope);
3409  gr->Remove(det);
3411 
3412  }
3413  else {
3414  Warning("SetPresent", "Method implemented only in case detector is alone in telescope");
3415  }
3416  }
3417  //On remet le detecteur dans le groupe auquel il appartenait
3418  else {
3419 
3420  if (!det->GetGroup()) {
3421  KVGroup* gr = GetGroupWithAngles(det->GetTheta(), det->GetPhi());
3422 
3423  PrepareModifGroup(gr, det);
3424 
3425  gr->Add(fTelescope);
3426  gr->Add(det);
3427  gr->Sort();
3428  gr->CountLayers();
3430 
3431  }
3432 
3433  }
3434 
3435 }
3436 
3437 
3438 
3447 
3449 {
3450 
3451  // This method has effect only if detector is present
3452  //
3453  // If detecting=kTRUE (default), detector is detecting
3454  // If detecting=kFALSE, detector has been switch off or no gas or just dead
3455  // Does nothing if:
3456  // - detector already marked as absent
3457  // - required state is already current state
3458 
3459  if (!det->IsPresent())
3460  return;
3461 
3462  if (detecting == det->IsDetecting())
3463  return;
3464 
3465  det->SetDetecting(detecting);
3466  if (!det->IsDetecting()) {
3467  KVGroup* gr = det->GetGroup();
3468  PrepareModifGroup(gr, det);
3470  }
3471  else {
3472  KVGroup* gr = GetGroupWithAngles(det->GetTheta(), det->GetPhi());
3473  PrepareModifGroup(gr, det);
3475  }
3476 
3477 }
3478 
3479 
3480 
3484 
3486 {
3487  // For each grid which is valid for this run, we call the KVIDTelescope::SetIDGrid method
3488  // of each associated ID telescope.
3489 
3490  if (gIDGridManager->IsSQLROOT()) {
3491  gIDGridManager->LoadGridsForRun(run);
3492  }
3493 
3494  TIter next(gIDGridManager->GetGrids());
3495  KVIDGraph* gr = 0;
3496  while ((gr = (KVIDGraph*) next())) {
3497  if (!gIDGridManager->IsSQLROOT()) {
3498  if (!gr->GetRuns().Contains((Int_t) run))
3499  continue;
3500  }
3501  else
3503 
3504  TIter nxtid(gr->GetIDTelescopes());
3505  KVIDTelescope* idt;
3506  while ((idt = (KVIDTelescope*) nxtid())) {
3507  idt->SetIDGrid(gr);
3508  }
3509  }
3510 }
3511 
3512 
3516 
3518 {
3519  // Fill list of ID telescopes with which this grid is associated
3520  // from list of names read from ascii file.
3521 
3522  gr->ClearListOfTelescopes();
3523  if (gr->GetParameters()->HasParameter("IDTelescopes")) {
3524  KVString tel_list = gr->GetParameters()->GetStringValue("IDTelescopes");
3525  tel_list.Begin(",");
3526  while (!tel_list.End()) {
3527  TString tel_name = tel_list.Next();
3528  KVIDTelescope* idt = GetIDTelescope(tel_name.Data()) ;
3529  if (idt) gr->AddIDTelescope(idt);
3530  }
3531  }
3532 }
3533 
3534 
3535 
3545 
3547 {
3548  // Use OpenGL viewer to view multidetector geometry (only for ROOT geometries)
3549  //
3550  // If option="tracks" we draw any tracks corresponding to the last simulated
3551  // event whose detection was simulated with DetectEvent
3552  // If option="tracks:[numberlist]" with a list of numbers,
3553  // it will be interpreted as a KVNumberList containing the Z of tracks to be drawn
3554  // e.g. option="tracks:1-92" draw only tracks with 1<=Z<=92 (no neutrons)
3555  // option="tracks:2" draw only helium isotopes
3556  if (IsROOTGeometry()) {
3557  GetGeometry()->GetTopVolume()->Draw("ogl");
3558  KVString opt(option);
3559  opt.Begin(":");
3560  if (opt.Next() == "tracks") {
3561  if (!opt.End()) {
3562  KVNumberList zlist(opt.Next());
3563  GetNavigator()->DrawTracks(&zlist);
3564  }
3565  else
3566  GetNavigator()->DrawTracks();
3567  }
3568 #ifdef WITH_OPENGL
3569  TGLViewer* view = (TGLViewer*)gPad->GetViewer3D();
3572  view->SetSmoothLines(kTRUE);
3573  view->SetSmoothPoints(kTRUE);
3574 #endif
3575  }
3576  else Error("Draw", "Only ROOT geometries can be viewed");
3577 
3578 }
3579 
3580 
3581 
3583 
3585 {
3587 }
3588 
3589 
3590 
3595 
3597 {
3598  // Create TH2F histograms for all IDTelescopes of the array
3599  // They will be added to the list
3600  // histograms will have resolution of dimension*dimension
3601 
3603  KVIDTelescope* idt;
3604  while ((idt = (KVIDTelescope*)it())) {
3605  TString name(idt->GetName());
3606  name.ReplaceAll("-", "_");
3607  list->Add(new TH2F(name, Form("Hits in %s", idt->GetName()), dimension, 0., 0., dimension, 0., 0.));
3608  }
3609 }
3610 
3611 
3612 
3615 
3617 {
3618  // Fill TH2F histograms for all IDTelescopes of the array
3619 
3621  KVIDTelescope* idt;
3622  while ((idt = (KVIDTelescope*)it())) {
3623  TString name(idt->GetName());
3624  name.ReplaceAll("-", "_");
3625  TH2F* h = (TH2F*)list->FindObject(name);
3626  if (h) h->Fill(idt->GetIDMapX(), idt->GetIDMapY());
3627  }
3628 }
3629 
3630 
3631 
3634 
3636 {
3637  // Modify the transparency of detector volumes in OpenGL view
3638 
3639  TIter itV(GetGeometry()->GetListOfVolumes());
3640  TGeoVolume* vol;
3641  while ((vol = (TGeoVolume*)itV())) vol->SetTransparency(t);
3642 }
3643 
3644 
3645 
3649 
3651 {
3652  // Calculate all possible (sub-)trajectories
3653  // for particle reconstruction (GetReconTrajectories())
3654 
3655  unique_ptr<KVSeqCollection> groups(GetStructureTypeList("GROUP"));
3656  TIter it(groups.get());
3657  KVGroup* group;
3658  Int_t ntr = 0;
3659  Info("CalculateReconstructionTrajectories", "Calculating trajectories for particle reconstruction:");
3661  std::cout << "\xd" << " -- calculated " << ntr << " reconstruction trajectories" << std::flush;
3662  while ((group = (KVGroup*)it())) {
3663  ntr += group->CalculateReconstructionTrajectories();
3665  std::cout << "\xd" << " -- calculated " << ntr << " reconstruction trajectories" << std::flush;
3666  }
3668  std::cout << " -- calculated " << ntr << " reconstruction trajectories" << std::endl;
3669  else
3670  std::cout << std::endl;
3671 }
3672 
3673 
3674 
3681 
3683 {
3684  // Track over all possible particle trajectories calling
3685  // GetIDTelescopes(KVDetector*,KVDetector*)
3686  // for each pair of (present & functioning) detectors.
3687  // This will create all possible KVIDTelescope identification
3688  // objects and put them in list fIDTelescopes
3689 
3690  fIDTelescopes->Delete();
3691  TIter next_traj(GetTrajectories());
3692  KVGeoDNTrajectory* traj;
3693  Int_t count = 0;
3694  Info("DeduceIdentificationTelescopesFromGeometry", "Calculating...");
3696  std::cout << "\xd" << " -- created " << count << " telescopes" << std::flush;
3697  while ((traj = (KVGeoDNTrajectory*)next_traj())) { // loop over all trajectories
3698 
3699  traj->IterateFrom(); // from furthest-out to closest-in detector
3700 
3702  while ((N = traj->GetNextNode())) {
3703  KVGeoDetectorNode* Nplus1 = traj->GetNodeInFront(N);
3704 
3705  if (Nplus1) {
3706  count += GetIDTelescopes(Nplus1->GetDetector(), N->GetDetector(), traj->AccessIDTelescopeList());
3708  std::cout << "\xd" << " -- created " << count << " telescopes" << std::flush;
3709  }
3710  }
3711  }
3713  std::cout << " -- created " << count << " telescopes" << std::endl;
3714  else
3715  std::cout << std::endl;
3716 }
3717 
3718 
3719 
3723 
3725 {
3726  // Eliminate any trajectories which are just sub-trajectories of others
3727  // For each trajectory in list fTrajectories, we add a reference to the trajectory to each node on the trajectory
3728 
3729  TIter it(&fTrajectories);
3730  KVGeoDNTrajectory* tr;
3731  KVList duplicates;
3732  // look for duplicate sub-trajectories
3733  while ((tr = (KVGeoDNTrajectory*)it())) {
3734  int len_tr = tr->GetN();
3735  TIter it2(&fTrajectories);
3736  KVGeoDNTrajectory* tr2;
3737  while ((tr2 = (KVGeoDNTrajectory*)it2())) {
3738  if ((tr2 != tr) && (len_tr < tr2->GetN()) && (tr2->ContainsPath(tr))) {
3739  duplicates.Add(tr);
3740  break;
3741  }
3742  }
3743  }
3744  // remove duplicates
3745  if (duplicates.GetEntries()) {
3746  TIter it_dup(&duplicates);
3747  while ((tr = (KVGeoDNTrajectory*)it_dup())) {
3748  fTrajectories.Remove(tr);
3749  }
3750  Info("AssociateTrajectoriesAndNodes", "Removed %d duplicated sub-trajectories", duplicates.GetEntries());
3751  }
3752  Info("AssociateTrajectoriesAndNodes", "Calculated %d particle trajectories", fTrajectories.GetEntries());
3753  it.Reset();
3754  while ((tr = (KVGeoDNTrajectory*)it())) {
3755  tr->AddToNodes();
3756  }
3757 }
3758 
3759 
3760 
3762 
3764 {
3765  if (N->GetNTraj() > 1) {
3766  if (!multitraj_nodes.FindObject(N)) { // look for any detectors which are on multiple trajectories
3767  //cout << "multitraj node found: " << N->GetName() << " (" << N->GetNTraj() << ")" << endl;
3768  multitraj_nodes.Add(N);
3769  TIter tr(N->GetTrajectories());
3770  KVGeoDNTrajectory* traj;
3771  while ((traj = (KVGeoDNTrajectory*)tr())) { // for each trajectory associated with detector
3772  if (tried_trajectories.FindObject(traj)) continue; // trajectory already used
3773  tried_trajectories.Add(traj);
3774  traj->IterateFrom();
3775  KVGeoDetectorNode* node;
3776  while ((node = traj->GetNextNode())) { // store names of all detectors on trajectory
3777  detectors_of_group.Add(node);
3778  RecursiveTrajectoryClustering(node, tried_trajectories, multitraj_nodes, detectors_of_group);
3779  }
3780  }
3781  }
3782  }
3783  else if (N->GetNTraj() == 1) {
3784  // single-trajectory node.
3785  // work along trajectory adding nodes to group
3786  KVGeoDNTrajectory* traj = (KVGeoDNTrajectory*)N->GetTrajectories()->First();
3787  if (tried_trajectories.FindObject(traj)) return; // trajectory already used
3788  tried_trajectories.Add(traj);
3789  traj->IterateFrom();
3790  KVGeoDetectorNode* node;
3791  while ((node = traj->GetNextNode())) { // store names of all detectors on trajectory
3792  detectors_of_group.Add(node);
3793  RecursiveTrajectoryClustering(node, tried_trajectories, multitraj_nodes, detectors_of_group);
3794  }
3795  }
3796  else {
3797  // orphan node? single-detector array?
3798  detectors_of_group.Add(N);
3799  }
3800 }
3801 
3802 
3803 
3810 
3812 {
3813  // Create and return pointer to new KVGroupReconstructor for reconstructing particles
3814  // in the given group. Returns nullptr if group is not part of this array.
3815  //
3816  // Plugins for specific arrays can be defined as plugins using the name of the array:
3817  // +Plugin.KVGroupReconstructor: my_array my_group_reconstructor my_lib "my_group_reconstructor()"
3818 
3819  KVGroupReconstructor* gr(nullptr);
3820  if (GetGroup(g->GetName())) {
3821  // look for plugin
3823  if (!gr) gr = new KVGroupReconstructor;
3824  }
3825  return gr;
3826 }
3827 
3828 
3829 
3833 
3835 {
3836  // Call this method just after opening a raw data file in order to perform any
3837  // necessary initialisations, depending on the type of data
3838 
3839 #ifdef WITH_BUILTIN_GRU
3840  if (r->GetDataFormat() == "EBYEDAT")
3841  dynamic_cast<KVGANILDataReader*>(r)->ConnectRawDataParameters();
3842 #endif
3843 }
3844 
3845 
3846 
3851 
3853 {
3854  // Deduce the "groups" in the array from the trajectories
3855  // Any trajectories with 1 or more common detectors define a group.
3856  // The group is constituted of all detectors belonging to the trajectories of the group.
3857 
3858  Info("DeduceGroupsFromTrajectories", "Deducing groups of detectors from trajectories");
3859  Int_t number_of_groups = 0;
3860  TIter next_det(GetDetectors());
3861  unique_ptr<KVSeqCollection> stl(GetStructureTypeList("GROUP"));
3862  if (stl.get() && stl->GetEntries()) {
3863  Info("DeduceGroupsFromTrajectories", "Deleting existing %d groups in array", stl->GetEntries());
3864  ClearStructures("GROUP");
3865  Info("DeduceGroupsFromTrajectories", "Done");
3866  }
3867  KVDetector* det;
3868  KVUniqueNameList tried_trajectories;//avoid double-counting/infinite loops
3869  KVUniqueNameList multitraj_nodes;//avoid double-counting/infinite loops
3870  while ((det = (KVDetector*) next_det())) {
3871  if (det->GetGroup()) continue; // group assignment already done
3872  KVUniqueNameList detectors_of_group;
3873  RecursiveTrajectoryClustering(det->GetNode(), tried_trajectories, multitraj_nodes, detectors_of_group);
3874  if (!detectors_of_group.GetEntries()) continue;
3875  KVGroup* Group = new KVGroup;
3876  Group->SetNumber(++number_of_groups);
3877  Add(Group);
3878  TIter next_node(&detectors_of_group);
3880  while ((d = (KVGeoDetectorNode*)next_node())) Group->Add(d->GetDetector());
3881  }
3882  TIter tr(&fTrajectories);
3883  KVGeoDNTrajectory* t;
3884  Info("DeduceGroupsFromTrajectories", "Filling group trajectory lists");
3885  while ((t = (KVGeoDNTrajectory*)tr())) {
3886  if (t->GetNodeAt(0)->GetDetector()->GetGroup())
3887  t->GetNodeAt(0)->GetDetector()->GetGroup()->AddTrajectory(t);
3888  else {
3889  t->Print();
3890  t->GetNodeAt(0)->GetDetector()->Print();
3891  }
3892  }
3893 }
3894 
3895 
3896 
3900 
3902 {
3903  // Called when required to fill KVReconstructedNucleus::fDetList with pointers to
3904  // the detectors whose names are stored in KVReconstructedNucleus::fDetNames.
3905 
3906  DetList->Clear();
3907  DetNames.Begin("/");
3908  while (!DetNames.End()) {
3909  KVDetector* det = GetDetector(DetNames.Next(kTRUE));
3910  if (det) DetList->Add(det);
3911  }
3912 }
3913 
3914 
3915 
3935 
3937 {
3938  // Set status of particle by comparing its identification/calibration codes
3939  // with those set as acceptable in fAcceptIDCodes and fAcceptECodes.
3940  // The status can be tested with method KVReconstructedNucles::IsOK().
3941  //
3942  // The default lists are defined in variables of the form
3943  //```
3944  // [DataSet].[name].ReconstructedNuclei.AcceptIDCodes: [list]
3945  // [DataSet].[name].ReconstructedNuclei.AcceptECodes: [list]
3946  //```
3947  // where:
3948  // + `DataSet` is an optional dataset name for dataset-specific lists
3949  // + `name` is the name of the multidetector array
3950  // + `list` is a numeric list (KVNumberList format)
3951  //
3952  // The default lists can be overridden using methods AcceptIDCodes(), AcceptECodes(),
3953  // AcceptAllIDCodes() and AcceptAllECodes().
3954  //
3955  // If either list is empty, no selection is made for the corresponding code
3956 
3957  Bool_t ok = kTRUE;
3959  if (!fAcceptECodes.IsEmpty()) ok = ok && fAcceptECodes.Contains(NUC->GetECode());
3960  NUC->SetIsOK(ok);
3961 }
3962 
3963 
3964 #ifdef WITH_BUILTIN_GRU
3965 
3968 
3970 {
3971  // General method for reading raw data in old GANIL ebyedat format
3972  AbstractMethod("handle_raw_data_event_ebyedat");
3973  return kFALSE;
3974 }
3975 
3976 #endif
3977 
3978 
3981 
3983 {
3984  // reset acquisition parameters etc. before reading new raw data event
3985 
3988  fHandledRawData = false;
3989  // reset fired signals
3990  TIter nxt(&fFiredSignals);
3991  KVDetectorSignal* ds;
3992  while ((ds = (KVDetectorSignal*)nxt())) {
3993  ds->SetFired(false);
3994  ds->SetValue(0);
3995  }
3996  fFiredSignals.Clear();
3997 }
3998 
3999 
4000 
4008 
4010 {
4011  // Perform any operations to finalise the description of the multidetector
4012  // which can only be done once the geometry is closed, e.g. use KVGeoImport
4013  // to set up nodes, trajectories, detectors, idtelescopes, etc.
4014  // This has to be kept separate for use with KVExpSetUp which first fills
4015  // a single ROOT geometry with all component KVMultiDetArray geometries,
4016  // then closes the geometry only when all have been built.
4017 }
4018 
4019 
4020 
4023 
4025 {
4026  // Copy any parameters in fReconParameters in to the reconstructed event parameter list
4027  *(e->GetParameters()) += fReconParameters;
4028 }
4029 
4030 
4031 
4044 
4046 {
4047  // values of fired raw data signals (acquisition parameters) from last read raw event
4048  // are copied to the fReconParameters list of parameters to be stored with the
4049  // reconstructed event.
4050  //
4051  // the format for each signal is:
4052  //
4053  // ACQPAR.[array].[detector].[signal]
4054  // ACQPAR.[array].[signal]
4055  //
4056  // in the first case for signals associated with detectors, in the latter case signals
4057  // which are not associated with a detector
4058 
4059  TIter it(GetFiredSignals());
4060  KVDetectorSignal* o;
4061  while ((o = (KVDetectorSignal*)it())) {
4062  fReconParameters.SetValue(Form("ACQPAR.%s.%s", GetName(), o->GetFullName().Data()), o->GetValue());
4063  }
4064 }
4065 
4066 
4067 
4076 
4078 {
4079  // Update array according to last event read using the KVRawDataReader object
4080  // (it is assumed that KVRawDataReader::GetNextEvent() was called before calling this method)
4081  //
4082  // Return kTRUE if raw data was treated
4083  //
4084  // All fired acquisition parameters are written in the fReconParameters list,
4085  // ready to be copied to the reconstructed event
4086 
4087  fRawDataReader = rawdata;
4089  if (rawdata->GetDataFormat() == "MFM") {
4090 #ifdef WITH_MFM
4092 #endif
4093  }
4094  else if (rawdata->GetDataFormat() == "PROTOBUF") {
4095 #ifdef WITH_PROTOBUF
4097 #endif
4098  }
4099  else if (rawdata->GetDataFormat() == "EBYEDAT") {
4100 #ifdef WITH_BUILTIN_GRU
4102 #endif
4103  }
4104  if (fHandledRawData) {
4106  }
4107  return fHandledRawData;
4108 }
4109 
4110 
4111 #ifdef WITH_MFM
4112 
4121 
4123 {
4124  // Update array according to last event read from MFM buffer
4125  // (it is assumed that MFMBufferReader::ReadNextFrame() was called before calling this method)
4126  //
4127  // Return kTRUE if raw data was treated
4128  //
4129  // All fired acquisition parameters are written in the fReconParameters list,
4130  // ready to be copied to the reconstructed event
4131 
4133  bool ok = false;
4134  ok = handle_raw_data_event_mfmfile(bufrdr);
4135  if (ok) {
4137  }
4138  return ok;
4139 }
4140 
4141 #endif
4142 
4143 
4154 
4156 {
4157  // Given a pointer to a detector (may be nullptr) try to set the data sig_data in the associated signal
4158  // of the given type, sig_typ.
4159  //
4160  // If the signal does not exist for the detector, it will be created.
4161  //
4162  // If detector pointer is null, the signal will be looked for in fExtraRawDataSignals
4163  // and created if necessary.
4164  //
4165  // All fired detectors and signals are added to the lists fFiredDetectors and fFiredSignals.
4166 
4167  KVDetectorSignal* det_signal = nullptr;
4168  if (detector) {
4169  det_signal = detector->GetDetectorSignal(sig_type);
4170  if (!det_signal) {
4171  det_signal = detector->AddDetectorSignal(sig_type);
4172  }
4173  fFiredDetectors.Add(detector);
4174  }
4175  else {
4176  // raw data not associated with a detector
4177  TString sig_name;
4178  if (detname != "") sig_name = Form("%s.%s", detname.Data(), sig_type.Data());
4179  else sig_name = sig_type;
4180  det_signal = fExtraRawDataSignals.get_object<KVDetectorSignal>(sig_name);
4181  if (!det_signal) {
4182  det_signal = new KVDetectorSignal(sig_name);
4183  fExtraRawDataSignals.Add(det_signal);
4184  }
4185  }
4186  if (det_signal) {
4187  det_signal->SetValue(sig_data);
4188  det_signal->SetFired();
4189  fFiredSignals.Add(det_signal);
4190  }
4191 }
4192 
4193 
4194 
4200 
4202 {
4203  // Take values 'ACQPAR.[array_name].[detname].[signal]' or 'ACQPAR.[array_name].[signal]'
4204  // in the parameter list and use them to set values of raw acquisition parameters.
4205  //
4206  // Any detector signals which don't already exist will be created
4207 
4208  prepare_to_handle_new_raw_data(); // clear previous fired parameters/detectors
4209  int N = l.GetNpar();
4210  for (int i = 0; i < N; ++i) {
4211  KVNamedParameter* np = l.GetParameter(i);
4212 
4213  KVString name(np->GetName());
4214  if (name.BeginsWith("ACQPAR")) {
4215  // 3 '.' => 4 values means associated detector
4216  // 2 '.' => 3 values means no detector
4217  int dots = name.GetNValues(".");
4218  bool with_det = (dots == 4);
4219  assert(with_det || (dots == 3)); // sanity check
4220  name.Begin(".");
4221  name.Next(); // "ACQPAR"
4222  if (name.Next() != GetName()) continue; // check name of array - somebody else's parameter ?
4223  KVString det_name;
4224  KVString sig_type;
4225  KVDetector* det = nullptr;
4226  if (with_det) {
4227  det_name = name.Next();
4228  sig_type = name.Next();
4229  det = GetDetector(det_name);
4230  }
4231  else {
4232  sig_type = name.Next();
4233  }
4234  add_and_set_detector_signal(det, det_name, np->GetDouble(), sig_type);
4235  }
4236  }
4237 }
4238 
4239 
4240 
4259 
4261 {
4262  // We first look for following files with the name given by
4263  //
4264  // [dataset].[name].OoODetectors: [name.OoODetectors.dat]
4265  // which should contain the runlists for each malfunctioning detector.
4266  // If found we add to the experiment database a table '[name].OoO Detectors' where [name] is the name of this array.
4267  //
4268  // [dataset].[name].AbsentDetectors: [name.AbsentDetectors.dat]
4269  // which should contain the runlists for each absent detector.
4270  // If found we add to the experiment database a table '[name].Absent Detectors' where [name] is the name of this array.
4271  //
4272  // Then we look for a file with the name given by
4273  //
4274  // [dataset].[name].CalibrationFiles: [CalibrationFiles.dat]
4275  //
4276  // which should contain the names of files to read with each type of calibration
4277  // If found we add to the experiment database a table '[name].Calibrations' where [name] is the name of this array,
4278  // containing all calibrations as KVDBParameterSet objects with the name of the detector concerned.
4279  db->SetDBType(Form("%sDB", GetName()));
4280  ReadOoODetectors(db);
4281  ReadAbsentDetectors(db);
4283 }
4284 
4285 
4286 
4288 
4290 {
4291  TString basic_name = db->GetCalibFileName(keyw);
4292  if (basic_name == "") {
4293  Info(meth, "No name found for \"%s\" file", keyw);
4294  return "";
4295  }
4296  Info(meth, "Search for %s for dataset %s ...", basic_name.Data(), fDataSet.Data());
4297  TString fp;
4298  SearchKVFile(basic_name.Data(), fp, fDataSet);
4299  if (fp == "") {
4300  Info(meth, "\tNo file found ...");
4301  }
4302  return fp;
4303 }
4304 
4305 
4306 
4308 
4309 unique_ptr<KVFileReader> KVMultiDetArray::GetKVFileReader(KVExpDB* db, const Char_t* meth, const Char_t* keyw)
4310 {
4311 
4312  TString fp = GetFileName(db, meth, keyw);
4313  if (fp == "")
4314  return unique_ptr<KVFileReader>();
4315 
4316  unique_ptr<KVFileReader> fr(new KVFileReader());
4317  if (!fr->OpenFileToRead(fp.Data())) {
4318  Error(meth, "Error in opening file %s", fp.Data());
4319  fr.reset(nullptr);
4320  }
4321  else
4322  Info(meth, "Reading %s file", fp.Data());
4323  return fr;
4324 }
4325 
4326 
4327 
4329 
4331 {
4332 
4333  unique_ptr<KVFileReader> fr = GetKVFileReader(db, "ReadCalibrationFiles()", "CalibrationFiles");
4334  if (!fr.get())
4335  return;
4336 
4337  KVDBTable* calib_table = db->AddTable(Form("%s.Calibrations", GetName()), Form("Calibrations for %s", GetName()));
4338  while (fr->IsOK()) {
4339  fr->ReadLine(0);
4340  if (fr->GetCurrentLine().BeginsWith("#") || fr->GetCurrentLine() == "") {}
4341  else {
4342  ReadCalibFile(fr->GetCurrentLine().Data(), db, calib_table);
4343  }
4344  }
4345  fr->CloseFile();
4346 }
4347 
4348 
4349 
4390 
4391 void KVMultiDetArray::ReadCalibFile(const Char_t* filename, KVExpDB* db, KVDBTable* calib_table)
4392 {
4393  // Read a calibration file with the format
4394  //
4395  //~~~~~~~~~~~~~
4396  // RunList: 1546-7485
4397  // SignalIn: PG
4398  // SignalOut: Volts
4399  // CalibType: ChannelVolt
4400  // CalibOptions: func=pol3,min=0,max=1
4401  // ZRange: 2-92
4402  // [detector1]: 0.0,0.261829,0.0
4403  // [detector2]: 0.1,0.539535,1.2
4404  //~~~~~~~~~~~~~
4405  //
4406  //The `[RunList]` is optional: if not given, the calibration will be applied to all runs in the database.
4407  //
4408  //If different parameters are required for different sets of runs, they should be written in different
4409  //files (all of which are listed in `CalibrationFiles.dat` or `[array].CalibrationFiles.dat`).
4410  //
4411  //The `[CalibClass]`, if given, must correspond to a KVCalibrator plugin name. The list of plugin names and the corresponding
4412  //classes can be retrieved with
4413  //
4414  //~~~~~~~~~~~
4415  //KVBase::GetListOfPlugins("KVCalibrator")
4416  //KVBase::GetListOfPluginURIs("KVCalibrator")
4417  //~~~~~~~~~~~
4418  //
4419  //KVCalibrator objects are added to detectors as required by the contents of calibration files.
4420  //If any detector has an existing calibrator of type `[CalibType]` which is not of the given class
4421  //it will be replaced with a new calibrator corresponding to the plugin.
4422  //
4423  //The `[CalibOptions]` is optional: list in `[CalibOptions]` will be used
4424  //to complete set-up of any new calibrator objects by calling the KVCalibrator::SetOptions()
4425  //method.
4426  //
4427  //`[CalibOptions]` should hold a comma-separated list of `parameter=value` pairs which will be used
4428  //to fill a KVNameValueList for the method call. See the KVCalibrator::SetOptions() method.
4429  //
4430  //`[ZRange]` is an option if several calibrations need to be used to provide the same signal
4431  //for certain detectors depending on the atomic number Z of the particle detected.
4432 
4433 
4434  TString fullpath = "";
4435  if (!SearchKVFile(filename, fullpath, fDataSet)) {
4436  Info("ReadCalibFile", "%s does not exist or not found", filename);
4437  return;
4438  }
4439 
4440  Info("ReadCalibFile", "file : %s found", fullpath.Data());
4441  TEnv env;
4442  env.ReadFile(fullpath, kEnvAll);
4443 
4444  // read options from file
4445  KVNameValueList options;
4446  KVString opt_list = "RunList SignalIn SignalOut CalibType CalibClass CalibOptions ZRange";
4447  opt_list.Begin(" ");
4448  while (!opt_list.End()) {
4449  KVString opt = opt_list.Next();
4450  KVString opt_val = env.GetValue(opt, "");
4451  opt_val.Remove(TString::kBoth, ' ');
4452  options.SetValue(opt, opt_val.Data());
4453  }
4454  // check for stupid spellnig mitskaes
4455  if (TString(env.GetValue("Runlist", "")) != "") {
4456  Warning("ReadCalibFile", "Calibration has 'Runlist' parameter (ignored): %s, did you mean 'RunList'?", env.GetValue("Runlist", ""));
4457  }
4458 
4459  if (options.GetTStringValue("SignalIn") == "") {
4460  Error("ReadCalibFile", "No input signal defined : SignalIn");
4461  return;
4462  }
4463  if (options.GetTStringValue("SignalOut") == "") {
4464  Error("ReadCalibFile", "No output signal defined : SignalOut");
4465  return;
4466  }
4467  if (options.GetTStringValue("CalibType") == "") {
4468  Error("ReadCalibFile", "No calibration type defined : CalibType");
4469  return;
4470  }
4471  Bool_t check_class(options.GetTStringValue("CalibClass") != "");
4472  TString calibrator_class;
4473  if (check_class) {
4474  TPluginHandler* ph = LoadPlugin("KVCalibrator", options.GetStringValue("CalibClass"));
4475  if (ph) calibrator_class = ph->GetClass();
4476  else {
4477  Error("ReadCalibFile", "No calibrator plugin of type %s", options.GetStringValue("CalibClass"));
4478  return;
4479  }
4480  }
4481 
4482  KVString clop;
4483  if (options.HasParameter("CalibOptions")) clop = options.GetStringValue("CalibOptions");
4484 
4485  KVString zrange;
4486  if (options.HasParameter("ZRange")) zrange = options.GetStringValue("ZRange");
4487 
4488  KVNumberList run_list = db->GetRunList();
4489  if (options.GetTStringValue("RunList") != "") {
4490  run_list.Set(options.GetTStringValue("RunList"));
4491  Info("ReadCalibFile", "Calibration used for runs %s", run_list.AsString());
4492  }
4493  else {
4494  Info("ReadCalibFile", "Calibration used for all runs in database");
4495  }
4496 
4497  TIter next(env.GetTable());
4498  TEnvRec* rec = 0;
4499  KVDBParameterSet* par = 0;
4500 
4501  while ((rec = (TEnvRec*)next())) {
4502 
4503  TString sname(rec->GetName());
4504  KVDetector* det = GetDetector(sname);
4505  if (!det) continue;
4506 
4507  KVString lval(rec->GetValue());
4508  par = new KVDBParameterSet(sname.Data(), options.GetStringValue("CalibType"), lval.GetNValues(","));
4509  par->SetParameter("SignalIn", options.GetStringValue("SignalIn"));
4510  par->SetParameter("SignalOut", options.GetStringValue("SignalOut"));
4511  // put infos on required calibrator class into database so that it can be replaced
4512  // as needed in SetCalibratorParameters
4513  par->SetParameter("CalibClass", options.GetStringValue("CalibClass"));
4514  if (clop != "") par->SetParameter("CalibOptions", clop);
4515  if (zrange != "") par->SetParameter("ZRange", zrange);
4516  Int_t np = 0;
4517  lval.Begin(",");
4518  while (!lval.End()) {
4519  par->SetParameter(np++, lval.Next().Atof());
4520  }
4521  calib_table->AddRecord(par);
4522  db->LinkRecordToRunRange(par, run_list);
4523 
4524  }
4525 }
4526 
4527 
4528 #ifdef WITH_MFM
4529 
4535 
4537 {
4538  // Update array according to last event read using the KVMFMDataFileReader object
4539  // (it is assumed that KVRawDataReader::GetNextEvent() was called before calling this method)
4540  //
4541  // Return kTRUE if raw data was treated
4542 
4543  if (mfmreader.IsFrameReadMerge()) {
4544  return handle_raw_data_event_mfmmergeframe(mfmreader.GetMergeManager());
4545  }
4546  else {
4547  return handle_raw_data_event_mfmframe(mfmreader.GetFrameRead());
4548  }
4549  return kFALSE;
4550 }
4551 
4552 
4553 
4557 
4558 Bool_t KVMultiDetArray::handle_raw_data_event_mfmmergeframe(const MFMMergeFrameManager& mergeframe)
4559 {
4560  // Method used to handle merged MFM frames
4561  // We call handle_raw_data_event_mfmframe() for each frame contained in the merge
4562 
4563  Bool_t ok = false;
4564  while (mergeframe.ReadNextFrame()) {
4565  Bool_t me = handle_raw_data_event_mfmframe(mergeframe.GetFrameRead());
4566  ok = (ok || me);
4567  }
4568  return ok;
4569 }
4570 
4571 
4572 
4583 
4585 {
4586  // Method used to treat raw data in MFM format read by KVMFMDataFileReader
4587  //
4588  // Here we dispatch two types of frame - MFMEbyedatFrame & MFMMesytecMDPPFrame -
4589  // to specific methods - handle_raw_data_event_mfmframe_ebyedat() and
4590  // handle_raw_data_event_mfmframe_mesytec_mdpp()
4591  // which need to be implemented in child classes for specific arrays which
4592  // use these data formats.
4593  //
4594  // Return kTRUE if raw data was treated
4595 #ifdef WITH_MESYTEC
4596  if (mfmframe.GetFrameType() == MFM_MESYTEC_MDPP_FRAME_TYPE)
4597  return handle_raw_data_event_mfmframe_mesytec_mdpp((const MFMMesytecMDPPFrame&)mfmframe);
4598 #endif
4599  if (mfmframe.GetFrameType() == MFM_EBY_EN_FRAME_TYPE
4600  || mfmframe.GetFrameType() == MFM_EBY_TS_FRAME_TYPE
4601  || mfmframe.GetFrameType() == MFM_EBY_EN_TS_FRAME_TYPE)
4602  return handle_raw_data_event_mfmframe_ebyedat((const MFMEbyedatFrame&)mfmframe);
4603 
4604  return kFALSE;
4605 }
4606 
4607 
4608 
4611 
4613 {
4614  // Read a raw data event from a EBYEDAT MFM Frame.
4615 
4616  AbstractMethod("handle_raw_data_event_mfmframe_ebyedat");
4617  return kFALSE;
4618 }
4619 
4620 
4621 #ifdef WITH_MESYTEC
4622 
4625 
4626 Bool_t KVMultiDetArray::handle_raw_data_event_mfmframe_mesytec_mdpp(const MFMMesytecMDPPFrame&)
4627 {
4628  // Read a raw data event from a Mesytec MFM Frame.
4629 
4630  AbstractMethod("handle_raw_data_event_mfmframe_mesytec_mdpp");
4631  return kFALSE;
4632 }
4633 
4634 #endif
4635 #endif
4636 
4637 #ifdef WITH_PROTOBUF
4638 
4640 
4642 {
4643  AbstractMethod("handle_raw_data_event_protobuf");
4644  return kFALSE;
4645 }
4646 
4647 #endif
4648 
4649 
4652 
4654 {
4655  // For each IDtelescope in array, calculate an identification grid
4656 
4657  TIter nxtid(GetListOfIDTelescopes());
4658  KVIDTelescope* idt;
4659  while ((idt = (KVIDTelescope*) nxtid())) {
4660  idt->CalculateDeltaE_EGrid("1-92", 0, 20);
4661  }
4662 }
4663 
4664 
4665 
4670 
4672 {
4673  // Sets status of detectors (KVDetector::IsPresent() and KVDetector::IsWorking()) for a given run of a dataset.
4674  //
4675  // If 'myname' is given, we look in database table "myname.OoODets"
4676 
4677  KVRList* absdet = (myname != "" ? kvrun->GetLinks(Form("%s.Absent Detectors", myname.Data())) : kvrun->GetLinks("Absent Detectors"));
4678  KVRList* ooodet = (myname != "" ? kvrun->GetLinks(Form("%s.OoO Detectors", myname.Data())) : kvrun->GetLinks("OoO Detectors"));
4679 
4680  TIter next(GetDetectors());
4681  KVDetector* det;
4682 
4683  Int_t ndet_absent = 0;
4684  Int_t ndet_ooo = 0;
4685  TString absent_dets, ooo_dets;
4686 
4687  while ((det = (KVDetector*)next())) {
4688  //Test de la presence ou non du detecteur
4689  if (!absdet) {
4690  det->SetPresent();
4691  }
4692  else {
4693  if (absdet->FindObject(det->GetName())) {
4694  det->SetPresent(kFALSE);
4695  if (ndet_absent) absent_dets += ",";
4696  absent_dets += det->GetName();
4697  ndet_absent += 1;
4698  }
4699  else {
4700  det->SetPresent();
4701  }
4702  }
4703  if (det->IsPresent()) {
4704  //Test du bon fonctionnement ou non du detecteur
4705  if (!ooodet) {
4706  det->SetDetecting();
4707  }
4708  else {
4709  if (ooodet->FindObject(det->GetName())) {
4710  det->SetDetecting(kFALSE);
4711  if (ndet_ooo) ooo_dets += ",";
4712  ooo_dets += det->GetName();
4713  ndet_ooo += 1;
4714  }
4715  else {
4716  det->SetDetecting();
4717  }
4718  }
4719  }
4720  }
4721 
4722  if (ndet_absent) Info("CheckStatusOfDetectors", "%d detectors absent during run : %s", ndet_absent, absent_dets.Data());
4723  else Info("CheckStatusOfDetectors", "All detectors present during run");
4724  if (ndet_ooo) Info("CheckStatusOfDetectors", "%d detectors malfunctioned during run : %s", ndet_ooo, ooo_dets.Data());
4725  else Info("CheckStatusOfDetectors", "All detectors functioning during run");
4726 }
4727 
4728 
4729 
4731 
4733 {
4734  CheckStatusOfDetectors(dbr, myname);
4735 }
4736 
4737 
4738 
4753 
4755 {
4756  // Read a file containing runlists for each temporarily non-functioning detector.
4757  //
4758  // The file should be in TEnv format like so:
4759  //
4760  //~~~~
4761  // DET_1: 100-122,541-1938
4762  // DET_2,DET_3: 91-765
4763  //~~~~
4764  //
4765  // i.e. more than one detector can be associated with the same runs (comma-separated list of
4766  // detector names) and the list of runs are given using KVNumberList syntax.
4767  //
4768  // The data is added to the database in a table '[name].OoO Detectors' with the name of this array.
4769 
4770  TString fullpath;
4771  if (!db->FindCalibFile("OoODet", fullpath, GetName())) return;
4772 
4773  Info("ReadOoODetectors()", "Reading lists of out-of-order detectors...");
4774  auto fOoODet = db->AddTable(Form("%s.OoO Detectors", GetName()), "Name of out of order detectors");
4775 
4776  KVDBRecord* dbrec = 0;
4777  TEnv env;
4778  TEnvRec* rec = 0;
4779  env.ReadFile(fullpath.Data(), kEnvAll);
4780  TIter it(env.GetTable());
4781 
4782  while ((rec = (TEnvRec*)it.Next())) {
4783  KVString srec(rec->GetName());
4784  KVNumberList nl(rec->GetValue());
4785  if (srec.Contains(",")) {
4786  srec.Begin(",");
4787  while (!srec.End()) {
4788  dbrec = new KVDBRecord(srec.Next(kTRUE), "OoO Detector");
4789  dbrec->AddKey("Runs", "List of Runs");
4790  fOoODet->AddRecord(dbrec);
4791  db->LinkRecordToRunRange(dbrec, nl);
4792  }
4793  }
4794  else {
4795  dbrec = new KVDBRecord(rec->GetName(), "OoO Detector");
4796  dbrec->AddKey("Runs", "List of Runs");
4797  fOoODet->AddRecord(dbrec);
4798  db->LinkRecordToRunRange(dbrec, nl);
4799  }
4800  }
4801 }
4802 
4803 
4818 
4820 {
4821  // Read a file containing runlists for each temporarily absent/dismounted detector.
4822  //
4823  // The file should be in TEnv format like so:
4824  //
4825  //~~~~
4826  // DET_1: 100-122,541-1938
4827  // DET_2,DET_3: 91-765
4828  //~~~~
4829  //
4830  // i.e. more than one detector can be associated with the same runs (comma-separated list of
4831  // detector names) and the list of runs are given using KVNumberList syntax.
4832  //
4833  // The data is added to the database in a table '[name].Absent Detectors' with the name of this array.
4834 
4835  TString fullpath;
4836  if (!db->FindCalibFile("AbsentDet", fullpath, GetName())) return;
4837 
4838  Info("ReadAbsentDetectors()", "Reading lists of absent/dismounted detectors... file=[%s]", fullpath.Data());
4839  auto fAbsDet = db->AddTable(Form("%s.Absent Detectors", GetName()), "Name of out of order detectors");
4840 
4841  KVDBRecord* dbrec = 0;
4842  TEnv env;
4843  TEnvRec* rec = 0;
4844  env.ReadFile(fullpath.Data(), kEnvAll);
4845  TIter it(env.GetTable());
4846 
4847  while ((rec = (TEnvRec*)it.Next())) {
4848  KVString srec(rec->GetName());
4849  KVNumberList nl(rec->GetValue());
4850  if (srec.Contains(",")) {
4851  srec.Begin(",");
4852  while (!srec.End()) {
4853  dbrec = new KVDBRecord(srec.Next(kTRUE), "Absent Detector");
4854  dbrec->AddKey("Runs", "List of Runs");
4855  fAbsDet->AddRecord(dbrec);
4856  db->LinkRecordToRunRange(dbrec, nl);
4857  }
4858  }
4859  else {
4860  dbrec = new KVDBRecord(rec->GetName(), "Absent Detector");
4861  dbrec->AddKey("Runs", "List of Runs");
4862  fAbsDet->AddRecord(dbrec);
4863  db->LinkRecordToRunRange(dbrec, nl);
4864  }
4865  }
4866 }
4867 
4868 
int Int_t
unsigned int UInt_t
ROOT::R::TRInterface & r
#define SafeDelete(p)
#define d(i)
#define f(i)
#define e(i)
bool Bool_t
unsigned short UShort_t
char Char_t
constexpr Bool_t kFALSE
double Double_t
constexpr Bool_t kTRUE
const char Option_t
R__EXTERN TEnv * gEnv
kEnvUser
kEnvAll
#define N
winID h TVirtualViewer3D TVirtualGLPainter p
Option_t Option_t option
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char filename
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t np
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize id
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void on
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t UChar_t Atom_t typelist
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t g
Option_t Option_t TPoint TPoint const char GetTextMagnitude GetFillStyle GetLineColor GetLineWidth GetMarkerStyle GetTextAlign GetTextColor GetTextSize void char Point_t Rectangle_t WindowAttributes_t Float_t Float_t Float_t Int_t Int_t UInt_t UInt_t Rectangle_t Int_t Int_t Window_t TString Int_t GCValues_t GetPrimarySelectionOwner GetDisplay GetScreen GetColormap GetNativeEvent const char const char dpyName wid window const char font_name cursor keysym reg const char only_if_exist regb h Point_t winding char text const char depth char const char Int_t count const char ColorStruct_t color const char Pixmap_t Pixmap_t PictureAttributes_t attr const char char ret_data h unsigned char height h Atom_t Int_t ULong_t ULong_t unsigned char prop_list Atom_t Atom_t Atom_t Time_t type
char name[80]
R__EXTERN TGeoManager * gGeoManager
char * Form(const char *fmt,...)
#define gPad
void SetLabel(const Char_t *lab)
Definition: KVBase.h:195
virtual const Char_t * GetType() const
Definition: KVBase.h:177
static const Char_t * GetWORKDIRFilePath(const Char_t *namefile="")
Definition: KVBase.cpp:127
const Char_t * GetLabel() const
Definition: KVBase.h:199
static bool is_gnuinstall()
Definition: KVBase.h:277
virtual void Print(Option_t *option="") const
Definition: KVBase.cpp:410
virtual void SetType(const Char_t *str)
Definition: KVBase.h:173
static const Char_t * GetDataSetEnv(const Char_t *dataset, const Char_t *type, const Char_t *defval)
Definition: KVBase.cpp:1619
static Bool_t SearchKVFile(const Char_t *name, TString &fullpath, const Char_t *kvsubdir="")
Definition: KVBase.cpp:538
static TPluginHandler * LoadPlugin(const Char_t *base, const Char_t *uri="0")
Definition: KVBase.cpp:793
Base class for all detector calibrations.
Definition: KVCalibrator.h:99
Int_t GetNumberParams() const
Definition: KVCalibrator.h:153
virtual void SetOptions(const KVNameValueList &)
void SetParameter(int i, Double_t par_val) const
Definition: KVCalibrator.h:158
void SetStatus(Bool_t ready)
Definition: KVCalibrator.h:166
void SetOutputSignalType(const TString &type)
Definition: KVCalibrator.h:220
void SetInputSignalType(const TString &type)
Definition: KVCalibrator.h:216
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:43
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:36
Table in a database.
Definition: KVDBTable.h:34
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:35
const Char_t * GetDataSetDir() const
Definition: KVDataSet.cpp:729
Bool_t HasCalibIdentInfos() const
Definition: KVDataSet.h:232
const Char_t * GetDataSetEnv(const Char_t *type, const Char_t *defval="") const
Definition: KVDataSet.cpp:767
TString GetFullPathToDataSetFile(const Char_t *filename)
Definition: KVDataSet.cpp:1898
void cd() const
Definition: KVDataSet.cpp:745
Bool_t DataBaseUpdateInProgress() const
Definition: KVDataSet.h:78
List of hit groups in a multidetector array.
void AddGroup(KVGroup *grp)
virtual void Clear(Option_t *opt="")
KVUniqueNameList * GetGroups()
Base class for output signal data produced by a detector.
virtual void SetValue(Double_t x)
virtual Double_t GetValue(const KVNameValueList &params="") const
TString GetFullName() const
void SetFired(Bool_t yes=true)
Base class for detector geometry description.
Definition: KVDetector.h:160
virtual Bool_t IsOK() const
Definition: KVDetector.h:682
TList * GetTelescopesForIdentification()
Definition: KVDetector.cpp:762
virtual void AddIDTelescope(TObject *idt)
Add ID telescope to list of telescopes to which detector belongs.
Definition: KVDetector.cpp:723
KVList * GetAlignedIDTelescopes()
Definition: KVDetector.cpp:737
KVGeoStrucElement * GetParentStructure(const Char_t *type, const Char_t *name="") const
KVGroup * GetGroup() const
void AddDetectorSignal(KVDetectorSignal *ds)
Definition: KVDetector.h:261
virtual void SetEnergyLoss(Double_t e) const
Definition: KVDetector.h:373
KVList * GetHits() const
Return the list of particles hitting this detector in an event.
Definition: KVDetector.h:426
virtual Double_t GetEnergy() const
Definition: KVDetector.h:349
Int_t GetNHits() const
Return the number of particles hitting this detector in an event.
Definition: KVDetector.h:436
KVList * GetIDTelescopes()
Definition: KVDetector.h:551
Double_t GetTheta() const
Definition: KVDetector.h:744
KVMaterial * GetAbsorber(Int_t i) const
Returns pointer to the i-th absorber in the detector (i=0 first absorber, i=1 second,...
Definition: KVDetector.cpp:646
virtual void DeduceACQParameters(KVEvent *, KVNumberList &)
Definition: KVDetector.h:688
void SetThickness(Double_t thick)
virtual KVDetectorSignal * GetDetectorSignal(const KVString &type) const
Definition: KVDetector.h:533
Bool_t IsCalibrated() const
Definition: KVDetector.h:390
void SetDetecting(Bool_t yes=kTRUE)
Definition: KVDetector.h:677
virtual void RemoveCalibrators()
Definition: KVDetector.cpp:700
Double_t GetPhi() const
Definition: KVDetector.h:762
virtual Double_t GetPunchThroughEnergy(Int_t Z, Int_t A)
virtual Bool_t IsDetecting() const
Definition: KVDetector.h:672
virtual TList * GetAlignedDetectors(UInt_t direction=1)
KVGeoDetectorNode * GetNode()
Definition: KVDetector.h:326
virtual Double_t GetIncidentEnergyFromERes(Int_t Z, Int_t A, Double_t Eres)
virtual Bool_t IsPresent() const
Definition: KVDetector.h:663
TVector3 GetRandomDirection(Option_t *t="isotropic")
Definition: KVDetector.h:720
void ResetAlignedDetectors(UInt_t direction=1)
virtual void Print(Option_t *option="") const
Definition: KVDetector.cpp:364
Bool_t AddCalibrator(KVCalibrator *cal, const KVNameValueList &opts="")
Definition: KVDetector.cpp:478
void SetPresent(Bool_t yes=kTRUE)
Definition: KVDetector.h:668
Abstract base class container for multi-particle events.
Definition: KVEvent.h:67
KVNameValueList * GetParameters() const
Definition: KVEvent.h:179
void Clear(Option_t *opt="")
Definition: KVEvent.h:238
Base class to describe database of an experiment ,,.
Definition: KVExpDB.h:20
void SetDBType(const TString &s)
Definition: KVExpDB.h:50
TString GetCalibFileName(const Char_t *type) const
Definition: KVExpDB.h:109
const KVNumberList & GetRunList() const
Definition: KVExpDB.h:80
virtual void LinkRecordToRunRange(KVDBRecord *rec, UInt_t first_run, UInt_t last_run)
Definition: KVExpDB.cpp:87
Bool_t FindCalibFile(const Char_t *type, TString &fullpath, const TString &array_name="") const
Definition: KVExpDB.cpp:487
Handle reading columns of numeric data in text files.
Definition: KVFileReader.h:120
KVString GetCurrentLine()
Definition: KVFileReader.h:319
ReadStatus ReadLine(const KVString &pattern="")
Definition: KVFileReader.h:242
Bool_t IsOK()
Definition: KVFileReader.h:230
Bool_t OpenFileToRead(const KVString &filename)
Definition: KVFileReader.h:209
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:20
void AddTrajectory(KVGeoDNTrajectory *t)
Definition: KVGroup.h:83
void Reset(Option_t *opt="")
Definition: KVGroup.cpp:114
@ kBackwards
Definition: KVGroup.h:34
@ kForwards
Definition: KVGroup.h:33
virtual void SetNumber(UInt_t num)
Definition: KVGroup.h:39
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:29
Base class for particle identification in a 2D map.
Definition: KVIDGraph.h:32
void RemoveIDTelescope(KVBase *t)
Definition: KVIDGraph.h:416
Handles a stock of identification grids to be used by one or more identification telescopes.
KVList * GetGrids()
virtual void LoadGridsForRun(UInt_t)
Bool_t ReadAsciiFile(const Char_t *filename)
const TList * GetLastReadGrids() const
virtual bool IsSQLROOT() const
Base class for all detectors or associations of detectors in array which can identify charged particl...
Definition: KVIDTelescope.h:84
virtual Double_t GetIDMapY(Option_t *opt="")
virtual Bool_t IsReadyForID()
KVIDGrid * CalculateDeltaE_EGrid(const KVNameValueList &AperZ, Int_t npoints=30, Double_t xfactor=1.)
void SetGroup(KVGroup *kvg)
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)
virtual UShort_t GetIDCode()
virtual void Initialize(void)
virtual void SetIdentificationStatus(KVReconstructedNucleus *)
UInt_t GetSize() const
Bool_t HasDetector(const KVDetector *d) const
Extended TList class which owns its objects by default.
Definition: KVList.h:28
Read MFM format acquisition data.
Description of physical materials used to construct detectors & targets; interface to range tables.
Definition: KVMaterial.h:94
static KVIonRangeTable * GetRangeTable()
Definition: KVMaterial.cpp:166
Base class for describing the geometry of a detector array.
const KVSeqCollection * GetFiredSignals() const
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)
KVUniqueNameList fExtraRawDataSignals
any signals read from raw data not associated with a detector
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 &)
Read a raw data event from a EBYEDAT MFM Frame.
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 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.
virtual void DeduceIdentificationTelescopesFromGeometry()
std::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()
void ReadAbsentDetectors(KVExpDB *db)
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)
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.
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.
void set_detector_thicknesses(const TString &)
virtual TGraph * DrawPunchThroughEsurAVsZ(const Char_t *detector, Int_t massform=KVNucleus::kBetaMass)
Bool_t ReadGridsFromAsciiFile(const Char_t *) const
virtual void InitialiseRawDataReading(KVRawDataReader *)
virtual void SetExpectedDetectorSignalNames()
virtual void SetParameters(UInt_t n, Bool_t physics_parameters_only=kFALSE)
virtual void SetDetectorParametersForRun(KVDBRun *, const TString &="")
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
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.
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="")
void CheckStatusOfDetectors(KVDBRun *, const TString &="")
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()
static Bool_t fMakeMultiDetectorPhysicsParametersOnly
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 &)
General method for reading raw data in old GANIL ebyedat format.
const TSeqCollection * GetTrajectories() const
virtual void MakeListOfDetectors()
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")
KVRawDataReader * fRawDataReader
last raw data reader object used in call to HandleRawData
virtual void ReconstructEvent(KVReconstructedEvent *, KVDetectorEvent *)
virtual KVGroup * GetGroupWithAngles(Float_t, Float_t)
virtual void SetRawDataFromReconEvent(KVNameValueList &)
void add_and_set_detector_signal(KVDetector *det, KVString detname, Double_t sig_data, KVString sig_type)
virtual TGraph * DrawPunchThroughZVsVpar(const Char_t *detector, Int_t massform=KVNucleus::kBetaMass)
static Int_t fMakeMultiDetectorRunNumber
virtual 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)
KVUniqueNameList fFiredDetectors
list of fired detectors after reading raw data event
virtual void RenumberGroups()
virtual void SetRunCalibrationParameters(UShort_t n)
void PrintStatusOfIDTelescopes()
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)
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.
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 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()
KVUnownedList fFiredSignals
list of fired signals after reading raw data event
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.
Double_t GetDouble() const
Description of properties and kinematics of atomic nuclei.
Definition: KVNucleus.h:126
virtual void Print(Option_t *t="") const
Display nucleus parameters.
Definition: KVNucleus.cpp:761
Int_t GetA() const
Definition: KVNucleus.cpp:802
void SetZ(Int_t z, Char_t mt=-1)
Definition: KVNucleus.cpp:707
void SetZandA(Int_t z, Int_t a)
Set atomic number and mass number.
Definition: KVNucleus.cpp:724
void SetMassFormula(UChar_t mt)
Definition: KVNucleus.h:345
Int_t GetZ() const
Return the number of proton / atomic number.
Definition: KVNucleus.cpp:773
Strings used to represent a set of ranges of values.
Definition: KVNumberList.h:85
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:135
Bool_t IsEmpty() const
Definition: KVNumberList.h:175
void SetIsOK(Bool_t flag=kTRUE)
Definition: KVParticle.cpp:339
void SetTheta(Double_t theta)
Definition: KVParticle.h:693
TVector3 * GetPInitial() const
Definition: KVParticle.h:726
void RemoveGroup(const Char_t *groupname)
Remove group from list of groups.
Definition: KVParticle.cpp:530
void AddGroup(const Char_t *groupname, const Char_t *from="") const
Definition: KVParticle.cpp:436
KVNameValueList * GetParameters() const
Definition: KVParticle.h:815
Double_t GetEnergy() const
Definition: KVParticle.h:621
Double_t GetE() const
Definition: KVParticle.h:652
void SetMomentum(const TVector3 *v)
Definition: KVParticle.h:542
void SetE(Double_t a)
Definition: KVParticle.h:594
void SetE0(TVector3 *e=0)
Definition: KVParticle.h:715
Double_t GetKE() const
Definition: KVParticle.h:614
Double_t GetVpar() const
Definition: KVParticle.h:675
KVParticle const * GetFrame(const Char_t *frame, Bool_t warn_and_return_null_if_unknown=kTRUE) const
Definition: KVParticle.cpp:865
Bool_t BelongsToGroup(const Char_t *groupname) const
Definition: KVParticle.cpp:509
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:37
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
Event containing KVReconstructedNucleus nuclei reconstructed from hits in detectors.
virtual Bool_t AnalyseDetectors(TList *kvtl)
virtual void SecondaryIdentCalib()
Nuclei reconstructed from data measured by a detector array .
virtual void SetIDCode(UShort_t s)
virtual void Reconstruct(KVDetector *kvd)
virtual void SetAMeasured(Bool_t yes=kTRUE)
virtual Int_t GetECode() const
static UInt_t GetNUnidentifiedInGroup(KVGroup *grp)
void RebuildReconTraj(bool in_streamer=true)
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)
virtual void SetECode(UChar_t s)
Combine ROOT file containing objects with SQLite database with info on the objects.
Definition: KVSQLROOTFile.h:76
ID grid manager using KVSQLROOTFile backend.
KaliVeda extensions to ROOT collection classes.
virtual TObject * FindObjectByLabel(const Char_t *) const
T * get_object(const TString &name) 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:73
void Begin(TString delim) const
Definition: KVString.cpp:565
Bool_t End() const
Definition: KVString.cpp:634
KVString Next(Bool_t strip_whitespace=kFALSE) const
Definition: KVString.cpp:695
Int_t GetNValues(TString delim) const
Definition: KVString.cpp:886
virtual void DetectParticle(KVNucleus *, TVector3 *norm=0)
Definition: KVTarget.cpp:485
virtual Double_t GetParticleEIncFromERes(KVNucleus *, TVector3 *norm=0)
Definition: KVTarget.cpp:957
void Clear(Option_t *opt="")
Definition: KVTarget.cpp:747
void SetOutgoing(Bool_t r=kTRUE)
Definition: KVTarget.h:237
Associates two detectors placed one behind the other.
Definition: KVTelescope.h:36
Particle * GetNextParticle(Option_t *opt="") const
Particle * AddParticle()
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:25
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
void SetName(const char *name)
const char * GetName() const override
virtual Int_t GetEntries() const
virtual void SetOwner(Bool_t enable=kTRUE)
void Delete(Option_t *option="") override=0
Bool_t Contains(const char *name) const
virtual Int_t GetSize() const
THashList * GetTable() 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
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)
void SetDz(Double_t dz) override
void Draw(Option_t *option="") override
void SetTransparency(Char_t transparency=0)
virtual void SetPoint(Int_t i, Double_t x, Double_t y)
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)
void SetName(const char *name="") override
void SetTitle(const char *title="") override
virtual Int_t Fill(const char *name, Double_t w)
TObject * Next()
void Reset()
TObject * FindObject(const char *name) const override
void Add(TObject *obj) override
TObject * First() const override
void Delete(Option_t *option="") override
TObject * At(Int_t idx) const override
virtual void SetTitle(const char *title="")
const char * GetName() const override
const char * GetTitle() const override
virtual void SetName(const char *name)
void AbstractMethod(const char *method) const
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 void Error(const char *method, const char *msgfmt,...) const
virtual void Info(const char *method, const char *msgfmt,...) const
const char * GetClass() const
Longptr_t ExecPlugin(int nargs)
Int_t GetEntries() const override
virtual TObject * RemoveAt(Int_t idx)
Double_t Atof() const
const char * Data() const
void ToUpper()
TObjArray * Tokenize(const TString &delim) const
Bool_t BeginsWith(const char *s, ECaseCompare cmp=kExact) 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
RVec< PromoteType< T > > abs(const RVec< T > &v)
RVec< PromoteType< T > > round(const RVec< T > &v)
const Int_t n
TGraphErrors * gr
TH1 * h
void init()
rec
Int_t Nint(T x)
Double_t Max(Double_t a, Double_t b)
TLine l
ClassImp(TPyArg)