def noiseg2_by_mean(P, nmean): """ Calculate :math:`g^{(2)}` value of the noise distribution for given noised distribution and mean value of the noise distribution. Parameters ---------- P : array_like Noised probability distribution. nmean : float Expected noise mean. Returns ------- g2 : float Expected :math:`g^{(2)}` value of the noise distribution. Notes ----- Analytical formula of the function is: .. math:: g^{(2)}(E)=\\frac{M[P]^2g^{(2)}(P) - M[L]^2 - 2M[L]M[E]}{M[E]^2} Here :math:`E` is a noise distribution, :math:`L` is a poisson distribution, :math:`P` is a noised distribution, :math:`M[P]` is a mean of P .. math:: g^{(2)}(P)=\\dfrac{M^2[P] - M[P]}{M[P]^2} """ pmean = mean(P) - nmean return (mean(P)**2 * g2(P) - pmean**2 - 2 * nmean * pmean) / nmean**2
def thermalnoise_mean(P): """ Calculate mean value of the noise thermal distribution. Convolution of this distribution and a poisson distributiob is optimal in the sense of minimal discrepancy Parameters ---------- P : array_like Noised probability distribution. Returns ------- nmean : float Mean value of the thermal distribution. """ N = len(P) def opt(x): return 1 - \ fidelity(p_convolve(ppoisson(x[0], N), pthermal(x[1], N)), P) res = brute(opt, [(0, mean(P)), (0.0, mean(P))], Ns=100, full_output=True) smean, nmean = res[0] fval = res[1] info("Optimum thermal noise mean found with discrepancy {0}".format(fval)) return nmean
def noisemean_by_g2(P, noise_g2): """ Calculate mean value of the noise distribution for given noised distribution and :math:`g^{(2)}` value of the noise distribution. Parameters ---------- P : array_like Noised probability distribution. noise_g2 : float Expected :math:`g^{(2)}` value of the noise distribution. Returns ------- mean Expected noise mean. Notes ----- Analytical formula of the function is: .. math:: M[E]=M[P]\\sqrt{\\frac{g^{(2)}(P) - 1}{g^{(2)}(E) - 1}} Here :math:`E` is a noise distribution, :math:`P` is a noised distribution, :math:`M[P]` is a mean of P .. math:: g^{(2)}(P)=\\dfrac{M^2[P] - M[P]}{M[P]^2} """ return np.sqrt((g2(P) - 1) / (noise_g2 - 1)) * mean(P)
def denoiseopt(dnmodel, mean_lbound=0, mean_ubound=0, g2_lbound=0, g2_ubound=0, eps_tol=0, solver_name='ipopt', solver_path='', save_all_nondom_x=False, plot=False, save_all_nondom_y=False, disp=False): """ Interface to epsilon-constrained algorithm Made to denoise photon-number or photounting statistics from the coherent background. It is usable for recovering spectrum of fluctuations, excess noise or single-photon signal. Parameters ---------- dnmodel : qpip.denoise.DenoisePBaseModel A model of the problem to solve. mean_lbound : float, optional Minimal possible value of noise's mean. The default is 0 and ignored. Also ignored if g2 bounds exist. mean_ubound : float, optional Maximal possible value of noise's mean. The default is 0 and ignored. Also ignored if g2 bounds exist. g2_lbound : float, optional Minimal possible value of noise's g2. The default is 0 and ignored. Also ignored if mean bounds exist. g2_ubound : float, optional Maximal possible value of noise's g2. The default is 0 and ignored. Also ignored if mean bounds exist. solver_name : str, optional Solver to solve the problem. The default is ipopt if installed. solver_path : str, optional Path to the solver executable eps_tol : float, optional Tolarance of additional variables to finish iterations. The default is 0. save_all_nondom_x : bool, optional Save all nondominate solutions in output. The default is False. save_all_nondom_y : bool, optional Save y vector values for all nondominate solutions. The default is False. disp : bool, optional Display calculation progress. Messages have following format: 'iteration number' 'status (1 is success, 0 is fail)' ['discrepancy', 'noise_mean', 'negentropy', 'noise_g2'] The default is False. plot : bool, optional Plot dependency of vars from an iteration number after the end of calculations. The default is False. Returns ------- res : scipy.optimize.OptimizeResult see help(qpip.epscon.iterate). """ if g2(dnmodel.P) < 1: warn( 'g2 of the given distribution is less than 1. Algorithm can not use g2 and mean bounds.', RuntimeWarning, __file__, 171) solver = SolverFactory(solver_name, executable=solver_path, solver_io="nl") if solver_path: solver.executable = solver_path y_vars = ['discrepancy', 'noise_mean', 'negentropy', 'noise_g2'] x_var = 'p_noise' if mean_ubound * g2_ubound or mean_ubound * g2_lbound or mean_lbound * g2_ubound or mean_lbound * g2_lbound: mean_ubound = 0 mean_lbound = 0 warn( 'It is not possible to set g2 and mean bounds together. Mean bounds are ignored.', RuntimeWarning, __file__, 101) if mean_ubound: dnmodel.c_low_g2 = Constraint( expr=dnmodel.noise_g2 >= noiseg2_by_mean(dnmodel.P, mean_ubound)) dnmodel.c_top_mean = Constraint(expr=dnmodel.noise_mean <= mean_ubound) if mean_lbound: dnmodel.c_top_g2 = Constraint( expr=dnmodel.noise_g2 <= noiseg2_by_mean(dnmodel.P, mean_lbound)) dnmodel.c_low_mean = Constraint(expr=dnmodel.noise_mean >= mean_lbound) if g2_ubound: dnmodel.c_top_g2 = Constraint(expr=dnmodel.noise_g2 <= g2_ubound) dnmodel.c_low_mean = Constraint( expr=dnmodel.noise_mean >= noisemean_by_g2(dnmodel.P, g2_ubound)) if g2_lbound: dnmodel.c_low_g2 = Constraint(expr=dnmodel.noise_g2 >= g2_lbound) dnmodel.c_top_mean = Constraint( expr=dnmodel.noise_mean <= noisemean_by_g2(dnmodel.P, g2_lbound)) mean_bound = mean(dnmodel.P) if not mean_ubound else mean_ubound noise_bounds = [[ max(0, mean_lbound), -np.log(len(dnmodel.NSET)), max(1, g2_lbound) ], [mean_bound, 0, max(20, g2_ubound)]] res = iterate(dnmodel, solver, y_vars, x_var, eps_bounds=noise_bounds, eps_tol=eps_tol, save_all_nondom_x=save_all_nondom_x, save_all_nondom_y=save_all_nondom_y, disp=disp) info('Optimization ended in %d iterations with eps_tol %.1e' % (res.nit, eps_tol)) info('Status "{0}", "{1}"'.format(*res.status)) if plot and res.nit > 1: for i in lrange(y_vars): plt.plot([e[i] for e in res.ndy], label=y_vars[i]) plt.legend(frameon=False) plt.show() return res
def find_pcrosstalk(Q: np.ndarray, PDE: float, N: int, mtype: str = 'binomial', n_cells: int = 0, Ns: int = 100, min_pct: float = 0, max_pct: float = 0.1): """ Brute searching of crosstalk probability by optimizing of g2 difference from noised data and noised poisson photocounting statistics. We use model with 4 neighbors with saturation. See [1] Parameters ---------- Q : iterable Experimental photocounting statistics of a laser source. PDE : float PDE of the detector. N : int Size of poisson photon-number statistics. mtype : {'binomial', 'subbinomial'}, optional Type of the detector: ideal is binomial, realistic is subbinomial, but in the most of applications one can consider the detector as binomial The default is 'binomial'. n_cells : TYPE, optional Number of photocounting cells in the subbinomial case. The default is 0. Ns : int, optional Size of calculation grid of brute function. The default is 100. Returns ------- p_ct: float The probability of a single crosstalk event. res: OptimizeResult See scipy.optimize.brute description. res.x0 consists of optimal p_crosstalk and optimal poisson photon-number distribution p_crosstalk is in res.x0[0] 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 """ res = brute( optctp, ([min_pct, max_pct], [mean(Q) / PDE * 0.9, mean(Q) / PDE * 1.1]), args=(Q, PDE, N, mtype, n_cells), Ns=Ns, full_output=True, workers=-1) info("P_ct = {r[0][0]}, Δg(2) = {r[1]}".format(r=res)) return res[0][0], OptimizeResult(x=res[0], fval=res[1], grid=res[2], Jout=res[3])
def g2_regularized(W, moms, Q, qe, *args): moms = np.append(moms, [g2(Q) * mean(Q)**2 / qe**2]) n = np.arange(W.shape[1]) W = np.vstack((W, n * (n - 1))) return W, moms