CbmRoot
Loading...
Searching...
No Matches
CbmMuchDigitizerQa.cxx
Go to the documentation of this file.
1/* Copyright (C) 2020-2021 Facility for Antiproton and Ion Research in Europe, Darmstadt
2 SPDX-License-Identifier: GPL-3.0-only
3 Authors: Dominik Smith [committer], Sergey Gorbunov */
4
13
14#include "CbmMuchDigitizerQa.h"
15
16#include "CbmDigiManager.h"
17#include "CbmLink.h"
18#include "CbmMCDataArray.h"
19#include "CbmMCDataManager.h"
20#include "CbmMCTrack.h"
21#include "CbmMatch.h"
22#include "CbmMuchAddress.h"
23#include "CbmMuchDigi.h"
24#include "CbmMuchGeoScheme.h"
25#include "CbmMuchModule.h"
26#include "CbmMuchModuleGem.h"
27#include "CbmMuchPad.h"
28#include "CbmMuchPoint.h"
29#include "CbmMuchPointInfo.h"
30#include "CbmMuchRecoDefs.h"
31#include "CbmMuchStation.h"
32#include "CbmQaCanvas.h"
33#include "CbmTimeSlice.h"
34#include "TClonesArray.h"
35#include "TDatabasePDG.h"
36#include "TF1.h"
37#include "TGraph.h"
38#include "TH1.h"
39#include "TH2.h"
40#include "TParameter.h"
41#include "TString.h"
42#include "TStyle.h"
43
44#include <FairRootManager.h>
45#include <FairSink.h>
46#include <FairTask.h>
47#include <Logger.h>
48
49#include <TAxis.h>
50#include <TCanvas.h>
51#include <TDirectory.h>
52#include <TMath.h>
53#include <TParticlePDG.h>
54#include <TVector2.h>
55
56#include <cmath>
57#include <iostream>
58#include <limits>
59#include <vector>
60
61using std::endl;
62using std::vector;
63
64#define BINNING_CHARGE 100, 0, 300.0
65#define BINNING_LENGTH 100, 0, 2.5
66#define BINNING_CHARGE_LOG 100, 3, 10
67#define BINNING_ENERGY_LOG 100, -0.5, 4.5
68#define BINNING_ENERGY_LOG_EL 100, -0.5, 4.5
69
71
72// -------------------------------------------------------------------------
74 : FairTask(name, verbose)
75 , fOutFolder("MuchDigiQA", "MuchDigitizerQA")
76 , fNevents("nEvents", 0)
80 , fvPadsTotalR()
81 , fvPadsFiredR()
83{
84}
85
86// -------------------------------------------------------------------------
88
89// -------------------------------------------------------------------------
91{
92
93 histFolder = nullptr;
94 fGeoScheme = nullptr;
95 fDigiManager = nullptr;
96 fPoints = nullptr;
97 fDigis = nullptr;
98 fDigiMatches = nullptr;
99 fMCTracks = nullptr;
100 fOutFolder.Clear();
101 fMcPointInfoMap.clear();
102
103 for (uint i = 0; i < fvUsPadsFiredR.size(); i++) {
104 SafeDelete(fvUsPadsFiredR[i]);
105 }
106 for (uint i = 0; i < fvUsPadsFiredXY.size(); i++) {
107 SafeDelete(fvUsPadsFiredXY[i]);
108 }
109 for (uint i = 0; i < fvTrackCharge.size(); i++) {
110 SafeDelete(fvTrackCharge[i]);
111 }
112 for (uint i = 0; i < fvPadsTotalR.size(); i++) {
113 SafeDelete(fvPadsTotalR[i]);
114 }
115 for (uint i = 0; i < fvPadsFiredR.size(); i++) {
116 SafeDelete(fvPadsFiredR[i]);
117 }
118 for (uint i = 0; i < fvPadOccupancyR.size(); i++) {
119 SafeDelete(fvPadOccupancyR[i]);
120 }
121 fvUsPadsFiredR.clear();
122 fvUsPadsFiredXY.clear();
123 fvTrackCharge.clear();
124 fvPadsTotalR.clear();
125 fvPadsFiredR.clear();
126 fvPadOccupancyR.clear();
127
128 SafeDelete(fhTrackLength);
129 SafeDelete(fhTrackLengthPi);
130 SafeDelete(fhTrackLengthPr);
131 SafeDelete(fhTrackLengthEl);
136 SafeDelete(fhTrackChargeVsTrackLength);
140 SafeDelete(fhNpadsVsS);
141 SafeDelete(fCanvCharge);
142 SafeDelete(fCanvStationCharge);
143 SafeDelete(fCanvChargeVsEnergy);
144 SafeDelete(fCanvChargeVsLength);
145 SafeDelete(fCanvTrackLength);
146 SafeDelete(fCanvNpadsVsArea);
147 SafeDelete(fCanvUsPadsFiredXY);
148 SafeDelete(fCanvPadOccupancyR);
149 SafeDelete(fCanvPadsTotalR);
150 SafeDelete(fFitEl);
151 SafeDelete(fFitPi);
152 SafeDelete(fFitPr);
153
154 fNevents.SetVal(0);
155 fNstations = 0;
156 fnPadSizesX = 0;
157 fnPadSizesY = 0;
158 fPadMinLx = 0.;
159 fPadMinLy = 0.;
160 fPadMaxLx = 0.;
161 fPadMaxLy = 0.;
162}
163
164// -------------------------------------------------------------------------
166{
167 DeInit();
168 fMcPointInfoMap.clear();
169 TDirectory* oldDirectory = gDirectory;
170
171 fManager = FairRootManager::Instance();
172 if (!fManager) {
173 LOG(fatal) << "Can not find FairRootManager";
174 return kFATAL;
175 }
176
178 if (!fGeoScheme) {
179 LOG(fatal) << "Can not find Much geo scheme";
180 return kFATAL;
181 }
182
183 fNstations = fGeoScheme->GetNStations();
184 LOG(info) << "CbmMuchDigitizerQa: N Stations = " << fNstations;
185
187 if (!fDigiManager) {
188 LOG(fatal) << "Can not find Much digi manager";
189 return kFATAL;
190 }
191 fDigiManager->Init();
192
193 fMCTracks = nullptr;
194 fPoints = nullptr;
195
196 fMcManager = dynamic_cast<CbmMCDataManager*>(fManager->GetObject("MCDataManager"));
197
198 fTimeSlice = (CbmTimeSlice*) fManager->GetObject("TimeSlice.");
199 if (!fTimeSlice) { LOG(error) << GetName() << ": No time slice found"; }
200
201 if (fMcManager) {
202 // Get MCTrack array
203 fMCTracks = fMcManager->InitBranch("MCTrack");
204
205 // Get StsPoint array
206 fPoints = fMcManager->InitBranch("MuchPoint");
207 }
208
209 if (fMCTracks && fPoints && fDigiManager->IsMatchPresent(ECbmModuleId::kMuch)) {
210 LOG(info) << " CbmMuchDigitizerQa: MC data read.";
211 }
212 else {
213 LOG(info) << " CbmMuchDigitizerQa: No MC data found.";
214 fMCTracks = nullptr;
215 fPoints = nullptr;
216 }
217 histFolder = fOutFolder.AddFolder("hist", "Histogramms");
218 fNevents.SetVal(0);
219 histFolder->Add(&fNevents);
220
221 //fVerbose = 3;
222 InitCanvases();
227 InitFits();
229
230 gDirectory = oldDirectory;
231 return kSUCCESS;
232}
233
234// -------------------------------------------------------------------------
236{
237
238 fPadMinLx = std::numeric_limits<Double_t>::max();
239 fPadMinLy = std::numeric_limits<Double_t>::max();
240 fPadMaxLx = std::numeric_limits<Double_t>::min();
241 fPadMaxLy = std::numeric_limits<Double_t>::min();
242
243 if (fVerbose > 2) {
244 printf("=========================================================\n");
245 printf(" Station Nr.\t| Sectors\t| Channels\t| Pad min size\t\t| Pad max"
246 "length\t \n");
247 printf("---------------------------------------------------------\n");
248 }
249
250 // Int_t nTotSectors = 0; // not used FU 23.03.23
251 Int_t nTotChannels = 0;
252 for (Int_t iStation = 0; iStation < fNstations; iStation++) {
253 Int_t nChannels = 0;
254 Int_t nSectors = 0;
255 Double_t padMinLx = std::numeric_limits<Double_t>::max();
256 Double_t padMinLy = std::numeric_limits<Double_t>::max();
257 Double_t padMaxLx = std::numeric_limits<Double_t>::min();
258 Double_t padMaxLy = std::numeric_limits<Double_t>::min();
259 vector<CbmMuchModule*> modules = fGeoScheme->GetModules(iStation);
260 for (UInt_t im = 0; im < modules.size(); im++) {
261 CbmMuchModule* mod = modules[im];
262 if (!mod) {
263 LOG(fatal) << "module pointer is 0";
264 return -1;
265 }
266 if (mod->GetDetectorType() != 4 && mod->GetDetectorType() != 3) {
267 LOG(fatal) << "unknown detector type " << mod->GetDetectorType();
268 return -1;
269 }
270 CbmMuchModuleGem* module = dynamic_cast<CbmMuchModuleGem*>(mod);
271 if (!module) {
272 LOG(fatal) << "module is not a Gem module";
273 return -1;
274 }
275 nChannels += module->GetNPads();
276 nSectors += module->GetNSectors();
277 vector<CbmMuchPad*> pads = module->GetPads();
278 for (UInt_t ip = 0; ip < pads.size(); ip++) {
279 CbmMuchPad* pad = pads[ip];
280 if (!pad) {
281 LOG(fatal) << "pad pointer is 0";
282 return -1;
283 }
284 if (pad->GetDx() < padMinLx) padMinLx = pad->GetDx();
285 if (pad->GetDy() < padMinLy) padMinLy = pad->GetDy();
286 if (pad->GetDx() > padMaxLx) padMaxLx = pad->GetDx();
287 if (pad->GetDy() > padMaxLy) padMaxLy = pad->GetDy();
288 }
289 }
290
291 if (fPadMinLx > padMinLx) fPadMinLx = padMinLx;
292 if (fPadMinLy > padMinLy) fPadMinLy = padMinLy;
293 if (fPadMaxLx < padMaxLx) fPadMaxLx = padMaxLx;
294 if (fPadMaxLy < padMaxLy) fPadMaxLy = padMaxLy;
295 // nTotSectors += nSectors; // not used FU 23.03.23
296 nTotChannels += nChannels;
297
298 if (fVerbose > 2) {
299 printf("%i\t\t| %i\t\t| %i\t| %5.4fx%5.4f\t\t| %5.4fx%5.4f\n", iStation + 1, nSectors, nChannels, padMinLx,
300 padMinLy, padMaxLx, padMaxLy);
301 printf("%i\t\t| %i\t\t\n", iStation + 1, nChannels);
302 }
303 }
304 if (fVerbose > 2) {
305 printf("-----------------------------------------------------------\n");
306 printf(" Much total channels:\t\t| %i\t\t\n", nTotChannels);
307 printf("===========================================================\n");
308 }
309 return 0;
310}
311
312// -------------------------------------------------------------------------
314{
315
316 /***** charge canvases ****/
317 if (fMCTracks && fPoints) {
318 fCanvCharge = new CbmQaCanvas("cTrackCharge", "Charge collected per track", 2 * 800, 2 * 400);
319 fCanvCharge->Divide2D(3);
320
321 fCanvStationCharge = new CbmQaCanvas("cTrackChargeVsStation", "Track charge per station", 2 * 800, 2 * 400);
323
324 fCanvChargeVsEnergy = new CbmQaCanvas("cTrackChargeVsEnergy", "Track charge vs particle Energy", 2 * 800, 2 * 400);
325 fCanvChargeVsEnergy->Divide2D(4);
326
327 fCanvChargeVsLength = new CbmQaCanvas("cTrackChargeVsLength", "Track charge vs track length", 2 * 800, 2 * 400);
328 fCanvChargeVsLength->Divide2D(4);
329
334 }
335
336 /***** length canvas ****/
337 if (fMCTracks && fPoints) {
338 fCanvTrackLength = new CbmQaCanvas("cTrackLength", "track length", 2 * 800, 2 * 400);
339 fCanvTrackLength->Divide2D(4);
341 }
342
343 /***** pad canvases ****/
344 fCanvUsPadsFiredXY = new CbmQaCanvas("cPadsFiredXY", "Number of pads fired vs XY", 2 * 400, 2 * 400);
346
347 fCanvPadOccupancyR = new CbmQaCanvas("cPadOccupancyR", "Pad occupancy [%] vs radius", 2 * 800, 2 * 400);
349
350 fCanvPadsTotalR = new CbmQaCanvas("cPadsTotalR", "Total pads vs radius", 2 * 800, 2 * 400);
351 fCanvPadsTotalR->Divide2D(fNstations);
352
356
357 /***** pad canvas (MC) ****/
358 if (fMCTracks && fPoints) {
359 fCanvNpadsVsArea = new CbmQaCanvas("cNpadsVsArea", "N pads Vs Area", 2 * 800, 2 * 400);
361 }
362}
363
364// -------------------------------------------------------------------------
366{
367
368 if (!fMCTracks || !fPoints) { return; }
369
371 for (Int_t i = 0; i < fNstations; i++) {
372 fvTrackCharge[i] = new TH1F(Form("hTrackCharge%i", i + 1),
373 Form("Track charge : Station %i; Charge [10^4 e]; Count", i + 1), BINNING_CHARGE);
374 histFolder->Add(fvTrackCharge[i]);
375 }
376
377 fhTrackCharge = new TH1F("hCharge", "Charge distribution from tracks", BINNING_CHARGE);
378 fhTrackCharge->GetXaxis()->SetTitle("Charge [10^{4} electrons]");
379
380 fhTrackChargeLog = new TH1F("hChargeLog", "Charge (log.) distribution from tracks", BINNING_CHARGE_LOG);
381 fhTrackChargeLog->GetXaxis()->SetTitle("Charge [Lg(Number of electrons)]");
382
383 fhTrackChargePr_1GeV_3mm = new TH1F("hChargePr_1GeV_3mm", "Charge for 1 GeV protons", BINNING_CHARGE);
384 fhTrackChargePr_1GeV_3mm->GetXaxis()->SetTitle("Charge [10^{4} electrons]");
385
387 new TH2F("hChargeEnergyLog", "Charge vs energy (log.) for all tracks", BINNING_ENERGY_LOG, BINNING_CHARGE);
388
390 new TH2F("hChargeEnergyLogPi", "Charge vs energy (log.) for pions", BINNING_ENERGY_LOG, BINNING_CHARGE);
391
393 new TH2F("hChargeEnergyLogPr", "Charge vs energy (log.) for protons", BINNING_ENERGY_LOG, BINNING_CHARGE);
394
396 new TH2F("hChargeEnergyLogEl", "Charge vs energy (log.) for electrons", BINNING_ENERGY_LOG_EL, BINNING_CHARGE);
397
399 new TH2F("hChargeTrackLength", "Charge vs length for all tracks", BINNING_LENGTH, BINNING_CHARGE);
400
402 new TH2F("hChargeTrackLengthPi", "Charge vs length for pions", BINNING_LENGTH, BINNING_CHARGE);
403
405 new TH2F("hChargeTrackLengthPr", "Charge vs length for proton", BINNING_LENGTH, BINNING_CHARGE);
406
408 new TH2F("hChargeTrackLengthEl", "Charge vs length for electrons", BINNING_LENGTH, BINNING_CHARGE);
409 std::vector<TH2F*> vChargeHistos;
410 vChargeHistos.push_back(fhTrackChargeVsTrackEnergyLog);
411 vChargeHistos.push_back(fhTrackChargeVsTrackEnergyLogPi);
412 vChargeHistos.push_back(fhTrackChargeVsTrackEnergyLogPr);
413 vChargeHistos.push_back(fhTrackChargeVsTrackEnergyLogEl);
414 vChargeHistos.push_back(fhTrackChargeVsTrackLength);
415 vChargeHistos.push_back(fhTrackChargeVsTrackLengthPi);
416 vChargeHistos.push_back(fhTrackChargeVsTrackLengthPr);
417 vChargeHistos.push_back(fhTrackChargeVsTrackLengthEl);
418
419 for (UInt_t i = 0; i < vChargeHistos.size(); i++) {
420 TH2F* histo = vChargeHistos[i];
421 histo->SetStats(0);
422 histo->GetYaxis()->SetDecimals(kTRUE);
423 histo->GetYaxis()->SetTitleOffset(1.4);
424 histo->GetYaxis()->CenterTitle();
425 histo->GetYaxis()->SetTitle("Charge [10^{4} electrons]");
426 if (i < 4) { histo->GetXaxis()->SetTitle("Lg(E_{kin} [MeV])"); }
427 else {
428 histo->GetXaxis()->SetTitle("Track length [cm]");
429 }
430 histFolder->Add(histo);
431 }
432}
433
434// -------------------------------------------------------------------------
436{
437
438 if (!fMCTracks || !fPoints) { return; }
439
440 fhTrackLength = new TH1F("hTrackLength", "Track length", BINNING_LENGTH);
441
442 fhTrackLengthPi = new TH1F("hTrackLengthPi", "Track length for pions", BINNING_LENGTH);
443
444 fhTrackLengthPr = new TH1F("hTrackLengthPr", "Track length for protons", BINNING_LENGTH);
445
446 fhTrackLengthEl = new TH1F("hTrackLengthEl", "Track length for electrons", BINNING_LENGTH);
447
448 std::vector<TH1F*> vLengthHistos;
449 vLengthHistos.push_back(fhTrackLength);
450 vLengthHistos.push_back(fhTrackLengthPi);
451 vLengthHistos.push_back(fhTrackLengthPr);
452 vLengthHistos.push_back(fhTrackLengthEl);
453
454 for (UInt_t i = 0; i < vLengthHistos.size(); i++) {
455 TH1F* histo = vLengthHistos[i];
456 histo->GetXaxis()->SetTitle("Track length [cm]");
457 histFolder->Add(histo);
458 }
459}
460
461// -------------------------------------------------------------------------
463{
464 // non-MC
465 fvPadsTotalR.resize(fNstations);
468 fvPadsFiredR.resize(fNstations);
470
471 for (Int_t i = 0; i < fNstations; i++) {
472 CbmMuchStation* station = fGeoScheme->GetStation(i);
473 Double_t rMax = station->GetRmax();
474 Double_t rMin = station->GetRmin();
475
476 fvPadsTotalR[i] =
477 new TH1F(Form("hPadsTotal%i", i + 1), Form("Number of pads vs radius: Station %i;Radius [cm]", i + 1), 100,
478 0.6 * rMin, 1.2 * rMax);
479
480 fvUsPadsFiredR[i] =
481 new TH1F(Form("hUsPadsFired%i", i + 1), Form("Number of fired pads vs radius: Station %i;Radius [cm]", i + 1),
482 100, 0.6 * rMin, 1.2 * rMax);
483
484 fvUsPadsFiredXY[i] = new TH2F(Form("hUsPadsFiredXY%i", i + 1), Form("Pads fired XY : Station %i; X; Y", i + 1), 100,
485 -1.2 * rMax, 1.2 * rMax, 100, -1.2 * rMax, 1.2 * rMax);
486
487 fvPadsFiredR[i] =
488 new TH1F(Form("hPadsFired%i", i + 1), Form("Number of fired pads vs radius: Station %i;Radius [cm]", i + 1), 100,
489 0.6 * rMin, 1.2 * rMax);
490
491 fvPadOccupancyR[i] = new TH1F(Form("hOccupancy%i", i + 1),
492 Form("Pad occupancy vs radius: Station %i;Radius [cm];Occupancy, %%", i + 1), 100,
493 0.6 * rMin, 1.2 * rMax);
494
495 histFolder->Add(fvPadsTotalR[i]);
497 histFolder->Add(fvPadsFiredR[i]);
499 }
500
501 // MC below
502 if (fMCTracks && fPoints) {
503 fhNpadsVsS =
504 new TH2F("hNpadsVsS", "Number of fired pads per particle vs average pad area", 50, 0, 5, 15, 0.5, 15.5);
505 fhNpadsVsS->SetYTitle("N fired pads");
506 fhNpadsVsS->SetXTitle("pad area [cm^2]");
508 }
509}
510
511// -------------------------------------------------------------------------
513{
514
515 vector<CbmMuchModule*> modules = fGeoScheme->GetModules();
516 for (vector<CbmMuchModule*>::iterator im = modules.begin(); im != modules.end(); im++) {
517 CbmMuchModule* mod = (*im);
518 if (mod->GetDetectorType() == 4 || mod->GetDetectorType() == 3) { // modified for rpc
519 CbmMuchModuleGem* module = (CbmMuchModuleGem*) mod;
520 vector<CbmMuchPad*> pads = module->GetPads();
521 for (UInt_t ip = 0; ip < pads.size(); ip++) {
522 CbmMuchPad* pad = pads[ip];
524 Double_t x0 = pad->GetX();
525 Double_t y0 = pad->GetY();
526 Double_t r0 = TMath::Sqrt(x0 * x0 + y0 * y0);
527 fvPadsTotalR[stationId]->Fill(r0);
528 }
529 }
530 }
531
532 Double_t errors[100];
533 for (Int_t i = 0; i < 100; i++) {
534 errors[i] = 0;
535 }
536 for (Int_t i = 0; i < fNstations; i++) {
537 //fvPadsTotalR[i]->Sumw2();
538 fvPadsTotalR[i]->SetError(errors);
539 }
540}
541
542// -------------------------------------------------------------------------
544{
545
546 fFitEl = new TF1("fit_el", LandauMPV, -0.5, 4.5, 1);
547 fFitEl->SetParameter(0, 0.511);
548 fFitEl->SetLineWidth(2);
549 fFitEl->SetLineColor(kBlack);
550
551 fFitPi = new TF1("fit_pi", LandauMPV, -0.5, 4.5, 1);
552 fFitPi->SetParameter(0, 139.57);
553 fFitPi->SetLineWidth(2);
554 fFitPi->SetLineColor(kBlack);
555
556 fFitPr = new TF1("fit_pr", LandauMPV, -0.5, 4.5, 1);
557 fFitPr->SetParameter(0, 938.27);
558 fFitPr->SetLineWidth(2);
559 fFitPr->SetLineColor(kBlack);
560}
561
562// -------------------------------------------------------------------------
564{
565 // Get run and runtime database
566
567 // The code currently does not work,
568 // CbmMuchGeoScheme::Instance() must be initialised outside.
569 // - Sergey
570
571 // FairRuntimeDb* db = FairRuntimeDb::instance();
572 // if ( ! db ) Fatal("SetParContainers", "No runtime database");
573 // Get MUCH geometry parameter container
574 // CbmGeoMuchPar *fGeoPar = (CbmGeoMuchPar*)
575 // db->getContainer("CbmGeoMuchPar"); TObjArray *stations =
576 // fGeoPar->GetStations(); cout<<"\n\n SG: stations:
577 // "<<stations->GetEntriesFast()<<endl;
578 // TString geoTag;
579 // CbmSetup::Instance()->GetGeoTag(ECbmModuleId::kMuch, geoTag);
580 // bool mcbmFlag = geoTag.Contains("mcbm", TString::kIgnoreCase);
581 // CbmMuchGeoScheme::Instance()->Init(stations, mcbmFlag);
582}
583
584// -------------------------------------------------------------------------x
586{
587 fNevents.SetVal(fNevents.GetVal() + 1);
588 LOG(debug) << "Event: " << fNevents.GetVal();
589
590 if (CheckConsistency() != 0) { return; }
591
592 TDirectory* oldDirectory = gDirectory;
593
594 OccupancyQa();
595
598
600
601 if (fVerbose > 1) {
604 }
605
606 gDirectory = oldDirectory;
607 return;
608}
609
610
611// -------------------------------------------------------------------------
613{
614 // check consistency of geometry & data
615 if (!fDigiManager) {
616 LOG(error) << "Can not find Much digi manager";
617 return -1;
618 }
619 if (!fGeoScheme) {
620 LOG(error) << "Can not find Much geo scheme";
621 return -1;
622 }
623
624 for (Int_t i = 0; i < fDigiManager->GetNofDigis(ECbmModuleId::kMuch); i++) {
626 if (!digi) {
627 LOG(error) << " Much digi " << i << " out of " << fDigiManager->GetNofDigis(ECbmModuleId::kMuch)
628 << " doesn't exist";
629 return -1;
630 }
631 UInt_t address = digi->GetAddress();
632
633 int ista = CbmMuchAddress::GetStationIndex(address);
634 if (ista < 0 || ista >= fNstations) {
635 LOG(error) << " Much station " << ista << " for adress " << address << " is out of the range";
636 return -1;
637 }
638
639 CbmMuchModule* module = fGeoScheme->GetModuleByDetId(address);
640 if (!module) {
641 LOG(error) << " Much module " << address << " doesn't exist";
642 return -1;
643 }
644 if (module->GetDetectorType() != 4 && module->GetDetectorType() != 3) {
645 LOG(error) << " Much module: unknown detector type " << module->GetDetectorType();
646 return -1;
647 }
648 CbmMuchModuleGem* moduleGem = dynamic_cast<CbmMuchModuleGem*>(module);
649 if (!moduleGem) {
650 LOG(error) << " Unexpected Much module type: module " << address << " is not a Gem module";
651 return -1;
652 }
653 CbmMuchPad* pad = moduleGem->GetPad(address);
654 if (!pad) {
655 LOG(error) << " Much pad for adress " << address << " doesn't exist";
656 return -1;
657 }
658
659 if (fDigiManager->IsMatchPresent(ECbmModuleId::kMuch)) {
660 CbmMatch* match = (CbmMatch*) fDigiManager->GetMatch(ECbmModuleId::kMuch, i);
661 if (!match) {
662 LOG(error) << " Much MC match for digi " << i << " out of " << fDigiManager->GetNofDigis(ECbmModuleId::kMuch)
663 << "doesn't exist";
664 return -1;
665 }
666 }
667 }
668 return 0;
669}
670
671// -------------------------------------------------------------------------
672const CbmMuchPad* CbmMuchDigitizerQa::GetPad(UInt_t address) const
673{
674 // get Much pad from the digi address
675 CbmMuchModuleGem* moduleGem = dynamic_cast<CbmMuchModuleGem*>(fGeoScheme->GetModuleByDetId(address));
676 CbmMuchPad* pad = moduleGem->GetPad(address);
677 return pad;
678}
679
680
681// -------------------------------------------------------------------------
683{
684 // Filling occupancy plots
685 for (Int_t i = 0; i < fDigiManager->GetNofDigis(ECbmModuleId::kMuch); i++) {
687 UInt_t address = digi->GetAddress();
688 int ista = CbmMuchAddress::GetStationIndex(address);
689 const CbmMuchPad* pad = GetPad(address);
690 Double_t x0 = pad->GetX();
691 Double_t y0 = pad->GetY();
692 double r0 = TMath::Sqrt(x0 * x0 + y0 * y0);
693 fvUsPadsFiredR[ista]->Fill(r0);
694 fvUsPadsFiredXY[ista]->Fill(x0, y0);
695 }
696}
697
698// -------------------------------------------------------------------------
700{
701
702 if (!fMCTracks || !fPoints || !fTimeSlice) {
703 LOG(debug) << " CbmMuchDigitizerQa::DigitizerQa(): Found no MC data. Skipping.";
704 return 0;
705 }
706 TVector3 vIn; // in position of the track
707 TVector3 vOut; // out position of the track
708 TVector3 p; // track momentum
709
710 fMcPointInfoMap.clear();
711
712 std::vector<CbmLink> events = fTimeSlice->GetMatch().GetLinks();
713 std::sort(events.begin(), events.end());
714
715 for (uint iLink = 0; iLink < events.size(); iLink++) {
716 CbmLink link = events[iLink];
717 int nMuchPoints = fPoints->Size(link);
718 int nMcTracks = fMCTracks->Size(link);
719 for (Int_t ip = 0; ip < nMuchPoints; ip++) {
720 link.SetIndex(ip);
721 CbmMuchPoint* point = (CbmMuchPoint*) fPoints->Get(link);
722 if (!point) {
723 LOG(error) << " Much MC point " << ip << " out of " << nMuchPoints << " doesn't exist";
724 return -1;
725 }
726
727 Int_t stId = CbmMuchAddress::GetStationIndex(point->GetDetectorID());
728
729 if (stId < 0 || stId > fNstations) {
730 LOG(error) << " Much MC point station " << stId << " is out of the range";
731 return -1;
732 }
733
734 // Check if the point corresponds to a certain MC Track
735 Int_t trackId = point->GetTrackID();
736 if (trackId < 0 || trackId >= nMcTracks) {
737 LOG(error) << " Much MC point track Id " << trackId << " is out of the range";
738 return -1;
739 }
740
741 CbmMCTrack* mcTrack = (CbmMCTrack*) fMCTracks->Get(link.GetFile(), link.GetEntry(), trackId);
742 if (!mcTrack) {
743 LOG(error) << " MC track" << trackId << " is not found";
744 return -1;
745 }
746
747 Int_t pdgCode = mcTrack->GetPdgCode();
748 TParticlePDG* particle = TDatabasePDG::Instance()->GetParticle(pdgCode);
749
750 point->PositionIn(vIn);
751 point->PositionOut(vOut);
752 point->Momentum(p);
753 Double_t length = (vOut - vIn).Mag(); // Track length
754 Double_t kine = 0; // Kinetic energy
755 if (particle) {
756 Double_t mass = particle->Mass();
757 kine = sqrt(p.Mag2() + mass * mass) - mass;
758 }
759
760 // Get mother pdg code
761 Int_t motherPdg = 0;
762 Int_t motherId = mcTrack->GetMotherId();
763 if (motherId >= nMcTracks) {
764 LOG(error) << " MC track mother Id" << trackId << " is out of the range";
765 return -1;
766 }
767 if (motherId >= 0) {
768 CbmMCTrack* motherTrack = (CbmMCTrack*) fMCTracks->Get(link.GetFile(), link.GetEntry(), motherId);
769 if (!motherTrack) {
770 LOG(error) << " MC track" << trackId << " is not found";
771 return -1;
772 }
773 motherPdg = motherTrack->GetPdgCode();
774 }
775 fMcPointInfoMap.insert({link, CbmMuchPointInfo(pdgCode, motherPdg, kine, length, stId)});
776 } // points
777 } // events
778 return 0;
779}
780
781// -------------------------------------------------------------------------
783{
784
785 if (!fMCTracks || !fPoints) {
786 LOG(debug) << " CbmMuchDigitizerQa::FillChargePerPoint()): Found no MC "
787 "data. Skipping.";
788 return;
789 }
790 for (Int_t i = 0; i < fDigiManager->GetNofDigis(ECbmModuleId::kMuch); i++) {
792 const CbmMatch* match = fDigiManager->GetMatch(ECbmModuleId::kMuch, i);
793 if (!match) {
794 LOG(error) << "digi has no match";
795 return;
796 }
797 const CbmMuchPad* pad = GetPad(digi->GetAddress());
798 Double_t area = pad->GetDx() * pad->GetDy();
799 Int_t nofLinks = match->GetNofLinks();
800 for (Int_t pt = 0; pt < nofLinks; pt++) {
801 const CbmLink& link = match->GetLink(pt);
802 Int_t charge = link.GetWeight();
803 CbmMuchPointInfo& info = getPointInfo(link);
804 info.AddCharge(charge);
805 info.AddArea(area);
806 }
807 }
808}
809
810// -------------------------------------------------------------------------
812{
813
814 if (!fMCTracks || !fPoints) {
815 LOG(debug) << " CbmMuchDigitizerQa::FillDigitizerPerformancePlots(): Found "
816 "no MC data. Skipping.";
817 return;
818 }
819 Bool_t verbose = (fVerbose > 2);
820 int iPoint = 0;
821 for (auto it = fMcPointInfoMap.begin(); it != fMcPointInfoMap.end(); it++, ++iPoint) {
822 const CbmMuchPointInfo& info = it->second;
823 if (verbose) {
824 printf("%i", iPoint);
825 info.Print();
826 }
827 Double_t length = info.GetLength();
828 Double_t kine = 1000 * (info.GetKine());
829 Double_t charge = info.GetCharge();
830 Int_t pdg = info.GetPdgCode();
831 if (charge <= 0) continue;
832
833 if (pdg == 22 || // photons
834 pdg == 2112) // neutrons
835 {
836 LOG(error) << "Particle with pdg code " << pdg << " produces signal in Much";
837 }
838
839 // special entry at -0.2 for the particles that are not known for TDataBasePDG
840 Double_t log_kine = (kine > 0) ? TMath::Log10(kine) : -0.2;
841 Double_t log_charge = TMath::Log10(charge);
842 charge = charge / 1.e+4; // measure charge in 10^4 electrons
843
844 Int_t nPads = info.GetNPads();
845 Double_t area = info.GetArea() / nPads;
846 // printf("%f %i\n",TMath::Log2(area),nPads);
847 //fhNpadsVsS->Fill(TMath::Log2(area), nPads);
848 fhNpadsVsS->Fill(area, nPads);
849 fhTrackCharge->Fill(charge);
850 fvTrackCharge[info.GetStationId()]->Fill(charge);
851 fhTrackChargeLog->Fill(log_charge);
852 fhTrackChargeVsTrackEnergyLog->Fill(log_kine, charge);
853 fhTrackChargeVsTrackLength->Fill(length, charge);
854 fhTrackLength->Fill(length);
855
856 if (pdg == 2212) {
857 fhTrackChargeVsTrackEnergyLogPr->Fill(log_kine, charge);
858 fhTrackChargeVsTrackLengthPr->Fill(length, charge);
859 fhTrackLengthPr->Fill(length);
860 }
861 else if (pdg == 211 || pdg == -211) {
862 fhTrackChargeVsTrackEnergyLogPi->Fill(log_kine, charge);
863 fhTrackChargeVsTrackLengthPi->Fill(length, charge);
864 fhTrackLengthPi->Fill(length);
865 }
866 else if (pdg == 11 || pdg == -11) {
867 fhTrackChargeVsTrackEnergyLogEl->Fill(log_kine, charge);
868 fhTrackChargeVsTrackLengthEl->Fill(length, charge);
869 fhTrackLengthEl->Fill(length);
870 }
871 if (pdg == 2212 && length > 0.3 && length < 0.32 && kine > 1000 && kine < 1020)
872 fhTrackChargePr_1GeV_3mm->Fill(charge);
873 }
874}
875
876
877// -------------------------------------------------------------------------
879{
880
881 if (!fMCTracks || !fPoints) { return; }
882
883 for (Int_t i = 0; i < fNstations; i++) {
884 fCanvStationCharge->cd(i + 1);
885 fvTrackCharge[i]->DrawCopy("", "");
886 }
887 fCanvCharge->cd(1);
888 fhTrackCharge->DrawCopy("", "");
889 fCanvCharge->cd(2);
890 fhTrackChargeLog->DrawCopy("", "");
891 fCanvCharge->cd(3);
892 fhTrackChargePr_1GeV_3mm->DrawCopy("", "");
893
894 for (Int_t i = 0; i < 4; i++) {
895 fCanvChargeVsEnergy->cd(i + 1);
896 gPad->Range(0, 0, 200, 200);
897 gPad->SetBottomMargin(0.11);
898 gPad->SetRightMargin(0.14);
899 gPad->SetLeftMargin(0.12);
900 gPad->SetLogz();
901 }
902 fCanvChargeVsEnergy->cd(1);
903 fhTrackChargeVsTrackEnergyLog->DrawCopy("colz", "");
904 fCanvChargeVsEnergy->cd(2);
905 fhTrackChargeVsTrackEnergyLogPi->DrawCopy("colz", "");
906 fFitPi->DrawCopy("same");
907 fCanvChargeVsEnergy->cd(3);
908 fhTrackChargeVsTrackEnergyLogPr->DrawCopy("colz", "");
909 fFitPr->DrawCopy("same");
910 fCanvChargeVsEnergy->cd(4);
911 fhTrackChargeVsTrackEnergyLogEl->DrawCopy("colz", "");
912 fFitEl->DrawCopy("same");
913
914 for (Int_t i = 0; i < 4; i++) {
915 fCanvChargeVsLength->cd(i + 1);
916 gPad->Range(0, 0, 200, 200);
917 gPad->SetBottomMargin(0.11);
918 gPad->SetRightMargin(0.14);
919 gPad->SetLeftMargin(0.12);
920 gPad->SetLogz();
921 }
922 fCanvChargeVsLength->cd(1);
923 fhTrackChargeVsTrackLength->DrawCopy("colz", "");
924 fCanvChargeVsLength->cd(2);
925 fhTrackChargeVsTrackLengthPi->DrawCopy("colz", "");
926 fCanvChargeVsLength->cd(3);
927 fhTrackChargeVsTrackLengthPr->DrawCopy("colz", "");
928 fCanvChargeVsLength->cd(4);
929 fhTrackChargeVsTrackLengthEl->DrawCopy("colz", "");
930}
931
932// -------------------------------------------------------------------------
934{
935 //non-MC
936 for (Int_t i = 0; i < fNstations; i++) {
938 //fvPadsFiredR[i]->Sumw2();
939 fvPadsFiredR[i]->Scale(1. / fNevents.GetVal());
940 fvPadOccupancyR[i]->Divide(fvPadsFiredR[i], fvPadsTotalR[i]);
941 fvPadOccupancyR[i]->Scale(100.);
942
943 fCanvPadOccupancyR->cd(i + 1);
944 fvPadOccupancyR[i]->DrawCopy("", "");
945 fCanvPadsTotalR->cd(i + 1);
946 fvPadsTotalR[i]->DrawCopy("", "");
947 fCanvUsPadsFiredXY->cd(i + 1);
948 fvUsPadsFiredXY[i]->DrawCopy("colz", "");
949 }
950 //MC below
951 if (fMCTracks && fPoints) {
952 fCanvNpadsVsArea->cd();
953 fhNpadsVsS->DrawCopy("colz", "");
954 }
955}
956
957// -------------------------------------------------------------------------
959{
960
961 if (!fMCTracks || !fPoints) { return; }
962
963 for (Int_t i = 0; i < 4; i++) {
964 fCanvTrackLength->cd(i + 1);
965 gPad->SetLogy();
966 gStyle->SetOptStat(1110);
967 }
968 fCanvTrackLength->cd(1);
969 fhTrackLength->DrawCopy("", "");
970 fCanvTrackLength->cd(2);
971 fhTrackLengthPi->DrawCopy("", "");
972 fCanvTrackLength->cd(3);
973 fhTrackLengthPr->DrawCopy("", "");
974 fCanvTrackLength->cd(4);
975 fhTrackLengthEl->DrawCopy("", "");
976}
977
978// -------------------------------------------------------------------------
980{
981
982 if (!fMCTracks || !fTimeSlice) { return; }
983
984 const CbmMatch& match = fTimeSlice->GetMatch();
985 for (int iLink = 0; iLink < match.GetNofLinks(); iLink++) {
986 CbmLink link = match.GetLink(iLink);
987 int nMuchPoints = fPoints->Size(link);
988 for (Int_t ip = 0; ip < nMuchPoints; ip++) {
989 link.SetIndex(ip);
990 CbmMuchPoint* point = (CbmMuchPoint*) fPoints->Get(link);
991 if (!point) {
992 LOG(error) << " Much MC point " << ip << " out of " << nMuchPoints << " doesn't exist";
993 return;
994 }
995 Int_t stId = CbmMuchAddress::GetStationIndex(point->GetDetectorID());
996 if (stId != 0) continue;
997 Int_t layerId = CbmMuchAddress::GetLayerIndex(point->GetDetectorID());
998 if (layerId != 0) continue;
999 printf("point %4i xin=%6.2f yin=%6.2f xout=%6.2f yout=%6.2f zin=%6.2f\n", ip, point->GetXIn(), point->GetYIn(),
1000 point->GetXOut(), point->GetYOut(), point->GetZIn());
1001 }
1002 }
1003}
1004
1005// -------------------------------------------------------------------------
1007{
1008 for (Int_t i = 0; i < fDigiManager->GetNofDigis(ECbmModuleId::kMuch); i++) {
1009 CbmMuchDigi* digi = (CbmMuchDigi*) fDigiManager->Get<CbmMuchDigi>(i);
1010 UInt_t address = digi->GetAddress();
1011 Int_t stId = CbmMuchAddress::GetStationIndex(address);
1012 if (stId != 0) continue;
1013 Int_t layerId = CbmMuchAddress::GetLayerIndex(address);
1014 if (layerId != 0) continue;
1015 CbmMuchModuleGem* module = (CbmMuchModuleGem*) fGeoScheme->GetModuleByDetId(address);
1016 if (!module) continue;
1017 CbmMuchPad* pad = module->GetPad(address);
1018 Double_t x0 = pad->GetX();
1019 Double_t y0 = pad->GetY();
1020 UInt_t charge = digi->GetAdc();
1021 printf("digi %4i x0=%5.1f y0=%5.1f charge=%3i\n", i, x0, y0, charge);
1022 }
1023}
1024
1025// -------------------------------------------------------------------------
1027{
1028 TDirectory* oldDirectory = gDirectory;
1032 gDirectory = oldDirectory;
1033 return fOutFolder;
1034}
1035
1036// -------------------------------------------------------------------------
1038{
1039
1040 if (!FairRootManager::Instance() || !FairRootManager::Instance()->GetSink()) {
1041 LOG(error) << "No sink found";
1042 return;
1043 }
1044 FairSink* sink = FairRootManager::Instance()->GetSink();
1045 sink->WriteObject(&GetQa(), nullptr);
1046}
1047
1048// -------------------------------------------------------------------------
1050{
1051 TCanvas* c = new TCanvas("nMeanVsS", "nMeanVsS", 2 * 800, 2 * 400);
1052 printf("===================================\n");
1053 printf("DigitizerQa:\n");
1054
1055 Double_t nMean[11];
1056 Double_t s[11];
1057 for (Int_t iS = 1; iS <= 10; iS++) {
1058 nMean[iS] = 0;
1059 s[iS] = -5.25 + 0.5 * iS;
1060 Double_t total = 0;
1061 for (Int_t iN = 1; iN <= 10; iN++) {
1062 nMean[iS] += iN * fhNpadsVsS->GetBinContent(iS, iN);
1063 total += fhNpadsVsS->GetBinContent(iS, iN);
1064 }
1065 if (total > 0) nMean[iS] /= total;
1066 printf("%f %f\n", s[iS], nMean[iS]);
1067 }
1068 c->cd();
1069
1070 TGraph* gNvsS = new TGraph(11, s, nMean);
1071 //gNvsS->SetLineColor(2);
1072 //gNvsS->SetLineWidth(4);
1073 gNvsS->SetMarkerColor(4);
1074 gNvsS->SetMarkerSize(1.5);
1075 gNvsS->SetMarkerStyle(21);
1076 gNvsS->SetTitle("nMeanVsS");
1077 gNvsS->GetYaxis()->SetTitle("nMean");
1078 gNvsS->GetYaxis()->SetTitle("nMean");
1079 //gNvsS->DrawClone("ALP");
1080 gNvsS->DrawClone("AP");
1081 fOutFolder.Add(c);
1082}
1083
1084// -------------------------------------------------------------------------
1085Double_t CbmMuchDigitizerQa::LandauMPV(Double_t* lg_x, Double_t* par)
1086{
1087 Double_t gaz_gain_mean = 1.7e+4;
1088 Double_t scale = 1.e+6;
1089 gaz_gain_mean /= scale;
1090 Double_t mass = par[0]; // mass in MeV
1091 Double_t x = TMath::Power(10, lg_x[0]);
1092 return gaz_gain_mean * MPV_n_e(x, mass);
1093}
1094
1095// -------------------------------------------------------------------------
1096Double_t CbmMuchDigitizerQa::MPV_n_e(Double_t Tkin, Double_t mass)
1097{
1098 Double_t logT;
1099 TF1 fPol6("fPol6", "pol6", -5, 10);
1100 if (mass < 0.1) {
1101 logT = log(Tkin * 0.511 / mass);
1102 if (logT > 9.21034) logT = 9.21034;
1103 if (logT < min_logT_e) logT = min_logT_e;
1104 return fPol6.EvalPar(&logT, mpv_e);
1105 }
1106 else if (mass >= 0.1 && mass < 0.2) {
1107 logT = log(Tkin * 105.658 / mass);
1108 if (logT > 9.21034) logT = 9.21034;
1109 if (logT < min_logT_mu) logT = min_logT_mu;
1110 return fPol6.EvalPar(&logT, mpv_mu);
1111 }
1112 else {
1113 logT = log(Tkin * 938.272 / mass);
1114 if (logT > 9.21034) logT = 9.21034;
1115 if (logT < min_logT_p) logT = min_logT_p;
1116 return fPol6.EvalPar(&logT, mpv_p);
1117 }
1118}
@ kMuch
Muon detection system.
Definition CbmDefs.h:50
#define BINNING_ENERGY_LOG
#define BINNING_LENGTH
ClassImp(CbmMuchDigitizerQa)
#define BINNING_CHARGE_LOG
#define BINNING_ENERGY_LOG_EL
#define BINNING_CHARGE
constexpr double min_logT_e
constexpr double mpv_e[]
constexpr double mpv_p[]
constexpr double min_logT_p
constexpr double mpv_mu[]
constexpr double min_logT_mu
Definition of the CbmQaCanvas class.
friend fvec sqrt(const fvec &a)
friend fvec log(const fvec &a)
int Int_t
bool Bool_t
static CbmDigiManager * Instance()
Static instance.
Task class creating and managing CbmMCDataArray objects.
int32_t GetMotherId() const
Definition CbmMCTrack.h:68
int32_t GetPdgCode() const
Definition CbmMCTrack.h:67
const CbmLink & GetLink(int32_t i) const
Definition CbmMatch.h:39
int32_t GetNofLinks() const
Definition CbmMatch.h:42
static int32_t GetLayerIndex(int32_t address)
static int32_t GetStationIndex(int32_t address)
uint16_t GetAdc() const
Definition CbmMuchDigi.h:90
int32_t GetAddress() const
Definition CbmMuchDigi.h:93
virtual void SetParContainers()
CbmTimeSlice * fTimeSlice
TH1F * fhTrackChargeLog
MC point charge.
std::vector< TH1F * > fvUsPadsFiredR
number of processed events
CbmQaCanvas * fCanvStationCharge
CbmQaCanvas * fCanvChargeVsEnergy
static Double_t LandauMPV(Double_t *x, Double_t *par)
CbmMCDataManager * fMcManager
const CbmMuchPad * GetPad(UInt_t address) const
get pad from the digi address
std::vector< TH2F * > fvUsPadsFiredXY
FairRootManager * fManager
folder wich contains histogramms
CbmQaCanvas * fCanvPadOccupancyR
CbmQaCanvas * fCanvPadsTotalR
virtual void Exec(Option_t *option)
std::vector< TH1F * > fvPadsFiredR
CbmMuchGeoScheme * fGeoScheme
CbmMuchPointInfo & getPointInfo(const CbmLink &link)
map point link -> point info
CbmMuchDigitizerQa(const char *name="MuchHitFinderQa", Int_t verbose=1)
TParameter< int > fNevents
output folder with histos and canvases
CbmQaCanvas * fCanvChargeVsLength
CbmQaCanvas * fCanvNpadsVsArea
CbmQaCanvas * fCanvTrackLength
CbmMCDataArray * fMCTracks
TH1F * fhTrackLength
MC point charge for selected protons.
CbmDigiManager * fDigiManager
std::vector< TH1F * > fvPadOccupancyR
static Double_t MPV_n_e(Double_t Tkin, Double_t mass)
std::map< CbmLink, CbmMuchPointInfo > fMcPointInfoMap
CbmMCDataArray * fPoints
TH1F * fhTrackChargePr_1GeV_3mm
MC point charge log scale.
CbmQaCanvas * fCanvUsPadsFiredXY
virtual InitStatus Init()
TClonesArray * fDigiMatches
std::vector< TH1F * > fvPadsTotalR
std::vector< TH1F * > fvTrackCharge
static CbmMuchGeoScheme * Instance()
CbmMuchPad * GetPad(Int_t address)
Int_t GetDetectorType() const
Double_t GetX() const
Definition CbmMuchPad.h:32
Double_t GetDy() const
Definition CbmMuchPad.h:35
Int_t GetAddress() const
Definition CbmMuchPad.h:31
Double_t GetDx() const
Definition CbmMuchPad.h:34
Double_t GetY() const
Definition CbmMuchPad.h:33
Double_t GetArea() const
void Print(Option_t *="") const
Double_t GetLength() const
Int_t GetCharge() const
Int_t GetPdgCode() const
void AddCharge(Int_t charge)
Int_t GetNPads() const
Double_t GetKine() const
Int_t GetStationId() const
void AddArea(Double_t s)
double GetYOut() const
double GetYIn() const
void PositionIn(TVector3 &pos) const
double GetZIn() const
void PositionOut(TVector3 &pos) const
double GetXOut() const
double GetXIn() const
Double_t GetRmin() const
Double_t GetRmax() const
Bookkeeping of time-slice content.