diff --git a/Control/CalypsoExample/Reconstruction/scripts/faser_reco.py b/Control/CalypsoExample/Reconstruction/scripts/faser_reco.py
index 7b9816c36241ca1b9a4041c046f0319ed79070a8..7671d13755f37e945b679796a15cb69f5d7aba98 100755
--- a/Control/CalypsoExample/Reconstruction/scripts/faser_reco.py
+++ b/Control/CalypsoExample/Reconstruction/scripts/faser_reco.py
@@ -24,6 +24,8 @@ parser.add_argument("-r", "--reco", default="",
                     help="Specify reco tag (to append to output filename)")
 parser.add_argument("-n", "--nevents", type=int, default=-1,
                     help="Specify number of events to process (default: all)")
+parser.add_argument("-v", "--verbose", action='store_true', 
+                    help="Turn on DEBUG output")
 
 args = parser.parse_args()
 
@@ -165,17 +167,20 @@ replicaSvc.UseGeomSQLite = True
 
 # Configure verbosity    
 # ConfigFlags.dump()
-# logging.getLogger('forcomps').setLevel(VERBOSE)
-# acc.foreach_component("*").OutputLevel = VERBOSE
-acc.foreach_component("*").OutputLevel = INFO
+if args.verbose:
+    acc.foreach_component("*").OutputLevel = VERBOSE
+
+    #acc.getService("FaserByteStreamInputSvc").DumpFlag = True
+    #acc.getService("FaserEventSelector").OutputLevel = VERBOSE
+    #acc.getService("FaserByteStreamInputSvc").OutputLevel = VERBOSE
+    #acc.getService("FaserByteStreamCnvSvc").OutputLevel = VERBOSE
+    #acc.getService("FaserByteStreamAddressProviderSvc").OutputLevel = VERBOSE
+
+else:
+    acc.foreach_component("*").OutputLevel = INFO
+
 acc.foreach_component("*ClassID*").OutputLevel = INFO
-# log.setLevel(VERBOSE)
 
-#acc.getService("FaserByteStreamInputSvc").DumpFlag = True
-#acc.getService("FaserEventSelector").OutputLevel = VERBOSE
-#acc.getService("FaserByteStreamInputSvc").OutputLevel = VERBOSE
-#acc.getService("FaserByteStreamCnvSvc").OutputLevel = VERBOSE
-#acc.getService("FaserByteStreamAddressProviderSvc").OutputLevel = VERBOSE
 acc.getService("MessageSvc").Format = "% F%40W%S%7W%R%T %0W%M"
 
 # Execute and finish
