Line Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330
// Original Author: Gero Flucke
// last change    : $Date: 2012/03/29 08:42:23 $
// by             : $Author: flucke $

#include <map>
#include <vector>
#include <iostream>

#include "TString.h"
#include "TTree.h"
#include "TGraph.h"
#include "TGraphErrors.h"
#include "TMultiGraph.h"
#include "TCanvas.h"
#include "TROOT.h"
#include "TFile.h"
#include "TList.h"
#include "TLegend.h"

#include "PlotMillePede.h"
#include "PlotMillePedeIOV.h"
#include "GFUtils/GFHistManager.h"

PlotMillePedeIOV::PlotMillePedeIOV(const char *fileName, Int_t maxIov,
				   Int_t hieraLevel)
  : fHistManager(new GFHistManager), fTitle("")
{
  if (maxIov <= 0) { // find maximum IOV in file if not specified
    maxIov = 0;
    TFile *file = TFile::Open(fileName);
    if (!file) return;

    // Loop as long as we find MillePedeUser_<n> trees:
    TTree *tree = 0;
    do {
      file->GetObject(Form("MillePedeUser_%d", ++maxIov), tree);
    } while (tree);
    --maxIov; // one step back since last try did not succeed

    delete file;
  }

  for (Int_t iov = 1; iov <= maxIov; ++iov) {
    fIovs.push_back(new PlotMillePede(fileName, iov, hieraLevel));
    fIovs.back()->GetHistManager()->SetBatch();
    TTree *tree = fIovs.back()->GetMainTree();
    tree->SetEstimate(tree->GetEntries()); // for safe use of tree->GetV1() etc.
  }

  fHistManager->SetLegendX1Y1X2Y2(0.14, 0.7, 0.45, 0.9);
}

PlotMillePedeIOV::~PlotMillePedeIOV()
{
  delete fHistManager;
  for (unsigned int i = 0; i < fIovs.size(); ++i) {
    delete fIovs[i];
  }
}

