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 #include "AliMUONTrackerQAChecker.h"
20 /// \class AliMUONTrackerQAChecker
22 /// Implementation of AliQACheckerBase for MCH and MTR
24 /// For the moment we only implement the checking of raw data QA for the tracker
25 /// by looking at the occupancy at the bus patch level.
27 /// \author Laurent Aphecetche, Subatech
29 #include "AliCDBManager.h"
30 #include "AliCodeTimer.h"
32 #include "AliMUONQAIndices.h"
33 #include "AliMUONRecoParam.h"
34 #include "AliMpBusPatch.h"
35 #include "AliMpDDLStore.h"
37 #include "Riostream.h"
39 #include "TDirectory.h"
44 #include "TPaveText.h"
45 #include "TVirtualPad.h"
50 ClassImp(AliMUONTrackerQAChecker)
55 //___________________________________________________________________________
65 // Calculates the trimmed (tmean) mean
66 // of a sample (x) and estimates the variance (tvar)
70 // First check input parameters
72 // number of observations
78 if ( alpha < 0 || alpha >= 0.5 )
79 // proportion of observations
80 // to be trimmed at each end of the sorted sample
85 // Input parameters are good. Let's move on.
87 // Insure we use a sample sorted into ascending order.
89 Int_t* indices = new Int_t[n];
91 TMath::Sort(n,x,indices,kFALSE);
93 Double_t* sx = new Double_t[n];
95 for ( Int_t i = 0; i < n; ++i )
97 sx[i] = x[indices[i]];
102 // Number of observations trimmed at each end.
104 Int_t k = TMath::FloorNint(alpha * n);
108 for ( Int_t i = k; i < n - k ; ++i )
113 tmean = sum / ( n - 2 * k );
117 for ( Int_t i = k; i < n - k; ++i )
119 t2 += (sx[i] - tmean) * (sx[i] - tmean);
124 k * (sx[k] - tmean) * (sx[k] - tmean) +
125 k * (sx[n - k - 1] - tmean) * (sx[n - k - 1] - tmean)
128 // get the min and max for the non-rejected values
132 for ( Int_t i = k; i < n-k; ++i )
134 min = TMath::Min(min,sx[i]);
135 max = TMath::Max(max,sx[i]);
143 //___________________________________________________________________________
144 Int_t GetColorFromCheckCode(AliMUONVQAChecker::ECheckCode code)
146 if ( code == AliMUONVQAChecker::kInfo ) return AliMUONVQAChecker::kInfoColor;
147 else if ( code == AliMUONVQAChecker::kWarning ) return AliMUONVQAChecker::kWarningColor;
148 else if ( code == AliMUONVQAChecker::kFatal) return AliMUONVQAChecker::kFatalColor;
149 else return AliMUONVQAChecker::kErrorColor;
152 const char* NOTENOUGHEVENTMESSAGE = "Not enough event to judge. Please wait a bit";
153 const char* NOTIFYEXPERTMESSAGE = "PLEASE NOTIFY EXPERT !";
154 const char* ALLISFINEMESSAGE = "All is fine. Just enjoy.";
156 const int NOTENOUGHEVENTLIMIT = 50;
158 //___________________________________________________________________________
159 void SetupHisto(Int_t neventsseen, Int_t neventsused, const TObjArray& messages, TH1& histo, AliMUONVQAChecker::ECheckCode code, const char* extraopt="")
161 Bool_t allIsFine(kFALSE);
163 if ( code == AliMUONVQAChecker::kInfo )
168 Double_t y1 = 0.99 - (messages.GetLast()+(allIsFine?1:0)+2)*0.075;
170 TPaveText* text = new TPaveText(0.5,y1,0.99,0.99,"NDC");
172 text->AddText(Form("MCH RUN %d - %d events seen - %d events used",AliCDBManager::Instance()->GetRun(),neventsseen,neventsused));
174 TIter next(&messages);
177 while ( ( str = static_cast<TObjString*>(next()) ) )
179 text->AddText(str->String());
184 text->AddText(ALLISFINEMESSAGE);
187 text->SetFillColor(GetColorFromCheckCode(code));
189 Int_t color = GetColorFromCheckCode(code);
191 histo.SetFillStyle(1001);
192 histo.SetFillColor(color);
195 histo.SetOption(sopt.Data());
197 histo.SetBit(TH1::kNoTitle);
199 TList* lstF = histo.GetListOfFunctions();
200 TObject* title = lstF->FindObject("title");
201 if (title) delete lstF->Remove(title);
207 //___________________________________________________________________________
208 void ShowTrueValue(TH1& hrostatusnorm, Int_t v)
210 // For a bar > 100% we put the text inside the bar (as TEXT45 option is putting above which
211 // would go offscreen)
213 Int_t bin = hrostatusnorm.FindBin(1.0*v);
215 Double_t value = hrostatusnorm.GetBinContent(bin);
219 TLatex* l = new TLatex(hrostatusnorm.GetBinCenter(bin),50,Form("%g",value));
220 l->SetTextFont(gStyle->GetTextFont());
223 l->SetTextSize(0.02*hrostatusnorm.GetMarkerSize());
224 hrostatusnorm.GetListOfFunctions()->Add(l);
229 //__________________________________________________________________
230 AliMUONTrackerQAChecker::AliMUONTrackerQAChecker() : AliMUONVQAChecker()
235 //__________________________________________________________________
236 AliMUONTrackerQAChecker::~AliMUONTrackerQAChecker()
241 //______________________________________________________________________________
242 AliMUONVQAChecker::ECheckCode*
243 AliMUONTrackerQAChecker::CheckRecPoints(TObjArray ** list, const AliMUONRecoParam* /*recoParam*/)
246 /// Very binary check for the moment.
248 AliCodeTimerAuto("",0);
250 AliMUONVQAChecker::ECheckCode * rv = new AliMUONVQAChecker::ECheckCode[AliRecoParam::kNSpecies] ;
251 for (Int_t specie = 0 ; specie < AliRecoParam::kNSpecies ; specie++)
252 rv[specie] = AliMUONVQAChecker::kInfo;
255 for (Int_t specie = 0 ; specie < AliRecoParam::kNSpecies ; specie++)
257 TH1* h = AliQAv1::GetData(list,AliMUONQAIndices::kTrackerNumberOfClustersPerDE,AliRecoParam::ConvertIndex(specie));
259 if ( !h ) rv[specie] = AliMUONVQAChecker::kWarning; // only a warning if histo not found, in order not to kill anything because QA failed...
261 else if ( h->GetMean() == 0.0 ) rv[specie] = MarkHisto(*h,AliMUONVQAChecker::kFatal);
266 //______________________________________________________________________________
267 AliMUONVQAChecker::ECheckCode
268 AliMUONTrackerQAChecker::MarkHisto(TH1& histo, AliMUONVQAChecker::ECheckCode value) const
270 /// Mark histo as originator of some QA error/warning
272 if ( value != AliMUONVQAChecker::kInfo )
274 histo.SetBit(AliQAv1::GetQABit());
280 //______________________________________________________________________________
281 AliMUONVQAChecker::ECheckCode*
282 AliMUONTrackerQAChecker::CheckESD(TObjArray ** list, const AliMUONRecoParam* /*recoParam*/)
286 AliCodeTimerAuto("",0);
288 AliMUONVQAChecker::ECheckCode * rv = new AliMUONVQAChecker::ECheckCode[AliRecoParam::kNSpecies] ;
289 for (Int_t specie = 0 ; specie < AliRecoParam::kNSpecies ; specie++)
290 rv[specie] = AliMUONVQAChecker::kInfo;
292 for (Int_t specie = 0 ; specie < AliRecoParam::kNSpecies ; specie++) {
294 TH1* h = AliQAv1::GetData(list,AliMUONQAIndices::kESDnTracks,AliRecoParam::ConvertIndex(specie));
296 if (!h) rv[specie] = AliMUONVQAChecker::kWarning;
298 else if ( h->GetMean() == 0.0 ) rv[specie] = MarkHisto(*h,AliMUONVQAChecker::kFatal); // no track -> fatal
300 h = AliQAv1::GetData(list,AliMUONQAIndices::kESDMatchTrig,AliRecoParam::ConvertIndex(specie));
302 if (!h) rv[specie] = AliMUONVQAChecker::kWarning;
304 else if (h->GetMean() == 0.0 ) rv[specie] = MarkHisto(*h,AliMUONVQAChecker::kError); // no trigger matching -> error
309 //______________________________________________________________________________
310 AliMUONVQAChecker::ECheckCode*
311 AliMUONTrackerQAChecker::CheckRaws(TObjArray ** list, const AliMUONRecoParam* recoParam)
315 AliCodeTimerAuto("",0);
317 if (!recoParam) return 0x0;
319 AliMUONVQAChecker::ECheckCode * rv = new AliMUONVQAChecker::ECheckCode[AliRecoParam::kNSpecies] ;
321 for (Int_t specie = 0 ; specie < AliRecoParam::kNSpecies ; specie++)
323 rv[specie] = AliMUONVQAChecker::kInfo;
326 for (Int_t specie = 0 ; specie < AliRecoParam::kNSpecies ; specie++)
328 TH1* hneventsseen = AliQAv1::GetData(list,AliMUONQAIndices::kTrackerNofPhysicsEventsSeen,AliRecoParam::ConvertIndex(specie));
329 TH1* hneventsused = AliQAv1::GetData(list,AliMUONQAIndices::kTrackerNofGoodPhysicsEventsUsed,AliRecoParam::ConvertIndex(specie));
331 if (!hneventsseen || !hneventsused ) continue;
333 Int_t neventsseen = TMath::Nint(hneventsseen->GetBinContent(1));
334 Int_t neventsused = TMath::Nint(hneventsused->GetBinContent(1));
336 AliMUONVQAChecker::ECheckCode c1 = AliMUONVQAChecker::kInfo;
337 AliMUONVQAChecker::ECheckCode c2 = AliMUONVQAChecker::kInfo;
338 AliMUONVQAChecker::ECheckCode c3 = AliMUONVQAChecker::kInfo;
340 TH1* hbp = AliQAv1::GetData(list,AliMUONQAIndices::kTrackerBusPatchOccupancy,AliRecoParam::ConvertIndex(specie));
341 TH1* hbpconfig = AliQAv1::GetData(list,AliMUONQAIndices::kTrackerBusPatchConfig,AliRecoParam::ConvertIndex(specie));
342 TH1* hddl = AliQAv1::GetData(list,AliMUONQAIndices::kTrackerDDLOccupancy,AliRecoParam::ConvertIndex(specie));
344 if ( hbp && hbpconfig && hddl )
346 c1 = BeautifyOccupancyHistograms(*hddl,*hbp,hbpconfig,neventsseen,neventsused,*recoParam);
350 AliError(Form("Could not BeautifyOccupancyHistograms : hddl=%p hbpconfig=%p hbp=%p",hddl,hbpconfig,hbp));
353 TH1* hbuspatchtokenerrors = AliQAv1::GetData(list,AliMUONQAIndices::kTrackerBusPatchTokenLostErrors,AliRecoParam::ConvertIndex(specie));
354 TH1* hrostatus = AliQAv1::GetData(list,AliMUONQAIndices::kTrackerReadoutStatus,AliRecoParam::ConvertIndex(specie));
355 TH1* hrostatusnorm = AliQAv1::GetData(list,AliMUONQAIndices::kTrackerReadoutStatusPerEvent,AliRecoParam::ConvertIndex(specie));
357 if ( hrostatus && hrostatusnorm && hbuspatchtokenerrors )
359 c2 = BeautifyReadoutHistograms(*hrostatus,*hrostatusnorm,*hbuspatchtokenerrors,
360 neventsseen,neventsused,*recoParam);
364 AliError(Form("Could not BeautifyReadoutHistograms : hrostatus=%p hrostatusnorm=%p hbuspatchtokenerrors=%p",
365 hrostatus,hrostatusnorm,hbuspatchtokenerrors));
369 TH1* heventsize = AliQAv1::GetData(list,AliMUONQAIndices::kTrackerDDLEventSize,AliRecoParam::ConvertIndex(specie));
370 TH1* heventsizeperevent = AliQAv1::GetData(list,AliMUONQAIndices::kTrackerDDLEventSizePerEvent,AliRecoParam::ConvertIndex(specie));
372 if ( heventsize && heventsizeperevent )
374 c3 = BeautifyEventsizeHistograms(*heventsize,*heventsizeperevent,
375 neventsseen,neventsused,*recoParam);
379 AliError(Form("Could not BeautifyEventsizeHistograms heventsize=%p heventsizeperevent=%p",heventsize,heventsizeperevent));
382 if ( c1 == AliMUONVQAChecker::kFatal || c2 == AliMUONVQAChecker::kFatal || c3 == AliMUONVQAChecker::kFatal )
384 rv[specie] = AliMUONVQAChecker::kFatal;
386 else if ( c1 == AliMUONVQAChecker::kError || c2 == AliMUONVQAChecker::kError || c3 == AliMUONVQAChecker::kError )
388 rv[specie] = AliMUONVQAChecker::kError;
390 else if ( c1 == AliMUONVQAChecker::kWarning || c2 == AliMUONVQAChecker::kWarning || c3 == AliMUONVQAChecker::kWarning )
392 rv[specie] = AliMUONVQAChecker::kWarning;
396 rv[specie] = AliMUONVQAChecker::kInfo;
403 //____________________________________________________________________________
404 AliMUONVQAChecker::ECheckCode
405 AliMUONTrackerQAChecker::BeautifyOccupancyHistograms(TH1& hddl,
407 const TH1* hbuspatchconfig,
410 const AliMUONRecoParam& recoParam)
412 /// Put labels, limits and so on on the TrackerBusPatchOccupancy histograms
413 /// hbuspatchconfig and hbp must have the same bin definitions
415 if ( hbuspatchconfig )
417 if ( hbp.GetNbinsX() != hbuspatchconfig->GetNbinsX() ||
418 hbp.GetXaxis()->GetXmin() != hbuspatchconfig->GetXaxis()->GetXmin() ||
419 hbp.GetXaxis()->GetXmax() != hbuspatchconfig->GetXaxis()->GetXmax() )
421 AliError("hbp and hbuspatchconfig histograms are not compatible !");
422 return AliMUONVQAChecker::kFatal;
426 hddl.SetStats(kFALSE);
427 hbp.SetXTitle("Absolute Bus Patch Id");
428 hbp.SetYTitle("Occupancy (percent)");
429 hbp.SetStats(kFALSE);
431 Double_t xmin = hbp.GetXaxis()->GetXmin();
432 Double_t xmax = hbp.GetXaxis()->GetXmax();
434 Double_t occMax(0.1); // 0.1% y-limit for the plot
435 Double_t maxToleratedOccupancy(recoParam.BuspatchOccupancyHighLimit()*100.0);
436 Double_t minToleratedOccupancy(recoParam.BuspatchOccupancyLowLimit()*100.0);
437 TLine* line1 = new TLine(xmin,maxToleratedOccupancy,xmax,maxToleratedOccupancy);
438 line1->SetLineColor(1);
439 line1->SetLineWidth(1);
441 TLine* line2 = new TLine(xmin,minToleratedOccupancy,xmax,minToleratedOccupancy);
442 line2->SetLineColor(1);
443 line2->SetLineWidth(1);
445 TList* lstF = hbp.GetListOfFunctions();
447 TObject *stats = lstF->FindObject("stats");
450 while ((obj = lstF->First())) { while(lstF->Remove(obj)) { } delete obj; }
451 if (stats) lstF->Add(stats);
454 hbp.GetListOfFunctions()->Add(line1);
455 hbp.GetListOfFunctions()->Add(line2);
457 TIter next(AliMpDDLStore::Instance()->CreateBusPatchIterator());
458 AliMpBusPatch* bp(0x0);
460 Int_t nBusPatches(0);
461 Int_t nMissingBusPatches(0);
463 while ( ( bp = static_cast<AliMpBusPatch*>(next())) )
467 Int_t bin = hbp.FindBin(bp->GetId());
469 if ( hbp.GetBinContent(bin) <= 0.0 )
471 ++nMissingBusPatches;
479 Int_t nBusPatchesAboveLimit(0);
480 Int_t nBusPatchesBelowLimit(0);
481 Double_t alpha(0.1); // trim 10% of data
482 Double_t tmean(0.0),tvar(0.0);
483 Double_t ymin(0.0),ymax(0.0);
487 Double_t* x = new Double_t[nBusPatches];
489 while ( ( bp = static_cast<AliMpBusPatch*>(next())) )
491 Int_t bin = hbp.FindBin(bp->GetId());
492 if ( hbp.GetBinContent(bin) > 0 )
494 x[n] = hbp.GetBinContent(bin);
497 if ( hbp.GetBinContent(bin) > maxToleratedOccupancy )
499 ++nBusPatchesAboveLimit;
501 if ( hbp.GetBinContent(bin) < minToleratedOccupancy )
503 // check whether this buspatch has a reason to be absent (only valid
504 // if we got the config, otherwise we cannot do the test)
505 if ( hbuspatchconfig && hbuspatchconfig->GetBinContent(bin) > 0 )
507 // should be there, so it's an error
508 ++nBusPatchesBelowLimit;
513 // computed the truncated mean of the occupancy values, in order to get a
514 // reasonable y-range for the histogram (without giant peaks to the roof
515 // for misbehaving buspatches).
516 ok = trim(n,x,alpha,tmean,tvar,ymin,ymax);
527 ymax = TMath::Max(ymax,occMax);
530 hbp.SetMaximum(ymax*1.4);
532 AliMUONVQAChecker::ECheckCode rv(AliMUONVQAChecker::kInfo);
535 messages.SetOwner(kTRUE);
537 if ( neventsseen < NOTENOUGHEVENTLIMIT )
539 messages.Add(new TObjString(NOTENOUGHEVENTMESSAGE));
545 messages.Add(new TObjString("Could not compute truncated mean. Not enough events ?"));
547 if ( neventsused < TMath::Nint(0.1*neventsseen) )
549 messages.Add(new TObjString(Form("We've actually seen %d events, but used only %d !",neventsseen,neventsused)));
550 messages.Add(new TObjString("For a normal physics run, this is highly suspect !"));
551 messages.Add(new TObjString(NOTIFYEXPERTMESSAGE));
552 rv = AliMUONVQAChecker::kFatal;
555 else if (!nBusPatches)
557 messages.Add(new TObjString(Form("Could not get the total number of buspatches (%d). ERROR !!!",
559 messages.Add(new TObjString("Please check with expert !"));
560 rv = AliMUONVQAChecker::kFatal;
564 Float_t missingBusPatchFraction = nMissingBusPatches*100.0/nBusPatches;
565 Float_t aboveLimitFraction = nBusPatchesAboveLimit*100.0/nBusPatches;
566 Float_t belowLimitFraction = nBusPatchesBelowLimit*100.0/nBusPatches;
568 messages.Add(new TObjString(Form("%5.2f %% of missing buspatches (%d out of %d)",missingBusPatchFraction,nMissingBusPatches,nBusPatches)));
569 messages.Add(new TObjString(Form("%5.2f %% bus patches above the %5.2f %% limit",aboveLimitFraction,maxToleratedOccupancy)));
570 messages.Add(new TObjString(Form("%5.2f %% bus patches below the %e %% limit",belowLimitFraction,minToleratedOccupancy)));
571 messages.Add(new TObjString(Form("Bus patch mean occupancy (truncated at %2d %%) is %7.2f %%",(Int_t)(alpha*100),tmean)));
573 if ( aboveLimitFraction > recoParam.FractionOfBuspatchOutsideOccupancyLimit()*100.0 ||
574 belowLimitFraction > recoParam.FractionOfBuspatchOutsideOccupancyLimit()*100.0 )
576 rv = AliMUONVQAChecker::kError;
580 rv = AliMUONVQAChecker::kInfo;
585 SetupHisto(neventsseen,neventsused,messages,hbp,rv);
587 /// Make as well a version for DDL occupancy, that'll be used by the shifter
588 SetupHisto(neventsseen,neventsused,messages,hddl,rv);
591 hddl.SetStats(kFALSE);
596 //______________________________________________________________________________
597 AliMUONVQAChecker::ECheckCode
598 AliMUONTrackerQAChecker::BeautifyReadoutHistograms(TH1& hrostatus,
600 const TH1& hbuspatchtokenerrors,
603 const AliMUONRecoParam& recoParam)
605 /// Normalize and put some text on the readout error histogram
606 /// Note in particular the treatment of tokenlost errors !
608 hrostatusnorm.Reset();
610 AliMUONVQAChecker::ECheckCode rv(AliMUONVQAChecker::kInfo);
613 messages.SetOwner(kTRUE);
615 if ( neventsseen < NOTENOUGHEVENTLIMIT )
617 messages.Add(new TObjString(NOTENOUGHEVENTMESSAGE));
621 hrostatusnorm.Add(&hrostatus,100.0/neventsseen);
622 hrostatusnorm.SetOption("TEXT45"); // note : cannot use HIST option, otherwise the associated function (i.e. the tpavetext) is not drawn...
623 hrostatusnorm.SetMinimum(0.0);
624 hrostatusnorm.SetMaximum(100.0);
626 Double_t tokenLost = hrostatusnorm.GetBinContent(hrostatusnorm.FindBin(1.0*AliMUONQAIndices::kTrackerRawNofTokenLostErrors));
628 if ( tokenLost > recoParam.TokenLostLimit() )
630 rv = AliMUONVQAChecker::kError;
632 messages.Add(new TObjString("There are some token lost errors !"));
633 messages.Add(new TObjString("PLEASE CHECK THE BUSY TIME FOR MUON !"));
634 messages.Add(new TObjString("If above 5 ms please have the MUON expert"));
635 messages.Add(new TObjString("check the following bus patches :"));
637 for ( Int_t i = 1; i <= hbuspatchtokenerrors.GetNbinsX(); ++i )
639 if ( hbuspatchtokenerrors.GetBinContent(i) > 0 )
641 messages.Add(new TObjString(Form("BP %4d",i)));
646 if ( hrostatusnorm.GetBinContent(hrostatusnorm.FindBin(AliMUONQAIndices::kTrackerRawNofEmptyEvents)) > 25.0 )
648 messages.Add(new TObjString("Too many empty events !"));
649 messages.Add(new TObjString(NOTIFYEXPERTMESSAGE));
650 rv = AliMUONVQAChecker::kFatal;
654 SetupHisto(neventsseen,neventsused,messages,hrostatusnorm,rv,"text45");
656 ShowTrueValue(hrostatusnorm,AliMUONQAIndices::kTrackerRawNofTokenLostErrors);
657 ShowTrueValue(hrostatusnorm,AliMUONQAIndices::kTrackerRawNofParityErrors);
658 ShowTrueValue(hrostatusnorm,AliMUONQAIndices::kTrackerRawNofPaddingErrors);
659 ShowTrueValue(hrostatusnorm,AliMUONQAIndices::kTrackerRawNofGlitchErrors);
664 //______________________________________________________________________________
665 AliMUONVQAChecker::ECheckCode
666 AliMUONTrackerQAChecker::BeautifyEventsizeHistograms(TH1& heventsize,
667 TH1& heventsizeperevent,
670 const AliMUONRecoParam& recoParam)
672 /// Normalize and put some text on the event size histogram
674 AliMUONVQAChecker::ECheckCode rv(AliMUONVQAChecker::kInfo);
676 heventsizeperevent.Reset();
679 messages.SetOwner(kTRUE);
681 if ( neventsseen < NOTENOUGHEVENTLIMIT )
683 messages.Add(new TObjString(NOTENOUGHEVENTMESSAGE));
687 heventsizeperevent.Add(&heventsize,1.0/neventsseen/1024.0);
688 heventsizeperevent.SetMinimum(0);
690 Double_t totalEventSizePerEvent = heventsizeperevent.Integral();
695 if ( totalEventSizePerEvent > recoParam.EventSizeHardLimit() )
697 rv = AliMUONVQAChecker::kError;
698 msg = "That is really too high.";
699 action = NOTIFYEXPERTMESSAGE;
701 else if ( totalEventSizePerEvent > recoParam.EventSizeSoftLimit() )
703 msg = "That is a bit high.";
704 action = "Please keep an eye on it.";
705 rv = AliMUONVQAChecker::kWarning;
709 rv = AliMUONVQAChecker::kInfo;
712 messages.Add(new TObjString(Form("<MCH event size> %5.1f KB/event\n",totalEventSizePerEvent)));
715 messages.Add(new TObjString(msg));
716 messages.Add(new TObjString(action));
720 SetupHisto(neventsseen,neventsused,messages,heventsizeperevent,rv);