diff --git a/Waveform/WaveRecAlgs/src/RawWaveformRecAlg.cxx b/Waveform/WaveRecAlgs/src/RawWaveformRecAlg.cxx
index 3c6da1c0eb5a365f469dba9acd0b2027c433c2f4..f1320c41e7dc75f5c9c8cd701dc06a92c3bab1c3 100644
--- a/Waveform/WaveRecAlgs/src/RawWaveformRecAlg.cxx
+++ b/Waveform/WaveRecAlgs/src/RawWaveformRecAlg.cxx
@@ -69,16 +69,8 @@ RawWaveformRecAlg::execute(const EventContext& ctx) const {
 
   ATH_MSG_DEBUG("WaveformsHitContainer '" << hitContainerHandle.name() << "' initialized");
 
-  // Reconstruct each waveform
-  for( const auto& wave : *waveformHandle) {
-
-    ATH_MSG_DEBUG("Reconstruct waveform for channel " << wave->channel());
-
-    // Reconstruct the hits, may be more than one, so pass container
-    CHECK( m_recoTool->reconstruct(*wave, clockptr, 
-				   hitContainerHandle.ptr()) );
-
-  }
+  // Reconstruct all waveforms
+  CHECK( m_recoTool->reconstructAll(*waveformHandle, clockptr, hitContainerHandle.ptr()) );
 
   ATH_MSG_DEBUG("WaveformsHitContainer '" << hitContainerHandle.name() << "' filled with "<< hitContainerHandle->size() <<" items");
 
diff --git a/Waveform/WaveRecTools/WaveRecTools/IWaveformReconstructionTool.h b/Waveform/WaveRecTools/WaveRecTools/IWaveformReconstructionTool.h
index e985cb1d66b81e0bddbee05e682798fdb0f61be8..cc10197b262f0695327f7304a84998d198300678 100644
--- a/Waveform/WaveRecTools/WaveRecTools/IWaveformReconstructionTool.h
+++ b/Waveform/WaveRecTools/WaveRecTools/IWaveformReconstructionTool.h
@@ -20,6 +20,7 @@
 #include "xAODFaserWaveform/WaveformClock.h"
 
 class RawWaveform;
+class RawWaveformContainer;
 
 ///Interface for Waveform reco algorithms
 class IWaveformReconstructionTool : virtual public IAlgTool 
@@ -31,6 +32,11 @@ class IWaveformReconstructionTool : virtual public IAlgTool
 
   virtual ~IWaveformReconstructionTool() = default;
 
+  // Reconstruct all waveforms
+  virtual StatusCode reconstructAll(const RawWaveformContainer& waveContainer,
+				 const xAOD::WaveformClock* clock, 
+				 xAOD::WaveformHitContainer* container) const = 0;
+				    
   // Reconstruct all peaks in a raw waveform
   virtual StatusCode reconstruct(const RawWaveform& wave, 
 				 const xAOD::WaveformClock* clock, 
diff --git a/Waveform/WaveRecTools/src/WaveformReconstructionTool.cxx b/Waveform/WaveRecTools/src/WaveformReconstructionTool.cxx
index 5de393166579eef162e308acd31b0b12b6a12039..69a1d2be1f1b4a9dae3f230bf9c9a4915d3b18fe 100644
--- a/Waveform/WaveRecTools/src/WaveformReconstructionTool.cxx
+++ b/Waveform/WaveRecTools/src/WaveformReconstructionTool.cxx
@@ -10,8 +10,6 @@
 
 #include "WaveformReconstructionTool.h"
 
-#include "xAODFaserWaveform/WaveformHit.h"
-
 #include "TH1F.h"
 #include "TF1.h"
 #include "TFitResult.h"
@@ -42,6 +40,215 @@ WaveformReconstructionTool::initialize() {
 }
 
 // Reconstruction step
+StatusCode
+WaveformReconstructionTool::reconstructAll(
+	 const RawWaveformContainer& waveContainer, 
+	 const xAOD::WaveformClock* clock, 
+	 xAOD::WaveformHitContainer* hitContainer) const {
+
+  ATH_MSG_DEBUG(" reconstructAll called ");
+
+  // Reconstruct each waveform
+  for( const auto& wave : waveContainer) {
+
+    ATH_MSG_DEBUG("Reconstruct waveform for channel " << wave->channel());
+
+    // Reconstruct the hits, may be more than one, so pass container
+    CHECK( this->reconstruct(*wave, clock, hitContainer) );
+  }
+
+  if (m_ensureChannelHits) {
+    ATH_MSG_DEBUG("Ensure all channels have hits at peak time");
+    ensureHits(waveContainer, clock, hitContainer);
+  }
+
+  return StatusCode::SUCCESS;
+}
+
+//
+// Make sure we have a hit for each channel at the time when
+// there is a significant pulse found in the detector
+//
+void
+WaveformReconstructionTool::ensureHits(
+	 const RawWaveformContainer& waveContainer, 
+	 const xAOD::WaveformClock* clock, 
+	 xAOD::WaveformHitContainer* hitContainer) const {
+
+  ATH_MSG_DEBUG(" ensureHits called ");
+
+  // Find peak time (most significant hit)
+  xAOD::WaveformHit* peakHit = NULL;
+
+  for( const auto& hit : *hitContainer) {
+
+    if (peakHit == NULL) {
+      peakHit = hit;
+    } else {
+      if ( hit->peak() > peakHit->peak() ) peakHit = hit;
+    }
+
+  }
+
+  // Didn't find anything?
+  if (peakHit == NULL) return;
+  if (peakHit->status_bit(xAOD::WaveformStatus::THRESHOLD_FAILED)) return;
+
+  ATH_MSG_DEBUG("Found peak hit in channel " << peakHit->channel() << " at time " << peakHit->localtime());
+
+  // Now go through all of the channels and check if there is a hit
+  // close in time to the peakHit
+  for( const auto& wave : waveContainer) {
+
+    // Don't worry about the peak channel, we know this has a hit...
+    if (wave->channel() == peakHit->channel()) continue;
+
+    ATH_MSG_DEBUG("Checking for hit in channel " << wave->channel());
+
+    bool found = false;
+    // Look for a baseline-only hit that we can update
+    xAOD::WaveformHit* baselineHit = NULL;
+
+    // There aren't so many hits, just loop over container
+    for( const auto& hit : *hitContainer) {
+      if (hit->channel() != wave->channel()) continue;
+
+      // Is this above threshold?
+      if (hit->status_bit(xAOD::WaveformStatus::THRESHOLD_FAILED)) {
+	baselineHit = hit;
+	continue;
+      }
+
+      // OK, this is the right channel, check the time
+      float dtime = abs(hit->localtime() - peakHit->localtime());
+      if (dtime > m_hitTimeDifference) continue;
+
+      // We have found a hit in the right channel at the right time
+      found = true;
+      ATH_MSG_DEBUG("Found hit in channel " << hit->channel() 
+		    << " at time " << hit->localtime());
+      break;
+    }
+
+    // Is there a hit?  If so, go to next waveform/channel
+    if (found) continue;
+
+    ATH_MSG_DEBUG("No hit found for channel " << wave->channel() 
+		  << " at time " << peakHit->localtime());
+
+    // Do we have a baseline-only hit we can use?
+    xAOD::WaveformHit* newhit = NULL;
+    if (baselineHit == NULL) {
+      // No, make a new hit here
+      newhit = new xAOD::WaveformHit();
+      hitContainer->push_back(newhit);
+
+      // Mark this as a secondary hit
+      newhit->set_status_bit(xAOD::WaveformStatus::THRESHOLD_FAILED);
+      newhit->set_status_bit(xAOD::WaveformStatus::SECONDARY);
+
+      // Set digitizer channel and identifier
+      newhit->set_channel(wave->channel());
+      newhit->set_id(wave->identify32().get_compact());
+
+      // Make sure we have ADC counts
+      if (wave->adc_counts().size() == 0) {
+	ATH_MSG_WARNING( "Found waveform for channel " << wave->channel() 
+			 << " with size " << wave->adc_counts().size() << "!");
+	
+	newhit->set_status_bit(xAOD::WaveformStatus::WAVEFORM_MISSING);
+	continue;
+      } 
+      
+      if (wave->adc_counts().size() != wave->n_samples()) {
+	ATH_MSG_WARNING( "Found waveform for channel " << wave->channel() 
+			 << " with size " << wave->adc_counts().size() 
+			 << " not equal to number of samples " << wave->n_samples());
+	
+	newhit->set_status_bit(xAOD::WaveformStatus::WAVEFORM_INVALID);
+	continue;
+      }
+
+      findBaseline(*wave, newhit);
+
+    } else {
+      // Use the existing baseline hit
+      newhit = baselineHit;
+    }
+
+    // Check for problems
+    if (newhit->status_bit(xAOD::WaveformStatus::BASELINE_FAILED)) continue;
+
+    // Set range for windowed data
+    unsigned int lo_edge = peakHit->time_vector().front()/2.;
+    unsigned int hi_edge = peakHit->time_vector().back()/2.;
+
+    ATH_MSG_DEBUG("Windowing waveform from " << lo_edge << " to " << hi_edge);
+    std::vector<float> wtime(hi_edge-lo_edge+1);
+    std::vector<float> wwave(hi_edge-lo_edge+1);
+    for (unsigned int i=lo_edge; i<=hi_edge; i++) {
+      unsigned int j = i-lo_edge;
+      wtime[j] = 2.*i;
+      wwave[j] = newhit->baseline_mean() - wave->adc_counts()[i];
+      //ATH_MSG_DEBUG(" Time: " << wtime[j] << " Wave: " << wwave[j]);
+    }
+
+    newhit->set_time_vector(wtime);
+    newhit->set_wave_vector(wwave);
+
+    //
+    // Find some raw values
+    WaveformFitResult raw = findRawHitValues(wtime, wwave);
+    newhit->set_peak(raw.peak);
+    newhit->set_mean(raw.mean);
+    newhit->set_width(raw.sigma);
+    newhit->set_integral(raw.integral);
+    newhit->set_localtime(raw.mean);
+    newhit->set_raw_peak(raw.peak);
+    newhit->set_raw_integral(raw.integral);
+
+    //
+    // Find time from clock
+    if (!clock || (clock->frequency() <= 0.)) {
+      newhit->set_status_bit(xAOD::WaveformStatus::CLOCK_INVALID);
+      newhit->set_bcid_time(-1.);
+    } else {
+      newhit->set_bcid_time(clock->time_from_clock(newhit->localtime()));
+    }
+
+  } // End of loop over waveContainer
+}
+
+// Find the baseline
+WaveformBaselineData& 
+WaveformReconstructionTool::findBaseline(const RawWaveform& raw_wave, 
+					 xAOD::WaveformHit* hit) const {
+
+  //
+  // Find baseline
+  static WaveformBaselineData baseline;
+
+  if (m_useSimpleBaseline.value())
+    baseline = findSimpleBaseline(raw_wave);
+  else
+    baseline = findAdvancedBaseline(raw_wave);
+
+  if (!(baseline.valid)) {
+    ATH_MSG_WARNING("Failed to reconstruct baseline!");
+
+    hit->set_baseline_mean(0.);
+    hit->set_baseline_rms(-1.);
+    hit->set_status_bit(xAOD::WaveformStatus::BASELINE_FAILED);
+
+  } else {
+    // Save baseline to hit collection object
+    hit->set_baseline_mean(baseline.mean);
+    hit->set_baseline_rms(baseline.rms);
+  }
+
+  return baseline;
+}
+
 StatusCode
 WaveformReconstructionTool::reconstruct(const RawWaveform& raw_wave,
 					const xAOD::WaveformClock* clock, 
@@ -64,16 +271,15 @@ WaveformReconstructionTool::reconstruct(const RawWaveform& raw_wave,
   hit->set_channel(raw_wave.channel());
   hit->set_id(raw_wave.identify32().get_compact());
 
-  //
-  // Make some sanity checks on the waveform data
+  // Make sure we have ADC counts
   if (raw_wave.adc_counts().size() == 0) {
     ATH_MSG_WARNING( "Found waveform for channel " << raw_wave.channel() 
 		     << " with size " << raw_wave.adc_counts().size() << "!");
 
     hit->set_status_bit(xAOD::WaveformStatus::WAVEFORM_MISSING);
     return StatusCode::SUCCESS;
-  }
-    
+  } 
+
   if (raw_wave.adc_counts().size() != raw_wave.n_samples()) {
     ATH_MSG_WARNING( "Found waveform for channel " << raw_wave.channel() 
 		     << " with size " << raw_wave.adc_counts().size() 
@@ -83,28 +289,12 @@ WaveformReconstructionTool::reconstruct(const RawWaveform& raw_wave,
     return StatusCode::SUCCESS;
   }
 
-  //
-  // Find baseline
-  WaveformBaselineData baseline;
-
-  if (m_useSimpleBaseline.value())
-    baseline = findSimpleBaseline(raw_wave);
-  else
-    baseline = findAdvancedBaseline(raw_wave);
-
-  if (!(baseline.valid)) {
-    ATH_MSG_WARNING("Failed to reconstruct baseline!");
+  // Find the baseline
+  WaveformBaselineData baseline = findBaseline(raw_wave, hit);
 
-    hit->set_baseline_mean(0.);
-    hit->set_baseline_rms(-1.);
-    hit->set_status_bit(xAOD::WaveformStatus::BASELINE_FAILED);
-
-    return StatusCode::SUCCESS;
-  }
-
-  // Save baseline to hit collection object
-  hit->set_baseline_mean(baseline.mean);
-  hit->set_baseline_rms(baseline.rms);
+  // Check that we have data to work with
+  // If any status bits are set, this is bad
+  if (hit->status()) return StatusCode::SUCCESS;
 
   //
   // Create baseline-subtracted data array for both time and signal
@@ -349,10 +539,19 @@ WaveformReconstructionTool::findAdvancedBaseline(const RawWaveform& raw_wave) co
   TH1F h1("", "", nbins, xlo, xhi);
 
   // Fill this histogram with the waveform
+  // Only use a subset, based on where we think there won't be signal
+  const std::vector<unsigned int>& counts = raw_wave.adc_counts();
+  for (int i=m_baselineSampleLo; i<=m_baselineSampleHi; i++) {
+    //ATH_MSG_INFO( "Entry " << i << " Value " << counts[i] );
+    h1.Fill(counts[i]);
+  }
+
+  /*
   for (auto value : raw_wave.adc_counts()) {
     //ATH_MSG_DEBUG( "Found value " << value );
     h1.Fill(value);
   }
+  */
 
   // Find max bin
   int maxbin = h1.GetMaximumBin();
@@ -366,8 +565,8 @@ WaveformReconstructionTool::findAdvancedBaseline(const RawWaveform& raw_wave) co
   ATH_MSG_DEBUG( "Filling 2nd histogram from " << xlo << " to " << xhi);
 
   TH1F h2("", "", nbins, xlo, xhi);
-  for (auto value : raw_wave.adc_counts()) {
-    h2.Fill(value);
+  for (int i=m_baselineSampleLo; i<=m_baselineSampleHi; i++) {
+    h2.Fill(counts[i]);
   }
 
   // Start with full histogram range
@@ -459,7 +658,7 @@ WaveformReconstructionTool::findRawHitValues(const std::vector<float> time, cons
   rfit.integral = 2*tot; // Factor of 2 because at 500 MHz, dt = 2 ns
   rfit.time = rfit.mean;
 
-  ATH_MSG_DEBUG( "Initial Mean: " << rfit.mean << " RMS: " << rfit.sigma << " Peak: " << rfit.peak);  
+  ATH_MSG_DEBUG( "Initial Mean: " << rfit.mean << " RMS: " << rfit.sigma << " Peak: " << rfit.peak << " Integral: " << rfit.integral);  
 
   // Fix bad values
   if (isnan(rfit.sigma)) {
diff --git a/Waveform/WaveRecTools/src/WaveformReconstructionTool.h b/Waveform/WaveRecTools/src/WaveformReconstructionTool.h
index 1bb0f20d4d2901468fa9982fd7bbed26c9c2d73b..e7e61205f62af237aacaa2d7b8f803638856d7b0 100644
--- a/Waveform/WaveRecTools/src/WaveformReconstructionTool.h
+++ b/Waveform/WaveRecTools/src/WaveformReconstructionTool.h
@@ -14,6 +14,8 @@
 #include "WaveRecTools/IWaveformReconstructionTool.h"
 
 #include "WaveRawEvent/RawWaveform.h"
+#include "WaveRawEvent/RawWaveformContainer.h"
+#include "xAODFaserWaveform/WaveformHit.h"
 
 #include "WaveformBaselineData.h"
 #include "WaveformFitResult.h"
@@ -35,25 +37,40 @@ class WaveformReconstructionTool: public extends<AthAlgTool, IWaveformReconstruc
   /// Retrieve the necessary services in initialize
   StatusCode initialize();
 
+  /// Reconstruct all hits from waveform container
+  virtual StatusCode reconstructAll(const RawWaveformContainer& waveContainer,
+				    const xAOD::WaveformClock* clock,
+				    xAOD::WaveformHitContainer* hitContainer) const;
+
   /// Reconstruct hits from waveform
   
   virtual StatusCode reconstruct(const RawWaveform& wave,
 				 const xAOD::WaveformClock* clock,
-				 xAOD::WaveformHitContainer* container) const;
+				 xAOD::WaveformHitContainer* hitContainer) const;
 
  private:
 
   //
   // Baseline Estimation Parameters
   BooleanProperty m_useSimpleBaseline{this, "UseSimpleBaseline", false};
+
+  // Minimum number of samples needed to calculate simple baseline
+  // Just average these first n values
   IntegerProperty m_samplesForBaselineAverage{this, "SamplesForBaselineAverage", 40};
 
+ 
   //
-  // Parameters of initial histogram to find baseline max
+  // Parameters for advanced baseline determination
+  // Parameters of initial histogram to find most likely ADC reading
   // Range and bins to use, ratio should be an integer (bin width)
   IntegerProperty m_baselineRange{this, "BaselineRange", 16000};
   IntegerProperty m_baselineRangeBins{this, "BaselineRangeBins", 320};
 
+  // Range of samples to use to find baseline (to avoid signal contamination)
+  // In samples (2 ns intervals) so 350 -> 700 ns in digitizer window
+  IntegerProperty m_baselineSampleLo{this, "BaselineSampleLo", 0};
+  IntegerProperty m_baselineSampleHi{this, "BaselineSampleHi", 350};
+
   // 
   // Parameters for the Gaussian fit to the baseline peak (in counts)
   // Range is total range to use to find truncated mean and width
@@ -82,9 +99,19 @@ class WaveformReconstructionTool: public extends<AthAlgTool, IWaveformReconstruc
   // Fraction of peak to set local hit time
   FloatProperty m_timingPeakFraction{this, "TimingPeakFraction", 0.45};
 
+  //
+  // Ensure each channel has a waveform hit at time of most significant 
+  // hit in the event
+  BooleanProperty m_ensureChannelHits{this, "EnsureChannelHits", true};
+  // Max Time difference in ns to say a hit exists in a different channel
+  FloatProperty m_hitTimeDifference{this, "HitTimeDifference", 10.};
+
   // Baseline algorithms
   WaveformBaselineData& findSimpleBaseline(const RawWaveform& wave) const;
   WaveformBaselineData& findAdvancedBaseline(const RawWaveform& wave) const;
+  WaveformBaselineData& findBaseline(const RawWaveform& wave, 
+				     xAOD::WaveformHit* hit) const;
+
 
   // Find peak in wave, return windowed region in windowed_time and windowed_wave
   // Windowed region is removed from original vectors
@@ -112,6 +139,11 @@ class WaveformReconstructionTool: public extends<AthAlgTool, IWaveformReconstruc
 			      const std::vector<float> wave) const;
 
 
+  /// Create hit in all channels at time of peak signal
+  void ensureHits(const RawWaveformContainer& waveContainer,
+		  const xAOD::WaveformClock* clock,
+		  xAOD::WaveformHitContainer* hitContainer) const;
+
 };
 
 #endif // WAVERECTOOLS_WAVEFORMRECONSTRUCTIONTOOL_H
diff --git a/faser-common b/faser-common
index 89ce6a07128eb2ebc367b6b68f29c9c88220e3e6..e7a3a145593c7bbda73b64a7106ffe3e43f8ff94 160000
--- a/faser-common
+++ b/faser-common
@@ -1 +1 @@
-Subproject commit 89ce6a07128eb2ebc367b6b68f29c9c88220e3e6
+Subproject commit e7a3a145593c7bbda73b64a7106ffe3e43f8ff94