diff --git a/notebooks/Jungfrau/Jungfrau_Create_Fit_Spectra_Histos_NBC.ipynb b/notebooks/Jungfrau/Jungfrau_Create_Fit_Spectra_Histos_NBC.ipynb
index 11765a8d7102e7cbd2c795fbbd31f3cb99312dce..f59eceda1c14960f0243ee7c18417431ec8ba09b 100644
--- a/notebooks/Jungfrau/Jungfrau_Create_Fit_Spectra_Histos_NBC.ipynb
+++ b/notebooks/Jungfrau/Jungfrau_Create_Fit_Spectra_Histos_NBC.ipynb
@@ -408,7 +408,7 @@
     "            # Allocate shared arrays for corrected data. Used in `correct_train()`\n",
     "            data_corr = context.alloc(shape=adc.shape, dtype=np.float32)\n",
     "            context.map(correct_train, adc)\n",
-    "            step_timer.done_step(\"correct_train\")\n",
+    "            step_timer.done_step(\"correcting trains per chunk\", print_step=False)\n",
     "\n",
     "            step_timer.start()\n",
     "            chunks = jungfrau_ff.chunk_multi(data_corr, block_size)\n",
@@ -425,7 +425,7 @@
     "                icol = i%n_blocks_col * block_size[1]\n",
     "                h_spectra[da][..., irow:irow+block_size[0], icol:icol+block_size[1]] += h_chk\n",
     "\n",
