Пример #1
0
def phyper_poisson(lam, beta, N, norm=True):
    """
    Bardwell, G. E., & Crow, E. L. (1964).
    A two-parameter family of hyper-Poisson distributions.
    Journal of the American Statistical Association, 59(305), 133-141.
    Formula (6)
    On the Hyper-Poisson Distribution and its
    Generalization with Applications
    Bayo H. Lawal
    Formulas (2.1, 2.2)    

    Parameters
    ----------
    lam : float
        Parameter 1.
    beta : float
        Parameter 2.
    N : int
        maximal photon number.

    Returns
    -------
    The photon-number distribution

    """
    def phi_function(beta, lam, N=100):
        k = np.arange(N)
        return np.sum(Γ(beta) / Γ(beta + k) * lam**k)

    n = np.arange(N)
    phi = phi_function(beta, lam)
    P = Γ(beta) / Γ(beta + n) * lam**n / phi
    return normalize(P) if norm else P
Пример #2
0
def qthermal_unpolarized(mean, dof, N, norm=True):
    """
    Дж. Гудмен, Статистическая оптика, ф-ла 9.2.29 при P = 0

    Parameters
    ----------
    mean : float
        Mean value of the distribution.
    dof : int
        Ration of measurement time to coherence time.
    N : int
        Maximal photocounts number.

    Returns
    -------
    np.ndarray
        Photounts distribution.

    """
    @np.vectorize
    def fsum(_m):
        k = np.arange(_m + 1)
        return np.sum(
            Γ(_m - k + dof) / (Γ(_m - k + 1) * Γ(dof)) * Γ(k + dof) /
            (Γ(k + 1) * Γ(dof)))

    m = np.arange(N)
    P = fsum(m) * (1 + 2 * dof / mean) ** (- m) * \
        (1 + mean / 2 / dof) ** (- 2 * dof)
    return normalize(P) if norm else P
Пример #3
0
def psqueezed_coherent1(ampl, sq_coeff, N, norm=True):
    vac = basis(N, 0)
    d = displace(N, ampl)
    s = squeeze(N, sq_coeff)
    print('Squeeze', np.exp(-2 * np.abs(sq_coeff)) / 4)
    P = d * s * vac
    return normalize(P) if norm else P
Пример #4
0
def mrec_maxent_pn(Q, qe: float, nmax: int = 0, max_order: int = 2):
    mmax = len(Q)
    if nmax == 0:
        nmax = mmax
    moments = imoms(Q, max_order, qe)
    P, _ = reconstruct(moments.astype(np.float64), rndvar=np.arange(nmax))
    return normalize(P)
Пример #5
0
def compensate(Q: np.ndarray, p_crosstalk: float) -> np.ndarray:
    """
    Remove crosstalk noise from photocounting statistics.
    We use model with 4 neighbors with saturation.

    See formula 2.21 in [1]


    Parameters
    ----------
    Q : iterable
        The photocounting statistics.
    p_crosstalk : float
        The probability of a single crosstalk event.

    Returns
    -------
    Qcorr : ndarray
        Denoised photocounting statistics.

    References
    ----------
    .. [1]
    Gallego, L., et al. "Modeling crosstalk in silicon photomultipliers."
    Journal of instrumentation 8.05 (2013): P05010.
    https://iopscience.iop.org/article/10.1088/1748-0221/8/05/P05010/pdf

    """
    N = len(Q)
    eps = total_pcrosstalk(p_crosstalk)
    Qcorr = np.zeros(N)
    Qcorr[0] = Q[0]
    Qcorr[1] = Q[1] / (1 - eps)
    for m in range(2, N):
        k = np.arange(1, m)
        c1 = (1 - eps)**-m
        c2 = np.sum(
            Qcorr[k] *
            np.vectorize(p_crosstalk_m, otypes=[float])(k, m, p_crosstalk))
        Qcorr[m] = c1 * (Q[m] - c2)

    return normalize(Qcorr)
Пример #6
0
def psqueezed_vacuum(r, theta, N, norm=True):
    """
    2-mode squeezed vacuum state

    Parameters
    ---------
    r : complex
        Pump parameter [0, 1]
    theta : float
        relative phase shift of two modes one by one
    N : int
        maximal photon number.

    Returns
    -------
        2-mode squeezed vacuum photon-number distribution
    """
    n = np.arange(N)
    distribution = np.tanh(r)**n / np.cosh(r) * (1 - n % 2)
    P = distribution**2
    return normalize(P) if norm else P
Пример #7
0
def qthermal_polarized(mean, dof, N, norm=True):
    """
    Дж. Гудмен, Статистическая оптика, ф-ла 9.2.24 

    Parameters
    ----------
    mean : float
        Mean value of the distribution.
    dof : int
        Ration of measurement time to coherence time.
    N : int
        Maximal photocounts number.

    Returns
    -------
    np.ndarray
        Photounts distribution.

    """
    m = np.arange(N)
    P = Γ(m + dof) / (Γ(m + 1) * Γ(dof)) * (1 + dof / mean)**(-m) * (
        1 + mean / dof)**(-dof)
    return normalize(P) if norm else P
