KaliVeda  1.12/06
Heavy-Ion Analysis Toolkit
KVIDTelescope.cpp
Go to the documentation of this file.
1 /***************************************************************************
2 $Id: KVIDTelescope.cpp,v 1.52 2009/05/05 15:54:04 franklan Exp $
3 Author : $Author: franklan $
4  KVIDTelescope.cpp - description
5  -------------------
6  begin : Wed Jun 18 2003
7  copyright : (C) 2003 by J.D Frankland
8  email : frankland@ganil.fr
9  ***************************************************************************/
10 
11 /***************************************************************************
12  * *
13  * This program is free software; you can redistribute it and/or modify *
14  * it under the terms of the GNU General Public License as published by *
15  * the Free Software Foundation; either version 2 of the License, or *
16  * (at your option) any later version. *
17  * *
18  ***************************************************************************/
19 #include "TROOT.h"
20 #include "KVIDTelescope.h"
21 #include "KVTelescope.h"
22 #include "KVGroup.h"
23 #include "KVNucleus.h"
24 #include "KVReconstructedNucleus.h"
25 #include "KVIDGraph.h"
26 #include "KVIDGrid.h"
27 #include "Riostream.h"
28 #include "TPluginManager.h"
29 #include "KVMultiDetArray.h"
30 #include "KVDataSet.h"
31 #include "KVIDGridManager.h"
32 #include "KVIDZALine.h"
33 #include "KVIDCutLine.h"
34 #include "KVIdentificationResult.h"
35 #include "TMath.h"
36 #include "TClass.h"
37 #include "TH2.h"
38 #include "KVParticleCondition.h"
39 
41 #include <KVIDZAGrid.h>
42 
43 using namespace std;
44 
47 
48 
50 
52  : fDetectors(kFALSE), fGroup(nullptr), fIDGrids(kFALSE)
53 {
54  init();
55 }
56 
57 
58 
61 
63 {
64  //default init
67  fMassIDValidity = nullptr;
68 }
69 
70 
71 
103 
105 {
106  // Default initialisation for ID telescopes.
107  // If telescope has at least 1 grid then it is ready to identify
108  // particles after initialising the grid(s) (kReadyForID=true);
109  // otherwise kReadyForID is set to kFALSE, unless the current dataset (if defined)
110  // has been declared to have no associated identification/calibration parameters,
111  // in which case kReadyForID is by default set to kTRUE (for filtering simulations).
112  //
113  // In order to enable mass identification for certain telescopes without a dedicated
114  // implementation (e.g. for simulating array response), put the following lines
115  // in your .kvrootrc:
116  //
117  // [dataset].[telescope label].MassID: yes
118  //
119  // If you want to limit mass identification to certain values of Z and/or A,
120  // add the following line:
121  //
122  // [dataset].[telescope label].MassID.Validity: [expression]
123  //
124  // where [expression] is some valid C++ boolean expression involving Z and/or A,
125  // for example
126  //
127  // [dataset].[telescope label].MassID.Validity: (Z>3)&&(A<20)
128  //
129  //For identifications using more than one grid, the default behaviour is to try identification
130  //with each grid in turn until a successful identification is obtained. The order in which
131  //the grids should be tried should be specified by a variable with the following format:
132  //
133  //~~~~~~~~~~~~~~~~
134  //[Dataset].[telescope label].GridOrder: [Grid1],[Grid2],...
135  //~~~~~~~~~~~~~~~~
136 
138 
139  // looping over detectors to check they are working
140  // if one of them is not -> set kReadyForID to false
141  TIter it(GetDetectors());
142  KVDetector* det = 0;
143  while ((det = (KVDetector*)it())) if (!det->IsOK()) {
145  return;
146  }
147 
148  if (GetIDGrid()) {
149  KVIDGraph* gr;
150  TIter it(GetListOfIDGrids());
151  bool ok = kTRUE;
152  KVUniqueNameList tmp_list;// for re-ordering grids
153  bool mass_id = false;
154  while ((gr = (KVIDGraph*)it())) {
155  tmp_list.Add(gr);
156  if (gr->HasMassIDCapability()) mass_id = true;
157  gr->Initialize();
158  // make sure both x & y axes' signals are well set up
159  if (!fGraphCoords[gr].fVarX || !fGraphCoords[gr].fVarY) {
160  ok = kFALSE;
161  Warning("Initialize",
162  "ID tel. %s: grid %s has undefined VarX(%s:%p) or VarY(%s:%p) - WILL NOT USE",
163  GetName(), gr->GetName(), gr->GetVarX(), fGraphCoords[gr].fVarX, gr->GetVarY(), fGraphCoords[gr].fVarY);
164  }
165  }
166  // set to true if at least one grid can provide mass identification
167  SetHasMassID(mass_id);
168  // if more than one grid, need to re-order them according to [Dataset].[telescope label].GridOrder
169  if (GetListOfIDGrids()->GetEntries() > 1 && gDataSet) {
170  KVString grid_list = gDataSet->GetDataSetEnv(Form("%s.GridOrder", GetLabel()));
171  ok = kFALSE;
172  if (grid_list == "")
173  Warning("Initialize", "ID telescope %s has %d grids but no %s variable defined",
174  GetName(), GetListOfIDGrids()->GetEntries(), Form("%s.GridOrder", GetLabel()));
175  else if (grid_list.GetNValues(",") != GetListOfIDGrids()->GetEntries())
176  Warning("Initialize", "ID telescope %s has %d grids but %d grids appear in variable %s",
177  GetName(), GetListOfIDGrids()->GetEntries(), grid_list.GetNValues(","), Form("%s.GridOrder", GetLabel()));
178  else {
179  fIDGrids.Clear();
180  grid_list.Begin(",");
181  while (!grid_list.End()) fIDGrids.Add(tmp_list.FindObject(grid_list.Next()));
182  ok = kTRUE;
183  }
184  }
185  if (ok) SetBit(kReadyForID);
186  }
188  else ResetBit(kReadyForID);
189 
190  if (gDataSet) {
192  KVString valid;
193  if ((valid = gDataSet->GetDataSetEnv(Form("%s.MassID.Validity", GetLabel()), "")) != "") {
194  valid.ReplaceAll("Z", "_NUC_->GetZ()");
195  valid.ReplaceAll("A", "_NUC_->GetA()");
198  }
199  }
200 }
201 
202 
203 
206 
207 KVIDTelescope::~KVIDTelescope()
208 {
209  //delete this ID telescope
211 }
212 
213 
214 
219 
221 {
222  //Add a detector to the telescope.
223  //The first detector added is the "DeltaE" member, the second the "Eresidual" member.
224  //Update name of telescope to "ID_[name of DE]_[name of E]"
225 
226  if (d) {
227  fDetectors.Add(d);
228  d->AddIDTelescope(this);
229  if (GetSize() > 1)
230  SetName(Form("ID_%s_%s", GetDetector(1)->GetName(), GetDetector(2)->GetName()));
231  else SetName(Form("ID_%s", GetDetector(1)->GetName()));
232  }
233  else {
234  Warning("AddDetector", "Called with null pointer");
235  }
236 }
237 
238 
239 
243 
245 {
246  // print out telescope structure
247  //if opt="fired" only fired detectors are printed
248 
249  TIter next(GetDetectors());
250  KVDetector* obj;
251 
252  if (!strcmp(opt, "fired")) {
253  while ((obj = (KVDetector*) next())) {
254 
255  if (obj->Fired() || obj->GetEnergy())
256  obj->Print("data");
257  }
258  }
259  else {
260  cout << "\n" << opt << "Structure of KVIDTelescope object: " <<
261  GetName() << " " << GetType() << endl;
262  cout << opt <<
263  "--------------------------------------------------------" <<
264  endl;
265  while ((obj = (KVDetector*) next())) {
266  cout << opt << "Detector: " << obj->GetName() << endl;
267  }
268  }
269 }
270 
271 
272 
273 
276 
278 {
279  // Return a pointer to the detector in the telescope with the name "name".
280 
281  KVDetector* tmp = (KVDetector*) GetDetectors()->FindObject(name);
282  if (!tmp)
283  Warning("GetDetector(const Char_t *name)",
284  "Detector %s not found in telescope %s", name, GetName());
285  return tmp;
286 }
287 
288 
289 
290 
292 
294 {
295  return fGroup;
296 }
297 
298 
299 
300 
302 
304 {
305  fGroup = kvg;
306 }
307 
308 
309 
311 
313 {
314  return (GetGroup() ? GetGroup()->GetNumber() : 0);
315 }
316 
317 
318 
319 
328 
330  Double_t Emax, Double_t Estep)
331 {
332  //For a given nucleus, generate a TGraph representing the line in the deltaE-E
333  //plane of the telescope which can be associated with nuclei of this (A,Z) with total
334  //incident energies between the two limits.
335  //NOTE: if there are other absorbers/detectors placed before this telescope,
336  //the energy losses of the particle in these will be taken into account.
337  //If the step in energy is not given, it is taken equal to 100 equal steps between min and max.
338  //The TGraph should be deleted by the user after use.
339 
340 
341  if (!Estep)
342  Estep = (Emax - Emin) / 100.;
343 
344  Int_t nsteps = 1 + (Int_t)((Emax - Emin) / Estep);
345 
346  if (nsteps < 1)
347  return 0;
348 
349  Double_t* y = new Double_t[nsteps];
350  Double_t* x = new Double_t[nsteps];
351  Int_t step = 0;
352 
353  //get list of all detectors through which particle must pass in order to reach
354  //2nd member of ID Telescope
355  TList* detectors =
357  //detectors->ls();
358  TIter next_det(detectors);
359  //cout << "nsteps =" << nsteps << endl;
360 
361  for (Double_t E = Emin; E <= Emax; E += Estep) {
362  //Set energy of nucleus
363  nuc->SetEnergy(E);
364  //cout << "Einc=" << E << endl;
365 
366  //Calculate energy loss in each member and stock in arrays x & y
367  //first member
368  KVDetector* det = 0;
369  x[step] = y[step] = -1;
370  while ((det = (KVDetector*) next_det())) {
371  //det->Print();
372  Double_t eloss = det->GetELostByParticle(nuc);
373  if (det == GetDetector(1))
374  y[step] = eloss;
375  else if (det == GetDetector(2))
376  x[step] = eloss;
377  Double_t E1 = nuc->GetEnergy() - eloss;
378  nuc->SetEnergy(E1);
379  //cout << "Eloss=" << eloss << endl;
380  //cout << "Enuc=" << nuc->GetEnergy() << endl;
381  if (E1 < 1.e-3) break;
382  }
383 
384  //cout << "step = " << step << " x = " << x[step] << " y = " << y[step] << endl;
385 
386  //make sure that some energy is lost in each member
387  //otherwise miss a step and reduce number of points in graph
388  if (x[step] > 0 && y[step] > 0) {
389  step++;
390  }
391  else {
392  nsteps--;
393  }
394 
395  //cout << "nsteps =" << nsteps << endl;
396  //reset iterator ready for next loop on detectors
397  next_det.Reset();
398  }
399  TGraph* tmp = 0;
400  if (nsteps > 1)
401  tmp = new TGraph(nsteps, x, y);
402  delete[]x;
403  delete[]y;
404  return tmp;
405 }
406 
407 
408 
409 
432 
434 {
435  //Default identification method.
436  //
437  //Works for ID telescopes for which one or more identification grids are defined, each
438  //with VARX/VARY parameters corresponding to a KVDetectorSignal or KVDetectorSignalExpression
439  //associated with one or other of the detectors constituting the telescope.
440  //
441  //For identifications using more than one grid, the default behaviour is to try identification
442  //with each grid in turn until a successful identification is obtained. The order in which
443  //the grids should be tried should be specified by a variable with the following format:
444  //
445  //~~~~~~~~~~~~~~~~
446  //[Dataset].[Array Name].[ID type].GridOrder: [Grid1],[Grid2],...
447  //~~~~~~~~~~~~~~~~
448  //
449  //where the name of each grid is given as "VARY_VARX". If no variable defining the order is found,
450  //the grids will be tried in the order they were found in the file containing the grids for this
451  //telescope.
452  //
453  // The KVIdentificationResult is first Clear()ed; then it is filled with IDtype = GetType()
454  // of this identification telescope, IDattempted = true, and the results of the identification
455  // procedure.
456 
457  idr->Clear();
458  idr->IDattempted = true;
459  idr->SetIDType(GetType());
460 
461  KVIDGraph* grid;
462  TIter it(GetListOfIDGrids());
463  while ((grid = (KVIDGraph*)it())) { //loop over grids in order given by [Dataset].[Array Name].[ID type].GridOrder:
464  Double_t de, e;
465  GetIDGridCoords(e, de, grid, x, y);
466  idr->SetGridName(grid->GetName());
467  if (grid->IsIdentifiable(e, de, &idr->Rejecting_Cut)) {
468  grid->Identify(e, de, idr);
469  if (idr->IDOK) break; // stop on first successful identification
470  }
471  else {
472  // particle rejected by cut in grid. idr->Rejecting_Cut contains its name.
473  idr->IDOK = kFALSE;
475  }
476  }
477  idr->IDcode = GetIDCode();
478 
479  return kTRUE;
480 }
481 
482 
483 
484 
520 
522 {
523  // Add an identification grid to the list of grids used by this telescope.
524  //
525  // If the grid's VARX and VARY parameters are set and contain the names of valid
526  // detector signals (see formatting rules below) they will be used by
527  // GetIDGridXCoord() and GetIDGridYCoord() to return the coordinates
528  // needed to perform particle identification using the grid.
529  //
530  // The name of the grid is set to "VARY_VARX" (just the signal names, not the detector
531  // label part - see below). This value will be stored in the
532  // KVIdentificationResult corresponding to an attempted identification of a
533  // KVReconstructedNucleus by this grid.
534  //
535  // VARX/VARY Formatting
536  //
537  // To be valid, grid VARX/Y parameters should be set as follows:
538  //
539  //~~~~~~~~~~~~~~~~~~
540  // [signal name]
541  // or [det_label]::[signal name]
542  //~~~~~~~~~~~~~~~~~~
543  //
544  // where
545  //
546  //~~~~~~~~~~~~~~~~~~
547  // [det_label] (optional) = detector label i.e. string returned by KVDetector::GetLabel()
548  // method for detector. By default, VARX is assumed to be the Eres detector
549  // or second detector and VARY the DE detector or first detector
550  // [signal_name] = name of a signal defined for the detector, possibly depending
551  // on availability of calibration
552  //
553  // To see all available signals for a detector, use
554  //
555  // KVDetector::GetListOfDetectorSignals()
556  //~~~~~~~~~~~~~~~~~~
557 
558  if (grid) {
559  fIDGrids.Add(grid);
560  KVDetectorSignal* xx = GetSignalFromGridVar(grid->GetVarX(), "X");
561  KVDetectorSignal* yy = GetSignalFromGridVar(grid->GetVarY(), "Y");
562  GraphCoords gc;
563  gc.fVarX = xx;
564  gc.fVarY = yy;
565  fGraphCoords[grid] = gc;
566  TString grid_name;
567  if (xx && yy) {
568  grid_name.Form("%s_%s", yy->GetName(), xx->GetName());
569  grid->SetName(grid_name);
570  }
571  }
572 }
573 
574 
575 
604 
606 {
607  // Deduce & return pointer to detector signal from grid VARX/VARY parameter
608  //
609  // To be valid, grid VARX/Y parameters should be set in one of two ways:
610  //
611  //~~~~~~~~~~~~~~~~~~
612  // [signal name]
613  // [det_label]::[signal name]
614  //~~~~~~~~~~~~~~~~~~
615  //
616  // where
617  //
618  //~~~~~~~~~~~~~~~~~~
619  // [signal_name] = name of a signal or a mathematical expression using
620  // any of the signals defined for the detector
621  // [det_label] = optional detector label i.e. string returned by
622  // KVDetector::GetLabel() method for detector
623  //~~~~~~~~~~~~~~~~~~
624  //
625  // If `[det_label]` is not given, we assume for `VARX` the second (E) detector,
626  // while for `VARY` we assume the first (dE) detector. If this telescope has only
627  // one detector, we use it for both variables.
628  //
629  // To see all available signals for a detector, use
630  //
631  //~~~~~~~~~~~~~~~~~~
632  // KVDetector::GetListOfDetectorSignals()
633  //~~~~~~~~~~~~~~~~~~
634 
635  if (var == "") {
636  Warning("GetSignalFromGridVar",
637  "No VAR%s defined for grid for telescope %s. KVIDTelescope-derived class handling identification must override GetIDMapX/GetIDMapY",
638  axe.Data(), GetName());
639  return nullptr;
640  }
641  KVDetector* det = nullptr;
642  KVDetectorSignal* ds(nullptr);
643  KVString sig_type;
644  if (var.GetNValues("::") == 2) {
645  // VARX/Y = [det_label]::[signal name]
646  var.Begin("::");
647  KVString det_label = var.Next();
648  sig_type = var.Next();
649  det = (KVDetector*)GetDetectors()->FindObjectByLabel(det_label);
650  if (!det) {
651  Error("GetSignalFromGridVar",
652  "Problem initialising ID-grid %s coordinate for telescope %s. Request for unknown detector label %s. Check definition of VAR%s for grid (=%s)",
653  axe.Data(), GetName(), det_label.Data(), axe.Data(), var.Data());
654  return nullptr;
655  }
656  }
657  else {
658  // VARX/Y = [signal name]
659  if (axe == "Y" || GetSize() == 1) det = GetDetector(1);
660  else det = GetDetector(2);
661  sig_type = var;
662  }
663  ds = det->GetDetectorSignal(sig_type);
664  if (!ds) {
665  // sig_type is not the name of a known signal: assume it is an expression using known signal names
666  if (!det->AddDetectorSignalExpression(sig_type, sig_type)) {
667  Error("GetSignalFromGridVar",
668  "Problem initialising ID-grid %s coordinate for telescope %s. Request for unknown signal %s for detector %s. Check definition of VAR%s for grid (=%s)",
669  axe.Data(), GetName(), sig_type.Data(), det->GetName(), axe.Data(), var.Data());
670  ds = nullptr;
671  }
672  else
673  ds = det->GetDetectorSignal(sig_type);
674  }
675  return ds;
676 }
677 
678 
679 
680 
684 
686 {
687  //Return the first in the list of identification grids used by this telescope
688  //(this is for backwards compatibility with ID telescopes which had only one grid).
689  return (KVIDGraph*)GetListOfIDGrids()->First();
690 }
691 
692 
693 
694 
697 
699 {
700  //Return pointer to grid using position in list. First grid has index = 1.
701  return (KVIDGraph*)GetListOfIDGrids()->At(index - 1);
702 }
703 
704 
705 
706 
710 
712 {
713  //Return pointer to grid using "label" to search in list of grids associated
714  //to this telescope.
715  return (KVIDGraph*)GetListOfIDGrids()->FindObjectByLabel(label);
716 }
717 
718 
719 
720 
722 
724 {
725  AbstractMethod("GetIDMapX");
726  return -1.;
727 }
728 
729 
730 
735 
737 {
738  // Returns the pedestal associated with the 2nd detector of the telescope,
739  // optionally depending on the given option string.
740  // By default this returns 0, and should be overridden in specific implementations.
741 
742  return 0.;
743 }
744 
745 
746 
751 
753 {
754  // Returns the pedestal associated with the 1st detector of the telescope,
755  // optionally depending on the given option string.
756  // By default this returns 0, and should be overridden in specific implementations.
757 
758  return 0.;
759 }
760 
761 
762 
766 
768 {
769  // Return value of X coordinate to be used with the given ID grid
770  // This corresponds to whatever was given as parameter "VARX" for the grid
771 
772  KVDetectorSignal* ds = fGraphCoords[g].fVarX;
773  if (ds) return ds->GetValue();
774  return -1;
775 }
776 
777 
778 
782 
784 {
785  // Return value of Y coordinate to be used with the given ID grid
786  // This corresponds to whatever was given as parameter "VARY" for the grid
787 
788  KVDetectorSignal* ds = fGraphCoords[g].fVarY;
789  if (ds) return ds->GetValue();
790  return -1;
791 }
792 
793 
794 
795 
797 
799 {
800  AbstractMethod("GetIDMapY");
801  return -1.;
802 }
803 
804 
805 
806 
810 
812 {
813  //Remove all identification grids for this ID telescope
814  //Grids are not deleted as this is handled by gIDGridManager
815  fIDGrids.Clear();
816  fGraphCoords.clear();
817 }
818 
819 
820 
821 
840 
842 {
843  //Static function which will create an instance of the KVIDTelescope-derived class
844  //corresponding to 'name'
845  //These are defined as 'Plugin' objects in the file $KVROOT/KVFiles/.kvrootrc :
846  //~~~~~~~
847  // # The KVMultiDetArray::GetIDTelescopes(KVDetector*de, KVDetector*e) method uses these plugins to
848  // # create KVIDTelescope instances adapted to the specific array geometry and detector types.
849  // # For each pair of detectors we look for a plugin with one of the following names:
850  // # [name_of_dataset].de_detector_type[de detector thickness]-e_detector_type[de detector thickness]
851  // # Each characteristic in [] brackets may or may not be present in the name; first we test for names
852  // # with these characteristics, then all combinations where one or other of the characteristics is not present.
853  // # In addition, we first test all combinations which begin with [name_of_dataset].
854  // # The first plugin found in this order will be used.
855  // # In addition, if for one of the two detectors there is a plugin called
856  // # [name_of_dataset].de_detector_type[de detector thickness]
857  // # [name_of_dataset].e_detector_type[e detector thickness]
858  // # then we add also an instance of this 1-detector identification telescope.
859  //~~~~~~~
860 
861  TPluginHandler* ph;
862  //check and load plugin library
863  if (!(ph = LoadPlugin("KVIDTelescope", uri)))
864  return 0;
865 
866  //execute constructor/macro for identification telescope
867  KVIDTelescope* mda = (KVIDTelescope*) ph->ExecPlugin(0);
868  if (mda) {
869  //set label of telescope with URI used to find plugin (minus dataset name)
870  mda->SetLabelFromURI(uri);
871  }
872 
873  return mda;
874 }
875 
876 
877 
878 
882 
884 {
885  //PRIVATE METHOD
886  //Sets label of telescope based on URI of plugin describing child class for this telescope
887 
888  TString _uri(uri);
889  if (gDataSet && _uri.BeginsWith(gDataSet->GetName())) _uri.Remove(0, strlen(gDataSet->GetName()) + 1);
890  SetLabel(_uri.Data());
891 }
892 
893 
894 
895 
912 
914 {
915  // Initialise the identification parameters (grids, etc.) of ALL identification telescopes of this
916  // kind (label) in the multidetector array. Therefore this method need only be called once, and not
917  // called for each telescope. The kind/label (returned by GetLabel) of the telescope corresponds
918  // to the URI used to find the plugin class in $KVROOT/KVFiles/.kvrootrc.
919  // By default, this method looks for the file with name given by the environment variable
920  //
921  // [dataset name].IdentificationParameterList.[telescope label]: [filename]
922  //
923  // which is assumed to contain the list of files containing the identification grids.
924  //
925  // If not such envionment variable is found, the method looks for another one:
926  //
927  // [dataset name].IdentificationParameterFile.[telescope label]: [filename]
928  //
929  // which is assumed to contain identification grids.
930 
931  TString filename = gDataSet->GetDataSetEnv(Form("IdentificationParameterList.%s", GetLabel()));
932 
933  if (filename != "") {
934  ReadIdentificationParameterFiles(filename.Data(), multidet);
935  }
936  else {
937  filename = gDataSet->GetDataSetEnv(Form("IdentificationParameterFile.%s", GetLabel()));
938 
939  if (filename == "") {
940  Warning("SetIdentificationParameters",
941  "No filename defined. Should be given by %s.IdentificationParameterFile.%s or %s.IdentificationParameterFile.%s",
943  return kFALSE;
944  }
945 
946  LoadIdentificationParameters(filename, multidet);
947  }
948  return kTRUE;
949 }
950 
951 
952 
953 
961 
963 {
964  // In the case where the identification grids are stored in several files, this method parse
965  // the file found with the following environment variable:
966  //
967  // [dataset name].IdentificationParameterList.[telescope label]: [filename]
968  //
969  // which contains the list of files containing the identification grids.
970 
971  KVFileReader fr;
973 
974  while (fr.IsOK()) {
975  fr.ReadLine(0);
976 
977  if (fr.GetCurrentLine() != "") LoadIdentificationParameters(fr.GetCurrentLine().Data(), multidet);
978  }
979 
980  fr.CloseFile();
981 }
982 
983 
984 
985 
988 
990 {
991  // This method add to the gIDGridManager list the identification grids.
992 
993  TString path;
994 
995  if ((path = gDataSet->GetFullPathToDataSetFile(filename)) == "") {
996  Error("LoadIdentificationParameters",
997  "File %s not found. Should be in %s",
998  filename, gDataSet->GetDataSetDir());
999  return;
1000  }
1001  //
1002  //Read grids from file
1003  Info("LoadIdentificationParameters", "Using file %s", path.Data());
1004  multidet->ReadGridsFromAsciiFile(path);
1005 }
1006 
1007 
1008 
1009 
1021 
1023 {
1024  //Remove identification parameters from telescope in such a way that they
1025  //can subsequently be reset e.g. with a new version.
1026  //This is used by KVMultiDetArray::UpdateIdentifications.
1027  //Child classes with specific SetIdentificationParameters methods should
1028  //also redefine this method in order to remove (destroy) cleanly the objects
1029  //created in SetIdentificationParameters.
1030  //
1031  //This default method takes the list of grids associated to the telescope,
1032  //and for each one: 1) checks if it is still in the gIDGridManager's list
1033  //2) if yes, delete the grid and remove it from gIDGridManager
1034 
1035  TIter next_grid(GetListOfIDGrids());
1036  KVIDGrid* grid;
1037  while ((grid = (KVIDGrid*)next_grid())) {
1038 
1039  if (gIDGridManager->GetGrids()->FindObject(grid)) { //this only works if KVIDTelescope uses TObject:IsEqual method (i.e. compares pointers)
1040 
1041  gIDGridManager->DeleteGrid(grid);
1042 
1043  }
1044  }
1045  //clear list of grids
1046  fIDGrids.Clear();
1048 }
1049 
1050 
1051 
1052 
1071 
1073 {
1074  // The energy of each particle is calculated as follows:
1075  //
1076  // E = dE_1 + dE_2 + ... + dE_N
1077  //
1078  // dE_1, dE_2, ... = energy losses measured in each detector through which
1079  // the particle has passed (or stopped, in the case of dE_N).
1080  // These energy losses are corrected for (Z,A)-dependent effects
1081  // such as pulse-heigth defect in silicon detectors, losses in
1082  // windows of gas detectors, etc.
1083  //
1084  // Whenever possible, the energy loss for fired detectors which are uncalibrated
1085  // or not functioning is calculated. In this case the status returned by GetCalibStatus()
1086  // will be KVIDTelescope::kCalibStatus_Calculated.
1087  // If none of the detectors is calibrated, the particle's energy cannot be calculated &
1088  // the status will be KVIDTelescope::kCalibStatus_NoCalibrations.
1089  // Otherwise, the status code will be KVIDTelescope::kCalibStatus_OK.
1090 
1091  //status code
1093 
1094  UInt_t z = nuc->GetZ();
1095  //uncharged particles
1096  if (z == 0) return;
1097 
1098  KVDetector* d1 = GetDetector(1);
1099  KVDetector* d2 = (GetSize() > 1 ? GetDetector(2) : 0);
1100  Bool_t d1_cal = d1->IsCalibrated();
1101  Bool_t d2_cal = (d2 ? d2->IsCalibrated() : kFALSE);
1102 
1103  //no calibrations
1104  if (!d1_cal && !d2)
1105  return;
1106  if ((d1 && d2) && !d1_cal && !d2_cal)
1107  return;
1108 
1109  //status code
1111 
1112  UInt_t a = nuc->GetA();
1113 
1114  // particles stopped in first member of telescope
1115  if (nuc->GetStatus() == 3) {
1116  if (d1_cal) {
1117  nuc->SetEnergy(d1->GetCorrectedEnergy(nuc, -1, kFALSE)); //N.B.: transmission=kFALSE because particle stop in d1
1118  }
1119  return;
1120  }
1121 
1122  Double_t e1, e2, einc;
1123  e1 = e2 = einc = 0.0;
1124 
1125  if (!d1_cal) {//1st detector not calibrated - calculate from residual energy in 2nd detector
1126 
1127  //second detector must exist and have all acquisition parameters fired with above-pedestal value
1128  if (d2 && d2->Fired("Pall")) e2 = d2->GetCorrectedEnergy(nuc, -1, kFALSE); //N.B.: transmission=kFALSE because particle stop in d2
1129  if (e2 <= 0.0) {
1130  // zero energy loss in 2nd detector ? can't do anything...
1132  return;
1133  }
1134  //calculate & set energy loss in dE detector
1135  //N.B. using e2 for the residual energy after detector 1 means
1136  //that we are assuming the particle stops in detector 2.
1137  //if this is not true, we will underestimate the energy of the particle.
1138  e1 = d1->GetDeltaEFromERes(z, a, e2);
1139  if (e1 < 0.0) e1 = 0.0;
1140  else {
1141  d1->SetEnergyLoss(e1);
1142  d1->SetEResAfterDetector(e2);
1143  e1 = d1->GetCorrectedEnergy(nuc);
1144  //status code
1146  }
1147  }
1148  else { //1st detector is calibrated too: get corrected energy loss
1149 
1150  e1 = d1->GetCorrectedEnergy(nuc);
1151 
1152  }
1153 
1154  if (d2 && !d2_cal) {//2nd detector not calibrated - calculate from energy loss in 1st detector
1155 
1156  e1 = d1->GetCorrectedEnergy(nuc);
1157  if (e1 <= 0.0) {
1158  // zero energy loss in 1st detector ? can't do anything...
1160  return;
1161  }
1162  //calculate & set energy loss in 2nd detector
1163  e2 = d1->GetEResFromDeltaE(z, a);
1164  if (e2 < 0.0) e2 = 0.0;
1165  else {
1166  e2 = d2->GetDeltaE(z, a, e2);
1167  d2->SetEnergyLoss(e2);
1168  e2 = d2->GetCorrectedEnergy(nuc);
1169  //status code
1171  }
1172  }
1173  else if (d2) { //2nd detector is calibrated too: get corrected energy loss
1174 
1175  e2 = d2->GetCorrectedEnergy(nuc, -1, kFALSE);//N.B.: transmission=kFALSE because particle assumed to stop in d2
1176  // recalculate corrected energy in first stage using info on Eres
1177  d1->SetEResAfterDetector(e2);
1178  e1 = d1->GetCorrectedEnergy(nuc);
1179  }
1180 
1181  //incident energy of particle (before 1st member of telescope)
1182  einc = e1 + e2;
1183 
1184  Double_t coherence_tolerance = gEnv->GetValue("KVIDTelescope.CoherencyTolerance", 1.05);
1185  if (coherence_tolerance < 1) coherence_tolerance += 1.00;
1186 
1187  //Now we have to work our way up the list of detectors from which the particle was
1188  //reconstructed. For each fired & calibrated detector which is only associated with
1189  //one particle in the events, we add the corrected measured energy loss
1190  //to the particle. For uncalibrated, unfired detectors and detectors through which
1191  //more than one particle has passed, we calculate the corrected energy loss and add it
1192  //to the particle.
1193  int ndets = nuc->GetNumDet();
1194  if (ndets > (int)GetSize()) { //particle passed through other detectors before this idtelesocpe
1195  //look at detectors not in this id telescope
1196  int idet = GetSize();//next detector after delta-e member of IDTelescope (stopping detector = 0)
1197  while (idet < ndets) {
1198 
1199  KVDetector* det = nuc->GetDetector(idet);
1200  if (det->Fired() && det->IsCalibrated() && det->GetNHits() == 1) {
1201  Double_t dE = det->GetEnergy();
1202  //in order to check if particle was really the only one to
1203  //hit each detector, we calculate the particle's energy loss
1204  //from its residual energy. if the measured energy loss is
1205  //significantly larger, there may be a second particle.
1206  e1 = det->GetDeltaEFromERes(z, a, einc);
1207  if (e1 < 0.0) e1 = 0.0;
1208  det->SetEResAfterDetector(einc);
1209  dE = det->GetCorrectedEnergy(nuc);
1210  einc += dE;
1211  }
1212  else {
1213  // Uncalibrated/unfired/multihit detector. Calculate energy loss.
1214  //calculate energy of particle before detector from energy after detector
1215  e1 = det->GetDeltaEFromERes(z, a, einc);
1216  if (e1 < 0.0) e1 = 0.0;
1217  if (det->GetNHits() > 1) {
1218  //Info("CalculateParticleEnergy",
1219  // "Detector %s was hit by %d particles. Calculated energy loss for particle %f MeV",
1220  // det->GetName(), det->GetNHits(), e1);
1221  if (!(det->Fired() && det->IsCalibrated())) {
1222  det->SetEnergyLoss(e1 + det->GetEnergy());// sum up calculated energy losses in uncalibrated detector
1223  }
1224  //status code
1226  }
1227  else if (!det->Fired() || !det->IsCalibrated()) {
1228  //Info("CalculateParticleEnergy",
1229  // "Detector %s uncalibrated/not fired. Calculated energy loss for particle %f MeV",
1230  // det->GetName(), e1);
1231  det->SetEnergyLoss(e1);
1232  //status code
1234  }
1235  det->SetEResAfterDetector(einc);
1236  e1 = det->GetCorrectedEnergy(nuc, e1);
1237  einc += e1;
1238  }
1239  idet++;
1240  }
1241  }
1242  //einc is now the energy of the particle before crossing the first detector
1243  nuc->SetEnergy(einc);
1244 }
1245 
1246 
1247 
1248 
1258 
1260 {
1261  // Returns name of default ID grid class for this ID telescope.
1262  // This is defined in a .kvrootrc configuration file by one of the following:
1263  // KVIDTelescope.DefaultGrid:
1264  // KVIDTelescope.DefaultGrid.[type]:
1265  // where [type] is the type of this identification telescope (which is given
1266  // by the character string returned by method GetLabel()... sorry :( )
1267  // If no default grid is defined for the specific type of this telescope,
1268  // the default defined by KVIDTelescope.DefaultGrid is used.
1269 
1270  TString specific;
1271  specific.Form("KVIDTelescope.DefaultGrid.%s", GetLabel());
1272  return gEnv->GetValue(specific.Data(), gEnv->GetValue("KVIDTelescope.DefaultGrid", "KVIDGraph"));
1273 }
1274 
1275 
1276 
1290 
1291 KVIDGrid* KVIDTelescope::CalculateDeltaE_EGrid(const KVNumberList& Zrange, Int_t deltaA, Int_t npoints, Double_t lifetime, UChar_t massformula, Double_t xfactor)
1292 {
1293  //Genere une grille dE-E (perte d'energie - energie residuelle) pour une gamme en Z donnee
1294  // - Zrange definit l'ensemble des charges pour lequel les lignes vont etre calculees
1295  // - deltaA permet de definir si a chaque Z n'est associee qu'un seul A (deltaA=0) ou plusieurs
1296  //Exemple :
1297  // deltaA=1 -> Aref-1, Aref et Aref+1 seront les masses associees a chaque Z et
1298  // donc trois lignes de A par Z. le Aref pour chaque Z est determine par
1299  // la formule de masse par defaut (Aref = KVNucleus::GetA() voir le .kvrootrc)
1300  // deltaA=0 -> pour chaque ligne de Z le A associe sera celui de KVNucleus::GetA()
1301  // - est le nombre de points par ligne
1302  //
1303  //un noyau de A et Z donne n'est considere que s'il retourne KVNucleus::IsKnown() = kTRUE
1304  //
1305  if (GetSize() <= 1) return 0;
1306 
1308  if (!cl || !cl->InheritsFrom("KVIDZAGrid")) cl = TClass::GetClass("KVIDZAGrid");
1309  KVIDGrid* idgrid = (KVIDGrid*)cl->New();
1310 
1311  idgrid->AddIDTelescope(this);
1312  idgrid->SetOnlyZId((deltaA == 0));
1313 
1314  KVDetector* det_de = GetDetector(1);
1315  if (!det_de) return 0;
1316  KVDetector* det_eres = GetDetector(2);
1317  if (!det_eres) return 0;
1318 
1319  KVNucleus part;
1320  Info("CalculateDeltaE_EGrid",
1321  "Calculating dE-E grid: dE detector = %s, E detector = %s",
1322  det_de->GetName(), det_eres->GetName());
1323 
1324  KVIDCutLine* B_line = (KVIDCutLine*)idgrid->Add("OK", "KVIDCutLine");
1325  Int_t npoi_bragg = 0;
1326  B_line->SetName("Bragg_line");
1327  B_line->SetAcceptedDirection("right");
1328 
1329  Double_t SeuilE = 0.1;
1330 
1331  Zrange.Begin();
1332  while (!Zrange.End()) {
1333  Int_t zz = Zrange.Next();
1334  part.SetZ(zz, massformula);
1335  Int_t aref = part.GetA();
1336  // printf("%d\n",zz);
1337  for (Int_t aa = aref - deltaA; aa <= aref + deltaA; aa += 1) {
1338  part.SetA(aa);
1339  // printf("+ %d %d %d\n",aa,aref,part.IsKnown());
1340  if (part.IsKnown() && (part.GetLifeTime() > lifetime)) {
1341 
1342  //loop over energy
1343  //first find :
1344  // ****E1 = energy at which particle passes 1st detector and starts to enter in the 2nd one****
1345  // E2 = energy at which particle passes the 2nd detector
1346  //then perform npoints calculations between these two energies and use these
1347  //to construct a KVIDZALine
1348 
1349  Double_t E1, E2;
1350  //find E1
1351  //go from SeuilE MeV to det_de->GetEIncOfMaxDeltaE(part.GetZ(),part.GetA()))
1352  Double_t E1min = SeuilE, E1max = det_de->GetEIncOfMaxDeltaE(zz, aa);
1353  E1 = (E1min + E1max) / 2.;
1354 
1355  while ((E1max - E1min) > SeuilE) {
1356 
1357  part.SetEnergy(E1);
1358  det_de->Clear();
1359  det_eres->Clear();
1360 
1361  det_de->DetectParticle(&part);
1362  det_eres->DetectParticle(&part);
1363  if (det_eres->GetEnergy() > SeuilE) {
1364  //particle got through - decrease energy
1365  E1max = E1;
1366  E1 = (E1max + E1min) / 2.;
1367  }
1368  else {
1369  //particle stopped - increase energy
1370  E1min = E1;
1371  E1 = (E1max + E1min) / 2.;
1372  }
1373  }
1374 
1375  //add point to Bragg line
1376  Double_t dE_B = det_de->GetMaxDeltaE(zz, aa);
1377  Double_t E_B = det_de->GetEIncOfMaxDeltaE(zz, aa);
1378  Double_t Eres_B = det_de->GetERes(zz, aa, E_B);
1379  B_line->SetPoint(npoi_bragg++, Eres_B, dE_B);
1380 
1381  //find E2
1382  //go from E1 MeV to maximum value where the energy loss formula is valid
1383  Double_t E2min = E1, E2max = det_eres->GetEmaxValid(part.GetZ(), part.GetA());
1384  E2 = (E2min + E2max) / 2.;
1385 
1386  while ((E2max - E2min > SeuilE)) {
1387 
1388  part.SetEnergy(E2);
1389  det_de->Clear();
1390  det_eres->Clear();
1391 
1392  det_de->DetectParticle(&part);
1393  det_eres->DetectParticle(&part);
1394  if (part.GetEnergy() > SeuilE) {
1395  //particle got through - decrease energy
1396  E2max = E2;
1397  E2 = (E2max + E2min) / 2.;
1398  }
1399  else {
1400  //particle stopped - increase energy
1401  E2min = E2;
1402  E2 = (E2max + E2min) / 2.;
1403  }
1404  }
1405  E2 *= xfactor;
1406  if ((!strcmp(det_eres->GetType(), "CSI")) && (E2 > 5000)) E2 = 5000;
1407  // printf("z=%d a=%d E1=%lf E2=%lf\n",zz,aa,E1,E2);
1408  KVIDZALine* line = (KVIDZALine*)idgrid->Add("ID", "KVIDZALine");
1409  if (TMath::Even(zz)) line->SetLineColor(4);
1410  line->SetZ(zz);
1411  line->SetA(aa);
1412 
1413  Double_t logE1 = TMath::Log(E1);
1414  Double_t logE2 = TMath::Log(E2);
1415  Double_t dLog = (logE2 - logE1) / (npoints - 1.);
1416 
1417  for (Int_t i = 0; i < npoints; i++) {
1418  // Double_t E = E1 + i*(E2-E1)/(npoints-1.);
1419  Double_t E = TMath::Exp(logE1 + i * dLog);
1420 
1421  Double_t Eres = 0.;
1422  Int_t niter = 0;
1423  while (Eres < SeuilE && niter <= 20) {
1424  det_de->Clear();
1425  det_eres->Clear();
1426 
1427  part.SetEnergy(E);
1428 
1429  det_de->DetectParticle(&part);
1430  det_eres->DetectParticle(&part);
1431 
1432  Eres = det_eres->GetEnergy();
1433  E += SeuilE;
1434  niter += 1;
1435  }
1436  if (!(niter > 20)) {
1437  Double_t dE = det_de->GetEnergy();
1438  Double_t gEres, gdE;
1439  line->GetPoint(i - 1, gEres, gdE);
1440  line->SetPoint(i, Eres, dE);
1441 
1442  }
1443  }
1444  //printf("sort de boucle points");
1445  }
1446  }
1447  }
1448 
1449  idgrid->SetRunList("1-10000");
1450 
1451  return idgrid;
1452 
1453 }
1454 
1455 
1456 
1472 
1474 {
1475  //Genere une grille dE-E (perte d'energie - energie residuelle)
1476  //Le calcul est fait pour chaque couple comptant de charge (Z) et masse (A)
1477  //au moins un coup dans l'histogramme haa_zz definit :
1478  // Axe X -> Z
1479  // Axe Y -> A
1480  //
1481  //- Si Zonly=kTRUE (kFALSE par defaut), pour un Z donne, le A choisi est la valeur entiere la
1482  //plus proche de la valeur moyenne <A>
1483  //- Si Zonly=kFALSE et que pour un Z donne il n'y a qu'un seul A associe, les lignes correspondants
1484  //a A-1 et A+1 sont ajoutes
1485  //- Si a un Z donne, il n'y a aucun A, pas de ligne tracee
1486  //un noyau de A et Z donne n'est considere que s'il retourne KVNucleus::IsKnown() = kTRUE
1487  //
1488  // Warning : the grid is not added to the list of the telescope and MUST BE DELETED by the user !
1489 
1490  if (GetSize() <= 1) return 0;
1491 
1493  KVIDGrid* idgrid = (KVIDGrid*)cl->New();
1494  delete cl;
1495 
1496  idgrid->AddIDTelescope(this);
1497  idgrid->SetOnlyZId(Zonly);
1498 
1499  KVDetector* det_de = GetDetector(1);
1500  if (!det_de) return 0;
1501  KVDetector* det_eres = GetDetector(2);
1502  if (!det_eres) return 0;
1503 
1504  KVNucleus part;
1505  Info("CalculateDeltaE_EGrid",
1506  "Calculating dE-E grid: dE detector = %s, E detector = %s",
1507  det_de->GetName(), det_eres->GetName());
1508 
1509  KVIDCutLine* B_line = (KVIDCutLine*)idgrid->Add("OK", "KVIDCutLine");
1510  Int_t npoi_bragg = 0;
1511  B_line->SetName("Bragg_line");
1512  B_line->SetAcceptedDirection("right");
1513 
1514  Double_t SeuilE = 0.1;
1515 
1516  for (Int_t nx = 1; nx <= haa_zz->GetNbinsX(); nx += 1) {
1517 
1518  Int_t zz = TMath::Nint(haa_zz->GetXaxis()->GetBinCenter(nx));
1519  KVNumberList nlA;
1520  Double_t sumA = 0, sum = 0;
1521  for (Int_t ny = 1; ny <= haa_zz->GetNbinsY(); ny += 1) {
1522  Double_t stat = haa_zz->GetBinContent(nx, ny);
1523  if (stat > 0) {
1524  Double_t val = haa_zz->GetYaxis()->GetBinCenter(ny);
1525  nlA.Add(TMath::Nint(val));
1526  sumA += val * stat;
1527  sum += stat;
1528  }
1529  }
1530  sumA /= sum;
1531  Int_t nA = nlA.GetNValues();
1532  if (nA == 0) {
1533  Warning("CalculateDeltaE_EGrid", "no count for Z=%d", zz);
1534  }
1535  else {
1536  if (Zonly) {
1537  nlA.Clear();
1538  nlA.Add(TMath::Nint(sumA));
1539  }
1540  else {
1541  if (nA == 1) {
1542  Int_t aref = nlA.Last();
1543  nlA.Add(aref - 1);
1544  nlA.Add(aref + 1);
1545  }
1546  }
1547  part.SetZ(zz);
1548  // printf("zz=%d\n",zz);
1549  nlA.Begin();
1550  while (!nlA.End()) {
1551  Int_t aa = nlA.Next();
1552  part.SetA(aa);
1553  // printf("+ aa=%d known=%d\n",aa,part.IsKnown());
1554  if (part.IsKnown()) {
1555 
1556  //loop over energy
1557  //first find :
1558  // ****E1 = energy at which particle passes 1st detector and starts to enter in the 2nd one****
1559  // E2 = energy at which particle passes the 2nd detector
1560  //then perform npoints calculations between these two energies and use these
1561  //to construct a KVIDZALine
1562 
1563  Double_t E1, E2;
1564  //find E1
1565  //go from SeuilE MeV to det_de->GetEIncOfMaxDeltaE(part.GetZ(),part.GetA()))
1566  Double_t E1min = SeuilE, E1max = det_de->GetEIncOfMaxDeltaE(zz, aa);
1567  E1 = (E1min + E1max) / 2.;
1568 
1569  while ((E1max - E1min) > SeuilE) {
1570 
1571  part.SetEnergy(E1);
1572  det_de->Clear();
1573  det_eres->Clear();
1574 
1575  det_de->DetectParticle(&part);
1576  det_eres->DetectParticle(&part);
1577  if (det_eres->GetEnergy() > SeuilE) {
1578  //particle got through - decrease energy
1579  E1max = E1;
1580  E1 = (E1max + E1min) / 2.;
1581  }
1582  else {
1583  //particle stopped - increase energy
1584  E1min = E1;
1585  E1 = (E1max + E1min) / 2.;
1586  }
1587  }
1588 
1589  //add point to Bragg line
1590  Double_t dE_B = det_de->GetMaxDeltaE(zz, aa);
1591  Double_t E_B = det_de->GetEIncOfMaxDeltaE(zz, aa);
1592  Double_t Eres_B = det_de->GetERes(zz, aa, E_B);
1593  B_line->SetPoint(npoi_bragg++, Eres_B, dE_B);
1594 
1595  //find E2
1596  //go from E1 MeV to maximum value where the energy loss formula is valid
1597  Double_t E2min = E1, E2max = det_eres->GetEmaxValid(part.GetZ(), part.GetA());
1598  E2 = (E2min + E2max) / 2.;
1599 
1600  while ((E2max - E2min > SeuilE)) {
1601 
1602  part.SetEnergy(E2);
1603  det_de->Clear();
1604  det_eres->Clear();
1605 
1606  det_de->DetectParticle(&part);
1607  det_eres->DetectParticle(&part);
1608  if (part.GetEnergy() > SeuilE) {
1609  //particle got through - decrease energy
1610  E2max = E2;
1611  E2 = (E2max + E2min) / 2.;
1612  }
1613  else {
1614  //particle stopped - increase energy
1615  E2min = E2;
1616  E2 = (E2max + E2min) / 2.;
1617  }
1618  }
1619 
1620  // printf("z=%d a=%d E1=%lf E2=%lf\n",zz,aa,E1,E2);
1621  KVIDZALine* line = (KVIDZALine*)idgrid->Add("ID", "KVIDZALine");
1622  if (TMath::Even(zz)) line->SetLineColor(4);
1623  line->SetAandZ(aa, zz);
1624 
1625  Double_t logE1 = TMath::Log(E1);
1626  Double_t logE2 = TMath::Log(E2);
1627  Double_t dLog = (logE2 - logE1) / (npoints - 1.);
1628 
1629  for (Int_t i = 0; i < npoints; i++) {
1630  Double_t E = TMath::Exp(logE1 + i * dLog);
1631  Double_t Eres = 0.;
1632  Int_t niter = 0;
1633  while (Eres < SeuilE && niter <= 20) {
1634  det_de->Clear();
1635  det_eres->Clear();
1636 
1637  part.SetEnergy(E);
1638 
1639  det_de->DetectParticle(&part);
1640  det_eres->DetectParticle(&part);
1641 
1642  Eres = det_eres->GetEnergy();
1643  E += SeuilE;
1644 
1645  niter += 1;
1646  }
1647  if (!(niter > 20)) {
1648  Double_t dE = det_de->GetEnergy();
1649  Double_t gEres, gdE;
1650  line->GetPoint(i - 1, gEres, gdE);
1651  line->SetPoint(i, Eres, dE);
1652  }
1653  }
1654 
1655  }
1656  }
1657 
1658  }
1659 
1660  }
1661 
1662  return idgrid;
1663 
1664 }
1665 
1666 
1667 
1683 
1685 {
1686  // Returns the Y-axis value in the 2D identification map containing isotope (Z,A)
1687  // corresponding to either the given X-axis/Eres value or the current X-axis value given by GetIDGridXCoord()
1688  // If no mass information is available, just give Z.
1689  //
1690  // In this (default) implementation this means scanning the ID grids associated with
1691  // this telescope until we find an identification line Z or (Z,A), and then interpolating
1692  // the Y-coordinate for the current X-coordinate value.
1693  //
1694  // Status variable can take one of following values:
1695  //
1696  // KVIDTelescope::kMeanDE_OK all OK
1697  // KVIDTelescope::kMeanDE_XtooSmall X-coordinate is smaller than smallest X-coordinate of ID line
1698  // KVIDTelescope::kMeanDE_XtooLarge X-coordinate is larger than largest X-coordinate of ID line
1699  // KVIDTelescope::kMeanDE_NoIdentifie No identifier found for Z or (Z,A)
1700 
1701  status = kMeanDE_OK;
1702  // loop over grids
1703  TIter next(GetListOfIDGrids());
1704  KVIDGrid* grid;
1705  KVIDLine* idline = 0;
1706  while ((grid = (KVIDGrid*)next())) {
1707  idline = (KVIDLine*)grid->GetIdentifier(Z, A);
1708  if (idline) break;
1709  }
1710  if (!idline) {
1711  status = kMeanDE_NoIdentifier;
1712  return -1.;
1713  }
1714  Double_t x, x1, y1, x2, y2;
1715  x = (Eres < 0 ? GetIDGridXCoord(grid) : Eres);
1716  idline->GetEndPoint(x2, y2);
1717  if (x > x2) {
1718  status = kMeanDE_XtooLarge;
1719  return -1;
1720  }
1721  idline->GetStartPoint(x1, y1);
1722  if (x < x1) {
1723  status = kMeanDE_XtooSmall;
1724  return -1.;
1725  }
1726  return idline->Eval(x);
1727 }
1728 
1729 
1730 
1731 
1740 
1742 {
1743  // Return kTRUE if energy of ION is > minimum incident energy required for identification
1744  // This theoretical limit is defined here to be the incident energy for which the
1745  // dE in the first detector of a dE-E telescope is maximum.
1746  // If EINC>0 it is assumed to be the energy of the ion just before the first detector
1747  // (case where ion would have to pass other detectors before reaching this telescope).
1748  //
1749  // If this is not a dE-E telescope, we return kTRUE by default.
1750 
1751  if (GetSize() < 2) return kTRUE;
1752 
1753  KVDetector* dEdet = GetDetector(1);
1754  Double_t emin = dEdet->GetEIncOfMaxDeltaE(ION->GetZ(), ION->GetA());
1755  if (EINC > 0.0) return (EINC > emin);
1756  return (ION->GetEnergy() > emin);
1757 }
1758 
1759 
1760 
1787 
1789 {
1790  // For filtering simulations
1791  // Set the n->IsZMeasured() and n->IsAMeasured() status of the particle
1792  // In principle this depends on whether this telescope provides mass
1793  // identification or not, but this may depend on the particle's energy.
1794  // If A was not measured, it will be replaced with a value calculated
1795  // from whatever mass formula is used for the particle.
1796  //
1797  // In order to enable mass identification for certain telescopes without a dedicated
1798  // implementation (e.g. for simulating array response), put the following lines
1799  // in your .kvrootrc:
1800  //
1801  // [dataset].[telescope label].MassID: yes
1802  //
1803  // If you want to limit mass identification to certain values of Z and/or A,
1804  // add the following line:
1805  //
1806  // [dataset].[telescope label].MassID.Validity: [expression]
1807  //
1808  // where [expression] is some valid C++ boolean expression involving Z and/or A,
1809  // for example
1810  //
1811  // [dataset].[telescope label].MassID.Validity: (Z>3)&&(A<20)
1812  //
1813  // Then this expression will be tested here in order to determine particle
1814  // identification status
1815 
1816  n->SetZMeasured();
1817  if (!HasMassID()) {
1818  n->SetAMeasured(kFALSE);
1819  // beware - changing particle's mass changes its KE (momentum is conserved)
1820  double e = n->GetE();
1821  n->SetZ(n->GetZ());// use mass formula for A
1822  n->SetE(e);
1823  }
1824  else {
1825  if (fMassIDValidity) n->SetAMeasured(fMassIDValidity->Test(n)); // test expression for mass ID validity
1826  else n->SetAMeasured(); // no expression set; all nuclei are identified in mass
1827  if (!n->IsAMeasured()) {
1828  // beware - changing particle's mass changes its KE (momentum is conserved)
1829  double e = n->GetE();
1830  n->SetZ(n->GetZ()); // use mass formula for A
1831  n->SetE(e);
1832  }
1833  }
1834 }
1835 
1836 
1837 
1840 
1842 {
1843  // Open IdentificationBilan.dat file with given path
1844 
1846  fgIdentificationBilan = new TEnv(path);
1847 }
1848 
1849 
1850 
1853 
1855 {
1856  // Set status of ID Telescope for given system
1857  if (!(fgIdentificationBilan->GetValue(Form("%s.%s", system.Data(), GetName()), kTRUE))) ResetBit(kReadyForID);
1858 }
1859 
1860 
int Int_t
unsigned int UInt_t
KVDataSet * gDataSet
Definition: KVDataSet.cpp:30
KVIDGridManager * gIDGridManager
ClassImp(KVPartitionList) void KVPartitionList
Initialisation.
#define SafeDelete(p)
#define d(i)
#define e(i)
unsigned char UChar_t
char Char_t
const Bool_t kFALSE
bool Bool_t
double Double_t
const Bool_t kTRUE
const char Option_t
R__EXTERN TEnv * gEnv
char * Form(const char *fmt,...)
void SetLabel(const Char_t *lab)
Definition: KVBase.h:188
const Char_t * GetLabel() const
Definition: KVBase.h:192
const Char_t * GetType() const
Definition: KVBase.h:170
static TPluginHandler * LoadPlugin(const Char_t *base, const Char_t *uri="0")
Definition: KVBase.cpp:756
UInt_t GetNumber() const
Definition: KVBase.h:213
const Char_t * GetDataSetDir() const
Definition: KVDataSet.cpp:719
Bool_t HasCalibIdentInfos() const
Definition: KVDataSet.h:396
const Char_t * GetDataSetEnv(const Char_t *type, const Char_t *defval="") const
Definition: KVDataSet.cpp:757
TString GetFullPathToDataSetFile(const Char_t *filename)
Definition: KVDataSet.cpp:1886
Output signal data produced by a detector.
virtual Double_t GetValue(const KVNameValueList &="") const
Base class for detector geometry description, interface to energy-loss calculations.
Definition: KVDetector.h:121
virtual KVDetectorSignal * GetDetectorSignal(const TString &type) const
Definition: KVDetector.h:463
virtual Bool_t IsOK() const
Definition: KVDetector.h:628
Bool_t AddDetectorSignalExpression(const TString &type, const KVString &_expr)
virtual Double_t GetMaxDeltaE(Int_t Z, Int_t A)
virtual Double_t GetERes(Int_t Z, Int_t A, Double_t Einc)
virtual Double_t GetELostByParticle(KVNucleus *, TVector3 *norm=0)
Definition: KVDetector.cpp:305
virtual void SetEnergyLoss(Double_t e) const
Definition: KVDetector.h:332
virtual Double_t GetEnergy() const
Definition: KVDetector.h:308
Int_t GetNHits() const
Return the number of particles hitting this detector in an event.
Definition: KVDetector.h:405
virtual Double_t GetEIncOfMaxDeltaE(Int_t Z, Int_t A)
virtual void Clear(Option_t *opt="")
Definition: KVDetector.cpp:713
Bool_t IsCalibrated() const
Definition: KVDetector.h:359
virtual Bool_t Fired(Option_t *opt="any") const
Definition: KVDetector.h:796
virtual void SetEResAfterDetector(Double_t e)
Definition: KVDetector.h:576
virtual TList * GetAlignedDetectors(UInt_t direction=1)
virtual Double_t GetDeltaE(Int_t Z, Int_t A, Double_t Einc)
virtual Double_t GetDeltaEFromERes(Int_t Z, Int_t A, Double_t Eres)
virtual void DetectParticle(KVNucleus *, TVector3 *norm=0)
Definition: KVDetector.cpp:232
virtual void Print(Option_t *option="") const
Definition: KVDetector.cpp:393
virtual Double_t GetCorrectedEnergy(KVNucleus *, Double_t e=-1., Bool_t transmission=kTRUE)
Definition: KVDetector.cpp:949
Handle reading text files.
Definition: KVFileReader.h:19
KVString GetCurrentLine()
Definition: KVFileReader.h:131
void CloseFile()
Definition: KVFileReader.h:79
Bool_t OpenFileToRead(KVString filename)
Definition: KVFileReader.h:59
void ReadLine(const Char_t *pattern)
Definition: KVFileReader.h:84
Bool_t IsOK()
Definition: KVFileReader.h:74
Group of detectors which can be treated independently of all others in array.
Definition: KVGroup.h:19
@ kForwards
Definition: KVGroup.h:32
Line in ID grid used to delimit regions where no identification is possible.
Definition: KVIDCutLine.h:22
virtual void SetName(const char *name)
This is redeclared to make it appear in context menus for KVIDCutLines.
Definition: KVIDCutLine.h:83
virtual void SetAcceptedDirection(const Char_t *dir)
Definition: KVIDCutLine.cpp:74
Base class for particle identification in a 2D map.
Definition: KVIDGraph.h:31
void Add(TString, KVIDentifier *)
Definition: KVIDGraph.cpp:853
void SetRunList(const char *runlist)
Definition: KVIDGraph.h:150
virtual void SetName(const char *name)
Definition: KVIDGraph.h:134
void AddIDTelescope(KVBase *t)
Definition: KVIDGraph.h:379
virtual void Identify(Double_t, Double_t, KVIdentificationResult *) const =0
KVIDentifier * GetIdentifier(Int_t Z, Int_t A) const
Definition: KVIDGraph.cpp:327
virtual Bool_t IsIdentifiable(Double_t, Double_t, TString *rejected_by=nullptr) const
Definition: KVIDGraph.cpp:1257
const Char_t * GetName() const
Definition: KVIDGraph.cpp:1320
virtual void SetOnlyZId(Bool_t yes=kTRUE)
Definition: KVIDGraph.cpp:1484
KVList * GetGrids()
void DeleteGrid(KVIDGraph *, Bool_t update=kTRUE)
Abstract base class for 2D identification grids in e.g. (dE,E) maps.
Definition: KVIDGrid.h:73
Base class for lines/cuts used for particle identification in 2D data maps.
Definition: KVIDLine.h:143
void GetStartPoint(Double_t &x, Double_t &y) const
Definition: KVIDLine.h:418
void GetEndPoint(Double_t &x, Double_t &y) const
Definition: KVIDLine.h:430
Base class for all detectors or associations of detectors in array which can identify charged particl...
Definition: KVIDTelescope.h:88
void LoadIdentificationParameters(const Char_t *filename, const KVMultiDetArray *multidet)
This method add to the gIDGridManager list the identification grids.
virtual Double_t GetIDMapY(Option_t *opt="")
void init()
default init
KVList fIDGrids
identification grid(s)
Definition: KVIDTelescope.h:97
void SetGroup(KVGroup *kvg)
void SetLabelFromURI(const Char_t *uri)
@ kCalibStatus_NoCalibrations
Double_t GetIDGridYCoord(KVIDGraph *) const
virtual Bool_t Identify(KVIdentificationResult *, Double_t x=-1., Double_t y=-1.)
KVIDGrid * CalculateDeltaE_EGrid(const KVNumberList &Zrange, Int_t deltaMasse, Int_t npoints, Double_t lifetime=-10, UChar_t massformula=0, Double_t xfactor=1.)
virtual Double_t GetIDMapX(Option_t *opt="")
static KVIDTelescope * MakeIDTelescope(const Char_t *name)
virtual Double_t GetPedestalY(Option_t *opt="")
virtual Bool_t SetIdentificationParameters(const KVMultiDetArray *)
void SetIDGrid(KVIDGraph *)
Bool_t HasMassID() const
KVDetector * GetDetector(UInt_t n) const
void ReadIdentificationParameterFiles(const Char_t *filename, const KVMultiDetArray *multidet)
virtual Bool_t CheckTheoreticalIdentificationThreshold(KVNucleus *, Double_t=0.0)
UInt_t GetGroupNumber()
KVGroup * GetGroup() const
Int_t fCalibStatus
temporary variable holding status code for last call to Calibrate(KVReconstructedNucleus*)
virtual Double_t GetPedestalX(Option_t *opt="")
virtual void CalculateParticleEnergy(KVReconstructedNucleus *nuc)
virtual void AddDetector(KVDetector *d)
virtual Double_t GetMeanDEFromID(Int_t &status, Int_t Z, Int_t A=-1, Double_t Eres=-1.0)
const KVList * GetDetectors() const
KVIDGraph * GetIDGrid()
virtual void Print(Option_t *opt="") const
std::unordered_map< KVIDGraph *, GraphCoords > fGraphCoords
X/Y coordinates from detector signals for ID maps.
virtual UShort_t GetIDCode()
KVDetectorSignal * GetSignalFromGridVar(const KVString &var, const KVString &axe)
void CheckIdentificationBilan(const TString &system)
Set status of ID Telescope for given system.
virtual void RemoveIdentificationParameters()
KVParticleCondition * fMassIDValidity
may be used to limit mass identification to certain Z and/or A range
static void OpenIdentificationBilan(const TString &path)
Open IdentificationBilan.dat file with given path.
void SetHasMassID(Bool_t yes=kTRUE)
virtual void Initialize(void)
KVList fDetectors
list of detectors in telescope
Definition: KVIDTelescope.h:95
Double_t GetIDGridXCoord(KVIDGraph *) const
const Char_t * GetDefaultIDGridClass()
virtual void SetIdentificationStatus(KVReconstructedNucleus *)
void GetIDGridCoords(Double_t &X, Double_t &Y, KVIDGraph *grid, Double_t x=-1, Double_t y=-1)
UInt_t GetSize() const
const KVList * GetListOfIDGrids() const
KVGroup * fGroup
group to which telescope belongs
Definition: KVIDTelescope.h:96
static TEnv * fgIdentificationBilan
Definition: KVIDTelescope.h:91
virtual void RemoveGrids()
virtual TGraph * MakeIDLine(KVNucleus *nuc, Double_t Emin, Double_t Emax, Double_t Estep=0.0)
Base class for identification ridge lines corresponding to different nuclear species.
Definition: KVIDZALine.h:32
Full result of one attempted particle identification.
Bool_t IDattempted
=kTRUE if identification was attempted
Bool_t IDOK
general quality of identification, =kTRUE if acceptable identification made
void SetGridName(const Char_t *n)
void Clear(Option_t *opt="")
Reset to initial values.
TString Rejecting_Cut
name of cut in grid which rejected particle for identification
Int_t IDquality
specific quality code returned by identification procedure
Int_t IDcode
a general identification code for this type of identification
void SetIDType(const Char_t *t)
virtual Double_t GetEmaxValid(Int_t Z, Int_t A)
virtual Double_t GetEResFromDeltaE(Int_t Z, Int_t A, Double_t dE=-1.0, enum SolType type=kEmax)
Definition: KVMaterial.cpp:750
Base class for describing the geometry of a detector array.
Bool_t ReadGridsFromAsciiFile(const Char_t *) const
Description of properties and kinematics of atomic nuclei.
Definition: KVNucleus.h:125
Bool_t IsKnown(int z=-1, int a=-1) const
Definition: KVNucleus.cpp:1279
Int_t GetA() const
Definition: KVNucleus.cpp:799
void SetA(Int_t a)
Definition: KVNucleus.cpp:655
void SetZ(Int_t z, Char_t mt=-1)
Definition: KVNucleus.cpp:704
Int_t GetZ() const
Return the number of proton / atomic number.
Definition: KVNucleus.cpp:770
Double_t GetLifeTime(Int_t z=-1, Int_t a=-1) const
Definition: KVNucleus.cpp:1040
Strings used to represent a set of ranges of values.
Definition: KVNumberList.h:83
Bool_t End(void) const
Definition: KVNumberList.h:196
Int_t GetNValues() const
void Begin(void) const
void Add(Int_t)
Add value 'n' to the list.
void Clear(Option_t *="")
Empty number list, reset it to initial state.
Int_t Last() const
Returns largest number included in list.
Int_t Next(void) const
Handles particle selection criteria for data analysis classes ,.
Bool_t Test(const KVNucleus *nuc) const
Double_t GetEnergy() const
Definition: KVParticle.h:582
void SetEnergy(Double_t e)
Definition: KVParticle.h:560
Nuclei reconstructed from data measured by a detector array ,.
KVDetector * GetDetector(const TString &label) const
virtual TObject * FindObjectByLabel(const Char_t *) const
virtual void Clear(Option_t *option="")
virtual TObject * At(Int_t idx) const
virtual TObject * First() const
virtual void SetCleanup(Bool_t enable=kTRUE)
virtual void Add(TObject *obj)
virtual TObject * FindObject(const char *name) const
Extension of ROOT TString class which allows backwards compatibility with ROOT v3....
Definition: KVString.h:72
void Begin(TString delim) const
Definition: KVString.cpp:562
Bool_t End() const
Definition: KVString.cpp:625
KVString Next(Bool_t strip_whitespace=kFALSE) const
Definition: KVString.cpp:675
Int_t GetNValues(TString delim) const
Definition: KVString.cpp:859
Optimised list in which named objects can only be placed once.
virtual void Add(TObject *obj)
virtual void SetLineColor(Color_t lcolor)
virtual Double_t GetBinCenter(Int_t bin) const
static TClass * GetClass(Bool_t load=kTRUE, Bool_t silent=kFALSE)
const char * GetVarY() const
const char * GetVarX() const
virtual const char * GetValue(const char *name, const char *dflt) const
virtual void SetPoint(Int_t i, Double_t x, Double_t y)
virtual Double_t Eval(Double_t x, TSpline *spline=nullptr, Option_t *option="") const
virtual Int_t GetNbinsY() const
TAxis * GetXaxis()
TAxis * GetYaxis()
virtual Int_t GetNbinsX() const
virtual Double_t GetBinContent(Int_t bin) const
void Reset()
virtual const char * GetName() const
virtual void SetName(const char *name)
void AbstractMethod(const char *method) const
void SetBit(UInt_t f)
virtual void Warning(const char *method, const char *msgfmt,...) const
virtual void Error(const char *method, const char *msgfmt,...) const
void ResetBit(UInt_t f)
virtual void Info(const char *method, const char *msgfmt,...) const
Longptr_t ExecPlugin(int nargs, const T &... params)
Bool_t BeginsWith(const char *s, ECaseCompare cmp=kExact) const
const char * Data() const
void Form(const char *fmt,...)
TString & Remove(EStripType s, char c)
TString & ReplaceAll(const char *s1, const char *s2)
TLine * line
Double_t y[n]
Double_t x[n]
const Int_t n
TGraphErrors * gr
const long double cl
Definition: KVUnits.h:85
const long double g
masses
Definition: KVUnits.h:72
Int_t Nint(T x)
Double_t Exp(Double_t x)
constexpr Double_t E()
Double_t Log(Double_t x)
Bool_t Even(Long_t a)
KVDetectorSignal * fVarY
KVDetectorSignal * fVarX
auto * a