def test_nu_lambda(self): """ Check that Bnu(nu, Te) * c/lmbda = Blmbda(lmbda, Te) """ nu = cst.c/lmbda x0 = rad.planck(lmbda*1.0e9, Te_eV, 'lambda') x1 = cst.c/lmbda**2 * rad.planck(nu, Te_eV, 'nu') assert_allclose(x0, x1)
def test_nu_lambda(self): """ Check that Bnu(nu, Te) * c/lmbda = Blmbda(lmbda, Te) """ nu = cst.c / lmbda x0 = rad.planck(lmbda * 1.0e9, Te_eV, 'lambda') x1 = cst.c / lmbda**2 * rad.planck(nu, Te_eV, 'nu') assert_allclose(x0, x1)
def plot_2D_map(fig, op, temp_val): from matplotlib.colors import LogNorm from hedp.rad import planck ax = [plt.subplot(1,3,idx+1) for idx in range(3)] groups = op[0]['groups'] x = op[0]['rho'] y = op[0]['temp'] X, Y = np.meshgrid(x, y, indices='ij') Bnu = planck(groups[:-1], temp_val, 'nu_eV') Bnu /= np.sum(Bnu) Bnu_arr = np.tile(Bnu, (len(x), len(y))).reshape(op[0]['opp_mg'].shape) plt.suptitle('Opacity comparaison for a black body radiation at {0:.1f} eV'.format(temp_val)) def norm(a,b): return np.fmax(a/b,b/a) - 1.0 for var_idx, var in enumerate(['opp_mg', 'opr_mg', 'eps_mg']): err = norm(op[0][var], op[1][var]) err = (err* Bnu_arr).sum(axis=-1) cs = ax[var_idx].pcolormesh(X, Y, err, norm=LogNorm(vmin=0.1, vmax=1e4)) cb = plt.colorbar(cs, ax=ax[var_idx]) ax[var_idx].set_title('Relative error for {0}'.format(var.replace('_','\_'))) for axi in ax: axi.set_xscale('log') axi.set_yscale('log') axi.set_xlim(x.min(),x.max()) axi.set_ylim(y.min(),y.max()) axi.set_xlabel(r'$\rho$ [g.cm$^{-3}$]') axi.set_ylabel(r'Te [eV]') return fig
def test_iplanck(self): """ Check that iBlambda(lmbda, Blambda(lmbda, x)) = x """ Flux = rad.planck(lmbda * 1.0e9, Te_eV, 'lambda') Flux = Flux * 1.0e-9 #to W.m⁻².sr⁻¹.nm⁻¹ Tout = rad.iplanck(lmbda * 1.0e9, Flux) assert_allclose(Tout, Te_eV)
def test_iplanck(self): """ Check that iBlambda(lmbda, Blambda(lmbda, x)) = x """ Flux = rad.planck(lmbda*1.0e9, Te_eV, 'lambda') Flux = Flux*1.0e-9 #to W.m⁻².sr⁻¹.nm⁻¹ Tout = rad.iplanck(lmbda*1.0e9, Flux) assert_allclose(Tout, Te_eV)
def _se_calibration_goi(lmbda, F, transmission, detectorsize, gain, timewindow, tele=None, method='explicit'): """ Compute the calibration for a streaked self emission system. This function calculates the number of electrons ejected by the photocathode in a SOP configuration. Parameters: ----------- - lmbda [ndarray]: wavelenght (nm) array - F [float]: F number of the first lens - gain [float]: Gain of the GOI - timewindow [float]: Time window [s] - transmission [ndarray]: Total transmission of the optical system, including the filter (same shape as the nu) - detectorsize [float] Size of a pixel in spatial direction in μm Returns: -------- - Flux_norm [float]: photon flux (W.m⁻².sr⁻¹.nm⁻¹.counts⁻¹) """ solid_angle = np.pi / (4 * F**2) # solid angle of the first optics in sr # Données Sophie [Joule/count] GOI S20 K_Jcounts = 1.2e-19 # J K_Jcounts = K_Jcounts / (goi_sens(gain, "S20") / goi_sens(5, "S20")) # Surface on the target for 1px (m^2) S_px = (detectorsize * 1e-6)**2 # Transmission at 420 nm # Approximate width of the filter system ( ~10 nm): if method == 'explicit': Tr_max = np.max(transmission) dlmbda = np.abs(np.trapz(transmission, lmbda) / Tr_max) # nm Flux_coeff = K_Jcounts / (S_px * solid_angle * timewindow * Tr_max * dlmbda) return Flux_coeff elif method == 'implicit': K = (S_px * solid_angle * timewindow) / K_Jcounts counts = K * np.trapz( transmission[np.newaxis,:]\ *planck(lmbda[np.newaxis,:], tele[:,np.newaxis]), dx=np.diff(lmbda*1e-9)[0], axis=1) return counts
def test_planck_integral(self): """ Check that \int Bnu dθdφdν = σT⁴ """ Te = 200.0 # quad integration fails if the temperature is too big Te_eV = Te / eV2K sigma = physical_constants['Stefan-Boltzmann constant'][0] x0 = sigma * Te**4 x1, x1_err = quad(lambda x: rad.planck(x, Te_eV, 'nu'), 0, 1.0e17) # 1e17 Hz max should be well enough for 200 eV # np.infinty doesn't work as integration bound (I probably don't # know enough about quad parameters) assert_allclose(x0, x1 * np.pi)
def test_planck_integral(self): """ Check that \int Bnu dθdφdν = σT⁴ """ Te = 200.0 # quad integration fails if the temperature is too big Te_eV = Te/eV2K sigma = physical_constants['Stefan-Boltzmann constant'][0] x0 = sigma*Te**4 x1, x1_err = quad(lambda x: rad.planck(x, Te_eV, 'nu'), 0, 1.0e17) # 1e17 Hz max should be well enough for 200 eV # np.infinty doesn't work as integration bound (I probably don't # know enough about quad parameters) assert_allclose(x0, x1*np.pi)
def _se_calibration_goi(lmbda, F, transmission, detectorsize, gain, timewindow, tele=None, method="explicit"): """ Compute the calibration for a streaked self emission system. This function calculates the number of electrons ejected by the photocathode in a SOP configuration. Parameters: ----------- - lmbda [ndarray]: wavelenght (nm) array - F [float]: F number of the first lens - gain [float]: Gain of the GOI - timewindow [float]: Time window [s] - transmission [ndarray]: Total transmission of the optical system, including the filter (same shape as the nu) - detectorsize [float] Size of a pixel in spatial direction in μm Returns: -------- - Flux_norm [float]: photon flux (W.m⁻².sr⁻¹.nm⁻¹.counts⁻¹) """ solid_angle = np.pi / (4 * F ** 2) # solid angle of the first optics in sr # Données Sophie [Joule/count] GOI S20 K_Jcounts = 1.2e-19 # J K_Jcounts = K_Jcounts / (goi_sens(gain, "S20") / goi_sens(5, "S20")) # Surface on the target for 1px (m^2) S_px = (detectorsize * 1e-6) ** 2 # Transmission at 420 nm # Approximate width of the filter system ( ~10 nm): if method == "explicit": Tr_max = np.max(transmission) dlmbda = np.abs(np.trapz(transmission, lmbda) / Tr_max) # nm Flux_coeff = K_Jcounts / (S_px * solid_angle * timewindow * Tr_max * dlmbda) return Flux_coeff elif method == "implicit": K = (S_px * solid_angle * timewindow) / K_Jcounts counts = K * np.trapz( transmission[np.newaxis, :] * planck(lmbda[np.newaxis, :], tele[:, np.newaxis]), dx=np.diff(lmbda * 1e-9)[0], axis=1, ) return counts
def _sop_calibration(lmbda, F, transmission, detectorsize, slitwidth, sweepspeed, tele=None, method='explicit'): """ Compute the calibration for a streaked self emission system. This function calculates the number of electrons ejected by the photocathode in a SOP configuration. Parameters: ----------- - lmbda [ndarray]: wavelenght (nm) array - F [float]: F number of the first lens - transmission [ndarray]: Total transmission of the optical system, including the filter (same shape as the nu) - detectorsize [float] Size of a pixel in spatial direction in μm - slitwidth [float] Size of the slit in px - sweepspeed Sweep speed of the streak [100ns, 50ns, etc]in pixel/ns - tele [ndarray]: plasma temperature [eV] Returns: -------- if method == 'explicit': - Flux_norm [float]: photon flux (W.m⁻².sr⁻¹.nm⁻¹.counts⁻¹) elif method == 'implicit': - counts [ndarray]: counts value on CCD of the same shape as counts with the temperature """ solid_angle = np.pi / (4 * F**2) # solid angle of the first optics in sr # Données Tommaso [Joule/count] Streak S20 K_Jcounts = 6.6434e-18 # # Normalize with streak sensitivity for the given wavelenght mstreak_sens = lambda lmbda: streak_sens(lmbda, 'hamamatsu', 'S20_2')[0] K_Jcounts = K_Jcounts # Surface on the target for 1px (m^2) S_px = (detectorsize * 1e-6)**2 #tr_itp = interp1d(lmbda, transmission) # Transmission at 420 nm # Time spend on each pxl: # Streak slit 100um = 8px pour calibre : # This remains approximately true for this polar experiment t_px = slitwidth * sweepspeed / 1024. # Approximate width of the filter system ( ~10 nm): if method == 'explicit': max_idx = np.argmax(transmission) Tr_max = transmission[max_idx] #tr_itp(420.) lmbda_max = lmbda[max_idx] dlmbda = np.abs(np.trapz(transmission, lmbda) / Tr_max) # nm Flux_coeff = K_Jcounts/(S_px * solid_angle * t_px * Tr_max * dlmbda *\ mstreak_sens(lmbda_max)/mstreak_sens(532.)) return Flux_coeff elif method == 'implicit': K = (S_px * solid_angle * t_px) / K_Jcounts counts = K * np.trapz( (transmission*mstreak_sens(lmbda)/mstreak_sens(532.))[np.newaxis,:]\ *planck(lmbda[np.newaxis,:], tele[:,np.newaxis]), dx=np.diff(lmbda*1e-9)[0], axis=1) return counts
def _sop_calibration(lmbda, F, transmission, detectorsize, slitwidth, sweepspeed, tele=None, method="explicit"): """ Compute the calibration for a streaked self emission system. This function calculates the number of electrons ejected by the photocathode in a SOP configuration. Parameters: ----------- - lmbda [ndarray]: wavelenght (nm) array - F [float]: F number of the first lens - transmission [ndarray]: Total transmission of the optical system, including the filter (same shape as the nu) - detectorsize [float] Size of a pixel in spatial direction in μm - slitwidth [float] Size of the slit in px - sweepspeed Sweep speed of the streak [100ns, 50ns, etc]in pixel/ns - tele [ndarray]: plasma temperature [eV] Returns: -------- if method == 'explicit': - Flux_norm [float]: photon flux (W.m⁻².sr⁻¹.nm⁻¹.counts⁻¹) elif method == 'implicit': - counts [ndarray]: counts value on CCD of the same shape as counts with the temperature """ solid_angle = np.pi / (4 * F ** 2) # solid angle of the first optics in sr # Données Tommaso [Joule/count] Streak S20 K_Jcounts = 6.6434e-18 # # Normalize with streak sensitivity for the given wavelenght mstreak_sens = lambda lmbda: streak_sens(lmbda, "hamamatsu", "S20_2")[0] K_Jcounts = K_Jcounts # Surface on the target for 1px (m^2) S_px = (detectorsize * 1e-6) ** 2 # tr_itp = interp1d(lmbda, transmission) # Transmission at 420 nm # Time spend on each pxl: # Streak slit 100um = 8px pour calibre : # This remains approximately true for this polar experiment t_px = slitwidth * sweepspeed / 1024.0 # Approximate width of the filter system ( ~10 nm): if method == "explicit": max_idx = np.argmax(transmission) Tr_max = transmission[max_idx] # tr_itp(420.) lmbda_max = lmbda[max_idx] dlmbda = np.abs(np.trapz(transmission, lmbda) / Tr_max) # nm Flux_coeff = K_Jcounts / ( S_px * solid_angle * t_px * Tr_max * dlmbda * mstreak_sens(lmbda_max) / mstreak_sens(532.0) ) return Flux_coeff elif method == "implicit": K = (S_px * solid_angle * t_px) / K_Jcounts counts = K * np.trapz( (transmission * mstreak_sens(lmbda) / mstreak_sens(532.0))[np.newaxis, :] * planck(lmbda[np.newaxis, :], tele[:, np.newaxis]), dx=np.diff(lmbda * 1e-9)[0], axis=1, ) return counts