diff --git a/scripts/AbinsModules/Instruments/Broadening.py b/scripts/AbinsModules/Instruments/Broadening.py
index 1c2971d7728d7f0297986c65bd7500a5abb8f664..1421a602529ea9e3121fcd16024949030a91a3e8 100644
--- a/scripts/AbinsModules/Instruments/Broadening.py
+++ b/scripts/AbinsModules/Instruments/Broadening.py
@@ -84,11 +84,12 @@ def broaden_spectrum(frequencies=None, bins=None, s_dft=None, sigma=None, scheme
         return freq_points, hist
 
     elif scheme == 'gaussian':
-        # Gaussian broadening on the full grid (no range cutoff, sum over all peaks)
-        # This is not very optimised but a useful reference for "correct" results
-        kernels = gaussian(sigma=sigma[:, np.newaxis],
-                           points=freq_points,
-                           center=frequencies[:, np.newaxis])
+        # Gaussian broadening on the full grid (no range cutoff, sum over all peaks).
+        # This is not very optimised but a useful reference for "correct" results.
+        bin_width = bins[1] - bins[0]
+        kernels = mesh_gaussian(sigma=sigma[:, np.newaxis],
+                                points=freq_points,
+                                center=frequencies[:, np.newaxis])
         spectrum = np.dot(kernels.transpose(), s_dft)
         return freq_points, spectrum
 
@@ -107,14 +108,17 @@ def broaden_spectrum(frequencies=None, bins=None, s_dft=None, sigma=None, scheme
         # Gaussian broadening on the full grid (sum over all peaks, Gaussian range limited to 3 sigma)
         # All peaks use the same number of points; if the center is located close to the low- or high-freq limit,
         # the frequency point set is "justified" to lie inside the range
-        return trunc_and_sum_inplace(function=gaussian,
-                                     sigma=sigma[:, np.newaxis],
-                                     points=freq_points,
-                                     bins=bins,
-                                     center=frequencies[:, np.newaxis],
-                                     limit=3,
-                                     weights=s_dft[:, np.newaxis],
-                                     method='auto')
+        points, spectrum = trunc_and_sum_inplace(function=gaussian,
+                                                 sigma=sigma[:, np.newaxis],
+                                                 points=freq_points,
+                                                 bins=bins,
+                                                 center=frequencies[:, np.newaxis],
+                                                 limit=3,
+                                                 weights=s_dft[:, np.newaxis],
+                                                 method='auto')
+        # Normalize the Gaussian kernel such that sum of points matches input
+        bin_width = bins[1] - bins[0]
+        return points, spectrum * bin_width
 
     elif scheme == 'normal_truncated':
         # Normal distribution on the full grid (sum over all peaks, Gaussian range limited to 3 sigma)
@@ -145,19 +149,47 @@ def broaden_spectrum(frequencies=None, bins=None, s_dft=None, sigma=None, scheme
                          'AbinsParameters.sampling["broadening_scheme"]'.format(scheme))
 
 
-def gaussian(sigma=None, points=None, center=0, normalized=True):
+def mesh_gaussian(sigma=None, points=None, center=0):
+    """Evaluate a Gaussian function over a regular (given) mesh
+
+    The Gaussian is normalized by multiplying by the bin-width. This approach will give correct results even when the
+    function extends (or originates) beyond the sampling region; however, it cannot be applied to an irreglar mesh.
+    Note that this normalisation gives a consistent _sum_ rather than a consistent _area_; it is a suitable kernel for
+    convolution of a histogram.
+
+    If 'points' contains less than two values, an empty or zero array is returned as the spacing cannot be inferred.
+
+    :param sigma: sigma defines width of Gaussian
+    :param points: points for which Gaussian should be evaluated
+    :type points: 1-D array
+    :param center: center of Gaussian
+    :type center: float or array
+    :returns:
+        numpy array with calculated Gaussian values. Dimensions are broadcast from inputs:
+        to obtain an (M x N) 2D array of gaussians at M centers and
+        corresponding sigma values, evaluated over N points, let *sigma* and
+        *center* be arrays of shape (M, 1) (column vectors) and *points* have
+         shape (N,) or (1, N) (row vector).
     """
-    Evaluate a Gaussian function over a given mesh
 
-    Note that in order to obtain a normalised convolution kernel this should be
-    divided by the width of the (regular) sampling bins.
+    if len(points) < 2:
+        return(np.zeros_like(points * sigma))
+        
+    bin_width = points[1] - points[0]
+    return(gaussian(sigma=sigma, points=points, center=center) * bin_width)
+    
+def gaussian(sigma=None, points=None, center=0):
+    """Evaluate a Gaussian function over a given mesh
 
     :param sigma: sigma defines width of Gaussian
     :param points: points for which Gaussian should be evaluated
     :type points: 1-D array
     :param center: center of Gaussian
     :type center: float or array
-    :param normalized: If True, scale the kernel so that the sum of all values equals 1
+    :param normalized:
+    If True, scale the output so that the sum of all values 
+    equals 1 (i.e. make a suitable kernel for convolution of a histogram.)
+    This will not be reliable if the function extends beyond the provided set of points.
     :type normalized: bool
     :returns:
         numpy array with calculated Gaussian values. Dimensions are broadcast from inputs:
@@ -165,13 +197,11 @@ def gaussian(sigma=None, points=None, center=0, normalized=True):
         corresponding sigma values, evaluated over N points, let *sigma* and
         *center* be arrays of shape (M, 1) (column vectors) and *points* have
          shape (N,) or (1, N) (row vector).
-    """
+         """
     two_sigma = 2.0 * sigma
     sigma_factor = two_sigma * sigma
     kernel = np.exp(-(points - center) ** 2 / sigma_factor) / (np.sqrt(sigma_factor * np.pi))
 
-    if normalized:
-        kernel = kernel / np.sum(kernel, axis=-1)[..., np.newaxis]
     return kernel
 
 
@@ -238,13 +268,19 @@ def trunc_function(function=None, sigma=None, points=None, center=None, limit=3)
     :returns: numpy array with calculated Gaussian values
     """
 
+    if isinstance(center, float):
+        center = np.array([[center]])
+    if isinstance(sigma, float):
+        sigma = sigma * np.ones_like(center)
+
     points_matrix = points * np.ones((len(center), 1))
+
     center_matrix = center * np.ones(len(points))
     sigma_matrix = sigma * np.ones(len(points))
 
     distances = abs(points_matrix - center_matrix)
     points_close_to_peaks = distances < (limit * sigma_matrix)
-
+    
     results = np.zeros((len(center), len(points)))
     results[points_close_to_peaks] = function(sigma=sigma_matrix[points_close_to_peaks],
                                               points=points_matrix[points_close_to_peaks],
@@ -345,6 +381,10 @@ def trunc_and_sum_inplace(function=None, function_uses='points',
     #
     start_indices = np.asarray((center - points[0] - freq_range + (bin_width / 2)) // bin_width,
                                int)
+    # Values exceeding calculation range would have illegally large "initial guess" indices so clip those to final point
+    #   |            | s---x----     ->       |           s|--x----
+    start_indices[start_indices > len(points)] = -1
+
     start_freqs = points[start_indices]
 
     # Next identify points which will overshoot left: x lies to left of freq range
@@ -508,9 +548,9 @@ def interpolated_broadening(sigma=None, points=None, bins=None,
     kernel_npts_oneside = np.ceil(freq_range / bin_width)
 
     if function == 'gaussian':
-        kernels = gaussian(sigma=sigma_samples[:, np.newaxis],
-                           points=np.arange(-kernel_npts_oneside, kernel_npts_oneside + 1, 1) * bin_width,
-                           center=0)
+        kernels = mesh_gaussian(sigma=sigma_samples[:, np.newaxis],
+                                points=np.arange(-kernel_npts_oneside, kernel_npts_oneside + 1, 1) * bin_width,
+                                center=0)
     else:
         raise ValueError('"{}" kernel not supported for "interpolate" broadening method.'.format(function))
 
diff --git a/scripts/test/AbinsBroadeningTest.py b/scripts/test/AbinsBroadeningTest.py
index 650860e2ce4738d87824752dbd3457d5c1fd24e3..630cb4147aed1e1c7e61fab41ae2d31262b8acb1 100644
--- a/scripts/test/AbinsBroadeningTest.py
+++ b/scripts/test/AbinsBroadeningTest.py
@@ -43,6 +43,21 @@ class AbinsBroadeningTest(unittest.TestCase):
                                    0.01257,
                                    places=places)
 
+    def test_out_of_bounds(self):
+        """Check schemes allowing arbitrary placement can handle data beyond bins"""
+        frequencies = np.array([2000.])
+        bins = np.linspace(0, 100, 100)
+        s_dft = np.array([1.])
+        sigma = np.array([3.])
+
+        schemes = ['none',
+                   'gaussian', 'gaussian_truncated',
+                   'normal', 'normal_truncated']
+
+        for scheme in schemes:
+            Broadening.broaden_spectrum(frequencies=frequencies,
+                                        bins=bins, s_dft=s_dft, sigma=sigma,
+                                        scheme=scheme)
 
     def test_broadening_normalisation(self):
         """Check broadening implementations do not change overall intensity"""
@@ -61,10 +76,8 @@ class AbinsBroadeningTest(unittest.TestCase):
 
         pre_broadening_total = sum(s_dft)
 
-        # Gaussian scheme is normalised by values; truncated form still has correct sum
-        for scheme in ('none',
-                       'gaussian', 'gaussian_truncated',
-                       ):
+        # Full Gaussian should reproduce null total
+        for scheme in ('none', 'gaussian'):
             freq_points, spectrum = Broadening.broaden_spectrum(frequencies=frequencies,
                                                                 bins=bins,
                                                                 s_dft=s_dft,
@@ -83,14 +96,16 @@ class AbinsBroadeningTest(unittest.TestCase):
                                pre_broadening_total * (bins[1] - bins[0]),)
         self.assertAlmostEqual(sum(spectrum), pre_broadening_total)
 
-        # truncated form will be a little off but shouldn't be _too_ off
-        freq_points, trunc_spectrum = Broadening.broaden_spectrum(frequencies=frequencies,
-                                                                 bins=bins,
-                                                                 s_dft=s_dft,
-                                                                 sigma=sigma,
-                                                                 scheme='normal_truncated')
-        self.assertLess(abs(sum(full_spectrum) - sum(trunc_spectrum)) / sum(full_spectrum),
-                            0.03)
+        # truncated forms will be a little off but shouldn't be _too_ off
+        for scheme in ('gaussian_truncated', 'normal_truncated'):
+                       
+            freq_points, trunc_spectrum = Broadening.broaden_spectrum(frequencies=frequencies,
+                                                                      bins=bins,
+                                                                      s_dft=s_dft,
+                                                                      sigma=sigma,
+                                                                      scheme=scheme)
+            self.assertLess(abs(sum(full_spectrum) - sum(trunc_spectrum)) / sum(full_spectrum),
+                                0.03)
 
         # Interpolated methods need histogram input and smooth sigma
         hist_spec, _ = np.histogram(frequencies, bins, weights=s_dft)