// ****************************************************************
//XXX: main
int main(int argc, char* argv[])
{
  //
  // **** May 20 2010 update ****
  // Usage: CreateEcalTimingCalibsEB fileWithTree options...
  //

  using namespace std;
  // Ao dependent timing corrections
  // By the definition of these corrections, the timing should be zero for the hits in
  // Module 1 or Low eta EE within the valid A/sigma ranges.
  // Earlier data will have positive time due to the gradual timing shifts in the positive direction.
  timeCorrectionEB_ = new TF1("timeCorrectionEB_","pol4(0)",0,1.2);
  //coefficients obtained in the interval (0, 1.5) from Module 1 of run 144011 EB data; 
  timeCorrectionEB_->SetParameters(0.0399144,-1.32993,2.00013,-1.51769,0.407406);
  //coefficients obtained in the interval (-0.5, 2.0)
  //timeCorrectionEB_->SetParameters(0.0544539,-1.51924,2.57379,-2.11848,0.606632);

  // For selection cuts
  string inBxs, inOrbits, inTrig, inTTrig, inLumi, inRuns;
  float avgTimeMin, avgTimeMax;
  float minAmpEB, minAmpEE;
  float maxSwissCrossNoise;  // EB only, no spikes seen in EE
  float maxHitTimeEB, minHitTimeEB;
  // init to sensible defaults
  avgTimeMin = -1; // in ns
  avgTimeMax = 1; // in ns
  minAmpEB = 5; // GeV
  minAmpEE = 5; // GeV
  maxHitTimeEB = 15; // ns
  minHitTimeEB = -15; // ns
  maxSwissCrossNoise = 0.95; // EB only
  inBxs = "-1";
  inOrbits = "-1";
  inTrig = "-1";
  inTTrig = "-1";
  inLumi = "-1";
  inRuns = "-1";

  char* infile = argv[1];
  if (!infile)
  {
    cout << " No input file specified !" << endl;
    return -1;
  }

  //TODO: Replace this with the parseArguments function from the pi0 binary
  std::string stringGenericOption    = "--";
  for (int i=1 ; i<argc ; i++) {
    if (argv[i] == std::string("-bxs") && argc>i+1) inBxs = std::string(argv[i+1]);
    if (argv[i] == std::string("-orbits") && argc>i+1) inOrbits = std::string(argv[i+1]);
    if (argv[i] == std::string("-trig") && argc>i+1) inTrig = std::string(argv[i+1]);
    if (argv[i] == std::string("-ttrig") && argc>i+1) inTTrig = std::string(argv[i+1]);
    if (argv[i] == std::string("-lumi") && argc>i+1) inLumi = std::string(argv[i+1]);
    if (argv[i] == std::string("-runs") && argc>i+1) inRuns = std::string(argv[i+1]);
    if (argv[i] == std::string("-ebampmin") && argc>i+1) minAmpEB = atof(argv[i+1]);
    if (argv[i] == std::string("-eeampmin") && argc>i+1) minAmpEE = atof(argv[i+1]);
    if (argv[i] == std::string("-swisskmax") && argc>i+1) maxSwissCrossNoise = atof(argv[i+1]);
    if (argv[i] == std::string("-avgtimemin") && argc>i+1) avgTimeMin = atof(argv[i+1]);
    if (argv[i] == std::string("-avgtimemax") && argc>i+1) avgTimeMax = atof(argv[i+1]);
    if (argv[i] == std::string("-ebhittimemax") && argc>i+1) maxHitTimeEB = atof(argv[i+1]);
    if (argv[i] == std::string("-ebhittimemin") && argc>i+1) minHitTimeEB = atof(argv[i+1]);
    // handle here the case of multiple arguments for input files
    if (argv[i] == std::string("--i"))// && argc>i+1)
    {
      for (int u=i+1; u<argc; u++)
      {
        if ( 0==std::string(argv[u]).find( stringGenericOption ) )
        {
          if ( 0==listOfFiles_.size())  {std::cout << "no input files listed" << std::cout;}
          else  {std::cout << "no more files listed, found: " << argv[u] << std::cout;}
          break;
        }
        else
        {
          listOfFiles_.push_back(argv[u]);
          i++;
        }
      }// loop on arguments following --i
      continue;
    }//end 'if input files'

  }
  // Open the input files
  if (listOfFiles_.size()==0){
    std::cout << "\tno input file found" << std::endl;
    return(1);
  }
  else{
    std::cout << "\tfound " << listOfFiles_.size() << " input files: " << std::endl;
    for(std::vector<std::string>::const_iterator  file_itr=listOfFiles_.begin(); file_itr!=listOfFiles_.end(); file_itr++){
      std::cout << "\t" << (*file_itr) << std::endl;
    }
  }
  // Tree construction
  TChain* chain = new TChain ("EcalTimeAnalysis") ;
  std::vector<std::string>::const_iterator file_itr;
  for(file_itr=listOfFiles_.begin(); file_itr!=listOfFiles_.end(); file_itr++){
    chain->Add( (*file_itr).c_str() );
  }


  cout << "Running with options: "
    << "avgTimeMin: " << avgTimeMin << " avgTimeMax: " << avgTimeMax
    << " minAmpEB: " << minAmpEB << " minAmpEE: " << minAmpEE
    << " maxSwissCrossNoise (EB): " << maxSwissCrossNoise
    << " maxHitTimeEB: " << maxHitTimeEB << " minHitTimeEB: " << minHitTimeEB                                                                   
    << " inTrig: " << inTrig << " inTTrig: " << inTTrig << " inLumi: " << inLumi 
    << " inBxs: " << inBxs << " inRuns: " << inRuns << " inOrbits: " << inOrbits
    << endl;

  // Ignore warnings
  gErrorIgnoreLevel = 2001;

  setBranchAddresses(chain,treeVars_);

  // Generate all the vectors for skipping selections
  std::vector<std::vector<double> > bxIncludeVector;
  std::vector<std::vector<double> > bxExcludeVector;
  std::vector<std::vector<double> > orbitIncludeVector;
  std::vector<std::vector<double> > orbitExcludeVector;
  std::vector<std::vector<double> > trigIncludeVector;
  std::vector<std::vector<double> > trigExcludeVector;
  std::vector<std::vector<double> > ttrigIncludeVector;
  std::vector<std::vector<double> > ttrigExcludeVector;
  std::vector<std::vector<double> > lumiIncludeVector;
  std::vector<std::vector<double> > lumiExcludeVector;
  std::vector<std::vector<double> > runIncludeVector;
  std::vector<std::vector<double> > runExcludeVector;
  //recall: string inBxs, inOrbits, inTrig, inTTrig, inLumi, inRuns;
  genIncludeExcludeVectors(inBxs,bxIncludeVector,bxExcludeVector);
  genIncludeExcludeVectors(inOrbits,orbitIncludeVector,orbitExcludeVector);
  genIncludeExcludeVectors(inTrig,trigIncludeVector,trigExcludeVector);
  genIncludeExcludeVectors(inTTrig,ttrigIncludeVector,ttrigExcludeVector);
  genIncludeExcludeVectors(inLumi,lumiIncludeVector,lumiExcludeVector);
  genIncludeExcludeVectors(inRuns,runIncludeVector,runExcludeVector);

  // Open output file and book hists
  string fileNameBeg = "timingCalibsEB";
  string rootFilename = fileNameBeg+".root";
  TFile* outfile = new TFile(rootFilename.c_str(),"RECREATE");
  outfile->cd();

  TH1F* calibHistEB = new TH1F("timingCalibsEB","timingCalibs EB [ns]",2000,-100,100);
  TH1F* calibErrorHistEB = new TH1F("calibErrorEB","timingCalibError EB [ns]",500,0,5);
  calibHistEB->Sumw2();
  calibErrorHistEB->Sumw2();

  TH2F* calibsVsErrors = new TH2F("timingCalibsAndErrors","TimingCalibs vs. errors [ns]",500,0,5,100,0,10);
  calibsVsErrors->Sumw2();

  TH1F* expectedStatPresHistEB = new TH1F("expectedStatPresEB","Avg. expected statistical precision EB [ns], all crys",200,0,2);
  TH2F* expectedStatPresVsObservedMeanErrHistEB = new TH2F("expectedStatPresVsObsEB","Expected stat. pres. vs. obs. error on mean each event EB [ns]",200,0,2,200,0,2);
  TH1F* expectedStatPresEachEventHistEB = new TH1F("expectedStatPresSingleEventEB","Expected stat. pres. each event EB [ns]",200,0,2);
  
  TH2F* errorOnMeanVsNumEvtsHist = new TH2F("errorOnMeanVsNumEvts","Error_on_mean vs. number of events",50,0,50,200,0,2);
  errorOnMeanVsNumEvtsHist->Sumw2();

  TH1F* hitsPerCryHistEB = new TH1F("hitsPerCryEB","Hits used in each crystal;hashedIndex",61200,0,61200);
  TH2F* hitsPerCryMapEB = new TH2F("hitsPerCryMapEB","Hits used in each crystal;i#phi;i#eta",360,1.,361.,172,-86,86);

  TProfile2D* ampProfileMapEB = new TProfile2D("ampProfileMapEB","amp profile map [ADC];i#phi;i#eta",360,1.,361.,172,-86,86);
  TProfile* ampProfileEB = new TProfile("ampProfileEB","Average amplitude in cry [ADC];hashedIndex",61200,0,61200);

  TH1F* sigmaHistEB = new TH1F("sigmaCalibsEB"," Sigma of calib distributions EB [ns]",100,0,1);

  //=============Special Bins for TT and Modules borders=============================
  double ttEtaBins[36] = {-85, -80, -75, -70, -65, -60, -55, -50, -45, -40, -35, -30, -25, -20, -15, -10, -5, 0, 1, 6, 11, 16, 21, 26, 31, 36, 41, 46, 51, 56, 61, 66, 71, 76, 81, 86 };
  // double modEtaBins[10]={-85, -65, -45, -25, 0, 1, 26, 46, 66, 86};
  double ttPhiBins[73];
  double modPhiBins[19];
  double timingBins[79];
  double highEBins[11];
  for (int i = 0; i < 79; ++i)
  {
    timingBins[i]=-7.+double(i)*14./78.;
    if (i<73)
    {
      ttPhiBins[i]=1+5*i;
      if ( i < 19) 
      {
        modPhiBins[i]=1+20*i;
        if (i < 11)
        {
          highEBins[i]=10.+double(i)*20.;
        }
      }
    }

  } 
  TH2F* calibMapEB = new TH2F("calibMapEB","time calib map EB [ns];i#phi;i#eta",360,1.,361.,172,-86,86);
  calibMapEB->Sumw2();
  TH2F* sigmaMapEB = new TH2F("sigmaMapEB","Sigma of time calib map EB [ns];i#phi;i#eta",360,1.,361.,172,-86,86);
  TH2F* calibErrorMapEB = new TH2F("calibErrorMapEB","Error of time calib map EB [ns];i#phi;i#eta",360,1.,361.,172,-86,86);
  TProfile2D* calibTTMapEB = new TProfile2D("calibTTMapEB","time calib map EB (TT) [ns];i#phi;i#eta",360/5,ttPhiBins,35, ttEtaBins);

  TDirectory* cryDirEB = gDirectory->mkdir("crystalTimingHistsEB");
  cryDirEB->cd();
  TH1C* cryTimingHistsEB[61200];
  EBDetId det;
  for(int hi=0; hi < 61200; ++hi)
  {
    det = EBDetId::unhashIndex(hi);
    if(det==EBDetId())
      continue;
    string histname = "EB_cryTiming_ieta";
    histname+=intToString(det.ieta());
    histname+="_iphi";
    histname+=intToString(det.iphi());
    cryTimingHistsEB[hi] = new TH1C(histname.c_str(),histname.c_str(),660,-33,33);
    cryTimingHistsEB[hi]->Sumw2();
  }
  outfile->cd();
  
  cout << "Making calibs...";

  CrystalCalibration* ebCryCalibs[61200];
  //XXX: Making calibs with weighted/unweighted mean
  for(int i=0; i < 61200; ++i)
    ebCryCalibs[i] = new CrystalCalibration(); //use weighted mean!
    //ebCryCalibs[i] = new CrystalCalibration(false); //don't use weighted mean!

  // Loop over the TTree
  int numEventsUsed = 0;
  int nEntries = chain->GetEntries();
  cout << "Begin loop over TTree." << endl;

  for(int entry = 0; entry < nEntries; ++entry)
  {
    chain->GetEntry(entry);

    // Loop once to calculate average event time
    float sumTime = 0;
    int numCrysEB = 0;
    for(int bCluster=0; bCluster < treeVars_.nClusters; bCluster++)
    {
      if(treeVars_.xtalInBCIEta[bCluster][0] == -999999) continue; // skip EE clusters
      for(int cryInBC=0; cryInBC < treeVars_.nXtalsInCluster[bCluster]; cryInBC++)
      {
        sumTime += treeVars_.xtalInBCTime[bCluster][cryInBC];
        numCrysEB++;
      }
    }
    //debug
    //cout << "Number of EB crys in event: " << numEBcrys << endl;

    //XXX: Event cuts
    if(sumTime/numCrysEB > avgTimeMax || sumTime/numCrysEB < avgTimeMin)
    {
      //cout << "Average event time: " << sumTime/numCrysEB  << " so event rejected." << endl;
      continue;
    }
    // check BX, orbit, lumi, run, L1 tech/phys triggers
    bool keepEvent = includeEvent(treeVars_.bx,bxIncludeVector,bxExcludeVector)
      && includeEvent(treeVars_.orbit,orbitIncludeVector,orbitExcludeVector)
      && includeEvent(treeVars_.lumiSection,lumiIncludeVector,lumiExcludeVector)
      && includeEvent(treeVars_.runId,runIncludeVector,runExcludeVector)
      && includeEvent(treeVars_.l1ActiveTriggers,
          treeVars_.l1NActiveTriggers,trigIncludeVector,trigExcludeVector)
      && includeEvent(treeVars_.l1ActiveTechTriggers,
          treeVars_.l1NActiveTechTriggers,ttrigIncludeVector,ttrigExcludeVector);
    if(!keepEvent)
      continue;
      
    numEventsUsed++;

    // Loop over the EB crys and fill the map
    for(int bCluster=0; bCluster < treeVars_.nClusters; bCluster++)
    {
      if(treeVars_.xtalInBCIEta[bCluster][0] == -999999) continue; // skip EE clusters
      for(int cryInBC=0; cryInBC < treeVars_.nXtalsInCluster[bCluster]; cryInBC++)
      {
        int hashedIndex = treeVars_.xtalInBCHashedIndex[bCluster][cryInBC];
        float cryTime = treeVars_.xtalInBCTime[bCluster][cryInBC];
        float cryTimeError = treeVars_.xtalInBCTimeErr[bCluster][cryInBC];
        float cryAmp = treeVars_.xtalInBCAmplitudeADC[bCluster][cryInBC];
        //float cryEt = treeVars_.cryETEB_[cryIndex]; // not in the tree
        //SIC FEB 14,16 2011 - removed E/E9
        //                - spike cleaning done higher up
        float crySwissCrossNoise = treeVars_.xtalInBCSwissCross[bCluster][cryInBC];
	float Ao = cryAmp/sigmaNoiseEB;
	float AoLog = log10(Ao/25);

        EBDetId det = EBDetId::unhashIndex(hashedIndex);
        if(det==EBDetId()) // make sure DetId is valid
          continue;

        int ieta = det.ieta();
        int iphi = det.iphi();

        //XXX: RecHit cuts
        bool keepHit = cryAmp >= minAmpEB
          && crySwissCrossNoise < maxSwissCrossNoise
          && cryTime > minHitTimeEB
          && cryTime < maxHitTimeEB
          && AoLog > 0
          && AoLog < 1.2;
        if(!keepHit)
          continue;

        //cout << "STUPID DEBUG: " << hashedIndex << " cryTime: " << cryTime << " cryTimeError: " << cryTimeError << " cryAmp: " << cryAmp << endl;

        // Timing correction to take out the energy dependence if log10(ampliOverSigOfThis/25)
        // is between 0 and 1.2 (about 1 and 13 GeV)
	// amplitude dependent timing corrections
        float timing = cryTime - timeCorrectionEB_->Eval(AoLog);
        //FIXME
        cryTimeError = 1;
        ebCryCalibs[hashedIndex]->insertEvent(cryAmp,timing,cryTimeError,false);
        //SIC Use when we don't have time_error available
        //ebCryCalibs[hashedIndex]->insertEvent(cryAmp,cryTime,35/(cryAmp/1.2),false);
        ampProfileEB->Fill(hashedIndex,cryAmp);
        ampProfileMapEB->Fill(iphi,ieta,cryAmp);
        //if(cryTime > 33 || cryTime < -33)
        //  cout << "Crystal: " << det << " event time is over/underflow: " << cryTime << endl;
      }
    }
  }

  //create output text file
  ofstream fileStream;
  string fileName = fileNameBeg+".calibs.txt";
  fileStream.open(fileName.c_str());
  if(!fileStream.good() || !fileStream.is_open())
  {
    cout << "Couldn't open text file." << endl;
    return -1;
  }
  //create problem channels text file
  ofstream fileStreamProb;
  string fileName2 = fileNameBeg+".problems.txt";
  fileStreamProb.open(fileName2.c_str());
  if(!fileStreamProb.good() || !fileStreamProb.is_open())
  {
    cout << "Couldn't open text file." << endl;
    return -1;
  }

  // Create calibration container objects
  EcalTimeCalibConstants timeCalibConstants;
  EcalTimeCalibErrors timeCalibErrors;

  cout << "Using " << numEventsUsed << " out of " << nEntries << " in the tree." << endl;
  cout << "Creating calibs..." << endl;
  float cryCalibAvg = 0;
  int numCrysCalibrated = 0;
  vector<int> hashesToCalibrateToAvg;
  //Loop over all the crys
  for(int hashedIndex=0; hashedIndex < 61200; ++hashedIndex)
  {
    EBDetId det = EBDetId::unhashIndex(hashedIndex);
    if(det==EBDetId())
      continue;
    CrystalCalibration cryCalib = *(ebCryCalibs[hashedIndex]);
    int ieta = det.ieta();
    int iphi = det.iphi();

    //chiSquaredTotalHist->Fill(cryCalib.totalChi2);
    //expectedStatPresHistEB->Fill(sqrt(1/expectedPresSumEB));
    //expectedStatPresVsObservedMeanErrHistEB->Fill(sigmaM,sqrt(1/expectedPresSumEB));

    //XXX: Filter events at default 0.5*meanE threshold
    cryCalib.filterOutliers();
    
    //numPointsErasedHist->Fill(numPointsErased);
    
    //Write cryTimingHists
    vector<TimingEvent> times = cryCalib.timingEvents;
    for(vector<TimingEvent>::const_iterator timeItr = times.begin();
        timeItr != times.end(); ++timeItr)
    {
      float weight = 1/((timeItr->sigmaTime)*(timeItr->sigmaTime));
      cryTimingHistsEB[hashedIndex]->Fill(timeItr->time,weight);
    }
    cryDirEB->cd();
    cryTimingHistsEB[hashedIndex]->Write();
    outfile->cd();
    hitsPerCryHistEB->SetBinContent(hashedIndex+1,cryCalib.timingEvents.size());
    hitsPerCryMapEB->Fill(iphi,ieta,cryCalib.timingEvents.size());
    
    // Make timing calibs
    double p1 = cryCalib.mean;
    double p1err = cryCalib.meanE;
    //cout << "cry ieta: " << ieta << " cry iphi: " << iphi << " p1: " << p1 << " p1err: " << p1err << endl;
    if(cryCalib.timingEvents.size() < 10)
    {
      fileStreamProb << "Cry (only " << cryCalib.timingEvents.size() << " events) was calibrated to avg: " << ieta <<", " << iphi << ", hash: "
                                                                        << hashedIndex
                                                                        << "\t Calib: " << p1 << "\t Error: " << p1err << std::endl;
      hashesToCalibrateToAvg.push_back(hashedIndex);
      continue;
    }
    // Make it so we can add calib to reco time
    p1*=-1;
    if(p1err < 0.5 && p1err > 0)
    {
      fileStream << "EB\t" << hashedIndex << "\t" << p1 << "\t\t" << p1err << endl;
      calibHistEB->Fill(p1);
      //calibMapEEMFlip->Fill(y-85,x+1,p1);
      calibMapEB->Fill(iphi,ieta,p1);
      calibTTMapEB->Fill(iphi,ieta,p1);
      //calibMapEEMPhase->Fill(x+1,y-85,p1/25-floor(p1/25));
      //errorOnMeanVsNumEvtsHist->Fill(times.size(),p1err);
      cryCalibAvg+=p1;
      ++numCrysCalibrated;
      
      //Store in timeCalibration container
      EcalTimeCalibConstant tcConstant = p1;
      EcalTimeCalibError tcError = p1err;
      uint32_t rawId = EBDetId::unhashIndex(hashedIndex);
      timeCalibConstants[rawId] = tcConstant;
      timeCalibErrors[rawId] = tcError;
    }
    else
    {
      //std::cout << "Cry: " << ieta <<", " << iphi << ", hash: " << itr->first
      //  << "\t Calib: " << p1 << "\t Error: " << p1err << std::endl;
      fileStreamProb << "Cry was calibrated to avg: " << ieta <<", " << iphi << ", hash: " << hashedIndex
        << "\t Calib: " << p1 << "\t Error: " << p1err << std::endl;
      hashesToCalibrateToAvg.push_back(hashedIndex);
    }
    //calibsVsErrorsEB->Fill(p1err, p1 > 0 ? p1 : -1*p1);
    calibErrorHistEB->Fill(p1err);
    calibErrorMapEB->Fill(iphi,ieta,p1err);
    sigmaHistEB->Fill(cryCalib.stdDev);
    sigmaMapEB->Fill(iphi,ieta,cryCalib.stdDev);
  }
  
  fileStream.close();
  fileStreamProb.close();
  // Calc average
  if(numCrysCalibrated > 0)
    cryCalibAvg/=numCrysCalibrated;
  cryCalibAvg-= 2.0833; // Global phase shift
  // calibrate uncalibratable crys
  for(vector<int>::const_iterator hashItr = hashesToCalibrateToAvg.begin();
      hashItr != hashesToCalibrateToAvg.end(); ++hashItr)
  {
    //Store in timeCalibration container
    EcalTimeCalibConstant tcConstant = cryCalibAvg;
    EcalTimeCalibError tcError = 999;
    uint32_t rawId = EBDetId::unhashIndex(*hashItr);
    timeCalibConstants[rawId] = tcConstant;
    timeCalibErrors[rawId] = tcError;
  }

  //Write XML files
  cout << "Writing XML files." << endl;
  EcalCondHeader header;
  header.method_="testmethod";
  header.version_="testversion";
  header.datasource_="testdata";
  header.since_=123;
  header.tag_="testtag";
  header.date_="Mar 24 1973";
  string timeCalibFile = "EcalTimeCalibsEB.xml";
  string timeCalibErrFile = "EcalTimeCalibErrorsEB.xml";
  // Hack to prevent seg fault
  EcalTimeCalibConstant tcConstant = 0;
  EcalTimeCalibError tcError = 0;
  uint32_t rawId = EEDetId::unhashIndex(0);
  timeCalibConstants[rawId] = tcConstant;
  timeCalibErrors[rawId] = tcError;
  // End hack
  EcalTimeCalibConstantsXMLTranslator::writeXML(timeCalibFile,header,timeCalibConstants);
  EcalTimeCalibErrorsXMLTranslator::writeXML(timeCalibErrFile,header,timeCalibErrors);

  cout << "Writing histograms." << endl;
  outfile->cd();
  calibHistEB->SetXTitle("timingCalib [ns]");
  calibHistEB->Write();
  sigmaHistEB->Write();
  calibErrorHistEB->SetXTitle("uncertainty on mean [ns]");
  calibErrorHistEB->Write();
  //eventsEBHist->Write();

  //can->Print("calibs1D.png");
  //cout << "Writing calibVsErrors" << endl;
  //calibsVsErrors->SetYTitle("AbsCalibConst");
  //calibsVsErrors->SetXTitle("calibConstError");
  //calibsVsErrors->Write();

  //cout << "Writing calibErrorHists" << endl;
  //calibErrorHistEB->Write();

  //cout << "Writing calib maps" << endl;
  sigmaMapEB->Write();
  calibMapEB->Write();
  calibErrorMapEB->Write();
  calibTTMapEB->Write();
  //calibMapEBFlip->SetXTitle("ieta");
  //calibMapEBFlip->SetYTitle("iphi");
  //calibMapEBFlip->Write();
  //calibMapEBPhase->SetXTitle("iphi");
  //calibMapEBPhase->SetYTitle("ieta");
  //calibMapEBPhase->Write();
  
  //Move empty bins out of the way
  //int nxbins = calibMapEEM->GetNbinsX();
  //int nybins = calibMapEEM->GetNbinsY();
  //for(int i=0;i<=(nxbins+2)*(nybins+2); ++i)
  //{
  //  double binentsM = calibMapEEM->GetBinContent(i);
  //  if(binentsM==0)
  //  {
  //    calibMapEEM->SetBinContent(i,-1000);
  //  }
  //  double binentsP = calibMapEEP->GetBinContent(i);
  //  if(binentsP==0)
  //  {
  //    calibMapEEP->SetBinContent(i,-1000);
  //  }
  //}
  //calibMapEEM->SetXTitle("ix");
  //calibMapEEM->SetYTitle("iy");
  //calibMapEEM->Write();
  //calibMapEEP->SetXTitle("ix");
  //calibMapEEP->SetYTitle("iy");
  //calibMapEEP->Write();

  //calibSigmaHist->SetXTitle("#sigma_{cryTime} [ns]");
  //calibSigmaHist->Write();
  
  // Old hist, commented Jun 15 2009
  //avgAmpVsSigmaTHist->SetXTitle("#sigma_{cryTime} [ns]");
  //avgAmpVsSigmaTHist->SetYTitle("Avg. amp. [adc]");
  //avgAmpVsSigmaTHist->Write();
 
  //errorOnMeanVsNumEvtsHist->SetXTitle("Events");
  //errorOnMeanVsNumEvtsHist->SetYTitle("Error_on_mean [ns]");
  //TProfile* theProf = (TProfile*) errorOnMeanVsNumEvtsHist->ProfileX();
  //TF1* myFit = new TF1("myFit","[0]/sqrt(x)+[1]",0,50);
  //myFit->SetRange(0,50);
  ////theProf->Fit("myFit");
  //theProf->Write();
  //errorOnMeanVsNumEvtsHist->Write();
  //
  //chiSquaredEachEventHist->Write();
  //chiSquaredVsAmpEachEventHist->SetXTitle("amplitude [ADC]");
  //chiSquaredVsAmpEachEventHist->SetYTitle("#Chi^{2}");
  //chiSquaredVsAmpEachEventHist->Write();
  //chiSquaredHighMap->SetXTitle("iphi");
  //chiSquaredHighMap->SetYTitle("ieta");
  //chiSquaredHighMap->Write();
  //chiSquaredTotalHist->Write();
  //chiSquaredSingleOverTotalHist->Write();

  expectedStatPresHistEB->Write();
  expectedStatPresVsObservedMeanErrHistEB->Write();
  expectedStatPresEachEventHistEB->Write();
  //ampEachEventHist->Write();
  //numPointsErasedHist->Write();

  //calibMapEtaAvgEB->SetXTitle("i#phi");
  //calibMapEtaAvgEB->SetYTitle("i#eta");
  //calibMapEtaAvgEB->Write();
  //calibHistEtaAvgEB->Write();
  
  hitsPerCryHistEB->Write();
  hitsPerCryMapEB->Write();
  ampProfileMapEB->Write();
  ampProfileEB->Write();
  
  //cout << "All done!  Close input." << endl;
  //f->Close();
  //cout << "Close output and quit!" << endl;
  outfile->Close();
  cout << "done." << endl;
}
// ****************************************************************
//XXX: main
int main(int argc, char* argv[])
{
  //
  // **** May 20 2010 update ****
  // Usage: CreateEcalTimingCalibsEE fileWithTree options...
  //

  using namespace std;
  // Ao dependent timing corrections
  timeCorrectionEE_ = new TF1("timeCorrectionEE_","pol4(0)",0,1.2);
  //coefficients obtained in the interval (0, 1.5) from Low eta region < 2.2, run 144011
  timeCorrectionEE_->SetParameters(-0.461192,0.0876435,-0.234752,0.143774,-0.051990);

  // For selection cuts
  string inBxs, inOrbits, inTrig, inTTrig, inLumi, inRuns;
  float avgTimeMin, avgTimeMax;
  float minAmpEB, minAmpEE;
  float maxE1E9, maxSwissCrossNoise;  // EB only, no spikes seen in EE
  float maxHitTimeEE, minHitTimeEE;
  // init to sensible defaults
  avgTimeMin = -1; // in ns
  avgTimeMax = 1; // in ns
  minAmpEB = 5; // GeV
  minAmpEE = 5; // GeV
  maxHitTimeEE = 15; // ns
  minHitTimeEE = -15; // ns
  maxE1E9 = 0.95; // EB only
  maxSwissCrossNoise = 0.95; // EB only
  inBxs = "-1";
  inOrbits = "-1";
  inTrig = "-1";
  inTTrig = "-1";
  inLumi = "-1";
  inRuns = "-1";

  char* infile = argv[1];
  if (!infile)
  {
    cout << " No input file specified !" << endl;
    return -1;
  }

  //TODO: Replace this with the parseArguments function from the pi0 binary
  std::string stringGenericOption    = "--";
  for (int i=1 ; i<argc ; i++) {
    if (argv[i] == std::string("-bxs") && argc>i+1) inBxs = std::string(argv[i+1]);
    if (argv[i] == std::string("-orbits") && argc>i+1) inOrbits = std::string(argv[i+1]);
    if (argv[i] == std::string("-trig") && argc>i+1) inTrig = std::string(argv[i+1]);
    if (argv[i] == std::string("-ttrig") && argc>i+1) inTTrig = std::string(argv[i+1]);
    if (argv[i] == std::string("-lumi") && argc>i+1) inLumi = std::string(argv[i+1]);
    if (argv[i] == std::string("-runs") && argc>i+1) inRuns = std::string(argv[i+1]);
    if (argv[i] == std::string("-ebampmin") && argc>i+1) minAmpEB = atof(argv[i+1]);
    if (argv[i] == std::string("-eeampmin") && argc>i+1) minAmpEE = atof(argv[i+1]);
    if (argv[i] == std::string("-e1e9max") && argc>i+1) maxE1E9 = atof(argv[i+1]);
    if (argv[i] == std::string("-swisskmax") && argc>i+1) maxSwissCrossNoise = atof(argv[i+1]);
    if (argv[i] == std::string("-avgtimemin") && argc>i+1) avgTimeMin = atof(argv[i+1]);
    if (argv[i] == std::string("-avgtimemax") && argc>i+1) avgTimeMax = atof(argv[i+1]);
    if (argv[i] == std::string("-eehittimemax") && argc>i+1) maxHitTimeEE = atof(argv[i+1]);
    if (argv[i] == std::string("-eehittimemin") && argc>i+1) minHitTimeEE = atof(argv[i+1]);
    // handle here the case of multiple arguments for input files
    if (argv[i] == std::string("--i"))// && argc>i+1)
    {
      for (int u=i+1; u<argc; u++)
      {
        if ( 0==std::string(argv[u]).find( stringGenericOption ) )
        {
          if ( 0==listOfFiles_.size())  {std::cout << "no input files listed" << std::cout;}
          else  {std::cout << "no more files listed, found: " << argv[u] << std::cout;}
          break;
        }
        else
        {
          listOfFiles_.push_back(argv[u]);
          i++;
        }
      }// loop on arguments following --i
      continue;
    }//end 'if input files'

  }
  // Open the input files
  if (listOfFiles_.size()==0){
    std::cout << "\tno input file found" << std::endl;
    return(1);
  }
  else{
    std::cout << "\tfound " << listOfFiles_.size() << " input files: " << std::endl;
    for(std::vector<std::string>::const_iterator  file_itr=listOfFiles_.begin(); file_itr!=listOfFiles_.end(); file_itr++){
      std::cout << "\t" << (*file_itr) << std::endl;
    }
  }
  // Tree construction
  TChain* chain = new TChain ("EcalTimeAnalysis") ;
  std::vector<std::string>::const_iterator file_itr;
  for(file_itr=listOfFiles_.begin(); file_itr!=listOfFiles_.end(); file_itr++){
    chain->Add( (*file_itr).c_str() );
  }


  cout << "Running with options: "
    << "avgTimeMin: " << avgTimeMin << " avgTimeMax: " << avgTimeMax
    << " minAmpEB: " << minAmpEB << " minAmpEE: " << minAmpEE
    << " maxHitTimeEE: " << maxHitTimeEE << " minHitTimeEE: " << minHitTimeEE
    << " inTrig: " << inTrig << " inTTrig: " << inTTrig << " inLumi: " << inLumi 
    << " inBxs: " << inBxs << " inRuns: " << inRuns << " inOrbits: " << inOrbits
    << endl;

  // Ignore warnings
  gErrorIgnoreLevel = 2001;

  setBranchAddresses(chain,treeVars_);

  // Generate all the vectors for skipping selections
  std::vector<std::vector<double> > bxIncludeVector;
  std::vector<std::vector<double> > bxExcludeVector;
  std::vector<std::vector<double> > orbitIncludeVector;
  std::vector<std::vector<double> > orbitExcludeVector;
  std::vector<std::vector<double> > trigIncludeVector;
  std::vector<std::vector<double> > trigExcludeVector;
  std::vector<std::vector<double> > ttrigIncludeVector;
  std::vector<std::vector<double> > ttrigExcludeVector;
  std::vector<std::vector<double> > lumiIncludeVector;
  std::vector<std::vector<double> > lumiExcludeVector;
  std::vector<std::vector<double> > runIncludeVector;
  std::vector<std::vector<double> > runExcludeVector;
  //recall: string inBxs, inOrbits, inTrig, inTTrig, inLumi, inRuns;
  genIncludeExcludeVectors(inBxs,bxIncludeVector,bxExcludeVector);
  genIncludeExcludeVectors(inOrbits,orbitIncludeVector,orbitExcludeVector);
  genIncludeExcludeVectors(inTrig,trigIncludeVector,trigExcludeVector);
  genIncludeExcludeVectors(inTTrig,ttrigIncludeVector,ttrigExcludeVector);
  genIncludeExcludeVectors(inLumi,lumiIncludeVector,lumiExcludeVector);
  genIncludeExcludeVectors(inRuns,runIncludeVector,runExcludeVector);

  // Open output file and book hists
  string fileNameBeg = "timingCalibsEE";
  string rootFilename = fileNameBeg+".root";
  TFile* outfile = new TFile(rootFilename.c_str(),"RECREATE");
  outfile->cd();

  TH1F* calibHistEE = new TH1F("timingCalibsEE","timingCalibs EE [ns]",2000,-100,100);
  TH1F* calibErrorHistEE = new TH1F("timingCalibErrorEE","timingCalibError EE [ns]",500,0,5);
  calibHistEE->Sumw2();
  calibErrorHistEE->Sumw2();

  TH2F* calibsVsErrors = new TH2F("timingCalibsAndErrors","TimingCalibs vs. errors [ns]",500,0,5,100,0,10);
  calibsVsErrors->Sumw2();

  //TH2F* calibMapEE = new TH2F("calibMapEE","time calib map EE",360,1,361,170,-86,86);
  //TH2F* calibMapEEFlip = new TH2F("calibMapEEFlip","time calib map EE",170,-86,86,360,1,361);
  //TH2F* calibMapEEPhase = new TH2F("calibMapEEPhase","time calib map EE (phase of Tmax)",360,1,361,170,-86,86);
  
  //TH2F* calibMapEtaAvgEE = new TH2F("calibMapEtaAvgEE","time calibs raw eta avg map EE",360,1,361,170,-86,86);
  //TH1F* calibHistEtaAvgEE = new TH1F("timingCalibsEtaAvgEE","EtaAvgTimingCalibs EE [ns]",2000,-100,100);

  TH2F* hitsPerCryMapEEM = new TH2F("hitsPerCryMapEEM","Hits per cry EEM;ix;iy",100,1,101,100,1,101);
  TH2F* hitsPerCryMapEEP = new TH2F("hitsPerCryMapEEP","Hits per cry EEP;ix;iy",100,1,101,100,1,101);
  TH1F* hitsPerCryHistEEM = new TH1F("hitsPerCryHistEEM","Hits per cry EEM;hashedIndex",14648,0,14648);
  TH1F* hitsPerCryHistEEP = new TH1F("hitsPerCryHistEEP","Hits per cry EEP;hashedIndex",14648,0,14648);
  //TH1C* eventsEEMHist = new TH1C("numEventsEEM","Number of events, EEM",100,0,100);
  //TH1C* eventsEEPHist = new TH1C("numEventsEEP","Number of events, EEP",100,0,100);
  TProfile* ampProfileEEM = new TProfile("ampProfileEEM","Amp. profile EEM;hashedIndex",14648,0,14648);
  TProfile* ampProfileEEP = new TProfile("ampProfileEEP","Amp. profile EEP;hashedIndex",14648,0,14648);
  TProfile2D* ampProfileMapEEP = new TProfile2D("ampProfileMapEEP","Amp. profile EEP;ix;iy",100,1,101,100,1,101);
  TProfile2D* ampProfileMapEEM = new TProfile2D("ampProfileMapEEM","Amp. profile EEM;ix;iy",100,1,101,100,1,101);

  //TH1F* eventsEEHist = new TH1F("numEventsEE","Number of events, EE",100,0,100);
  //TH1F* calibSigmaHist = new TH1F("timingSpreadEE","Crystal timing spread [ns]",1000,-5,5);

  TH1F* sigmaHistEE = new TH1F("sigmaCalibsEE"," Sigma of calib distributions EE [ns]",100,0,1);

  //TH1F* chiSquaredEachEventHist = new TH1F("chi2eachEvent","Chi2 of each event",500,0,500);
  //TH2F* chiSquaredVsAmpEachEventHist = new TH2F("chi2VsAmpEachEvent","Chi2 vs. amplitude of each event",500,0,500,750,0,750);
  //TH2F* chiSquaredHighMap = new TH2F("chi2HighMap","Channels with event #Chi^{2} > 100",360,1,361,170,-86,86);
  //TH1F* chiSquaredTotalHist = new TH1F("chi2Total","Total chi2 of all events in each crystal",500,0,500);
  //TH1F* chiSquaredSingleOverTotalHist = new TH1F("chi2SingleOverTotal","Chi2 of each event over total chi2",100,0,1);
  //TH1F* ampEachEventHist = new TH1F("energyEachEvent","Energy of all events [GeV]",1000,0,10);
  //TH1F* numPointsErasedHist = new TH1F("numPointsErased","Number of points erased per crystal",25,0,25);
  
  //TProfile2D* myAmpProfile = (TProfile2D*)EBampProfile->Clone();
  //myAmpProfile->Write();
  TH1F* expectedStatPresHistEEM = new TH1F("expectedStatPresEEM","Avg. expected statistical precision EEM [ns], all crys",200,0,2);
  TH2F* expectedStatPresVsObservedMeanErrHistEEM = new TH2F("expectedStatPresVsObsEEM","Expected stat. pres. vs. obs. error on mean each event EEM [ns]",200,0,2,200,0,2);
  TH1F* expectedStatPresEachEventHistEEM = new TH1F("expectedStatPresSingleEventEEM","Expected stat. pres. each event EEM [ns]",200,0,2);
  TH1F* expectedStatPresHistEEP = new TH1F("expectedStatPresEEP","Avg. expected statistical precision EEP [ns], all crys",200,0,2);
  TH2F* expectedStatPresVsObservedMeanErrHistEEP = new TH2F("expectedStatPresVsObsEEP","Expected stat. pres. vs. obs. error on mean each event [ns] EEP",200,0,2,200,0,2);
  TH1F* expectedStatPresEachEventHistEEP = new TH1F("expectedStatPresSingleEventEEP","Expected stat. pres. each event EEP [ns]",200,0,2);
  
  TH2F* errorOnMeanVsNumEvtsHist = new TH2F("errorOnMeanVsNumEvts","Error_on_mean vs. number of events",50,0,50,200,0,2);
  errorOnMeanVsNumEvtsHist->Sumw2();
  
  TH1F* calibHistEEM = new TH1F("timingCalibsEEM","timingCalibs EEM [ns]",500,-25,25);
  TH1F* calibHistEEP = new TH1F("timingCalibsEEP","timingCalibs EEP [ns]",500,-25,25);
  TH1F* calibErrorHistEEM = new TH1F("calibErrorEEM","timingCalibError EEM [ns]",250,0,5);
  TH1F* calibErrorHistEEP = new TH1F("calibErrorEEP","timingCalibError EEP [ns]",250,0,5);
  calibHistEEM->Sumw2();
  calibHistEEP->Sumw2();
  calibErrorHistEEM->Sumw2();
  calibErrorHistEEP->Sumw2();

  TH2F* calibMapEEM = new TH2F("calibMapEEM","time calib map EEM",100,1,101,100,1,101);
  TH2F* calibMapEEP = new TH2F("calibMapEEP","time calib map EEP",100,1,101,100,1,101);
  calibMapEEM->Sumw2();
  calibMapEEP->Sumw2();

  TH2F* sigmaMapEEM = new TH2F("sigmaMapEEM","Sigma of time calib map EEM [ns];ix;iy",100,1.,101.,100,1,101);
  TH2F* sigmaMapEEP = new TH2F("sigmaMapEEP","Sigma of time calib map EEP [ns];ix;iy",100,1.,101.,100,1,101);
  TH2F* calibErrorMapEEM = new TH2F("calibErrorMapEEM","Error of time calib map EEM [ns];ix;iy",100,1.,101.,100,1,101);
  TH2F* calibErrorMapEEP = new TH2F("calibErrorMapEEP","Error of time calib map EEP [ns];ix;iy",100,1.,101.,100,1,101);

  TDirectory* cryDirEEP = gDirectory->mkdir("crystalTimingHistsEEP");
  cryDirEEP->cd();
  TH1C* cryTimingHistsEEP[100][100]; // [0][0] = ix 1, iy 1
  for(int x=0; x < 100; ++x)
  {
    for(int y=0; y < 100; ++y)
    {
      if(!EEDetId::validDetId(x+1,y+1,1))
        continue;
      string histname = "EEP_cryTiming_ix";
      histname+=intToString(x+1);
      histname+="_iy";
      histname+=intToString(y+1);
      cryTimingHistsEEP[x][y] = new TH1C(histname.c_str(),histname.c_str(),660,-33,33);
      cryTimingHistsEEP[x][y]->Sumw2();
    }
  }
  outfile->cd();
  TDirectory* cryDirEEM = gDirectory->mkdir("crystalTimingHistsEEM");
  cryDirEEM->cd();
  TH1C* cryTimingHistsEEM[100][100]; // [0][0] = ix 1, iy 1
  for(int x=0; x < 100; ++x)
  {
    for(int y=0; y < 100; ++y)
    {
      if(!EEDetId::validDetId(x+1,y+1,-1))
        continue;
      string histname = "EEM_cryTiming_ix";
      histname+=intToString(x+1);
      histname+="_iy";
      histname+=intToString(y+1);
      cryTimingHistsEEM[x][y] = new TH1C(histname.c_str(),histname.c_str(),660,-33,33);
      cryTimingHistsEEM[x][y]->Sumw2();
    }
  }
  outfile->cd();
  
  cout << "Making calibs..." << endl;

  CrystalCalibration* eeCryCalibs[14648];
  //XXX: Making calibs with weighted/unweighted mean
  for(int i=0; i < 14648; ++i)
    eeCryCalibs[i] = new CrystalCalibration(); //use weighted mean!
    //eeCryCalibs[i] = new CrystalCalibration(false); //don't use weighted mean!

  cout << "Looping over TTree...";

  // Loop over the TTree
  int numEventsUsed = 0;
  int nEntries = chain->GetEntries();
  cout << "Begin loop over TTree." << endl;

  for(int entry = 0; entry < nEntries; ++entry)
  {
    chain->GetEntry(entry);

    // Loop once to calculate average event time
    float sumTime = 0;
    int numCrysEE = 0;
    for(int bCluster=0; bCluster < treeVars_.nClusters; bCluster++)
    {
      if(treeVars_.xtalInBCIEta[bCluster][0] != -999999) continue; // skip EB clusters
      for(int cryInBC=0; cryInBC < treeVars_.nXtalsInCluster[bCluster]; cryInBC++)
      {
        sumTime += treeVars_.xtalInBCTime[bCluster][cryInBC];
        numCrysEE++;
      }
    }
    //debug
    //cout << "Number of EE crys in event: " << numEEcrys << endl;

    //XXX: Event cuts
    if(sumTime/numCrysEE > avgTimeMax || sumTime/numCrysEE < avgTimeMin)
    {
      //cout << "Average event time: " << sumTime/numCrysEE  << " so event rejected." << endl;
      continue;
    }
    // check BX, orbit, lumi, run, L1 tech/phys triggers
    bool keepEvent = includeEvent(treeVars_.bx,bxIncludeVector,bxExcludeVector)
      && includeEvent(treeVars_.orbit,orbitIncludeVector,orbitExcludeVector)
      && includeEvent(treeVars_.lumiSection,lumiIncludeVector,lumiExcludeVector)
      && includeEvent(treeVars_.runId,runIncludeVector,runExcludeVector)
      && includeEvent(treeVars_.l1ActiveTriggers,
          treeVars_.l1NActiveTriggers,trigIncludeVector,trigExcludeVector)
      && includeEvent(treeVars_.l1ActiveTechTriggers,
          treeVars_.l1NActiveTechTriggers,ttrigIncludeVector,ttrigExcludeVector);
    if(!keepEvent)
      continue;
      
    numEventsUsed++;

    // Loop over the EE crys and fill the map
    for(int bCluster=0; bCluster < treeVars_.nClusters; bCluster++)
    {
      if(treeVars_.xtalInBCIEta[bCluster][0] != -999999) continue; // skip EB clusters
      for(int cryInBC=0; cryInBC < treeVars_.nXtalsInCluster[bCluster]; cryInBC++)
      {
        int hashedIndex = treeVars_.xtalInBCHashedIndex[bCluster][cryInBC];
        float cryTime = treeVars_.xtalInBCTime[bCluster][cryInBC];
        float cryTimeError = treeVars_.xtalInBCTimeErr[bCluster][cryInBC];
        float cryAmp = treeVars_.xtalInBCAmplitudeADC[bCluster][cryInBC];
	float Ao = cryAmp/sigmaNoiseEE;
	float AoLog = log10(Ao/25);

        EEDetId det = EEDetId::unhashIndex(hashedIndex);
        if(det==EEDetId()) // make sure DetId is valid
          continue;

        int ix = det.ix();
        int iy = det.iy();

        //XXX: RecHit cuts
        bool keepHit = cryAmp >= minAmpEE
          && cryTime > minHitTimeEE
          && cryTime < maxHitTimeEE
	  && AoLog > 0
          && AoLog < 1.2;
        if(!keepHit)
          continue;

        //cout << "STUPID DEBUG: " << hashedIndex << " cryTime: " << cryTime << " cryTimeError: " << cryTimeError << " cryAmp: " << cryAmp << endl;

	// Timing correction to take out the energy dependence if log10(ampliOverSigOfThis/25)
        // is between 0 and 1.2 (about 1 and 13 GeV)
	// amplitude dependent timing corrections
        float timing = cryTime - timeCorrectionEE_->Eval(AoLog);
        //FIXME
        cryTimeError = 1;
        eeCryCalibs[hashedIndex]->insertEvent(cryAmp,timing,cryTimeError,false);

        //SIC Use when we don't have time_error available
        //eeCryCalibs[hashedIndex]->insertEvent(cryAmp,cryTime,35/(cryAmp/1.2),false);
        if(det.zside() < 0)
        {
          ampProfileEEM->Fill(hashedIndex,cryAmp);
          ampProfileMapEEM->Fill(ix,iy,cryAmp);
        }
        else
        {
          ampProfileEEP->Fill(hashedIndex,cryAmp);
          ampProfileMapEEP->Fill(ix,iy,cryAmp);
        }
      }
    }
  }

  //create output text file
  ofstream fileStream;
  string fileName = fileNameBeg+".calibs.txt";
  fileStream.open(fileName.c_str());
  if(!fileStream.good() || !fileStream.is_open())
  {
    cout << "Couldn't open text file." << endl;
    return -1;
  }
  //create problem channels text file
  ofstream fileStreamProb;
  string fileName2 = fileNameBeg+".problems.txt";
  fileStreamProb.open(fileName2.c_str());
  if(!fileStreamProb.good() || !fileStreamProb.is_open())
  {
    cout << "Couldn't open text file." << endl;
    return -1;
  }

  // Create calibration container objects
  EcalTimeCalibConstants timeCalibConstants;
  EcalTimeCalibErrors timeCalibErrors;

  cout << "Using " << numEventsUsed << " out of " << nEntries << " in the tree." << endl;
  cout << "Creating calibs..." << endl;
  float cryCalibAvg = 0;
  int numCrysCalibrated = 0;
  vector<int> hashesToCalibrateToAvg;
  //Loop over all the crys
  for(int hashedIndex=0; hashedIndex < 14648; ++hashedIndex)
  {
    EEDetId det = EEDetId::unhashIndex(hashedIndex);
    if(det==EEDetId())
      continue;
    CrystalCalibration cryCalib = *(eeCryCalibs[hashedIndex]);
    int x = det.ix();
    int y = det.iy();

    //chiSquaredTotalHist->Fill(cryCalib.totalChi2);
    //expectedStatPresHistEB->Fill(sqrt(1/expectedPresSumEB));
    //expectedStatPresVsObservedMeanErrHistEB->Fill(sigmaM,sqrt(1/expectedPresSumEB));

    //XXX: Filter events at default 0.5*meanE threshold
    cryCalib.filterOutliers();
    
    //numPointsErasedHist->Fill(numPointsErased);
    
    //Write cryTimingHists
    vector<TimingEvent> times = cryCalib.timingEvents;
    for(vector<TimingEvent>::const_iterator timeItr = times.begin();
        timeItr != times.end(); ++timeItr)
    {
      if(det.zside() < 0)
      {
        float weight = 1/((timeItr->sigmaTime)*(timeItr->sigmaTime));
        cryTimingHistsEEM[x-1][y-1]->Fill(timeItr->time,weight);
      }
      else
      {
        float weight = 1/((timeItr->sigmaTime)*(timeItr->sigmaTime));
        cryTimingHistsEEP[x-1][y-1]->Fill(timeItr->time,weight);
      }
    }
    if(det.zside() < 0)
    {
      cryDirEEM->cd();
      cryTimingHistsEEM[x-1][y-1]->Write();
    }
    else
    {
      cryDirEEP->cd();
      cryTimingHistsEEP[x-1][y-1]->Write();
    }
    outfile->cd();

    if(det.zside() < 0)
    {
      hitsPerCryHistEEM->SetBinContent(hashedIndex+1,cryCalib.timingEvents.size());
      hitsPerCryMapEEM->Fill(x,y,cryCalib.timingEvents.size());
    }
    else
    {
      hitsPerCryHistEEP->SetBinContent(hashedIndex+1,cryCalib.timingEvents.size());
      hitsPerCryMapEEP->Fill(x,y,cryCalib.timingEvents.size());
    }
    
    // Make timing calibs
    double p1 = cryCalib.mean;
    double p1err = cryCalib.meanE;
    //cout << "cry ieta: " << ieta << " cry iphi: " << iphi << " p1: " << p1 << " p1err: " << p1err << endl;
    if(cryCalib.timingEvents.size() < 10)
    {
      fileStreamProb << "Cry (only " << cryCalib.timingEvents.size() << " events) was calibrated to avg: " << det.zside() << ", "
                                                                                        << x <<", " << y << ", hash: "
                                                                        << hashedIndex
                                                                          << "\t Calib: " << p1 << "\t Error: " << p1err << std::endl;
      hashesToCalibrateToAvg.push_back(hashedIndex);
      continue;
    }
    // Make it so we can add calib to reco time
    p1*=-1;
    if(p1err < 0.5 && p1err > 0)
    {
      fileStream << "EE\t" << hashedIndex << "\t" << p1 << "\t\t" << p1err << endl;
      if(det.zside() < 0)
      {
        calibHistEEM->Fill(p1);
        //calibMapEEMFlip->Fill(y-85,x+1,p1);
        calibMapEEM->Fill(x,y,p1);
        //calibMapEEMPhase->Fill(x+1,y-85,p1/25-floor(p1/25));
        //errorOnMeanVsNumEvtsHist->Fill(times.size(),p1err);
      }
      else
      {
        calibHistEEP->Fill(p1);
        //calibMapEEPFlip->Fill(y-85,x+1,p1);
        calibMapEEP->Fill(x,y,p1);
        //calibMapEEPPhase->Fill(x+1,y-85,p1/25-floor(p1/25));
        //errorOnMeanVsNumEvtsHist->Fill(times.size(),p1err);
      }
      cryCalibAvg+=p1;
      ++numCrysCalibrated;
      //Store in timeCalibration container
      EcalTimeCalibConstant tcConstant = p1;
      EcalTimeCalibError tcError = p1err;
      uint32_t rawId = EEDetId::unhashIndex(hashedIndex);
      timeCalibConstants[rawId] = tcConstant;
      timeCalibErrors[rawId] = tcError;
    }
    else
    {
      //std::cout << "Cry: " << y <<", " << x << ", hash: " << itr->first
      //  << "\t Calib: " << p1 << "\t Error: " << p1err << std::endl;
      fileStreamProb << "Cry was calibrated to avg: " << x <<", " << y << ", hash: " << hashedIndex
        << "\t Calib: " << p1 << "\t Error: " << p1err << std::endl;
    }

    sigmaHistEE->Fill(cryCalib.stdDev);
    if(det.zside() < 0)
    {
      //calibsVsErrorsEEM->Fill(p1err, p1 > 0 ? p1 : -1*p1);
      calibErrorHistEEM->Fill(p1err);
      calibErrorMapEEM->Fill(x,y,p1err);
      sigmaMapEEM->Fill(x,y,cryCalib.stdDev);
    }
    else
    {
      //calibsVsErrorsEEP->Fill(p1err, p1 > 0 ? p1 : -1*p1);
      calibErrorHistEEP->Fill(p1err);
      calibErrorMapEEP->Fill(x,y,p1err);
      sigmaMapEEP->Fill(x,y,cryCalib.stdDev);
    }
  }
  
  fileStream.close();
  fileStreamProb.close();
  // Calc average
  if(numCrysCalibrated > 0)
    cryCalibAvg/=numCrysCalibrated;
  cryCalibAvg-= 2.0833; // Global phase shift
  // calibrate uncalibratable crys
  for(vector<int>::const_iterator hashItr = hashesToCalibrateToAvg.begin();
      hashItr != hashesToCalibrateToAvg.end(); ++hashItr)
  {
    //Store in timeCalibration container
    EcalTimeCalibConstant tcConstant = cryCalibAvg;
    EcalTimeCalibError tcError = 999;
    uint32_t rawId = EEDetId::unhashIndex(*hashItr);
    timeCalibConstants[rawId] = tcConstant;
    timeCalibErrors[rawId] = tcError;
  }

  //Write XML files
  cout << "Writing XML files." << endl;
  EcalCondHeader header;
  header.method_="testmethod";
  header.version_="testversion";
  header.datasource_="testdata";
  header.since_=123;
  header.tag_="testtag";
  header.date_="Mar 24 1973";
  string timeCalibFile = "EcalTimeCalibsEE.xml";
  string timeCalibErrFile = "EcalTimeCalibErrorsEE.xml";
  // Hack to prevent seg fault
  EcalTimeCalibConstant tcConstant = 0;
  EcalTimeCalibError tcError = 0;
  uint32_t rawId = EBDetId::unhashIndex(0);
  timeCalibConstants[rawId] = tcConstant;
  timeCalibErrors[rawId] = tcError;
  // End hack
  EcalTimeCalibConstantsXMLTranslator::writeXML(timeCalibFile,header,timeCalibConstants);
  EcalTimeCalibErrorsXMLTranslator::writeXML(timeCalibErrFile,header,timeCalibErrors);

  cout << "Writing histograms." << endl;
  outfile->cd();
  calibHistEEM->SetXTitle("timingCalib [ns]");
  calibHistEEM->Write();
  calibHistEEP->SetXTitle("timingCalib [ns]");
  calibHistEEP->Write();
  calibErrorHistEEP->SetXTitle("uncertainty on mean [ns]");
  calibErrorHistEEP->Write();
  calibErrorHistEEM->SetXTitle("uncertainty on mean [ns]");
  calibErrorHistEEM->Write();
  calibErrorMapEEP->Write();
  calibErrorMapEEM->Write();
  sigmaHistEE->Write();
  sigmaMapEEM->Write();
  sigmaMapEEP->Write();

  //can->Print("calibs1D.png");
  //cout << "Writing calibVsErrors" << endl;
  //calibsVsErrors->SetYTitle("AbsCalibConst");
  //calibsVsErrors->SetXTitle("calibConstError");
  //calibsVsErrors->Write();

  //Move empty bins out of the way
  int nxbins = calibMapEEM->GetNbinsX();
  int nybins = calibMapEEM->GetNbinsY();
  for(int i=0;i<=(nxbins+2)*(nybins+2); ++i)
  {
    double binentsM = calibMapEEM->GetBinContent(i);
    if(binentsM==0)
    {
      calibMapEEM->SetBinContent(i,-1000);
    }
    double binentsP = calibMapEEP->GetBinContent(i);
    if(binentsP==0)
    {
      calibMapEEP->SetBinContent(i,-1000);
    }
  }
  calibMapEEM->SetXTitle("ix");
  calibMapEEM->SetYTitle("iy");
  calibMapEEM->Write();
  calibMapEEP->SetXTitle("ix");
  calibMapEEP->SetYTitle("iy");
  calibMapEEP->Write();

  //calibSigmaHist->SetXTitle("#sigma_{cryTime} [ns]");
  //calibSigmaHist->Write();
  
  // Old hist, commented Jun 15 2009
  //avgAmpVsSigmaTHist->SetXTitle("#sigma_{cryTime} [ns]");
  //avgAmpVsSigmaTHist->SetYTitle("Avg. amp. [adc]");
  //avgAmpVsSigmaTHist->Write();
 
  //errorOnMeanVsNumEvtsHist->SetXTitle("Events");
  //errorOnMeanVsNumEvtsHist->SetYTitle("Error_on_mean [ns]");
  //TProfile* theProf = (TProfile*) errorOnMeanVsNumEvtsHist->ProfileX();
  //TF1* myFit = new TF1("myFit","[0]/sqrt(x)+[1]",0,50);
  //myFit->SetRange(0,50);
  ////theProf->Fit("myFit");
  //theProf->Write();
  //errorOnMeanVsNumEvtsHist->Write();
  //
  //chiSquaredEachEventHist->Write();
  //chiSquaredVsAmpEachEventHist->SetXTitle("amplitude [ADC]");
  //chiSquaredVsAmpEachEventHist->SetYTitle("#Chi^{2}");
  //chiSquaredVsAmpEachEventHist->Write();
  //chiSquaredHighMap->SetXTitle("iphi");
  //chiSquaredHighMap->SetYTitle("ieta");
  //chiSquaredHighMap->Write();
  //chiSquaredTotalHist->Write();
  //chiSquaredSingleOverTotalHist->Write();

  expectedStatPresHistEEM->Write();
  expectedStatPresVsObservedMeanErrHistEEM->Write();
  expectedStatPresEachEventHistEEM->Write();
  expectedStatPresHistEEP->Write();
  expectedStatPresVsObservedMeanErrHistEEP->Write();
  expectedStatPresEachEventHistEEP->Write();
  //ampEachEventHist->Write();
  //numPointsErasedHist->Write();
  hitsPerCryHistEEP->Write();
  hitsPerCryMapEEP->Write();
  hitsPerCryHistEEM->Write();
  hitsPerCryMapEEM->Write();
  ampProfileEEP->Write();
  ampProfileMapEEP->Write();
  ampProfileEEM->Write();
  ampProfileMapEEM->Write();
  
  //cout << "All done!  Close input." << endl;
  //f->Close();
  //cout << "Close output and quit!" << endl;
  outfile->Close();
  cout << "done." << endl;
}
int main (int argc, char **argv)
{
  /// Mc Ntuplas
  TString input = Form("/data1/rgerosa/NTUPLES_FINAL_CALIB/MC/WJetsToLNu_DYJetsToLL_7TeV-madgraph-tauola_Fall11_All.root"); 
  /// MC Calibration result E/p
  TString input2 = Form("/data1/rgerosa/L3_Weight/MC_WJets/EB_Z_recoFlag/WJetsToLNu_DYJetsToLL_7TeV-madgraph-tauola_Fall11_Z_noEP.root"); 

  TApplication* theApp = new TApplication("Application",&argc, argv);

  TFile *f = new TFile(input,"");
  TTree *inputTree = (TTree*)f->Get("ntu");

  TFile *f2 = new TFile(input2,"");
  TH2F *h_scale_EB = (TH2F*)f2->Get("h_scale_EB");
  TH2F *hcmap = (TH2F*) h_scale_EB->Clone("hcmap");
  
  hcmap -> Reset("ICEMS");
  hcmap -> ResetStats();
  
  /// Taking infos

  std::vector<float>* ele1_recHit_E=0;
  std::vector<float>* ele2_recHit_E=0;
  std::vector<int>* ele1_recHit_hashedIndex=0;
  std::vector<int>* ele2_recHit_hashedIndex=0;
  std::vector<int>* ele1_recHit_flag=0;
  std::vector<int>* ele2_recHit_flag=0;
  float ele1_E_true,ele2_E_true;
  float ele1_tkP,ele2_tkP;
  int ele1_isEB, ele2_isEB;
  float   ele1_fbrem,ele2_fbrem;
  int isW, isZ;
  
  inputTree->SetBranchAddress("ele1_recHit_E", &ele1_recHit_E);
  inputTree->SetBranchAddress("ele2_recHit_E", &ele2_recHit_E);
  inputTree->SetBranchAddress("ele1_recHit_hashedIndex", &ele1_recHit_hashedIndex);
  inputTree->SetBranchAddress("ele2_recHit_hashedIndex", &ele2_recHit_hashedIndex);
  inputTree->SetBranchAddress("ele1_recHit_flag", &ele1_recHit_flag);
  inputTree->SetBranchAddress("ele2_recHit_flag", &ele2_recHit_flag);
  inputTree->SetBranchAddress("ele1_E_true", &ele1_E_true);
  inputTree->SetBranchAddress("ele2_E_true", &ele2_E_true);
  inputTree->SetBranchAddress("ele1_tkP", &ele1_tkP);
  inputTree->SetBranchAddress("ele2_tkP", &ele2_tkP);
  inputTree->SetBranchAddress("ele1_isEB", &ele1_isEB);
  inputTree->SetBranchAddress("ele2_isEB", &ele2_isEB);
  inputTree->SetBranchAddress("ele1_fbrem", &ele1_fbrem);
  inputTree->SetBranchAddress("ele2_fbrem", &ele2_fbrem);
  inputTree->SetBranchAddress("isW", &isW);
  inputTree->SetBranchAddress("isZ", &isZ);
 
  TProfile2D* mapMomentum = new TProfile2D("mapMomentum","mapMomentum",360,0,360,170,-85,85);
  TProfile2D* mapfbrem = new TProfile2D("mapfbrem","mapfbrem",360,0,360,170,-85,85);

  /// Make fbrem and p/ptrue map cycling on MC --> all the events 

  for(Long64_t i=0; i< inputTree->GetEntries(); i++)
  {
   inputTree->GetEntry(i);
   if (!(i%100000))std::cerr<<i;
   if (!(i%10000)) std::cerr<<".";
       
   if (ele1_isEB == 1 && (isW==1 || isZ==1)) {
  
      double E_seed=0;
      int seed_hashedIndex, iseed;

      for (unsigned int iRecHit = 0; iRecHit < ele1_recHit_E->size(); iRecHit++ ) {
            
            if(ele1_recHit_E -> at(iRecHit) > E_seed &&  ele1_recHit_flag->at(iRecHit) < 4 ) /// control if this recHit is good
            {
              seed_hashedIndex=ele1_recHit_hashedIndex -> at(iRecHit);
              iseed=iRecHit;
              E_seed=ele1_recHit_E -> at(iRecHit);  ///! Seed search

            }
      }
    
   int eta_seed = GetIetaFromHashedIndex(seed_hashedIndex);
   int phi_seed = GetIphiFromHashedIndex(seed_hashedIndex);
   if(ele1_tkP>0 && ele1_E_true>0 && abs(ele1_tkP/ele1_E_true)<2. && abs(ele1_tkP/ele1_E_true)>0.5) mapMomentum->Fill(phi_seed,eta_seed,abs(ele1_tkP/ele1_E_true));
   mapfbrem->Fill(phi_seed,eta_seed,abs(ele1_fbrem)); 
   }
   
   if (ele2_isEB == 1 && isZ==1) {

      double E_seed=0;
      int seed_hashedIndex, iseed;

      for (unsigned int iRecHit = 0; iRecHit < ele2_recHit_E->size(); iRecHit++ ) {
            
            if(ele2_recHit_E -> at(iRecHit) > E_seed &&  ele2_recHit_flag->at(iRecHit) < 4 ) /// control if this recHit is good
            {
              seed_hashedIndex=ele2_recHit_hashedIndex -> at(iRecHit);
              iseed=iRecHit;
              E_seed=ele2_recHit_E -> at(iRecHit);  ///! Seed search

            }
      }
    
   int eta_seed = GetIetaFromHashedIndex(seed_hashedIndex);
   int phi_seed = GetIphiFromHashedIndex(seed_hashedIndex);
   if(ele2_tkP>0 && ele2_E_true>0 && abs(ele2_tkP/ele2_E_true)<2. && abs(ele2_tkP/ele2_E_true)>0.5) mapMomentum->Fill(phi_seed,eta_seed,abs(ele2_tkP/ele2_E_true));
   mapfbrem->Fill(phi_seed,eta_seed,abs(ele2_fbrem));

   }
 }

 /// Map of IC normalized in eta rings

 std::vector< std::pair<int,int> > TT_centre ;
 
 TT_centre.push_back(std::pair<int,int> (58,49));
 TT_centre.push_back(std::pair<int,int> (53,109));
 TT_centre.push_back(std::pair<int,int> (8,114));
 TT_centre.push_back(std::pair<int,int> (83,169));
 TT_centre.push_back(std::pair<int,int> (53,174));
 TT_centre.push_back(std::pair<int,int> (63,194));
 TT_centre.push_back(std::pair<int,int> (83,224));
 TT_centre.push_back(std::pair<int,int> (73,344));
 TT_centre.push_back(std::pair<int,int> (83,358));
 TT_centre.push_back(std::pair<int,int> (-13,18));
 TT_centre.push_back(std::pair<int,int> (-18,23));
 TT_centre.push_back(std::pair<int,int> (-8,53));
 TT_centre.push_back(std::pair<int,int> (-3,63));
 TT_centre.push_back(std::pair<int,int> (-53,128));
 TT_centre.push_back(std::pair<int,int> (-53,183));
 TT_centre.push_back(std::pair<int,int> (-83,193));
 TT_centre.push_back(std::pair<int,int> (-74,218));
 TT_centre.push_back(std::pair<int,int> (-8,223));
 TT_centre.push_back(std::pair<int,int> (-68,303));
 TT_centre.push_back(std::pair<int,int> (-43,328));
 
 /// Mean over phi corrected skipping dead channel 

 for (int iEta = 1 ; iEta < h_scale_EB->GetNbinsY()+1; iEta ++)
 {
   float SumIC = 0;
   int numIC = 0;
   
   for(int iPhi = 1 ; iPhi < h_scale_EB->GetNbinsX()+1 ; iPhi++)
   {
    bool isGood = CheckxtalIC(h_scale_EB,iPhi,iEta);
    bool isGoodTT = CheckxtalTT(iPhi,iEta,TT_centre);
 
     if(isGood && isGoodTT)
     {
      SumIC = SumIC + h_scale_EB->GetBinContent(iPhi,iEta);
      numIC ++ ;
     }
    }
   //fede: skip bad channels and bad TTs
   for (int iPhi = 1; iPhi< h_scale_EB->GetNbinsX()+1  ; iPhi++)
   { 
     if(numIC==0 || SumIC==0) continue;

     bool isGood = CheckxtalIC(h_scale_EB,iPhi,iEta);
     bool isGoodTT = CheckxtalTT(iPhi,iEta,TT_centre);
     if (!isGood || !isGoodTT) continue;

     hcmap->SetBinContent(iPhi,iEta,h_scale_EB->GetBinContent(iPhi,iEta)/(SumIC/numIC));
   }
  }

 /// ratio map

 TH2F* ratioMap = (TH2F*) hcmap -> Clone("ratioMap");
 ratioMap->Reset();

 for( int i =0 ; i<hcmap->GetNbinsX() ; i++){
  for( int j=0; j<hcmap->GetNbinsY() ; j++){
   if(hcmap->GetBinContent(i,j)!=0 && mapMomentum->GetBinContent(i,j)!=0)
    ratioMap->SetBinContent(i+1,j+1,mapMomentum->GetBinContent(i,j)/hcmap->GetBinContent(i,j));
  }
 }

 /// Profile along phi taking into account dead channels
 TGraphErrors *coeffEBp = new TGraphErrors();
 TGraphErrors *coeffEBm = new TGraphErrors();

 for (int iPhi =1; iPhi< hcmap->GetNbinsX()+1 ; iPhi++){
  double SumEBp =0, SumEBm=0;
  double iEBp=0, iEBm=0;
  for(int iEta = 1; iEta<hcmap->GetNbinsY()+1 ; iEta++){
     if(hcmap->GetBinContent(iPhi,iEta)==0)continue;
     if(iEta>85) {SumEBp=SumEBp+mapMomentum->GetBinContent(iPhi,iEta)/hcmap->GetBinContent(iPhi,iEta);
                  iEBp++;}
     else{ SumEBm=SumEBm+mapMomentum->GetBinContent(iPhi,iEta)/hcmap->GetBinContent(iPhi,iEta);
           iEBm++;}
     }
  coeffEBp->SetPoint(iPhi-1,iPhi-1,SumEBp/iEBp);
  coeffEBm->SetPoint(iPhi-1,iPhi-1,SumEBm/iEBm);

  }
     
 TFile* outputGraph = new TFile("output/GraphFor_P_Correction.root","RECREATE");
 outputGraph->cd();

 coeffEBp->Write("coeffEBp");
 coeffEBm->Write("coeffEBm");
 outputGraph->Close();
     
 gROOT->Reset();
 gROOT->SetStyle("Plain");

 gStyle->SetPadTickX(1);
 gStyle->SetPadTickY(1);
 gStyle->SetOptTitle(1); 
 gStyle->SetOptStat(0); 
 gStyle->SetOptFit(0); 
 gStyle->SetFitFormat("6.3g"); 
 gStyle->SetPalette(1); 
  
 gStyle->SetTextFont(42);
 gStyle->SetTextSize(0.05);
 gStyle->SetTitleFont(42,"xyz");
 gStyle->SetTitleSize(0.05);
 gStyle->SetLabelFont(42,"xyz");
 gStyle->SetLabelSize(0.05);
 gStyle->SetTitleXOffset(0.8);
 gStyle->SetTitleYOffset(1.1);
 gROOT->ForceStyle();
 
 TCanvas* c1 = new TCanvas("mapMomentum","mapMomentum",1);
 c1->cd();
 mapMomentum->GetXaxis()->SetTitle("#phi");
 mapMomentum->GetXaxis()->SetNdivisions(20);
 c1->SetGridx(); 
 mapMomentum->GetYaxis()->SetTitle("#eta");
 mapMomentum->GetZaxis()->SetRangeUser(0.7,1.3);
 mapMomentum->Draw("colz");

 TCanvas* c2 = new TCanvas("mapfbrem","mapfbrem",1);
 c2->cd();
 mapfbrem->GetXaxis()->SetTitle("#phi");
 mapfbrem->GetYaxis()->SetTitle("#eta");
 mapfbrem->GetXaxis()->SetNdivisions(20);
 c2->SetGridx(); 
 mapfbrem->GetZaxis()->SetRangeUser(0.,0.7);
 mapfbrem->Draw("colz");

 TCanvas* c3 = new TCanvas("ratioMap","ratioMap",1);
 c3->cd();
 ratioMap->GetXaxis()->SetTitle("#phi");
 ratioMap->GetYaxis()->SetTitle("#eta");
 ratioMap->GetXaxis()->SetNdivisions(20);
 c3->SetGridx(); 
 ratioMap->GetZaxis()->SetRangeUser(0.7,1.3);
 ratioMap->Draw("colz");

 TCanvas* c4 = new TCanvas("coeffEB","coeffEB",1);
 c4->cd();
 coeffEBp->GetXaxis()->SetTitle("#phi");
 coeffEBp->GetYaxis()->SetTitle("p/p_{true}");
 coeffEBp -> SetMarkerStyle(20);
 coeffEBp -> SetMarkerSize(1);
 coeffEBp -> SetMarkerColor(kRed+1); 
 coeffEBp -> SetLineColor(kRed+1); 
 c4->SetGridx(); 
 c4->SetGridy(); 
 ratioMap->Draw("ap");

 coeffEBm->GetXaxis()->SetTitle("#phi");
 coeffEBm->GetYaxis()->SetTitle("p/p_{true}");
 coeffEBm -> SetMarkerStyle(20);
 coeffEBm -> SetMarkerSize(1);
 coeffEBm -> SetMarkerColor(kBlue+1); 
 coeffEBm -> SetLineColor(kBlue+1); 
 coeffEBm->Draw("ap same");


 theApp->Run();
 return 0;
}
예제 #4
0
void Dcurvature(const char *chargechoice = "plus", double ptmin=20){

  TString sign=chargechoice;

  gStyle->SetPalette(1);
  gStyle->SetOptStat("e");

//  double ptmin=20;
  double ptmax=200;
  double etamax=2.1; 
  int ptbins=(ptmax-ptmin)/10;
  double ptbinwidth=(ptmax-ptmin)/ptbins;
  int etabins=21;
  int phibins=21;


  TProfile3D *khistptetaphi = new TProfile3D("DeltaCurv(pt,eta,phi)","DeltaCurv(pt,eta,phi) "+sign,ptbins,ptmin,ptmax,etabins,-etamax,etamax,phibins,-3.14,3.14);
  khistptetaphi->GetXaxis()->SetTitle("Pt");
  khistptetaphi->GetYaxis()->SetTitle("Eta");
  khistptetaphi->GetZaxis()->SetTitle("Phi");

  TProfile2D *khistpteta = new TProfile2D("DeltaCurv(pt,eta)","DeltaCurv(pt,eta) "+sign,ptbins,ptmin,ptmax,etabins,-etamax,etamax);
  khistpteta->GetXaxis()->SetTitle("Pt");
  khistpteta->GetYaxis()->SetTitle("Eta");
  TProfile2D *khistptphi = new TProfile2D("DeltaCurv(pt,phi)","DeltaCurv(pt,phi) "+sign,ptbins,ptmin,ptmax,phibins,-3.14,3.14);
  khistptphi->GetXaxis()->SetTitle("Pt");
  khistptphi->GetYaxis()->SetTitle("Phi");

  TProfile *khistpt = new TProfile("DeltaCurv(pt)","DeltaCurv(pt) "+sign,ptbins,ptmin,ptmax);
  khistpt->GetXaxis()->SetTitle("Pt");
  khistpt->SetAxisRange(-0.001,0.001,"Y");
  TProfile *khisteta = new TProfile("DeltaCurv(eta)","DeltaCurv(eta) "+sign,etabins,-etamax,etamax);
  khistpt->GetXaxis()->SetTitle("Eta");
  TProfile *khistphi = new TProfile("DeltaCurv(phi)","DeltaCurv(phi) "+sign,phibins,-3.14,3.14);
  khistpt->GetXaxis()->SetTitle("Phi");

  TObjArray *khistptbins= new TObjArray();
  for (int i=0; i<ptbins; i++) {
    TString name="DeltaCurv(eta,phi), pt bin ";
    name+=int(ptmin+i*(ptmax-ptmin)/ptbins);
    name+=TString(", charge ")+sign;
    TProfile2D *ist = new TProfile2D(name.Data(),name.Data(),phibins,-3.14,3.14,etabins,-etamax,etamax);
    ist->SetAxisRange(-0.002,0.002,"Z");
    khistptbins->Add(ist);
  }

  TFile *f = new TFile("RecoRoutines_Z-selection_ZJets_TuneZ2_7TeV_alpgen_tauola.rew8.corr1.root","read");

  TTree *tree;

  f->GetObject("SingleMuPtScale/"+sign+"muonstree",tree);

  Double_t MCPt;
  Double_t MCEta;
  Double_t MCPhi;
  Double_t RecoPt;
  Double_t RecoEta;
  Double_t RecoPhi;
  Double_t EvWeight;

  tree->SetBranchAddress("RecoPt",&RecoPt);
  tree->SetBranchAddress("RecoEta",&RecoEta);
  tree->SetBranchAddress("RecoPhi",&RecoPhi);
  tree->SetBranchAddress("MCPt",&MCPt);
  tree->SetBranchAddress("MCEta",&MCEta);
  tree->SetBranchAddress("MCPhi",&MCPhi);
  tree->SetBranchAddress("EvWeight",&EvWeight);

  long nentries = tree->GetEntriesFast();

  for (int i=0; i<nentries; i++){
    tree->GetEntry(i);
    if (RecoPt<ptmin || RecoPt>ptmax || RecoEta<-etamax || RecoEta>etamax) continue;
    double quantity=(MCPt-RecoPt)/MCPt/RecoPt;
    khistptetaphi->Fill(RecoPt,RecoEta,RecoPhi,quantity,EvWeight);
    khistpteta->Fill(RecoPt,RecoEta,quantity,EvWeight);
    khistptphi->Fill(RecoPt,RecoPhi,quantity,EvWeight);
    ((TProfile2D*)(khistptbins->At(int((RecoPt-ptmin)/ptbinwidth))))->Fill(RecoPhi,RecoEta,quantity,EvWeight);
    khistpt->Fill(RecoPt,quantity,EvWeight);
    khisteta->Fill(RecoEta,quantity,EvWeight);
    khistphi->Fill(RecoPhi,quantity,EvWeight);
  }



  TCanvas *c1 = new TCanvas();
  khistptetaphi->Draw("BOX");

  TCanvas *c2 = new TCanvas();
  c2->Divide(2,1);
  c2->cd(1);
  khistpteta->Draw("BOX");
  c2->cd(2);
  khistptphi->Draw("BOX");

  TCanvas *c2b = new TCanvas();
  c2b->Divide(3,1);
  c2b->cd(1);
  khistpt->Draw();
  c2b->cd(2);
  khisteta->Draw();
  c2b->cd(3);
  khistphi->Draw();

  TCanvas *c3 = new TCanvas();
  c3->Divide(int(sqrt(ptbins))+1,int(sqrt(ptbins)));
  for (int i=0;i<ptbins;i++) { c3->cd(i+1); ((TProfile2D*)(khistptbins->At(i)))->Draw("SURF1 PSR Z");}




  TProfile *khistcorrpt = new TProfile("DeltaCurv(pt)","DeltaCurv(pt) "+sign,ptbins,ptmin,ptmax);
  khistcorrpt->GetXaxis()->SetTitle("Pt");
  khistcorrpt->SetAxisRange(-0.001,0.001,"Y");
  TProfile *khistcorreta = new TProfile("DeltaCurv(eta)","DeltaCurv(eta) "+sign,etabins,-etamax,etamax);
  khistcorrpt->GetXaxis()->SetTitle("Eta");
  TProfile *khistcorrphi = new TProfile("DeltaCurv(phi)","DeltaCurv(phi) "+sign,phibins,-3.14,3.14);
  khistcorrpt->GetXaxis()->SetTitle("Phi");

  // correction
   for (int i=0; i<nentries; i++){
    tree->GetEntry(i);
    if (RecoPt<ptmin || RecoPt>ptmax || RecoEta<-etamax || RecoEta>etamax) continue;
    double newpt=RecoPt+RecoPt*RecoPt*khistptetaphi->GetBinContent(khistptetaphi->FindBin(RecoPt,RecoEta,RecoPhi));
    double quantity=(MCPt-newpt)/MCPt/newpt;
    khistcorrpt->Fill(RecoPt,quantity,EvWeight);
    khistcorreta->Fill(RecoEta,quantity,EvWeight);
    khistcorrphi->Fill(RecoPhi,quantity,EvWeight);
   }

   TCanvas *corrc2b = new TCanvas();
  corrc2b->Divide(3,1);
  corrc2b->cd(1);
  khistcorrpt->Draw();
  corrc2b->cd(2);
  khistcorreta->Draw();
  corrc2b->cd(3);
  khistcorrphi->Draw();


khistptetaphi->SetName("ist");
khistptetaphi->SaveAs("mcptbinscorrectionfactors.C");

}
예제 #5
0
//! main program
int main (int argc, char** argv)
{

  std::string outputRootName = "matchDistance.root" ;
  std::string fileName (argv[1]) ;
  boost::shared_ptr<edm::ProcessDesc> processDesc = edm::readConfigFile (fileName) ;
  boost::shared_ptr<edm::ParameterSet> parameterSet = processDesc->getProcessPSet () ;
  std::cout << parameterSet->dump () << std::endl ; //PG for testing
  
  edm::ParameterSet subPSetSelections =  parameterSet->getParameter<edm::ParameterSet> ("selections") ;
  //cuts on SC Energy
  double EnergyMaxSC = subPSetSelections.getParameter<double> ("EnergyMaxSC") ;
  double EnergyMinSC = subPSetSelections.getParameter<double> ("EnergyMinSC") ;
  
  //cuts on Angle Muon / SCdirection
  double angleMAX = subPSetSelections.getParameter<double> ("angleMAX") ;
  double angleMIN = subPSetSelections.getParameter<double> ("angleMIN") ;
 
  //cuts on Xtal Energy
  double XtalMaxEnergyMin = subPSetSelections.getParameter<double> ("XtalMaxEnergyMin") ;
  double XtalMaxEnergyMax = subPSetSelections.getParameter<double> ("XtalMaxEnergyMax") ;
  double XtalMinEnergy = subPSetSelections.getParameter<double> ("XtalMinEnergy") ;
  
  //cuts on Windows
  double phiWINDOW    = subPSetSelections.getParameter<double> ("phiWINDOW") ;
  double ietaMAX    = subPSetSelections.getUntrackedParameter<int> ("ietaMAX",85) ;

  edm::ParameterSet subPSetInput =  
    parameterSet->getParameter<edm::ParameterSet> ("inputNtuples") ;
  std::vector<std::string> inputFiles = 
   subPSetInput.getParameter<std::vector<std::string> > ("inputFiles") ;
  std::cout << "reading : " ;

  TChain *chain = new TChain ("EcalCosmicsAnalysis") ;
  EcalCosmicsTreeContent treeVars ; 
  setBranchAddresses (chain, treeVars) ;

  for (std::vector<std::string>::const_iterator listIt = inputFiles.begin () ;
       listIt != inputFiles.end () ;
       ++listIt)
    {   
      std::cout << *listIt << " " << std::endl ;
      chain->Add (listIt->c_str ()) ;
    }

  TProfile2D aveEoxMap ("aveEoxMap","aveEoxMap",360,1.,361.,172,-86.,86.); 

  int nEntries = chain->GetEntries () ;
  std::cout << "FOUND " << nEntries << " ENTRIES\n" ;    

  //PG loop over entries
  for (int entry = 0 ; entry < nEntries ; ++entry)
    {
      chain->GetEntry (entry) ;
      if (entry % 100000 == 0) std::cout << "reading entry " << entry << std::endl ;


      std::vector<ect::association> associations ;
      ect::fillAssocVector (associations, treeVars) ;
      ect::selectOnDR (associations, treeVars, 0.3) ;

      //PG loop on associations vector
      for (unsigned int i = 0 ; 
           i < associations.size () ; 
           ++i)
        {
          int MUindex = associations.at (i).first  ;
          int SCindex = associations.at (i).second ;

          TVector3 SC0_pos (treeVars.superClusterX[SCindex], 
                            treeVars.superClusterY[SCindex], 
                            treeVars.superClusterZ[SCindex]) ; 
	       
          TVector3 MuonDir (treeVars.muonPx[MUindex], 
                            treeVars.muonPy[MUindex], 
                            treeVars.muonPz[MUindex]) ;

          float dummyEmax = 0.;
          float dummyLmax = 0.;
          int numCrystalEMax = -1;
          int numCrystalLMax = -1;
          bool SclOk = false;
          double dummyLength = 0;
       
          for (int XTLindex = treeVars.xtalIndexInSuperCluster[SCindex] ;
               XTLindex < treeVars.xtalIndexInSuperCluster[SCindex] +
                          treeVars.nXtalsInSuperCluster[SCindex] ; 
               ++XTLindex)
            {
              if(treeVars.xtalTkLength[XTLindex] == -1) continue;
          
              dummyLength+= treeVars.xtalTkLength[XTLindex];
          
              //---- check the link Xtal with max energy  == Xtal with max length ----
              if (treeVars.xtalEnergy[XTLindex] > dummyEmax) numCrystalEMax = XTLindex;
              if(treeVars.xtalTkLength[XTLindex] > dummyLmax) numCrystalLMax = XTLindex;
            }
       
          //   if( abs(treeVars.muonTkLengthInEcalDetail[associations.at(i).first] - dummyLength) > 0.5) continue;
       
          if ( (numCrystalEMax != numCrystalLMax) && 
               (numCrystalEMax != -1) && 
               (numCrystalLMax != -1)) 
          {
            if ( 3.*treeVars.xtalEnergy[numCrystalLMax] < 
                 treeVars.xtalTkLength[numCrystalLMax] * 0.0125) SclOk = false;
          }
          else SclOk = true;
          if ((numCrystalEMax == -1) || (numCrystalLMax == -1)) SclOk = false;
          if(SclOk == false) continue;

          double SCphi = fabs(SC0_pos.Phi()) / 3.1415 * 180. ;
          if ( (SCphi < 90. - phiWINDOW/2) || (SCphi > 90. + phiWINDOW/2) ) continue;

          double SCieta = SC0_pos.Eta () / 0.0175 ;
          if (fabs (SCieta) > ietaMAX) continue ;
        
          double angle = MuonDir.Angle ( SC0_pos ) ;
          if( angle > 3.1415/2. ) angle = 3.1415 - angle; // angle belongs to [0:90]

          if ((angle < angleMIN) || (angle >= angleMAX)) continue ;

          if ((treeVars.superClusterRawEnergy[SCindex] >= EnergyMaxSC) || 
              (treeVars.superClusterRawEnergy[SCindex] < EnergyMinSC)) continue ; 

          std::pair <int,int> maxima = findMaxXtalsInSC (treeVars, SCindex) ;
          double XtalEnergyMax = treeVars.xtalEnergy[maxima.first] ;

          if ((XtalEnergyMax < XtalMaxEnergyMin) || 
              (XtalEnergyMax >= XtalMaxEnergyMax)) continue ;
          
          //loop su cristalli di Supercluster Associato
          for (int XTLindex = treeVars.xtalIndexInSuperCluster[SCindex] ;
                   XTLindex < treeVars.xtalIndexInSuperCluster[SCindex] +
                              treeVars.nXtalsInSuperCluster[SCindex] ;
                   ++XTLindex)
            {
              if (treeVars.xtalEnergy[XTLindex] < XtalMinEnergy) continue ;               
              if (treeVars.xtalTkLength[XTLindex] <= 0.) continue ;
              double eox = treeVars.xtalEnergy[XTLindex] / 
                           treeVars.xtalTkLength[XTLindex] ;
              EBDetId dummy = EBDetId::unhashIndex (treeVars.xtalHashedIndex[XTLindex]) ;
              aveEoxMap.Fill (dummy.iphi (), dummy.ieta (), eox) ;
            }
        }
    } //PG loop over entries

  TH1F aveEoxDistr ("aveEoxDistr","aveEoxDistr",500,0,0.5) ;
  for (int phiIndex = 1 ; phiIndex < 361 ; ++phiIndex)
    for (int etaIndex = 1 ; etaIndex < 173 ; ++etaIndex)
      aveEoxDistr.Fill (aveEoxMap.GetBinContent (phiIndex,etaIndex)) ;

  TFile saving ("singleXtalEox.root","recreate") ;
  saving.cd () ;  
  aveEoxMap.Write () ;
  aveEoxDistr.Write () ;
  saving.Close () ;

  return 0 ;
}