+ qa->Set(ret, AliRecoParam::ConvertIndex(specie));
+ AliDebugF(3, "Quality of %s: %d -> %d",
+ AliRecoParam::GetEventSpecieName(specie), value, ret);
+ }
+}
+
+//__________________________________________________________________
+UShort_t
+AliFMDQAChecker::BasicCheck(TH1* hist) const
+{
+ if (hist->GetEntries() <= 0) return kOK;
+ return (hist->GetMean() > 0 ? kOK : kProblem);
+}
+
+//__________________________________________________________________
+UShort_t
+AliFMDQAChecker::CheckOne(AliQAv1::ALITASK_t what,
+ AliRecoParam::EventSpecie_t specie,
+ TH1* hist) const
+{
+ if(what == AliQAv1::kESD) return CheckESD(specie, hist);
+ if(what == AliQAv1::kRAW) return CheckRaw(specie, hist);
+ if(what == AliQAv1::kSIM) return CheckSim(specie, hist);
+ if(what == AliQAv1::kREC) return CheckRec(specie, hist);
+ return 0;
+}
+//__________________________________________________________________
+UShort_t
+AliFMDQAChecker::CheckESD(AliRecoParam::EventSpecie_t /* specie*/,
+ TH1* hist) const
+{
+ return BasicCheck(hist);
+}
+namespace {
+ Double_t Chi2Scale(TH1* h, Double_t base=10000)
+ {
+ return 1. / TMath::Max(1., h->GetEntries() / base);
+ }
+ void AddLine(TObjArray* lines,
+ Double_t x1, Double_t x2, Double_t x3,
+ Double_t y, Double_t dy,
+ const char* name, Double_t val, Double_t lim,
+ Bool_t ok, Int_t color)
+ {
+ TString n; n.Form("%s:", name);
+ TLatex* ltx = new TLatex(x1, y, n);
+ ltx->SetNDC(true);
+ ltx->SetTextSize(dy-0.01);
+ ltx->SetTextColor(color);
+ lines->Add(ltx);
+
+ n.Form("%7.3f", val);
+ ltx = new TLatex(x2, y, n);
+ ltx->SetNDC(true);
+ ltx->SetTextSize(dy-0.01);
+ ltx->SetTextColor(color);
+ lines->Add(ltx);
+
+ if (lim < 0) n = "(ignored)";
+ else n.Form("%c %4.2f", ok ? '<' : '>', lim);
+ ltx = new TLatex(x3, y, n);
+ ltx->SetNDC(true);
+ ltx->SetTextSize(dy-0.01);
+ ltx->SetTextColor(color);
+ lines->Add(ltx);
+ }
+}
+
+//__________________________________________________________________
+UShort_t
+AliFMDQAChecker::CheckFit(TH1* hist, const TFitResultPtr& res,
+ Double_t low, Double_t high, Int_t& color) const
+{
+ color = kGreen+4;
+
+ UShort_t ret = 0;
+ Int_t nPar = res->NPar();
+ Double_t dy = .06;
+ Double_t x = .2;
+ Double_t x2 = .3;
+ Double_t x3 = .4;
+ Double_t y = .9-dy;
+ Double_t chi2 = res->Chi2();
+ Int_t nu = res->Ndf();
+ Double_t s = Chi2Scale(hist,fELossMinEntries);
+ Double_t red = (nu == 0 ? fELossFkupChi2Nu : chi2 / nu);
+ TObjArray* lines = 0;
+ // TLatex* lRed = 0;
+ TLatex* ltx = 0;
+ Int_t chi2Check = 0;
+ Double_t chi2Lim = fELossBadChi2Nu;
+ if (AliDebugLevel() > 0)
+ printf("FIT: %s, 1, %d, %f, %f\n", hist->GetName(),
+ Int_t(hist->GetEntries()), red, s * red);
+ red *= s;
+ if (red > fELossBadChi2Nu) { // || res->Prob() < .01) {
+ // AliWarningF("Fit gave chi^2/nu=%f/%d=%f>%f (%f)",
+ // res->Chi2(), res->Ndf(), red, fELossBadChi2Nu,
+ // fELossFkupChi2Nu);
+ // res->Print();
+ chi2Check++;
+ if (red > fELossFkupChi2Nu) {
+ chi2Check++;
+ chi2Lim = fELossFkupChi2Nu;
+ }
+ }
+ ret += chi2Check;
+
+ if (fShowFitResults) {
+ lines = new TObjArray(nPar+3);
+ lines->SetName("lines");
+ lines->SetOwner(true);
+
+ AddLine(lines, x, x2, x3, y, dy, "#chi^{2}/#nu", red, chi2Lim,
+ chi2Check < 1, chi2Check < 1 ? color :
+ chi2Check < 2 ? kOrange+2 : kRed+2);
+
+ Double_t x1 = .85;
+ Double_t y1 = .5;
+
+ // y1 -= dy;
+ ltx = new TLatex(x1, y1, Form("Fit range: [%6.2f,%6.2f]", low, high));
+ ltx->SetTextColor(kGray+3);
+ ltx->SetTextSize(dy-.01);
+ ltx->SetTextAlign(31);
+ ltx->SetNDC(true);
+ lines->Add(ltx);
+
+ y1 -= dy;
+ ltx = new TLatex(x1, y1, Form("Entries: %d (%d)",
+ Int_t(hist->GetEffectiveEntries()),
+ fELossMaxEntries));
+ ltx->SetTextColor(kGray+3);
+ ltx->SetTextSize(dy-.01);
+ ltx->SetTextAlign(31);
+ ltx->SetNDC(true);
+ lines->Add(ltx);
+
+ y1 -= dy;
+ ltx = new TLatex(x1, y1, Form("%s: %f #pm %f",
+ res->ParName(1).c_str(),
+ res->Parameter(1),
+ res->ParError(1)));
+ ltx->SetTextColor(kGray+3);
+ ltx->SetTextSize(dy-.01);
+ ltx->SetTextAlign(31);
+ ltx->SetNDC(true);
+ lines->Add(ltx);
+ }
+
+ // Now check the relative error on the fit parameters
+ Int_t parsOk = 0;
+ for (Int_t i = 0; i < nPar; i++) {
+ if (res->IsParameterFixed(i)) continue;
+ Double_t thr = fELossGoodParError;
+ Double_t pv = res->Parameter(i);
+ Double_t pe = res->ParError(i);
+ Double_t rel = (pv == 0 ? 100 : pe / pv);
+ Bool_t ok = (i == 3) || (rel < thr);
+ if (lines) {
+ y -= dy;
+ AddLine(lines, x, x2, x3, y, dy,Form("#delta%s/%s",
+ res->ParName(i).c_str(),
+ res->ParName(i).c_str()),
+ rel, (i == 3 ? -1 : thr), ok, ok ? color : kOrange+2);
+ }
+ if (i == 3) continue; // Skip sigma
+ if (ok) parsOk++;
+ }
+ if (parsOk > 0)
+ ret = TMath::Max(ret-(parsOk-1),0);
+ if (ret > 1) color = kRed+2;
+ if (ret > 0) color = kOrange+2;
+
+ if (lines) {
+ TList* lf = hist->GetListOfFunctions();
+ TObject* old = lf->FindObject(lines->GetName());
+ if (old) {
+ lf->Remove(old);
+ delete old;
+ }
+ lf->Add(lines);
+ }
+ hist->SetStats(false);
+
+ return ret;
+}
+
+//__________________________________________________________________
+UShort_t
+AliFMDQAChecker::CheckRaw(AliRecoParam::EventSpecie_t specie,
+ TH1* hist) const
+{
+ Int_t ret = BasicCheck(hist);
+ TString name(hist->GetName());
+ if (name.Contains("readouterrors", TString::kIgnoreCase)) {
+ // Check the mean number of errors per event
+ TH2* roErrors = static_cast<TH2*>(hist);
+ Int_t nY = roErrors->GetNbinsY();
+
+ TLatex* ltx = new TLatex(.15, .9, Form("Thresholds: %5.2f,%5.2f",
+ fROErrorsBad, fROErrorsFkup));
+ ltx->SetName("thresholds");
+ ltx->SetTextColor(kGray+3);
+ ltx->SetNDC();
+
+ TList* ll = hist->GetListOfFunctions();
+ TObject* old = ll->FindObject(ltx->GetName());
+ if (old) {
+ ll->Remove(old);
+ delete old;
+ }
+ ll->Add(ltx);
+
+ for (Int_t i = 1; i <= 3; i++) {
+ Double_t sum = 0;
+ Int_t cnt = 0;
+ for (Int_t j = 1; j <= nY; j++) {
+ Int_t n = roErrors->GetBinContent(i, j);
+ sum += n * roErrors->GetYaxis()->GetBinCenter(j);
+ cnt += n;
+ }
+ Double_t mean = (cnt <= 0 ? 0 : sum / cnt);
+ Double_t x = ((i-.5) * (1-0.1-0.1) / 3 + 0.1);