diff --git a/src/toolbox_scs/detectors/hrixs.py b/src/toolbox_scs/detectors/hrixs.py
index 31f6984f3b653e470d53e4130c9c19a682d192c4..aa40480e53977097d437fe68464fe9daa5512955 100644
--- a/src/toolbox_scs/detectors/hrixs.py
+++ b/src/toolbox_scs/detectors/hrixs.py
@@ -196,6 +196,50 @@ def _esrf_centroid(image, threshold=THRESHOLD, curvature=(CURVE_A, CURVE_B)):
             res.append((my, mx))
     return res
 
+def _esrf_centroid_double(image, energy=700, avoid_dbl=False):
+
+    # Multiplication factor * ADU/photon
+    SpotLOW = 0.2 * energy/3.6/1.06
+    SpotHIGH = 1.5 * energy/3.6/1.06
+    low_th_px = 0.2 * energy/3.6/1.06
+    high_th_px = 1 * energy/3.6/1.06 
+    
+    if avoid_dbl:
+        SpotHIGH = 100000
+        print("Double hit events are not taken into account\n")
+
+    img = image-image.mean()
+
+    gs = 2
+ 
+    # Find potential hits on a clipped image where 2 rows/columns are excluded
+    # from the edges because centroiding can't be done at the edge
+    cp = np.argwhere((img[gs//2 : -gs//2, gs//2 : -gs//2] > low_th_px)*
+                     (img[gs//2 : -gs//2, gs//2 : -gs//2] < high_th_px))+np.array([gs//2, gs//2])
+    
+    if len(cp) > 100000:
+        raise RuntimeError('Threshold to low or acquisition time to long')
+
+    res = []
+    double = []
+    for cy, cx in cp:
+        spot = img[cy - gs//2 : cy + gs//2 + 1, cx - gs//2 : cx + gs//2 + 1] 
+        #spot = img[cy - gs//2 : cy + gs//2 + 1, cx - gs//2 : cx + gs//2 + 1]
+        #if spot.sum() < 2 * (THRESHOLD - base):
+        #    continue
+        spot[spot < 0] = 0
+        if (spot > img[cy, cx]).sum() == 0:
+            mx = np.average(np.arange(cx - gs//2, cx + gs//2 + 1), weights=spot.sum(axis=0))
+            my = np.average(np.arange(cy - gs//2, cy + gs//2 + 1), weights=spot.sum(axis=1))
+            my -= (CURVE_A + CURVE_B * mx) * mx
+            if (spot.sum()>SpotLOW) and (spot.sum()<=SpotHIGH):               
+                res.append((my, mx))
+            elif (spot.sum()>SpotHIGH):
+                res.append((my, mx))
+                res.append((my, mx))
+                double.append((my, mx))
+    return res, double
+    
 
 def _new_centroid(image, threshold=THRESHOLD, std_threshold=3.5, curvature=(CURVE_A, CURVE_B)):
     """find the position of photons with sub-pixel precision
@@ -223,6 +267,7 @@ def _new_centroid(image, threshold=THRESHOLD, std_threshold=3.5, curvature=(CURV
             "too many peaks, threshold too low or acquisition time too high")
 
     res = []
+    double = []
     for cy, cx in cp:
         spot = image[cy: cy + 4, cx: cx + 4] - base
         mx = np.average(np.arange(cx, cx + 4), weights=spot.sum(axis=0))
@@ -231,9 +276,58 @@ def _new_centroid(image, threshold=THRESHOLD, std_threshold=3.5, curvature=(CURV
         res.append((my, mx))
     return res
 
+def _new_centroid_double(image, threshold=THRESHOLD, std_threshold=3.5, 
+        dbl_threshold=1.5, curvature=(CURVE_A, CURVE_B)):
+    """
+    A photon is supposed to have hit the detector if the intensity within a
+    2-by-2 square exceeds a threshold. In this case the position of the photon
+    is calculated as the center-of-mass in a 4-by-4 square.
 
-centroid = _new_centroid
+    Return the list of x,y coordinate pairs, corrected by the curvature.
 
+    This implementation includes standard energy dependent threshholds and
+    checks for double hits. If a double hit is found two instances of the
+    photon are returned and the double hits are also returned
+    """
+
+    # Implement energy dependent threshhold later
+    #SpotLOW = 0.2 * energy/3.6/1.06
+    #SpotHIGH = 1.5 * energy/3.6/1.06
+    #low_th_px = 0.2 * energy/3.6/1.06
+    #high_th_px = 1 * energy/3.6/1.06 
+    
+
+    base = image.mean()
+    corners = image[1:, 1:] + image[:-1, 1:] + image[1:, :-1] + image[:-1, :-1]
+    if threshold is None:
+        threshold = corners.mean() + std_threshold * corners.std()
+    SpotHIGH=1.5*threshold
+    middle = corners[1:-1, 1:-1]
+    candidates = (
+            (middle > threshold)
+            * (middle >= corners[:-2, 1:-1]) * (middle > corners[2:, 1:-1])
+            * (middle >= corners[1:-1, :-2]) * (middle > corners[1:-1, 2:])
+            * (middle >= corners[:-2, :-2]) * (middle > corners[2:, :-2])
+            * (middle >= corners[:-2, 2:]) * (middle > corners[2:, 2:]))
+    cp = np.argwhere(candidates)
+    if len(cp) > 10000:
+        raise RuntimeError(
+            "too many peaks, threshold too low or acquisition time too high")
+
+    res = []
+    dres = []
+    for cy, cx in cp:
+        spot = image[cy: cy + 4, cx: cx + 4] - base
+        mx = np.average(np.arange(cx, cx + 4), weights=spot.sum(axis=0))
+        my = np.average(np.arange(cy, cy + 4), weights=spot.sum(axis=1))
+        my -= (curvature[0] + curvature[1] * mx) * mx
+        if spot.sum()<=SpotHIGH:
+            res.append((my, mx))
+        else:
+            res.append((my, mx))
+            res.append((my, mx))
+            dres.append((my,mx))
+    return res, dres
 
 def decentroid(res):
     res = np.array(res)
@@ -286,6 +380,7 @@ class hRIXS:
     # centroid
     THRESHOLD = None  # pixel counts above which a hit candidate is assumed
     STD_THRESHOLD = 3.5  # same as THRESHOLD, in standard deviations
+    DBL_THRESHOLD = 1.5 # threshhold for doubles if not given
     CURVE_A = CURVE_A  # curvature parameters as determined elsewhere
     CURVE_B = CURVE_B
 
@@ -313,7 +408,9 @@ class hRIXS:
     ENERGY_INTERCEPT = 0
     ENERGY_SLOPE = 1
 
-    FIELDS = ['hRIXS_det', 'hRIXS_index', 'hRIXS_delay', 'hRIXS_norm']
+
+    # Load hrixs detector details + mono energy for automatic threshold value
+    FIELDS = ['hRIXS_det', 'hRIXS_index', 'hRIXS_delay', 'hRIXS_norm', 'nrj']
 
     def set_params(self, **params):
         for key, value in params.items():
@@ -418,7 +515,35 @@ class hRIXS:
 
     
     def centroid(self, data, bins=None, return_hits=False, fit_elastic=False,
-                 hv=None, fit_delta=None):
+                 hv=None, fit_delta=None, algorithm='martin2'):
+        """
+        Carry out hit finding and bin them on grid
+
+        Parameters
+        ----------
+        data: xarray.DataArray
+            container containing run data and images to process
+        bins: int
+            number of bins to use in histogram of hits
+        return_hits: bool
+            option to return list of hits or only return the binned spectrum
+        fit_elastic: bool
+            option to fit the elastic line in each image and stores the energy
+            and position of the elastic line in the data container
+        hv: float
+            Incident energy
+        fit_delta: int
+            Width of the fit window in bins
+        algorithm: str
+            one of 'esrf', 'esrf2', 'martin', and 'martin2' where martin2 and
+            esrf2 account for double hits
+
+        Returns
+        -------
+        data: xarray.DataArray
+            container containing data and centroided spectra 
+
+        """
         #*************************************************************
         # Carry out hit finding on data and bin them in grid
         # Allows for 
@@ -432,6 +557,7 @@ class hRIXS:
         #*************************************************************
         # If new bins are given, use them
         #*************************************************************
+        print('message')
         if bins is None:
             bins = self.BINS
         #*************************************************************
@@ -440,7 +566,14 @@ class hRIXS:
         hit_x = []
         hit_y = []
         hits = []
+        if algorithm == 'martin2' or algorithm=='esrf2':
+            dbl_x = []
+            dbl_y = []
+            dbl_hits = []
+            do_doubles = True
+
         ret = np.zeros((len(data["hRIXS_det"]), bins))
+        retd = np.zeros((len(data["hRIXS_det"]), bins))
         #*************************************************************
         # If the 'actual' photon energy is desired, we'll need to know
         # where to start looking for the elastic line
@@ -451,7 +584,7 @@ class hRIXS:
             if fit_delta == None:
                 fit_delta = self.HV_FIT_DELTA
             if hv == None:
-                # ?? We'll make a guess later
+                #ave_nrj = data.nrj.mean().mean().data
                 hv = -1 * np.ones(len(data["hRIXS_det"]))
             else:
                 # hv is given as one value or a train-vector
@@ -464,7 +597,7 @@ class hRIXS:
         #*************************************************************
         # Handle each Aq image separately
         #*************************************************************
-        for i, (image, r) in enumerate(zip(data["hRIXS_det"], ret)):
+        for i, (image, r, rr) in enumerate(zip(data["hRIXS_det"], ret, retd)):
             use_image = image.to_numpy()
             #*************************************************************
             # Treat background by optionally 
@@ -494,14 +627,34 @@ class hRIXS:
             #*************************************************************
             # Run centroiding on the preprocessed image
             #*************************************************************
-            c = centroid(
-                use_image[self.X_RANGE, self.Y_RANGE].T,
-                threshold=self.THRESHOLD,
-                std_threshold=self.STD_THRESHOLD,
-                curvature=(self.CURVE_A, self.CURVE_B))
+            if algorithm == 'martin': 
+                c = _new_centroid(
+                    use_image[self.X_RANGE, self.Y_RANGE].T,
+                    threshold=self.THRESHOLD,
+                    std_threshold=self.STD_THRESHOLD,
+                    curvature=(self.CURVE_A, self.CURVE_B))
+            elif algorithm == 'martin2':
+                c,d = _new_centroid_double(
+                    use_image[self.X_RANGE, self.Y_RANGE].T,
+                    threshold=self.THRESHOLD,
+                    std_threshold=self.STD_THRESHOLD,
+                    dbl_threshold=self.DBL_THRESHOLD,
+                    curvature=(self.CURVE_A, self.CURVE_B))
+            elif algorithm=='esrf':
+                c = _esrf_centroid( 
+                    use_image[self.X_RANGE, self.Y_RANGE].T,
+                    threshold=self.THRESHOLD,
+                    curvature=(self.CURVE_A, self.CURVE_B))
+            elif algorithm=='esrf2':
+                ave_nrj = data.nrj.mean().mean().data
+                c,d = _esrf_centroid_double(
+                    use_image[self.X_RANGE, self.Y_RANGE].T,
+                    energy=ave_nrj,avoid_dbl=False)
+
             if not len(c):
                 continue
             rc = np.array(c)
+
             #*************************************************************
             # If hits have been requested, append the hit data of the 
             # image to the lists of hit lists
@@ -510,14 +663,37 @@ class hRIXS:
                 hit_x.append(rc[:, 0])
                 hit_y.append(rc[:, 1])
                 hits.append(rc)
-            #*************************************************************
-            # Assign the spectrum to the spectrum matrix ret. Iteration
-            # variable r points to the proper location of ret.
-            #*************************************************************
+
+            # Store histogram of hits in ret
             hy, hx = np.histogram(
                 rc[:, 0], bins=bins,
                 range=(0, self.Y_RANGE.stop - self.Y_RANGE.start))
             r[:] = hy
+
+            if do_doubles:
+                # Check to make sure there are actually double hits. 
+                # Make empty arrays if not, so hit lits still work
+                if not len(d):
+                    print("No Double hits found in image number ",str(i))
+                    doubles_found = False
+                    if return_hits:
+                        dbl_x.append([])
+                        dbl_y.append([])
+                        dbl_hits.append([])
+                else:
+                    doubles_found = True
+                    rd = np.array(d)
+                    if return_hits:
+                        dbl_x.append(rd[:,0])
+                        dbl_y.append(rd[:,1])
+                        dbl_hits.append(rd)
+                # Make histogram of doubles hits store in retd
+                    dy, dx = np.histogram(
+                        rd[:,0], bins=bins,
+                        range=(0, self.Y_RANGE.stop - self.Y_RANGE.start))
+                    rr[:]= dy
+            
+            
             #*************************************************************
             # Return the found elastic peak energy, if requested
             #*************************************************************
@@ -550,6 +726,11 @@ class hRIXS:
             data = data.assign(hits=(("trainId"), hits),
                         xhits=(("trainId"), hit_x),
                         yhits=(("trainId"), hit_y))
+            if do_doubles:
+                data = data.assign(dbl_hits=(("trainId"), dbl_hits),
+                        dblx=(("trainId"), dbl_x),
+                        dbly=(("trainId"), dbl_y))
+
         #**********************************************
         # If hv was fitted, return it
         #**********************************************
@@ -560,6 +741,8 @@ class hRIXS:
         # Always assign the spectrum to data
         #**********************************************
         data = data.assign(spectrum=(("trainId", "energy"), ret))
+        if do_doubles:
+            data = data.assign(dbl_spectrum=(("trainId", "energy"), retd))
         return data