def update(self, arr, mask=None):
        """
        update moving average (and variance) with new ndarray
        (of the same shape as the init array) and an optional mask
        """
        if mask is not None:
            refI = np.logical_and(mask, self.n == 0)
        else:
            refI = self.n == 0
        if refI.any():
            # fill areas of the reference array that where empty before
            # create initial average value:
            self.avg[refI] = arr[refI]
        # the density of the marked array increases by one:
        self.n[mask] += 1
        # only consider filled areas:
        if mask is not None:
            i = mask  # np.logical_and(mask,self.n>0)
        else:
            i = self.n > 0
        # current value:
        xn = arr[i]
        # initial value:
        x0 = self.avg[i]
        n = self.n[i]
        # calculate the new average:
        new_Avg = self.avg[i] + ((xn - x0) / n)

        if self.var is not None:
            t = (xn - new_Avg + x0 - self.avg[i]) * (xn - x0) / (n - 1)
            t = np.nan_to_num(t)
            self.var[i] += t

        # assign the new average now to remain the old average
        # for calculating variance above:
        self.avg[i] = new_Avg
update moving average (and variance) with new ndarray
        (of the same shape as the init array) and an optional mask