Пример #8
0
def pcompound_poisson(mu: float, a: float, N: int, norm=True):
    """
    Bogdanov, Y. I., Bogdanova, N. A., Katamadze, K. G., Avosopyants,
    G. V., & Lukichev, V. F. (2016).
    Study of photon statistics using a compound Poisson distribution
    and quadrature measurements.
    Optoelectronics, Instrumentation and Data Processing, 52(5), 475-485.

    Formula (10)

    Parameters
    ----------
    mu : float
        mean value.
    a : float
        a parameter.
    N : int
        maximal photon number.
    norm : bool, optional
        Flag to normalization. The default is True.

    Returns
    -------
    The photon-number distribution

    """
    n = np.arange(N)
    if a > 0:
        P = (mu / a) ** n * Γ(a + n) / Γ(a) / \
            Γ(n + 1) / (1 + mu / a) ** (n + a)
    elif a < 0:
        if int(a) == a and mu == -a:
            P = pfock(-a, N)
        else:
            P = (mu / a) ** n / (beta(a - 1, n + 1) * (a - 1)) / \
                (1 + mu / a) ** (n + a)
    return normalize(P) if norm else P
Пример #9
0
def pthermal_photonadd(mean, photonadd, N, norm=True):
    """
    Barnett, Stephen M., et al.
    "Statistics of photon-subtracted and photon-added states."
    Physical Review A 98.1 (2018): 013809.

    Parameters
    ----------
    mean : float
        mean of distribution.
    photonadd : int
        count of added photons.
    N : int
        maximal photon number.

    Returns
    -------
    The photon-number distribution

    """
    n = np.arange(N)
    P = mean**(n - photonadd) / (1 + mean)**(n + 1) * binom(n, photonadd)
    P[:photonadd] = 0
    return normalize(P) if norm else P
Пример #10
0
def pfock(mean, N, norm=True):
    if np.floor(mean) != mean:
        raise ValueError(f'Fock state energy must be int, not {mean}')
    P = np.zeros(N)
    P[mean] = 1
    return normalize(P) if norm else P
Пример #11
0
def pthermal(mean, N, norm=True):
    P = pthermal_polarized(mean, 1, N)
    return normalize(P) if norm else P
Пример #12
0
def ppoisson(mean, N, norm=True):
    P = poisson.pmf(np.arange(N), mean)
    return normalize(P) if norm else P
Пример #13
0
def pthermal_polarized(mean, dof, N, norm=True):
    p = 1 - mean / (dof + mean)
    P = nbinom.pmf(np.arange(N), dof, p)
    return normalize(P) if norm else P
Пример #14
0
def hist2Q(hist: np.ndarray, bins: np.ndarray, discrete: int,
           method: str = 'sum', threshold: float = 1,
           peak_width: float = 1, down_width: float = 1,
           manual_zero_offset: int = 0,
           plot: bool = False, logplot: bool = False, *args, **kwargs) -> np.ndarray:
    """
    Build photocounting statistics from an experimental histogram
    by gaussian-hermite polynoms or simple sum

    Parameters
    ----------
    hist : ndarray
        Experimental histogram values.
    bins : ndarray
        Experimental histogram bins.
    discrete : int
        The amplitude of single photocount pulse in points.
    manual_zero_offset: int, optional
        Offset for calculate zero-photon probability in presence of non-zero noise pulses (in points).
        The default is 0.
    threshold : float, optional
        Minimal number of events to find histogram peak.
        The default is 1.
    peak_width : float, optional
        The width of peaks.
        It must be greater than 1 if the histogram is made by oscilloscope or 'max' method.
        The default is 1.
    down_width : float, optional
        The width of downs.
        It must be greater than 1 if the histogram is made by oscilloscope or 'max' method.
        The default is 1.
    plot : bool, optional
        Flag to plot hist and results of find_peaks.
        The default is False.
    logplot : bool
        Enable log yscale for histogram plotting.
        The default is False.        
    method : {'sum', 'fit', 'manual'}
        Method of the photocounting statistics construction.
            'sum' is a simple summation between minimums of the histogram

            'fit' is a gauss-hermite function fitteing like in [1]

            'manual' is a simple summation of intervals with fixed length. 

    Returns
    -------
    Q : ndarray
        The photocounting statistics.

    References
    ----------
    .. [1]
    Ramilli, Marco, et al. "Photon-number statistics with silicon photomultipliers."
    JOSA B 27.5 (2010): 852-862.

    """
    if method != 'manual':
        discrete = int(discrete * 0.9)
        downs, _ = find_peaks(-hist, distance=discrete, width=down_width)
        downs = np.append([0], downs)

        peaks, _ = find_peaks(np.concatenate(([0], hist)), threshold=threshold, distance=discrete,
                              width=peak_width, plateau_size=(0, 10))
        peaks -= 1

        if peaks == []:
            raise ValueError(
                'Histogram peaks were not found with given settings')

        if plot:
            plt.scatter(bins[peaks], hist[peaks])
            plt.scatter(bins[downs], hist[downs])

    if method == 'manual':
        Q = []
        peaks = np.arange(manual_zero_offset, len(bins), discrete)

        for p in peaks:
            if p == manual_zero_offset:
                low = 0
            else:
                low = int(max(0, p - discrete // 2))
            top = int(min(p + discrete // 2, len(hist) - 1))
            Q.append(np.sum(hist[low:top]))

            if plot:
                plt.axvline(bins[low], linestyle=':', color='black')
                plt.axvline(bins[top], linestyle=':', color='black')

        if top != len(hist) - 1:
            Q.append(sum(hist[top:]))

    elif method == 'sum':
        Q = construct_q_sum(hist, peaks, downs)
    elif method == 'fit':
        Q = construct_q_fit(hist, bins, peaks, downs)

    if plot:
        plt.plot(bins, hist)
        plt.xlabel('Amplitude, V')
        plt.ylabel("Events' number")
        if logplot:
            plt.yscale('log')
        plt.show()

    return normalize(Q)