Exemplo n.º 1
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 ;
}
// ****************************************************************
//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;
}
int main(int argc,  char * argv[])
{
  // Binary to view the hits per crystal maps of a TTree
  // Also prints out information on run range of the TTree and number of: hits, entries, and consecutive duplicate hits with amplitude above 26 (47) in EB (EE) and |t| < 5 (7) ns
  // Duplicate hits require the same time, amplitude, time error and in the barrel also the same swiss cross noise. Some duplicates are expected by random chance when enough hits are present in the input tree
  // To view for instance the occupancy EB map produced by this binary, open root and type .x occupancyEB.C
  // Jared Turkewitz
  // Usage: MakeEcalTimingTreePlots <TTree input file>

  char* infile = argv[1];
  if(!infile)
  {
    std::cout << "Missing input file." << std::endl;
    return -1;
  }

  EcalTimeTreeContent treeVars_;

  TFile* myFile = new TFile(infile);
  TTree *myInputTree_ = (TTree*)myFile->Get("EcalTimeAnalysis");

  float lastCryTimesEB[EBDetId::kSizeForDenseIndexing];
  for(int i=0; i<EBDetId::kSizeForDenseIndexing;++i)
    lastCryTimesEB[i] = 0;
  float lastCryAmpsEB[EBDetId::kSizeForDenseIndexing];
  for(int i=0; i<EBDetId::kSizeForDenseIndexing;++i)
    lastCryAmpsEB[i] = 0;
  float lastCrySwissCrossEB[EBDetId::kSizeForDenseIndexing];
  for(int i=0; i<EBDetId::kSizeForDenseIndexing;++i)
    lastCrySwissCrossEB[i] = 0;
  float lastCryTimeErrorEB[EBDetId::kSizeForDenseIndexing];
  for(int i=0; i<EBDetId::kSizeForDenseIndexing;++i)
    lastCryTimeErrorEB[i] = 0;

  float lastCryTimesEE[EEDetId::kSizeForDenseIndexing];
  for(int i=0; i<EEDetId::kSizeForDenseIndexing;++i)
    lastCryTimesEE[i] = 0;
  float lastCryAmpsEE[EEDetId::kSizeForDenseIndexing];
  for(int i=0; i<EEDetId::kSizeForDenseIndexing;++i)
    lastCryAmpsEE[i] = 0;
  float lastCryTimeErrorEE[EEDetId::kSizeForDenseIndexing];
  for(int i=0; i<EEDetId::kSizeForDenseIndexing;++i)
    lastCryTimeErrorEE[i] = 0;

  float hitCounterPerCrystalEB[EBDetId::kSizeForDenseIndexing];
  for(int i=0; i<EBDetId::kSizeForDenseIndexing;++i)
    hitCounterPerCrystalEB[i] = 0;
  float hitCounterPerCrystalEE[EEDetId::kSizeForDenseIndexing];
  for(int i=0; i<EEDetId::kSizeForDenseIndexing;++i)
    hitCounterPerCrystalEE[i] = 0;
  
  int runFirst = 999999;
  int runLast = 0;
  
  TCanvas* canvas = new TCanvas();
  TH2F* occupancyEB = new TH2F("hitsPerCryMapEB","Hits used in each crystal;i#phi;i#eta",360,1.,361.,171,-85,86);
  TH2F* occupancyEBNoDuplicates = new TH2F("occupancyEBNoDuplicates","occupancyEBNoDuplicates",360,1,361,171,-85,86); 
  TH2F* duplicatesEB = new TH2F("duplicatesEB","duplicatesEB",360,1,361,171,-85,86);
  TH2F* occupancyEEM = new TH2F("hitsPerCryMapEEM","Hits per cry EEM;ix;iy",100,1,101,100,1,101);
  TH2F* occupancyEEP = new TH2F("hitsPerCryMapEEP","Hits per cry EEP;ix;iy",100,1,101,100,1,101);

  setBranchAddresses(myInputTree_,treeVars_);
  int hitCounterEBAll = 0;
  int duplicateCounterEBAll = 0;
  int hitCounterEEAll = 0;
  int duplicateCounterEEAll = 0;
  int nEntries = myInputTree_->GetEntries();
  for(int entry = 0; entry < nEntries; ++entry)
  {
    myInputTree_->GetEntry(entry);
    // Loop over the clusters in the event
    for(int bCluster=0; bCluster < treeVars_.nClusters; bCluster++)
    {
      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 crySwissCrossNoise = treeVars_.xtalInBCSwissCross[bCluster][cryInBC];

	int runNumber = treeVars_.runId;
	if (runNumber < runFirst)
	{
	  runFirst = runNumber;
	}
	if (runNumber > runLast)
	{
	  runLast = runNumber;
	}
	
        if(treeVars_.xtalInBCIEta[bCluster][0] != -999999)
        {
	  EBDetId det = EBDetId::unhashIndex(hashedIndex);
          if(det==EBDetId()) // make sure DetId is valid
	  {
            continue;
          }
          int ieta = det.ieta();
          int iphi = det.iphi();

          // RecHit cuts
          bool keepHit = cryAmp >= 26
            && crySwissCrossNoise < 0.95
	    && cryTime >= -5
	    && cryTime <= 5;
          if(!keepHit)
            continue;
	  hitCounterEBAll++;
          hitCounterPerCrystalEB[hashedIndex]++;

          if(cryTime==lastCryTimesEB[hashedIndex] && cryAmp==lastCryAmpsEB[hashedIndex] && crySwissCrossNoise == lastCrySwissCrossEB[hashedIndex] && cryTimeError==lastCryTimeErrorEB[hashedIndex])
          {
            duplicateCounterEBAll++;
          }
          occupancyEB->Fill(iphi,ieta);
          if(cryTime!=lastCryTimesEB[hashedIndex])
            occupancyEBNoDuplicates->Fill(iphi,ieta);

          if(cryTime==lastCryTimesEB[hashedIndex])
	  {
	     duplicatesEB->Fill(iphi,ieta);
	  }
          //Store information on previous hit for duplicate checking
          lastCryTimesEB[hashedIndex] = cryTime;
	  lastCryAmpsEB[hashedIndex] = cryAmp;
	  lastCrySwissCrossEB[hashedIndex] = crySwissCrossNoise;
	  lastCryTimeErrorEB[hashedIndex] = cryTimeError;
        }
	else
       	{

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

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

          bool keepHit = cryAmp >= 47 
	    && cryTime >= -7
	    && cryTime <= 7;
          if(!keepHit)
            continue;
          hitCounterPerCrystalEE[hashedIndex]++;
	  hitCounterEEAll++;
          if(cryTime==lastCryTimesEE[hashedIndex] && cryAmp==lastCryAmpsEE[hashedIndex] && cryTimeError==lastCryTimeErrorEE[hashedIndex])
          {
            duplicateCounterEEAll++;
          }
	  if(zside == -1)
            occupancyEEM->Fill(ix,iy);
	  if(zside == 1)
            occupancyEEP->Fill(ix,iy);

          //Store information on previous hit for duplicate checking
          lastCryTimesEE[hashedIndex] = cryTime;
	  lastCryAmpsEE[hashedIndex] = cryAmp;
	  lastCryTimeErrorEE[hashedIndex] = cryTimeError;
        }
      }
    }
  }
  if(runFirst > runLast)
  {
    std::cout << "No runs in the tree!" << std::endl;
  }
  std::cout << "Run Range: " << runFirst << "-" << runLast << std::endl;
  std::cout << "nEntries: " << nEntries << std::endl;  
  std::cout << "hitCounterEBAll: " << hitCounterEBAll << " duplicateCounterEBAll: " << duplicateCounterEBAll << std::endl;
  std::cout << "hitCounterEEAll: " << hitCounterEEAll << " duplicateCounterEEAll: " << duplicateCounterEEAll << std::endl;
  int nXtalsUnder10HitsEB = 0;
  for(int i=0; i<EBDetId::kSizeForDenseIndexing;++i)
    if(hitCounterPerCrystalEB[i] <= 10)
    {
      nXtalsUnder10HitsEB++; 
    } 
  int nXtalsUnder10HitsEE = 0;
  for(int i=0; i<EEDetId::kSizeForDenseIndexing;++i)
    if(hitCounterPerCrystalEE[i] <= 10)
    {
      nXtalsUnder10HitsEE++; 
    } 

  int nXtalsWithZeroHitsEB = 0;
  for(int i=0; i<EBDetId::kSizeForDenseIndexing;++i)
    if(hitCounterPerCrystalEB[i] == 0)
    {
      nXtalsWithZeroHitsEB++; 
    } 
  int nXtalsWithZeroHitsEE = 0;
  for(int i=0; i<EEDetId::kSizeForDenseIndexing;++i)
    if(hitCounterPerCrystalEE[i] == 0)
    {
      nXtalsWithZeroHitsEE++; 
    } 

  std::cout << "nXtalsWithZeroHitsEB: " << nXtalsWithZeroHitsEB << std::endl;
  std::cout << "nXtalsUnder10HitsEB: " << nXtalsUnder10HitsEB << std::endl;
  std::cout << "nXtalsWithZeroHitsEE: " << nXtalsWithZeroHitsEE << std::endl;
  std::cout << "nXtalsUnder10HitsEE: " << nXtalsUnder10HitsEE << std::endl;
  
  canvas->cd();
  occupancyEB->Draw("colz");
  canvas->Print("occupancyEB.C");

  occupancyEEM->Draw("colz");
  canvas->Print("occupancyEEM.C");

  occupancyEEP->Draw("colz");
  canvas->Print("occupancyEEP.C");

  occupancyEBNoDuplicates->Draw("colz");
  canvas->Print("occupancyEBNoDuplicates.C");
  
  duplicatesEB->Draw("colz");
  canvas->Print("duplicatesEB.C");
}