// Author: Gero Flucke <mailto:flucke@mail.desy.de>
//____________________________________
// GFDstarAnalyseMc
//   Author:      Gero Flucke
//   Date:        June 1st, 2002
//   last update: $Date: 2006/01/11 12:23:11 $  often
//   by:          $Author: flucke $
//
// C++
// #include <iostream>
#include <cstdlib>
#include <limits.h>

// RooT
#include <TString.h>
#include <TMath.h>
#include <TRandom.h>
#include <TH2.h>
#include <TProfile.h>
#include <TProfile2D.h>
#include <TF1.h>

// H1OO
#include "H1Steering/H1SteerManager.h"
#include "H1Skeleton/H1Tree.h"
#include "H1Skeleton/H1EventList.h"
#include "H1UserDstar/H1UserDstarEvent.h"
#include "H1UserDstar/H1UserDstarAccess.h"
#include "H1UserDstar/H1UserDstarUtil.h"
#include "H1Skeleton/H1SteerTree.h"
#include "H1Pointers/H1BytePtr.h"
#include "H1Geom/H1DBManager.h"
#include "H1Geom/H1ElectronTagger.h"
#include "H1Pointers/H1FloatPtr.h"
#include "H1Mods/H1PartSelTrack.h"
#include "H1Mods/H1PartDstar.h"
#include "H1Mods/H1PartDstarArrayPtr.h"
#include "H1Mods/H1PartMC.h"
#include "H1Mods/H1PartMCArrayPtr.h"
#include "H1Mods/H1PartJetArrayPtr.h"
#include "H1Mods/H1PartJet.h"
#include "H1Mods/H1GetPartMCId.h"
#include "H1OOBanks/ODS/H1Yrcl.h"
#include "H1OOBanks/ODS/H1YrclBankPtr.h"
#include "H1OOBanks/ODS/H1Gtr.h"
#include "H1OOBanks/ODS/H1GtrBankPtr.h"
#include "H1OOBanks/ODS/H1Str.h"
#include "H1Tracks/H1Track.h"
#include "H1Tracks/H1VertexFittedTrack.h"

// #include "H1HatFiller/H1HatMCFiller.h"

// private
#include "GFDstarAnalyseMc.h"
#include "GFUtils/GFHistArray.h"
#include "GFUtils/GFHistManip.h"
#include "GFUtils/GFDstarRunPeriods.h"
#include "GFData/GFSteerDstarAnalyse.h"

using namespace std;

ClassImp(GFDstarAnalyseMc)

 GFDstarAnalyseMc::GFDstarAnalyseMc()
{
  fEventCutQ2Gen = fSteer->GetQ2maxGen();

  this->SetIgnoreDedx(kTRUE); // FIXME: need MC with correct dedx!

  fTrigHistsS83 = fTrigHistsS84 = fNonTrigHistsS83 = fNonTrigHistsS84 = 
    fTrigHists19S83 = fTrigHists19S84 = fTrigHists31S83 = fTrigHists31S84 = NULL;

  fGenHistsS83 = fGenHistsS84 = fGenWeightHistsS83 = fGenWeightHistsS84 = NULL;
  fDetAccHistsS83 = NULL;
  fGenAcceptHistsS83 = fGenAcceptHistsS84 = NULL;
  fGenNoAccWeightHistsS83 = fGenNoAccWeightHistsS84 = NULL;

  fWeightHistsS83 = fWeightHistsS84 = NULL;

  fAcceptHistsS83 = fAcceptHistsS84 = NULL;
//   fAcceptHistsS84Pt = fAcceptHistsS84Eta = fAcceptHistsS84Phi
//     = fAcceptHistsS84WgammaP = NULL;
//   fTrigHistsS84Pt = fTrigHistsS84Eta = fTrigHistsS84Phi
//     = fTrigHistsS84WgammaP = NULL;
  fYjbResHists = fYjbResHistsS83 = fYjbResHistsS84 = NULL;
  fEflowHistsS83 = fEflowHistsS84 = NULL;

  fJetQuarkHists = fJetQuarkHistsS83 = fJetQuarkHistsS84 = NULL;
  fNumJetQuarkHistsPerJet = 0;
  fDsJetQuarkHistsS83 = NULL;
//   fJetPurStabHists = fJetPurStabHistsS83 = fJetPurStabHistsS84 = NULL;
//   fJetPurStabPtInEtaHists = fJetPurStabPtInEtaHistsS83 = fJetPurStabPtInEtaHistsS84 = NULL;


  fDstar1JetHistsGS83 = fDstar1JetHistsGAS83 = fDstar1JetHistsGWS83
    = fDstar1JetHistsGNAWS83 = fDstarBack1JetHistsGS83 = fDstarBack1JetHistsGAS83
    = fDstarBack1JetHistsGWS83 = fDstarBack1JetHistsGNAWS83 = fDstarForw1JetHistsGS83
    = fDstarForw1JetHistsGAS83 = fDstarForw1JetHistsGWS83 = fDstarForw1JetHistsGNAWS83
    = fDstar1JetHistsGS84 = fDstar1JetHistsGAS84 = fDstar1JetHistsGWS84
    = fDstar1JetHistsGNAWS84 = fDstarBack1JetHistsGS84 = fDstarBack1JetHistsGAS84
    = fDstarBack1JetHistsGWS84 = fDstarBack1JetHistsGNAWS84 = fDstarForw1JetHistsGS84
    = fDstarForw1JetHistsGAS84 = fDstarForw1JetHistsGWS84 = fDstarForw1JetHistsGNAWS84 
    = NULL;

  fDstarDiJetHistsGS83 = fDstarDiJetHistsGAS83 = fDstarDiJetHistsGWS83 
    = fDstarDiJetHistsGNAWS83 = fDstarDiJetHistsGS84 = fDstarDiJetHistsGAS84
    = fDstarDiJetHistsGWS84 = fDstarDiJetHistsGNAWS84 = NULL;


  fTrigDs1JetHistsS83 = fTrigDs1JetHistsS84 = fNonTrigDs1JetHistsS83 = fNonTrigDs1JetHistsS84 
    = fTrig19Ds1JetHistsS83 = fTrig19Ds1JetHistsS84 
    = fTrig31Ds1JetHistsS83 = fTrig31Ds1JetHistsS84 = NULL;
  fTrigDs1JetBackHistsS83 = fTrigDs1JetBackHistsS84 
    = fNonTrigDs1JetBackHistsS83 = fNonTrigDs1JetBackHistsS84 
    = fTrig19Ds1JetBackHistsS83 = fTrig19Ds1JetBackHistsS84 
    = fTrig31Ds1JetBackHistsS83 = fTrig31Ds1JetBackHistsS84 = NULL;
  fTrigDs1JetForwHistsS83 = fTrigDs1JetForwHistsS84 
    = fNonTrigDs1JetForwHistsS83 = fNonTrigDs1JetForwHistsS84 
    = fTrig19Ds1JetForwHistsS83 = fTrig19Ds1JetForwHistsS84 
    = fTrig31Ds1JetForwHistsS83 = fTrig31Ds1JetForwHistsS84 = NULL;

  fNonTrigDsDiJetHistsS83 = fNonTrigDsDiJetHistsS84 = fTrigDsDiJetHistsS83
    = fTrigDsDiJetHistsS84 = fTrig19DsDiJetHistsS83 = fTrig19DsDiJetHistsS84
    = fTrig31DsDiJetHistsS83 = fTrig31DsDiJetHistsS84 = NULL;

  fDsJetPurStabHists 
    = fDsJetPurStabHistsDphi = fDsJetPurStabHistsDeta = fDsJetPurStabHistsDeltaR 
    = fDsJetPurStabHistsXgam
    = fDsJetPurStabHistsDsPt = fDsJetPurStabHistsJetPt = fDsJetPurStabHistsJetEta 
    = fDsJetPurStabHistsJetPhi = fDsJetPurStabHistsJetDaugh = fDsJetPurStabHistsChFrac 
    = fDsJetPurStabHistsDsJetPt = fDsJetPurStabHistsDsJetM 
    = fDsJetPurStabHistsCosTh = fDsJetPurStabHistsPtDsJetOrth = NULL;
  fDsJetPurStabHistsS83 
    = fDsJetPurStabHistsDphiS83 = fDsJetPurStabHistsDetaS83 = fDsJetPurStabHistsDeltaRS83 
    = fDsJetPurStabHistsXgamS83
    = fDsJetPurStabHistsDsPtS83 = fDsJetPurStabHistsJetPtS83 = fDsJetPurStabHistsJetEtaS83 
    = fDsJetPurStabHistsJetPhiS83 = fDsJetPurStabHistsJetDaughS83 = fDsJetPurStabHistsChFracS83 
    = fDsJetPurStabHistsDsJetPtS83 = fDsJetPurStabHistsDsJetPt2S83 
    = fDsJetPurStabHistsDsJetMS83 = fDsJetPurStabHistsCosThS83 
    = fDsJetPurStabHistsPtDsJetOrthS83 = NULL;
  fDsPurStabHistsZDsS83 = NULL;

  fDsJetPurStabPtInEtaHistArrays = fDsJetPurStabPtInPtHistArrays 
    = fDsJetPurStabEtaInPtHistArrays = NULL;
  fDsJetPurStabPtInEtaHistArraysS83= fDsJetPurStabPtInPtHistArraysS83 
    = fDsJetPurStabEtaInPtHistArraysS83 = NULL;

  fDsDiJetPurStabHistsS83 = fDsDiJetPurStabHistsDetaS83 = fDsDiJetPurStabHistsDphiS83 
    = fDsDiJetPurStabHistsXgamS83 = fDsDiJetPurStabHistsCosThS83
    = fDsDiJetPurStabHistsDijetPtS83 = fDsDiJetPurStabHistsDijetPt2S83
    = fDsDiJetPurStabHistsDJetPtS83 = fDsDiJetPurStabHistsOthJetPtS83 
    = fDsDiJetPurStabHistsDJetEtaS83 = fDsDiJetPurStabHistsOthJetEtaS83
    = NULL;

  fBranchingHists = NULL;
  fHadronisationHistsS83 = fHadronisationGenHistsS83 = NULL;
  fHadPurStabHists = fHadPurStabHistsJetPt = fHadPurStabHistsJetEta = fHadPurStabHistsDphi = 
    fHadPurStabHistsDeta = fHadPurStabHistsXgam = fHadPurStabHistsMDsJet = 
    fHadPurStabHistsPtDsJet = NULL;

  fHadronisationDsDiJetHistsS83 = fHadronisationDsDiJetGenHistsS83 = NULL;
  fHadPurStabDijetHists = fHadPurStabDijetHistsDphi 
    = fHadPurStabDijetHistsXgam = NULL;

  fWeight83 = fWeight84 = fWeightPt = 1.; // storage for weights to apply
  fInversePrescale33 = fInversePrescale44 = 1.;
  fY33Rec = 0.;
  fWeightFunc = NULL;
  if(*fPeriod == "Cascade"){
    this->Info("GFDstarAnalyseMc", "cascade weights!");
    fWeightFunc = new TF1("cascweights", "expo");
    Double_t params[2] = {4.36940020045478772e-01, -1.43098217256363430e-01};
    fWeightFunc->SetParameters(params);
  }

//   this->Warning("GFDstarAnalysMc", "Do not open user tree!");
//   fOpenUserTree = kFALSE;

  fMeanAccept84 = NULL;//this->CreateMeanAccept84();

  fTag84OfPeriod = NULL;

  TFile *fileEffCor = TFile::Open("/afs/desy.de/user/f/flucke/h1/oo/analyse/trackcalib.root");
  if(!fileEffCor) this->Fatal("GFDstarAnalyseMc", "trackcalib file not accessable!");
  fHistEffCorrLowPt  = static_cast<TH2*>(fileEffCor->Get("h1226"));
  fHistEffCorrHighPt = static_cast<TH2*>(fileEffCor->Get("h1206"));

  if(!fHistEffCorrHighPt || !fHistEffCorrLowPt){
    fileEffCor->ls();
    this->Fatal("GFDstarAnalyseMc", "track weighting hists not found");
  }
  fHistEffCorrLowPt->SetDirectory(NULL);
  fHistEffCorrHighPt->SetDirectory(NULL);
  delete fileEffCor;
}

//_____________________________________________________
 GFDstarAnalyseMc::~GFDstarAnalyseMc()
{
  delete fDsJetPurStabEtaInPtHistArrays;
  delete fDsJetPurStabPtInEtaHistArrays;
  delete fDsJetPurStabPtInPtHistArrays;
  delete fDsJetPurStabEtaInPtHistArraysS83;
  delete fDsJetPurStabPtInEtaHistArraysS83;
  delete fDsJetPurStabPtInPtHistArraysS83;

  GFDstarRunPeriods per(84, fPeriod->Data());
  for(Int_t i = 0; i < per.GetNumPeriods(); ++i){
    delete fTag84OfPeriod[i];
    fTag84OfPeriod[i] = NULL;
  }
  delete[] fTag84OfPeriod; fTag84OfPeriod = NULL;
  delete fMeanAccept84; fMeanAccept84 = NULL;

  delete fHistEffCorrLowPt;
  delete fHistEffCorrHighPt;
}

//_____________________________________________________
 void GFDstarAnalyseMc::StartJob()
{
  // create taggers for different periods
  GFDstarRunPeriods per(84, fPeriod->Data());
  fTag84OfPeriod = new H1ElectronTagger*[per.GetNumPeriods()];
//   this->Warning("GFDstarAnalyseMc", 
  // 		"Hard coding periods for lumi weighted acceptance mean (right)!!!n");
  for(Int_t i = 0; i < per.GetNumPeriods(); ++i){
    fTag84OfPeriod[i] = static_cast<H1ElectronTagger*>
      (H1DBManager::Instance()->CreateDBEntry(H1ElectronTagger::Class(), 
     					      // i <= 8 ? 253307 : 275801)); // most right
					      // i <= 8 ? 258544 : 262204)); // most left
					      per.GetFirstRun(i)));
  }
}

//_____________________________________________________
 void GFDstarAnalyseMc::StartRun(Int_t run)
{
  // adjust the inverse prescale values

//   static Int_t numWarn = 0;
//   if(numWarn == 10) this->Warning("StartRun", "Last show up of following error:");
//   if(numWarn <= 10) {
//     this->Warning("StartRun","Ignoring prescales for run %d!", run);
//     ++numWarn;
//   }
//   fInversePrescale33 = fInversePrescale44 = 1.;
//   return;
  GFDstarRunPeriods per(84, fPeriod->Data());
  Double_t prescale = per.GetPrescale(per.GetPeriod(run));
  if(prescale > 0.) fInversePrescale44 = 1./prescale;
  else {
    static Int_t numWarn = 0;
    if(numWarn == 10) this->Error("StartRun", "Last show up of following error:");
    if(numWarn <= 10) {
      this->Error("StartRun","84-prescale for period of run %d is %f! Use 1!", run, prescale);
      ++numWarn;
    }
    fInversePrescale44 = 1.;
  }
  per.SetTrigger(83, fPeriod->Data());
  prescale = per.GetPrescale(per.GetPeriod(run));
  if(prescale > 0.) fInversePrescale33 = 1./prescale;
  else {
    static Int_t numWarn = 0;
    if(numWarn == 10) this->Error("StartRun", "Last show up of following error:");
    if(numWarn <= 10) {
      this->Error("StartRun","83-prescale for period of run %d is %f! Use 1!", run, prescale);
      ++numWarn;
    }
    fInversePrescale33 = 1.;
  }
  return;
}

//_____________________________________________________
 void GFDstarAnalyseMc::EndJob()
{
  // divide hists by lumi and call EndJob from base class

  H1SteerTree *steerTree = static_cast<H1SteerTree*>
    (gH1SteerManager->GetSteer(H1SteerTree::Class()));
  const char *name = gH1SteerManager->GetCurrentNameSpace();
  if(steerTree->GetLumi()){
    const Double_t invLumi = 1./steerTree->GetLumi();
    cout << "nNormalise histograms to lumi " << steerTree->GetLumi() << " (" << name << ").n"
	 << endl;
    for(Int_t iArr = 0; iArr < fAllHistArrays.GetEntriesFast(); ++iArr){
      GFHistArray *hists = static_cast<GFHistArray*>(fAllHistArrays[iArr]);
      for(Int_t iHist = 0; iHist < hists->GetEntriesFast(); ++iHist){
	TH1 *h = hists->At(iHist);
	if (h){
	  if (h->InheritsFrom(TProfile::Class()) 
	      || h->InheritsFrom(TProfile2D::Class())) {
	    cout << "Do not scale profile hist " << h->GetName() << endl;
	    continue; // skip profile
	  }
	  if(!h->GetSumw2N()){
	    TString name(h->GetName());
	    if(!name.EndsWith("S83") && !name.EndsWith("S84")){
	      cout << "In " << h->GetDirectory()->GetName() 
		   << ": no array of weights for hist " << name.Data()
		   << endl;
	    }
	  }
	  GFHistManip::Scale(h, invLumi);
	}
      }
    }
  } else {
    this->Error("EndJob", "No lumi for %s, skip normalisation!", name);
  }

  this->GFDstarAnalyse::EndJob();
}

//_____________________________________________________
 void GFDstarAnalyseMc::PrepareEvent()
{
  // do things that should manipulate the event and should stay for the whole event

  this->GFDstarAnalyse::PrepareEvent();

  static Bool_t first = kTRUE;
  if (first) {
    first = kFALSE;
    this->Info("PrepareEvent", "change jet pt upwards");
  }

  static H1PartDstarArrayPtr dstars; // what about WC D* jets?
  for (Int_t iDs = 0; iDs < dstars.GetEntries(); ++iDs) {
    TObjArray *jets = H1UserDstarAccess::DstarJets(iDs);
    if (!jets) continue;
    for (Int_t iJ = 0; iJ < jets->GetEntriesFast(); ++iJ) {
      H1PartJet *jet = static_cast<H1PartJet*>(jets->At(iJ));
      Double_t ratioTrack = 0., ratioEmClus = 0., ratioHadClus = 0.;
      this->GetEtRatios(jet, ratioTrack, ratioEmClus, ratioHadClus);
      TVector3 mom(jet->GetMomentum());
      const Double_t ptOrig = mom.Pt();
      const Double_t ptNew =
	//ptOrig * (ratioTrack + ratioEmClus * 1.02 + ratioHadClus * 1.04);
	//ptOrig * (ratioTrack + ratioEmClus * 0.98 + ratioHadClus * 0.96);
	//ptOrig * (ratioTrack * 0.99 + ratioEmClus + ratioHadClus);
	ptOrig * (ratioTrack * 1.01 + ratioEmClus + ratioHadClus);
      mom *= (ptNew/ptOrig);
      jet->SetFourVector(mom.Px(),mom.Py(),mom.Pz(), jet->GetMass());
    }
  }

  return;
}



//_____________________________________________________
 Double_t GFDstarAnalyseMc::GetMeanAccept44(Double_t y)
{
  if(!fMeanAccept84){
    TDirectory* oldDir = this->OpenHistsFile();
    const Int_t nBins = 2000;
    const Double_t upperY = 0.4;
    fMeanAccept84 = new TH1D("meanAccept84", "lumi weighted mean A_{44}(y)", nBins, 0., upperY);
    GFDstarRunPeriods per(84, fPeriod->Data());
    for(Int_t iPer = 0; iPer < per.GetNumPeriods(); ++iPer){
      for(Int_t iY = 0; iY < nBins; ++iY){
	Double_t y = (upperY * iY) / nBins;
	fMeanAccept84->AddBinContent(iY, 
				     fTag84OfPeriod[iPer]->Acceptance44(y) * per.GetLumi(iPer));
      }
    }
    fMeanAccept84->Scale(1./per.GetTotalLumi());
    oldDir->cd();
  }
  Int_t bin = fMeanAccept84->FindBin(y);
  return fMeanAccept84->GetBinContent(bin);
}

//_____________________________________________________
 void GFDstarAnalyseMc::CreateHistsDm(GFHistArray*& dmHists, GFHistArray*& dmHistsS83, 
				     GFHistArray*& dmHistsS84, const TString& nameAdd)
{
  // creating structure for weights for trigger hists
  this->GFDstarAnalyse::CreateHistsDm(dmHists, dmHistsS83, dmHistsS84, nameAdd);
  
  GFHistManip::CallSumw2(dmHistsS83);
  GFHistManip::CallSumw2(dmHistsS84);
}

//_____________________________________________________
 void GFDstarAnalyseMc::CreateHistsD0()
{

  this->GFDstarAnalyse::CreateHistsD0();

  GFHistManip::CallSumw2(fD0HistsS83);
  GFHistManip::CallSumw2(fD0HistsS84);
}


//_____________________________________________________
 void GFDstarAnalyseMc::CreateHistsL4Eff2()
{
  // creating structure for weights for trigger hists
  this->GFDstarAnalyse::CreateHistsL4Eff2();

  GFHistManip::CallSumw2(fL4NoHistsS83);
  GFHistManip::CallSumw2(fL4NoHistsS84);
  GFHistManip::CallSumw2(fL4YesHistsS83);
  GFHistManip::CallSumw2(fL4YesHistsS84);

  GFHistManip::CallSumw2(fL4YesNotDsHistsS83);
  GFHistManip::CallSumw2(fL4YesNotDsHistsS84);
  
  GFHistManip::CallSumw2(fL4NoDstarHistsS83);
  GFHistManip::CallSumw2(fL4NoDstarHistsS84);
  GFHistManip::CallSumw2(fL4YesDstarHistsS83);
  GFHistManip::CallSumw2(fL4YesDstarHistsS84);
}

//_____________________________________________________
 void GFDstarAnalyseMc::CreateHistsDstarJets()
{

  this->GFDstarAnalyse::CreateHistsDstarJets();

//   GFHistManip::CallSumw2(fDstar1JetHists);
  GFHistManip::CallSumw2(fDstar1JetHistsS83);
  GFHistManip::CallSumw2(fDstar1JetHistsS84);
//   GFHistManip::CallSumw2(fDstarBack1JetHists);
  GFHistManip::CallSumw2(fDstarBack1JetHistsS83);
  GFHistManip::CallSumw2(fDstarBack1JetHistsS84);
//   GFHistManip::CallSumw2(fDstarForw1JetHists);
  GFHistManip::CallSumw2(fDstarForw1JetHistsS83);
  GFHistManip::CallSumw2(fDstarForw1JetHistsS84);
}

//_____________________________________________________
 void GFDstarAnalyseMc::CreateHistsTracks()
{
  this->GFDstarAnalyse::CreateHistsTracks();
  //  GFHistManip::CallSumw2(fTrackHists);
  GFHistManip::CallSumw2(fTrackHistsS83);
  GFHistManip::CallSumw2(fTrackHistsS84);
}

//_____________________________________________________
 void GFDstarAnalyseMc::CreateHistsJetMult()
{
  this->GFDstarAnalyse::CreateHistsJetMult();
  GFHistManip::CallSumw2(fJetMultHistsS83);
}

//_____________________________________________________
 void GFDstarAnalyseMc::CreateHistsSumEt()
{
  this->GFDstarAnalyse::CreateHistsSumEt();
  GFHistManip::CallSumw2(fSumEtHistsS83);
  GFHistManip::CallSumw2(fSumEtHistsS84);
}


//_____________________________________________________
 void GFDstarAnalyseMc::CreateHistsDstarDiJet()
{
  this->GFDstarAnalyse::CreateHistsDstarDiJet();
  GFHistManip::CallSumw2(fDstarDiJetHists);
  GFHistManip::CallSumw2(fDstarDiJetHistsS83);
  GFHistManip::CallSumw2(fDstarDiJetHistsS84);
}


//_____________________________________________________
 void GFDstarAnalyseMc::CreateHistsTrig()//const char* nameAdd)
{
  TDirectory* oldDir = this->OpenHistsFile();
  TDirectory* dir = new TDirectory("trig", "trigger efficiency hists");

  fTrigHistsS83 = this->CreateHists("Trig", "efficiency TE ", 83, 1, dir);// ST, 1-D
  GFHistManip::CallSumw2(fTrigHistsS83);
  fNonTrigHistsS83 = this->CreateHists("NonTrig", "efficiency TE ", 83, 1, dir);
  GFHistManip::CallSumw2(fNonTrigHistsS83);
  fTrigHists19S83 = this->CreateHists("Trig19", "efficiency TE ", 83, 1, dir);
  GFHistManip::CallSumw2(fTrigHists19S83);
  fTrigHists31S83 = this->CreateHists("Trig31", "efficiency TE ", 83, 1, dir);
  GFHistManip::CallSumw2(fTrigHists31S83);

  fTrigHistsS84 = this->CreateHists("Trig", "efficiency TE ", 84, 1, dir);// ST, 1-D
  GFHistManip::CallSumw2(fTrigHistsS84);
  fNonTrigHistsS84 = this->CreateHists("NonTrig", "efficiency TE ", 84, 1, dir);
  GFHistManip::CallSumw2(fNonTrigHistsS84);
  fTrigHists19S84 = this->CreateHists("Trig19", "efficiency TE ", 84, 1, dir);
  GFHistManip::CallSumw2(fTrigHists19S84);
  fTrigHists31S84 = this->CreateHists("Trig31", "efficiency TE ", 84, 1, dir);
  GFHistManip::CallSumw2(fTrigHists31S84);

//   this->CreateHistsRunDepTrig84(fTrigHistsS84, dir);  // FIXME: needed???

  oldDir->cd();

  fAllHistArrays.Add(fTrigHistsS83);
  fAllHistArrays.Add(fNonTrigHistsS83);
  fAllHistArrays.Add(fTrigHists19S83);
  fAllHistArrays.Add(fTrigHists31S83);
  fAllHistArrays.Add(fTrigHistsS84);
  fAllHistArrays.Add(fNonTrigHistsS84);
  fAllHistArrays.Add(fTrigHists19S84);
  fAllHistArrays.Add(fTrigHists31S84);
}


//_____________________________________________________
 void GFDstarAnalyseMc::CreateHistsAccept()
{
  TDirectory* oldDir = this->OpenHistsFile();
  TDirectory* dir = new TDirectory("accept", "tagger acceptance hists");
//   dir->cd();

//   fAcceptHistsS83 = this->ClearCreateArray(fAcceptHistsS83);
//   fAcceptHistsS84 = this->ClearCreateArray(fAcceptHistsS84);

  fAcceptHistsS83 = this->CreateHists("Acc", "#sum_{i=1}^{N_{rec+trig}} (accept(y_{i}, run(i))",
				      83, 1, dir);// ST, 1-D
  fAcceptHistsS84 = this->CreateHists("Acc", "#sum_{i=1}^{N_{rec+trig}} (accept(y_{i}, run(i))",
				      84, 1, dir);// ST, 1-D

  // for correct error propagation:
  GFHistManip::CallSumw2(fAcceptHistsS83);
  GFHistManip::CallSumw2(fAcceptHistsS84);

//   this->CreateHistsRunDepAccept84(fAcceptHistsS84, dir);  // FIXME: still needed?

  oldDir->cd();

  fAllHistArrays.Add(fAcceptHistsS83);
  fAllHistArrays.Add(fAcceptHistsS84);
}

// //_____________________________________________________
// void GFDstarAnalyseMc::CreateHistsRunDepAccept84(
// GFHistArray* notRunDepPtEtaPhiWgammaP, TDirectory* dir)
// {
//   // FIXME: needed?
//   if(dir) dir->cd();

//   fAcceptHistsS84Pt = GFHistManip::ClearCreateArray(fAcceptHistsS84Pt);
//   fAcceptHistsS84Eta = GFHistManip::ClearCreateArray(fAcceptHistsS84Eta);
//   fAcceptHistsS84Phi = GFHistManip::ClearCreateArray(fAcceptHistsS84Phi);
//   fAcceptHistsS84WgammaP = GFHistManip::ClearCreateArray(fAcceptHistsS84WgammaP);
  
//   this->CreateRunDepAnalog((*notRunDepPtEtaPhiWgammaP)[0], fAcceptHistsS84Pt, 84);
//   this->CreateRunDepAnalog((*notRunDepPtEtaPhiWgammaP)[1], fAcceptHistsS84Eta, 84);
//   this->CreateRunDepAnalog((*notRunDepPtEtaPhiWgammaP)[2], fAcceptHistsS84Phi, 84);
//   this->CreateRunDepAnalog((*notRunDepPtEtaPhiWgammaP)[4], fAcceptHistsS84WgammaP, 84);// 4!!
// }

//_____________________________________________________
 void GFDstarAnalyseMc::CreateHistsGen()//const char* nameAdd)
{
  TDirectory* oldDir = this->OpenHistsFile();
  TDirectory* dir = new TDirectory("gen", "generator level hists");

  fGenHistsS83 = this->CreateHists("Gen", "generated D*", 83, 1, dir);// ST, 1-D
  fGenAcceptHistsS83 = this->CreateHists("GenAcc", "generated D* (accept. weighted)", 83,1,dir);
  fGenWeightHistsS83 = this->CreateHists("GenWeight", "generated D* (weighted)", 83, 1, dir);
  fGenNoAccWeightHistsS83 = 
    this->CreateHists("GenNoAccWeight", "generated D* (accept. * (!) weighted)", 83, 1, dir);

  fGenHistsS84 = this->CreateHists("Gen", "generated D*", 84, 1, dir);// ST, 1-D
  fGenAcceptHistsS84 = this->CreateHists("GenAcc", "generated D* (accept. weighted)", 84,1,dir);
  fGenWeightHistsS84 = this->CreateHists("GenWeight", "generated D* (weighted)", 84, 1, dir);
  fGenNoAccWeightHistsS84 = 
    this->CreateHists("GenNoAccWeight", "generated D* (accept. * (!) weighted)", 84, 1, dir);

  GFHistManip::CallSumw2(fGenHistsS83);
  GFHistManip::CallSumw2(fGenAcceptHistsS83);
  GFHistManip::CallSumw2(fGenWeightHistsS83);
  GFHistManip::CallSumw2(fGenNoAccWeightHistsS83);

  GFHistManip::CallSumw2(fGenHistsS84);
  GFHistManip::CallSumw2(fGenAcceptHistsS84);
  GFHistManip::CallSumw2(fGenWeightHistsS84);
  GFHistManip::CallSumw2(fGenNoAccWeightHistsS84);

  fDetAccHistsS83 = 
    this->CreateHists("GenWeightDetAcc", "(weighted) gen. D*, passing p_{t}(tr) etc.",83,1,dir);
  GFHistManip::CallSumw2(fDetAccHistsS83);
  fAllHistArrays.Add(fDetAccHistsS83);

  oldDir->cd();

  fAllHistArrays.Add(fGenHistsS83);
  fAllHistArrays.Add(fGenAcceptHistsS83);
  fAllHistArrays.Add(fGenWeightHistsS83);
  fAllHistArrays.Add(fGenNoAccWeightHistsS83);
  fAllHistArrays.Add(fGenHistsS84);
  fAllHistArrays.Add(fGenAcceptHistsS84);
  fAllHistArrays.Add(fGenWeightHistsS84);
  fAllHistArrays.Add(fGenNoAccWeightHistsS84);

}

// //_____________________________________________________
// void GFDstarAnalyseMc::CreateHistsRunDepTrig84(
// GFHistArray* notRunDepPtEtaPhiWgammaP, TDirectory* dir)
// {
//   // FIXME: needed?
//   if(dir) dir->cd();

//   fTrigHistsS84Pt = GFHistManip::ClearCreateArray(fTrigHistsS84Pt);
//   fTrigHistsS84Eta = GFHistManip::ClearCreateArray(fTrigHistsS84Eta);
//   fTrigHistsS84Phi = GFHistManip::ClearCreateArray(fTrigHistsS84Phi);
//   fTrigHistsS84WgammaP = GFHistManip::ClearCreateArray(fTrigHistsS84WgammaP);
  
//   this->CreateRunDepAnalog((*notRunDepPtEtaPhiWgammaP)[0], fTrigHistsS84Pt, 84);
//   this->CreateRunDepAnalog((*notRunDepPtEtaPhiWgammaP)[1], fTrigHistsS84Eta, 84);
//   this->CreateRunDepAnalog((*notRunDepPtEtaPhiWgammaP)[2], fTrigHistsS84Phi, 84);
//   this->CreateRunDepAnalog((*notRunDepPtEtaPhiWgammaP)[4], fTrigHistsS84WgammaP, 84);// 4!!
// }


//_____________________________________________________
 void GFDstarAnalyseMc::CreateHistsYjbRes(const char * nameAdd)
{
  if(!nameAdd){
    this->CreateHistsYjbRes("");
    this->CreateHistsYjbRes("S83");
    this->CreateHistsYjbRes("S84");
    return;
  }
  TDirectory* oldDir = this->OpenHistsFile();

  GFHistArray *hists = NULL;
  const TArrayD *wGammaPBins,*ptBins, *etaBins;
  Double_t yMin, yMax;

  TString add(nameAdd);
  if(add == "S83"){
    hists = GFHistManip::ClearCreateArray(fYjbResHistsS83);
    wGammaPBins = &fWgammaP33Bins;
    ptBins = fSteer->GetPtBins33();
    etaBins = fSteer->GetEtaBins33();
    yMin = fEventCutyMinS83;
    yMax = fEventCutyMaxS83;
  } else if(add == "S84"){
    hists = GFHistManip::ClearCreateArray(fYjbResHistsS84);
    wGammaPBins = &fWgammaP44Bins;
    ptBins = fSteer->GetPtBins44();
    etaBins = fSteer->GetEtaBins44();
    yMin = fEventCutyMinS84;
    yMax = fEventCutyMaxS84;
  } else if(add == ""){
    hists = GFHistManip::ClearCreateArray(fYjbResHists);
    wGammaPBins = &fWgammaP33Bins;
    ptBins = fSteer->GetPtBins44();
    etaBins = fSteer->GetEtaBins33();
    yMin = fEventCutyMinS84;
    yMax = fEventCutyMaxS83;
  } else {
    this->Warning("CreateHistsYjbRes",
		  "No histograms to build for nameAdd = %s, ignore!", nameAdd);
    oldDir->cd();
    return;
  }

   
  Int_t resBins = 40;
  Double_t resRange = 0.8;
  Double_t diffRange = 0.4;
  hists->Add(new TH2F("yjbResHist2D"+add, "y_{jb} vs. y_{gen}", // 0
		      50, yMin, yMax, 50, yMin, yMax));
  hists->Add(new TH1F("yjbResHist"+add, "(y_{jb} - y_{gen})/y_{gen}", // 1
		      2 * resBins, -resRange, resRange));

  hists->Add(new TH2F("yjbResPtHist2D"+add, "(y_{jb} - y_{gen})/y_{gen} vs p_{t}", //2
		      resBins, -resRange, resRange,
		      ptBins->GetSize()-1, ptBins->GetArray()));
  hists->Add(new TH2F("yjbResEtaHist2D"+add, "(y_{jb} - y_{gen})/y_{gen} vs #eta", //3
		      resBins, -resRange, resRange,
		      etaBins->GetSize()-1, etaBins->GetArray()));
  hists->Add(new TH2F("yjbResPhiHist2D"+add, "(y_{jb} - y_{gen})/y_{gen} vs #phi",//4
		      resBins, -resRange, resRange,
		      fSteer->GetPhiBins()->GetSize()-1, fSteer->GetPhiBins()->GetArray()));
  hists->Add(new TH2F("yjbResWgammaPHist2D"+add,                                  //5
		      "(y_{jb} - y_{gen})/y_{gen} vs W_{#gammap}", 
		      resBins, -resRange, resRange,
		      wGammaPBins->GetSize()-1, wGammaPBins->GetArray()));

  hists->Add(new TH2F("yjbResYgenHist2D"+add, "(y_{jb} - y_{gen})/y_{gen} vs y_{gen}",//6
		      resBins, -resRange, resRange, 25, yMin, yMax));
  hists->Add(new TH2F("yjbResYjbHist2D"+add, "(y_{jb} - y_{gen})/y_{gen} vs y_{jb}",//7
		      resBins, -resRange, resRange, 25, yMin, yMax));

  hists->Add(new TH2F("yjbYgenDiffHist2D"+add, "y_{jb} - y_{gen} vs y_{gen}",//8
		      resBins, -diffRange, diffRange, 25, yMin, yMax));
  hists->Add(new TH2F("yjbYjbDiffHist2D"+add, "y_{jb} - y_{gen} vs y_{jb}",//9
		      resBins, -diffRange, diffRange, 25, yMin, yMax));


  hists->Add(new TH2F("yjbvisgenResHist2D"+add, "y_{jb} vs. y_{gen-vis}", // 10
		      50, yMin, yMax, 50, yMin, yMax));
  hists->Add(new TH1F("yjbvisgenResHist"+add, "(y_{jb} - y_{gen-vis})/y_{gen-vis}", // 11
		      2 * resBins, -resRange, resRange));
  hists->Add(new TH2F("ygenyvisgenHist2D"+add, "y_{gen} vs. y_{gen-vis}", // 12
		      50, yMin, yMax, 50, yMin, yMax));
  hists->Add(new TH1F("ygenvisgenResHist"+add, "(y_{gen-vis} - y_{gen})/y_{gen}", // 13
		      2 * resBins, -0.5*resRange, 0.5*resRange));

  if(fYjbResHistsS83 == hists){
    hists->Add(new TH2F("yjbResYtagHist2D"+add, "y_{jb} vs. y_{tag}", // 14
			50, yMin, yMax, 50, yMin, yMax));
    hists->Add(new TH1F("yjbResYtagHist"+add, "(y_{jb} - y_{tag})/y_{tag}", // 15
			2 * resBins, -resRange, resRange));
    
    hists->Add(new TH2F("yjbResYtagPtHist2D"+add, "(y_{jb} - y_{tag})/y_{tag} vs p_{t}", //16
			resBins, -resRange, resRange,
			ptBins->GetSize()-1, ptBins->GetArray()));
    hists->Add(new TH2F("yjbResYtagEtaHist2D"+add, "(y_{jb} - y_{tag})/y_{tag} vs #eta", //17
			resBins, -resRange, resRange,
			etaBins->GetSize()-1, etaBins->GetArray()));
    hists->Add(new TH2F("yjbResYtagPhiHist2D"+add, "(y_{jb} - y_{tag})/y_{tag} vs #phi",//18
			resBins, -resRange, resRange,
			fSteer->GetPhiBins()->GetSize()-1, fSteer->GetPhiBins()->GetArray()));
    hists->Add(new TH2F("yjbResYtagWgammaPHist2D"+add,                                  //19
			"(y_{jb} - y_{tag})/y_{tag} vs W_{#gammap}", 
			resBins, -resRange, resRange,
			wGammaPBins->GetSize()-1, wGammaPBins->GetArray()));
    
    hists->Add(new TH2F("yjbResYtagYtagHist2D"+add, "(y_{jb} - y_{tag})/y_{tag} vs y_{tag}",//20
			resBins, -resRange, resRange, 25, yMin, yMax));
  }

  GFHistManip::CallSumw2(hists);
  oldDir->cd();

  fAllHistArrays.Add(hists);
}

//_____________________________________________________
 void GFDstarAnalyseMc::OpenTree()
{
  H1Tree::Instance()->Open();
  this->HatSelectYear(*fPeriod);
  H1Tree::Instance()->Register(this);
}

//_____________________________________________________
 void GFDstarAnalyseMc::HatSelectYear(const TString& year)
{
  TString hatSelection;
  if(year.Contains("2000")) {
    (((hatSelection = "RunNumber >= ") += H1RunDependent::FirstRun(2000))
     += " && RunNumber <= ") += H1RunDependent::LastRun(2000);
  } else if(year.Contains("99eplus")){
    //    (hatSelection = "RunNumber >= 246605 && RunNumber <= ") += H1RunDependent::LastRun(1999);
    this->Info("HatSelectYear", "hardcoded skipping of HAT selcetion");
  } else if(year.Contains("99eminus")){
    this->Fatal("HatSelectYear", "99eMinus not yet foreseen!");
  }

  if(hatSelection.Length()){
    cout << "HAT selection for year " << year << ": " << hatSelection.Data() << "n  ==> "
	 << H1Tree::Instance()->SelectHat(hatSelection.Data())
	 << " events survived.n"
	 << endl;
  } else {
    cout << "No HAT selection applied for a special year!" << endl;
  }
}

//_____________________________________________________
 void GFDstarAnalyseMc::FillHistsGen(const H1PartMC* genDstar)
{
  // assume genDstar to be a D* -> K, pi, pi_s

  if(!this->DstarCutLoose(genDstar)) return;

  const Bool_t s83 = this->IsS83Gen(genDstar); // cuts on higher pt
  const Bool_t s84 = this->IsS84Gen(genDstar); // cuts on backward direction
  if(!s83 && !s84) return;

  if(!fGenHistsS83) this->CreateHistsGen();

//   TObjArray allJets = this->GetGenJets();
  TObjArray allJets;
  this->GetNonDstarGenJets(genDstar, allJets);

  const Double_t yGen = this->GetYgen();

  H1ElectronTagger* tag = static_cast<H1ElectronTagger*>
    (H1DBManager::Instance()->GetDBEntry(H1ElectronTagger::Class()));
  if(s83) {
    const Double_t weight = this->GetWeight(83, NULL);
    const Double_t acceptance = tag->Acceptance33(yGen);
    const Double_t noAcceptWeight = weight/acceptance; // corr for run dep
    
    this->FillHistsGen(genDstar, &allJets, fGenHistsS83, 1.);
    this->FillHistsGen(genDstar, &allJets, fGenAcceptHistsS83, acceptance);
    this->FillHistsGen(genDstar, &allJets, fGenNoAccWeightHistsS83, noAcceptWeight);
    this->FillHistsGen(genDstar, &allJets, fGenWeightHistsS83, weight);

    static H1PartMCArrayPtr partMc;
    const H1PartMC *k = H1UserDstarUtil::GetK(genDstar, partMc.GetArray());
    const Double_t thetaMin = 20.*TMath::DegToRad();
    const Double_t thetaMax = 160.*TMath::DegToRad();
    if(k->GetPt() > fSteer->GetPtCutK() && 
	 k->GetTheta() < thetaMax && k->GetTheta() > thetaMin){
      const H1PartMC *pi = H1UserDstarUtil::GetPi(genDstar, partMc.GetArray());
      if(pi->GetPt() > fSteer->GetPtCutPi() && 
	 pi->GetTheta() < thetaMax && pi->GetTheta() > thetaMin){
	const H1PartMC *pis = H1UserDstarUtil::GetPis(genDstar, partMc.GetArray());
	if(pis->GetPt() > 0.12 && 
	 pis->GetTheta() < thetaMax && pis->GetTheta() > thetaMin){
	  this->FillHistsGen(genDstar, &allJets, fDetAccHistsS83, weight);
	}
      }
    }
  }
  if(s84) {
    const Double_t meanAcceptance = this->GetMeanAccept44(yGen);
    const Double_t weight = this->GetWeight(84, NULL);
    const Double_t noAcceptWeight = weight/tag->Acceptance44(yGen); // corr for run dep
    
    this->FillHistsGen(genDstar, &allJets, fGenHistsS84, 1.);
    this->FillHistsGen(genDstar, &allJets, fGenAcceptHistsS84, meanAcceptance);
    this->FillHistsGen(genDstar, &allJets, fGenNoAccWeightHistsS84, noAcceptWeight);
    this->FillHistsGen(genDstar, &allJets, fGenWeightHistsS84, weight);
  }
}

//_____________________________________________________
 void GFDstarAnalyseMc::FillHistsGen(const H1PartMC* genDstar, const TObjArray* jets, 
				    GFHistArray* hists, Double_t weight) const
{
  // filling 'hists' with default set of generated quantities

  (*hists)[0]->Fill(genDstar->GetPt(), weight);
  (*hists)[1]->Fill(genDstar->GetEta(), weight);
  (*hists)[2]->Fill(genDstar->GetPhi(), weight);
//   (*hists)[3]->Fill(?????????, weight);
  (*hists)[4]->Fill(this->GetWgammaPgen(), weight);
  const Double_t yGen = this->GetYgen();
  (*hists)[5]->Fill(yGen, weight);

  static H1FloatPtr simVtxZ("GenVtxZ");
  (*hists)[6]->Fill(*simVtxZ, weight);

  static H1PartMCArrayPtr mcP;
  const H1PartMC* d0 = H1UserDstarUtil::GetD0(genDstar, mcP.GetArray());
  const Double_t ptKpi = mcP[d0->GetDaughter1()]->GetPt() + mcP[d0->GetDaughter2()]->GetPt();
  (*hists)[7]->Fill(ptKpi, weight);

  // 8: NumCentralTracks
  const Int_t nJets = jets ? jets->GetEntriesFast() : 0;
  (*hists)[9]->Fill(nJets, weight);

  const Double_t zDs = this->GetZgen(genDstar);
  (*hists)[10]->Fill(zDs, weight);

  static_cast<TH2*>((*hists)[11])->Fill(genDstar->GetEta(), genDstar->GetPt(), weight);

  static_cast<TH2*>((*hists)[12])->Fill(this->GetWgammaPgen(), genDstar->GetPt(), weight);

  static_cast<TH2*>((*hists)[13])->Fill(this->GetWgammaPgen(), genDstar->GetEta(), weight);

  static_cast<TH2*>((*hists)[14])->Fill(zDs, genDstar->GetEta(), weight);

  static_cast<TH2*>((*hists)[15])->Fill(zDs, genDstar->GetPt(), weight);

//   TObjArray highPtJets;
//   highPtJets.AddAll(const_cast<TObjArray*>(jets)); // UGLY!!!
// //   if(this->RemoveLowPt(&highPtJets, 2) < 2) return;
//   this->RemoveLowPt(&highPtJets, 2);

//   H1PartJet* jet1 = (nJets > 0 ? static_cast<H1PartJet*>(highPtJets[0]) : NULL);
//   H1PartJet* jet2 = (nJets > 1 ? static_cast<H1PartJet*>(highPtJets[1]) : NULL);

//   if(jet1){
//     (*hists)[10]->Fill(jet1->GetPt(), weight);
//     (*hists)[12]->Fill(jet1->GetEta(), weight);
//   }
//   if(jet2){
//     (*hists)[11]->Fill(jet2->GetPt(), weight);
//     (*hists)[13]->Fill(jet2->GetEta(), weight);
//   }

//   if(nJets){
//     const H1PartJet* jetHighPt = 
//       static_cast<H1PartJet*>(highPtJets[this->GetHighestPt(highPtJets)]);
//     const Double_t xGamma = this->GetXgammaMass(genDstar, jetHighPt, this->GetYjbGen());
//     (*hists)[14]->Fill(xGamma, weight);
//   }
  
//   (*hists)[14]->Fill(ptKpi-genDstar->GetPt(), weight);
}

//_____________________________________________________
 Bool_t GFDstarAnalyseMc::FillHistsEffTrigAccept(const H1PartDstar* trigDstar)
{
  // assuming that trigDstar is already reconstructed with the lower
  // pt-cut and wider eta region
  // true if trigger bits 19 and 31 are set and we have s83 or s84
  // filling only for dm-window!

  if(!fNonTrigHistsS83) this->CreateHistsTrig();
  if(!fAcceptHistsS83) this->CreateHistsAccept();

  if(trigDstar->GetDm() >= fSteer->GetD0DeltaMHigh() 
     || trigDstar->GetDm() < fSteer->GetD0DeltaMLow()){
    return kFALSE;
  }


  const Bool_t s83 = this->IsS83NoL1Check(trigDstar);
  const Bool_t s84 = this->IsS84NoL1Check(trigDstar);

  if(s83 || s84){
    Bool_t result = kFALSE;

    static H1BytePtr  trigElements("Il1te");

    H1ElectronTagger* tagger =  static_cast<H1ElectronTagger*>
      (H1DBManager::Instance()->GetDBEntry(H1ElectronTagger::Class()));

    if(s83){
      this->FillHists(fNonTrigHistsS83, trigDstar, 83);
      if(trigElements[19]){
	this->FillHists(fTrigHists19S83, trigDstar, 83);
      }
      if(trigElements[31]){
	this->FillHists(fTrigHists31S83, trigDstar, 83);
      }

      if(trigElements[19] && trigElements[31]){
	this->FillHists(fTrigHistsS83, trigDstar, 83);
	const Float_t acceptance33 = tagger->Acceptance33(this->GetY33());
	this->FillHists(fAcceptHistsS83, trigDstar, 83, acceptance33);
	result = kTRUE;
      }
    } // if s83
    if(s84) {
      this->FillHists(fNonTrigHistsS84, trigDstar, 84);
      if(trigElements[19]){
	this->FillHists(fTrigHists19S84, trigDstar, 84);
      }
      if(trigElements[31]){
	this->FillHists(fTrigHists31S84, trigDstar, 84);
      }
      if(trigElements[19] && trigElements[31]){
	this->FillHists(fTrigHistsS84, trigDstar, 84);
	const Double_t y = this->GetY44();
	const Float_t acceptance44 = tagger->Acceptance44(y);
	this->FillHists(fAcceptHistsS84, trigDstar, 84, acceptance44);
// 	this->FillHistsRunDepAccept84(trigDstar, y);  // FIXME: needed?
	result = kTRUE;
      }
    }
    return result;
  } else return kFALSE;
}

// //_____________________________________________________
// void GFDstarAnalyseMc::FillHistsRunDepAccept84(const H1PartDstar* trigDstar, 
// 					       Double_t y)
// {
//   // FIXME: needed?
//     const Double_t ptDstar  = trigDstar->GetPt();
//     const Double_t etaDstar = trigDstar->GetEta();
//     const Double_t phiDstar = trigDstar->GetPhi();

//     GFDstarRunPeriods per(84, fPeriod->Data());
//     for(Int_t i = 0; i < per.GetNumPeriods(); ++i){
//       const Double_t acceptance44 = fTag84OfPeriod[i]->Acceptance44(y);
//       (*fAcceptHistsS84Pt)[i]->Fill(ptDstar, acceptance44);
//       (*fAcceptHistsS84Eta)[i]->Fill(etaDstar, acceptance44);
//       (*fAcceptHistsS84Phi)[i]->Fill(phiDstar, acceptance44);
//       (*fAcceptHistsS84WgammaP)[i]->Fill(this->GetWgammaP44(), acceptance44);

//       (*fTrigHistsS84Pt)[i]->Fill(ptDstar);
//       (*fTrigHistsS84Eta)[i]->Fill(etaDstar);
//       (*fTrigHistsS84Phi)[i]->Fill(phiDstar);
//       (*fTrigHistsS84WgammaP)[i]->Fill(this->GetWgammaP44());
//     }
// }

//_____________________________________________________
 void GFDstarAnalyseMc::FillHistsYjbRes(const H1PartDstar* ds)
{
  if(!fYjbResHistsS83) this->CreateHistsYjbRes();

  const Bool_t noYcut = //this->IsSumEt(ds) &&// this->IsZvtxCut() && 
    this->GetQ2gen() < fEventCutQ2Gen;
  const Bool_t s83noYcut = (!(ds && (ds->GetPt() < fSteer->GetPtBins33()->At(0))) && noYcut);
  const Bool_t s84noYcut = (!(ds && (ds->GetEta() < fSteer->GetEtaBins44()->At(0))) && noYcut);
  // weights are somehow aequivalent to y-cuts


  const Double_t y = this->GetYgen();
  const Double_t yVis = this->GetYgenVis();
  static H1FloatPtr yjb("Yjb"); // from dstarUser
  
  const Double_t yjbMinYgenThruYgen = y ? (*yjb - y)/y : 0.;

  if(noYcut){
    const Double_t weight = 1.;
    static_cast<TH2*>((*fYjbResHists)[0])->Fill(*yjb, y, weight);
    static_cast<TH2*>((*fYjbResHists)[1])->Fill(yjbMinYgenThruYgen, weight);
    static_cast<TH2*>((*fYjbResHists)[2])->Fill(yjbMinYgenThruYgen, ds->GetPt(), weight);
    static_cast<TH2*>((*fYjbResHists)[3])->Fill(yjbMinYgenThruYgen, ds->GetEta(), weight);
    static_cast<TH2*>((*fYjbResHists)[4])->Fill(yjbMinYgenThruYgen, ds->GetPhi(), weight);
    static_cast<TH2*>((*fYjbResHists)[5])->Fill(yjbMinYgenThruYgen, this->GetWgammaPgen(), 
						     weight);

    static_cast<TH2*>((*fYjbResHists)[6])->Fill(yjbMinYgenThruYgen, y, weight);
    static_cast<TH2*>((*fYjbResHists)[7])->Fill(yjbMinYgenThruYgen, *yjb, weight);
    static_cast<TH2*>((*fYjbResHists)[8])->Fill(*yjb - y, y, weight);
    static_cast<TH2*>((*fYjbResHists)[9])->Fill(*yjb - y, *yjb, weight);

    static_cast<TH2*>((*fYjbResHists)[10])->Fill(*yjb, yVis, weight);
    (*fYjbResHists)[11]->Fill((*yjb - yVis)/yVis, weight);
    static_cast<TH2*>((*fYjbResHists)[12])->Fill(y, yVis, weight);
    (*fYjbResHists)[13]->Fill((yVis - y)/y, weight);
  }
  if(s83noYcut){
    const Double_t weight = this->GetWeight(83, ds);
    static_cast<TH2*>((*fYjbResHistsS83)[0])->Fill(*yjb, y, weight);
    static_cast<TH2*>((*fYjbResHistsS83)[1])->Fill(yjbMinYgenThruYgen, weight);
    static_cast<TH2*>((*fYjbResHistsS83)[2])->Fill(yjbMinYgenThruYgen, ds->GetPt(), weight);
    static_cast<TH2*>((*fYjbResHistsS83)[3])->Fill(yjbMinYgenThruYgen, ds->GetEta(), weight);
    static_cast<TH2*>((*fYjbResHistsS83)[4])->Fill(yjbMinYgenThruYgen, ds->GetPhi(), weight);
    static_cast<TH2*>((*fYjbResHistsS83)[5])->Fill(yjbMinYgenThruYgen, this->GetWgammaP33(),
						   weight);
    static_cast<TH2*>((*fYjbResHistsS83)[6])->Fill(yjbMinYgenThruYgen, y, weight);
    static_cast<TH2*>((*fYjbResHistsS83)[7])->Fill(yjbMinYgenThruYgen, *yjb, weight);
    static_cast<TH2*>((*fYjbResHistsS83)[8])->Fill(*yjb - y, y, weight);
    static_cast<TH2*>((*fYjbResHistsS83)[9])->Fill(*yjb - y, *yjb, weight);

    static_cast<TH2*>((*fYjbResHistsS83)[10])->Fill(*yjb, yVis, weight);
    (*fYjbResHistsS83)[11]->Fill((*yjb - yVis)/yVis, weight);
    static_cast<TH2*>((*fYjbResHistsS83)[12])->Fill(y, yVis, weight);
    (*fYjbResHistsS83)[13]->Fill((yVis - y)/y, weight);

    const Double_t y33 = this->GetY33();
    const Double_t yjbMinY33ThruYgen = y33 ? (*yjb - y33)/y33 : 0.;

    static_cast<TH2*>((*fYjbResHistsS83)[14])->Fill(*yjb, y33, weight);
    static_cast<TH2*>((*fYjbResHistsS83)[15])->Fill(yjbMinY33ThruYgen, weight);
    static_cast<TH2*>((*fYjbResHistsS83)[16])->Fill(yjbMinY33ThruYgen, ds->GetPt(), weight);
    static_cast<TH2*>((*fYjbResHistsS83)[17])->Fill(yjbMinY33ThruYgen, ds->GetEta(), weight);
    static_cast<TH2*>((*fYjbResHistsS83)[18])->Fill(yjbMinY33ThruYgen, ds->GetPhi(), weight);
    static_cast<TH2*>((*fYjbResHistsS83)[19])->Fill(yjbMinY33ThruYgen, this->GetWgammaP33(),
						   weight);
    static_cast<TH2*>((*fYjbResHistsS83)[20])->Fill(yjbMinY33ThruYgen, y33, weight);


  }
  if(s84noYcut){
    const Double_t weight = this->GetWeight(84, ds);
    static_cast<TH2*>((*fYjbResHistsS84)[0])->Fill(*yjb, y, weight);
    static_cast<TH2*>((*fYjbResHistsS84)[1])->Fill(yjbMinYgenThruYgen, weight);
    static_cast<TH2*>((*fYjbResHistsS84)[2])->Fill(yjbMinYgenThruYgen, ds->GetPt(), weight);
    static_cast<TH2*>((*fYjbResHistsS84)[3])->Fill(yjbMinYgenThruYgen, ds->GetEta(), weight);
    static_cast<TH2*>((*fYjbResHistsS84)[4])->Fill(yjbMinYgenThruYgen, ds->GetPhi(), weight);
    static_cast<TH2*>((*fYjbResHistsS84)[5])->Fill(yjbMinYgenThruYgen, this->GetWgammaP44(),
						     weight);
    static_cast<TH2*>((*fYjbResHistsS84)[6])->Fill(yjbMinYgenThruYgen, y, weight);
    static_cast<TH2*>((*fYjbResHistsS84)[7])->Fill(yjbMinYgenThruYgen, *yjb, weight);
    static_cast<TH2*>((*fYjbResHistsS84)[8])->Fill(*yjb - y, y, weight);
    static_cast<TH2*>((*fYjbResHistsS84)[9])->Fill(*yjb - y, *yjb, weight);

    static_cast<TH2*>((*fYjbResHistsS84)[10])->Fill(*yjb, yVis, weight);
    (*fYjbResHistsS84)[11]->Fill((*yjb - yVis)/yVis, weight);
    static_cast<TH2*>((*fYjbResHistsS84)[12])->Fill(y, yVis, weight);
    (*fYjbResHistsS84)[13]->Fill((yVis - y)/y, weight);

  }
}

//_____________________________________________________
 void GFDstarAnalyseMc::CreateHistsWeight()
{

  TDirectory* oldDir = this->OpenHistsFile();
  TDirectory* dir = new TDirectory("weights", "different kind of weights to be applied");
  dir->cd();

  GFHistManip::ClearCreateArray(fWeightHistsS83);
  GFHistManip::ClearCreateArray(fWeightHistsS84);
  
  fWeightHistsS83->Add(new TH1F("weightHistRecS83", "weights (rec events)",//0
				40, 0., 0.8));
  fWeightHistsS83->Add(new TH1F("weightHistGenS83", "weights (gen events)",//1
				40, 0., 0.8));
//   fWeightHistsS83->Add(new TH1F("weightHistEffCorS83", "Seb. eff.-corr. weights",
// 				40, 0.5, 1.5));
  const TArrayD *ar = fSteer->GetPtBins33();
  fWeightHistsS83->Add(new TH2F("weightHistPtEffCorS83", "Seb. eff.-corr. weights",//2
				ar->GetSize()-1, ar->GetArray(), 40, 0.75, 1.25));
  fWeightHistsS83->Last()->Sumw2();
  ar = fSteer->GetEtaBins33();
  fWeightHistsS83->Add(new TH2F("weightHistEtaEffCorS83", "Seb. eff.-corr. weights",//3
				ar->GetSize()-1, ar->GetArray(), 40, 0.75, 1.25));
  fWeightHistsS83->Last()->Sumw2();

  fWeightHistsS84->Add(new TH1F("weightHistRecS84", "weights (rec events)",//0
				40, 0., 0.8));
  fWeightHistsS84->Add(new TH1F("weightHistGenS84", "weights (gen events)",//1
				40, 0., 0.8));
  oldDir->cd();

  fAllHistArrays.Add(fWeightHistsS83);
  fAllHistArrays.Add(fWeightHistsS84);
}

//_____________________________________________________
 void GFDstarAnalyseMc::FillHistsWeight(TObjArray* dstars, TObjArray* genParts)
{

  if(!fWeightHistsS83) this->CreateHistsWeight();

  Bool_t s83 = kFALSE;
  Bool_t s84 = kFALSE;
  const Double_t w83 = this->GetWeight(83, NULL);
  TIter dstar(dstars);
  while(TObject* obj = dstar()){
    if(obj->InheritsFrom(H1PartDstar::Class())){
      H1PartDstar* ds = static_cast<H1PartDstar*>(obj);
      if(this->DstarCutLoose(ds)){
	if(this->IsS83(ds)) {
	  s83 = kTRUE;
	  static_cast<TH2*>(fWeightHistsS83->At(2))
	    ->Fill(ds->GetPt(),  this->GetEffCorrFactor(ds), w83);
	  static_cast<TH2*>(fWeightHistsS83->At(3))
	    ->Fill(ds->GetEta(), this->GetEffCorrFactor(ds), w83);
	}
	if(this->IsS84(ds)) s84 = kTRUE;
      }
    }
  }

  if(s83) (*fWeightHistsS83)[0]->Fill(w83);
  if(s84) (*fWeightHistsS84)[0]->Fill(this->GetWeight(84, NULL));


  s83 = kFALSE;
  s84 = kFALSE;
  TIter genPart(genParts);
  while(TObject* obj = genPart()){
    if(obj->InheritsFrom(H1PartMC::Class())){
      const H1PartMC* mc = static_cast<H1PartMC*>(obj);
      if(H1UserDstarUtil::IsDstarKPiPis(mc, genParts) && this->DstarCutLoose(mc)){
  	if(this->IsS83Gen(mc)) s83 = kTRUE;
  	if(this->IsS84Gen(mc)) s84 = kTRUE;
      }
    }
  }

  if(s83) (*fWeightHistsS83)[1]->Fill(this->GetWeight(83, NULL));
  if(s84) (*fWeightHistsS84)[1]->Fill(this->GetWeight(84, NULL));
}


//_____________________________________________________
 void GFDstarAnalyseMc::CreateHistsEflow()
{
  TDirectory* oldDir = this->OpenHistsFile();

  TDirectory* dir = new TDirectory("Eflow", "Erec vs Egen in detector parts");
  dir->cd();

  GFHistManip::ClearCreateArray(fEflowHistsS83);
  GFHistManip::ClearCreateArray(fEflowHistsS84);

  const Int_t nBinsE = 40;
  const Float_t minE = 0.;
  const Float_t maxE = 35.;//40.;
  const Float_t maxRatio = 3.0;//2.5;// forward take + 1.0 // no, now always maxRatio

  fEflowHistsS83->Add(new TH2F("ErecEgenHist2D", "E_{rec} vs E_{gen-vis}",//0
			       nBinsE, minE, 3.* maxE, nBinsE, minE, 3.* maxE));
  fEflowHistsS83->Add(new TH2F("ErecEgenForwHist2D", "E_{rec} vs E_{gen-vis} forward LAr ",//1
			       nBinsE, minE, 2.* maxE, nBinsE, minE, 2.* maxE));
  fEflowHistsS83->Add(new TH2F("ErecEgenForwBarHist2D", 
			       "E_{rec} vs E_{gen-vis} LAr forward  barrel",//2
			       nBinsE, minE, maxE, nBinsE, minE, maxE));
  fEflowHistsS83->Add(new TH2F("ErecEgenBarrelHist2D", "E_{rec} vs E_{gen-vis} LAr barrel",//3
			       nBinsE, minE, //.75 * maxE, nBinsE, minE, .75 * maxE));
			       maxE, nBinsE, minE, maxE));
  fEflowHistsS83->Add(new TH2F("ErecEgenSpacalHist2D", "E_{rec} vs E_{gen-vis} Spacal",//4
			       nBinsE, minE, 0.3 * maxE, nBinsE, minE, 0.3 * maxE));

  fEflowHistsS83->Add(new TH1F("ErecEgenHist", "E_{rec} / E_{gen-vis}",//5
			       nBinsE, 0, maxRatio));
  fEflowHistsS83->Add(new TH1F("ErecEgenForwHist", "E_{rec} / E_{gen-vis} forward LAr ",//6
			       nBinsE, 0, maxRatio));//+1.0));
  fEflowHistsS83->Add(new TH1F("ErecEgenForwBarHist", 
			       "E_{rec} / E_{gen-vis} LAr forward barrel",//7
			       nBinsE, 0, maxRatio));//+1.0));
  fEflowHistsS83->Add(new TH1F("ErecEgenBarrelHist", "E_{rec} / E_{gen-vis} LAr barrel",//8
			       nBinsE, 0, maxRatio));
  fEflowHistsS83->Add(new TH1F("ErecEgenSpacalHist", "E_{rec} / E_{gen-vis} Spacal",//9
			       nBinsE, 0, maxRatio));

  fEflowHistsS83->Add(new TH1F("ErecEgenrelHist", "(E_{rec} - E_{gen-vis}) / E_{gen-vis}",//10
			       nBinsE, -0.5, 2.));
  fEflowHistsS83->Add(new TH1F("ErecEgenForwrelHist", 
			       "(E_{rec} - E_{gen-vis}) / E_{gen-vis} forward LAr ",//11
			       nBinsE, -0.8, 1.5));
  fEflowHistsS83->Add(new TH1F("ErecEgenForwBarrelHist", 
			       "(E_{rec} - E_{gen-vis}) / E_{gen-vis} LAr forward barrel",//12
			       nBinsE, -0.8, 1.5));
  fEflowHistsS83->Add(new TH1F("ErecEgenBarrelrelHist", 
			       "(E_{rec} - E_{gen-vis}) / E_{gen-vis} LAr barrel",//13
			       nBinsE, -0.8, 1.5));
  fEflowHistsS83->Add(new TH1F("ErecEgenSpacalrelHist", 
			       "(E_{rec} - E_{gen-vis}) / E_{gen-vis} Spacal",//14
			       nBinsE, -1., 1.5));

  fEflowHistsS83->Add(new TH1F("ErecEgendiffHist", "E_{rec} - E_{gen-vis}",//15
			       nBinsE, -0.5 * maxE, 0.5 * maxE));
  fEflowHistsS83->Add(new TH1F("ErecEgenForwdiffHist", "E_{rec} - E_{gen-vis} forward LAr ",//16
			       nBinsE, -0.4 * maxE, 0.4 * maxE));
  fEflowHistsS83->Add(new TH1F("ErecEgenForwBardiffHist", 
			       "E_{rec} - E_{gen-vis}) LAr forward barrel",//17
			       nBinsE, -0.1 * maxE, 0.1 * maxE));
  fEflowHistsS83->Add(new TH1F("ErecEgenBarreldiffHist", "E_{rec} - E_{gen-vis} LAr barrel",//18
			       nBinsE, -0.15 * maxE, 0.15 * maxE));
  fEflowHistsS83->Add(new TH1F("ErecEgenSpacaldiffHist", "E_{rec} - E_{gen-vis} Spacal",//19
			       nBinsE, -0.06 * maxE, 0.06 * maxE));

  fEflowHistsS83->Add(new TH2F("corrForwBeamHist2D", 
			       "E_{rec}-E_{gen} (forward)  vs E_{gen} (forwBeam)",//20
			       nBinsE, minE-10., 0.5 * maxE, nBinsE, minE, 4. * maxE));


  GFHistManip::CreateAnalogHists(fEflowHistsS83, fEflowHistsS84, "S84");
  GFHistManip::AddToHistsName("S83", fEflowHistsS83);
			       
  oldDir->cd();

  fAllHistArrays.Add(fEflowHistsS83);
  fAllHistArrays.Add(fEflowHistsS84);
}

//_____________________________________________________
 void GFDstarAnalyseMc::FillHistsEflow(const H1PartDstar* ds)
{
  if(!fEflowHistsS83) this->CreateHistsEflow();
  const Bool_t s83 = this->IsS83(ds);
  const Bool_t s84 = this->IsS84(ds);

  if(!s83 && !s84) return;

  Double_t eForwardRec = 0.; 
  Double_t eForwardBarRec = 0.; 
  Double_t eBarrelRec = 0.; 
  Double_t eSpacalRec = 0.; 
  const Double_t eSumRec = this->GetRecEnergies(eForwardRec, eForwardBarRec, 
						eBarrelRec, eSpacalRec);

  Double_t eForwBeamGen = 0.; 
  Double_t eForwardGen = 0.; 
  Double_t eForwardBarGen = 0.; 
  Double_t eBarrelGen = 0.; 
  Double_t eSpacalGen = 0.; 
  const Double_t eSumGen = this->GetGenEnergies(eForwBeamGen, eForwardGen, eForwardBarGen,
						eBarrelGen, eSpacalGen);
  
  const Double_t ratioSum = eSumGen ? eSumRec/eSumGen : -2.;
  const Double_t ratioForward = eForwardGen ? eForwardRec/eForwardGen : -2.;
  const Double_t ratioForwardBar = eForwardBarGen ? eForwardBarRec/eForwardBarGen : -2.;
  const Double_t ratioBarrel = eBarrelGen ? eBarrelRec/eBarrelGen : -2.;
  const Double_t ratioSpacal = eSpacalGen ? eSpacalRec/eSpacalGen : -2.;

  const Double_t diffSum = eSumRec - eSumGen;
  const Double_t diffForward = eForwardRec - eForwardGen;
  const Double_t diffForwardBar = eForwardBarRec - eForwardBarGen;
  const Double_t diffBarrel = eBarrelRec - eBarrelGen;
  const Double_t diffSpacal = eSpacalRec - eSpacalGen;

  const Double_t relDiffSum = eSumGen ? diffSum/eSumGen : -2.;
  const Double_t relDiffForward = eForwardGen ? diffForward/eForwardGen : -2.;
  const Double_t relDiffForwardBar = eForwardBarGen ? diffForwardBar/eForwardBarGen : -2.;
  const Double_t relDiffBarrel = eBarrelGen ? diffBarrel/eBarrelGen : -2.;
  const Double_t relDiffSpacal = eSpacalGen ? diffSpacal/eSpacalGen : -2.;

  if(s83){
    (*fEflowHistsS83)[0]->Fill(eSumRec, eSumGen);
    (*fEflowHistsS83)[1]->Fill(eForwardRec, eForwardGen);
    (*fEflowHistsS83)[2]->Fill(eForwardBarRec, eForwardBarGen);
    (*fEflowHistsS83)[3]->Fill(eBarrelRec, eBarrelGen);
    (*fEflowHistsS83)[4]->Fill(eSpacalRec, eSpacalGen);

    if(ratioSum != -2.)        (*fEflowHistsS83)[5]->Fill(ratioSum);
    if(ratioForward != -2.)    (*fEflowHistsS83)[6]->Fill(ratioForward);
    if(ratioForwardBar != -2.) (*fEflowHistsS83)[7]->Fill(ratioForwardBar);
    if(ratioBarrel != -2.)     (*fEflowHistsS83)[8]->Fill(ratioBarrel);
    if(ratioSpacal != -2.)     (*fEflowHistsS83)[9]->Fill(ratioSpacal);

    if(relDiffSum != -2.)        (*fEflowHistsS83)[10]->Fill(relDiffSum);
    if(relDiffForward != -2.)    (*fEflowHistsS83)[11]->Fill(relDiffForward);
    if(relDiffForwardBar != -2.) (*fEflowHistsS83)[12]->Fill(relDiffForwardBar);
    if(relDiffBarrel != -2.)     (*fEflowHistsS83)[13]->Fill(relDiffBarrel);
    if(relDiffSpacal != -2.)     (*fEflowHistsS83)[14]->Fill(relDiffSpacal);

    (*fEflowHistsS83)[15]->Fill(diffSum);        
    (*fEflowHistsS83)[16]->Fill(diffForward);    
    (*fEflowHistsS83)[17]->Fill(diffForwardBar); 
    (*fEflowHistsS83)[18]->Fill(diffBarrel);     
    (*fEflowHistsS83)[19]->Fill(diffSpacal);

    if(eForwardBarRec - eForwardGen > -10.) 
      (*fEflowHistsS83)[20]->Fill(eForwardBarRec-eForwardGen, eForwBeamGen);
  }
  if(s84){
    (*fEflowHistsS84)[0]->Fill(eSumRec, eSumGen);
    (*fEflowHistsS84)[1]->Fill(eForwardRec, eForwardGen);
    (*fEflowHistsS84)[2]->Fill(eForwardBarRec, eForwardBarGen);
    (*fEflowHistsS84)[3]->Fill(eBarrelRec, eBarrelGen);
    (*fEflowHistsS84)[4]->Fill(eSpacalRec, eSpacalGen);

    if(ratioSum != -2.)        (*fEflowHistsS84)[5]->Fill(ratioSum);
    if(ratioForward != -2.)    (*fEflowHistsS84)[6]->Fill(ratioForward);
    if(ratioForwardBar != -2.) (*fEflowHistsS84)[7]->Fill(ratioForwardBar);
    if(ratioBarrel != -2.)     (*fEflowHistsS84)[8]->Fill(ratioBarrel);
    if(ratioSpacal != -2.)     (*fEflowHistsS84)[9]->Fill(ratioSpacal);

    if(relDiffSum != -2.)        (*fEflowHistsS84)[10]->Fill(relDiffSum);
    if(relDiffForward != -2.)    (*fEflowHistsS84)[11]->Fill(relDiffForward);
    if(relDiffForwardBar != -2.) (*fEflowHistsS84)[12]->Fill(relDiffForwardBar);
    if(relDiffBarrel != -2.)     (*fEflowHistsS84)[13]->Fill(relDiffBarrel);
    if(relDiffSpacal != -2.)     (*fEflowHistsS84)[14]->Fill(relDiffSpacal);

    (*fEflowHistsS84)[15]->Fill(diffSum);        
    (*fEflowHistsS84)[16]->Fill(diffForward);    
    (*fEflowHistsS84)[17]->Fill(diffForwardBar); 
    (*fEflowHistsS84)[18]->Fill(diffBarrel);     
    (*fEflowHistsS84)[19]->Fill(diffSpacal);

    if(eForwardBarRec - eForwardGen > -10.) 
      (*fEflowHistsS84)[20]->Fill(eForwardBarRec-eForwardGen, eForwBeamGen);
  }
}

//________________________________________________
 void GFDstarAnalyseMc::CreateHistsJetQuark()
{
  TDirectory* oldDir = this->OpenHistsFile();
  TDirectory* dir = new TDirectory("jetquark","jet vs quark plots");
  dir->cd();

  GFHistManip::ClearCreateArray(fJetQuarkHists);

  const Int_t nBins = 30;
  const Float_t maxE = 15.;
  const Float_t maxEt = 10.;
  const Float_t maxRatio = 3.;
  const Float_t maxDiff = 6.;
  const Float_t maxEta = 3.5;
  const Float_t maxDist = 4.;

  fJetQuarkHists->Add(new TH2F("Ejet1EcVs","E^{D*-jet} vs E^{c/#bar{c}}", nBins, 0., maxE, // 0
			       nBins, 0., maxE));
  fJetQuarkHists->Add(new TH1F("Ejet1EcOver","E^{D*-jet} / E^{c/#bar{c}}", nBins, 0.,maxRatio));
  fJetQuarkHists->Add(new TH1F("Ejet1EcDiff","E^{D*-jet} - E^{c/#bar{c}}", 
			       2*nBins, -maxDiff, maxDiff));

  fJetQuarkHists->Add(new TH2F("Etjet1EtcVs","E^{D*-jet}_{t} vs E^{c/#bar{c}}_{t}", // 3
			       nBins, 0., maxEt, nBins, 0., maxEt));
  fJetQuarkHists->Add(new TH1F("Etjet1EtcOver","E^{D*-jet}_{t} / E_{t}^{c/#bar{c}}",
			       nBins, 0., maxRatio));
  fJetQuarkHists->Add(new TH1F("Etjet1EtcDiff","E_{t}^{D*-jet} - E_{t}^{c/#bar{c}}",
			       2*nBins, -maxDiff, maxDiff));

  fJetQuarkHists->Add(new TH2F("phijet1phicVs","#phi^{D*-jet} vs #phi^{c/#bar{c}}", // 6
			       nBins,-TMath::Pi(),TMath::Pi(),nBins,-TMath::Pi(),TMath::Pi()));
  fJetQuarkHists->Add(new TH1F("phijet1phicDiff","#phi^{D*-jet} - #phi^{c/#bar{c}}",
			       2*nBins, -TMath::Pi(), TMath::Pi()));

  fJetQuarkHists->Add(new TH2F("etajet1etacVs","#eta^{D*-jet} vs #eta^{c/#bar{c}}", // 8
			       2*nBins, -maxEta, maxEta, nBins, -maxEta, maxEta));
  fJetQuarkHists->Add(new TH1F("etajet1etacDiff","#eta^{D*-jet} - #eta^{c/#bar{c}}",
			       2*nBins, -0.5*maxDiff, maxDiff));

  fJetQuarkHists->Add(new TH1F("distjet1Charm",                                     // 10
			       "R^{D*-jet} = #sqrt{#Delta#phi^{2} + #Delta#eta^{2}}",
			       nBins, 0., maxDist));
  fNumJetQuarkHistsPerJet = fJetQuarkHists->GetEntriesFast();
  // start of 2nd jet:
  fJetQuarkHists->Add(new TH2F("Ejet2EcVs","E^{o. jet} vs E^{c/#bar{c}}", nBins, 0., maxE, // 11
			       nBins, 0., maxE));
  fJetQuarkHists->Add(new TH1F("Ejet2EcOver","E^{o. jet} / E^{c/#bar{c}}", nBins, 0.,maxRatio));
  fJetQuarkHists->Add(new TH1F("Ejet2EcDiff","E^{o. jet} - E^{c/#bar{c}}", 
			       2*nBins, -maxDiff, maxDiff));

  fJetQuarkHists->Add(new TH2F("Etjet2EtcVs","E^{o. jet}_{t} vs E^{c/#bar{c}}_{t}", // 14
			       nBins, 0., maxEt, nBins, 0., maxEt));
  fJetQuarkHists->Add(new TH1F("Etjet2EtcOver","E^{o. jet}_{t} / E_{t}^{c#bar{c}}",
			       nBins, 0., maxRatio));
  fJetQuarkHists->Add(new TH1F("Etjet2EtcDiff","E_{t}^{o. jet} - E_{t}^{c#bar{c}}",
			       2*nBins, -maxDiff, maxDiff));

  fJetQuarkHists->Add(new TH2F("phijet2phicVs","#phi^{o. jet} vs #phi^{c(#bar{c})}", // 17
			       nBins,-TMath::Pi(),TMath::Pi(),nBins,-TMath::Pi(),TMath::Pi()));
  fJetQuarkHists->Add(new TH1F("phijet2phicDiff","#phi^{o. jet} - #phi^{c#bar{c}}",
			       2*nBins, -TMath::Pi(), TMath::Pi()));

  fJetQuarkHists->Add(new TH2F("etajet2etacVs","#eta^{o. jet} vs #eta^{c(#bar{c})}", // 19
			       2*nBins, -maxEta, maxEta, nBins, -maxEta, maxEta));
  fJetQuarkHists->Add(new TH1F("etajet2etacDiff","#eta^{o. jet} - #eta^{c#bar{c}}",
			       2*nBins, -0.5*maxDiff, maxDiff));

  fJetQuarkHists->Add(new TH1F("distjet2Charm",                                     // 21
			       "R^{o. jet} = #sqrt{#Delta#phi^{2} + #Delta#eta^{2}}",
			       nBins, 0., maxDist));
  // now a hist for both pairs together:
  fJetQuarkHists->Add(new TH1F("sumDistsJetCharm",                                     // 22
			       "#Sigma (R = #sqrt{#Delta#phi^{2} + #Delta#eta^{2}})",
			       nBins, 0., 7.));
  fJetQuarkHists->Add(new TH1F("distCloserJetCharm",                                   // 23
			       "R^{close} = #sqrt{#Delta#phi^{2} + #Delta#eta^{2}}",
			       nBins, 0., 2.));
  fJetQuarkHists->Add(new TH1F("distFarerJetCharm",                                   // 24
			       "R^{far} = #sqrt{#Delta#phi^{2} + #Delta#eta^{2}}",
			       nBins, 0., 7.));

  GFHistManip::CreateAnalogHists(fJetQuarkHists, fJetQuarkHistsS83, "S83");
  GFHistManip::CreateAnalogHists(fJetQuarkHists, fJetQuarkHistsS84, "S84");
  fJetQuarkHistsS83->Add(new TH1F("dphiDsQuarkS83", "#phi(D*)-#phi(c)[#circ]",//25
				  2*nBins, -70., 70.));

  GFHistManip::CallSumw2(fJetQuarkHistsS83);
  GFHistManip::CallSumw2(fJetQuarkHistsS84);

  oldDir->cd();

  fAllHistArrays.Add(fJetQuarkHists);
  fAllHistArrays.Add(fJetQuarkHistsS83);
  fAllHistArrays.Add(fJetQuarkHistsS84);
}

//_____________________________________________________
 void GFDstarAnalyseMc::FillHistsJetQuark(const H1PartDstar* ds)
{
  if(!fJetQuarkHists) this->CreateHistsJetQuark();

  const H1PartJet *dstarJet = NULL;
  const H1PartJet *oJet = NULL;
  this->GetDiJets(ds, dstarJet, oJet);
  if(!dstarJet || !oJet) {
    return; // need both jets...
  }

  H1PartMC* quark1 = NULL; // will become associate to dstarJet
  H1PartMC* quark2 = NULL; //                          oJet
  if(!this->GetHeavyQuarks(quark1, quark2)) return;
  Associate(dstarJet, oJet, quark1, quark2);
  
  this->FillHistsJetQuark(fJetQuarkHists, dstarJet, oJet, quark1, quark2);
  if(this->IsS83(ds)) {
    this->FillHistsJetQuark(fJetQuarkHistsS83, dstarJet, oJet, quark1, quark2);
    if(quark1->GetCharge() * ds->GetCharge() > 0){
      fJetQuarkHistsS83->At(25)->Fill
	(TMath::RadToDeg()*TVector2::Phi_mpi_pi(quark1->GetPhi() - ds->GetPhi()));
    } else if(quark2->GetCharge() * ds->GetCharge() > 0){
      fJetQuarkHistsS83->At(25)->Fill
	(TMath::RadToDeg()*TVector2::Phi_mpi_pi(quark2->GetPhi() - ds->GetPhi()));
    }
  }
  if(this->IsS84(ds)) this->FillHistsJetQuark(fJetQuarkHistsS84, dstarJet, oJet, quark1, quark2);
}

//_____________________________________________________
 void GFDstarAnalyseMc::FillHistsJetQuark(const GFHistArray* jetQuarkHists, 
					 const H1PartJet* jet1, const H1PartJet* jet2, 
					 const H1PartMC* quark1, const H1PartMC* quark2)
{
  if(!jetQuarkHists || !jet1 || !jet2 || !quark1 || !quark2){
    this->Error("FillHistsJetQuark", "Missing pointer!");
    return;
  }
  
  const Double_t jetE[2] = {jet1->GetE(), jet2->GetE()};
  const Double_t jetEt[2] = {jetE[0] * TMath::Sin(jet1->GetTheta()), 
			       jetE[1] * TMath::Sin(jet2->GetTheta())};
  const Double_t jetPhi[2] = {jet1->GetPhi(), jet2->GetPhi()};
  const Double_t jetEta[2] = {jet1->GetEta(), jet2->GetEta()};

  const Double_t quarkE[2] = {quark1->GetE(), quark2->GetE()};
  const Double_t quarkEt[2] = {quarkE[0] * TMath::Sin(quark1->GetTheta()), 
				 quarkE[1] * TMath::Sin(quark2->GetTheta())};
  const Double_t quarkPhi[2] = {quark1->GetPhi(), quark2->GetPhi()};
  const Double_t quarkEta[2] = {quark1->GetEta(), quark2->GetEta()};
  
  const Double_t dist[2] = {jet1->GetMomentum().DeltaR(quark1->GetMomentum()),
			      jet2->GetMomentum().DeltaR(quark2->GetMomentum())};
  for(Int_t i = 0; i < 2; ++i){
    (*jetQuarkHists)[i*fNumJetQuarkHistsPerJet+0]->Fill(jetE[i] , quarkE[i]);
    (*jetQuarkHists)[i*fNumJetQuarkHistsPerJet+1]->Fill(jetE[i] / quarkE[i]);
    (*jetQuarkHists)[i*fNumJetQuarkHistsPerJet+2]->Fill(jetE[i] - quarkE[i]);

    (*jetQuarkHists)[i*fNumJetQuarkHistsPerJet+3]->Fill(jetEt[i] , quarkEt[i]);
    (*jetQuarkHists)[i*fNumJetQuarkHistsPerJet+4]->Fill(jetEt[i] / quarkEt[i]);
    (*jetQuarkHists)[i*fNumJetQuarkHistsPerJet+5]->Fill(jetEt[i] - quarkEt[i]);

    (*jetQuarkHists)[i*fNumJetQuarkHistsPerJet+6]->Fill(jetPhi[i] , quarkPhi[i]);
    (*jetQuarkHists)[i*fNumJetQuarkHistsPerJet+7]->
      Fill(TVector2::Phi_mpi_pi(jetPhi[i] - quarkPhi[i]));

    (*jetQuarkHists)[i*fNumJetQuarkHistsPerJet+8]->Fill(jetEta[i] , quarkEta[i]);
    (*jetQuarkHists)[i*fNumJetQuarkHistsPerJet+9]->Fill(jetEta[i] - quarkEta[i]);
    
    (*jetQuarkHists)[i*fNumJetQuarkHistsPerJet+10]->Fill(dist[i]);
  }
  (*jetQuarkHists)[2*fNumJetQuarkHistsPerJet+0]->Fill(dist[0] + dist[1]);
  (*jetQuarkHists)[2*fNumJetQuarkHistsPerJet+1]->Fill(dist[0] >= dist[1] ? dist[1] : dist[0]);
  (*jetQuarkHists)[2*fNumJetQuarkHistsPerJet+2]->Fill(dist[0] <= dist[1] ? dist[1] : dist[0]);
}

//____________________________________________________
 void GFDstarAnalyseMc::CreateHistsDsJetQuark()
{
  TDirectory* oldDir = this->OpenHistsFile();
  TDirectory* dir = new TDirectory("dsjetquark","jet/dstar vs quark plots");
  dir->cd();
  
  GFHistManip::ClearCreateArray(fDsJetQuarkHistsS83);
  
  const Int_t nBins = 30;
  const Float_t maxE = 15.;
  const Float_t maxPt = 10.;
  const Float_t maxEta = 1.5;
  const Float_t maxPhi = TMath::Pi();
  const Float_t maxRatio = 2.5;
  const Float_t maxDiff = 6.;
  
  fDsJetQuarkHistsS83->Add(new TH2F("EDsEQuVs","E(D*) vs E(c/#bar{c})", nBins, 0., maxE, // 0
				    nBins, 0., maxE));
  fDsJetQuarkHistsS83->Add(new TH1F("EDsEQuOver","E(D*)/E(c/#bar{c})", nBins, 0., maxRatio));
  fDsJetQuarkHistsS83->Add(new TH1F("EDsEQuDiff","E(D*)-E(c/#bar{c})",nBins,-maxDiff,maxDiff));
  
  fDsJetQuarkHistsS83->Add(new TH2F("EDsJetEQuVs","E(D*-jet) vs E(c/#bar{c})",
				    nBins, 0., maxE, nBins, 0., maxE));
  fDsJetQuarkHistsS83->Add(new TH1F("EDsJetEQuOver", "E(D*-jet)/E(c/#bar{c})", 
				    nBins, 0., maxRatio));
  fDsJetQuarkHistsS83->Add(new TH1F("EDsJetEQuDiff", "E(D*-jet)-E(c/#bar{c})",
				    nBins, -maxDiff, maxDiff));
  
  
  fDsJetQuarkHistsS83->Add(new TH2F("ptDsptQuVs","p_{t}(D*) vs p_{t}(c/#bar{c})", 
				    nBins, 0., maxPt, nBins, 0., maxPt));
  fDsJetQuarkHistsS83->Add(new TH1F("ptDsptQuOver","p_{t}(D*)/p_{t}(c/#bar{c})",
				    nBins, 0., maxRatio));
  fDsJetQuarkHistsS83->Add(new TH1F("ptDsptQuDiff","p_{t}(D*)-p_{t}(c/#bar{c})",
				    nBins,-maxDiff,maxDiff));
  
  fDsJetQuarkHistsS83->Add(new TH2F("ptDsJetptQuVs","p_{t}(D*-jet) vs p_{t}(c/#bar{c})", 
				    nBins, 0., maxPt, nBins, 0., maxPt));
  fDsJetQuarkHistsS83->Add(new TH1F("ptDsJetptQuOver","p_{t}(D*-jet)/p_{t}(c/#bar{c})",
				    nBins, 0., maxRatio));
  fDsJetQuarkHistsS83->Add(new TH1F("ptDsJetptQuDiff","p_{t}(D*-jet)-p_{t}(c/#bar{c})",
				    nBins,-maxDiff,maxDiff));
  
  fDsJetQuarkHistsS83->Add(new TH2F("etaDsetaQuVs","#eta(D*) vs #eta(c/#bar{c})", 
				    nBins, -maxEta, maxEta, nBins, -maxEta, maxEta));
  fDsJetQuarkHistsS83->Add(new TH1F("etaDsetaQuDiff","#eta(D*)-#eta(c/#bar{c})",
				    nBins, -maxDiff/4., maxDiff/4.));
  
  fDsJetQuarkHistsS83->Add(new TH2F("etaDsJetetaQuVs","#eta(D*-jet) vs #eta(c/#bar{c})", 
				    nBins, -maxEta, maxEta, nBins, -maxEta, maxEta));
  fDsJetQuarkHistsS83->Add(new TH1F("etaDsJetetaQuDiff","#eta(D*-jet)-#eta(c/#bar{c})",
				    nBins, -maxDiff/4., maxDiff/4.));
  
  fDsJetQuarkHistsS83->Add(new TH2F("phiDsphiQuVs","#phi(D*) vs #phi(c/#bar{c})", 
				    nBins, -maxPhi, maxPhi, nBins, -maxPhi, maxPhi));
  fDsJetQuarkHistsS83->Add(new TH1F("phiDsphiQuDiff","#phi(D*)-#phi(c/#bar{c})",
				    nBins, -maxDiff/4., maxDiff/4.));
  
  fDsJetQuarkHistsS83->Add(new TH2F("phiDsJetphiQuVs","#phi(D*-jet) vs #phi(c/#bar{c})", 
				    nBins, -maxPhi, maxPhi, nBins, -maxPhi, maxPhi));
  fDsJetQuarkHistsS83->Add(new TH1F("phiDsJetphiQuDiff","#phi(D*-jet)-#phi(c/#bar{c})",
				    nBins, -maxDiff/4., maxDiff/4.));
  
  
  
  GFHistManip::AddToHistsName("S83", fDsJetQuarkHistsS83);
  GFHistManip::CallSumw2(fDsJetQuarkHistsS83);
  
  oldDir->cd();
  
  fAllHistArrays.Add(fDsJetQuarkHistsS83);
}

//______________________________________________________
 void GFDstarAnalyseMc::FillHistsDsJetQuark(const H1PartDstar *ds)
{
  // ds is with soft cuts
  // fill D* vs quark and D*-jet vs quark hists for S83 in case we have event reconstructed
  // and generated as D* dijet

  if(!ds || !this->IsS83(ds) || !this->IsSignalRegionDm(ds)) return;
  // get detector jets
  const H1PartJet *dsJet = NULL, *oJet = NULL;
  this->GetDiJets(ds, dsJet, oJet);
  if(!dsJet || !oJet) return;

  // get generator D* of same charge and 'OK'
  const H1PartMC* genDs = this->GetCloseGenDsKpipi(ds, "C83");
  if(!genDs) return;
  // get generator jets
  const H1PartJet *dsGenJet = NULL, *oGenJet = NULL;
  this->GetGenDiJets(genDs, dsGenJet, oGenJet);
  if(!dsGenJet || !oGenJet) return;

  // OK, we generated AND reconstructed S83 dijet event, we can start!
  if(!fDsJetQuarkHistsS83) this->CreateHistsDsJetQuark();

  H1PartMC *quark = NULL, *antiQuark = NULL;
  if(!this->GetHeavyQuarks(quark, antiQuark)) return;

  const H1PartMC *dsQuark = (quark->GetCharge() * ds->GetCharge() > 0 ? quark : antiQuark);

  const TLorentzVector p4Qu = dsQuark->GetFourVector();
  const TLorentzVector p4Ds = ds->GetFourVector();
  const TLorentzVector p4J  = dsJet->GetFourVector();
  const Double_t w83 = this->GetWeight(83, ds);

//   if(p4Ds.Pt() / p4Qu.Pt() > 1.5){
//     if(!fList){
//       TDirectory *old = gDirectory;
//       gROOT->cd();
//       fList = new H1EventList("badDijetRes");
//       H1Event *event = new H1UserDstarEvent;
//       fList->AddChainInfo("DSTAR", event);
//       delete event;
//       old->cd();
//     }
//     fList->Enter();
//   }

  static_cast<TH2*>(fDsJetQuarkHistsS83->At(0))->Fill(p4Ds.E(), p4Qu.E(), w83);
  fDsJetQuarkHistsS83->At(1)->Fill(p4Ds.E() / p4Qu.E(), w83);
  fDsJetQuarkHistsS83->At(2)->Fill(p4Ds.E() - p4Qu.E(), w83);

  static_cast<TH2*>(fDsJetQuarkHistsS83->At(3))->Fill(p4J.E(), p4Qu.E(), w83);
  fDsJetQuarkHistsS83->At(4)->Fill(p4J.E() / p4Qu.E(), w83);
  fDsJetQuarkHistsS83->At(5)->Fill(p4J.E() - p4Qu.E(), w83);

  static_cast<TH2*>(fDsJetQuarkHistsS83->At(6))->Fill(p4Ds.Pt(), p4Qu.Pt(), w83);
  fDsJetQuarkHistsS83->At(7)->Fill(p4Ds.Pt() / p4Qu.Pt(), w83);
  fDsJetQuarkHistsS83->At(8)->Fill(p4Ds.Pt() - p4Qu.Pt(), w83);

  static_cast<TH2*>(fDsJetQuarkHistsS83->At(9))->Fill(p4J.Pt(), p4Qu.Pt(), w83);
  fDsJetQuarkHistsS83->At(10)->Fill(p4J.Pt() / p4Qu.Pt(), w83);
  fDsJetQuarkHistsS83->At(11)->Fill(p4J.Pt() - p4Qu.Pt(), w83);

  static_cast<TH2*>(fDsJetQuarkHistsS83->At(12))->Fill(p4Ds.Eta(), p4Qu.Eta(), w83);
  fDsJetQuarkHistsS83->At(13)->Fill(p4Ds.Eta() - p4Qu.Eta(), w83);

  static_cast<TH2*>(fDsJetQuarkHistsS83->At(14))->Fill(p4J.Eta(), p4Qu.Eta(), w83);
  fDsJetQuarkHistsS83->At(15)->Fill(p4J.Eta() - p4Qu.Eta(), w83);

  static_cast<TH2*>(fDsJetQuarkHistsS83->At(16))->Fill(p4Ds.Phi(), p4Qu.Phi(), w83);
  fDsJetQuarkHistsS83->At(17)->Fill(TVector2::Phi_mpi_pi(p4Ds.Phi() - p4Qu.Phi()), w83);

  static_cast<TH2*>(fDsJetQuarkHistsS83->At(18))->Fill(p4J.Phi(), p4Qu.Phi(), w83);
  fDsJetQuarkHistsS83->At(19)->Fill(TVector2::Phi_mpi_pi(p4J.Phi() - p4Qu.Phi()), w83);

}


//////////////////////////////////////////////////////////////////////
//
//  The following not maintained, use Create/FillHistsDsJetPurStab!
//
//////////////////////////////////////////////////////////////////////
// //_____________________________________________________
// void GFDstarAnalyseMc::CreateHistsJetPurStab()
// {
//   TDirectory* oldDir = this->OpenHistsFile();
//   TDirectory* dir = new TDirectory("jetPurStab","jet purity and stability plots");
//   dir->cd();
//
//   GFHistManip::ClearCreateArray(fJetPurStabHists);
//
//   const Int_t maxNjets = 5;
//   const Int_t nBinsVs = 30;
//   const Float_t maxDevRes = 0.5;
//   const Int_t nBinsRes = 30;
//   fJetPurStabHists->Add(new TH1F("nJetRec", "N_{jet} rec",
// 				 maxNjets, 0, maxNjets));
//   fJetPurStabHists->Add(new TH1F("nJetGenRec", "N_{jet} rec and gen",
// 				 maxNjets, 0, maxNjets));
//   fJetPurStabHists->Add(new TH1F("nJetGenNonRec", "N_{jet} not rec but gen",
// 				 maxNjets, 0, maxNjets));
//   fJetPurStabHists->Add(new TH2F("nJetGenVsRec", "N_{jet} rec vs gen",
// 				 maxNjets, 0, maxNjets, maxNjets, 0, maxNjets));
//   fJetPurStabHists->Add(new TH1F("nJetResRel", "dummy hist", // DUMMY!
// 				 /*nBinsRes*/1, -maxDevRes, maxDevRes));
//   fJetPurStabHists->Add(new TH1F("nJetRes", "dummy hist", // DUMMY!
// 				 /*nBinsRes*/1, -maxDevRes, maxDevRes));
//
//   const Int_t nBinsPt = fSteer->GetDstar1JetPtBins()->GetSize()-1;
//   const Double_t *binsPt = fSteer->GetDstar1JetPtBins()->GetArray();
//   fJetPurStabHists->Add(new TH1F("ptJetRec", "p_{t}^{jet} rec",
// 				 nBinsPt, binsPt));
//   fJetPurStabHists->Add(new TH1F("ptJetGenRec", "p_{t}^{jet} rec and gen",
// 				 nBinsPt, binsPt));
//   fJetPurStabHists->Add(new TH1F("ptJetGenNonRec", "p_{t}^{jet} not rec but gen",
// 				 nBinsPt, binsPt));
//   fJetPurStabHists->Add(new TH2F("ptJetGenVsRec", "p_{t}^{jet}: rec vs gen",
// 				 nBinsVs, binsPt[0], binsPt[nBinsPt],
// 				 nBinsVs, binsPt[0], binsPt[nBinsPt]));
//   fJetPurStabHists->Add(new TH1F("ptJetResRel","jet res.: (p_{t}^{rec}-p_{t}^{gen})/p_{t}^{gen}"
// 				 , 2*nBinsRes, -2.*maxDevRes, 2.*maxDevRes));
//   fJetPurStabHists->Add(new TH1F("ptJetRes", "jet res.: p_{t}^{rec}-p_{t}^{gen}",
// 				 2*nBinsRes, -2.*maxDevRes, 2.*maxDevRes));
//
//   const Int_t nBinsEta = fSteer->GetDstar1JetEtaBins()->GetSize()-1;
//   const Double_t *etaBins = fSteer->GetDstar1JetEtaBins()->GetArray();
//   fJetPurStabHists->Add(new TH1F("etaJetRec", "#eta^{jet} rec",
// 				 nBinsEta, etaBins));
//   fJetPurStabHists->Add(new TH1F("etaJetGenRec", "#eta^{jet} rec and gen",
// 				 nBinsEta, etaBins));
//   fJetPurStabHists->Add(new TH1F("etaJetGenNonRec", "#eta^{jet} not rec but gen",
// 				 nBinsEta, etaBins));
//   fJetPurStabHists->Add(new TH2F("etaJetGenVsRec", "#eta^{jet}: rec vs gen",
// 				 nBinsVs, etaBins[0], etaBins[nBinsEta],
// 				 nBinsVs, etaBins[0], etaBins[nBinsEta]));
//   fJetPurStabHists->Add(new TH1F("etaJetResRel", "jet res.: (#eta^{rec}-#eta^{gen})/#eta^{gen}",
// 				 nBinsRes, -maxDevRes, maxDevRes));
//   fJetPurStabHists->Add(new TH1F("etaJetRes", "jet res.: #eta^{rec}-#eta^{gen}",
// 				 nBinsRes, -maxDevRes, maxDevRes));
//
//   const Int_t nPhiBins = fSteer->GetPhiBins()->GetSize()-1;
//   const Double_t* phiBins = fSteer->GetPhiBins()->GetArray();
//   fJetPurStabHists->Add(new TH1F("phiJetRec", "#phi^{jet} rec", nPhiBins, phiBins));
//   fJetPurStabHists->Add(new TH1F("phiJetGenRec", "#phi^{jet} rec and gen", nPhiBins, phiBins));
//   fJetPurStabHists->Add(new TH1F("phiJetGenNonRec", "#phi^{jet} not rec but gen",
// 				 nPhiBins,phiBins));
//   fJetPurStabHists->Add(new TH2F("phiJetGenVsRec", "#phi^{jet}: rec vs gen",
// 				 nBinsVs, -TMath::Pi(), TMath::Pi(),
// 				 nBinsVs, -TMath::Pi(), TMath::Pi()));
//   fJetPurStabHists->Add(new TH1F("phiJetResRel", 
// 				 "jet res.: (#phi^{rec}-#phi^{gen})/#phi^{gen} no #phi mapping",
// 				 nBinsRes, -maxDevRes, maxDevRes));
//   fJetPurStabHists->Add(new TH1F("phiJetRes", "jet res.: #phi^{rec}-#phi^{gen} no #phi mapping",
// 				 nBinsRes, -maxDevRes, maxDevRes));
//
//   GFHistManip::ClearCreateArray(fJetPurStabPtInEtaHists);
//
//   for(Int_t i = 1; i < fSteer->GetDstar1JetEtaBins()->GetSize(); ++i){
//     fJetPurStabPtInEtaHists->
//       Add(new TH2F(Form("ptJetGenVsRecEta%d", i), 
// 		   Form("p_{t}^{jet}: rec vs gen, %.2f < #eta_{jet}^{gen} < %.2f", 
// 			fSteer->GetDstar1JetEtaBins()->At(i-1), 
// 			fSteer->GetDstar1JetEtaBins()->At(i)),	  
// 		   nBinsVs, binsPt[0], binsPt[nBinsPt],
// 		   nBinsVs, binsPt[0], binsPt[nBinsPt]));
//     fJetPurStabPtInEtaHists->
//       Add(new TH1F(Form("ptJetResRelEta%d",i),
// 		   Form("jet res.: (p_{t}^{rec}-p_{t}^{gen})/p_{t}^{gen},"
// 			" %.2f < #eta_{jet}^{gen} < %.2f", 
// 			etaBins[i-1], etaBins[i]),
// 		   2*nBinsRes, -2.*maxDevRes, 2.*maxDevRes));
//     fJetPurStabPtInEtaHists->
//       Add(new TH1F(Form("ptJetResEta%d",i),
// 		   Form("jet res.: p_{t}^{rec}-p_{t}^{gen}, %.2f < #eta_{jet}^{gen} < %.2f", 
// 			etaBins[i-1], etaBins[i]),
// 		   2*nBinsRes, -2.*maxDevRes, 2.*maxDevRes));
//   }
//
//   //   GFHistManip::CallSumw2(fJetPurStabHists); as soon as we fill weights...
//   // then also put sum2 out in GFDstarHistsAnalysisMc::CreateJetPurity/Stability
//
//   GFHistManip::CreateAnalogHists(fJetPurStabHists, fJetPurStabHistsS83, "S83");
//   GFHistManip::CreateAnalogHists(fJetPurStabHists, fJetPurStabHistsS84, "S84");
//
//   GFHistManip::CreateAnalogHists(fJetPurStabPtInEtaHists, fJetPurStabPtInEtaHistsS83, "S83");
//   GFHistManip::CreateAnalogHists(fJetPurStabPtInEtaHists, fJetPurStabPtInEtaHistsS84, "S84");
//
//   oldDir->cd();
// }
//
//_____________________________________________________
// void GFDstarAnalyseMc::FillHistsJetPurStab(const H1PartDstar* ds)
// {
//   // fill only for D* in SR, tighten to higher pt cut
//
//   if(!this->IsSignalRegionDm(ds) || ds->GetPt() < fDsCutPt2) return;
//
//   if(!fJetPurStabHists) this->CreateHistsJetPurStab();  
//   GFHistArray histsNjet, histsPt, histsEta, histsPhi;
//   GFHistArray histsNjetS83, histsPtS83, histsEtaS83, histsPhiS83;
//   GFHistArray histsNjetS84, histsPtS84, histsEtaS84, histsPhiS84;
//   const Int_t nHistsPerQuantity = 6; // match with CreateHistsJetPurStab ...
//   for(Int_t i = 0; i < nHistsPerQuantity; ++i) {
//     histsNjet.Add(fJetPurStabHists->At(i));
//     histsPt.Add(fJetPurStabHists->At(i+nHistsPerQuantity));
//     histsEta.Add(fJetPurStabHists->At(i+2*nHistsPerQuantity));
//     histsPhi.Add(fJetPurStabHists->At(i+3*nHistsPerQuantity));
//
//     histsNjetS83.Add(fJetPurStabHistsS83->At(i));
//     histsPtS83.Add(fJetPurStabHistsS83->At(i+nHistsPerQuantity));
//     histsEtaS83.Add(fJetPurStabHistsS83->At(i+2*nHistsPerQuantity));
//     histsPhiS83.Add(fJetPurStabHistsS83->At(i+3*nHistsPerQuantity));
//
//     histsNjetS84.Add(fJetPurStabHistsS84->At(i));
//     histsPtS84.Add(fJetPurStabHistsS84->At(i+nHistsPerQuantity));
//     histsEtaS84.Add(fJetPurStabHistsS84->At(i+2*nHistsPerQuantity));
//     histsPhiS84.Add(fJetPurStabHistsS84->At(i+3*nHistsPerQuantity));
//   }
//
//   const Bool_t s83 = this->IsS83Gen(NULL) && this->IsS83(ds);
//   const Bool_t s84 = this->IsS84Gen(NULL) && this->IsS84(ds);
//
//   // get jets and number of jets
//   const Double_t oldMinPt = fSteer->GetDstar1JetPtBins()->At(0);
//   fSteer->SetDstar1JetPtBins()->AddAt(0., 0); // for purity/stab. no cut!!!
//
//   TObjArray jets;
//   this->GetNonDstarJets(ds, jets);
//   TObjArray genJets;
//   this->GetNonDstarGenJets(this->GetCloseGenDsKpipi(ds, "C"), genJets);
//
//   fSteer->SetDstar1JetPtBins()->AddAt(oldMinPt, 0);
//
//   Int_t nGenJets = 0;
//   for(Int_t i = 0; i < genJets.GetEntriesFast(); ++i){
//     if(static_cast<H1PartJet*>(genJets[i])->GetPt() > oldMinPt) ++nGenJets;
//   }
//   Int_t nJets = 0;
//   for(Int_t i = 0; i < jets.GetEntriesFast(); ++i){
//     if(static_cast<H1PartJet*>(jets[i])->GetPt() > oldMinPt) ++nJets;
//   }
//
//   // now fill:
//   // as soon as we fill weights, we need to call Sumw2 before!
//   this->FillHistsPurStab(nJets, nGenJets, &histsNjet);
//   if(s83) this->FillHistsPurStab(nJets, nGenJets, &histsNjetS83);
//   if(s84) this->FillHistsPurStab(nJets, nGenJets, &histsNjetS84);
//
//   Int_t nJetsNew = this->RemoveLowPt(&jets, 1);//2);
//   nJetsNew = TMath::Min(nJetsNew, this->RemoveLowPt(&genJets, 1));//2));
//
//   if(nJetsNew == 0) return;
//
//   if(nJetsNew == 2){// obsolete!
//     H1PartJet* gen1 = static_cast<H1PartJet*>(genJets[0]);
//     H1PartJet* gen2 = static_cast<H1PartJet*>(genJets[1]);
//     GFDstarAnalyse::Associate(static_cast<H1PartJet*>(jets[0]),static_cast<H1PartJet*>(jets[1]),
// 			      gen1, gen2);
//     genJets[0] = gen1; genJets[1] = gen2;
//   }
//
//   for(Int_t i = 0; i < nJetsNew; ++i){//jets.GetEntriesFast(); ++i){
//     const Double_t jetPt = static_cast<H1PartJet*>(jets[i])->GetPt();
//     const Double_t genJetPt = static_cast<H1PartJet*>(genJets[i])->GetPt();
//     const Double_t jetEta = static_cast<H1PartJet*>(jets[i])->GetEta();
//     const Double_t genJetEta = static_cast<H1PartJet*>(genJets[i])->GetEta();
//     const Double_t jetPhi = static_cast<H1PartJet*>(jets[i])->GetPhi();
//     const Double_t genJetPhi = static_cast<H1PartJet*>(genJets[i])->GetPhi();
//     this->FillHistsPurStab(jetPt, genJetPt, &histsPt);
//     this->FillHistsPurStab(jetEta, genJetEta, &histsEta);
//     this->FillHistsPurStab(jetPhi, genJetPhi, &histsPhi);
//
//     if(s83){
//       this->FillHistsPurStab(jetPt, genJetPt, &histsPtS83);
//       this->FillHistsPurStab(jetEta, genJetEta, &histsEtaS83);
//       this->FillHistsPurStab(jetPhi, genJetPhi, &histsPhiS83);
//     }
//     if(s84){
//       this->FillHistsPurStab(jetPt, genJetPt, &histsPtS84);
//       this->FillHistsPurStab(jetEta, genJetEta, &histsEtaS84);
//       this->FillHistsPurStab(jetPhi, genJetPhi, &histsPhiS84);
//     }
//
//     for(Int_t iBin = 0; iBin < fSteer->GetDstar1JetEtaBins()->GetSize() - 1; ++iBin){
//       if(fSteer->GetDstar1JetEtaBins()->At(iBin) <= genJetEta  
// 	 && genJetEta < fSteer->GetDstar1JetEtaBins()->At(iBin+1)){
// // 	cout << "OK: " << fJetEtaBins[iBin] << " " << genJetEta << " " << fJetEtaBins[iBin+1] 
// // 	     << endl;
// 	fJetPurStabPtInEtaHists->At(iBin*3+0)->Fill(genJetPt, jetPt);
// 	if(genJetPt) fJetPurStabPtInEtaHists->At(iBin*3+1)->Fill((jetPt - genJetPt) / genJetPt);
// 	fJetPurStabPtInEtaHists->At(iBin*3+2)->Fill(jetPt - genJetPt);
// 	if(s83){
// 	  fJetPurStabPtInEtaHistsS83->At(iBin*3+0)->Fill(genJetPt, jetPt);
// 	  if(genJetPt)fJetPurStabPtInEtaHistsS83->At(iBin*3+1)->Fill((jetPt-genJetPt)/genJetPt);
// 	  fJetPurStabPtInEtaHistsS83->At(iBin*3+2)->Fill(jetPt - genJetPt);
// 	}
// 	if(s84){
// 	  fJetPurStabPtInEtaHistsS84->At(iBin*3+0)->Fill(genJetPt, jetPt);
// 	  if(genJetPt)fJetPurStabPtInEtaHistsS84->At(iBin*3+1)->Fill((jetPt-genJetPt)/genJetPt);
// 	  fJetPurStabPtInEtaHistsS84->At(iBin*3+2)->Fill(jetPt - genJetPt);
// 	}
// 	break;
// //       } else {
// // 	cout << "not OK: "<< fJetEtaBins[iBin] << " " << genJetEta << " " << fJetEtaBins[iBin+1]
// // 	     << endl;
//       }
//     }
//   } // loop on jets
// }

//_____________________________________________________
 void GFDstarAnalyseMc::FillHistsPurStab(Double_t varRec, Double_t varGen,
					GFHistArray* hists, Double_t weight, 
					const Bool_t* fill) const
{
  // hists: 0 = rec, 1 = rec & gen, 2 = !rec & gen, 3 = rec vs gen (TH2), 
  //        4 = (rec-gen)/gen (if gen != 0), 5 = rec-gen
  // must have same binning, 3/4/5 not filled if not existing
  // if 'fill' given, only thos hists are filled where fill[i] == kTRUE
  if(!hists || hists->GetEntriesFast() < 3) {
    this->Fatal("FillHistsPurStab", "Not enough hists in input array!");
    return;
  }

  if(!fill || fill[0]) hists->At(0)->Fill(varRec, weight); // N_{rec}
  const Int_t binRec = hists->At(0)->FindBin(varRec);
  const Int_t binGen = hists->At(0)->FindBin(varGen);

  if(binRec == binGen) {
    if(!fill || fill[1]) hists->At(1)->Fill(varGen, weight); // N_{gen}^{rec}
  } else if(!fill || fill[2]) hists->At(2)->Fill(varGen, weight);            // N_{gen}^{!rec}

  if((!fill || fill[3]) && hists->At(3)){
    static_cast<TH2*>(hists->At(3))->Fill(varGen, varRec, weight);
  }

//   // resolution: fill only if we do not have just over and underflow...
//   const Int_t binOverFlow = hists->At(3)->GetNbinsX()+1;
//   if(binRec == 0 || binRec == binOverFlow) return;

  if((!fill || fill[4]) && hists->At(4) && varGen) {
    hists->At(4)->Fill((varRec - varGen)/varGen, weight);
  }
  if((!fill || fill[5]) && hists->At(5)) hists->At(5)->Fill(varRec - varGen, weight);
}

//_____________________________________________________
 void GFDstarAnalyseMc::CreateHistsDsJetPurStab()
{
  TDirectory* oldDir = this->OpenHistsFile();
  TDirectory* dir = new TDirectory("dsJetPurStab", "pur./stab. hists for D* + jet");
  dir->cd();

  const Int_t nBinsVs = 60;
  const Float_t maxDevRes = 1.;
  const Int_t nBinsRes = 60;

  // overall
  GFHistManip::ClearCreateArray(fDsJetPurStabHists);
  fAllHistArrays.Add(fDsJetPurStabHists);
  fDsJetPurStabHists->AddAt(new TH1F("AllRec", "D* + jet (rec)", 1, 0., 1.), 0);
  fDsJetPurStabHists->AddAt(new TH1F("AllRecGen", "D* + jet (rec && gen)",  1, 0., 1.), 1);
  fDsJetPurStabHists->AddAt(new TH1F("AllNRecGen", "D* + jet (!rec && gen)",  1, 0., 1.), 2);
  // no 3/4/5
  GFHistManip::CreateAnalogHists(fDsJetPurStabHists, fDsJetPurStabHistsS83, "S83");
  fAllHistArrays.Add(fDsJetPurStabHistsS83);
  GFHistManip::CallSumw2(fDsJetPurStabHistsS83);

  // Dphi 
  GFHistManip::ClearCreateArray(fDsJetPurStabHistsDphi);
  fAllHistArrays.Add(fDsJetPurStabHistsDphi);
  const TArrayD* ar = fSteer->GetDstar1JetDphiBins();
  TArrayD special(ar->GetSize() +1);
  special[0] = -20.;
  for (Int_t i = 0; i < ar->GetSize(); ++i) special[i+1] = ar->At(i);
  fDsJetPurStabHistsDphi->AddAt(new TH1F("DphiRec", "#Delta(#phi) D* + jet (rec)", 
					 ar->GetSize()-1, ar->GetArray()), 0);
  fDsJetPurStabHistsDphi->AddAt(new TH1F("DphiRecGen", "#Delta(#phi) D* + jet (rec && gen)", 
					 ar->GetSize()-1, ar->GetArray()), 1);
  fDsJetPurStabHistsDphi->AddAt(new TH1F("DphiNRecGen", "#Delta(#phi) D* + jet (!rec && gen)", 
					 ar->GetSize()-1, ar->GetArray()), 2);

  fDsJetPurStabHistsDphi->AddAt(new TH2F("DphiRecVsGen", "#Delta(#phi) D* + jet (rec vs gen)",
// 					 nBinsVs/2+1, -6., ar->At(ar->GetSize() -1),
// 					 nBinsVs/2+1, -6.,ar->At(ar->GetSize()-1)),3);
					 special.GetSize()-1, special.GetArray(),
					 special.GetSize()-1, special.GetArray()), 3);
  // no 4
  fDsJetPurStabHistsDphi->AddAt(new TH1F("DphiJetRes", "#Delta(#phi) (rec - gen)", 
					 nBinsRes, -30.*maxDevRes, 30.*maxDevRes), 5);
  GFHistManip::CreateAnalogHists(fDsJetPurStabHistsDphi, fDsJetPurStabHistsDphiS83, "S83");
  fAllHistArrays.Add(fDsJetPurStabHistsDphiS83);
  GFHistManip::CallSumw2(fDsJetPurStabHistsDphiS83);

  // Deta
  GFHistManip::ClearCreateArray(fDsJetPurStabHistsDeta);
  fAllHistArrays.Add(fDsJetPurStabHistsDeta);
  ar = fSteer->GetDstar1JetDetaBins();
  fDsJetPurStabHistsDeta->AddAt(new TH1F("DetaRec", "#eta(D*) - #eta(jet) (rec)",
					 ar->GetSize()-1, ar->GetArray()), 0);
  fDsJetPurStabHistsDeta->AddAt(new TH1F("DetaRecGen", "#eta(D*) - #eta(jet) (rec && gen)",
					 ar->GetSize()-1, ar->GetArray()), 1);
  fDsJetPurStabHistsDeta->AddAt(new TH1F("DetaNRecGen", "#eta(D*) - #eta(jet) (!rec && gen)",
					 ar->GetSize()-1, ar->GetArray()), 2);
  fDsJetPurStabHistsDeta->AddAt(new TH2F("DetaRecVsGen", "#eta(D*) - #eta(jet) (rec vs gen)",
					 nBinsVs, ar->At(0), ar->At(ar->GetSize() -1),
					 nBinsVs, ar->At(0), ar->At(ar->GetSize() -1)), 3);
  // no 4
  fDsJetPurStabHistsDeta->AddAt(new TH1F("DetaJetRes", "#eta(D*) - #eta(jet) (rec - gen)", 
					 nBinsRes, -0.4*maxDevRes, 0.4*maxDevRes), 5);
  GFHistManip::CreateAnalogHists(fDsJetPurStabHistsDeta, fDsJetPurStabHistsDetaS83, "S83");
  fAllHistArrays.Add(fDsJetPurStabHistsDetaS83);
  GFHistManip::CallSumw2(fDsJetPurStabHistsDetaS83);

  // DeltaR
  GFHistManip::ClearCreateArray(fDsJetPurStabHistsDeltaR);
  fAllHistArrays.Add(fDsJetPurStabHistsDeltaR);
  fDsJetPurStabHistsDeltaR->AddAt(new TH1F("DeltaRRec", "#Delta R(D*-jet) (rec)",
					 10, 0., 4.5), 0);
  fDsJetPurStabHistsDeltaR->AddAt(new TH1F("DeltaRRecGen", "#Delta R(D*-jet) (rec && gen)",
					 10, 0., 4.5), 1);
  fDsJetPurStabHistsDeltaR->AddAt(new TH1F("DeltaRNRecGen", "#Delta R(D*-jet) (!rec && gen)",
					 10, 0., 4.5), 2);
  fDsJetPurStabHistsDeltaR->AddAt(new TH2F("DeltaRRecVsGen", "#Delta R(D*-jet) (rec vs gen)",
					 nBinsVs, 0., 4.5, nBinsVs, 0., 4.5), 3);
  // no 4
  fDsJetPurStabHistsDeltaR->AddAt(new TH1F("DeltaRJetRes", "#Delta R(D*-jet) (rec - gen)", 
					 nBinsRes, -0.8*maxDevRes, 0.8*maxDevRes), 5);
  GFHistManip::CreateAnalogHists(fDsJetPurStabHistsDeltaR, fDsJetPurStabHistsDeltaRS83, "S83");
  fAllHistArrays.Add(fDsJetPurStabHistsDeltaRS83);
  GFHistManip::CallSumw2(fDsJetPurStabHistsDeltaRS83);

  // xGam
  GFHistManip::ClearCreateArray(fDsJetPurStabHistsXgam);
  fAllHistArrays.Add(fDsJetPurStabHistsXgam);
  ar = fSteer->GetXgammaBins();
  fDsJetPurStabHistsXgam->AddAt(new TH1F("xGamRec", "x_{#gamma}(D* + jet) (rec)", 
					 ar->GetSize()-1, ar->GetArray()), 0);
  fDsJetPurStabHistsXgam->AddAt(new TH1F("xGamRecGen", "x_{#gamma}(D* + jet) (rec && gen)", 
					 ar->GetSize()-1, ar->GetArray()), 1);
  fDsJetPurStabHistsXgam->AddAt(new TH1F("xGamNRecGen", "x_{#gamma}(D* + jet) (!rec && gen)", 
					 ar->GetSize()-1, ar->GetArray()), 2);
  fDsJetPurStabHistsXgam->AddAt(new TH2F("xGamRecVsGen", "x_{#gamma}(D* + jet) (rec vs gen)",
					 nBinsVs-9, -0.02, ar->At(ar->GetSize() -1),
					 nBinsVs-9, -0.02, ar->At(ar->GetSize() -1)), 3);
  // no 4
  fDsJetPurStabHistsXgam->AddAt(new TH1F("XgamJetRes", "x_{#gamma}(D*-jet) (rec - gen)", 
					 nBinsRes, -0.8*maxDevRes, 0.8*maxDevRes), 5);
  GFHistManip::CreateAnalogHists(fDsJetPurStabHistsXgam, fDsJetPurStabHistsXgamS83, "S83");
  fAllHistArrays.Add(fDsJetPurStabHistsXgamS83);
  GFHistManip::CallSumw2(fDsJetPurStabHistsXgamS83);

  // PtJet
  GFHistManip::ClearCreateArray(fDsJetPurStabHistsJetPt);
  fAllHistArrays.Add(fDsJetPurStabHistsJetPt);
  ar = fSteer->GetDstar1JetPtBins();
  fDsJetPurStabHistsJetPt->AddAt(new TH1F("PtJetRec", "p_{t}(jet) D*+jet (rec)", 
					 ar->GetSize()-1, ar->GetArray()), 0);
  fDsJetPurStabHistsJetPt->AddAt(new TH1F("PtJetRecGen", "p_{t}(jet) D*+jet (rec && gen)", 
					 ar->GetSize()-1, ar->GetArray()), 1);
  fDsJetPurStabHistsJetPt->AddAt(new TH1F("PtJetNRecGen", "p_{t}(jet) D*+jet (!rec && gen)", 
					 ar->GetSize()-1, ar->GetArray()), 2);
  fDsJetPurStabHistsJetPt->AddAt(new TH2F("PtJetRecVsGen", "p_{t}(jet) D*+jet (rec vs gen)", 
					  nBinsVs, ar->At(0), ar->At(ar->GetSize() -1),
					  nBinsVs, ar->At(0), ar->At(ar->GetSize() -1)), 3);
  fDsJetPurStabHistsJetPt->AddAt(new TH1F("PtJetResRel", "p_{t}(jet) D*+jet (rec-gen)/gen",
					  nBinsRes, -maxDevRes, maxDevRes), 4);
  fDsJetPurStabHistsJetPt->AddAt(new TH1F("PtJetRes", "p_{t}(jet) D*+jet (rec-gen)",
					  nBinsRes, -3.*maxDevRes, 3.*maxDevRes), 5);
  GFHistManip::CreateAnalogHists(fDsJetPurStabHistsJetPt, fDsJetPurStabHistsJetPtS83, "S83");
  fAllHistArrays.Add(fDsJetPurStabHistsJetPtS83);
  GFHistManip::CallSumw2(fDsJetPurStabHistsJetPtS83);

  // PtJet in bins of EtaJet
  fDsJetPurStabPtInEtaHistArrays = new TObjArray;
  fDsJetPurStabPtInEtaHistArraysS83 = new TObjArray;
  for(Int_t i = 1; i < fSteer->GetDstar1JetEtaBins()->GetSize(); ++i){
    GFHistArray *purStabPtInEta = NULL;
    GFHistManip::ClearCreateArray(purStabPtInEta);
    fAllHistArrays.Add(purStabPtInEta);
    fDsJetPurStabPtInEtaHistArrays->Add(purStabPtInEta);
    TString range(Form("%.2f < #eta^{rec}(jet) < %.2f", fSteer->GetDstar1JetEtaBins()->At(i-1),
		       fSteer->GetDstar1JetEtaBins()->At(i)));
    purStabPtInEta->AddAt(new TH1F(Form("PtJetEta%dRec", i),
				 Form("p_{t}(jet): D*+jet (rec), %s", range.Data()),
				 ar->GetSize()-1, ar->GetArray()), 0);
    purStabPtInEta->AddAt(new TH1F(Form("PtJetEta%dRecGen", i),
				 Form("p_{t}(jet) D*+jet (rec && gen), %s", range.Data()),
				 ar->GetSize()-1, ar->GetArray()), 1);
    purStabPtInEta->AddAt(new TH1F(Form("PtJetEta%dNRecGen", i),
				 Form("p_{t}(jet) D*+jet (!rec && gen), %s", range.Data()),
				 ar->GetSize()-1, ar->GetArray()), 2);
    purStabPtInEta->AddAt(new TH2F(Form("PtJetEta%dRecVsGen", i),
				 Form("p_{t}(jet) D*+jet (rec vs gen), %s", range.Data()),
				 nBinsVs, ar->At(0), ar->At(ar->GetSize() -1),
				 nBinsVs, ar->At(0), ar->At(ar->GetSize() -1)), 3);
    purStabPtInEta->AddAt(new TH1F(Form("PtJetEta%dResRel", i),
				 Form("p_{t}(jet) D*+jet (rec-gen)/gen, %s", range.Data()),
				 nBinsRes, -maxDevRes, maxDevRes), 4);
    purStabPtInEta->AddAt(new TH1F(Form("PtJetEta%dRes", i),
				 Form("p_{t}(jet) D*+jet (rec-gen), %s", range.Data()),
				 nBinsRes, -3.*maxDevRes, 3.*maxDevRes), 5);
    GFHistArray *purStabPtInEtaS83 = NULL;
    GFHistManip::CreateAnalogHists(purStabPtInEta, purStabPtInEtaS83, "S83");
    fAllHistArrays.Add(purStabPtInEtaS83);
    fDsJetPurStabPtInEtaHistArraysS83->Add(purStabPtInEtaS83);
    GFHistManip::CallSumw2(purStabPtInEtaS83);
  }
  // PtJet in bins of PtJet
  fDsJetPurStabPtInPtHistArrays = new TObjArray;
  fDsJetPurStabPtInPtHistArraysS83 = new TObjArray;
  for(Int_t i = 1; i < fSteer->GetDstar1JetPtBins()->GetSize(); ++i){
    GFHistArray *purStabPtInPt = NULL;
    GFHistManip::ClearCreateArray(purStabPtInPt);
    fAllHistArrays.Add(purStabPtInPt);
    fDsJetPurStabPtInPtHistArrays->Add(purStabPtInPt);
    TString range(Form("%.2f < p_{t}^{rec}(jet) < %.2f", fSteer->GetDstar1JetPtBins()->At(i-1),
		       fSteer->GetDstar1JetPtBins()->At(i)));
    purStabPtInPt->AddAt(new TH1F(Form("PtJetPt%dRec", i),
				 Form("p_{t}(jet): D*+jet (rec), %s", range.Data()),
				 ar->GetSize()-1, ar->GetArray()), 0);
    purStabPtInPt->AddAt(new TH1F(Form("PtJetPt%dRecGen", i),
				 Form("p_{t}(jet) D*+jet (rec && gen), %s", range.Data()),
				 ar->GetSize()-1, ar->GetArray()), 1);
    purStabPtInPt->AddAt(new TH1F(Form("PtJetPt%dNRecGen", i),
				 Form("p_{t}(jet) D*+jet (!rec && gen), %s", range.Data()),
				 ar->GetSize()-1, ar->GetArray()), 2);
    purStabPtInPt->AddAt(new TH2F(Form("PtJetPt%dRecVsGen", i),
				 Form("p_{t}(jet) D*+jet (rec vs gen), %s", range.Data()),
				 nBinsVs, ar->At(0), ar->At(ar->GetSize() -1),
				 nBinsVs, ar->At(0), ar->At(ar->GetSize() -1)), 3);
    purStabPtInPt->AddAt(new TH1F(Form("PtJetPt%dResRel", i),
				 Form("p_{t}(jet) D*+jet (rec-gen)/gen, %s", range.Data()),
				 nBinsRes, -maxDevRes, maxDevRes), 4);
    purStabPtInPt->AddAt(new TH1F(Form("PtJetPt%dRes", i),
				 Form("p_{t}(jet) D*+jet (rec-gen), %s", range.Data()),
				 nBinsRes, -3.*maxDevRes, 3.*maxDevRes), 5);
    GFHistArray *purStabPtInPtS83 = NULL;
    GFHistManip::CreateAnalogHists(purStabPtInPt, purStabPtInPtS83, "S83");
    fAllHistArrays.Add(purStabPtInPtS83);
    fDsJetPurStabPtInPtHistArraysS83->Add(purStabPtInPtS83);
    GFHistManip::CallSumw2(purStabPtInPtS83);
  }

  // PtDs
  GFHistManip::ClearCreateArray(fDsJetPurStabHistsDsPt);
  fAllHistArrays.Add(fDsJetPurStabHistsDsPt);
  ar = fSteer->GetDstarPtBins1Jet();
  fDsJetPurStabHistsDsPt->AddAt(new TH1F("PtDsRec", "p_{t}(D*) D*+jet (rec)", 
					 ar->GetSize()-1, ar->GetArray()), 0);
  fDsJetPurStabHistsDsPt->AddAt(new TH1F("PtDsRecGen", "p_{t}(D*) D*+jet (rec && gen)", 
					 ar->GetSize()-1, ar->GetArray()), 1);
  fDsJetPurStabHistsDsPt->AddAt(new TH1F("PtDsNRecGen", "p_{t}(D*) D*+jet (!rec && gen)", 
					 ar->GetSize()-1, ar->GetArray()), 2);
  fDsJetPurStabHistsDsPt->AddAt(new TH2F("PtDsRecVsGen", "p_{t}(D*) D*+jet (rec vs gen)", 
					 nBinsVs, ar->At(0), ar->At(ar->GetSize() -1),
					 nBinsVs, ar->At(0), ar->At(ar->GetSize() -1)), 3);
  fDsJetPurStabHistsDsPt->AddAt(new TH1F("PtDsResRel", "p_{t}(D*) D*+jet (rec-gen)/gen", 
					 nBinsRes, -0.3*maxDevRes, 0.3*maxDevRes), 4);
  // no 5
  GFHistManip::CreateAnalogHists(fDsJetPurStabHistsDsPt, fDsJetPurStabHistsDsPtS83, "S83");
  fAllHistArrays.Add(fDsJetPurStabHistsDsPtS83);
  GFHistManip::CallSumw2(fDsJetPurStabHistsDsPtS83);

  // EtaJet
  GFHistManip::ClearCreateArray(fDsJetPurStabHistsJetEta);
  fAllHistArrays.Add(fDsJetPurStabHistsJetEta);
  ar = fSteer->GetDstar1JetEtaBins();
  fDsJetPurStabHistsJetEta->AddAt(new TH1F("EtaJetRec", "#eta(jet) D*+jet (rec)", 
					   ar->GetSize()-1, ar->GetArray()), 0);
  fDsJetPurStabHistsJetEta->AddAt(new TH1F("EtaJetRecGen", "#eta(jet) D*+jet (rec && gen)", 
					   ar->GetSize()-1, ar->GetArray()), 1);
  fDsJetPurStabHistsJetEta->AddAt(new TH1F("EtaJetNRecGen", "#eta(jet) D*+jet (!rec && gen)", 
					   ar->GetSize()-1, ar->GetArray()), 2);
  fDsJetPurStabHistsJetEta->AddAt(new TH2F("EtaJetRecVsGen", "#eta(jet) D*+jet (rec vs gen)", 
					   nBinsVs, ar->At(0), ar->At(ar->GetSize() -1),
					   nBinsVs, ar->At(0), ar->At(ar->GetSize() -1)), 3);
  // no 4
  fDsJetPurStabHistsJetEta->AddAt(new TH1F("EtaJetRes", "#eta(jet) D*+jet (rec - gen)", 
					   (5*nBinsRes)/6, -0.5*maxDevRes, 0.5*maxDevRes), 5);
  GFHistManip::CreateAnalogHists(fDsJetPurStabHistsJetEta, fDsJetPurStabHistsJetEtaS83, "S83");
  fAllHistArrays.Add(fDsJetPurStabHistsJetEtaS83);
  GFHistManip::CallSumw2(fDsJetPurStabHistsJetEtaS83);

  // EtaJet in bins of PtJet
  fDsJetPurStabEtaInPtHistArrays = new TObjArray;
  fDsJetPurStabEtaInPtHistArraysS83 = new TObjArray;
  for(Int_t i = 1; i < fSteer->GetDstar1JetPtBins()->GetSize(); ++i){
    GFHistArray *purStabEtaInPt = NULL;
    GFHistManip::ClearCreateArray(purStabEtaInPt);
    fAllHistArrays.Add(purStabEtaInPt);
    fDsJetPurStabEtaInPtHistArrays->Add(purStabEtaInPt);
    TString range(Form("%.2f < p_{t}^{rec}(jet) < %.2f", fSteer->GetDstar1JetPtBins()->At(i-1),
		       fSteer->GetDstar1JetPtBins()->At(i)));
    purStabEtaInPt->AddAt(new TH1F(Form("EtaJetPt%dRec", i), 
				   Form("#eta(jet) D*+jet (rec), %s", range.Data()),
				   ar->GetSize()-1, ar->GetArray()), 0);
    purStabEtaInPt->AddAt(new TH1F(Form("EtaJetPt%dRecGen", i),
				   Form("#eta(jet) D*+jet (rec && gen), %s", range.Data()),
				   ar->GetSize()-1, ar->GetArray()), 1);
    purStabEtaInPt->AddAt(new TH1F(Form("EtaJetPt%dNRecGen", i),
				   Form("#eta(jet) D*+jet (!rec && gen), %s", range.Data()),
				   ar->GetSize()-1, ar->GetArray()), 2);
    purStabEtaInPt->AddAt(new TH2F(Form("EtaJetPt%dRecVsGen", i),
				   Form("#eta(jet) D*+jet (rec vs gen), %s", range.Data()),
				   nBinsVs, ar->At(0), ar->At(ar->GetSize() -1),
				   nBinsVs, ar->At(0), ar->At(ar->GetSize() -1)), 3);
    // no 4
    purStabEtaInPt->AddAt(new TH1F(Form("EtaJetPt%dRes", i),
				   Form("#eta(jet) D*+jet (rec - gen), %s", range.Data()),
				   (5*nBinsRes)/6, -0.5*maxDevRes, 0.5*maxDevRes), 5);
    GFHistArray *purStabEtaInPtS83 = NULL;
    GFHistManip::CreateAnalogHists(purStabEtaInPt, purStabEtaInPtS83, "S83");
    fAllHistArrays.Add(purStabEtaInPtS83);
    fDsJetPurStabEtaInPtHistArraysS83->Add(purStabEtaInPtS83);
    GFHistManip::CallSumw2(purStabEtaInPtS83);
  }

  // PhiJet
  GFHistManip::ClearCreateArray(fDsJetPurStabHistsJetPhi);
  fAllHistArrays.Add(fDsJetPurStabHistsJetPhi);
  ar = fSteer->GetPhiBins();
  fDsJetPurStabHistsJetPhi->AddAt(new TH1F("PhiJetRec", "#phi(jet) D*+jet (rec)", 
					   ar->GetSize()-1, ar->GetArray()), 0);
  fDsJetPurStabHistsJetPhi->AddAt(new TH1F("PhiJetRecGen", "#phi(jet) D*+jet (rec && gen)", 
					   ar->GetSize()-1, ar->GetArray()), 1);
  fDsJetPurStabHistsJetPhi->AddAt(new TH1F("PhiJetNRecGen", "#phi(jet) D*+jet (!rec && gen)", 
					   ar->GetSize()-1, ar->GetArray()), 2);
  fDsJetPurStabHistsJetPhi->AddAt(new TH2F("PhiJetRecVsGen", "#phi(jet) D*+jet (rec vs gen)", 
					   nBinsVs, ar->At(0), ar->At(ar->GetSize() -1),
					   nBinsVs, ar->At(0), ar->At(ar->GetSize() -1)), 3);
  // no 4
  fDsJetPurStabHistsJetPhi->AddAt(new TH1F("PhiJetRes", "#phi(jet) D*+jet (rec - gen)", 
					   nBinsRes, -0.6*maxDevRes, 0.6*maxDevRes), 5);
  
  GFHistManip::CreateAnalogHists(fDsJetPurStabHistsJetPhi, fDsJetPurStabHistsJetPhiS83, "S83");
  fAllHistArrays.Add(fDsJetPurStabHistsJetPhiS83);
  GFHistManip::CallSumw2(fDsJetPurStabHistsJetPhiS83);

  // DaughJet
  GFHistManip::ClearCreateArray(fDsJetPurStabHistsJetDaugh);
  fAllHistArrays.Add(fDsJetPurStabHistsJetDaugh);
  const Int_t maxDaught = 15;
  fDsJetPurStabHistsJetDaugh->AddAt(new TH1F("DaughJetRec", "N_{daught}^{jet} D*+jet (rec)", 
					     maxDaught/3, 0, maxDaught), 0);
  fDsJetPurStabHistsJetDaugh->AddAt(new TH1F("DaughJetRecGen", 
					     "N_{daught}^{jet} D*+jet (rec && gen)", 
					     maxDaught/3, 0, maxDaught), 1);
  fDsJetPurStabHistsJetDaugh->AddAt(new TH1F("DaughJetNRecGen",
					     "N_{daught}^{jet} D*+jet (!rec && gen)",
					     maxDaught/3, 0, maxDaught), 2);
  fDsJetPurStabHistsJetDaugh->AddAt(new TH2F("DaughJetRecVsGen",
					     "N_{daught}^{jet} D*+jet (rec vs gen)",
					     maxDaught,0,maxDaught,maxDaught,0,maxDaught), 3);
  // no 4/5
  GFHistManip::CreateAnalogHists(fDsJetPurStabHistsJetDaugh, fDsJetPurStabHistsJetDaughS83,
				 "S83");
  fAllHistArrays.Add(fDsJetPurStabHistsJetDaughS83);
  GFHistManip::CallSumw2(fDsJetPurStabHistsJetDaughS83);

  // ChFrac
  GFHistManip::ClearCreateArray(fDsJetPurStabHistsChFrac);
  fAllHistArrays.Add(fDsJetPurStabHistsChFrac);
  fDsJetPurStabHistsChFrac->AddAt(new TH1F("ChFracRec","N_{daught}^{jet}#otimes q D*+jet (rec)",
					   nBinsVs/6, 0., 1.+1.e-5), 0);
  fDsJetPurStabHistsChFrac->AddAt(new TH1F("ChFracRecGen", 
					   "N_{daught}^{jet}#otimes q D*+jet (rec && gen)", 
					   nBinsVs/6, 0., 1.+1.e-5), 1);
  fDsJetPurStabHistsChFrac->AddAt(new TH1F("ChFracNRecGen",
					   "N_{daught}^{jet}#otimes q D*+jet (!rec && gen)",
					   nBinsVs/6, 0., 1.+1.e-5), 2);
  fDsJetPurStabHistsChFrac->AddAt(new TH2F("ChFracRecVsGen",
					   "N_{daught}^{jet}#otimes q D*+jet (rec vs gen)",
					   nBinsVs/3, 0., 1.+1.e-5, nBinsVs/3, 0., 1.+1.e-5),3);
  // no 4
  fDsJetPurStabHistsChFrac->AddAt(new TH1F("ChFracRes", 
					   "N_{daught}^{jet}#otimes q D*+jet (rec - gen)", 
					   nBinsRes, -0.8*maxDevRes, 0.8*maxDevRes), 5);
  GFHistManip::CreateAnalogHists(fDsJetPurStabHistsChFrac, fDsJetPurStabHistsChFracS83, "S83");
  fAllHistArrays.Add(fDsJetPurStabHistsChFracS83);
  GFHistManip::CallSumw2(fDsJetPurStabHistsChFracS83);

  //  PtDsJet
  GFHistManip::ClearCreateArray(fDsJetPurStabHistsDsJetPt);
  fAllHistArrays.Add(fDsJetPurStabHistsDsJetPt);
  ar = fSteer->GetDstar1JetDsJetPtBins();
  fDsJetPurStabHistsDsJetPt->AddAt(new TH1F("PtDsJetRec", "p_{t}(D*+j) D*+jet (rec)", 
					    ar->GetSize()-1, ar->GetArray()),0);
  fDsJetPurStabHistsDsJetPt->AddAt(new TH1F("PtDsJetRecGen", "p_{t}(D*+j) D*+jet (rec && gen)", 
					    ar->GetSize()-1, ar->GetArray()),1);
  fDsJetPurStabHistsDsJetPt->AddAt(new TH1F("PtDsJetNRecGen","p_{t}(D*+j) D*+jet (!rec && gen)",
					    ar->GetSize()-1, ar->GetArray()),2);
  fDsJetPurStabHistsDsJetPt->AddAt(new TH2F("PtDsJetRecVsGen","p_{t}(D*+j) D*+jet (rec vs gen)",
					    nBinsVs, ar->At(0), ar->At(ar->GetSize() -1),
					    nBinsVs, ar->At(0),  ar->At(ar->GetSize() -1)), 3);
  fDsJetPurStabHistsDsJetPt->AddAt(new TH1F("PtDsJetResRel", "p_{t}(D*+j) D*+jet (rec-gen)/gen",
					    nBinsRes, -maxDevRes, maxDevRes), 4);
  // no 5
  GFHistManip::CreateAnalogHists(fDsJetPurStabHistsDsJetPt, fDsJetPurStabHistsDsJetPtS83,"S83");
  fAllHistArrays.Add(fDsJetPurStabHistsDsJetPtS83);
  GFHistManip::CallSumw2(fDsJetPurStabHistsDsJetPtS83);

  //  PtDsJetOrth
  GFHistManip::ClearCreateArray(fDsJetPurStabHistsPtDsJetOrth);
  fAllHistArrays.Add(fDsJetPurStabHistsPtDsJetOrth);
  const Double_t tmp[] = {0.,0.5, 1.,1.5,2.,2.5,3.,3.5,4.,4.5,5.,5.5,6.,6.5,7.,7.5,8.,8.5};
  const TArrayD tmpAr(sizeof(tmp)/sizeof(tmp[0]), tmp);
  ar = &tmpAr;
  fDsJetPurStabHistsPtDsJetOrth->AddAt(new TH1F("PtDsJetOrthRec",
					    "p_{xy}(D*+j)#perp p_{xy}(j) D*+jet (rec)", 
					    ar->GetSize()-1, ar->GetArray()),0);
  fDsJetPurStabHistsPtDsJetOrth->AddAt(new TH1F("PtDsJetOrthRecGen",
					    "p_{xy}(D*+j)#perp p_{xy}(j) D*+jet (rec && gen)", 
					    ar->GetSize()-1, ar->GetArray()),1);
  fDsJetPurStabHistsPtDsJetOrth->AddAt(new TH1F("PtDsJetOrthNRecGen",
					    "p_{xy}(D*+j)#perp p_{xy}(j) D*+jet (!rec && gen)",
					    ar->GetSize()-1, ar->GetArray()),2);
  fDsJetPurStabHistsPtDsJetOrth->AddAt(new TH2F("PtDsJetOrthRecVsGen",
					    "p_{xy}(D*+j)#perp p_{xy}(j) D*+jet (rec vs gen)",
					    nBinsVs, ar->At(0), ar->At(ar->GetSize() -1),
					    nBinsVs, ar->At(0),  ar->At(ar->GetSize() -1)), 3);
  // no 4/5
  GFHistManip::CreateAnalogHists(fDsJetPurStabHistsPtDsJetOrth,fDsJetPurStabHistsPtDsJetOrthS83,
				 "S83");
  fAllHistArrays.Add(fDsJetPurStabHistsPtDsJetOrthS83);
  GFHistManip::CallSumw2(fDsJetPurStabHistsPtDsJetOrthS83);


  //  Pt2DsJet (only S83!)
  GFHistManip::ClearCreateArray(fDsJetPurStabHistsDsJetPt2S83);
  fAllHistArrays.Add(fDsJetPurStabHistsDsJetPt2S83);
  ar = fSteer->GetDstar1JetDsJetPt2Bins();
  fDsJetPurStabHistsDsJetPt2S83->AddAt(new TH1F("Pt2DsJetRec", "p_{t}^{2}(D*+j) D*+jet (rec)", 
					    ar->GetSize()-1, ar->GetArray()),0);
  fDsJetPurStabHistsDsJetPt2S83->AddAt(new TH1F("Pt2DsJetRecGen", "p_{t}^{2}(D*+j) D*+jet (rec && gen)", 
					    ar->GetSize()-1, ar->GetArray()),1);
  fDsJetPurStabHistsDsJetPt2S83->AddAt(new TH1F("Pt2DsJetNRecGen","p_{t}^{2}(D*+j) D*+jet (!rec && gen)",
					    ar->GetSize()-1, ar->GetArray()),2);
  fDsJetPurStabHistsDsJetPt2S83->AddAt(new TH2F("Pt2DsJetRecVsGen","p_{t}^{2}(D*+j) D*+jet (rec vs gen)",
					    nBinsVs, ar->At(0), ar->At(ar->GetSize() -1),
					    nBinsVs, ar->At(0),  ar->At(ar->GetSize() -1)), 3);
  fDsJetPurStabHistsDsJetPt2S83->AddAt(new TH1F("Pt2DsJetResRel", "p_{t}^{2}(D*+j) D*+jet (rec-gen)/gen",
					    nBinsRes, -maxDevRes, maxDevRes), 4);
  // no 5
  GFHistManip::AddToHistsName("S83", fDsJetPurStabHistsDsJetPt2S83);
  GFHistManip::CallSumw2(fDsJetPurStabHistsDsJetPt2S83);

  //  MDsJet
  GFHistManip::ClearCreateArray(fDsJetPurStabHistsDsJetM);
  fAllHistArrays.Add(fDsJetPurStabHistsDsJetM);
  ar = fSteer->GetDstar1JetDsJetMassBins();
  fDsJetPurStabHistsDsJetM->AddAt(new TH1F("MDsJetRec", "M(D*+j) D*+jet (rec)", 
					    ar->GetSize()-1, ar->GetArray()),0);
  fDsJetPurStabHistsDsJetM->AddAt(new TH1F("MDsJetRecGen", "M(D*+j) D*+jet (rec && gen)", 
					    ar->GetSize()-1, ar->GetArray()),1);
  fDsJetPurStabHistsDsJetM->AddAt(new TH1F("MDsJetNRecGen","M(D*+j) D*+jet (!rec && gen)",
					    ar->GetSize()-1, ar->GetArray()),2);
  fDsJetPurStabHistsDsJetM->AddAt(new TH2F("MDsJetRecVsGen","M(D*+j) D*+jet (rec vs gen)",
					    nBinsVs, ar->At(0), ar->At(ar->GetSize() -1),
					    nBinsVs, ar->At(0),  ar->At(ar->GetSize() -1)), 3);
  // no 4/5
  GFHistManip::CreateAnalogHists(fDsJetPurStabHistsDsJetM, fDsJetPurStabHistsDsJetMS83, "S83");
  fAllHistArrays.Add(fDsJetPurStabHistsDsJetMS83);
  GFHistManip::CallSumw2(fDsJetPurStabHistsDsJetMS83);

  //  CosTh
  GFHistManip::ClearCreateArray(fDsJetPurStabHistsCosTh);
  fAllHistArrays.Add(fDsJetPurStabHistsCosTh);
  ar = fSteer->GetDstar1JetDsJetCosThBins();
  fDsJetPurStabHistsCosTh->AddAt(new TH1F("CosThRec", "cos(#theta*) D*+jet (rec)", 
					  ar->GetSize()-1, ar->GetArray()),0);
  fDsJetPurStabHistsCosTh->AddAt(new TH1F("CosThRecGen", "cos(#theta*) D*+jet (rec && gen)", 
					  ar->GetSize()-1, ar->GetArray()),1);
  fDsJetPurStabHistsCosTh->AddAt(new TH1F("CosThNRecGen","cos(#theta*) D*+jet (!rec && gen)",
					  ar->GetSize()-1, ar->GetArray()),2);
  fDsJetPurStabHistsCosTh->AddAt(new TH2F("CosThRecVsGen","cos(#theta*) D*+jet (rec vs gen)",
					  nBinsVs, ar->At(0), ar->At(ar->GetSize() -1),
					  nBinsVs, ar->At(0),  ar->At(ar->GetSize() -1)), 3);
  // no 4/5
  GFHistManip::CreateAnalogHists(fDsJetPurStabHistsCosTh, fDsJetPurStabHistsCosThS83, "S83");
  fAllHistArrays.Add(fDsJetPurStabHistsCosThS83);
  GFHistManip::CallSumw2(fDsJetPurStabHistsCosThS83);

  // zDs: This is a missuse of this method, has nothing to do with jets!
  GFHistManip::ClearCreateArray(fDsPurStabHistsZDsS83);
  fAllHistArrays.Add(fDsPurStabHistsZDsS83);
  ar = fSteer->GetZDsBins();
  fDsPurStabHistsZDsS83->AddAt(new TH1F("zDsRec", "z(D*) (inclusive!) (rec)", 
					ar->GetSize()-1, ar->GetArray()), 0);
  fDsPurStabHistsZDsS83->AddAt(new TH1F("zDsRecGen", "z(D*) (inclusive!) (rec && gen)", 
					ar->GetSize()-1, ar->GetArray()), 1);
  fDsPurStabHistsZDsS83->AddAt(new TH1F("zDsNRecGen", "z(D*) (inclusive!) (!rec && gen)", 
					ar->GetSize()-1, ar->GetArray()), 2);
  fDsPurStabHistsZDsS83->AddAt(new TH2F("zDsRecVsGen", "z(D*) (inclusive!) (rec vs gen)", 
					nBinsVs, ar->At(0), 1.,//ar->At(ar->GetSize() -1),
					nBinsVs, ar->At(0), 1./*ar->At(ar->GetSize() -1)*/), 3);
  // no 4
  fDsPurStabHistsZDsS83->AddAt(new TH1F("zDsRes", "z(D*) (inclusive!) (rec - gen)", 
					   nBinsRes, -0.6*maxDevRes, 0.6*maxDevRes), 5);
  GFHistManip::AddToHistsName("S83", fDsPurStabHistsZDsS83);
  GFHistManip::CallSumw2(fDsPurStabHistsZDsS83);



  oldDir->cd();
}

//_____________________________________________________
 void GFDstarAnalyseMc::FillHistsDsJetPurStab(const H1PartDstar* ds, Bool_t all)
{
  // assume loose cut on ds, tighten to higher pt cut, use only signal region
  // but if ds == NULL: go on!
  // if all == kFALSE: skip stuff that will load jet particle branches
  
  if(ds && (!this->IsSignalRegionDm(ds) || ds->GetPt() < fDsCutPt2)) return;
  
  if(!fDsJetPurStabHistsDphi) this->CreateHistsDsJetPurStab();

  const Bool_t s83 = this->IsS83(ds);
  const Double_t weight83 = this->GetWeight(83, ds);
  
  // first care about all quantities that are not explicitely cutted on the shown quantity
  
  const H1PartMC *genDs = this->GetCloseGenDsKpipi(ds, "C83");//OK, what about S84 or ...?
  if(!genDs && ds) return; // if no D* given, go on!


  const TLorentzVector ds4vec  = ds ? ds->GetFourVector() : TLorentzVector(0,0,0,0);
  const TLorentzVector gDs4vec = genDs ? genDs->GetFourVector() : TLorentzVector(0,0,0,0);

  ////////////////////////
  // INTERMEZZO: z(D*)!
  if(s83) this->FillHistsPurStab(this->GetZ(ds), this->GetZgen(genDs), fDsPurStabHistsZDsS83,
				 weight83);
  // END INTERMEZZO
  ///////////////////////




  // find generated non dstar jet
  TObjArray genJets;
  const H1PartJet* genJet = NULL;
  this->GetNonDstarGenJets(genDs, genJets);
  if(genJets.GetEntriesFast()){
    genJet = static_cast<H1PartJet*>(genJets[this->GetHighestPt(genJets)]);
  }
  // find non dstar jet
  TObjArray jets;
  this->GetNonDstarJets(ds, jets);
  const H1PartJet* jet = NULL;
  if(jets.GetEntriesFast()){
    jet = static_cast<H1PartJet*>(jets[this->GetHighestPt(jets)]);
  }
  if(genJet || jet){
    // overall
    this->FillHistsPurStab((jet ? .5 : -.5), (genJet ? .5 : -.5), fDsJetPurStabHists);
    if(s83) this->FillHistsPurStab((jet ? .5 : -.5), (genJet ? .5 : -.5),
				   fDsJetPurStabHistsS83, weight83);
    const TLorentzVector jet4vec = (jet ? jet->GetFourVector() : TLorentzVector(0,0,0,0));
    const TLorentzVector gJet4vec = (genJet ? genJet->GetFourVector():TLorentzVector(0,0,0,0));
    // Dphi
    const Double_t dPhi    = (jet    ? 
			      TMath::Abs(ds4vec.DeltaPhi(jet4vec))*TMath::RadToDeg()   : -.1);
    const Double_t dPhiGen = (genJet ? 
			      TMath::Abs(gDs4vec.DeltaPhi(gJet4vec))*TMath::RadToDeg() : -.1);
    this->FillHistsPurStab(dPhi, dPhiGen, fDsJetPurStabHistsDphi);
    if(s83) this->FillHistsPurStab(dPhi, dPhiGen, fDsJetPurStabHistsDphiS83, weight83);
//     if(jet && genJet && dPhi - dPhiGen < -1.5){
//       if(!fList){
// 	TDirectory * old = gDirectory;
// 	gROOT->cd();
// 	//      this->OpenHistsFile();
// 	fList = new H1EventList("badDeltaPhi");
// 	H1Event* event = new H1UserDstarEvent;
// 	fList->AddChainInfo("DSTAR", event);
// 	delete event;
// 	old->cd();
//       }
//       fList->Enter();
//     }
    // Deta after cut on eta: Deta within visible eta-range
    const Double_t dEta    = (jet    ? ds4vec.Eta()  - jet4vec.Eta()  : -1.e7);
    const Double_t dEtaGen = (genJet ? gDs4vec.Eta() - gJet4vec.Eta() : -1.e7);
    this->FillHistsPurStab(dEta, dEtaGen, fDsJetPurStabHistsDeta);
    if(s83) this->FillHistsPurStab(dEta, dEtaGen, fDsJetPurStabHistsDetaS83, weight83);
    // CosTh - similar to delta eta!
    const Double_t cosTheta    =(jet    ? TMath::TanH((ds4vec.Eta()-jet4vec.Eta())/2.)  : -2.);
    const Double_t cosThetaGen =(genJet ? TMath::TanH((gDs4vec.Eta()-gJet4vec.Eta())/2.): -2.);
    this->FillHistsPurStab(cosTheta, cosThetaGen, fDsJetPurStabHistsCosTh);
    if(s83) this->FillHistsPurStab(cosTheta, cosThetaGen, fDsJetPurStabHistsCosThS83, weight83);
    // DeltaR
    const Double_t dR    = (jet    ? ds4vec.DeltaR(jet4vec)   : -6.);
    const Double_t dRGen = (genJet ? gDs4vec.DeltaR(gJet4vec) : -6.);
    this->FillHistsPurStab(dR, dRGen, fDsJetPurStabHistsDeltaR);
    if(s83) this->FillHistsPurStab(dR, dRGen, fDsJetPurStabHistsDeltaRS83, weight83);
    // xGam
//     const Double_t xGam    = (jet    ? this->GFDstarAnalyse::GetXgammaMass
// 			      (ds,    jet,    this->GetYjb())    : -1.);
//     const Double_t xGamGen = (genJet ? this->GetXgammaMass
// 			      (genDs, genJet, this->GetYjbGen()) : -1.);     
    const Double_t xGam    = (jet    ? this->GetXgammaMassHelp(ds,    jet   ) : -.001);
    const Double_t xGamGen = (genJet ? this->GetXgammaMassHelp(genDs, genJet) : -.001);

    this->FillHistsPurStab(xGam, xGamGen, fDsJetPurStabHistsXgam);
    if(s83) this->FillHistsPurStab(xGam, xGamGen, fDsJetPurStabHistsXgamS83, weight83);
    // PtDs // schmuh: cut auf pt!
    this->FillHistsPurStab(ds4vec.Pt(), gDs4vec.Pt(), fDsJetPurStabHistsDsPt);
    if(s83) this->FillHistsPurStab(ds4vec.Pt(),gDs4vec.Pt(),fDsJetPurStabHistsDsPtS83,weight83);
    // PhiJet
    const Double_t phiJet    = (jet    ? jet4vec.Phi()    : -1.e7);
    const Double_t phiJetGen = (genJet ? gJet4vec.Phi() : -1.e7);
    this->FillHistsPurStab(phiJet, phiJetGen, fDsJetPurStabHistsJetPhi);
    if(s83) this->FillHistsPurStab(phiJet, phiJetGen, fDsJetPurStabHistsJetPhiS83, weight83);  
    // PtDsJet after cut on pt: PtDsJet within visible pt-range
    const Double_t ptJetDs    = (jet    ? (jet4vec  + ds4vec).Pt() : -1.e7);
    const Double_t ptJetDsGen = (genJet ? (gJet4vec + gDs4vec).Pt(): -1.e7);
    this->FillHistsPurStab(ptJetDs, ptJetDsGen, fDsJetPurStabHistsDsJetPt, 1.);
    if(s83) this->FillHistsPurStab(ptJetDs, ptJetDsGen, fDsJetPurStabHistsDsJetPtS83, weight83);
    // Pt2DsJet 
    if(s83) { // only for S83
      const Double_t pt2JetDs    = (jet    ? ptJetDs * ptJetDs : -1.e7);
      const Double_t pt2JetDsGen = (genJet ? ptJetDsGen * ptJetDsGen : -1.e7);
      this->FillHistsPurStab(pt2JetDs, pt2JetDsGen,fDsJetPurStabHistsDsJetPt2S83,weight83);
    }
    // PtDsJetOrth after cut on pt: within visible pt-range
    Double_t ptJetDsOrth    = -1.e7;
    Double_t ptJetDsOrthGen = -1.e7;
    if(jet){
      const TVector2 jetXYvect = jet4vec.Vect().XYvector();
      const TVector2 dsJetXYvect = jetXYvect + ds4vec.Vect().XYvector();
      ptJetDsOrth = dsJetXYvect.Norm(jetXYvect).Mod2();
    }
    if(genJet){
      const TVector2 jetXYvectGen = gJet4vec.Vect().XYvector();
      const TVector2 dsJetXYvectGen = jetXYvectGen + gDs4vec.Vect().XYvector();
      ptJetDsOrthGen = dsJetXYvectGen.Norm(jetXYvectGen).Mod2();
    }
    this->FillHistsPurStab(ptJetDsOrth, ptJetDsOrthGen, fDsJetPurStabHistsPtDsJetOrth, 1.);
    if(s83) this->FillHistsPurStab(ptJetDsOrth, ptJetDsOrthGen,
				   fDsJetPurStabHistsPtDsJetOrthS83, weight83);
    // MDsJet after cut on pt: MDsJet within visible pt-range
    const Double_t mJetDs    = (jet    ? (jet4vec + ds4vec).M()   : -1.e7);
    const Double_t mJetDsGen = (genJet ? (gJet4vec + gDs4vec).M() : -1.e7);
    this->FillHistsPurStab(mJetDs, mJetDsGen, fDsJetPurStabHistsDsJetM);
    if(s83) this->FillHistsPurStab(mJetDs, mJetDsGen, fDsJetPurStabHistsDsJetMS83, weight83);

    if(all){ // only if requested (load particle candidates!)
      // DaughJet
      const Int_t nDaugh    = (jet    ? jet->GetNumOfParticles()    : -1);
      const Int_t nDaughGen = (genJet ? genJet->GetNumOfParticles() : -1);
      this->FillHistsPurStab(nDaugh, nDaughGen, fDsJetPurStabHistsJetDaugh);
      if(s83) this->FillHistsPurStab(nDaugh, nDaughGen, fDsJetPurStabHistsJetDaughS83,weight83);
      // ChFrac
      Double_t chFrac = -1., chFracGen = -1.;
      if(jet){
	Double_t sumPtCh = 0.;
	for(Int_t i = 0; i < nDaugh; ++i){
	  if(jet->GetParticle(i)->GetCharge()) sumPtCh += jet->GetParticle(i)->GetPt();
	}
	chFrac = sumPtCh/jet->GetPt();
	if(TMath::Abs(1.-chFrac) < 1.e-9) chFrac = 1.-1.e-9; // catch 1. to be outside overflow
      }
      if(genJet){
	Double_t sumPtCh = 0.;
	for(Int_t i = 0; i < nDaughGen; ++i){
	  if(genJet->GetParticle(i)->GetCharge()) sumPtCh += genJet->GetParticle(i)->GetPt();
	}
	chFracGen = sumPtCh/gJet4vec.Pt();
	if(TMath::Abs(1.-chFracGen) < 1.e-9)chFracGen=1.-1.e-9;//catch 1. to be outside overflow
      }
      this->FillHistsPurStab(chFrac, chFracGen, fDsJetPurStabHistsChFrac);
      if(s83) this->FillHistsPurStab(chFrac, chFracGen, fDsJetPurStabHistsChFracS83, weight83);
    }
  }

  //
  // now find jets/fill hists for things that depend on the pt-cut:
  //
  const Double_t oldMinPt = fSteer->GetDstar1JetPtBins()->At(0);
  const_cast<TArrayD*>(fSteer->GetDstar1JetPtBins())->AddAt(0., 0); //for purity/stab. no cut
  // find generated non dstar jet
  this->GetNonDstarGenJets(genDs, genJets);
  if(genJets.GetEntriesFast()){
    genJet = static_cast<H1PartJet*>(genJets[this->GetHighestPt(genJets)]);
  }
  // find non dstar jet
  this->GetNonDstarJets(ds, jets);
  if(jets.GetEntriesFast()){
    jet = static_cast<H1PartJet*>(jets[this->GetHighestPt(jets)]);
  }
  const_cast<TArrayD*>(fSteer->GetDstar1JetPtBins())->AddAt(oldMinPt, 0);

  if(jet || genJet){
    const TLorentzVector jet4vec = (jet ? jet->GetFourVector() : TLorentzVector(0,0,0,0));
    const TLorentzVector gJet4vec = (genJet ? genJet->GetFourVector():TLorentzVector(0,0,0,0));
    Bool_t fill[6] = {1,1,1,1,1,1}; // flag whether hists should be filled or not
    if(!jet || !genJet || jet->GetMomentum().DeltaR(genJet->GetMomentum()) > 1. 
       || jet->GetPt() < oldMinPt){
      // don't fill pt-resolution if one is not measured or delta R > 1 or pt^rec < pt-cut
      fill[4] = fill[5] = kFALSE;
    }
    // PtJet
    const Double_t ptJet    = (jet    ? jet4vec.Pt()  : -1.e7);
    const Double_t ptJetGen = (genJet ? gJet4vec.Pt() : -1.e7);
    this->FillHistsPurStab(ptJet, ptJetGen, fDsJetPurStabHistsJetPt, 1., fill);
    if(s83) this->FillHistsPurStab(ptJet, ptJetGen, fDsJetPurStabHistsJetPtS83, weight83, fill);
    // PtJet in bins of EtaJet and PtJet
    if(jet){
      const Double_t jetEta = jet4vec.Eta();
      for(Int_t iBin = 0; iBin < fSteer->GetDstar1JetEtaBins()->GetSize() - 1; ++iBin){
	if(fSteer->GetDstar1JetEtaBins()->At(iBin) <= jetEta  
	   && jetEta < fSteer->GetDstar1JetEtaBins()->At(iBin+1)){
	  GFHistArray* purStabPtInEta = static_cast<GFHistArray*>
	    (fDsJetPurStabPtInEtaHistArrays->At(iBin));
	  this->FillHistsPurStab(ptJet, ptJetGen, purStabPtInEta, 1., fill);
	  if(s83){
	    GFHistArray* purStabPtInEtaS83 = static_cast<GFHistArray*>
	      (fDsJetPurStabPtInEtaHistArraysS83->At(iBin));
	    this->FillHistsPurStab(ptJet, ptJetGen, purStabPtInEtaS83, weight83, fill);
	  }
	}
      }
      for(Int_t iBin = 0; iBin < fSteer->GetDstar1JetPtBins()->GetSize() - 1; ++iBin){
	if(fSteer->GetDstar1JetPtBins()->At(iBin) <= ptJet
	   && ptJet < fSteer->GetDstar1JetPtBins()->At(iBin+1)){
	  GFHistArray* purStabPtInPt = static_cast<GFHistArray*>
	    (fDsJetPurStabPtInPtHistArrays->At(iBin));
	  this->FillHistsPurStab(ptJet, ptJetGen, purStabPtInPt, 1., fill);
	  if(s83){
	    GFHistArray* purStabPtInPtS83 = static_cast<GFHistArray*>
	      (fDsJetPurStabPtInPtHistArraysS83->At(iBin));
	    this->FillHistsPurStab(ptJet, ptJetGen, purStabPtInPtS83, weight83, fill);
	  }
	}
      }
    }
  }

  //
  // now find jets/fill hists for things that depend on the eta-cut:
  //
  TArrayD* etaBins = const_cast<TArrayD*>(fSteer->GetDstar1JetEtaBins());
  const Double_t oldMinEta = etaBins->At(0);
  etaBins->AddAt(-DBL_MAX, 0); //for purity/stab. no cut
  const Double_t oldMaxEta = etaBins->At(etaBins->GetSize()-1);
  etaBins->AddAt(DBL_MAX, etaBins->GetSize()-1); //for purity/stab. no cut
  // find generated non dstar jet
  this->GetNonDstarGenJets(genDs, genJets);
  if(genJets.GetEntriesFast()){
    genJet = static_cast<H1PartJet*>(genJets[this->GetHighestPt(genJets)]);
  } else {
    genJet = NULL;
  }
  // find non dstar jet
  this->GetNonDstarJets(ds, jets);
  if(jets.GetEntriesFast()){
    jet = static_cast<H1PartJet*>(jets[this->GetHighestPt(jets)]);
  } else {
    jet = NULL;
  }
  etaBins->AddAt(oldMinEta, 0);
  etaBins->AddAt(oldMaxEta, etaBins->GetSize()-1);

  if(jet || genJet){
    const TLorentzVector jet4vec = (jet ? jet->GetFourVector() : TLorentzVector(0,0,0,0));
    const TLorentzVector gJet4vec = (genJet ? genJet->GetFourVector():TLorentzVector(0,0,0,0));
    // EtaJet
    const Double_t etaJet    = (jet    ? jet4vec.Eta()    : -1.e7);
    const Double_t etaJetGen = (genJet ? gJet4vec.Eta()   : -1.e7);
    Bool_t fill[6] = {1,1,1,1,1,1}; // flag whether hists should be filled or not
    if(!jet || !genJet || etaJet < oldMinEta || etaJet > oldMaxEta
       || etaJetGen < oldMinEta-1. || etaJetGen > oldMaxEta+1.
       || TMath::Abs(jet->GetMomentum().DeltaPhi(genJet->GetMomentum()) > 1.)){
      // don't fill pt-resolution if one is not measured or eta^rec outside region 
      // or not close enough in phi:
      fill[4] = fill[5] = kFALSE;
    }

    this->FillHistsPurStab(etaJet, etaJetGen, fDsJetPurStabHistsJetEta, 1., fill);
    if(s83) this->FillHistsPurStab(etaJet, etaJetGen,fDsJetPurStabHistsJetEtaS83,weight83,fill);
    // EtaJet in bin of PtJet
    const Double_t jetPt = (jet ? jet4vec.Pt() : -1.e7);
    for(Int_t iBin = 0; iBin < fSteer->GetDstar1JetPtBins()->GetSize() - 1; ++iBin){
      if(fSteer->GetDstar1JetPtBins()->At(iBin) <= jetPt  
 	 && jetPt < fSteer->GetDstar1JetPtBins()->At(iBin+1)){
	GFHistArray* purStabEtaInPt = static_cast<GFHistArray*>
	  (fDsJetPurStabEtaInPtHistArrays->At(iBin));
	this->FillHistsPurStab(etaJet, etaJetGen, purStabEtaInPt, 1., fill);
	if(s83){
	  GFHistArray* purStabEtaInPtS83 = static_cast<GFHistArray*>
	    (fDsJetPurStabEtaInPtHistArraysS83->At(iBin));
	  this->FillHistsPurStab(etaJet, etaJetGen, purStabEtaInPtS83, weight83, fill);
	}
      }
    }
  }
}

//_____________________________________________________
 void GFDstarAnalyseMc::CreateHistsDsDiJetPurStab()
{
  TDirectory* oldDir = this->OpenHistsFile();
  TDirectory* dir = new TDirectory("dsDiJetPurStab", "pur./stab. hists for D* with dijet");
  dir->cd();

  const Int_t nBinsVs = 60;
  const Float_t maxDevRes = 1.;
  const Int_t nBinsRes = 60;

  // overall
  GFHistManip::ClearCreateArray(fDsDiJetPurStabHistsS83);
  fAllHistArrays.Add(fDsDiJetPurStabHistsS83);
  fDsDiJetPurStabHistsS83->AddAt(new TH1F("AllRecS83", "D* dijet (rec)", 1, 0., 1.), 0);
  fDsDiJetPurStabHistsS83->AddAt(new TH1F("AllRecGenS83", "D* dijet (rec && gen)",1, 0.,1.), 1);
  fDsDiJetPurStabHistsS83->AddAt(new TH1F("AllNRecGenS83","D* dijet (!rec && gen)",1, 0.,1.),2);
  // no 3/4/5
  GFHistManip::CallSumw2(fDsDiJetPurStabHistsS83);

  // DphiDijet 
  GFHistManip::ClearCreateArray(fDsDiJetPurStabHistsDphiS83);
  fAllHistArrays.Add(fDsDiJetPurStabHistsDphiS83);
  const TArrayD* ar = fSteer->GetDstar1JetDphiBins();
  TArrayD special(ar->GetSize() +1);
  special[0] = -20.;
  for (Int_t i = 0; i < ar->GetSize(); ++i) special[i+1] = ar->At(i);
  fDsDiJetPurStabHistsDphiS83->AddAt
    (new TH1F("DphiDijetRecS83","#Delta(#phi) jet-jet (rec)",ar->GetSize()-1,ar->GetArray()),0);
  fDsDiJetPurStabHistsDphiS83->AddAt
    (new TH1F("DphiDijetRecGenS83", "#Delta(#phi) jet-jet (rec && gen)", 
	      ar->GetSize()-1, ar->GetArray()), 1);
  fDsDiJetPurStabHistsDphiS83->AddAt
    (new TH1F("DphiDijetNRecGenS83", "#Delta(#phi) jet-jet (!rec && gen)", 
	      ar->GetSize()-1, ar->GetArray()), 2);
  fDsDiJetPurStabHistsDphiS83->AddAt
    (new TH2F("DphiDijetRecVsGenS83", "#Delta(#phi) jet-jet (rec vs gen)",
// 	      nBinsVs/2+1, -6., ar->At(ar->GetSize() -1),
// 	      nBinsVs/2+1, -6., ar->At(ar->GetSize() -1)), 3);
	      special.GetSize()-1, special.GetArray(),
	      special.GetSize()-1, special.GetArray()), 3);
  // no 4
  fDsDiJetPurStabHistsDphiS83->AddAt
    (new TH1F("DphiDijetJetResS83", "#Delta(#phi) (jet-jet)(rec - gen)", 
	      nBinsRes, -30.*maxDevRes, 30.*maxDevRes), 5);
  GFHistManip::CallSumw2(fDsDiJetPurStabHistsDphiS83);

  // DetaDijet
  GFHistManip::ClearCreateArray(fDsDiJetPurStabHistsDetaS83);
  fAllHistArrays.Add(fDsDiJetPurStabHistsDetaS83);
  ar = fSteer->GetDstar1JetDetaBins();
  fDsDiJetPurStabHistsDetaS83->AddAt
    (new TH1F("DetaDijetRecS83","#eta(D*) - #eta(jet) (rec)",ar->GetSize()-1,ar->GetArray()),0);
  fDsDiJetPurStabHistsDetaS83->AddAt
    (new TH1F("DetaDijetRecGenS83", "#eta(D*) - #eta(jet) (rec && gen)",
	      ar->GetSize()-1, ar->GetArray()), 1);
  fDsDiJetPurStabHistsDetaS83->AddAt
    (new TH1F("DetaDijetNRecGenS83", "#eta(D*) - #eta(jet) (!rec && gen)",
	      ar->GetSize()-1, ar->GetArray()), 2);
  fDsDiJetPurStabHistsDetaS83->AddAt
    (new TH2F("DetaDijetRecVsGenS83", "#eta(D*) - #eta(jet) (rec vs gen)",
	      nBinsVs, ar->At(0), ar->At(ar->GetSize() -1),
	      nBinsVs, ar->At(0), ar->At(ar->GetSize() -1)), 3);
  // no 4
  fDsDiJetPurStabHistsDetaS83->AddAt
    (new TH1F("DetaDijetJetResS83", "#eta(D*) - #eta(jet) (rec - gen)", 
	      nBinsRes, -0.4*maxDevRes, 0.4*maxDevRes), 5);
  GFHistManip::CallSumw2(fDsDiJetPurStabHistsDetaS83);

  // xGamDijet
  GFHistManip::ClearCreateArray(fDsDiJetPurStabHistsXgamS83);
  fAllHistArrays.Add(fDsDiJetPurStabHistsXgamS83);
  ar = fSteer->GetXgammaDijetBins();
  fDsDiJetPurStabHistsXgamS83->AddAt
    (new TH1F("xGamDijetRecS83", "x_{#gamma}(D* dijet) (rec)", 
	      ar->GetSize()-1, ar->GetArray()), 0);
  fDsDiJetPurStabHistsXgamS83->AddAt
    (new TH1F("xGamDijetRecGenS83", "x_{#gamma}(D* dijet) (rec && gen)", 
	      ar->GetSize()-1, ar->GetArray()), 1);
  fDsDiJetPurStabHistsXgamS83->AddAt
    (new TH1F("xGamDijetNRecGenS83", "x_{#gamma}(D* dijet) (!rec && gen)", 
	      ar->GetSize()-1, ar->GetArray()), 2);
  fDsDiJetPurStabHistsXgamS83->AddAt
    (new TH2F("xGamDijetRecVsGenS83", "x_{#gamma}(D* dijet) (rec vs gen)",
	      nBinsVs-9, -0.02, ar->At(ar->GetSize() -1),
	      nBinsVs-9, -0.02, ar->At(ar->GetSize() -1)), 3);
  // no 4/5
  GFHistManip::CallSumw2(fDsDiJetPurStabHistsXgamS83);

  // PtDJet
  GFHistManip::ClearCreateArray(fDsDiJetPurStabHistsDJetPtS83);
  fAllHistArrays.Add(fDsDiJetPurStabHistsDJetPtS83);
  ar = fSteer->GetDstar1JetPtBins();
  fDsDiJetPurStabHistsDJetPtS83->AddAt(new TH1F("PtDJetRecS83", "p_{t}(D*-j) dijet (rec)", 
					 ar->GetSize()-1, ar->GetArray()), 0);
  fDsDiJetPurStabHistsDJetPtS83->AddAt
    (new TH1F("PtDJetRecGenS83", "p_{t}(D*-j) dijet (rec && gen)", 
	      ar->GetSize()-1, ar->GetArray()), 1);
  fDsDiJetPurStabHistsDJetPtS83->AddAt
    (new TH1F("PtDJetNRecGenS83", "p_{t}(D*-j) dijet (!rec && gen)", 
	      ar->GetSize()-1, ar->GetArray()), 2);
  fDsDiJetPurStabHistsDJetPtS83->AddAt
    (new TH2F("PtDJetRecVsGenS83", "p_{t}(D*-j) dijet (rec vs gen)", 
	      nBinsVs, ar->At(0), ar->At(ar->GetSize() -1),
	      nBinsVs, ar->At(0), ar->At(ar->GetSize() -1)), 3);
  fDsDiJetPurStabHistsDJetPtS83->AddAt
    (new TH1F("PtDJetResRelS83", "p_{t}(D*-j) dijet (rec-gen)/gen",
	      nBinsRes, -maxDevRes, maxDevRes), 4);
  fDsDiJetPurStabHistsDJetPtS83->AddAt(new TH1F("PtDJetResS83", "p_{t}(D*-j) dijet (rec-gen)",
						nBinsRes, -3.*maxDevRes, 3.*maxDevRes), 5);
  GFHistManip::CallSumw2(fDsDiJetPurStabHistsDJetPtS83);

  // PtOthJet
  GFHistManip::ClearCreateArray(fDsDiJetPurStabHistsOthJetPtS83);
  fAllHistArrays.Add(fDsDiJetPurStabHistsOthJetPtS83);
  ar = fSteer->GetDstar1JetPtBins();
  fDsDiJetPurStabHistsOthJetPtS83->AddAt(new TH1F("PtOthJetRecS83", "p_{t}(D*-j) dijet (rec)", 
					 ar->GetSize()-1, ar->GetArray()), 0);
  fDsDiJetPurStabHistsOthJetPtS83->AddAt
    (new TH1F("PtOthJetRecGenS83", "p_{t}(oth. j) dijet (rec && gen)", 
	      ar->GetSize()-1, ar->GetArray()), 1);
  fDsDiJetPurStabHistsOthJetPtS83->AddAt
    (new TH1F("PtOthJetNRecGenS83", "p_{t}(oth. j) dijet (!rec && gen)", 
	      ar->GetSize()-1, ar->GetArray()), 2);
  fDsDiJetPurStabHistsOthJetPtS83->AddAt
    (new TH2F("PtOthJetRecVsGenS83", "p_{t}(oth. j) dijet (rec vs gen)", 
	      nBinsVs, ar->At(0), ar->At(ar->GetSize() -1),
	      nBinsVs, ar->At(0), ar->At(ar->GetSize() -1)), 3);
  fDsDiJetPurStabHistsOthJetPtS83->AddAt
    (new TH1F("PtOthJetResRelS83", "p_{t}(oth. j) dijet (rec-gen)/gen",
	      nBinsRes, -maxDevRes, maxDevRes), 4);
  fDsDiJetPurStabHistsOthJetPtS83->AddAt
    (new TH1F("PtOthJetResS83", "p_{t}(oth. j) dijet (rec-gen)",
	      nBinsRes, -3.*maxDevRes, 3.*maxDevRes), 5);
  GFHistManip::CallSumw2(fDsDiJetPurStabHistsOthJetPtS83);

  // EtaDJet
  GFHistManip::ClearCreateArray(fDsDiJetPurStabHistsDJetEtaS83);
  fAllHistArrays.Add(fDsDiJetPurStabHistsDJetEtaS83);
  ar = fSteer->GetDstar1JetEtaBins();
  fDsDiJetPurStabHistsDJetEtaS83->AddAt(new TH1F("EtaDJetRecS83", "#eta(D*-j) dijet (rec)", 
					   ar->GetSize()-1, ar->GetArray()), 0);
  fDsDiJetPurStabHistsDJetEtaS83->AddAt
    (new TH1F("EtaDJetRecGenS83", "#eta(D*-j) dijet (rec && gen)", 
	      ar->GetSize()-1, ar->GetArray()), 1);
  fDsDiJetPurStabHistsDJetEtaS83->AddAt
    (new TH1F("EtaDJetNRecGenS83", "#eta(D*-j) dijet (!rec && gen)", 
	      ar->GetSize()-1, ar->GetArray()), 2);
  fDsDiJetPurStabHistsDJetEtaS83->AddAt
    (new TH2F("EtaDJetRecVsGenS83", "#eta(D*-j) dijet (rec vs gen)", 
	      nBinsVs, ar->At(0), ar->At(ar->GetSize() -1),
	      nBinsVs, ar->At(0), ar->At(ar->GetSize() -1)), 3);
  // no 4
  fDsDiJetPurStabHistsDJetEtaS83->AddAt
    (new TH1F("EtaDJetResS83", "#eta(D*-j) dijet (rec - gen)", 
	      (5*nBinsRes)/6, -0.5*maxDevRes, 0.5*maxDevRes), 5);
  GFHistManip::CallSumw2(fDsDiJetPurStabHistsDJetEtaS83);

  // EtaOthJet
  GFHistManip::ClearCreateArray(fDsDiJetPurStabHistsOthJetEtaS83);
  fAllHistArrays.Add(fDsDiJetPurStabHistsOthJetEtaS83);
  ar = fSteer->GetDstar1JetEtaBins();
  fDsDiJetPurStabHistsOthJetEtaS83->AddAt
    (new TH1F("EtaOthJetRecS83","#eta(oth. j) dijet (rec)",ar->GetSize()-1,ar->GetArray()),0);
  fDsDiJetPurStabHistsOthJetEtaS83->AddAt
    (new TH1F("EtaOthJetRecGenS83", "#eta(oth. j) dijet (rec && gen)", 
	      ar->GetSize()-1, ar->GetArray()), 1);
  fDsDiJetPurStabHistsOthJetEtaS83->AddAt
    (new TH1F("EtaOthJetNRecGenS83", "#eta(oth. j) dijet (!rec && gen)", 
	      ar->GetSize()-1, ar->GetArray()), 2);
  fDsDiJetPurStabHistsOthJetEtaS83->AddAt
    (new TH2F("EtaOthJetRecVsGenS83", "#eta(oth. j) dijet (rec vs gen)", 
	      nBinsVs, ar->At(0), ar->At(ar->GetSize() -1),
	      nBinsVs, ar->At(0), ar->At(ar->GetSize() -1)), 3);
  // no 4
  fDsDiJetPurStabHistsOthJetEtaS83->AddAt
    (new TH1F("EtaOthJetResS83", "#eta(oth. j) dijet (rec - gen)", 
	      (5*nBinsRes)/6, -0.5*maxDevRes, 0.5*maxDevRes), 5);
  GFHistManip::CallSumw2(fDsDiJetPurStabHistsOthJetEtaS83);


  //  PtDijet
  GFHistManip::ClearCreateArray(fDsDiJetPurStabHistsDijetPtS83);
  fAllHistArrays.Add(fDsDiJetPurStabHistsDijetPtS83);
  ar = fSteer->GetDstar1JetDsJetPtBins();
  fDsDiJetPurStabHistsDijetPtS83->AddAt(new TH1F("PtDijetRecS83", "p_{t}(j+j) dijet (rec)", 
					    ar->GetSize()-1, ar->GetArray()),0);
  fDsDiJetPurStabHistsDijetPtS83->AddAt(new TH1F("PtDijetRecGenS83", "p_{t}(j+j) dijet (rec && gen)", 
					    ar->GetSize()-1, ar->GetArray()),1);
  fDsDiJetPurStabHistsDijetPtS83->AddAt(new TH1F("PtDijetNRecGenS83","p_{t}(j+j) dijet (!rec && gen)",
					    ar->GetSize()-1, ar->GetArray()),2);
  fDsDiJetPurStabHistsDijetPtS83->AddAt(new TH2F("PtDijetRecVsGenS83","p_{t}(j+j) dijet (rec vs gen)",
					    nBinsVs, ar->At(0), ar->At(ar->GetSize() -1),
					    nBinsVs, ar->At(0),  ar->At(ar->GetSize() -1)), 3);
  fDsDiJetPurStabHistsDijetPtS83->AddAt(new TH1F("PtDijetResRelS83", "p_{t}(j+j) dijet (rec-gen)/gen",
					    nBinsRes, -maxDevRes, maxDevRes), 4);
  // no 5
  GFHistManip::CallSumw2(fDsDiJetPurStabHistsDijetPtS83);


  //  Pt2Dijet
  GFHistManip::ClearCreateArray(fDsDiJetPurStabHistsDijetPt2S83);
  fAllHistArrays.Add(fDsDiJetPurStabHistsDijetPt2S83);
  ar = fSteer->GetDstar1JetDsJetPt2Bins();
  fDsDiJetPurStabHistsDijetPt2S83->AddAt(new TH1F("Pt2DijetRecS83", "p_{t}^{2}(j+j) dijet (rec)", 
					    ar->GetSize()-1, ar->GetArray()),0);
  fDsDiJetPurStabHistsDijetPt2S83->AddAt(new TH1F("Pt2DijetRecGenS83", "p_{t}^{2}(j+j) dijet (rec && gen)", 
					    ar->GetSize()-1, ar->GetArray()),1);
  fDsDiJetPurStabHistsDijetPt2S83->AddAt(new TH1F("Pt2DijetNRecGenS83","p_{t}^{2}(j+j) dijet (!rec && gen)",
					    ar->GetSize()-1, ar->GetArray()),2);
  fDsDiJetPurStabHistsDijetPt2S83->AddAt(new TH2F("Pt2DijetRecVsGenS83","p_{t}^{2}(j+j) dijet (rec vs gen)",
					    nBinsVs, ar->At(0), ar->At(ar->GetSize() -1),
					    nBinsVs, ar->At(0),  ar->At(ar->GetSize() -1)), 3);
  fDsDiJetPurStabHistsDijetPt2S83->AddAt(new TH1F("Pt2DijetResRelS83", "p_{t}^{2}(j+j) dijet (rec-gen)/gen",
					    nBinsRes, -maxDevRes, maxDevRes), 4);
  // no 5
  GFHistManip::CallSumw2(fDsDiJetPurStabHistsDijetPt2S83);

  //  CosThDijet
  GFHistManip::ClearCreateArray(fDsDiJetPurStabHistsCosThS83);
  fAllHistArrays.Add(fDsDiJetPurStabHistsCosThS83);
  ar = fSteer->GetDstar1JetDsJetCosThBins();
  fDsDiJetPurStabHistsCosThS83->AddAt
    (new TH1F("CosThDijetRecS83", "cos(#theta*) dijet (rec)",ar->GetSize()-1,ar->GetArray()),0);
  fDsDiJetPurStabHistsCosThS83->AddAt
    (new TH1F("CosThDijetRecGenS83", "cos(#theta*) dijet (rec && gen)", 
	      ar->GetSize()-1, ar->GetArray()),1);
  fDsDiJetPurStabHistsCosThS83->AddAt
    (new TH1F("CosThDijetNRecGenS83","cos(#theta*) dijet (!rec && gen)",
	      ar->GetSize()-1, ar->GetArray()),2);
  fDsDiJetPurStabHistsCosThS83->AddAt
    (new TH2F("CosThDijetRecVsGenS83","cos(#theta*) dijet (rec vs gen)",
	      nBinsVs, ar->At(0), ar->At(ar->GetSize() -1),
	      nBinsVs, ar->At(0),  ar->At(ar->GetSize() -1)), 3);
  // no 4/5
  GFHistManip::CallSumw2(fDsDiJetPurStabHistsCosThS83);

  oldDir->cd();
}

//_____________________________________________________
 void GFDstarAnalyseMc::FillHistsDsDiJetPurStab(const H1PartDstar* ds)
{
  // assume loose cut on ds, tighten to higher pt cut, use only signal region
  // S83 only!  

  if(!ds || !this->IsS83(ds) || !this->IsSignalRegionDm(ds)) return;
  
  // get generator D* of same charge and 'OK'
  const H1PartMC* genDs = this->GetCloseGenDsKpipi(ds, "C83");
  if(!genDs) return;

  // get generator jets
  const H1PartJet *dsGenJet = NULL;
  const H1PartJet *oGenJet = NULL;
  //const Bool_t realDsGenJet = 
  this->GetGenDiJets(genDs, dsGenJet, oGenJet);
  if(!dsGenJet || !oGenJet) {
    dsGenJet = oGenJet = NULL;// need both jets...
  }

  // get detector jets
  const H1PartJet *dsJet = NULL;
  const H1PartJet *oJet = NULL;
  //const Bool_t realDsJet = 
  this->GetDiJets(ds, dsJet, oJet);
  if(!dsJet || !oJet) {
    dsJet = oJet = NULL;// need both jets...
  }

  if(!dsJet && !dsGenJet) return; // gen or rec needs two jets!

  if(!fDsDiJetPurStabHistsDphiS83) this->CreateHistsDsDiJetPurStab();
  const Double_t weight83 = this->GetWeight(83, ds);

  const TLorentzVector p4Ds  = ds ? ds->GetFourVector() : TLorentzVector(0,0,0,0);
  const TLorentzVector p4DsGen = genDs ? genDs->GetFourVector() : TLorentzVector(0,0,0,0);

  const TLorentzVector p4DsJet  = dsJet ? dsJet->GetFourVector() : TLorentzVector();
  const TLorentzVector p4DsJetGen = dsGenJet ? dsGenJet->GetFourVector() : TLorentzVector();

  const TLorentzVector p4OthJet  = oJet ? oJet->GetFourVector() : TLorentzVector();
  const TLorentzVector p4OthJetGen = oGenJet ? oGenJet->GetFourVector() : TLorentzVector();

  // overall
  this->FillHistsPurStab((dsJet ? .5 : -.5), (dsGenJet ? .5 : -.5), fDsDiJetPurStabHistsS83,
			 weight83);
  // DphiDijet
  const Double_t dPhi =(dsJet ? TMath::Abs(p4DsJet.DeltaPhi(p4OthJet))*TMath::RadToDeg():-.1);
  const Double_t dPhiGen = (dsGenJet ? 
			    TMath::Abs(p4DsJetGen.DeltaPhi(p4OthJetGen))*TMath::RadToDeg():-.1);
  this->FillHistsPurStab(dPhi, dPhiGen, fDsDiJetPurStabHistsDphiS83, weight83);
  // DetaDijet
  const Double_t dEta =(dsJet ? p4DsJet.Eta() - p4OthJet.Eta() : -1.e7);
  const Double_t dEtaGen =(dsGenJet ? p4DsJetGen.Eta() - p4OthJetGen.Eta() : -1.e7);
  this->FillHistsPurStab(dEta, dEtaGen, fDsDiJetPurStabHistsDetaS83, weight83);
  // CosThDijet
  const Double_t cosTheta    = (dsJet    ? TMath::TanH(dEta/2.)   : -2.);
  const Double_t cosThetaGen = (dsGenJet ? TMath::TanH(dEtaGen/2.): -2.);
  this->FillHistsPurStab(cosTheta, cosThetaGen, fDsDiJetPurStabHistsCosThS83, weight83);
  // xGamDijet
  const Double_t xGam   =(dsJet    ? this->GetXgammaMassDiJetHelp(ds,   dsJet,   oJet   ):-.001);
  const Double_t xGamGen=(dsGenJet ? this->GetXgammaMassDiJetHelp(genDs,dsGenJet,oGenJet):-.001);
  this->FillHistsPurStab(xGam, xGamGen, fDsDiJetPurStabHistsXgamS83, weight83);
  // PtDijet
  const Double_t ptJetJet    = (dsJet    ? (p4DsJet    + p4OthJet   ).Pt() : -1.e7);
  const Double_t ptJetJetGen = (dsGenJet ? (p4DsJetGen + p4OthJetGen).Pt() : -1.e7);
  this->FillHistsPurStab(ptJetJet, ptJetJetGen, fDsDiJetPurStabHistsDijetPtS83, weight83);
  // Pt2Dijet
  const Double_t pt2JetJet    = (dsJet    ? ptJetJet    * ptJetJet    : -1.e7);
  const Double_t pt2JetJetGen = (dsGenJet ? ptJetJetGen * ptJetJetGen : -1.e7);
  this->FillHistsPurStab(pt2JetJet, pt2JetJetGen, fDsDiJetPurStabHistsDijetPt2S83, weight83);
  // PtDJet
  const Double_t ptDJet    = (dsJet    ? p4DsJet.Pt()    : -1.e7);
  const Double_t ptDJetGen = (dsGenJet ? p4DsJetGen.Pt() : -1.e7);
  this->FillHistsPurStab(ptDJet, ptDJetGen, fDsDiJetPurStabHistsDJetPtS83, weight83);
  // PtOthJet
  const Double_t ptOthJet    = (oJet    ? p4OthJet.Pt()    : -1.e7);
  const Double_t ptOthJetGen = (oGenJet ? p4OthJetGen.Pt() : -1.e7);
  this->FillHistsPurStab(ptOthJet, ptOthJetGen, fDsDiJetPurStabHistsOthJetPtS83, weight83);
  // EtaDJet
  const Double_t etaDJet    = (dsJet    ? p4DsJet.Eta()    : -1.e7);
  const Double_t etaDJetGen = (dsGenJet ? p4DsJetGen.Eta() : -1.e7);
  this->FillHistsPurStab(etaDJet, etaDJetGen, fDsDiJetPurStabHistsDJetEtaS83, weight83);
  // EtaOthJet
  const Double_t etaOthJet    = (oJet    ? p4OthJet.Eta()    : -1.e7);
  const Double_t etaOthJetGen = (oGenJet ? p4OthJetGen.Eta() : -1.e7);
  this->FillHistsPurStab(etaOthJet, etaOthJetGen, fDsDiJetPurStabHistsOthJetEtaS83, weight83);
  
}

//_____________________________________________________
 void GFDstarAnalyseMc::CreateHistsDstarJetsGen()
{
  TDirectory* oldDir = this->OpenHistsFile();
  TDirectory* dir = new TDirectory("genJet", "generator level hists for D* + jet");
  dir->cd();

  // ------------ no order in eta
  // s83
  fDstar1JetHistsGS83     = this->CreateHistsDstar1Jet(0, 1); // 1D hists
  GFHistManip::CreateAnalogHists(fDstar1JetHistsGS83, fDstar1JetHistsGAS83, 
				 "GenAccS83", " gen, acc. weighted");
  GFHistManip::CreateAnalogHists(fDstar1JetHistsGS83, fDstar1JetHistsGWS83, 
				 "GenWeightS83", " gen, weighted");
  GFHistManip::CreateAnalogHists(fDstar1JetHistsGS83, fDstar1JetHistsGNAWS83, 
				 "GenNoAccWeightS83", " gen, no acc. weighted");

  // s84
  GFHistManip::CreateAnalogHists(fDstar1JetHistsGS83, fDstar1JetHistsGS84, 
				 "Gen", " gen");
  GFHistManip::CreateAnalogHists(fDstar1JetHistsGS84, fDstar1JetHistsGAS84, 
				 "AccS84", ", acc. weighted");
  GFHistManip::CreateAnalogHists(fDstar1JetHistsGS84, fDstar1JetHistsGWS84, 
				 "WeightS84", ", weighted");
  GFHistManip::CreateAnalogHists(fDstar1JetHistsGS84, fDstar1JetHistsGNAWS84, 
				 "NoAccWeightS84", ", no acc. weighted");
  // add sth.
  GFHistManip::AddToHistsName("GenS83", fDstar1JetHistsGS83, " gen");
  GFHistManip::AddToHistsName("S84", fDstar1JetHistsGS84);


  // ------------ backward D*
  // s83
  fDstarBack1JetHistsGS83     = this->CreateHistsDstar1Jet(-1, 1); // 1D hists
  GFHistManip::CreateAnalogHists(fDstarBack1JetHistsGS83, fDstarBack1JetHistsGAS83, 
				 "GenAccS83", " gen, acc. weighted");
  GFHistManip::CreateAnalogHists(fDstarBack1JetHistsGS83, fDstarBack1JetHistsGWS83, 
				 "GenWeightS83", " gen, weighted");
  GFHistManip::CreateAnalogHists(fDstarBack1JetHistsGS83, fDstarBack1JetHistsGNAWS83, 
				 "GenNoAccWeightS83", " gen, no acc. weighted");

  // s84
  GFHistManip::CreateAnalogHists(fDstarBack1JetHistsGS83, fDstarBack1JetHistsGS84, 
				 "Gen", " gen");
  GFHistManip::CreateAnalogHists(fDstarBack1JetHistsGS84, fDstarBack1JetHistsGAS84, 
				 "AccS84", ", acc. weighted");
  GFHistManip::CreateAnalogHists(fDstarBack1JetHistsGS84, fDstarBack1JetHistsGWS84, 
				 "WeightS84", ", weighted");
  GFHistManip::CreateAnalogHists(fDstarBack1JetHistsGS84, fDstarBack1JetHistsGNAWS84, 
				 "NoAccWeightS84", ", no acc. weighted");
  // add sth.
  GFHistManip::AddToHistsName("GenS83", fDstarBack1JetHistsGS83, " gen");
  GFHistManip::AddToHistsName("S84", fDstarBack1JetHistsGS84);

  // ------------ forward D*
  // s83
  fDstarForw1JetHistsGS83     = this->CreateHistsDstar1Jet(+1, 1); // 1D hists
  GFHistManip::CreateAnalogHists(fDstarForw1JetHistsGS83, fDstarForw1JetHistsGAS83, 
				 "GenAccS83", " gen, acc. weighted");
  GFHistManip::CreateAnalogHists(fDstarForw1JetHistsGS83, fDstarForw1JetHistsGWS83, 
				 "GenWeightS83", " gen, weighted");
  GFHistManip::CreateAnalogHists(fDstarForw1JetHistsGS83, fDstarForw1JetHistsGNAWS83, 
				 "GenNoAccWeightS83", " gen, no acc. weighted");

  // s84
  GFHistManip::CreateAnalogHists(fDstarForw1JetHistsGS83, fDstarForw1JetHistsGS84, 
				 "Gen", " gen");
  GFHistManip::CreateAnalogHists(fDstarForw1JetHistsGS84, fDstarForw1JetHistsGAS84, 
				 "AccS84", ", acc. weighted");
  GFHistManip::CreateAnalogHists(fDstarForw1JetHistsGS84, fDstarForw1JetHistsGWS84, 
				 "WeightS84", ", weighted");
  GFHistManip::CreateAnalogHists(fDstarForw1JetHistsGS84, fDstarForw1JetHistsGNAWS84, 
				 "NoAccWeightS84", ", no acc. weighted");
  // add sth.
  GFHistManip::AddToHistsName("GenS83", fDstarForw1JetHistsGS83, " gen");
  GFHistManip::AddToHistsName("S84", fDstarForw1JetHistsGS84);

//   // fixme for angela
//   fDstar1JetHistsGS83->Add(new TH2F("ptEtaDsJetGenS83", "p_{t}(D*+j) vs #eta((D*+j)",
// 				    20, -5., 5., 30, 0., 15.));

  GFHistManip::CallSumw2(fDstar1JetHistsGS83);
  GFHistManip::CallSumw2(fDstar1JetHistsGAS83);
  GFHistManip::CallSumw2(fDstar1JetHistsGWS83);
  GFHistManip::CallSumw2(fDstar1JetHistsGNAWS83);

  GFHistManip::CallSumw2(fDstarBack1JetHistsGS83);
  GFHistManip::CallSumw2(fDstarBack1JetHistsGAS83);
  GFHistManip::CallSumw2(fDstarBack1JetHistsGWS83);
  GFHistManip::CallSumw2(fDstarBack1JetHistsGNAWS83);

  GFHistManip::CallSumw2(fDstarForw1JetHistsGS83);
  GFHistManip::CallSumw2(fDstarForw1JetHistsGAS83);
  GFHistManip::CallSumw2(fDstarForw1JetHistsGWS83);
  GFHistManip::CallSumw2(fDstarForw1JetHistsGNAWS83);

  GFHistManip::CallSumw2(fDstar1JetHistsGS84);
  GFHistManip::CallSumw2(fDstar1JetHistsGAS84);
  GFHistManip::CallSumw2(fDstar1JetHistsGWS84);
  GFHistManip::CallSumw2(fDstar1JetHistsGNAWS84);

  GFHistManip::CallSumw2(fDstarBack1JetHistsGS84);
  GFHistManip::CallSumw2(fDstarBack1JetHistsGAS84);
  GFHistManip::CallSumw2(fDstarBack1JetHistsGWS84);
  GFHistManip::CallSumw2(fDstarBack1JetHistsGNAWS84);

  GFHistManip::CallSumw2(fDstarForw1JetHistsGS84);
  GFHistManip::CallSumw2(fDstarForw1JetHistsGAS84);
  GFHistManip::CallSumw2(fDstarForw1JetHistsGWS84);
  GFHistManip::CallSumw2(fDstarForw1JetHistsGNAWS84);

  oldDir->cd();

  fAllHistArrays.Add(fDstar1JetHistsGS83);
  fAllHistArrays.Add(fDstar1JetHistsGAS83);
  fAllHistArrays.Add(fDstar1JetHistsGWS83);
  fAllHistArrays.Add(fDstar1JetHistsGNAWS83);
  fAllHistArrays.Add(fDstarBack1JetHistsGS83);
  fAllHistArrays.Add(fDstarBack1JetHistsGAS83);
  fAllHistArrays.Add(fDstarBack1JetHistsGWS83);
  fAllHistArrays.Add(fDstarBack1JetHistsGNAWS83);
  fAllHistArrays.Add(fDstarForw1JetHistsGS83);
  fAllHistArrays.Add(fDstarForw1JetHistsGAS83);
  fAllHistArrays.Add(fDstarForw1JetHistsGWS83);
  fAllHistArrays.Add(fDstarForw1JetHistsGNAWS83);

  fAllHistArrays.Add(fDstar1JetHistsGS84);
  fAllHistArrays.Add(fDstar1JetHistsGAS84);
  fAllHistArrays.Add(fDstar1JetHistsGWS84);
  fAllHistArrays.Add(fDstar1JetHistsGNAWS84);
  fAllHistArrays.Add(fDstarBack1JetHistsGS84);
  fAllHistArrays.Add(fDstarBack1JetHistsGAS84);
  fAllHistArrays.Add(fDstarBack1JetHistsGWS84);
  fAllHistArrays.Add(fDstarBack1JetHistsGNAWS84);
  fAllHistArrays.Add(fDstarForw1JetHistsGS84);
  fAllHistArrays.Add(fDstarForw1JetHistsGAS84);
  fAllHistArrays.Add(fDstarForw1JetHistsGWS84);
  fAllHistArrays.Add(fDstarForw1JetHistsGNAWS84);
}

//_____________________________________________________
 void GFDstarAnalyseMc::FillHistsDstarJetsGen(const H1PartMC* genDstar)
{
  // generator hists for D* and (other) jet(s)
  // assume dstar  is really a generated D*

  if(!this->DstarCutLoose(genDstar)) return;
  const Bool_t s83 = this->IsS83Gen(genDstar); // cuts on higher pt
  const Bool_t s84 = this->IsS84Gen(genDstar); // cuts on backward direction
  if(!s83 && !s84) return;


  TObjArray jets;
  const Int_t posDstar = this->GetNonDstarGenJets(genDstar, jets);
  if(jets.GetEntriesFast() == 0) return; //no jets

  if(!fDstar1JetHistsGS83) this->CreateHistsDstarJetsGen();

  const Int_t iJetHighPt = this->GetHighestPt(jets); 
  const H1PartJet* jetHighPt = static_cast<H1PartJet*>(jets[iJetHighPt]);

  H1ElectronTagger* tag = static_cast<H1ElectronTagger*>
    (H1DBManager::Instance()->GetDBEntry(H1ElectronTagger::Class()));
  const Double_t yGen = this->GetYgen();

  if(s83) {
      const Double_t weight = this->GetWeight(83, NULL);
      const Double_t acc = tag->Acceptance33(yGen);
      const Double_t noAccW = weight/acc; // corr for run dep

      // (-1. = dm < 0) => 1-D hists
      this->FillHistsDstar1Jet(genDstar, jetHighPt, fDstar1JetHistsGS83, 1., -1.); // no weight
      this->FillHistsDstar1Jet(genDstar, jetHighPt, fDstar1JetHistsGAS83, acc, -1.);
      this->FillHistsDstar1Jet(genDstar, jetHighPt, fDstar1JetHistsGWS83, weight, -1.);
      this->FillHistsDstar1Jet(genDstar, jetHighPt, fDstar1JetHistsGNAWS83, noAccW, -1.);

//       // FIXME for angela
//       TLorentzVector pDsJet = genDstar->GetFourVector() + jetHighPt->GetFourVector();
//       fDstar1JetHistsGS83->Last()->Fill(pDsJet.Eta(), pDsJet.Pt());

      if(iJetHighPt >= posDstar){
	this->FillHistsDstar1Jet(genDstar, jetHighPt, fDstarBack1JetHistsGS83, 1., -1.);
	this->FillHistsDstar1Jet(genDstar, jetHighPt, fDstarBack1JetHistsGAS83, acc,-1.);
	this->FillHistsDstar1Jet(genDstar, jetHighPt, fDstarBack1JetHistsGWS83, weight, -1.);
	this->FillHistsDstar1Jet(genDstar, jetHighPt, fDstarBack1JetHistsGNAWS83, noAccW, -1.);
      } else {
	this->FillHistsDstar1Jet(genDstar, jetHighPt, fDstarForw1JetHistsGS83, 1., -1.);
	this->FillHistsDstar1Jet(genDstar, jetHighPt, fDstarForw1JetHistsGAS83, acc,-1.);
	this->FillHistsDstar1Jet(genDstar, jetHighPt, fDstarForw1JetHistsGWS83, weight, -1.);
	this->FillHistsDstar1Jet(genDstar, jetHighPt, fDstarForw1JetHistsGNAWS83, noAccW, -1.);
      }
  }
  if(s84) {
      const Double_t weight = this->GetWeight(84, NULL);
      const Double_t acc = tag->Acceptance44(yGen);
      const Double_t noAccW = weight/acc; // corr for run dep

      // (-1. = dm < 0) => 1-D hists
      this->FillHistsDstar1Jet(genDstar, jetHighPt, fDstar1JetHistsGS84, 1., -1.); // no weight
      this->FillHistsDstar1Jet(genDstar, jetHighPt, fDstar1JetHistsGAS84, acc, -1.);
      this->FillHistsDstar1Jet(genDstar, jetHighPt, fDstar1JetHistsGWS84, weight, -1.);
      this->FillHistsDstar1Jet(genDstar, jetHighPt, fDstar1JetHistsGNAWS84, noAccW, -1.);

      if(iJetHighPt >= posDstar){
	this->FillHistsDstar1Jet(genDstar, jetHighPt, fDstarBack1JetHistsGS84, 1., -1.);
	this->FillHistsDstar1Jet(genDstar, jetHighPt, fDstarBack1JetHistsGAS84, acc,-1.);
	this->FillHistsDstar1Jet(genDstar, jetHighPt, fDstarBack1JetHistsGWS84, weight, -1.);
	this->FillHistsDstar1Jet(genDstar, jetHighPt, fDstarBack1JetHistsGNAWS84, noAccW, -1.);
      } else {
	this->FillHistsDstar1Jet(genDstar, jetHighPt, fDstarForw1JetHistsGS84, 1., -1.);
	this->FillHistsDstar1Jet(genDstar, jetHighPt, fDstarForw1JetHistsGAS84, acc,-1.);
	this->FillHistsDstar1Jet(genDstar, jetHighPt, fDstarForw1JetHistsGWS84, weight, -1.);
	this->FillHistsDstar1Jet(genDstar, jetHighPt, fDstarForw1JetHistsGNAWS84, noAccW, -1.);
      }
  }
}

//_____________________________________________________
 void GFDstarAnalyseMc::CreateHistsDstarDiJetGen()
{

  TDirectory* oldDir = this->OpenHistsFile();
  TDirectory* dir = new TDirectory("genDiJet", "generator level hists for D*-dijet");
  dir->cd();

  // s83
  fDstarDiJetHistsGS83     = this->CreateHistsDstarDiJetInt(1); // 1D hists
  GFHistManip::CreateAnalogHists(fDstarDiJetHistsGS83, fDstarDiJetHistsGAS83, 
				 "GenAccS83", " gen, acc. weighted");
  GFHistManip::CreateAnalogHists(fDstarDiJetHistsGS83, fDstarDiJetHistsGWS83, 
				 "GenWeightS83", " gen, weighted");
  GFHistManip::CreateAnalogHists(fDstarDiJetHistsGS83, fDstarDiJetHistsGNAWS83,
				 "GenNoAccWeightS83", " gen, no acc. weighted");

  // s84
  GFHistManip::CreateAnalogHists(fDstarDiJetHistsGS83, fDstarDiJetHistsGS84, 
				 "Gen", " gen");
  GFHistManip::CreateAnalogHists(fDstarDiJetHistsGS84, fDstarDiJetHistsGAS84, 
				 "AccS84", ", acc. weighted");
  GFHistManip::CreateAnalogHists(fDstarDiJetHistsGS84, fDstarDiJetHistsGWS84, 
				 "WeightS84", ", weighted");
  GFHistManip::CreateAnalogHists(fDstarDiJetHistsGS84, fDstarDiJetHistsGNAWS84,
				 "NoAccWeightS84", ", no acc. weighted");
  // add sth.
  GFHistManip::AddToHistsName("GenS83", fDstarDiJetHistsGS83, " gen");
  GFHistManip::AddToHistsName("S84", fDstarDiJetHistsGS84);


  GFHistManip::CallSumw2(fDstarDiJetHistsGS83);
  GFHistManip::CallSumw2(fDstarDiJetHistsGAS83);
  GFHistManip::CallSumw2(fDstarDiJetHistsGWS83);
  GFHistManip::CallSumw2(fDstarDiJetHistsGNAWS83);

  GFHistManip::CallSumw2(fDstarDiJetHistsGS84);
  GFHistManip::CallSumw2(fDstarDiJetHistsGAS84);
  GFHistManip::CallSumw2(fDstarDiJetHistsGWS84);
  GFHistManip::CallSumw2(fDstarDiJetHistsGNAWS84);

  fAllHistArrays.Add(fDstarDiJetHistsGS83);
  fAllHistArrays.Add(fDstarDiJetHistsGAS83);
  fAllHistArrays.Add(fDstarDiJetHistsGWS83);
  fAllHistArrays.Add(fDstarDiJetHistsGNAWS83);
  
  fAllHistArrays.Add(fDstarDiJetHistsGS84);
  fAllHistArrays.Add(fDstarDiJetHistsGAS84);
  fAllHistArrays.Add(fDstarDiJetHistsGWS84);
  fAllHistArrays.Add(fDstarDiJetHistsGNAWS84);
  

  oldDir->cd();
}


//_____________________________________________________
 void GFDstarAnalyseMc::FillHistsDstarDiJetGen(const H1PartMC* genDstar)
{
  // generator hists for D*-dijet
  // assume dstar  is really a generated D*

  if(!this->DstarCutLoose(genDstar)) return;
  const Bool_t s83 = this->IsS83Gen(genDstar); // cuts on higher pt
  const Bool_t s84 = this->IsS84Gen(genDstar); // cuts on backward direction
  if(!s83 && !s84) return;

  if(!fDstarDiJetHistsGS83) this->CreateHistsDstarDiJetGen();

  const H1PartJet *dstarJet = NULL;
  const H1PartJet *oJet = NULL;

  const Bool_t realDsJet = this->GetGenDiJets(genDstar, dstarJet, oJet);
  if(!dstarJet || !oJet) return;

  H1ElectronTagger* tag = static_cast<H1ElectronTagger*>
    (H1DBManager::Instance()->GetDBEntry(H1ElectronTagger::Class()));
  const Double_t yGen = this->GetYgen();

  if(s83) {
      const Double_t weight = this->GetWeight(83, NULL);
      const Double_t acc = tag->Acceptance33(yGen);
      const Double_t noAccW = weight/acc; // corr for run dep

      // (-1. = dm < 0) => 1-D hists
      this->FillHistsDstarDiJet(genDstar, dstarJet, oJet, realDsJet, fDstarDiJetHistsGS83, 1., -1.); // no weight
      this->FillHistsDstarDiJet(genDstar, dstarJet, oJet, realDsJet, fDstarDiJetHistsGAS83, acc, -1.);
      this->FillHistsDstarDiJet(genDstar, dstarJet, oJet, realDsJet, fDstarDiJetHistsGWS83, weight, -1.);
      this->FillHistsDstarDiJet(genDstar, dstarJet, oJet, realDsJet, fDstarDiJetHistsGNAWS83, noAccW, -1.);

  }
  if(s84) {
      const Double_t weight = this->GetWeight(84, NULL);
      const Double_t acc = tag->Acceptance44(yGen);
      const Double_t noAccW = weight/acc; // corr for run dep

      // (-1. = dm < 0) => 1-D hists
      this->FillHistsDstarDiJet(genDstar, dstarJet, oJet, realDsJet, fDstarDiJetHistsGS84, 1., -1.); // no weight
      this->FillHistsDstarDiJet(genDstar, dstarJet, oJet, realDsJet, fDstarDiJetHistsGAS84, acc, -1.);
      this->FillHistsDstarDiJet(genDstar, dstarJet, oJet, realDsJet, fDstarDiJetHistsGWS84, weight, -1.);
      this->FillHistsDstarDiJet(genDstar, dstarJet, oJet, realDsJet, fDstarDiJetHistsGNAWS84, noAccW, -1.);
  }
}

//_____________________________________________________
 void GFDstarAnalyseMc::CreateHistsDsJetTrig()
{
  // D* + 1 jet hists for trigger eff
  TDirectory* oldDir = this->OpenHistsFile();
  TDirectory* dir = new TDirectory("trigJet", "D* + jet hists: trig eff");
  dir->cd();

  // ------------ no order in eta
  // s83
  fTrigDs1JetHistsS83     = this->CreateHistsDstar1Jet(0, 1); // 1D hists
  GFHistManip::CallSumw2(fTrigDs1JetHistsS83);
  GFHistManip::CreateAnalogHists(fTrigDs1JetHistsS83, fNonTrigDs1JetHistsS83,
				 "NonTrigS83", " no trig required");
  GFHistManip::CreateAnalogHists(fTrigDs1JetHistsS83, fTrig19Ds1JetHistsS83,
				 "Trig19S83", " TE 19");
  GFHistManip::CreateAnalogHists(fTrigDs1JetHistsS83, fTrig31Ds1JetHistsS83,
				 "Trig31S83", " TE 31");
  GFHistManip::AddToHistsName("TrigS83", fTrigDs1JetHistsS83, " TE 19 && 31");
  // s84
  fTrigDs1JetHistsS84     = this->CreateHistsDstar1Jet(0, 1); // 1D hists
  GFHistManip::CallSumw2(fTrigDs1JetHistsS84);
  GFHistManip::CreateAnalogHists(fTrigDs1JetHistsS84, fNonTrigDs1JetHistsS84,
				 "NonTrigS84", " no trig required");
  GFHistManip::CreateAnalogHists(fTrigDs1JetHistsS84, fTrig19Ds1JetHistsS84,
				 "Trig19S84", " TE 19");
  GFHistManip::CreateAnalogHists(fTrigDs1JetHistsS84, fTrig31Ds1JetHistsS84,
				 "Trig31S84", " TE 31");
  GFHistManip::AddToHistsName("TrigS84", fTrigDs1JetHistsS84, " TE 19 && 31");

  // ------------ backward D*
  // s83
  fTrigDs1JetBackHistsS83     = this->CreateHistsDstar1Jet(-1, 1); // Back, 1D hists
  GFHistManip::CallSumw2(fTrigDs1JetBackHistsS83);
  GFHistManip::CreateAnalogHists(fTrigDs1JetBackHistsS83, fNonTrigDs1JetBackHistsS83,
				 "NonTrigS83", " no trig required");
  GFHistManip::CreateAnalogHists(fTrigDs1JetBackHistsS83, fTrig19Ds1JetBackHistsS83,
				 "Trig19S83", " TE 19");
  GFHistManip::CreateAnalogHists(fTrigDs1JetBackHistsS83, fTrig31Ds1JetBackHistsS83,
				 "Trig31S83", " TE 31");
  GFHistManip::AddToHistsName("TrigS83", fTrigDs1JetBackHistsS83, " TE 19 && 31");
  // s84
  fTrigDs1JetBackHistsS84     = this->CreateHistsDstar1Jet(-1, 1); // Back, 1D hists
  GFHistManip::CallSumw2(fTrigDs1JetBackHistsS84);
  GFHistManip::CreateAnalogHists(fTrigDs1JetBackHistsS84, fNonTrigDs1JetBackHistsS84,
				 "NonTrigS84", " no trig required");
  GFHistManip::CreateAnalogHists(fTrigDs1JetBackHistsS84, fTrig19Ds1JetBackHistsS84,
				 "Trig19S84", " TE 19");
  GFHistManip::CreateAnalogHists(fTrigDs1JetBackHistsS84, fTrig31Ds1JetBackHistsS84,
				 "Trig31S84", " TE 31");
  GFHistManip::AddToHistsName("TrigS84", fTrigDs1JetBackHistsS84, " TE 19 && 31");


  // ------------ forward D*
  // s83
  fTrigDs1JetForwHistsS83     = this->CreateHistsDstar1Jet(+1, 1); // Forw, 1D hists
  GFHistManip::CallSumw2(fTrigDs1JetForwHistsS83);
  GFHistManip::CreateAnalogHists(fTrigDs1JetForwHistsS83, fNonTrigDs1JetForwHistsS83,
				 "NonTrigS83", " no trig required");
  GFHistManip::CreateAnalogHists(fTrigDs1JetForwHistsS83, fTrig19Ds1JetForwHistsS83,
				 "Trig19S83", " TE 19");
  GFHistManip::CreateAnalogHists(fTrigDs1JetForwHistsS83, fTrig31Ds1JetForwHistsS83,
				 "Trig31S83", " TE 31");
  GFHistManip::AddToHistsName("TrigS83", fTrigDs1JetForwHistsS83, " TE 19 && 31");
  // s84
  fTrigDs1JetForwHistsS84     = this->CreateHistsDstar1Jet(+1, 1); // Forw, 1D hists
  GFHistManip::CallSumw2(fTrigDs1JetForwHistsS84);
  GFHistManip::CreateAnalogHists(fTrigDs1JetForwHistsS84, fNonTrigDs1JetForwHistsS84,
				 "NonTrigS84", " no trig required");
  GFHistManip::CreateAnalogHists(fTrigDs1JetForwHistsS84, fTrig19Ds1JetForwHistsS84,
				 "Trig19S84", " TE 19");
  GFHistManip::CreateAnalogHists(fTrigDs1JetForwHistsS84, fTrig31Ds1JetForwHistsS84,
				 "Trig31S84", " TE 31");
  GFHistManip::AddToHistsName("TrigS84", fTrigDs1JetForwHistsS84, " TE 19 && 31");

  oldDir->cd();

  fAllHistArrays.Add(fTrigDs1JetHistsS83);
  fAllHistArrays.Add(fTrigDs1JetHistsS84);
  fAllHistArrays.Add(fNonTrigDs1JetHistsS83);
  fAllHistArrays.Add(fNonTrigDs1JetHistsS84);
  fAllHistArrays.Add(fTrig19Ds1JetHistsS83);
  fAllHistArrays.Add(fTrig19Ds1JetHistsS84);
  fAllHistArrays.Add(fTrig31Ds1JetHistsS83);
  fAllHistArrays.Add(fTrig31Ds1JetHistsS84);
  fAllHistArrays.Add(fTrigDs1JetBackHistsS83);
  fAllHistArrays.Add(fTrigDs1JetBackHistsS84);
  fAllHistArrays.Add(fNonTrigDs1JetBackHistsS83);
  fAllHistArrays.Add(fNonTrigDs1JetBackHistsS84);
  fAllHistArrays.Add(fTrig19Ds1JetBackHistsS83);
  fAllHistArrays.Add(fTrig19Ds1JetBackHistsS84);
  fAllHistArrays.Add(fTrig31Ds1JetBackHistsS83);
  fAllHistArrays.Add(fTrig31Ds1JetBackHistsS84);
  fAllHistArrays.Add(fTrigDs1JetForwHistsS83);
  fAllHistArrays.Add(fTrigDs1JetForwHistsS84);
  fAllHistArrays.Add(fNonTrigDs1JetForwHistsS83);
  fAllHistArrays.Add(fNonTrigDs1JetForwHistsS84);
  fAllHistArrays.Add(fTrig19Ds1JetForwHistsS83);
  fAllHistArrays.Add(fTrig19Ds1JetForwHistsS84);
  fAllHistArrays.Add(fTrig31Ds1JetForwHistsS83);
  fAllHistArrays.Add(fTrig31Ds1JetForwHistsS84);
}

//_____________________________________________________
 void GFDstarAnalyseMc::FillHistsDsJetTrig(const H1PartDstar* dstar)
{
  // fill D* + 1 jet hists for trigger eff 
  // assuming that dstar is already reconstructed with the lower
  // pt-cut and wider eta region

  const Bool_t s83 = this->IsS83NoL1Check(dstar);
  const Bool_t s84 = this->IsS84NoL1Check(dstar);
  if(!s83 && !s84) return;

  TObjArray jets;
  const Int_t posDstar = this->GetNonDstarJets(dstar, jets);
  if(jets.GetEntriesFast() == 0) return; // no jets

  if(!fTrigDs1JetHistsS83) this->CreateHistsDsJetTrig();

  const Int_t iJetHighPt = this->GetHighestPt(jets); 
  const H1PartJet* jetHighPt = static_cast<H1PartJet*>(jets[iJetHighPt]);

  static H1BytePtr  trigElements("Il1te");

  if(s83){
    const Double_t weight = this->GetWeight(83, dstar);
    //    const Double_t y = this->GetY33();
    this->FillHistsDstar1Jet(dstar, jetHighPt, fNonTrigDs1JetHistsS83, weight, -1.);
    if(trigElements[19]){
      this->FillHistsDstar1Jet(dstar, jetHighPt, fTrig19Ds1JetHistsS83, weight, -1.);
    }
    if(trigElements[31]){
      this->FillHistsDstar1Jet(dstar, jetHighPt, fTrig31Ds1JetHistsS83, weight, -1.);
    }
    if(trigElements[19] && trigElements[31]){
      this->FillHistsDstar1Jet(dstar, jetHighPt, fTrigDs1JetHistsS83, weight, -1.);
    }
    if(iJetHighPt >= posDstar){ // eta(D*) < eta(jet)
      this->FillHistsDstar1Jet(dstar, jetHighPt, fNonTrigDs1JetBackHistsS83, weight, -1.);
      if(trigElements[19]){
	this->FillHistsDstar1Jet(dstar, jetHighPt, fTrig19Ds1JetBackHistsS83, weight, -1.);
      }
      if(trigElements[31]){
	this->FillHistsDstar1Jet(dstar, jetHighPt, fTrig31Ds1JetBackHistsS83, weight, -1.);
      }
      if(trigElements[19] && trigElements[31]){
	this->FillHistsDstar1Jet(dstar, jetHighPt, fTrigDs1JetBackHistsS83, weight, -1.);
      }
    } else { // eta(D*) > eta(jet)
      this->FillHistsDstar1Jet(dstar, jetHighPt, fNonTrigDs1JetForwHistsS83, weight, -1.);
      if(trigElements[19]){
	this->FillHistsDstar1Jet(dstar, jetHighPt, fTrig19Ds1JetForwHistsS83, weight, -1.);
      }
      if(trigElements[31]){
	this->FillHistsDstar1Jet(dstar, jetHighPt, fTrig31Ds1JetForwHistsS83, weight, -1.);
      }
      if(trigElements[19] && trigElements[31]){
	this->FillHistsDstar1Jet(dstar, jetHighPt, fTrigDs1JetForwHistsS83, weight, -1.);
      }
    }
  }
  if(s84){
    const Double_t weight = this->GetWeight(84, dstar);
    //    const Double_t y = this->GetY44();
    this->FillHistsDstar1Jet(dstar, jetHighPt, fNonTrigDs1JetHistsS84, weight, -1.);
    if(trigElements[19]){
      this->FillHistsDstar1Jet(dstar, jetHighPt, fTrig19Ds1JetHistsS84, weight, -1.);
    }
    if(trigElements[31]){
      this->FillHistsDstar1Jet(dstar, jetHighPt, fTrig31Ds1JetHistsS84, weight, -1.);
    }

    if(trigElements[19] && trigElements[31]){
      this->FillHistsDstar1Jet(dstar, jetHighPt, fTrigDs1JetHistsS84, weight, -1.);
    }
    if(iJetHighPt >= posDstar){ // eta(D*) < eta(jet)
      this->FillHistsDstar1Jet(dstar, jetHighPt, fNonTrigDs1JetBackHistsS84, weight, -1.);
      if(trigElements[19]){
	this->FillHistsDstar1Jet(dstar, jetHighPt, fTrig19Ds1JetBackHistsS84, weight, -1.);
      }
      if(trigElements[31]){
	this->FillHistsDstar1Jet(dstar, jetHighPt, fTrig31Ds1JetBackHistsS84, weight, -1.);
      }
      if(trigElements[19] && trigElements[31]){
	this->FillHistsDstar1Jet(dstar, jetHighPt, fTrigDs1JetBackHistsS84, weight, -1.);
      }
    } else { // eta(D*) > eta(jet)
      this->FillHistsDstar1Jet(dstar, jetHighPt, fNonTrigDs1JetForwHistsS84, weight, -1.);
      if(trigElements[19]){
	this->FillHistsDstar1Jet(dstar, jetHighPt, fTrig19Ds1JetForwHistsS84, weight, -1.);
      }
      if(trigElements[31]){
	this->FillHistsDstar1Jet(dstar, jetHighPt, fTrig31Ds1JetForwHistsS84, weight, -1.);
      }
      if(trigElements[19] && trigElements[31]){
	this->FillHistsDstar1Jet(dstar, jetHighPt, fTrigDs1JetForwHistsS84, weight, -1.);
      }
    }
  }
}

//_____________________________________________________
 void GFDstarAnalyseMc::CreateHistsDsDiJetTrig()
{
  // D* dijet hists for trigger eff
  TDirectory* oldDir = this->OpenHistsFile();
  TDirectory* dir = new TDirectory("trigDiJet", "D* dijet hists: trig eff");
  dir->cd();

  // s83
  fTrigDsDiJetHistsS83     = this->CreateHistsDstarDiJetInt(1); // 1D hists
  GFHistManip::CallSumw2(fTrigDsDiJetHistsS83);
  GFHistManip::CreateAnalogHists(fTrigDsDiJetHistsS83, fNonTrigDsDiJetHistsS83,
				 "NonTrigS83", " no trig required");
  GFHistManip::CreateAnalogHists(fTrigDsDiJetHistsS83, fTrig19DsDiJetHistsS83,
				 "Trig19S83", " TE 19");
  GFHistManip::CreateAnalogHists(fTrigDsDiJetHistsS83, fTrig31DsDiJetHistsS83,
				 "Trig31S83", " TE 31");
  GFHistManip::AddToHistsName("TrigS83", fTrigDsDiJetHistsS83, " TE 19 && 31");
  // s84
  fTrigDsDiJetHistsS84     = this->CreateHistsDstarDiJetInt(1); // 1D hists
  GFHistManip::CallSumw2(fTrigDsDiJetHistsS84);
  GFHistManip::CreateAnalogHists(fTrigDsDiJetHistsS84, fNonTrigDsDiJetHistsS84,
				 "NonTrigS84", " no trig required");
  GFHistManip::CreateAnalogHists(fTrigDsDiJetHistsS84, fTrig19DsDiJetHistsS84,
				 "Trig19S84", " TE 19");
  GFHistManip::CreateAnalogHists(fTrigDsDiJetHistsS84, fTrig31DsDiJetHistsS84,
				 "Trig31S84", " TE 31");
  GFHistManip::AddToHistsName("TrigS84", fTrigDsDiJetHistsS84, " TE 19 && 31");


  oldDir->cd();
}

//_____________________________________________________
 void GFDstarAnalyseMc::FillHistsDsDiJetTrig(const H1PartDstar* ds)
{
  // fill D* dijet hists for trigger eff 
  // assuming that dstar is already reconstructed with the lower
  // pt-cut and wider eta region

  const Bool_t s83 = this->IsS83NoL1Check(ds);
  const Bool_t s84 = this->IsS84NoL1Check(ds);
  if(!s83 && !s84) return;

  Int_t iDsJet = -1;
  TObjArray jets = this->GetJets(ds, &iDsJet);
  H1PartJet *dsJet = (iDsJet>=0 ? static_cast<H1PartJet*>(jets[iDsJet]):NULL);
  if(this->RemoveLowPt(&jets, 2) < 2) return;
  H1PartJet *jet1 = static_cast<H1PartJet*>(jets[0]);
  H1PartJet *jet2 = static_cast<H1PartJet*>(jets[1]);

  H1PartJet *dstarJet = NULL;
  H1PartJet *oJet = NULL;
  Bool_t realDsJet = kTRUE;
  if(jet1 == dsJet){
    dstarJet = jet1; 
    oJet = jet2; 
  } else if(jet2 == dsJet){
    dstarJet = jet2; 
    oJet = jet1; 
  } else {
    realDsJet = kFALSE;
//     this->Warning("FillHistsDsDiJetsTrig", "D* not in first two jets");
    if(jet1->GetMomentum().DeltaR(ds->GetMomentum()) < jet2->GetMomentum().DeltaR(ds->GetMomentum())){
      dstarJet = jet1; 
      oJet = jet2; 
    } else {
      dstarJet = jet2; 
      oJet = jet1; 
    }
  }

  if(!fNonTrigDsDiJetHistsS83) this->CreateHistsDsDiJetTrig();

  static H1BytePtr  trigElements("Il1te");

  if(s83){
    const Double_t weight = this->GetWeight(83, ds);
    //    const Double_t y = this->GetY33();
    this->FillHistsDstarDiJet(ds, dstarJet, oJet, realDsJet,
			      fNonTrigDsDiJetHistsS83, weight, -1.);
    if(trigElements[19]){
      this->FillHistsDstarDiJet(ds, dstarJet, oJet, realDsJet, 
				fTrig19DsDiJetHistsS83, weight, -1.);
    }
    if(trigElements[31]){
      this->FillHistsDstarDiJet(ds, dstarJet, oJet, realDsJet,
				fTrig31DsDiJetHistsS83, weight, -1.);
    }
    if(trigElements[19] && trigElements[31]){
      this->FillHistsDstarDiJet(ds, dstarJet, oJet, realDsJet,
				fTrigDsDiJetHistsS83, weight, -1.);
    }

  }
  if(s84){
    const Double_t weight = this->GetWeight(84, ds);
    //    const Double_t y = this->GetY44();
    this->FillHistsDstarDiJet(ds, dstarJet, oJet, realDsJet, 
			      fNonTrigDsDiJetHistsS84, weight, -1.);
    if(trigElements[19]){
      this->FillHistsDstarDiJet(ds, dstarJet, oJet, realDsJet, 
				fTrig19DsDiJetHistsS84, weight, -1.);
    }
    if(trigElements[31]){
      this->FillHistsDstarDiJet(ds, dstarJet, oJet, realDsJet, 
				fTrig31DsDiJetHistsS84, weight, -1.);
    }
    if(trigElements[19] && trigElements[31]){
      this->FillHistsDstarDiJet(ds, dstarJet, oJet, realDsJet, 
				fTrigDsDiJetHistsS84, weight, -1.);
    }
  }
}

//_____________________________________________________
 void GFDstarAnalyseMc::CreateHistsBranching()
{
  TDirectory* oldDir = this->OpenHistsFile();
  TDirectory* dir = new TDirectory("branching", "hists for c->D* and D*->Kpipi branching");
  dir->cd();
  GFHistManip::ClearCreateArray(fBranchingHists);
  fAllHistArrays.Add(fBranchingHists);

  fBranchingHists->Add(new TH1I("dstarDecay","D* decay: [0,1[ golden, [1,2[ other", 2, 0., 2.));
  fBranchingHists->Add(new TH1I("cToHadron", "c ->: [0,1[ D*, [1,2[ other", 2, 0.,2.));

  oldDir->cd();
}

//_____________________________________________________
 void GFDstarAnalyseMc::FillHistsBranching()
{

  if(!fBranchingHists) this->CreateHistsBranching();
  static H1PartMCArrayPtr mcs;
 
  TObjArray cQuarks;

  Bool_t firstGoldenFound = kFALSE;
  for(Int_t i = 0; i < mcs.GetEntries(); ++i){
    if(TMath::Abs(mcs[i]->GetPDG()) == H1UserDstarUtil::kDstarPDG){
      const Bool_t isGolden = H1UserDstarUtil::IsDstarKPiPis(mcs[i], mcs.GetArray());
      if(isGolden && !firstGoldenFound && mcs[i]->GetPt() > 1.0 &&
	 mcs[i]->GetTheta()>15.*TMath::DegToRad() && mcs[i]->GetTheta()<165.*TMath::DegToRad()){
	firstGoldenFound = kTRUE; // selected in generation
      } else {
	if(isGolden) fBranchingHists->At(0)->Fill(0.5);
	else fBranchingHists->At(0)->Fill(1.5);
      }
    } else if(TMath::Abs(mcs[i]->GetPDG()) == 4 && mcs[i]->GetStatus() == 2){ // charm, decayed
      cQuarks.Add(mcs[i]);
    }
  }

  Bool_t firstGoldenFound2 = kFALSE;
  TIter next(&cQuarks);
  while(H1PartMC* quark = static_cast<H1PartMC*>(next())){
    const Int_t qDaught1 = quark->GetDaughter1();
    const Int_t qDaught2 = (quark->GetDaughter2() == -1 ? qDaught1 : quark->GetDaughter2());
    TArrayI ind(qDaught2-qDaught1+1); // for all daughters, will be expanded...
    for(Int_t i = qDaught1; i <= qDaught2; ++i) ind[i-qDaught1] = i;

    Bool_t foundDstar = kFALSE; // whether this c quark produced a D*
    for(Int_t i = 0; i < ind.GetSize(); ++i){
      const Int_t mcInd = ind[i];
      const Bool_t isGolden = H1UserDstarUtil::IsDstarKPiPis(mcs[mcInd], mcs.GetArray());
      if(isGolden && !firstGoldenFound2 && mcs[i]->GetPt() > 1.0 &&
	 mcs[i]->GetTheta()>15.*TMath::DegToRad() && mcs[i]->GetTheta()<165.*TMath::DegToRad()){
	firstGoldenFound2 = kTRUE; // selected in generation
	foundDstar = kTRUE;
      } else if(TMath::Abs(mcs[mcInd]->GetPDG()) == H1UserDstarUtil::kDstarPDG){
	fBranchingHists->At(1)->Fill(0.5);
	foundDstar = kTRUE;
      } else if(!mcs[mcInd]->IsStable()){// add daughters to ind
	Int_t tmpDaught1 = mcs[mcInd]->GetDaughter1();
	const Int_t tmpDaught2 = (mcs[mcInd]->GetDaughter2() == -1 ? tmpDaught1 
				  : mcs[mcInd]->GetDaughter2());
	const Int_t oldIndSize = ind.GetSize();
	ind.Set(oldIndSize + tmpDaught2 - tmpDaught1 + 1);
	for(Int_t j = oldIndSize; j < ind.GetSize(); ++j){
	  ind[j] = tmpDaught1++;//POSTfix!!
	}
      }
    } // loop on ind
    if(!foundDstar) fBranchingHists->At(1)->Fill(1.5);
  } // loop on decayed charm quarks
}

//_____________________________________________________
 void GFDstarAnalyseMc::CreateHistsHadronisation()
{
  TDirectory* oldDir = this->OpenHistsFile();
  TDirectory* dir = new TDirectory("partonJet", "parton level hists for D* + jet");
  dir->cd();

  // correction hists:
  fHadronisationHistsS83 = this->CreateHistsDstar1Jet(0, 1); // 1D hists
//   // HACK HACK HACK: need to manipulate dphi hist, merge the last 2 bins for FMNR:
//   const TArrayD *ar = fSteer->GetDstar1JetDphiBins();
//   TArrayD dPhiAr(ar->GetSize()-1, ar->GetArray());
//   dPhiAr[dPhiAr.GetSize()-1] = ar->At(ar->GetSize()-1);
//   delete fHadronisationHistsS83->At(5);
//   fHadronisationHistsS83->AddAt(new TH1F("dstar1JetDphi", "#Delta #phi, D* + 1 jet",
// 					 dPhiAr.GetSize()-1, dPhiAr.GetArray()), 5);
//   // end HACK
  GFHistManip::CallSumw2(fHadronisationHistsS83);
  GFHistManip::CreateAnalogHists(fHadronisationHistsS83, fHadronisationGenHistsS83, "GenS83", 
				 " gen");
  GFHistManip::AddToHistsName("PartonS83", fHadronisationHistsS83, " parton");
  fAllHistArrays.Add(fHadronisationHistsS83);
  fAllHistArrays.Add(fHadronisationGenHistsS83);

  // pur/stab hists:
  const Int_t nBinsVs = 10;
  const Float_t maxDevRes = 1.;
  const Int_t nBinsRes = 60;
  // overall
  GFHistManip::ClearCreateArray(fHadPurStabHists);
  fAllHistArrays.Add(fHadPurStabHists);
  fHadPurStabHists->AddAt(new TH1F("AllGen", "D* + jet (gen)", 1, 0., 1.), 0);
  fHadPurStabHists->AddAt(new TH1F("AllGenPs", "D* + jet (gen && part. sh.)",  1, 0., 1.), 1);
  fHadPurStabHists->AddAt(new TH1F("AllNGenPs", "D* + jet (!gen && part. sh.)",  1, 0., 1.), 2);
  // no 3/4/5
//   GFHistManip::CreateAnalogHists(fHadPurStabHists, fHadPurStabHistsS83, "S83");
  GFHistManip::AddToHistsName("S83", fHadPurStabHists);
  GFHistManip::CallSumw2(fHadPurStabHists);
  // PtJet
  GFHistManip::ClearCreateArray(fHadPurStabHistsJetPt);
  fAllHistArrays.Add(fHadPurStabHistsJetPt);
  const TArrayD *ar = fSteer->GetDstar1JetPtBins();
  fHadPurStabHistsJetPt->AddAt(new TH1F("PtJetGen", "p_{t}(jet) D*+jet (gen)",
					     ar->GetSize()-1, ar->GetArray()), 0);
  fHadPurStabHistsJetPt->AddAt(new TH1F("PtJetGenPs","p_{t}(jet) D*+jet (gen&&parton sh.)", 
					     ar->GetSize()-1, ar->GetArray()), 1);
  fHadPurStabHistsJetPt->AddAt(new TH1F("PtJetNGenPs",
					     "p_{t}(jet) D*+jet (!gen&&parton sh.)", 
					     ar->GetSize()-1, ar->GetArray()), 2);
  fHadPurStabHistsJetPt->AddAt(new TH2F("PtJetGenVsPs",
					     "p_{t}(jet) D*+jet (gen vs parton sh.)", 
					     nBinsVs, ar->At(0), ar->At(ar->GetSize() -1),
					     nBinsVs, ar->At(0), ar->At(ar->GetSize() -1)), 3);
  fHadPurStabHistsJetPt->AddAt(new TH1F("PtJetResRel", 
					     "p_{t}(jet) D*+jet (gen-parton)/parton",
					     nBinsRes, -maxDevRes, maxDevRes), 4);
  fHadPurStabHistsJetPt->AddAt(new TH1F("PtJetRes", "p_{t}(jet) D*+jet (gen-parton sh.)",
					     nBinsRes, -3.*maxDevRes, 3.*maxDevRes), 5);
  //GFHistManip::CreateAnalogHists(fDsJetPurStabHistsJetPt, fDsJetPurStabHistsJetPtS83, "S83");
  GFHistManip::AddToHistsName("S83", fHadPurStabHistsJetPt);
  GFHistManip::CallSumw2(fHadPurStabHistsJetPt);


  // EtaJet
  GFHistManip::ClearCreateArray(fHadPurStabHistsJetEta);
  fAllHistArrays.Add(fHadPurStabHistsJetEta);
  ar = fSteer->GetDstar1JetEtaBins();
  fHadPurStabHistsJetEta->AddAt(new TH1F("EtaJetGen", "#eta(jet) D*+jet (Gen)", 
					 ar->GetSize()-1, ar->GetArray()), 0);
  fHadPurStabHistsJetEta->AddAt(new TH1F("EtaJetGenPs", "#eta(jet) D*+jet (Gen && part. sh.)", 
					 ar->GetSize()-1, ar->GetArray()), 1);
  fHadPurStabHistsJetEta->AddAt(new TH1F("EtaJetNGenPs", "#eta(jet) D*+jet (!Gen && part. sh.)",
					 ar->GetSize()-1, ar->GetArray()), 2);
  fHadPurStabHistsJetEta->AddAt(new TH2F("EtaJetGenVsPs", "#eta(jet) D*+jet (Gen vs part. sh.)",
					 nBinsVs, ar->At(0), ar->At(ar->GetSize() -1),
					 nBinsVs, ar->At(0), ar->At(ar->GetSize() -1)), 3);
  // no 4
  fHadPurStabHistsJetEta->AddAt(new TH1F("EtaJetRes", "#eta(jet) D*+jet (Gen - part. sh.)", 
					 (5*nBinsRes)/6, -0.5*maxDevRes, 0.5*maxDevRes), 5);
// GFHistManip::CreateAnalogHists(fDsJetPurStabHistsJetEta, fDsJetPurStabHistsJetEtaS83, "S83");
  GFHistManip::AddToHistsName("S83", fHadPurStabHistsJetEta);
  GFHistManip::CallSumw2(fHadPurStabHistsJetEta);
  
  
  // Dphi
  ar = fSteer->GetDstar1JetDphiBins();
  TArrayD dPhiAr(ar->GetSize()-1, ar->GetArray());
  dPhiAr[dPhiAr.GetSize()-1] = ar->At(ar->GetSize()-1);
  GFHistManip::ClearCreateArray(fHadPurStabHistsDphi);
  fAllHistArrays.Add(fHadPurStabHistsDphi);
  TArrayD special(dPhiAr.GetSize() +1);
  special[0] = -20.;
  for (Int_t i = 0; i < dPhiAr.GetSize(); ++i) special[i+1] = dPhiAr[i];

  fHadPurStabHistsDphi->AddAt(new TH1F("DphiGen", "#Delta #phi(D*,jet) D*+jet (Gen)", 
				       dPhiAr.GetSize()-1, dPhiAr.GetArray()), 0);
  fHadPurStabHistsDphi->AddAt(new TH1F("DphiGenPs", "#Delta #phi(D*,jet) (Gen && part. sh.)",
				       dPhiAr.GetSize()-1, dPhiAr.GetArray()), 1);
  fHadPurStabHistsDphi->AddAt(new TH1F("DphiNGenPs","#Delta #phi(D*,jet) (!Gen && part. sh.)",
				       dPhiAr.GetSize()-1, dPhiAr.GetArray()), 2);
  fHadPurStabHistsDphi->AddAt(new TH2F("DphiGenVsPs","#Delta #phi(D*,jet) (Gen vs part. sh.)",
// 	  3*nBinsVs+1, -6., dPhiAr.At(dPhiAr.GetSize()-1),
// 	  3*nBinsVs+1, -6., dPhiAr.At(dPhiAr.GetSize()-1)),3);
					 special.GetSize()-1, special.GetArray(),
					 special.GetSize()-1, special.GetArray()), 3);
  // no 4/5
// GFHistManip::CreateAnalogHists(fDsJetPurStabHistsDphi, fDsJetPurStabHistsDphiS83, "S83");
  GFHistManip::AddToHistsName("S83", fHadPurStabHistsDphi);
  GFHistManip::CallSumw2(fHadPurStabHistsDphi);

  // Deta
  GFHistManip::ClearCreateArray(fHadPurStabHistsDeta);
  fAllHistArrays.Add(fHadPurStabHistsDeta);
  ar = fSteer->GetDstar1JetDetaBins();
  fHadPurStabHistsDeta->AddAt(new TH1F("DetaGen", "#eta(D*) - #eta(jet) D*+jet (Gen)", 
				       ar->GetSize()-1, ar->GetArray()), 0);
  fHadPurStabHistsDeta->AddAt(new TH1F("DetaGenPs", "#eta(D*) - #eta(jet) (Gen && part. sh.)",
				       ar->GetSize()-1, ar->GetArray()), 1);
  fHadPurStabHistsDeta->AddAt(new TH1F("DetaNGenPs", "#eta(D*) - #eta(jet) (!Gen && part. sh.)",
				       ar->GetSize()-1, ar->GetArray()), 2);
  fHadPurStabHistsDeta->AddAt(new TH2F("DetaGenVsPs", "#eta(D*) - #eta(jet) (Gen vs part. sh.)",
				       nBinsVs, ar->At(0), ar->At(ar->GetSize() -1),
				       nBinsVs, ar->At(0), ar->At(ar->GetSize() -1)), 3);
  // no 4
  fHadPurStabHistsDeta->AddAt(new TH1F("DetaRes", "#eta(D*)-#eta(jet) D*+jet (Gen - part. sh.)",
				       (5*nBinsRes)/6, -0.5*maxDevRes, 0.5*maxDevRes), 5);
  // GFHistManip::CreateAnalogHists(fDsJetPurStabHistsDeta, fDsJetPurStabHistsDetaS83, "S83");
  GFHistManip::AddToHistsName("S83", fHadPurStabHistsDeta);
  GFHistManip::CallSumw2(fHadPurStabHistsDeta);
  
  
  // Xgam
  GFHistManip::ClearCreateArray(fHadPurStabHistsXgam);
  fAllHistArrays.Add(fHadPurStabHistsXgam);
  ar = fSteer->GetXgammaBins();
  fHadPurStabHistsXgam->AddAt(new TH1F("xGamGen", "x_{#gamma}(D*,jet) D*+jet (Gen)", 
				       ar->GetSize()-1, ar->GetArray()), 0);
  fHadPurStabHistsXgam->AddAt(new TH1F("xGamGenPs", "x_{#gamma}(D*,jet) (Gen && part. sh.)",
				       ar->GetSize()-1, ar->GetArray()), 1);
  fHadPurStabHistsXgam->AddAt(new TH1F("xGamNGenPs", "x_{#gamma}(D*,jet) (!Gen && part. sh.)",
				       ar->GetSize()-1, ar->GetArray()), 2);
  fHadPurStabHistsXgam->AddAt(new TH2F("xGamGenVsPs", "x_{#gamma}(D*,jet) (Gen vs part. sh.)",
				       5*nBinsVs+1, -.02, ar->At(ar->GetSize() -1),
				       5*nBinsVs+1, -.02, ar->At(ar->GetSize() -1)), 3);
  // no 4/5
  // GFHistManip::CreateAnalogHists(fDsJetPurStabHistsXgam, fDsJetPurStabHistsXgamS83, "S83");
  GFHistManip::AddToHistsName("S83", fHadPurStabHistsXgam);
  GFHistManip::CallSumw2(fHadPurStabHistsXgam);

  // PtDsJet
  GFHistManip::ClearCreateArray(fHadPurStabHistsPtDsJet);
  fAllHistArrays.Add(fHadPurStabHistsPtDsJet);
  ar = fSteer->GetDstar1JetDsJetPtBins();
  fHadPurStabHistsPtDsJet->AddAt(new TH1F("PtDsJetGen", "p_{t}(D*,jet) D*+jet (Gen)", 
				       ar->GetSize()-1, ar->GetArray()), 0);
  fHadPurStabHistsPtDsJet->AddAt(new TH1F("PtDsJetGenPs", "p_{t}(D*,jet) (Gen && part. sh.)",
				       ar->GetSize()-1, ar->GetArray()), 1);
  fHadPurStabHistsPtDsJet->AddAt(new TH1F("PtDsJetNGenPs", "p_{t}(D*,jet) (!Gen && part. sh.)",
				       ar->GetSize()-1, ar->GetArray()), 2);
  fHadPurStabHistsPtDsJet->AddAt(new TH2F("PtDsJetGenVsPs", "p_{t}(D*,jet) (Gen vs part. sh.)",
				       nBinsVs, ar->At(0), ar->At(ar->GetSize() -1),
				       nBinsVs, ar->At(0), ar->At(ar->GetSize() -1)), 3);
  // no 4/5
  // GFHistManip::CreateAnalogHists(fDsJetPurStabHistsPtDsJet, ...S83, "S83");
  GFHistManip::AddToHistsName("S83", fHadPurStabHistsPtDsJet);
  GFHistManip::CallSumw2(fHadPurStabHistsPtDsJet);

  // MDsJet
  GFHistManip::ClearCreateArray(fHadPurStabHistsMDsJet);
  fAllHistArrays.Add(fHadPurStabHistsMDsJet);
  ar = fSteer->GetDstar1JetDsJetMassBins();
  fHadPurStabHistsMDsJet->AddAt(new TH1F("MDsJetGen", "m(D*,jet) D*+jet (Gen)", 
				       ar->GetSize()-1, ar->GetArray()), 0);
  fHadPurStabHistsMDsJet->AddAt(new TH1F("MDsJetGenPs", "m(D*,jet) (Gen && part. sh.)",
				       ar->GetSize()-1, ar->GetArray()), 1);
  fHadPurStabHistsMDsJet->AddAt(new TH1F("MDsJetNGenPs", "m(D*,jet) (!Gen && part. sh.)",
				       ar->GetSize()-1, ar->GetArray()), 2);
  fHadPurStabHistsMDsJet->AddAt(new TH2F("MDsJetGenVsPs", "m(D*,jet) (Gen vs part. sh.)",
				       nBinsVs, ar->At(0), ar->At(ar->GetSize() -1),
				       nBinsVs, ar->At(0), ar->At(ar->GetSize() -1)), 3);
  // no 4/5
  // GFHistManip::CreateAnalogHists(fDsJetPurStabHistsMDsJet, ...S83, "S83");
  GFHistManip::AddToHistsName("S83", fHadPurStabHistsMDsJet);
  GFHistManip::CallSumw2(fHadPurStabHistsMDsJet);

  oldDir->cd();
}

//_____________________________________________________
 void GFDstarAnalyseMc::FillHistsHadronisation(const H1PartMC *dstar)
{
  if(!this->DstarCutLoose(dstar)) return;
  if(!this->IsS83Gen(dstar)) return;

  Double_t weight83 = fWeightPt;//this->GetWeight(83, NULL); // FIXME: no sense here?
//   // fudge for Jeannine
//   static Bool_t first = kTRUE;
//   if(first){
//     this->Info("FillHistsHadronisation", "no weights");
//     first = kFALSE;
//   }
//   weight83 = 1.;
//   // end fudge for Jeannine

  if(!fHadronisationHistsS83) this->CreateHistsHadronisation();

  // completely neglect events with off shell parton shower partons
  // should happen for charm excitation only...
  static H1PartMCArrayPtr partmc;
  if (this->HasOffShellParton(partmc.GetArray())) return;

  TObjArray partonJets = this->GetPartonJets();
  H1PartJet *dstarJet = this->GetDstarPartonJet(&partonJets, dstar, partmc.GetArray());
  if (dstarJet) {
    partonJets.Remove(dstarJet);
    partonJets.Compress();
  }
  const H1PartJet* partonJet = NULL;
  if(partonJets.GetEntriesFast()){
    partonJet = static_cast<H1PartJet*>(partonJets[this->GetHighestPt(partonJets)]);
  }

  // find generated non dstar jet
  TObjArray genJets;
  this->GetNonDstarGenJets(dstar, genJets);
  const H1PartJet* genJet = NULL;
  if(genJets.GetEntriesFast()){
    genJet = static_cast<H1PartJet*>(genJets[this->GetHighestPt(genJets)]);
  }

  // fill parton jet
  if(partonJet) {
    this->FillHistsDstar1Jet(dstar, partonJet, fHadronisationHistsS83, weight83, -1.);
  }
  // fill generated jet
  if(genJet){
    this->FillHistsDstar1Jet(dstar, genJet, fHadronisationGenHistsS83, weight83, -1.);
  }


  // now for pur/stab
  if(!partonJet && !genJet) return;

  TLorentzVector pJet4vec;
  if(partonJet) pJet4vec = partonJet->GetFourVector();
  TLorentzVector gJet4vec;
  if(genJet) gJet4vec = genJet->GetFourVector();
  TLorentzVector pDstar = dstar->GetFourVector();

  this->FillHistsPurStab((genJet ? .5: -.5), (partonJet ? .5:-.5), fHadPurStabHists, weight83);

  const Double_t ptJetPart = (partonJet ? pJet4vec.Pt() : -1.e7);
  const Double_t ptJetGen  = (genJet    ? gJet4vec.Pt() : -1.e7);
  this->FillHistsPurStab(ptJetGen, ptJetPart, fHadPurStabHistsJetPt, weight83);
  const Double_t etaJetPart = (partonJet ? pJet4vec.Eta() : -1.e7);
  const Double_t etaJetGen  = (genJet    ? gJet4vec.Eta() : -1.e7);
  this->FillHistsPurStab(etaJetGen, etaJetPart, fHadPurStabHistsJetEta, weight83);
  const Double_t detaJetPart = (partonJet ? pDstar.Eta() - etaJetPart : -1.e7);
  const Double_t detaJetGen  = (genJet    ? pDstar.Eta() - etaJetGen  : -1.e7);
  this->FillHistsPurStab(detaJetGen, detaJetPart, fHadPurStabHistsDeta, weight83);
  const Double_t dphiJetPart = (partonJet ? 
				TMath::Abs(pDstar.DeltaPhi(pJet4vec))*TMath::RadToDeg() :-.1);
  const Double_t dphiJetGen  = (genJet    ? 
				TMath::Abs(pDstar.DeltaPhi(gJet4vec))*TMath::RadToDeg() :-.1);
  this->FillHistsPurStab(dphiJetGen, dphiJetPart, fHadPurStabHistsDphi, weight83);
  const Double_t xGamJetPart = (partonJet ? this->GetXgammaMassHelp(dstar, partonJet) : -.001);
  const Double_t xGamJetGen =  (genJet    ? this->GetXgammaMassHelp(dstar, genJet   ) : -.001); 
  this->FillHistsPurStab(xGamJetGen, xGamJetPart, fHadPurStabHistsXgam, weight83);
  const Double_t ptDsJetPart = (partonJet ? (pDstar+pJet4vec).Pt() : -1.e7);
  const Double_t ptDsJetGen  = (genJet    ? (pDstar+gJet4vec).Pt() : -1.e7);
  this->FillHistsPurStab(ptDsJetGen, ptDsJetPart, fHadPurStabHistsPtDsJet, weight83);
  const Double_t mDsJetPart = (partonJet ? (pDstar+pJet4vec).M() : -1.e7);
  const Double_t mDsJetGen  = (genJet    ? (pDstar+gJet4vec).M() : -1.e7);
  this->FillHistsPurStab(mDsJetGen, mDsJetPart, fHadPurStabHistsMDsJet, weight83);

}

//_____________________________________________________
 Bool_t GFDstarAnalyseMc::HasOffShellParton(const TObjArray *allPartMc) const
{
  // true if the event contains a parton shower parton which is off-shell
  // (or some kind of off-shell, at least...)

  if (!allPartMc) return kFALSE;

  Bool_t garbage = kFALSE;
  for(Int_t i = 0; i < allPartMc->GetEntriesFast(); ++i){
    const H1PartMC *part = static_cast<H1PartMC*>(allPartMc->At(i));
    if(part->IsStable()) continue;
    const Int_t daughter1 = part->GetDaughter1();
    const Int_t daughter2 = part->GetDaughter2();
    const H1PartMC *daughter1Ptr = 
      (daughter1 != -1 ? static_cast<H1PartMC*>(allPartMc->At(daughter1)) : NULL);
    const H1PartMC *daughter2Ptr = 
      (daughter2 != -1 ? static_cast<H1PartMC*>(allPartMc->At(daughter2)) : NULL);
    const Int_t pdg1 = (daughter1Ptr ? daughter1Ptr->GetPDG() : -1);
    const Int_t pdg2 = (daughter2Ptr ? daughter2Ptr->GetPDG() : -1);
    if(pdg1 == 91 || pdg1 == 92 || pdg2 == 91 || pdg2 == 92){// string or cluster is daughter
//   well, this means really of shell, but cf. logbook 8.11.2004:
//       TVector3 mom = part->GetMomentum();
//       if(part->GetE()*part->GetE() - mom*mom - part->GetMass()*part->GetMass() < -1.e-7){
      if(part->GetE() < part->GetMass()){
// 	part->Print("HEAD"); part->Print();
	garbage = kTRUE;
	break;
      }
    }
  }
  
  return garbage;
}

//_____________________________________________________
 H1PartJet* GFDstarAnalyseMc::GetDstarPartonJet(const TObjArray *partonJets, 
					       const H1PartMC *dstar,
					       const TObjArray *allPartMc) const
{
// returns parton level jet in input array that contains heavy quark 
// fragmenting into dstar

  H1PartJet *dstarJet = NULL;
  for(Int_t iJet = 0; iJet < partonJets->GetEntriesFast(); ++iJet){
    H1PartJet *jet = static_cast<H1PartJet*>(partonJets->At(iJet));
    for(Int_t iDaught = 0; iDaught < jet->GetNumOfParticles(); ++iDaught){
      switch(fJetFlag){
      case 0: // jets with D* as input: go on
	break;
      case 1: // jets without D* as input: no loop over daughters needed
	continue;
	break;
      default:
	this->Fatal("GetDstarPartonJet", "Don't know fJetFlag = %d", fJetFlag);
      }
      const H1PartMC *daught = static_cast<const H1PartMC*>(jet->GetParticle(iDaught));
      if((TMath::Abs(daught->GetPDG()) == 4 && daught->GetCharge() * dstar->GetCharge() > 0.)||
	 (TMath::Abs(daught->GetPDG()) == 5 && daught->GetCharge() * dstar->GetCharge() < 0.)){
	// only charm/beauty (4/5) with correct charge to become D* can define D* jet
	if(this->IsAncestor(daught, dstar, allPartMc)){
	  // we neglect the case that there may be charms from gluon splitting, too...
	  if (dstarJet) {
	    this->Error("GetDstarPartonJet", "Found second jet with quark fragmenting to D*");
	    allPartMc->Print();
	  } else {
	    dstarJet = jet;
	  }
	  break; // loop over daughters stopped
	}
      } // if daughter is heavy quark with correct charge for dstar
    } // end loop on daughters
  } // end loop on jets

  return dstarJet;
}

//_____________________________________________________
 void GFDstarAnalyseMc::CreateHistsHadronisationDsDiJet()
{
  TDirectory* oldDir = this->OpenHistsFile();
  TDirectory* dir = new TDirectory("partonDiJet", "parton level hists for D* dijet");
  dir->cd();

  // correction hists:
  fHadronisationDsDiJetHistsS83 = this->CreateHistsDstarDiJetInt(1); // 1D hists
//   ////////////////////////////////////////
//   // HACK HACK: need to manipulate dphi hist, merge the last 2 bins for FMNR:
//   const TArrayD *ar = fSteer->GetDstar1JetDphiBins();
//   TArrayD dPhiAr(ar->GetSize()-1, ar->GetArray());
//   dPhiAr[dPhiAr.GetSize()-1] = ar->At(ar->GetSize()-1);
//   delete fHadronisationDsDiJetHistsS83->At(7);

//   fHadronisationDsDiJetHistsS83->AddAt(new TH1F("dstarDiJetDphiDijet",
// 						"#Delta#phi(D*j,oj), D*-dijet",
// 						dPhiAr.GetSize()-1, dPhiAr.GetArray()), 7);
//   // end HACK
//   ////////////////////////////////////////
  GFHistManip::CallSumw2(fHadronisationDsDiJetHistsS83);
  GFHistManip::CreateAnalogHists(fHadronisationDsDiJetHistsS83,fHadronisationDsDiJetGenHistsS83,
				 "GenS83", " gen");
  GFHistManip::AddToHistsName("PartonS83", fHadronisationDsDiJetHistsS83, " parton");
  fAllHistArrays.Add(fHadronisationDsDiJetHistsS83);
  fAllHistArrays.Add(fHadronisationDsDiJetGenHistsS83);


  // pur/stab hists:
  const Int_t nBinsVs = 10;
//   const Float_t maxDevRes = 1.;
//   const Int_t nBinsRes = 60;
  // overall
  GFHistManip::ClearCreateArray(fHadPurStabDijetHists);
  fAllHistArrays.Add(fHadPurStabDijetHists);
  fHadPurStabDijetHists->AddAt(new TH1F("AllDijetGen", "D* dijet (gen)", 1, 0., 1.), 0);
  fHadPurStabDijetHists->AddAt(new TH1F("AllDijetGenPs", "D* dijet (gen && part. sh.)",  1, 0., 1.), 1);
  fHadPurStabDijetHists->AddAt(new TH1F("AllDijetNGenPs", "D* dijet (!gen && part. sh.)",  1, 0., 1.), 2);
  // no 3/4/5
  GFHistManip::AddToHistsName("S83", fHadPurStabDijetHists);
  GFHistManip::CallSumw2(fHadPurStabDijetHists);

  // Dphi
  GFHistManip::ClearCreateArray(fHadPurStabDijetHistsDphi);
  fAllHistArrays.Add(fHadPurStabDijetHistsDphi);
  const TArrayD *ar = fSteer->GetDstar1JetDphiBins();
  TArrayD dPhiAr(ar->GetSize()-1, ar->GetArray());
  dPhiAr[dPhiAr.GetSize()-1] = ar->At(ar->GetSize()-1);
  TArrayD special(dPhiAr.GetSize() +1);
  special[0] = -20.;
  for (Int_t i = 0; i < dPhiAr.GetSize(); ++i) special[i+1] = dPhiAr[i];

  fHadPurStabDijetHistsDphi->AddAt(new TH1F("DphiDijetGen", "#Delta #phi(dijets) D*+jet (Gen)", 
				       dPhiAr.GetSize()-1, dPhiAr.GetArray()), 0);
  fHadPurStabDijetHistsDphi->AddAt(new TH1F("DphiDijetGenPs", "#Delta #phi(dijets) (Gen && part. sh.)",
				       dPhiAr.GetSize()-1, dPhiAr.GetArray()), 1);
  fHadPurStabDijetHistsDphi->AddAt(new TH1F("DphiDijetNGenPs", "#Delta #phi(dijets) (!Gen && part. sh.)",
				       dPhiAr.GetSize()-1, dPhiAr.GetArray()), 2);
  fHadPurStabDijetHistsDphi->AddAt(new TH2F("DphiDijetGenVsPs", "#Delta #phi(dijets) (Gen vs part. sh.)",
//	       3*nBinsVs+1, -6., dPhiAr.At(dPhiAr.GetSize()-1),
//            3*nBinsVs+1, -6., dPhiAr.At(dPhiAr.GetSize()-1)),3);
					    special.GetSize()-1, special.GetArray(),
					    special.GetSize()-1, special.GetArray()), 3);
  // no 4/5
  GFHistManip::AddToHistsName("S83", fHadPurStabDijetHistsDphi);
  GFHistManip::CallSumw2(fHadPurStabDijetHistsDphi);

  // Xgam
  GFHistManip::ClearCreateArray(fHadPurStabDijetHistsXgam);
  fAllHistArrays.Add(fHadPurStabDijetHistsXgam);
  ar = fSteer->GetXgammaDijetBins();
  fHadPurStabDijetHistsXgam->AddAt(new TH1F("xGamDijetGen", "x_{#gamma}(dijet) D*+jet (Gen)", 
				       ar->GetSize()-1, ar->GetArray()), 0);
  fHadPurStabDijetHistsXgam->AddAt(new TH1F("xGamDijetGenPs", "x_{#gamma}(dijet) (Gen && part. sh.)",
				       ar->GetSize()-1, ar->GetArray()), 1);
  fHadPurStabDijetHistsXgam->AddAt(new TH1F("xGamDijetNGenPs", "x_{#gamma}(dijet) (!Gen && part. sh.)",
				       ar->GetSize()-1, ar->GetArray()), 2);
  fHadPurStabDijetHistsXgam->AddAt(new TH2F("xGamDijetGenVsPs", "x_{#gamma}(dijet) (Gen vs part. sh.)",
				       nBinsVs, -0.02, ar->At(ar->GetSize() -1),
				       nBinsVs, -0.02, ar->At(ar->GetSize() -1)), 3);
  // no 4/5
  GFHistManip::AddToHistsName("S83", fHadPurStabDijetHistsXgam);
  GFHistManip::CallSumw2(fHadPurStabDijetHistsXgam);

  oldDir->cd();
}

//_____________________________________________________
 void GFDstarAnalyseMc::FillHistsHadronisationDsDiJet(const H1PartMC *ds)
{
  if(!this->DstarCutLoose(ds)) return;
  if(!this->IsS83Gen(ds)) return;

  const Double_t weight83 = fWeightPt;//this->GetWeight(83, NULL);

  if(!fHadronisationDsDiJetHistsS83) this->CreateHistsHadronisationDsDiJet();

  // completely neglect events with off shell parton shower partons
  // should happen for charm excitation only...
  static H1PartMCArrayPtr partmc;
  if (this->HasOffShellParton(partmc.GetArray())) return;

  // fill parton jet
  const H1PartJet* dsJetPart = NULL;
  const H1PartJet* oJetPart = NULL;
  const Bool_t realDsJetPart = this->GetPartDiJets(ds,dsJetPart,oJetPart,partmc.GetArray());
  Bool_t partOk = kFALSE;
  if(dsJetPart && oJetPart) {
    this->FillHistsDstarDiJet(ds, dsJetPart, oJetPart, realDsJetPart,
			      fHadronisationDsDiJetHistsS83, weight83, -1.);//-1.=> 1D hist
    partOk = kTRUE;
  }

  // fill generated jet
  const H1PartJet *dsJetGen = NULL;
  const H1PartJet *oJetGen = NULL;
  const Bool_t realDsJetGen = this->GetGenDiJets(ds, dsJetGen, oJetGen);

  Bool_t genOk = kFALSE;
  if(dsJetGen && oJetGen){
    this->FillHistsDstarDiJet(ds, dsJetGen, oJetGen, realDsJetGen,
			      fHadronisationDsDiJetGenHistsS83, weight83,-1.);//-1. => s.a.
    genOk = kTRUE;
  }

  // now for pur/stab
  if(!partOk && !genOk) return;

  this->FillHistsPurStab((genOk ? .5: -.5), (partOk ? .5:-.5),fHadPurStabDijetHists,weight83);

  const Double_t dphiJetPart = 
    (partOk ? TMath::Abs(dsJetPart->GetMomentum().DeltaPhi(oJetPart->GetMomentum()))
     * TMath::RadToDeg() :-.1);
  const Double_t dphiJetGen  = 
    (genOk  ? TMath::Abs(dsJetGen ->GetMomentum().DeltaPhi(oJetGen ->GetMomentum()))
     * TMath::RadToDeg() :-.1);
  this->FillHistsPurStab(dphiJetGen, dphiJetPart, fHadPurStabDijetHistsDphi, weight83);

  const Double_t xGamJetPart = 
    (partOk ? this->GetXgammaMassDiJetHelp(ds, dsJetPart, oJetPart) : -.001);
  const Double_t xGamJetGen =
    (genOk  ? this->GetXgammaMassDiJetHelp(ds, dsJetGen,  oJetGen)  : -.001);
  this->FillHistsPurStab(xGamJetGen, xGamJetPart, fHadPurStabDijetHistsXgam, weight83);
}

//_____________________________________________________
 void GFDstarAnalyseMc::FillHistsTest(const H1PartDstar* ds)
{
  this->GFDstarAnalyse::FillHistsTest(ds);
  return;
}

//_____________________________________________________
//_____________________________________________________
//_____________________________________________________
//_____________________________________________________



//_____________________________________________________
 Bool_t GFDstarAnalyseMc::DstarCutLoose(const H1PartMC* dstar) const
{
  // just check basic D* kinematic, no check on whether we have D* -> K, pi, pi_s
  const TArrayD* eta33 = fSteer->GetEtaBins33();
  const TArrayD* eta44 = fSteer->GetEtaBins44();
  const Double_t eta = dstar->GetEta();
  return (dstar->GetPt() > fDsCutPt1 &&
	  ((eta > eta33->At(0) && eta < eta33->At(eta33->GetSize()-1))
	   || (eta > eta44->At(0) && eta < eta44->At(eta44->GetSize()-1)))
	  );
}


//_____________________________________________________
 Bool_t GFDstarAnalyseMc::DstarCutLoose(const H1PartDstar* dstar) const
{
//   static Bool_t first = kTRUE;
//   if(first){
//     this->Warning("DstarCutLoose", "manipulated to require generated D* -> K pi pi_s"); 
//     first = kFALSE;
//    DO NOT FORGET to change also D0CutLoose!!
//   }
//   Bool_t genDs = kFALSE;
//   static H1PartMCArrayPtr mcs;
//   for(Int_t i = 0; i < mcs.GetEntries(); ++i){
//     if(H1UserDstarUtil::IsDstarKPiPis(mcs[i], mcs.GetArray())){
//       // with p_t(D*) > 1.0 GeV and 15 < theta(D*) < 165 degrees
//       if(mcs[i]->GetPt() > 1.
// 	 && mcs[i]->GetTheta() > 15.*TMath::DegToRad()
// 	 && mcs[i]->GetTheta() < 165.*TMath::DegToRad()){
// 	genDs = kTRUE;
// 	break;
//       }
//     }
//   }
//   const Bool_t result = (genDs && this->GFDstarAnalyse::DstarCutLoose(dstar));
//   if(fList){
//     const Double_t dm = dstar->GetDm();
//     if(dm > 0.148 && dm < 0.15){
//       static Int_t lastRun = 0;
//       static Int_t lastEvent = 0;
//       if(lastEvent != gH1Tree->GetEventNumber() && lastRun != gH1Tree->GetRunNumber()){
// 	lastEvent = gH1Tree->GetEventNumber();
// 	lastRun = gH1Tree->GetRunNumber();
// 	fList->Enter();
//       }
//     }
//   }
//   return result;
  return this->GFDstarAnalyse::DstarCutLoose(dstar);
}

//_____________________________________________________
 Bool_t GFDstarAnalyseMc::IsS83(const H1PartDstar* ds) const
{
  //  cuts on generated y/Q^2 for ETA33 sample and recunstructed z-Vertex
  // if dstar != NULL, cuts also on special dstar values (i.e.pt)


//   static Bool_t first = kTRUE;
//   if(first){
//     this->Warning("IsS83", "manipulated to require generated D*, too"); 
//     first = kFALSE;
//   }

//   Bool_t genDs = kFALSE;
//   static H1PartMCArrayPtr mcs;
//   for(Int_t i = 0; i < mcs.GetEntries(); ++i){
//     if(H1UserDstarUtil::IsDstarKPiPis(mcs[i], mcs.GetArray())){
//       // with p_t(D*) > 1.0GeV and 15 < theta(D*) < 165 degrees
//       if(mcs[i]->GetPt() > 1.
//  	 && mcs[i]->GetTheta() > 15.*TMath::DegToRad()
//  	 && mcs[i]->GetTheta() < 165.*TMath::DegToRad()){
//  	genDs = kTRUE;
//  	break;
//       }
//     }
//   }
//   if(!genDs) return kFALSE;
/////////////////////////////////////////////

//   static Bool_t first = kTRUE;
//   if(first) {
//     this->Warning("IsS83", "DIS!");
//     first = kFALSE;
//   }

//   static H1BytePtr   subTrigL4v("Il4vst");
//   static H1BytePtr   subTrigL1ac("Il1ac");

//   return (subTrigL4v[61] && subTrigL1ac[61] && this->IsS83NoL1Check(ds));

  static H1BytePtr trigElements("Il1te");
  return (trigElements[31] && trigElements[19] && this->IsS83NoL1Check(ds));
}

//_____________________________________________________
 Bool_t GFDstarAnalyseMc::IsS83NoL1Check(const H1PartDstar* ds) const
{

  const Double_t ptCut = fSteer->GetPtBins33()->At(0);
  if(ds && ds->GetPt() <  ptCut)  return kFALSE;

//   static Bool_t first = kTRUE;
//   if(first) {
//     this->Warning("IsS83NoL1Check", "DIS!");
//     first = kFALSE;
//   }

  const Double_t y = this->GetY33();
//   static H1FloatPtr q2e("Q2e");
  return (y >= fEventCutyMinS83 && y < fEventCutyMaxS83
// 	  && *q2e > 2.
 	  && this->GetQ2gen() < fEventCutQ2Gen
 	  // && this->IsZvtxCut());
 // 	  && (!dstar || this->IsSumEt(dstar))
	  );
}

//_____________________________________________________
 Bool_t GFDstarAnalyseMc::IsS83NoL4Check(const H1PartDstar* dstar) const
{
  //  this->Warning("IsS83NoL4Check", "call usual IsS83");
  return this->IsS83(dstar);
}

//_____________________________________________________
 Bool_t GFDstarAnalyseMc::IsS84(const H1PartDstar* ds) const
{
  //  cuts on generated y/Q^2 for ETAG44 sample and recunstructed z-Vertex
  // if dstar != NULL, cuts also on special dstar values (i.e.eta)

//   static Bool_t first = kTRUE;
//   if(first){
//     this->Warning("IsS84", "manipulated to be IsS83 + generated D* close by"); 
//     first = kFALSE;
//   }
//   if(!this->IsS83(dstar)) return kFALSE;
//   static H1PartMCArrayPtr mcs;
//   for(Int_t i = 0; i < mcs.GetEntries(); ++i){
//     if(H1UserDstarUtil::IsDstarKPiPis(mcs[i], mcs.GetArray())){
//       if(mcs[i]->GetMomentum().DrEtaPhi(dstar->GetMomentum()) < 1.) return kTRUE;
//     }
//   }
//   return kFALSE;
///////////////////////////////////////

  static H1BytePtr trigElements("Il1te");
  return (trigElements[31] && trigElements[19] && this->IsS84NoL1Check(ds));
}

//_____________________________________________________
 Bool_t GFDstarAnalyseMc::IsS84NoL1Check(const H1PartDstar* ds) const
{
  if(ds && (ds->GetEta() < fSteer->GetEtaBins44()->At(0))) return kFALSE;

  if(this->GetQ2gen() >= fEventCutQ2Gen) return kFALSE;
  const Double_t y = this->GetY44();
  if(y < fEventCutyMaxS84 && y >= fEventCutyMinS84) return kFALSE;

  return kTRUE;
}

//_____________________________________________________
 Bool_t GFDstarAnalyseMc::IsS84NoL4Check(const H1PartDstar* dstar) const
{
  //  this->Warning("IsS84NoL4Check", "call usual IsS84");
  return this->IsS84(dstar);
}

//_____________________________________________________
 Bool_t GFDstarAnalyseMc::IsL4Found(Int_t hqsel45Bit, const H1PartDstar *ds, Int_t hqselMode) const
{
  // true if bit 'hqsel45Bit' of L4 charm finder is set in given mode
  // looking into offline bank YRCL 
  // ds is ignored
  static H1YrclBankPtr yrcl; // output of offline open charm finder on L4
  if(this->GFDstarAnalyse::IsL4Found(hqsel45Bit, hqselMode, yrcl)){
    return kTRUE;
//   } else if(ds && ds->GetPt() > 6.){
// //     this->Info("IsL4Found", "pt(D*) = %.2f always taken", ds->GetPt());
//     return kTRUE;
  }
  return kFALSE;
}

//_____________________________________________________
 Bool_t GFDstarAnalyseMc::IsL4Ref(Int_t subtrig) const
{
  // for 83/84 always true!

  static H1FloatPtr et33("Etag33");
  static H1FloatPtr et44("Etag44");
  static H1FloatPtr et8("Etag8");

  switch(subtrig){
  case 83: 
  case 84: 
    if(*et33 > 3. || *et44 > 5. || *et8 > 5.) return kTRUE;
    else return kFALSE;
  default:
    this->Error("IsL4Ref", "Don't know subtrigger %d", subtrig);
    return kFALSE;
  }
}


//_____________________________________________________
 Bool_t GFDstarAnalyseMc::IsS83Gen(const H1PartMC* dstar) const
{
  // true if cuts on generated y_gki and Q2_gki fullfilled
  // if dstar != NULL (NULL is default): cuts on lower pt for ETAG33 sample

  if(dstar && dstar->GetPt() < fSteer->GetPtBins33()->At(0)){
    return kFALSE;
  }
  const Double_t y = this->GetYgen();
  return (y >= fEventCutyMinS83 && y < fEventCutyMaxS83
	  && this->GetQ2gen() < fEventCutQ2Gen);
}

//_____________________________________________________
 Bool_t GFDstarAnalyseMc::IsS84Gen(const H1PartMC* dstar) const
{
  // true if cuts on generated y_gki and Q2_gki fullfilled
  // if dstar != NULL (NULL is default): cuts on lower eta for ETAG44 sample

  const Double_t y = this->GetYgen();
  const Double_t q2 = this->GetQ2gen();

  if(dstar && dstar->GetEta() < fSteer->GetEtaBins44()->At(0)){
    return kFALSE;
  }
  return (y >= fEventCutyMinS84 && y < fEventCutyMaxS84
	  && q2 < fEventCutQ2Gen);
}



//_____________________________________________________
 Double_t GFDstarAnalyseMc::GetYgen() const 
{
  static H1FloatPtr yGki("YGki");
  return *yGki;
}

//_____________________________________________________
 Double_t GFDstarAnalyseMc::GetYjbGen() const
{
  static H1FloatPtr yHfsGen("YhGen");
  return *yHfsGen;
}


//_____________________________________________________
 Double_t GFDstarAnalyseMc::GetYgenVis() const
{
  static H1PartMCArrayPtr partMc;
  static H1FloatPtr zGen("GenVtxZ");
//   const Double_t thetaLAr0 = 4./TMath::Pi();
//   const Double_t zLAr = 350;// cm
//   const Double_t radLArAt3_5m = TMath::Tan(thetaLAr0) * zLAr;
//   const Double_t thetaLAr = TMath::ATan(radLArAt3_5m / (zLAr - *zGen));
  const Double_t thetaLAr = TMath::ATan(24.4744 / (350. - *zGen));
//   const Double_t piMinusthetaSpacal0 = (180.-178.)/TMath::Pi();
//   const Double_t minusZSpacal = 150;// cm
//   const Double_t radSpacalAt1_5m = TMath::Tan(piMinusthetaSpacal0) * minusZSpacal;
  const Double_t thetaSpacal = TMath::Pi() - TMath::ATan(5.238 / (150. + *zGen));
  // no z-vertex correction...:
  const Double_t thetaSpacBar = 153.5/180. * TMath::Pi();
  const Double_t thetaBarForw = 55./180. * TMath::Pi();

  H1GetPartMCId mcFiller(partMc.GetArray(), H1Tree::Instance()->IsMC());
  Double_t eMinusPz = 0.;
  for(Int_t i = 0; i < partMc.GetEntries(); ++i){
    if(!partMc[i]->IsStable()) continue;
    const Int_t pdg = TMath::Abs(partMc[i]->GetPDG());
    if(pdg == 12 || pdg == 14 || pdg == 16) continue; // no neutrinos
    const Double_t theta = partMc[i]->GetTheta();
    if(theta < thetaLAr) continue;
    if(theta > thetaSpacal) continue;
    //even in photoproduction it may reach spacal edge...:
    if(mcFiller.IsScatElectron(i)) continue;
    const Double_t en = partMc[i]->GetE();
    // cuts and theta should be similar to GetGenEnergies() ...:
    Bool_t take = kFALSE;
    if(theta < thetaBarForw) {
      if(en > 0.2) take = kTRUE;
    } else if(theta < thetaSpacBar){
      if(en > 0.2 || (partMc[i]->GetCharge() && partMc[i]->GetPt() > 0.12)) take = kTRUE;
    } else {
      if(en > 0.1) take = kTRUE;
    }
    if(take){
      eMinusPz += partMc[i]->GetE();
      eMinusPz -= partMc[i]->GetPz();
    }
  }
  static H1FloatPtr elecBeam("BeamEnergyElec");
  Double_t y = eMinusPz / (2. * (*elecBeam));
  return y;
}

//_____________________________________________________
 Double_t GFDstarAnalyseMc::GetQ2gen() const 
{
  static H1FloatPtr q2Gki("Q2Gki");
  return *q2Gki;
}


//_____________________________________________________
 Bool_t GFDstarAnalyseMc::DstarIsGenerated(const H1PartDstar* ds) const
{
  // checks whether K/pi/pis are generated as K/pi/pis and come from proper
  // decay channel
  // FIXME: - no check done whether D0 has more than two decay products!
  //        - always assumed that (GTR[i]->GetPmo()%10000 -1) is the only mother!

  const H1Track* kaonTrack = ds->GetKaon()->GetParticle()->GetTrack();
  const H1Track* pionTrack = ds->GetPion()->GetParticle()->GetTrack();
  const H1Track* slowPionTrack = ds->GetSlowPion()->GetParticle()->GetTrack();

  const H1StrRow* strKaon = kaonTrack->GetSimulatedParticle();
  const H1StrRow* strPion = pionTrack->GetSimulatedParticle();
  const H1StrRow* strSlowPion = slowPionTrack->GetSimulatedParticle();

  H1GtrRow* gtrKaon     = strKaon ? strKaon->GetGtr() : NULL;
  H1GtrRow* gtrPion     = strPion ? strPion->GetGtr() : NULL;
  H1GtrRow* gtrSlowPion = strSlowPion ? strSlowPion->GetGtr() : NULL;


  if (gtrKaon == NULL || gtrPion == NULL || gtrSlowPion == NULL){
//     this->Warning("DstarIsGenerated", 
// 		  "STR row of K/pi/pis doesn't point to any GTR row (0x%08x / 0x%08x / 0x%08x)",
// 		  gtrKaon, gtrPion, gtrSlowPion);
    return kFALSE;
  }
  if(TMath::Abs(gtrKaon->GetPcode()) != 321
     || TMath::Abs(gtrPion->GetPcode()) != 211
     || TMath::Abs(gtrSlowPion->GetPcode()) != 211
     ){
//     this->Warning("DstarIsGenerated", "K/pi/pis are not generated, but %d/%d/%d!",
// 		  gtrKaon->GetPcode(), gtrPion->GetPcode(), gtrSlowPion->GetPcode());
    return kFALSE;
  }

  Int_t kaonMotherGtrIndex = gtrKaon->GetPmo()%10000 -1;
  Int_t pionMotherGtrIndex = gtrPion->GetPmo()%10000 -1;

  static H1GtrBankPtr gtr;   // generated tracks
  if(kaonMotherGtrIndex != pionMotherGtrIndex
     || TMath::Abs(gtr[pionMotherGtrIndex]->GetPcode()) != 421
     ){
//     this->Warning("DstarIsGenerated", 
// 		  "kaon/pion don't come from the same D0, but from GTR[%d/%d], i.e. PDG %d/%d!",
// 		  kaonMotherGtrIndex, pionMotherGtrIndex,
// 		  gtr[kaonMotherGtrIndex]->GetPcode(), gtr[pionMotherGtrIndex]->GetPcode());
    return kFALSE;
  }
  
//   Int_t gtrNum = gtr.GetEntries();
//   for(Int_t i = 0; i < gtrNum; ++i){
//     if(gtr[i]->GetPmo()%10000 -1 == kaonMotherGtrIndex
//        && gtr[i] != gtrKaon 
//        && gtr[i] != gtrPion
//        ){
//       this->Warning("DstarIsGenerated", "third particle from D0!");
//       return kFALSE;
//     } 
//   }

  Int_t d0MotherGtrIndex = gtr[kaonMotherGtrIndex]->GetPmo()%10000 -1;
  Int_t slowPionMotherGtrIndex = gtrSlowPion->GetPmo()%10000 -1;

  if(d0MotherGtrIndex != slowPionMotherGtrIndex
     || TMath::Abs(gtr[d0MotherGtrIndex]->GetPcode()) != 413
     ){
//      this->Warning("DstarIsGenerated", 
// 		   "D0/pis don't come from the same D*, but from GTR[%d/%d], i.e. PDG %d/%d!",
// 		   d0MotherGtrIndex, slowPionMotherGtrIndex,
// 		   gtr[d0MotherGtrIndex]->GetPcode(), gtr[slowPionMotherGtrIndex]->GetPcode());
     return kFALSE;
   }

  return kTRUE;
}

//_____________________________________________________
 Float_t GFDstarAnalyseMc::GetWgammaP33() const
{
  return TMath::Sqrt(this->GetY33() * this->GetCmEnergySqr());
}

//_____________________________________________________
 Float_t GFDstarAnalyseMc::GetWgammaP44() const
{
  return TMath::Sqrt(this->GetY44() * this->GetCmEnergySqr());
}
//_____________________________________________________
 Float_t GFDstarAnalyseMc::GetWgammaPgen() const
{
  return TMath::Sqrt(this->GetYgen() * this->GetCmEnergySqr());
}

//_____________________________________________________
 Float_t GFDstarAnalyseMc::GetY33() const
{
  return fY33Rec;//this->GetYgen();
}

//_____________________________________________________
 Float_t GFDstarAnalyseMc::GetY44() const
{

//   static Bool_t first = kTRUE;
//   if(first){
//     this->Warning("GetY44", "manipulated to be GetY33"); 
//     first = kFALSE;
//   }
//   return this->GetY33();

  static H1FloatPtr yjb("Yjb");
  return *yjb;
}

//_____________________________________________________
 Double_t GFDstarAnalyseMc::GetZgen(const H1PartMC *genDs) const
{

  static H1FloatPtr beamElecE("BeamEnergyElec");
  return (genDs->GetE() - genDs->GetPz())/ (2. * this->GetYgen() * (*beamElecE));

}

//_____________________________________________________
 Double_t GFDstarAnalyseMc::GetXgammaMass(const H1PartMC* dstar,const H1PartJet* jet,
					 Double_t yHfs) const
{
  // SLOW: loop over jet daughters!!!
  //
  // xgamma taking into account masses:
  // [(E-pz)_{D*} + sum_{i=1}^{N(jet daught)}(E-pz)_{i}]/2*yHfs*E_{e}
  // BUT:
  // extra (massless) formula for parton jets that overwrites yHfs!
  if(!dstar || !jet) return -1.;
  Double_t eMinPzCount = 0.;
  if(jet->GetParticle(0) && !static_cast<const H1PartMC*>(jet->GetParticle(0))->IsStable()){
    // parton jet: p-pz, overwrite y as generated y (h61 in FMNR: y_phot, massless jet...)
    const TVector3 mom(jet->GetMomentum());
    eMinPzCount = mom.Mag() - mom.Pz();
    yHfs = this->GetYgen();
  }  else {
    for(Int_t i = 0; i < jet->GetNumOfParticles(); ++i){
      eMinPzCount += jet->GetParticle(i)->GetE();
      eMinPzCount -= jet->GetParticle(i)->GetPz();
    }
  }

  eMinPzCount += dstar->GetE();
  eMinPzCount -= dstar->GetPz();

  static H1FloatPtr beamElecE("BeamEnergyElec");
  return eMinPzCount/(2. * yHfs * (*beamElecE));
}

//_____________________________________________________
 Double_t GFDstarAnalyseMc::GetXgammaMassHelp(const H1Part* dstar, 
					     const H1PartJet* jet) const
{
  if(dstar->InheritsFrom(H1PartMC::Class())){
      return this->GetXgammaMass(static_cast<const H1PartMC*>(dstar), jet, 
				 this->GetYjbGen());// yjb overwritten if parton jet!
  } else if(dstar->InheritsFrom(H1PartDstar::Class())){
      return this->GFDstarAnalyse::GetXgammaMass(static_cast<const H1PartDstar*>(dstar), 
						 jet, this->GetYjb());
  } else {
    this->Fatal("GetXgammaMassHelp", "neither H1PartMC nor H1PartDstar");
    return 0.;
  }
}

//_____________________________________________________
 Double_t GFDstarAnalyseMc::GetXgammaMassDiJet(const H1PartMC *dstar,
					      const H1PartJet *dsJet, const H1PartJet *oJet,
					      Double_t yHfs) const
{
  // SLOW: loop over jet daughters!!!
  //
  // xgamma taking into account masses
  // [(sum_{i=1}^{N(D*-jet daught)}(E-pz)_{i}] + sum_{i=j}^{N(D*-jet daught)}(E-pz)_{j}])
  //                       /2*yHfs*E_{e}
  // BUT:
  // extra (massless) formula for parton jets that overwrites yHfs!
  if(!dstar || !dsJet || !oJet) return -1.;
  static H1PartMCArrayPtr partMc;
  Double_t eMinPzCount = 0.;
  if ((oJet->GetParticle(0)
       && !static_cast<const H1PartMC*>(oJet->GetParticle(0))->IsStable())
      || (dsJet->GetParticle(0)
	  && !static_cast<const H1PartMC*>(dsJet->GetParticle(0))->IsStable())) {
    // parton jet: p-pz, overwrite y as generated y (h61 in FMNR: y_phot, massless jet...)
    // but first maybe D*
    const TVector3 p3DsJet(dsJet->GetMomentum());
    const TVector3 p3oJet(oJet->GetMomentum());
    eMinPzCount += p3DsJet.Mag();
    eMinPzCount -= p3DsJet.Pz();
    eMinPzCount += p3oJet.Mag();
    eMinPzCount -= p3oJet.Pz();
    yHfs = this->GetYgen();
  } else {
    for(Int_t i = 0; i < dsJet->GetNumOfParticles(); ++i){
      // no need to check for D*->Kpipi_s: sum of daughter E-pz is the same!
      eMinPzCount += dsJet->GetParticle(i)->GetE();
      eMinPzCount -= dsJet->GetParticle(i)->GetPz();
    }
    for(Int_t i = 0; i < oJet->GetNumOfParticles(); ++i){
      eMinPzCount += oJet->GetParticle(i)->GetE();
      eMinPzCount -= oJet->GetParticle(i)->GetPz();
    }
  }

  static H1FloatPtr beamElecE("BeamEnergyElec");
  return eMinPzCount/(2. * yHfs * (*beamElecE));
}

//_____________________________________________________
 Double_t GFDstarAnalyseMc::GetXgammaMassDiJetHelp(const H1Part *dstar,
						  const H1PartJet *dsJet, 
						  const H1PartJet *oJet) const
{
  if(dstar->InheritsFrom(H1PartMC::Class())){
    return this->GetXgammaMassDiJet(static_cast<const H1PartMC*>(dstar), dsJet, oJet,
				    this->GetYjbGen());
  } else if(dstar->InheritsFrom(H1PartDstar::Class())){
    return this->GFDstarAnalyse::GetXgammaMassDiJet(static_cast<const H1PartDstar*>(dstar),
						    dsJet, oJet, this->GetYjb());
  } else {
    this->Fatal("GetXgammaMassDiJetHelp", "neither H1PartMC nor H1PartDstar");
    return 0.;
  }
}

//_____________________________________________________
 Double_t GFDstarAnalyseMc::GetXpMass(const H1PartMC* dstar,const H1PartJet* jet) const
{
  // SLOW: loop over jet daughters!!!
  //
  // x_p taking into account masses:
  // [(E+-pz)_{D*} + sum_{i=1}^{N(jet daught)}(E+pz)_{i}]/2*E_{p}

  if(!dstar || !jet) return -1.;

  Double_t ePlusPzCount = 0.;
  for(Int_t i = 0; i < jet->GetNumOfParticles(); ++i){
    ePlusPzCount += jet->GetParticle(i)->GetE();
    ePlusPzCount += jet->GetParticle(i)->GetPz();
  }
  
  ePlusPzCount += dstar->GetE();
  ePlusPzCount += dstar->GetPz();

  static H1FloatPtr beamProtE("BeamEnergyProt");
  return ePlusPzCount/(2.* *beamProtE);
}

//_____________________________________________________
 Double_t GFDstarAnalyseMc::GetXpMassHelp(const H1Part* dstar, 
					 const H1PartJet* jet) const
{
  if(dstar->InheritsFrom(H1PartMC::Class())){
    return this->GetXpMass(static_cast<const H1PartMC*>(dstar), jet);
  } else if(dstar->InheritsFrom(H1PartDstar::Class())){
    return this->GFDstarAnalyse::GetXpMass(static_cast<const H1PartDstar*>(dstar), jet);
  } else {
    this->Fatal("GetXpMassHelp", "neither H1PartMC nor H1PartDstar");
    return 0.;
  }
}


//_____________________________________________________
 Double_t GFDstarAnalyseMc::GetGenEnergies(Double_t &forwBeam, Double_t& forward, 
					  Double_t& forwardBar, Double_t& barrel, 
					  Double_t& spacal) const
{
  // fills generated energie sums in detector region defined by some angle (cf.code)
  // returns sum of all DETECTOR regions (forwBeam not added!)
  // we take only visible energy: no neutrinos and...
  // ...cuts against low momentum particles that do not reach device 
  // in spacal region E > 0.1 || (theta > 20 && theta < 160 && pt > 0.12 && charged),
  //    Barrel        E > 0.2 || -----------------"---------------------------------,
  //    Forward       E > 0.2 || -----------------"---------------------------------

  // angles should be the same as in GFDstarAnalyse::GetRecEnergies(...)!!!
  const Double_t thetaSpac = 177. * TMath::DegToRad();
  const Double_t thetaSpacBar = 153.5 * TMath::DegToRad();
  const Double_t thetaBarForwBar = 55. * TMath::DegToRad();
  const Double_t thetaForwBarForw = 30. * TMath::DegToRad();
//   static Bool_t first = kTRUE;
//   if(first){
//     first = kFALSE;
//     this->Info("GetGenEnergies", "manipulated angles of detector regions");
//   }
//   const Double_t thetaSpacBar = 150.0 * TMath::DegToRad();
//   const Double_t thetaBarForwBar = 30. * TMath::DegToRad();
//   const Double_t thetaForwBarForw = 15. * TMath::DegToRad();
  const Double_t thetaForw = 4.5 * TMath::DegToRad();
  const Double_t thetaForwBeam = 1. * TMath::DegToRad();

  forwBeam = forward = forwardBar = barrel = spacal = 0.;

  static H1PartMCArrayPtr partMc;
  for(Int_t i = 0; i < partMc.GetEntries(); ++i){
    // cuts should be the same in GetYgenVis()
    if(!partMc[i]->IsStable()) continue;
    const Int_t pdg = TMath::Abs(partMc[i]->GetPDG());
    if(pdg == 12 || pdg == 14 || pdg == 16) continue; // no neutrinos
    const Double_t theta = partMc[i]->GetTheta();
    const Double_t en = partMc[i]->GetE();
    const Bool_t isOkTrack = (theta > 20.*TMath::DegToRad() && theta < 160.*TMath::DegToRad() 
			      && partMc[i]->GetCharge() && partMc[i]->GetPt() > 0.12);
    if(theta < thetaForwBeam) continue;
    else if(theta < thetaForw){
      forwBeam += en;
    } else if(theta < thetaForwBarForw){
      if(en > 0.2 || isOkTrack) forward += en;
    } else if(theta < thetaBarForwBar){
      if(en > 0.2 || isOkTrack) forwardBar += en;
    } else if(theta < thetaSpacBar){
      if(en > 0.2 || isOkTrack) barrel += en;
    } else if(theta < thetaSpac){
      if(en > 0.1 || isOkTrack) spacal += en;
    }
  }

  return forward + forwardBar + barrel + spacal;
}

//_____________________________________________________
 void GFDstarAnalyseMc::SwitchOffExtraW() 
{
  // delete a potential additional weight function (only CASCADE has one so far...)
  if(fWeightFunc) this->Info("SwitchOffExtraW", "weighting removed");
  delete fWeightFunc; 
  fWeightFunc = NULL;
}

//_____________________________________________________
 Bool_t GFDstarAnalyseMc::SetWeight()
{
  // weights, y33rec,...

  if(gH1Tree->GetRunNumber() < 244968 || gH1Tree->GetRunNumber() > 279215){
    this->Warning("SetWeight", "ET33-smearing does not know run %d", gH1Tree->GetRunNumber());
  }

  const Double_t yGen = this->GetYgen();
  //smearing y33rec according to https://www.desy.de/~levonian/lumi_cal.html
  static H1FloatPtr elecBeam("BeamEnergyElec");
  const Double_t e33Gen = *elecBeam * (1. - yGen); // 0.18: mean value for 99e+/2000
  const Double_t e33Rec = gRandom->Gaus(e33Gen, 0.18*TMath::Sqrt(e33Gen) + 0.01*e33Gen);
  fY33Rec = 1. -  e33Rec / *elecBeam;
  //no smearing  fY33Rec = yGen;

  H1ElectronTagger* tag = static_cast<H1ElectronTagger*>
    (H1DBManager::Instance()->GetDBEntry(H1ElectronTagger::Class()));
  fWeight83 = tag->Acceptance33(yGen);
  fWeight83 *= fInversePrescale33;
  fWeight84 = tag->Acceptance44(yGen);
  fWeight84 *= fInversePrescale44;
  // FillHistsGen assumes that 'tag->Acceptance44(this->GetYgen())' is factor in fWeight84!!!
  // and                       'tag->Acceptance33(this->GetYgen())' is factor in fWeight83!!!

//   static Bool_t first = kTRUE;
//   if(first){
//     this->Warning("SetWeight", "manipulated: fWeight84 = fWeight83"); 
//     first = kFALSE;
//     fWeight84 = fWeight83;
//   }

  if(!fWeightFunc) {
    fWeightPt = 1.;
    return kTRUE;
  }

  static H1PartMCArrayPtr partMc;
  H1PartMC *dstarGen[2] = {NULL, NULL};
  for(Int_t i = 0; i < partMc.GetEntries(); ++i){
    if(H1UserDstarUtil::IsDstarKPiPis(partMc[i], partMc.GetArray())){
      if(!dstarGen[0]) dstarGen[0] = partMc[i];
      else if(!dstarGen[1]) dstarGen[1] = partMc[i];
      else {
	this->Warning("SetWeight", "Found a 3rd generated D*->Kpipi, take weight from 1+2");
	break;
      }
    }
  }
  if(!dstarGen[0]) {
    this->Warning("SetWeight", "No generated D* in Kpipi, skip event?");
    return kFALSE;
  }

  Double_t pt = dstarGen[0]->GetPt();
  if(dstarGen[1]) pt = (pt + dstarGen[1]->GetPt())/2.;

  fWeightPt = fWeightFunc->Eval(pt);

  return kTRUE;
}


//_____________________________________________________
 Double_t GFDstarAnalyseMc::GetWeight(Int_t trigger, const H1PartDstar *ds) const
{
  const Double_t dsW = (ds ? this->GetEffCorrFactor(ds) : 1.);
  if(trigger == 84){
    return fWeight84 * dsW * fWeightPt;
  } else if(trigger == 83){
    return fWeight83 * dsW * fWeightPt;
  } else {
    return 1. * dsW;
  }
}

//_____________________________________________________
 Bool_t GFDstarAnalyseMc::GetHeavyQuarks(H1PartMC*& quark, H1PartMC*& antiQuark) const 
{
  // find the quarks coming from the hard process

  static H1PartMCArrayPtr genPart("QuarkPartons");
  if(genPart.GetEntries() < 2) return kFALSE;
  
  quark  = genPart[0];
  antiQuark  = genPart[1];

  return (quark && antiQuark);
}

//_____________________________________________________
 Double_t GFDstarAnalyseMc::Associate(const H1Part* ref1, const H1Part* ref2, 
				     H1PartMC*& outCloseTo1, H1PartMC*& outCloseTo2)
{
  // taking outCloseTo1/2 as input, which combination 
  //       (ref1 <-> outCloseTo1 + ref2 <-> outCloseTo2)
  // or    (ref1 <-> outCloseTo2 + ref2 <-> outCloseTo1)
  // gives the minimal sum of eta-phi distances.
  // outCloseTo1/2 are changed that 1 is the one for ref1, analog for2,
  // return sum of distances.
  const TVector3 ref1Mom = ref1->GetMomentum();
  const TVector3 ref2Mom = ref2->GetMomentum();
  const TVector3 out1Mom = outCloseTo1->GetMomentum();
  const TVector3 out2Mom = outCloseTo2->GetMomentum();

  const Double_t dist11_22 = ref1Mom.DeltaR(out1Mom) + ref2Mom.DeltaR(out2Mom);
  const Double_t dist12_21 = ref1Mom.DeltaR(out2Mom) + ref2Mom.DeltaR(out1Mom);
  
  if(dist11_22 <= dist12_21){
    return dist11_22;
  } else {
    H1PartMC* temp = outCloseTo1;
    outCloseTo1 = outCloseTo2;
    outCloseTo2 = temp;
    return dist12_21;
  }

}

//_____________________________________________________
 TObjArray GFDstarAnalyseMc::GetGenJets() const
{
  // returns array of jets surviving the cuts, sorted in eta

  static H1PartJetArrayPtr dstarJets("DstarGenJets");
  static H1PartJetArrayPtr noDstarJets("KtGenJets");
  TObjArray *myJets = NULL;
  switch(fJetFlag){
  case 0:
    myJets = dstarJets.GetArray();//H1UserDstarAccess::DstarGenJets();
    break;
  case 1: 
    myJets = noDstarJets.GetArray();
    break;
  default:
    this->Fatal("GetGenJets", "Don't know fJetFlag = %d", fJetFlag);
  }

  TArrayD etas(myJets->GetEntriesFast());
  TObjArray jets(etas.GetSize());

  // fill array with jets passing cuts
//   Bool_t tightCut = kTRUE;
  for(Int_t i = 0; i < etas.GetSize(); ++i){
    H1PartJet* jet = static_cast<H1PartJet*>(myJets->At(i));
    if(this->JetCut(jet)){//, tightCut)){
      etas[jets.GetEntriesFast()] = jet->GetEta(); // before Add(jet)!!
      jets.Add(jet);
//       tightCut = kFALSE; // further jets with looser cuts...
    }
  }

  // now sort in eta:
  etas.Set(jets.GetEntriesFast()); // shorten 
  TArrayI indices(etas.GetSize());
  TMath::Sort(etas.GetSize(), etas.GetArray(), indices.GetArray(), kFALSE); // upwart!

  //fill output
  TObjArray result(etas.GetSize());
  for(Int_t i = 0; i < etas.GetSize(); ++i){
    result.Add(jets[indices[i]]);
  }

  return result;
} 


//_____________________________________________________
 Int_t GFDstarAnalyseMc::GetNonDstarGenJets(const H1PartMC* dstar, 
					   TObjArray& jets) const
{
  // array of generator (hadron) jets passing the minimal criteria and NOT containing 'dstar'
  // will be put into 'jets'
  // ordered in eta: most backward first!
  // 
  // returns the index of the jet, that comes after the D*
  // if we put the D* into the list, too:
  // 
  //-1: no jets left
  // 0: D* more backwards than most backward jet
  // 1: D* between most backward and next more forward jet
  // 2: etc.

  Int_t posDstar = -1;
  jets.Clear();
  //  if(!dstar) return posDstar;

  // if you change something here, do it analog in GFDstarAnalyse::GetNonDstarJets(...) !

//   const Double_t oldHighPtCut = fSteer->GetJetHigherPtCut();
//   fSteer->SetJetHigherPtCut(0.); // manipulate...

  TObjArray allJets = this->GetGenJets();
//   fSteer->SetJetHigherPtCut(oldHighPtCut);

  for(Int_t i = 0; i < allJets.GetEntriesFast(); ++i){
    H1PartJet* jet = static_cast<H1PartJet*>(allJets[i]);
    if(!jet->Contains(dstar)){
//       if(TMath::Abs(jet->GetMomentum().DeltaPhi(dstar->GetMomentum())) > TMath::Pi()/2.){
	jets.Add(jet);
//       } else {
//  	static Int_t first = 0;
//  	static H1PartJet *oldJet = NULL;
//  	if(jet->GetPt() > 3. && oldJet != jet && first++ < 5){
//  	  this->Info("GetNonDstarGenJets", 
//  		     "exclude jets: deltaR(D*+j) %.3f, dphi %.3f, deta %.3f (%d)", 
//  		     jet->GetMomentum().DeltaR(dstar->GetMomentum()), 
//  		     jet->GetMomentum().DeltaPhi(dstar->GetMomentum()), 
//  		     jet->GetEta() - dstar->GetEta(),
//  		     first);
// 	  cout << "gen D*: theta = " << dstar->GetTheta()*TMath::RadToDeg() << " phi = "
// 	       << dstar->GetPhi()*TMath::RadToDeg() 
// 	       << " eta = " << dstar->GetEta() << endl; 
// 	  dstar->Print();
// 	  cout << "gen jet: theta = " << jet->GetTheta()*TMath::RadToDeg() << endl;
// 	  jet->Print();
// 	  cout << endl << endl;
//  	  oldJet = jet;
//  	}
//       }
    }
  }


//   // start specials for Jeannine
//   static Bool_t first = kTRUE;
//   if(first){
//     this->Info("GetNonDstarGenJets", "Require at least 2 or asymm pt cuts/dijet mass cut");
//     first = kFALSE;
//   }
//   if(jets.GetEntriesFast() < 2) {
//     jets.Clear();
//   } else {
//     // asymm pt cuts
// //     H1PartJet *higherPtJet = static_cast<H1PartJet*>(jets[this->GetHighestPt(jets)]);
// //     if(fSteer->GetDstar1JetPtBins()->At(0) > higherPtJet->GetPt()+1.) {
// //       jets.Clear();
// //     }
//     // dijet cuts
//     this->RemoveLowPt(&jets, 2);
//     const H1PartJet *jet1 = static_cast<H1PartJet*>(jets[0]);
//     const H1PartJet *jet2 = static_cast<H1PartJet*>(jets[1]);
//     TLorentzVector pJ1 = jet1->GetFourVector();
//     TLorentzVector pJ2 = jet2->GetFourVector();
//     const Double_t cosTheta = TMath::TanH((pJ1.Eta() - pJ2.Eta())/2.);
//     const Double_t dijetMass = (pJ1.E() + pJ2.E())/TMath::Sqrt(1.-cosTheta*cosTheta);
//     if(dijetMass < 18. || TMath::Abs(pJ1.Eta() + pJ2.Eta())/2. < 0.7){
//       jets.Clear();
//     }
//   }
//   // end specials for Jeannine

  if(jets.GetEntriesFast()) posDstar = 0;
  const Double_t etaDs = dstar ?  dstar->GetEta() : -1.e7;
  for(Int_t i = 0; i < jets.GetEntriesFast(); ++i){
    H1PartJet* jet = static_cast<H1PartJet*>(jets[i]);
    if(etaDs > jet->GetEta()) ++posDstar;
  }

  return posDstar;
}

//_____________________________________________________
 Bool_t GFDstarAnalyseMc::GetGenDiJets(const H1PartMC* dstar, const H1PartJet *&dsJet,
				      const H1PartJet *&oJet) const
{
  // dsJet and oJet are set (possibly only one of them!)
  // return kFALSE if dstar not in dsJet (i.e. dsJet is closer than oJet to D*)

  dsJet = oJet = NULL;

  TObjArray jets = this->GetGenJets();
  const Int_t nJet = this->RemoveLowPt(&jets, 2);
  if(nJet == 0) return kFALSE;
  H1PartJet *jet1 = static_cast<H1PartJet*>(jets[0]);
  H1PartJet *jet2 = (nJet > 1 ? static_cast<H1PartJet*>(jets[1]) : NULL);

  Bool_t realDsJet = kTRUE;
  if(jet1->Contains(dstar)){
    dsJet = jet1;
    oJet = jet2;
  } else if(jet2 && jet2->Contains(dstar)){
    dsJet = jet2;
    oJet = jet1;
  } else {
    realDsJet = kFALSE;
    if(!jet2){
      dsJet = jet2;// jet2 == NULL anyway
      oJet = jet1;
    } else {
      // this->Warning("GetGenDiJets", "D* not in first two jets");
      if(jet1->GetMomentum().DeltaR(dstar->GetMomentum()) 
	 < jet2->GetMomentum().DeltaR(dstar->GetMomentum())){
	dsJet = jet1; 
	oJet = jet2; 
      } else {
	dsJet = jet2; 
	oJet = jet1; 
      }
    }
  }

  if ((dsJet && dsJet->GetPt() > fSteer->GetDstar1JetPtBins()->At(0) + 1.)
      || (oJet && oJet->GetPt() > fSteer->GetDstar1JetPtBins()->At(0) + 1.)) {
    return realDsJet;
  } else {
    dsJet = oJet = NULL;
    return kFALSE;
  }
}


//_____________________________________________________
 Bool_t GFDstarAnalyseMc::GetPartDiJets(const H1PartMC* dstar, const H1PartJet *&dsJet,
				       const H1PartJet *&oJet, 
				       const TObjArray *allPartMc) const
{
  // dijets on parton level (after shower)
  // dsJet and oJet are set (possibly only one of them!)
  // return kFALSE if the parton hadronsing into the D* is not
  // in dsJet (than dsJet is defined as being closer to D* than oJet)

  dsJet = oJet = NULL;

  TObjArray jets = this->GetPartonJets();
  const Int_t nJet = this->RemoveLowPt(&jets, 2);
  if (nJet == 0) return kFALSE;
  H1PartJet *jet1 = static_cast<H1PartJet*>(jets[0]);
  H1PartJet *jet2 = (nJet > 1 ? static_cast<H1PartJet*>(jets[1]) : NULL);
  dsJet = this->GetDstarPartonJet(&jets, dstar, allPartMc);

  Bool_t realDsJet = kTRUE;
  if (jet1 == dsJet) { // i.e. && dsJet since jet1 != NULL for sure!
    oJet = jet2;
  } else if (jet2 && jet2 == dsJet) {
    oJet = jet1;
  } else {
    realDsJet = kFALSE;
    if (!jet2) {
      dsJet = jet2;// jet2 == NULL anyway
      oJet = jet1;
    } else {
      //this->Warning("GetPartDiJets", "D* not in first two jets");
      if (jet1->GetMomentum().DeltaR(dstar->GetMomentum()) 
	 < jet2->GetMomentum().DeltaR(dstar->GetMomentum())) {
	dsJet = jet1; 
	oJet = jet2; 
      } else {
	dsJet = jet2; 
	oJet = jet1; 
      }
    }
  }

  if ((dsJet && dsJet->GetPt() > fSteer->GetDstar1JetPtBins()->At(0) + 1.)
      || (oJet && oJet->GetPt() > fSteer->GetDstar1JetPtBins()->At(0) + 1.)) {
    return realDsJet;
  } else {
    dsJet = oJet = NULL;
    return kFALSE;
  }
}

//_____________________________________________________
 TObjArray GFDstarAnalyseMc::GetPartonJets() const
{
  
  TObjArray partonJets;
  static H1PartJetArrayPtr partonJetsPtr("PartonJets");
  TObjArray *jets = partonJetsPtr.GetArray();//H1UserDstarAccess::PartonJets();
  TIter next(jets);
  while(H1PartJet *jet = static_cast<H1PartJet*>(next())){
    if(this->JetCut(jet)) {
      // now check
      partonJets.Add(jet);
    }
  }

//   // start specials for Jeannine
//   static Bool_t first = kTRUE;
//   if(first){
//     this->Info("GetPartonJets", "Require at least 2 or asymm pt cuts/dijet cut");
//     first = kFALSE;
//   }
//   if(partonJets.GetEntriesFast() < 2) {
//     partonJets.Clear();
//   } else {
//     // asymm pt cut:
// //  H1PartJet *higherPtJet =static_cast<H1PartJet*>(partonJets[this->GetHighestPt(partonJets)]);
// //     if(fSteer->GetDstar1JetPtBins()->At(0) > higherPtJet->GetPt()+1.) {
// //       partonJets.Clear();
// //     }
//     // dijet cuts
//     this->RemoveLowPt(&partonJets, 2);
//     const H1PartJet *jet1 = static_cast<H1PartJet*>(partonJets[0]);
//     const H1PartJet *jet2 = static_cast<H1PartJet*>(partonJets[1]);
//     TLorentzVector pJ1 = jet1->GetFourVector();
//     TLorentzVector pJ2 = jet2->GetFourVector();
//     const Double_t cosTheta = TMath::TanH((pJ1.Eta() - pJ2.Eta())/2.);
//     const Double_t dijetMass = (pJ1.E() + pJ2.E())/TMath::Sqrt(1.-cosTheta*cosTheta);
//     if(dijetMass < 18. || TMath::Abs(pJ1.Eta() + pJ2.Eta())/2. < 0.7){
//       partonJets.Clear();
//     }
//   }
//   // end specials for Jeannine


  return partonJets;
}

//_____________________________________________________
 const H1PartMC* GFDstarAnalyseMc::GetCloseGenDsKpipi(const H1Part* ds, Option_t *opt) const
{
  // returns closest same charged D*->Kpipi on generator level to ds, 
  TString option(opt);
  const Bool_t cut = option.Contains("C", TString::kIgnoreCase); 
  const Bool_t cut83 = option.Contains("83");
  const Bool_t cut84 = option.Contains("84");

  static H1PartMCArrayPtr partmc;
  TObjArray dstars;
  for(Int_t i = 0; i < partmc.GetEntries(); ++i){
    if(H1UserDstarUtil::IsDstarKPiPis(partmc[i], partmc.GetArray())){
      if(TMath::Abs(ds->GetCharge() - partmc[i]->GetCharge()) < 1.e-7){
	Bool_t add = kTRUE;
	if(cut && !this->DstarCutLoose(partmc[i])) add = kFALSE;
	if(cut83 && !this->IsS83Gen(partmc[i])) add = kFALSE;
	if(cut84 && !this->IsS84Gen(partmc[i])) add = kFALSE;
	if(add) dstars.Add(partmc[i]);
// 	else {
// 	  partmc[i]->Print("HEAD");// FIXME PRINT
// 	  partmc[i]->Print();// FIXME PRINT
// 	}
      }
    }
  }

  if(dstars.GetEntriesFast() == 1){
    return static_cast<H1PartMC*>(dstars[0]);
  } else if(dstars.GetEntriesFast() == 2) {
    return static_cast<const H1PartMC*>(this->GetCloser(ds, static_cast<H1Part*>(dstars[0]), 
							static_cast<H1Part*>(dstars[1])));
  } else { // 0 or 3, 4, ...
    H1PartMC* closest = NULL;
    Float_t minDist = FLT_MAX;
    for(Int_t i = 0; i < dstars.GetEntriesFast(); ++i){
      Float_t dist = 0.;
      this->GetCloser(ds, static_cast<H1Part*>(dstars[i]), NULL, &dist);
      if(dist < minDist){
	closest = static_cast<H1PartMC*>(dstars[i]);
	minDist = dist;
      }
    }
    return closest;
  }
}


//_____________________________________________________
 Bool_t GFDstarAnalyseMc::IsAncestor(const H1PartMC *const ancest, const H1PartMC *part,
				    const TObjArray *allMc) const
{
  // check whether ancest is a mother or grandmother or whatever generation of ancestors 
  // of part, allMc must be the array from H1PartMCArrayPtr 
  // (ancest and part must be from this array and not a copy!)

  // implemented as recursive method!
  if(!ancest || !part || !allMc) return kFALSE;

  Int_t mother1 = part->GetMother1();
  Int_t mother2 = part->GetMother2();
  if(mother1 < 0){
    if(mother2 < 0) return kFALSE;// no mothers
    mother1 = mother2; // only one mother, the 2nd (???)
  } else {
    if(mother2 < 0) mother2 = mother1;// only one mother, the 1st
    else if(mother1 > mother2){ // wrong order
      const Int_t temp = mother1;
      mother1 = mother2;
      mother2 = temp;
    }
  }
  for(Int_t i = mother1; i <= mother2; ++i){
    const H1PartMC *mother = static_cast<H1PartMC*>(allMc->At(i));
    if(mother == ancest || this->IsAncestor(ancest, mother, allMc)) return kTRUE;
  }

  return kFALSE;
}

//_____________________________________________________
 Double_t GFDstarAnalyseMc::GetEffCorrFactor(const H1PartDstar *ds) const
{
  // Sebastian's efficiency correction for whole D*
  if(!ds) return 1.;
  Double_t weight = this->GetEffCorrFactor(ds->GetKaon()->GetPt(), ds->GetKaon()->GetTheta());
  weight *= this->GetEffCorrFactor(ds->GetPion()->GetPt(), ds->GetPion()->GetTheta());
  weight *= this->GetEffCorrFactor(ds->GetSlowPion()->GetPt(), ds->GetSlowPion()->GetTheta());
  
  return weight;
}

//_____________________________________________________
 Double_t GFDstarAnalyseMc::GetEffCorrFactor(Double_t pt, Double_t theta) const
{
  // Sebastian's efficiency correction for a track with pt and theta
  
  if(pt >= 5.) return 1.;

  TH2 *h = const_cast<TH2*>(pt > 1.5 ? fHistEffCorrHighPt : fHistEffCorrLowPt);
  const Double_t weight = h->GetBinContent(h->FindBin(pt, theta));// FindBin not const!!!
  if(weight != 0) {
    return 1./weight;
  } else {
    this->Error("GetEffCorrFactor", "got 0 for pt/theta %.3f/%.1f", pt,theta*TMath::RadToDeg());
    return 1.;
  }
//       real function trackweight (mode, pttrack, thetatrack)
//       implicit none
// *      include 'hqpawcommon'
// *      include 'hqdivcommon'
// *      include 'mycommon'
//       integer mode
//       real pttrack, thetatrack, hxy
//      
//       trackweight = 1.
//      
//       if (pttrack.lt.1.5) then      
//         trackweight = 1./hxy(1226,pttrack,thetatrack)
//       elseif (pttrack.lt.5.0) then
//         trackweight = 1./hxy(1206,pttrack,thetatrack)
//       else
//         trackweight = 1.  
//       endif
//         
//       if (mode.eq.1) then
// c        trackweight = 1.
//       elseif (mode.eq.2) then
// c        trackweight = 1.
//       elseif (mode.eq.3.) then
//       else 
//         print *, 'trackweight: mode invalid'
//       endif      
//      
//       return 
//       end
}


ROOT page - Class index - Top of the page

This page has been automatically generated. If you have any comments or suggestions about the page layout send a mail to ROOT support, or contact the developers with any questions or problems regarding ROOT.