////////////////////////////////////////////////////////////////////////////////
void PlotMillePedeIOV::DrawPedeParam(Option_t *option, unsigned int nNonRigidParam)
{
  const unsigned int nPar = PlotMillePede::kNpar + nNonRigidParam;
  const Int_t layer = this->PrepareAdd(TString(option).Contains("add", TString::kIgnoreCase));
  const Int_t xInTitle = TString(option).Contains("x", TString::kIgnoreCase);
  const Int_t yInTitle = TString(option).Contains("y", TString::kIgnoreCase);
  const Int_t zInTitle = TString(option).Contains("z", TString::kIgnoreCase);
  // if no position is selected for legend, use DetId:
  const Int_t idInTitle = (!xInTitle && !yInTitle && !zInTitle)
    || TString(option).Contains("id", TString::kIgnoreCase);
  const Int_t doErr = TString(option).Contains("err", TString::kIgnoreCase);
  const Int_t noErr = TString(option).Contains("val", TString::kIgnoreCase);
  
  typedef std::map<ParId, TGraphErrors*> GraphMap;
  GraphMap graphs; // size will be nPar*numAlis (if same nPar for all alignables)

  unsigned int maxPar = 0;
  for (unsigned int iIov = 0; iIov < fIovs.size(); ++iIov) { // loop in IOVs
    PlotMillePede *iov = fIovs[iIov];
    TTree *tree = iov->GetMainTree();
    for (unsigned int iPar = 0; iPar < nPar; ++iPar) { // loop on parameters
      if (iPar > maxPar) maxPar = iPar;
      const TString pedePar(iov->MpT() += iov->Par(iPar) += iov->ToMumMuRadPede(iPar));
      const TString parSi(iov->ParSi(iPar) += iov->ToMumMuRadPede(iPar));
      const TString par(doErr ? parSi : pedePar); // decide to do param or error
      // The selection is tree-name (but not parameter...) dependent:
      TString selection;//(iov->Valid(iPar)); // FIXME??
      iov->AddBasicSelection(selection);
      // main command to get parameter & also (Det)Id and ObjId (e.g. TPBLayer)
      const Long64_t numAlis = tree->Draw(par + ":Id:ObjId:" + parSi, selection, "goff");
      // copy result of above Draw(..) 
      const std::vector<double> values(tree->GetV1(), tree->GetV1() + numAlis);
      const std::vector<double> ids   (tree->GetV2(), tree->GetV2() + numAlis);
      const std::vector<double> objIds(tree->GetV3(), tree->GetV3() + numAlis);
      const std::vector<double> sigmas(tree->GetV4(), tree->GetV4() + numAlis);

      // now loop on selected alignables and create/fill graphs
      for (Long64_t iAli = 0; iAli < numAlis; ++iAli) {
	// ParId is Id, ObjId and parameter number - used as key for the map
	const ParId id(ids[iAli], objIds[iAli], iPar);
	TGraphErrors *&gr = graphs[id]; // pointer by ref (might be created!)
	if (!gr) {
	  // this tree->Draw(..) is only needed if xyz position requested...
	  tree->Draw(iov->XPos() += ":" + iov->YPos() +=
		     ":" + iov->ZPos(), selection, "goff");
	  gr = new TGraphErrors; // Assigns value to map-internal pointer. (!)
	  // We define title for legend here:
	  TString title(iov->AlignableObjIdString(id.objId_));
	  if (idInTitle)title += Form(", %d", id.id_);
	  if (xInTitle) title += Form(", x=%.1f", tree->GetV1()[iAli]);
	  if (yInTitle) title += Form(", y=%.1f", tree->GetV2()[iAli]);
	  if (zInTitle) title += Form(", z=%.f", tree->GetV3()[iAli]);
	  // if (title.Last(',') != kNPOS) title.Remove(title.Last(','));
	  gr->SetTitle(title);
	}
	gr->SetPoint(gr->GetN(), iIov+1, values[iAli]); // add new point for IOV
	if (!doErr      // not if we plot error instead of value
	    && !noErr   // not if error bar is deselected
	    && sigmas[iAli] > 0.) { // determined by pede (inversion...)
	  gr->SetPointError(gr->GetN()-1, 0., sigmas[iAli]); // add error in y
        }
      } // end loop on alignables
    } // end loop on parameters 
  } // end loop on IOVs

  //  if (graphs.empty()) return; // 

  // Now we have all graphs filled - order them such that 
  // the same parameter is attached to the same multigraph:
  std::vector<TMultiGraph*> multis(maxPar+1); // one multigraph per parameter
  for (GraphMap::const_iterator iGr = graphs.begin(); iGr != graphs.end();
       ++iGr) { // loop on map of graphs
    const ParId &id = iGr->first;
    if (!multis[id.par_]) multis[id.par_] = new TMultiGraph;
    multis[id.par_]->Add(iGr->second, ""); // add an option?
  }

  // Need to draw the multigraph to get its histogram for the axes.
  // This histogram has to be given to the hist manager before the multigraphs.
  // Therefore set ROOT to batch and prepare a temporary TCanvas for drawing.
  const bool isBatch = gROOT->IsBatch(); gROOT->SetBatch();
  TCanvas c; // On stack: later goes out of scope...
  // Finally loop on multigraphs 
  for (unsigned int iMulti = 0; iMulti < multis.size(); ++iMulti) {
    if (multis[iMulti] == 0) continue;
    TIter iter(multis[iMulti]->GetListOfGraphs());
    multis[iMulti]->Draw("ALP"); //'Draw' graph into batch canvas to create hist
    TH1 *h = static_cast<TH1*>(multis[iMulti]->GetHistogram() //...but clone it:
			       ->Clone(this->Unique(Form("IOV%u", iMulti))));
    const PlotMillePede *i0 = fIovs[0]; // IOV does not matter here...
    if (doErr) { // title if we draw error instead of value
      const TString errPar(Form("#sigma(%s)", i0->NamePede(iMulti).Data()));
      h->SetTitle(errPar + " IOVs" += i0->TitleAdd() += ";IOV;"
		  + errPar + i0->UnitPede(iMulti));
    } else if (fTitle != "" ) {
      h->SetTitle(i0->NamePede(iMulti) + " IOVs" + i0->TitleAdd() + ", " + fTitle + ";IOV;"
		  + i0->NamePede(iMulti) += i0->UnitPede(iMulti));
    } else {     // 'usual' title for drawing parameter values
      h->SetTitle((i0->NamePede(iMulti) += " IOVs") += i0->TitleAdd() += ";IOV;"
		  + i0->NamePede(iMulti) += i0->UnitPede(iMulti));
    }
    fHistManager->AddHistSame(h, layer, iMulti); // cloned hist for axes
    fHistManager->AddObject(multis[iMulti], layer, iMulti, "LP");
    // Create legend refering to graphs and add to manager:  
    Double_t x1, x2, y1, y2; fHistManager->GetLegendX1Y1X2Y2(x1, y1, x2, y2);
    TLegend *legend = new TLegend(x1, y1, x2, y2);
    legend->SetFillColor(kWhite);
    legend->SetTextFont(42);
    legend->SetBorderSize(1);
    fHistManager->AddLegend(legend, layer, iMulti);
    Int_t nGr = 0;
    while (TGraph* graph = static_cast<TGraph*>(iter.Next())){
      legend->AddEntry(graph, graph->GetTitle(), "lp"); // title set above
      this->SetLineMarkerStyle(*graph, nGr++);
    }
  }
  gROOT->SetBatch(isBatch); // reset batch mode 

  fHistManager->Draw();
}

//////////////////////////////////////////////////////////////////////////
void PlotMillePedeIOV::SetSubDetId(Int_t subDet)
{
  for (unsigned int iIov = 0; iIov < fIovs.size(); ++iIov) {
    fIovs[iIov]->SetSubDetId(subDet);
  }
}

