# Path: imgProcessor/camera/NoiseLevelFunction.py
# def oneImageNLF(img, img2=None, signal=None):
#     '''
#     Estimate the NLF from one or two images of the same kind
#     '''
#     x, y, weights, signal = calcNLF(img, img2, signal)
#     _, fn, _ = _evaluate(x, y, weights)
#     return fn, signal
# 
# Path: imgProcessor/filters/removeSinglePixels.py
# @jit(nopython=True)
# def removeSinglePixels(img):
#     '''
#     img - boolean array
#     remove all pixels that have no neighbour
#     '''
# 
#     gx = img.shape[0]
#     gy = img.shape[1]
# 
#     for i in range(gx):
#         for j in range(gy):
# 
#             if img[i, j]:
# 
#                 found_neighbour = False
#                 for ii in range(max(0, i - 1), min(gx, i + 2)):
#                     for jj in range(max(0, j - 1), min(gy, j + 2)):
# 
#                         if ii == i and jj == j:
#                             continue
# 
#                         if img[ii, jj]:
#                             found_neighbour = True
#                             break
#                     if found_neighbour:
#                         break
# 
#                 if not found_neighbour:
#                     img[i, j] = 0
# 
# Path: imgProcessor/imgIO.py
# def imread(img, color=None, dtype=None):
#     '''
#     dtype = 'noUint', uint8, float, 'float', ...
#     '''
#     COLOR2CV = {'gray': cv2.IMREAD_GRAYSCALE,
#                 'all': cv2.IMREAD_COLOR,
#                 None: cv2.IMREAD_ANYCOLOR
#                 }
#     c = COLOR2CV[color]
#     if callable(img):
#         img = img()
#     elif isinstance(img, string_types):
#         #         from_file = True
#         #         try:
#         #             ftype = img[img.find('.'):]
#         #             img = READERS[ftype](img)[0]
#         #         except KeyError:
#         # open with openCV
#         # grey - 8 bit
#         if dtype in (None, "noUint") or np.dtype(dtype) != np.uint8:
#             c |= cv2.IMREAD_ANYDEPTH
#         img2 = cv2.imread(img, c)
#         if img2 is None:
#             raise IOError("image '%s' is not existing" % img)
#         img = img2
# 
#     elif color == 'gray' and img.ndim == 3:  # multi channel img like rgb
#         # cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) #cannot handle float64
#         img = toGray(img)
#     # transform array to uint8 array due to openCV restriction
#     if dtype is not None:
#         if isinstance(img, np.ndarray):
#             img = _changeArrayDType(img, dtype, cutHigh=False)
# 
#     return img


