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 "KVNucleus.h"
11 #include "KVGroup.h"
12 #include "KVMaterial.h"
13 #include "KVTarget.h"
14 #include "KVIDTelescope.h"
15 #include <KVString.h>
16 #include <TObjString.h>
17 #include <TObjArray.h>
18 #include <KVIDGridManager.h>
19 #include <KVDataSetManager.h>
20 #include <KVUpDater.h>
21 #include "TPluginManager.h"
22 #include "KVDataSet.h"
23 #include "TGeoManager.h"
24 #include "KVHashList.h"
25 #include "KVNameValueList.h"
26 #include "KVUniqueNameList.h"
27 #include "KVIonRangeTable.h"
28 #include "KVRangeTableGeoNavigator.h"
29 #include <KVDataAnalyser.h>
30 #include <KVNamedParameter.h>
31 #include <KVCalibrator.h>
32 #include <KVDBParameterSet.h>
33 #ifdef WITH_RSQLITE
34 #include <KVSQLROOTIDGridManager.h>
35 #endif
36 #ifdef WITH_OPENGL
37 #include <TGLViewer.h>
38 #include <TVirtualPad.h>
39 #endif
40 #ifdef WITH_BUILTIN_GRU
41 #include "KVGANILDataReader.h"
42 #else
43 #include "KVRawDataReader.h"
44 #endif
45 #ifdef WITH_MFM
46 #include "KVMFMDataFileReader.h"
47 #include "MFMEbyedatFrame.h"
48 #endif
49 #ifdef WITH_PROTOBUF
50 #include "KVProtobufDataReader.h"
51 #endif
52 using namespace std;
53 
54 KVMultiDetArray* gMultiDetArray = nullptr;
55 
56 Bool_t KVMultiDetArray::fCloseGeometryNow = kTRUE;
57 Bool_t KVMultiDetArray::fBuildTarget = kFALSE;
58 Bool_t KVMultiDetArray::fMakeMultiDetectorSetParameters = kTRUE;
59 Bool_t KVMultiDetArray::fMakeMultiDetectorPhysicsParametersOnly = kFALSE;
60 Int_t KVMultiDetArray::fMakeMultiDetectorRunNumber = -1;
61 
63 
64 
65 
69  : KVGeoStrucElement(), fTrajectories(kTRUE)
70 {
71  // Default constructor
72  init();
73  gMultiDetArray = this;
74 }
75 
76 
77 
80 
82  : KVGeoStrucElement(name, type), fTrajectories(kTRUE)
83 {
84  // Constructor with name and optional type
85  init();
86  gMultiDetArray = this;
87 }
88 
89 
90 
102 
104 {
105  //Basic initialisation called by constructor.
106  //Creates detectors list fDetectors,
107  //groups list fGroups, identification telescopes list
108  //fIDTelescopes
109  //
110  //The fGroups & fIDTelescopes lists contain objects owned by the multidetector array,
111  //but which may be deleted by other objects (or as a result of the deletion of other
112  //objects: i.e. if all the detectors in a group are deleted, the group itself is destroyed).
113  //We use the ROOT automatic garbage collection to make sure that any object deleted
114  //elsewhere is removed automatically from these lists.
115 
116  fIDTelescopes = new KVHashList();
117  fIDTelescopes->SetOwner(kTRUE); // owns its objects
118  fIDTelescopes->SetCleanup(kTRUE);
119 
120  fHitGroups = 0;
121 
122  fTarget = 0;
123  fCurrentRun = 0;
124 
125  fStatusIDTelescopes = 0;
126  fCalibStatusDets = 0;
127  fSimMode = kFALSE;
128 
129  fFilterType = kFilterType_Full;
130 
131  fUpDater = 0;
132 
133  if (!gIDGridManager) new KVIDGridManager;
134 
135  // all trajectories belong to us
136  fTrajectories.SetOwner();
137 
138  //all detectors belong to us
140 
141  fRawDataReader = nullptr;
142  fHandledRawData = false;
143 
144  // any extra raw data signals created when reading data belong to us
145  fExtraRawDataSignals.SetOwner(kTRUE);
146 }
147 
148 
149 
152 
154 {
155  //destroy (delete) the MDA and all the associated structure, detectors etc.
156 
157  SafeDelete(fHitGroups);
158  //destroy all identification telescopes
159  if (fIDTelescopes && fIDTelescopes->TestBit(kNotDeleted)) {
160  fIDTelescopes->Delete();
161  delete fIDTelescopes;
162  }
163  fIDTelescopes = 0;
164 
165  if (gMultiDetArray == this)
166  gMultiDetArray = nullptr;
167 
168  if (fStatusIDTelescopes) {
169  fStatusIDTelescopes->Delete();
170  delete fStatusIDTelescopes;
171  fStatusIDTelescopes = 0;
172  }
173  if (fCalibStatusDets) {
174  fCalibStatusDets->Delete();
175  delete fCalibStatusDets;
176  fCalibStatusDets = 0;
177  }
178 
179  SafeDelete(fUpDater);
180 }
181 
182 
183 
184 
185 
187 
189 {
190 
191 
192 
193 }
194 
195 
196 
197 
221 
222 Int_t KVMultiDetArray::GetIDTelescopes(KVGeoDetectorNode* de, KVDetector* e, TCollection* list)
223 {
224  // Create one or more KVIDTelescope particle-identification objects from the two detectors
225  //
226  // The different ID telescopes are defined as 'Plugin' objects in the file $KVROOT/KVFiles/.kvrootrc :
227  // # The KVMultiDetArray::GetIDTelescopes(KVDetector*de, KVDetector*e) method uses these plugins to
228  // # create KVIDTelescope instances adapted to the specific array geometry and detector types.
229  // # For each pair of detectors we look for a plugin with one of the following names:
230  // # [name_of_dataset].array_name.de_detector_type[de detector thickness]-e_detector_type[de detector thickness]
231  // # Each characteristic in [] brackets may or may not be present in the name; first we test for names
232  // # with these characteristics, then all combinations where one or other of the characteristics is not present.
233  // # In addition, we first test all combinations which begin with [name_of_dataset].
234  // # The first plugin found in this order will be used.
235  // # In addition, if for one of the two detectors there is a plugin called
236  // # [name_of_dataset].array_name.de_detector_type[de detector thickness]
237  // # [name_of_dataset].array_name.e_detector_type[e detector thickness]
238  // # then we add also an instance of this 1-detector identification telescope.
239  //
240  // This method is called by DeduceIdentificationTelescopesFromGeometry
241  // in order to set up all ID telescopes of the array.
242  //
243  // \returns number of ID telescopes created
244  // \param[in] de node corresponding to \f$\Delta E\f$ detector; may be nullptr
245  // \param[in] e residual energy detector; always points to valid object
246 
247  assert(e);
248 
249  Int_t ntels = 0;
250 
251  if (fDataSet == "" && gDataSet) fDataSet = gDataSet->GetName();
252 
253  //look for ID telescopes starting from furthest from target
254  if (e->IsOK()) ntels += try_all_singleID_telescopes(e, list);
255  if (de && (de->GetDetector() != e)) {
256  if (e->IsOK() && de->GetDetector()->IsOK()) ntels += try_all_doubleID_telescopes(de->GetDetector(), e, list);
257  if (de->GetDetector()->IsOK()) ntels += try_all_singleID_telescopes(de->GetDetector(), list);
258  }
259 
260  return ntels;
261 }
262 
263 
264 
282 
283 Int_t KVMultiDetArray::try_all_singleID_telescopes(KVDetector* d, TCollection* l)
284 {
285  // Attempt to find a plugin KVIDTelescope class for making a single-detector
286  // ID telescope from detector *d
287  // We look for plugins with the following signatures (uri):
288  //
289  // [array name].[type]
290  // [array_name].[type][thickness]
291  //
292  // where 'type' is the type of the detector in UPPER or lowercase letters
293  // 'thickness' is the nearest-integer thickness of the detector as returned by d->GetThickness()
294  // In addition, if a dataset is set (gDataSet!=nullptr) we try also for dataset-specific
295  // plugins:
296  //
297  // [dataset].[array name].[type]
298  // [dataset].[array name].[type][thickness]
299  //
300  // Returns number of generated telescopes
301 
302  TString uri = Form("%s.%s", GetName(), d->GetType());
303  Int_t ntels = 0;
304  if (!(ntels += try_upper_and_lower_singleIDtelescope(uri, d, l))) {
305  Int_t d_thick = TMath::Nint(d->GetThickness());
306  uri += d_thick;
307  ntels += try_upper_and_lower_singleIDtelescope(uri, d, l);
308  }
309  return ntels;
310 }
311 
312 
313 
314 
337 
338 Int_t KVMultiDetArray::try_all_doubleID_telescopes(KVDetector* de, KVDetector* e, TCollection* l)
339 {
340  // Attempt to find a plugin KVIDTelescope class for making an ID telescope from detectors de & e.
341  // We look for plugins with the following signatures (uri):
342  //
343  // [array name].[de-type]-[e-type]
344  // [array name].[de-type][thickness]-[e-type]
345  // [array name].[de-type]-[e-type][thickness]
346  // [array name].[de-type][thickness]-[e-type][thickness]
347  //
348  // where 'type' is the type of the detector in UPPER or lowercase letters
349  // 'thickness' is the nearest-integer thickness of the detector.
350  // In addition, if a dataset is set (gDataSet!=nullptr) we try also for dataset-specific
351  // plugins:
352  //
353  // [dataset].[array name].[de-type][thickness]-[e-type][thickness]
354  // [dataset].[array name].[de-type][thickness]-[e-type]
355  // [dataset].[array name].[de-type]-[e-type][thickness]
356  // [dataset].[array name].[de-type]-[e-type]
357  //
358  // if no plugin is found, we return a KVIDTelescope base class object
359  //
360  // Returns 1 (we always generate exactly one telescope)
361 
362  TString de_type = de->GetType();
363  TString e_type = e->GetType();
364  TString de_thick = Form("%d", TMath::Nint(de->GetThickness()));
365  TString e_thick = Form("%d", TMath::Nint(e->GetThickness()));
366 
367  TString uri = de_type + de_thick + "-" + e_type + e_thick;
368  uri.Prepend(Form("%s.", GetName()));
369  if (try_upper_and_lower_doubleIDtelescope(uri, de, e, l)) return 1;
370 
371  uri = de_type + de_thick + "-" + e_type;
372  uri.Prepend(Form("%s.", GetName()));
373  if (try_upper_and_lower_doubleIDtelescope(uri, de, e, l)) return 1;
374 
375  uri = de_type + "-" + 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 + "-" + e_type;
380  uri.Prepend(Form("%s.", GetName()));
381  if (try_upper_and_lower_doubleIDtelescope(uri, de, e, l)) return 1;
382 
383  // default id telescope object
384  KVIDTelescope* idt = new KVIDTelescope;
385  uri = de_type + "-" + e_type;
386  idt->SetLabel(uri);
387  // set type as "[DEtype]-[Etype]" where "[*type]" is type of DE/E detectors
388  idt->SetType(Form("%s-%s", de_type.Data(), e_type.Data()));
389  set_up_telescope(de, e, idt, l);
390 
391  return 1;
392 }
393 
394 
395 
403 
404 bool KVMultiDetArray::try_upper_and_lower_singleIDtelescope(TString uri, KVDetector* d, TCollection* l)
405 {
406  // Attempt to find a plugin KVIDTelescope class for making a single-detector
407  // ID telescope from detector *d with the given signature/uri
408  // Both original & all-upper-case versions of uri are tried.
409  // uri is tried both with & without prepended dataset name (if set)
410  // Returns true if successful (the new ID telescope will be added to internal
411  // list fIDTelescopes and also to TCollection* l)
412 
413  if (try_a_singleIDtelescope(uri, d, l)) return true;
414  uri.ToUpper();
415  return try_a_singleIDtelescope(uri, d, l);
416 }
417 
418 
419 
426 
427 bool KVMultiDetArray::try_upper_and_lower_doubleIDtelescope(TString uri, KVDetector* de, KVDetector* e, TCollection* l)
428 {
429  // Attempt to find a plugin KVIDTelescope class for making an ID telescope with the given signature/uri
430  // Both original & all-upper-case versions of uri are tried.
431  // uri is tried both with & without prepended dataset name (if set)
432  // Returns true if successful (the new ID telescope will be added to internal
433  // list fIDTelescopes and also to TCollection* l)
434 
435  if (try_a_doubleIDtelescope(uri, de, e, l)) return true;
436  uri.ToUpper();
437  return try_a_doubleIDtelescope(uri, de, e, l);
438 }
439 
440 
441 
449 
450 bool KVMultiDetArray::try_a_singleIDtelescope(TString uri, KVDetector* d, TCollection* l)
451 {
452  // Attempt to find a plugin KVIDTelescope class for making a single-detector
453  // ID telescope from detector *d with the given signature/uri
454  // Both original & all-upper-case versions of uri are tried.
455  // uri is tried both with & without prepended dataset name (if set)
456  // Returns true if successful (the new ID telescope will be added to internal
457  // list fIDTelescopes and also to TCollection* l)
458 
459  if(!check_idtelescope_in_allowed_list(uri))
460  return false;
461 
462  // dataset-specific version takes precedence over default
463  TString duri = uri;
464  if (gDataSet) {
465  // try with dataset name
466  duri.Prepend(Form("%s.", fDataSet.Data()));
467  KVIDTelescope* idt;
468  if ((idt = KVIDTelescope::MakeIDTelescope(duri))) {
469  set_up_single_stage_telescope(d, idt, l);
470  return true;
471  }
472  }
473 
474  // look for default version
475  KVIDTelescope* idt;
476  if ((idt = KVIDTelescope::MakeIDTelescope(uri))) {
477  set_up_single_stage_telescope(d, idt, l);
478  return true;
479  }
480 
481  return false;
482 }
483 
484 
485 
491 
492 bool KVMultiDetArray::try_a_doubleIDtelescope(TString uri, KVDetector* de, KVDetector* e, TCollection* l)
493 {
494  // Attempt to find a plugin KVIDTelescope class for making an ID telescope with the given signature/uri
495  // uri is tried both with & without prepended dataset name (if set)
496  // Returns true if successful (the new ID telescope will be added to internal
497  // list fIDTelescopes and also to TCollection* l)
498 
499  if(!check_idtelescope_in_allowed_list(uri))
500  return false;
501 
502  // dataset-specific version takes precedence over default
503  TString duri = uri;
504  if (gDataSet) {
505  // try with dataset name
506  duri.Prepend(Form("%s.", fDataSet.Data()));
507  KVIDTelescope* idt;
508  if ((idt = KVIDTelescope::MakeIDTelescope(duri))) {
509  set_up_telescope(de, e, idt, l);
510  return true;
511  }
512  }
513  // look for default version
514  KVIDTelescope* idt;
515  if ((idt = KVIDTelescope::MakeIDTelescope(uri))) {
516  set_up_telescope(de, e, idt, l);
517  return true;
518  }
519 
520  return false;
521 }
522 
523 
524 
527 
528 void KVMultiDetArray::set_up_telescope(KVDetector* de, KVDetector* e, KVIDTelescope* idt, TCollection* l)
529 {
530  // Set up detectors in de-e identification telescope and add to fIDTelescopes and to l
531 
532  idt->AddDetector(de);
533  idt->AddDetector(e);
534  if (de->GetGroup()) {
535  idt->SetGroup(de->GetGroup());
536  }
537  else {
538  idt->SetGroup(e->GetGroup());
539  }
540  // if telescope already exists, we delete this new version and add a reference to
541  // the original into list l
542  KVIDTelescope* p = (KVIDTelescope*)fIDTelescopes->FindObject(idt->GetName());
543  if (p) {
544  l->Add(p);
545  delete idt;
546  }
547  else {
548  fIDTelescopes->Add(idt);
549  l->Add(idt);
550  }
551 }
552 
553 
554 
557 
558 void KVMultiDetArray::set_up_single_stage_telescope(KVDetector* det, KVIDTelescope* idt, TCollection* l)
559 {
560  // Set up detector in single-stage identification telescope and add to fIDTelescopes and to l
561 
562  idt->AddDetector(det);
563  idt->SetGroup(det->GetGroup());
564  // if telescope already exists, we delete this new version and add a reference to
565  // the original into list l
566  KVIDTelescope* p = (KVIDTelescope*)fIDTelescopes->FindObject(idt->GetName());
567  if (p) {
568  l->Add(p);
569  delete idt;
570  }
571  else {
572  fIDTelescopes->Add(idt);
573  l->Add(idt);
574  }
575 }
576 
577 
578 
579 
583 
584 void KVMultiDetArray::RenumberGroups()
585 {
586  //Number groups according to position in list fGroups and set fGr counter to the number
587  //of groups in the list
588  Int_t fGr = 0;
589  KVGroup* g = 0;
590  KVSeqCollection* fGroups = GetStructures()->GetSubListWithType("GROUP");
591  TIter next(fGroups);
592  while ((g = (KVGroup*) next())) {
593  g->SetNumber(++fGr);
594  }
595  delete fGroups;
596 }
597 
598 
599 
602 
604 {
605  //Return pointer to DeltaE-E ID Telescope with "name"
606 
607  return (KVIDTelescope*) fIDTelescopes->FindObject(name);
608 }
609 
610 
611 
616 
618 {
619  //Reset all groups (lists of detected particles etc.)
620  //and detectors in groups (energy losses, ACQparams etc. etc.)
621  //and the target if there is one
622 
623  unique_ptr<KVSeqCollection> fGroups(GetStructures()->GetSubListWithType("GROUP"));
624 
625  TIter next(fGroups.get());
626  KVGroup* grp;
627  while ((grp = (KVGroup*) next())) {
628  grp->Reset();
629  }
630  if (GetTarget())
631  GetTarget()->Clear();
632 }
633 
634 
635 
636 
642 
644 {
645  // Sets up calibrators for all detectors with a defined calibration for run
646  // Set parameters for all detectors with links to table "Calibrations" for run
647  // If 'myname' is given, we look in "myname.Calibrations"
648 
649  //Reset all calibrators of all detectors first
650  TIter next(GetDetectors());
651  KVDetector* kvd;
652  while ((kvd = (KVDetector*) next())) kvd->RemoveCalibrators();
653 
654  TString tabname = (myname != "" ? Form("%s.Calibrations", myname.Data()) : "Calibrations");
655  //Info("SetCalibratorParameters", "For array %s in table %s", GetName(), tabname.Data());
656  KVRList* run_links = r->GetLinks(tabname);
657  if (run_links) Info("SetCalibratorParameters", "Found %d calibrations for this run", run_links->GetEntries());
658  else {
659 // Warning("SetCalibratorParameters", "Got no links for %s", tabname.Data());
660 // r->GetKeys()->ls();
661  return;
662  }
663  TIter nxt_link(run_links);
664  KVDBParameterSet* dbps;
665  while ((dbps = (KVDBParameterSet*)nxt_link())) {
666 
667  KVDetector* det = GetDetector(dbps->GetName());
668  if (!det) {
669  KVError::Warning(this, "SetCalibratorParameters", "Got parameters for unknown detector: %s", dbps->GetName());
670  continue;
671  }
672 
673  KVNameValueList class_options;
674  KVString clop;
675  if (dbps->HasParameter("CalibOptions")) clop = dbps->GetStringParameter("CalibOptions");
676  if (clop != "") {
677  clop.Begin(",");
678  while (!clop.End()) {
679  KVString clopp = clop.Next(true);
680  clopp.Begin("=");
681  KVString par(clopp.Next(true)), val(clopp.Next(true));
682  class_options.SetValue(par, val);
683  }
684  }
686  cal->SetType(dbps->GetTitle());
687  if (clop != "") {
688  try {
689  cal->SetOptions(class_options);
690  }
691  catch (std::exception& e) {
692  KVError::Error(this, "SetCalibratorParameters",
693  "Problem for %s [%s] : %s", det->GetName(), cal->GetType(), e.what());
694  delete cal;
695  continue;
696  }
697  }
698  cal->SetInputSignalType(dbps->GetStringParameter("SignalIn"));
699  cal->SetOutputSignalType(dbps->GetStringParameter("SignalOut"));
700  if (!det->AddCalibrator(cal, dbps->GetParameters())) {
701  // Calibrator invalid - probably input signal is not defined for detector
702  // N.B. 'cal' deleted by KVDetector::AddCalibrator
703  continue;
704  }
705 
706  if (dbps->GetParamNumber() > cal->GetNumberParams()) {
707  KVError::Warning(this, "SetCalibratorParameters", "Wrong number of parameters (%d) for calibrator %s for detector %s : should be %d",
708  dbps->GetParamNumber(), dbps->GetTitle(), dbps->GetName(), cal->GetNumberParams());
709  dbps->Print();
710  continue;
711  }
712  for (int i = 0; i < dbps->GetParamNumber(); ++i) {
713  if (i >= cal->GetNumberParams())
714  cal->SetParameter(i, 0);
715  else
716  cal->SetParameter(i, dbps->GetParameter(i));
717  }
718  cal->SetStatus(true);
719  }
720 }
721 
722 
723 
741 
742 void KVMultiDetArray::SetExpectedDetectorSignalNames()
743 {
744  // Detector signals corresponding to raw data acquisition parameters are typically only created and
745  // added to detectors when some raw data has been read including those parameters.
746  //
747  // However, when reconstructing data, we may define identification matrices or calibration formulae
748  // which use these signals before starting to read data. Therefore we need to know beforehand what
749  // detector signals are expected to be available once data has been read.
750  //
751  // These are defined, according to detector types, by variables of the form
752  //
753  //~~~~
754  // [dataset].[array].[detector-type].ExpectedDetectorSignals: [comma-separated list of signal names]
755  //~~~~
756  //
757  // where [dataset] is optionally used to provide dataset-specific definitions.
758  //
759  // Here we add a detector signal of each expected type to each detector of the array
760 
761  TIter it(GetDetectors());
762  KVDetector* det;
763  while ((det = (KVDetector*)it())) {
764  auto s = KVBase::GetDataSetEnv<KVString>(fDataSet.Data(), Form("%s.%s.ExpectedDetectorSignals", GetName(), det->GetType()));
765  if (s.IsNull()) continue;
766  s.Begin(",");
767  while (!s.End()) {
768  det->AddDetectorSignal(s.Next(kTRUE));
769  }
770  }
771 }
772 
773 
774 
785 
787 {
788  // First step in event reconstruction based on current status of detectors in array.
789  // Fills the given KVDetectorEvent with the list of all groups which have fired.
790  // i.e. loop over all groups of the array and test whether KVGroup::Fired() returns true or false.
791  //
792  // If the list of fired detectors 'fired_dets' is given, then we use this list
793  // to find the associated groups. If not given, or if it is empty, we may use the internal fFiredDetectors list.
794  //
795  // Call method detev->Clear() before reading another event in order to reset all of the hit groups
796  // (including all detectors etc.) and emptying the list.
797 
798  if (!fired_dets || !fired_dets->GetEntries()) {
799  if (fFiredDetectors.GetEntries()) fired_dets = &fFiredDetectors;
800  }
801  if (fired_dets && fired_dets->GetEntries()) {
802  // list of fired detectorsgiven
803  TIter next_det(fired_dets);
804  KVDetector* det = 0;
805  KVGroup* grp = 0;
806  while ((det = (KVDetector*)next_det())) {
807  if ((grp = det->GetGroup()) && grp->GetParents()->Contains(this)) detev->AddGroup(grp);
808  }
809  }
810  else {
811  //loop over groups
812  unique_ptr<KVSeqCollection> fGroups(GetStructures()->GetSubListWithType("GROUP"));
813 
814  TIter next_grp(fGroups.get());
815  KVGroup* grp;
816  while ((grp = (KVGroup*) next_grp())) {
817  if (grp->Fired()) {
818  //if (!fHitGroups->FindObject(grp))
819  // grp->Print();
820  //add new group to list of hit groups
821  detev->AddGroup(grp);
822  }
823  }
824  }
825 }
826 
827 
828 
848 
850 {
851  //Static function which will create and 'Build' the multidetector object corresponding to
852  //a given run of dataset 'dataset_name'. Any previously existing multidetector will be
853  //deleted.
854  //
855  //We first activate the given dataset if not already done
856  //
857  //Multidetector arrays are defined as 'Plugin' objects :
858  //
859  //~~~
860  //Plugin.KVMultiDet: [dataset_name] [classname] [library] "[constructor]()"
861  //~~~
862  //
863  //The constructors/macros are always without arguments
864  //
865  //Dataset name is stored in fDataSet
866 
867  // store the run number (if given) so that if the dataset needs to update its database
868  // (which requires building the multidetector by calling MakeMultiDetector()) then it
869  // will build the correct geometry for the run
870  if (run > 0) fMakeMultiDetectorRunNumber = run;
871  else if (fMakeMultiDetectorRunNumber > 0) run = fMakeMultiDetectorRunNumber;
872 
873  if(!gDataSetManager)
874  {
875  auto dsm = new KVDataSetManager;
876  dsm->Init();
877  }
878  if (gDataSetManager && (!gDataSet || (gDataSet != gDataSetManager->GetDataSet(dataset_name)))) {
879  printf("Info in <KVMultiDetArray::MakeMultiDetector>: Changing dataset\n");
880  gDataSetManager->GetDataSet(dataset_name)->cd();
881  }
882 
883  if (gMultiDetArray && gMultiDetArray->GetDataSet() != dataset_name) {
884  printf("Info in <KVMultiDetArray::MakeMultiDetector>: Deleting existing array %s\n", gMultiDetArray->GetName());
885  if (gIDGridManager) {
886  delete gIDGridManager;
887  gIDGridManager = nullptr;
888  }
889  delete gMultiDetArray;
890  gMultiDetArray = nullptr;
891  }
892 
893 
894  // Creation of database when dataset is selected for first time may
895  // include creation of multidetector array (by calling this method)
896  KVMultiDetArray* mda = nullptr;
897  if (!gMultiDetArray) {
898  TPluginHandler* ph;
899  if (!(ph = LoadPlugin(classname.Data(), dataset_name)))
900  return nullptr;
901 
902  //execute constructor/macro for multidetector - assumed without arguments
903  mda = (KVMultiDetArray*) ph->ExecPlugin(0);
904  mda->fDataSet = dataset_name;
905  mda->Build(run);
906  // set dataset-dependent lists of acceptable ID/E codes for reconstructed nuclei
907  auto codes = GetDataSetEnv<KVString>(dataset_name, Form("%s.ReconstructedNuclei.AcceptIDCodes", mda->GetName()));
908  if (codes != "") mda->fAcceptIDCodes.Set(codes);
909  codes = GetDataSetEnv<KVString>(dataset_name, Form("%s.ReconstructedNuclei.AcceptECodes", mda->GetName()));
910  if (codes != "") mda->fAcceptECodes.Set(codes);
911  // set dataset-dependent condition for seeding reconstructed nuclei
912  mda->SetPartSeedCond(GetDataSetEnv<KVString>(dataset_name, Form("%s.ReconstructedNuclei.ParticleSeedCond", mda->GetName())));
913 #ifdef WITH_RSQLITE
914  // save contents of grid manager in an SQL-ROOT database if not already done
915  if (fMakeMultiDetectorSetParameters && !gIDGridManager->IsSQLROOT()) {
916  // 'if(fMakeMultiDetectorSetParameters...' ensures that we are not currently building a subarray
917  // of a KVExpSetUp. Grids can only be saved once in a single file after all have been read.
918  TString filepath;
919  if (is_gnuinstall()) {
920  // GNU-style install: use working directory $HOME/.kaliveda
921  filepath = GetWORKDIRFilePath(gDataSet->GetName());
922  }
923  else
924  filepath = gDataSet->GetDataSetDir();
925 
926  filepath += "/idgrids_DB";
927 
928  int n_grids_to_write = gIDGridManager->GetGrids()->GetEntries();
929 
930  // we retrieve the index multiplier for the dataset in case it is >1,
931  // we use it to "correct" the runlists for the grids
932  auto index_multiplier = gDataSet->GetDataSetEnv("DataSet.RunFileIndexMultiplier.raw", 1);
933 
934  // we also set the runlist for any grids which don't have one, to the runlist of the entire dataset.
935  // in other words, grids with no runlist are considered valid for all runs
936  if (n_grids_to_write) {
937  KVSQLROOTFile f(filepath, "recreate");
938 
939  printf("Info in <KVMultiDetArray::MakeMultiDetector>: Saving %d grids in SQL-ROOT database file %s\n",
940  n_grids_to_write, filepath.Data());
941 
942  TIter it(gIDGridManager->GetGrids());
943  KVIDGraph* gr;
944  if (!db) db = gExpDB;
945  while ((gr = (KVIDGraph*)it())) {
946  // self-consistently modify runlist if necessary
947  auto rl = gr->GetRuns().GetListDividedBy(index_multiplier);
948  if (rl.IsEmpty() && db) rl = db->GetRunList();
949  gr->SetRuns(rl);
950  f.WriteObject(gr, {
951  {"IDLabel", gr->GetIDTelescopeLabel()},
952  {"IDTelescopes", gr->GetParameters()->GetStringValue("IDTelescopes")},
953  {"VarX", gr->GetVarX()},
954  {"VarY", gr->GetVarY()},
955  {"Runlist", gr->GetRunList()},
956  }
957  );
958  --n_grids_to_write;
959  if (!(n_grids_to_write % 1000)) printf("Info in <KVMultiDetArray::MakeMultiDetector>: ...%d grids left...\n",
960  n_grids_to_write);
961 
962  }
963  }
964  }
965 #endif
966  }
967  else {
968  mda = gMultiDetArray;
969  }
970  // set parameters if required & allowed & not done yet
971  if (fMakeMultiDetectorSetParameters && (run > -1) && gExpDB) mda->SetParameters(run, fMakeMultiDetectorPhysicsParametersOnly);
972  return mda;
973 }
974 
975 
976 
988 
990 {
991  // Return pointer to KVUpDater defined by dataset for this multidetector, the class used
992  // is defined as a plugin like this:
993  //
994  // # Plugin.KVUpDater: name_of_dataset name_of_class name_of_plugin_library constructor_to_call
995  //
996  // However, if a dataset defines a variable like this:
997  //
998  // [dataset].ExpSetUp.Updater.[multidetector name]: [name_of_dataset for plugin]
999  //
1000  // then we use the updater plugin defined for the given dataset
1001 
1002  if (!fUpDater) {
1003  auto alt_updater = KVBase::GetDataSetEnv<KVString>(fDataSet, Form("ExpSetUp.Updater.%s", GetName()));
1004  if (alt_updater != "") fUpDater = KVUpDater::MakeUpDater(alt_updater, this);
1005  else fUpDater = KVUpDater::MakeUpDater(fDataSet, this);
1006  }
1007  Info("GetUpDater", "updater class for dataset %s: %s", fDataSet.Data(), fUpDater->IsA()->GetName());
1008  return fUpDater;
1009 }
1010 
1011 
1012 
1013 
1022 
1023 void KVMultiDetArray::SetParameters(UInt_t run, Bool_t physics_parameters_only)
1024 {
1025  // Set run-dependent parameters of the array.
1026  //
1027  // if physics_parameters_only==false, identification and calibration parameters are set.
1028  // if physics_parameters_only==true, just the minimum necessary for physics analysis of reduced data are set.
1029  //
1030  // This can only be done if gDataSet has been set i.e. a dataset has been chosen,
1031  // otherwise this just has the effect of setting the current run number
1032 
1033  fCurrentRun = run;
1034  KVDataSet* ds = gDataSet;
1035  if (!ds) {
1036  if (gDataSetManager)
1037  ds = gDataSetManager->GetDataSet(fDataSet.Data());
1038  }
1039  if (ds) {
1040  GetUpDater()->SetParameters(run, physics_parameters_only);
1041  SetBit(kParamsSet);
1042  }
1043 }
1044 
1045 
1046 
1047 
1052 
1054 {
1055  //Set identification parameters for run.
1056  //This can only be done if gDataSet has been set i.e. a dataset has been chosen
1057  //Otherwise this just has the effect of setting the current run number
1058 
1059  fCurrentRun = run;
1060  KVDataSet* ds = gDataSet;
1061  if (!ds) {
1062  if (gDataSetManager)
1063  ds = gDataSetManager->GetDataSet(fDataSet.Data());
1064  }
1065  if (ds) {
1067  SetBit(kIDParamsSet);
1068  }
1069 }
1070 
1071 
1072 
1073 
1078 
1080 {
1081  //Set calibration parameters for run.
1082  //This can only be done if gDataSet has been set i.e. a dataset has been chosen
1083  //Otherwise this just has the effect of setting the current run number
1084 
1085  fCurrentRun = run;
1086  KVDataSet* ds = gDataSet;
1087  if (!ds) {
1088  if (gDataSetManager)
1089  ds = gDataSetManager->GetDataSet(fDataSet.Data());
1090  }
1091  if (ds) {
1093  SetBit(kCalParamsSet);
1094  }
1095 }
1096 
1097 
1098 
1099 
1116 
1118 {
1119  //Initialisation of all ACTIVE identification telescopes in the array, i.e. those appearing in a line
1120  //in the .kvrootrc file such as this:
1121  //
1122  //# [dataset name].ActiveIdentifications: [type1] [type2] ...
1123  //
1124  //The 'types' given correspond to the value given by KVIDTelescope::GetLabel(), these are the
1125  //identifiers used to retrieve the different plugin classes in GetIDTelescopes(KVDetector*,KVDetector*,KVList*).
1126  //
1127  //For each type of identification in the list, we retrieve the first identification telescope with this
1128  //label from the list of all ID telescopes, in order to call its KVIDTelescope::SetIdentificationParameters() method.
1129  //This method (when rederived in child classes of KVIDTelescope) initialises the identification objects
1130  //for ALL of the ID telescopes of the same type (class) in the array.
1131  //
1132  //Note that, in general, the parameters of the identifications for a given run are not
1133  //set until SetParameters or SetRunIdentificationParameters is called.
1134 
1135 #ifdef WITH_RSQLITE
1136  // if a KVSQLROOTFile has been filled with the dataset identification parameters we use it.
1137  if (gIDGridManager->IsSQLROOT()) {
1138  // nothing more to do
1139  return;
1140  }
1141  else if (!gDataSet->DataBaseUpdateInProgress())
1142  // the update of the database may have been caused by 1 or more identification files being modified
1143  // (even if they are not part of the database). in this case we read in all the grids again even
1144  // if it has already been done before.
1145  {
1146  TString filepath;
1147  if (is_gnuinstall()) {
1148  // GNU-style install: use working directory $HOME/.kaliveda
1149  filepath = GetWORKDIRFilePath(gDataSet->GetName());
1150  }
1151  else
1152  filepath = gDataSet->GetDataSetDir();
1153 
1154  filepath += "/idgrids_DB";
1155 
1156  if (SearchKVFile(filepath.Data(), filepath)) {
1157  delete gIDGridManager;
1158  gIDGridManager = new KVSQLROOTIDGridManager(filepath);
1159  return;
1160  }
1161  }
1162 #endif
1163 
1164  auto id_labels = GetDataSetEnv<KVString>(fDataSet, "ActiveIdentifications");
1165  if (id_labels == "" || (gDataSet && !gDataSet->HasCalibIdentInfos())) {
1166  Info("SetIdentifications", "No active identifications");
1167  return;
1168  }
1169  //split list of labels
1170  id_labels.Begin(" ");
1171  int ok(0);
1172  //loop over labels/identification 'types'
1173  while (!id_labels.End()) {
1174 
1175  //get first telescope in list with right label
1177  //set ID parameters for all telescopes of this 'type'
1178  if (idt) {
1179  Info("SetIdentifications", "Initialising %s identifications...", idt->GetLabel());
1180  if (idt->SetIdentificationParameters(this))
1181  Info("SetIdentifications", "OK");
1182  ++ok;
1183  }
1184 
1185  }
1186  if (!ok) {
1187  // None of the labels in the list correspond to telescopes in the array
1188  KVError::Warning(this, "SetIdentfications", "No telescopes found with labels given in %s.ActiveIdentifications list: %s",
1189  gDataSet->GetName(), id_labels.Data());
1190  }
1191 }
1192 
1193 
1194 
1195 
1202 
1204 {
1205  // Calls Initialize() method of each identification telescope (see KVIDTelescope
1206  // and derived classes) and sets the general identification code defined for each
1207  // telescope.
1208  //
1209  // Calling this method is essential before identification of particles is attempted.
1210 
1211  TIter next(fIDTelescopes);
1212  KVIDTelescope* idt;
1213  while ((idt = (KVIDTelescope*)next())) {
1214  idt->Initialize();
1215  SetIDCodeForIDTelescope(idt);
1216  }
1217 }
1218 
1219 
1220 
1231 
1233 {
1234  // Read all identification grids from the file and add them to the IDGridManager object
1235  // used by this array. This method sets up the links between each grid and the
1236  // IDtelescope(s) it is to be used for, unlike calling
1237  //
1238  // gIDGridManager->ReadAsciiFile(grids)
1239  //
1240  // which does not.
1241  //
1242  // Returns kFALSE if there is a problem reading the file
1243 
1244  if (gIDGridManager->ReadAsciiFile(grids)) {
1245  TIter next(gIDGridManager->GetLastReadGrids());
1246  KVIDGraph* gr;
1247  while ((gr = (KVIDGraph*)next())) FillListOfIDTelescopes(gr);
1248  return kTRUE;
1249  }
1250  return kFALSE;
1251 }
1252 
1253 
1254 
1255 
1259 
1261 {
1262  // Print full status report on ID telescopes in array, using informations stored in
1263  // fStatusIDTelescopes (see GetStatusOfIDTelescopes).
1264 
1265  cout << endl << "-----STATUS OF IDENTIFICATION TELESCOPES";
1266  if (GetCurrentRunNumber()) cout << " FOR RUN "
1267  << GetCurrentRunNumber();
1268  cout << "------" << endl << endl;
1269  //get list of active telescopes
1270  KVString id_labels;
1271  if (gDataSet) id_labels = gDataSet->GetDataSetEnv<KVString>("ActiveIdentifications");
1272  else {
1273  auto typelist = GetIDTelescopeTypes();
1274  TIter it(&typelist);
1275  TObjString* type;
1276  while ((type = (TObjString*)it())) {
1277  if (id_labels == "") id_labels += type->GetString().Data();
1278  else {
1279  id_labels += Form(" %s", type->GetString().Data());
1280  }
1281  }
1282  }
1283  if (id_labels == "") {
1284  cout << " *** No active identifications *** " << endl;
1285  return;
1286  }
1287  // iterate over labels
1288  unique_ptr<TObjArray> toks(id_labels.Tokenize(' '));
1289 
1290  //update status infos
1292 
1293  TIter next_type(fStatusIDTelescopes);
1294  TList* id_type_list = 0;
1295  while ((id_type_list = (TList*)next_type())) {
1296 
1297  cout << " *** " << id_type_list->GetName() << " Identifications -------------------" << endl;
1298  if (!toks->FindObject(id_type_list->GetName())) {
1299  cout << " [NOT ACTIVE]" << endl;
1300  }
1301  TList* ok_list = (TList*)id_type_list->FindObject("OK");
1302  TList* notok_list = (TList*)id_type_list->FindObject("NOT OK");
1303  TList* print_list = 0;
1304  Int_t Nok = ok_list->GetEntries();
1305  Int_t Notok = notok_list->GetEntries();
1306  if (Nok && Notok) {
1307  if (Nok < Notok) print_list = ok_list;
1308  else print_list = notok_list;
1309  }
1310  if (Nok && (!Notok)) cout << " ALL telescopes are OK" << endl;
1311  else if (Notok && (!Nok)) cout << " NO telescopes are OK" << endl;
1312  else {
1313  cout << " " << ok_list->GetEntries() << " telescopes are OK, "
1314  << notok_list->GetEntries() << " telescopes are NOT OK" << endl;
1315  cout << " " << print_list->GetName() << " :" << endl;
1316  TIter it(print_list);
1317  TObject* ob = it();
1318  cout << ob->GetName();
1319  while ((ob = it())) cout << "," << ob->GetName();
1320  cout << endl;
1321  }
1322  cout << endl;
1323 
1324  }
1325 }
1326 
1327 
1328 
1329 
1337 
1339 {
1340  // Fill and return pointer to list fStatusIDTelescopes which contains
1341  // a list for each type of ID telescope in the array, each list contains a list
1342  // "OK" with the ID telescopes which have IsReadyForID()=kTRUE, and
1343  // a list "NOT OK" with the others.
1344  //
1345  // The returned TList object must not be deleted (it belongs to the KVMultiDetArray).
1346 
1347  if (!fStatusIDTelescopes) {
1348  fStatusIDTelescopes = new TList;
1349  fStatusIDTelescopes->SetOwner(kTRUE);
1350  }
1351  else {
1352  fStatusIDTelescopes->Delete();
1353  }
1354  if (!fIDTelescopes || !fIDTelescopes->GetEntries()) return fStatusIDTelescopes;
1355  TIter next(fIDTelescopes);
1356  KVIDTelescope* idt = 0;
1357  while ((idt = (KVIDTelescope*)next())) {
1358 
1359  TString id_type = idt->GetLabel();
1360  TList* id_type_list = (TList*)fStatusIDTelescopes->FindObject(id_type.Data());
1361  if (!id_type_list) {
1362  id_type_list = new TList;
1363  id_type_list->SetOwner(kTRUE);
1364  id_type_list->SetName(id_type.Data());
1365  fStatusIDTelescopes->Add(id_type_list);
1366  id_type_list->Add(new TList);
1367  ((TList*)id_type_list->At(0))->SetName("OK");
1368  id_type_list->Add(new TList);
1369  ((TList*)id_type_list->At(1))->SetName("NOT OK");
1370  }
1371  if (idt->IsReadyForID())
1372  ((TList*)id_type_list->FindObject("OK"))->Add(idt);
1373  else
1374  ((TList*)id_type_list->FindObject("NOT OK"))->Add(idt);
1375  }
1376  return fStatusIDTelescopes;
1377 }
1378 
1379 
1380 
1381 
1385 
1387 {
1388  // Create, fill and return pointer to a list of TObjString containing the name of each type
1389  // of ID telescope (actually the label) in the array.
1390 
1391  KVUniqueNameList type_list(kTRUE);
1392  type_list.SetOwner();
1393  if (!fIDTelescopes || !fIDTelescopes->GetEntries()) return type_list;
1394  TIter next(fIDTelescopes);
1395  KVIDTelescope* idt = 0;
1396  while ((idt = (KVIDTelescope*)next())) {
1397  type_list.Add(new TObjString(idt->GetLabel()));
1398  }
1399  return type_list;
1400 }
1401 
1402 
1403 
1404 
1412 
1414 {
1415  // Create, fill and return pointer to a list of KVIDTelescopes with
1416  // the given type (label) in the array.
1417  // WARNING! - check pointer is not zero (we return NULL if ID telescopes
1418  // list is not defined or empty)
1419  //
1420  // Delete the KVList after use (it does not own the KVIDTelescopes).
1421 
1422  if (!fIDTelescopes || !fIDTelescopes->GetEntries()) return NULL;
1423  return fIDTelescopes->GetSubListWithLabel(type);
1424 }
1425 
1426 
1427 
1428 
1436 
1438 {
1439  // Fill and return pointer to list fCalibStatusDets which contains
1440  // a list for each type of detector in the array, each list contains a list
1441  // "OK" with the detectors which are calibrated, and
1442  // a list "NOT OK" with the others.
1443  //
1444  // The returned TList object must not be deleted (it belongs to the KVMultiDetArray).
1445 
1446  if (!fCalibStatusDets) {
1447  fCalibStatusDets = new TList;
1448  fCalibStatusDets->SetOwner(kTRUE);
1449  }
1450  else {
1451  fCalibStatusDets->Delete();
1452  }
1453  if (!GetDetectors()->GetEntries()) return fCalibStatusDets;
1454  TIter next(GetDetectors());
1455  KVDetector* det = 0;
1456  while ((det = (KVDetector*)next())) {
1457 
1458  TString type = det->GetType();
1459  TList* type_list = (TList*)fCalibStatusDets->FindObject(type.Data());
1460  if (!type_list) {
1461  type_list = new TList;
1462  type_list->SetOwner(kTRUE);
1463  type_list->SetName(type.Data());
1464  fCalibStatusDets->Add(type_list);
1465  type_list->Add(new TList);
1466  ((TList*)type_list->At(0))->SetName("OK");
1467  type_list->Add(new TList);
1468  ((TList*)type_list->At(1))->SetName("NOT OK");
1469  }
1470  // check for working calibration for detector, taking into account that some may
1471  // have calibrations which only work for certain specific Z values (CsI...)
1472  bool det_is_cal=false;
1473  for(int z=0; z<100; ++z) // note we start from Z=0 (gamma calibration!)
1474  {
1475  if(det->IsCalibrated(Form("Z=%d",z)))
1476  {
1477  det_is_cal=true;
1478  break;
1479  }
1480  }
1481  if (det_is_cal)
1482  ((TList*)type_list->FindObject("OK"))->Add(det);
1483  else
1484  ((TList*)type_list->FindObject("NOT OK"))->Add(det);
1485  }
1486  return fCalibStatusDets;
1487 }
1488 
1489 
1490 
1491 
1495 
1497 {
1498  // Print full status report on calibration of detectors in array, using informations stored in
1499  // fCalibStatusDets (see GetCalibrationStatusOfDetectors).
1500 
1501  if (!GetCurrentRunNumber()) {
1502  Info("PrintCalibStatusOfDetectors", "Cannot know status without knowing RUN NUMBER");
1503  return;
1504  }
1505 
1506  cout << endl << "-----------STATUS OF CALIBRATIONS FOR RUN "
1507  << GetCurrentRunNumber() << "------------" << endl << endl;
1508 
1509  //update status infos
1511 
1512  TIter next_type(fCalibStatusDets);
1513  TList* id_type_list = 0;
1514  while ((id_type_list = (TList*)next_type())) {
1515 
1516  cout << " *** " << id_type_list->GetName() << " Detectors -------------------" << endl;
1517  TList* ok_list = (TList*)id_type_list->FindObject("OK");
1518  TList* notok_list = (TList*)id_type_list->FindObject("NOT OK");
1519  TList* print_list = 0;
1520  Int_t Nok = ok_list->GetEntries();
1521  Int_t Notok = notok_list->GetEntries();
1522  if (Nok && Notok) {
1523  if (Nok < Notok) print_list = ok_list;
1524  else print_list = notok_list;
1525  }
1526  if (Nok && (!Notok)) cout << " ALL calibrations are OK" << endl;
1527  else if (Notok && (!Nok)) cout << " NO calibrations are OK" << endl;
1528  else {
1529  cout << " " << ok_list->GetEntries() << " calibrations are OK, "
1530  << notok_list->GetEntries() << " calibrations are NOT OK" << endl;
1531  cout << " " << print_list->GetName() << " :" << endl;
1532  TIter it(print_list);
1533  TObject* ob = it();
1534  cout << ob->GetName();
1535  while ((ob = it())) cout << "," << ob->GetName();
1536  cout << endl;
1537  }
1538  cout << endl;
1539 
1540  }
1541 }
1542 
1543 
1544 
1545 
1561 
1563 {
1564  // Calculate the energy loss in the current target of the multidetector
1565  // for the reconstructed charged particle 'ion', assuming that the current
1566  // energy and momentum of this particle correspond to its state on
1567  // leaving the target.
1568  //
1569  // WARNING: for this correction to work, the target must be in the right 'state':
1570  //
1571  // gMultiDetArray->GetTarget()->SetIncoming(kFALSE);
1572  // gMultiDetArray->GetTarget()->SetOutgoing(kTRUE);
1573  //
1574  // (see KVTarget::GetParticleEIncFromERes).
1575  //
1576  // The returned value is the energy lost in the target in MeV.
1577  // The energy/momentum of 'ion' are not affected.
1578 
1579  if (fTarget && ion) return (fTarget->GetParticleEIncFromERes(ion) - ion->GetEnergy());
1580  return 0;
1581 }
1582 
1583 
1584 
1585 
1588 
1590 {
1591  // Return pointer to the (ROOT) geometry of the array.
1592  return gGeoManager;
1593 }
1594 
1595 
1596 
1598 
1600 {
1601  return fNavigator.get();
1602 }
1603 
1604 
1605 
1624 
1626 {
1627  // Actual thicknesses of detectors can be given in one or more files associated with a dataset/multidetector.
1628  //
1629  // We look for the first of the files
1630  //~~~~
1631  //[array_name].DetectorThicknessFiles.dat
1632  //DetectorThicknessFiles.dat
1633  //~~~~
1634  // which exists for the current dataset, and if found we read each file listed in it.
1635  //
1636  // Otherwise we look for the first of the files
1637  //~~~~
1638  //[array_name].DetectorThicknesses.dat
1639  //DetectorThicknesses.dat
1640  //~~~~
1641  // which exists for the current dataset, and if found we read the thicknesses from it.
1642  //
1643  // See set_detector_thicknesses() for details of the format of the individual thickness files.
1644 
1645  auto find_a_file = [this](const TString & _base_filename) {
1646  TString filename = TString(GetName()) + "." + _base_filename;
1647  TString fullpath;
1648  if (KVDataSet::FindDataSetFile(fDataSet, filename))
1650 
1651  filename = _base_filename;
1652  if (KVDataSet::FindDataSetFile(fDataSet, filename))
1654 
1655  return TString();
1656  };
1657 
1658  // look for list of files
1659  auto fullpath = find_a_file("DetectorThicknessFiles.dat");
1660  if (!fullpath.IsNull()) {
1661  KVFileReader fr;
1662  fr.OpenFileToRead(fullpath);
1663  while (fr.IsOK()) {
1664  fr.ReadLine(0);
1665  if (fr.GetCurrentLine().BeginsWith("#") || fr.GetCurrentLine() == "") continue;
1666  set_detector_thicknesses(KVDataSet::GetFullPathToDataSetFile(fDataSet, fr.GetCurrentLine()));
1667  }
1668  return;
1669  }
1670 
1671  // look for single file
1672  fullpath = find_a_file("DetectorThicknesses.dat");
1673  if (!fullpath.IsNull()) set_detector_thicknesses(fullpath);
1674 }
1675 
1676 
1677 
1696 
1697 void KVMultiDetArray::set_detector_thicknesses(const TString& fullpath)
1698 {
1699  // Use file given by fullpath to set the real thicknesses of the detectors.
1700  // Any detector which is not in the file will be left with its nominal thickness.
1701  //
1702  // EXAMPLE FILE:
1703  //
1704  //# thickness of detector DET01 in default units
1705  //DET01: 56.4627
1706  //
1707  //# DET03 has several layers
1708  //DET03.Abs0: 61.34
1709  //DET03.Abs1: 205.62
1710  //
1711  // !!! WARNING !!!
1712  // Single-layer detectors: The units are those defined by default for the detector's
1713  // Get/SetThickness methods.
1714  // Multi-layer: Each layer is a KVMaterial object. The thickness MUST be given in centimetres
1715  // (default thickness unit for KVMaterial).
1716 
1717  TEnv thickdat;
1718  if (thickdat.ReadFile(fullpath, kEnvUser) != 0) {
1719  KVError::Error(this, "SetDetectorThicknesses", "Problem opening file %s", fullpath.Data());
1720  return;
1721  }
1722  Info("SetDetectorThicknesses", "Setting thicknesses of detectors from file %s", fullpath.Data());
1723  TIter next(GetDetectors());
1724  KVDetector* det;
1725  while ((det = (KVDetector*)next())) {
1726  if (thickdat.Defined(det->GetName())) {
1727  // simple single layer detector
1728  Double_t thick = thickdat.GetValue(det->GetName(), 0.0);
1729  det->SetThickness(thick);
1730  //Info("SetDetectorThicknesses", "Set thickness of %s to %f", det->GetName(), thick);
1731  }
1732  else {
1733  Char_t i = 0;
1734  TString absname;
1735  absname.Form("%s.Abs%d", det->GetName(), (Int_t)i);
1736  if (thickdat.Defined(absname.Data())) {
1737  // detector with several layers
1738  KVMaterial* abs = 0;
1739  while ((abs = det->GetAbsorber(i))) {
1740  Double_t thick = thickdat.GetValue(absname.Data(), 0.0);
1741  abs->SetThickness(thick);
1742  //Info("SetDetectorThicknesses", "Set thickness of %s.Abs%d to %f", det->GetName(), (Int_t)i, thick);
1743  i++;
1744  absname.Form("%s.Abs%d", det->GetName(), (Int_t)i);
1745  if (!thickdat.Defined(absname.Data())) break;
1746  }
1747  }
1748  }
1749  }
1750 }
1751 
1752 
1753 
1762 
1764 {
1765  // Called by KVGeoImport::ImportGeometry
1766  //
1767  // Creates KVRangeTableGeoNavigator for calculating energy losses of
1768  // particles propagated through array.
1769  //
1770  // If no name and/or title are defined for the array, the name and title of the TGeoManager
1771  // object will be used for the array.
1772 
1773  if (!strcmp(GetName(), "")) SetName(g->GetName());
1774  if (!strcmp(GetTitle(), "")) SetTitle(g->GetTitle());
1775  if (!fNavigator) fNavigator.reset(new KVRangeTableGeoNavigator(g, KVMaterial::GetRangeTable()));
1776 }
1777 
1778 
1779 
1808 
1810 {
1811  // Method for positioning volumes in detector geometries
1812  //
1813  // Given:
1814  //
1815  // distance [cm] = distance from target (origin) to the CENTRE of the volume in position
1816  // theta [deg] = polar angle of vector from target to centre of volume in position
1817  // phi [deg] = azimuthal angle of vector
1818  //
1819  // this method generates the matrix which is required to position the volume as required
1820  // while also turning the volume so that the side nearest the target (i.e. the entrance
1821  // window of the detector) remains perpendicular to the vector joining the origin and
1822  // the centre of the volume.
1823  //
1824  // If required, a further translation can be given which will be applied to the volume after
1825  // it has been placed with the required orientation at the nominal distance. This can be used
1826  // e.g. for detector misalignment, when detectors are in a structure which guarantees their line
1827  // of sight to be orthogonal to their surface at a nominal distance, but the nominal distance
1828  // is not respected.
1829  //
1830  // Example of use:
1831  //
1832  //~~~~~~~~~~~~
1833  // TGeoVolume* vol;// volume to be positioned
1834  // double depth = vol->GetShape()->GetDZ(); // half-width of volume in direction of target
1835  // // place front of volume at 100cm, with theta=45 deg. and phi=60 deg.
1836  // gGeoManager->GetTopVolume()->AddNode(vol, 1, KVMultiDetArray::GetVolumePositioningMatrix(100+depth,45,60));
1837  //~~~~~~~~~~~~
1838 
1839  TGeoRotation rot;
1840  TGeoTranslation trans;
1841  rot.SetAngles(phi + 90, theta, -90) ;
1842  trans.SetDz(distance) ;
1843  TGeoHMatrix h;
1844  if (postTrans) h = (*postTrans) * rot * trans ;
1845  else h = rot * trans;
1846  TGeoHMatrix* ph = new TGeoHMatrix(h);
1847  return ph;
1848 }
1849 
1850 
1851 
1852 
1856 
1858 {
1859  // For each grid which is valid for this run, we call the KVIDTelescope::SetIDGrid method
1860  // of each associated ID telescope.
1861 
1862  if (gIDGridManager->IsSQLROOT()) {
1863  gIDGridManager->LoadGridsForRun(run);
1864  }
1865 
1866  TIter next(gIDGridManager->GetGrids());
1867  KVIDGraph* gr = 0;
1868  while ((gr = (KVIDGraph*) next())) {
1869  if (!gIDGridManager->IsSQLROOT()) {
1870  if (!gr->GetRuns().Contains((Int_t) run))
1871  continue;
1872  }
1873  else
1875 
1876  TIter nxtid(gr->GetListOfIDTelescopes());
1877  KVIDTelescope* idt;
1878  while ((idt = (KVIDTelescope*) nxtid())) {
1879  idt->SetIDGrid(gr);
1880  }
1881  }
1882 }
1883 
1884 
1888 
1890 {
1891  // Fill list of ID telescopes with which this grid is associated
1892  // from list of names read from ascii file.
1893 
1894  if (gr->GetParameters()->HasParameter("IDTelescopes")) {
1895  KVString tel_list = gr->GetParameters()->GetStringValue("IDTelescopes");
1896  tel_list.Begin(",");
1897  gr->ClearListOfIDTelescopes();
1898  while (!tel_list.End()) {
1899  TString tel_name = tel_list.Next();
1900  KVIDTelescope* idt = GetIDTelescope(tel_name.Data()) ;
1901  if (idt) gr->AddIDTelescope(idt);
1902  }
1903  }
1904 }
1905 
1906 
1907 
1917 
1919 {
1920  // Use OpenGL viewer to view multidetector geometry
1921  //
1922  // If option="tracks" we draw any tracks corresponding to the last simulated
1923  // event whose detection was simulated with DetectEvent
1924  // If option="tracks:[numberlist]" with a list of numbers,
1925  // it will be interpreted as a KVNumberList containing the Z of tracks to be drawn
1926  // e.g. option="tracks:1-92" draw only tracks with 1<=Z<=92 (no neutrons)
1927  // option="tracks:2" draw only helium isotopes
1928 
1929  GetGeometry()->GetTopVolume()->Draw("ogl");
1930  KVString opt(option);
1931  opt.Begin(":");
1932  if (opt.Next() == "tracks") {
1933  if (!opt.End()) {
1934  KVNumberList zlist(opt.Next());
1935  GetNavigator()->DrawTracks(&zlist);
1936  }
1937  else
1938  GetNavigator()->DrawTracks();
1939  }
1940 #ifdef WITH_OPENGL
1941  TGLViewer* view = (TGLViewer*)gPad->GetViewer3D();
1944  view->SetSmoothLines(kTRUE);
1945  view->SetSmoothPoints(kTRUE);
1946 #endif
1947 }
1948 
1949 
1950 
1952 
1954 {
1955  fNavigator.reset(geo);
1956 }
1957 
1958 
1959 
1964 
1966 {
1967  // Create TH2F histograms for all IDTelescopes of the array
1968  // They will be added to the list
1969  // histograms will have resolution of dimension*dimension
1970 
1972  KVIDTelescope* idt;
1973  while ((idt = (KVIDTelescope*)it())) {
1974  TString name(idt->GetName());
1975  name.ReplaceAll("-", "_");
1976  list->Add(new TH2F(name, Form("Hits in %s", idt->GetName()), dimension, 0., 0., dimension, 0., 0.));
1977  }
1978 }
1979 
1980 
1981 
1984 
1986 {
1987  // Modify the transparency of detector volumes in OpenGL view
1988 
1989  TIter itV(GetGeometry()->GetListOfVolumes());
1990  TGeoVolume* vol;
1991  while ((vol = (TGeoVolume*)itV())) vol->SetTransparency(t);
1992 }
1993 
1994 
1995 
1999 
2000 void KVMultiDetArray::CalculateReconstructionTrajectories()
2001 {
2002  // Calculate all possible (sub-)trajectories
2003  // for particle reconstruction (GetReconTrajectories())
2004 
2005  unique_ptr<KVSeqCollection> groups(GetStructureTypeList("GROUP"));
2006  TIter it(groups.get());
2007  KVGroup* group;
2008  Int_t ntr = 0;
2009  Info("CalculateReconstructionTrajectories", "Calculating trajectories for particle reconstruction:");
2011  std::cout << "\xd" << " -- calculated " << ntr << " reconstruction trajectories" << std::flush;
2012  while ((group = (KVGroup*)it())) {
2013  ntr += group->CalculateReconstructionTrajectories();
2015  std::cout << "\xd" << " -- calculated " << ntr << " reconstruction trajectories" << std::flush;
2016  }
2018  std::cout << " -- calculated " << ntr << " reconstruction trajectories" << std::endl;
2019  else
2020  std::cout << std::endl;
2021 }
2022 
2023 
2024 
2028 
2029 Bool_t KVMultiDetArray::check_idtelescope_in_allowed_list(const TString& plugin)
2030 {
2031  //if a variable [[dataset].][array name].IDTelescopes is defined, returns true only
2032  //if plugin is in this list
2033 
2034  auto idt_list = GetDataSetEnv<KVString>(fDataSet, Form("%s.IDTelescopes",GetName()));
2035  if(!idt_list.IsNull())
2036  {
2037  // set up map only once, on first call
2038  static std::unordered_map<std::string,int> allowed_idt;
2039  if(allowed_idt.empty())
2040  {
2041  idt_list.Begin(" ");
2042  while(!idt_list.End())
2043  ++allowed_idt[idt_list.Next(true).Data()];
2044  }
2045  auto _plug = plugin;
2046  if(plugin.BeginsWith(Form("%s.",GetName())))
2047  _plug.Remove(0,_plug.Index(".")+1);
2048  return allowed_idt.find(_plug.Data()) != allowed_idt.end();
2049  }
2050  return kTRUE;
2051 }
2052 
2053 
2054 
2064 
2065 void KVMultiDetArray::DeduceIdentificationTelescopesFromGeometry()
2066 {
2067  // Track over all possible particle trajectories calling GetIDTelescopes(KVDetector*,KVDetector*)
2068  // for each pair of (present & functioning) detectors.
2069  //
2070  // This will create all possible KVIDTelescope identification objects using the combinations,
2071  // unless:
2072  //
2073  // + if a variable [[dataset].][array name].IDTelescopes is defined, only the telescopes
2074  // with the labels given in the list will be created
2075 
2076  fIDTelescopes->Delete();
2077  TIter next_traj(GetTrajectories());
2078  KVGeoDNTrajectory* traj;
2079  Int_t count = 0;
2080  Info("DeduceIdentificationTelescopesFromGeometry", "Calculating...");
2082  std::cout << "\xd" << " -- created " << count << " telescopes" << std::flush;
2083  while ((traj = (KVGeoDNTrajectory*)next_traj())) { // loop over all trajectories
2084 
2085  traj->IterateFrom(); // from furthest-out to closest-in detector
2086 
2088  while ((N = traj->GetNextNode())) {
2089  KVGeoDetectorNode* Nplus1 = traj->GetNodeInFront(N);
2090  count += GetIDTelescopes(Nplus1, N->GetDetector(), traj->AccessIDTelescopeList());
2092  std::cout << "\xd" << " -- created " << count << " telescopes" << std::flush;
2093  }
2094  }
2096  std::cout << " -- created " << count << " telescopes" << std::endl;
2097  else
2098  std::cout << std::endl;
2099 }
2100 
2101 
2102 
2106 
2107 void KVMultiDetArray::AssociateTrajectoriesAndNodes()
2108 {
2109  // Eliminate any trajectories which are just sub-trajectories of others
2110  // For each trajectory in list fTrajectories, we add a reference to the trajectory to each node on the trajectory
2111 
2112  TIter it(&fTrajectories);
2113  KVGeoDNTrajectory* tr;
2114  KVList duplicates;
2115  // look for duplicate sub-trajectories
2116  while ((tr = (KVGeoDNTrajectory*)it())) {
2117  int len_tr = tr->GetN();
2118  TIter it2(&fTrajectories);
2119  KVGeoDNTrajectory* tr2;
2120  while ((tr2 = (KVGeoDNTrajectory*)it2())) {
2121  if ((tr2 != tr) && (len_tr < tr2->GetN()) && (tr2->ContainsPath(tr))) {
2122  duplicates.Add(tr);
2123  break;
2124  }
2125  }
2126  }
2127  // remove duplicates
2128  if (duplicates.GetEntries()) {
2129  TIter it_dup(&duplicates);
2130  while ((tr = (KVGeoDNTrajectory*)it_dup())) {
2131  fTrajectories.Remove(tr);
2132  }
2133  Info("AssociateTrajectoriesAndNodes", "Removed %d duplicated sub-trajectories", duplicates.GetEntries());
2134  }
2135  Info("AssociateTrajectoriesAndNodes", "Calculated %d particle trajectories", fTrajectories.GetEntries());
2136  it.Reset();
2137  while ((tr = (KVGeoDNTrajectory*)it())) {
2138  tr->AddToNodes();
2139  }
2140 }
2141 
2142 
2143 
2145 
2147 {
2148  if (N->GetNTraj() > 1) {
2149  if (!multitraj_nodes.FindObject(N)) { // look for any detectors which are on multiple trajectories
2150  //cout << "multitraj node found: " << N->GetName() << " (" << N->GetNTraj() << ")" << endl;
2151  multitraj_nodes.Add(N);
2152  TIter tr(N->GetTrajectories());
2153  KVGeoDNTrajectory* traj;
2154  while ((traj = (KVGeoDNTrajectory*)tr())) { // for each trajectory associated with detector
2155  if (tried_trajectories.FindObject(traj)) continue; // trajectory already used
2156  tried_trajectories.Add(traj);
2157  traj->IterateFrom();
2158  KVGeoDetectorNode* node;
2159  while ((node = traj->GetNextNode())) { // store names of all detectors on trajectory
2160  detectors_of_group.Add(node);
2161  RecursiveTrajectoryClustering(node, tried_trajectories, multitraj_nodes, detectors_of_group);
2162  }
2163  }
2164  }
2165  }
2166  else if (N->GetNTraj() == 1) {
2167  // single-trajectory node.
2168  // work along trajectory adding nodes to group
2169  KVGeoDNTrajectory* traj = (KVGeoDNTrajectory*)N->GetTrajectories()->First();
2170  if (tried_trajectories.FindObject(traj)) return; // trajectory already used
2171  tried_trajectories.Add(traj);
2172  traj->IterateFrom();
2173  KVGeoDetectorNode* node;
2174  while ((node = traj->GetNextNode())) { // store names of all detectors on trajectory
2175  detectors_of_group.Add(node);
2176  RecursiveTrajectoryClustering(node, tried_trajectories, multitraj_nodes, detectors_of_group);
2177  }
2178  }
2179  else {
2180  // orphan node? single-detector array?
2181  detectors_of_group.Add(N);
2182  }
2183 }
2184 
2185 
2186 
2195 
2197 {
2198  // Create and return pointer to new KVGroupReconstructor for reconstructing particles
2199  // in the given group. Returns nullptr if group is not part of this array.
2200  //
2201  // Plugins for specific arrays can be defined as plugins using the name of the array:
2202  // +Plugin.KVGroupReconstructor: my_array my_group_reconstructor my_lib "my_group_reconstructor()"
2203  //
2204  // If we are in 'SimMode', the default reconstructor is a KVFilterGroupReconstructor
2205 
2206  KVGroupReconstructor* gr(nullptr);
2207  if (GetGroup(g->GetName())) {
2208  // look for plugin
2210  if (!gr) {
2211  if (IsSimMode()) return KVGroupReconstructor::Factory("Filter", g);
2212  else
2213  gr = new KVGroupReconstructor(g);
2214  }
2215  }
2216  return gr;
2217 }
2218 
2219 
2220 
2224 
2226 {
2227  // Call this method just after opening a raw data file in order to perform any
2228  // necessary initialisations, depending on the type of data
2229 
2230 #ifdef WITH_BUILTIN_GRU
2231  if (r->GetDataFormat() == "EBYEDAT")
2232  dynamic_cast<KVGANILDataReader*>(r)->ConnectRawDataParameters();
2233 #endif
2234 }
2235 
2236 
2237 
2242 
2243 void KVMultiDetArray::DeduceGroupsFromTrajectories()
2244 {
2245  // Deduce the "groups" in the array from the trajectories
2246  // Any trajectories with 1 or more common detectors define a group.
2247  // The group is constituted of all detectors belonging to the trajectories of the group.
2248 
2249  Info("DeduceGroupsFromTrajectories", "Deducing groups of detectors from trajectories");
2250  Int_t number_of_groups = 0;
2251  TIter next_det(GetDetectors());
2252  unique_ptr<KVSeqCollection> stl(GetStructureTypeList("GROUP"));
2253  if (stl.get() && stl->GetEntries()) {
2254  Info("DeduceGroupsFromTrajectories", "Deleting existing %d groups in array", stl->GetEntries());
2255  ClearStructures("GROUP");
2256  Info("DeduceGroupsFromTrajectories", "Done");
2257  }
2258  KVDetector* det;
2259  KVUniqueNameList tried_trajectories;//avoid double-counting/infinite loops
2260  KVUniqueNameList multitraj_nodes;//avoid double-counting/infinite loops
2261  while ((det = (KVDetector*) next_det())) {
2262  if (det->GetGroup()) continue; // group assignment already done
2263  KVUniqueNameList detectors_of_group;
2264  RecursiveTrajectoryClustering(det->GetNode(), tried_trajectories, multitraj_nodes, detectors_of_group);
2265  if (!detectors_of_group.GetEntries()) continue;
2266  KVGroup* Group = new KVGroup;
2267  Group->SetNumber(++number_of_groups);
2268  Add(Group);
2269  TIter next_node(&detectors_of_group);
2271  while ((d = (KVGeoDetectorNode*)next_node())) Group->Add(d->GetDetector());
2272  }
2273  TIter tr(&fTrajectories);
2274  KVGeoDNTrajectory* t;
2275  Info("DeduceGroupsFromTrajectories", "Filling group trajectory lists");
2276  while ((t = (KVGeoDNTrajectory*)tr())) {
2277  if (t->GetNodeAt(0)->GetDetector()->GetGroup())
2278  t->GetNodeAt(0)->GetDetector()->GetGroup()->AddTrajectory(t);
2279  else {
2280  t->Print();
2281  t->GetNodeAt(0)->GetDetector()->Print();
2282  }
2283  }
2284 }
2285 
2286 
2287 
2291 
2293 {
2294  // Called when required to fill KVReconstructedNucleus::fDetList with pointers to
2295  // the detectors whose names are stored in KVReconstructedNucleus::fDetNames.
2296 
2297  DetList->Clear();
2298  DetNames.Begin("/");
2299  while (!DetNames.End()) {
2300  KVDetector* det = GetDetector(DetNames.Next(kTRUE));
2301  if (det) DetList->Add(det);
2302  }
2303 }
2304 
2305 
2306 
2326 
2328 {
2329  // Set status of particle by comparing its identification/calibration codes
2330  // with those set as acceptable in fAcceptIDCodes and fAcceptECodes.
2331  // The status can be tested with method KVReconstructedNucles::IsOK().
2332  //
2333  // The default lists are defined in variables of the form
2334  //```
2335  // [DataSet].[name].ReconstructedNuclei.AcceptIDCodes: [list]
2336  // [DataSet].[name].ReconstructedNuclei.AcceptECodes: [list]
2337  //```
2338  // where:
2339  // + `DataSet` is an optional dataset name for dataset-specific lists
2340  // + `name` is the name of the multidetector array
2341  // + `list` is a numeric list (KVNumberList format)
2342  //
2343  // The default lists can be overridden using methods AcceptIDCodes(), AcceptECodes(),
2344  // AcceptAllIDCodes() and AcceptAllECodes().
2345  //
2346  // If either list is empty, no selection is made for the corresponding code
2347 
2348  Bool_t ok = kTRUE;
2349  if (!fAcceptIDCodes.IsEmpty()) ok = fAcceptIDCodes.Contains(NUC->GetIDCode());
2350  if (!fAcceptECodes.IsEmpty()) ok = ok && fAcceptECodes.Contains(NUC->GetECode());
2351  NUC->SetIsOK(ok);
2352 }
2353 
2354 
2355 #ifdef WITH_BUILTIN_GRU
2356 
2359 
2360 Bool_t KVMultiDetArray::handle_raw_data_event_ebyedat(KVGANILDataReader&)
2361 {
2362  // General method for reading raw data in old GANIL ebyedat format
2363  AbstractMethod("handle_raw_data_event_ebyedat");
2364  return kFALSE;
2365 }
2366 
2367 #endif
2368 
2369 
2372 
2374 {
2375  // reset acquisition parameters etc. before reading new raw data event
2376 
2377  fReconParameters.Clear();
2378  fFiredDetectors.Clear();
2379  fHandledRawData = false;
2380  // reset fired signals
2381  TIter nxt(&fFiredSignals);
2382  KVDetectorSignal* ds;
2383  while ((ds = (KVDetectorSignal*)nxt())) {
2384  ds->SetFired(false);
2385  ds->SetValue(0);
2386  }
2387  fFiredSignals.Clear();
2388 }
2389 
2390 
2391 
2399 
2400 void KVMultiDetArray::PerformClosedROOTGeometryOperations()
2401 {
2402  // Perform any operations to finalise the description of the multidetector
2403  // which can only be done once the geometry is closed, e.g. use KVGeoImport
2404  // to set up nodes, trajectories, detectors, idtelescopes, etc.
2405  // This has to be kept separate for use with KVExpSetUp which first fills
2406  // a single ROOT geometry with all component KVMultiDetArray geometries,
2407  // then closes the geometry only when all have been built.
2408 }
2409 
2410 
2411 
2414 
2416 {
2417  // Copy any parameters in fReconParameters in to the reconstructed event parameter list
2418  e->GetParameters()->Concatenate(fReconParameters);
2419 }
2420 
2421 
2422 
2435 
2436 void KVMultiDetArray::copy_fired_parameters_to_recon_param_list()
2437 {
2438  // values of fired raw data signals (acquisition parameters) from last read raw event
2439  // are copied to the fReconParameters list of parameters to be stored with the
2440  // reconstructed event.
2441  //
2442  // the format for each signal is:
2443  //
2444  // ACQPAR.[array].[detector].[signal]
2445  // ACQPAR.[array].[signal]
2446  //
2447  // in the first case for signals associated with detectors, in the latter case signals
2448  // which are not associated with a detector
2449 
2450  TIter it(GetFiredSignals());
2451  KVDetectorSignal* o;
2452  while ((o = (KVDetectorSignal*)it())) {
2453  fReconParameters.SetValue(Form("ACQPAR.%s.%s", GetName(), o->GetFullName().Data()), o->GetValue());
2454  }
2455 }
2456 
2457 
2458 
2467 
2469 {
2470  // Update array according to last event read using the KVRawDataReader object
2471  // (it is assumed that KVRawDataReader::GetNextEvent() was called before calling this method)
2472  //
2473  // Return kTRUE if raw data was treated
2474  //
2475  // All fired acquisition parameters are written in the fReconParameters list,
2476  // ready to be copied to the reconstructed event
2477 
2478  fRawDataReader = rawdata;
2480  if (rawdata->GetDataFormat() == "MFM") {
2481 #ifdef WITH_MFM
2482  fHandledRawData = handle_raw_data_event_mfmfile(dynamic_cast<KVMFMDataFileReader&>(*rawdata));
2483 #endif
2484  }
2485  else if (rawdata->GetDataFormat() == "PROTOBUF") {
2486 #ifdef WITH_PROTOBUF
2487  fHandledRawData = handle_raw_data_event_protobuf(dynamic_cast<KVProtobufDataReader&>(*rawdata));
2488 #endif
2489  }
2490  else if (rawdata->GetDataFormat() == "EBYEDAT") {
2491 #ifdef WITH_BUILTIN_GRU
2492  fHandledRawData = handle_raw_data_event_ebyedat(dynamic_cast<KVGANILDataReader&>(*rawdata));
2493 #endif
2494  }
2495  if (fHandledRawData) {
2496  copy_fired_parameters_to_recon_param_list();
2497  }
2498  return fHandledRawData;
2499 }
2500 
2501 
2502 #ifdef WITH_MFM
2503 
2512 
2514 {
2515  // Update array according to last event read from MFM buffer
2516  // (it is assumed that MFMBufferReader::ReadNextFrame() was called before calling this method)
2517  //
2518  // Return kTRUE if raw data was treated
2519  //
2520  // All fired acquisition parameters are written in the fReconParameters list,
2521  // ready to be copied to the reconstructed event
2522 
2524  bool ok = false;
2525  ok = handle_raw_data_event_mfmfile(bufrdr);
2526  if (ok) {
2527  copy_fired_parameters_to_recon_param_list();
2528  }
2529  return ok;
2530 }
2531 
2532 #endif
2533 
2534 
2545 
2546 void KVMultiDetArray::add_and_set_detector_signal(KVDetector* detector, KVString detname, Double_t sig_data, KVString sig_type)
2547 {
2548  // Given a pointer to a detector (may be nullptr) try to set the data sig_data in the associated signal
2549  // of the given type, sig_typ.
2550  //
2551  // If the signal does not exist for the detector, it will be created.
2552  //
2553  // If detector pointer is null, the signal will be looked for in fExtraRawDataSignals
2554  // and created if necessary.
2555  //
2556  // All fired detectors and signals are added to the lists fFiredDetectors and fFiredSignals.
2557 
2558  KVDetectorSignal* det_signal = nullptr;
2559  if (detector) {
2560  det_signal = detector->GetDetectorSignal(sig_type);
2561  if (!det_signal) {
2562  det_signal = detector->AddDetectorSignal(sig_type);
2563  }
2564  fFiredDetectors.Add(detector);
2565  }
2566  else {
2567  // raw data not associated with a detector
2568  TString sig_name;
2569  if (detname != "") sig_name = Form("%s.%s", detname.Data(), sig_type.Data());
2570  else sig_name = sig_type;
2571  det_signal = fExtraRawDataSignals.get_object<KVDetectorSignal>(sig_name);
2572  if (!det_signal) {
2573  det_signal = new KVDetectorSignal(sig_name);
2574  fExtraRawDataSignals.Add(det_signal);
2575  }
2576  }
2577  if (det_signal) {
2578  det_signal->SetValue(sig_data);
2579  det_signal->SetFired();
2580  fFiredSignals.Add(det_signal);
2581  }
2582 }
2583 
2584 
2585 
2591 
2593 {
2594  // Take values 'ACQPAR.[array_name].[detname].[signal]' or 'ACQPAR.[array_name].[signal]'
2595  // in the parameter list and use them to set values of raw acquisition parameters.
2596  //
2597  // Any detector signals which don't already exist will be created
2598 
2599  prepare_to_handle_new_raw_data(); // clear previous fired parameters/detectors
2600  auto l = recev.GetParameters();
2601  int N = l->GetNpar();
2602  for (int i = 0; i < N; ++i) {
2603  KVNamedParameter* np = l->GetParameter(i);
2604 
2605  KVString name(np->GetName());
2606  if (name.BeginsWith("ACQPAR")) {
2607  // 3 '.' => 4 values means associated detector
2608  // 2 '.' => 3 values means no detector
2609  int dots = name.GetNValues(".");
2610  bool with_det = (dots == 4);
2611  assert(with_det || (dots == 3)); // sanity check
2612  name.Begin(".");
2613  name.Next(); // "ACQPAR"
2614  if (name.Next() != GetName()) continue; // check name of array - somebody else's parameter ?
2615  KVString det_name;
2616  KVString sig_type;
2617  KVDetector* det = nullptr;
2618  if (with_det) {
2619  det_name = name.Next();
2620  sig_type = name.Next();
2621  det = GetDetector(det_name);
2622  }
2623  else {
2624  sig_type = name.Next();
2625  }
2626  add_and_set_detector_signal(det, det_name, np->GetDouble(), sig_type);
2627  }
2628  }
2629 }
2630 
2631 
2632 
2651 
2653 {
2654  // We first look for following files with the name given by
2655  //
2656  // [dataset].[name].OoODetectors: [name.OoODetectors.dat]
2657  // which should contain the runlists for each malfunctioning detector.
2658  // If found we add to the experiment database a table '[name].OoO Detectors' where [name] is the name of this array.
2659  //
2660  // [dataset].[name].AbsentDetectors: [name.AbsentDetectors.dat]
2661  // which should contain the runlists for each absent detector.
2662  // If found we add to the experiment database a table '[name].Absent Detectors' where [name] is the name of this array.
2663  //
2664  // Then we look for a file with the name given by
2665  //
2666  // [dataset].[name].CalibrationFiles: [CalibrationFiles.dat]
2667  //
2668  // which should contain the names of files to read with each type of calibration
2669  // If found we add to the experiment database a table '[name].Calibrations' where [name] is the name of this array,
2670  // containing all calibrations as KVDBParameterSet objects with the name of the detector concerned.
2671  db->SetDBType(Form("%sDB", GetName()));
2672  ReadOoODetectors(db);
2673  ReadAbsentDetectors(db);
2674  ReadCalibrationFiles(db);
2675 }
2676 
2677 
2678 
2680 
2681 TString KVMultiDetArray::GetFileName(KVExpDB* db, const Char_t* meth, const Char_t* keyw)
2682 {
2683  TString basic_name = db->GetCalibFileName(keyw);
2684  if (basic_name == "") {
2685  Info(meth, "No name found for \"%s\" file", keyw);
2686  return "";
2687  }
2688  Info(meth, "Search for %s for dataset %s ...", basic_name.Data(), fDataSet.Data());
2689  TString fp;
2690  SearchKVFile(basic_name.Data(), fp, fDataSet);
2691  if (fp == "") {
2692  Info(meth, "\tNo file found ...");
2693  }
2694  return fp;
2695 }
2696 
2697 
2698 
2700 
2701 unique_ptr<KVFileReader> KVMultiDetArray::GetKVFileReader(KVExpDB* db, const Char_t* meth, const Char_t* keyw)
2702 {
2703 
2704  TString fp = GetFileName(db, meth, keyw);
2705  if (fp == "")
2706  return unique_ptr<KVFileReader>();
2707 
2708  unique_ptr<KVFileReader> fr(new KVFileReader());
2709  if (!fr->OpenFileToRead(fp.Data())) {
2710  KVError::Error(this, meth, "Error in opening file %s", fp.Data());
2711  fr.reset(nullptr);
2712  }
2713  else
2714  KVError::Info(this, meth, "Reading %s file", fp.Data());
2715  return fr;
2716 }
2717 
2718 
2719 
2721 
2722 void KVMultiDetArray::ReadCalibrationFiles(KVExpDB* db)
2723 {
2724 
2725  unique_ptr<KVFileReader> fr = GetKVFileReader(db, "ReadCalibrationFiles()", "CalibrationFiles");
2726  if (!fr.get())
2727  return;
2728 
2729  KVDBTable* calib_table = db->AddTable(Form("%s.Calibrations", GetName()), Form("Calibrations for %s", GetName()));
2730  while (fr->IsOK()) {
2731  fr->ReadLine(0);
2732  if (fr->GetCurrentLine().BeginsWith("#") || fr->GetCurrentLine() == "") {}
2733  else {
2734  ReadCalibFile(fr->GetCurrentLine().Data(), db, calib_table);
2735  }
2736  }
2737  fr->CloseFile();
2738 }
2739 
2740 
2741 
2787 
2788 void KVMultiDetArray::ReadCalibFile(const Char_t* filename, KVExpDB* db, KVDBTable* calib_table)
2789 {
2790  // Read a calibration file with the format
2791  //
2792  //~~~~~~~~~~~~~
2793  // RunList: 1546-7485
2794  // SignalIn: PG
2795  // SignalOut: Volts
2796  // CalibType: ChannelVolt
2797  // CalibOptions: func=pol3,min=0,max=1
2798  // ZRange: 2-92
2799  // [detector1]: 0.0,0.261829,0.0
2800  // [detector2]: 0.1 0.539535 1.2
2801  //~~~~~~~~~~~~~
2802  //
2803  //The `[RunList]` is optional: if not given, the calibration will be applied to all runs in the database.
2804  //
2805  //If different parameters are required for different sets of runs, they should be written in different
2806  //files (all of which are listed in `CalibrationFiles.dat` or `[array].CalibrationFiles.dat`).
2807  //
2808  //Numerical parameter values for each detector can be given separated by commas, whitespace or tab characters.
2809  //
2810  //The `[CalibClass]`, if given, must correspond to a KVCalibrator plugin name. The list of plugin names and the corresponding
2811  //classes can be retrieved with
2812  //
2813  //~~~~~~~~~~~
2814  //KVBase::GetListOfPlugins("KVCalibrator")
2815  //KVBase::GetListOfPluginURIs("KVCalibrator")
2816  //~~~~~~~~~~~
2817  //
2818  //KVCalibrator objects are added to detectors as required by the contents of calibration files.
2819  //If any detector has an existing calibrator of type `[CalibType]` which is not of the given class
2820  //it will be replaced with a new calibrator corresponding to the plugin.
2821  //
2822  //The `[CalibOptions]` is optional: list in `[CalibOptions]` will be used
2823  //to complete set-up of any new calibrator objects by calling the KVCalibrator::SetOptions()
2824  //method.
2825  //
2826  //`[CalibOptions]` should hold a comma-separated list of `parameter=value` pairs which will be used
2827  //to fill a KVNameValueList for the method call. See the KVCalibrator::SetOptions() method.
2828  //
2829  //`[ZRange]` is an option if several calibrations need to be used to provide the same signal
2830  //for certain detectors depending on the atomic number Z of the particle detected.
2831  //
2832  // If any of the detector names (`[detector1]`, `[detector2]` in above example) contains the `'*'` wildcard character,
2833  // it will be interpreted as a list of detectors whose names correspond to the given wildcard expression.
2834 
2835 
2836  TString fullpath = "";
2837  if (!SearchKVFile(filename, fullpath, fDataSet)) {
2838  Info("ReadCalibFile", "%s does not exist or not found", filename);
2839  return;
2840  }
2841 
2842  Info("ReadCalibFile", "file : %s found", fullpath.Data());
2843  TEnv env;
2844  env.ReadFile(fullpath, kEnvAll);
2845 
2846  // read options from file
2847  KVNameValueList options;
2848  KVString opt_list = "RunList SignalIn SignalOut CalibType CalibClass CalibOptions ZRange";
2849  opt_list.Begin(" ");
2850  while (!opt_list.End()) {
2851  KVString opt = opt_list.Next();
2852  KVString opt_val = env.GetValue(opt, "");
2853  opt_val.Remove(TString::kBoth, ' ');
2854  options.SetValue(opt, opt_val.Data());
2855  }
2856  // check for stupid spellnig mitskaes
2857  if (TString(env.GetValue("Runlist", "")) != "") {
2858  KVError::Warning(this, "ReadCalibFile", "Calibration has 'Runlist' parameter (ignored): %s, did you mean 'RunList'?", env.GetValue("Runlist", ""));
2859  }
2860 
2861  if (options.GetTStringValue("SignalIn") == "") {
2862  KVError::Error(this, "ReadCalibFile", "No input signal defined : SignalIn");
2863  return;
2864  }
2865  if (options.GetTStringValue("SignalOut") == "") {
2866  KVError::Error(this, "ReadCalibFile", "No output signal defined : SignalOut");
2867  return;
2868  }
2869  if (options.GetTStringValue("CalibType") == "") {
2870  KVError::Error(this, "ReadCalibFile", "No calibration type defined : CalibType");
2871  return;
2872  }
2873  Bool_t check_class(options.GetTStringValue("CalibClass") != "");
2874  TString calibrator_class;
2875  if (check_class) {
2876  TPluginHandler* ph = LoadPlugin("KVCalibrator", options.GetStringValue("CalibClass"));
2877  if (ph) calibrator_class = ph->GetClass();
2878  else {
2879  KVError::Error(this, "ReadCalibFile", "No calibrator plugin of type %s", options.GetStringValue("CalibClass"));
2880  return;
2881  }
2882  }
2883 
2884  KVString clop;
2885  if (options.HasParameter("CalibOptions")) clop = options.GetStringValue("CalibOptions");
2886 
2887  KVString zrange;
2888  if (options.HasParameter("ZRange")) zrange = options.GetStringValue("ZRange");
2889 
2890  KVNumberList run_list = db->GetRunList();
2891  if (options.GetTStringValue("RunList") != "") {
2892  run_list.Set(options.GetTStringValue("RunList"));
2893  Info("ReadCalibFile", "Calibration used for runs %s", run_list.AsString());
2894  }
2895  else {
2896  Info("ReadCalibFile", "Calibration used for all runs in database");
2897  }
2898 
2899  TIter next(env.GetTable());
2900  TEnvRec* rec = nullptr;
2901  KVDBParameterSet* par = nullptr;
2902 
2903  // valid delimiters for numerical parameters are: space - comma - tab
2904  // here we add ':' because if there is space in the TEnv file between the key name and the ':'
2905  // i.e. if we have
2906  // SI2-11 : 0.1,0.3
2907  // then the ':' becomes part of the value: TEnv::GetValue("SI2-11","") will give ": 0.1,0.3"
2908  // instead of
2909  // SI2-11: 0.1,0.3
2910  // => TEnv::GetValue("SI2-11","") gives "0.1,0.3"
2911  TString param_delimiters = ":, \t";
2912 
2913  auto set_calib_parameters = [&](const TEnvRec* rec, const KVDetector* det)
2914  {
2915  KVString lval(rec->GetValue());
2916  par = new KVDBParameterSet(det->GetName(), options.GetStringValue("CalibType"), lval.GetNValues(param_delimiters));
2917  par->SetParameter("SignalIn", options.GetStringValue("SignalIn"));
2918  par->SetParameter("SignalOut", options.GetStringValue("SignalOut"));
2919  // put infos on required calibrator class into database so that it can be replaced
2920  // as needed in SetCalibratorParameters
2921  par->SetParameter("CalibClass", options.GetStringValue("CalibClass"));
2922  if (clop != "") par->SetParameter("CalibOptions", clop);
2923  if (zrange != "") par->SetParameter("ZRange", zrange);
2924  Int_t np = 0;
2925  lval.Begin(param_delimiters);
2926  while (!lval.End()) {
2927  par->SetParameter(np++, lval.Next().Atof());
2928  }
2929  calib_table->AddRecord(par);
2930  db->LinkRecordToRunRange(par, run_list);
2931  };
2932 
2933  while ((rec = (TEnvRec*)next()))
2934  {
2935  std::unique_ptr<KVSeqCollection> det_list{GetDetectorNameList(rec->GetName())};
2936  for(auto p_det : *det_list)
2937  set_calib_parameters(rec,dynamic_cast<KVDetector*>(p_det));
2938  }
2939 }
2940 
2941 
2942 #ifdef WITH_MFM
2943 
2949 
2950 Bool_t KVMultiDetArray::handle_raw_data_event_mfmfile(MFMBufferReader& mfmreader)
2951 {
2952  // Update array according to last event read using the KVMFMDataFileReader object
2953  // (it is assumed that KVRawDataReader::GetNextEvent() was called before calling this method)
2954  //
2955  // Return kTRUE if raw data was treated
2956 
2957  if (mfmreader.IsFrameReadMerge()) {
2958  return handle_raw_data_event_mfmmergeframe(mfmreader.GetMergeManager());
2959  }
2960  else {
2961  return handle_raw_data_event_mfmframe(mfmreader.GetFrameRead());
2962  }
2963  return kFALSE;
2964 }
2965 
2966 
2967 
2971 
2972 Bool_t KVMultiDetArray::handle_raw_data_event_mfmmergeframe(const MFMMergeFrameManager& mergeframe)
2973 {
2974  // Method used to handle merged MFM frames
2975  // We call handle_raw_data_event_mfmframe() for each frame contained in the merge
2976 
2977  Bool_t ok = false;
2978  while (mergeframe.ReadNextFrame()) {
2979  Bool_t me = handle_raw_data_event_mfmframe(mergeframe.GetFrameRead());
2980  ok = (ok || me);
2981  }
2982  return ok;
2983 }
2984 
2985 
2986 
2997 
2998 Bool_t KVMultiDetArray::handle_raw_data_event_mfmframe(const MFMCommonFrame& mfmframe)
2999 {
3000  // Method used to treat raw data in MFM format read by KVMFMDataFileReader
3001  //
3002  // Here we dispatch two types of frame - MFMEbyedatFrame & MFMMesytecMDPPFrame -
3003  // to specific methods - handle_raw_data_event_mfmframe_ebyedat() and
3004  // handle_raw_data_event_mfmframe_mesytec_mdpp()
3005  // which need to be implemented in child classes for specific arrays which
3006  // use these data formats.
3007  //
3008  // Return kTRUE if raw data was treated
3009 #ifdef WITH_MESYTEC
3010  if (mfmframe.GetFrameType() == MFM_MESYTEC_FRAME_TYPE)
3011  return handle_raw_data_event_mfmframe_mesytec_mdpp((const MFMMesytecMDPPFrame&)mfmframe);
3012 #endif
3013  if (mfmframe.GetFrameType() == MFM_EBY_EN_FRAME_TYPE
3014  || mfmframe.GetFrameType() == MFM_EBY_TS_FRAME_TYPE
3015  || mfmframe.GetFrameType() == MFM_EBY_EN_TS_FRAME_TYPE)
3016  return handle_raw_data_event_mfmframe_ebyedat((const MFMEbyedatFrame&)mfmframe);
3017 
3018  return kFALSE;
3019 }
3020 
3021 
3022 
3025 
3026 Bool_t KVMultiDetArray::handle_raw_data_event_mfmframe_ebyedat(const MFMEbyedatFrame&)
3027 {
3028  // Read a raw data event from a EBYEDAT MFM Frame.
3029 
3030  AbstractMethod("handle_raw_data_event_mfmframe_ebyedat");
3031  return kFALSE;
3032 }
3033 
3034 
3035 #ifdef WITH_MESYTEC
3036 
3039 
3040 Bool_t KVMultiDetArray::handle_raw_data_event_mfmframe_mesytec_mdpp(const MFMMesytecMDPPFrame&)
3041 {
3042  // Read a raw data event from a Mesytec MFM Frame.
3043 
3044  AbstractMethod("handle_raw_data_event_mfmframe_mesytec_mdpp");
3045  return kFALSE;
3046 }
3047 
3048 #endif
3049 #endif
3050 
3051 #ifdef WITH_PROTOBUF
3052 
3054 
3055 Bool_t KVMultiDetArray::handle_raw_data_event_protobuf(KVProtobufDataReader&)
3056 {
3057  AbstractMethod("handle_raw_data_event_protobuf");
3058  return kFALSE;
3059 }
3060 
3061 #endif
3062 
3063 
3066 
3068 {
3069  // For each IDtelescope in array, calculate an identification grid
3070 
3071  TIter nxtid(GetListOfIDTelescopes());
3072  KVIDTelescope* idt;
3073  while ((idt = (KVIDTelescope*) nxtid())) {
3074  idt->CalculateDeltaE_EGrid("1-92", 0, 20);
3075  }
3076 }
3077 
3078 
3079 
3084 
3086 {
3087  // Sets status of detectors (KVDetector::IsPresent() and KVDetector::IsWorking()) for a given run of a dataset.
3088  //
3089  // If 'myname' is given, we look in database table "myname.OoODets"
3090 
3091  KVRList* absdet = (myname != "" ? kvrun->GetLinks(Form("%s.Absent Detectors", myname.Data())) : kvrun->GetLinks("Absent Detectors"));
3092  KVRList* ooodet = (myname != "" ? kvrun->GetLinks(Form("%s.OoO Detectors", myname.Data())) : kvrun->GetLinks("OoO Detectors"));
3093 
3094  TIter next(GetDetectors());
3095  KVDetector* det;
3096 
3097  Int_t ndet_absent = 0;
3098  Int_t ndet_ooo = 0;
3099  TString absent_dets, ooo_dets;
3100 
3101  while ((det = (KVDetector*)next())) {
3102  //Test de la presence ou non du detecteur
3103  if (!absdet) {
3104  det->SetPresent();
3105  }
3106  else {
3107  if (absdet->FindObject(det->GetName())) {
3108  det->SetPresent(kFALSE);
3109  if (ndet_absent) absent_dets += ",";
3110  absent_dets += det->GetName();
3111  ndet_absent += 1;
3112  }
3113  else {
3114  det->SetPresent();
3115  }
3116  }
3117  if (det->IsPresent()) {
3118  //Test du bon fonctionnement ou non du detecteur
3119  if (!ooodet) {
3120  det->SetDetecting();
3121  }
3122  else {
3123  if (ooodet->FindObject(det->GetName())) {
3124  det->SetDetecting(kFALSE);
3125  if (ndet_ooo) ooo_dets += ",";
3126  ooo_dets += det->GetName();
3127  ndet_ooo += 1;
3128  }
3129  else {
3130  det->SetDetecting();
3131  }
3132  }
3133  }
3134  }
3135 
3136  if (ndet_absent) Info("CheckStatusOfDetectors", "%d detectors absent during run : %s", ndet_absent, absent_dets.Data());
3137  else Info("CheckStatusOfDetectors", "All detectors present during run");
3138  if (ndet_ooo) Info("CheckStatusOfDetectors", "%d detectors malfunctioned during run : %s", ndet_ooo, ooo_dets.Data());
3139  else Info("CheckStatusOfDetectors", "All detectors functioning during run");
3140 }
3141 
3142 
3143 
3145 
3147 {
3148  CheckStatusOfDetectors(dbr, myname);
3149 }
3150 
3151 
3152 
3167 
3168 void KVMultiDetArray::ReadOoODetectors(KVExpDB* db)
3169 {
3170  // Read a file containing runlists for each temporarily non-functioning detector.
3171  //
3172  // The file should be in TEnv format like so:
3173  //
3174  //~~~~
3175  // DET_1: 100-122,541-1938
3176  // DET_2,DET_3: 91-765
3177  //~~~~
3178  //
3179  // i.e. more than one detector can be associated with the same runs (comma-separated list of
3180  // detector names) and the list of runs are given using KVNumberList syntax.
3181  //
3182  // The data is added to the database in a table '[name].OoO Detectors' with the name of this array.
3183 
3184  TString fullpath;
3185  if (!db->FindCalibFile("OoODet", fullpath, GetName())) return;
3186 
3187  Info("ReadOoODetectors()", "Reading lists of out-of-order detectors...");
3188  auto fOoODet = db->AddTable(Form("%s.OoO Detectors", GetName()), "Name of out of order detectors");
3189 
3190  KVDBRecord* dbrec = 0;
3191  TEnv env;
3192  TEnvRec* rec = 0;
3193  env.ReadFile(fullpath.Data(), kEnvAll);
3194  TIter it(env.GetTable());
3195 
3196  while ((rec = (TEnvRec*)it.Next())) {
3197  KVString srec(rec->GetName());
3198  KVNumberList nl(rec->GetValue());
3199  if (srec.Contains(",")) {
3200  srec.Begin(",");
3201  while (!srec.End()) {
3202  dbrec = new KVDBRecord(srec.Next(kTRUE), "OoO Detector");
3203  dbrec->AddKey("Runs", "List of Runs");
3204  fOoODet->AddRecord(dbrec);
3205  db->LinkRecordToRunRange(dbrec, nl);
3206  }
3207  }
3208  else {
3209  dbrec = new KVDBRecord(rec->GetName(), "OoO Detector");
3210  dbrec->AddKey("Runs", "List of Runs");
3211  fOoODet->AddRecord(dbrec);
3212  db->LinkRecordToRunRange(dbrec, nl);
3213  }
3214  }
3215 }
3216 
3217 
3232 
3233 void KVMultiDetArray::ReadAbsentDetectors(KVExpDB* db)
3234 {
3235  // Read a file containing runlists for each temporarily absent/dismounted detector.
3236  //
3237  // The file should be in TEnv format like so:
3238  //
3239  //~~~~
3240  // DET_1: 100-122,541-1938
3241  // DET_2,DET_3: 91-765
3242  //~~~~
3243  //
3244  // i.e. more than one detector can be associated with the same runs (comma-separated list of
3245  // detector names) and the list of runs are given using KVNumberList syntax.
3246  //
3247  // The data is added to the database in a table '[name].Absent Detectors' with the name of this array.
3248 
3249  TString fullpath;
3250  if (!db->FindCalibFile("AbsentDet", fullpath, GetName())) return;
3251 
3252  Info("ReadAbsentDetectors()", "Reading lists of absent/dismounted detectors... file=[%s]", fullpath.Data());
3253  auto fAbsDet = db->AddTable(Form("%s.Absent Detectors", GetName()), "Name of out of order detectors");
3254 
3255  KVDBRecord* dbrec = 0;
3256  TEnv env;
3257  TEnvRec* rec = 0;
3258  env.ReadFile(fullpath.Data(), kEnvAll);
3259  TIter it(env.GetTable());
3260 
3261  while ((rec = (TEnvRec*)it.Next())) {
3262  KVString srec(rec->GetName());
3263  KVNumberList nl(rec->GetValue());
3264  if (srec.Contains(",")) {
3265  srec.Begin(",");
3266  while (!srec.End()) {
3267  dbrec = new KVDBRecord(srec.Next(kTRUE), "Absent Detector");
3268  dbrec->AddKey("Runs", "List of Runs");
3269  fAbsDet->AddRecord(dbrec);
3270  db->LinkRecordToRunRange(dbrec, nl);
3271  }
3272  }
3273  else {
3274  dbrec = new KVDBRecord(rec->GetName(), "Absent Detector");
3275  dbrec->AddKey("Runs", "List of Runs");
3276  fAbsDet->AddRecord(dbrec);
3277  db->LinkRecordToRunRange(dbrec, nl);
3278  }
3279  }
3280 }
3281 
3282 
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
#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 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:201
virtual const Char_t * GetType() const
Definition: KVBase.h:177
static const Char_t * GetWORKDIRFilePath(const Char_t *namefile="")
Definition: KVBase.cpp:120
const Char_t * GetLabel() const
Definition: KVBase.h:205
static bool is_gnuinstall()
Definition: KVBase.h:284
void Print(Option_t *option="") const override
Definition: KVBase.cpp:412
virtual void SetType(const Char_t *str)
Definition: KVBase.h:173
static Bool_t SearchKVFile(const Char_t *name, TString &fullpath, const Char_t *kvsubdir="")
Definition: KVBase.cpp:540
static TPluginHandler * LoadPlugin(const Char_t *base, const Char_t *uri="0")
Definition: KVBase.cpp:795
Base class for all detector calibrations.
Definition: KVCalibrator.h:99
virtual Int_t GetNumberParams() const
Definition: KVCalibrator.h:154
virtual void SetParameter(int i, Double_t par_val)
Definition: KVCalibrator.h:159
virtual void SetOptions(const KVNameValueList &)
void SetStatus(Bool_t ready)
Definition: KVCalibrator.h:167
void SetOutputSignalType(const TString &type)
Definition: KVCalibrator.h:224
void SetInputSignalType(const TString &type)
Definition: KVCalibrator.h:220
static KVCalibrator * MakeCalibrator(const Char_t *type)
To store calibration parameters in a database ,.
TString GetStringParameter(const TString &name) const
Double_t GetParameter(UShort_t i=0) const
Bool_t HasParameter(const TString &name) const
void Print(Option_t *option="") const override
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:41
Table in a database.
Definition: KVDBTable.h:34
virtual Bool_t AddRecord(KVDBRecord *add)
Definition: KVDBTable.cpp:75
static Bool_t IsRunningBatchAnalysis()
virtual Bool_t AddTable(KVDBTable *table)
Definition: KVDataBase.cpp:84
Manage all datasets contained in a given data repository.
Bool_t Init(KVDataSetRepository *=0)
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:146
TString GetFullPathToDataSetFile(const Char_t *filename) const
Definition: KVDataSet.cpp:2149
const Char_t * GetDataSetDir() const
Definition: KVDataSet.cpp:756
Bool_t HasCalibIdentInfos() const
Definition: KVDataSet.h:381
void cd() const
Definition: KVDataSet.cpp:778
Bool_t DataBaseUpdateInProgress() const
Definition: KVDataSet.h:187
ValType GetDataSetEnv(const Char_t *type, const ValType &defval={}) const
Definition: KVDataSet.h:270
static Bool_t FindDataSetFile(const TString &dataset, const Char_t *filename)
Definition: KVDataSet.cpp:2185
List of hit groups in a multidetector array.
void AddGroup(KVGroup *grp)
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, interface to energy-loss calculations.
Definition: KVDetector.h:173
void SetThickness(Double_t thick) override
KVGroup * GetGroup() const
Bool_t IsCalibrated(const KVNameValueList &params={}) const
Definition: KVDetector.cpp:527
void Print(Option_t *option="") const override
Definition: KVDetector.cpp:338
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:608
virtual KVDetectorSignal * GetDetectorSignal(const KVString &type) const
Definition: KVDetector.h:543
void SetDetecting(Bool_t yes=kTRUE)
Definition: KVDetector.h:671
virtual void RemoveCalibrators()
Definition: KVDetector.cpp:684
KVGeoDetectorNode * GetNode()
Definition: KVDetector.h:354
virtual Bool_t IsPresent() const
Definition: KVDetector.h:657
Bool_t AddCalibrator(KVCalibrator *cal, const KVNameValueList &opts="")
Definition: KVDetector.cpp:421
void SetPresent(Bool_t yes=kTRUE)
Definition: KVDetector.h:662
KVNameValueList * GetParameters() const
Definition: KVEvent.h:180
Base class to describe database of an experiment ,,.
Definition: KVExpDB.h:61
void SetDBType(const TString &s)
Definition: KVExpDB.h:118
TString GetCalibFileName(const Char_t *type) const
Definition: KVExpDB.h:188
const KVNumberList & GetRunList() const
Definition: KVExpDB.h:156
virtual void LinkRecordToRunRange(KVDBRecord *rec, UInt_t first_run, UInt_t last_run)
Definition: KVExpDB.cpp:290
Bool_t FindCalibFile(const Char_t *type, TString &fullpath, const TString &array_name="") const
Definition: KVExpDB.cpp:672
Handle reading columns of numeric data in text files.
Definition: KVFileReader.h:121
KVString GetCurrentLine()
Definition: KVFileReader.h:320
ReadStatus ReadLine(const KVString &pattern="")
Definition: KVFileReader.h:243
Bool_t IsOK()
Definition: KVFileReader.h:231
Bool_t OpenFileToRead(const KVString &filename)
Definition: KVFileReader.h:210
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
KVGeoDetectorNode * GetNodeInFront(const KVGeoDetectorNode *n) const
Bool_t ContainsPath(const KVGeoDNTrajectory *other) 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.
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)
virtual 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
void ClearStructures(const Char_t *type="")
KVSeqCollection * GetDetectorNameList(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="", const KVGroup *g=nullptr)
Group of detectors which can be treated independently of all others in array.
Definition: KVGroup.h:20
void SetNumber(UInt_t num) override
Definition: KVGroup.h:38
void AddTrajectory(KVGeoDNTrajectory *t)
Definition: KVGroup.h:91
void Reset(Option_t *opt="")
Definition: KVGroup.h:45
Extended version of ROOT THashList.
Definition: KVHashList.h:29
Base class for particle identification in a 2D map.
Definition: KVIDGraph.h:31
Handles a stock of identification grids to be used by one or more identification telescopes.
virtual void LoadGridsForRun(UInt_t)
KVSeqCollection * GetGrids()
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:85
virtual Bool_t IsReadyForID()
KVIDGrid * CalculateDeltaE_EGrid(const KVNameValueList &AperZ, Int_t npoints=30, Double_t xfactor=1.)
void SetGroup(KVGroup *kvg)
static KVIDTelescope * MakeIDTelescope(const Char_t *name)
virtual Bool_t SetIdentificationParameters(const KVMultiDetArray *)
void SetIDGrid(KVIDGraph *)
virtual void AddDetector(KVDetector *d)
virtual void Initialize(void)
Extended TList class which owns its objects by default.
Definition: KVList.h:22
Read MFM format acquisition data.
Description of physical materials used to construct detectors & targets; interface to range tables.
Definition: KVMaterial.h:115
static KVIonRangeTable * GetRangeTable()
Definition: KVMaterial.cpp:158
Base class for describing the geometry of a detector array.
const KVSeqCollection * GetFiredSignals() const
KVSeqCollection * GetListOfIDTelescopes() const
void FillListOfIDTelescopes(KVIDGraph *gr) const
virtual void GetDetectorEvent(KVDetectorEvent *detev, const TSeqCollection *fired_params=0)
void MakeHistogramsForAllIDTelescopes(KVSeqCollection *list, Int_t dimension=100)
TList * GetStatusOfIDTelescopes()
void Draw(Option_t *option="") override
static KVMultiDetArray * MakeMultiDetector(const Char_t *dataset_name, Int_t run=-1, TString classname="KVMultiDetArray", KVExpDB *db=nullptr)
virtual Double_t GetTargetEnergyLossCorrection(KVReconstructedNucleus *)
KVSeqCollection * GetIDTelescopesWithType(const Char_t *type)
KVTarget * GetTarget()
void RecursiveTrajectoryClustering(KVGeoDetectorNode *N, KVUniqueNameList &tried_trajectories, KVUniqueNameList &multitraj_nodes, KVUniqueNameList &detectors_of_group)
virtual void SetRawDataFromReconEvent(const KVReconstructedEvent &)
void Clear(Option_t *opt="") override
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
Bool_t IsSimMode() const
Bool_t ReadGridsFromAsciiFile(const Char_t *) const
virtual void InitialiseRawDataReading(KVRawDataReader *)
virtual void SetParameters(UInt_t n, Bool_t physics_parameters_only=kFALSE)
virtual void SetDetectorParametersForRun(KVDBRun *, const TString &="")
TString GetDataSet() const
KVGroup * GetGroup(const Char_t *name) const
static TGeoHMatrix * GetVolumePositioningMatrix(Double_t distance, Double_t theta, Double_t phi, TGeoTranslation *postTrans=nullptr)
KVGeoNavigator * GetNavigator() const
void SetGeometry(TGeoManager *)
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 &)
void CheckStatusOfDetectors(KVDBRun *, const TString &="")
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()
virtual void Build(Int_t run=-1)
virtual void FillDetectorList(KVReconstructedNucleus *rnuc, KVHashList *DetList, const KVString &DetNames)
const TSeqCollection * GetTrajectories() const
TList * GetCalibrationStatusOfDetectors()
TGeoManager * GetGeometry() const
Return pointer to the (ROOT) geometry of the array.
virtual Bool_t HandleRawDataEvent(KVRawDataReader *)
virtual void InitializeIDTelescopes()
virtual void SetRunCalibrationParameters(UShort_t n)
void PrintStatusOfIDTelescopes()
void PrintCalibStatusOfDetectors()
virtual void SetCalibratorParameters(KVDBRun *, const TString &="")
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".
virtual void SetReconParametersInEvent(KVReconstructedEvent *) const
Copy any parameters in fReconParameters in to the reconstructed event parameter list.
virtual void AcceptParticleForAnalysis(KVReconstructedNucleus *) const
void SetNavigator(KVGeoNavigator *geo)
KVMultiDetArray()
Default constructor.
KVUpDater * GetUpDater()
KVUniqueNameList GetIDTelescopeTypes()
Handles lists of named parameters with different types, a list of KVNamedParameter objects.
void SetValue(const Char_t *name, value_type value)
void Clear(Option_t *opt="") override
const Char_t * GetStringValue(const Char_t *name) const
Bool_t HasParameter(const Char_t *name) const
TString GetTStringValue(const Char_t *name) const
A generic named parameter storing values of different types.
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 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:371
Double_t GetEnergy() const
Definition: KVParticle.h:624
Read Google Protobuf DAQ files.
Wrapper for TRefArray adding some functionality.
Definition: KVRList.h:37
KVBase * FindObject(const Char_t *name, const Char_t *type) const
Definition: KVRList.cpp:106
Propagate particles through array geometry calculating energy losses.
Abstract base class for reading raw (DAQ) data.
virtual TString GetDataFormat() const =0
Event containing KVReconstructedNucleus nuclei reconstructed from hits in detectors.
Nuclei reconstructed from data measured by a detector array .
virtual Int_t GetECode() const
virtual Int_t GetIDCode() const
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
TObject * Remove(TObject *obj) override
Remove object from list.
void Add(TObject *obj) override
TObject * FindObject(const char *name) const override
KVSeqCollection * GetSubListWithType(const Char_t *retvalue) const
void Clear(Option_t *option="") override
virtual void SetCleanup(Bool_t enable=kTRUE)
void SetOwner(Bool_t enable=kTRUE) override
void Delete(Option_t *option="") override
KVSeqCollection * GetSubListWithLabel(const Char_t *retvalue) 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
Double_t GetParticleEIncFromERes(KVNucleus *, TVector3 *norm=0) override
Definition: KVTarget.cpp:969
void Clear(Option_t *opt="") override
Definition: KVTarget.cpp:748
Optimised list in which named objects can only be placed once.
void Add(TObject *obj) override
Base class implementing necessary methods for setting multidetector parameters for each run of the cu...
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)
Bool_t Contains(const char *name) 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 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)
TObject * FindObject(const char *name) const override
void Add(TObject *obj) 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)
TClass * IsA() const override
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 Info(const char *method, const char *msgfmt,...) const
const char * GetClass() const
Longptr_t ExecPlugin(int nargs)
Int_t GetEntries() const override
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)
RVec< PromoteType< T > > abs(const RVec< T > &v)
TGraphErrors * gr
TH1 * h
void Error(UserClass p, const char *location, const char *va_(fmt),...)
Definition: KVError.h:116
void Warning(UserClass p, const char *location, const char *va_(fmt),...)
Definition: KVError.h:125
void Info(UserClass p, const char *location, const char *va_(fmt),...)
Definition: KVError.h:134
void init()
rec
Int_t Nint(T x)
TLine l
ClassImp(TPyArg)