You can model the saturated gaussian, fit the data with the model, and recover the original gaussian with the fitting parameter.
Here is an example:
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import minimize
from numba import njit
@njit
def get_model(mu_x, mu_y, sig_x, sig_y, amp, cutoff, image_size):
"""
simulate a 2D gaussian were the value higher than cutoff
were saturated.
"""
dom_x = -1 / 2 / sig_x ** 2
dom_y = -1 / 2 / sig_y ** 2
result = np.empty(image_size)
for x in range(image_size[0]):
for y in range(image_size[1]):
gx = (x - mu_x)**2 * dom_x
gy = (y - mu_y)**2 * dom_y
g = amp * np.exp(gx + gy)
g = min(g, cutoff)
result[x, y] = g
return result
def cost(args, data):
model = get_model(*args, data.shape)
return np.power(model - data, 2).sum()
img = get_model(25, 25, 10, 5, 300, 255, (70, 70))
result = minimize(
cost, x0=(25, 25, 1, 1, 255, 255),
args=(img)
)
fit = get_model(*result.x, img.shape)
gauss = get_model(
*result.x[:-1],
cutoff=np.inf, # set cutoff to inf == no saturation
image_size=img.shape
)
plt.figure(figsize=(10, 4))
plt.subplot(131).imshow(img, vmin=0, vmax=300)
plt.title("data")
plt.subplot(132).imshow(fit, vmin=0, vmax=300)
plt.title("fitting result")
plt.subplot(133).imshow(gauss, vmin=0, vmax=300)
plt.title("gaussian from fit")
plt.tight_layout()
plt.show()