]> git.uio.no Git - u/mrichter/AliRoot.git/blob - MUON/AliMUONPadStatusMaker.cxx
Protection against division by zero.
[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 //-----------------------------------------------------------------------------
19 /// \class AliMUONPadStatusMaker
20 ///
21 /// Make a 2DStore of pad statuses, using different sources of information,
22 /// like pedestal values, gain values, and HV values.
23 ///
24 /// \author Laurent Aphecetche
25 //-----------------------------------------------------------------------------
26
27 #include "AliMUONPadStatusMaker.h"
28
29 #include "AliQAv1.h"
30
31 #include "AliMUON2DMap.h"
32 #include "AliMUON2DStoreValidator.h"
33 #include "AliMUONCalibParamNI.h"
34 #include "AliMUONCalibrationData.h"
35 #include "AliMUONStringIntMap.h"
36 #include "AliMUONVCalibParam.h"
37 #include "AliMUONVTrackerData.h"
38
39 #include "AliMpArea.h"
40 #include "AliMpArrayI.h"
41 #include "AliMpConstants.h"
42 #include "AliMpDDLStore.h"
43 #include "AliMpDEManager.h"
44 #include "AliMpDetElement.h"
45 #include "AliMpDCSNamer.h"
46 #include "AliMpManuUID.h"
47
48 #include "AliCDBEntry.h"
49 #include "AliCDBManager.h"
50 #include "AliCodeTimer.h"
51 #include "AliDCSValue.h"
52 #include "AliLog.h"
53
54 #include <Riostream.h>
55 #include <TArrayI.h>
56 #include <TExMap.h>
57 #include <TFile.h>
58 #include <TKey.h>
59 #include <TMap.h>
60 #include <TROOT.h>
61 #include <TString.h>
62 #include <TSystem.h>
63
64 /// \cond CLASSIMP
65 ClassImp(AliMUONPadStatusMaker)
66 /// \endcond
67
68 //_____________________________________________________________________________
69 AliMUONPadStatusMaker::AliMUONPadStatusMaker(const AliMUONCalibrationData& calibData)
70 : fkCalibrationData(calibData),
71 fGainA1Limits(0,1E30),
72 fGainA2Limits(-1E-30,1E30),
73 fGainThresLimits(0,4095),
74 fHVSt12Limits(0,5000),
75 fHVSt345Limits(0,5000),
76 fPedMeanLimits(0,4095),
77 fPedSigmaLimits(0,4095),
78 fManuOccupancyLimits(0,0.1),
79 fStatus(new AliMUON2DMap(true)),
80 fHV(new TExMap),
81 fPedestals(calibData.Pedestals()),
82 fGains(calibData.Gains()),
83 fTrackerData(0x0),
84 fKillMap(calibData.KillMap())
85 {
86   /// ctor
87   AliDebug(1,Form("ped store %s gain store %s",
88                   fPedestals->ClassName(),
89                   fGains->ClassName()));
90   
91   TString qaFileName(AliQAv1::GetQADataFileName("MUON",calibData.RunNumber()));
92   
93   // search the QA file in memory first.
94   TFile* f = static_cast<TFile*>(gROOT->GetListOfFiles()->FindObject(qaFileName.Data()));
95
96   if (!f)
97   {
98     // then tries to open it
99     if ( gSystem->AccessPathName(qaFileName.Data()) == kFALSE ) 
100     {
101       f = TFile::Open(qaFileName.Data());
102       if ( f )
103       {
104         AliDebug(1,Form("Got %s from disk",qaFileName.Data()));
105       }
106     }
107   }
108   else
109   {
110     AliDebug(1,Form("Got %s from memory",qaFileName.Data()));
111   }
112   
113   if (f)
114   {
115     TDirectory* d = gDirectory;
116     
117     f->cd("MUON/Raws");
118     
119     TIter next(gDirectory->GetListOfKeys());
120     TKey* key;
121     
122     while ( ( key = static_cast<TKey*>(next()) ) && !fTrackerData )
123     {
124       TString name(key->GetName());
125       
126       if ( name.Contains("CALZ") )
127       {
128         fTrackerData = dynamic_cast<AliMUONVTrackerData*>(key->ReadObj());
129       }
130       
131     }
132     
133     gDirectory = d;
134     
135     if ( fTrackerData ) 
136     {
137       AliInfo(Form("Will make a cut on MANU occupancy from TrackerData=%s",fTrackerData->GetName()));
138     }
139     else
140     {
141       AliWarning(Form("Found a QA file = %s, but could not get the expected TrackerData in there... (probably not a serious problem though)",
142                       f->GetName()));
143     }
144   }
145   else
146   {
147     AliWarning("Did not find QA file, so will not use manu occupancy as a criteria");
148   }
149 }
150
151 //_____________________________________________________________________________
152 AliMUONPadStatusMaker::~AliMUONPadStatusMaker()
153 {
154   /// dtor.
155   delete fStatus;
156   delete fHV;
157 }
158
159 //_____________________________________________________________________________
160 TString
161 AliMUONPadStatusMaker::AsString(Int_t status)
162 {
163   /// return a human readable version of the integer status
164   
165   Int_t pedStatus;
166   Int_t gainStatus;
167   Int_t hvStatus;
168   Int_t otherStatus;
169   
170   DecodeStatus(status,pedStatus,hvStatus,gainStatus,otherStatus);
171   
172   TString s;
173   
174   if ( pedStatus & kPedMeanZero ) s += "& Ped Mean is Zero ";
175   if ( pedStatus & kPedMeanTooLow ) s += "& Ped Mean Too Low ";
176   if ( pedStatus & kPedMeanTooHigh ) s += "& Ped Mean Too High ";
177   if ( pedStatus & kPedSigmaTooLow ) s += "& Ped Sigma Too Low ";
178   if ( pedStatus & kPedSigmaTooHigh ) s += "& Ped Sigma Too High ";
179   if ( pedStatus & kPedMissing ) s += "& Ped is missing ";
180   
181         if ( gainStatus & kGainA1TooLow ) s+="& Gain A1 is Too Low ";
182         if ( gainStatus & kGainA1TooHigh ) s+="& Gain A1 is Too High ";
183         if ( gainStatus & kGainA2TooLow ) s+="& Gain A2 is Too Low ";
184         if ( gainStatus & kGainA2TooHigh ) s+="& Gain A2 is Too High ";
185         if ( gainStatus & kGainThresTooLow ) s+="& Gain Thres is Too Low ";
186         if ( gainStatus & kGainThresTooHigh ) s+="& Gain Thres is Too High ";
187         if ( gainStatus & kGainMissing ) s+="& Gain is missing ";
188         
189         if ( hvStatus & kHVError ) s+="& HV is on error ";
190         if ( hvStatus & kHVTooLow ) s+="& HV is Too Low ";
191         if ( hvStatus & kHVTooHigh ) s+="& HV is Too High ";
192         if ( hvStatus & kHVChannelOFF ) s+="& HV has channel OFF ";
193         if ( hvStatus & kHVSwitchOFF ) s+="& HV has switch OFF ";
194         if ( hvStatus & kHVMissing ) s+="& HV is missing ";
195
196   if ( otherStatus & kManuOccupancyTooHigh ) s+="& manu occupancy too high ";
197   if ( otherStatus & kManuOccupancyTooLow ) s+="& manu occupancy too low ";
198   if ( otherStatus & kKilled ) s+="& killed";
199   
200   if ( s[0] == '&' ) s[0] = ' ';
201   
202   return s;
203 }
204
205 //_____________________________________________________________________________
206 TString
207 AliMUONPadStatusMaker::AsCondition(Int_t mask)
208 {
209   /// return a human readable version of the mask's equivalent condition
210   
211   TString s(AsString(mask));
212   
213   s.ReplaceAll("&","|");
214   
215   return s;
216 }
217
218 //_____________________________________________________________________________
219 Int_t
220 AliMUONPadStatusMaker::BuildStatus(Int_t pedStatus, 
221                                    Int_t hvStatus, 
222                                    Int_t gainStatus,
223                                    Int_t otherStatus)
224 {
225   /// Build a complete status from specific parts (ped,hv,gain)
226   
227   return ( hvStatus & 0xFF ) | ( ( pedStatus & 0xFF ) << 8 ) | 
228   ( ( gainStatus & 0xFF ) << 16 ) |
229   ( ( otherStatus & 0xFF ) << 24 ) ;
230 }
231
232 //_____________________________________________________________________________
233 void
234 AliMUONPadStatusMaker::DecodeStatus(Int_t status, 
235                                     Int_t& pedStatus, 
236                                     Int_t& hvStatus, 
237                                     Int_t& gainStatus,
238                                     Int_t& otherStatus)
239 {
240   /// Decode complete status into specific parts (ped,hv,gain)
241   
242   otherStatus = ( status & 0xFF000000 ) >> 24;
243   gainStatus = ( status & 0xFF0000 ) >> 16;
244   pedStatus = ( status & 0xFF00 ) >> 8;
245   hvStatus = (status & 0xFF);
246 }
247
248 //_____________________________________________________________________________
249 Bool_t 
250 AliMUONPadStatusMaker::HVSt12Status(Int_t detElemId, Int_t sector,
251                                     Bool_t& hvChannelTooLow,
252                                     Bool_t& hvChannelTooHigh,
253                                     Bool_t& hvChannelON) const
254 {
255   /// Get HV status for one HV sector of St12
256   
257   /// For a given PCB in a given DE, get the HV status (both the channel
258   /// and the switch).
259   /// Returns false if hv switch changed during the run.
260   
261   AliCodeTimerAuto("")
262   
263   Bool_t error = kFALSE;
264   hvChannelTooLow = kFALSE;
265   hvChannelTooHigh = kFALSE;
266   hvChannelON = kTRUE;
267
268   AliMpDCSNamer hvNamer("TRACKER");
269   
270   TString hvChannel(hvNamer.DCSChannelName(detElemId,sector));
271   
272   TMap* hvMap = fkCalibrationData.HV();
273   TPair* hvPair = static_cast<TPair*>(hvMap->FindObject(hvChannel.Data()));
274   if (!hvPair)
275   {
276     AliError(Form("Did not find expected alias (%s) for DE %d",
277                   hvChannel.Data(),detElemId));  
278     error = kTRUE;
279   }
280   else
281   {
282     TObjArray* values = static_cast<TObjArray*>(hvPair->Value());
283     if (!values)
284     {
285       AliError(Form("Could not get values for alias %s",hvChannel.Data()));
286       error = kTRUE;
287     }
288     else
289     {
290       // find out min and max value, and makes a cut
291       Float_t hvMin(1E9);
292       Float_t hvMax(0);
293       TIter next(values);
294       AliDCSValue* val;
295       
296       while ( ( val = static_cast<AliDCSValue*>(next()) ) )
297       {
298         Float_t hv = val->GetFloat();
299         hvMin = TMath::Min(hv,hvMin);
300         hvMax = TMath::Max(hv,hvMax);
301       }
302       
303       float lowThreshold = fHVSt12Limits.X();
304       float highThreshold = fHVSt12Limits.Y();
305             
306       if ( hvMin < lowThreshold ) hvChannelTooLow = kTRUE;
307       if ( hvMax > highThreshold ) hvChannelTooHigh = kTRUE;
308       if ( hvMin < 1 ) hvChannelON = kFALSE;
309     }
310   }
311   
312   return error;
313 }
314
315 //_____________________________________________________________________________
316 Bool_t 
317 AliMUONPadStatusMaker::HVSt345Status(Int_t detElemId, Int_t pcbIndex,
318                                      Bool_t& hvChannelTooLow,
319                                      Bool_t& hvChannelTooHigh,
320                                      Bool_t& hvChannelON,
321                                      Bool_t& hvSwitchON) const
322 {
323   /// For a given PCB in a given DE, get the HV status (both the channel
324   /// and the switch).
325   /// Returns false if something goes wrong (in particular if 
326   /// hv switch changed during the run).
327   
328   AliCodeTimerAuto("")
329   
330   Bool_t error = kFALSE;
331   hvChannelTooLow = kFALSE;
332   hvChannelTooHigh = kFALSE;
333   hvSwitchON = kTRUE;
334   hvChannelON = kTRUE;
335   
336   AliMpDCSNamer hvNamer("TRACKER");
337   
338   TString hvChannel(hvNamer.DCSChannelName(detElemId));
339   
340   TMap* hvMap = fkCalibrationData.HV();
341   
342   TPair* hvPair = static_cast<TPair*>(hvMap->FindObject(hvChannel.Data()));
343   if (!hvPair)
344   {
345     AliError(Form("Did not find expected alias (%s) for DE %d",
346                   hvChannel.Data(),detElemId));  
347     error = kTRUE;
348   }
349   else
350   {
351     TObjArray* values = static_cast<TObjArray*>(hvPair->Value());
352     if (!values)
353     {
354       AliError(Form("Could not get values for alias %s",hvChannel.Data()));
355       error = kTRUE;
356     }
357     else
358     {
359       // find out min and max value, and makes a cut
360       Float_t hvMin(1E9);
361       Float_t hvMax(0);
362       TIter next(values);
363       AliDCSValue* val;
364       
365       while ( ( val = static_cast<AliDCSValue*>(next()) ) )
366       {
367         Float_t hv = val->GetFloat();
368         hvMin = TMath::Min(hv,hvMin);
369         hvMax = TMath::Max(hv,hvMax);
370       }
371
372       float lowThreshold = fHVSt345Limits.X();
373       float highThreshold = fHVSt345Limits.Y();
374
375       if ( hvMin < lowThreshold ) hvChannelTooLow = kTRUE;
376       else if ( hvMax > highThreshold ) hvChannelTooHigh = kTRUE;
377       if ( hvMin < 1 ) hvChannelON = kFALSE;
378     }
379   }
380   
381   TString hvSwitch(hvNamer.DCSSwitchName(detElemId,pcbIndex));
382   TPair* switchPair = static_cast<TPair*>(hvMap->FindObject(hvSwitch.Data()));
383   if (!switchPair)
384   {
385     AliError(Form("Did not find expected alias (%s) for DE %d PCB %d",
386                   hvSwitch.Data(),detElemId,pcbIndex));
387     error = kTRUE;
388   }
389   else
390   {
391     TObjArray* values = static_cast<TObjArray*>(switchPair->Value());
392     if (!values)
393     {    
394       AliError(Form("Could not get values for alias %s",hvSwitch.Data()));
395       error = kTRUE;
396     }
397     else
398     {
399       // we'll count the number of ON/OFF for this pad, to insure
400       // consistency (i.e. if status changed during the run, we should
401       // at least notify this fact ;-) and hope it's not the norm)
402       Int_t nTrue(0);
403       Int_t nFalse(0);
404       TIter next(values);
405       AliDCSValue* val;
406       
407       while ( ( val = static_cast<AliDCSValue*>(next()) ) )
408       {
409         if ( val->GetBool() )
410         {
411           ++nTrue;
412         }
413         else
414         {
415           ++nFalse;
416         }
417       }
418       
419       if ( (nTrue>0 && nFalse>0) )
420       {
421         AliWarning(Form("Status of HV Switch %s changed during this run nTrue=%d nFalse=%d! Will consider it OFF",
422                         hvSwitch.Data(),nTrue,nFalse));
423         error = kTRUE;
424       }
425       
426       if ( nFalse ) hvSwitchON = kFALSE;
427     }
428   }
429   return error;
430 }
431
432 //_____________________________________________________________________________
433 Int_t
434 AliMUONPadStatusMaker::HVStatus(Int_t detElemId, Int_t manuId) const
435 {
436   /// Get HV status of one manu
437   
438   AliCodeTimerAuto("")
439   
440   if ( !fkCalibrationData.HV() ) return kMissing;
441
442   Long_t lint = fHV->GetValue(AliMpManuUID::BuildUniqueID(detElemId,manuId));
443   
444   if ( lint ) 
445   {
446     return (Int_t)(lint - 1);
447   }
448
449   Int_t status(0);
450   
451   AliMpDCSNamer hvNamer("TRACKER");
452   
453   switch ( AliMpDEManager::GetStationType(detElemId) )
454   {
455     case AliMp::kStation12:
456     {
457       int sector = hvNamer.ManuId2Sector(detElemId,manuId);
458       if ( sector >= 0 ) 
459       {
460         Bool_t hvChannelTooLow, hvChannelTooHigh, hvChannelON;
461         Bool_t error = HVSt12Status(detElemId,sector,
462                                     hvChannelTooLow,
463                                     hvChannelTooHigh,
464                                     hvChannelON);
465         if ( error ) status |= kHVError;
466         if ( hvChannelTooLow ) status |= kHVTooLow;
467         if ( hvChannelTooHigh ) status |= kHVTooHigh; 
468         if ( !hvChannelON ) status |= kHVChannelOFF;
469         // assign this status to all the other manus handled by the same HV channel
470         SetHVStatus(detElemId,sector,status);
471       }
472     }
473       break;
474     case AliMp::kStation345:
475     {
476       int pcbIndex = hvNamer.ManuId2PCBIndex(detElemId,manuId);
477       if ( pcbIndex >= 0 ) 
478       {
479         Bool_t hvChannelTooLow, hvChannelTooHigh, hvChannelON,hvSwitchON;
480         Bool_t error = HVSt345Status(detElemId,pcbIndex,
481                                      hvChannelTooLow,hvChannelTooHigh,
482                                      hvChannelON,hvSwitchON);
483         if ( error ) status |= kHVError;
484         if ( hvChannelTooLow ) status |= kHVTooLow;
485         if ( hvChannelTooHigh ) status |= kHVTooHigh; 
486         if ( !hvSwitchON ) status |= kHVSwitchOFF; 
487         if ( !hvChannelON) status |= kHVChannelOFF;
488         // assign this status to all the other manus handled by the same HV channel
489         SetHVStatus(detElemId,pcbIndex,status);
490       }
491     }
492       break;
493     default:
494       break;
495   }
496   
497   return status;
498 }
499
500 //_____________________________________________________________________________
501 AliMUONVCalibParam* 
502 AliMUONPadStatusMaker::Neighbours(Int_t detElemId, Int_t manuId) const
503 {
504   /// Get the neighbours parameters for a given manu
505   AliMUONVStore* neighbourStore = fkCalibrationData.Neighbours();
506   return static_cast<AliMUONVCalibParam*>(neighbourStore->FindObject(detElemId,manuId));
507 }
508
509 //_____________________________________________________________________________
510 AliMUONVStore* 
511 AliMUONPadStatusMaker::NeighboursStore() const
512 {
513   /// Return the store containing all the neighbours
514   return fkCalibrationData.Neighbours();
515 }
516
517 //_____________________________________________________________________________
518 AliMUONVCalibParam*
519 AliMUONPadStatusMaker::ComputeStatus(Int_t detElemId, Int_t manuId) const
520 {
521   /// Compute the status of a given manu, using all available information,
522   /// i.e. pedestals, gains, and HV
523   
524   AliMUONVCalibParam* param = new AliMUONCalibParamNI(1,AliMpConstants::ManuNofChannels(),detElemId,manuId,-1);
525   fStatus->Add(param);
526
527   AliMUONVCalibParam* pedestals = static_cast<AliMUONVCalibParam*>(fPedestals->FindObject(detElemId,manuId));
528
529   AliMUONVCalibParam* gains = static_cast<AliMUONVCalibParam*>(fGains->FindObject(detElemId,manuId));
530   
531   AliMUONVCalibParam* kill(0x0);
532   
533   if ( fKillMap ) 
534   {
535     kill = static_cast<AliMUONVCalibParam*>(fKillMap->FindObject(detElemId,manuId));
536   }
537   
538   Int_t hvStatus = HVStatus(detElemId,manuId);
539
540   Int_t otherStatus = OtherStatus(detElemId,manuId);
541   
542   for ( Int_t manuChannel = 0; manuChannel < param->Size(); ++manuChannel )
543   {
544     Int_t pedStatus(0);
545     
546     if (pedestals) 
547     {
548       Float_t pedMean = pedestals->ValueAsFloatFast(manuChannel,0);
549       Float_t pedSigma = pedestals->ValueAsFloatFast(manuChannel,1);
550       if ( pedMean < fPedMeanLimits.X() ) pedStatus |= kPedMeanTooLow;
551       else if ( pedMean > fPedMeanLimits.Y() ) pedStatus |= kPedMeanTooHigh;
552       if ( pedSigma < fPedSigmaLimits.X() ) pedStatus |= kPedSigmaTooLow;
553       else if ( pedSigma > fPedSigmaLimits.Y() ) pedStatus |= kPedSigmaTooHigh;
554       if ( pedMean == 0 ) pedStatus |= kPedMeanZero;
555     }
556     else
557     {
558       pedStatus = kPedMissing;
559     }
560     
561     Int_t gainStatus(0);
562   
563     if ( gains ) 
564     {
565       Float_t a0 = gains->ValueAsFloatFast(manuChannel,0);
566       Float_t a1 = gains->ValueAsFloatFast(manuChannel,1);
567       Float_t thres = gains->ValueAsFloatFast(manuChannel,2);
568   
569       if ( a0 < fGainA1Limits.X() ) gainStatus |= kGainA1TooLow;
570       else if ( a0 > fGainA1Limits.Y() ) gainStatus |= kGainA1TooHigh;
571       if ( a1 < fGainA2Limits.X() ) gainStatus |= kGainA2TooLow;
572       else if ( a1 > fGainA2Limits.Y() ) gainStatus |= kGainA2TooHigh;
573       if ( thres < fGainThresLimits.X() ) gainStatus |= kGainThresTooLow;
574       else if ( thres > fGainThresLimits.Y() ) gainStatus |= kGainThresTooHigh;
575     }
576     else
577     {
578       gainStatus = kGainMissing;
579     }
580     
581     if ( kill && (kill->ValueAsInt(manuChannel,0) > 0) ) 
582     {
583       otherStatus |= kKilled;
584     }
585         
586     Int_t status = BuildStatus(pedStatus,hvStatus,gainStatus,otherStatus);
587       
588     param->SetValueAsIntFast(manuChannel,0,status);
589   }
590   
591   return param;
592 }
593
594 //_____________________________________________________________________________
595 Int_t 
596 AliMUONPadStatusMaker::OtherStatus(Int_t detElemId, Int_t manuId) const
597 {
598   /// Get the "other" status for a given manu
599   if ( fTrackerData ) 
600   {
601     Double_t occ = fTrackerData->Manu(detElemId,manuId,2);
602     if ( occ < fManuOccupancyLimits.X() )
603     {
604       return kManuOccupancyTooLow;
605     }
606     if ( occ > fManuOccupancyLimits.Y() )
607     {
608       return kManuOccupancyTooHigh;
609     }
610   }
611   return 0;
612 }
613
614 //_____________________________________________________________________________
615 AliMUONVCalibParam* 
616 AliMUONPadStatusMaker::PadStatus(Int_t detElemId, Int_t manuId) const
617 {
618   /// Get the status container for a given manu
619   
620   AliMUONVCalibParam* param = static_cast<AliMUONVCalibParam*>(fStatus->FindObject(detElemId,manuId));
621   if (!param)
622   {
623     // not already there, so compute it now
624     AliCodeTimerAuto("ComputeStatus");
625     param = ComputeStatus(detElemId,manuId);
626   }
627   return param;
628 }
629
630 //_____________________________________________________________________________
631 Int_t 
632 AliMUONPadStatusMaker::PadStatus(Int_t detElemId, Int_t manuId, Int_t manuChannel) const
633 {
634   /// Get the status for a given channel
635   
636   AliMUONVCalibParam* param = static_cast<AliMUONVCalibParam*>(fStatus->FindObject(detElemId,manuId));
637   if (!param)
638   {
639     // not already there, so compute it now
640     param = ComputeStatus(detElemId,manuId);
641   }
642   return param->ValueAsInt(manuChannel,0);
643 }
644
645 //_____________________________________________________________________________
646 void
647 AliMUONPadStatusMaker::SetHVStatus(Int_t detElemId, Int_t index, Int_t status) const
648 {
649   /// Assign status to all manus in a given HV "zone" (defined by index, meaning
650   /// is different thing from St12 and St345)
651   
652   AliCodeTimerAuto("")
653   
654   AliMpDetElement* de = AliMpDDLStore::Instance()->GetDetElement(detElemId);
655   
656   const AliMpArrayI* manus = de->ManusForHV(index);
657   
658   for ( Int_t i = 0; i < manus->GetSize(); ++ i ) 
659   {
660     Int_t manuId = manus->GetValue(i);
661     fHV->Add(AliMpManuUID::BuildUniqueID(detElemId,manuId),status + 1);
662   }
663 }