int main(int argc, char *argv[])
{

  if ( argc<2 || argc>3 ) {
    std::cout << "USAGE: ./replay_pass3.exe [run] [applyEndpointGain = false]\n\n";
    exit(0);
  }
  
  cout.setf(ios::fixed, ios::floatfield);
  cout.precision(12);
  
  int runNumber = atoi(argv[1]);
  bool applyEndpointGain = false;
  if ( argc==3 && ( TString(argv[2])==TString("true") || atoi(argv[2])==1 ) ) applyEndpointGain = true; 

  
  int nPMT = 8;
  int nParams = 3; //takes a quadratic 

  // Run number integer
  cout << "Run " << runNumber << " ..." << endl;

  char tempOut[500];
  sprintf(tempOut, "%s/replay_pass3_%s.root",getenv("REPLAY_PASS3"), argv[1]);
  //sprintf(tempOut, "replay_pass3_%s.root", argv[1]);

  //Check if the file is good already and quit if it is so that we can 
  // only replay the files that are bad...

  if ( OnlyReplayBadFiles ) {
     
    if ( checkIfReplayFileIsGood(std::string(tempOut)) == 1 ) return 1;
  
    else {
      std::ofstream badRuns("badRuns.txt", std::fstream::app);
      badRuns << argv[1] << "\n";
      badRuns.close();
    }
  }

  // Reading in pedestals file to get cathode pedestals
  // Read pedestals file
  char tempFilePed[500];
  int iRun;
  sprintf(tempFilePed, "%s/pedestals_%s.dat", getenv("PEDESTALS"), argv[1]);
  std::cout << "... Reading: " << tempFilePed << std::endl;

  std::ifstream filePed(tempFilePed);
  for (int i=0; i<8; i++) {
    filePed >> iRun >> pedQadc[i];   
  }
  for (int i=0; i<32; i++) {
    filePed >> iRun >> pedPdc2[i];
  }
  for (int i=0; i<32; i++) {
    filePed >> iRun >> pedPadc[i];
  }

  
  filePed >> iRun >> pedPdc30;
  filePed >> iRun >> pedPdc34;
  


  cout << "... Applying Calibration ..." << endl;

  unsigned int calibrationPeriod = getSrcRunPeriod(runNumber);
  
  LinearityCurve linearityCurve(calibrationPeriod,false); //Get the linearity curve  
  EreconParameterization eRecon(runNumber); //Load the simulated relationship between EQ and Etrue
  WirechamberCal mwpcCal(runNumber);        //Load the Wirechamber Calibration

  std::vector <Double_t> epGain(8,1.); // Loading the endpoint gain factors if they are to be used
  if ( applyEndpointGain ) epGain = loadEndpointGain(runNumber);
  
  std::vector <Int_t> pmtQuality = getEreconPMTQuality(runNumber); //Read in PMT quality file
  std::vector <Double_t> alpha = GetAlphaValues(calibrationPeriod); //Get values for nPE/keV...
    
  PositionMap posmap(5.0,50.); //Reading Scintillator position maps
  posmap.readPositionMap( getXeRunPeriod(runNumber), "endpoint" );

  MWPCPositionMap anodeMap(5., 50.);    // Reading Anode position maps
  anodeMap.readMWPCPositionMap( getXeRunPeriodForMWPCmap(runNumber) ,250.,300.); // Using 250-300 keV because that's the most probable range

  
  DataTree *t = new DataTree(); // DataTree structure for input pass2 and output pass3
  t->makeOutputTree(std::string(tempOut),"pass3");  // Open output ntuple

  // Input ntuple
  char tempIn[500];
  sprintf(tempIn, "%s/replay_pass2_%s.root", getenv("REPLAY_PASS2"),argv[1]);
  t->setupInputTree(std::string(tempIn),"pass2");
 
  int nEvents = t->getEntries();
  cout << "... Processing nEvents = " << nEvents << endl;

  vector < vector <Int_t> > gridPoint;
  vector < Double_t > eta;
  vector < Double_t > old_eta;
  vector < Double_t > gaus_eta;


  // Loop over events
  for (int i=0; i<nEvents; i++) {
    t->getEvent(i);

    if ( i%10000==0 ) std::cout << i << std::endl;

    // Only process event if it's an electron
    
    if ( t->PID==1 || t->PID==6 ) { //PID==6 includes the APD events as they don't have coincidence on one side...

      std::vector <double> posex(3,0.);
      std::vector <double> poswx(3,0.);
      std::vector <double> posey(3,0.);
      std::vector <double> poswy(3,0.);

      MWPCCathodeHandler cathResp(t->Cathodes_Ex,t->Cathodes_Ey,t->Cathodes_Wx,t->Cathodes_Wy,&pedPdc2[16],&pedPdc2[0],&pedPadc[16],&pedPadc[0]);
 
  
      //First do the normal way... weighted average of good events, gaus fit of clipped
      cathResp.findAllPositions(true,false);
      
      posex = cathResp.getPosEX();
      posey = cathResp.getPosEY();
      poswx = cathResp.getPosWX();
      poswy = cathResp.getPosWY();

      t->xE.center = posex[0] * positionProjection;
      t->yE.center = posey[0] * positionProjection;
      t->xW.center = poswx[0] * positionProjection;
      t->yW.center = poswy[0] * positionProjection;

      t->xE.width = posex[1] * positionProjection;
      t->yE.width = posey[1] * positionProjection;
      t->xW.width = poswx[1] * positionProjection;
      t->yW.width = poswy[1] * positionProjection;
      
      t->xE.height = posex[2];
      t->yE.height = posey[2];
      t->xW.height = poswx[2];
      t->yW.height = poswy[2];

      t->xE.mult = cathResp.getMultEX();
      t->yE.mult = cathResp.getMultEY();
      t->xW.mult = cathResp.getMultWX();
      t->yW.mult = cathResp.getMultWY();

      t->xE.nClipped = cathResp.getnClippedEX();
      t->yE.nClipped = cathResp.getnClippedEY();
      t->xW.nClipped = cathResp.getnClippedWX();
      t->yW.nClipped = cathResp.getnClippedWY();

      t->xE.maxWire = cathResp.getMaxWireEX();
      t->yE.maxWire = cathResp.getMaxWireEY();
      t->xW.maxWire = cathResp.getMaxWireWX();
      t->yW.maxWire = cathResp.getMaxWireWY();

      t->xE.maxValue = cathResp.getMaxSignalEX();
      t->yE.maxValue = cathResp.getMaxSignalEY();
      t->xW.maxValue = cathResp.getMaxSignalWX();
      t->yW.maxValue = cathResp.getMaxSignalWY();

      t->xE.cathSum = cathResp.getCathSumEX();
      t->yE.cathSum = cathResp.getCathSumEY();
      t->xW.cathSum = cathResp.getCathSumWX();
      t->yW.cathSum = cathResp.getCathSumWY();

      t->CathSumE = t->xE.cathSum + t->yE.cathSum;
      t->CathSumW = t->xW.cathSum + t->yW.cathSum;

      t->CathMaxE = t->xE.maxValue + t->yE.maxValue;
      t->CathMaxW = t->xW.maxValue + t->yW.maxValue;
	    
      t->xE.rawCenter = cathResp.getWirePosEX(t->xE.maxWire);
      t->yE.rawCenter = cathResp.getWirePosEY(t->yE.maxWire);
      t->xW.rawCenter = cathResp.getWirePosWX(t->xW.maxWire);
      t->yW.rawCenter = cathResp.getWirePosWY(t->yW.maxWire);

      
      //Now do all gaussian fits... 
      //cathResp.loadGainFactors(runNumber);

      cathResp.findAllPositions(true,true);

      posex = cathResp.getPosEX();
      posey = cathResp.getPosEY();
      poswx = cathResp.getPosWX();
      poswy = cathResp.getPosWY();

      t->gaus_xE.center = posex[0] * positionProjection;
      t->gaus_yE.center = posey[0] * positionProjection;
      t->gaus_xW.center = poswx[0] * positionProjection;
      t->gaus_yW.center = poswy[0] * positionProjection;

      t->gaus_xE.width = posex[1] * positionProjection;
      t->gaus_yE.width = posey[1] * positionProjection;
      t->gaus_xW.width = poswx[1] * positionProjection;
      t->gaus_yW.width = poswy[1] * positionProjection;
      
      t->gaus_xE.height = posex[2];
      t->gaus_yE.height = posey[2];
      t->gaus_xW.height = poswx[2];
      t->gaus_yW.height = poswy[2];

      t->gaus_xE.mult = cathResp.getMultEX();
      t->gaus_yE.mult = cathResp.getMultEY();
      t->gaus_xW.mult = cathResp.getMultWX();
      t->gaus_yW.mult = cathResp.getMultWY();

      t->gaus_xE.nClipped = cathResp.getnClippedEX();
      t->gaus_yE.nClipped = cathResp.getnClippedEY();
      t->gaus_xW.nClipped = cathResp.getnClippedWX();
      t->gaus_yW.nClipped = cathResp.getnClippedWY();

      t->gaus_xE.maxWire = cathResp.getMaxWireEX();
      t->gaus_yE.maxWire = cathResp.getMaxWireEY();
      t->gaus_xW.maxWire = cathResp.getMaxWireWX();
      t->gaus_yW.maxWire = cathResp.getMaxWireWY();
      
      t->gaus_xE.maxValue = cathResp.getMaxSignalEX();
      t->gaus_yE.maxValue = cathResp.getMaxSignalEY();
      t->gaus_xW.maxValue = cathResp.getMaxSignalWX();
      t->gaus_yW.maxValue = cathResp.getMaxSignalWY();

      t->gaus_xE.cathSum = cathResp.getCathSumEX();
      t->gaus_yE.cathSum = cathResp.getCathSumEY();
      t->gaus_xW.cathSum = cathResp.getCathSumWX();
      t->gaus_yW.cathSum = cathResp.getCathSumWY();

      t->gaus_xE.rawCenter = cathResp.getWirePosEX(t->xE.maxWire);
      t->gaus_yE.rawCenter = cathResp.getWirePosEY(t->yE.maxWire);
      t->gaus_xW.rawCenter = cathResp.getWirePosWX(t->xW.maxWire);
      t->gaus_yW.rawCenter = cathResp.getWirePosWY(t->yW.maxWire);


      
      // Now for all weighted averages...
      cathResp.purgeGainFactors();
      cathResp.findAllPositions(false,false);

      posex = cathResp.getPosEX();
      posey = cathResp.getPosEY();
      poswx = cathResp.getPosWX();
      poswy = cathResp.getPosWY();

      t->old_xE.center = posex[0] * positionProjection;
      t->old_yE.center = posey[0] * positionProjection;
      t->old_xW.center = poswx[0] * positionProjection;
      t->old_yW.center = poswy[0] * positionProjection;

      t->old_xE.width = posex[1] * positionProjection;
      t->old_yE.width = posey[1] * positionProjection;
      t->old_xW.width = poswx[1] * positionProjection;
      t->old_yW.width = poswy[1] * positionProjection;
      
      t->old_xE.height = posex[2];
      t->old_yE.height = posey[2];
      t->old_xW.height = poswx[2];
      t->old_yW.height = poswy[2];

      t->old_xE.mult = cathResp.getMultEX();
      t->old_yE.mult = cathResp.getMultEY();
      t->old_xW.mult = cathResp.getMultWX();
      t->old_yW.mult = cathResp.getMultWY();

      t->old_xE.nClipped = cathResp.getnClippedEX();
      t->old_yE.nClipped = cathResp.getnClippedEY();
      t->old_xW.nClipped = cathResp.getnClippedWX();
      t->old_yW.nClipped = cathResp.getnClippedWY();

      t->old_xE.maxWire = cathResp.getMaxWireEX();
      t->old_yE.maxWire = cathResp.getMaxWireEY();
      t->old_xW.maxWire = cathResp.getMaxWireWX();
      t->old_yW.maxWire = cathResp.getMaxWireWY();

      t->old_xE.maxValue = cathResp.getMaxSignalEX();
      t->old_yE.maxValue = cathResp.getMaxSignalEY();
      t->old_xW.maxValue = cathResp.getMaxSignalWX();
      t->old_yW.maxValue = cathResp.getMaxSignalWY();

      t->old_xE.cathSum = cathResp.getCathSumEX();
      t->old_yE.cathSum = cathResp.getCathSumEY();
      t->old_xW.cathSum = cathResp.getCathSumWX();
      t->old_yW.cathSum = cathResp.getCathSumWY();

      t->old_xE.rawCenter = cathResp.getWirePosEX(t->xE.maxWire);
      t->old_yE.rawCenter = cathResp.getWirePosEY(t->yE.maxWire);
      t->old_xW.rawCenter = cathResp.getWirePosWX(t->xW.maxWire);
      t->old_yW.rawCenter = cathResp.getWirePosWY(t->yW.maxWire);

      
      /////////////////////////////////////////////////////////////
      /////// Now do the energy reconstruction
      /*std::cout << "Event " << i << std::endl;    
      std::cout << "Optimal: " << t->xE.center << "\t" << t->yE.center << "\t" << t->xW.center << "\t" << t->yW.center << "\n"
		<< "Old: " << t->old_xE.center << "\t" << t->old_yE.center << "\t" << t->old_xW.center << "\t" << t->old_yW.center << "\n"
		<< "Gaus: " << t->gaus_xE.center << "\t" << t->gaus_yE.center << "\t" << t->gaus_xW.center << "\t" << t->gaus_yW.center << "\n\n" ;*/

      eta = posmap.getInterpolatedEta(t->xE.center, t->yE.center, t->xW.center, t->yW.center);
      old_eta = posmap.getInterpolatedEta(t->old_xE.center, t->old_yE.center, t->old_xW.center, t->old_yW.center);
      gaus_eta = posmap.getInterpolatedEta(t->gaus_xE.center, t->gaus_yE.center, t->gaus_xW.center, t->gaus_yW.center);
      
      //First calculate old position reconstruction old_Erecon
      t->ScintE.e1 = linearityCurve.applyLinCurve(0,t->ScintE.q1) * epGain[0];
      t->ScintE.e2 = linearityCurve.applyLinCurve(1,t->ScintE.q2) * epGain[1];
      t->ScintE.e3 = linearityCurve.applyLinCurve(2,t->ScintE.q3) * epGain[2];
      t->ScintE.e4 = linearityCurve.applyLinCurve(3,t->ScintE.q4) * epGain[3];
      
      t->ScintE.e1 = ( old_eta[0]>0. && t->ScintE.e1>0. ) ? t->ScintE.e1 / old_eta[0] : 0.;
      t->ScintE.e2 = ( old_eta[1]>0. && t->ScintE.e2>0. ) ? t->ScintE.e2 / old_eta[1] : 0.;
      t->ScintE.e3 = ( old_eta[2]>0. && t->ScintE.e3>0. ) ? t->ScintE.e3 / old_eta[2] : 0.;
      t->ScintE.e4 = ( old_eta[3]>0. && t->ScintE.e4>0. ) ? t->ScintE.e4 / old_eta[3] : 0.;
      
      t->ScintE.nPE1 = old_eta[0] > 0. ? t->ScintE.e1 * old_eta[0] * alpha[0] : 0.;
      t->ScintE.nPE2 = old_eta[1] > 0. ? t->ScintE.e2 * old_eta[1] * alpha[1] : 0.;
      t->ScintE.nPE3 = old_eta[2] > 0. ? t->ScintE.e3 * old_eta[2] * alpha[2] : 0.;
      t->ScintE.nPE4 = old_eta[3] > 0. ? t->ScintE.e4 * old_eta[3] * alpha[3] : 0.;
      
      t->ScintE.de1 = t->ScintE.nPE1 > 0. ? t->ScintE.e1/sqrt(t->ScintE.nPE1) : 0.;
      t->ScintE.de2 = t->ScintE.nPE2 > 0. ? t->ScintE.e2/sqrt(t->ScintE.nPE2) : 0.;
      t->ScintE.de3 = t->ScintE.nPE3 > 0. ? t->ScintE.e3/sqrt(t->ScintE.nPE3) : 0.;
      t->ScintE.de4 = t->ScintE.nPE4 > 0. ? t->ScintE.e4/sqrt(t->ScintE.nPE4) : 0.;
      
      
      t->ScintW.e1 = linearityCurve.applyLinCurve(4,t->ScintW.q1) * epGain[4];
      t->ScintW.e2 = linearityCurve.applyLinCurve(5,t->ScintW.q2) * epGain[5];
      t->ScintW.e3 = linearityCurve.applyLinCurve(6,t->ScintW.q3) * epGain[6];
      t->ScintW.e4 = linearityCurve.applyLinCurve(7,t->ScintW.q4) * epGain[7];
      
      t->ScintW.e1 = ( old_eta[4]>0. && t->ScintW.e1>0. ) ? t->ScintW.e1 / old_eta[4] : 0.;
      t->ScintW.e2 = ( old_eta[5]>0. && t->ScintW.e2>0. ) ? t->ScintW.e2 / old_eta[5] : 0.;
      t->ScintW.e3 = ( old_eta[6]>0. && t->ScintW.e3>0. ) ? t->ScintW.e3 / old_eta[6] : 0.;
      t->ScintW.e4 = ( old_eta[7]>0. && t->ScintW.e4>0. ) ? t->ScintW.e4 / old_eta[7] : 0.;
      
      t->ScintW.nPE1 = old_eta[4] > 0. ? t->ScintW.e1 * old_eta[4] * alpha[4] : 0.;
      t->ScintW.nPE2 = old_eta[5] > 0. ? t->ScintW.e2 * old_eta[5] * alpha[5] : 0.;
      t->ScintW.nPE3 = old_eta[6] > 0. ? t->ScintW.e3 * old_eta[6] * alpha[6] : 0.;
      t->ScintW.nPE4 = old_eta[7] > 0. ? t->ScintW.e4 * old_eta[7] * alpha[7] : 0.;
      
      t->ScintW.de1 = t->ScintW.nPE1 > 0. ? t->ScintW.e1/sqrt(t->ScintW.nPE1) : 0.;
      t->ScintW.de2 = t->ScintW.nPE2 > 0. ? t->ScintW.e2/sqrt(t->ScintW.nPE2) : 0.;
      t->ScintW.de3 = t->ScintW.nPE3 > 0. ? t->ScintW.e3/sqrt(t->ScintW.nPE3) : 0.;
      t->ScintW.de4 = t->ScintW.nPE4 > 0. ? t->ScintW.e4/sqrt(t->ScintW.nPE4) : 0.;
      
      //std::cout << "Made it here" << std::endl;
      
      
      //Calculate the weighted energy on a side
      
      //EAST
      Double_t numer = ( (pmtQuality[0] && t->ScintE.nPE1>0. ? t->ScintE.nPE1 : 0.) +
			 (pmtQuality[1] && t->ScintE.nPE1>0. ? t->ScintE.nPE2 : 0.) + 
			 (pmtQuality[2] && t->ScintE.nPE1>0. ? t->ScintE.nPE3 : 0.) + 
			 (pmtQuality[3] && t->ScintE.nPE1>0. ? t->ScintE.nPE4 : 0.) );
      
      Double_t denom  = ( (pmtQuality[0] && t->ScintE.nPE1>0. ? alpha[0] * old_eta[0] : 0.) +
			  (pmtQuality[1] && t->ScintE.nPE2>0. ? alpha[1] * old_eta[1] : 0.) +
			  (pmtQuality[2] && t->ScintE.nPE3>0. ? alpha[2] * old_eta[2] : 0.) + 
			  (pmtQuality[3] && t->ScintE.nPE4>0. ? alpha[3] * old_eta[3] : 0.) ); 
      
      t->ScintE.energy = t->EvisE = (denom!=0. ? numer/denom : 0.);
      t->ScintE.denergy = (denom!=0. ? sqrt(t->ScintE.energy/denom) : 0.);
      
      //WEST
      numer = denom = 0.;
      
      numer = ( (pmtQuality[4] && t->ScintW.nPE1>0. ? t->ScintW.nPE1 : 0.) +
		(pmtQuality[5] && t->ScintW.nPE1>0. ? t->ScintW.nPE2 : 0.) + 
		(pmtQuality[6] && t->ScintW.nPE1>0. ? t->ScintW.nPE3 : 0.) + 
		(pmtQuality[7] && t->ScintW.nPE1>0. ? t->ScintW.nPE4 : 0.) );
      
      denom  = ( (pmtQuality[4] && t->ScintW.nPE1>0. ? alpha[4] * old_eta[4] : 0.) +
		 (pmtQuality[5] && t->ScintW.nPE2>0. ? alpha[5] * old_eta[5] : 0.) +
		 (pmtQuality[6] && t->ScintW.nPE3>0. ? alpha[6] * old_eta[6] : 0.) + 
		 (pmtQuality[7] && t->ScintW.nPE4>0. ? alpha[7] * old_eta[7] : 0.) ); 
      
      
      t->ScintW.energy = t->EvisW = (denom!=0. ? numer/denom : 0.);
      t->ScintW.denergy = (denom!=0. ? sqrt(t->ScintW.energy/denom) : 0.);
      
      
      // Determine the reconstructed energy
      
      int typeIndex = t->Type==0 ? 0:(t->Type==1 ? 1:2); //for retrieving the parameters from EQ2Etrue
      
      double totalEvis=0.;
      
      if (t->Side==0) {
	totalEvis = t->Type==1 ? (t->EvisE+t->EvisW):t->EvisE;
	if (t->EvisE>0. && totalEvis>0.) {
	  t->old_Erecon = eRecon.getErecon(0,typeIndex,totalEvis);
	}
	else t->old_Erecon=-1.;
      }
      if (t->Side==1) {
	totalEvis = t->Type==1 ? (t->EvisE+t->EvisW):t->EvisW;
	if (t->EvisW>0. && totalEvis>0.) {
	  t->old_Erecon = eRecon.getErecon(1,typeIndex,totalEvis);
	}
	else t->old_Erecon=-1.;
      }
    

      ////////////////////////////////////////////////////////////////////
      
      //First calculate old position reconstruction gaus_Erecon
      t->ScintE.e1 = linearityCurve.applyLinCurve(0,t->ScintE.q1) * epGain[0];
      t->ScintE.e2 = linearityCurve.applyLinCurve(1,t->ScintE.q2) * epGain[1];
      t->ScintE.e3 = linearityCurve.applyLinCurve(2,t->ScintE.q3) * epGain[2];
      t->ScintE.e4 = linearityCurve.applyLinCurve(3,t->ScintE.q4) * epGain[3];
      
      t->ScintE.e1 = ( gaus_eta[0]>0. && t->ScintE.e1>0. ) ? t->ScintE.e1 / gaus_eta[0] : 0.;
      t->ScintE.e2 = ( gaus_eta[1]>0. && t->ScintE.e2>0. ) ? t->ScintE.e2 / gaus_eta[1] : 0.;
      t->ScintE.e3 = ( gaus_eta[2]>0. && t->ScintE.e3>0. ) ? t->ScintE.e3 / gaus_eta[2] : 0.;
      t->ScintE.e4 = ( gaus_eta[3]>0. && t->ScintE.e4>0. ) ? t->ScintE.e4 / gaus_eta[3] : 0.;
      
      t->ScintE.nPE1 = gaus_eta[0] > 0. ? t->ScintE.e1 * gaus_eta[0] * alpha[0] : 0.;
      t->ScintE.nPE2 = gaus_eta[1] > 0. ? t->ScintE.e2 * gaus_eta[1] * alpha[1] : 0.;
      t->ScintE.nPE3 = gaus_eta[2] > 0. ? t->ScintE.e3 * gaus_eta[2] * alpha[2] : 0.;
      t->ScintE.nPE4 = gaus_eta[3] > 0. ? t->ScintE.e4 * gaus_eta[3] * alpha[3] : 0.;
      
      t->ScintE.de1 = t->ScintE.nPE1 > 0. ? t->ScintE.e1/sqrt(t->ScintE.nPE1) : 0.;
      t->ScintE.de2 = t->ScintE.nPE2 > 0. ? t->ScintE.e2/sqrt(t->ScintE.nPE2) : 0.;
      t->ScintE.de3 = t->ScintE.nPE3 > 0. ? t->ScintE.e3/sqrt(t->ScintE.nPE3) : 0.;
      t->ScintE.de4 = t->ScintE.nPE4 > 0. ? t->ScintE.e4/sqrt(t->ScintE.nPE4) : 0.;
      
      
      t->ScintW.e1 = linearityCurve.applyLinCurve(4,t->ScintW.q1) * epGain[4];
      t->ScintW.e2 = linearityCurve.applyLinCurve(5,t->ScintW.q2) * epGain[5];
      t->ScintW.e3 = linearityCurve.applyLinCurve(6,t->ScintW.q3) * epGain[6];
      t->ScintW.e4 = linearityCurve.applyLinCurve(7,t->ScintW.q4) * epGain[7];
      
      t->ScintW.e1 = ( gaus_eta[4]>0. && t->ScintW.e1>0. ) ? t->ScintW.e1 / gaus_eta[4] : 0.;
      t->ScintW.e2 = ( gaus_eta[5]>0. && t->ScintW.e2>0. ) ? t->ScintW.e2 / gaus_eta[5] : 0.;
      t->ScintW.e3 = ( gaus_eta[6]>0. && t->ScintW.e3>0. ) ? t->ScintW.e3 / gaus_eta[6] : 0.;
      t->ScintW.e4 = ( gaus_eta[7]>0. && t->ScintW.e4>0. ) ? t->ScintW.e4 / gaus_eta[7] : 0.;
      
      t->ScintW.nPE1 = gaus_eta[4] > 0. ? t->ScintW.e1 * gaus_eta[4] * alpha[4] : 0.;
      t->ScintW.nPE2 = gaus_eta[5] > 0. ? t->ScintW.e2 * gaus_eta[5] * alpha[5] : 0.;
      t->ScintW.nPE3 = gaus_eta[6] > 0. ? t->ScintW.e3 * gaus_eta[6] * alpha[6] : 0.;
      t->ScintW.nPE4 = gaus_eta[7] > 0. ? t->ScintW.e4 * gaus_eta[7] * alpha[7] : 0.;
      
      t->ScintW.de1 = t->ScintW.nPE1 > 0. ? t->ScintW.e1/sqrt(t->ScintW.nPE1) : 0.;
      t->ScintW.de2 = t->ScintW.nPE2 > 0. ? t->ScintW.e2/sqrt(t->ScintW.nPE2) : 0.;
      t->ScintW.de3 = t->ScintW.nPE3 > 0. ? t->ScintW.e3/sqrt(t->ScintW.nPE3) : 0.;
      t->ScintW.de4 = t->ScintW.nPE4 > 0. ? t->ScintW.e4/sqrt(t->ScintW.nPE4) : 0.;
      
      //std::cout << "Made it here" << std::endl;
      
      
      //Calculate the weighted energy on a side
      
      //EAST
      numer = 0.;
      numer = ( (pmtQuality[0] && t->ScintE.nPE1>0. ? t->ScintE.nPE1 : 0.) +
		(pmtQuality[1] && t->ScintE.nPE2>0. ? t->ScintE.nPE2 : 0.) + 
		(pmtQuality[2] && t->ScintE.nPE3>0. ? t->ScintE.nPE3 : 0.) + 
		(pmtQuality[3] && t->ScintE.nPE4>0. ? t->ScintE.nPE4 : 0.) );
      
      denom = 0.;
      denom  = ( (pmtQuality[0] && t->ScintE.nPE1>0. ? alpha[0] * gaus_eta[0] : 0.) +
		 (pmtQuality[1] && t->ScintE.nPE2>0. ? alpha[1] * gaus_eta[1] : 0.) +
		 (pmtQuality[2] && t->ScintE.nPE3>0. ? alpha[2] * gaus_eta[2] : 0.) + 
		 (pmtQuality[3] && t->ScintE.nPE4>0. ? alpha[3] * gaus_eta[3] : 0.) ); 
      
      t->ScintE.energy = t->EvisE = (denom!=0. ? numer/denom : 0.);
      t->ScintE.denergy = (denom!=0. ? sqrt(t->ScintE.energy/denom) : 0.);
      
      //WEST
      numer = denom = 0.;
      
      numer = ( (pmtQuality[4] && t->ScintW.nPE1>0. ? t->ScintW.nPE1 : 0.) +
		(pmtQuality[5] && t->ScintW.nPE2>0. ? t->ScintW.nPE2 : 0.) + 
		(pmtQuality[6] && t->ScintW.nPE3>0. ? t->ScintW.nPE3 : 0.) + 
		(pmtQuality[7] && t->ScintW.nPE4>0. ? t->ScintW.nPE4 : 0.) );
      
      denom  = ( (pmtQuality[4] && t->ScintW.nPE1>0. ? alpha[4] * gaus_eta[4] : 0.) +
		 (pmtQuality[5] && t->ScintW.nPE2>0. ? alpha[5] * gaus_eta[5] : 0.) +
		 (pmtQuality[6] && t->ScintW.nPE3>0. ? alpha[6] * gaus_eta[6] : 0.) + 
		 (pmtQuality[7] && t->ScintW.nPE4>0. ? alpha[7] * gaus_eta[7] : 0.) ); 
      
      
      t->ScintW.energy = t->EvisW = (denom!=0. ? numer/denom : 0.);
      t->ScintW.denergy = (denom!=0. ? sqrt(t->ScintW.energy/denom) : 0.);
      
      
      // Determine the reconstructed energy
    
      typeIndex = t->Type==0 ? 0:(t->Type==1 ? 1:2); //for retrieving the parameters from EQ2Etrue
    
      totalEvis=0.;
    
      if (t->Side==0) {
	totalEvis = t->Type==1 ? (t->EvisE+t->EvisW):t->EvisE;
	if (t->EvisE>0. && totalEvis>0.) {
	  t->gaus_Erecon = eRecon.getErecon(0,typeIndex,totalEvis);
	}
	else t->gaus_Erecon=-1.;
      }
      if (t->Side==1) {
	totalEvis = t->Type==1 ? (t->EvisE+t->EvisW):t->EvisW;
	if (t->EvisW>0. && totalEvis>0.) {
	  t->gaus_Erecon = eRecon.getErecon(1,typeIndex,totalEvis);
	}
	else t->gaus_Erecon=-1.;
      }
      
      
      
      /////////////////////////////////////////////////////////////
      // Now for the real Erecon and all of the variables that will be saved to file
      
      t->ScintE.e1 = linearityCurve.applyLinCurve(0,t->ScintE.q1) * epGain[0];
      t->ScintE.e2 = linearityCurve.applyLinCurve(1,t->ScintE.q2) * epGain[1];
      t->ScintE.e3 = linearityCurve.applyLinCurve(2,t->ScintE.q3) * epGain[2];
      t->ScintE.e4 = linearityCurve.applyLinCurve(3,t->ScintE.q4) * epGain[3];
      
      t->ScintE.e1 = ( eta[0]>0. ) ? t->ScintE.e1 / eta[0] : 0.;
      t->ScintE.e2 = ( eta[1]>0. ) ? t->ScintE.e2 / eta[1] : 0.;
      t->ScintE.e3 = ( eta[2]>0. ) ? t->ScintE.e3 / eta[2] : 0.;
      t->ScintE.e4 = ( eta[3]>0. ) ? t->ScintE.e4 / eta[3] : 0.;
      
      t->ScintE.nPE1 = eta[0] > 0. ? t->ScintE.e1 * eta[0] * alpha[0] : 0.;
      t->ScintE.nPE2 = eta[1] > 0. ? t->ScintE.e2 * eta[1] * alpha[1] : 0.;
      t->ScintE.nPE3 = eta[2] > 0. ? t->ScintE.e3 * eta[2] * alpha[2] : 0.;
      t->ScintE.nPE4 = eta[3] > 0. ? t->ScintE.e4 * eta[3] * alpha[3] : 0.;
      
      t->ScintE.de1 = t->ScintE.nPE1 > 0. ? t->ScintE.e1/sqrt(t->ScintE.nPE1) : 0.;
      t->ScintE.de2 = t->ScintE.nPE2 > 0. ? t->ScintE.e2/sqrt(t->ScintE.nPE2) : 0.;
      t->ScintE.de3 = t->ScintE.nPE3 > 0. ? t->ScintE.e3/sqrt(t->ScintE.nPE3) : 0.;
      t->ScintE.de4 = t->ScintE.nPE4 > 0. ? t->ScintE.e4/sqrt(t->ScintE.nPE4) : 0.;
      
      
      t->ScintW.e1 = linearityCurve.applyLinCurve(4,t->ScintW.q1) * epGain[4];
      t->ScintW.e2 = linearityCurve.applyLinCurve(5,t->ScintW.q2) * epGain[5];
      t->ScintW.e3 = linearityCurve.applyLinCurve(6,t->ScintW.q3) * epGain[6];
      t->ScintW.e4 = linearityCurve.applyLinCurve(7,t->ScintW.q4) * epGain[7];
      
      t->ScintW.e1 = ( eta[4]>0. ) ? t->ScintW.e1 / eta[4] : 0.;
      t->ScintW.e2 = ( eta[5]>0. ) ? t->ScintW.e2 / eta[5] : 0.;
      t->ScintW.e3 = ( eta[6]>0. ) ? t->ScintW.e3 / eta[6] : 0.;
      t->ScintW.e4 = ( eta[7]>0. ) ? t->ScintW.e4 / eta[7] : 0.;
      
      t->ScintW.nPE1 = eta[4] > 0. ? t->ScintW.e1 * eta[4] * alpha[4] : 0.;
      t->ScintW.nPE2 = eta[5] > 0. ? t->ScintW.e2 * eta[5] * alpha[5] : 0.;
      t->ScintW.nPE3 = eta[6] > 0. ? t->ScintW.e3 * eta[6] * alpha[6] : 0.;
      t->ScintW.nPE4 = eta[7] > 0. ? t->ScintW.e4 * eta[7] * alpha[7] : 0.;
      
      t->ScintW.de1 = t->ScintW.nPE1 > 0. ? t->ScintW.e1/sqrt(t->ScintW.nPE1) : 0.;
      t->ScintW.de2 = t->ScintW.nPE2 > 0. ? t->ScintW.e2/sqrt(t->ScintW.nPE2) : 0.;
      t->ScintW.de3 = t->ScintW.nPE3 > 0. ? t->ScintW.e3/sqrt(t->ScintW.nPE3) : 0.;
      t->ScintW.de4 = t->ScintW.nPE4 > 0. ? t->ScintW.e4/sqrt(t->ScintW.nPE4) : 0.;
      

      // Fill bare scintillator branch with no endpoint gain
      t->ScintE_bare.q1 = t->ScintE.q1;
      t->ScintE_bare.q2 = t->ScintE.q2;
      t->ScintE_bare.q3 = t->ScintE.q3;
      t->ScintE_bare.q4 = t->ScintE.q4;

      t->ScintW_bare.q1 = t->ScintW.q1;
      t->ScintW_bare.q2 = t->ScintW.q2;
      t->ScintW_bare.q3 = t->ScintW.q3;
      t->ScintW_bare.q4 = t->ScintW.q4;

      t->ScintE_bare.e1 = linearityCurve.applyLinCurve(0,t->ScintE_bare.q1);
      t->ScintE_bare.e2 = linearityCurve.applyLinCurve(1,t->ScintE_bare.q2);
      t->ScintE_bare.e3 = linearityCurve.applyLinCurve(2,t->ScintE_bare.q3);
      t->ScintE_bare.e4 = linearityCurve.applyLinCurve(3,t->ScintE_bare.q4);
      
      t->ScintE_bare.e1 = ( eta[0]>0. ) ? t->ScintE_bare.e1 / eta[0] : 0.;
      t->ScintE_bare.e2 = ( eta[1]>0. ) ? t->ScintE_bare.e2 / eta[1] : 0.;
      t->ScintE_bare.e3 = ( eta[2]>0. ) ? t->ScintE_bare.e3 / eta[2] : 0.;
      t->ScintE_bare.e4 = ( eta[3]>0. ) ? t->ScintE_bare.e4 / eta[3] : 0.;
      
      t->ScintE_bare.nPE1 = eta[0] > 0. ? t->ScintE_bare.e1 * eta[0] * alpha[0] : 0.;
      t->ScintE_bare.nPE2 = eta[1] > 0. ? t->ScintE_bare.e2 * eta[1] * alpha[1] : 0.;
      t->ScintE_bare.nPE3 = eta[2] > 0. ? t->ScintE_bare.e3 * eta[2] * alpha[2] : 0.;
      t->ScintE_bare.nPE4 = eta[3] > 0. ? t->ScintE_bare.e4 * eta[3] * alpha[3] : 0.;
      
      t->ScintE_bare.de1 = t->ScintE_bare.nPE1 > 0. ? t->ScintE_bare.e1/sqrt(t->ScintE_bare.nPE1) : 0.;
      t->ScintE_bare.de2 = t->ScintE_bare.nPE2 > 0. ? t->ScintE_bare.e2/sqrt(t->ScintE_bare.nPE2) : 0.;
      t->ScintE_bare.de3 = t->ScintE_bare.nPE3 > 0. ? t->ScintE_bare.e3/sqrt(t->ScintE_bare.nPE3) : 0.;
      t->ScintE_bare.de4 = t->ScintE_bare.nPE4 > 0. ? t->ScintE_bare.e4/sqrt(t->ScintE_bare.nPE4) : 0.;
      
      
      t->ScintW_bare.e1 = linearityCurve.applyLinCurve(4,t->ScintW_bare.q1);
      t->ScintW_bare.e2 = linearityCurve.applyLinCurve(5,t->ScintW_bare.q2);
      t->ScintW_bare.e3 = linearityCurve.applyLinCurve(6,t->ScintW_bare.q3);
      t->ScintW_bare.e4 = linearityCurve.applyLinCurve(7,t->ScintW_bare.q4);
      
      t->ScintW_bare.e1 = ( eta[4]>0. ) ? t->ScintW_bare.e1 / eta[4] : 0.;
      t->ScintW_bare.e2 = ( eta[5]>0. ) ? t->ScintW_bare.e2 / eta[5] : 0.;
      t->ScintW_bare.e3 = ( eta[6]>0. ) ? t->ScintW_bare.e3 / eta[6] : 0.;
      t->ScintW_bare.e4 = ( eta[7]>0. ) ? t->ScintW_bare.e4 / eta[7] : 0.;
      
      t->ScintW_bare.nPE1 = eta[4] > 0. ? t->ScintW_bare.e1 * eta[4] * alpha[4] : 0.;
      t->ScintW_bare.nPE2 = eta[5] > 0. ? t->ScintW_bare.e2 * eta[5] * alpha[5] : 0.;
      t->ScintW_bare.nPE3 = eta[6] > 0. ? t->ScintW_bare.e3 * eta[6] * alpha[6] : 0.;
      t->ScintW_bare.nPE4 = eta[7] > 0. ? t->ScintW_bare.e4 * eta[7] * alpha[7] : 0.;
      
      t->ScintW_bare.de1 = t->ScintW_bare.nPE1 > 0. ? t->ScintW_bare.e1/sqrt(t->ScintW_bare.nPE1) : 0.;
      t->ScintW_bare.de2 = t->ScintW_bare.nPE2 > 0. ? t->ScintW_bare.e2/sqrt(t->ScintW_bare.nPE2) : 0.;
      t->ScintW_bare.de3 = t->ScintW_bare.nPE3 > 0. ? t->ScintW_bare.e3/sqrt(t->ScintW_bare.nPE3) : 0.;
      t->ScintW_bare.de4 = t->ScintW_bare.nPE4 > 0. ? t->ScintW_bare.e4/sqrt(t->ScintW_bare.nPE4) : 0.;

      //std::cout << "Made it here" << std::endl;
      
      
      //Calculate the weighted energy on a side
      
      //EAST
      numer = 0.;
      numer = ( (pmtQuality[0] ? t->ScintE.nPE1 : 0.) +
		(pmtQuality[1] ? t->ScintE.nPE2 : 0.) + 
		(pmtQuality[2] ? t->ScintE.nPE3 : 0.) + 
		(pmtQuality[3] ? t->ScintE.nPE4 : 0.) );
      
      denom = 0.;
      denom  = ( (pmtQuality[0] ? alpha[0] * eta[0] : 0.) +
		 (pmtQuality[1] ? alpha[1] * eta[1] : 0.) +
		 (pmtQuality[2] ? alpha[2] * eta[2] : 0.) + 
		 (pmtQuality[3] ? alpha[3] * eta[3] : 0.) ); 
      
      t->ScintE.energy = t->EvisE = (denom!=0. ? numer/denom : 0.);
      t->ScintE.denergy = (denom!=0. ? sqrt(t->ScintE.energy/denom) : 0.);
      
      //WEST
      numer = denom = 0.;
      
      numer = ( (pmtQuality[4] ? t->ScintW.nPE1 : 0.) +
		(pmtQuality[5] ? t->ScintW.nPE2 : 0.) + 
		(pmtQuality[6] ? t->ScintW.nPE3 : 0.) + 
		(pmtQuality[7] ? t->ScintW.nPE4 : 0.) );
      
      denom  = ( (pmtQuality[4] ? alpha[4] * eta[4] : 0.) +
		 (pmtQuality[5] ? alpha[5] * eta[5] : 0.) +
		 (pmtQuality[6] ? alpha[6] * eta[6] : 0.) + 
		 (pmtQuality[7] ? alpha[7] * eta[7] : 0.) ); 
      
      
      t->ScintW.energy = t->EvisW = (denom!=0. ? numer/denom : 0.);
      t->ScintW.denergy = (denom!=0. ? sqrt(t->ScintW.energy/denom) : 0.);
      
      
      // Determine the reconstructed energy
      
      typeIndex = t->Type==0 ? 0:(t->Type==1 ? 1:2); //for retrieving the parameters from EQ2Etrue
      
      totalEvis=0.;
      t->Erecon_ee = 0.;
      //Handling APD events
      if (t->PID==6) {
	if (t->PassedCathE && t->PassedCathW) {
	  typeIndex=2;
	  t->Type=2;
	  t->Side = t->EvisE>t->EvisW?0:1;
	} else if (t->PassedCathE) {
	  typeIndex=0;
	  t->Type=0;
	  t->Side = 0;
	}
	else if (t->PassedCathW) {
	  typeIndex=0;
	  t->Type=0;
	  t->Side = 1;
	} else t->Side=2; //This won't create an Erecon.
	
      }

      if (t->Side==0) {
	totalEvis = t->Type==1 ? (t->EvisE+t->EvisW):t->EvisE;
	if (t->EvisE>0. && totalEvis>0.) {
	  t->Erecon = eRecon.getErecon(0,typeIndex,totalEvis);
	}
	else t->Erecon=-1.;
      }
      if (t->Side==1) {
	totalEvis = t->Type==1 ? (t->EvisE+t->EvisW):t->EvisW;
	if (t->EvisW>0. && totalEvis>0.) {
	  t->Erecon = eRecon.getErecon(1,typeIndex,totalEvis);
	}
	else t->Erecon=-1.;
      }
      
      if (t->Type==1 && t->EvisW>0. && t->EvisE>0.) {
	t->Erecon_ee = eRecon.getErecon(0,0,t->EvisE) + eRecon.getErecon(1,0,t->EvisW);
      }

    }
    else if (t->PID==0) {
      
      eta = posmap.getInterpolatedEta(0., 0., 0., 0.);
      //eta = posmap.getInterpolatedEta(xEast[0], yEast[0], xWest[0], yWest[0]);
      
      t->ScintE.e1 = linearityCurve.applyLinCurve(0,t->ScintE.q1);
      t->ScintE.e2 = linearityCurve.applyLinCurve(1,t->ScintE.q2);
      t->ScintE.e3 = linearityCurve.applyLinCurve(2,t->ScintE.q3);
      t->ScintE.e4 = linearityCurve.applyLinCurve(3,t->ScintE.q4);
      
      t->ScintE.e1 = ( eta[0]>0. ) ? t->ScintE.e1 / eta[0] : 0.;
      t->ScintE.e2 = ( eta[1]>0. ) ? t->ScintE.e2 / eta[1] : 0.;
      t->ScintE.e3 = ( eta[2]>0. ) ? t->ScintE.e3 / eta[2] : 0.;
      t->ScintE.e4 = ( eta[3]>0. ) ? t->ScintE.e4 / eta[3] : 0.;
      
      t->ScintE.nPE1 = eta[0] > 0. ? t->ScintE.e1 * eta[0] * alpha[0] : 0.;
      t->ScintE.nPE2 = eta[1] > 0. ? t->ScintE.e2 * eta[1] * alpha[1] : 0.;
      t->ScintE.nPE3 = eta[2] > 0. ? t->ScintE.e3 * eta[2] * alpha[2] : 0.;
      t->ScintE.nPE4 = eta[3] > 0. ? t->ScintE.e4 * eta[3] * alpha[3] : 0.;
      
      t->ScintE.de1 = t->ScintE.nPE1 > 0. ? t->ScintE.e1/sqrt(t->ScintE.nPE1) : 0.;
      t->ScintE.de2 = t->ScintE.nPE2 > 0. ? t->ScintE.e2/sqrt(t->ScintE.nPE2) : 0.;
      t->ScintE.de3 = t->ScintE.nPE3 > 0. ? t->ScintE.e3/sqrt(t->ScintE.nPE3) : 0.;
      t->ScintE.de4 = t->ScintE.nPE4 > 0. ? t->ScintE.e4/sqrt(t->ScintE.nPE4) : 0.;
      
      
      t->ScintW.e1 = linearityCurve.applyLinCurve(4,t->ScintW.q1);
      t->ScintW.e2 = linearityCurve.applyLinCurve(5,t->ScintW.q2);
      t->ScintW.e3 = linearityCurve.applyLinCurve(6,t->ScintW.q3);
      t->ScintW.e4 = linearityCurve.applyLinCurve(7,t->ScintW.q4);
    
      t->ScintW.e1 = ( eta[4]>0. ) ? t->ScintW.e1 / eta[4] : 0.;
      t->ScintW.e2 = ( eta[5]>0. ) ? t->ScintW.e2 / eta[5] : 0.;
      t->ScintW.e3 = ( eta[6]>0. ) ? t->ScintW.e3 / eta[6] : 0.;
      t->ScintW.e4 = ( eta[7]>0. ) ? t->ScintW.e4 / eta[7] : 0.;
    
      t->ScintW.nPE1 = eta[4] > 0. ? t->ScintW.e1 * eta[4] * alpha[4] : 0.;
      t->ScintW.nPE2 = eta[5] > 0. ? t->ScintW.e2 * eta[5] * alpha[5] : 0.;
      t->ScintW.nPE3 = eta[6] > 0. ? t->ScintW.e3 * eta[6] * alpha[6] : 0.;
      t->ScintW.nPE4 = eta[7] > 0. ? t->ScintW.e4 * eta[7] * alpha[7] : 0.;
    
      t->ScintW.de1 = t->ScintW.nPE1 > 0. ? t->ScintW.e1/sqrt(t->ScintW.nPE1) : 0.;
      t->ScintW.de2 = t->ScintW.nPE2 > 0. ? t->ScintW.e2/sqrt(t->ScintW.nPE2) : 0.;
      t->ScintW.de3 = t->ScintW.nPE3 > 0. ? t->ScintW.e3/sqrt(t->ScintW.nPE3) : 0.;
      t->ScintW.de4 = t->ScintW.nPE4 > 0. ? t->ScintW.e4/sqrt(t->ScintW.nPE4) : 0.;
    
      //std::cout << "Made it here" << std::endl;
    
    
      //Calculate the weighted energy on a side
    
      //EAST
      double numer = 0.;
      numer = ( (pmtQuality[0] ? t->ScintE.nPE1 : 0.) +
		(pmtQuality[1] ? t->ScintE.nPE2 : 0.) + 
		(pmtQuality[2] ? t->ScintE.nPE3 : 0.) + 
		(pmtQuality[3] ? t->ScintE.nPE4 : 0.) );
    
      double denom = 0.;
      denom  = ( (pmtQuality[0] ? alpha[0] * eta[0] : 0.) +
		 (pmtQuality[1] ? alpha[1] * eta[1] : 0.) +
		 (pmtQuality[2] ? alpha[2] * eta[2] : 0.) + 
		 (pmtQuality[3] ? alpha[3] * eta[3] : 0.) ); 
    
      t->ScintE.energy = t->EvisE = (denom!=0. ? numer/denom : 0.);
      t->ScintE.denergy = (denom!=0. ? sqrt(t->ScintE.energy/denom) : 0.);
    
      //WEST
      numer = denom = 0.;
    
      numer = ( (pmtQuality[4] ? t->ScintW.nPE1 : 0.) +
		(pmtQuality[5] ? t->ScintW.nPE2 : 0.) + 
		(pmtQuality[6] ? t->ScintW.nPE3 : 0.) + 
		(pmtQuality[7] ? t->ScintW.nPE4 : 0.) );
    
      denom  = ( (pmtQuality[4] ? alpha[4] * eta[4] : 0.) +
		 (pmtQuality[5] ? alpha[5] * eta[5] : 0.) +
		 (pmtQuality[6] ? alpha[6] * eta[6] : 0.) + 
		 (pmtQuality[7] ? alpha[7] * eta[7] : 0.) ); 
    
    
      t->ScintW.energy = t->EvisW = (denom!=0. ? numer/denom : 0.);
      t->ScintW.denergy = (denom!=0. ? sqrt(t->ScintW.energy/denom) : 0.);
  
    
      // Determine the reconstructed energy
    
      Int_t typeIndex = 0; //for retrieving the parameters from EQ2Etrue
     
      if (t->Side==0) {
	if (t->EvisE>0.) {
	  t->Erecon = eRecon.getErecon(0,typeIndex,t->EvisE);
	}
	else t->Erecon=-1.;
      }
      if (t->Side==1) {
	if (t->EvisW>0.) {
	  t->Erecon = eRecon.getErecon(1,typeIndex,t->EvisW);
	}
	else t->Erecon=-1.;
      }

    }
      
    // Last thing to do for electrons is position correct the anode signal and
    // apply the wirechamber energy calibration
    
    // Get the position response
    std::vector <Double_t> etaMWPC = anodeMap.getInterpolatedEta(t->xE.center,t->yE.center,
								 t->xW.center,t->yW.center);
    t->AnodeE = t->AnodeE / etaMWPC[0];
    t->AnodeW = t->AnodeW / etaMWPC[1];
    
    t->EMWPC_E = mwpcCal.applyCal( 0, t->AnodeE ) ;
    t->EMWPC_W = mwpcCal.applyCal( 1, t->AnodeW ) ;
    
  
  
    // write out pedestal subtracted cathode values for all events
    
    for ( int ii = 0; ii<16; ++ii ) {
      t->Cathodes_Ex[ii] = t->Cathodes_Ex[ii] - pedPdc2[ii+16]; 
      t->Cathodes_Ey[ii] = t->Cathodes_Ey[ii] - pedPdc2[ii];
      t->Cathodes_Wx[ii] = t->Cathodes_Wx[ii] - pedPadc[ii+16];
      t->Cathodes_Wy[ii] = t->Cathodes_Wy[ii] - pedPadc[ii];
    }
    
    t->fillOutputTree();
    
  }
  // Write output ntuple
  t->writeOutputFile();
  
  delete t; //Closes files

  if ( checkIfReplayFileIsGood(std::string(tempOut)) != 1 ) {

    std::ofstream badRuns("badRuns.txt", std::fstream::app);
    badRuns << argv[1] << "\n";
    badRuns.close();

  }

  return 0;
}
int main(int argc, char *argv[]) {

  
  if (argc!=2) {
    std::cout << "Usage: ./endpointGain.exe [octet]\n";
    //std::cout << "The code will produce comparisons for every octet in the range given,\non an octet-by-octet basis, and as a whole, using the Super-Sum\n";
    exit(0);
  }
  

  int octet = atoi(argv[1]);

  if ( std::find(badOct.begin(), badOct.end(),octet) != badOct.end() ) {

    std::cout << "Bad Octet... \n";

    std::ofstream gainFile(TString::Format("%s/EndpointGain/endpointGain_octet-%i.dat", getenv("ENDPOINT_ANALYSIS"),octet));

    for ( int i=0; i<8; ++i )  gainFile << 1. << std::endl;

    gainFile.close();

    return 0;
  }
  

  int nBins = 100;
  double minRange = 0.;
  double maxRange = 1000.;
  
  std::vector <int> runs = readOctetFile(octet);
  std::vector <int> bgruns = readOctetFileForBGruns(octet);

  std::vector < std::vector <Double_t> > pmtBackgroundRates = readPMTbackgroundRates(octet);

  

  ////////////////// Begin with data files /////////////////////

  // Vectors for creating the individual runs events and errors
  std::vector < std::vector < std::vector <Double_t> > > pmtSpec;
  std::vector < std::vector < std::vector <Double_t> > > pmtSpecErr;
    
  pmtSpec.resize(runs.size(),std::vector<std::vector<Double_t>>(8,std::vector<Double_t>(nBins,0.)));
  pmtSpecErr.resize(runs.size(),std::vector<std::vector<Double_t>>(8,std::vector<Double_t>(nBins,0.)));

  std::vector < std::vector < std::vector <Double_t> > > bgpmtSpec;
  std::vector < std::vector < std::vector <Double_t> > > bgpmtSpecErr;
    
  bgpmtSpec.resize(runs.size(),std::vector<std::vector<Double_t>>(8,std::vector<Double_t>(nBins,0.)));
  bgpmtSpecErr.resize(runs.size(),std::vector<std::vector<Double_t>>(8,std::vector<Double_t>(nBins,0.)));

  // Now loop over each run to determine the individual spectra, then fill their appropriate bins in the vector

  TH1D *spec[8]; // All 8 PMTs signals
  TH1D *bgspec[8]; // All 8 PMTs bg signals
  TH1D *simspec[8]; // All 8 PMTs signals

  int nRun = 0;
  
  std::vector <Double_t> totalTime(runs.size(),0.); // Holds the runLengths 
  std::vector <Double_t> bgtotalTime(runs.size(),0.); // Holds the runLengths 
  
  //runs.resize(0);
  for ( auto rn : runs ) {

    for ( int i=0; i<8; ++i ) {
      spec[i] = new TH1D(TString::Format("PMT%i",i),TString::Format("PMT %i",i),
		      nBins, minRange, maxRange);
    }
    
    // DataTree structure
    DataTree t;

    // Input ntuple
    char tempIn[500];
    sprintf(tempIn, "%s/replay_pass3_%i.root", getenv("REPLAY_PASS3"),rn);
    
    t.setupInputTree(std::string(tempIn),"pass3");

    unsigned int nevents = t.getEntries();

    t.getEvent(nevents-1);
    totalTime[nRun] = t.Time;

    double r2E = 0.; //position of event squared
    double r2W = 0.;
    
    for (unsigned int n=0 ; n<nevents ; n++ ) {

      t.getEvent(n);

      r2E = t.xE.center*t.xE.center + t.yE.center*t.yE.center;
      r2W = t.xW.center*t.xW.center + t.yW.center*t.yW.center;

      if ( t.PID==1 && t.Side<2 && t.Type==0 && t.Erecon>0. ) {

	if ( t.Side==0 ) {
	  if ( t.xeRC>6 || t.yeRC>6 ) continue; //only look at MWPC signal on East
	  else if ( t.xE.mult<1 || t.yE.mult<1 ) continue;
	}
	else if ( t.Side==1 ) {
	  if ( t.xwRC>6 || t.ywRC>6 ) continue; //only look at MWPC signal on West
	  else if ( t.xW.mult<1 || t.yW.mult<1 ) continue;      
	}

	if ( r2E > 30.*30. || r2W > 30.*30. ) continue;

	if ( t.Side==0 ) {
	  spec[0]->Fill(t.ScintE_bare.e1);
	  spec[1]->Fill(t.ScintE_bare.e2);
	  spec[2]->Fill(t.ScintE_bare.e3);
	  spec[3]->Fill(t.ScintE_bare.e4);
	}

	if ( t.Side==1 ) {
	  spec[4]->Fill(t.ScintW_bare.e1);
	  spec[5]->Fill(t.ScintW_bare.e2);
	  spec[6]->Fill(t.ScintW_bare.e3);
	  spec[7]->Fill(t.ScintW_bare.e4);
	}

      }
    }

    for ( int p=0; p<8; ++p ) {
      for ( int bin=1; bin<=nBins; ++bin ) {
	pmtSpec[nRun][p][bin-1] = (double)spec[p]->GetBinContent(bin)/totalTime[nRun];
	pmtSpecErr[nRun][p][bin-1] = spec[p]->GetBinError(bin)/totalTime[nRun];
      }
    }

    for ( int i=0; i<8; ++i ) { 
      // std::cout << "deleting spec[" << i << "]\n";
      delete spec[i];
    }
    nRun++;
    
  }

  nRun = 0;

  for ( auto rn : bgruns ) {

    for ( int i=0; i<8; ++i ) {
      bgspec[i] = new TH1D(TString::Format("bgPMT%i",i),TString::Format("bg PMT %i",i),
		      nBins, minRange, maxRange);
    }
    
    // DataTree structure
    DataTree t;

    // Input ntuple
    char tempIn[500];
    sprintf(tempIn, "%s/replay_pass3_%i.root", getenv("REPLAY_PASS3"),rn);
    
    t.setupInputTree(std::string(tempIn),"pass3");

    unsigned int nevents = t.getEntries();

    t.getEvent(nevents-1);
    bgtotalTime[nRun] = t.Time;

    double r2E = 0.; //position of event squared
    double r2W = 0.;
    
    for (unsigned int n=0 ; n<nevents ; n++ ) {

      t.getEvent(n);

      r2E = t.xE.center*t.xE.center + t.yE.center*t.yE.center;
      r2W = t.xW.center*t.xW.center + t.yW.center*t.yW.center;

      if ( t.PID==1 && t.Side<2 && t.Type==0 && t.Erecon>0. ) {

	if ( t.Side==0 ) {
	  if ( t.xeRC>6 || t.yeRC>6 ) continue; //only look at MWPC signal on East
	  else if ( t.xE.mult<1 || t.yE.mult<1 ) continue;
	}
	else if ( t.Side==1 ) {
	  if ( t.xwRC>6 || t.ywRC>6 ) continue; //only look at MWPC signal on West
	  else if ( t.xW.mult<1 || t.yW.mult<1 ) continue;      
	}

	if ( r2E > 30.*30. || r2W > 30.*30. ) continue;

	if ( t.Side==0 ) {
	  bgspec[0]->Fill(t.ScintE_bare.e1);
	  bgspec[1]->Fill(t.ScintE_bare.e2);
	  bgspec[2]->Fill(t.ScintE_bare.e3);
	  bgspec[3]->Fill(t.ScintE_bare.e4);
	}

	if ( t.Side==1 ) {
	  bgspec[4]->Fill(t.ScintW_bare.e1);
	  bgspec[5]->Fill(t.ScintW_bare.e2);
	  bgspec[6]->Fill(t.ScintW_bare.e3);
	  bgspec[7]->Fill(t.ScintW_bare.e4);
	}

      }
    }
    std::cout << "Made it through filling hists\n";
    for ( int p=0; p<8; ++p ) {
      for ( int bin=1; bin<=nBins; ++bin ) {
	bgpmtSpec[nRun][p][bin-1] = (double)bgspec[p]->GetBinContent(bin)/bgtotalTime[nRun];
	bgpmtSpecErr[nRun][p][bin-1] = ( bgspec[p]->GetBinContent(bin)>20 ?
					 bgspec[p]->GetBinError(bin)/bgtotalTime[nRun] :
					 TMath::Sqrt(pmtBackgroundRates[bin-1][p]/bgtotalTime[nRun]) );
      }
    }

    for ( int i=0; i<8; ++i ) { 
      // std::cout << "deleting spec[" << i << "]\n";
      delete bgspec[i];
    }
    nRun++;
    
  }

  

  ////////////// Now for simulation //////////////////
  // Vectors for creating the individual runs events and errors
  std::vector < std::vector < std::vector <Double_t> > > simSpec;
  std::vector < std::vector < std::vector <Double_t> > > simSpecErr;
    
  simSpec.resize(runs.size(),std::vector<std::vector<Double_t>>(8,std::vector<Double_t>(nBins,0.)));
  simSpecErr.resize(runs.size(),std::vector<std::vector<Double_t>>(8,std::vector<Double_t>(nBins,0.)));

  

  // Now loop over each run to determine the individual spectra, then fill their appropriate bins in the vector

  nRun = 0;
  
  for ( auto rn : runs ) {

    for ( int i=0; i<8; ++i ) {
      simspec[i] = new TH1D(TString::Format("SIM%i",i),TString::Format("SIM %i",i),
			 nBins, minRange, maxRange);
    }
    
    TFile *f = new TFile(TString::Format("%s/beta/revCalSim_%i_Beta.root",getenv("REVCALSIM"),rn), "READ");
    TTree *Tin = (TTree*)f->Get("revCalSim");

    std::cout << "Reading from " << TString::Format("%s/beta_highStatistics/revCalSim_%i_Beta.root",getenv("REVCALSIM"),rn).Data() << "\n";
    
    Double_t e0,e1,e2,e3,e4,e5,e6,e7;
    MWPC xE, yE, xW, yW;
    int PID, Side, Type;
    Double_t Erecon;
    
    
    Tin->SetBranchAddress("PID", &PID);
    Tin->SetBranchAddress("type", &Type);
    Tin->SetBranchAddress("side", &Side); 
    Tin->SetBranchAddress("Erecon",&Erecon);
    Tin->SetBranchAddress("xE",&xE);
    Tin->SetBranchAddress("yE",&yE);
    Tin->SetBranchAddress("xW",&xW);
    Tin->SetBranchAddress("yW",&yW);
    Tin->GetBranch("PMT")->GetLeaf("Evis0")->SetAddress(&e0);
    Tin->GetBranch("PMT")->GetLeaf("Evis1")->SetAddress(&e1);
    Tin->GetBranch("PMT")->GetLeaf("Evis2")->SetAddress(&e2);
    Tin->GetBranch("PMT")->GetLeaf("Evis3")->SetAddress(&e3);
    Tin->GetBranch("PMT")->GetLeaf("Evis4")->SetAddress(&e4);
    Tin->GetBranch("PMT")->GetLeaf("Evis5")->SetAddress(&e5);
    Tin->GetBranch("PMT")->GetLeaf("Evis6")->SetAddress(&e6);
    Tin->GetBranch("PMT")->GetLeaf("Evis7")->SetAddress(&e7);
    /*
      Tin->GetBranch("xE")->GetLeaf("center")->SetAddress(&EmwpcX);
      Tin->GetBranch("yE")->GetLeaf("center")->SetAddress(&EmwpcY);
      Tin->GetBranch("xW")->GetLeaf("center")->SetAddress(&WmwpcX);
      Tin->GetBranch("yW")->GetLeaf("center")->SetAddress(&WmwpcY);
      Tin->GetBranch("xE")->GetLeaf("nClipped")->SetAddress(&xE_nClipped);
      Tin->GetBranch("yE")->GetLeaf("nClipped")->SetAddress(&yE_nClipped);
      Tin->GetBranch("xW")->GetLeaf("nClipped")->SetAddress(&xW_nClipped);
      Tin->GetBranch("yW")->GetLeaf("nClipped")->SetAddress(&yW_nClipped);
      Tin->GetBranch("xE")->GetLeaf("mult")->SetAddress(&xE_mult);
      Tin->GetBranch("yE")->GetLeaf("mult")->SetAddress(&yE_mult);
      Tin->GetBranch("xW")->GetLeaf("mult")->SetAddress(&xW_mult);
      Tin->GetBranch("yW")->GetLeaf("mult")->SetAddress(&yW_mult);*/
    
    
    double r2E = 0.; //position of event squared
    double r2W = 0.;

    UInt_t nevents = Tin->GetEntriesFast();
    
    for (unsigned int n=0 ; n<nevents ; n++ ) {
      
      Tin->GetEvent(n);
      
      r2E = xE.center*xE.center + yE.center*yE.center;
      r2W = xW.center*xW.center + yW.center*yW.center;

      if ( PID==1 && Side<2 && Type==0 && Erecon>0. ) {

	if ( Side==0 && ( xE.mult<1 || yE.mult<1 ) ) continue;
	else if ( Side==1 && ( xW.mult<1 || yW.mult<1 ) ) continue;

	if ( r2E > 30.*30. || r2W > 30.*30. ) continue;

	
	if ( Side==0 ) {
	  simspec[0]->Fill(e0);
	  simspec[1]->Fill(e1);
	  simspec[2]->Fill(e2);
	  simspec[3]->Fill(e3);
	}

	if ( Side==1 ) {
	  simspec[4]->Fill(e4);
	  simspec[5]->Fill(e5);
	  simspec[6]->Fill(e6);
	  simspec[7]->Fill(e7);
	}

      }
    }

    for ( int p=0; p<8; ++p ) {
      for ( int bin=1; bin<=nBins; ++bin ) {
	simSpec[nRun][p][bin-1] = (double)simspec[p]->GetBinContent(bin)/totalTime[nRun];
	simSpecErr[nRun][p][bin-1] = simspec[p]->GetBinError(bin)/totalTime[nRun];
      }
    }

    for ( int i=0; i<8; ++i ) { 
      // std::cout << "deleting spec[" << i << "]\n";
      delete simspec[i];
    }
    nRun++;
    delete f;
    
  }

  //Now we take the weighted average over the runs in the octet
  
  TFile *fout = new TFile(TString::Format("%s/EndpointGain/endpointGain_octet-%i.root",
					  getenv("ENDPOINT_ANALYSIS"),octet),"RECREATE");
  //TFile *fout = new TFile(TString::Format("endpointGain_octet-%i.root",
  //					  octet),"RECREATE");
  
  std::cout << "Made output rootfile...\n\n";

  // Data //

  for ( int i=0; i<8; ++i ) {

    spec[i] = new TH1D(TString::Format("PMT%i",i),TString::Format("PMT %i",i),
		    nBins, minRange, maxRange);

  }
 
  for ( int p=0; p<8; ++p ) {
    for ( int bin=1; bin<=nBins; ++bin ) {
      
      double numer = 0.;
      double denom = 0.;
      
      for ( UInt_t i=0; i<runs.size(); ++i ) {
	
	//First background subtract each rate (keeping the error on the rate as just the counting
	// error
	if (i==0) std::cout << bin << ": " <<  pmtSpec[i][p][bin-1] << " - " << bgpmtSpec[i][p][bin-1] << " = ";
	pmtSpec[i][p][bin-1] -= bgpmtSpec[i][p][bin-1];//pmtBackgroundRates[bin-1][p];	
	pmtSpecErr[i][p][bin-1] = TMath::Sqrt( 
					      TMath::Power(bgpmtSpecErr[i][p][bin-1],2) + 
					      TMath::Power(pmtSpecErr[i][p][bin-1],2) );
	if (i==0) std::cout << pmtSpec[i][p][bin-1] << std::endl;

	double weight = pmtSpecErr[i][p][bin-1]>0. ? 1./(pmtSpecErr[i][p][bin-1]*pmtSpecErr[i][p][bin-1]) : 0.;
	numer += pmtSpec[i][p][bin-1]*weight;
	denom += weight;
      }

      spec[p]->SetBinContent(bin, denom>0. ? numer/denom : 0.);
      spec[p]->SetBinError(bin, denom>0. ? TMath::Sqrt(1./denom) : 0. );
    }
  }

  // Sim //
  for ( int i=0; i<8; ++i ) {

    simspec[i] = new TH1D(TString::Format("SIM%i",i),TString::Format("SIM %i",i),
		    nBins, minRange, maxRange);

  }
 
  for ( int p=0; p<8; ++p ) {
    for ( int bin=1; bin<=nBins; ++bin ) {

      double numer = 0.;
      double denom = 0.;
      
      for ( UInt_t i=0; i<runs.size(); ++i ) {
	double weight = simSpec[i][p][bin-1]>0. ? 1./(simSpecErr[i][p][bin-1]*simSpecErr[i][p][bin-1]) : 0.;
	numer += simSpec[i][p][bin-1]*weight;
	denom += weight;
      }

      simspec[p]->SetBinContent(bin, denom>0. ? numer/denom : 0.);
      simspec[p]->SetBinError(bin, denom>0. ? TMath::Sqrt(1./denom) : 0. );
    }
  }

  
  
  
  /////////////////////////// Kurie Fitting ////////////////////

  // First I'm going to Kurie fit the simulated endpoint, and then
  // I will iterate until the data until the endpoint matches this endpoint

  std::vector <Double_t> gain(8,0.);

  TGraphErrors kurie[8];
  TGraphErrors simkurie[8];

  KurieFitter kf, simkf;

  for ( int i=0; i<8; ++i ) {
    
    simkf.FitSpectrum(simspec[i],250.,500.,1.); //Fit the simulated spectrum to get relative endpoint

    kf.setActualW0( simkf.returnW0() ); // Setting the comparison endpoint to the extracted ep from sim
    kf.IterativeKurie(spec[i],250.,500.,1.,1.e-7);
   

    kurie[i] = kf.returnKuriePlot();
    kurie[i].SetName(TString::Format("data%i",i));
    kurie[i].Write();
    
    simkurie[i] = simkf.returnKuriePlot();
    simkurie[i].SetName(TString::Format("sim%i",i));
    simkurie[i].Write();

    gain[i] = kf.returnAlpha();

  }

  
  /*///// Getting the gains... 

  std::vector <Double_t> alpha_data(8,0.);
  std::vector <Double_t> alpha_sim(8,0.);
  std::vector <Double_t> gain(8,0.);

  TGraphErrors kurie[8];
  TGraphErrors simkurie[8];

  KurieFitter kf, simkf;

  for ( int i=0; i<8; ++i ) {
    
    kf.IterativeKurie(spec[i],300.,500.,1.1,1.e-6);
    simkf.IterativeKurie(simspec[i],300.,500.,1.1,1.e-6);

    kurie[i] = kf.returnKuriePlot();
    kurie[i].SetName(TString::Format("data%i",i));
    kurie[i].Write();
    
    simkurie[i] = simkf.returnKuriePlot();
    simkurie[i].SetName(TString::Format("sim%i",i));
    simkurie[i].Write();

    alpha_data[i] = kf.returnAlpha();
    alpha_sim[i] = simkf.returnAlpha();

    gain[i] = alpha_sim[i]>0. ? alpha_data[i]/alpha_sim[i] : 1.;

    }*/

  /// Write out pmt endpoint gain corrections
  std::ofstream gainFile(TString::Format("%s/EndpointGain/endpointGain_octet-%i.dat",
  					 getenv("ENDPOINT_ANALYSIS"),octet));
  // std::ofstream gainFile(TString::Format("endpointGain_octet-%i.dat",octet));

  for ( auto g : gain ) gainFile << g << std::endl;

  gainFile.close();
  

  fout->Write();
  delete fout;

  return 0;
  
}
Beispiel #3
0
int main(int argc, char *argv[])
{
  cout.setf(ios::fixed, ios::floatfield);
  cout.precision(12);

  cout << "Run " << argv[1] << " ..." << endl;
  cout << "... Applying Bi pulser gain corrections ..." << endl;

  // Read gain corrections file
  char tempFileGain[500];
  sprintf(tempFileGain, "%s/gain_bismuth_%s.dat",getenv("GAIN_BISMUTH"), argv[1]);
  cout << "... Reading: " << tempFileGain << endl;

  double fitMean[8], gainCorrection[8];
  ifstream fileGain(tempFileGain);
  for (int i=0; i<8; i++) {
    fileGain >> fitMean[i] >> gainCorrection[i];
  }
  cout << "...   PMT E1: " << gainCorrection[0] << endl;
  cout << "...   PMT E2: " << gainCorrection[1] << endl;
  cout << "...   PMT E3: " << gainCorrection[2] << endl;
  cout << "...   PMT E4: " << gainCorrection[3] << endl;
  cout << "...   PMT W1: " << gainCorrection[4] << endl;
  cout << "...   PMT W2: " << gainCorrection[5] << endl;
  cout << "...   PMT W3: " << gainCorrection[6] << endl;
  cout << "...   PMT W4: " << gainCorrection[7] << endl;

  // Open output ntuple
  char tempOut[500];
  sprintf(tempOut, "%s/replay_pass2_%s.root",getenv("REPLAY_PASS2"), argv[1]);
  //sprintf(tempOut, "replay_pass2_%s.root", argv[1]);
  DataTree *t = new DataTree();
  t->makeOutputTree(std::string(tempOut),"pass2");

  char tempIn[500];
  sprintf(tempIn, "%s/replay_pass1_%s.root", getenv("REPLAY_PASS1"),argv[1]);
  //sprintf(tempIn, "../replay_pass1/replay_pass1_%s.root", argv[1]);
  t->setupInputTree(std::string(tempIn),"pass1");

  int nEvents = t->getEntries();
  cout << "... Processing nEvents = " << nEvents << endl;

  // Loop over events
  for (Int_t i=0; i<nEvents; i++) {
    t->getEvent(i);

    // Apply gain correction factors
    t->ScintE.q1 = t->ScintE.q1*gainCorrection[0];
    t->ScintE.q2 = t->ScintE.q2*gainCorrection[1];
    t->ScintE.q3 = t->ScintE.q3*gainCorrection[2];
    t->ScintE.q4 = t->ScintE.q4*gainCorrection[3];

    t->ScintW.q1 = t->ScintW.q1*gainCorrection[4];
    t->ScintW.q2 = t->ScintW.q2*gainCorrection[5];
    t->ScintW.q3 = t->ScintW.q3*gainCorrection[6];
    t->ScintW.q4 = t->ScintW.q4*gainCorrection[7]; 

    t->fillOutputTree();
  }

  // Write output ntuple
  t->writeOutputFile();
  delete t;

  return 0;
}
int main(int argc, char *argv[])
{
  cout.setf(ios::fixed, ios::floatfield);
  cout.precision(12);

  // Prompt for filename of run numbers
  int iXeRunPeriod;
  cout << "Enter Xenon run period: " << endl;
  cin  >> iXeRunPeriod;
  cout << endl;

  /*bool allResponseClasses = true;
  int numResponseClasses = 0;
  vector <int> responseClasses;
  
  cout << "All Response Classes? (true=1/false=0): " << endl;
  cin  >> allResponseClasses;
  cout << endl;

  if (!allResponseClasses) {
    
    cout << "Enter number of response classes: " << endl;
    cin >> numResponseClasses;
    cout << endl;

    if (numResponseClasses<1 || numResponseClasses>9) {
      cout << "Bad number of response classes to include!!\n";
      exit(1);
    }
    responseClasses.resize(numResponseClasses,0);
    char quest[30];
    for (int i=0; i<numResponseClasses; i++) {
      sprintf(quest,"Enter class #%i: ",i+1);
      cout << quest;
      cin >> responseClasses[i];
      cout << endl;
      
      if (responseClasses[i]<0 || responseClasses[i]>8) {
	cout << "You entered a non-existent response class!\n";
	exit(1);
      }
    }
    }*/


  int nRuns = 0;
  int runList[500];

  char temp[500];
  sprintf(temp, "%s/run_lists/Xenon_Calibration_Run_Period_%i.dat", getenv("ANALYSIS_CODE"),iXeRunPeriod);
  ifstream fileRuns(temp);

  int ii = 0;
  while (fileRuns >> runList[ii]) {
    ii++;
    nRuns++;
  }

  cout << "... Number of runs: " << nRuns << endl;
  for (int i=0; i<nRuns; i++) {
    cout << runList[i] << endl;
  }

  
  double xyBinWidth = 5.; //2.5;
  PositionMap posmap(xyBinWidth,50.);
  posmap.setRCflag(false); //telling the position map to not use the RC choices
  Int_t nBinsXY = posmap.getNbinsXY();
  

  // Open output ntuple
  string tempOutBase;
  string tempOut;
  //sprintf(tempOut, "position_map_%s.root", argv[1]);
  tempOutBase = "position_map_" + itos(iXeRunPeriod);
  /*if (!allResponseClasses) {
    tempOutBase+="_RC_";
    for (int i=0; i< numResponseClasses; i++) {
      tempOutBase+=itos(responseClasses[i]);
    }
    }*/
  tempOut =  getenv("POSITION_MAPS")+tempOutBase+"_"+ftos(xyBinWidth)+"mm.root";
  TFile *fileOut = new TFile(tempOut.c_str(),"RECREATE");

  // Output histograms
  int nPMT = 8;
  int nBinHist = 4100;//1025;

  TH1D *hisxy[nPMT][nBinsXY][nBinsXY];
  char *hisxyName = new char[10];

  for (int p=0; p<nPMT; p++) {
    for (int i=0; i<posmap.getNbinsXY(); i++) {
      for (int j=0; j<posmap.getNbinsXY(); j++) {
        if (p == 0)
          sprintf(hisxyName, "e0_%0.0f_%0.0f", posmap.getBinCenter(i), posmap.getBinCenter(j));
        if (p == 1)
          sprintf(hisxyName, "e1_%0.0f_%0.0f", posmap.getBinCenter(i), posmap.getBinCenter(j));
        if (p == 2)
          sprintf(hisxyName, "e2_%0.0f_%0.0f", posmap.getBinCenter(i), posmap.getBinCenter(j));
        if (p == 3)
          sprintf(hisxyName, "e3_%0.0f_%0.0f", posmap.getBinCenter(i), posmap.getBinCenter(j));
        if (p == 4)
          sprintf(hisxyName, "w0_%0.0f_%0.0f", posmap.getBinCenter(i), posmap.getBinCenter(j));
        if (p == 5)
          sprintf(hisxyName, "w1_%0.0f_%0.0f", posmap.getBinCenter(i), posmap.getBinCenter(j));
        if (p == 6)
          sprintf(hisxyName, "w2_%0.0f_%0.0f", posmap.getBinCenter(i), posmap.getBinCenter(j));
        if (p == 7)
          sprintf(hisxyName, "w3_%0.0f_%0.0f", posmap.getBinCenter(i), posmap.getBinCenter(j));

        hisxy[p][i][j] = new TH1D(hisxyName, "", nBinHist,-100.,4000.0);

      }
    }
  }

  // Loop through input ntuples
  char tempIn[500];
  for (int i=0; i<nRuns; i++) {

    // Open input ntuple
    sprintf(tempIn, "%s/replay_pass2_%i.root",getenv("REPLAY_PASS2"), runList[i]);
    DataTree *t = new DataTree();
    t->setupInputTree(std::string(tempIn),"pass2");

    if ( !t->inputTreeIsGood() ) { 
      std::cout << "Skipping " << tempIn << "... Doesn't exist or couldn't be opened.\n";
      continue;
    }

    int nEvents = t->getEntries();
    cout << "Processing " << runList[i] << " ... " << endl;
    cout << "... nEvents = " << nEvents << endl;


    // Loop over events
    for (int i=0; i<nEvents; i++) {
      t->getEvent(i);  

      // Select Type 0 events
      if (t->PID != 1) continue;
      if (t->Type != 0) continue;

      //Cut out clipped events
      if ( t->Side==0 && ( t->xE.nClipped>0 || t->yE.nClipped>0 || t->xeRC<1 || t->xeRC>4 || t->yeRC<1 || t->yeRC>4 ) ) continue;
      else if ( t->Side==1 && ( t->xW.nClipped>0 || t->yW.nClipped>0 || t->xwRC<1 || t->xwRC>4 || t->ywRC<1 || t->ywRC>4) ) continue;

		
      
      /*bool moveOnX = true, moveOnY=true; // Determining if the event is of the correct response class in x and y
     
	//Swank addition: Wire Chamber Response class. 
	for (int j=0; j<numResponseClasses; j++) {
	  if (t->xeRC == responseClasses[j]) {moveOnX=false;}
	  if (t->yeRC == responseClasses[j]) {moveOnY=false;}
	}
      
	if (moveOnX || moveOnY) continue;*/

      // Type 0 East Trigger
      int intBinX, intBinY; 
      
      if (t->Side == 0) {
	
	intBinX = posmap.getBinNumber(t->xE.center);
        intBinY = posmap.getBinNumber(t->yE.center);

        // Fill PMT histograms
        if (intBinX>-1 && intBinY>-1) hisxy[0][intBinX][intBinY]->Fill(t->ScintE.q1);
        if (intBinX>-1 && intBinY>-1) hisxy[1][intBinX][intBinY]->Fill(t->ScintE.q2);
        if (intBinX>-1 && intBinY>-1) hisxy[2][intBinX][intBinY]->Fill(t->ScintE.q3);
        if (intBinX>-1 && intBinY>-1) hisxy[3][intBinX][intBinY]->Fill(t->ScintE.q4);
      }

      // Type 0 West Trigger
      //moveOnX=moveOnY=true;
      else if (t->Side == 1) {

	//Swank Only Allow triangles!!!	  	
	//for (int j=0; j<numResponseClasses; j++) {
	// if (t->xwRC == responseClasses[j]) {moveOnX=false;}
	// if (t->ywRC == responseClasses[j]) {moveOnY=false;}
	//}
      
	//if (moveOnX || moveOnY) continue;
	
        intBinX = posmap.getBinNumber(t->xW.center);
        intBinY = posmap.getBinNumber(t->yW.center);

	// Fill PMT histograms 
        if (intBinX>-1 && intBinY>-1) hisxy[4][intBinX][intBinY]->Fill(t->ScintW.q1);
        if (intBinX>-1 && intBinY>-1) hisxy[5][intBinX][intBinY]->Fill(t->ScintW.q2);
        if (intBinX>-1 && intBinY>-1) hisxy[6][intBinX][intBinY]->Fill(t->ScintW.q3);
        if (intBinX>-1 && intBinY>-1) hisxy[7][intBinX][intBinY]->Fill(t->ScintW.q4);
      }


    }

    // Close input ntuple
    delete t;

  }


  //Rebinning the histograms based on the mean value...
  for (int p=0; p<nPMT; p++) {
    for (int i=0; i<nBinsXY; i++) {
      for (int j=0; j<nBinsXY; j++) {	

	hisxy[p][i][j]->GetXaxis()->SetRange(1,nBinHist);
	Double_t mean = hisxy[p][i][j]->GetMean();
	hisxy[p][i][j]->GetXaxis()->SetRange(0,nBinHist);
	double nGroup = 4.*mean/200.;
	nGroup = nGroup>1. ? nGroup : 1.;
	hisxy[p][i][j]->Rebin((int)nGroup);
	
      }
    }
  }

  // Extracting mean from 200 keV peak 

  // Define fit ranges
  double xLowBin[nPMT][nBinsXY][nBinsXY];
  double xHighBin[nPMT][nBinsXY][nBinsXY];
  double xLow[nPMT][nBinsXY][nBinsXY];
  double xHigh[nPMT][nBinsXY][nBinsXY];
  int maxBin[nPMT][nBinsXY][nBinsXY];
  double maxCounts[nPMT][nBinsXY][nBinsXY];
  double binCenterMax[nPMT][nBinsXY][nBinsXY];
  double meanVal[nPMT][nBinsXY][nBinsXY]; // Holds the mean of the distribution as defined by first fitting the peak
  double fitMean[nPMT][nBinsXY][nBinsXY]; // Holds the mean of the low energy peak
  double fitSigma[nPMT][nBinsXY][nBinsXY]; // Holds the sigma of the low energy peak
  double endpoint[nPMT][nBinsXY][nBinsXY]; // Holds the endpoint


  /////// First determine roughly where the low energy peak is
  TSpectrum *spec;

  for (int p=0; p<nPMT; p++) {
    for (int i=0; i<nBinsXY; i++) {
      for (int j=0; j<nBinsXY; j++) {	
	
	double r = sqrt(power(posmap.getBinCenter(j),2)+power(posmap.getBinCenter(i),2));
	
        // Find bin with maximum content
	hisxy[p][i][j]->GetXaxis()->SetRange(2,nBinHist);
        maxBin[p][i][j] = hisxy[p][i][j]->GetMaximumBin();
        maxCounts[p][i][j] = hisxy[p][i][j]->GetBinContent(maxBin[p][i][j]);
        binCenterMax[p][i][j] = hisxy[p][i][j]->GetBinCenter(maxBin[p][i][j]);
	
	  
	if (r<=(50.+2*xyBinWidth))
	      {
		spec = new TSpectrum(20);
		Int_t npeaks = spec->Search(hisxy[p][i][j],1.5,"",0.5);
		
		if (npeaks==0)
		  {
		    cout << "No peaks identified at PMT" << p << " position " << posmap.getBinCenter(i) << ", " << posmap.getBinCenter(j) << endl;
		  }
		else
		  {
		    Float_t *xpeaks = spec->GetPositionX(); // Note that newer versions of ROOT return a pointer to double...
		    TAxis *xaxis = (TAxis*)(hisxy[p][i][j]->GetXaxis());
		    Int_t peakBin=0;
		    Double_t BinSum=0.;
		    Double_t BinSumHold = 0.;
		    Int_t maxPeak=0.;
		    for (int pk=0;pk<npeaks;pk++) {
		      peakBin = xaxis->FindBin(xpeaks[pk]);
		      //Sum over 3 center bins of peak and compare to previos BinSum to see which peak is higher
		      BinSum = hisxy[p][i][j]->GetBinContent(peakBin) + hisxy[p][i][j]->GetBinContent(peakBin-1) + hisxy[p][i][j]->GetBinContent(peakBin+1);
		      if (BinSum>BinSumHold) {
			BinSumHold=BinSum;
			maxPeak=pk;
		      }
		    }
		    binCenterMax[p][i][j] = xpeaks[maxPeak];
		  }
		delete spec;
	      }
	xLow[p][i][j] = binCenterMax[p][i][j]*2./3.;
	xHigh[p][i][j] = 1.5*binCenterMax[p][i][j];

	
      }
    }
  }
  
  //////// Now fit the histograms for the peak

  for (int p=0; p<nPMT; p++) {
    for (int i=0; i<nBinsXY; i++) {
      for (int j=0; j<nBinsXY; j++) {	

	if ( hisxy[p][i][j]->Integral() > 500.) {// && r<=(50.+2*xBinWidth)) {

	  SinglePeakHist sing(hisxy[p][i][j], xLow[p][i][j], xHigh[p][i][j], true, 5, 0.8, 1.);

	  if (sing.isGoodFit() && sing.ReturnMean()>xLow[p][i][j] && sing.ReturnMean()<xHigh[p][i][j]) {
	    fitMean[p][i][j] = sing.ReturnMean();
	    fitSigma[p][i][j] = sing.ReturnSigma();
	  }

	  else  {
	    cout << "Can't converge on peak in PMT " << p << " at (" << posmap.getBinCenter(i) << ", " << posmap.getBinCenter(j) << "). Trying one more time......" << endl;
	    sing.SetRangeMin(xLow[p][i][j]);
	    sing.SetRangeMax(xHigh[p][i][j]);
	    sing.FitHist((double)maxBin[p][i][j], hisxy[p][i][j]->GetMean()/5., hisxy[p][i][j]->GetBinContent(maxBin[p][i][j]));

	    if (sing.isGoodFit() && sing.ReturnMean()>xLow[p][i][j] && sing.ReturnMean()<xHigh[p][i][j]) { 
	      fitMean[p][i][j] = sing.ReturnMean();
	      fitSigma[p][i][j] = sing.ReturnSigma();
	    }
	    else {
	      fitMean[p][i][j] = hisxy[p][i][j]->GetMean()/1.8;
	      int meanBin = hisxy[p][i][j]->GetXaxis()->FindBin(fitMean[p][i][j]);
	      int counts_check = hisxy[p][i][j]->GetBinContent(meanBin);
	      int counts = counts_check;
	      int bin=0;
	      if ( counts_check > 10 ) {
		while (counts>0.6*counts_check) {
		  bin++;
		  counts = hisxy[p][i][j]->GetBinContent(meanBin+bin);
		}
	      }
	  
	      xHighBin[p][i][j] = (meanBin+bin) < hisxy[p][i][j]->GetNbinsX()/3 ? (meanBin+bin): meanBin;
	      fitSigma[p][i][j] = hisxy[p][i][j]->GetBinCenter(xHighBin[p][i][j]) - fitMean[p][i][j];

	      cout << "Can't converge on peak in PMT " << p << " at bin (" << posmap.getBinCenter(i) << ", " << posmap.getBinCenter(j) << "). ";
	      cout << "**** replaced fit mean with hist_mean/1.8 " << fitMean[p][i][j] << endl;
	    }
	  }
	}
	else { 
	  fitMean[p][i][j] = hisxy[p][i][j]->GetMean()/1.8;
	  //if ( fitMean[p][i][j]>xLow[p][i][j] && fitMean[p][i][j]<xHigh[p][i][j] ) 
	  cout << "**** replaced fit mean with hist_mean/1.8 " << fitMean[p][i][j] << endl;
	  //else { 
	  //fitMean[p][i][j] = binCenterMax[p][i][j];
	  //cout << "**** replaced fit mean with binCenterMax " << fitMean[p][i][j] << endl;
	  //}
	  int meanBin = hisxy[p][i][j]->GetXaxis()->FindBin(fitMean[p][i][j]);
	  int counts_check = hisxy[p][i][j]->GetBinContent(meanBin);
	  int counts = counts_check;
	  int bin=0;
	  double frac = exp(-1/2.); // This should be the fraction of events for a gaussian at 1 sigma
	  if ( counts_check > 10 ) {
	    while (counts>frac*counts_check) {
	      bin++;
	      counts = hisxy[p][i][j]->GetBinContent(meanBin+bin);
	    }
	  }	  
	  xHighBin[p][i][j] = (meanBin+bin) < hisxy[p][i][j]->GetNbinsX()/3 ? (meanBin+bin): meanBin;
	  fitSigma[p][i][j] = hisxy[p][i][j]->GetBinCenter(xHighBin[p][i][j]) - fitMean[p][i][j];	 
	}

      }
    }
  }

  fileOut->Write(); // Writing the histograms with the peaks to file

  ////////// Now determine the mean of the Xe distribution in every position bin above the peak to avoid
  ////////// trigger effects
  
  double nSigmaFromMean = 1.5; // This is how far over from the peak we are starting the sum of the spectra

  for (int p=0; p<nPMT; p++) {
    for (int i=0; i<nBinsXY; i++) {
      for (int j=0; j<nBinsXY; j++) {

	hisxy[p][i][j]->GetXaxis()->SetRange(hisxy[p][i][j]->GetXaxis()->FindBin(fitMean[p][i][j]+nSigmaFromMean*fitSigma[p][i][j]), hisxy[p][i][j]->GetNbinsX()-1);
	meanVal[p][i][j] = hisxy[p][i][j]->GetMean();
	hisxy[p][i][j]->GetXaxis()->SetRange(0, hisxy[p][i][j]->GetNbinsX()); // Set the range back to the full range

      }
    }
  }

  ////////// Now determine the endpoint of the Xe distribution in every position bin

  double lowerBoundMult = 1.;
  double upperBoundMult = 2.;

  TFile *epfile = new TFile(TString::Format("%s/%s_%smm_endpoints.root",getenv("POSITION_MAPS"),tempOutBase.c_str(),ftos(xyBinWidth).c_str()),"RECREATE");

  TGraphErrors epgraph;
  
  KurieFitter kf;
  
  for (int p=0; p<nPMT; p++) {
    for (int i=0; i<nBinsXY; i++) {
      for (int j=0; j<nBinsXY; j++) {

	kf.FitSpectrum(hisxy[p][i][j], lowerBoundMult*meanVal[p][i][j], upperBoundMult*meanVal[p][i][j], 1.);
	endpoint[p][i][j] = kf.returnK0();

	epgraph = kf.returnKuriePlot();
	epgraph.SetName(TString::Format("pmt%i_x%0.1f_y%0.1f",p,posmap.getBinCenter(i), posmap.getBinCenter(j)));
	epgraph.Write();

      }
    }
  }

  delete epfile;
  delete fileOut;


  ///////////////////////// Extract position maps for meanVal ///////////////////////////////
  double norm[nPMT];
  for (int p=0; p<nPMT; p++) {
    norm[p] = meanVal[p][nBinsXY/2][nBinsXY/2];
    cout << norm[p] << endl;
  }

  //Checking for weird outliers
  for (int p=0; p<nPMT; p++) {
    for (int i=0; i<nBinsXY; i++) {
      for (int j=0; j<nBinsXY; j++) {
	
	if ( meanVal[p][i][j]<(0.1*norm[p]) || meanVal[p][i][j]>(8.*norm[p]) ) 
	  meanVal[p][i][j] = (0.1*norm[p]);

      }
    }
  }

  double positionMap[nPMT][nBinsXY][nBinsXY];
  for (int p=0; p<nPMT; p++) {
    for (int i=0; i<nBinsXY; i++) {
      for (int j=0; j<nBinsXY; j++) {
        positionMap[p][i][j] = meanVal[p][i][j] / norm[p];
      }
    }
  }

  // Write position maps to file
  TString mapFile = TString::Format("%s/%s_%0.1fmm.dat", getenv("POSITION_MAPS"),tempOutBase.c_str(),xyBinWidth);
  ofstream outMap(mapFile.Data());

  for (int i=0; i<nBinsXY; i++) {
    for (int j=0; j<nBinsXY; j++) {
      outMap << posmap.getBinCenter(i) << "  "
             << posmap.getBinCenter(j) << "  "
             << positionMap[0][i][j] << "  "
             << positionMap[1][i][j] << "  "
             << positionMap[2][i][j] << "  "
             << positionMap[3][i][j] << "  "
             << positionMap[4][i][j] << "  "
             << positionMap[5][i][j] << "  "
             << positionMap[6][i][j] << "  "
             << positionMap[7][i][j] << endl;
    }
  }
  outMap.close();

  // Write norms to file
  TString normFile = TString::Format("%s/norm_%s_%0.1fmm.dat", getenv("POSITION_MAPS"),tempOutBase.c_str(),xyBinWidth);
  ofstream outNorm(normFile.Data());

  for (int p=0; p<nPMT; p++) {
    outNorm << norm[p] << endl;
  }
  outNorm.close();

  ///////////////////////// Extract position maps for peaks ///////////////////////////////

  for (int p=0; p<nPMT; p++) {
    norm[p] = fitMean[p][nBinsXY/2][nBinsXY/2];
    cout << norm[p] << endl;
  }

  //Checking for weird outliers
  for (int p=0; p<nPMT; p++) {
    for (int i=0; i<nBinsXY; i++) {
      for (int j=0; j<nBinsXY; j++) {
	
	if ( fitMean[p][i][j]<(0.1*norm[p]) || fitMean[p][i][j]>(8.*norm[p]) ) 
	  fitMean[p][i][j] = (0.1*norm[p]);

      }
    }
  }

  for (int p=0; p<nPMT; p++) {
    for (int i=0; i<nBinsXY; i++) {
      for (int j=0; j<nBinsXY; j++) {
        positionMap[p][i][j] = fitMean[p][i][j] / norm[p];
      }
    }
  }

  // Write position maps to file
  mapFile = TString::Format("%s/%s_%0.1fmm_peakFits.dat", getenv("POSITION_MAPS"),tempOutBase.c_str(),xyBinWidth);
  outMap.open(mapFile.Data());
  

  for (int i=0; i<nBinsXY; i++) {
    for (int j=0; j<nBinsXY; j++) {
      outMap << posmap.getBinCenter(i) << "  "
             << posmap.getBinCenter(j) << "  "
             << positionMap[0][i][j] << "  "
             << positionMap[1][i][j] << "  "
             << positionMap[2][i][j] << "  "
             << positionMap[3][i][j] << "  "
             << positionMap[4][i][j] << "  "
             << positionMap[5][i][j] << "  "
             << positionMap[6][i][j] << "  "
             << positionMap[7][i][j] << endl;
    }
  }
  outMap.close();


  ///////////////////////// Extract position maps for endpoints ///////////////////////////////

  for (int p=0; p<nPMT; p++) {
    norm[p] = endpoint[p][nBinsXY/2][nBinsXY/2];
    cout << norm[p] << endl;
  }

  //Checking for weird outliers
  for (int p=0; p<nPMT; p++) {
    for (int i=0; i<nBinsXY; i++) {
      for (int j=0; j<nBinsXY; j++) {
	
	if ( endpoint[p][i][j]<(0.1*norm[p]) || endpoint[p][i][j]>(8.*norm[p]) ) 
	  endpoint[p][i][j] = (0.1*norm[p]);

      }
    }
  }

  for (int p=0; p<nPMT; p++) {
    for (int i=0; i<nBinsXY; i++) {
      for (int j=0; j<nBinsXY; j++) {
        positionMap[p][i][j] = endpoint[p][i][j] / norm[p];
      }
    }
  }

  // Write position maps to file
  mapFile = TString::Format("%s/%s_%0.1fmm_endpoints.dat", getenv("POSITION_MAPS"),tempOutBase.c_str(),xyBinWidth);
  outMap.open(mapFile.Data());

  for (int i=0; i<nBinsXY; i++) {
    for (int j=0; j<nBinsXY; j++) {
      outMap << posmap.getBinCenter(i) << "  "
             << posmap.getBinCenter(j) << "  "
             << positionMap[0][i][j] << "  "
             << positionMap[1][i][j] << "  "
             << positionMap[2][i][j] << "  "
             << positionMap[3][i][j] << "  "
             << positionMap[4][i][j] << "  "
             << positionMap[5][i][j] << "  "
             << positionMap[6][i][j] << "  "
             << positionMap[7][i][j] << endl;
    }
  }
  outMap.close();



  return 0;
}