correct previous non intended commit, but leaving some new things
[u/mrichter/AliRoot.git] / EMCAL / AliEMCALQADataMakerRec.cxx
CommitLineData
9e47432c 1/**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
3 * *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
6 * *
7 * Permission to use, copy, modify and distribute this software and its *
8 * documentation strictly for non-commercial purposes is hereby granted *
9 * without fee, provided that the above copyright notice appears in all *
10 * copies and that both the copyright notice and this permission notice *
11 * appear in the supporting documentation. The authors make no claims *
12 * about the suitability of this software for any purpose. It is *
13 * provided "as is" without express or implied warranty. *
14 **************************************************************************/
15/*
16Based on the QA code for PHOS written by Yves Schutz July 2007
17
18Authors: J.Klay (Cal Poly) May 2008
19 S. Salur LBL April 2008
20
38986b78 21Created one histogram for QA shifter;-- Yaxian Mao: 11/2009
9e47432c 22The idea:average counts for all the towers should be flat
23Change all existing histograms as experts
9e47432c 24
38986b78 25Change histograms for DQM shifter: -- Yaxian Mao 04/2010
26Calcuate the amplitude ratio from current run and the LED reference, for QAChecker use
27Also calculate the ratio of amplitude from LED Monitor system (current/Reference), to check LED system
28
9e47432c 29*/
30
31// --- ROOT system ---
32#include <TClonesArray.h>
33#include <TFile.h>
34#include <TH1F.h>
35#include <TH1I.h>
36#include <TH2F.h>
38986b78 37#include <TLine.h>
38#include <TText.h>
9e47432c 39#include <TProfile.h>
ecbba853 40#include <TProfile2D.h>
38986b78 41#include <TStyle.h>
9e47432c 42// --- Standard library ---
43
44
45// --- AliRoot header files ---
e03bcdd4 46#include "AliDAQ.h"
9e47432c 47#include "AliESDCaloCluster.h"
48#include "AliESDCaloCells.h"
49#include "AliESDEvent.h"
50#include "AliLog.h"
51#include "AliEMCALQADataMakerRec.h"
52#include "AliQAChecker.h"
53#include "AliEMCALDigit.h"
54#include "AliEMCALRecPoint.h"
55#include "AliEMCALRawUtils.h"
56#include "AliEMCALReconstructor.h"
57#include "AliEMCALRecParam.h"
58#include "AliRawReader.h"
59#include "AliCaloRawStreamV3.h"
60#include "AliEMCALGeoParams.h"
def665cb 61#include "AliRawEventHeaderBase.h"
38986b78 62#include "AliQAManager.h"
63#include "AliCDBEntry.h"
def665cb 64
65#include "AliCaloBunchInfo.h"
66#include "AliCaloFitResults.h"
67#include "AliCaloRawAnalyzerFastFit.h"
68#include "AliCaloRawAnalyzerNN.h"
9f966f11 69//#include "AliCaloRawAnalyzerLMS.h"
70#include "AliCaloRawAnalyzerKStandard.h"
def665cb 71#include "AliCaloRawAnalyzerPeakFinder.h"
72#include "AliCaloRawAnalyzerCrude.h"
3d66fb5e 73#include "AliEMCALGeometry.h"
74#include "AliEMCALTriggerSTURawStream.h"
9e47432c 75
92d9f317 76#include "AliCaloRawAnalyzerFactory.h"
77
ce95bae9 78using namespace std;
79
9e47432c 80ClassImp(AliEMCALQADataMakerRec)
81
82//____________________________________________________________________________
def665cb 83AliEMCALQADataMakerRec::AliEMCALQADataMakerRec(fitAlgorithm fitAlgo) :
84 AliQADataMakerRec(AliQAv1::GetDetName(AliQAv1::kEMCAL), "EMCAL Quality Assurance Data Maker"),
85 fFittingAlgorithm(0),
86 fRawAnalyzer(0),
87 fRawAnalyzerTRU(0),
3d66fb5e 88 fGeom(0),
b8769ad2 89 fSuperModules(12), // FIXME!!! number of SuperModules; 12 for 2012; update default for later runs
def665cb 90 fFirstPedestalSample(0),
91 fLastPedestalSample(3),
92 fFirstPedestalSampleTRU(0),
93 fLastPedestalSampleTRU(3),
94 fMinSignalLG(0),
95 fMaxSignalLG(AliEMCALGeoParams::fgkSampleMax),
96 fMinSignalHG(0),
97 fMaxSignalHG(AliEMCALGeoParams::fgkSampleMax),
98 fMinSignalTRU(0),
99 fMaxSignalTRU(AliEMCALGeoParams::fgkSampleMax),
100 fMinSignalLGLEDMon(0),
101 fMaxSignalLGLEDMon(AliEMCALGeoParams::fgkSampleMax),
102 fMinSignalHGLEDMon(0),
38986b78 103 fMaxSignalHGLEDMon(AliEMCALGeoParams::fgkSampleMax),
104 fCalibRefHistoPro(NULL),
105 fCalibRefHistoH2F(NULL),
106 fLEDMonRefHistoPro(NULL),
107 fHighEmcHistoH2F(NULL)
108// fTextSM(new TText*[fSuperModules]) ,
109// fLineCol(NULL),
110// fLineRow(NULL)
111
def665cb 112{
9e47432c 113 // ctor
def665cb 114 SetFittingAlgorithm(fitAlgo);
92d9f317 115
116 //fRawAnalyzerTRU = new AliCaloRawAnalyzerLMS();
117
9f966f11 118 fRawAnalyzerTRU = ( AliCaloRawAnalyzerKStandard*)AliCaloRawAnalyzerFactory::CreateAnalyzer(kLMS);
92d9f317 119
def665cb 120 fRawAnalyzerTRU->SetFixTau(kTRUE);
121 fRawAnalyzerTRU->SetTau(2.5); // default for TRU shaper
3d66fb5e 122
d7f5c01a 123 fGeom = new AliEMCALGeometry("EMCAL_COMPLETE12SMV1", "EMCAL");
38986b78 124// for (Int_t sm = 0 ; sm < fSuperModules ; sm++){
125// fTextSM[sm] = NULL ;
126// }
9e47432c 127}
128
129//____________________________________________________________________________
130AliEMCALQADataMakerRec::AliEMCALQADataMakerRec(const AliEMCALQADataMakerRec& qadm) :
131 AliQADataMakerRec(),
def665cb 132 fFittingAlgorithm(0),
133 fRawAnalyzer(0),
134 fRawAnalyzerTRU(0),
3d66fb5e 135 fGeom(0),
9e47432c 136 fSuperModules(qadm.GetSuperModules()),
137 fFirstPedestalSample(qadm.GetFirstPedestalSample()),
138 fLastPedestalSample(qadm.GetLastPedestalSample()),
def665cb 139 fFirstPedestalSampleTRU(qadm.GetFirstPedestalSampleTRU()),
140 fLastPedestalSampleTRU(qadm.GetLastPedestalSampleTRU()),
141 fMinSignalLG(qadm.GetMinSignalLG()),
142 fMaxSignalLG(qadm.GetMaxSignalLG()),
9e47432c 143 fMinSignalHG(qadm.GetMinSignalHG()),
def665cb 144 fMaxSignalHG(qadm.GetMaxSignalHG()),
145 fMinSignalTRU(qadm.GetMinSignalTRU()),
146 fMaxSignalTRU(qadm.GetMaxSignalTRU()),
147 fMinSignalLGLEDMon(qadm.GetMinSignalLGLEDMon()),
148 fMaxSignalLGLEDMon(qadm.GetMaxSignalLGLEDMon()),
149 fMinSignalHGLEDMon(qadm.GetMinSignalHGLEDMon()),
38986b78 150 fMaxSignalHGLEDMon(qadm.GetMaxSignalHGLEDMon()),
151 fCalibRefHistoPro(NULL),
152 fCalibRefHistoH2F(NULL),
153 fLEDMonRefHistoPro(NULL),
154 fHighEmcHistoH2F(NULL)
155// fTextSM(new TText*[fSuperModules]) ,
156// fLineCol(NULL),
157// fLineRow(NULL)
9e47432c 158{
159 //copy ctor
160 SetName((const char*)qadm.GetName()) ;
161 SetTitle((const char*)qadm.GetTitle());
def665cb 162 SetFittingAlgorithm(qadm.GetFittingAlgorithm());
92d9f317 163
164 //fRawAnalyzerTRU = new AliCaloRawAnalyzerLMS();
9f966f11 165 fRawAnalyzerTRU = (AliCaloRawAnalyzerKStandard*)AliCaloRawAnalyzerFactory::CreateAnalyzer(kLMS);
def665cb 166 fRawAnalyzerTRU->SetFixTau(kTRUE);
167 fRawAnalyzerTRU->SetTau(2.5); // default for TRU shaper
38986b78 168// for (Int_t sm = 0 ; sm < fSuperModules ; sm++){
169// fTextSM[sm] = qadm.fTextSM[sm] ;
170// }
9e47432c 171}
172
173//__________________________________________________________________
174AliEMCALQADataMakerRec& AliEMCALQADataMakerRec::operator = (const AliEMCALQADataMakerRec& qadm )
175{
176 // Equal operator.
177 this->~AliEMCALQADataMakerRec();
178 new(this) AliEMCALQADataMakerRec(qadm);
38986b78 179// fLineCol = NULL;
180// fLineRow = NULL;
181// for (Int_t sm = 0 ; sm < fSuperModules ; sm++){
182// fTextSM[sm] = qadm.fTextSM[sm] ;
183// }
9e47432c 184 return *this;
185}
186
187//____________________________________________________________________________
188void AliEMCALQADataMakerRec::EndOfDetectorCycle(AliQAv1::TASKINDEX_t task, TObjArray ** list)
189{
190 //Detector specific actions at end of cycle
191
192// if(fCycleCounter)
193// GetRawsData(kNEventsPerTower)->Scale(1./fCycleCounter);
194
195 // do the QA checking
92664bc8 196 ResetEventTrigClasses(); // reset triggers list to select all histos
9e47432c 197 AliQAChecker::Instance()->Run(AliQAv1::kEMCAL, task, list) ;
198}
199
200//____________________________________________________________________________
38986b78 201void AliEMCALQADataMakerRec::GetCalibRefFromOCDB()
202{
203 //Get the reference histogram from OCDB
204 TString sName1("hHighEmcalRawMaxMinusMin") ;
205 TString sName2("hLowLEDMonEmcalRawMaxMinusMin") ;
206 sName1.Prepend(Form("%s_", AliRecoParam::GetEventSpecieName(AliRecoParam::kCalib))) ;
207 sName2.Prepend(Form("%s_", AliRecoParam::GetEventSpecieName(AliRecoParam::kCalib))) ;
208
209 TString refStorage(AliQAv1::GetQARefStorage()) ;
210 if (!refStorage.Contains(AliQAv1::GetLabLocalOCDB()) && !refStorage.Contains(AliQAv1::GetLabAliEnOCDB())) {
211 AliFatal(Form("%s is not a valid location for reference data", refStorage.Data())) ;
212 } else {
213 AliQAManager* manQA = AliQAManager::QAManager(AliQAv1::kRAWS) ;
214 AliQAv1::SetQARefDataDirName(AliRecoParam::kCalib) ;
215 if ( ! manQA->GetLock() ) {
216 manQA->SetDefaultStorage(AliQAv1::GetQARefStorage()) ;
217 manQA->SetSpecificStorage("*", AliQAv1::GetQARefStorage()) ;
218 manQA->SetRun(AliCDBManager::Instance()->GetRun()) ;
219 manQA->SetLock() ;
220 }
221 char * detOCDBDir = Form("%s/%s/%s", GetName(), AliQAv1::GetRefOCDBDirName(), AliQAv1::GetRefDataDirName()) ;
222 AliCDBEntry * entry = manQA->Get(detOCDBDir, manQA->GetRun()) ;
223 if (entry) {
224 TList * listDetQAD =static_cast<TList *>(entry->GetObject()) ;
225 if ( strcmp(listDetQAD->ClassName(), "TList") != 0 ) {
226 AliError(Form("Expected a Tlist and found a %s for detector %s", listDetQAD->ClassName(), GetName())) ;
227 listDetQAD = NULL ;
228 }
229 TObjArray * dirOCDB= NULL ;
230 if ( listDetQAD )
231 dirOCDB = static_cast<TObjArray *>(listDetQAD->FindObject(Form("%s/%s", AliQAv1::GetTaskName(AliQAv1::kRAWS).Data(), AliRecoParam::GetEventSpecieName(AliRecoParam::kCalib)))) ;
232 if (dirOCDB){
233 fCalibRefHistoPro = dynamic_cast<TProfile *>(dirOCDB->FindObject(sName1.Data())) ;
234 fLEDMonRefHistoPro = dynamic_cast<TProfile *>(dirOCDB->FindObject(sName2.Data())) ;
235 }
236 }
237 }
238
239 if(fCalibRefHistoPro && fLEDMonRefHistoPro){
240
241 //Defining histograms binning, each 2D histogram covers all SMs
242 Int_t nSMSectors = fSuperModules / 2; // 2 SMs per sector
243 Int_t nbinsZ = 2*AliEMCALGeoParams::fgkEMCALCols;
244 Int_t nbinsPhi = nSMSectors * AliEMCALGeoParams::fgkEMCALRows;
245
246 if(!fCalibRefHistoH2F)
247 fCalibRefHistoH2F = new TH2F("hCalibRefHisto", "hCalibRefHisto", nbinsZ, -0.5, nbinsZ - 0.5, nbinsPhi, -0.5, nbinsPhi -0.5);
248 ConvertProfile2H(fCalibRefHistoPro,fCalibRefHistoH2F) ;
249 } else {
250 AliFatal(Form("No reference object with name %s or %s found", sName1.Data(), sName2.Data())) ;
251 }
252}
253//____________________________________________________________________________
9e47432c 254void AliEMCALQADataMakerRec::InitESDs()
255{
256 //Create histograms to controll ESD
257 const Bool_t expert = kTRUE ;
258 const Bool_t image = kTRUE ;
259
260 TH1F * h1 = new TH1F("hESDCaloClusterE", "ESDs CaloCluster energy in EMCAL;Energy [GeV];Counts", 200, 0., 100.) ;
261 h1->Sumw2() ;
262 Add2ESDsList(h1, kESDCaloClusE, !expert, image) ;
263
264 TH1I * h2 = new TH1I("hESDCaloClusterM", "ESDs CaloCluster multiplicity in EMCAL;# of Clusters;Entries", 100, 0, 100) ;
265 h2->Sumw2() ;
266 Add2ESDsList(h2, kESDCaloClusM, !expert, image) ;
267
268 TH1F * h3 = new TH1F("hESDCaloCellA", "ESDs CaloCell amplitude in EMCAL;Energy [GeV];Counts", 500, 0., 50.) ;
269 h3->Sumw2() ;
270 Add2ESDsList(h3, kESDCaloCellA, !expert, image) ;
271
272 TH1I * h4 = new TH1I("hESDCaloCellM", "ESDs CaloCell multiplicity in EMCAL;# of Clusters;Entries", 200, 0, 1000) ;
273 h4->Sumw2() ;
274 Add2ESDsList(h4, kESDCaloCellM, !expert, image) ;
92664bc8 275 //
276 ClonePerTrigClass(AliQAv1::kESDS); // this should be the last line
9e47432c 277}
278
279//____________________________________________________________________________
280void AliEMCALQADataMakerRec::InitDigits()
281{
282 // create Digits histograms in Digits subdir
283 const Bool_t expert = kTRUE ;
284 const Bool_t image = kTRUE ;
285
286 TH1I * h0 = new TH1I("hEmcalDigits", "Digits amplitude distribution in EMCAL;Amplitude [ADC counts];Counts", 500, 0, 500) ;
287 h0->Sumw2() ;
288 Add2DigitsList(h0, 0, !expert, image) ;
289 TH1I * h1 = new TH1I("hEmcalDigitsMul", "Digits multiplicity distribution in EMCAL;# of Digits;Entries", 200, 0, 2000) ;
290 h1->Sumw2() ;
291 Add2DigitsList(h1, 1, !expert, image) ;
92664bc8 292 //
293 ClonePerTrigClass(AliQAv1::kDIGITS); // this should be the last line
9e47432c 294}
295
296//____________________________________________________________________________
297void AliEMCALQADataMakerRec::InitRecPoints()
298{
38986b78 299 // create Reconstructed PoInt_ts histograms in RecPoints subdir
9e47432c 300 const Bool_t expert = kTRUE ;
301 const Bool_t image = kTRUE ;
302
303 TH1F* h0 = new TH1F("hEMCALRpE","EMCAL RecPoint energies;Energy [GeV];Counts",200, 0.,20.); //GeV
304 h0->Sumw2();
305 Add2RecPointsList(h0,kRecPE, !expert, image);
306
307 TH1I* h1 = new TH1I("hEMCALRpM","EMCAL RecPoint multiplicities;# of Clusters;Entries",100,0,100);
308 h1->Sumw2();
309 Add2RecPointsList(h1,kRecPM, !expert, image);
310
311 TH1I* h2 = new TH1I("hEMCALRpDigM","EMCAL RecPoint Digit Multiplicities;# of Digits;Entries",20,0,20);
312 h2->Sumw2();
313 Add2RecPointsList(h2,kRecPDigM, !expert, image);
92664bc8 314 //
315 ClonePerTrigClass(AliQAv1::kRECPOINTS); // this should be the last line
9e47432c 316}
317
318//____________________________________________________________________________
319void AliEMCALQADataMakerRec::InitRaws()
320{
321 // create Raws histograms in Raws subdir
1557b01a 322 const Bool_t expert = kTRUE ;
323 const Bool_t saveCorr = kTRUE ;
324 const Bool_t image = kTRUE ;
325 const Option_t *profileOption = "s";
9e47432c 326
38986b78 327 Int_t nTowersPerSM = AliEMCALGeoParams::fgkEMCALRows * AliEMCALGeoParams::fgkEMCALCols; // number of towers in a SuperModule; 24x48
328 Int_t nTot = fSuperModules * nTowersPerSM; // max number of towers in all SuperModules
922017a7 329
1557b01a 330 //Defining histograms binning, each 2D histogram covers all SMs
331 Int_t nSMSectors = fSuperModules / 2; // 2 SMs per sector
332 Int_t nbinsZ = 2*AliEMCALGeoParams::fgkEMCALCols;
333 Int_t nbinsPhi = nSMSectors * AliEMCALGeoParams::fgkEMCALRows;
ecbba853 334
335 Int_t nTRUCols = 2*AliEMCALGeoParams::fgkEMCALTRUCols; //total TRU columns for 2D TRU histos
336 Int_t nTRURows = nSMSectors*AliEMCALGeoParams::fgkEMCALTRUsPerSM*AliEMCALGeoParams::fgkEMCALTRURows; //total TRU rows for 2D TRU histos
38986b78 337 // counter info: number of channels per event (bins are SM index)
9e47432c 338 TProfile * h0 = new TProfile("hLowEmcalSupermodules", "Low Gain EMC: # of towers vs SuperMod;SM Id;# of towers",
1557b01a 339 fSuperModules, -0.5, fSuperModules-0.5, profileOption) ;
00957c37 340 Add2RawsList(h0, kNsmodLG, expert, !image, !saveCorr) ;
9e47432c 341 TProfile * h1 = new TProfile("hHighEmcalSupermodules", "High Gain EMC: # of towers vs SuperMod;SM Id;# of towers",
1557b01a 342 fSuperModules, -0.5, fSuperModules-0.5, profileOption) ;
00957c37 343 Add2RawsList(h1, kNsmodHG, expert, !image, !saveCorr) ;
9e47432c 344
345 // where did max sample occur? (bins are towers)
346 TProfile * h2 = new TProfile("hLowEmcalRawtime", "Low Gain EMC: Time at Max vs towerId;Tower Id;Time [ticks]",
1557b01a 347 nTot, -0.5, nTot-0.5, profileOption) ;
00957c37 348 Add2RawsList(h2, kTimeLG, expert, !image, !saveCorr) ;
9e47432c 349 TProfile * h3 = new TProfile("hHighEmcalRawtime", "High Gain EMC: Time at Max vs towerId;Tower Id;Time [ticks]",
1557b01a 350 nTot, -0.5, nTot-0.5, profileOption) ;
00957c37 351 Add2RawsList(h3, kTimeHG, expert, !image, !saveCorr) ;
9e47432c 352
353 // how much above pedestal was the max sample? (bins are towers)
354 TProfile * h4 = new TProfile("hLowEmcalRawMaxMinusMin", "Low Gain EMC: Max - Min vs towerId;Tower Id;Max-Min [ADC counts]",
1557b01a 355 nTot, -0.5, nTot-0.5, profileOption) ;
e4a4c62f 356 Add2RawsList(h4, kSigLG, expert, !image, !saveCorr) ;
9e47432c 357 TProfile * h5 = new TProfile("hHighEmcalRawMaxMinusMin", "High Gain EMC: Max - Min vs towerId;Tower Id;Max-Min [ADC counts]",
1557b01a 358 nTot, -0.5, nTot-0.5, profileOption) ;
e4a4c62f 359 Add2RawsList(h5, kSigHG, expert, !image, !saveCorr) ;
9e47432c 360
361 // total counter: channels per event
362 TH1I * h6 = new TH1I("hLowNtot", "Low Gain EMC: Total Number of found towers;# of Towers;Counts", 200, 0, nTot) ;
363 h6->Sumw2() ;
00957c37 364 Add2RawsList(h6, kNtotLG, expert, !image, !saveCorr) ;
9e47432c 365 TH1I * h7 = new TH1I("hHighNtot", "High Gain EMC: Total Number of found towers;# of Towers;Counts", 200,0, nTot) ;
366 h7->Sumw2() ;
00957c37 367 Add2RawsList(h7, kNtotHG, expert, !image, !saveCorr) ;
9e47432c 368
369 // pedestal (bins are towers)
370 TProfile * h8 = new TProfile("hLowEmcalRawPed", "Low Gain EMC: Pedestal vs towerId;Tower Id;Pedestal [ADC counts]",
1557b01a 371 nTot, -0.5, nTot-0.5, profileOption) ;
00957c37 372 Add2RawsList(h8, kPedLG, expert, !image, !saveCorr) ;
9e47432c 373 TProfile * h9 = new TProfile("hHighEmcalRawPed", "High Gain EMC: Pedestal vs towerId;Tower Id;Pedestal [ADC counts]",
1557b01a 374 nTot, -0.5, nTot-0.5, profileOption) ;
00957c37 375 Add2RawsList(h9, kPedHG, expert, !image, !saveCorr) ;
9e47432c 376
38986b78 377
9e47432c 378 // now repeat the same for TRU and LEDMon data
38986b78 379 Int_t nTot2x2 = fSuperModules * AliEMCALGeoParams::fgkEMCALTRUsPerSM * AliEMCALGeoParams::fgkEMCAL2x2PerTRU; // max number of TRU channels for all SuperModules
9e47432c 380
381 // counter info: number of channels per event (bins are SM index)
382 TProfile * hT0 = new TProfile("hTRUEmcalSupermodules", "TRU EMC: # of TRU channels vs SuperMod;SM Id;# of TRU channels",
1557b01a 383 fSuperModules, -0.5, fSuperModules-0.5, profileOption) ;
00957c37 384 Add2RawsList(hT0, kNsmodTRU, expert, !image, !saveCorr) ;
9e47432c 385
9e47432c 386 // how much above pedestal was the max sample? (bins are TRU channels)
e4a4c62f 387 TProfile * hT1 = new TProfile("hTRUEmcalRawMaxMinusMin", "TRU EMC: Max - Min vs 2x2Id;2x2 Id;Max-Min [ADC counts]",
1557b01a 388 nTot2x2, -0.5, nTot2x2-0.5, profileOption) ;
e4a4c62f 389 Add2RawsList(hT1, kSigTRU, expert, !image, !saveCorr) ;
9e47432c 390
391 // total counter: channels per event
e4a4c62f 392 TH1I * hT2 = new TH1I("hTRUNtot", "TRU EMC: Total Number of found TRU channels;# of TRU Channels;Counts", 200, 0, nTot2x2) ;
393 hT2->Sumw2() ;
394 Add2RawsList(hT2, kNtotTRU, expert, !image, !saveCorr) ;
9e47432c 395
5c6517c3 396 // L0 trigger hits: # of hits (bins are TRU channels)
ecbba853 397 TH2I * hT3 = new TH2I("hTRUEmcalL0hits", "L0 trigger hits: Total number of 2x2 L0 generated", nTRUCols, -0.5, nTRUCols - 0.5, nTRURows, -0.5, nTRURows-0.5);
398 hT3->SetOption("COLZ");
399 //hT3->Sumw2();
a2e583d8 400 Add2RawsList(hT3, kNL0TRU, expert, image, !saveCorr);
5c6517c3 401
402 // L0 trigger hits: average time (bins are TRU channels)
ecbba853 403 TProfile2D * hT4 = new TProfile2D("hTRUEmcalL0hitsAvgTime", "L0 trigger hits: average time bin", nTRUCols, -0.5, nTRUCols - 0.5, nTRURows, -0.5, nTRURows-0.5, profileOption);
404 hT4->SetOption("COLZ");
a2e583d8 405 Add2RawsList(hT4, kTimeL0TRU, expert, image, !saveCorr);
e4a4c62f 406
407 // L0 trigger hits: first in the event (bins are TRU channels)
408 TH1I * hT5 = new TH1I("hTRUEmcalL0hitsFirst", "L0 trigger hits: First hit in the event", nTot2x2, -0.5, nTot2x2);
409 hT5->Sumw2();
410 Add2RawsList(hT5, kNL0FirstTRU, expert, !image, !saveCorr);
411
412 // L0 trigger hits: average time of first hit in the event (bins are TRU channels)
413 TProfile * hT6 = new TProfile("hTRUEmcalL0hitsFirstAvgTime", "L0 trigger hits: average time of first hit", nTot2x2, -0.5, nTot2x2, profileOption);
414 Add2RawsList(hT6, kTimeL0FirstTRU, expert, !image, !saveCorr);
5c6517c3 415
9e47432c 416 // and also LED Mon..
417 // LEDMon has both high and low gain channels, just as regular FEE/towers
38986b78 418 Int_t nTotLEDMon = fSuperModules * AliEMCALGeoParams::fgkEMCALLEDRefs; // max number of LEDMon channels for all SuperModules
9e47432c 419
420 // counter info: number of channels per event (bins are SM index)
421 TProfile * hL0 = new TProfile("hLowLEDMonEmcalSupermodules", "LowLEDMon Gain EMC: # of strips vs SuperMod;SM Id;# of strips",
1557b01a 422 fSuperModules, -0.5, fSuperModules-0.5, profileOption) ;
00957c37 423 Add2RawsList(hL0, kNsmodLGLEDMon, expert, !image, !saveCorr) ;
9e47432c 424 TProfile * hL1 = new TProfile("hHighLEDMonEmcalSupermodules", "HighLEDMon Gain EMC: # of strips vs SuperMod;SM Id;# of strips",
1557b01a 425 fSuperModules, -0.5, fSuperModules-0.5, profileOption) ;
00957c37 426 Add2RawsList(hL1, kNsmodHGLEDMon, expert, !image, !saveCorr) ;
9e47432c 427
428 // where did max sample occur? (bins are strips)
429 TProfile * hL2 = new TProfile("hLowLEDMonEmcalRawtime", "LowLEDMon Gain EMC: Time at Max vs stripId;Strip Id;Time [ticks]",
1557b01a 430 nTotLEDMon, -0.5, nTotLEDMon-0.5, profileOption) ;
00957c37 431 Add2RawsList(hL2, kTimeLGLEDMon, expert, !image, !saveCorr) ;
9e47432c 432 TProfile * hL3 = new TProfile("hHighLEDMonEmcalRawtime", "HighLEDMon Gain EMC: Time at Max vs stripId;Strip Id;Time [ticks]",
1557b01a 433 nTotLEDMon, -0.5, nTotLEDMon-0.5, profileOption) ;
00957c37 434 Add2RawsList(hL3, kTimeHGLEDMon, expert, !image, !saveCorr) ;
9e47432c 435
436 // how much above pedestal was the max sample? (bins are strips)
437 TProfile * hL4 = new TProfile("hLowLEDMonEmcalRawMaxMinusMin", "LowLEDMon Gain EMC: Max - Min vs stripId;Strip Id;Max-Min [ADC counts]",
1557b01a 438 nTotLEDMon, -0.5, nTotLEDMon-0.5, profileOption) ;
00957c37 439 Add2RawsList(hL4, kSigLGLEDMon, expert, !image, !saveCorr) ;
9e47432c 440 TProfile * hL5 = new TProfile("hHighLEDMonEmcalRawMaxMinusMin", "HighLEDMon Gain EMC: Max - Min vs stripId;Strip Id;Max-Min [ADC counts]",
1557b01a 441 nTotLEDMon, -0.5, nTotLEDMon-0.5, profileOption) ;
00957c37 442 Add2RawsList(hL5, kSigHGLEDMon, expert, !image, !saveCorr) ;
38986b78 443
444 // total counter: channels per event
9e47432c 445 TH1I * hL6 = new TH1I("hLowLEDMonNtot", "LowLEDMon Gain EMC: Total Number of found strips;# of Strips;Counts", 200, 0, nTotLEDMon) ;
446 hL6->Sumw2() ;
00957c37 447 Add2RawsList(hL6, kNtotLGLEDMon, expert, !image, !saveCorr) ;
9e47432c 448 TH1I * hL7 = new TH1I("hHighLEDMonNtot", "HighLEDMon Gain EMC: Total Number of found strips;# of Strips;Counts", 200,0, nTotLEDMon) ;
449 hL7->Sumw2() ;
00957c37 450 Add2RawsList(hL7, kNtotHGLEDMon, expert, !image, !saveCorr) ;
9e47432c 451
452 // pedestal (bins are strips)
453 TProfile * hL8 = new TProfile("hLowLEDMonEmcalRawPed", "LowLEDMon Gain EMC: Pedestal vs stripId;Strip Id;Pedestal [ADC counts]",
1557b01a 454 nTotLEDMon, -0.5, nTotLEDMon-0.5, profileOption) ;
00957c37 455 Add2RawsList(hL8, kPedLGLEDMon, expert, !image, !saveCorr) ;
9e47432c 456 TProfile * hL9 = new TProfile("hHighLEDMonEmcalRawPed", "HighLEDMon Gain EMC: Pedestal vs stripId;Strip Id;Pedestal [ADC counts]",
1557b01a 457 nTotLEDMon, -0.5, nTotLEDMon-0.5, profileOption) ;
00957c37 458 Add2RawsList(hL9, kPedHGLEDMon, expert, !image, !saveCorr) ;
38986b78 459
e4a4c62f 460 //temp 2D amplitude histogram for the current run
461 fHighEmcHistoH2F = new TH2F("h2DHighEC2", "High Gain EMC:Max - Min [ADC counts]", nbinsZ, -0.5 , nbinsZ-0.5, nbinsPhi, -0.5, nbinsPhi-0.5);
462 fHighEmcHistoH2F->SetDirectory(0) ; // this histo must be memory resident
463 //add ratio histograms: to comapre the current run with the reference data
464 TH2F * h15 = new TH2F("h2DRatioAmp", "High Gain Ratio to Reference:Amplitude_{current run}/Amplitude_{reference run}", nbinsZ, -0.5 , nbinsZ-0.5,
465 nbinsPhi, -0.5, nbinsPhi-0.5);
466 //settings for display in amore
467 h15->SetTitle("Amplitude_{current run}/Amplitude_{reference run}");
468 h15->SetMaximum(2.0);
469 h15->SetMinimum(0.1);
470 h15->SetOption("COLZ");
471 gStyle->SetOptStat(0);
472 Int_t color[] = {4,3,2} ;
473 gStyle->SetPalette(3,color);
474 h15->GetZaxis()->SetNdivisions(3);
475 h15->UseCurrentStyle();
476 h15->SetDirectory(0);
a2e583d8 477 Add2RawsList(h15, k2DRatioAmp, expert, image, !saveCorr) ;
e4a4c62f 478
479 TH1F * h16 = new TH1F("hRatioDist", "Amplitude_{current run}/Amplitude_{reference run} ratio distribution", nTot, 0., 2.);
3211986c 480 // h16->SetMinimum(0.1);
481 // h16->SetMaximum(100.);
e4a4c62f 482 gStyle->SetOptStat(0);
483 h16->UseCurrentStyle();
484 h16->SetDirectory(0);
485 Add2RawsList(h16, kRatioDist, !expert, image, !saveCorr) ;
486
38986b78 487 //add two histograms for shifter from the LED monitor system: comapre LED monitor with the reference run
488 //to be used for decision whether we need to change reference data
489 TH1F * hL10 = new TH1F("hMaxMinusMinLEDMonRatio", "LEDMon amplitude, Ratio to reference run", nTotLEDMon, -0.5, nTotLEDMon-0.5) ;
38986b78 490 //settings for display in amore
491 hL10->SetTitle("Amplitude_{LEDMon current}/Amplitude_{LEDMon reference}");
00957c37 492 hL10->SetMaximum(2.0);
493 hL10->SetMinimum(0.1);
494 gStyle->SetOptStat(0);
495 hL10->UseCurrentStyle();
496 hL10->SetDirectory(0);
38986b78 497// hL10->SetOption("E");
a2e583d8 498 Add2RawsList(hL10, kLEDMonRatio, expert, image, !saveCorr) ;
00957c37 499
922017a7 500 TH1F * hL11 = new TH1F("hMaxMinusMinLEDMonRatioDist", "LEDMon amplitude, Ratio distribution", nTotLEDMon, 0, 2);
3211986c 501 // hL11->SetMinimum(0.1) ;
00957c37 502 gStyle->SetOptStat(0);
503 hL11->UseCurrentStyle();
504 hL11->SetDirectory(0);
a2e583d8 505 Add2RawsList(hL11, kLEDMonRatioDist, expert, image, !saveCorr) ;
38986b78 506
922017a7 507 GetCalibRefFromOCDB();
3d66fb5e 508
509
510 //STU histgrams
511
512 //histos
513 Int_t nSTUCols = AliEMCALGeoParams::fgkEMCALSTUCols;
514 Int_t nSTURows = AliEMCALGeoParams::fgkEMCALSTURows;
515// kAmpL1, kGL1, kJL1,
516// kGL1V0, kJL1V0, kSTUTRU
517
518 TProfile2D *hS0 = new TProfile2D("hL1Amp", "Mean STU signal per Row and Column", nSTUCols, -0.5, nSTUCols-0.5, nSTURows, -0.5, nSTURows-0.5);
519 Add2RawsList(hS0, kAmpL1, expert, !image, !saveCorr) ;
520
a57708c8 521 TH2F *hS1 = new TH2F("hL1Gamma", "L1 Gamma patch position (FastOR top-left)", nSTUCols, -0.50, nSTUCols-0.5, nSTURows + 5, -0.5, nSTURows-0.5 + 5); //+5 for better visible error box
a2e583d8 522 Add2RawsList(hS1, kGL1, !expert, image, !saveCorr) ;
3d66fb5e 523
524 TH2F *hS2 = new TH2F("hL1Jet", "L1 Jet patch position (FastOR top-left)", 12, -0.5, nSTUCols-0.5, 16, 0, nSTURows-0.5);
a2e583d8 525 Add2RawsList(hS2, kJL1, !expert, image, !saveCorr) ;
3d66fb5e 526
527 TH2I *hS3 = new TH2I("hL1GV0", "L1 Gamma patch amplitude versus V0 signal", 500, 0, 50000, 1500, 0, 1500);
3b0945ff 528 Add2RawsList(hS3, kGL1V0, expert, image, !saveCorr) ;
3d66fb5e 529
530 TH2I *hS4 = new TH2I("hL1JV0", "L1 Jet patch amplitude versus V0 signal", 500, 0, 50000, 1000, 0, 1000);
531 Add2RawsList(hS4, kJL1V0, expert, !image, !saveCorr) ;
532
533 TH1I *hS5 = new TH1I("hFrameR","Link between TRU and STU", 32, 0, 32);
a2e583d8 534 Add2RawsList(hS5, kSTUTRU, !expert, image, !saveCorr) ;
3d66fb5e 535
180c431b 536 hS0->SetOption("COLZ");
537 hS1->SetOption("COLZ");
538 hS2->SetOption("COLZ");
539 hS3->SetOption("COLZ");
540 hS4->SetOption("COLZ");
3d66fb5e 541
92664bc8 542 //
543 ClonePerTrigClass(AliQAv1::kRAWS); // this should be the last line
9e47432c 544}
545
546//____________________________________________________________________________
547void AliEMCALQADataMakerRec::MakeESDs(AliESDEvent * esd)
548{
549 // make QA data from ESDs
550
551 Int_t nTot = 0 ;
552 for ( Int_t index = 0; index < esd->GetNumberOfCaloClusters() ; index++ ) {
553 AliESDCaloCluster * clu = esd->GetCaloCluster(index) ;
554 if( clu->IsEMCAL() ) {
92664bc8 555 FillESDsData(kESDCaloClusE,clu->E()) ;
9e47432c 556 nTot++ ;
557 }
558 }
92664bc8 559 FillESDsData(kESDCaloClusM,nTot) ;
9e47432c 560
561 //fill calo cells
562 AliESDCaloCells* cells = esd->GetEMCALCells();
92664bc8 563 FillESDsData(kESDCaloCellM,cells->GetNumberOfCells()) ;
9e47432c 564
565 for ( Int_t index = 0; index < cells->GetNumberOfCells() ; index++ ) {
92664bc8 566 FillESDsData(kESDCaloCellA,cells->GetAmplitude(index)) ;
9e47432c 567 }
92664bc8 568 //
569 IncEvCountCycleESDs();
570 IncEvCountTotalESDs();
9e47432c 571}
572
573//____________________________________________________________________________
574void AliEMCALQADataMakerRec::MakeRaws(AliRawReader* rawReader)
575{
92664bc8 576 // Check that all the reference histograms exist before we try to use them - otherwise call InitRaws
577 // RS: Attention: the counters are increments after custom modification of eventSpecie
922017a7 578 if (!fCalibRefHistoPro || !fCalibRefHistoH2F || !fLEDMonRefHistoPro || !fHighEmcHistoH2F) {
579 InitRaws();
580 }
581
e03bcdd4 582 // make sure EMCal was readout during the event
583 Int_t emcID = AliDAQ::DetectorID("EMCAL"); // bit 18..
7b2c20bb 584 const UInt_t *detPattern = rawReader->GetDetectorPattern();
e03bcdd4 585 UInt_t emcInReadout = ( ((1 << emcID) & detPattern[0]) >> emcID);
38986b78 586 if (! emcInReadout) return; // no poInt_t in looking at this event, if no EMCal data
e03bcdd4 587
def665cb 588 // setup
9e47432c 589 rawReader->Reset() ;
590 AliCaloRawStreamV3 in(rawReader,"EMCAL");
30aa89b0 591 rawReader->Select("EMCAL", 0, AliEMCALGeoParams::fgkLastAltroDDL) ; //select EMCAL DDL's
9e47432c 592
5c6517c3 593 AliRecoParam::EventSpecie_t saveSpecie = fEventSpecie ;
def665cb 594 if (rawReader->GetType() == AliRawEventHeaderBase::kCalibrationEvent) {
e4a4c62f 595 SetEventSpecie(AliRecoParam::kCalib) ;
def665cb 596 }
ecbba853 597
38986b78 598 const Int_t nTowersPerSM = AliEMCALGeoParams::fgkEMCALRows * AliEMCALGeoParams::fgkEMCALCols; // number of towers in a SuperModule; 24x48
599 const Int_t nRows = AliEMCALGeoParams::fgkEMCALRows; // number of rows per SuperModule
600 const Int_t nStripsPerSM = AliEMCALGeoParams::fgkEMCALLEDRefs; // number of strips per SuperModule
601 const Int_t n2x2PerSM = AliEMCALGeoParams::fgkEMCALTRUsPerSM * AliEMCALGeoParams::fgkEMCAL2x2PerTRU; // number of TRU 2x2's per SuperModule
602 const Int_t n2x2PerTRU = AliEMCALGeoParams::fgkEMCAL2x2PerTRU;
ecbba853 603 const Int_t nTot2x2 = fSuperModules * n2x2PerSM; // total TRU channel
9e47432c 604
9e47432c 605 // SM counters; decl. should be safe, assuming we don't get more than expected SuperModules..
38986b78 606 Int_t nTotalSMLG[AliEMCALGeoParams::fgkEMCALModules] = {0};
607 Int_t nTotalSMHG[AliEMCALGeoParams::fgkEMCALModules] = {0};
608 Int_t nTotalSMTRU[AliEMCALGeoParams::fgkEMCALModules] = {0};
609 Int_t nTotalSMLGLEDMon[AliEMCALGeoParams::fgkEMCALModules] = {0};
610 Int_t nTotalSMHGLEDMon[AliEMCALGeoParams::fgkEMCALModules] = {0};
611
612 const Int_t nTRUL0ChannelBits = 10; // used for L0 trigger bits checks
e4a4c62f 613 int firstL0TimeBin = 999;
614 int triggers[nTot2x2][24]; //auxiliary array for L0 trigger - TODO remove hardcoded 24
615 memset(triggers, 0, sizeof(int) * 24 * nTot2x2);
616
38986b78 617 Int_t iSM = 0; // SuperModule index
def665cb 618 // start loop over input stream
def665cb 619 while (in.NextDDL()) {
38986b78 620 Int_t iRCU = in.GetDDLNumber() % 2; // RCU0 or RCU1, within SuperModule
ecbba853 621 Int_t iDDL = in.GetDDLNumber();
dc16c015 622 fRawAnalyzer->SetIsZeroSuppressed( in.GetZeroSupp() );
ecbba853 623
98d6fe2e 624 while (in.NextChannel()) {
ecbba853 625 Int_t iBranch = in.GetBranch();
626
98d6fe2e 627 iSM = in.GetModule(); // SuperModule
38986b78 628 //prInt_tf("iSM %d DDL %d", iSM, in.GetDDLNumber());
98d6fe2e 629 if (iSM>=0 && iSM<fSuperModules) { // valid module reading
9e47432c 630
38986b78 631 Int_t nsamples = 0;
def665cb 632 vector<AliCaloBunchInfo> bunchlist;
633 while (in.NextBunch()) {
634 nsamples += in.GetBunchLength();
635 bunchlist.push_back( AliCaloBunchInfo(in.GetStartTimeBin(), in.GetBunchLength(), in.GetSignals() ) );
636 }
637
638 if (nsamples > 0) { // this check is needed for when we have zero-supp. on, but not sparse readout
38986b78 639 Float_t time = 0.;
640 Float_t amp = 0.;
def665cb 641 // indices for pedestal calc.
38986b78 642 Int_t firstPedSample = 0;
643 Int_t lastPedSample = 0;
644 bool isTRUL0IdData = false;
def665cb 645
646 if (! in.IsTRUData() ) { // high gain, low gain, LED Mon data - all have the same shaper/sampling
647 AliCaloFitResults fitResults = fRawAnalyzer->Evaluate( bunchlist, in.GetAltroCFG1(), in.GetAltroCFG2());
38986b78 648 amp = fitResults.GetAmp();
def665cb 649 time = fitResults.GetTof();
650 firstPedSample = fFirstPedestalSample;
38986b78 651 lastPedSample = fLastPedestalSample;
9e47432c 652 }
def665cb 653 else { // TRU data is special, needs its own analyzer
654 AliCaloFitResults fitResults = fRawAnalyzerTRU->Evaluate( bunchlist, in.GetAltroCFG1(), in.GetAltroCFG2());
38986b78 655 amp = fitResults.GetAmp();
def665cb 656 time = fitResults.GetTof();
657 firstPedSample = fFirstPedestalSampleTRU;
38986b78 658 lastPedSample = fLastPedestalSampleTRU;
e4a4c62f 659 if (in.GetColumn() >= n2x2PerTRU) {
5c6517c3 660 isTRUL0IdData = true;
661 }
def665cb 662 }
663
664 // pedestal samples
38986b78 665 Int_t nPed = 0;
666 vector<Int_t> pedSamples;
9e47432c 667
def665cb 668 // select earliest bunch
669 unsigned int bunchIndex = 0;
670 unsigned int startBin = bunchlist.at(0).GetStartBin();
671 if (bunchlist.size() > 0) {
672 for(unsigned int ui=1; ui < bunchlist.size(); ui++ ) {
673 if (startBin > bunchlist.at(ui).GetStartBin() ) {
674 startBin = bunchlist.at(ui).GetStartBin();
675 bunchIndex = ui;
676 }
9e47432c 677 }
678 }
def665cb 679
680 // check bunch for entries in the pedestal sample range
38986b78 681 Int_t bunchLength = bunchlist.at(bunchIndex).GetLength();
def665cb 682 const UShort_t *sig = bunchlist.at(bunchIndex).GetData();
38986b78 683 Int_t timebin = 0;
5c6517c3 684
685 if (! isTRUL0IdData) { // regular data, can look at pedestals
38986b78 686 for (Int_t i = 0; i<bunchLength; i++) {
5c6517c3 687 timebin = startBin--;
688 if ( firstPedSample<=timebin && timebin<=lastPedSample ) {
689 pedSamples.push_back( sig[i] );
690 nPed++;
691 }
692 } // i
5c6517c3 693 }
694 else { // TRU L0 Id Data
695 // which TRU the channel belongs to?
38986b78 696 Int_t iTRUId = in.GetModule()*3 + (iRCU*in.GetBranch() + iRCU);
5c6517c3 697
38986b78 698 for (Int_t i = 0; i< bunchLength; i++) {
699 for( Int_t j = 0; j < nTRUL0ChannelBits; j++ ){
5c6517c3 700 // check if the bit j is 1
701 if( (sig[i] & ( 1 << j )) > 0 ){
38986b78 702 Int_t iTRUIdInSM = (in.GetColumn() - n2x2PerTRU)*nTRUL0ChannelBits+j;
ce95bae9 703 if(iTRUIdInSM < n2x2PerTRU) {
38986b78 704 Int_t iTRUAbsId = iTRUIdInSM + n2x2PerTRU * iTRUId;
5c6517c3 705 // Fill the histograms
ecbba853 706 Int_t globTRUCol, globTRURow;
707 GetTruChannelPosition(globTRURow, globTRUCol, iSM, iDDL, iBranch, iTRUIdInSM );
708
709 FillRawsData(kNL0TRU, globTRUCol, globTRURow);
710 FillRawsData(kTimeL0TRU, globTRUCol, globTRURow, startBin);
711 triggers[iTRUAbsId][startBin] = 1;
712
713 if((int)startBin < firstL0TimeBin) firstL0TimeBin = startBin;
5c6517c3 714 }
715 }
716 }
717 startBin--;
718 } // i
719 } // TRU L0 Id data
ecbba853 720
def665cb 721 // fill histograms
722 if ( in.IsLowGain() || in.IsHighGain() ) { // regular towers
38986b78 723 Int_t towerId = iSM*nTowersPerSM + in.GetColumn()*nRows + in.GetRow();
def665cb 724 if ( in.IsLowGain() ) {
725 nTotalSMLG[iSM]++;
def665cb 726 if ( (amp > fMinSignalLG) && (amp < fMaxSignalLG) ) {
92664bc8 727 FillRawsData(kSigLG,towerId, amp);
728 FillRawsData(kTimeLG,towerId, time);
def665cb 729 }
730 if (nPed > 0) {
38986b78 731 for (Int_t i=0; i<nPed; i++) {
92664bc8 732 FillRawsData(kPedLG,towerId, pedSamples[i]);
def665cb 733 }
734 }
735 } // gain==0
736 else if ( in.IsHighGain() ) {
737 nTotalSMHG[iSM]++;
def665cb 738 if ( (amp > fMinSignalHG) && (amp < fMaxSignalHG) ) {
92664bc8 739 FillRawsData(kSigHG,towerId, amp);
740 FillRawsData(kTimeHG,towerId, time);
def665cb 741 }
742 if (nPed > 0) {
38986b78 743 for (Int_t i=0; i<nPed; i++) {
92664bc8 744 FillRawsData(kPedHG,towerId, pedSamples[i]);
def665cb 745 }
746 }
747 } // gain==1
748 } // low or high gain
38986b78 749 // TRU
def665cb 750 else if ( in.IsTRUData() && in.GetColumn()<AliEMCALGeoParams::fgkEMCAL2x2PerTRU) {
38986b78 751 // for TRU data, the mapping class holds the TRU Int_ternal 2x2 number (0..95) in the Column var..
752 Int_t iTRU = (iRCU*in.GetBranch() + iRCU); //TRU0 is from RCU0, TRU1 from RCU1, TRU2 is from branch B on RCU1
753 Int_t iTRU2x2Id = iSM*n2x2PerSM + iTRU*AliEMCALGeoParams::fgkEMCAL2x2PerTRU
def665cb 754 + in.GetColumn();
def665cb 755 nTotalSMTRU[iSM]++;
756 if ( (amp > fMinSignalTRU) && (amp < fMaxSignalTRU) ) {
92664bc8 757 FillRawsData(kSigTRU,iTRU2x2Id, amp);
e4a4c62f 758 //FillRawsData(kTimeTRU,iTRU2x2Id, time);
9e47432c 759 }
e4a4c62f 760 //if (nPed > 0) {
761 //for (Int_t i=0; i<nPed; i++) {
762 //FillRawsData(kPedTRU,iTRU2x2Id, pedSamples[i]);
763 //}
764 //}
def665cb 765 }
766 // LED Mon
767 else if ( in.IsLEDMonData() ) {
768 // for LED Mon data, the mapping class holds the gain info in the Row variable
769 // and the Strip number in the Column..
38986b78 770 Int_t gain = in.GetRow();
771 Int_t stripId = iSM*nStripsPerSM + in.GetColumn();
def665cb 772
773 if ( gain == 0 ) {
774 nTotalSMLGLEDMon[iSM]++;
5df32a1d 775 if ( (amp > fMinSignalLGLEDMon) && (amp < fMaxSignalLGLEDMon) ) {
92664bc8 776 FillRawsData(kSigLGLEDMon,stripId, amp);
777 FillRawsData(kTimeLGLEDMon,stripId, time);
def665cb 778 }
779 if (nPed > 0) {
38986b78 780 for (Int_t i=0; i<nPed; i++) {
92664bc8 781 FillRawsData(kPedLGLEDMon,stripId, pedSamples[i]);
def665cb 782 }
783 }
784 } // gain==0
785 else if ( gain == 1 ) {
786 nTotalSMHGLEDMon[iSM]++;
787 if ( (amp > fMinSignalHGLEDMon) && (amp < fMaxSignalHGLEDMon) ) {
92664bc8 788 FillRawsData(kSigHGLEDMon,stripId, amp);
789 FillRawsData(kTimeHGLEDMon,stripId, time);
def665cb 790 }
791 if (nPed > 0) {
38986b78 792 for (Int_t i=0; i<nPed; i++) {
92664bc8 793 FillRawsData(kPedHGLEDMon,stripId, pedSamples[i]);
def665cb 794 }
795 }
796 } // low or high gain
797 } // LEDMon
798
799 } // SM index OK
9e47432c 800
801 } // nsamples>0 check, some data found for this channel; not only trailer/header
802 }// end while over channel
803
804 }//end while over DDL's, of input stream
ecbba853 805 //filling some L0 trigger histos
806 if( firstL0TimeBin < 999 ){
807 for(Int_t i = 0; i < nTot2x2; i++) {
808 if( triggers[i][firstL0TimeBin] > 0 ) {
809 //histo->Fill(i,j);
810 FillRawsData(kNL0FirstTRU, i);
811 FillRawsData(kTimeL0FirstTRU, i, firstL0TimeBin);
812 }
813 }
814 }
00957c37 815
38986b78 816 //calculate the ratio of the amplitude and fill the histograms, only if the events type is Calib
92664bc8 817 // RS: operation on the group of histos kSigHG,k2DRatioAmp,kRatioDist,kLEDMonRatio,kLEDMonRatio,kSigLGLEDMon
5df32a1d 818 const int hGrp[] = {kSigHG,k2DRatioAmp,kRatioDist,kLEDMonRatio,kLEDMonRatioDist,kSigLGLEDMon};
92664bc8 819 if ( rawReader->GetType() == AliRawEventHeaderBase::kCalibrationEvent &&
820 CheckCloningConsistency(fRawsQAList, hGrp, sizeof(hGrp)/sizeof(int)) ) { // RS converting original code to loop over all matching triggers
821 int nTrig =IsClonedPerTrigClass(kSigHG,fRawsQAList) ? GetNEventTrigClasses() : 0; // loop over triggers only if histos were cloned
822 //
823 for (int itr=-1;itr<nTrig;itr++) { // start from -1 to acknowledge original histos if they were kept
824 TObjArray* trArr = GetMatchingRawsHistosSet(hGrp, sizeof(hGrp)/sizeof(int) ,itr);
825 if (!trArr) continue; // no histos for current trigger
826 //
827 Double_t binContent = 0.;
828 TProfile* prSigHG = (TProfile *)trArr->At(0); //kSigHG
829 TH1* th2DRatioAmp = (TH1*) trArr->At(1); //k2DRatioAmp
830 TH1* thRatioDist = (TH1*) trArr->At(2); //kRatioDist
831 TH1* thLEDMonRatio = (TH1*) trArr->At(3); //kLEDMonRatio
832 TH1* thLEDMonRatioDist = (TH1*) trArr->At(4); //kLEDMonRatio
833 TH1* hSigLGLEDMon = (TH1*) trArr->At(5); //kSigLGLEDMon
834 th2DRatioAmp->Reset("ICE");
835 thRatioDist->Reset("ICE");
836 thLEDMonRatio->Reset("ICE");
837 thLEDMonRatioDist->Reset("ICE");
838 th2DRatioAmp->ResetStats();
839 thRatioDist->ResetStats();
840 thLEDMonRatio->ResetStats();
841 thLEDMonRatioDist->ResetStats();
842 ConvertProfile2H(prSigHG, fHighEmcHistoH2F);
843 //
844 for(Int_t ix = 1; ix <= fHighEmcHistoH2F->GetNbinsX(); ix++) {
845 for(Int_t iy = 1; iy <= fHighEmcHistoH2F->GetNbinsY(); iy++) {
846 if(fCalibRefHistoH2F->GetBinContent(ix, iy))
847 binContent = fHighEmcHistoH2F->GetBinContent(ix, iy)/fCalibRefHistoH2F->GetBinContent(ix, iy);
848 th2DRatioAmp->SetBinContent(ix, iy, binContent);
849 thRatioDist->Fill(binContent);
850 }
851 }
852 //
853 //Now for LED monitor system, to calculate the ratio as well
854 Double_t binError = 0. ;
855 // for the binError, we add the relative errors, squared
856 Double_t relativeErrorSqr = 0. ;
857 //
858 for(int ib = 1; ib <= fLEDMonRefHistoPro->GetNbinsX(); ib++) {
859 //
860 if(fLEDMonRefHistoPro->GetBinContent(ib) != 0) {
861 binContent = hSigLGLEDMon->GetBinContent(ib) / fLEDMonRefHistoPro->GetBinContent(ib);
5df32a1d 862
92664bc8 863 relativeErrorSqr = TMath::Power( (fLEDMonRefHistoPro->GetBinError(ib) / fLEDMonRefHistoPro->GetBinContent(ib)), 2);
864 if( hSigLGLEDMon->GetBinContent(ib) != 0) {
865 relativeErrorSqr += TMath::Power( (hSigLGLEDMon->GetBinError(ib)/hSigLGLEDMon->GetBinContent(ib)), 2);
866 }
867 }
c76d0f92 868 else { // ref. run info is zero
869 binContent = -1;
870 relativeErrorSqr = 1;
92664bc8 871 }
5df32a1d 872 thLEDMonRatio->SetBinContent(ib, binContent);
92664bc8 873
874 binError = sqrt(relativeErrorSqr) * binContent;
875 thLEDMonRatio->SetBinError(ib, binError);
876 thLEDMonRatioDist->Fill(thLEDMonRatio->GetBinContent(ib));
12ef6821 877 }
92664bc8 878 } // loop over eventual trigger clones
879 }
9e47432c 880 // let's also fill the SM and event counter histograms
38986b78 881 Int_t nTotalHG = 0;
882 Int_t nTotalLG = 0;
883 Int_t nTotalTRU = 0;
884 Int_t nTotalHGLEDMon = 0;
885 Int_t nTotalLGLEDMon = 0;
1a78a765 886 for (iSM=0; iSM<fSuperModules; iSM++) {
9e47432c 887 nTotalLG += nTotalSMLG[iSM];
888 nTotalHG += nTotalSMHG[iSM];
889 nTotalTRU += nTotalSMTRU[iSM];
98d6fe2e 890 nTotalLGLEDMon += nTotalSMLGLEDMon[iSM];
891 nTotalHGLEDMon += nTotalSMHGLEDMon[iSM];
92664bc8 892 FillRawsData(kNsmodLG,iSM, nTotalSMLG[iSM]);
893 FillRawsData(kNsmodHG,iSM, nTotalSMHG[iSM]);
894 FillRawsData(kNsmodTRU,iSM, nTotalSMTRU[iSM]);
895 FillRawsData(kNsmodLGLEDMon,iSM, nTotalSMLGLEDMon[iSM]);
896 FillRawsData(kNsmodHGLEDMon,iSM, nTotalSMHGLEDMon[iSM]);
9e47432c 897 }
5c6517c3 898
92664bc8 899 FillRawsData(kNtotLG,nTotalLG);
900 FillRawsData(kNtotHG,nTotalHG);
901 FillRawsData(kNtotTRU,nTotalTRU);
902 FillRawsData(kNtotLGLEDMon,nTotalLGLEDMon);
903 FillRawsData(kNtotHGLEDMon,nTotalHGLEDMon);
904
905 IncEvCountCycleESDs();
906 IncEvCountTotalESDs();
def665cb 907 SetEventSpecie(saveSpecie) ;
3d66fb5e 908
909 MakeRawsSTU(rawReader);
910
9e47432c 911 // just in case the next rawreader consumer forgets to reset; let's do it here again..
912 rawReader->Reset() ;
9e47432c 913 return;
914}
915
916//____________________________________________________________________________
917void AliEMCALQADataMakerRec::MakeDigits()
918{
919 // makes data from Digits
92664bc8 920 FillDigitsData(1,fDigitsArray->GetEntriesFast()) ;
9e47432c 921 TIter next(fDigitsArray) ;
922 AliEMCALDigit * digit ;
923 while ( (digit = dynamic_cast<AliEMCALDigit *>(next())) ) {
92664bc8 924 FillDigitsData(0, digit->GetAmplitude()) ;
9e47432c 925 }
92664bc8 926 //
9e47432c 927}
928
929//____________________________________________________________________________
930void AliEMCALQADataMakerRec::MakeDigits(TTree * digitTree)
931{
932 // makes data from Digit Tree
92664bc8 933 // RS: Attention: the counters are increments in the MakeDigits()
9e47432c 934 if (fDigitsArray)
e0dc3f7d 935 fDigitsArray->Clear("C") ;
9e47432c 936 else
937 fDigitsArray = new TClonesArray("AliEMCALDigit", 1000) ;
938
939 TBranch * branch = digitTree->GetBranch("EMCAL") ;
92664bc8 940 if ( ! branch ) { AliWarning("EMCAL branch in Digit Tree not found"); return; }
941 //
942 branch->SetAddress(&fDigitsArray) ;
943 branch->GetEntry(0) ;
944 MakeDigits() ;
945 //
946 IncEvCountCycleDigits();
947 IncEvCountTotalDigits();
948 //
9e47432c 949}
950
951//____________________________________________________________________________
952void AliEMCALQADataMakerRec::MakeRecPoints(TTree * clustersTree)
953{
954 // makes data from RecPoints
955 TBranch *emcbranch = clustersTree->GetBranch("EMCALECARP");
956 if (!emcbranch) {
957 AliError("can't get the branch with the EMCAL clusters !");
958 return;
959 }
960
38986b78 961 TObjArray * emcRecPoints = new TObjArray(100) ;
962 emcbranch->SetAddress(&emcRecPoints);
9e47432c 963 emcbranch->GetEntry(0);
964
92664bc8 965 FillRecPointsData(kRecPM,emcRecPoints->GetEntriesFast()) ;
38986b78 966 TIter next(emcRecPoints) ;
9e47432c 967 AliEMCALRecPoint * rp ;
968 while ( (rp = dynamic_cast<AliEMCALRecPoint *>(next())) ) {
92664bc8 969 FillRecPointsData(kRecPE,rp->GetEnergy()) ;
970 FillRecPointsData(kRecPDigM,rp->GetMultiplicity());
9e47432c 971 }
38986b78 972 emcRecPoints->Delete();
973 delete emcRecPoints;
92664bc8 974 IncEvCountCycleRecPoints();
975 IncEvCountTotalRecPoints();
9e47432c 976}
977
978//____________________________________________________________________________
979void AliEMCALQADataMakerRec::StartOfDetectorCycle()
980{
981 //Detector specific actions at start of cycle
982
983}
984
def665cb 985//____________________________________________________________________________
986void AliEMCALQADataMakerRec::SetFittingAlgorithm(Int_t fitAlgo)
987{
988 //Set fitting algorithm and initialize it if this same algorithm was not set before.
989 //printf("**** Set Algorithm , number %d ****\n",fitAlgo);
92d9f317 990
991
430e7d8e 992 fRawAnalyzer = AliCaloRawAnalyzerFactory::CreateAnalyzer(fitAlgo);
993 fFittingAlgorithm = fitAlgo;
92d9f317 994
995 /*
def665cb 996 if(fitAlgo == fFittingAlgorithm && fRawAnalyzer) {
997 //Do nothing, this same algorithm already set before.
998 //printf("**** Algorithm already set before, number %d, %s ****\n",fitAlgo, fRawAnalyzer->GetName());
999 return;
1000 }
1001 //Initialize the requested algorithm
1002 if(fitAlgo != fFittingAlgorithm || !fRawAnalyzer) {
1003 //printf("**** Init Algorithm , number %d ****\n",fitAlgo);
1004
1005 fFittingAlgorithm = fitAlgo;
1006 if (fRawAnalyzer) delete fRawAnalyzer; // delete prev. analyzer if existed.
1007
1008 if (fitAlgo == kFastFit) {
1009 fRawAnalyzer = new AliCaloRawAnalyzerFastFit();
1010 }
1011 else if (fitAlgo == kNeuralNet) {
1012 fRawAnalyzer = new AliCaloRawAnalyzerNN();
1013 }
1014 else if (fitAlgo == kLMS) {
1015 fRawAnalyzer = new AliCaloRawAnalyzerLMS();
1016 }
1017 else if (fitAlgo == kPeakFinder) {
1018 fRawAnalyzer = new AliCaloRawAnalyzerPeakFinder();
1019 }
1020 else if (fitAlgo == kCrude) {
1021 fRawAnalyzer = new AliCaloRawAnalyzerCrude();
1022 }
1023 else {
1024 AliWarning("EMCAL QA invalid fit algorithm choice") ;
1025 }
1026
1027 }
1028 return;
92d9f317 1029 */
def665cb 1030}
1031
38986b78 1032//_____________________________________________________________________________________
1033void AliEMCALQADataMakerRec::ConvertProfile2H(TProfile * p, TH2 * histo)
1034{
922017a7 1035 // reset histogram
1036 histo->Reset("ICE") ;
1037 histo->ResetStats();
1038
38986b78 1039 Int_t nbinsProf = p->GetNbinsX();
1040
1041 // loop through the TProfile p and fill the TH2F histo
1042 Int_t row = 0;
1043 Int_t col = 0;
1044 Double_t binContent = 0;
1045 Int_t towerNum = 0; // global tower Id
1046 // i = 0; // tower Id within SuperModule
1047 Int_t iSM = 0; // SuperModule index
1048 Int_t iSMSide = 0; // 0=A, 1=C side
1049 Int_t iSMSector = 0; // 2 SM's per sector
1050
1051 // indices for 2D plots
1052 Int_t col2d = 0;
1053 Int_t row2d = 0;
1054
1055 for (Int_t ibin = 1; ibin <= nbinsProf; ibin++) {
1056 towerNum = (Int_t) p->GetBinCenter(ibin);
1057 binContent = p->GetBinContent(ibin);
1058
1059 // figure out what the tower indices are: col, row within a SuperModule
1060 iSM = towerNum/(AliEMCALGeoParams::fgkEMCALRows * AliEMCALGeoParams::fgkEMCALCols);
1061 col = (towerNum/AliEMCALGeoParams::fgkEMCALRows) % (AliEMCALGeoParams::fgkEMCALCols);
1062 row = towerNum % (AliEMCALGeoParams::fgkEMCALRows);
1063
1064 //DecodeTowerNum(towerNum, &SM, &col, &row);
1065 // then we calculate what the global 2D coord are, based on which SM
1066 // we are in
1067 iSMSector = iSM / 2;
1068 iSMSide = iSM % 2;
1069
1070 if (iSMSide == 1) { // C side, shown to the right
1071 col2d = col + AliEMCALGeoParams::fgkEMCALCols;
1072 }
1073 else { // A side, shown to the left
1074 col2d = col;
1075 }
1076
1077 row2d = row + iSMSector * AliEMCALGeoParams::fgkEMCALRows;
1078
1079 histo->SetBinContent(col2d+1, row2d+1, binContent);
1080 }
1081}
3d66fb5e 1082//____________________________________________________________________________
dab4328c 1083void AliEMCALQADataMakerRec::GetTruChannelPosition( Int_t &globRow, Int_t &globColumn, Int_t module, Int_t ddl, Int_t branch, Int_t column ) const
1084{ // from local to global indices
ecbba853 1085 Int_t mrow;
1086 Int_t mcol;
1087 Int_t trow;
1088 Int_t tcol;
1089 Int_t drow;
1090 Int_t rcu;
1091 // RCU 0 or 1
1092 rcu = ddl % 2;
1093
1094 // 12 rows of 2x2s in a module (3 TRUs by 4 rows)
1095 mrow = (module/2) * 12;
1096 // 24 columns per module, odd module numbers increased by 24
1097 mcol = (module%2) * 24;
1098
1099 // position within TRU coordinates
1100 tcol = column / 4;
1101 trow = column % 4;
1102
1103 //.combine
1104 if( module%2 == 0 ){ // A side
1105 // mirror rows
1106 trow = 3 - trow;
1107
1108 // TRU in module row addition
1109 drow = (rcu*branch+rcu) * 4;
1110
1111 }
1112 else{ // C side
1113 // mirror columns
1114 tcol = 23 - tcol;
1115
1116 // TRU in module row addition
1117 drow = (2 - (rcu*branch+rcu)) * 4;
1118 }
1119
1120 // output global row/collumn position (0,0 = SMA0, phi = 0, |eta| = max)
1121 globRow = mrow + drow + trow;
1122 globColumn = mcol + tcol;
afae9650 1123 return;
ecbba853 1124
1125}
3d66fb5e 1126//____________________________________________________________________________
afae9650 1127void AliEMCALQADataMakerRec::MakeRawsSTU(AliRawReader* rawReader)
1128{ // STU specifics
1129 AliEMCALTriggerSTURawStream* inSTU = new AliEMCALTriggerSTURawStream(rawReader);
3d66fb5e 1130
afae9650 1131 rawReader->Reset();
1132 rawReader->Select("EMCAL", 44);
3d66fb5e 1133
afae9650 1134 //L1 segmentation
1135 Int_t sizeL1gsubr = 1;
1136 Int_t sizeL1gpatch = 2;
1137 Int_t sizeL1jsubr = 4;
3d66fb5e 1138
afae9650 1139 Int_t iEMCALtrig[AliEMCALGeoParams::fgkEMCALSTUCols][AliEMCALGeoParams::fgkEMCALSTURows];
1140 memset(iEMCALtrig, 0, sizeof(int) * AliEMCALGeoParams::fgkEMCALSTUCols * AliEMCALGeoParams::fgkEMCALSTURows);
3d66fb5e 1141
afae9650 1142 if (inSTU->ReadPayLoad())
1143 {
1144 //Fw version (use in case of change in L1 jet
1145 Int_t fw = inSTU->GetFwVersion();
1146 Int_t sizeL1jpatch = 2+(fw >> 16);
3d66fb5e 1147
afae9650 1148 //To check link
a2e583d8 1149 Int_t mask = inSTU->GetFrameReceived() ^ inSTU->GetRegionEnable();
3d66fb5e 1150
afae9650 1151 for (int i = 0; i < 32; i++)
1152 {
a2e583d8 1153 if (!((mask >> i) & 0x1)) FillRawsData(kSTUTRU, i);
afae9650 1154 }
3d66fb5e 1155
afae9650 1156 //V0 signal in STU
1157 Int_t iV0Sig = inSTU->GetV0A()+inSTU->GetV0C();
1158
1159 //FastOR amplitude receive from TRU
1160 for (Int_t i = 0; i < 32; i++)
1161 {
1162 UInt_t adc[96];
1163 for (Int_t j = 0; j < 96; j++) adc[j] = 0;
1164
1165 inSTU->GetADC(i, adc);
1166
1167 Int_t iTRU = fGeom->GetTRUIndexFromSTUIndex(i);
3d66fb5e 1168
afae9650 1169 for (Int_t j = 0; j < 96; j++)
1170 {
1171 Int_t idx;
1172 fGeom->GetAbsFastORIndexFromTRU(iTRU, j, idx);
3d66fb5e 1173
afae9650 1174 Int_t px, py;
1175 fGeom->GetPositionInEMCALFromAbsFastORIndex(idx, px, py);
3d66fb5e 1176
afae9650 1177 iEMCALtrig[px][py] = adc[j];
3d66fb5e 1178 }
afae9650 1179 }
3d66fb5e 1180
afae9650 1181 //L1 Gamma patches
1182 Int_t iTRUSTU, x, y;
63c22917 1183 for (Int_t i = 0; i < inSTU->GetNL1GammaPatch(0); i++)
afae9650 1184 {
63c22917 1185 if (inSTU->GetL1GammaPatch(i, 0, iTRUSTU, x, y)) // col (0..23), row (0..3)
3d66fb5e 1186 {
afae9650 1187 Int_t iTRU;
1188 iTRU = fGeom->GetTRUIndexFromSTUIndex(iTRUSTU);
1189
1190 Int_t etaG = 23-x, phiG = y + 4 * int(iTRU/2); //position in EMCal
1191 if (iTRU%2) etaG += 24; //C-side
3d66fb5e 1192
afae9650 1193 etaG = etaG - sizeL1gsubr * sizeL1gpatch + 1;
3d66fb5e 1194
afae9650 1195 //Position of patch L1G (bottom-left FastOR of the patch)
1196 FillRawsData(kGL1, etaG, phiG);
3d66fb5e 1197
afae9650 1198 //loop to sum amplitude of FOR in the gamma patch
dab4328c 1199 Int_t iL1GPatchAmp = 0;
afae9650 1200 for (Int_t L1Gx = 0; L1Gx < sizeL1gpatch; L1Gx ++)
1201 {
1202 for (Int_t L1Gy = 0; L1Gy < sizeL1gpatch; L1Gy ++)
3d66fb5e 1203 {
dab4328c 1204 if (etaG+L1Gx < 48 && phiG+L1Gy < 64) iL1GPatchAmp += iEMCALtrig[etaG+L1Gx][phiG+L1Gy];
afae9650 1205 //cout << iEMCALtrig[etaG+L1Gx][phiG+L1Gy] << endl;
3d66fb5e 1206 }
3d66fb5e 1207 }
afae9650 1208
dab4328c 1209 //if (iL1GPatchAmp > 500) cout << "L1G amp =" << iL1GPatchAmp << endl;
1210 FillRawsData(kGL1V0, iV0Sig, iL1GPatchAmp);
afae9650 1211
3d66fb5e 1212 }
afae9650 1213 }
3d66fb5e 1214
afae9650 1215 //L1 Jet patches
63c22917 1216 for (Int_t i = 0; i < inSTU->GetNL1JetPatch(0); i++)
afae9650 1217 {
63c22917 1218 if (inSTU->GetL1JetPatch(i, 0, x, y)) // col (0,15), row (0,11)
3d66fb5e 1219 {
afae9650 1220
1221 Int_t etaJ = sizeL1jsubr * (11-y-sizeL1jpatch + 1);
1222 Int_t phiJ = sizeL1jsubr * (15-x-sizeL1jpatch + 1);
1223
1224 //position of patch L1J (FOR bottom-left)
1225 FillRawsData(kJL1, etaJ, phiJ);
3d66fb5e 1226
afae9650 1227 //loop the sum aplitude of FOR in the jet patch
dab4328c 1228 Int_t iL1JPatchAmp = 0;
afae9650 1229 for (Int_t L1Jx = 0; L1Jx < sizeL1jpatch*4; L1Jx ++)
1230 {
1231 for (Int_t L1Jy = 0; L1Jy < sizeL1jpatch*4; L1Jy ++)
3d66fb5e 1232 {
dab4328c 1233 if (etaJ+L1Jx < 48 && phiJ+L1Jy < 64) iL1JPatchAmp += iEMCALtrig[etaJ+L1Jx][phiJ+L1Jy];
3d66fb5e 1234 }
3d66fb5e 1235 }
afae9650 1236
dab4328c 1237 //cout << "L1J amp =" << iL1JPatchAmp << endl;
1238 FillRawsData(kJL1V0, iV0Sig, iL1JPatchAmp);
3d66fb5e 1239 }
3d66fb5e 1240 }
afae9650 1241 }
3d66fb5e 1242
afae9650 1243 //Fill FOR amplitude histo
1244 for (Int_t i = 0; i < 48; i++)
1245 {
1246 for (Int_t j = 0; j < 60; j++)
3d66fb5e 1247 {
afae9650 1248 if (iEMCALtrig[i][j] != 0) FillRawsData(kAmpL1, i, j, iEMCALtrig[i][j]);
3d66fb5e 1249 }
afae9650 1250 }
1251
1252 delete inSTU;
1253 return;
3d66fb5e 1254}
1255
ecbba853 1256