49 p_tel: conf.Param_tel, npts_force: int =
None):
50 """ Set the pyramid modulation amplitude
54 nwfs : (int): WFS index
56 ampli : (float) : new amplitude in units of lambda/D
58 p_wfss : (list of Param_wfs) : list of wfs parameters
60 p_tel : (Param_tel) : Telescope parameters
66 if npts_force
is None:
70 pyr_npts = int(np.ceil(int(2 * 2 * np.pi) / nFace) * nFace)
72 pyr_npts = int(np.ceil(int(ampli * 2 * np.pi) / nFace) * nFace)
76 pixsize = pwfs._qpixsize * CONST.ARCSEC2RAD
77 scale_fact = 2 * np.pi / pwfs._Nfft * (
78 pwfs.Lambda * 1e-6 / p_tel.diam) / pixsize * ampli
80 np.sin((np.arange(pyr_npts, dtype=np.float32)) * 2. * np.pi / pyr_npts)
82 np.cos((np.arange(pyr_npts, dtype=np.float32)) * 2. * np.pi / pyr_npts)
84 scale = pwfs.Lambda * 1e-6 / p_tel.diam * ampli * 180. / np.pi * 3600.
86 return cx, cy, scale, pyr_npts
89 def noise_cov(nw: int, p_wfs: conf.Param_wfs, p_atmos: conf.Param_atmos,
90 p_tel: conf.Param_tel):
91 """ Compute the diagonal of the noise covariance matrix for a SH WFS (arcsec^2)
92 Photon noise: (pi^2/2)*(1/Nphotons)*(d/r0)^2 / (2*pi*d/lambda)^2
93 Electronic noise: (pi^2/3)*(wfs.noise^2/N^2photons)*wfs.npix^2*(wfs.npix*wfs.pixsize*d/lambda)^2 / (2*pi*d/lambda)^2
99 p_wfs: (Param_wfs) : wfs settings
101 p_atmos: (Param_atmos) : atmos settings
103 p_tel: (Param_tel) : telescope settings
107 cov : (np.ndarray(ndim=1,dtype=np.float64)) : noise covariance diagonal
109 cov = np.zeros(2 * p_wfs._nvalid)
110 if (p_wfs.noise >= 0):
111 ind = np.where(p_wfs._isvalid.T)
112 flux = p_wfs._fluxPerSub[ind[1], ind[0]]
113 Nph = flux * p_wfs._nphotons
115 r0 = (p_wfs.Lambda / 0.5)**(6.0 / 5.0) * p_atmos.r0
117 sig = (np.pi ** 2 / 2) * (1 / Nph) * \
120 sig /= (2 * np.pi / (p_wfs.Lambda * 1e-6))**2
121 sig *= CONST.RAD2ARCSEC**2
124 Nd = (p_wfs.Lambda * 1e-6) * CONST.RAD2ARCSEC / p_wfs.pixsize
125 sigphi = (np.pi ** 2 / 3.0) * (1 / Nph ** 2) * (p_wfs.noise) ** 2 * \
126 Ns ** 2 * (Ns / Nd) ** 2
128 sigsh = sigphi / (2 * np.pi / (p_wfs.Lambda * 1e-6))**2
129 sigsh *= CONST.RAD2ARCSEC**2
131 cov[:len(sig)] = sig + sigsh
132 cov[len(sig):] = sig + sigsh
137 def comp_new_fstop(wfs: Sensors, n: int, p_wfs: conf.Param_wfs, fssize: float,
139 """ Compute a new field stop for pyrhr WFS
143 n : (int) : WFS index
145 wfs : (Param_wfs) : WFS parameters
147 fssize : (float) : field stop size [arcsec]
149 fstop : (string) : "square" or "round" (field stop shape)
151 fsradius_pixels = int(fssize / p_wfs._qpixsize / 2.)
152 if (fstop == scons.FieldStopType.ROUND):
154 focmask = util.dist(p_wfs._Nfft, xc=p_wfs._Nfft / 2. - 0.5,
155 yc=p_wfs._Nfft / 2. - 0.5) < (fsradius_pixels)
157 elif (p_wfs.fstop == scons.FieldStopType.SQUARE):
159 y, x = np.indices((p_wfs._Nfft, p_wfs._Nfft))
160 x -= (p_wfs._Nfft - 1.) / 2.
161 y -= (p_wfs._Nfft - 1.) / 2.
162 focmask = (np.abs(x) <= (fsradius_pixels)) * \
163 (np.abs(y) <= (fsradius_pixels))
166 msg =
"p_wfs " + str(n) +
". fstop must be round or square"
167 raise ValueError(msg)
171 pyr_focmask = focmask * 1.0
172 p_wfs._submask = np.fft.fftshift(pyr_focmask).astype(np.float32)
173 p_wfs_fssize = fssize
174 wfs.d_wfs[n].set_submask(p_wfs._submask)