//////////////////////////////////////////////////////////////////////////
void PlotMillePedeIOV::SetSubDetIds(Int_t id1, Int_t id2, Int_t id3, Int_t id4, Int_t id5)
{
  for (unsigned int iIov = 0; iIov < fIovs.size(); ++iIov) {
    fIovs[iIov]->SetSubDetIds(id1, id2, id3, id4, id5);
  }
}

//////////////////////////////////////////////////////////////////////////
void PlotMillePedeIOV::SetAlignableTypeId(Int_t alignableTypeId)
{
  for (unsigned int iIov = 0; iIov < fIovs.size(); ++iIov) {
    fIovs[iIov]->SetAlignableTypeId(alignableTypeId);
  }
}

//////////////////////////////////////////////////////////////////////////
void PlotMillePedeIOV::SetHieraLevel(Int_t hieraLevel)
{
  for (unsigned int iIov = 0; iIov < fIovs.size(); ++iIov) {
    fIovs[iIov]->SetHieraLevel(hieraLevel);
  }
}

//////////////////////////////////////////////////////////////////////////
void PlotMillePedeIOV::SetBowsParameters(bool use)
{
  for (unsigned int iIov = 0; iIov < fIovs.size(); ++iIov) {
    fIovs[iIov]->SetBowsParameters(use);
  }
}

//////////////////////////////////////////////////////////////////////////
void PlotMillePedeIOV::AddAdditionalSel(const TString &xyzrPhiNhit, Float_t min, Float_t max)
{
  for (unsigned int iIov = 0; iIov < fIovs.size(); ++iIov) {
    fIovs[iIov]->AddAdditionalSel(xyzrPhiNhit, min, max);
  }
}

//////////////////////////////////////////////////////////////////////////
void PlotMillePedeIOV::ClearAdditionalSel()
{
  for (unsigned int iIov = 0; iIov < fIovs.size(); ++iIov) {
    fIovs[iIov]->ClearAdditionalSel();
  }
}

//////////////////////////////////////////////////////////////////////////
TString PlotMillePedeIOV::Unique(const char *name) const
{
  if (!gROOT->FindObject(name)) return name;

  UInt_t i = 1;
  while (gROOT->FindObject(Form("%s_%u", name, i))) ++i;

  return Form("%s_%u", name, i);
}

//////////////////////////////////////////////////////////////////////////
Int_t PlotMillePedeIOV::PrepareAdd(bool addPlots)
{
  if (addPlots) {
    return fHistManager->GetNumLayers();
  } else {
    fHistManager->Clear();
    return 0;
  }
}

//////////////////////////////////////////////////////////////////////////
template<class T> 
void PlotMillePedeIOV::SetLineMarkerStyle(T &object, Int_t num) const
{
  // styles start with num=0
  // color: use 1-4, 6-9, 41, 46, 49
  Int_t colour = num%11 + 1; // i.e. 1-11 
  if (colour > 4) ++colour; // skip 5=yellow
  if (colour == 10) colour = 41;
  else if (colour == 11) colour = 46;
  else if (colour == 12) colour = 49;
  object.SetLineColor(colour);
  object.SetMarkerColor(object.GetLineColor());

  // style
  Int_t marker = 0; // use 14 styles
  switch (num%14) {
  case 0: marker = kFullCircle;
    break;
  case 1: marker = kFullSquare;
    break;
  case 2: marker = kFullTriangleUp;
    break;
  case 3: marker = kFullTriangleDown;
    break;
  case 4: marker = kOpenCircle;
    break;
  case 5: marker = kOpenSquare;
    break;
  case 6: marker = kOpenTriangleUp;
    break;
  case 7: marker = kOpenTriangleDown; // 32
    break;
  case 8: marker = kOpenStar;
    break;
  case 9: marker = kFullStar;
    break;
  case 10: marker = kOpenCross;
    break;
  case 11: marker = kFullCross;
    break;
  case 12: marker = kOpenDiamond;
    break;
  case 13: marker = kFullDiamond;
    break;
  default: marker = kPlus; // should not be reached...
  }
  object.SetMarkerStyle(marker);
  
  //object.SetLineStyle(num%10 + 1); // use (default) line styles 1-10
  object.SetLineStyle(num%4 + 1); // use only line styles 1-4

}

bool PlotMillePedeIOV::ParId::operator< (const ParId& other) const
{
  // Sorting needed for use as key in std::map:
  // first sort by id_, second objId_, finally par_.
  if (id_ < other.id_) return true;
  else if (id_ > other.id_) return false;
  else { // id the same
    if (objId_ < other.objId_) return true;
    else if (objId_ > other.objId_) return false;
    else { // id and objId the same
      if (par_ < other.par_) return true;
      // redundant: else if (par_ > other.par_) return false;
      else return false; // all are the same!
    }
  }
}