1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
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 **************************************************************************/
18 Revision 1.3 2006/04/12 08:32:31 hristov
19 New SPD simulation (Massimo):
20 - speeding up of the diffusion code (Bjorn)
21 - creation of CDB file with the dead channels, implementation
22 of the CDB reading, check of the code (Henrik, Giuseppe, Domenico)
23 - final tuning of the diffusion model parameters (Romualdo)
25 Revision 1.2 2006/02/03 11:31:18 masera
26 Calibration framework improved (E. Crescio)
28 Revision 1.1 2005/10/11 12:31:50 masera
29 Preprocessor classes for SPD (Paul Nilsson)
33 ///////////////////////////////////////////////////////////////////////////
34 // AliITSPreprocessorSPD implementation by P. Nilsson 2005
35 // MAIN AUTHOR/CONTACT: Paul.Nilsson@cern.ch
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
40 // Examples on how to use this class can be found in the macros:
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)
47 // Modified by D. Elia, H. Tydesjo
48 // March 2006: Mixed up coordinates, bug fixed
50 ///////////////////////////////////////////////////////////////////////////
53 #include "AliITSPreprocessorSPD.h"
54 #include "AliCDBEntry.h"
55 #include "AliITSCalibrationSPD.h"
56 ClassImp(AliITSPreprocessorSPD)
57 //__________________________________________________________________________
58 AliITSPreprocessorSPD::AliITSPreprocessorSPD(void):
63 fMaximumNumberOfEvents(1000000),
65 fHighestModuleNumber(0),
68 fSelectedAlgorithm(kOptimizedForRealData),
69 fGeometryMode(kALICEGeometry),
70 fNumberOfBadChannels(0),
75 fBadChannelsObjArray(0),
76 fBadChannelsIntArray(0),
77 fBadChannelsIndexArray(0),
78 fBadChannelsContainer(0)
80 // Default constructor for the SPD preprocessor
82 // Initialization has to be done by hand using Set* methods and the Open method
86 // Return: <empty/uninitialized AliITSPreprocessorSPD object>
90 //__________________________________________________________________________
91 AliITSPreprocessorSPD::AliITSPreprocessorSPD(const char *fileName, const char *mode,
92 const char *fileNameg, const Int_t maxNumberOfEvents):
97 fMaximumNumberOfEvents(1000000),
99 fHighestModuleNumber(0),
102 fSelectedAlgorithm(kOptimizedForRealData),
103 fGeometryMode(kALICEGeometry),
104 fNumberOfBadChannels(0),
109 fBadChannelsObjArray(0),
110 fBadChannelsIntArray(0),
111 fBadChannelsIndexArray(0),
112 fBadChannelsContainer(0)
114 // Standard constructor for the SPD preprocessor
116 // Input : Name of digit file
118 // Return: Initialized SPD preprocessor object
121 AliITSPreprocessorSPD::Init();
122 AliITSPreprocessorSPD::SetMaximumNumberOfEvents(maxNumberOfEvents);
124 // Open and read the galice and digit files
125 if (!AliITSPreprocessorSPD::Open(fileName, mode, fileNameg))
127 AliError("Failed to open file");
133 //__________________________________________________________________________
134 AliITSPreprocessorSPD::AliITSPreprocessorSPD(const AliITSPreprocessorSPD &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),
150 fVMEMode(prep.fVMEMode),
151 fDigitsHistogram(prep.fDigitsHistogram),
152 fBadChannelsObjArray(prep.fBadChannelsObjArray),
153 fBadChannelsIntArray(prep.fBadChannelsIntArray),
154 fBadChannelsIndexArray(prep.fBadChannelsIndexArray),
155 fBadChannelsContainer(prep.fBadChannelsContainer)
157 // Default copy constructor
158 // Notice that only pointer addresses are copied!
159 // Memory allocations of new objects are not done.
165 //__________________________________________________________________________
166 AliITSPreprocessorSPD& AliITSPreprocessorSPD::operator=(const AliITSPreprocessorSPD &prep)
168 // Assignment operator
170 AliError("Not implemented");
172 if (this != &prep) { } // Do not delete this line
178 //__________________________________________________________________________
179 AliITSPreprocessorSPD::~AliITSPreprocessorSPD(void)
181 // Destructor for the SPD preprocessor
183 if (fDigitsHistogram)
185 // try fDigitsHistogram->Delete(); if the following crashes
186 for (UInt_t module = 0; module < fNumberOfModules; module++)
188 (*fDigitsHistogram)[module]->Delete();
190 delete fDigitsHistogram;
191 fDigitsHistogram = 0;
194 if (fNumberOfBadChannels)
196 delete [] fNumberOfBadChannels;
197 fNumberOfBadChannels = 0;
200 if (fBadChannelsIntArray)
202 delete [] fBadChannelsIntArray;
203 fBadChannelsIntArray = 0;
206 if (fBadChannelsIndexArray)
208 delete [] fBadChannelsIndexArray;
209 fBadChannelsIndexArray = 0;
212 if (fBadChannelsObjArray)
214 fBadChannelsObjArray->Delete();
215 delete fBadChannelsObjArray;
216 fBadChannelsObjArray = 0;
222 delete fBadChannelsContainer;
223 fBadChannelsContainer = 0;
227 //__________________________________________________________________________
228 void AliITSPreprocessorSPD::Init(void)
230 // Initialization of the SPD preprocessor
233 // Output: Several logistical variables
236 // Default maximum number of events per histogram
237 fMaximumNumberOfEvents = 1000000;
239 // Default noisy channel removal algorithm
240 fSelectedAlgorithm = kOptimizedForRealData;
242 // Default noisy channel threshold and threshold ratio
243 // (threshold for current bin content divided by the average neighboring bin contents)
245 fThresholdRatio = 5.;
247 // Set default geometry mode (ALICE geometry). This also sets fNumberOfModules
248 AliITSPreprocessorSPD::SetGeometryMode(kALICEGeometry);
250 // The highest module number with found bad channels
251 fHighestModuleNumber = 0;
253 // Assume input is not from a VME file
256 // Initialization is complete
261 //__________________________________________________________________________
262 void AliITSPreprocessorSPD::SetGeometryMode(UInt_t mode)
264 // Set the geometry mode
266 // Input : Geometry mode (either kTestBeamGeometry or kALICEGeometry)
270 fGeometryMode = mode;
272 // In case of an input VME file, the number of modules has already been fixed.
273 // Do not try to change it
276 if (mode == kALICEGeometry)
278 fNumberOfModules = kNumberOfSPDModules;
280 else if (mode == kTestBeamGeometry)
282 fNumberOfModules = kNumberOfTestBeamSPDModules;
286 AliError("Unknown geometry mode, defaults to ALICE geometry");
287 fNumberOfModules = kNumberOfSPDModules;
293 //__________________________________________________________________________
294 void AliITSPreprocessorSPD::SetFakeNoisyChannel(Int_t module, Int_t column, Int_t row)
296 // Introduce a fake noisy channel in the hit histograms
298 // Input : Module, column and row numbers
299 // Output: Updated hit histograms
302 if ((UInt_t)module < fNumberOfModules)
304 ((TH2F*)(*fDigitsHistogram)[module])->Fill(column, row, 1000000);
308 AliError("No such module number");
313 //__________________________________________________________________________
314 Bool_t AliITSPreprocessorSPD::Open(const char *fileName, const char *mode, const char *fileNameg)
318 // Input : Name and mode of ITS digit file, name of galice file
320 // Return: kTRUE if loaders succeed
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;
328 // Only proceed if initialization has been done
331 TString m = (TString)mode;
332 if (m == "daq" || m == "DAQ")
334 // Open the data file and get the run loader
335 fRunLoader = AliRunLoader::Open(fileNameg);
338 // Get the gAlice object
339 status0 = AliITSPreprocessorSPD::GetgAlice();
341 // Get the ITS digits
342 if (status0) status1 = AliITSPreprocessorSPD::GetITSDigits(fileName);
344 // Create the test beam object
345 if (status1) status2 = AliITSPreprocessorSPD::CreateGeometryObj();
347 // Fill histograms with DAQ digits
348 if (status2) status3 = AliITSPreprocessorSPD::FillHistograms();
350 status = status0 & status1 & status2 & status3;
354 AliError("Failed to get the run loader");
357 else if (m == "vme" || m == "VME")
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);
362 if (!vmeFile->IsOpen())
364 AliError("Could not open VME input file");
368 // Get the histograms from the VME file that contains all fired channels
369 status0 = AliITSPreprocessorSPD::GetVMEHistograms(vmeFile);
371 // Create the test beam object
372 if (status0) status1 = AliITSPreprocessorSPD::CreateGeometryObj();
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
380 status = status0 & status1;
384 AliError("Unknown filetype - assuming DAQ file");
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
391 // Create the arrays for bookkeeping and storing the noisy channels
392 if (!fBadChannelsObjArray)
394 fBadChannelsObjArray = new TObjArray();
396 if (!fBadChannelsIndexArray)
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++)
404 fBadChannelsIndexArray[module] = 0;
411 AliError("SPD preprocessor not initialized. Can't load digits");
418 //__________________________________________________________________________
419 Bool_t AliITSPreprocessorSPD::GetgAlice(void)
421 // Get the gAlice object
424 // Output: gAlice object
425 // Return: kTRUE if the gAlice object was found
427 Bool_t status = kTRUE;
430 fRunLoader->LoadgAlice();
431 if (!fRunLoader->GetAliRun())
433 AliError("gAlice not found on file. Aborting.");
441 //__________________________________________________________________________
442 Bool_t AliITSPreprocessorSPD::GetVMEHistograms(TFile *vmeFile)
444 // Get pre-filled digit histograms from input VME file
446 // Input : pointer to VME file
448 // Return: kTRUE if histograms are found on file
450 Bool_t status = kFALSE;
452 // Get the file directory
453 TDirectory *dir = (TDirectory *)vmeFile;
455 // Get the number of keys (histograms in this case corresponding to modules/ladders)
456 fNumberOfModules = dir->GetNkeys();
457 if ((fNumberOfModules > 0) && (fNumberOfModules <= kNumberOfSPDModules))
461 // Create bad channel histograms
462 fDigitsHistogram = new TObjArray(fNumberOfModules);
464 // Create a key iterator
465 TIter nextkey(dir->GetListOfKeys());
468 // Loop over all objects, read them in to memory one by one
470 while ( (key = (TKey *)nextkey()) )
472 (*fDigitsHistogram)[module++] = (TH2F *)key->ReadObj();
475 if (module > fNumberOfModules)
477 AliError("Wrong number of keys in VME file");
485 AliError("Wrong number of histograms in VME file");
490 //__________________________________________________________________________
491 Bool_t AliITSPreprocessorSPD::GetITSDigits(const char *fileName)
493 // Get the ITS digits
495 // Input : name of digits file
496 // Output: fITSLoader object, ITS digits
497 // Return: kTRUE if loader succeed
499 Bool_t status = kTRUE;
501 // Load the gAlice and the header
502 fRunLoader->LoadgAlice();
503 fRunLoader->LoadHeader();
505 // Get the ITS loader
506 fITSLoader = (AliITSLoader*) fRunLoader->GetLoader("ITSLoader");
509 AliError("ITS loader not found");
514 // Open the digits file
515 fITSLoader->SetDigitsFileName(fileName);
522 //__________________________________________________________________________
523 TClonesArray* AliITSPreprocessorSPD::CreateDigitsArray(void) const
525 // Creation of the digits array
529 // Return: Pointer to the SPD digits array
531 // Create an array for 5 chips with 8192 channels each
532 TClonesArray *digitsArray = new TClonesArray("AliITSdigitSPD", kNumberOfChannels);
538 //__________________________________________________________________________
539 Bool_t AliITSPreprocessorSPD::CreateGeometryObj(void)
541 // Creation of the geometry object
543 // This object is used to get the number of SPD half-staves
546 // Output: fGeometryObj
547 // Return: kTRUE if fGeometryObj has been created
549 Bool_t status = true;
551 // Create geometry object
552 // fGeometryObj = new ...
553 // if (!fGeometryObj) status = kFALSE;
555 // Get SPD parameters
556 // fNumberOfColumns = fGeometryObject->GetNumberOfColumns();
557 // fNumberOfRows = fGeometryObject->GetNumberOfRows();
559 fNumberOfColumns = kNumberOfColumns;
560 fNumberOfRows = kNumberOfRows;
566 //__________________________________________________________________________
567 void AliITSPreprocessorSPD::CreateHistograms(void)
569 // Create the noisy channel histograms
572 // Output: Noisy channel histograms
576 char n[4]; // For storing the module number (maximum module number is 240)
578 // Create noisy channel histograms
579 fDigitsHistogram = new TObjArray(fNumberOfModules);
581 for (UInt_t i = 0; i < fNumberOfModules; i++)
584 moduleName = "module_";
586 moduleName.Append(n);
588 (*fDigitsHistogram)[i] = new TH2F(moduleName,"Digits",
589 fNumberOfColumns,-.5,(1.*fNumberOfColumns - .5),
590 fNumberOfRows,-.5,(1.*fNumberOfRows - .5));
595 //__________________________________________________________________________
596 Bool_t AliITSPreprocessorSPD::FillHistograms(void)
598 // Fill the histograms with digits (hit positions of unclustered hits)
600 // (There is one digit histogram per SPD module, i.e. a half-stave, 10 chips)
602 // Input : No arguments (Empty digit histograms)
603 // Output: Filled digit histograms
604 // Return: kTRUE if histograms are filled with digits, kFALSE otherwise
606 AliInfo("Filling noisy channel histograms");
608 Bool_t status = kTRUE;
609 AliITSdigitSPD *digitSPD = 0;
612 TBranch *digitsSPDBranch;
616 fITSLoader->LoadDigits("read");
618 // Create noisy channel histograms
619 AliITSPreprocessorSPD::CreateHistograms();
621 // Create an empty SPD digits array
622 TClonesArray *digitsArraySPD = AliITSPreprocessorSPD::CreateDigitsArray();
624 // Get number of events
625 UInt_t numberOfEvents = (fRunLoader->TreeE()) ? static_cast<UInt_t>(fRunLoader->TreeE()->GetEntries()) : 0;
627 // Make sure we don't try to analyze more data than there actually is
628 if (numberOfEvents < fMaximumNumberOfEvents)
630 fMaximumNumberOfEvents = numberOfEvents;
633 // Loop over all digits and put them in the corresponding histograms
634 if (numberOfEvents > 0)
636 for (UInt_t event = 0; event < fMaximumNumberOfEvents; event++)
638 // Get the current event
639 fRunLoader->GetEvent(event);
641 // Get the ITS digits tree
642 digitsTree = fITSLoader->TreeD();
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);
649 // Reset the SPD digits array to make sure it is empty
650 digitsArraySPD->Clear();
652 // Get the SPD digits branch and set the address
653 digitsSPDBranch = digitsTree->GetBranch("ITSDigitsSPD");
655 digitsSPDBranch->SetAddress(&digitsArraySPD);
657 if (event%100 == 0) AliInfo(Form("Event #%d", event));
659 // Loop over all modules
660 UInt_t numberOfDigits = 0;
661 for (UInt_t module = 0; module < fNumberOfModules; module++)
663 // Get event data for current module
664 digitsTree->GetEvent(module);
666 // Get the number of entries
667 numberOfDigits = digitsArraySPD->GetEntries();
669 // Loop over all digits
670 for (UInt_t digit = 0; digit < numberOfDigits; digit++)
672 // Get the current digit
673 digitSPD = (AliITSdigitSPD*) digitsArraySPD->At(digit);
674 column = digitSPD->GetCoord1();
675 row = digitSPD->GetCoord2();
677 // Fill the digits histogram
678 ((TH2F*)(*fDigitsHistogram)[module])->Fill(column, row);
683 } // end numberOfEvents > 0
691 delete digitsArraySPD;
698 //__________________________________________________________________________
699 Bool_t AliITSPreprocessorSPD::FindDeadChannels(void)
701 // Locate dead channels
703 // Input : Filled hit histograms
704 // Output: TObjArray (fBadChannelsObjArray) with all identified dead channels
705 // Return: kTRUE if dead channels have been found
707 Bool_t status = kFALSE;
709 // Proceed only if properly initialized
714 // Initialize counters
715 fNumberOfBadChannels = new Int_t[fNumberOfModules];
716 for (UInt_t module = 0; module < fNumberOfModules; module++)
718 fNumberOfBadChannels[module] = 0;
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++)
726 status |= AliITSPreprocessorSPD::FindDeadChannelsInModule(module);
731 AliError("Dead channels can only be found in data taken with stand-alone VME system");
736 AliError("Not properly initialized");
743 //__________________________________________________________________________
744 Bool_t AliITSPreprocessorSPD::FindDeadChannelsInModule(UInt_t module)
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".
753 // Input : Filled hit histograms
754 // Output: TObjArray (fBadChannelsObjArray) with all identified noisy channels
755 // Return: kTRUE if dead channels have been found
757 // Store the index number for this module
758 fBadChannelsIndexArray[module] = fIndex++;
760 UInt_t xBin, numberOfXBins;
761 UInt_t yBin, numberOfYBins;
764 numberOfXBins = ((TH2F*)(*fDigitsHistogram)[module])->GetNbinsX();
765 numberOfYBins = ((TH2F*)(*fDigitsHistogram)[module])->GetNbinsY();
767 // Loop over all bins in this histogram
768 for (xBin = 1; xBin <= numberOfXBins; xBin++)
769 for (yBin = 1; yBin <= numberOfYBins; yBin++)
771 binContent = ((TH2F*)(*fDigitsHistogram)[module])->GetBinContent(xBin, yBin);
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)
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));
783 // Store the noisy channel in the array
784 fBadChannelsObjArray->Add(channel);
786 // Keep track of the number of bad channels in this module
787 fNumberOfBadChannels[module]++;
790 // Keep track of the highest module number
791 if (module > fHighestModuleNumber) fHighestModuleNumber = module;
793 //AliInfo(Form("New dead pixel in (m,c,r) = (%d,%d,%d)", module, xBin - 1, yBin - 1));
797 return (fNumberOfBadChannels[module] > 0);
801 //__________________________________________________________________________
802 Bool_t AliITSPreprocessorSPD::FindNoisyChannels(void)
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)
808 // Output: TObjArray (fBadChannelsObjArray) with all identified noisy channels
809 // Return: kTRUE if noisy channels have been found
811 Bool_t status = kFALSE;
813 // Proceed only if properly initialized
816 // (For testing purposes, noisy channels can be inserted here)
817 //SetFakeNoisyChannel(4,10,10);
818 // Initialize counters
819 fNumberOfBadChannels = new Int_t[fNumberOfModules];
820 for (UInt_t module = 0; module < fNumberOfModules; module++)
822 fNumberOfBadChannels[module] = 0;
825 // Scan through all the histogram bins and search for average filling deviations
826 if ((fSelectedAlgorithm == kOptimizedForRealData) || (fSelectedAlgorithm == kOptimizedForRealDataRMS))
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
834 if (fSelectedAlgorithm == kOptimizedForRealData)
836 AliInfo("Searching for noisy channels (optimized for real data)");
840 AliInfo("Searching for noisy channels (optimized for real data, RMS version)");
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++)
848 status |= AliITSPreprocessorSPD::FindNoisyChannelsInModuleAlgo0(module);
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
859 AliInfo("Searching for noisy channels (optimized for calibration data)");
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++)
866 status |= AliITSPreprocessorSPD::FindNoisyChannelsInModuleAlgo1(module);
872 AliError("Not properly initialized");
879 //__________________________________________________________________________
880 Bool_t AliITSPreprocessorSPD::FindNoisyChannelsInModuleAlgo0(UInt_t module)
882 // Locate the noisy channels in a module (optimized for real data)
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.
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.
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
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
909 // Store the index number for this module
910 fBadChannelsIndexArray[module] = fIndex++;
912 UInt_t xBin, numberOfXBins;
913 UInt_t yBin, numberOfYBins;
916 UInt_t numberOfNeighboringBins;
918 Float_t sumBinContent;
919 Float_t neighborBinContent;
920 Float_t maxBinContent;
921 Float_t averageBinContent;
924 numberOfXBins = (UInt_t)((TH2F*)(*fDigitsHistogram)[module])->GetNbinsX();
925 numberOfYBins = (UInt_t)((TH2F*)(*fDigitsHistogram)[module])->GetNbinsY();
927 // Loop over all bins in this histogram
928 for (xBin = 1; xBin <= numberOfXBins; xBin++)
929 for (yBin = 1; yBin <= numberOfYBins; yBin++)
931 numberOfNeighboringBins = 0;
932 averageBinContent = 0.;
934 binContent = ((TH2F*)(*fDigitsHistogram)[module])->GetBinContent(xBin, yBin);
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++)
941 if ( !((neighborXBin == xBin) && (neighborYBin == yBin)) )
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))
948 ((TH2F*)(*fDigitsHistogram)[module])->GetBinContent(neighborXBin, neighborYBin);
950 if (fSelectedAlgorithm == kOptimizedForRealDataRMS)
953 sumBinContent += neighborBinContent*neighborBinContent;
958 sumBinContent += neighborBinContent;
961 if (neighborBinContent > maxBinContent) maxBinContent = neighborBinContent;
963 numberOfNeighboringBins++;
968 // Calculate the average. Remove the largest neighboring bin
969 // (Correction for potential clusters of noisy channels)
970 if (fSelectedAlgorithm == kOptimizedForRealDataRMS)
972 // Square the max bin content before removing it from the average calculation
973 maxBinContent *= maxBinContent;
975 averageBinContent = TMath::Sqrt((sumBinContent - maxBinContent)/(Float_t)(numberOfNeighboringBins - 1));
980 averageBinContent = (sumBinContent - maxBinContent)/(Float_t)(numberOfNeighboringBins - 1);
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) )
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));
995 // Store the noisy channel in the array
996 fBadChannelsObjArray->Add(channel);
998 // Keep track of the number of bad channels in this module
999 fNumberOfBadChannels[module]++;
1002 // Keep track of the highest module number
1003 if (module > fHighestModuleNumber) fHighestModuleNumber = module;
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));
1010 return (fNumberOfBadChannels[module] > 0);
1014 //__________________________________________________________________________
1015 Bool_t AliITSPreprocessorSPD::FindNoisyChannelsInModuleAlgo1(UInt_t module)
1017 // Locate the noisy channels in a module (optimized for calibration data)
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
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
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
1038 // Store the index number for this module
1039 fBadChannelsIndexArray[module] = fIndex++;
1041 UInt_t xBin, numberOfXBins;
1042 UInt_t yBin, numberOfYBins;
1045 numberOfXBins = ((TH2F*)(*fDigitsHistogram)[module])->GetNbinsX();
1046 numberOfYBins = ((TH2F*)(*fDigitsHistogram)[module])->GetNbinsY();
1048 // Loop over all bins in this histogram
1049 for (xBin = 1; xBin <= numberOfXBins; xBin++)
1050 for (yBin = 1; yBin <= numberOfYBins; yBin++)
1052 binContent = ((TH2F*)(*fDigitsHistogram)[module])->GetBinContent(xBin, yBin);
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)
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));
1064 // Store the noisy channel in the array
1065 fBadChannelsObjArray->Add(channel);
1067 // Keep track of the number of bad channels in this module
1068 fNumberOfBadChannels[module]++;
1071 // Keep track of the highest module number
1072 if (module > fHighestModuleNumber) fHighestModuleNumber = module;
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));
1079 return (fNumberOfBadChannels[module] > 0);
1083 //__________________________________________________________________________
1084 void AliITSPreprocessorSPD::PrintChannels(void)
1086 // Print all found bad channels to stdout
1088 // Input : fBadChannelsObjArray
1089 // Output: (dump to stdout)
1094 AliITSChannelSPD *channel = 0;
1096 // Print the bad channels stores in the array
1097 AliInfo("\nModule #\tColumn #\tRow #\n------------------------------------------------");
1098 for (UInt_t module = 0; module < fNumberOfModules; module++)
1101 while (j < fNumberOfBadChannels[module])
1103 channel = (AliITSChannelSPD *) fBadChannelsObjArray->At(i++);
1104 std::cout << module << "\t\t" << channel->GetColumn() << "\t\t" << channel->GetRow() << std::endl;
1106 // Go to next bad channel
1111 AliInfo(Form("%d bad channels were found", fBadChannelsObjArray->GetEntries()));
1115 //__________________________________________________________________________
1116 void AliITSPreprocessorSPD::MarkNoisyChannels(void)
1118 // WARNING: THIS METHOD DOESN'T WORK!!!
1120 // Mark all identified noisy channels
1122 // Input : List of noisy channels, original digits tree
1123 // Output: New digits tree containing SPD digits marked when noisy
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..
1132 // Interpretation of digit status bits (LSB):
1133 // Dead channel Noisy channel | Integer
1134 // -----------------------------------------
1139 // meaning e.g. that a channel that is noisy will have the first bit set in its status bits
1141 // Do not continue unless we are processing DAQ data
1144 AliInfo("Marking bad channels");
1146 // Create the storage container that will be used to access the bad channels
1147 if (!fBadChannelsContainer)
1149 // Add the bad channels array to the storage container
1150 // (ownership is passed to the AliRunDataStorage object)
1151 fBadChannelsContainer = new AliITSBadChannelsSPD();
1153 // Convert the bad channels from TObjArray to Int_t[]
1154 AliITSPreprocessorSPD::ConvertObjToIntArray();
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);
1163 // Create the bad channels helper object
1164 // (will be used to find a bad channel within a TObjArray)
1165 AliITSBadChannelsAuxSPD *aux = new AliITSBadChannelsAuxSPD();
1167 AliITSdigitSPD *digitSPD = 0;
1168 UInt_t numberOfDigits;
1170 Bool_t mark = kFALSE;
1172 TBranch *digitsBranch = 0;
1175 // Create an empty SPD digit array
1176 TObjArray *digitsArraySPD = new TObjArray();
1178 // Get the digits in update mode (we want to modify them if there are noisy channels)
1179 fITSLoader->UnloadDigits();
1180 fITSLoader->LoadDigits("update");
1182 // Get the number of events
1183 UInt_t numberOfEvents = (fRunLoader->TreeE()) ? static_cast<UInt_t>(fRunLoader->TreeE()->GetEntries()) : 0;
1185 // Loop over all events
1186 for (UInt_t event = 0; event < numberOfEvents; event++)
1188 if (event%100 == 0) AliInfo(Form("Event #%d", event));
1190 // Get the current event
1191 fRunLoader->GetEvent(event);
1193 // Get the ITS digits tree
1194 digitsTree = fITSLoader->TreeD();
1196 // Get SPD branch that will contain all digits with marked noisy channels
1197 digitsBranch = digitsTree->GetBranch("ITSDigitsSPD");
1198 digitsBranch->SetAddress(&digitsArraySPD);
1200 // Get the stored number of modules
1201 UInt_t numberOfModules = (Int_t)digitsTree->GetEntries();
1202 TObjArray **newDigitsArraySPD = new TObjArray*[numberOfModules];
1204 Int_t *digitNumber = new Int_t[numberOfModules];
1205 for (UInt_t m = 0; m < numberOfModules; m++)
1207 newDigitsArraySPD[m] = new TObjArray();
1211 AliInfo(Form("ent = %d", (Int_t)digitsTree->GetEntries()));
1213 // Reset the SPD digit arrays to make sure they are empty
1214 digitsArraySPD->Clear();
1216 // Get the SPD digits branch from the original digits tree and set the address
1217 digitsBranch = digitsTree->GetBranch("ITSDigitsSPD");
1218 digitsBranch->SetAddress(&digitsArraySPD);
1220 // Loop over all modules
1221 for (UInt_t module = 0; module < fNumberOfModules; module++)
1223 // Get event data for current module
1224 digitsTree->GetEvent(module);
1226 // Get the hits in the current module
1227 TObjArray *moduleObjArray = fBadChannelsContainer->CreateModuleObjArray(module);
1229 // Get the number of entries
1230 numberOfDigits = digitsArraySPD->GetEntries();
1232 // Loop over all digits and all channels
1233 for (UInt_t digit = 0; digit < numberOfDigits; digit++)
1235 // Get the current digit
1236 digitSPD = (AliITSdigitSPD*) digitsArraySPD->At(digit);
1237 newDigit[0] = digitSPD->GetCoord1(); // column
1238 newDigit[1] = digitSPD->GetCoord2(); // row
1239 newDigit[2] = digitSPD->GetSignal(); // signal
1241 // Check if this channel is noisy
1242 // (Compare with all stored channels in the bad channels array)
1243 if (aux->Find(digitSPD, moduleObjArray))
1245 // Set the mark flag and break the loop
1249 // Store this digit in the SPD digits array using a placement new operation
1250 new ((*newDigitsArraySPD[module])[digitNumber[module]]) AliITSdigitSPD(newDigit);
1252 // Mark it if noisy and store in the noisy channel array
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);
1259 // Mark the original channel as noisy
1260 ((*newDigitsArraySPD[module])[digitNumber[module]])->SetBit(kNoisyChannel);
1265 digitNumber[module]++;
1270 delete moduleObjArray;
1273 } // end module loop
1275 digitsBranch->Reset();
1276 digitsBranch->ResetAddress();
1279 delete digitsArraySPD;
1281 digitsTree->Reset();
1283 // WHY THIS RANGE?????????????????????????????????????????????????????????????????????
1284 for (UInt_t n = 0; n < event; n++)
1286 digitsTree->SetBranchAddress("ITSDigitsSPD", &newDigitsArraySPD[n]);
1290 digitsTree->AutoSave();
1293 for (UInt_t n = 0; n < event; n++)
1295 delete newDigitsArraySPD[n];
1297 delete [] newDigitsArraySPD;
1298 newDigitsArraySPD = 0;
1299 delete [] digitNumber;
1304 } // end loop over all events
1306 // Unload the digits
1307 fITSLoader->UnloadDigits();
1317 //__________________________________________________________________________
1318 Bool_t AliITSPreprocessorSPD::Store(AliCDBId &id, AliCDBMetaData *md)
1320 // Store the bad channels object in the calibration database
1321 // (See the corresponding run macro for further explanations)
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
1327 Bool_t status = kFALSE;
1329 AliInfo("Storing bad channels");
1331 // Add the bad channels array to the storage container
1332 // (ownership is passed to the AliRunDataStorage object)
1333 fBadChannelsContainer = new AliITSBadChannelsSPD();
1335 // Convert the bad channels from TObjArray to Int_t[]
1336 AliITSPreprocessorSPD::ConvertObjToIntArray();
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);
1344 // Store the container
1345 if(!AliCDBManager::Instance()->IsDefaultStorageSet()) {
1346 //AliError("No storage set!");
1348 AliCDBManager::Instance()->SetDefaultStorage("local://Calib");
1351 if (AliCDBManager::Instance()->GetDefaultStorage()->Put(fBadChannelsContainer, id, md))
1353 AliInfo("Bad channels object stored in database");
1358 AliError("Failed to store object in database");
1365 //__________________________________________________________________________
1366 void AliITSPreprocessorSPD::ConvertObjToIntArray()
1368 // Convert the bad channel TObjArray to an Int_t array
1370 // Input : fBadChannelsObjArray (now containing all found bad channels)
1371 // Output: fBadChannelsIntArray
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:
1380 // badChannelsArray =
1381 // | N(m) | col0 | row0 | .. | colN(m) | N(m+1) | col0 | row0 | ...
1382 // . .......... module m ......... . .... module m+1 ......
1384 // The bad channels index array (fBadChannelsIndexArray) contains the indices of
1385 // the badChannelsArray, i.e. where the bad channels in certain module starts:
1387 // fBadChannelsObjArray =
1388 // | i0 | i1 | .. | iM | (where M = the number of SPD modules)
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
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;
1401 // Loop over all modules
1402 for (UInt_t module = 0; module < fNumberOfModules; module++)
1404 // Encode the number of bad channels of the current module
1405 fBadChannelsIntArray[k++] = fNumberOfBadChannels[module];
1407 // The columns and rows of the fBadChannelsObjArray will be stored sequentially
1408 // in the Int_t array
1410 while (j < fNumberOfBadChannels[module])
1412 channel = (AliITSChannelSPD *) fBadChannelsObjArray->At(i++);
1413 fBadChannelsIntArray[k++] = channel->GetColumn();
1414 fBadChannelsIntArray[k++] = channel->GetRow();
1416 // Go to next bad channel
1423 //__________________________________________________________________________
1424 Bool_t AliITSPreprocessorSPD::Store(AliCDBId& /*id*/, AliCDBMetaData* /*md*/, Int_t runNumber)
1426 // Store the bad channels object in the calibration database
1427 // (See the corresponding run macro for further explanations)
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
1433 Bool_t status = kFALSE;
1435 AliInfo("Storing bad channels");
1437 if(!AliCDBManager::Instance()->IsDefaultStorageSet()) {
1438 AliWarning("No storage set! Will use dummy one");
1439 AliCDBManager::Instance()->SetDefaultStorage("local://$ALICE_ROOT");
1443 AliCDBEntry *entrySPD = AliCDBManager::Instance()->Get("ITS/Calib/CalibSPD", runNumber);
1445 AliWarning("Calibration object retrieval failed! Dummy calibration will be used.");
1446 AliCDBStorage *origStorage = AliCDBManager::Instance()->GetDefaultStorage();
1447 AliCDBManager::Instance()->SetDefaultStorage("local://$ALICE_ROOT");
1449 entrySPD = AliCDBManager::Instance()->Get("ITS/Calib/CalibSPD", runNumber);
1450 AliCDBManager::Instance()->SetDefaultStorage(origStorage);
1453 TObjArray *respSPD = (TObjArray *)entrySPD->GetObject();
1456 AliWarning("Can not get calibration from calibration database !");
1462 AliITSChannelSPD *channel = 0;
1463 AliITSCalibrationSPD* res;
1464 for (Int_t module=0; module<respSPD->GetEntries(); module++) {
1465 res = (AliITSCalibrationSPD*) respSPD->At(module);
1467 while (j < fNumberOfBadChannels[module]) {
1468 channel = (AliITSChannelSPD *) fBadChannelsObjArray->At(i++);
1469 res->AddDead(channel->GetColumn(),channel->GetRow());
1470 // Go to next bad channel
1476 AliCDBManager::Instance()->Put(entrySPD);
1477 entrySPD->SetObject(NULL);
1478 entrySPD->SetOwner(kTRUE);