from scipy.ndimage.measurements import label
from imgProcessor.camera.NoiseLevelFunction import oneImageNLF
from imgProcessor.filters.removeSinglePixels import removeSinglePixels
from imgProcessor.imgIO import imread
from fancytools.math.MaskedMovingAverage import MaskedMovingAverage
import numpy as np

    .mask_STE   --> STE indices (only avail. if save_ste_indices=True)
    .noSTE      --> STE free average image
    '''

    def __init__(self, images, noise_level_function=None, nStd=4,
                 save_ste_indices=False, calcVariance=False, dtype=float):
        self.save_ste_indices = save_ste_indices

        i1 = imread(images[0], 'gray', dtype=dtype)
        i2 = imread(images[1], 'gray')

        self.mask_STE = None
        if save_ste_indices:
            self.mask_STE = np.zeros(shape=i1.shape, dtype=bool)

        self.mma = MaskedMovingAverage(shape=i1.shape,
                                       calcVariance=calcVariance,
                                       dtype=i1.dtype)

        # MINIMUM OF BOTH IMAGES:
        self.mma.update(np.min((i1, i2), axis=0))

        if noise_level_function is None:
            noise_level_function = oneImageNLF(self.mma.avg)[0]
        self.noise_level_function = noise_level_function
        self.threshold = noise_level_function(self.mma.avg) * nStd

        self.addImage(np.max((i1, i2), axis=0))

        for i in images[2:]:

# Path: imgProcessor/camera/NoiseLevelFunction.py
# def oneImageNLF(img, img2=None, signal=None):
#     '''
#     Estimate the NLF from one or two images of the same kind
#     '''
#     x, y, weights, signal = calcNLF(img, img2, signal)
#     _, fn, _ = _evaluate(x, y, weights)
#     return fn, signal
# 
# Path: imgProcessor/filters/removeSinglePixels.py
# @jit(nopython=True)
# def removeSinglePixels(img):
#     '''
#     img - boolean array
#     remove all pixels that have no neighbour
#     '''
# 
#     gx = img.shape[0]
#     gy = img.shape[1]
# 
#     for i in range(gx):
#         for j in range(gy):
# 
#             if img[i, j]:
# 
#                 found_neighbour = False
#                 for ii in range(max(0, i - 1), min(gx, i + 2)):
#                     for jj in range(max(0, j - 1), min(gy, j + 2)):
# 
#                         if ii == i and jj == j:
#                             continue
# 
#                         if img[ii, jj]:
#                             found_neighbour = True
#                             break
#                     if found_neighbour:
#                         break
# 
#                 if not found_neighbour:
#                     img[i, j] = 0
# 
# Path: imgProcessor/imgIO.py
# def imread(img, color=None, dtype=None):
#     '''
#     dtype = 'noUint', uint8, float, 'float', ...
#     '''
#     COLOR2CV = {'gray': cv2.IMREAD_GRAYSCALE,
#                 'all': cv2.IMREAD_COLOR,
#                 None: cv2.IMREAD_ANYCOLOR
#                 }
#     c = COLOR2CV[color]
#     if callable(img):
#         img = img()
#     elif isinstance(img, string_types):
#         #         from_file = True
#         #         try:
#         #             ftype = img[img.find('.'):]
#         #             img = READERS[ftype](img)[0]
#         #         except KeyError:
#         # open with openCV
#         # grey - 8 bit
#         if dtype in (None, "noUint") or np.dtype(dtype) != np.uint8:
#             c |= cv2.IMREAD_ANYDEPTH
#         img2 = cv2.imread(img, c)
#         if img2 is None:
#             raise IOError("image '%s' is not existing" % img)
#         img = img2
# 
#     elif color == 'gray' and img.ndim == 3:  # multi channel img like rgb
#         # cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) #cannot handle float64
#         img = toGray(img)
#     # transform array to uint8 array due to openCV restriction
#     if dtype is not None:
#         if isinstance(img, np.ndarray):
#             img = _changeArrayDType(img, dtype, cutHigh=False)
# 
#     return img


# Path: imgProcessor/features/SingleTimeEffectDetection.py
from scipy.ndimage.measurements import label
from imgProcessor.camera.NoiseLevelFunction import oneImageNLF
from imgProcessor.filters.removeSinglePixels import removeSinglePixels
from imgProcessor.imgIO import imread
from fancytools.math.MaskedMovingAverage import MaskedMovingAverage
import numpy as np

    .mask_STE   --> STE indices (only avail. if save_ste_indices=True)
    .noSTE      --> STE free average image
    '''

    def __init__(self, images, noise_level_function=None, nStd=4,
                 save_ste_indices=False, calcVariance=False, dtype=float):
        self.save_ste_indices = save_ste_indices

        i1 = imread(images[0], 'gray', dtype=dtype)
        i2 = imread(images[1], 'gray')

        self.mask_STE = None
        if save_ste_indices:
            self.mask_STE = np.zeros(shape=i1.shape, dtype=bool)

        self.mma = MaskedMovingAverage(shape=i1.shape,
                                       calcVariance=calcVariance,
                                       dtype=i1.dtype)

        # MINIMUM OF BOTH IMAGES:
        self.mma.update(np.min((i1, i2), axis=0))

        if noise_level_function is None:
            noise_level_function = oneImageNLF(self.mma.avg)[0]
        self.noise_level_function = noise_level_function
        self.threshold = noise_level_function(self.mma.avg) * nStd

        self.addImage(np.max((i1, i2), axis=0))

        for i in images[2:]:

            self.addImage(imread(i, 'gray'))
