void plot_efficiencies( TFile* file, Int_t type = 2, TDirectory* BinDir=0)
{
   // input:   - Input file (result from TMVA),
   //          - type = 1 --> plot efficiency(B) versus eff(S)
   //                 = 2 --> plot rejection (B) versus efficiency (S)
   //                 = 3 --> plot 1/eff(B) versus efficiency (S)

   Bool_t __PLOT_LOGO__  = kTRUE;
   Bool_t __SAVE_IMAGE__ = kTRUE;

   // the coordinates
   Float_t x1 = 0;
   Float_t x2 = 1;
   Float_t y1 = 0;
   Float_t y2 = 0.8;

   // reverse order if "rejection"
   if (type == 2) {
      Float_t z = y1;
      y1 = 1 - y2;
      y2 = 1 - z;
      //      cout << "--- type==2: plot background rejection versus signal efficiency" << endl;
   } else if (type == 3) {
      y1 = 0;
      y2 = -1; // will be set to the max found in the histograms

   } else {
      //  cout << "--- type==1: plot background efficiency versus signal efficiency" << endl;
   }
   // create canvas
   TCanvas* c = new TCanvas( "c", "the canvas", 200, 0, 650, 500 );

   // global style settings
   c->SetGrid();
   c->SetTicks();

   // legend
   Float_t x0L = 0.107,     y0H = 0.899;
   Float_t dxL = 0.457-x0L, dyH = 0.22;
   if (type == 2) {
      x0L = 0.15;
      y0H = 1 - y0H + dyH + 0.07;
   }
   TLegend *legend = new TLegend( x0L, y0H-dyH, x0L+dxL, y0H );
   //legend->SetTextSize( 0.05 );
   legend->SetHeader( "MVA Method:" );
   legend->SetMargin( 0.4 );

   TString xtit = "Signal efficiency";
   TString ytit = "Background efficiency";
   if (type == 2) ytit = "Background rejection";
   if (type == 3) ytit = "1/(Background eff.)";
   TString ftit = ytit + " versus " + xtit;

   TString hNameRef = "effBvsS";
   if (type == 2) hNameRef = "rejBvsS";
   if (type == 3) hNameRef = "invBeffvsSeff";


   if (TString(BinDir->GetName()).Contains("multicut")){
      ftit += "  Bin: ";
      ftit += (BinDir->GetTitle());
   }

   TList xhists;
   TList xmethods;
   UInt_t xnm = TMVAGlob::GetListOfMethods( xmethods );
   TIter xnext(&xmethods);
   // loop over all methods
   TKey *xkey;
   while ((xkey = (TKey*)xnext())) {
      TDirectory * mDir = (TDirectory*)xkey->ReadObj();
      TList titles;
      UInt_t ninst = TMVAGlob::GetListOfTitles(mDir,titles);
      TIter nextTitle(&titles);
      TKey *titkey;
      TDirectory *titDir;
      while ((titkey = TMVAGlob::NextKey(nextTitle,"TDirectory"))) {
         titDir = (TDirectory *)titkey->ReadObj();
         TString methodTitle;
         TMVAGlob::GetMethodTitle(methodTitle,titDir);
         TIter nextKey( titDir->GetListOfKeys() );
         TKey *hkey2;
         while ((hkey2 = TMVAGlob::NextKey(nextKey,"TH1"))) {
            TH1 *h = (TH1*)hkey2->ReadObj();
            TString hname = h->GetName();
            if (hname.Contains( hNameRef ) && hname.BeginsWith( "MVA_" )) {
               if (type==3 && h->GetMaximum() > y2) y2 = h->GetMaximum();
            }
         }
      }
   }


   // draw empty frame
   if(gROOT->FindObject("frame")!=0) gROOT->FindObject("frame")->Delete();
   TH2F* frame = new TH2F( "frame", ftit, 500, x1, x2, 500, y1, y2 );
   frame->GetXaxis()->SetTitle( xtit );
   frame->GetYaxis()->SetTitle( ytit );
   TMVAGlob::SetFrameStyle( frame, 1.0 );

   frame->Draw();

   Int_t color = 1;
   Int_t nmva  = 0;
   TKey *key, *hkey;

   TList hists;
   TList methods;
   UInt_t nm = TMVAGlob::GetListOfMethods( methods );
   //   TIter next(file->GetListOfKeys());
   TIter next(&methods);

   // loop over all methods
   while ((key = (TKey*)next())) {
      TDirectory * mDir = (TDirectory*)key->ReadObj();
      TList titles;
      UInt_t ninst = TMVAGlob::GetListOfTitles(mDir,titles);
      TIter nextTitle(&titles);
      TKey *titkey;
      TDirectory *titDir;
      while ((titkey = TMVAGlob::NextKey(nextTitle,"TDirectory"))) {
         titDir = (TDirectory *)titkey->ReadObj();
         TString methodTitle;
         TMVAGlob::GetMethodTitle(methodTitle,titDir);
         TIter nextKey( titDir->GetListOfKeys() );
         TKey *hkey2;
         while ((hkey2 = TMVAGlob::NextKey(nextKey,"TH1"))) {
            TH1 *h = (TH1*)hkey2->ReadObj();
            TString hname = h->GetName();
            if (hname.Contains( hNameRef ) && hname.BeginsWith( "MVA_" )) {
               h->SetLineWidth(3);
               h->SetLineColor(color);
               color++; if (color == 5 || color == 10 || color == 11) color++;
               h->Draw("csame");
               hists.Add(h);
               nmva++;
            }
         }
      }
   }

   while (hists.GetSize()) {
      TListIter hIt(&hists);
      TH1* hist(0);
      Double_t largestInt=-1;
      TH1* histWithLargestInt(0);
      while ((hist = (TH1*)hIt())!=0) {
         Double_t integral = hist->Integral(1,hist->FindBin(0.9999));
         if (integral>largestInt) {
            largestInt = integral;
            histWithLargestInt = hist;
         }
      }
      if (histWithLargestInt == 0) {
         cout << "ERROR - unknown hist \"histWithLargestInt\" --> serious problem in ROOT file" << endl;
         break;
      }
      legend->AddEntry(histWithLargestInt,TString(histWithLargestInt->GetTitle()).ReplaceAll("MVA_",""),"l");
      hists.Remove(histWithLargestInt);
   }

   // rescale legend box size
   // current box size has been tuned for 3 MVAs + 1 title
   if (type == 1) {
      dyH *= (1.0 + Float_t(nmva - 3.0)/4.0);
      legend->SetY1( y0H - dyH );
   }
   else {
      dyH *= (Float_t(TMath::Min(10,nmva) - 3.0)/4.0);
      legend->SetY2( y0H + dyH);
   }

   // redraw axes
   frame->Draw("sameaxis");
   legend->Draw("same");

   // ============================================================

   if (__PLOT_LOGO__) TMVAGlob::plot_logo();

   // ============================================================

   c->Update();

   TString fname = "plots/" + hNameRef;
   if (TString(BinDir->GetName()).Contains("multicut")){
      TString fprepend(BinDir->GetName());
      fprepend.ReplaceAll("multicutMVA_","");
      fname = "plots/" + fprepend + "_" + hNameRef;
   }
   if (__SAVE_IMAGE__) TMVAGlob::imgconv( c, fname );

   return;
}
Exemple #2
0
// Read decay modes from single file
void ReadFile(TFile *f, TList &list)
{
	f->cd();
	cout<<"Reading file: "<<f->GetName()<<endl<<endl;
	TList *dir=f->GetListOfKeys();	
	TIter nextdir(dir);
	TKey *key_dir=0;
	while(key_dir=(TKey*)nextdir())
	{
		if(strcmp(key_dir->GetClassName(),"TDirectoryFile")==0 ||
		   strcmp(key_dir->GetClassName(),"TDirectory")==0 )
		{
			TDirectory *subdir=(TDirectory*)f->Get(key_dir->GetName());
			TList *keys=subdir->GetListOfKeys();
			TIter  nextKey(keys);
			TKey  *key=0;
			// User Histograms
			if(strcmp(key_dir->GetName(),"USER_HISTOGRAMS")==0)
			{
				TDecayMode *dm = new TDecayMode();
				dm->histograms = new TObjArray();
				while(key=(TKey*)nextKey())
				{
					int cycle=-10;
					if(strcmp(key->GetClassName(),"TH1D")==0)
					{
						TH1D *h=0;
						int cycleh=key->GetCycle();
						if(cycleh<cycle) { cout<<"Skipping..."<<endl; continue; }
						if(cycle<cycleh) cycle=cycleh;
						h=(TH1D*)key->ReadObj();
						if(!h)
						{
							cout<<"Cannot read: "<<key->GetName()<<endl;
							exit(-2);
						}
						TH1D *h1=new TH1D(*h);
						dm->histograms->Add(h1);
					}
				}
				if(userHisto==NULL) userHisto = (TDecayMode*) new TDecayMode(*dm);
				else                dmMerge(userHisto,dm,keys);
				continue;
			}
			TDecayMode *file_dm=0;
			TDecayMode *dm=0;
			// Regular decay mode
			while(key=(TKey*)nextKey())
			{
				if(strcmp(key->GetClassName(),"TDecayMode")==0)
				{
					file_dm=(TDecayMode*)key->ReadObj();
					dm = new TDecayMode(*file_dm);
				}
			}
			if(!dm)
			{
				cout<<"ERROR: no TDecayMode object found in directory: "<<subdir->GetName()<<endl;
				subdir->ls();
				continue;
			}
			// Merge with existing decay mode or add as new one
			TObject *existingDM=list.FindObject(dm->GetName());
			if(existingDM)
			{
				int ret = dmMerge(existingDM,dm,keys);
				if(ret==-1)
				{
					printf("WARNING: Histograms with different ranges or number of bins. File skipped.\n");
					return;
				}
			}
			else
			{
				dmRestoreHistograms(dm,keys);
				list.Add(dm);
			}
		}
		else
		{
			//If not directory, it's generation description
			if(genDesc || strcmp(key_dir->GetClassName(),"GenerationDescription")!=0) continue;
			GenerationDescription *file_gd = (GenerationDescription*) key_dir->ReadObj();
			GenerationDescription *gd = new GenerationDescription(*file_gd);
			genDesc=gd;
		}
	}
}
Exemple #3
0
qlonglong QueryExecutor::nextTimeSlotKey() const
{
  return nextKey("timeSlots_seq");
}
void statUncertainties(TString inFileName, TString outFileName, bool is8TeV=true ) {

  int numChannels = 15;
  TString channelNames[] = {
    //"ljets_j4_t2", 		//	 "j4_2t",
    "ljets_j4_t3", 		//	 "j4_3t",
    "ljets_j4_t4", 		//	 "j4_3t",
    //"ljets_j5_t2", 		//	 "j5_2t",
    "ljets_j5_t3", 		//	 "j5_3t",
    "ljets_j5_tge4", 		//	 "j5_3t",
    "ljets_jge6_t2", 		//	 "j6_2t",
    "ljets_jge6_t3", 		//	 "j6_3t",
    "ljets_jge6_tge4",    	//	 "j6_3t",
    "ge3t",	       		// dilep >= 3tags
    "e2je2t",   		// dilep 2 jets 2 tags
    "e3je2t",   		// dilep 3 jets 2 tags
    "ge4je2t",   		// dilep >=4 jets 2 tags
    "SS_e3je1t",   		// dilep SS 3 jets 1 tags
    "SS_ge4je1t",   		// dilep SS >=4 jets 1 tags
    "SS_e3jge2t",   		// dilep SS 3 jets >=2 tags
    "SS_ge4jge2t",   		// dilep SS >=4 jets >=2 tags
  };

  //Open the root file
  TFile *inFile = TFile::Open(inFileName);
  TFile *outFile = TFile::Open(outFileName,"RECREATE");

  int numSamples = 16;
  TString sampleNames[] = {"ttbar","ttbarPlusBBbar","ttbarPlusCCbar","singlet","wjets","zjets","ttbarW","ttbarZ","diboson",
			   "ttH110","ttH115","ttH120","ttH125","ttH130","ttH135","ttH140"};


  for (int iChan = 0; iChan < numChannels; ++iChan) {

    for (int iSample = 0; iSample < numSamples; ++iSample) {

      TString histName = sampleNames[iSample];
      histName += "_CFMlpANN_";
      histName += channelNames[iChan];

      std::cout << histName << " " << std::endl;

      TH1D* hist = (TH1D*)inFile->Get(histName);

      int numBins = hist->GetNbinsX();

      TString era = ( is8TeV ) ? "8TeV" : "7TeV";

      for( int bin=0; bin<numBins; bin++ ){
	TString bin_name;
	bin_name.Form("%d",bin);

	TString histName_Up = histName;
	histName_Up += "_" + sampleNames[iSample] + "_" + channelNames[iChan] + "_" + era + "_ANNbin" + bin_name + "Up";

	TString histName_Down = histName;
	histName_Down += "_" + sampleNames[iSample] + "_" + channelNames[iChan] + "_" + era + "_ANNbin" + bin_name + "Down";

	if( sampleNames[iSample].Contains("ttH") ){
	  histName_Up = histName;
	  histName_Up += "_ttH_" + channelNames[iChan] + "_" + era + "_ANNbin" + bin_name + "Up";

	  histName_Down = histName;
	  histName_Down += "_ttH_" + channelNames[iChan] + "_" + era + "_ANNbin" + bin_name + "Down";
	}

	TH1D* hist_Up   = (TH1D*)hist->Clone(histName_Up);
	TH1D* hist_Down = (TH1D*)hist->Clone(histName_Down);

	hist_Up->SetBinContent(bin+1, hist->GetBinContent(bin+1) + hist->GetBinError(bin+1) );
	hist_Down->SetBinContent(bin+1, hist->GetBinContent(bin+1) - hist->GetBinError(bin+1) );

	outFile->cd();

	hist_Up->Write(histName_Up);
	hist_Down->Write(histName_Down);
      }
    }
  }


  //Now copy all other histograms in the file as is (preserving names...)
  TList *keys = inFile->GetListOfKeys();

  TIter nextKey(keys);
  TKey *key = 0;

  while ((key = (TKey *)nextKey())) {

    TString name = key->GetName();

    TH1 *hist2 = 0;
    hist2 = (TH1 *)inFile->Get(name);

    outFile->cd();
    hist2->Write(name);
  }


  outFile->Close();

  std::cout << "Done." << std::endl;

}
Exemple #5
0
qlonglong QueryExecutor::nextUserKey() const
{
  return nextKey("users_seq");
}
Exemple #6
0
qlonglong QueryExecutor::nextChannelKey() const
{
  return nextKey("channels_seq");
}
Exemple #7
0
qlonglong QueryExecutor::nextTagKey() const
{
  return nextKey("tags_seq");
}
Exemple #8
0
void Editor::updateFocus()
{
  focus.clear();
  //if (caret != selStart)
  //  return;
  POINT pt = toPoint(caret);

  int ctx = lines[pt.y].ctx;
  int ctxType = lines[pt.y].ctxType;
  wchar_t const* text = lines[pt.y].text.c_str();
  int pos = 0;
  while (pos < pt.x && text[pos])
  {
    if (ctx)
    {
      if (text[pos] == ']')
      {
        pos++;
        int count = 0;
        while (text[pos] == '=' && count < ctxType)
          pos++, count++;
        if (text[pos] == ']' && count == ctxType)
        {
          pos++;
          ctx = 0;
          ctxType = 0;
        }
      }
      else
        pos++;
    }
    else
    {
      if (text[pos] == '[')
      {
        pos++;
        while (text[pos] == '=')
          pos++, ctxType++;
        if (text[pos] == '[')
        {
          pos++;
          ctx = ctxString;
        }
        else
          ctxType = 0;
      }
      else if (text[pos] == '-' && text[pos + 1] == '-')
      {
        pos += 2;
        if (text[pos] == '[')
        {
          pos++;
          while (text[pos] == '=')
            pos++, ctxType++;
          if (text[pos] == '[')
          {
            pos++;
            ctx = ctxComment;
          }
          else
            return;
        }
        else
          return;
      }
      else if (text[pos] == '"' || text[pos] == '\'')
      {
        wchar_t end = text[pos++];
        while (text[pos] && text[pos] != end)
        {
          if (text[pos] == '\\') pos++;
          if (text[pos]) pos++;
        }
        if (text[pos])
          pos++;
      }
      else
        pos++;
    }
  }
  if (pos > pt.x || ctx) return;
  if (text[pt.x] == '[')
  {
    int pos = pt.x + 1;
    while (text[pos] == '=')
      pos++;
    if (text[pos] == '[')
      return;
  }

  int start = pt.x;
  int type = 0;
  WideString kw;
  if (isBracket(lines[pt.y].text[pt.x]))
    type = 1;
  else
  {
    int end = start;
    while (start > 0 && iswalpha(lines[pt.y].text[start - 1]))
      start--;
    while (iswalpha(lines[pt.y].text[end]))
      end++;
    kw = lines[pt.y].text.substring(start, end);
    if (keywords.has(kw))
      type = -1;
  }
  if (type == 0 && pt.x > 0 && isBracket(lines[pt.y].text[pt.x - 1]))
  {
    start = pt.x - 1;
    type = 1;
  }
  pt.x = start;
  if (type == 1)
  {
    int stack = 1;
    wchar_t fwd = lines[pt.y].text[start];
    wchar_t rev = isBracket(fwd);
    bool forward = (fwd == '(' || fwd == '[' || fwd == '{');
    while (stack > 0)
    {
      WideString brk = (forward ? nextKey(pt, true) : prevKey(pt, true));
      if (brk.length() == 0 || pt.y < 0 || pt.y >= lines.length())
        break;
      if (brk[0] == fwd)
        stack++;
      else if (brk[0] == rev)
        stack--;
    }
    if (stack == 0)
    {
      focus.push(FocusWord(fromPoint(pt), 1));
      pt = toPoint(caret); pt.x = start;
      focus.push(FocusWord(fromPoint(pt), 1));
    }
  }
  else if (type == -1 && kwInGraph.has(kw))
  {
    Array<WideString> stk;
    stk.push(kw);
    POINT save = pt;
    while (stk.length() && pt.y < lines.length())
    {
      WideString next = nextKey(pt, false);
      if (next.length() == 0) break;
      if (inKwGraph(stk.top(), next))
      {
        if (stk.length() == 1)
          focus.push(FocusWord(fromPoint(pt), next.length()));
        stk.top() = next;
      }
      else if (kwBegin.has(next))
        stk.push(next);
      if (kwEnd.has(stk.top()))
        stk.pop();
    }
    pt = save;
    stk.clear();
    stk.push(kw);
    while (stk.length() && pt.y >= 0)
    {
      WideString prev = prevKey(pt, false);
      if (prev.length() == 0) break;
      if (inKwGraph(prev, stk.top()))
      {
        if (stk.length() == 1)
          focus.push(FocusWord(fromPoint(pt), prev.length()));
        stk.top() = prev;
      }
      else if (kwEnd.has(prev))
        stk.push(prev);
      if (kwBegin.has(stk.top()) && (stk.top() != L"do" || stk.length() > 1))
        stk.pop();
    }
    if (focus.length())
    {
      pt = toPoint(caret); pt.x = start;
      focus.push(FocusWord(fromPoint(pt), kw.length()));
    }
  }
  focus.sort();
}
Exemple #9
0
//________________________________________________________
void GFOverlay::Overlay(const TObjArray &dirs, const TObjArray &legends)
{
  // 'directories' must contain TDirectory and inheriting, being parallel with legends,
  // method is called recursively
  TDirectory *dir1 = 0;
  for (Int_t iDir = 0; !dir1 && iDir < dirs.GetEntriesFast(); ++iDir) {
    dir1 = static_cast<TDirectory*>(dirs[iDir]);
  }
  if (!dir1) return;

  const Int_t currentLayer = fLayer;
  fLayer += (fSummaries ? 2 : 1);
  std::vector<TH1*> meanHists, rmsHists;

  // Now loop on keys of first directory (i.e. first file). If not deselected, foresee hists
  // for plotting and directories for recursion. Other objects are ignored. 
  UInt_t counter = 0;
  TIter nextKey(dir1->GetListOfKeys());
//   //  while(TKey* key = static_cast <TKey*> (nextKey())) {
//   // OK, make CINT happy, i.e. make .L GFOverlay.C work without extending '+':
  TKey* key = NULL; 
  while ((key = static_cast <TKey*> (nextKey()))) {
    // If key's name is deselected for both cases (hist and dir), avoid reading object:
    if (!fHistNames.IsEmpty()   && !this->KeyContainsListMember(key->GetName(), fHistNames)
	&& !fDirNames.IsEmpty() && !this->KeyContainsListMember(key->GetName(), fDirNames )) {
      continue; // type (dir/hist) independent skip: not actively selected!
    }
    if (this->KeyContainsListMember(key->GetName(), fSkipHistNames)
	&& this->KeyContainsListMember(key->GetName(), fSkipDirNames)) {
      continue; // type (dir/hist) independent skip: actively deselected!
    }
    // Now read object (only of first directory/file!) to be able to check type specific
    // skipping (hist or dir):
    TObject *obj = key->ReadObj();
    if (!obj) continue; // What ? How that?
    if (obj->InheritsFrom(TH1::Class())) {
      if (!fHistNames.IsEmpty() && !this->KeyContainsListMember(key->GetName(), fHistNames)) {
	continue;
      }
      if (this->KeyContainsListMember(key->GetName(), fSkipHistNames)) continue;
    } else if (obj->InheritsFrom(TDirectory::Class())) {
      if (!fDirNames.IsEmpty() && !this->KeyContainsListMember(key->GetName(), fDirNames)) {
	continue;
      }
      if (this->KeyContainsListMember(key->GetName(), fSkipDirNames)) continue;
    }
    // Now key survived! First treat for hist case:
    TObjArray hists(this->GetTypeWithNameFromDirs(TH1::Class(), key->GetName(), dirs));
    if (this->AddHistsAt(hists, legends, currentLayer, counter) > 0) {
      if (fSummaries) {
	this->CreateFillMeanRms(hists, currentLayer, dir1->GetName(), meanHists, rmsHists);
      }
      ++counter;
    }
    // Now treat directory case:
    TObjArray subDirs(this->GetTypeWithNameFromDirs(TDirectory::Class(), key->GetName(), dirs));
    if (subDirs.GetEntries()) { // NOT GetEntriesFast()!
      ::Info("GFOverlay::Overlay", "Key '%s' is directory to do recursion.", key->GetName());
      this->Overlay(subDirs, legends);
    }
  } // end of loop on keys
   
  // If mean/rms hists created, add them to manager:
  for (unsigned int iMean = 0; iMean < meanHists.size(); ++iMean) {
    fHistMan->AddHistSame(meanHists[iMean], currentLayer + 1, 0, legends[iMean]->GetName());
    fHistMan->AddHistSame(rmsHists[iMean], currentLayer + 1, 1, legends[iMean]->GetName());
  }
}
void splitUncertainties_byCat(TString inFileName, TString outFileName) {

  int numChannels = 15;
  TString channelNames[] = {
    //"ljets_j4_t2", 		//	 "j4_2t",
    "ljets_j4_t3", 		//	 "j4_3t",
    "ljets_j4_t4", 		//	 "j4_3t",
    //"ljets_j5_t2", 		//	 "j5_2t",
    "ljets_j5_t3", 		//	 "j5_3t",
    "ljets_j5_tge4", 		//	 "j5_3t",
    "ljets_jge6_t2", 		//	 "j6_2t",
    "ljets_jge6_t3", 		//	 "j6_3t",
    "ljets_jge6_tge4",    	//	 "j6_3t",
    "ge3t",	       		// dilep >= 3tags
    "e2je2t",   		// dilep 2 jets 2 tags
    "e3je2t",   		// dilep 3 jets 2 tags
    "ge4je2t",   		// dilep >=4 jets 2 tags
    "SS_e3je1t",   		// dilep SS 3 jets 1 tags
    "SS_ge4je1t",   		// dilep SS >=4 jets 1 tags
    "SS_e3jge2t",   		// dilep SS 3 jets >=2 tags
    "SS_ge4jge2t",   		// dilep SS >=4 jets >=2 tags
  };

  //Open the root file
  TFile *inFile = TFile::Open(inFileName);
  TFile *outFile = TFile::Open(outFileName,"RECREATE");

  //Define the list of uncertainties we're going to split
  TList nuisancePars;
  nuisancePars.Add(new TObjString("CMS_eff_b"));
  nuisancePars.Add(new TObjString("CMS_fake_b"));

  //Now loop over all the histograms in the file and either copy or 
  //Split as needed
  TList *keys = inFile->GetListOfKeys();

  TIter nextKey(keys);
  TKey *key = 0;

  while ((key = (TKey *)nextKey())) {

    TString name = key->GetName();
    TString newName = name;

//     std::cout << "Copying histogram " << name << std::endl;

    TH1 *hist = (TH1 *)inFile->Get(name);

    if( name.Contains("bShape") ){
      for (int j=0; j<numChannels; j++) {
	if( name.Contains(channelNames[j]) ) newName.ReplaceAll("CMS",channelNames[j]);
      }
    }

    //Automatically copy the original histogram over
    outFile->cd();
    hist->Write(newName);

  }

}
void CombineTGraphsFromTwoDirectories(TDirectory *dir1, TDirectory *dir2, Int_t iBaseDir, TDirectory *outputDir, Bool_t shouldAddQuadrature)
{

  // Gather TGraphErrors from 1st directory
  vector<TGraphAsymmErrors*> graphsDir1;
  TIter nextKey(dir1->GetListOfKeys());
  TObject *obj;
  while ((obj = nextKey())) {
    TKey *thisKey = dynamic_cast<TKey*>(obj);
    TGraphAsymmErrors *graph = dynamic_cast<TGraphAsymmErrors*>(thisKey->ReadObj());
    if(!graph) continue;
    graphsDir1.push_back(graph);
    cout << "This graph name is " << graph->GetName() << endl;
  }

  // Gather equivalent TGraphErrors from 2nd directory
  vector<TGraphAsymmErrors*> graphsDir2;
  for (UInt_t iGraph = 0; iGraph < graphsDir1.size(); iGraph++) {
    TString graphName = graphsDir1[iGraph]->GetName();
    TGraphAsymmErrors *equivGraph = (TGraphAsymmErrors*)dir2->Get(graphName);
    if (!equivGraph) {
      cout << "Could not find equivalent graph in 2nd directory for "
	   << graphName << endl;
      graphsDir2.push_back(NULL); // Put in Null as a place holder
    } else {
      graphsDir2.push_back(equivGraph);
    }
  }

  // Figure out which directory to get the base histogram from
  TDirectory *baseDir;
  if (iBaseDir == 1) {
    baseDir = dir1;
  } else if (iBaseDir == 2) {
    baseDir = dir2;
  } else {
    cout << "Uh oh! Not a valid directory from which to get base histograms. Index: "
	 << iBaseDir << endl;
  }

  // Gather the base histograms
  vector<TH1D*> baseHists;
  for (UInt_t iGraph = 0; iGraph < graphsDir1.size(); iGraph++) {
    TString histName = graphsDir1[iGraph]->GetName();
    histName.ReplaceAll("AsymmErrors","");
    TH1D *hist = (TH1D*) baseDir->Get(histName);
    if(!hist) {
      cout << "Could not find base histogram with name "
	   << histName << endl;
      baseHists.push_back(NULL); // Put in NULL as placeholder
    } else {
      baseHists.push_back(hist);
    }
  }

  // Now combine each graph, save it with its corresponding histogram, and draw it
  for (UInt_t iGraph = 0; iGraph < graphsDir1.size(); iGraph++) {
    // Make sure the components exist
    if (!graphsDir1[iGraph] || !graphsDir2[iGraph] || !baseHists[iGraph]) {
      cout << "Missing component. Cannot combine graphs for index "
	   << iGraph << endl;
      continue;
    }

    TGraphAsymmErrors* combinedGraph = CombineTwoTGraphAsymm(graphsDir1[iGraph], graphsDir2[iGraph], baseHists[iGraph], shouldAddQuadrature);
    WriteResults(combinedGraph, baseHists[iGraph], outputDir, shouldAddQuadrature);
  }
}