new SDD preprocessor + removal of eff C++ warning (base) - E. Crescio
[u/mrichter/AliRoot.git] / ITS / AliITSPreprocessorSPD.cxx
CommitLineData
3f0e013c 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
16/*
17$Log$
120a99c7 18Revision 1.3 2006/04/12 08:32:31 hristov
19New SPD simulation (Massimo):
20- speeding up of the diffusion code (Bjorn)
21- creation of CDB file with the dead channels, implementation
22of the CDB reading, check of the code (Henrik, Giuseppe, Domenico)
23- final tuning of the diffusion model parameters (Romualdo)
24
5bfe44ce 25Revision 1.2 2006/02/03 11:31:18 masera
26Calibration framework improved (E. Crescio)
27
fcf95fc7 28Revision 1.1 2005/10/11 12:31:50 masera
29Preprocessor classes for SPD (Paul Nilsson)
30
3f0e013c 31*/
32
33///////////////////////////////////////////////////////////////////////////
34// AliITSPreprocessorSPD implementation by P. Nilsson 2005
35// MAIN AUTHOR/CONTACT: Paul.Nilsson@cern.ch
36//
37// The purpose of this class is to provide algorithms for identification
38// of "bad channels" such as dead channels and noisy channels in the SPD
39//
40// Examples on how to use this class can be found in the macros:
41//
42// .findNoisyChannels.C (Locate and store noisy channels in the CDB)
43// .readNoisyChannels.C (Read noisy channels from the CDB)
44// .findDeadChannels.C (Locate and store dead channels in the CDB)
45// .readDeadChannels.C (Read dead channels from the CDB)
5bfe44ce 46//
47// Modified by D. Elia, H. Tydesjo
48// March 2006: Mixed up coordinates, bug fixed
49//
3f0e013c 50///////////////////////////////////////////////////////////////////////////
51
fcf95fc7 52#include "TFile.h"
3f0e013c 53#include "AliITSPreprocessorSPD.h"
fcf95fc7 54#include "AliCDBEntry.h"
55#include "AliITSCalibrationSPD.h"
3f0e013c 56ClassImp(AliITSPreprocessorSPD)
3f0e013c 57//__________________________________________________________________________
58AliITSPreprocessorSPD::AliITSPreprocessorSPD(void):
e56160b8 59fITSLoader(0x0),
60fRunLoader(0x0),
61fThresholdRatio(5.),
62fThreshold(5),
63fMaximumNumberOfEvents(1000000),
64fNumberOfModules(0),
65fHighestModuleNumber(0),
66fNumberOfColumns(0),
67fNumberOfRows(0),
68fSelectedAlgorithm(kOptimizedForRealData),
69fGeometryMode(kALICEGeometry),
70fNumberOfBadChannels(0),
71 fIndex(0),
72fInit(kFALSE),
73fVMEMode(kFALSE),
74fDigitsHistogram(0),
75fBadChannelsObjArray(0),
76fBadChannelsIntArray(0),
77fBadChannelsIndexArray(0),
78fBadChannelsContainer(0)
3f0e013c 79{
80 // Default constructor for the SPD preprocessor
81 //
82 // Initialization has to be done by hand using Set* methods and the Open method
83 //
84 // Input :
85 // Output:
86 // Return: <empty/uninitialized AliITSPreprocessorSPD object>
87}
88
89
90//__________________________________________________________________________
91AliITSPreprocessorSPD::AliITSPreprocessorSPD(const char *fileName, const char *mode,
92 const char *fileNameg, const Int_t maxNumberOfEvents):
93 fITSLoader(0x0),
94 fRunLoader(0x0),
e56160b8 95 fThresholdRatio(0),
96 fThreshold(0),
97 fMaximumNumberOfEvents(1000000),
98 fNumberOfModules(0),
99 fHighestModuleNumber(0),
100 fNumberOfColumns(0),
101 fNumberOfRows(0),
102 fSelectedAlgorithm(kOptimizedForRealData),
103 fGeometryMode(kALICEGeometry),
104 fNumberOfBadChannels(0),
105 fIndex(0),
106 fInit(kFALSE),
107 fVMEMode(kFALSE),
108 fDigitsHistogram(0),
109 fBadChannelsObjArray(0),
110 fBadChannelsIntArray(0),
111 fBadChannelsIndexArray(0),
112 fBadChannelsContainer(0)
3f0e013c 113{
114 // Standard constructor for the SPD preprocessor
115 //
116 // Input : Name of digit file
117 // Output: fInit
118 // Return: Initialized SPD preprocessor object
119
120 // Initialize
121 AliITSPreprocessorSPD::Init();
122 AliITSPreprocessorSPD::SetMaximumNumberOfEvents(maxNumberOfEvents);
123
124 // Open and read the galice and digit files
125 if (!AliITSPreprocessorSPD::Open(fileName, mode, fileNameg))
126 {
127 AliError("Failed to open file");
128 fInit = kFALSE;
129 }
130}
131
132
133//__________________________________________________________________________
134AliITSPreprocessorSPD::AliITSPreprocessorSPD(const AliITSPreprocessorSPD &prep) :
e56160b8 135TTask(prep),
136 fITSLoader(prep.fITSLoader),
137 fRunLoader(prep.fRunLoader),
138 fThresholdRatio(prep.fThresholdRatio),
139 fThreshold(prep.fThreshold),
140 fMaximumNumberOfEvents(prep.fMaximumNumberOfEvents),
141 fNumberOfModules(prep.fNumberOfModules),
142 fHighestModuleNumber(prep.fHighestModuleNumber),
143 fNumberOfColumns(prep.fNumberOfColumns),
144 fNumberOfRows(prep.fNumberOfRows),
145 fSelectedAlgorithm(prep.fSelectedAlgorithm),
146 fGeometryMode(prep.fGeometryMode),
147 fNumberOfBadChannels(prep.fNumberOfBadChannels),
148 fIndex(prep.fIndex),
149 fInit(prep.fInit),
150 fVMEMode(prep.fVMEMode),
151 fDigitsHistogram(prep.fDigitsHistogram),
152 fBadChannelsObjArray(prep.fBadChannelsObjArray),
153 fBadChannelsIntArray(prep.fBadChannelsIntArray),
154 fBadChannelsIndexArray(prep.fBadChannelsIndexArray),
155 fBadChannelsContainer(prep.fBadChannelsContainer)
3f0e013c 156{
157 // Default copy constructor
158 // Notice that only pointer addresses are copied!
159 // Memory allocations of new objects are not done.
160
e56160b8 161
3f0e013c 162}
163
164
165//__________________________________________________________________________
166AliITSPreprocessorSPD& AliITSPreprocessorSPD::operator=(const AliITSPreprocessorSPD &prep)
167{
168 // Assignment operator
169
170 AliError("Not implemented");
171
172 if (this != &prep) { } // Do not delete this line
173
174 return *this;
175}
176
177
178//__________________________________________________________________________
179AliITSPreprocessorSPD::~AliITSPreprocessorSPD(void)
180{
181 // Destructor for the SPD preprocessor
182
183 if (fDigitsHistogram)
184 {
185 // try fDigitsHistogram->Delete(); if the following crashes
186 for (UInt_t module = 0; module < fNumberOfModules; module++)
187 {
188 (*fDigitsHistogram)[module]->Delete();
189 }
190 delete fDigitsHistogram;
191 fDigitsHistogram = 0;
192 }
193
194 if (fNumberOfBadChannels)
195 {
196 delete [] fNumberOfBadChannels;
197 fNumberOfBadChannels = 0;
198 }
199
200 if (fBadChannelsIntArray)
201 {
202 delete [] fBadChannelsIntArray;
203 fBadChannelsIntArray = 0;
204 }
205
206 if (fBadChannelsIndexArray)
207 {
208 delete [] fBadChannelsIndexArray;
209 fBadChannelsIndexArray = 0;
210 }
211
212 if (fBadChannelsObjArray)
213 {
214 fBadChannelsObjArray->Delete();
215 delete fBadChannelsObjArray;
216 fBadChannelsObjArray = 0;
217 }
218
219 delete fRunLoader;
220 fRunLoader = 0;
221
222 delete fBadChannelsContainer;
223 fBadChannelsContainer = 0;
224}
225
226
227//__________________________________________________________________________
228void AliITSPreprocessorSPD::Init(void)
229{
230 // Initialization of the SPD preprocessor
231 //
232 // Input : (void)
233 // Output: Several logistical variables
234 // Return: (void)
235
236 // Default maximum number of events per histogram
237 fMaximumNumberOfEvents = 1000000;
238
239 // Default noisy channel removal algorithm
240 fSelectedAlgorithm = kOptimizedForRealData;
241
242 // Default noisy channel threshold and threshold ratio
243 // (threshold for current bin content divided by the average neighboring bin contents)
244 fThreshold = 10;
245 fThresholdRatio = 5.;
246
247 // Set default geometry mode (ALICE geometry). This also sets fNumberOfModules
248 AliITSPreprocessorSPD::SetGeometryMode(kALICEGeometry);
249
250 // The highest module number with found bad channels
251 fHighestModuleNumber = 0;
252
253 // Assume input is not from a VME file
254 fVMEMode = kFALSE;
255
256 // Initialization is complete
257 fInit = kTRUE;
258}
259
260
261//__________________________________________________________________________
262void AliITSPreprocessorSPD::SetGeometryMode(UInt_t mode)
263{
264 // Set the geometry mode
265 //
266 // Input : Geometry mode (either kTestBeamGeometry or kALICEGeometry)
267 // Output:
268 // Return: (void)
269
270 fGeometryMode = mode;
271
272 // In case of an input VME file, the number of modules has already been fixed.
273 // Do not try to change it
274 if (!fVMEMode)
275 {
276 if (mode == kALICEGeometry)
277 {
278 fNumberOfModules = kNumberOfSPDModules;
279 }
280 else if (mode == kTestBeamGeometry)
281 {
282 fNumberOfModules = kNumberOfTestBeamSPDModules;
283 }
284 else
285 {
286 AliError("Unknown geometry mode, defaults to ALICE geometry");
287 fNumberOfModules = kNumberOfSPDModules;
288 }
289 }
290}
291
292
293//__________________________________________________________________________
294void AliITSPreprocessorSPD::SetFakeNoisyChannel(Int_t module, Int_t column, Int_t row)
295{
296 // Introduce a fake noisy channel in the hit histograms
297 //
298 // Input : Module, column and row numbers
299 // Output: Updated hit histograms
300 // Return: (void)
301
302 if ((UInt_t)module < fNumberOfModules)
303 {
304 ((TH2F*)(*fDigitsHistogram)[module])->Fill(column, row, 1000000);
305 }
306 else
307 {
308 AliError("No such module number");
309 }
310}
311
312
313//__________________________________________________________________________
314Bool_t AliITSPreprocessorSPD::Open(const char *fileName, const char *mode, const char *fileNameg)
315{
316 // Open digit file
317 //
318 // Input : Name and mode of ITS digit file, name of galice file
319 // Output: Digits
320 // Return: kTRUE if loaders succeed
321
322 Bool_t status = kFALSE;
323 Bool_t status0 = kFALSE;
324 Bool_t status1 = kFALSE;
325 Bool_t status2 = kFALSE;
326 Bool_t status3 = kFALSE;
327
328 // Only proceed if initialization has been done
329 if (fInit)
330 {
331 TString m = (TString)mode;
332 if (m == "daq" || m == "DAQ")
333 {
334 // Open the data file and get the run loader
335 fRunLoader = AliRunLoader::Open(fileNameg);
336 if (fRunLoader)
337 {
338 // Get the gAlice object
339 status0 = AliITSPreprocessorSPD::GetgAlice();
340
341 // Get the ITS digits
342 if (status0) status1 = AliITSPreprocessorSPD::GetITSDigits(fileName);
343
344 // Create the test beam object
345 if (status1) status2 = AliITSPreprocessorSPD::CreateGeometryObj();
346
347 // Fill histograms with DAQ digits
348 if (status2) status3 = AliITSPreprocessorSPD::FillHistograms();
349
350 status = status0 & status1 & status2 & status3;
351 }
352 else
353 {
354 AliError("Failed to get the run loader");
355 }
356 }
357 else if (m == "vme" || m == "VME")
358 {
359 // Open the VME file that contains histograms with fired channels as read by the stand-alone VME system
360 TFile *vmeFile = TFile::Open(fileName);
361
362 if (!vmeFile->IsOpen())
363 {
364 AliError("Could not open VME input file");
365 }
366 else
367 {
368 // Get the histograms from the VME file that contains all fired channels
369 status0 = AliITSPreprocessorSPD::GetVMEHistograms(vmeFile);
370
371 // Create the test beam object
372 if (status0) status1 = AliITSPreprocessorSPD::CreateGeometryObj();
373 }
374
375 // This boolean will be used to override any attempts of changing the number of modules by the user
376 // with the SetGeometryMode method. For VME files the number of modules will entirely be determined by
377 // the input VME root file, i.e. by the number of histograms in this file
378 fVMEMode = kTRUE;
379
380 status = status0 & status1;
381 }
382 else
383 {
384 AliError("Unknown filetype - assuming DAQ file");
385 }
386
387 // At this stage, the final number of modules will be known (safe to define arrays)
388 // In case data is read from a VME root file, it will not be known before
389 if (status)
390 {
391 // Create the arrays for bookkeeping and storing the noisy channels
392 if (!fBadChannelsObjArray)
393 {
394 fBadChannelsObjArray = new TObjArray();
395 }
396 if (!fBadChannelsIndexArray)
397 {
398 // This array will contain the begin and end indices for each module, i.e. where to begin
399 // and stop reading the fBadChannelsObjArray for a certain module.
400 // The last position of the array will contain the end index of the last module
401 fBadChannelsIndexArray = new Int_t[fNumberOfModules + 1];
402 for (UInt_t module = 0; module < fNumberOfModules + 1; module++)
403 {
404 fBadChannelsIndexArray[module] = 0;
405 }
406 }
407 }
408 }
409 else
410 {
411 AliError("SPD preprocessor not initialized. Can't load digits");
412 }
413
414 return status;
415}
416
417
418//__________________________________________________________________________
419Bool_t AliITSPreprocessorSPD::GetgAlice(void)
420{
421 // Get the gAlice object
422 //
423 // Input : (void)
424 // Output: gAlice object
425 // Return: kTRUE if the gAlice object was found
426
427 Bool_t status = kTRUE;
428
429 // Load gAlice
430 fRunLoader->LoadgAlice();
431 if (!fRunLoader->GetAliRun())
432 {
433 AliError("gAlice not found on file. Aborting.");
434 status = kFALSE;
435 }
436
437 return status;
438}
439
440
441//__________________________________________________________________________
442Bool_t AliITSPreprocessorSPD::GetVMEHistograms(TFile *vmeFile)
443{
444 // Get pre-filled digit histograms from input VME file
445 //
446 // Input : pointer to VME file
447 // Output:
448 // Return: kTRUE if histograms are found on file
449
450 Bool_t status = kFALSE;
451
452 // Get the file directory
453 TDirectory *dir = (TDirectory *)vmeFile;
454
455 // Get the number of keys (histograms in this case corresponding to modules/ladders)
456 fNumberOfModules = dir->GetNkeys();
457 if ((fNumberOfModules > 0) && (fNumberOfModules <= kNumberOfSPDModules))
458 {
459 status = kTRUE;
460
461 // Create bad channel histograms
462 fDigitsHistogram = new TObjArray(fNumberOfModules);
463
464 // Create a key iterator
465 TIter nextkey(dir->GetListOfKeys());
466 TKey *key = 0;
467
468 // Loop over all objects, read them in to memory one by one
469 UInt_t module = 0;
470 while ( (key = (TKey *)nextkey()) )
471 {
472 (*fDigitsHistogram)[module++] = (TH2F *)key->ReadObj();
473
474 // For safety
475 if (module > fNumberOfModules)
476 {
477 AliError("Wrong number of keys in VME file");
478 status = kFALSE;
479 break;
480 }
481 }
482 }
483 else
484 {
485 AliError("Wrong number of histograms in VME file");
486 }
487 return status;
488}
489
490//__________________________________________________________________________
491Bool_t AliITSPreprocessorSPD::GetITSDigits(const char *fileName)
492{
493 // Get the ITS digits
494 //
495 // Input : name of digits file
496 // Output: fITSLoader object, ITS digits
497 // Return: kTRUE if loader succeed
498
499 Bool_t status = kTRUE;
500
501 // Load the gAlice and the header
502 fRunLoader->LoadgAlice();
503 fRunLoader->LoadHeader();
504
505 // Get the ITS loader
506 fITSLoader = (AliITSLoader*) fRunLoader->GetLoader("ITSLoader");
507 if (!fITSLoader)
508 {
509 AliError("ITS loader not found");
510 status = kFALSE;
511 }
512 else
513 {
514 // Open the digits file
515 fITSLoader->SetDigitsFileName(fileName);
516 }
517
518 return status;
519}
520
521
522//__________________________________________________________________________
523TClonesArray* AliITSPreprocessorSPD::CreateDigitsArray(void) const
524{
525 // Creation of the digits array
526 //
527 // Input : (void)
528 // Output:
529 // Return: Pointer to the SPD digits array
530
531 // Create an array for 5 chips with 8192 channels each
532 TClonesArray *digitsArray = new TClonesArray("AliITSdigitSPD", kNumberOfChannels);
533
534 return digitsArray;
535}
536
537
538//__________________________________________________________________________
539Bool_t AliITSPreprocessorSPD::CreateGeometryObj(void)
540{
541 // Creation of the geometry object
542 //
543 // This object is used to get the number of SPD half-staves
544 //
545 // Input : (void)
546 // Output: fGeometryObj
547 // Return: kTRUE if fGeometryObj has been created
548
549 Bool_t status = true;
550
551 // Create geometry object
552 // fGeometryObj = new ...
553 // if (!fGeometryObj) status = kFALSE;
554
555 // Get SPD parameters
556 // fNumberOfColumns = fGeometryObject->GetNumberOfColumns();
557 // fNumberOfRows = fGeometryObject->GetNumberOfRows();
558
559 fNumberOfColumns = kNumberOfColumns;
560 fNumberOfRows = kNumberOfRows;
561
562 return status;
563}
564
565
566//__________________________________________________________________________
567void AliITSPreprocessorSPD::CreateHistograms(void)
568{
569 // Create the noisy channel histograms
570 //
571 // Input : (void)
572 // Output: Noisy channel histograms
573 // Return: (void)
574
575 TString moduleName;
576 char n[4]; // For storing the module number (maximum module number is 240)
577
578 // Create noisy channel histograms
579 fDigitsHistogram = new TObjArray(fNumberOfModules);
580
581 for (UInt_t i = 0; i < fNumberOfModules; i++)
582 {
583 // Histogram name
584 moduleName = "module_";
585 sprintf(n,"%d",i);
586 moduleName.Append(n);
587
588 (*fDigitsHistogram)[i] = new TH2F(moduleName,"Digits",
589 fNumberOfColumns,-.5,(1.*fNumberOfColumns - .5),
590 fNumberOfRows,-.5,(1.*fNumberOfRows - .5));
591 }
592}
593
594
595//__________________________________________________________________________
596Bool_t AliITSPreprocessorSPD::FillHistograms(void)
597{
598 // Fill the histograms with digits (hit positions of unclustered hits)
599 //
600 // (There is one digit histogram per SPD module, i.e. a half-stave, 10 chips)
601 //
602 // Input : No arguments (Empty digit histograms)
603 // Output: Filled digit histograms
604 // Return: kTRUE if histograms are filled with digits, kFALSE otherwise
605
606 AliInfo("Filling noisy channel histograms");
607
608 Bool_t status = kTRUE;
609 AliITSdigitSPD *digitSPD = 0;
610 UInt_t row;
611 UInt_t column;
612 TBranch *digitsSPDBranch;
613 TTree *digitsTree;
614
615 // Get the digits
616 fITSLoader->LoadDigits("read");
617
618 // Create noisy channel histograms
619 AliITSPreprocessorSPD::CreateHistograms();
620
621 // Create an empty SPD digits array
622 TClonesArray *digitsArraySPD = AliITSPreprocessorSPD::CreateDigitsArray();
623
624 // Get number of events
625 UInt_t numberOfEvents = (fRunLoader->TreeE()) ? static_cast<UInt_t>(fRunLoader->TreeE()->GetEntries()) : 0;
626
627 // Make sure we don't try to analyze more data than there actually is
628 if (numberOfEvents < fMaximumNumberOfEvents)
629 {
630 fMaximumNumberOfEvents = numberOfEvents;
631 }
632
633 // Loop over all digits and put them in the corresponding histograms
634 if (numberOfEvents > 0)
635 {
636 for (UInt_t event = 0; event < fMaximumNumberOfEvents; event++)
637 {
638 // Get the current event
639 fRunLoader->GetEvent(event);
640
641 // Get the ITS digits tree
642 digitsTree = fITSLoader->TreeD();
643
644 // Disable all branches except the SPD branch to speed up the reading process
645 digitsTree->SetBranchStatus("ITSDigitsSPD",1);
646 digitsTree->SetBranchStatus("ITSDigitsSDD",0);
647 digitsTree->SetBranchStatus("ITSDigitsSSD",0);
648
649 // Reset the SPD digits array to make sure it is empty
650 digitsArraySPD->Clear();
651
652 // Get the SPD digits branch and set the address
653 digitsSPDBranch = digitsTree->GetBranch("ITSDigitsSPD");
654
655 digitsSPDBranch->SetAddress(&digitsArraySPD);
656
657 if (event%100 == 0) AliInfo(Form("Event #%d", event));
658
659 // Loop over all modules
660 UInt_t numberOfDigits = 0;
661 for (UInt_t module = 0; module < fNumberOfModules; module++)
662 {
663 // Get event data for current module
664 digitsTree->GetEvent(module);
665
666 // Get the number of entries
667 numberOfDigits = digitsArraySPD->GetEntries();
668
669 // Loop over all digits
670 for (UInt_t digit = 0; digit < numberOfDigits; digit++)
671 {
672 // Get the current digit
673 digitSPD = (AliITSdigitSPD*) digitsArraySPD->At(digit);
5bfe44ce 674 column = digitSPD->GetCoord1();
675 row = digitSPD->GetCoord2();
3f0e013c 676
677 // Fill the digits histogram
678 ((TH2F*)(*fDigitsHistogram)[module])->Fill(column, row);
fcf95fc7 679
3f0e013c 680 } // end digit loop
681 } // end module loop
682 } // end event loop
683 } // end numberOfEvents > 0
fcf95fc7 684
3f0e013c 685 else
686 {
687 status = kFALSE;
688 }
689
690 // Cleanup
691 delete digitsArraySPD;
692 digitsArraySPD = 0;
693
694 return status;
695}
696
697
698//__________________________________________________________________________
699Bool_t AliITSPreprocessorSPD::FindDeadChannels(void)
700{
701 // Locate dead channels
702 //
703 // Input : Filled hit histograms
704 // Output: TObjArray (fBadChannelsObjArray) with all identified dead channels
705 // Return: kTRUE if dead channels have been found
706
707 Bool_t status = kFALSE;
708
709 // Proceed only if properly initialized
710 if (fInit)
711 {
712 if (fVMEMode)
713 {
714 // Initialize counters
715 fNumberOfBadChannels = new Int_t[fNumberOfModules];
716 for (UInt_t module = 0; module < fNumberOfModules; module++)
717 {
718 fNumberOfBadChannels[module] = 0;
719 }
720
721 // Loop over all modules (intentional modularization - DCS will occationally want to
722 // look for noisy channels in certain modules, but not all)
723 fIndex = 0; // Global bad channels array counter (must be reset here)
724 for (UInt_t module = 0; module < fNumberOfModules; module++)
725 {
726 status |= AliITSPreprocessorSPD::FindDeadChannelsInModule(module);
727 }
728 }
729 else
730 {
731 AliError("Dead channels can only be found in data taken with stand-alone VME system");
732 }
733 }
734 else
735 {
736 AliError("Not properly initialized");
737 }
738
739 return status;
740}
741
742
743//__________________________________________________________________________
744Bool_t AliITSPreprocessorSPD::FindDeadChannelsInModule(UInt_t module)
745{
746 // Locate dead channels
747 // This method assumes that the preprocessor is operator in VME mode.
748 // The algorithm is very simple. It assumes that the data was taken in
749 // a mode where all working SPD pixels should respond as being hit.
750 // fThreshold is used as the limit where everything below this value will
751 // be considered as "dead".
752 //
753 // Input : Filled hit histograms
754 // Output: TObjArray (fBadChannelsObjArray) with all identified noisy channels
755 // Return: kTRUE if dead channels have been found
756
757 // Store the index number for this module
758 fBadChannelsIndexArray[module] = fIndex++;
759
760 UInt_t xBin, numberOfXBins;
761 UInt_t yBin, numberOfYBins;
762 Float_t binContent;
763
764 numberOfXBins = ((TH2F*)(*fDigitsHistogram)[module])->GetNbinsX();
765 numberOfYBins = ((TH2F*)(*fDigitsHistogram)[module])->GetNbinsY();
766
767 // Loop over all bins in this histogram
768 for (xBin = 1; xBin <= numberOfXBins; xBin++)
769 for (yBin = 1; yBin <= numberOfYBins; yBin++)
770 {
771 binContent = ((TH2F*)(*fDigitsHistogram)[module])->GetBinContent(xBin, yBin);
772
773 // Store this channel/bin if outside accepted limits
774 // A channel has to fire MORE times than the fThreshold value, or it will
775 // be considered as "dead"
776 if (binContent <= fThreshold)
777 {
778 // Store the dead channel in the array
779 // The channel object will be deleted in the destructor using the TObjArray Delete() method
780 // (The array will assume ownership of the channel object)
781 AliITSChannelSPD *channel = new AliITSChannelSPD((Int_t)(xBin - 1), (Int_t)(yBin - 1));
782
783 // Store the noisy channel in the array
784 fBadChannelsObjArray->Add(channel);
785
786 // Keep track of the number of bad channels in this module
787 fNumberOfBadChannels[module]++;
788 fIndex += 2;
789
790 // Keep track of the highest module number
791 if (module > fHighestModuleNumber) fHighestModuleNumber = module;
792
fcf95fc7 793 //AliInfo(Form("New dead pixel in (m,c,r) = (%d,%d,%d)", module, xBin - 1, yBin - 1));
3f0e013c 794 }
795 } // end bin loop
796
797 return (fNumberOfBadChannels[module] > 0);
798}
799
800
801//__________________________________________________________________________
802Bool_t AliITSPreprocessorSPD::FindNoisyChannels(void)
803{
804 // Locate noisy channels by searching through the digit histograms
805 // (There is one digit histogram per SPD module, i.e. a half-stave, 5 chips)
806 //
807 // Input : Digits
808 // Output: TObjArray (fBadChannelsObjArray) with all identified noisy channels
809 // Return: kTRUE if noisy channels have been found
810
811 Bool_t status = kFALSE;
812
813 // Proceed only if properly initialized
814 if (fInit)
815 {
816 // (For testing purposes, noisy channels can be inserted here)
fcf95fc7 817 //SetFakeNoisyChannel(4,10,10);
3f0e013c 818 // Initialize counters
819 fNumberOfBadChannels = new Int_t[fNumberOfModules];
820 for (UInt_t module = 0; module < fNumberOfModules; module++)
821 {
822 fNumberOfBadChannels[module] = 0;
823 }
824
825 // Scan through all the histogram bins and search for average filling deviations
826 if ((fSelectedAlgorithm == kOptimizedForRealData) || (fSelectedAlgorithm == kOptimizedForRealDataRMS))
827 {
828 // Noisy channel algorithm optimized for real data..........................
829 // Histograms can have any shape (both thresholds and quotients are used)
830 // This algorithm can be used to find noisy channels even if the data was
831 // taken with beam. All channels outside accepted limits (set by fThreshold
832 // and fThresholdRatio) will be marked as noisy
833
834 if (fSelectedAlgorithm == kOptimizedForRealData)
835 {
836 AliInfo("Searching for noisy channels (optimized for real data)");
837 }
838 else
839 {
840 AliInfo("Searching for noisy channels (optimized for real data, RMS version)");
841 }
842
843 // Loop over all modules (intentional modularization - DCS will occationally want to
844 // look for noisy channels in certain modules, but not all)
845 fIndex = 0; // Global bad channels array counter (must be reset here)
846 for (UInt_t module = 0; module < fNumberOfModules; module++)
847 {
848 status |= AliITSPreprocessorSPD::FindNoisyChannelsInModuleAlgo0(module);
849 }
850 } // end algorithm 0
851 else
852 {
853 // Noisy channel algorithm optimized for calibration data...........................
854 // Histograms will/should only contain noisy channels (only thresholds are used)
855 // Calibration histograms should have no background. The calibration data
856 // should have been taken without beam. All channels outside accepted limits
857 // (set by fThreshold) will be marked as noisy
858
859 AliInfo("Searching for noisy channels (optimized for calibration data)");
860
861 // Loop over all modules (intentional modularization - DCS will occationally want to
862 // look for noisy channels in certain modules, but not all)
863 fIndex = 0; // Global bad channels array counter (must be reset here)
864 for (UInt_t module = 0; module < fNumberOfModules; module++)
865 {
866 status |= AliITSPreprocessorSPD::FindNoisyChannelsInModuleAlgo1(module);
867 }
868 } // end algorithm 1
869 } // end if fInit
870 else
871 {
872 AliError("Not properly initialized");
873 }
874
875 return status;
876}
877
878
879//__________________________________________________________________________
880Bool_t AliITSPreprocessorSPD::FindNoisyChannelsInModuleAlgo0(UInt_t module)
881{
882 // Locate the noisy channels in a module (optimized for real data)
883 //
884 // For each channel in these histograms, the algorithm checks the average
885 // filling of the neighboring 3, 5 or 8 channels (depending on the location
886 // of the channel in question; corner, border or inside), or compares with the
887 // RMS of the neighbors. If the average is "much" lower, the channel will be
888 // considered to be noisy. The default noisy-to-normal fraction is stored in the
889 // fThresholdRatio varible. It can be set with the SetThresholdRatio method.
890 // The channel also has to have fired more than a certain minimum, fThreshold.
891 // It can be set with the SetThreshold method.
892 //
893 // To avoid difficulties with noisy channels that occur in pairs, the
894 // neighboring channel with largest number of fillings will be removed from
895 // the average calculation.
896 //
897 // NOTE: Since this method modifies the fBadChannelsObjArray and fBadChannelsIndexArray
898 // it is essential to initialize the fIndex counter before calling this module
899 // the first time. The bad channel data does not have to be ordered per module
900 // in the fBadChannelsObjArray, but the indices of where the data of a certain module
901 // starts has to be correct. A wrong fIndex can lead to segmentation violation
902 //
903 // Input : module number, filled digit histograms
904 // Output: TObjArray (fBadChannelsObjArray) with all identified noisy channels,
905 // Int_t[] (fBadChannelsIndexArray) with fBadChannelsObjArray module indices,
906 // number of noisy channels in this module (global variable fNumberOfBadChannels[module])
907 // Return: kTRUE if there are noisy channels in this module
908
909 // Store the index number for this module
910 fBadChannelsIndexArray[module] = fIndex++;
911
912 UInt_t xBin, numberOfXBins;
913 UInt_t yBin, numberOfYBins;
914 UInt_t neighborXBin;
915 UInt_t neighborYBin;
916 UInt_t numberOfNeighboringBins;
917 Float_t binContent;
918 Float_t sumBinContent;
919 Float_t neighborBinContent;
920 Float_t maxBinContent;
921 Float_t averageBinContent;
922 Float_t ratio;
923
924 numberOfXBins = (UInt_t)((TH2F*)(*fDigitsHistogram)[module])->GetNbinsX();
925 numberOfYBins = (UInt_t)((TH2F*)(*fDigitsHistogram)[module])->GetNbinsY();
926
927 // Loop over all bins in this histogram
928 for (xBin = 1; xBin <= numberOfXBins; xBin++)
929 for (yBin = 1; yBin <= numberOfYBins; yBin++)
930 {
931 numberOfNeighboringBins = 0;
932 averageBinContent = 0.;
933 sumBinContent = 0.;
934 binContent = ((TH2F*)(*fDigitsHistogram)[module])->GetBinContent(xBin, yBin);
935 maxBinContent = 0.;
936
937 // Calculate the average pixel level on the surrounding pixels
938 for (neighborXBin = xBin - 1; neighborXBin <= xBin + 1; neighborXBin++)
939 for (neighborYBin = yBin - 1; neighborYBin <= yBin + 1; neighborYBin++)
940 {
941 if ( !((neighborXBin == xBin) && (neighborYBin == yBin)) )
942 {
943 // Only update the number of neighboring bins when we are not on the border
944 if ((neighborXBin > 0) && (neighborXBin <= numberOfXBins+1) &&
945 (neighborYBin > 0) && (neighborYBin <= numberOfYBins+1))
946 {
947 neighborBinContent =
948 ((TH2F*)(*fDigitsHistogram)[module])->GetBinContent(neighborXBin, neighborYBin);
949
950 if (fSelectedAlgorithm == kOptimizedForRealDataRMS)
951 {
952 // RMS
953 sumBinContent += neighborBinContent*neighborBinContent;
954 }
955 else
956 {
957 // Geometrical mean
958 sumBinContent += neighborBinContent;
959 }
960
961 if (neighborBinContent > maxBinContent) maxBinContent = neighborBinContent;
962
963 numberOfNeighboringBins++;
964 }
965 }
966 }
fcf95fc7 967
3f0e013c 968 // Calculate the average. Remove the largest neighboring bin
969 // (Correction for potential clusters of noisy channels)
970 if (fSelectedAlgorithm == kOptimizedForRealDataRMS)
971 {
972 // Square the max bin content before removing it from the average calculation
973 maxBinContent *= maxBinContent;
3f0e013c 974 // RMS
fcf95fc7 975 averageBinContent = TMath::Sqrt((sumBinContent - maxBinContent)/(Float_t)(numberOfNeighboringBins - 1));
3f0e013c 976 }
977 else
978 {
979 // Geometrical mean
980 averageBinContent = (sumBinContent - maxBinContent)/(Float_t)(numberOfNeighboringBins - 1);
981 }
982
983 // Store this channel/bin if outside accepted limits
984 // The threshold ratio is the threshold for the current bin content divided by the
985 // average neighboring bin contents. The threshold bin content is the minimum number of
986 // times a channel has to have fired to be called noisy
987 ratio = (averageBinContent > 0) ? binContent/averageBinContent : 0.;
988 if ( ((ratio >= fThresholdRatio) || (ratio == 0.)) && (binContent >= fThreshold) )
989 {
990 // Store the noisy channel in the array
991 // The channel object will be deleted in the destructor using the TObjArray Delete() method
992 // (The array will assume ownership of the channel object)
993 AliITSChannelSPD *channel = new AliITSChannelSPD((Int_t)(xBin - 1), (Int_t)(yBin - 1));
994
995 // Store the noisy channel in the array
996 fBadChannelsObjArray->Add(channel);
997
998 // Keep track of the number of bad channels in this module
999 fNumberOfBadChannels[module]++;
1000 fIndex += 2;
1001
1002 // Keep track of the highest module number
1003 if (module > fHighestModuleNumber) fHighestModuleNumber = module;
1004
1005 AliInfo(Form("New noisy pixel in (m,c,r) = (%d,%d,%d)", module, xBin - 1, yBin - 1));
1006 AliInfo(Form("- Noisy pixel fired %d times, average neighborhood: %f",(Int_t)binContent,averageBinContent));
1007 }
1008 } // end bin loop
1009
1010 return (fNumberOfBadChannels[module] > 0);
1011}
1012
1013
1014//__________________________________________________________________________
1015Bool_t AliITSPreprocessorSPD::FindNoisyChannelsInModuleAlgo1(UInt_t module)
1016{
1017 // Locate the noisy channels in a module (optimized for calibration data)
1018 //
1019 // This algorithm locates noisy channels by assuming original data was taken
1020 // in calibration mode. This should be done without beam and will thus only
1021 // contain data corresponding to background and noisy channels. The latter
1022 // should be clearly visible in this data so this algorithm simply assumes
1023 // that all histogram bins that are filled more than fThreshold times are
1024 // noisy.
1025 //
1026 // NOTE: Since this method modifies the fBadChannelsObjArray and fBadChannelsIndexArray
1027 // it is essential to initialize the fIndex counter before calling this module
1028 // the first time. The bad channel data does not have to be ordered per module
1029 // in the fBadChannelsObjArray, but the indices of where the data of a certain module
1030 // starts has to be correct. A wrong fIndex can lead to segmentation violation
1031 //
1032 // Input : module number, filled digit histograms
1033 // Output: TObjArray (fBadChannelsObjArray) with all identified noisy channels,
1034 // Int_t[] (fBadChannelsIndexArray) with fBadChannelsObjArray module indices,
1035 // number of noisy channels in this module (global variable fNumberOfBadChannels[module])
1036 // Return: kTRUE if there are noisy channels in this module
1037
1038 // Store the index number for this module
1039 fBadChannelsIndexArray[module] = fIndex++;
1040
1041 UInt_t xBin, numberOfXBins;
1042 UInt_t yBin, numberOfYBins;
1043 Float_t binContent;
1044
1045 numberOfXBins = ((TH2F*)(*fDigitsHistogram)[module])->GetNbinsX();
1046 numberOfYBins = ((TH2F*)(*fDigitsHistogram)[module])->GetNbinsY();
1047
1048 // Loop over all bins in this histogram
1049 for (xBin = 1; xBin <= numberOfXBins; xBin++)
1050 for (yBin = 1; yBin <= numberOfYBins; yBin++)
1051 {
1052 binContent = ((TH2F*)(*fDigitsHistogram)[module])->GetBinContent(xBin, yBin);
1053
1054 // Store this channel/bin if outside accepted limits
1055 // The threshold bin content is the minimum number of times a channel has to have
1056 // fired to be called noisy
1057 if (binContent >= fThreshold)
1058 {
1059 // Store the noisy channel in the array
1060 // The channel object will be deleted in the destructor using the TObjArray Delete() method
1061 // (The array will assume ownership of the channel object)
1062 AliITSChannelSPD *channel = new AliITSChannelSPD((Int_t)(xBin - 1), (Int_t)(yBin - 1));
1063
1064 // Store the noisy channel in the array
1065 fBadChannelsObjArray->Add(channel);
1066
1067 // Keep track of the number of bad channels in this module
1068 fNumberOfBadChannels[module]++;
1069 fIndex += 2;
1070
1071 // Keep track of the highest module number
1072 if (module > fHighestModuleNumber) fHighestModuleNumber = module;
1073
1074 AliInfo(Form("New noisy pixel in (m,c,r) = (%d,%d,%d)", module, xBin - 1, yBin - 1));
1075 AliInfo(Form("- Noisy pixel fired %d times",(Int_t)binContent));
1076 }
1077 } // end bin loop
1078
1079 return (fNumberOfBadChannels[module] > 0);
1080}
1081
1082
1083//__________________________________________________________________________
1084void AliITSPreprocessorSPD::PrintChannels(void)
1085{
1086 // Print all found bad channels to stdout
1087 //
1088 // Input : fBadChannelsObjArray
1089 // Output: (dump to stdout)
1090 // Return: (void)
1091
1092 Int_t i = 0;
1093 Int_t j = 0;
1094 AliITSChannelSPD *channel = 0;
1095
1096 // Print the bad channels stores in the array
1097 AliInfo("\nModule #\tColumn #\tRow #\n------------------------------------------------");
1098 for (UInt_t module = 0; module < fNumberOfModules; module++)
1099 {
1100 j = 0;
1101 while (j < fNumberOfBadChannels[module])
1102 {
1103 channel = (AliITSChannelSPD *) fBadChannelsObjArray->At(i++);
1104 std::cout << module << "\t\t" << channel->GetColumn() << "\t\t" << channel->GetRow() << std::endl;
1105
1106 // Go to next bad channel
1107 j++;
1108 }
1109 }
1110
1111 AliInfo(Form("%d bad channels were found", fBadChannelsObjArray->GetEntries()));
1112}
1113
1114
1115//__________________________________________________________________________
1116void AliITSPreprocessorSPD::MarkNoisyChannels(void)
1117{
1118 // WARNING: THIS METHOD DOESN'T WORK!!!
1119 //
1120 // Mark all identified noisy channels
1121 //
1122 // Input : List of noisy channels, original digits tree
1123 // Output: New digits tree containing SPD digits marked when noisy
1124 // Return: (void)
1125 //
1126 // The original digits tree (digitsTree) is cloned except for the SPD branch (ITSDigitSPD).
1127 // This branch is then redefined for each event and will contain all the original
1128 // information. All known noisy channels will be marked by using the TObject status bits
1129 // according to the following scheme. Dead channels are included for completeness. Note
1130 // that a dead channel will NEVER show up among digits..
1131 //
1132 // Interpretation of digit status bits (LSB):
1133 // Dead channel Noisy channel | Integer
1134 // -----------------------------------------
1135 // 0 0 | 0
1136 // 0 1 | 1
1137 // 1 0 | 2
1138 //
1139 // meaning e.g. that a channel that is noisy will have the first bit set in its status bits
1140
1141 // Do not continue unless we are processing DAQ data
1142 if (!fVMEMode)
1143 {
1144 AliInfo("Marking bad channels");
1145
1146 // Create the storage container that will be used to access the bad channels
1147 if (!fBadChannelsContainer)
1148 {
1149 // Add the bad channels array to the storage container
1150 // (ownership is passed to the AliRunDataStorage object)
1151 fBadChannelsContainer = new AliITSBadChannelsSPD();
1152
1153 // Convert the bad channels from TObjArray to Int_t[]
1154 AliITSPreprocessorSPD::ConvertObjToIntArray();
1155
1156 // Store the arrays in the bad channels container object
1157 const Int_t kBadChannelsArraySize =
1158 2*fBadChannelsObjArray->GetEntries() + fNumberOfModules;
1159 fBadChannelsContainer->Put(fBadChannelsIntArray, kBadChannelsArraySize,
1160 fBadChannelsIndexArray, fNumberOfModules);
1161 }
1162
1163 // Create the bad channels helper object
1164 // (will be used to find a bad channel within a TObjArray)
1165 AliITSBadChannelsAuxSPD *aux = new AliITSBadChannelsAuxSPD();
1166
1167 AliITSdigitSPD *digitSPD = 0;
1168 UInt_t numberOfDigits;
1169 Int_t newDigit[3];
1170 Bool_t mark = kFALSE;
1171
1172 TBranch *digitsBranch = 0;
1173 TTree *digitsTree;
1174
1175 // Create an empty SPD digit array
1176 TObjArray *digitsArraySPD = new TObjArray();
1177
1178 // Get the digits in update mode (we want to modify them if there are noisy channels)
1179 fITSLoader->UnloadDigits();
1180 fITSLoader->LoadDigits("update");
1181
1182 // Get the number of events
1183 UInt_t numberOfEvents = (fRunLoader->TreeE()) ? static_cast<UInt_t>(fRunLoader->TreeE()->GetEntries()) : 0;
1184
1185 // Loop over all events
1186 for (UInt_t event = 0; event < numberOfEvents; event++)
1187 {
1188 if (event%100 == 0) AliInfo(Form("Event #%d", event));
1189
1190 // Get the current event
1191 fRunLoader->GetEvent(event);
1192
1193 // Get the ITS digits tree
1194 digitsTree = fITSLoader->TreeD();
1195
1196 // Get SPD branch that will contain all digits with marked noisy channels
1197 digitsBranch = digitsTree->GetBranch("ITSDigitsSPD");
1198 digitsBranch->SetAddress(&digitsArraySPD);
1199
1200 // Get the stored number of modules
1201 UInt_t numberOfModules = (Int_t)digitsTree->GetEntries();
1202 TObjArray **newDigitsArraySPD = new TObjArray*[numberOfModules];
1203
1204 Int_t *digitNumber = new Int_t[numberOfModules];
1205 for (UInt_t m = 0; m < numberOfModules; m++)
1206 {
1207 newDigitsArraySPD[m] = new TObjArray();
1208 digitNumber[m] = 0;
1209 }
1210
1211 AliInfo(Form("ent = %d", (Int_t)digitsTree->GetEntries()));
1212
1213 // Reset the SPD digit arrays to make sure they are empty
1214 digitsArraySPD->Clear();
1215
1216 // Get the SPD digits branch from the original digits tree and set the address
1217 digitsBranch = digitsTree->GetBranch("ITSDigitsSPD");
1218 digitsBranch->SetAddress(&digitsArraySPD);
1219
1220 // Loop over all modules
1221 for (UInt_t module = 0; module < fNumberOfModules; module++)
1222 {
1223 // Get event data for current module
1224 digitsTree->GetEvent(module);
1225
1226 // Get the hits in the current module
1227 TObjArray *moduleObjArray = fBadChannelsContainer->CreateModuleObjArray(module);
1228
1229 // Get the number of entries
1230 numberOfDigits = digitsArraySPD->GetEntries();
1231
1232 // Loop over all digits and all channels
1233 for (UInt_t digit = 0; digit < numberOfDigits; digit++)
1234 {
1235 // Get the current digit
1236 digitSPD = (AliITSdigitSPD*) digitsArraySPD->At(digit);
5bfe44ce 1237 newDigit[0] = digitSPD->GetCoord1(); // column
1238 newDigit[1] = digitSPD->GetCoord2(); // row
3f0e013c 1239 newDigit[2] = digitSPD->GetSignal(); // signal
1240
1241 // Check if this channel is noisy
1242 // (Compare with all stored channels in the bad channels array)
1243 if (aux->Find(digitSPD, moduleObjArray))
1244 {
1245 // Set the mark flag and break the loop
1246 mark = kTRUE;
1247 }
1248
1249 // Store this digit in the SPD digits array using a placement new operation
1250 new ((*newDigitsArraySPD[module])[digitNumber[module]]) AliITSdigitSPD(newDigit);
1251
1252 // Mark it if noisy and store in the noisy channel array
1253 if (mark)
1254 {
1255 // Store this digit in the marked SPD digits array using a placement new operation
1256 //new ((*badChannels[m])[numberOfBadChannels[m]]) AliITSChannelSPD(newBadChannel);
1257 //new ((*newDigitsArraySPD[module])[digitNumber[module]]) AliITSdigitSPD(newDigit);
1258
1259 // Mark the original channel as noisy
1260 ((*newDigitsArraySPD[module])[digitNumber[module]])->SetBit(kNoisyChannel);
1261
1262 mark = kFALSE;
1263 }
1264
1265 digitNumber[module]++;
1266
1267 } // end digit loop
1268
1269 // Cleanup
1270 delete moduleObjArray;
1271 moduleObjArray = 0;
1272
1273 } // end module loop
1274
1275 digitsBranch->Reset();
1276 digitsBranch->ResetAddress();
1277
1278 // Cleanup
1279 delete digitsArraySPD;
1280 digitsArraySPD = 0;
1281 digitsTree->Reset();
1282
1283 // WHY THIS RANGE?????????????????????????????????????????????????????????????????????
1284 for (UInt_t n = 0; n < event; n++)
1285 {
1286 digitsTree->SetBranchAddress("ITSDigitsSPD", &newDigitsArraySPD[n]);
1287 digitsTree->Fill();
1288 }
1289
1290 digitsTree->AutoSave();
1291
1292 // Cleanup
1293 for (UInt_t n = 0; n < event; n++)
1294 {
1295 delete newDigitsArraySPD[n];
1296 }
1297 delete [] newDigitsArraySPD;
1298 newDigitsArraySPD = 0;
1299 delete [] digitNumber;
1300 digitNumber = 0;
1301 delete digitsTree;
1302 digitsTree = 0;
1303
1304 } // end loop over all events
1305
1306 // Unload the digits
1307 fITSLoader->UnloadDigits();
1308
1309 // Cleanup
1310 delete aux;
1311 aux = 0;
1312 }
1313}
1314
fcf95fc7 1315/*
3f0e013c 1316
1317//__________________________________________________________________________
1318Bool_t AliITSPreprocessorSPD::Store(AliCDBId &id, AliCDBMetaData *md)
1319{
1320 // Store the bad channels object in the calibration database
1321 // (See the corresponding run macro for further explanations)
1322 //
1323 // Input : fBadChannelsObjArray (now containing all found bad channels), object meta data
1324 // Output: Database file containing the bad channels
1325 // Return: kTRUE if successful
1326
1327 Bool_t status = kFALSE;
1328
1329 AliInfo("Storing bad channels");
1330
1331 // Add the bad channels array to the storage container
1332 // (ownership is passed to the AliRunDataStorage object)
1333 fBadChannelsContainer = new AliITSBadChannelsSPD();
1334
1335 // Convert the bad channels from TObjArray to Int_t[]
1336 AliITSPreprocessorSPD::ConvertObjToIntArray();
1337
1338 // Store the arrays in the bad channels container object
1339 const Int_t kBadChannelsArraySize =
1340 2*fBadChannelsObjArray->GetEntries() + fNumberOfModules;
1341 fBadChannelsContainer->Put(fBadChannelsIntArray, kBadChannelsArraySize,
1342 fBadChannelsIndexArray, fNumberOfModules);
1343
1344 // Store the container
1345 if(!AliCDBManager::Instance()->IsDefaultStorageSet()) {
fcf95fc7 1346 //AliError("No storage set!");
1347 // return status;
1348 AliCDBManager::Instance()->SetDefaultStorage("local://Calib");
1349 }
3f0e013c 1350
1351 if (AliCDBManager::Instance()->GetDefaultStorage()->Put(fBadChannelsContainer, id, md))
1352 {
1353 AliInfo("Bad channels object stored in database");
1354 status = kTRUE;
1355 }
1356 else
1357 {
1358 AliError("Failed to store object in database");
1359 }
1360
1361 return status;
1362}
1363
fcf95fc7 1364*/
3f0e013c 1365//__________________________________________________________________________
fcf95fc7 1366void AliITSPreprocessorSPD::ConvertObjToIntArray()
3f0e013c 1367{
1368 // Convert the bad channel TObjArray to an Int_t array
1369 //
1370 // Input : fBadChannelsObjArray (now containing all found bad channels)
1371 // Output: fBadChannelsIntArray
1372 // Return: (void)
1373 //
1374 // Data encoding:
1375 // The TObjArray of this class (fBadChannelsObjArray) is converted to a sequential
1376 // Int_t array (fBadChannelsIntArray) in this method. For each module, the first
1377 // stored number is the number of bad channels in the current module. This is
1378 // followed by all the columns and rows of the bad channels:
1379 //
1380 // badChannelsArray =
1381 // | N(m) | col0 | row0 | .. | colN(m) | N(m+1) | col0 | row0 | ...
1382 // . .......... module m ......... . .... module m+1 ......
1383 //
1384 // The bad channels index array (fBadChannelsIndexArray) contains the indices of
1385 // the badChannelsArray, i.e. where the bad channels in certain module starts:
1386 //
1387 // fBadChannelsObjArray =
1388 // | i0 | i1 | .. | iM | (where M = the number of SPD modules)
1389 //
1390 // e.g. i1 corresponds to the index of the badChannelsArray where N(1) is stored,
1391 // i.e. the number of bad channels for module 1
1392
1393 const Int_t kBadChannelsArraySize =
1394 2*fBadChannelsObjArray->GetEntries() + fNumberOfModules;
1395 fBadChannelsIntArray = new Int_t[kBadChannelsArraySize]; // Will be deleted in dtor
1396 AliITSChannelSPD *channel = 0;
1397 Int_t i = 0;
1398 Int_t j = 0;
1399 Int_t k = 0;
1400
1401 // Loop over all modules
1402 for (UInt_t module = 0; module < fNumberOfModules; module++)
1403 {
1404 // Encode the number of bad channels of the current module
1405 fBadChannelsIntArray[k++] = fNumberOfBadChannels[module];
1406
1407 // The columns and rows of the fBadChannelsObjArray will be stored sequentially
1408 // in the Int_t array
1409 j = 0;
1410 while (j < fNumberOfBadChannels[module])
1411 {
1412 channel = (AliITSChannelSPD *) fBadChannelsObjArray->At(i++);
1413 fBadChannelsIntArray[k++] = channel->GetColumn();
1414 fBadChannelsIntArray[k++] = channel->GetRow();
1415
1416 // Go to next bad channel
1417 j++;
1418 }
1419 }
1420}
fcf95fc7 1421
1422
1423//__________________________________________________________________________
1424Bool_t AliITSPreprocessorSPD::Store(AliCDBId& /*id*/, AliCDBMetaData* /*md*/, Int_t runNumber)
1425{
1426 // Store the bad channels object in the calibration database
1427 // (See the corresponding run macro for further explanations)
1428 //
1429 // Input : fBadChannelsObjArray (now containing all found bad channels), object meta data
1430 // Output: Database file containing the bad channels
1431 // Return: kTRUE if successful
1432
1433 Bool_t status = kFALSE;
1434
1435 AliInfo("Storing bad channels");
1436
e56160b8 1437 if(!AliCDBManager::Instance()->IsDefaultStorageSet()) {
1438 AliWarning("No storage set! Will use dummy one");
1439 AliCDBManager::Instance()->SetDefaultStorage("local://$ALICE_ROOT");
1440 }
120a99c7 1441
e56160b8 1442
1443 AliCDBEntry *entrySPD = AliCDBManager::Instance()->Get("ITS/Calib/CalibSPD", runNumber);
fcf95fc7 1444 if(!entrySPD){
1445 AliWarning("Calibration object retrieval failed! Dummy calibration will be used.");
e56160b8 1446 AliCDBStorage *origStorage = AliCDBManager::Instance()->GetDefaultStorage();
1447 AliCDBManager::Instance()->SetDefaultStorage("local://$ALICE_ROOT");
fcf95fc7 1448
e56160b8 1449 entrySPD = AliCDBManager::Instance()->Get("ITS/Calib/CalibSPD", runNumber);
1450 AliCDBManager::Instance()->SetDefaultStorage(origStorage);
fcf95fc7 1451 }
1452
1453 TObjArray *respSPD = (TObjArray *)entrySPD->GetObject();
1454
1455 if ((! respSPD)) {
1456 AliWarning("Can not get calibration from calibration database !");
1457 return kFALSE;
1458 }
1459
5bfe44ce 1460
fcf95fc7 1461 Int_t i=0;
1462 AliITSChannelSPD *channel = 0;
1463 AliITSCalibrationSPD* res;
1464 for (Int_t module=0; module<respSPD->GetEntries(); module++) {
fcf95fc7 1465 res = (AliITSCalibrationSPD*) respSPD->At(module);
fcf95fc7 1466 Int_t j = 0;
5bfe44ce 1467 while (j < fNumberOfBadChannels[module]) {
1468 channel = (AliITSChannelSPD *) fBadChannelsObjArray->At(i++);
1469 res->AddDead(channel->GetColumn(),channel->GetRow());
1470 // Go to next bad channel
1471 j++;
1472 }
fcf95fc7 1473 }
5bfe44ce 1474
e56160b8 1475
1476 AliCDBManager::Instance()->Put(entrySPD);
fcf95fc7 1477 entrySPD->SetObject(NULL);
1478 entrySPD->SetOwner(kTRUE);
1479
1480 delete entrySPD;
e56160b8 1481 status=kTRUE;
fcf95fc7 1482 return status;
1483}