KaliVeda
Toolkit for HIC analysis
Loading...
Searching...
No Matches
KVIDTelescope.cpp
1/***************************************************************************
2$Id: KVIDTelescope.cpp,v 1.52 2009/05/05 15:54:04 franklan Exp $
3Author : $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
40#include <KVDetectorSignalExpression.h>
41#include <KVIDZAGrid.h>
42
43using namespace std;
44
47
48
50
52 : fGroup(nullptr)
53{
54 init();
55}
56
57
58
61
63{
64 //default init
67}
68
69
70
102
104{
105 // Default initialisation for ID telescopes.
106 // If telescope has at least 1 grid then it is ready to identify
107 // particles after initialising the grid(s) (kReadyForID=true);
108 // otherwise kReadyForID is set to kFALSE, unless the current dataset (if defined)
109 // has been declared to have no associated identification/calibration parameters,
110 // in which case kReadyForID is by default set to kTRUE (for filtering simulations).
111 //
112 // In order to enable mass identification for certain telescopes without a dedicated
113 // implementation (e.g. for simulating array response), put the following lines
114 // in your .kvrootrc:
115 //
116 // [dataset].[telescope label].MassID: yes
117 //
118 // If you want to limit mass identification to certain values of Z and/or A,
119 // add the following line:
120 //
121 // [dataset].[telescope label].MassID.Validity: [expression]
122 //
123 // where [expression] is some valid C++ boolean expression involving Z and/or A,
124 // for example
125 //
126 // [dataset].[telescope label].MassID.Validity: (Z>3)&&(A<20)
127 //
128 //For identifications using more than one grid, the default behaviour is to try identification
129 //with each grid in turn until a successful identification is obtained. The order in which
130 //the grids should be tried should be specified by a variable with the following format:
131 //
132 //~~~~~~~~~~~~~~~~
133 //[Dataset].[telescope label].GridOrder: [Grid1],[Grid2],...
134 //~~~~~~~~~~~~~~~~
135
137
138 // for datasets with no calib/ident infos, all id telescopes work
139 if (gDataSet && !gDataSet->HasCalibIdentInfos()) {
141 }
142 else { // for datasets with calib/ident infos, we need a grid & all detectors working
143 // looping over detectors to check they are working
144 // if one of them is not -> set kReadyForID to false
145 TIter it(GetDetectors());
146 KVDetector* det = 0;
147 while ((det = (KVDetector*)it())) if (!det->IsOK()) {
149 return;
150 }
151
152 if (GetIDGrid()) {
153 KVIDGraph* gr;
155 bool ok = kTRUE;
156 KVUniqueNameList tmp_list;// for re-ordering grids
157 bool mass_id = false;
158 while ((gr = (KVIDGraph*)it())) {
159 tmp_list.Add(gr);
160 if (gr->HasMassIDCapability()) mass_id = true;
161 gr->Initialize();
162 // make sure both x & y axes' signals are well set up
163 if (!fGraphCoords[gr].fVarX || !fGraphCoords[gr].fVarY) {
164 ok = kFALSE;
165 Warning("Initialize",
166 "ID tel. %s: grid %s has undefined VarX(%s:%p) or VarY(%s:%p) - WILL NOT USE",
167 GetName(), gr->GetName(), gr->GetVarX(), fGraphCoords[gr].fVarX, gr->GetVarY(), fGraphCoords[gr].fVarY);
168 }
169 }
170 // set to true if at least one grid can provide mass identification
171 SetHasMassID(mass_id);
172 // if more than one grid, need to re-order them according to [Dataset].[telescope label].GridOrder
173 if (GetListOfIDGrids()->GetEntries() > 1 && gDataSet) {
174 KVString grid_list = gDataSet->GetDataSetEnv(Form("%s.GridOrder", GetLabel()));
175 ok = kFALSE;
176 if (grid_list == "")
177 Warning("Initialize", "ID telescope %s has %d grids but no %s variable defined",
178 GetName(), GetListOfIDGrids()->GetEntries(), Form("%s.GridOrder", GetLabel()));
179 else if (grid_list.GetNValues(",") != GetListOfIDGrids()->GetEntries())
180 Warning("Initialize", "ID telescope %s has %d grids but %d grids appear in variable %s",
181 GetName(), GetListOfIDGrids()->GetEntries(), grid_list.GetNValues(","), Form("%s.GridOrder", GetLabel()));
182 else {
183 fIDGrids.Clear();
184 grid_list.Begin(",");
185 while (!grid_list.End()) {
186 auto gr_name = grid_list.Next();
187 auto gr_ob = tmp_list.FindObject(gr_name);
188 if (!gr_ob) {
189 Info("Initialize", "IDtel=%s grid %s missing", GetName(), gr_name.Data());
190 }
191 else {
192 fIDGrids.Add(gr_ob);
193 }
194 }
195 ok = kTRUE;
196 }
197 }
198 if (ok) SetBit(kReadyForID);
199 }
200 }
201
202 if (gDataSet) {
203 SetHasMassID(gDataSet->GetDataSetEnv(Form("%s.MassID", GetLabel()), kFALSE));
204 KVString valid;
205 if ((valid = gDataSet->GetDataSetEnv(Form("%s.MassID.Validity", GetLabel()), "")) != "") {
206 valid.ReplaceAll("Z", "_NUC_->GetZ()");
207 valid.ReplaceAll("A", "_NUC_->GetA()");
208 fMassIDValidity.reset(new KVParticleCondition(valid));
209 }
210 }
211}
212
213
214
223
225{
226 // Add a detector to the telescope.
227 //
228 // Detectors must be added in the order they will be hit by impinging particles,
229 // with the last detector being the one particles stopped in the telescope will stop in.
230 // i.e. dE1, dE2, ..., Eres
231 //
232 // Update name of telescope to "ID_[name of 1st detector]_[name of 2nd detector]_ ... _[name of last detector]"
233
234 if (d) {
236 if (GetSize() > 1) {
237 TString old_name = GetName();
238 old_name += Form("_%s", GetDetectors()->Last()->GetName());
239 SetName(old_name);
240 }
241 else SetName(Form("ID_%s", GetDetector(1)->GetName()));
242 //d->AddIDTelescope(this); <= caused multiple copies to exist in detector's list
243 }
244 else {
245 Warning("AddDetector", "Called with null pointer");
246 }
247}
248
249
250
254
256{
257 // print out telescope structure
258 //if opt="fired" only fired detectors are printed
259
260 TIter next(GetDetectors());
261 KVDetector* obj;
262
263 if (!strcmp(opt, "fired")) {
264 while ((obj = (KVDetector*) next())) {
265
266 if (obj->Fired() || obj->GetEnergy())
267 obj->Print("data");
268 }
269 }
270 else {
271 cout << "\n" << opt << "Structure of KVIDTelescope object: " <<
272 GetName() << " " << GetType() << endl;
273 cout << opt <<
274 "--------------------------------------------------------" <<
275 endl;
276 while ((obj = (KVDetector*) next())) {
277 cout << opt << "Detector: " << obj->GetName() << endl;
278 }
279 }
280}
281
282
283
284
287
289{
290 // Return a pointer to the detector in the telescope with the name "name".
291
293 if (!tmp)
294 Warning("GetDetector(const Char_t *name)",
295 "Detector %s not found in telescope %s", name, GetName());
296 return tmp;
297}
298
299
300
301
303
305{
306 return fGroup;
307}
308
309
310
311
313
315{
316 fGroup = kvg;
317}
318
319
320
322
324{
325 return (GetGroup() ? GetGroup()->GetNumber() : 0);
326}
327
328
329
330
339
341 Double_t Emax, Double_t Estep)
342{
343 //For a given nucleus, generate a TGraph representing the line in the deltaE-E
344 //plane of the telescope which can be associated with nuclei of this (A,Z) with total
345 //incident energies between the two limits.
346 //NOTE: if there are other absorbers/detectors placed before this telescope,
347 //the energy losses of the particle in these will be taken into account.
348 //If the step in energy is not given, it is taken equal to 100 equal steps between min and max.
349 //The TGraph should be deleted by the user after use.
350
351
352 if (!Estep)
353 Estep = (Emax - Emin) / 100.;
354
355 Int_t nsteps = 1 + (Int_t)((Emax - Emin) / Estep);
356
357 if (nsteps < 1)
358 return 0;
359
360 Double_t* y = new Double_t[nsteps];
361 Double_t* x = new Double_t[nsteps];
362 Int_t step = 0;
363
364 //get list of all detectors through which particle must pass in order to reach
365 //2nd member of ID Telescope
366 TList* detectors =
368 //detectors->ls();
369 TIter next_det(detectors);
370 //cout << "nsteps =" << nsteps << endl;
371
372 for (Double_t E = Emin; E <= Emax; E += Estep) {
373 //Set energy of nucleus
374 nuc->SetEnergy(E);
375 //cout << "Einc=" << E << endl;
376
377 //Calculate energy loss in each member and stock in arrays x & y
378 //first member
379 KVDetector* det = 0;
380 x[step] = y[step] = -1;
381 while ((det = (KVDetector*) next_det())) {
382 //det->Print();
383 Double_t eloss = det->GetELostByParticle(nuc);
384 if (det == GetDetector(1))
385 y[step] = eloss;
386 else if (det == GetDetector(2))
387 x[step] = eloss;
388 Double_t E1 = nuc->GetEnergy() - eloss;
389 nuc->SetEnergy(E1);
390 //cout << "Eloss=" << eloss << endl;
391 //cout << "Enuc=" << nuc->GetEnergy() << endl;
392 if (E1 < 1.e-3) break;
393 }
394
395 //cout << "step = " << step << " x = " << x[step] << " y = " << y[step] << endl;
396
397 //make sure that some energy is lost in each member
398 //otherwise miss a step and reduce number of points in graph
399 if (x[step] > 0 && y[step] > 0) {
400 step++;
401 }
402 else {
403 nsteps--;
404 }
405
406 //cout << "nsteps =" << nsteps << endl;
407 //reset iterator ready for next loop on detectors
408 next_det.Reset();
409 }
410 TGraph* tmp = 0;
411 if (nsteps > 1)
412 tmp = new TGraph(nsteps, x, y);
413 delete[]x;
414 delete[]y;
415 return tmp;
416}
417
418
419
420
443
445{
446 //Default identification method.
447 //
448 //Works for ID telescopes for which one or more identification grids are defined, each
449 //with VARX/VARY parameters corresponding to a KVDetectorSignal or KVDetectorSignalExpression
450 //associated with one or other of the detectors constituting the telescope.
451 //
452 //For identifications using more than one grid, the default behaviour is to try identification
453 //with each grid in turn until a successful identification is obtained. The order in which
454 //the grids should be tried should be specified by a variable with the following format:
455 //
456 //~~~~~~~~~~~~~~~~
457 //[Dataset].[Array Name].[ID type].GridOrder: [Grid1],[Grid2],...
458 //~~~~~~~~~~~~~~~~
459 //
460 //where the name of each grid is given as "VARY_VARX". If no variable defining the order is found,
461 //the grids will be tried in the order they were found in the file containing the grids for this
462 //telescope.
463 //
464 // The KVIdentificationResult is first Clear()ed; then it is filled with IDtype = GetType()
465 // of this identification telescope, IDattempted = true, and the results of the identification
466 // procedure.
467
468 idr->Clear();
469 idr->IDattempted = true;
470 idr->SetIDType(GetType());
471
472 KVIDGraph* grid;
474 while ((grid = (KVIDGraph*)it())) { //loop over grids in order given by [Dataset].[Array Name].[ID type].GridOrder:
475 Double_t de, e;
476 GetIDGridCoords(e, de, grid, x, y);
477 idr->SetGridName(grid->GetName());
478 if (grid->IsIdentifiable(e, de, &idr->Rejecting_Cut)) {
479 grid->Identify(e, de, idr);
480 if (idr->IDOK) break; // stop on first successful identification
481 }
482 else {
483 // particle rejected by cut in grid. idr->Rejecting_Cut contains its name.
484 idr->IDOK = kFALSE;
486 }
487 }
488 idr->IDcode = GetIDCode();
489
490 return kTRUE;
491}
492
493
494
495
531
533{
534 // Add an identification grid to the list of grids used by this telescope.
535 //
536 // If the grid's VARX and VARY parameters are set and contain the names of valid
537 // detector signals (see formatting rules below) they will be used by
538 // GetIDGridXCoord() and GetIDGridYCoord() to return the coordinates
539 // needed to perform particle identification using the grid.
540 //
541 // The name of the grid is set to "VARY_VARX" (just the signal names, not the detector
542 // label part - see below). This value will be stored in the
543 // KVIdentificationResult corresponding to an attempted identification of a
544 // KVReconstructedNucleus by this grid.
545 //
546 // VARX/VARY Formatting
547 //
548 // To be valid, grid VARX/Y parameters should be set as follows:
549 //
550 //~~~~~~~~~~~~~~~~~~
551 // [signal name]
552 // or [det_label]::[signal name]
553 //~~~~~~~~~~~~~~~~~~
554 //
555 // where
556 //
557 //~~~~~~~~~~~~~~~~~~
558 // [det_label] (optional) = detector label i.e. string returned by KVDetector::GetLabel()
559 // method for detector. By default, VARX is assumed to be the Eres detector
560 // or last detector and VARY the DE detector or first detector
561 // [signal_name] = name of a signal defined for the detector, possibly depending
562 // on availability of calibration
563 //
564 // To see all available signals for a detector, use
565 //
566 // KVDetector::GetListOfDetectorSignals()
567 //~~~~~~~~~~~~~~~~~~
568
569 if (grid) {
570 fIDGrids.Add(grid);
571 KVString det_labels_x, det_labels_y;
572 KVDetectorSignal* xx = GetSignalFromGridVar(grid->GetVarX(), "X", det_labels_x);
573 KVDetectorSignal* yy = GetSignalFromGridVar(grid->GetVarY(), "Y", det_labels_y);
575 gc.fVarX = xx;
576 gc.fDetLabelsX = det_labels_x;
577 gc.fVarY = yy;
578 gc.fDetLabelsY = det_labels_y;
579 fGraphCoords[grid] = gc;
580 TString grid_name;
581 if (xx && yy) {
582 grid_name.Form("%s_%s", yy->GetName(), xx->GetName());
583 grid->SetName(grid_name);
584 }
585 }
586}
587
588
589
635
637{
638 // Deduce & return pointer to detector signal from grid VARX/VARY parameter
639 //
640 // To be valid, grid VARX/Y parameters should be set using mathematical expressions
641 // which use the following references to detector signals for the telescope:
642 //
643 //~~~~~~~~~~~~~~~~~~
644 // [signal name]
645 // OR [det_label]::[signal name]
646 //~~~~~~~~~~~~~~~~~~
647 //
648 // where
649 //
650 //~~~~~~~~~~~~~~~~~~
651 // [signal_name] = name of a signal defined for 1 of the detectors of the telescope
652 // [det_label] = optional detector label i.e. string returned by
653 // KVDetector::GetLabel() method for detector
654 //~~~~~~~~~~~~~~~~~~
655 //
656 // If `[det_label]` is not given, we assume for `VARX` the last (E) detector,
657 // while for `VARY` we assume the first (dE) detector. If this telescope has only
658 // one detector, we use it for both variables.
659 //
660 // To see all available signals for a detector, use
661 //
662 //~~~~~~~~~~~~~~~~~~
663 // KVDetector::GetListOfDetectorSignals()
664 //~~~~~~~~~~~~~~~~~~
665 //
666 // #### Example ####
667 // Imagine a telescope which combines 2 detectors, with labels SI and CSI (in that order, i.e. SI is the dE detector,
668 // CSI is the residual energy detector). The following cases are valid:
669 //
670 //~~~~~
671 // VARX = Energy : use 'Energy' signal of CSI detector (default for VARX)
672 // VARY = ADC : use 'ADC' signal of SI detector (default for VARY)
673 // VARY = CSI::Energy : use 'Energy' signal of CSI detector (overrides default for VARY, SI)
674 // VARX = (Q3-Q3Fast)/(0.8*Q3) : uses 'Q3' and 'Q3Fast' signals of CSI detector (default for VARX)
675 // VARY = 1.5*SI::ADC - CSI::Q3Fast/CSI::Q3 : combination of signals from both detectors
676 //~~~~~
677 //
678 // The 'det_labels' string will be filled with a comma-separated list of the labels of each detector used
679 // in the expressions.
680 //
681 // \note if any signals are not defined, they will be evaluated as zero
682
683 if (var == "") {
684 Warning("GetSignalFromGridVar",
685 "No VAR%s defined for grid for telescope %s. KVIDTelescope-derived class handling identification must override GetIDMapX/GetIDMapY",
686 axe.Data(), GetName());
687 return nullptr;
688 }
689
690 KVString dum = var;
691 KVDetector* det = nullptr;
692 KVDetectorSignal* ds(nullptr);
693 KVString sig_type;
694
695 // check if VARX/Y is a mathematical expression
696 Bool_t is_expression = var.GetNValues("+-*/()") > 1;
697 // examine each term in expression (this will split the elements in a mathematical expression,
698 // or just take the whole expression if no math operators are present)
699 var.Begin("+-*/()");
700 bool explicit_det_ref = false;
701 bool multidetexpr = false;
702 KVString det_label;
703 while (!var.End()) {
704 KVString t = var.Next();
705 // check if we have an explicit reference to a detector
706 if (t.Contains("::")) {
707 t.Begin("::");
708 det_label = t.Next();
709 auto _det = (KVDetector*)GetDetectors()->FindObjectByLabel(det_label);
710 if (_det) {
711 explicit_det_ref = true;
712 sig_type = t.Next();
713 // check signal is defined for detector
714 if (_det->GetDetectorSignal(sig_type)) {
715 if (det_labels.Length()) {
716 if (!det_labels.Contains(det_label)) det_labels += Form(",%s", det_label.Data());
717 }
718 else
719 det_labels = det_label;
720 }
721 else {
722 Warning("GetSignalFromGridVar", "signal '%s' not found in det '%s' -> replaced by '0'", sig_type.Data(), _det->GetName());
723 dum.ReplaceAll(Form("%s::%s", _det->GetLabel(), sig_type.Data()), "0");
724 }
725 }
726 if (det && (_det != det)) multidetexpr = true; // more than 1 detector is referenced
727 det = _det;
728 }
729 }
730 // treat all cases with explicit detector references
731 if (explicit_det_ref) {
732 if (!multidetexpr) {
733 // only 1 detector is directly referenced
734 if (!is_expression) {
735 // it is not a mathematical expression: this is just the name of a detector signal
736 return det->GetDetectorSignal(sig_type);
737 }
738 else {
739 // math expression with explicit reference to signal(s) of 1 detector
740 sig_type = var;
741 // remove all explicit references to detector: 'det' pointer has been set
742 sig_type.ReplaceAll(Form("%s::", det_label.Data()), "");
743 // expression will be handled below
744 }
745 }
746 else {
747 // use specific constructor for explicit detector references
748 ds = new KVDetectorSignalExpression(var, dum, GetDetectors());
749 if (!ds->IsValid()) {
750 delete ds;
751 ds = nullptr;
752 Error("GetSignalFromGridVar",
753 "Problem initialising ID-grid %s coordinate for telescope %s."
754 " Check definition of VAR%s for grid (=%s)",
755 axe.Data(), GetName(), axe.Data(), var.Data());
756 return ds;
757 }
759 return ds;
760 }
761 }
762 else {
763 // no explicit reference to detectors - by default, use detector (1) for Y axis,
764 // and the last detector for X axis
765 if (axe == "Y" || GetSize() == 1) det = GetDetector(1);
766 else det = GetDetector(GetSize());
767 sig_type = var;
768 det_labels = det->GetLabel();
769 }
770 ds = det->GetDetectorSignal(sig_type);
771 if (!ds) {
772 // sig_type is not the name of a known signal: assume it is an expression using known signal names
773 if (!det->AddDetectorSignalExpression(sig_type, sig_type)) {
774 Error("GetSignalFromGridVar",
775 "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)",
776 axe.Data(), GetName(), sig_type.Data(), det->GetName(), axe.Data(), var.Data());
777 ds = nullptr;
778 }
779 else
780 ds = det->GetDetectorSignal(sig_type);
781 }
782 return ds;
783}
784
785
786
788
790{
791 TClass* cl = TClass::GetClass(GetDefaultIDGridClass());
792 if (!cl || !cl->InheritsFrom("KVIDZAGrid")) cl = TClass::GetClass("KVIDZAGrid");
793 KVIDGrid* idgrid = (KVIDGrid*)cl->New();
794
795 idgrid->AddIDTelescope(this);
796 idgrid->SetOnlyZId(onlyZ);
797 idgrid->SetRunList("1-10000");
798
799 KVIDCutLine* B_line = (KVIDCutLine*)idgrid->Add("OK", "KVIDCutLine");
800 Int_t npoi_bragg = 0;
801 B_line->SetName("Bragg_line");
802 B_line->SetAcceptedDirection("right");
803
804 return idgrid;
805}
806
807
808
816
817void KVIDTelescope::addLineToGrid(KVIDGrid* idgrid, int zz, int aa, int npoints)
818{
819
820 //loop over energy
821 //first find :
822 // ****E1 = energy at which particle passes 1st detector and starts to enter in the 2nd one****
823 // E2 = energy at which particle passes the 2nd detector
824 //then perform npoints calculations between these two energies and use these
825 //to construct a KVIDZALine
826
827 double xfactor = 1.;
828
829 KVNucleus part;
830
831 KVDetector* det_de = GetDetector(1);
832 KVDetector* det_eres = GetDetector(2);
833
834 Double_t SeuilE = 0.1;
835
836 part.SetZ(zz);
837 part.SetA(aa);
838
839 Double_t E1, E2;
840 //find E1
841 //go from SeuilE MeV to det_de->GetEIncOfMaxDeltaE(part.GetZ(),part.GetA()))
842 Double_t E1min = SeuilE, E1max = det_de->GetEIncOfMaxDeltaE(zz, aa);
843 E1 = (E1min + E1max) / 2.;
844
845 while ((E1max - E1min) > SeuilE) {
846
847 part.SetEnergy(E1);
848 det_de->Clear();
849 det_eres->Clear();
850
851 det_de->DetectParticle(&part);
852 det_eres->DetectParticle(&part);
853 if (det_eres->GetEnergy() > SeuilE) {
854 //particle got through - decrease energy
855 E1max = E1;
856 E1 = (E1max + E1min) / 2.;
857 }
858 else {
859 //particle stopped - increase energy
860 E1min = E1;
861 E1 = (E1max + E1min) / 2.;
862 }
863 }
864
865 //add point to Bragg line
866 Double_t dE_B = det_de->GetMaxDeltaE(zz, aa);
867 Double_t E_B = det_de->GetEIncOfMaxDeltaE(zz, aa);
868 Double_t Eres_B = det_de->GetERes(zz, aa, E_B);
869
870 KVIDCutLine* B_line = (KVIDCutLine*)idgrid->GetCut("Bragg_line");
871 if (B_line) B_line->SetPoint(B_line->GetN(), Eres_B, dE_B);
872
873 //find E2
874 //go from E1 MeV to maximum value where the energy loss formula is valid
875 Double_t E2min = E1, E2max = det_eres->GetEmaxValid(part.GetZ(), part.GetA());
876 E2 = (E2min + E2max) / 2.;
877
878 while ((E2max - E2min > SeuilE)) {
879
880 part.SetEnergy(E2);
881 det_de->Clear();
882 det_eres->Clear();
883
884 det_de->DetectParticle(&part);
885 det_eres->DetectParticle(&part);
886 if (part.GetEnergy() > SeuilE) {
887 //particle got through - decrease energy
888 E2max = E2;
889 E2 = (E2max + E2min) / 2.;
890 }
891 else {
892 //particle stopped - increase energy
893 E2min = E2;
894 E2 = (E2max + E2min) / 2.;
895 }
896 }
897 E2 *= xfactor;
898 if ((!strcmp(det_eres->GetType(), "CSI")) && (E2 > 5000)) E2 = 5000;
899 // printf("z=%d a=%d E1=%lf E2=%lf\n",zz,aa,E1,E2);
900 KVIDZALine* line = (KVIDZALine*)idgrid->Add("ID", "KVIDZALine");
901 if (TMath::Even(zz)) line->SetLineColor(4);
902 line->SetZ(zz);
903 line->SetA(aa);
904
905 Double_t logE1 = TMath::Log(E1);
906 Double_t logE2 = TMath::Log(E2);
907 Double_t dLog = (logE2 - logE1) / (npoints - 1.);
908
909 for (Int_t i = 0; i < npoints; i++) {
910 // Double_t E = E1 + i*(E2-E1)/(npoints-1.);
911 Double_t E = TMath::Exp(logE1 + i * dLog);
912
913 Double_t Eres = 0.;
914 Int_t niter = 0;
915 while (Eres < SeuilE && niter <= 20) {
916 det_de->Clear();
917 det_eres->Clear();
918
919 part.SetEnergy(E);
920
921 det_de->DetectParticle(&part);
922 det_eres->DetectParticle(&part);
923
924 Eres = det_eres->GetEnergy();
925 E += SeuilE;
926 niter += 1;
927 }
928 if (!(niter > 20)) {
929 Double_t dE = det_de->GetEnergy();
930 Double_t gEres, gdE;
931 line->GetPoint(i - 1, gEres, gdE);
932 line->SetPoint(i, Eres, dE);
933
934 }
935 }
936 //printf("sort de boucle points");
937
938
939}
940
941
942
951
953{
954 // Returns a comma-separated list of the labels of the detectors used to determine
955 // the "x" or "y" coordinates of the identification grid(s)
956 //
957 // If there is more than 1 grid and the list is not the same for all grids,
958 // prints a warning message.
959 //
960 // \param[in] axis name of grid axis i.e. "x", "X", "y" or "Y" (case insensitive)
961
962 KVString _axis = axis;
963 _axis.ToUpper();
964
965 if (_axis != "X" && _axis != "Y") {
966 Error("GetDetectorLabelsForGridCoord", "Called with illegal axis name '%s'", axis.Data());
967 return "";
968 }
969 KVString lab_list;
970
971 for (auto& __gc : fGraphCoords) {
972 KVString labs;
973 if (_axis == "X") labs = __gc.second.fDetLabelsX;
974 else labs = __gc.second.fDetLabelsY;
975 if (lab_list.Length() && lab_list != labs) {
976 Error("GetDetectorLabelsForGridCoord", "Grids for telescope %s use different detector types for %s-coordinate: "
977 "%s and %s", GetName(), _axis.Data(), lab_list.Data(), labs.Data());
978 return "";
979 }
980 lab_list = labs;
981 }
982 return lab_list;
983}
984
985
986
987
991
993{
994 //Return the first in the list of identification grids used by this telescope
995 //(this is for backwards compatibility with ID telescopes which had only one grid).
996 return (KVIDGraph*)GetListOfIDGrids()->First();
997}
998
999
1000
1001
1004
1006{
1007 //Return pointer to grid using position in list. First grid has index = 1.
1008 if (index < 1) {
1009 Error("GetIDGrid(int)", "Index must be >=1!");
1010 return nullptr;
1011 }
1012 return (KVIDGraph*)GetListOfIDGrids()->At(index - 1);
1013}
1014
1015
1016
1017
1021
1023{
1024 //Return pointer to grid using "label" to search in list of grids associated
1025 //to this telescope.
1026 return (KVIDGraph*)GetListOfIDGrids()->FindObjectByLabel(label);
1027}
1028
1029
1030
1031
1033
1035{
1036 AbstractMethod("GetIDMapX");
1037 return -1.;
1038}
1039
1040
1041
1046
1048{
1049 // Returns the pedestal associated with the 2nd detector of the telescope,
1050 // optionally depending on the given option string.
1051 // By default this returns 0, and should be overridden in specific implementations.
1052
1053 return 0.;
1054}
1055
1056
1057
1062
1064{
1065 // Returns the pedestal associated with the 1st detector of the telescope,
1066 // optionally depending on the given option string.
1067 // By default this returns 0, and should be overridden in specific implementations.
1068
1069 return 0.;
1070}
1071
1072
1073
1077
1079{
1080 // Return value of X coordinate to be used with the given ID grid
1081 // This corresponds to whatever was given as parameter "VARX" for the grid
1082
1083 KVDetectorSignal* ds = fGraphCoords[g].fVarX;
1084 if (ds) return ds->GetValue();
1085 return -1;
1086}
1087
1088
1089
1093
1095{
1096 // Return value of Y coordinate to be used with the given ID grid
1097 // This corresponds to whatever was given as parameter "VARY" for the grid
1098
1099 KVDetectorSignal* ds = fGraphCoords[g].fVarY;
1100 if (ds) return ds->GetValue();
1101 return -1;
1102}
1103
1104
1105
1106
1108
1110{
1111 AbstractMethod("GetIDMapY");
1112 return -1.;
1113}
1114
1115
1116
1117
1121
1123{
1124 //Remove all identification grids for this ID telescope
1125 //Grids are not deleted as this is handled by gIDGridManager
1126 fIDGrids.Clear();
1127 fGraphCoords.clear();
1128}
1129
1130
1131
1132
1151
1153{
1154 //Static function which will create an instance of the KVIDTelescope-derived class
1155 //corresponding to 'name'
1156 //These are defined as 'Plugin' objects in the file $KVROOT/KVFiles/.kvrootrc :
1157 //~~~~~~~
1158 // # The KVMultiDetArray::GetIDTelescopes(KVDetector*de, KVDetector*e) method uses these plugins to
1159 // # create KVIDTelescope instances adapted to the specific array geometry and detector types.
1160 // # For each pair of detectors we look for a plugin with one of the following names:
1161 // # [name_of_dataset].de_detector_type[de detector thickness]-e_detector_type[de detector thickness]
1162 // # Each characteristic in [] brackets may or may not be present in the name; first we test for names
1163 // # with these characteristics, then all combinations where one or other of the characteristics is not present.
1164 // # In addition, we first test all combinations which begin with [name_of_dataset].
1165 // # The first plugin found in this order will be used.
1166 // # In addition, if for one of the two detectors there is a plugin called
1167 // # [name_of_dataset].de_detector_type[de detector thickness]
1168 // # [name_of_dataset].e_detector_type[e detector thickness]
1169 // # then we add also an instance of this 1-detector identification telescope.
1170 //~~~~~~~
1171
1172 TPluginHandler* ph;
1173 //check and load plugin library
1174 if (!(ph = LoadPlugin("KVIDTelescope", uri)))
1175 return 0;
1176
1177 //execute constructor/macro for identification telescope
1178 KVIDTelescope* mda = (KVIDTelescope*) ph->ExecPlugin(0);
1179 if (mda) {
1180 //set label of telescope with URI used to find plugin (minus dataset name)
1181 mda->SetLabelFromURI(uri);
1182 }
1183
1184 return mda;
1185}
1186
1187
1188
1189
1193
1195{
1196 //PRIVATE METHOD
1197 //Sets label of telescope based on URI of plugin describing child class for this telescope
1198
1199 TString _uri(uri);
1200 if (gDataSet && _uri.BeginsWith(gDataSet->GetName())) _uri.Remove(0, strlen(gDataSet->GetName()) + 1);
1201 SetLabel(_uri.Data());
1202}
1203
1204
1205
1206
1223
1225{
1226 // Initialise the identification parameters (grids, etc.) of ALL identification telescopes of this
1227 // kind (label) in the multidetector array. Therefore this method need only be called once, and not
1228 // called for each telescope. The kind/label (returned by GetLabel) of the telescope corresponds
1229 // to the URI used to find the plugin class in $KVROOT/KVFiles/.kvrootrc.
1230 // By default, this method looks for the file with name given by the environment variable
1231 //
1232 // [dataset name].IdentificationParameterList.[telescope label]: [filename]
1233 //
1234 // which is assumed to contain the list of files containing the identification grids.
1235 //
1236 // If not such envionment variable is found, the method looks for another one:
1237 //
1238 // [dataset name].IdentificationParameterFile.[telescope label]: [filename]
1239 //
1240 // which is assumed to contain identification grids.
1241
1242 TString filename = gDataSet->GetDataSetEnv(Form("IdentificationParameterList.%s", GetLabel()));
1243
1244 if (filename != "") {
1246 }
1247 else {
1248 filename = gDataSet->GetDataSetEnv(Form("IdentificationParameterFile.%s", GetLabel()));
1249
1250 if (filename == "") {
1251 Warning("SetIdentificationParameters",
1252 "No filename defined. Should be given by %s.IdentificationParameterFile.%s or %s.IdentificationParameterFile.%s",
1253 gDataSet->GetName(), GetLabel(), gDataSet->GetName(), GetLabel());
1254 return kFALSE;
1255 }
1256
1258 }
1259 return kTRUE;
1260}
1261
1262
1263
1264
1272
1274{
1275 // In the case where the identification grids are stored in several files, this method parse
1276 // the file found with the following environment variable:
1277 //
1278 // [dataset name].IdentificationParameterList.[telescope label]: [filename]
1279 //
1280 // which contains the list of files containing the identification grids.
1281
1282 KVFileReader fr;
1284
1285 while (fr.IsOK()) {
1286 fr.ReadLine(0);
1287
1288 if (fr.GetCurrentLine() != "") LoadIdentificationParameters(fr.GetCurrentLine().Data(), multidet);
1289 }
1290
1291 fr.CloseFile();
1292}
1293
1294
1295
1296
1299
1301{
1302 // This method add to the gIDGridManager list the identification grids.
1303
1304 TString path;
1305
1306 if ((path = gDataSet->GetFullPathToDataSetFile(filename)) == "") {
1307 Error("LoadIdentificationParameters",
1308 "File %s not found. Should be in %s",
1309 filename, gDataSet->GetDataSetDir());
1310 return;
1311 }
1312 //
1313 //Read grids from file
1314 Info("LoadIdentificationParameters", "Using file %s", path.Data());
1315 multidet->ReadGridsFromAsciiFile(path);
1316}
1317
1318
1319
1320
1332
1334{
1335 //Remove identification parameters from telescope in such a way that they
1336 //can subsequently be reset e.g. with a new version.
1337 //This is used by KVMultiDetArray::UpdateIdentifications.
1338 //Child classes with specific SetIdentificationParameters methods should
1339 //also redefine this method in order to remove (destroy) cleanly the objects
1340 //created in SetIdentificationParameters.
1341 //
1342 //This default method takes the list of grids associated to the telescope,
1343 //and for each one: 1) checks if it is still in the gIDGridManager's list
1344 //2) if yes, delete the grid and remove it from gIDGridManager
1345
1346 TIter next_grid(GetListOfIDGrids());
1347 KVIDGrid* grid;
1348 while ((grid = (KVIDGrid*)next_grid())) {
1349
1350 if (gIDGridManager->GetGrids()->FindObject(grid)) { //this only works if KVIDTelescope uses TObject:IsEqual method (i.e. compares pointers)
1351
1352 gIDGridManager->DeleteGrid(grid);
1353
1354 }
1355 }
1356 //clear list of grids
1357 fIDGrids.Clear();
1359}
1360
1361
1362
1363
1382
1384{
1385 // The energy of each particle is calculated as follows:
1386 //
1387 // E = dE_1 + dE_2 + ... + dE_N
1388 //
1389 // dE_1, dE_2, ... = energy losses measured in each detector through which
1390 // the particle has passed (or stopped, in the case of dE_N).
1391 // These energy losses are corrected for (Z,A)-dependent effects
1392 // such as pulse-heigth defect in silicon detectors, losses in
1393 // windows of gas detectors, etc.
1394 //
1395 // Whenever possible, the energy loss for fired detectors which are uncalibrated
1396 // or not functioning is calculated. In this case the status returned by GetCalibStatus()
1397 // will be KVIDTelescope::kCalibStatus_Calculated.
1398 // If none of the detectors is calibrated, the particle's energy cannot be calculated &
1399 // the status will be KVIDTelescope::kCalibStatus_NoCalibrations.
1400 // Otherwise, the status code will be KVIDTelescope::kCalibStatus_OK.
1401
1402 //status code
1404
1405 UInt_t z = nuc->GetZ();
1406 //uncharged particles
1407 if (z == 0) return;
1408
1409 KVDetector* d1 = GetDetector(1);
1410 KVDetector* d2 = (GetSize() > 1 ? GetDetector(2) : 0);
1411 Bool_t d1_cal = d1->IsCalibrated();
1412 Bool_t d2_cal = (d2 ? d2->IsCalibrated() : kFALSE);
1413
1414 //no calibrations
1415 if (!d1_cal && !d2)
1416 return;
1417 if ((d1 && d2) && !d1_cal && !d2_cal)
1418 return;
1419
1420 //status code
1422
1423 UInt_t a = nuc->GetA();
1424
1425 // particles stopped in first member of telescope
1426 if (nuc->GetStatus() == 3) {
1427 if (d1_cal) {
1428 nuc->SetEnergy(d1->GetCorrectedEnergy(nuc, -1, kFALSE)); //N.B.: transmission=kFALSE because particle stop in d1
1429 }
1430 return;
1431 }
1432
1433 Double_t e1, e2, einc;
1434 e1 = e2 = einc = 0.0;
1435
1436 if (!d1_cal) {//1st detector not calibrated - calculate from residual energy in 2nd detector
1437
1438 //second detector must exist and have all acquisition parameters fired with above-pedestal value
1439 if (d2 && d2->Fired("Pall")) e2 = d2->GetCorrectedEnergy(nuc, -1, kFALSE); //N.B.: transmission=kFALSE because particle stop in d2
1440 if (e2 <= 0.0) {
1441 // zero energy loss in 2nd detector ? can't do anything...
1443 return;
1444 }
1445 //calculate & set energy loss in dE detector
1446 //N.B. using e2 for the residual energy after detector 1 means
1447 //that we are assuming the particle stops in detector 2.
1448 //if this is not true, we will underestimate the energy of the particle.
1449 e1 = d1->GetDeltaEFromERes(z, a, e2);
1450 if (e1 < 0.0) e1 = 0.0;
1451 else {
1452 d1->SetEnergyLoss(e1);
1453 d1->SetEResAfterDetector(e2);
1454 e1 = d1->GetCorrectedEnergy(nuc);
1455 //status code
1457 }
1458 }
1459 else { //1st detector is calibrated too: get corrected energy loss
1460
1461 e1 = d1->GetCorrectedEnergy(nuc);
1462
1463 }
1464
1465 if (d2 && !d2_cal) {//2nd detector not calibrated - calculate from energy loss in 1st detector
1466
1467 e1 = d1->GetCorrectedEnergy(nuc);
1468 if (e1 <= 0.0) {
1469 // zero energy loss in 1st detector ? can't do anything...
1471 return;
1472 }
1473 //calculate & set energy loss in 2nd detector
1474 e2 = d1->GetEResFromDeltaE(z, a);
1475 if (e2 < 0.0) e2 = 0.0;
1476 else {
1477 e2 = d2->GetDeltaE(z, a, e2);
1478 d2->SetEnergyLoss(e2);
1479 e2 = d2->GetCorrectedEnergy(nuc);
1480 //status code
1482 }
1483 }
1484 else if (d2) { //2nd detector is calibrated too: get corrected energy loss
1485
1486 e2 = d2->GetCorrectedEnergy(nuc, -1, kFALSE);//N.B.: transmission=kFALSE because particle assumed to stop in d2
1487 // recalculate corrected energy in first stage using info on Eres
1488 d1->SetEResAfterDetector(e2);
1489 e1 = d1->GetCorrectedEnergy(nuc);
1490 }
1491
1492 //incident energy of particle (before 1st member of telescope)
1493 einc = e1 + e2;
1494
1495 Double_t coherence_tolerance = gEnv->GetValue("KVIDTelescope.CoherencyTolerance", 1.05);
1496 if (coherence_tolerance < 1) coherence_tolerance += 1.00;
1497
1498 //Now we have to work our way up the list of detectors from which the particle was
1499 //reconstructed. For each fired & calibrated detector which is only associated with
1500 //one particle in the events, we add the corrected measured energy loss
1501 //to the particle. For uncalibrated, unfired detectors and detectors through which
1502 //more than one particle has passed, we calculate the corrected energy loss and add it
1503 //to the particle.
1504 int ndets = nuc->GetNumDet();
1505 if (ndets > (int)GetSize()) { //particle passed through other detectors before this idtelesocpe
1506 //look at detectors not in this id telescope
1507 int idet = GetSize();//next detector after delta-e member of IDTelescope (stopping detector = 0)
1508 while (idet < ndets) {
1509
1510 KVDetector* det = nuc->GetDetector(idet);
1511 if (det->Fired() && det->IsCalibrated() && det->GetNHits() == 1) {
1512 Double_t dE = det->GetEnergy();
1513 //in order to check if particle was really the only one to
1514 //hit each detector, we calculate the particle's energy loss
1515 //from its residual energy. if the measured energy loss is
1516 //significantly larger, there may be a second particle.
1517 e1 = det->GetDeltaEFromERes(z, a, einc);
1518 if (e1 < 0.0) e1 = 0.0;
1519 det->SetEResAfterDetector(einc);
1520 dE = det->GetCorrectedEnergy(nuc);
1521 einc += dE;
1522 }
1523 else {
1524 // Uncalibrated/unfired/multihit detector. Calculate energy loss.
1525 //calculate energy of particle before detector from energy after detector
1526 e1 = det->GetDeltaEFromERes(z, a, einc);
1527 if (e1 < 0.0) e1 = 0.0;
1528 if (det->GetNHits() > 1) {
1529 //Info("CalculateParticleEnergy",
1530 // "Detector %s was hit by %d particles. Calculated energy loss for particle %f MeV",
1531 // det->GetName(), det->GetNHits(), e1);
1532 if (!(det->Fired() && det->IsCalibrated())) {
1533 det->SetEnergyLoss(e1 + det->GetEnergy());// sum up calculated energy losses in uncalibrated detector
1534 }
1535 //status code
1537 }
1538 else if (!det->Fired() || !det->IsCalibrated()) {
1539 //Info("CalculateParticleEnergy",
1540 // "Detector %s uncalibrated/not fired. Calculated energy loss for particle %f MeV",
1541 // det->GetName(), e1);
1542 det->SetEnergyLoss(e1);
1543 //status code
1545 }
1546 det->SetEResAfterDetector(einc);
1547 e1 = det->GetCorrectedEnergy(nuc, e1);
1548 einc += e1;
1549 }
1550 idet++;
1551 }
1552 }
1553 //einc is now the energy of the particle before crossing the first detector
1554 nuc->SetEnergy(einc);
1555}
1556
1557
1558
1559
1569
1571{
1572 // Returns name of default ID grid class for this ID telescope.
1573 // This is defined in a .kvrootrc configuration file by one of the following:
1574 // KVIDTelescope.DefaultGrid:
1575 // KVIDTelescope.DefaultGrid.[type]:
1576 // where [type] is the type of this identification telescope (which is given
1577 // by the character string returned by method GetLabel()... sorry :( )
1578 // If no default grid is defined for the specific type of this telescope,
1579 // the default defined by KVIDTelescope.DefaultGrid is used.
1580
1581 TString specific;
1582 specific.Form("KVIDTelescope.DefaultGrid.%s", GetLabel());
1583 return gEnv->GetValue(specific.Data(), gEnv->GetValue("KVIDTelescope.DefaultGrid", "KVIDGraph"));
1584}
1585
1586
1587
1593
1595{
1596 //Create a dE-E grid (energy loss in detector 1 versus residual energy in detector 2) for a given list of isotopes
1597 // - AperZ : list of A for each Z. (ex: "1=1-3,2=3-4 5,3=6-8,4=7 9-12"...)
1598 // - npoints : number of points in each generated line
1599 // - xfactor : scales the detector 2 thickness to prolongate the lines
1600
1601 if (GetSize() <= 1) return 0;
1602 if (!GetDetector(1) || !GetDetector(2)) return 0;
1603 double thickness = GetDetector(2)->GetThickness();
1604 GetDetector(2)->SetThickness(thickness * xfactor);
1605
1606 Info("CalculateDeltaE_EGrid", "called with KVNameValueList");
1607
1608 KVIDGrid* idgrid = newGrid(0);
1609
1610 for (auto par : AperZ) {
1611 KVString tmp = par.GetName();
1612 int zz = tmp.Atoi();
1613 KVNumberList alist = par.GetString();
1614 for (auto aa : alist) {
1615 addLineToGrid(idgrid, zz, aa, npoints);
1616 }
1617 }
1618
1619 GetDetector(2)->SetThickness(thickness);
1620
1621 return idgrid;
1622
1623}
1624
1625
1626
1634
1635KVIDGrid* KVIDTelescope::CalculateDeltaE_EGrid(const KVNumberList& Zrange, Int_t deltaA, Int_t npoints, Double_t lifetime, UChar_t massformula, Double_t xfactor)
1636{
1637 //Create a dE-E grid (energy loss in detector 1 versus residual energy in detector 2) for a given list of isotopes
1638 // - Zrange : list of element for which we create lines
1639 // - deltaA : number of isotopes generated for each Z around massformula (ex: deltaA=1, Aref-1 Aref Aref+1)
1640 // - npoints : number of points in each generated line
1641 // - lifetime: remove isotopes with lifetime lower than this value
1642 // - xfactor : scales the detector 2 thickness to prolongate the lines
1643
1644 if (GetSize() <= 1) return 0;
1645 if (!GetDetector(1) || !GetDetector(2)) return 0;
1646 double thickness = GetDetector(2)->GetThickness();
1647 GetDetector(2)->SetThickness(thickness * xfactor);
1648
1649 Info("CalculateDeltaE_EGrid", "called with KVNumberList");
1650
1651 KVIDGrid* idgrid = newGrid(0);
1652 KVNucleus part;
1653
1654 Zrange.Begin();
1655 while (!Zrange.End()) {
1656 Int_t zz = Zrange.Next();
1657 part.SetZ(zz, massformula);
1658 Int_t aref = part.GetA();
1659 for (Int_t aa = aref - deltaA; aa <= aref + deltaA; aa += 1) {
1660 part.SetA(aa);
1661 if (part.IsKnown() && (part.GetLifeTime() > lifetime)) {
1662 addLineToGrid(idgrid, zz, aa, npoints);
1663
1664 }
1665 }
1666 }
1667 GetDetector(2)->SetThickness(thickness);
1668 return idgrid;
1669}
1670
1671
1672
1678
1680{
1681 //Create a dE-E grid (energy loss in detector 1 versus residual energy in detector 2) for a given list of isotopes
1682 // - haa_zz : lines will be generated for A,Z filled with 1 in this histogram
1683 // - Zonly : if true, generate only one line per Z with the <A>(Z) of the histogram
1684 // - npoints : number of points in each generated line
1685
1686 if (GetSize() <= 1) return 0;
1687 if (!GetDetector(1) || !GetDetector(2)) return 0;
1688 double thickness = GetDetector(2)->GetThickness();
1689
1690 Info("CalculateDeltaE_EGrid", "called with TH2");
1691
1692 KVIDGrid* idgrid = newGrid(0);
1693 KVNucleus part;
1694
1695 for (Int_t nx = 1; nx <= haa_zz->GetNbinsX(); nx += 1) {
1696
1697 Int_t zz = TMath::Nint(haa_zz->GetXaxis()->GetBinCenter(nx));
1698 KVNumberList nlA;
1699 Double_t sumA = 0, sum = 0;
1700 for (Int_t ny = 1; ny <= haa_zz->GetNbinsY(); ny += 1) {
1701 Double_t stat = haa_zz->GetBinContent(nx, ny);
1702 if (stat > 0) {
1703 Double_t val = haa_zz->GetYaxis()->GetBinCenter(ny);
1704 nlA.Add(TMath::Nint(val));
1705 sumA += val * stat;
1706 sum += stat;
1707 }
1708 }
1709 sumA /= sum;
1710 Int_t nA = nlA.GetNValues();
1711 if (nA == 0) {
1712 Warning("CalculateDeltaE_EGrid", "no count for Z=%d", zz);
1713 }
1714 else {
1715 if (Zonly) {
1716 nlA.Clear();
1717 nlA.Add(TMath::Nint(sumA));
1718 }
1719 else {
1720 if (nA == 1) {
1721 Int_t aref = nlA.Last();
1722 nlA.Add(aref - 1);
1723 nlA.Add(aref + 1);
1724 }
1725 }
1726 part.SetZ(zz);
1727 nlA.Begin();
1728 while (!nlA.End()) {
1729 Int_t aa = nlA.Next();
1730 part.SetA(aa);
1731 if (part.IsKnown()) {
1732 addLineToGrid(idgrid, zz, aa, npoints);
1733 }
1734 }
1735 }
1736 }
1737 return idgrid;
1738}
1739
1740
1741
1757
1759{
1760 // Returns the Y-axis value in the 2D identification map containing isotope (Z,A)
1761 // corresponding to either the given X-axis/Eres value or the current X-axis value given by GetIDGridXCoord()
1762 // If no mass information is available, just give Z.
1763 //
1764 // In this (default) implementation this means scanning the ID grids associated with
1765 // this telescope until we find an identification line Z or (Z,A), and then interpolating
1766 // the Y-coordinate for the current X-coordinate value.
1767 //
1768 // Status variable can take one of following values:
1769 //
1770 // KVIDTelescope::kMeanDE_OK all OK
1771 // KVIDTelescope::kMeanDE_XtooSmall X-coordinate is smaller than smallest X-coordinate of ID line
1772 // KVIDTelescope::kMeanDE_XtooLarge X-coordinate is larger than largest X-coordinate of ID line
1773 // KVIDTelescope::kMeanDE_NoIdentifie No identifier found for Z or (Z,A)
1774
1775 status = kMeanDE_OK;
1776 // loop over grids
1777 TIter next(GetListOfIDGrids());
1778 KVIDGrid* grid;
1779 KVIDLine* idline = 0;
1780 while ((grid = (KVIDGrid*)next())) {
1781 idline = (KVIDLine*)grid->GetIdentifier(Z, A);
1782 if (idline) break;
1783 }
1784 if (!idline) {
1785 status = kMeanDE_NoIdentifier;
1786 return -1.;
1787 }
1788 Double_t x, x1, y1, x2, y2;
1789 x = (Eres < 0 ? GetIDGridXCoord(grid) : Eres);
1790 idline->GetEndPoint(x2, y2);
1791 if (x > x2) {
1792 status = kMeanDE_XtooLarge;
1793 return -1;
1794 }
1795 idline->GetStartPoint(x1, y1);
1796 if (x < x1) {
1797 status = kMeanDE_XtooSmall;
1798 return -1.;
1799 }
1800 return idline->Eval(x);
1801}
1802
1803
1804
1805
1814
1816{
1817 // Return kTRUE if energy of ION is > minimum incident energy required for identification
1818 // This theoretical limit is defined here to be the incident energy for which the
1819 // dE in the first detector of a dE-E telescope is maximum.
1820 // If EINC>0 it is assumed to be the energy of the ion just before the first detector
1821 // (case where ion would have to pass other detectors before reaching this telescope).
1822 //
1823 // If this is not a dE-E telescope, we return kTRUE by default.
1824
1825 if (GetSize() < 2) return kTRUE;
1826
1827 KVDetector* dEdet = GetDetector(1);
1828 Double_t emin = dEdet->GetEIncOfMaxDeltaE(ION->GetZ(), ION->GetA());
1829 if (EINC > 0.0) return (EINC > emin);
1830 return (ION->GetEnergy() > emin);
1831}
1832
1833
1834
1861
1863{
1864 // For filtering simulations
1865 // Set the n->IsZMeasured() and n->IsAMeasured() status of the particle
1866 // In principle this depends on whether this telescope provides mass
1867 // identification or not, but this may depend on the particle's energy.
1868 // If A was not measured, it will be replaced with a value calculated
1869 // from whatever mass formula is used for the particle.
1870 //
1871 // In order to enable mass identification for certain telescopes without a dedicated
1872 // implementation (e.g. for simulating array response), put the following lines
1873 // in your .kvrootrc:
1874 //
1875 // [dataset].[telescope label].MassID: yes
1876 //
1877 // If you want to limit mass identification to certain values of Z and/or A,
1878 // add the following line:
1879 //
1880 // [dataset].[telescope label].MassID.Validity: [expression]
1881 //
1882 // where [expression] is some valid C++ boolean expression involving Z and/or A,
1883 // for example
1884 //
1885 // [dataset].[telescope label].MassID.Validity: (Z>3)&&(A<20)
1886 //
1887 // Then this expression will be tested here in order to determine particle
1888 // identification status
1889
1890 n->SetZMeasured();
1891 if (!HasMassID()) {
1892 n->SetAMeasured(kFALSE);
1893 // beware - changing particle's mass changes its KE (momentum is conserved)
1894 double e = n->GetE();
1895 n->SetZ(n->GetZ());// use mass formula for A
1896 n->SetE(e);
1897 }
1898 else {
1899 if (fMassIDValidity) n->SetAMeasured(fMassIDValidity->Test(n)); // test expression for mass ID validity
1900 else n->SetAMeasured(); // no expression set; all nuclei are identified in mass
1901 if (!n->IsAMeasured()) {
1902 // beware - changing particle's mass changes its KE (momentum is conserved)
1903 double e = n->GetE();
1904 n->SetZ(n->GetZ()); // use mass formula for A
1905 n->SetE(e);
1906 }
1907 }
1908}
1909
1910
1911
1914
1916{
1917 // Open IdentificationBilan.dat file with given path
1918
1920 fgIdentificationBilan = new TEnv(path);
1921}
1922
1923
1924
1927
1929{
1930 // Set status of ID Telescope for given system
1931 if (!(fgIdentificationBilan->GetValue(Form("%s.%s", system.Data(), GetName()), kTRUE))) ResetBit(kReadyForID);
1932}
1933
1934
int Int_t
unsigned int UInt_t
#define d(i)
#define e(i)
bool Bool_t
unsigned char UChar_t
char Char_t
constexpr Bool_t kFALSE
double Double_t
constexpr Bool_t kTRUE
const char Option_t
R__EXTERN TEnv * gEnv
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 index
Option_t Option_t TPoint TPoint const char x2
Option_t Option_t TPoint TPoint const char x1
Option_t Option_t TPoint TPoint const char y2
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 gc
Option_t Option_t TPoint TPoint const char y1
char name[80]
char * Form(const char *fmt,...)
void SetLabel(const Char_t *lab)
Definition KVBase.h:195
const Char_t * GetLabel() const
Definition KVBase.h:199
virtual const Char_t * GetType() const
Definition KVBase.h:177
static TPluginHandler * LoadPlugin(const Char_t *base, const Char_t *uri="0")
Definition KVBase.cpp:793
UInt_t GetNumber() const
Definition KVBase.h:220
const Char_t * GetDataSetDir() const
Bool_t HasCalibIdentInfos() const
Definition KVDataSet.h:232
const Char_t * GetDataSetEnv(const Char_t *type, const Char_t *defval="") const
TString GetFullPathToDataSetFile(const Char_t *filename)
Signal output from a mathematical combination of other signals.
Base class for output signal data produced by a detector.
virtual Bool_t IsValid() const
virtual Double_t GetValue(const KVNameValueList &params="") const
Base class for detector geometry description.
Definition KVDetector.h:160
virtual Bool_t IsOK() const
Definition KVDetector.h:682
virtual KVDetectorSignal * GetDetectorSignal(const KVString &type) const
Definition KVDetector.h:533
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)
virtual void SetEnergyLoss(Double_t e) const
Definition KVDetector.h:373
virtual Double_t GetEnergy() const
Definition KVDetector.h:349
Int_t GetNHits() const
Return the number of particles hitting this detector in an event.
Definition KVDetector.h:436
virtual Double_t GetEIncOfMaxDeltaE(Int_t Z, Int_t A)
virtual void Clear(Option_t *opt="")
void SetThickness(Double_t thick)
virtual Bool_t Fired(Option_t *opt="any") const
Definition KVDetector.h:451
Bool_t IsCalibrated() const
Definition KVDetector.h:390
Bool_t AddDetectorSignalExpression(const KVString &type, const KVString &_expr)
virtual void SetEResAfterDetector(Double_t e)
Definition KVDetector.h:630
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)
virtual void Print(Option_t *option="") const
virtual Double_t GetCorrectedEnergy(KVNucleus *, Double_t e=-1., Bool_t transmission=kTRUE)
Handle reading columns of numeric data in text files.
KVString GetCurrentLine()
ReadStatus ReadLine(const KVString &pattern="")
Bool_t IsOK()
Bool_t OpenFileToRead(const KVString &filename)
Group of detectors which can be treated independently of all others in array.
Definition KVGroup.h:20
@ kForwards
Definition KVGroup.h:33
Line in ID grid used to delimit regions where no identification is possible.
Definition KVIDCutLine.h:23
virtual void SetName(const char *name)
This is redeclared to make it appear in context menus for KVIDCutLines.
Definition KVIDCutLine.h:84
virtual void SetAcceptedDirection(const Char_t *dir)
Base class for particle identification in a 2D map.
Definition KVIDGraph.h:32
void Add(TString, KVIDentifier *)
void SetRunList(const char *runlist)
Definition KVIDGraph.h:156
virtual void SetName(const char *name)
Definition KVIDGraph.h:140
void AddIDTelescope(KVBase *t)
Definition KVIDGraph.h:407
virtual void Identify(Double_t, Double_t, KVIdentificationResult *) const =0
KVIDentifier * GetIdentifier(Int_t Z, Int_t A) const
virtual Bool_t IsIdentifiable(Double_t, Double_t, TString *rejected_by=nullptr) const
const Char_t * GetName() const
KVIDentifier * GetCut(const Char_t *name) const
Definition KVIDGraph.h:280
virtual void SetOnlyZId(Bool_t yes=kTRUE)
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:74
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
void GetEndPoint(Double_t &x, Double_t &y) const
Base class for all detectors or associations of detectors in array which can identify charged particl...
KVIDGrid * newGrid(bool onlyZ)
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
KVIDGrid * CalculateDeltaE_EGrid(const KVNameValueList &AperZ, Int_t npoints=30, Double_t xfactor=1.)
void SetGroup(KVGroup *kvg)
KVList fMultiDetExpressions
used to clean up any multi-detector signal expressions generated to calculate X/Y coordinates
void SetLabelFromURI(const Char_t *uri)
Double_t GetIDGridYCoord(KVIDGraph *) const
virtual Bool_t Identify(KVIdentificationResult *, Double_t x=-1., Double_t y=-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
void ReadIdentificationParameterFiles(const Char_t *filename, const KVMultiDetArray *multidet)
virtual Bool_t CheckTheoreticalIdentificationThreshold(KVNucleus *, Double_t=0.0)
const KVList * GetListOfIDGrids() const
UInt_t GetGroupNumber()
void addLineToGrid(KVIDGrid *gg, int zz, int aa, int npoints)
KVGroup * GetGroup() const
Int_t fCalibStatus
temporary variable holding status code for last call to Calibrate(KVReconstructedNucleus*)
virtual Double_t GetPedestalX(Option_t *opt="")
KVDetector * GetDetector(UInt_t n) const
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)
KVDetectorSignal * GetSignalFromGridVar(const KVString &var, const KVString &axe, KVString &det_labels)
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()
void CheckIdentificationBilan(const TString &system)
Set status of ID Telescope for given system.
virtual void RemoveIdentificationParameters()
static void OpenIdentificationBilan(const TString &path)
Open IdentificationBilan.dat file with given path.
void SetHasMassID(Bool_t yes=kTRUE)
virtual void Initialize(void)
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
KVUnownedList fIDGrids
identification grid(s)
KVUnownedList fDetectors
list of detectors in telescope
KVString GetDetectorLabelsForGridCoord(const KVString &axis) const
const KVList * GetDetectors() const
std::unique_ptr< KVParticleCondition > fMassIDValidity
may be used to limit mass identification to certain Z and/or A range
KVGroup * fGroup
group to which telescope belongs
static TEnv * fgIdentificationBilan
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:33
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 GetThickness() const
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)
Base class for describing the geometry of a detector array.
Bool_t ReadGridsFromAsciiFile(const Char_t *) const
Handles lists of named parameters with different types, a list of KVNamedParameter objects.
Description of properties and kinematics of atomic nuclei.
Definition KVNucleus.h:126
Bool_t IsKnown(int z=-1, int a=-1) const
Int_t GetA() const
void SetA(Int_t a)
void SetZ(Int_t z, Char_t mt=-1)
Int_t GetZ() const
Return the number of proton / atomic number.
Double_t GetLifeTime(Int_t z=-1, Int_t a=-1) const
Strings used to represent a set of ranges of values.
Bool_t End(void) const
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
Double_t GetEnergy() const
Definition KVParticle.h:621
void SetEnergy(Double_t e)
Definition KVParticle.h:599
Nuclei reconstructed from data measured by a detector array .
KVDetector * GetDetector(const TString &label) const
virtual TObject * FindObject(const char *name) const
virtual TObject * FindObjectByLabel(const Char_t *) const
virtual void Clear(Option_t *option="")
virtual TObject * First() const
virtual TObject * At(Int_t idx) const
virtual void SetCleanup(Bool_t enable=kTRUE)
virtual void Add(TObject *obj)
Extension of ROOT TString class which allows backwards compatibility with ROOT v3....
Definition KVString.h:73
void Begin(TString delim) const
Definition KVString.cpp:565
Bool_t End() const
Definition KVString.cpp:634
KVString Next(Bool_t strip_whitespace=kFALSE) const
Definition KVString.cpp:695
Int_t GetNValues(TString delim) const
Definition KVString.cpp:886
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
const char * GetVarX() const
const char * GetVarY() const
virtual const char * GetValue(const char *name, const char *dflt) const
virtual void SetPoint(Int_t i, Double_t x, Double_t y)
Int_t GetN() const
virtual Double_t Eval(Double_t x, TSpline *spline=nullptr, Option_t *option="") const
virtual Int_t GetNbinsY() const
TAxis * GetXaxis()
virtual Int_t GetNbinsX() const
TAxis * GetYaxis()
virtual Double_t GetBinContent(Int_t bin) const
void Reset()
const char * GetName() const override
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)
Ssiz_t Length() const
Int_t Atoi() const
const char * Data() const
void ToUpper()
Bool_t BeginsWith(const char *s, ECaseCompare cmp=kExact) const
void Form(const char *fmt,...)
TString & Remove(EStripType s, char c)
Bool_t Contains(const char *pat, ECaseCompare cmp=kExact) const
TString & ReplaceAll(const char *s1, const char *s2)
TLine * line
Double_t y[n]
Double_t x[n]
const Int_t n
TGraphErrors * gr
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)
TArc a
ClassImp(TPyArg)