*/
struct QAPlotter : public QABase
{
- /*******************************************************************
+ /**
* Ring class
*/
struct Ring : public QARing
/**
* Constuctor
*
- * @param d Detector
- * @param r Ring
+ * @param d Detector
+ * @param r Ring
+ * @param useVar Use variance for errors (not min/max)
*/
- Ring(UShort_t d, Char_t r)
+ Ring(UShort_t d, Char_t r, Bool_t useVar=false)
: QARing(d, r),
fGChi2(0),
fGC(0),
fGSingles(0),
fGLoss(0),
fGBeta(0),
- fGOccupancy(0)
+ fGOccupancy(0),
+ fUseVar(useVar)
{
fGChi2 = new TGraphAsymmErrors;
fGC = new TGraphAsymmErrors;
*
* @param g Graph
* @param name Name of graph
- * @param title Title (not used)
*/
void SetAtt(TGraph* g, const char* name, const char* /*title=""*/)
{
Double_t y = q.mean;
Double_t el = y-q.min;
Double_t eh = q.max-y;
+ if (fUseVar) {
+ //Info("UpdateGraph", "Setting errors on %s to variance",g->GetName());
+ el = q.var;
+ eh = q.var;
+ }
if (TMath::Abs(y) < 1e-6) return;
Int_t i = g->GetN();
g->SetPoint(i, runNo, y);
TGraph* fGLoss; // Graph of 'lost' data
TGraph* fGBeta; // Graph of Poisson vs ELoss correlation
TGraphAsymmErrors* fGOccupancy;// Graph of mean occupancy
+ Bool_t fUseVar; // Use variance
};
+ // =================================================================
+ /**
+ * Compatiblity constructor
+ *
+ * @param prodYear Year
+ * @param prodLetter Letter
+ * @param useVar Use variance
+ */
+ QAPlotter(Long_t prodYear, Char_t prodLetter, Bool_t useVar)
+ : QABase("", (prodYear < 2000 ? 2000 : 0) + prodYear,
+ Form("LHC%02d%c", int(prodYear % 100), prodLetter), "pass0"),
+ fNAccepted(0),
+ fVz(0),
+ fUseVar(useVar)
+ {
+ Info("QAPlotter", "Do we use variance? %s", fUseVar ? "yes" : "no");
+ fFMD1i = new Ring(1, 'I', useVar);
+ fFMD2i = new Ring(2, 'I', useVar);
+ fFMD2o = new Ring(2, 'O', useVar);
+ fFMD3i = new Ring(3, 'I', useVar);
+ fFMD3o = new Ring(3, 'O', useVar);
+ fNAccepted = new TGraph;
+ fNAccepted->SetName("nAccepted");
+ fNAccepted->SetMarkerStyle(20);
+ fNAccepted->SetLineWidth(2);
+
+ fVz = new TGraphErrors;
+ fVz->SetName("vz");
+ fVz->SetMarkerStyle(20);
+ fVz->SetLineWidth(2);
+ }
/**
* Constructor
*/
- QAPlotter()
- : QABase(),
+ QAPlotter(const TString& dataType,
+ Int_t year,
+ const TString& period,
+ const TString& pass,
+ Bool_t useVar=true)
+ : QABase(dataType, year, period, pass),
fNAccepted(0),
- fVz(0)
+ fVz(0),
+ fUseVar(useVar)
{
- fFMD1i = new Ring(1, 'I');
- fFMD2i = new Ring(2, 'I');
- fFMD2o = new Ring(2, 'O');
- fFMD3i = new Ring(3, 'I');
- fFMD3o = new Ring(3, 'O');
+ Info("QAPlotter", "Do we use variance? %s", fUseVar ? "yes" : "no");
+ fFMD1i = new Ring(1, 'I', useVar);
+ fFMD2i = new Ring(2, 'I', useVar);
+ fFMD2o = new Ring(2, 'O', useVar);
+ fFMD3i = new Ring(3, 'I', useVar);
+ fFMD3o = new Ring(3, 'O', useVar);
fNAccepted = new TGraph;
fNAccepted->SetName("nAccepted");
fNAccepted->SetMarkerStyle(20);
{
fFiles.Add(new TObjString(filename));
}
+ const char* GetUserInfo(TList* l, const char* name, const char* def) const
+ {
+ if (!l) {
+ Warning("GetUserInfo", "No user information list");
+ return def;
+ }
+
+ TObject* o = l->FindObject(name);
+ if (!o) {
+ Warning("GetUserInfo", "User information %s not found", name);
+ l->ls();
+ return def;
+ }
+
+ Info("GetUserInfo", "Got user information %s=%s", name, o->GetTitle());
+ return o->GetTitle();
+ }
+ /**
+ * Make a tree
+ *
+ * @param read If true, read from file
+ *
+ * @return True on success
+ */
Bool_t MakeTree(bool read)
{
if (fFiles.GetEntriesFast() <= 0) return QABase::MakeTree(read);
-
+ if (fFiles.GetEntriesFast() == 1 && read) {
+ TFile* file = TFile::Open(fFiles.At(0)->GetName(), "READ");
+ if (file) {
+ fTree = static_cast<TTree*>(file->Get("T"));
+ return true;
+ }
+ }
TChain* chain = new TChain("T", "T");
if (!chain->AddFileInfoList(&fFiles)) return false;
fTree = chain;
+
return true;
}
Error("Run", "No input tree");
return;
}
-
fFirst = 0xFFFFFFFF;
fLast = 0;
UInt_t nEntries = fTree->GetEntries();
UInt_t j = 0;
fRuns.Set(nEntries);
+ Info("Run", "Got %d runs", nEntries);
+ TList* l = fTree->GetUserInfo();
+ fPeriod = GetUserInfo(l, "period", "?");
+ fPass = GetUserInfo(l, "pass", "?");
+ fDataType = GetUserInfo(l, "type", "?");
+
+
for (UInt_t i = 0; i < nEntries; i++) {
fTree->GetEntry(i);
*/
void Plot()
{
-
- fTeXName = Form("trend_%09d_%09d", fFirst, fLast);
- MakeCanvas(Form("QA trends for runs %d --- %d", fFirst, fLast));
+ // fTeXName = Form("trend_%09d_%09d", fFirst, fLast);
+ TString title;
+ if (!fPeriod.IsNull() && !fPass.IsNull())
+ title.Form("QA trends for %s/%s runs %d --- %d",
+ fPeriod.Data(), fPass.Data(), fFirst, fLast);
+ else
+ title.Form("QA trends for runs %d --- %d", fFirst, fLast);
+ MakeCanvas(title);
CanvasTitle("# of accepted events");
fNAccepted->Draw("apl");
occ->Write();
beta->Write();
+ std::ofstream doc(".doc");
+ doc << fPeriod << " " << fPass << " ("
+ << fDataType << ")" << std::endl;
+ doc.close();
+
Close(false); // Do not delete PNGs
}
/**
*
* @param mg Multi graph
* @param title Title
+ * @param logy If true, make @f$\log@f$ scale
*/
void PlotMulti(TMultiGraph* mg, const char* title, Bool_t logy=false)
{
}
l->Draw();
- AddRuns(h, title, &runs);
+ TList areas;
+ areas.SetOwner();
+ AddRuns(h, title, &runs, &areas);
- PrintCanvas(mg->GetName());
+ PrintCanvas(mg->GetName(), &areas);
}
+ /**
+ * Find a run
+ *
+ * @param runs List of runs
+ * @param run Run to find
+ *
+ * @return Index of run in run list
+ */
Int_t FindRun(const TArrayI& runs, Int_t run)
{
std::sort(&(runs.fArray[0]), &(runs.fArray[runs.GetSize()]));
*
* @param h Frame histogram
* @param title Title
+ * @param runs List of runs, if any
+ * @param areas Other areas
*/
- void AddRuns(TH1* h, const char* title, TArrayI* runs=0)
+ void AddRuns(TH1* h, const char* title, TArrayI* runs=0,
+ TList* areas=0)
{
h->GetXaxis()->SetNoExponent();
// h->GetXaxis()->SetTitleOffset(1);
- h->SetYTitle(title);
+ TString ytitle(title);
+ if (fUseVar) ytitle.Append(" (errors: variance)");
+ else ytitle.Append(" (errors: min/max)");
+ h->SetYTitle(ytitle.Data());
h->SetXTitle("Run #");
-
+ // Info("AddRuns", "%s: %s vs %s", h->GetName(),
+ // h->GetXaxis()->GetTitle(), h->GetYaxis()->GetTitle());
+
Int_t r1 = h->GetXaxis()->GetXmin();
Int_t r2 = h->GetXaxis()->GetXmax();
Double_t lx = 0;
- Double_t tx = .045; // (r2 - r1) / 18;
+ Double_t tx = .025; // (r2 - r1) / 18;
Double_t wx = 1 - fCanvas->GetLeftMargin() - fCanvas->GetRightMargin();
Double_t dy = .025;
Double_t y = fCanvas->GetBottomMargin()+dy;
tl->SetLineStyle(3);
tl->SetLineColor(color);
tl->Draw();
+
+ if (!areas) continue;
+
+ TObjString* area = new TObjString;
+ TString& spec = area->String();
+ spec.Form("<span style=\"left: %d%%; bottom: %d%%;\" "
+ "onClick='window.location=\"%09d/index.html\"' "
+ "onMouseOver='this.style.cursor=\"pointer\"' "
+ "alt=\"%d\""
+ ">%d</span>",
+ UInt_t(100*x)-2, UInt_t(100*y), r, r, r);
+
+#if 0
+ spec.Form("<area shape='rect' alt='%d' title='%d' href='qa_%09d.html' "
+ "coords='%d,%d,%d,%d'>", r, r, r,
+ UInt_t(cw*(x-tx)), 0, UInt_t(cw*(x+tx)), ch);
+#endif
+ areas->Add(area);
}
}
+ /**
+ * Output list of runs
+ *
+ * @param o Output stream
+ */
void WriteRuns(std::ostream& o)
{
o << "<div class='jobid'><!--JOBID--></div>\n"
<< "<div class='runs'>\n"
<< " Runs:<br> ";
for (Int_t i = 0; i < fRuns.GetSize(); i++) {
- o << "<a href='qa_" << Form("%09d", fRuns[i]) << ".html'>"
+ o << "<a href='" << Form("%09d", fRuns[i]) << "/index.html'>"
<< fRuns[i] << "</a> " << std::flush;
}
o << "\n"
<< "</div>" << std::endl;
}
+ /**
+ * Write page footer
+ *
+ */
void WriteFooter()
{
WriteRuns(*fHtml);
QABase::WriteFooter();
}
+ /**
+ * Write out image footer
+ *
+ * @param o Output stream
+ * @param pngName Name of the PNG file
+ */
void WriteImageFooter(std::ostream& o, const char* pngName)
{
WriteRuns(o);
UInt_t fLast; // Last run
TArrayI fRuns; // Seen runs
TObjArray fFiles;
+ Bool_t fUseVar; // Use variance rather than min/max
};
//