Project
Loading...
Searching...
No Matches
recalibrator.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
16#include "PHOSBase/Geometry.h"
23#include <boost/program_options.hpp>
24#include <boost/timer/progress_display.hpp>
25#include "TChain.h"
26#include "TH1F.h"
27#include "TH2F.h"
28#include <list>
29
30namespace bpo = boost::program_options;
31
32void evalAll(o2::phos::Cluster* clu, std::vector<o2::phos::CluElement>& cluel);
33
34int main(int argc, const char** argv)
35{
36 bpo::variables_map vm;
37 bpo::options_description opt_general("Usage:\n " + std::string(argv[0]) +
38 " <cmds/options>\n"
39 " Tool will recalibrate phos calib digits and produce inv. mass histos\n"
40 "Commands / Options");
41 bpo::options_description opt_hidden("");
42 bpo::options_description opt_all;
43 bpo::positional_options_description opt_pos;
44
45 try {
46 auto add_option = opt_general.add_options();
47 add_option("help,h", "Print this help message");
48 add_option("input,i", bpo::value<std::string>()->default_value("list"), "List of input *.root files");
49 add_option("calib,c", bpo::value<std::string>()->default_value("Calib.root"), "Current calibration");
50 add_option("badmap,b", bpo::value<std::string>()->default_value("BadMap.root"), "Bad channels map or none");
51 add_option("ptmin,p", bpo::value<float>()->default_value(0.5), "Min pT for inv mass analysis");
52 opt_all.add(opt_general).add(opt_hidden);
53 bpo::store(bpo::command_line_parser(argc, argv).options(opt_all).positional(opt_pos).run(), vm);
54
55 if (vm.count("help") || argc == 1) {
56 std::cout << opt_general << std::endl;
57 exit(0);
58 }
59
60 } catch (bpo::error& e) {
61 std::cerr << "ERROR: " << e.what() << std::endl
62 << std::endl;
63 std::cerr << opt_general << std::endl;
64 exit(1);
65 } catch (std::exception& e) {
66 std::cerr << e.what() << ", application will now exit" << std::endl;
67 exit(2);
68 }
69
70 std::string input = "list";
71 if (vm.count("input")) {
72 input = vm["input"].as<std::string>();
73 if (input.empty()) {
74 std::cerr << "Please provide input file list with option --input-files list" << std::endl;
75 exit(1);
76 }
77 }
78
79 std::string calibFile = "Calib.root";
80 if (vm.count("calib")) {
81 calibFile = vm["calib"].as<std::string>();
82 }
83
84 std::string badmapFile;
85 if (vm.count("badmap")) {
86 badmapFile = vm["badmap"].as<std::string>();
87 }
88 float ptMin = 0.5;
89 if (vm.count("ptmin")) {
90 ptMin = vm["ptmin"].as<float>();
91 }
92
93 // Read current calibration
94 o2::phos::CalibParams* calibParams = new o2::phos::CalibParams(1);
95
96 o2::phos::BadChannelsMap* badmap = nullptr;
97 if (!badmapFile.empty() && badmapFile != "none") {
98 TFile* fBadMap = TFile::Open(badmapFile.c_str());
99 if (fBadMap->IsOpen()) {
100 badmap = (o2::phos::BadChannelsMap*)fBadMap->Get("BadMap");
101 } else {
102 badmap = new o2::phos::BadChannelsMap(); // default/empty bad map
103 std::cout << "Using empty bad map" << std::endl;
104 }
105 } else {
106 badmap = new o2::phos::BadChannelsMap(); // default/empty bad map
107 std::cout << "Using empty bad map" << std::endl;
108 }
109
110 // Scan data
111 TChain* chain = new TChain("phosCalibDig");
112 std::ifstream fin(input);
113 if (!fin.is_open()) {
114 std::cerr << "can not open file " << input << std::endl;
115 exit(1);
116 }
117 while (!fin.eof()) {
118 std::string fname;
119 fin >> fname;
120 if (!fname.empty()) {
121 chain->AddFile(fname.c_str());
122 }
123 }
124 fin.close();
125
127 // Histogram init
128 static constexpr int nChannels = 14336 - 1793; // 4 full modules -1/2
129 static constexpr int offset = 1793; // 1/2 full module
130 static constexpr int nMass = 150.;
131 static constexpr float massMax = 0.3;
132 static constexpr int npt = 200;
133 static constexpr float ptMax = 20;
134 TH1F* hNev = new TH1F("hNev", "Number of events", 2, 0., 2.);
135 TH2F* hNonLinRe = new TH2F("hNonLinRe", "Nonlinearity", npt, 0, ptMax, nMass, 0., massMax);
136 TH2F* hNonLinMi = new TH2F("hNonLinMi", "Nonlinearity", npt, 0, ptMax, nMass, 0., massMax);
137 TH2F* hMassPerCellRe = new TH2F("hMassPerCellRe", "MinvRe", nChannels, offset, nChannels + offset, nMass, 0., massMax);
138 TH2F* hMassPerCellMi = new TH2F("hMassPerCellMi", "MinvRe", nChannels, offset, nChannels + offset, nMass, 0., massMax);
139
140 std::vector<uint32_t>* digits = nullptr;
141 chain->SetBranchAddress("PHOSCalib", &digits);
142
144
146 o2::phos::CalibDigit cd = {0};
147 std::vector<o2::phos::CluElement> cluelements;
148 std::vector<o2::phos::Cluster> clusters;
149 std::list<o2::phos::Cluster> mixedClu;
150 o2::phos::Cluster* clu = nullptr;
151 TVector3 globaPos;
152
153 boost::timer::progress_display progress(100);
154 for (int i = 0; i < chain->GetEntries(); i++) {
155 // Print progress
156 if (i % (chain->GetEntries() / 100) == 0) {
157 ++progress;
158 }
159 chain->GetEvent(i);
160 auto d = digits->begin();
161 int bc = -1, orbit = -1, currentCluIndex = -1; // not defined yet
162 while (d != digits->end()) {
163 h.mDataWord = *d;
164 if (h.mMarker == 16383) { // new event marker
165 if (bc > -1) { // process previous event
166
167 buffer.startNewEvent(); // mark stored clusters to be used for Mixing
168 hNev->Fill(1);
169 for (o2::phos::Cluster& c : clusters) {
170 short absId;
171 float x, z;
172 c.getLocalPosition(x, z);
173 o2::phos::Geometry::GetInstance()->relPosToAbsId(c.module(), x, z, absId);
174 o2::phos::Geometry::GetInstance()->local2Global(c.module(), x, z, globaPos);
175 float e = c.getEnergy();
176 double sc = e / globaPos.Mag();
177 TLorentzVector v(sc * globaPos.X(), sc * globaPos.Y(), sc * globaPos.Z(), e);
178 bool isGood = true; // badmap->isChannelGood(absId);
179 for (short ip = buffer.size(); ip--;) {
180 const TLorentzVector& vp = buffer.getEntry(ip);
181 TLorentzVector sum = v + vp;
182 if (buffer.isCurrentEvent(ip)) { // same (real) event
183 if (isGood) {
184 hNonLinRe->Fill(e, sum.M());
185 }
186 if (sum.Pt() > ptMin) {
187 hMassPerCellRe->Fill(absId, sum.M());
188 }
189 } else { // Mixed
190 if (isGood) {
191 hNonLinMi->Fill(e, sum.M());
192 }
193 if (sum.Pt() > ptMin) {
194 hMassPerCellMi->Fill(absId, sum.M());
195 }
196 }
197 }
198 // Add to list ot partners only if cluster is good
199 if (isGood) {
200 buffer.addEntry(v);
201 }
202 }
203 clusters.clear();
204 currentCluIndex = -1;
205 }
206 bc = h.mBC;
207 d++;
208 if (d == digits->end()) {
209 std::cout << "No orbit number, exit" << std::endl;
210 exit(1);
211 }
212 orbit = *d;
213 d++;
214 if (d == digits->end()) { // no digits in event
215 break;
216 }
217 } else { // normal digit
218 if (bc < 0) {
219 std::cout << "Corrupted data: no header" << std::endl;
220 exit(1);
221 }
222 // read new digit
223 cd.mDataWord = *d;
224 d++;
225 short absId = cd.mAddress;
226 short adcCounts = cd.mAdcAmp;
227 float e = calibParams->getGain(absId) * adcCounts;
228 bool isHG = cd.mHgLg;
229 float x = 0., z = 0.;
231 int cluIndex = cd.mCluster;
232 if (cluIndex != currentCluIndex) {
233 if (currentCluIndex >= 0) {
234 clu->setLastCluEl(cluelements.size());
235 evalAll(clu, cluelements);
236 }
237 // start new cluster
238 clusters.emplace_back();
239 clu = &(clusters.back());
240 clu->setFirstCluEl(cluelements.size());
241 currentCluIndex = cluIndex;
242 }
243 cluelements.emplace_back(absId, isHG, e, 0., x, z, -1, 0.);
244 }
245 } // digits loop
246 }
247 TFile fout("histos.root", "recreate");
248 hNev->Write();
249 hNonLinRe->Write();
250 hNonLinMi->Write();
251 hMassPerCellRe->Write();
252 hMassPerCellMi->Write();
253 fout.Close();
254}
255//____________________________________________________________________________
256void evalAll(o2::phos::Cluster* clu, std::vector<o2::phos::CluElement>& cluel)
257{
258 // position, energy, coreEnergy, dispersion, time,
259
260 // Calculates the center of gravity in the local PHOS-module coordinates
261 // Note that correction for non-perpendicular incidence will be applied later
262 // when vertex will be known.
263 float fullEnergy = 0.;
264 uint32_t iFirst = clu->getFirstCluEl(), iLast = clu->getLastCluEl();
265 clu->setModule(o2::phos::Geometry::absIdToModule(cluel[iFirst].absId));
266 float eMin = o2::phos::PHOSSimParams::Instance().mDigitMinEnergy;
267 for (uint32_t i = iFirst; i < iLast; i++) {
268 float ei = cluel[i].energy;
269 if (ei < eMin) {
270 continue;
271 }
272 fullEnergy += ei;
273 }
274 clu->setEnergy(fullEnergy);
275 if (fullEnergy <= 0) {
276 return;
277 }
278 // Calculate time as time in the digit with maximal energy
279 clu->setTime(0.);
280
281 float localPosX = 0., localPosZ = 0.;
282 float wtot = 0.;
283 float invE = 1. / fullEnergy;
284 for (uint32_t i = iFirst; i < iLast; i++) {
285 o2::phos::CluElement& ce = cluel[i];
286 if (ce.energy < eMin) {
287 continue;
288 }
289 float w = std::max(float(0.), o2::phos::PHOSSimParams::Instance().mLogWeight + std::log(ce.energy * invE));
290 localPosX += ce.localX * w;
291 localPosZ += ce.localZ * w;
292 wtot += w;
293 }
294 if (wtot > 0) {
295 wtot = 1. / wtot;
296 localPosX *= wtot;
297 localPosZ *= wtot;
298 }
299 clu->setLocalPosition(localPosX, localPosZ);
300}
uint64_t orbit
Definition RawEventData.h:6
uint64_t bc
Definition RawEventData.h:5
int32_t i
GPUChain * chain
uint32_t c
Definition RawData.h:2
Class for time synchronization of RawReader instances.
CCDB container for bad (masked) channels in PHOS.
float getGain(short cellID) const
Get High Gain energy calibration coefficients.
Definition CalibParams.h:53
Contains PHOS cluster parameters.
Definition Cluster.h:39
static void relPosToAbsId(char module, float x, float z, short &absId)
Definition Geometry.cxx:220
void local2Global(char module, float x, float z, TVector3 &globaPos) const
Definition Geometry.cxx:234
static char absIdToModule(short absId)
Definition Geometry.cxx:151
static void absIdToRelPosInModule(short absId, float &x, float &z)
Definition Geometry.cxx:198
static Geometry * GetInstance()
Definition Geometry.h:63
float sum(float s, o2::dcs::DataPointValue v)
Definition dcs-ccdb.cxx:39
GLint GLenum GLint x
Definition glcorearb.h:403
GLuint buffer
Definition glcorearb.h:655
const GLdouble * v
Definition glcorearb.h:832
GLintptr offset
Definition glcorearb.h:660
GLubyte GLubyte GLubyte GLubyte w
Definition glcorearb.h:852
GLdouble GLdouble GLdouble z
Definition glcorearb.h:843
void evalAll(o2::phos::Cluster *clu, std::vector< o2::phos::CluElement > &cluel)
#define main
constexpr size_t nChannels
Cluster clu
std::vector< Cluster > clusters
std::vector< Digit > digits
uint32_t mHgLg
Bit 24: LG/HG.
uint32_t mCluster
Bits 25-32: index of cluster in event.
uint32_t mAddress
Bits 0 - 13: Hardware address.
uint32_t mAdcAmp
Bits 14 - 23: ADC counts.