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