GRSISort "v4.0.0.5"
An extension of the ROOT analysis Framework
Loading...
Searching...
No Matches
tac_calibrator.cxx
Go to the documentation of this file.
1//Written by B. Olaizola
2//Date: 2017-08-11
3
4//ROOT:6.08/06
5//GRSISort:3.1.3.2
6
7//Usage is: tac_calibration /path/to/analysistree.root
8
9//Takes an AnalysisTree, searches for anti-coincidences TAC-LaBr (so we are sure we only have the TAC-calibrator and not LaBr-LaBr timing) and performs a linear fit to the peaks it finds. The output is a *.cal file with the TAC calibrated. If a list of analysistrees is given, the script will calibrate them one by one independently, it will NOT add them together.
10
11//NOTE1: The need for LaBr anticoincidences is the reason it has to work at the AnalysisTree level.
12//NOTE2: The TAC and TAC-calibrator parameters must be edited for every experiment (but the default would be 50 ns TAC range and 10 ns calibrator period).
13//NOTE3: There are several sections of the code commented. They produce different quality-control plots and files. Consider uncommenting them to double check your results.
14
15#include "TFile.h"
16#include "TTree.h"
17#include "TH1F.h"
18#include "TF1.h"
19#include "TMath.h"
20#include "TSpectrum.h"
21#include "TGraph.h"
22#include "TGainMatch.h"
23
24#include "TGriffin.h"
25#include "TSceptar.h"
26#include "TLaBr.h"
27#include "TZeroDegree.h"
28#include "TTAC.h"
29
30#include <vector>
31#include <string>
32
33int main(int argc, char** argv)
34{
35 if(argc == 1) {
36 std::cout << "Usage: " << argv[0] << " <analysis tree file(s)>" << std::endl;
37 return 1;
38 }
39
40 for(int file_num = 1; file_num < argc; ++file_num) {
41 auto* f = new TFile(argv[file_num]);
42
43 std::cout << "Reading from file: " << f << std::endl;
44
45 ////////////////////////////EDIT THIS PART//////////////////////////////////////////////////////////EDIT THIS PART///////////////////////////////////////////////////////////////////////////////////////////////////////////////
46 double calibrator_period = 10000.; //The period of the calibrator (manually set in the module). It is the time difference between the peaks, which will be 10 ns in most cases
47 double tac_range = 50000.; //TAC range, 50 ns for most experiments
48 double ps_per_chan = 10.; //binning of the TACs, in ps per channel, 10 is a reasonable number
49 int first_TAC_channel = 75; //This is the channel number of the first TAC, it is needed to write the calibration file. In general it will be 84
50 int number_of_peaks = static_cast<int>(tac_range / calibrator_period); //maximum number of peaks that we expect to find in the TAC-calibrator spectra
51 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
52
53 std::string inname;
54 inname = argv[file_num];
55 std::string num;
56 num.append(inname, inname.length() - 14, 9);
57 std::string calfile = "TAC_calibration_run" + num + ".cal";
58
59 TList list;
60
61 auto* tree = static_cast<TTree*>(f->Get("AnalysisTree"));
62
64
65 TLaBr* labr = nullptr;
66 TZeroDegree* zds = nullptr;
67 TTAC* tac = nullptr;
68
69 if(tree->FindBranch("TLaBr") != nullptr) { //We check to see if we have a LaBr branch in the analysis tree
70 tree->SetBranchAddress("TLaBr", &labr);
71 }
72 if(tree->FindBranch("TZeroDegree") != nullptr) { //We check to see if we have a ZeroDegree branch in the analysis tree
73 tree->SetBranchAddress("TZeroDegree", &zds);
74 }
75 if(tree->FindBranch("TTAC") == nullptr) { //We check to see if we have a TAC branch in the analysis tree
76 std::cout << "Exiting the program because there are no TACs to calibrate " << std::endl;
77 exit(-1);
78 } else {
79 tree->SetBranchAddress("TTAC", &tac);
80 }
81
82 std::array<TH1F*, 8> raw_tac_calibrator = {};
83 for(int i = 0; i < 8; i++) {
84 raw_tac_calibrator[i] = new TH1F(Form("raw_TAC_calibrator%d", i), Form("raw_TAC_calibrator%d", i), static_cast<int>(tac_range / ps_per_chan), 0, tac_range);
85 list.Add(raw_tac_calibrator[i]);
86 }
87
88 for(int i = 0; i < tree->GetEntries(); i++) { //Loops through the whole AnalysisTree
89 tree->GetEntry(i);
90
91 if(tac->GetMultiplicity() > 0 && labr->GetMultiplicity() == 0) {
92 for(int j = 0; j < tac->GetMultiplicity(); j++) {
93 int histnum = tac->GetTACHit(j)->GetDetector() - 1;
94 if(histnum >= 0 && histnum <= 7) {
95 double charge = tac->GetTACHit(j)->GetCharge();
96 raw_tac_calibrator[histnum]->Fill(charge);
97 }
98 }
99 }
100 }
101
102 std::array<TH1F*, 8> calibration_hist;
103 for(int i = 0; i < 8; i++) {
104 calibration_hist[i] = new TH1F(Form("calibration_hist%d", i), Form("calibration_hist%d", i), static_cast<Int_t>(tac_range / ps_per_chan), 0, tac_range);
105 list.Add(calibration_hist[i]);
106 }
107
108 for(int j = 0; j <= 7; j++) {
109 TSpectrum spec; //It can take an argument as the max number of peaks to be found, but I recomend leaving it blank
110 spec.Search(raw_tac_calibrator[j], 1, "", 0.10); //The 4th argument will discard peaks below 10% of the highest peak. This is important to tune, in a very high rate the number of LaBr-LaBr coincidences that sneak in could be considerable.
111 Int_t nfound = spec.Search(raw_tac_calibrator[j], 1, "", 0.10);
112 if(nfound > number_of_peaks) {
113 std::cout << " " << std::endl;
114 std::cout << "WARNING!!! Tspectrum found " << (nfound - number_of_peaks) << " too many peaks in TAC #" << j << std::endl; //Warning for bad peak found, results should be inspected
115 nfound = number_of_peaks;
116 }
117
118 std::vector<double> vec;
119 vec.resize(nfound); //we make sure we have a vector with the right number of peaks
120 for(int i = 0; i < nfound; i++) { vec.at(i) = spec.GetPositionX()[i]; }
121 std::sort(vec.begin(), vec.end());
122
123 for(int k = 0; k < nfound; k++) {
124 raw_tac_calibrator[j]->GetXaxis()->SetRangeUser((vec.at(k) - 100) / ps_per_chan, (vec.at(k) + 100) / ps_per_chan);
125 vec[k] = raw_tac_calibrator[j]->GetMean();
126 }
127
128 TGraph g;
129 for(int i = 0; i < nfound; i++) {
130 if(vec.at(i) > 10) {
131 g.SetPoint(i, vec.at(i), i * calibrator_period);
132 calibration_hist[j]->SetBinContent(static_cast<int>(vec.at(i) + 1), i * calibrator_period);
133 }
134 }
135 auto* fitfunc = new TF1("fitfunc", "[0] + [1]*x"); //linear polinomy
136
137 g.Fit(fitfunc, "Q");
138 calibration_hist[j]->Fit(fitfunc, "Q");
139
140 auto* gm = new TGainMatch();
141 gm->SetFitFunction(fitfunc);
142 gm->SetChannel(j + first_TAC_channel); //TAC channel, this may need a better implamentation
143
144 gm->GetFitFunction()->SetParameter(0, 0);
145
146 gm->WriteToChannel();
147
148 vec.clear(); //Clear the vector for the next iteration
149 }
150
151 f->cd();
152 TChannel::WriteCalFile(calfile);
153 std::cout << "" << std::endl;
154 std::cout << "--->>> cal file written to: " << calfile << std::endl;
155 std::cout << "" << std::endl;
156 }
157 return 0;
158}
static void WriteCalFile(const std::string &outfilename="")
Definition TChannel.cxx:992
static Int_t ReadCalFromTree(TTree *, Option_t *opt="overwrite")
virtual Float_t GetCharge() const
!
virtual Int_t GetDetector() const
!
virtual Short_t GetMultiplicity() const
Definition TDetector.h:73
Definition TLaBr.h:28
Definition TTAC.h:27
TTACHit * GetTACHit(const int &i) const
Definition TTAC.h:36
int main(int argc, char **argv)