-    "            step_timer.done_step(\"Histogram created\")"
+    "            step_timer.done_step(\"Histogram created per chunk\", print_step=False)"
    ]
   },
   {
diff --git a/src/cal_tools/jungfrau/jungfrau_ff.py b/src/cal_tools/jungfrau/jungfrau_ff.py
index f1c421efe2e55f2baf43572d6b3c968e7fceefc5..b451d5ad3d949aa402ec4d459d059ed8f916bb62 100644
--- a/src/cal_tools/jungfrau/jungfrau_ff.py
+++ b/src/cal_tools/jungfrau/jungfrau_ff.py
@@ -3,25 +3,28 @@ from scipy.special import erf
 from iminuit import Minuit
 
 
-def histogram_errors(x):
+def histogram_errors(bin_counts):
     """
     Calculate the errors for histogram bins.
 
+    This function computes the error for each bin in a histogram,
+    treating positive and negative bin counts differently.
+
     Args:
         x (np.ndarray): Input array of histogram bin counts.
 
     Returns:
         np.ndarray: Array of calculated errors.
     """
-    out = np.ones_like(x)
+    out = np.ones_like(bin_counts)
 
     # Handle positive values
-    positive_mask = x > 0
-    out[positive_mask] = np.sqrt(x[positive_mask])
+    positive_mask = bin_counts > 0
+    out[positive_mask] = np.sqrt(bin_counts[positive_mask])
 
     # Handle negative values
-    negative_mask = x < 0
-    out[negative_mask] = np.sqrt(-x[negative_mask])
+    negative_mask = bin_counts < 0
+    out[negative_mask] = np.sqrt(-bin_counts[negative_mask])
     return out
 
 
@@ -73,37 +76,41 @@ def chunk_multi(data, block_size):
     return chunks
 
 
-def fill_histogram(imgs, h_bins):
+def fill_histogram(image_data, histogram_bins):
     """
-    Fills an histogram with shape
-    (n_bins-1, memory_cells, n_rows, n_cols)
-    from input images.
+    Fill a histogram from input images.
+    This function creates a histogram with shape
+    (n_bins-1, memory_cells, n_rows, n_cols) from the input image data.
 
     Args:
-        h_bins (list, float): the binning of the x-axis
-        imgs (np.ndarray): image data to histogram
+        histogram_bins (list, float): the binning of the x-axis
+        image_data (np.ndarray): image data to histogram
             (trains, memory_cells, row, col).
 
     Returns: histogram bin counts, bin edges.
+
+    Raises
+        TypeError: If imgs is not a numpy ndarray.
+        ValueError: If imgs is not a 4D array.
     """
-    if not isinstance(imgs, np.ndarray):
+    if not isinstance(image_data, np.ndarray):
         raise TypeError("Expected imgs numpy ndarray type.")
 
-    if imgs.ndim < 4:
+    if image_data.ndim < 4:
         raise ValueError("Expected 4D imgs array.")
 
-    n_cells, n_rows, n_cols = imgs.shape[1:]
+    n_cells, n_rows, n_cols = image_data.shape[1:]
 
     h_chk = np.zeros(
-        (len(h_bins)-1, n_cells, n_rows, n_cols),
+        (len(histogram_bins)-1, n_cells, n_rows, n_cols),
         dtype=np.int32)
 
     e_chk = None
     for cell in range(n_cells):
         for row in range(n_rows):
             for col in range(n_cols):
-                this_pix = imgs[:, cell, row, col]
-                _h, _e = np.histogram(this_pix, bins=h_bins)
+                this_pix = image_data[:, cell, row, col]
+                _h, _e = np.histogram(this_pix, bins=histogram_bins)
                 h_chk[..., cell, row, col] += _h
                 if e_chk is None:
                     e_chk = np.array(_e)
@@ -237,7 +244,7 @@ def fit_histogram(
             - CHARGE_SHARING_2: sum of two CHARGE_SHARING
             - GAUSS: gaussian function
         n_sigma (int): to calculate threshold of the peak finder as
-            thr = n_sigma * sigma0
+            thr = n_sigma * initial_sigma
         ratio (float): ratio parameter of the peak finder
         histo (ndarray): histogram bin counts with shape
             (n_bins, memory_cells, row, col)
@@ -253,12 +260,12 @@ def fit_histogram(
         CHARGE_SHARING_2=fit_double_charge_sharing,
         GAUSS=fit_gauss,
     )
-    sigma0 = 15.
+    initial_sigma = 15.
     fit_func = _funcs[_fit_func]
     n_cells, n_rows, n_cols = histo.shape[1:]
 
     _init_array = np.zeros((n_cells, n_rows, n_cols), dtype=np.float32)
-    g0_chk = _init_array.copy()
+    peak_positions = _init_array.copy()
     sigma_chk = _init_array.copy()
     chi2ndf_chk = _init_array.copy()
     alpha_chk = _init_array.copy()
@@ -271,19 +278,19 @@ def fit_histogram(
                 yerr = histogram_errors(y)
 
                 if noise[0, cell, row, col] > 0.:
-                    sigma0 = noise[0, cell, row, col]
+                    initial_sigma = noise[0, cell, row, col]
 
                 q, sigma, chi2ndf, alpha = fit_func(
-                    x_rebinned, y, yerr, sigma0, n_sigma, ratio)
+                    x_rebinned, y, yerr, initial_sigma, n_sigma, ratio)
 
-                g0_chk[cell, row, col] = q
+                peak_positions[cell, row, col] = q
                 sigma_chk[cell, row, col] = sigma
                 chi2ndf_chk[cell, row, col] = chi2ndf
                 alpha_chk[cell, row, col] = alpha
-    return g0_chk, sigma_chk, chi2ndf_chk, alpha_chk
+    return peak_positions, sigma_chk, chi2ndf_chk, alpha_chk
 
 
-def erfbox(x, ped, q0, s0):
+def erfbox(x, ped, q, sigma):
     """
     Compute the error function box used in charge sharing calculations.
 
@@ -291,34 +298,34 @@ def erfbox(x, ped, q0, s0):
 
     erfbox is mostly flat between ped and q0 and quickly goes to zero
     outside the range [ped, q0]. The function integral is normalized to 1.
-    The slope of the box sides is given by erf(x)/s0; if s0 == 0 then the
+    The slope of the box sides is given by erf(x)/sigma; if sigma == 0 then the
     function goes abruptly to 0 at the edges.
 
     Args:
         x (array-like): Input values
         ped (float): Pedestal value
         q0 (float): Charge value
-        s0 (float): Width parameter
+        sigma (float): Width parameter
 
     Returns:
         array-like: Computed erfbox values
     """
-    if ped == q0:
+    if ped == q:
         return np.zeros_like(x)
-    if ped > q0:
-        q0, ped = ped, q0
-
-    slope = lambda x: erf(x / abs(s0)) if s0 != 0 else 2 * np.heaviside(x, 1)  # noqa
-    return (slope(x - ped) - slope(x - q0)) * 0.5 / (q0 - ped)
-
+    if ped > q:
+        q, ped = ped, q
 
-def double_peak(x, ped, q_a, sigma_a, alpha, norm_a, q_b, sigma_b,  norm_b):
-    k_a = charge_sharing(x, ped, q_a, sigma_a, alpha, norm_a)
-    k_b = charge_sharing(x, ped, q_b, sigma_b, alpha, norm_b)
-    return k_a + k_b
+    slope = lambda x: erf(x / abs(sigma)) if sigma != 0 else 2 * np.heaviside(x, 1)  # noqa
+    return (slope(x - ped) - slope(x - q)) * 0.5 / (q - ped)
 
 
 def gauss(x, amp, mean, sigma):
+    """
+    Compute a Gaussian function.
+
+    This function calculates the values of a Gaussian distribution
+    for given input parameters.
+    """
     z = (x - mean) / sigma
     return amp * np.exp(-0.5 * z**2)
 
@@ -328,11 +335,7 @@ def charge_sharing(x, ped, q, sigma, alpha, norm):
     Model the detector response to a single photon with charge sharing.
 
     This function combines a Gaussian peak
-    (representing full charge collection)
-    with a charge sharing tail.
-
-    More details on JOURNAL OF SYNCHROTRON RADIATION 23, 1462-1473 (2016)
-    - f(x) = norm * (gaussian_peak + charge_sharing_tail) / ((1 + α)²)
+    (representing full charge collection) with a charge sharing tail.
 
     Args:
         x (array-like): Input charge values
@@ -344,22 +347,42 @@ def charge_sharing(x, ped, q, sigma, alpha, norm):
 
     Returns:
         array-like: Modeled detector response
-    """
-    # A small threshold to avoid division by zero
-    small_value_threshold = 1e-10
-    log_term = (x - ped) / (q - ped)
-    # Avoid log of zero or negative numbers
-    log_term = np.maximum(log_term, small_value_threshold)
 
+    Notes: More details on JOURNAL OF SYNCHROTRON RADIATION 23, 1462-1473 (2016)
+            - f(x) = norm * (gaussian_peak + charge_sharing_tail) / ((1 + α)²)
+    """
     A = ((1. - alpha)**2) / (sigma * np.sqrt(2. * np.pi))
     B = 4. * alpha * (1. - alpha)
     C = 4. * alpha**2
 
-    charge_sh_tail = (B - C * np.log1p(log_term)) * erfbox(x, ped, q, sigma)
+    charge_sh_tail = (
+        B - C * np.log1p((x - ped) / (q - ped))) * erfbox(x, ped, q, sigma)
     return norm * (charge_sh_tail + gauss(x, A, q, sigma)) / ((1. + alpha)**2)
 
 
+def double_peak(x, ped, q_a, sigma_a, alpha, norm_a, q_b, sigma_b,  norm_b):
+    """
+    Model the detector response for two overlapping peaks with charge sharing.
+
+    This function combines two charge sharing models to represent two 
+    overlapping peaks in the detector response.
+    """
+    k_a = charge_sharing(x, ped, q_a, sigma_a, alpha, norm_a)
+    k_b = charge_sharing(x, ped, q_b, sigma_b, alpha, norm_b)
+    return k_a + k_b
+
+
 def set_fit_range(x, x1, x2):
+    """
+    Set the range of x values to be used in fitting.
+
+    This function determines the indices of x that fall within the
+    specified range [x1, x2].
+
+    Notes: If x2 <= x1, the function ensures at least two points are included
+            in the range. The returned x values are cast to np.float64 for 
+            higher precision in fitting.
+    """
     i1 = 0
     i2 = len(x)
     i = 0
@@ -389,7 +412,7 @@ def set_fit_range(x, x1, x2):
 
 
 def fit_charge_sharing(
-    x, y, yerr, sigma0, n_sigma, ratio, alpha0=0.3
+    x, y, yerr, initial_sigma, n_sigma, ratio, alpha0=0.3
 ):
     """
     Perform charge sharing fit using iminuit optimization.
@@ -401,12 +424,13 @@ def fit_charge_sharing(
         x (array-like): Input charge values
         y (array-like): Observed counts or intensities
         yerr (array-like): Errors on y values
-        sigma0 (float): Initial guess for peak width
+        initial_sigma (float): Initial guess for peak width
         n_sigma (float): Number of sigmas for threshold calculation
             (not used in this implementation)
         ratio (float): Ratio parameter (not used in this implementation)
         alpha0: Initial guess for alpha
-    Returns:AC
+
+    Returns:
         tuple: (q, sigma, chi2ndf, alpha)
             q (float): Fitted peak position
             sigma (float): Fitted peak width
@@ -422,15 +446,14 @@ def fit_charge_sharing(
     norm = np.sum(y) * (x[1] - x[0])
 
     # Use _peak_position function to find initial q0
-    _peaks, _ = _peak_position(x, y, thr=n_sigma*sigma0, ratio=ratio)
+    _peaks, _ = _peak_position(x, y, thr=n_sigma*initial_sigma, ratio=ratio)
     if len(_peaks) > 0:
         q0 = np.min(x[_peaks])
     else:
         return -1, -1, -1, -1
 
-    x_fit, i1, i2 = set_fit_range(x, 0.5 * q0, q0 + 2. * sigma0)
+    x_fit, i1, i2 = set_fit_range(x, 0.5 * q0, q0 + 2. * initial_sigma)
 
-    x_fit = x_fit
     y_fit = y[i1:i2]
     yerr_fit = yerr[i1:i2]
 
@@ -441,12 +464,12 @@ def fit_charge_sharing(
 
     m = Minuit(
         cost_function,
-        ped=0., q=q0, sigma=sigma0, alpha=alpha0, norm=norm,
-        error_ped=0.1, error_q=0.1*q0, error_sigma=0.1*sigma0,
+        ped=0., q=q0, sigma=initial_sigma, alpha=alpha0, norm=norm,
+        error_ped=0.1, error_q=0.1*q0, error_sigma=0.1*initial_sigma,
         error_alpha=0.1, error_norm=0.1*norm,
         fix_ped=True,
-        limit_q=(q0 - sigma0, q0 + sigma0),
-        limit_sigma=(0.1 * sigma0, 2. * sigma0),
+        limit_q=(q0 - initial_sigma, q0 + initial_sigma),
+        limit_sigma=(0.1 * initial_sigma, 2. * initial_sigma),
         limit_alpha=(0.01 * alpha0, 1.),
         limit_norm=(np.sqrt(0.1 * norm), 3. * norm),
         errordef=1,  # for least squares cost function
@@ -454,19 +477,18 @@ def fit_charge_sharing(
     )
 
     m.migrad()
-    m.hesse()
 
     if m.get_fmin().is_valid:
         q = m.values['q']
         sigma = m.values['sigma']
         alpha = m.values['alpha']
-        chi2ndf = m.fval / (len(x) - len(m.values))
+        chi2ndf = m.fval / (len(x_fit) - len(m.values))
     else:
         q, sigma, chi2ndf, alpha = -1000, -1000, -1000, -1000
     return q, sigma, chi2ndf, alpha
 
 
-def fit_double_charge_sharing(x, y, yerr, sigma0, n_sigma, ratio):
+def fit_double_charge_sharing(x, y, yerr, initial_sigma, n_sigma, ratio):
     """
     Fits histogram with sum of two single photon functions with
     charge sharing tail.
@@ -475,9 +497,9 @@ def fit_double_charge_sharing(x, y, yerr, sigma0, n_sigma, ratio):
         x (array, float): x values
         y (array, float): y values
         yerr (array, float): errors of the y values
-        sigma0 (float): rough estimate of peak variance
+        initial_sigma (float): rough estimate of peak variance
         n_sigma (int): to calculate threshold of the peak finder as
-            thr = n_sigma * sigma0
+            thr = n_sigma * initial_sigma
         ratio (float): ratio parameter of the peak finder
 
     Returns:
@@ -487,14 +509,14 @@ def fit_double_charge_sharing(x, y, yerr, sigma0, n_sigma, ratio):
     alpha0 = 0.3
     norm = np.sum(y) * (x[1] - x[0])
 
-    _peaks, _ = _peak_position(x, y, thr=n_sigma*sigma0, ratio=ratio)
+    _peaks, _ = _peak_position(x, y, thr=n_sigma*initial_sigma, ratio=ratio)
     if len(_peaks) > 0:
         q0 = np.min(x[_peaks])
     else:
         return -1, -1, -1, -1
 
     q_b = 1.1 * q0
-    x_fit, i1, i2 = set_fit_range(x, 0.5 * q0, q_b + sigma0)
+    x_fit, i1, i2 = set_fit_range(x, 0.5 * q0, q_b + initial_sigma)
     y_fit = y[i1:i2]
     yerr_fit = yerr[i1:i2]
 
@@ -509,25 +531,25 @@ def fit_double_charge_sharing(x, y, yerr, sigma0, n_sigma, ratio):
 
     limit_alpha = (0.01, 1.)
     limit_norm_a = (np.sqrt(0.1 * norm), 2. * norm)
-    limit_q_b = (q_b - sigma0, q_b + sigma0)
-    limit_sigma = (0.1 * sigma0, 2. * sigma0)
+    limit_q_b = (q_b - initial_sigma, q_b + initial_sigma)
+    limit_sigma = (0.1 * initial_sigma, 2. * initial_sigma)
     limit_norm_b = (np.sqrt(0.1 * 0.2 * norm), 2 * 0.2 * norm)
 
     m = Minuit(
         cost_function,
         ped=0.,
         q_a=q0,
-        sigma_a=sigma0,
+        sigma_a=initial_sigma,
         alpha=alpha0,
         norm_a=norm,
         q_b=q_b,
-        sigma_b=sigma0,
+        sigma_b=initial_sigma,
         norm_b=norm,
-        error_ped=0.1, error_q_a=0.1*q0, error_sigma_a=0.1*sigma0,
+        error_ped=0.1, error_q_a=0.1*q0, error_sigma_a=0.1*initial_sigma,
         error_alpha=0.1, error_norm_a=0.1*norm,
-        error_q_b=0.1*q_b, error_sigma_b=0.1*sigma0,
+        error_q_b=0.1*q_b, error_sigma_b=0.1*initial_sigma,
         error_norm_b=0.1*norm,
-        limit_q_a=(q0 - sigma0, q0 + sigma0),
+        limit_q_a=(q0 - initial_sigma, q0 + initial_sigma),
         limit_sigma_a=limit_sigma,
         limit_alpha=limit_alpha,
         limit_norm_a=limit_norm_a,
@@ -540,19 +562,18 @@ def fit_double_charge_sharing(x, y, yerr, sigma0, n_sigma, ratio):
     )
 
     m.migrad()
-    m.hesse()
 
     if m.get_fmin().is_valid:
         q = m.values['q_a']
         sigma = m.values['sigma_a']
         alpha = m.values['alpha']
-        chi2ndf = m.fval / (len(x) - len(m.values))
+        chi2ndf = m.fval / (len(x_fit) - len(m.values))
     else:
         q, sigma, chi2ndf, alpha = -1000, -1000, -1000, -1000
     return q, sigma, chi2ndf, alpha
 
 
-def fit_gauss(x, y, yerr, sigma0, n_sigma, ratio):
+def fit_gauss(x, y, yerr, initial_sigma, n_sigma, ratio):
     """
     Fits histogram with a gaussian function
 
@@ -560,9 +581,9 @@ def fit_gauss(x, y, yerr, sigma0, n_sigma, ratio):
         x (array, float): x values
         y (array, float): y values
         yerr (array, float): errors of the y values
-        sigma0 (float): rough estimate of peak variance
+        initial_sigma (float): rough estimate of peak variance
         n_sigma (int): to calculate threshold of the peak finder as
-            thr = n_sigma * sigma0
+            thr = n_sigma * initial_sigma
         ratio (float): ratio parameter of the peak finder
 
     Returns:
@@ -570,15 +591,15 @@ def fit_gauss(x, y, yerr, sigma0, n_sigma, ratio):
         (last one alway == 0)
         all of them are kept for compatibility with the wrap around function
     """
-    norm = np.sum(y) * (x[1] - x[0])/np.sqrt(2.*np.pi*sigma0**2)
+    norm = np.sum(y) * (x[1] - x[0])/np.sqrt(2.*np.pi*initial_sigma**2)
 
-    _peaks, _ = _peak_position(x, y, thr=n_sigma*sigma0, ratio=ratio)
+    _peaks, _ = _peak_position(x, y, thr=n_sigma*initial_sigma, ratio=ratio)
     if len(_peaks) > 0:
         q0 = np.min(x[_peaks])
     else:
         return -1, -1, -1, -1
 
-    x_fit, i1, i2 = set_fit_range(x, q0 - sigma0, q0 + 2.*sigma0)
+    x_fit, i1, i2 = set_fit_range(x, q0 - initial_sigma, q0 + 2.*initial_sigma)
     y_fit = y[i1:i2]
     yerr_fit = yerr[i1:i2]
 
@@ -589,23 +610,22 @@ def fit_gauss(x, y, yerr, sigma0, n_sigma, ratio):
 
     m = Minuit(
         cost_function,
-        amp=norm, mean=q0, sigma=sigma0,
-        error_amp=0.1*norm, error_mean=0.1*sigma0, error_sigma=0.1*sigma0,
+        amp=norm, mean=q0, sigma=initial_sigma,
+        error_amp=0.1*norm, error_mean=0.1*initial_sigma, error_sigma=0.1*initial_sigma,
         limit_amp=(0.01*norm, 2.*norm),
-        limit_mean=(q0-sigma0, q0+sigma0),
-        limit_sigma=(0.1*sigma0, 3.*sigma0),
+        limit_mean=(q0-initial_sigma, q0+initial_sigma),
+        limit_sigma=(0.1*initial_sigma, 3.*initial_sigma),
         errordef=1,  # for least squares cost function
         print_level=0,
     )
 
     m.migrad()
-    m.hesse()
 
     if m.get_fmin().is_valid:
         q = m.values['mean']
         sigma = m.values['sigma']
         alpha = 0.
-        chi2ndf = m.fval / (len(x) - len(m.values))
+        chi2ndf = m.fval / (len(x_fit) - len(m.values))
     else:
         q, sigma, chi2ndf, alpha = -1000, -1000, -1000, -1000
     return q, sigma, chi2ndf, alpha
diff --git a/src/cal_tools/step_timing.py b/src/cal_tools/step_timing.py
index a68587dcbac336e9a85f7c1fafa5d44d9c823c11..1ce001c8c6cccc5965b320e11238b9362eebf494 100644
--- a/src/cal_tools/step_timing.py
+++ b/src/cal_tools/step_timing.py
@@ -17,12 +17,13 @@ class StepTimer:
             self.t0 = t
         self.t_latest = t
 
-    def done_step(self, step_name):
+    def done_step(self, step_name, print_step=True):
         """Record a step timing, since the last call to done_step() or start()
         """
         t = perf_counter()
         self.steps[step_name].append(t - self.t_latest)
-        print(f"{step_name}: {t - self.t_latest:.01f} s")
+        if print_step:
+            print(f"{step_name}: {t - self.t_latest:.01f} s")
         self.t_latest = t
 
     def timespan(self):