void ExtractTrackBasedTiming(TString fileName = "hd_root.root", int runNumber = 10390, TString variation = "default", bool verbose = false,TString prefix = ""){

   // set "prefix" in case you want to ship the txt files elsewhere...
   cout << "Performing Track Matched timing fits for File: " << fileName.Data() << " Run: " << runNumber << " Variation: " << variation.Data() << endl;

   ExtractTrackBasedTimingNS::thisFile = TFile::Open( fileName , "UPDATE");
   if (ExtractTrackBasedTimingNS::thisFile == 0) {
      cout << "Unable to open file " << fileName.Data() << "...Exiting" << endl;
      return;
   }

   //We need the existing constants, The best we can do here is just read them from the file.
   vector<double> sc_tdc_time_offsets;
   vector<double> sc_fadc_time_offsets;
   vector<double> tof_tdc_time_offsets;
   vector<double> tof_fadc_time_offsets;
   vector<double> tagm_tdc_time_offsets;
   vector<double> tagm_fadc_time_offsets;
   vector<double> tagh_tdc_time_offsets;
   vector<double> tagh_fadc_time_offsets;
   vector<double> tagh_counter_quality;

   double sc_t_base_fadc, sc_t_base_tdc;
   double tof_t_base_fadc, tof_t_base_tdc;
   double bcal_t_base_fadc, bcal_t_base_tdc;
   double tagm_t_base_fadc, tagm_t_base_tdc;
   double tagh_t_base_fadc, tagh_t_base_tdc;
   double fdc_t_base_fadc, fdc_t_base_tdc;
   double fcal_t_base;
   double cdc_t_base;
   double RF_Period;

   cout << "Grabbing CCDB constants..." << endl;
   // Base times
   GetCCDBConstants1("/CDC/base_time_offset" ,runNumber, variation, cdc_t_base);
   GetCCDBConstants1("/FCAL/base_time_offset",runNumber, variation, fcal_t_base);
   GetCCDBConstants1("/PHOTON_BEAM/RF/beam_period",runNumber, variation, RF_Period);
   GetCCDBConstants2("/FDC/base_time_offset" ,runNumber, variation, fdc_t_base_fadc, fdc_t_base_tdc);
   GetCCDBConstants2("/BCAL/base_time_offset" ,runNumber, variation, bcal_t_base_fadc, bcal_t_base_tdc);
   GetCCDBConstants2("/PHOTON_BEAM/microscope/base_time_offset" ,runNumber, variation, tagm_t_base_fadc, tagm_t_base_tdc);
   GetCCDBConstants2("/PHOTON_BEAM/hodoscope/base_time_offset" ,runNumber, variation, tagh_t_base_fadc, tagh_t_base_tdc);
   GetCCDBConstants2("/START_COUNTER/base_time_offset" ,runNumber, variation, sc_t_base_fadc, sc_t_base_tdc);
   GetCCDBConstants2("/TOF/base_time_offset" ,runNumber, variation, tof_t_base_fadc, tof_t_base_tdc);
   // Per channel
   //GetCCDBConstants("/BCAL/TDC_offsets"    ,runNumber, variation, bcal_tdc_offsets);
   //GetCCDBConstants("/FCAL/timing_offsets" ,runNumber, variation, fcal_adc_offsets);
   GetCCDBConstants("/START_COUNTER/adc_timing_offsets" ,runNumber, variation, sc_fadc_time_offsets);
   GetCCDBConstants("/START_COUNTER/tdc_timing_offsets" ,runNumber, variation, sc_tdc_time_offsets);
   GetCCDBConstants("/PHOTON_BEAM/microscope/fadc_time_offsets" ,runNumber, variation, tagm_fadc_time_offsets,3);// Interested in 3rd column
   GetCCDBConstants("/PHOTON_BEAM/microscope/tdc_time_offsets"  ,runNumber, variation, tagm_tdc_time_offsets,3);
   GetCCDBConstants("/PHOTON_BEAM/hodoscope/fadc_time_offsets"  ,runNumber, variation, tagh_fadc_time_offsets,2);// Interested in 2nd column
   GetCCDBConstants("/PHOTON_BEAM/hodoscope/tdc_time_offsets"   ,runNumber, variation, tagh_tdc_time_offsets,2);
   GetCCDBConstants("/PHOTON_BEAM/hodoscope/counter_quality"    ,runNumber, variation, tagh_counter_quality,2);
   GetCCDBConstants("/TOF/adc_timing_offsets",runNumber, variation, tof_fadc_time_offsets);
   GetCCDBConstants("/TOF/timing_offsets",runNumber, variation, tof_tdc_time_offsets);

   cout << "CDC base times = " << cdc_t_base << endl;
   cout << "FCAL base times = " << fcal_t_base << endl;
   cout << "FDC base times = " << fdc_t_base_fadc << ", " << fdc_t_base_tdc << endl;
   cout << "BCAL base times = " << bcal_t_base_fadc << ", " << bcal_t_base_tdc << endl;
   cout << "SC base times = " << sc_t_base_fadc << ", " << sc_t_base_tdc << endl;
   cout << "TOF base times = " << tof_t_base_fadc << ", " << tof_t_base_tdc << endl;
   cout << "TAGH base times = " << tagh_t_base_fadc << ", " << tagh_t_base_tdc << endl;
   cout << "TAGM base times = " << tagm_t_base_fadc << ", " << tagm_t_base_tdc << endl;

   cout << endl;
   cout << "RF_Period = " << RF_Period << endl;
   cout << endl;

   cout << "Done grabbing CCDB constants...Entering fits..." << endl;

   // Do our final step in the timing alignment with tracking

   //When the RF is present we can try to simply pick out the correct beam bucket for each of the runs
   //First just a simple check to see if we have the appropriate data
   bool useRF = false;
   TH1I *testHist = ExtractTrackBasedTimingNS::Get1DHistogram("HLDetectorTiming", "TAGH_TDC_RF_Compare","Counter ID 001");
   if (testHist != NULL){ // Not great since we rely on channel 1 working, but can be craftier later.
      cout << "Using RF Times for Calibration" << endl;
      useRF = true;
   }
   ofstream outFile;
   TH2I *thisHist; 
   thisHist = ExtractTrackBasedTimingNS::Get2DHistogram("HLDetectorTiming", "TRACKING", "TAGM - SC Target Time");
   if (useRF) thisHist = ExtractTrackBasedTimingNS::Get2DHistogram("HLDetectorTiming", "TRACKING", "TAGM - RFBunch Time");
   if (thisHist != NULL){
      //Statistics on these histograms are really quite low we will have to rebin and do some interpolation
      outFile.open(prefix + "tagm_tdc_timing_offsets.txt", ios::out | ios::trunc);
      outFile.close(); // clear file
      outFile.open(prefix + "tagm_adc_timing_offsets.txt", ios::out | ios::trunc);
      outFile.close(); // clear file
      int nBinsX = thisHist->GetNbinsX();
      int nBinsY = thisHist->GetNbinsY();
      TH1D * selectedTAGMOffset = new TH1D("selectedTAGMOffset", "Selected TAGM Offset; Column; Offset [ns]", nBinsX, 0.5, nBinsX + 0.5);
      TH1I * TAGMOffsetDistribution = new TH1I("TAGMOffsetDistribution", "TAGM Offset; TAGM Offset [ns]; Entries", 500, -250, 250);
      for (int i = 1 ; i <= nBinsX; i++){ 
         TH1D *projY = thisHist->ProjectionY("temp", i, i);
         // Scan over the histogram
         //chose the correct number of bins based on the histogram
         float nsPerBin = (projY->GetBinCenter(projY->GetNbinsX()) - projY->GetBinCenter(1)) / projY->GetNbinsX();
         float timeWindow = 3; //ns (Full Width)
         int binWindow = int(timeWindow / nsPerBin);
         double maxEntries = 0;
         double maxMean = 0;
         for (int j = 1 ; j <= projY->GetNbinsX();j++){
            int minBin = j;
            int maxBin = (j + binWindow) <= projY->GetNbinsX() ? (j + binWindow) : projY->GetNbinsX();
            double sum = 0, nEntries = 0;
            for (int bin = minBin; bin <= maxBin; bin++){
               sum += projY->GetBinContent(bin) * projY->GetBinCenter(bin);
               nEntries += projY->GetBinContent(bin);
               if (bin == maxBin){
                  if (nEntries > maxEntries) {
                     maxMean = sum / nEntries;
                     maxEntries = nEntries;
                  }
               } 
            }
         }
         //In the case there is RF, our job is to pick just the number of the correct beam bunch, so that's really all we need.
         if(useRF) {
            int beamBucket = int((maxMean / RF_Period) + 0.5); // +0.5 to handle rounding correctly
            selectedTAGMOffset->SetBinContent(i, beamBucket);
            TAGMOffsetDistribution->Fill(beamBucket);
         }
         else{
            selectedTAGMOffset->SetBinContent(i, maxMean);
            TAGMOffsetDistribution->Fill(maxMean);
         }
      }
      double meanOffset = TAGMOffsetDistribution->GetMean();
      // This might be in units of beam bunches, so we need to convert
      if (useRF) meanOffset *= RF_Period;
      if (verbose) {
         cout << "Dumping TAGM results...\n=======================================" << endl;
         cout << "TAGM mean Offset = " << meanOffset << endl;
         cout << "fADC Offsets" << endl;
      }

      outFile.open(prefix + "tagm_adc_timing_offsets.txt", ios::out);
      //for (int i = 1 ; i <= nBinsX; i++){
      // Loop over rows
      if (verbose) cout << "Column\tRow\tvalueToUse\toldValue\tmeanOffset\tTotal" << endl;
      for (unsigned int column = 1; column <= 102; column++){
         int index = GetCCDBIndexTAGM(column, 0);
         double valueToUse = selectedTAGMOffset->GetBinContent(index);
         if (useRF) valueToUse *= RF_Period;

         //if (valueToUse == 0) valueToUse = meanOffset;
         outFile << "0 " << column << " " << valueToUse + tagm_fadc_time_offsets[index-1] - meanOffset<< endl;
         if (verbose) printf("0\t%i\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\n", column, valueToUse, tagm_fadc_time_offsets[index-1], meanOffset, 
               valueToUse + tagm_fadc_time_offsets[index-1] - meanOffset);
         if (column == 9 || column == 27 || column == 81 || column == 99){
            for (unsigned int row = 1; row <= 5; row++){
               index = GetCCDBIndexTAGM(column, row);
               valueToUse = selectedTAGMOffset->GetBinContent(index);
               if (useRF) valueToUse *= RF_Period;
               //if (valueToUse == 0) valueToUse = meanOffset;
               outFile << row << " " << column << " " << valueToUse + tagm_fadc_time_offsets[index-1] - meanOffset<< endl;
               if (verbose) printf("%i\t%i\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\n", row, column, valueToUse, tagm_fadc_time_offsets[index-1], meanOffset,
                     valueToUse + tagm_fadc_time_offsets[index-1] - meanOffset);
            }
         }
      }
      outFile.close();

      if (verbose) {
         cout << "TDC Offsets" << endl;
         cout << "Column\tRow\tvalueToUse\toldValue\tmeanOffset\tTotal" << endl;
      }
      outFile.open(prefix + "tagm_tdc_timing_offsets.txt", ios::out);
      //for (int i = 1 ; i <= nBinsX; i++){
      // Loop over rows
      for (unsigned int column = 1; column <= 102; column++){
         int index = GetCCDBIndexTAGM(column, 0);
         double valueToUse = selectedTAGMOffset->GetBinContent(index);
         if (useRF) valueToUse *= RF_Period;
         //if (valueToUse == 0) valueToUse = meanOffset;
         outFile << "0 " << column << " " << valueToUse + tagm_tdc_time_offsets[index-1] - meanOffset << endl;
         if (verbose) printf("0\t%i\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\n", column, valueToUse, tagm_tdc_time_offsets[index-1], meanOffset,
               valueToUse + tagm_tdc_time_offsets[index-1] - meanOffset);
         if (column == 9 || column == 27 || column == 81 || column == 99){
            for (unsigned int row = 1; row <= 5; row++){
               index = GetCCDBIndexTAGM(column, row);
               valueToUse = selectedTAGMOffset->GetBinContent(index);
               if (useRF) valueToUse *= RF_Period;
               //if (valueToUse == 0) valueToUse = meanOffset;
               outFile << row << " " << column << " " << valueToUse + tagm_tdc_time_offsets[index-1] - meanOffset << endl;
               if (verbose) printf("%i\t%i\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\n", row, column, valueToUse, tagm_tdc_time_offsets[index-1], meanOffset,
                     valueToUse + tagm_tdc_time_offsets[index-1] - meanOffset);
            }
         }
      }
      outFile.close();
      outFile.open(prefix + "tagm_base_time.txt", ios::out);
      if (verbose) {
         printf("TAGM ADC Base = %f - (%f) = %f\n", tagm_t_base_fadc, meanOffset, tagm_t_base_fadc - meanOffset);
         printf("TAGM TDC Base = %f - (%f) = %f\n", tagm_t_base_tdc, meanOffset, tagm_t_base_tdc - meanOffset);
      }
      outFile << tagm_t_base_fadc - meanOffset << " " << tagm_t_base_tdc - meanOffset << endl;
      outFile.close();

   }

   thisHist = ExtractTrackBasedTimingNS::Get2DHistogram("HLDetectorTiming", "TRACKING", "TAGH - SC Target Time");
   if (useRF) thisHist = ExtractTrackBasedTimingNS::Get2DHistogram("HLDetectorTiming", "TRACKING", "TAGH - RFBunch Time");
   if (thisHist != NULL) {
      outFile.open(prefix + "tagh_tdc_timing_offsets.txt", ios::out | ios::trunc);
      outFile.close(); // clear file
      outFile.open(prefix + "tagh_adc_timing_offsets.txt", ios::out | ios::trunc);
      outFile.close(); // clear file

      // Setup histogram for determining the most probable change in offset for each F1TDC slot
      // This is needed to account for the occasional uniform shift in offsets of the 32 counters in a slot
      const int NtdcSlots = 8;
      TH1I * tdcDist[NtdcSlots];
      for (int i = 1; i <= NtdcSlots; i++) {
         stringstream ss; ss << i;
         TString s = ss.str();
         double range = 500.0; double width = 0.1;
         int Nbins = range/width;
         double low = -0.5*range - 0.5*width;
         double high = 0.5*range - 0.5*width;
         tdcDist[i-1] = new TH1I("TAGHOffsetDistribution_"+s, "TAGH Offset (slot "+s+"); TAGH Offset [ns]; Entries", Nbins, low, high);
      }

      int nBinsX = thisHist->GetNbinsX();
      TH1D * selectedTAGHOffset = new TH1D("selectedTAGHOffset", "Selected TAGH Offset; ID; Offset [ns]", nBinsX, 0.5, nBinsX + 0.5);
      for (int i = 1 ; i <= nBinsX; i++) {
         TH1D *projY = thisHist->ProjectionY("temp", i, i);
         // Scan over histogram to find mean offset in timeWindow with largest integral
         // Choose the correct number of bins based on the histogram
         double nsPerBin = (projY->GetBinCenter(projY->GetNbinsX()) - projY->GetBinCenter(1)) / projY->GetNbinsX();
         double timeWindow = 2.0; // ns (Full Width)
         int binWindow = int(timeWindow / nsPerBin);

         double maxEntries = 0;
         double maxMean = 0;
         for (int j = 1; j <= projY->GetNbinsX(); j++) {
            int minBin = j;
            int maxBin = (j + binWindow) <= projY->GetNbinsX() ? (j + binWindow) : projY->GetNbinsX();
            double sum = 0; 
            double nEntries = 0;
            for (int bin = minBin; bin <= maxBin; bin++) {
               sum += projY->GetBinContent(bin) * projY->GetBinCenter(bin);
               nEntries += projY->GetBinContent(bin);
               if (bin == maxBin) {
                  if (nEntries > maxEntries) {
                     maxMean = sum / nEntries;
                     maxEntries = nEntries;
                  }
               }
            }
         }

         if (tagh_counter_quality[i-1] == 0.0) {
            selectedTAGHOffset->SetBinContent(i, 0);
            continue;
         }
         int tdc_slot = GetF1TDCslotTAGH(i);
         if (useRF) {
            int beamBucket;
            if (maxMean >= 0) beamBucket = int((maxMean / RF_Period) + 0.5); // +0.5 to handle rounding correctly
            else beamBucket = int((maxMean / RF_Period) - 0.5);
            selectedTAGHOffset->SetBinContent(i, beamBucket);
            if (maxEntries != 0.0) tdcDist[tdc_slot - 1]->Fill(beamBucket);
         } else {
            selectedTAGHOffset->SetBinContent(i, maxMean);
            if (maxEntries != 0.0) tdcDist[tdc_slot - 1]->Fill(maxMean);
         }
      }
      // Most probable change in offset or beam bucket per F1TDC slot
      double mpDelta[NtdcSlots];
      for (int i = 1; i <= NtdcSlots; i++) {
         int mpBin = tdcDist[i-1]->GetMaximumBin();
         mpDelta[i-1] = (mpBin > 0) ? tdcDist[i-1]->GetBinCenter(mpBin) : 0.0;
         if (useRF) mpDelta[i-1] *= RF_Period;
         if (verbose) {
            cout << "TAGH most probable Offset = " << i << ", " << mpDelta[i-1] << endl;
         }
      }

      if (verbose) {
         cout << "Dumping TAGH results...\n=======================================" << endl;
         cout << "Type\tChannel\tvalueToUse\toldValue\tmpDelta\tTotal" << endl;
      }

      double limit = 2.5; // ns
      double ccdb_sum = 0.0;
      for (int i = 1; i <= nBinsX; i++) ccdb_sum += tagh_tdc_time_offsets[i-1];
      double c1_tdcOffset = 0.0;
      outFile.open(prefix + "tagh_tdc_timing_offsets.txt");
      for (int i = 1; i <= nBinsX; i++) {
         if (tagh_counter_quality[i-1] == 0.0) {
            outFile << i << " " << 0 << endl;
            continue;
         }
         int tdc_slot = GetF1TDCslotTAGH(i);
         double delta = selectedTAGHOffset->GetBinContent(i);
         if (useRF) delta *= RF_Period;
         if (ccdb_sum > 0.0 && fabs(delta - mpDelta[tdc_slot-1]) > limit) {
            delta = mpDelta[tdc_slot-1];
         }
         double ccdb = tagh_tdc_time_offsets[i-1];
         double offset = ccdb + delta;
         if (i == 1) c1_tdcOffset = offset;
         offset -= c1_tdcOffset;
         outFile << i << " " << offset << endl;
         if (verbose) printf("TDC\t%i\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\n", i, delta, ccdb, mpDelta[tdc_slot-1], offset);
      }
      outFile.close();

      ccdb_sum = 0.0;
      for (int i = 1; i <= nBinsX; i++) ccdb_sum += tagh_fadc_time_offsets[i-1];
      double c1_adcOffset = 0.0;
      outFile.open(prefix + "tagh_adc_timing_offsets.txt");
      for (int i = 1; i <= nBinsX; i++) {
         if (tagh_counter_quality[i-1] == 0.0) {
            outFile << i << " " << 0 << endl;
            continue;
         }
         int tdc_slot = GetF1TDCslotTAGH(i);
         double delta = selectedTAGHOffset->GetBinContent(i);
         if (useRF) delta *= RF_Period;
         if (ccdb_sum > 0.0 && fabs(delta - mpDelta[tdc_slot-1]) > limit) {
            delta = mpDelta[tdc_slot-1];
         }
         double ccdb = tagh_fadc_time_offsets[i-1];
         double offset = ccdb + delta;
         if (i == 1) c1_adcOffset = offset;
         offset -= c1_adcOffset;
         outFile << i << " " << offset << endl;
         if (verbose) printf("ADC\t%i\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\n", i, delta, ccdb, mpDelta[tdc_slot-1], offset);
      }
      outFile.close();

      outFile.open(prefix + "tagh_base_time.txt");
      outFile << tagh_t_base_fadc - c1_adcOffset << " " << tagh_t_base_tdc - c1_tdcOffset << endl;
      if (verbose) {
         printf("TAGH ADC Base = %f - (%f) = %f\n", tagh_t_base_fadc, c1_adcOffset, tagh_t_base_fadc - c1_adcOffset);
         printf("TAGH TDC Base = %f - (%f) = %f\n", tagh_t_base_tdc, c1_tdcOffset, tagh_t_base_tdc - c1_tdcOffset);
      }
      outFile.close();
   }

   // We can use the RF time to calibrate the SC time (Experimental for now)
   double meanSCOffset = 0.0; // In case we change the time of the SC, we need this in this scope
   if(useRF){
      TH1F * selectedSCSectorOffset = new TH1F("selectedSCSectorOffset", "Selected TDC-RF offset;Sector; Time", 30, 0.5, 30.5);
      TH1F * selectedSCSectorOffsetDistribution = new TH1F("selectedSCSectorOffsetDistribution", "Selected TDC-RF offset;Time;Entries", 100, -3.0, 3.0);
      TF1* f = new TF1("f","pol0(0)+gaus(1)", -3.0, 3.0);
      for (int sector = 1; sector <= 30; sector++){
         TH1I *scRFHist = ExtractTrackBasedTimingNS::Get1DHistogram("HLDetectorTiming", "SC_Target_RF_Compare", Form("Sector %.2i", sector));
         if (scRFHist == NULL) continue;
         //Do the fit
         TFitResultPtr fr = scRFHist->Fit("pol0", "SQ", "", -2, 2);
         double p0 = fr->Parameter(0);

         f->FixParameter(0,p0);
         f->SetParLimits(2, -2, 2);
         f->SetParLimits(3, 0, 2);
         f->SetParameter(1, 10);
         f->SetParameter(2, scRFHist->GetBinCenter(scRFHist->GetMaximumBin()));
         f->SetParameter(3, 0);

         fr = scRFHist->Fit(f, "SQ", "", -2, 2);
         double SCOffset = fr->Parameter(2);
         selectedSCSectorOffset->SetBinContent(sector, SCOffset);
         selectedSCSectorOffsetDistribution->Fill(SCOffset);
      }
      // Now write out the offsets
      meanSCOffset = selectedSCSectorOffsetDistribution->GetMean();
      if (verbose){
         cout << "Dumping SC results...\n=======================================" << endl;
         cout << "SC mean Offset = " << meanSCOffset << endl;
         cout << "TDC Offsets" << endl;
         cout << "Sector\toldValue\tValueToUse\tmeanOffset\tTotal" << endl;
      }
      outFile.open(prefix + "sc_tdc_timing_offsets.txt");
      for (int sector = 1; sector <= 30; sector++){
         outFile << sc_tdc_time_offsets[sector-1] + selectedSCSectorOffset->GetBinContent(sector) - meanSCOffset << endl;
         if (verbose) printf("%i\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\n",sector, sc_tdc_time_offsets[sector-1], selectedSCSectorOffset->GetBinContent(sector), meanSCOffset,
               sc_tdc_time_offsets[sector-1] + selectedSCSectorOffset->GetBinContent(sector) - meanSCOffset);
      }
      outFile.close();
      if (verbose){
         cout << "ADC Offsets" << endl;
         cout << "Sector\tvalueToUse\toldValue\tmeanOffset\tTotal" << endl;
      }
      outFile.open(prefix + "sc_adc_timing_offsets.txt");
      for (int sector = 1; sector <= 30; sector++){
         outFile << sc_fadc_time_offsets[sector-1] + selectedSCSectorOffset->GetBinContent(sector) - meanSCOffset << endl;
         if (verbose) printf("%i\t%.3f\t\t%.3f\t\t%.3f\t\t%.3f\n",sector,sc_fadc_time_offsets[sector-1], selectedSCSectorOffset->GetBinContent(sector), meanSCOffset,
               sc_fadc_time_offsets[sector-1] + selectedSCSectorOffset->GetBinContent(sector) - meanSCOffset);
      }
      outFile.close();

      outFile.open(prefix + "sc_base_time.txt");
      outFile << sc_t_base_fadc - meanSCOffset << " " << sc_t_base_tdc - meanSCOffset << endl;
      if (verbose) {
         printf("SC ADC Base = %f - (%f) = %f\n", sc_t_base_fadc, meanSCOffset, sc_t_base_fadc - meanSCOffset);
         printf("SC TDC Base = %f - (%f) = %f\n", sc_t_base_tdc, meanSCOffset, sc_t_base_tdc - meanSCOffset);
      }
      outFile.close();
   }

   TH1I *this1DHist = ExtractTrackBasedTimingNS::Get1DHistogram("HLDetectorTiming", "TRACKING", "TOF - RF Time");
   if(this1DHist != NULL){
      //Gaussian
      Double_t maximum = this1DHist->GetBinCenter(this1DHist->GetMaximumBin());
      TFitResultPtr fr = this1DHist->Fit("gaus", "S", "", maximum - 1.5, maximum + 1.5);
      float mean = fr->Parameter(1);
      outFile.open(prefix + "tof_base_time.txt");
      if (verbose) {
         printf("TOF ADC Base = %f - (%f) - (%f) = %f\n", tof_t_base_fadc, mean, meanSCOffset, tof_t_base_fadc - mean - meanSCOffset);
         printf("TOF TDC Base = %f - (%f) - (%f) = %f\n", tof_t_base_tdc, mean, meanSCOffset, tof_t_base_tdc - mean - meanSCOffset);
      }
      outFile << tof_t_base_fadc - mean - meanSCOffset<< " " << tof_t_base_tdc - mean - meanSCOffset<< endl;
      outFile.close();
   }

   this1DHist = ExtractTrackBasedTimingNS::Get1DHistogram("HLDetectorTiming", "TRACKING", "BCAL - RF Time");
   if(this1DHist != NULL){
      //Gaussian
      Double_t maximum = this1DHist->GetBinCenter(this1DHist->GetMaximumBin());
      TFitResultPtr fr = this1DHist->Fit("gaus", "S", "", maximum - 5, maximum + 5);
      float mean = fr->Parameter(1);
      outFile.open(prefix + "bcal_base_time.txt");
      if (verbose) {
         printf("BCAL ADC Base = %f - (%f) - (%f) = %f\n", bcal_t_base_fadc, mean, meanSCOffset, bcal_t_base_fadc - mean - meanSCOffset);
         printf("BCAL TDC Base = %f - (%f) - (%f) = %f\n", bcal_t_base_tdc, mean, meanSCOffset, bcal_t_base_tdc - mean - meanSCOffset);
      }
      outFile << bcal_t_base_fadc - mean - meanSCOffset << " " << bcal_t_base_tdc - mean - meanSCOffset << endl; // TDC info not used
      outFile.close();
   }

   this1DHist = ExtractTrackBasedTimingNS::Get1DHistogram("HLDetectorTiming", "TRACKING", "FCAL - RF Time");
   if(this1DHist != NULL){
      //Gaussian
      Double_t maximum = this1DHist->GetBinCenter(this1DHist->GetMaximumBin());
      TFitResultPtr fr = this1DHist->Fit("gaus", "S", "", maximum - 5, maximum + 5);
      float mean = fr->Parameter(1);
      outFile.open(prefix + "fcal_base_time.txt");
      if (verbose) {
         printf("FCAL ADC Base = %f - (%f) - (%f) = %f\n",fcal_t_base, mean, meanSCOffset, fcal_t_base - mean - meanSCOffset);
      }
      outFile << fcal_t_base - mean - meanSCOffset<< endl; 
      outFile.close();
   }

   this1DHist = ExtractTrackBasedTimingNS::Get1DHistogram("HLDetectorTiming", "TRACKING", "Earliest CDC Time Minus Matched SC Time");
   if(this1DHist != NULL){
      //Gaussian
      Double_t maximum = this1DHist->GetBinCenter(this1DHist->GetMaximumBin());
      TFitResultPtr fr = this1DHist->Fit("gaus", "S", "", maximum - 15, maximum + 10);
      float mean = fr->Parameter(1);
      outFile.open(prefix + "cdc_base_time.txt");
      if (verbose) {
         printf("CDC ADC Base = %f - (%f) - (%f) = %f\n",cdc_t_base, mean, meanSCOffset, cdc_t_base - mean - meanSCOffset);
      }
      outFile << cdc_t_base - mean - meanSCOffset << endl;
      outFile.close();
   }

   // We want to account for any residual difference between the cathode and anode times.
   double FDC_ADC_Offset = 0.0, FDC_TDC_Offset = 0.0; 
   this1DHist = ExtractTrackBasedTimingNS::Get1DHistogram("HLDetectorTiming", "FDC", "FDCHit Cathode time;1");
    if(this1DHist != NULL){
        Int_t firstBin = this1DHist->FindFirstBinAbove( 1 , 1); // Find first bin with content above 1 in the histogram
        for (int i = 0; i <= 16; i++){
            if ((firstBin + i) > 0) this1DHist->SetBinContent((firstBin + i), 0);
        }
        //Fit a gaussian to the left of the main peak
        Double_t maximum = this1DHist->GetBinCenter(this1DHist->GetMaximumBin());
        TF1 *f = new TF1("f", "gaus");
        f->SetParameters(100, maximum, 20);
        //this1DHist->Rebin(2);
        TFitResultPtr fr = this1DHist->Fit(f, "S", "", maximum - 10, maximum + 7); // Cant fix value at end of range
        double mean = fr->Parameter(1);
        float sigma = fr->Parameter(2);
        FDC_ADC_Offset = mean;
        delete f;
    }

    this1DHist = ExtractTrackBasedTimingNS::Get1DHistogram("HLDetectorTiming", "FDC", "FDCHit Wire time;1");
    if(this1DHist != NULL){
        Int_t firstBin = this1DHist->FindLastBinAbove( 1 , 1); // Find first bin with content above 1 in the histogram
        for (int i = 0; i <= 25; i++){
            if ((firstBin + i) > 0) this1DHist->SetBinContent((firstBin + i), 0);
        }
        //Fit a gaussian to the left of the main peak
        Double_t maximum = this1DHist->GetBinCenter(this1DHist->GetMaximumBin());
        TF1 *f = new TF1("f", "gaus");
        f->SetParameters(100, maximum, 20);
        TFitResultPtr fr = this1DHist->Fit(f, "S", "", maximum - 10, maximum + 5); // Cant fix value at end of range
        double mean = fr->Parameter(1);
        float sigma = fr->Parameter(2);
        FDC_TDC_Offset = mean;
        delete f;
    }
    double FDC_ADC_TDC_Offset = FDC_ADC_Offset - FDC_TDC_Offset;

   this1DHist = ExtractTrackBasedTimingNS::Get1DHistogram("HLDetectorTiming", "TRACKING", "Earliest Flight-time Corrected FDC Time");
   if(this1DHist != NULL){
      //Landau
      Double_t maximum = this1DHist->GetBinCenter(this1DHist->GetMaximumBin());
      TFitResultPtr fr = this1DHist->Fit("landau", "S", "", maximum - 2.5, maximum + 4);
      float MPV = fr->Parameter(1);
      outFile.open(prefix + "fdc_base_time.txt");
      if (verbose) {
         printf("FDC ADC Base = %f - (%f) - (%f) - (%f) = %f\n",fdc_t_base_fadc, MPV, meanSCOffset, FDC_ADC_TDC_Offset, fdc_t_base_fadc - MPV - meanSCOffset - FDC_ADC_TDC_Offset);
         printf("FDC TDC Base = %f - (%f) - (%f) = %f\n",fdc_t_base_tdc, MPV, meanSCOffset, fdc_t_base_tdc - MPV - meanSCOffset);
      }
      outFile << fdc_t_base_fadc - MPV - meanSCOffset - FDC_ADC_TDC_Offset << " " << fdc_t_base_tdc - MPV - meanSCOffset << endl;
      outFile.close();
   }

   ExtractTrackBasedTimingNS::thisFile->Write();
   return;
}
Beispiel #2
0
int main()
{

  float const conS =.3/2.35;
  ofstream fout("cal/backN.cal");
  ofstream fwhm("cal/fwhmback.dat");
  TFile f("sort.root");
  TCanvas* canvas[14];
  int Ntele = 14;
  int Nstrip = 32;
  ostringstream outstring;
  TH2I frame("frame","",10,4.5,9.5,10,0,130);
  frame.SetStats(kFALSE);

  double xx[14*32];
  double yy[14*32];

  TF1 *func = new TF1("fit",ThPeaks,3,9,4);
  double para[5];
  ifstream file("cal/back.cal");
  float intercept, slope;
  int i1,i2;
  string name;

  TH1F con("con","",500,0,10);
  for (int itele=0;itele<Ntele;itele++)
    {
      outstring.str("");
      outstring << "B"<<itele;
      name = outstring.str();
      canvas[itele] = new TCanvas(name.c_str());
      canvas[itele]->Divide(6,6);
      for (int istrip =0;istrip<Nstrip;istrip++)
        {
      
          canvas[itele]->cd(istrip+1);
          file >> i1 >> i2  >> slope >> intercept;


          outstring.str("");
          outstring << "back/cal/EBC"<<itele<<"_"<<istrip;
          string name = outstring.str();
          cout <<  name << endl;
          TH1I * hist = (TH1I*) f.Get(name.c_str());
	  frame.Draw();


          hist->SetStats(kFALSE);
          hist->GetXaxis()->SetRangeUser(4.5,9.5);
          con.GetXaxis()->SetRangeUser(4.5,9.5);
	  for (int i=1;i<=500;i++)
	    for (int j=1;j<500;j++)
	    {
              float deltax = hist->GetBinCenter(i)-con.GetBinCenter(j);
	      if (fabs(deltax) > 10.*conS)continue;
              float fact = gauss(deltax,0.,conS);
	      float y = fact*hist->GetBinContent(i)*hist->GetBinWidth(i);
              con.SetBinContent(j,y+con.GetBinContent(j));
	    }



	  for (int i=1;i<=500;i++) 
	    {
	      hist->SetBinContent(i,con.GetBinContent(i));
	      con.SetBinContent(i,0.);
	    }

          hist->Draw("same");



          func->SetParameter(0,0);
          func->SetParameter(1,1.);
	  func->FixParameter(2,conS);
          //func->SetParameter(2,0.1);
          func->SetParameter(3,8.);
          func->SetLineColor(2);
          //func->Draw("same");



	  hist->Fit(func);
          func->GetParameters(para);
          cout << "chisq=" << func->GetChisquare() << endl;
           if (fabs(para[1]-1.) < .2) 
	     { 

              slope *= para[1];
              intercept = intercept*para[1] + para[0];
	     }
            fout << itele << " " << istrip << " " 
                 << slope << " " << intercept << endl;
            fwhm << itele << " " << istrip << " " 
                  << para[2]*2.35 << endl;
            int ii = itele*32+istrip;
            xx[ii] = (float)ii;
            yy[ii] = para[2]*2.35;
            cout << para[0] << " " << para[1] << " " << para[2] << endl;

        }
    }

  TFile g("ThBack.root","RECREATE");
  for (int itele=0;itele<Ntele;itele++) canvas[itele]->Write();
  TCanvas fwhmCan("fwhm");
  TH2I frame2("frame2","",10,0,448,10,0,0.12);
  frame2.SetStats(kFALSE);
  frame2.GetYaxis()->SetTitle("FWHM [MeV]");
  frame2.GetXaxis()->SetTitle("back strip");
  frame2.Draw();
  TGraph graph(32*14,xx,yy);
  graph.Draw("*");
  graph.Write();
  fwhmCan.Write();
  g.Write();
}
void ExtractTrackBasedTiming(int runNumber){

    TString fileName = Form ("Run%i/TrackBasedTiming.root", runNumber);
    TString prefix = Form ("Run%i/constants/TrackBasedTiming/",runNumber);
    TString inputPrefix = Form ("Run%i/constants/TDCADCTiming/",runNumber);

    thisFile = TFile::Open( fileName , "UPDATE");
    if (thisFile == 0) {
        cout << "Unable to open file " << fileName.Data() << "...Exiting" << endl;
        return;
    }

    //We need the existing constants, The best we can do here is just read them from the file.
    vector<double> sc_tdc_time_offsets;
    vector<double> sc_fadc_time_offsets;
    vector<double> tof_tdc_time_offsets;
    vector<double> tof_fadc_time_offsets;
    vector<double> tagm_tdc_time_offsets;
    vector<double> tagm_fadc_time_offsets;
    vector<double> tagh_tdc_time_offsets;
    vector<double> tagh_fadc_time_offsets;

    double sc_t_base_fadc;
    double sc_t_base_tdc;
    double tof_t_base_fadc;
    double tof_t_base_tdc;
    double bcal_t_base_fadc;
    double bcal_t_base_tdc;
    double tagm_t_base_fadc;
    double tagm_t_base_tdc;
    double tagh_t_base_fadc;
    double tagh_t_base_tdc;
    double fcal_t_base;
    double cdc_t_base;

    ifstream inFile;
    inFile.open(inputPrefix + "sc_tdc_timing_offsets.txt");
    string line;
    if (inFile.is_open()){
        while (getline (inFile, line)){
            sc_tdc_time_offsets.push_back(atof(line.data()));
        }
    }
    inFile.close();

    ifstream inFile;
    inFile.open(inputPrefix + "sc_adc_timing_offsets.txt");
    string line;
    if (inFile.is_open()){
        while (getline (inFile, line)){
            sc_fadc_time_offsets.push_back(atof(line.data()));
        }
    }
    inFile.close();

    inFile.open(inputPrefix + "tof_tdc_timing_offsets.txt");
    if (inFile.is_open()){
        while (getline (inFile, line)){
            tof_tdc_time_offsets.push_back(atof(line.data()));
        }
    }
    inFile.close();

    inFile.open(inputPrefix + "tof_adc_timing_offsets.txt");
    if (inFile.is_open()){
        while (getline (inFile, line)){
            tof_fadc_time_offsets.push_back(atof(line.data()));
        }
    }
    inFile.close();

    inFile.open(inputPrefix + "tagm_tdc_timing_offsets.txt");
    if (inFile.is_open()){
        while (getline (inFile, line)){
            istringstream iss(line);
            double r, c, offset;
            while (iss>>r>>c>>offset){
                //if (row != 0) continue;
                tagm_tdc_time_offsets.push_back(offset);
            }
        }
    }
    inFile.close();

    inFile.open(inputPrefix + "tagm_adc_timing_offsets.txt");
    if (inFile.is_open()){
        while (getline (inFile, line)){
            istringstream iss(line);
            double r, c, offset;
            while (iss>>r>>c>>offset){
                //if (row != 0) continue;
                tagm_fadc_time_offsets.push_back(offset);
            }
        }
    }
    inFile.close();

    inFile.open(inputPrefix + "tagh_tdc_timing_offsets.txt");
    if (inFile.is_open()){
        while (getline (inFile, line)){
            istringstream iss(line);
            double counter, offset;
            while (iss>>counter>>offset){
                tagh_tdc_time_offsets.push_back(offset);
            }
        }
    }
    inFile.close();

    inFile.open(inputPrefix + "tagh_adc_timing_offsets.txt");
    if (inFile.is_open()){
        while (getline (inFile, line)){
            istringstream iss(line);
            double counter, offset;
            while (iss>>counter>>offset){
                tagh_fadc_time_offsets.push_back(offset);
            }
        }
    }
    inFile.close();

    inFile.open(inputPrefix + "tof_base_time.txt");
    if (inFile.is_open()){
        while (getline (inFile, line)){
            istringstream iss(line);
            iss>>tof_t_base_fadc>>tof_t_base_tdc;
        }
    }
    inFile.close();

    inFile.open(inputPrefix + "sc_base_time.txt");
    if (inFile.is_open()){
        while (getline (inFile, line)){
            istringstream iss(line);
            iss>>sc_t_base_fadc>>sc_t_base_tdc;
        }
    }
    inFile.close();

    inFile.open(inputPrefix + "bcal_base_time.txt");
    if (inFile.is_open()){
        while (getline (inFile, line)){
            istringstream iss(line);
            double adc_offset, tdc_offset;
            iss>>adc_offset>>tdc_offset; // TDC not used currently
            bcal_t_base_fadc = adc_offset;
            bcal_t_base_tdc = tdc_offset;
        }
    }
    inFile.close();

    inFile.open(inputPrefix + "tagm_base_time.txt");
    if (inFile.is_open()){
        while (getline (inFile, line)){
            istringstream iss(line);
            double adc_offset, tdc_offset;
            iss>>adc_offset>>tdc_offset; // TDC not used currently
            tagm_t_base_fadc = adc_offset;
            tagm_t_base_tdc = tdc_offset;
        }
    }

    inFile.close();
    inFile.open(inputPrefix + "tagh_base_time.txt");
    if (inFile.is_open()){
        while (getline (inFile, line)){
            istringstream iss(line);
            double adc_offset, tdc_offset;
            iss>>adc_offset>>tdc_offset; // TDC not used currently
            tagh_t_base_fadc = adc_offset;
            tagh_t_base_tdc = tdc_offset;
        }
    }
    inFile.close();

    inFile.open(inputPrefix + "fcal_base_time.txt");
    if (inFile.is_open()){
        while (getline (inFile, line)){
            istringstream iss(line);
            iss>>fcal_t_base; 
        }
    }
    inFile.close();

    inFile.open(inputPrefix + "cdc_base_time.txt");
    if (inFile.is_open()){
        while (getline (inFile, line)){
            istringstream iss(line);
            iss>>cdc_t_base; 
        }
    }
    inFile.close();


    // Do our final step in the timing alignment with tracking

    //When the RF is present we can try to simply pick out the correct beam bucket for each of the runs
    //First just a simple check to see if we have the appropriate data
    bool useRF = false;
    double RF_Period = 4.0080161;
    TH1I *testHist = Get1DHistogram("HLDetectorTiming", "TAGH_TDC_RF_Compare","Counter ID 001");
    if (testHist != NULL){ // Not great since we rely on channel 1 working, but can be craftier later.
        useRF = true;
    }
    ofstream outFile;
    TH2I *thisHist; 
    thisHist = Get2DHistogram("HLDetectorTiming", "TRACKING", "TAGM - SC Target Time");
    if (useRF) thisHist = Get2DHistogram("HLDetectorTiming", "TRACKING", "TAGM - RFBunch Time");
    if (thisHist != NULL){
        //Statistics on these histograms are really quite low we will have to rebin and do some interpolation
        outFile.open(prefix + "tagm_tdc_timing_offsets.txt", ios::out | ios::trunc);
        outFile.close(); // clear file
        outFile.open(prefix + "tagm_adc_timing_offsets.txt", ios::out | ios::trunc);
        outFile.close(); // clear file
        int nBinsX = thisHist->GetNbinsX();
        int nBinsY = thisHist->GetNbinsY();
        TH1D * selectedTAGMOffset = new TH1D("selectedTAGMOffset", "Selected TAGM Offset; Column; Offset [ns]", nBinsX, 0.5, nBinsX + 0.5);
        TH1I * TAGMOffsetDistribution = new TH1I("TAGMOffsetDistribution", "TAGM Offset; TAGM Offset [ns]; Entries", 500, -250, 250);
        for (int i = 1 ; i <= nBinsX; i++){ 
            TH1D *projY = thisHist->ProjectionY("temp", i, i);
            // Scan over the histogram
            //chose the correct number of bins based on the histogram
            float nsPerBin = (projY->GetBinCenter(projY->GetNbinsX()) - projY->GetBinCenter(1)) / projY->GetNbinsX();
            float timeWindow = 3; //ns (Full Width)
            int binWindow = int(timeWindow / nsPerBin);
            double maxEntries = 0;
            double maxMean = 0;
            for (int j = 1 ; j <= projY->GetNbinsX();j++){
                int minBin = j;
                int maxBin = (j + binWindow) <= projY->GetNbinsX() ? (j + binWindow) : projY->GetNbinsX();
                double sum = 0, nEntries = 0;
                for (int bin = minBin; bin <= maxBin; bin++){
                    sum += projY->GetBinContent(bin) * projY->GetBinCenter(bin);
                    nEntries += projY->GetBinContent(bin);
                    if (bin == maxBin){
                        if (nEntries > maxEntries) {
                            maxMean = sum / nEntries;
                            maxEntries = nEntries;
                        }
                    } 
                }
            }
            //In the case there is RF, our job is to pick just the number of the correct beam bunch, so that's really all we need.
            if(useRF) {
                int beamBucket = int((maxMean / RF_Period) + 0.5); // +0.5 to handle rounding correctly
                selectedTAGMOffset->SetBinContent(i, beamBucket);
                TAGMOffsetDistribution->Fill(beamBucket);
            }
            else{
                selectedTAGMOffset->SetBinContent(i, maxMean);
                TAGMOffsetDistribution->Fill(maxMean);
            }
        }
        /*
        if (!useRF){
            //TFitResultPtr fr1 = selectedTAGMOffset->Fit("pol1", "SQ", "", 0.5, nBinsX + 0.5);
            TFitResultPtr fr1 = selectedTAGMOffset->Fit("pol1", "SQ", "", 5, 50);

            for (int i = 1 ; i <= nBinsX; i++){
                double x0 = fr1->Parameter(0);
                double x1 = fr1->Parameter(1);
                //double x2 = fr1->Parameter(2);
                //double fitResult = x0 + i*x1 + i*i*x2;
                double fitResult = x0 + i*x1;

                double outlierCut = 20;
                double valueToUse = selectedTAGMOffset->GetBinContent(i);
                if (fabs(selectedTAGMOffset->GetBinContent(i) - fitResult) > outlierCut && valueToUse != 0.0){
                    valueToUse = fitResult;
                }

                selectedTAGMOffset->SetBinContent(i, valueToUse);
                if (valueToUse != 0 ) TAGMOffsetDistribution->Fill(valueToUse);
            }
        }
*/
        double meanOffset = TAGMOffsetDistribution->GetMean();
        // This might be in units of beam bunches, so we need to convert
        if (useRF) meanOffset *= RF_Period;
        /*
           for (int i = 1 ; i <= nBinsX; i++){
           double valueToUse = selectedTAGMOffset->GetBinContent(i);
           if (useRF) valueToUse *= RF_Period;
           if (valueToUse == 0) valueToUse = meanOffset;
           outFile.open(prefix + "tagm_tdc_timing_offsets.txt", ios::out | ios::app);
           outFile << "0 " << i << " " << valueToUse + tagm_tdc_time_offsets[i-1] - meanOffset<< endl;
           if (i == 7 || i == 25 || i == 79 || i == 97){
           for(int j = 1; j <= 5; j++){
           outFile << j << " " << i << " " << valueToUse + tagm_tdc_time_offsets[i-1] - meanOffset<< endl;
           }
           }
           outFile.close();
        // Apply the same shift to the adc offsets
        outFile.open(prefix + "tagm_adc_timing_offsets.txt", ios::out | ios::app);
        outFile << "0 " << i << " " << valueToUse + tagm_fadc_time_offsets[i-1] - meanOffset<< endl;
        if (i == 7 || i == 25 || i == 79 || i == 97){
        for(int j = 1; j <= 5; j++){
        outFile << j << " " << i << " " << valueToUse + tagm_fadc_time_offsets[i-1] - meanOffset<< endl;
        }
        }
        outFile.close();
        }
        */

        outFile.open(prefix + "tagm_adc_timing_offsets.txt", ios::out);
        //for (int i = 1 ; i <= nBinsX; i++){
        // Loop over rows
        for (unsigned int column = 1; column <= 102; column++){
            int index = GetCCDBIndexTAGM(column, 0);
            double valueToUse = selectedTAGMOffset->GetBinContent(index);
            if (useRF) valueToUse *= RF_Period;
            if (valueToUse == 0) valueToUse = meanOffset;
            outFile << "0 " << column << " " << valueToUse + tagm_fadc_time_offsets[index-1] - meanOffset<< endl;
            if (column == 9 || column == 27 || column == 81 || column == 99){
                for (unsigned int row = 1; row <= 5; row++){
                    index = GetCCDBIndexTAGM(column, row);
                    valueToUse = selectedTAGMOffset->GetBinContent(index);
                    if (useRF) valueToUse *= RF_Period;
                    if (valueToUse == 0) valueToUse = meanOffset;
                    outFile << row << " " << column << " " << valueToUse + tagm_fadc_time_offsets[index-1] - meanOffset<< endl;
                }
            }
        }
        outFile.close();

        outFile.open(prefix + "tagm_tdc_timing_offsets.txt", ios::out);
        //for (int i = 1 ; i <= nBinsX; i++){
        // Loop over rows
        for (unsigned int column = 1; column <= 102; column++){
            int index = GetCCDBIndexTAGM(column, 0);
            double valueToUse = selectedTAGMOffset->GetBinContent(index);
            if (useRF) valueToUse *= RF_Period;
            if (valueToUse == 0) valueToUse = meanOffset;
            outFile << "0 " << column << " " << valueToUse + tagm_tdc_time_offsets[index-1] - meanOffset << endl;
            if (column == 9 || column == 27 || column == 81 || column == 99){
                for (unsigned int row = 1; row <= 5; row++){
                    index = GetCCDBIndexTAGM(column, row);
                    valueToUse = selectedTAGMOffset->GetBinContent(index);
                    if (useRF) valueToUse *= RF_Period;
                    if (valueToUse == 0) valueToUse = meanOffset;
                    outFile << row << " " << column << " " << valueToUse + tagm_tdc_time_offsets[index-1] - meanOffset << endl;
                }
            }
        }
        outFile.close();
        outFile.open(prefix + "tagm_base_time.txt", ios::out);
        outFile << tagm_t_base_fadc - meanOffset << " " << tagm_t_base_tdc - meanOffset << endl;
        outFile.close();

    }

    thisHist = Get2DHistogram("HLDetectorTiming", "TRACKING", "TAGH - SC Target Time");
    if (useRF) thisHist = Get2DHistogram("HLDetectorTiming", "TRACKING", "TAGH - RFBunch Time");
    if(thisHist != NULL){
        outFile.open(prefix + "tagh_tdc_timing_offsets.txt", ios::out | ios::trunc);
        outFile.close(); // clear file
        outFile.open(prefix + "tagh_adc_timing_offsets.txt", ios::out | ios::trunc);
        outFile.close(); // clear file

        int nBinsX = thisHist->GetNbinsX();
        int nBinsY = thisHist->GetNbinsY();
        TH1D * selectedTAGHOffset = new TH1D("selectedTAGHOffset", "Selected TAGH Offset; ID; Offset [ns]", nBinsX, 0.5, nBinsX + 0.5);
        TH1I * TAGHOffsetDistribution = new TH1I("TAGHOffsetDistribution", "TAGH Offset; TAGH Offset [ns]; Entries", 500, -250, 250);
        for (int i = 1 ; i <= nBinsX; i++){
            TH1D *projY = thisHist->ProjectionY("temp", i, i);
            // Scan over the histogram
            //chose the correct number of bins based on the histogram
            float nsPerBin = (projY->GetBinCenter(projY->GetNbinsX()) - projY->GetBinCenter(1)) / projY->GetNbinsX();
            float timeWindow = 2; //ns (Full Width)
            int binWindow = int(timeWindow / nsPerBin);

            double maxEntries = 0;
            double maxMean = 0;
            for (int j = 1 ; j <= projY->GetNbinsX();j++){
                int minBin = j;
                int maxBin = (j + binWindow) <= projY->GetNbinsX() ? (j + binWindow) : projY->GetNbinsX();
                double sum = 0; 
                double nEntries = 0;
                for (int bin = minBin; bin <= maxBin; bin++){
                    sum += projY->GetBinContent(bin) * projY->GetBinCenter(bin);
                    nEntries += projY->GetBinContent(bin);
                    if (bin == maxBin){
                        if (nEntries > maxEntries){
                            maxMean = sum / nEntries;
                            maxEntries = nEntries;
                        }
                    }
                }
            }

            if(useRF) {
                int beamBucket = int((maxMean / RF_Period) + 0.5); // +0.5 to handle rounding correctly
                selectedTAGHOffset->SetBinContent(i, beamBucket);
                TAGHOffsetDistribution->Fill(beamBucket);
            }
            else{
                selectedTAGHOffset->SetBinContent(i, maxMean);
            }
            /*
               outFile.open("tagh_tdc_timing_offsets.txt", ios::out | ios::app);
               outFile << i << " " << maxMean + tagh_tdc_time_offsets[i] << endl;
               outFile.close();
               outFile.open("tagh_adc_timing_offsets.txt", ios::out | ios::app);
               outFile << i << " " << maxMean + tagh_fadc_time_offsets[i] << endl;
               outFile.close();
               */
        }

        // Fit 1D histogram. If value is far from the fit use the fitted value
        // Two behaviors above and below microscope
        // This isn't working well, so removing...
        /*
           TFitResultPtr fr1 = selectedTAGHOffset->Fit("pol2", "SQ", "", 0.5, 131.5);
           TFitResultPtr fr2 = selectedTAGHOffset->Fit("pol2", "SQ", "", 182.5, 274.5);        

           for (int i = 1 ; i <= nBinsX; i++){
           double fitResult = 0.0;
           if (i < 150){
           double x0 = fr1->Parameter(0);
           double x1 = fr1->Parameter(1);
           double x2 = fr1->Parameter(2);
           fitResult = x0 + i*x1 + i*i*x2;
           }
           else{
           double x0 = fr2->Parameter(0);
           double x1 = fr2->Parameter(1);
           double x2 = fr2->Parameter(2);
           fitResult = x0 + i*x1 + i*i*x2;
           }

           double outlierCut = 7;
           double valueToUse = selectedTAGHOffset->GetBinContent(i);
           if (fabs(selectedTAGHOffset->GetBinContent(i) - fitResult) > outlierCut && valueToUse != 0.0){
           valueToUse = fitResult;
           }

           selectedTAGHOffset->SetBinContent(i, valueToUse);
           if(valueToUse != 0) TAGHOffsetDistribution->Fill(valueToUse);
           }
           */
        double meanOffset = TAGHOffsetDistribution->GetMean();
        if (useRF) meanOffset *= RF_Period;
        for (int i = 1 ; i <= nBinsX; i++){
            valueToUse = selectedTAGHOffset->GetBinContent(i);
            if (useRF) valueToUse *= RF_Period;
            if (valueToUse == 0) valueToUse = meanOffset;
            outFile.open(prefix + "tagh_tdc_timing_offsets.txt", ios::out | ios::app);
            outFile << i << " " << valueToUse + tagh_tdc_time_offsets[i-1] - meanOffset << endl;
            outFile.close();
            outFile.open(prefix + "tagh_adc_timing_offsets.txt", ios::out | ios::app);
            outFile << i << " " << valueToUse + tagh_fadc_time_offsets[i-1] - meanOffset << endl;
            outFile.close();
        }

        outFile.open(prefix + "tagh_base_time.txt", ios::out);
        outFile << tagh_t_base_fadc - meanOffset << " " << tagh_t_base_tdc - meanOffset << endl;
        outFile.close();
    }

    // We can use the RF time to calibrate the SC time (Experimental for now)
    double meanSCOffset = 0.0; // In case we change the time of the SC, we need this in this scope
    if(useRF){
        TH1F * selectedSCSectorOffset = new TH1F("selectedSCSectorOffset", "Selected TDC-RF offset;Sector; Time", 30, 0.5, 30.5);
        TH1F * selectedSCSectorOffsetDistribution = new TH1F("selectedSCSectorOffsetDistribution", "Selected TDC-RF offset;Time;Entries", 100, -3.0, 3.0);
        TF1* f = new TF1("f","pol0(0)+gaus(1)", -3.0, 3.0);
        for (int sector = 1; sector <= 30; sector++){
            TH1I *scRFHist = Get1DHistogram("HLDetectorTiming", "SC_Target_RF_Compare", Form("Sector %.2i", sector));
            if (scRFHist == NULL) continue;
            //Do the fit
            TFitResultPtr fr = scRFHist->Fit("pol0", "SQ", "", -2, 2);
            double p0 = fr->Parameter(0);

            f->FixParameter(0,p0);
            f->SetParLimits(2, -2, 2);
            f->SetParLimits(3, 0, 2);
            f->SetParameter(1, 10);
            f->SetParameter(2, scRFHist->GetBinCenter(scRFHist->GetMaximumBin()));
            f->SetParameter(3, 0);

            fr = scRFHist->Fit(f, "SQ", "", -2, 2);
            double SCOffset = fr->Parameter(2);
            selectedSCSectorOffset->SetBinContent(sector, SCOffset);
            selectedSCSectorOffsetDistribution->Fill(SCOffset);
        }
        // Now write out the offsets
        meanSCOffset = selectedSCSectorOffsetDistribution->GetMean();
        outFile.open(prefix + "sc_tdc_timing_offsets.txt");
        for (int sector = 1; sector <= 30; sector++){
            outFile << sc_tdc_time_offsets[sector-1] + selectedSCSectorOffset->GetBinContent(sector) - meanSCOffset << endl;
        }
        outFile.close();
        outFile.open(prefix + "sc_adc_timing_offsets.txt");
        for (int sector = 1; sector <= 30; sector++){
            outFile << sc_fadc_time_offsets[sector-1] + selectedSCSectorOffset->GetBinContent(sector) - meanSCOffset << endl;
        }
        outFile.close();
        
        outFile.open(prefix + "sc_base_time.txt");
        outFile << sc_t_base_fadc - meanSCOffset << " " << sc_t_base_tdc - meanSCOffset << endl;
        outFile.close();
    }

    TH1I *this1DHist = Get1DHistogram("HLDetectorTiming", "TRACKING", "TOF - SC Target Time");
    if(this1DHist != NULL){
        //Gaussian
        Double_t maximum = this1DHist->GetBinCenter(this1DHist->GetMaximumBin());
        TFitResultPtr fr = this1DHist->Fit("gaus", "S", "", maximum - 1.5, maximum + 1.5);
        float mean = fr->Parameter(1);
        outFile.open(prefix + "tof_base_time.txt");
        outFile << tof_t_base_fadc - mean - meanSCOffset<< " " << tof_t_base_tdc - mean - meanSCOffset<< endl;
        outFile.close();
    }

    this1DHist = Get1DHistogram("HLDetectorTiming", "TRACKING", "BCAL - SC Target Time");
    if(this1DHist != NULL){
        //Gaussian
        Double_t maximum = this1DHist->GetBinCenter(this1DHist->GetMaximumBin());
        TFitResultPtr fr = this1DHist->Fit("gaus", "S", "", maximum - 5, maximum + 5);
        float mean = fr->Parameter(1);
        outFile.open(prefix + "bcal_base_time.txt");
        outFile << bcal_t_base_fadc - mean - meanSCOffset << " " << bcal_t_base_tdc - mean - meanSCOffset << endl; // TDC info not used
        outFile.close();
    }

    this1DHist = Get1DHistogram("HLDetectorTiming", "TRACKING", "FCAL - SC Target Time");
    if(this1DHist != NULL){
        //Gaussian
        Double_t maximum = this1DHist->GetBinCenter(this1DHist->GetMaximumBin());
        TFitResultPtr fr = this1DHist->Fit("gaus", "S", "", maximum - 5, maximum + 5);
        float mean = fr->Parameter(1);
        outFile.open(prefix + "fcal_base_time.txt");
        outFile << fcal_t_base - mean - meanSCOffset<< endl; 
        outFile.close();
    }

    this1DHist = Get1DHistogram("HLDetectorTiming", "TRACKING", "Earliest CDC Time Minus Matched SC Time");
    if(this1DHist != NULL){
        //Gaussian
        Double_t maximum = this1DHist->GetBinCenter(this1DHist->GetMaximumBin());
        TFitResultPtr fr = this1DHist->Fit("gaus", "S", "", maximum - 15, maximum + 10);
        float mean = fr->Parameter(1);
        outFile.open(prefix + "cdc_base_time.txt");
        outFile << cdc_t_base - mean - meanSCOffset << endl;
        outFile.close();
    }
    thisFile->Write();
    return;
    }