Source code for common.instru.model_effect

'''
Created on 25 mars 2019

@author: colley APC/IN2P3/CNRS
'''

from common import add_path_data_ref_eclairs
from astropy.io import fits
import numpy as np
import matplotlib.pyplot as plt
import common.instru.array_convention as ac
import common.num.array_square_cell as asc
import scipy.stats as scs
import scipy.interpolate as sci



[docs]class ECLAIRsDetectorEffectDefault(object): def __init__(self): """Read ARF, IRF, RMF and return values/products or processing expected by ECPI .. warning:: 2015 version with old mask so **IRF isn't update**, ARF is in approximative percent format """ # default value path_arf = add_path_data_ref_eclairs("instru/ecl_rsp_0008_arf.fits") path_irf = add_path_data_ref_eclairs("instru/ecl_irf_0008_10keV.fits") path_rmf = add_path_data_ref_eclairs("instru/ecl_rsp_0008_rmf.fits") # ARF f_arf = fits.open(path_arf) arf = f_arf[1].data f_arf.close() # # TODO : revoir la ded open_surface dans prochain ARF avec le bon masque #r open_surface = arf["SPECRESP"].max()*1.01 self._arf_percent = arf["SPECRESP"]/open_surface # boundary channel self._boundary_chan = np.concatenate((arf["ENERG_LO"], np.array([arf["ENERG_HI"][-1]]))) self._channel = (arf["ENERG_LO"] + arf["ENERG_HI"])/2 a_step_channel = arf["ENERG_HI"] - arf["ENERG_LO"] self._step_channel = arf["ENERG_HI"][0] - arf["ENERG_LO"][0] assert np.allclose(a_step_channel, self._step_channel, rtol=1e-3) self._update_array_index() # IRF f_irf = fits.open(path_irf) array_irf = ac.ijdet_to_yzegp_array(f_irf[0].data) # irf is in pixel unit self._irf = asc.ArraySquareCell(199, 199, 1) self._irf.set_array(array_irf) self._irf.set_origin_center() f_irf.close() y_g, z_g = self._irf.pos_center_cells() self._irf_interpol = sci.interp2d(y_g, z_g, self._irf.ar_val.transpose(), kind='cubic', fill_value=None) # RMF f_rmf = fits.open(path_rmf) # TO DO : test if same channel than ARF self.rmf_col = f_rmf[1].data f_rmf.close() def _update_array_index(self): self._a_idx = np.array(list(range(self.chan_nb())))
[docs] def reduce_channel(self, nb_chan): if (nb_chan > 0) and (nb_chan < self.chan_nb()): self._arf_percent = self._arf_percent[:nb_chan] self._boundary_chan = self._boundary_chan[:nb_chan+1] self._channel = self._channel[:nb_chan] self._update_array_index() else: print('Invalid value nb_chan, no change !')
[docs] def arf_percent(self): return self._arf_percent
@property def chan_step(self): return self._step_channel @property def chan_boundary(self): return self._boundary_chan @property def chan_center(self): return self._channel
[docs] def chan_nb(self): return self._channel.size
[docs] def get_irf_val_ecllos(self, y_pix, z_pix, channel=None, NGP=False, verbose=False): """Return IRF value at position with ECLLos referential in pixel unit .. warning:: problem with border with array 199x199 ? Need to extrapolate ? :param y_pix: y position in ECLLos referential in pixel unit :type y_pix: Any float :param z_pix:z position in ECLLos referential in pixel unit :type z_pix:ny float :param channel: Energy channel index in EIC convention :type channel: Any int :param verbose: print IRF value :type verbose: Boolean :return: value of IRF at (y_pix, z_pix) :rtype: float """ # TODO: interpolation irf # NGP method if NGP: coef_irf = self._irf.value_at_pos_check([y_pix, z_pix]) else: # interpolation/extrapolation coef_irf = self._irf_interpol(y_pix, z_pix) if verbose: print(f"coef irf {coef_irf} at y_pix={y_pix} z_pix={z_pix}.") return coef_irf
[docs] def get_irf_array_ijecpi(self, channel=None): """Return raw IRF array from EIC :param channel: energy channel in EIC convention :type channel: uint :return: raw IRF array, ie IRF value for pixel center in array 199x199 :rtype: 2D numpy array 199x199 """ return self._irf.ar_val
[docs] def get_rmf_raw(self, channel): rmf = self.rmf_col[channel]["MATRIX"][:self.chan_nb()].astype(np.float64) return rmf
[docs] def get_rmf_norm(self, channel): rmf = self.rmf_col[channel]["MATRIX"][:self.chan_nb()].astype(np.float64) return rmf/rmf.sum()
[docs] def get_list_rv_rmf(self): l_rmf =[] for idx in range(self.chan_nb()): l_rmf.append(scs.rv_discrete(values=(self._a_idx.copy(), self.get_rmf_norm(idx).copy()))) return l_rmf
[docs] def simu_rmf_channel(self, channel, nb_photon): rmf = scs.rv_discrete(values=(self._a_idx, self.get_rmf_norm(channel))) y_rdn = np.random.uniform(size=nb_photon) return (rmf.ppf(y_rdn)+0.5).astype(np.uint32)
[docs] def plot_irf(self, p_mes=""): plt.figure() plt.title(p_mes) #plt.imshow(np.flip(self.ar_val,0)) plt.imshow(self._irf) plt.colorbar() plt.show()