Instead of crashing, allow some holes in the calibration data, and simply accounts...
[u/mrichter/AliRoot.git] / MUON / AliMUONPadStatusMaker.cxx
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 // $Id$
17 /// \class AliMUONPadStatusMaker
18 ///
19 /// Make a 2DStore of pad statuses, using different sources of information,
20 /// like pedestal values, gain values, and HV values.
21 ///
22 ///
23 // Author Laurent Aphecetche
24
25 #include "AliMUONPadStatusMaker.h"
26
27 #include "AliMUON2DMap.h"
28 #include "AliMUONCalibParam1I.h"
29 #include "AliMUONCalibrationData.h"
30 #include "AliMUONHVNamer.h"
31 #include "AliMUONObjectPair.h"
32 #include "AliMUONVCalibParam.h"
33 #include "AliMUONVDataIterator.h"
34
35 #include "AliMpArea.h"
36 #include "AliMpDEIterator.h"
37 #include "AliMpDEManager.h"
38 #include "AliMpIntPair.h"
39 #include "AliMpManuList.h"
40 #include "AliMpMotifMap.h"
41 #include "AliMpMotifPosition.h"
42 #include "AliMpPCB.h"
43 #include "AliMpPad.h"
44 #include "AliMpSector.h"
45 #include "AliMpSectorSegmentation.h"
46 #include "AliMpSegmentation.h"
47 #include "AliMpSlat.h"
48 #include "AliMpSlatSegmentation.h"
49 #include "AliMpStationType.h"
50 #include "AliMpVPadIterator.h"
51 #include "AliMUON2DStoreValidator.h"
52 #include "AliCDBManager.h"
53 #include "AliCDBEntry.h"
54 #include "AliDCSValue.h"
55 #include "AliLog.h"
56
57 #include "Riostream.h"
58 #include "TMap.h"
59 #include "TStopwatch.h"
60 #include "TString.h"
61
62 #include <cassert>
63
64 ClassImp(AliMUONPadStatusMaker)
65
66 //_____________________________________________________________________________
67 AliMUONPadStatusMaker::AliMUONPadStatusMaker(const AliMUONCalibrationData& calibData)
68 : fCalibrationData(calibData),
69   fPedMeanLimits(0,4095),
70   fPedSigmaLimits(0,4095),
71   fHVSt12Limits(0,5000),
72   fHVSt345Limits(0,5000)
73 {
74     // ctor
75 }
76
77 //_____________________________________________________________________________
78 AliMUONPadStatusMaker::~AliMUONPadStatusMaker()
79 {
80   // dtor.
81 }
82
83 //_____________________________________________________________________________
84 AliMUONV2DStore*
85 AliMUONPadStatusMaker::Combine(const AliMUONV2DStore& store1,
86                                const AliMUONV2DStore& store2,
87                                Int_t binShift) const
88 {
89   /// Combine two status containers into one, shifting store2 status bits
90   /// to the left by binShift before making an OR with store1.
91   
92   TStopwatch timer;
93   timer.Start(kTRUE);
94   
95   AliMUONV2DStore* combined = static_cast<AliMUONV2DStore*>(store1.Clone());
96   
97   AliMUONVDataIterator* it = store1.Iterator();
98   AliMUONObjectPair* pair;
99   
100   while ( ( pair = static_cast<AliMUONObjectPair*>(it->Next()) ) )
101   {
102     AliMpIntPair* ip = static_cast<AliMpIntPair*>(pair->First());
103     Int_t detElemId = ip->GetFirst();
104     Int_t manuId = ip->GetSecond();
105     AliMUONVCalibParam* param1 = static_cast<AliMUONVCalibParam*>(store1.Get(detElemId,manuId));
106     AliMUONVCalibParam* param2 = static_cast<AliMUONVCalibParam*>(store2.Get(detElemId,manuId));
107     if (!param2)
108     {
109       AliWarning(Form("Could not get statuses for store2 for DE %d ManuId %d. Marking as missing.",
110                     detElemId,manuId));
111       param2 = static_cast<AliMUONVCalibParam*>(param1->Clone());
112       for ( Int_t manuChannel = 0; manuChannel < param2->Size(); ++manuChannel )
113       {
114         param2->SetValueAsInt(manuChannel,0,kMissing);
115       }      
116     }
117     AliMUONVCalibParam* paramCombined = static_cast<AliMUONVCalibParam*>(combined->Get(detElemId,manuId));
118     if (!paramCombined)
119     {
120       paramCombined = static_cast<AliMUONVCalibParam*>(param2->Clone());
121       combined->Set(detElemId,manuId,paramCombined,kFALSE);
122     }
123     
124     for ( Int_t manuChannel = 0; manuChannel < param1->Size(); ++manuChannel )
125     {
126       if ( AliMpManuList::DoesChannelExist(detElemId, manuId, manuChannel) )
127       {
128         Int_t status1(param1->ValueAsInt(manuChannel));
129         Int_t status2(param2->ValueAsInt(manuChannel));
130         
131         Int_t status = status1 | (status2 << binShift);
132         
133         paramCombined->SetValueAsInt(manuChannel,0,status);
134       }
135     }
136   }
137   
138   delete it;
139   
140   AliInfo("Timer:");
141   StdoutToAliInfo(timer.Print(););
142   
143   return combined;
144 }
145
146 //_____________________________________________________________________________
147 AliMUONV2DStore* 
148 AliMUONPadStatusMaker::GeneratePadStatus(Int_t value)
149 {
150   /// Generate a "fake" store, with all (detElemId,manuId) present,
151   /// and containing all the same value
152   
153   AliMUONCalibParam1I param(64,value);
154   
155   return AliMUON2DMap::Generate(param);
156 }
157
158 //_____________________________________________________________________________
159 Bool_t 
160 AliMUONPadStatusMaker::GetSt12Status(const TMap& hvMap,
161                                      Int_t detElemId, Int_t sector,
162                                      Bool_t& hvChannelTooLow,
163                                      Bool_t& hvChannelTooHigh,
164                                      Bool_t& hvChannelON) const
165 {
166   /// Get HV status for one HV sector of St12
167   
168   /// For a given PCB in a given DE, get the HV status (both the channel
169   /// and the switch).
170   /// Returns false if hv switch changed during the run.
171   
172   Bool_t error = kFALSE;
173   hvChannelTooLow = kFALSE;
174   hvChannelTooHigh = kFALSE;
175   hvChannelON = kTRUE;
176   
177   AliMUONHVNamer hvNamer;
178   
179   TString hvChannel(hvNamer.DCSHVChannelName(detElemId,sector));
180   
181   TPair* hvPair = static_cast<TPair*>(hvMap.FindObject(hvChannel.Data()));
182   if (!hvPair)
183   {
184     AliError(Form("Did not find expected alias (%s) for DE %d",
185                   hvChannel.Data(),detElemId));  
186     error = kTRUE;
187   }
188   else
189   {
190     TObjArray* values = static_cast<TObjArray*>(hvPair->Value());
191     if (!values)
192     {
193       AliError(Form("Could not get values for alias %s",hvChannel.Data()));
194       error = kTRUE;
195     }
196     else
197     {
198       // find out min and max value, and makes a cut
199       Float_t hvMin(1E9);
200       Float_t hvMax(0);
201       TIter next(values);
202       AliDCSValue* val;
203       
204       while ( ( val = static_cast<AliDCSValue*>(next()) ) )
205       {
206         Float_t hv = val->GetFloat();
207         hvMin = TMath::Min(hv,hvMin);
208         hvMax = TMath::Max(hv,hvMax);
209       }
210       
211       float lowThreshold = fHVSt12Limits.X();
212       float highThreshold = fHVSt12Limits.Y();
213             
214       if ( hvMin < lowThreshold ) hvChannelTooLow = kTRUE;
215       if ( hvMax > highThreshold ) hvChannelTooHigh = kTRUE;
216       if ( hvMin < 1 ) hvChannelON = kFALSE;
217     }
218   }
219   
220   return error;
221 }
222
223 //_____________________________________________________________________________
224 Bool_t 
225 AliMUONPadStatusMaker::GetSt345Status(const TMap& hvMap,
226                                       Int_t detElemId, Int_t pcbIndex,
227                                       Bool_t& hvChannelTooLow,
228                                       Bool_t& hvChannelTooHigh,
229                                       Bool_t& hvChannelON,
230                                       Bool_t& hvSwitchON) const
231 {
232   /// For a given PCB in a given DE, get the HV status (both the channel
233   /// and the switch).
234   /// Returns false if something goes wrong (in particular if 
235   /// hv switch changed during the run).
236   
237   Bool_t error = kFALSE;
238   hvChannelTooLow = kFALSE;
239   hvChannelTooHigh = kFALSE;
240   hvSwitchON = kTRUE;
241   hvChannelON = kTRUE;
242   
243   AliMUONHVNamer hvNamer;
244   
245   TString hvChannel(hvNamer.DCSHVChannelName(detElemId));
246   
247   TPair* hvPair = static_cast<TPair*>(hvMap.FindObject(hvChannel.Data()));
248   if (!hvPair)
249   {
250     AliError(Form("Did not find expected alias (%s) for DE %d",
251                   hvChannel.Data(),detElemId));  
252     error = kTRUE;
253   }
254   else
255   {
256     TObjArray* values = static_cast<TObjArray*>(hvPair->Value());
257     if (!values)
258     {
259       AliError(Form("Could not get values for alias %s",hvChannel.Data()));
260       error = kTRUE;
261     }
262     else
263     {
264       // find out min and max value, and makes a cut
265       Float_t hvMin(1E9);
266       Float_t hvMax(0);
267       TIter next(values);
268       AliDCSValue* val;
269       
270       while ( ( val = static_cast<AliDCSValue*>(next()) ) )
271       {
272         Float_t hv = val->GetFloat();
273         hvMin = TMath::Min(hv,hvMin);
274         hvMax = TMath::Max(hv,hvMax);
275       }
276
277       float lowThreshold = fHVSt345Limits.X();
278       float highThreshold = fHVSt345Limits.Y();
279
280       if ( hvMin < lowThreshold ) hvChannelTooLow = kTRUE;
281       if ( hvMax > highThreshold ) hvChannelTooHigh = kTRUE;
282       if ( hvMin < 1 ) hvChannelON = kFALSE;
283     }
284   }
285   
286   TString hvSwitch(hvNamer.DCSHVSwitchName(detElemId,pcbIndex));
287   TPair* switchPair = static_cast<TPair*>(hvMap.FindObject(hvSwitch.Data()));
288   if (!switchPair)
289   {
290     AliError(Form("Did not find expected alias (%s) for DE %d PCB %d",
291                   hvSwitch.Data(),detElemId,pcbIndex));
292     error = kTRUE;
293   }
294   else
295   {
296     TObjArray* values = static_cast<TObjArray*>(switchPair->Value());
297     if (!values)
298     {    
299       AliError(Form("Could not get values for alias %s",hvSwitch.Data()));
300       error = kTRUE;
301     }
302     else
303     {
304       // we'll count the number of ON/OFF for this pad, to insure
305       // consistency (i.e. if status changed during the run, we should
306       // at least notify this fact ;-) and hope it's not the norm)
307       Int_t nTrue(0);
308       Int_t nFalse(0);
309       TIter next(values);
310       AliDCSValue* val;
311       
312       while ( ( val = static_cast<AliDCSValue*>(next()) ) )
313       {
314         if ( val->GetBool() )
315         {
316           ++nTrue;
317         }
318         else
319         {
320           ++nFalse;
321         }
322       }
323       
324       if ( (nTrue>0 && nFalse>0) )
325       {
326         AliWarning(Form("Status of HV Switch %s changed during this run nTrue=%d nFalse=%d! Will consider it OFF",
327                         hvSwitch.Data(),nTrue,nFalse));
328         error = kTRUE;
329       }
330       
331       if ( nFalse ) hvSwitchON = kFALSE;
332     }
333   }
334   return error;
335 }
336
337 //_____________________________________________________________________________
338 AliMUONV2DStore* 
339 AliMUONPadStatusMaker::MakeGainStatus(const AliMUONV2DStore& /*gainValues*/) const
340 {
341   /// FIXME: to be implemented
342   AliWarning("Not implemented yet");
343   return 0x0;
344 }
345
346 //_____________________________________________________________________________
347 AliMUONV2DStore* 
348 AliMUONPadStatusMaker::MakeHVStatus(const TMap& hvValues) const
349 {
350   /// Scrutinize HV values and deduce an HV status for each pad
351   
352   TStopwatch timerSt12;
353   TStopwatch timerSt345;
354   
355   timerSt12.Start(kTRUE);
356   timerSt12.Stop();
357   timerSt345.Start(kTRUE);
358   timerSt345.Stop();
359   
360   AliMUONHVNamer hvNamer;
361   
362   AliMpDEIterator deIt;
363   
364   deIt.First();
365   
366   AliMUONV2DStore* hv = new AliMUON2DMap(kTRUE);
367   
368   while ( !deIt.IsDone() )
369   {
370     Int_t detElemId = deIt.CurrentDEId();
371     
372     switch ( AliMpDEManager::GetStationType(detElemId) )
373     {
374       case AliMp::kStation1:
375       case AliMp::kStation2:
376         timerSt12.Start(kFALSE);
377         for ( int sector = 0; sector < 3; ++sector)
378         {
379           AliDebug(1,Form("detElemId %5d sector %d",detElemId,sector));
380
381           Bool_t hvChannelTooLow, hvChannelTooHigh, hvChannelON;
382           Bool_t error = GetSt12Status(hvValues,
383                                        detElemId,sector,
384                                        hvChannelTooLow,hvChannelTooHigh,
385                                        hvChannelON);
386           Int_t status = 0;
387           if ( error ) status |= kHVError;
388           if ( hvChannelTooLow ) status |= kHVTooLow;
389           if ( hvChannelTooHigh ) status |= kHVTooHigh; 
390           if ( !hvChannelON ) status |= kHVChannelOFF;
391           SetStatusSt12(*hv,detElemId,sector,status);
392           
393         }
394           timerSt12.Stop();
395         break;
396       case AliMp::kStation345:
397       {
398         timerSt345.Start(kFALSE);
399         for ( Int_t pcbIndex = 0; pcbIndex < hvNamer.NumberOfPCBs(detElemId); ++pcbIndex)
400         {
401           AliDebug(1,Form("detElemId %5d pcbIndex %d",detElemId,pcbIndex));
402           Bool_t hvChannelTooLow, hvChannelTooHigh, hvChannelON,hvSwitchON;
403           Bool_t error = GetSt345Status(hvValues,
404                                         detElemId,pcbIndex,
405                                         hvChannelTooLow,hvChannelTooHigh,
406                                         hvChannelON,hvSwitchON);
407           Int_t status = 0;
408           if ( error ) status |= kHVError;
409           if ( hvChannelTooLow ) status |= kHVTooLow;
410           if ( hvChannelTooHigh ) status |= kHVTooHigh; 
411           if ( !hvSwitchON ) status |= kHVSwitchOFF; 
412           if ( !hvChannelON) status |= kHVChannelOFF;
413           SetStatusSt345(*hv,detElemId,pcbIndex,status);
414         }
415         timerSt345.Stop();
416       }
417         break;
418       default:
419         break;
420     }
421     deIt.Next();
422   }
423   
424   AliInfo("St12 timer:");
425   StdoutToAliInfo(timerSt12.Print(););
426   AliInfo("St345 timer:");
427   StdoutToAliInfo(timerSt345.Print(););
428   
429   return hv;
430 }
431
432 //_____________________________________________________________________________
433 AliMUONV2DStore* 
434 AliMUONPadStatusMaker::MakePedestalStatus(const AliMUONV2DStore& pedValues) const
435 {
436   /// Assign a pedestal status to each pad
437   
438   TStopwatch timer;
439   
440   timer.Start(kTRUE);
441   
442   AliMUONV2DStore* pedStatuses = new AliMUON2DMap(kTRUE);
443   
444   AliMUONVDataIterator* it = pedValues.Iterator();
445   AliMUONObjectPair* pair;
446   Int_t nofManus(0);
447   
448   while ( ( pair = static_cast<AliMUONObjectPair*>(it->Next() ) ) )
449   {
450     AliMpIntPair* ip = static_cast<AliMpIntPair*>(pair->First());
451     Int_t detElemId = ip->GetFirst();
452     Int_t manuId = ip->GetSecond();
453     AliMUONVCalibParam* pedestals = static_cast<AliMUONVCalibParam*>(pair->Second());
454     ++nofManus;
455     for ( Int_t manuChannel = 0; manuChannel < pedestals->Size(); ++manuChannel )
456     {
457       Int_t status(0);
458       if ( AliMpManuList::DoesChannelExist(detElemId, manuId, manuChannel) )
459       {
460         Float_t pedMean = pedestals->ValueAsFloat(manuChannel,0);
461         Float_t pedSigma = pedestals->ValueAsFloat(manuChannel,1);
462         if ( pedMean < fPedMeanLimits.X() ) status |= kPedMeanTooLow;
463         if ( pedMean > fPedMeanLimits.Y() ) status |= kPedMeanTooHigh;
464         if ( pedSigma < fPedSigmaLimits.X() ) status |= kPedSigmaTooLow;
465         if ( pedSigma > fPedSigmaLimits.Y() ) status |= kPedSigmaTooHigh;
466         if ( pedMean == 0 ) status |= kPedMeanZero;
467         
468         AliMUONVCalibParam* vStatus = 
469           static_cast<AliMUONVCalibParam*>(pedStatuses->Get(detElemId,manuId));
470         if ( !vStatus ) 
471         {
472           vStatus = new AliMUONCalibParam1I(64,0);
473           pedStatuses->Set(detElemId,manuId,vStatus,false);
474         }
475         vStatus->SetValueAsInt(manuChannel,0,status);
476       }
477     }
478   }
479   
480   AliInfo(Form("%d manus checked in :",nofManus));
481   StdoutToAliInfo(timer.Print(););
482   return pedStatuses;  
483 }
484
485 //_____________________________________________________________________________
486 AliMUONV2DStore* 
487 AliMUONPadStatusMaker::MakeStatus() const
488 {
489   /// Read ped, gains and hv values from CDB, apply some Q&A and produces
490   /// a combined status for each pad.
491
492   TMap* hvValues = fCalibrationData.HV();
493   AliMUONV2DStore* hvStatus(0x0);
494   
495   if (!hvValues)
496   {
497     AliError("Could not get HV values from CDB. Will create dummy ones and mark those as missing");
498     AliMUONCalibParam1I param(64,kHVMissing);
499     hvStatus = AliMUON2DMap::Generate(param);
500   }
501   else
502   {
503     hvStatus = MakeHVStatus(*hvValues);
504   }
505   
506   AliMUONV2DStore* pedValues = fCalibrationData.Pedestals();
507   AliMUONV2DStore* pedStatus(0x0);
508
509   if (!pedValues)
510   {
511     AliError("Could not get pedestals values from CDB. Will create dummy ones and mark those as missing");
512     AliMUONCalibParam1I param(64,kPedMissing);
513     pedStatus = AliMUON2DMap::Generate(param);
514   }
515   else
516   {
517     pedStatus = MakePedestalStatus(*pedValues);
518   }
519   
520   // FIXME: should do the same for gains as for hv and ped.    
521   
522   AliMUONV2DStore* status = Combine(*hvStatus,*pedStatus,8);
523   
524   delete hvStatus;
525   delete pedStatus;
526   
527   // Insure we get all channels there (some or even all can be bad, but they
528   // must be there somehow).
529   
530   AliMUON2DStoreValidator validator;
531         
532   TObjArray* a = validator.Validate(*status);
533     
534   if (a) 
535   {
536     // this should not happen.
537     AliError("Status store not complete. Crash to follow soon...");
538     StdoutToAliError(a->Print(););
539     AliFatal("this should not happen at all!");
540     delete status;
541     status = 0x0;
542   }
543     
544   return status;
545 }
546
547 //_____________________________________________________________________________
548 void
549 AliMUONPadStatusMaker::SetStatusSt12(AliMUONV2DStore& hvStatus,
550                                      Int_t detElemId, 
551                                      Int_t isector,
552                                      Int_t status) const
553 {
554   /// Flag all pads of detElemId (for St12) as bad.
555   
556   // FIXME: need a way to iterator on pads over a given HV sector for St12... 
557   // we currently suppose that one sector is about a third of the chamber...
558   // FIXME !! This has to be checked very carefully...
559   
560   const AliMp::CathodType kCathodes[] = { AliMp::kCath0, AliMp::kCath1 };
561   
562   for ( Int_t icathode = 0; icathode < 2; ++icathode )
563   {
564     const AliMpSectorSegmentation* seg = 
565     static_cast<const AliMpSectorSegmentation*>(AliMpSegmentation::Instance()->GetMpSegmentation(detElemId,kCathodes[icathode]));
566     const AliMpSector* sector = seg->GetSector();
567     AliMpMotifMap* mMap = sector->GetMotifMap();
568     TArrayI a;
569     
570     mMap->GetAllMotifPositionsIDs(a);
571     
572     TVector2 dim = seg->Dimensions();
573     Double_t x = dim.X()*2;
574     Double_t xmin = isector*x/3.0;
575     Double_t xmax = xmin + x/3.0;   
576     
577     for ( Int_t i = 0; i < a.GetSize(); ++i ) 
578     {
579       AliMpMotifPosition* pos = mMap->FindMotifPosition(a[i]);
580       Int_t manuId = pos->GetID();
581       TVector2 position = pos->Position();
582       if ( position.X() >= xmin && position.X() <= xmax) 
583       {
584         AliMUONVCalibParam* dead =
585         static_cast<AliMUONVCalibParam*>(hvStatus.Get(detElemId,manuId));
586         if (!dead)
587         {
588           dead = new AliMUONCalibParam1I(64,status);
589           hvStatus.Set(detElemId,manuId,dead,false);
590         }        
591         else
592         {
593           // FIXME: this should really not happen, if we'd know really the
594           // relationship between manuId and HV sector...
595           // For the time being, let's leave it like that, for testing
596           // purposes only. For production, this will have to be fixed.
597           AliWarning("Please fixme.");
598         }
599       }
600     }
601   }  
602 }
603
604 //_____________________________________________________________________________
605 void
606 AliMUONPadStatusMaker::SetStatusSt345(AliMUONV2DStore& hvStatus,
607                                       Int_t detElemId, Int_t pcbIndex,
608                                       Int_t status) const
609 {
610   /// Flag all pads of pcbIndex-th PCB of detElemId (for St345) as bad.
611   
612   const AliMp::CathodType kCathodes[] = { AliMp::kCath0, AliMp::kCath1 };
613   
614   for ( Int_t icathode = 0; icathode < 2; ++icathode )
615   {
616     const AliMpSlatSegmentation* seg = static_cast<const AliMpSlatSegmentation*>
617     (AliMpSegmentation::Instance()->GetMpSegmentation(detElemId,kCathodes[icathode]));
618     const AliMpSlat* slat = seg->Slat();
619     const AliMpPCB* pcb = slat->GetPCB(pcbIndex);
620
621     for ( Int_t i = 0; i < pcb->GetSize(); ++i ) 
622     {
623       AliMpMotifPosition* pos = pcb->GetMotifPosition(i);
624       Int_t manuId = pos->GetID();
625       AliMUONVCalibParam* dead = 
626         static_cast<AliMUONVCalibParam*>(hvStatus.Get(detElemId,manuId));
627       if (dead)
628       {
629         AliError(Form("dead is not null as expected from DE %d manuId %d",
630                       detElemId,manuId));
631       }
632       if (!dead)
633       {
634         dead = new AliMUONCalibParam1I(64,status);
635         hvStatus.Set(detElemId,manuId,dead,false);
636       }
637     }    
638   }
639 }
640
641
642