Beispiel #1
0
def parse_light_curve(file_path, num_bins=150):
    """Read the light-curve data points and make sense out of them.

    Here we make a weighted average of the input data over a logarithmic
    time binning, then we interpolate in log space to fill the gaps in the
    input data, and finally we create a spline in linear space.
    """
    t, tp, tm, f, fp, fm = parse_light_curve_data(file_path)
    binning = numpy.logspace(numpy.log10(t[0]), numpy.log10(t[-1]), num_bins)
    tave = [t[0]]
    fave = [f[0]]
    for _tmin, _tmax in zip(binning[:-1], binning[1:]):
        _tave = (_tmin*_tmax)**0.5
        _mask = (t >= _tmin)*(t <= _tmax)
        if numpy.count_nonzero(_mask) > 1:
            _weights = numpy.power(0.5*(fp + fm)[_mask], -2.)
            _fave = numpy.average(f[_mask], weights=_weights)
            tave.append(_tave)
            fave.append(_fave)
    tave = numpy.log10(numpy.array(tave))
    fave = numpy.log10(numpy.array(fave))
    spline = xInterpolatedUnivariateSplineLinear(tave, fave)
    tave = numpy.linspace(tave[0], tave[-1], num_bins)
    fave = spline(tave)
    tave = numpy.power(10., tave)
    fave = numpy.power(10., fave)
    fmt = dict(xname='Time', xunits='s',
               yname='Energy integral flux 0.3-10 keV',
               yunits='erg cm$^{-2}$ s$^{-1}$')
    return xInterpolatedUnivariateSplineLinear(tave, fave, **fmt)
Beispiel #2
0
def parse_light_curve(file_path, num_bins=150):
    """Read the light-curve data points and make sense out of them.

    Here we make a weighted average of the input data over a logarithmic
    time binning, then we interpolate in log space to fill the gaps in the
    input data, and finally we create a spline in linear space.
    """
    t, tp, tm, f, fp, fm = parse_light_curve_data(file_path)
    binning = numpy.logspace(numpy.log10(t[0]), numpy.log10(t[-1]), num_bins)
    tave = [t[0]]
    fave = [f[0]]
    for _tmin, _tmax in zip(binning[:-1], binning[1:]):
        _tave = (_tmin * _tmax)**0.5
        _mask = (t >= _tmin) * (t <= _tmax)
        if numpy.count_nonzero(_mask) > 1:
            _weights = numpy.power(0.5 * (fp + fm)[_mask], -2.)
            _fave = numpy.average(f[_mask], weights=_weights)
            tave.append(_tave)
            fave.append(_fave)
    tave = numpy.log10(numpy.array(tave))
    fave = numpy.log10(numpy.array(fave))
    spline = xInterpolatedUnivariateSplineLinear(tave, fave)
    tave = numpy.linspace(tave[0], tave[-1], num_bins)
    fave = spline(tave)
    tave = numpy.power(10., tave)
    fave = numpy.power(10., fave)
    fmt = dict(xname='Time',
               xunits='s',
               yname='Energy integral flux 0.3-10 keV',
               yunits='erg cm$^{-2}$ s$^{-1}$')
    return xInterpolatedUnivariateSplineLinear(tave, fave, **fmt)
Beispiel #3
0
def parse_light_curve(file_path, num_bins=150, num_min_data=5):
    """Read the light-curve data points and make sense out of them.

    Here we make a weighted average of the input data over a logarithmic
    time binning, then we interpolate in log space to fill the gaps in the
    input data, and finally we create a spline in linear space.
    """
    t, tp, tm, f, fp, fm = parse_light_curve_data(file_path)
    t, _index = numpy.unique(t, return_index=True)
    tp = tp[_index]
    tm = tm[_index]
    f = f[_index]
    fp = fp[_index]
    fm = fm[_index]
    if len(t) < num_min_data:
        return None
    binning = numpy.logspace(numpy.log10(t[0]),numpy.log10(t[-1]), num_bins)
    tave = [t[0]]
    fave = [f[0]]
    for _tmin, _tmax in zip(binning[:-1], binning[1:]):
        _tave = (_tmin*_tmax)**0.5
        _mask = (t >= _tmin)*(t <= _tmax)
        if numpy.count_nonzero(_mask) > 1:
            _weights = numpy.power(0.5*(fp + fm)[_mask], -2.)
            _fave = numpy.average(f[_mask], weights=_weights)
            tave.append(_tave)
            fave.append(_fave)
        elif numpy.count_nonzero(_mask) == 1:
            tave.append(_tave)
            fave.append(f[_mask])
        else:
            _t1 = numpy.log10(t[t <= _tmin][-1])
            _t2 = numpy.log10(t[t >= _tmax][0])
            _f1 = numpy.log10(f[t <= _tmin][-1])
            _f2 = numpy.log10(f[t >= _tmax][0])
            _t = numpy.log10(_tave)
            _f = _f1 + (_f2 - _f1)*(_t - _t1)/(_t2 - _t1)
            _fave = 10**(_f)
            tave.append(_tave)
            fave.append(_fave)
    tave = numpy.log10(numpy.array(tave))
    fave = numpy.log10(numpy.array(fave))
    spline = xInterpolatedUnivariateSplineLinear(tave, fave)
    tave = numpy.linspace(tave[0], tave[-1], num_bins)
    fave = spline(tave)
    tave = numpy.power(10., tave)
    fave = numpy.power(10., fave)
    fmt = dict(xname='Time', xunits='s',
               yname='Energy integral flux 0.3-10 keV',
               yunits='erg cm$^{-2}$ s$^{-1}$')
    return xInterpolatedUnivariateSplineLinear(tave, fave, **fmt)
Beispiel #4
0
    def transmission_factor(self, column_density):
        """Return the transmission factor for a given column density.

        This is essentially returning

        .. math::
            \\varepsilon = \\exp(-n_H\\sigma)

        .. image:: ../figures/gabs_trans_samples.png

        Arguments
        ---------
        column_density : float
            The column density at which the transmission factor should be
            calculated.

        Warning
        -------
        We do have an issue with the extrapolation, here, as at the current
        stage there is no guarantee that the result of the spline evaluation
        would be <= 1. We could set the ext class member of the spline to 3
        before reurning it, but event that would not be right in general.
        This is probably not a huge issue, but it should be addressed
        properly.
        """
        _x = self.xsection.x
        _y = numpy.exp(-column_density*self(_x))
        _fmt = dict(xname='Energy', xunits='keV', yname='Transmission factor')
        return xInterpolatedUnivariateSplineLinear(_x, _y, **_fmt)
Beispiel #5
0
def make_mrf(modf_file_path, irf_name):
    """Write the XIPE modulation factor response function.
    """
    logger.info('Creating XIPE effective area fits file...')
    output_file_name = '%s.mrf' % irf_name
    output_file_path = os.path.join(XIMPOL_IRF, 'fits', output_file_name)
    if os.path.exists(output_file_path):
        rm(output_file_path)
    logger.info('Loading modulation factor from %s...' % modf_file_path)
    _x, _y = numpy.loadtxt(modf_file_path, unpack=True)
    modf = xInterpolatedUnivariateSplineLinear(_x, _y)
    logger.info('Filling in arrays...')
    modfresp = modf(ENERGY_CENTER)
    logger.info('Creating PRIMARY HDU...')
    primary_hdu = xPrimaryHDU('ximpol', INSTR_KEYWORDS, INSTR_COMMENTS)
    print(repr(primary_hdu.header))
    logger.info('Creating MODFRESP HDU...')
    data = [ENERGY_LO, ENERGY_HI, modfresp]
    modfresp_hdu = xBinTableHDUMODFRESP(data, INSTR_KEYWORDS, INSTR_COMMENTS)
    print(repr(modfresp_hdu.header))
    logger.info('Writing output file %s...' % output_file_path)
    hdulist = fits.HDUList([primary_hdu, modfresp_hdu])
    hdulist.info()
    hdulist.writeto(output_file_path)
    logger.info('Done.')
Beispiel #6
0
    def build_mdp_table(self, energy_binning, modulation_factor):
        """Calculate the MDP values in energy bins, given the modulation
        factor of the instrument as a function of the energy.

        Arguments
        ---------
        energy_binning : array
            The energy binning
        modulation_factor : ximpol.irf.mrf.xModulationFactor instance
            The instrument modulation factor as a function of the energy.
        """
        # Build the time-integrated spectrum.
        time_integrated_spectrum = self.build_time_integral()
        # Build the modulation-factor spectrum, i.e. the object that we
        # integrate to calculate the effective modulation factor in a
        # given energy bin for a given spectrum.
        _x = time_integrated_spectrum.x
        _y = time_integrated_spectrum.y*modulation_factor(_x)
        mu_spectrum = xInterpolatedUnivariateSplineLinear(_x, _y)
        # Loop over the energy bins and calculate the actual MDP values.
        # Note that we also calculate the MDP on the entire energy range.
        observation_time = self.scale_factor*(self.xmax() - self.xmin())
        mdp_table = xMDPTable(observation_time)
        ebins = zip(energy_binning[:-1], energy_binning[1:])
        if len(energy_binning) > 2:
            ebins.append((energy_binning[0], energy_binning[-1]))
        for _emin, _emax in ebins:
            num_counts = self.num_expected_counts(emin=_emin, emax=_emax)
            mu_eff = mu_spectrum.integral(_emin, _emax)/num_counts
            mdp = mdp99(mu_eff, num_counts)
            mdp_table.add_row(mdp, _emin, _emax, mu_eff, num_counts)
        return mdp_table
Beispiel #7
0
    def integral_flux(self, emin=2.0, emax=8.0, t=None, erg=True):
        """Return the integral source flux at a generic time.

        This is achieved by taking a "slice" of the source spectrum
        at that time and integrating between a minimum and maximum energy.

        Arguments
        ---------
        emin : float
            The minimum integration energy (default 2 keV).

        emax : float
            The maximum integration energy (default 2 keV).

        t : float
            The time (default is the minimum source validity time).
        """
        if t is None:
            t = self.min_validity_time
        _x = numpy.linspace(emin, emax, 100)
        _y = _x*self.energy_spectrum(_x, t)
        _flux = xInterpolatedUnivariateSplineLinear(_x, _y).integral(emin, emax)
        if erg:
            _flux = keV2erg(_flux)
        return _flux
Beispiel #8
0
def xpmdp(**kwargs):
    """Calculate the MDP.
    """
    logger.info('Loading the instrument response functions...')
    aeff = load_arf(kwargs['irfname'])
    modf = load_mrf(kwargs['irfname'])
    module_name = os.path.basename(kwargs['configfile']).replace('.py', '')
    ROI_MODEL = imp.load_source(module_name, kwargs['configfile']).ROI_MODEL
    logger.info(ROI_MODEL)

    # This is copied from xpobbsim and should probably be factored out.
    # Actually, this should be a method of the ROI class. TBD
    if kwargs['tstart'] < ROI_MODEL.min_validity_time():
        kwargs['tstart'] = ROI_MODEL.min_validity_time()
        logger.info('Simulation start time set to %s...' % kwargs['tstart'])
    tstop = kwargs['tstart'] + kwargs['duration']
    if tstop > ROI_MODEL.max_validity_time():
        tstop = ROI_MODEL.max_validity_time()
        logger.info('Simulation stop time set to %s...' % tstop)
    kwargs['tstop'] = tstop
    observation_time = kwargs['tstop'] - kwargs['tstart']

    # This is copied from roi.py and should probably be factored out.
    # Again, the ROI class should be able to sum the count spectra of all the
    # component and expose the result.
    sources = ROI_MODEL.values()
    if len(sources) > 1:
        abort('Multiple sources not implemented, yet.')
    source = sources[0]
    if isinstance(source, xPeriodicPointSource):
        psamples = numpy.linspace(kwargs['phasemin'], kwargs['phasemax'], 100)
        logger.info('Sampling phases: %s' % psamples)
        count_spectrum = xCountSpectrum(source.energy_spectrum,
                                        aeff,
                                        psamples,
                                        scale=observation_time)
        time_integrated_spectrum = count_spectrum.build_time_integral()
    else:
        tsamples = source.sampling_time(kwargs['tstart'], kwargs['tstop'])
        logger.info('Sampling times: %s' % tsamples)
        count_spectrum = xCountSpectrum(source.energy_spectrum, aeff, tsamples)
        time_integrated_spectrum = count_spectrum.build_time_integral()

    # Thuis should be a callable method in the binning module.
    ebinning = _make_binning(kwargs['ebinalg'], kwargs['emin'], kwargs['emax'],
                             kwargs['ebins'], kwargs['ebinning'])

    # And this might be implemented in the irf.mrf module.
    _x = time_integrated_spectrum.x
    _y = time_integrated_spectrum.y * modf(_x)
    mu_spectrum = xInterpolatedUnivariateSplineLinear(_x, _y)

    for _emin, _emax in zip(ebinning[:-1], ebinning[1:]) +\
        [(ebinning[0], ebinning[-1])]:
        num_counts = count_spectrum.num_expected_counts(emin=_emin, emax=_emax)
        mu_average = mu_spectrum.integral(_emin, _emax) / num_counts
        mdp = 4.29 / mu_average / numpy.sqrt(num_counts)
        logger.info('%.2f--%.2f keV: %d counts in %d s, mu %.3f, MDP %.2f%%' %\
                    (_emin, _emax, num_counts, observation_time, mu_average,
                     100*mdp))
Beispiel #9
0
def make_mrf(modf_file_path, irf_name):
    """Write the XIPE modulation factor response function.
    """
    logger.info('Creating XIPE effective area fits file...')
    output_file_name = '%s.mrf' % irf_name
    output_file_path = os.path.join(XIMPOL_IRF, 'fits', output_file_name)
    if os.path.exists(output_file_path):
        rm(output_file_path)
    logger.info('Loading modulation factor from %s...' % modf_file_path)
    _x, _y = numpy.loadtxt(modf_file_path, unpack=True)
    modf = xInterpolatedUnivariateSplineLinear(_x, _y)
    logger.info('Filling in arrays...')
    modfresp = modf(ENERGY_CENTER)
    logger.info('Creating PRIMARY HDU...')
    primary_hdu = xPrimaryHDU('ximpol', XIPE_KEYWORDS, XIPE_COMMENTS)
    print(repr(primary_hdu.header))
    logger.info('Creating MODFRESP HDU...')
    data = [ENERGY_LO, ENERGY_HI, modfresp]
    modfresp_hdu = xBinTableHDUMODFRESP(data, XIPE_KEYWORDS, XIPE_COMMENTS)
    print(repr(modfresp_hdu.header))
    logger.info('Writing output file %s...' % output_file_path)
    hdulist = fits.HDUList([primary_hdu, modfresp_hdu])
    hdulist.info()
    hdulist.writeto(output_file_path)
    logger.info('Done.')
Beispiel #10
0
def xpmdp(**kwargs):
    """Calculate the MDP.
    """
    logger.info('Loading the instrument response functions...')
    aeff = load_arf(kwargs['irfname'])
    modf = load_mrf(kwargs['irfname'])
    module_name = os.path.basename(kwargs['configfile']).replace('.py', '')
    ROI_MODEL = imp.load_source(module_name, kwargs['configfile']).ROI_MODEL
    logger.info(ROI_MODEL)

    # This is copied from xpobbsim and should probably be factored out.
    # Actually, this should be a method of the ROI class. TBD
    if kwargs['tstart'] < ROI_MODEL.min_validity_time():
        kwargs['tstart'] = ROI_MODEL.min_validity_time()
        logger.info('Simulation start time set to %s...' % kwargs['tstart'])
    tstop = kwargs['tstart'] + kwargs['duration']
    if tstop > ROI_MODEL.max_validity_time():
        tstop = ROI_MODEL.max_validity_time()
        logger.info('Simulation stop time set to %s...' % tstop)
    kwargs['tstop'] = tstop
    observation_time = kwargs['tstop'] - kwargs['tstart']

    # This is copied from roi.py and should probably be factored out.
    # Again, the ROI class should be able to sum the count spectra of all the
    # component and expose the result.
    sources = ROI_MODEL.values()
    if len(sources) > 1:
        abort('Multiple sources not implemented, yet.')
    source = sources[0]
    if isinstance(source, xPeriodicPointSource):
        psamples = numpy.linspace(kwargs['phasemin'], kwargs['phasemax'], 100)
        logger.info('Sampling phases: %s' % psamples)
        count_spectrum = xCountSpectrum(source.energy_spectrum, aeff, psamples,
                                        scale=observation_time)
        time_integrated_spectrum = count_spectrum.build_time_integral()
    else:
        tsamples = source.sampling_time(kwargs['tstart'], kwargs['tstop'])
        logger.info('Sampling times: %s' % tsamples)
        count_spectrum = xCountSpectrum(source.energy_spectrum, aeff, tsamples)
        time_integrated_spectrum = count_spectrum.build_time_integral()

    # Thuis should be a callable method in the binning module.
    ebinning =_make_binning(kwargs['ebinalg'], kwargs['emin'], kwargs['emax'],
                            kwargs['ebins'], kwargs['ebinning'])

    # And this might be implemented in the irf.mrf module.
    _x = time_integrated_spectrum.x
    _y = time_integrated_spectrum.y*modf(_x)
    mu_spectrum = xInterpolatedUnivariateSplineLinear(_x, _y)

    for _emin, _emax in zip(ebinning[:-1], ebinning[1:]) +\
        [(ebinning[0], ebinning[-1])]:
        num_counts = count_spectrum.num_expected_counts(emin=_emin, emax=_emax)
        mu_average = mu_spectrum.integral(_emin, _emax)/num_counts
        mdp = 4.29/mu_average/numpy.sqrt(num_counts)
        logger.info('%.2f--%.2f keV: %d counts in %d s, mu %.3f, MDP %.2f%%' %\
                    (_emin, _emax, num_counts, observation_time, mu_average,
                     100*mdp))
Beispiel #11
0
    def test_xipe_arf(self):
        """Test the XIPE effective area.

        This is loading the effective area from the .arf FITS file, then
        loading the data points from the text files the response function
        is created from, and finally testing that the actual values from the
        two methods are close enough over the entire energy range.
        """
        _x, _y = numpy.loadtxt(OPT_AEFF_FILE_PATH, unpack=True)
        opt_aeff = xInterpolatedUnivariateSplineLinear(_x, _y)
        _x, _y = numpy.loadtxt(GPD_QEFF_FILE_PATH, unpack=True)
        gpd_eff = xInterpolatedUnivariateSplineLinear(_x, _y)
        aeff = load_arf(IRF_NAME)
        _x = numpy.linspace(aeff.xmin(), aeff.xmax(), 100)
        # Remove the data points where the effective area is 0.
        _x = _x[aeff(_x) > 0.]
        _delta = abs((aeff(_x) - opt_aeff(_x)*gpd_eff(_x))/aeff(_x))
        self.assertTrue(_delta.max() < 5e-3, 'max. diff. %.9f' % _delta.max())
Beispiel #12
0
def scale_flux(energy, flux, emin=2., emax=8.):
    ism_model = xpeInterstellarAbsorptionModel()
    ism_trans = ism_model.transmission_factor(GAL_NH)
    flux *= ism_trans(energy)
    norm = xInterpolatedUnivariateSplineLinear(energy,energy*flux).integral(
                                                                emin, emax)
    norm = keV2erg(norm)
    scale_factor =  FLUX/norm
    return flux*scale_factor
Beispiel #13
0
def _load_chandra_arf(arf_file):
    """Load the Chandra effective area data from file.
    """
    hdu_list = fits.open(arf_file)
    tbdata = hdu_list["SPECRESP"].data
    _x = 0.5 * (tbdata.field("ENERG_LO") + tbdata.field("ENERG_HI"))
    _y = tbdata.field("SPECRESP")
    fmt = dict(xname="Energy", xunits="keV", yname="Effective area", yunits="cm$^2$")
    return xInterpolatedUnivariateSplineLinear(_x, _y, **fmt)
Beispiel #14
0
def get_grb_mdp(grb_name, repointing=21600., obs_time=100000, \
                aeff_file_path=os.path.join(XIMPOL_IRF,'fits',\
                                            'xipe_baseline.arf'), \
                mu_file_path=os.path.join(XIMPOL_IRF,'fits',\
                                             'xipe_baseline.mrf')):
    """Calculate the MDP, given GRB name, the repointing elapsed time [sec]
       after the trigger, and the oservationrange of time [sec]
    """
    file_path = download_swift_grb_lc_file(grb_name)
    if file_path is not None:
        index = get_grb_spec_index(file_path)
        E_light_curve = parse_light_curve(file_path,num_min_data=10.)
        #E_light_curve.plot(logx=True,logy=True)
        if E_light_curve is not None:
            scale_factor = (2. - index)/(numpy.power(MAX_ENERGY, 2. - index) - \
                                     numpy.power(MIN_ENERGY, 2. - index))
            scale_factor *= 6.242e8
            light_curve = E_light_curve.scale(scale_factor)
            #light_curve.plot(logx=True,logy=True)
            t_min = repointing
            if t_min < light_curve.xmin():
                logger.info('Repointing time < to the minimum time of the burst...')
                return None
            else:
                t_max = t_min + obs_time
                if t_max > light_curve.xmax():
                    t_max = light_curve.xmax()
                norm = light_curve.integral(t_min,t_max)
                _energy = numpy.linspace(2.,MAX_ENERGY,1000)
                _modf = get_eff_mu(_energy,mu_file_path)
                _spectrum = get_spectrum(_energy,norm,index,aeff_file_path)
                energy_spectrum = xInterpolatedUnivariateSplineLinear(_energy,\
                                                                      _spectrum)
                #plt.xlim(1.,10.)
                #energy_spectrum.plot(logx=True,logy=True)
                
                num_evt = energy_spectrum.integral(MIN_ENERGY,MAX_ENERGY)
                if not math.isnan(num_evt) and num_evt != 0.:
                    logger.info('Total estimated number of events: %i'\
                                %int(num_evt))
                    mu = numpy.average(_modf,weights=_spectrum)
                    mdp = mdp99(mu,int(num_evt))
                    if not math.isnan(mdp):
                        logger.info('%.2f--%.2f keV: %i counts (%.1e s), mu %.2f, MDP %.2f%%'\
                                    %(MIN_ENERGY,MAX_ENERGY,int(num_evt),\
                                      obs_time,mu,mdp*100))
                        return mdp
                    else:
                        return None
                else:
                    logger.info('Total number of events cannot be estimated...')
                    return None
        else:
            return None
    else:
        return None
Beispiel #15
0
def parse_spectral_model(file_name):
    """Parse a spectral model written by XSPEC and return the corresponding
    interpolated univariate spline.
    """
    file_path = os.path.join(XIMPOL_CONFIG, 'ascii', file_name)
    data = numpy.loadtxt(file_path, unpack=True)
    energy, flux = data[0], data[2]
    fmt = dict(xname='Energy', xunits='keV', yname='Flux',
               yunits='cm$^{-2}$ s$^{-1}$ keV$^{-1}$')
    return xInterpolatedUnivariateSplineLinear(energy, flux, **fmt)
Beispiel #16
0
def make_arf(aeff_file_path, qeff_file_path, irf_name, off_axis_data=None):
    """Write the XIPE effective area response function.
    """
    logger.info('Creating XIPE effective area fits file...')
    output_file_name = '%s.arf' % irf_name
    output_file_path = os.path.join(XIMPOL_IRF, 'fits', output_file_name)
    if os.path.exists(output_file_path):
        rm(output_file_path)
    logger.info('Loading mirror effective area from %s...' % aeff_file_path)
    _x, _y = numpy.loadtxt(aeff_file_path, unpack=True)
    opt_aeff = xInterpolatedUnivariateSplineLinear(_x, _y)
    logger.info('Loading quantum efficiency from %s...' % qeff_file_path)
    _x, _y = numpy.loadtxt(qeff_file_path, unpack=True)
    gpd_eff = xInterpolatedUnivariateSplineLinear(_x, _y)
    aeff = opt_aeff * gpd_eff
    specresp = aeff(ENERGY_CENTER)
    logger.info('Creating PRIMARY HDU...')
    primary_hdu = xPrimaryHDU('ximpol', XIPE_KEYWORDS, XIPE_COMMENTS)
    print(repr(primary_hdu.header))
    logger.info('Creating SPECRESP HDU...')
    data = [ENERGY_LO, ENERGY_HI, specresp]
    specresp_hdu = xBinTableHDUSPECRESP(data, XIPE_KEYWORDS, XIPE_COMMENTS)
    print(repr(specresp_hdu.header))
    logger.info('Processing off-axis data...')
    energy = numpy.linspace(ENERGY_MIN, ENERGY_MAX, 100)
    theta = [0]
    vignetting = [[1.] * len(energy)]
    for r, file_path in off_axis_data:
        logger.info('Reading %s (at %.2f arcsec)...' % (file_path, r))
        theta.append(r)
        _x, _y = numpy.loadtxt(file_path, unpack=True)
        _aeff = xInterpolatedUnivariateSplineLinear(_x, _y)
        ratio = _aeff / opt_aeff
        vignetting.append(ratio(energy))
    theta = numpy.array(theta)
    vignetting = numpy.array(vignetting).transpose()
    data = [energy, theta, vignetting]
    vignetting_hdu = xBinTableHDUVIGNETTING(data)
    logger.info('Writing output file %s...' % output_file_path)
    hdulist = fits.HDUList([primary_hdu, specresp_hdu, vignetting_hdu])
    hdulist.info()
    hdulist.writeto(output_file_path)
    logger.info('Done.')
Beispiel #17
0
def load_chandra_arf(arf_file):
    """Load the Chandra effective area data
    """
    hdu_list = fits.open(arf_file)
    tbdata = hdu_list['SPECRESP'].data
    _x = 0.5*(tbdata.field('ENERG_LO') + tbdata.field('ENERG_HI'))
    _y = tbdata.field('SPECRESP')
    fmt = dict(xname='Energy', xunits='keV', yname='Effective area',
               yunits='cm$^2$')
    return xInterpolatedUnivariateSplineLinear(_x, _y, **fmt)
Beispiel #18
0
def make_arf(aeff_file_path, qeff_file_path, irf_name, off_axis_data=[]):
    """Write the XIPE effective area response function.
    """
    logger.info('Creating XIPE effective area fits file...')
    output_file_name = '%s.arf' % irf_name
    output_file_path = os.path.join(XIMPOL_IRF, 'fits', output_file_name)
    if os.path.exists(output_file_path):
        rm(output_file_path)
    logger.info('Loading mirror effective area from %s...' % aeff_file_path)
    _x, _y = numpy.loadtxt(aeff_file_path, unpack=True)
    opt_aeff = xInterpolatedUnivariateSplineLinear(_x, _y)
    logger.info('Loading quantum efficiency from %s...' % qeff_file_path)
    _x, _y = numpy.loadtxt(qeff_file_path, unpack=True)
    gpd_eff = xInterpolatedUnivariateSplineLinear(_x, _y)
    aeff = opt_aeff*gpd_eff
    specresp = aeff(ENERGY_CENTER)
    logger.info('Creating PRIMARY HDU...')
    primary_hdu = xPrimaryHDU('ximpol', INSTR_KEYWORDS, INSTR_COMMENTS)
    print(repr(primary_hdu.header))
    logger.info('Creating SPECRESP HDU...')
    data = [ENERGY_LO, ENERGY_HI, specresp]
    specresp_hdu = xBinTableHDUSPECRESP(data, INSTR_KEYWORDS, INSTR_COMMENTS)
    print(repr(specresp_hdu.header))
    logger.info('Processing off-axis data...')
    energy = numpy.linspace(ENERGY_MIN, ENERGY_MAX, 100)
    theta = [0]
    vignetting = [[1.]*len(energy)]
    for r, file_path in off_axis_data:
        logger.info('Reading %s (at %.2f arcsec)...' % (file_path, r))
        theta.append(r)
        _x, _y = numpy.loadtxt(file_path, unpack=True)
        _aeff = xInterpolatedUnivariateSplineLinear(_x, _y)
        ratio = _aeff/opt_aeff
        vignetting.append(ratio(energy))
    theta = numpy.array(theta)
    vignetting = numpy.array(vignetting).transpose()
    data = [energy, theta, vignetting]
    vignetting_hdu = xBinTableHDUVIGNETTING(data)
    logger.info('Writing output file %s...' % output_file_path)
    hdulist = fits.HDUList([primary_hdu, specresp_hdu, vignetting_hdu])
    hdulist.info()
    hdulist.writeto(output_file_path)
    logger.info('Done.')
Beispiel #19
0
def parse_spectral_model(file_name, emin=0.9, emax=11.):
    """Parse the input file with the spectral point.
    """
    file_path = os.path.join(XIMPOL_CONFIG, 'ascii', file_name)
    logger.info('Parsing input file %s...' % file_path)
    _energy, _flux, _fluxerr = numpy.loadtxt(file_path, unpack=True)
    _mask = (_energy >= emin)*(_energy <= emax)
    _energy = _energy[_mask]
    _flux = _flux[_mask]
    fmt = dict(xname='Energy', xunits='keV', yname='Flux',
               yunits='cm$^{-2}$ s$^{-1}$ keV$^{-1}$')
    return xInterpolatedUnivariateSplineLinear(_energy, _flux, **fmt)
Beispiel #20
0
def parse_spectral_model(file_name, emin=0.5, emax=15.):
    """Parse the input file with the spectral point.
    """
    file_path = os.path.join(XIMPOL_CONFIG, 'ascii', file_name)
    logger.info('Parsing input file %s...' % file_path)
    _energy, _flux = numpy.loadtxt(file_path, delimiter=',', unpack=True)
    _mask = (_energy >= emin)*(_energy <= emax)
    _energy = _energy[_mask]
    _flux = _flux[_mask]
    _flux /= _energy**2.
    fmt = dict(xname='Energy', xunits='keV', yname='Flux',
               yunits='cm$^{-2}$ s$^{-1}$ keV$^{-1}$')
    return xInterpolatedUnivariateSplineLinear(_energy, _flux, **fmt)
Beispiel #21
0
 def xsection_ecube(self):
     """Return a spline with the values of absorption cross section
     multiplied by the cube of the energy, as a function of the energy.
     
     This is essentially the same plot in Figure 1 of the original paper, as
     illustrated in the following figure
     
     .. image:: ../figures/gabs_xsection_ecube.png
     """
     _x = self.xsection.x
     _y = self(_x)*(_x**3.)
     _fmt = dict(xname='Energy', xunits='keV',
                 yname='$\\sigma_{abs} \\times E^3$',
                 yunits='cm$^2$~keV$^3$')
     return xInterpolatedUnivariateSplineLinear(_x, _y, **_fmt)
Beispiel #22
0
def make_rmf(eres_file_path, irf_name):
    """Write the XIPE edisp response function.

    The specifications are describes at page ~15 of the following document:
    ftp://legacy.gsfc.nasa.gov/caldb/docs/memos/cal_gen_92_002/cal_gen_92_002.ps
    """
    output_file_name = '%s.rmf' % irf_name
    output_file_path = os.path.join(XIMPOL_IRF, 'fits', output_file_name)
    if os.path.exists(output_file_path):
        rm(output_file_path)
    logger.info('Loading energy dispersion from %s...' % eres_file_path)
    _x, _y = numpy.loadtxt(eres_file_path, unpack=True)
    edisp_fwhm = xInterpolatedUnivariateSplineLinear(_x, _y)
    logger.info('Creating PRIMARY HDU...')
    primary_hdu = xPrimaryHDU('ximpol', XIPE_KEYWORDS, XIPE_COMMENTS)
    print(repr(primary_hdu.header))
    keyword = ('DETCHANS', NUM_CHANNELS, 'Total number of detector channels')
    rmf_header_keywords = XIPE_KEYWORDS + [keyword]
    logger.info('Creating MATRIX HDU...')
    nrows = len(ENERGY_LO)
    ngrp = numpy.ones(nrows)
    fchan = numpy.zeros(nrows)
    nchan = numpy.array([NUM_CHANNELS] * nrows, 'i')
    matrix = numpy.zeros((0, NUM_CHANNELS))
    ch = numpy.arange(NUM_CHANNELS)
    for energy, rms in zip(ENERGY_CENTER, edisp_fwhm(ENERGY_CENTER) / 2.358):
        mean_chan = int((energy - E_CHAN_OFFSET) / E_CHAN_SLOPE)
        rms_chan = rms / E_CHAN_SLOPE
        rv = stats.norm(loc=mean_chan, scale=rms_chan)
        matrix = numpy.vstack([matrix, rv.pdf(ch)])
    data = [ENERGY_LO, ENERGY_HI, ngrp, fchan, nchan, matrix]
    matrix_hdu = xBinTableHDUMATRIX(NUM_CHANNELS, data, rmf_header_keywords,
                                    XIPE_COMMENTS)
    print(repr(matrix_hdu.header))
    logger.info('Creating EBOUNDS HDU...')
    ch = numpy.arange(NUM_CHANNELS)
    emin = ch * E_CHAN_SLOPE + E_CHAN_OFFSET
    emax = (ch + 1) * E_CHAN_SLOPE + E_CHAN_OFFSET
    data = [ch, emin, emax]
    ebounds_hdu = xBinTableHDUEBOUNDS(data, rmf_header_keywords, XIPE_COMMENTS)
    print(repr(ebounds_hdu.header))
    logger.info('Writing output file %s...' % output_file_path)
    hdulist = fits.HDUList([primary_hdu, matrix_hdu, ebounds_hdu])
    hdulist.info()
    hdulist.writeto(output_file_path)
    logger.info('Done.')
Beispiel #23
0
def make_rmf(eres_file_path, irf_name):
    """Write the XIPE edisp response function.

    The specifications are describes at page ~15 of the following document:
    ftp://legacy.gsfc.nasa.gov/caldb/docs/memos/cal_gen_92_002/cal_gen_92_002.ps
    """
    output_file_name = '%s.rmf' % irf_name
    output_file_path = os.path.join(XIMPOL_IRF, 'fits', output_file_name)
    if os.path.exists(output_file_path):
        rm(output_file_path)
    logger.info('Loading energy dispersion from %s...' % eres_file_path)
    _x, _y = numpy.loadtxt(eres_file_path, unpack=True)
    edisp_fwhm = xInterpolatedUnivariateSplineLinear(_x, _y)
    logger.info('Creating PRIMARY HDU...')
    primary_hdu = xPrimaryHDU('ximpol', INSTR_KEYWORDS, INSTR_COMMENTS)
    print(repr(primary_hdu.header))
    keyword = ('DETCHANS', NUM_CHANNELS, 'Total number of detector channels')
    rmf_header_keywords = INSTR_KEYWORDS + [keyword]
    logger.info('Creating MATRIX HDU...')
    nrows = len(ENERGY_LO)
    ngrp = numpy.ones(nrows)
    fchan = numpy.zeros(nrows)
    nchan = numpy.array([NUM_CHANNELS]*nrows, 'i')
    matrix = numpy.zeros((0, NUM_CHANNELS))
    ch = numpy.arange(NUM_CHANNELS)
    for energy, rms in zip(ENERGY_CENTER, edisp_fwhm(ENERGY_CENTER)/2.358):
        mean_chan = int((energy - E_CHAN_OFFSET)/E_CHAN_SLOPE)
        rms_chan = rms/E_CHAN_SLOPE
        rv = stats.norm(loc=mean_chan, scale=rms_chan)
        matrix = numpy.vstack([matrix, rv.pdf(ch)])
    data = [ENERGY_LO, ENERGY_HI, ngrp, fchan, nchan, matrix]
    matrix_hdu = xBinTableHDUMATRIX(NUM_CHANNELS, data, rmf_header_keywords,
                                    INSTR_COMMENTS)
    print(repr(matrix_hdu.header))
    logger.info('Creating EBOUNDS HDU...')
    ch = numpy.arange(NUM_CHANNELS)
    emin = ch*E_CHAN_SLOPE + E_CHAN_OFFSET
    emax = (ch + 1)*E_CHAN_SLOPE + E_CHAN_OFFSET
    data = [ch, emin, emax]
    ebounds_hdu = xBinTableHDUEBOUNDS(data, rmf_header_keywords, INSTR_COMMENTS)
    print(repr(ebounds_hdu.header))
    logger.info('Writing output file %s...' % output_file_path)
    hdulist = fits.HDUList([primary_hdu, matrix_hdu, ebounds_hdu])
    hdulist.info()
    hdulist.writeto(output_file_path)
    logger.info('Done.')
 def test_cdf(self):
     """Test the one-dimensional azimuthal response underlying pdf.
     """
     phi = numpy.linspace(0., 2*numpy.pi, 100)
     for visibility in numpy.linspace(1, 0, 5):
         cdf = self.generator.cdf(phi, visibility)
         plt.plot(phi, cdf, label='$\\xi = %.2f$' % visibility)
         spline = xInterpolatedUnivariateSplineLinear(phi, cdf)
         self.assertTrue(abs(spline(0.)) < 1e-5, 'cdf(0) = %.3e' % spline(0))
         self.assertTrue(abs(spline(2*numpy.pi) - 1) < 1e-5,
                         'cdf(2pi) = %.3e' % spline(2*numpy.pi))
     plt.axis([0., 2*numpy.pi, None, None])
     plt.xlabel('$\\phi$ [rad]')
     plt.ylabel('cdf($\\phi$)')
     plt.legend(bbox_to_anchor=(0.4, 0.92))
     overlay_tag()
     save_current_figure('test_azimuthal_resp_cdf.png',
                         show=self.interactive)
Beispiel #25
0
 def test_cdf(self):
     """Test the one-dimensional azimuthal response underlying pdf.
     """
     phi = numpy.linspace(0., 2 * numpy.pi, 100)
     for visibility in numpy.linspace(1, 0, 5):
         cdf = self.generator.cdf(phi, visibility)
         plt.plot(phi, cdf, label='$\\xi = %.2f$' % visibility)
         spline = xInterpolatedUnivariateSplineLinear(phi, cdf)
         self.assertTrue(
             abs(spline(0.)) < 1e-5, 'cdf(0) = %.3e' % spline(0))
         self.assertTrue(
             abs(spline(2 * numpy.pi) - 1) < 1e-5,
             'cdf(2pi) = %.3e' % spline(2 * numpy.pi))
     plt.axis([0., 2 * numpy.pi, None, None])
     plt.xlabel('$\\phi$ [rad]')
     plt.ylabel('cdf($\\phi$)')
     plt.legend(bbox_to_anchor=(0.4, 0.92))
     overlay_tag()
     save_current_figure('test_azimuthal_resp_cdf.png',
                         show=self.interactive)
 def test_pdf(self):
     """Test the one-dimensional azimuthal response underlying pdf.
     """
     self.generator.plot(show=self.interactive)
     overlay_tag(color='white')
     save_current_figure('test_azimuthal_resp_generator.png',
                         show=self.interactive)
     phi = numpy.linspace(0., 2*numpy.pi, 100)
     for visibility in numpy.linspace(1, 0, 5):
         pdf = self.generator.pdf(phi, visibility)
         plt.plot(phi, pdf, label='$\\xi = %.2f$' % visibility)
         spline = xInterpolatedUnivariateSplineLinear(phi, pdf)
         norm = spline.norm()
         self.assertTrue(abs(norm - 1.) < 1e-5,
                         'Normalization is %.3e' % norm)
     plt.axis([0., 2*numpy.pi, None, None])
     plt.xlabel('$\\phi$ [rad]')
     plt.ylabel('pdf($\\phi$) [1/rad]')
     plt.legend(bbox_to_anchor=(0.88, 0.92))
     overlay_tag()
     save_current_figure('test_azimuthal_resp_pdf.png',
                         show=self.interactive)
    def mdp_table(self, column_density, index, exposure_time, eflux):
        """Return the MDP table for a point source with a power-law
        spectral shape with a given set of parameters and for a given
        observation time.

        There's a slight complication, here, due to the fact that the
        sensitivity calculator is rescaling the absorbed fluxes so that the
        input energy flux (in the web form) is that at the observer instead of
        that at the source. Therefore we need to do the same here.
        """
        tsamples = numpy.linspace(0.0, exposure_time, 2)
        norm = int_eflux2pl_norm(eflux, self.emin, self.emax, index, erg=True)
        energy_spectrum = power_law(norm, index)
        ism_trans = self.ism_model.transmission_factor(column_density)
        _x = numpy.linspace(self.emin, self.emax, 1000)
        _y = _x * energy_spectrum(_x, 0.0) * ism_trans(_x)
        absorbed_energy_spectrum = xInterpolatedUnivariateSplineLinear(_x, _y)
        absorbed_eflux = keV2erg(absorbed_energy_spectrum.norm())
        scale = eflux / absorbed_eflux
        count_spectrum = xCountSpectrum(energy_spectrum, self.aeff, tsamples, column_density, scale_factor=scale)
        mdp_table = count_spectrum.build_mdp_table(self.ebinning, self.modf)
        return mdp_table
Beispiel #28
0
 def fit_histogram(cls, histogram, fit_normalization=False):
     """Fit an azimuthal histogram.
     """
     from scipy.optimize import curve_fit
     _y, binning, patches = histogram
     _x = 0.5*(binning[1:] + binning[:-1])
     norm = _y.sum()*(binning[1] - binning[0])
     if not fit_normalization:
         p0 = (0.5, 0.5)
         # Wrap the fit function, keeping the normalization frozen.
         def f(phi, visibility, phase):
             return cls.fit_function(phi, visibility, phase, norm)
     else:
         p0 = (0.5, 0.5, norm)
         f = cls.fit_function
     popt, pcov = curve_fit(f, _x, _y, p0, numpy.sqrt(_y))
     if not fit_normalization:
         # Add back the normalization to the parameter vector and covariance
         # matrix.
         popt = numpy.concatenate((popt, numpy.array([norm])))
         pcov = numpy.vstack((pcov, numpy.array([[0., 0.]])))
         pcov = numpy.hstack((pcov, numpy.array([[0., 0., 0.]]).transpose()))
     _xs = numpy.linspace(0, 2*numpy.pi, 250)
     _ys = cls.fit_function(_xs, *popt)/(binning[1] - binning[0])
     spline = xInterpolatedUnivariateSplineLinear(_xs, _ys)
     mask = _y > 0.
     obs = _y[mask]
     exp = []
     for _min, _max in zip(binning[:-1], binning[1:]):
         exp.append(spline.integral(_min, _max))
     exp = numpy.array(exp)[mask]
     chisquare = ((exp - obs)**2/exp).sum()
     # Horrible hack.
     if popt[0] < 0.:
         popt[0] = -popt[0]
         popt[1] += 0.5*numpy.pi
     if popt[1] < 0.:
         popt[1] += numpy.pi
     return xModulationFitResults(popt, pcov, chisquare, len(mask))
Beispiel #29
0
 def test_pdf(self):
     """Test the one-dimensional azimuthal response underlying pdf.
     """
     self.generator.plot(show=self.interactive)
     overlay_tag(color='white')
     save_current_figure('test_azimuthal_resp_generator.png',
                         show=self.interactive)
     phi = numpy.linspace(0., 2 * numpy.pi, 100)
     for visibility in numpy.linspace(1, 0, 5):
         pdf = self.generator.pdf(phi, visibility)
         plt.plot(phi, pdf, label='$\\xi = %.2f$' % visibility)
         spline = xInterpolatedUnivariateSplineLinear(phi, pdf)
         norm = spline.norm()
         self.assertTrue(
             abs(norm - 1.) < 1e-5, 'Normalization is %.3e' % norm)
     plt.axis([0., 2 * numpy.pi, None, None])
     plt.xlabel('$\\phi$ [rad]')
     plt.ylabel('pdf($\\phi$) [1/rad]')
     plt.legend(bbox_to_anchor=(0.88, 0.92))
     overlay_tag()
     save_current_figure('test_azimuthal_resp_pdf.png',
                         show=self.interactive)
Beispiel #30
0
 def fit_histogram(cls, histogram, fit_normalization=False):
     """Fit an azimuthal histogram.
     """
     from scipy.optimize import curve_fit
     _y, binning, patches = histogram
     _x = 0.5*(binning[1:] + binning[:-1])
     norm = _y.sum()*(binning[1] - binning[0])
     if not fit_normalization:
         p0 = (0.5, 0.5)
         # Wrap the fit function, keeping the normalization frozen.
         def f(phi, visibility, phase):
             return cls.fit_function(phi, visibility, phase, norm)
     else:
         p0 = (0.5, 0.5, norm)
         f = cls.fit_function
     popt, pcov = curve_fit(f, _x, _y, p0, numpy.sqrt(_y))
     if not fit_normalization:
         # Add back the normalization to the parameter vector and covariance
         # matrix.
         popt = numpy.concatenate((popt, numpy.array([norm])))
         pcov = numpy.vstack((pcov, numpy.array([[0., 0.]])))
         pcov = numpy.hstack((pcov, numpy.array([[0., 0., 0.]]).transpose()))
     _xs = numpy.linspace(0, 2*numpy.pi, 250)
     _ys = cls.fit_function(_xs, *popt)/(binning[1] - binning[0])
     spline = xInterpolatedUnivariateSplineLinear(_xs, _ys)
     mask = _y > 0.
     obs = _y[mask]
     exp = []
     for _min, _max in zip(binning[:-1], binning[1:]):
         exp.append(spline.integral(_min, _max))
     exp = numpy.array(exp)[mask]
     chisquare = ((exp - obs)**2/exp).sum()
     # Horrible hack.
     if popt[0] < 0.:
         popt[0] = -popt[0]
         popt[1] += 0.5*numpy.pi
     if popt[1] < 0.:
         popt[1] += numpy.pi
     return xModulationFitResults(popt, pcov, chisquare, len(mask))
Beispiel #31
0
    def __init__(self, num_samples=1000):
        """Constructor.

        Arguments
        ---------
        num_samples : int
            The number of data points used to sample (logarithmically) the
            photon energies when tabulating the absorption cross section
            internally.
        """
        file_path = os.path.join(XIMPOL_SRCMODEL, 'ascii', 'XsecFitParam.txt')
        if not os.path.exists(file_path):
            abort('Could not find %s' % file_path)
        # Read the data from file and calculate the minimum and maximum
        # energies.
        e_lo, e_hi, c0, c1, c2 = numpy.loadtxt(file_path, delimiter=',',
                                               unpack=True)
        emin = e_lo[0]
        emax = e_hi[-1]
        # Sample the energy logarithmically between emin and emax.
        _x = numpy.logspace(numpy.log10(emin), numpy.log10(emax), num_samples)
        # Here comes the interesting part---the cross section is tabulated
        # by means of a set of piecewise quadratic functions, and the
        # three coefficients are provided in each energy bin. We do some
        # magic with the numpy.digitize() function, returning for each value
        # in _x its bin index in the original table. Note that we need to
        # clip the array removing negative numbers, as the double log/exp
        # operations done in defining the binning where driving the first
        # index to -1.
        _bin = (numpy.digitize(_x, e_lo) - 1).clip(min=0)
        # Calculate the cross section values---compact, isn't it?
        _y = 1.0e-24*(c0[_bin] + c1[_bin]*_x + c2[_bin]*(_x**2.))/(_x**3.)
        # And, finally, build the basic spline underlying the model.
        _fmt = dict(xname='Energy', xunits='keV', yname='$\\sigma_{abs}$',
                    yunits='cm$^2$')
        self.xsection = xInterpolatedUnivariateSplineLinear(_x, _y, **_fmt)
Beispiel #32
0
integral_flux_spline = parse_light_curve(lc_file_path)
# This needs to be fixed---the conversion between integral energy flux
# and differential flux is wrong.
scale_factor = (2. - PL_INDEX)/(numpy.power(MAX_ENERGY, 2. - PL_INDEX) - \
                                numpy.power(MIN_ENERGY, 2. - PL_INDEX))
# Convert from erg to keV.
scale_factor *= 6.242e8
fmt = dict(yname='PL normalization', yunits='cm$^{-2}$ s$^{-1}$ keV$^{-1}$')
pl_normalization_spline = integral_flux_spline.scale(scale_factor, **fmt)
"""For the polarization degree we are literally making up something
that decreases with time.
"""
_t = integral_flux_spline.x
_p = 0.6 * (1. - (_t / integral_flux_spline.xmax())**0.1)
fmt = dict(xname='Time', xunits='s', yname='Polarization degree')
pol_degree_spline = xInterpolatedUnivariateSplineLinear(_t, _p, **fmt)


def energy_spectrum(E, t):
    return pl_normalization_spline(t) * numpy.power(E, -PL_INDEX)


def polarization_degree(E, t, ra, dec):
    return pol_degree_spline(t)


polarization_angle = constant(numpy.radians(28.))

grb = xPointSource('GRB',
                   GRB_RA,
                   GRB_DEC,
Beispiel #33
0
def chandra2ximpol(file_path, **kwargs):
    """Make the conversion from Chandra to ximpol.
    """
    assert(file_path.endswith('.fits'))
    if kwargs['outfile'] is None:
        outfile = os.path.basename(file_path).replace('.fits','_xipe.fits')
        mkdir(XIMPOL_DATA)
        kwargs['outfile'] = os.path.join(XIMPOL_DATA, outfile)
        logger.info('Setting output file path to %s...' % kwargs['outfile'])
    if os.path.exists(kwargs['outfile']) and not kwargs['clobber']:
        logger.info('Output file %s already exists.' % kwargs['outfile'])
        logger.info('Remove the file or set "clobber = True" to overwite it.')
        return kwargs['outfile']
   
    chrono = xChrono()
    logger.info('Setting the random seed to %d...' % kwargs['seed'])
    numpy.random.seed(kwargs['seed'])   
    logger.info('Loading the instrument response functions...')
    aeff, psf, modf, edisp = load_irfs(kwargs['irfname'])   
    c_aeff_name = 'chandra_acis_%s.arf' % kwargs['acis']
    c_aeff_file = os.path.join(XIMPOL_IRF, 'fits', c_aeff_name)   
    logger.info('Reading Chandra effective area data from %s...' % c_aeff_file)    
    c_aeff = load_chandra_arf(c_aeff_file) 
    _x = aeff.x
    _y = aeff.y/c_aeff(_x)
    aeff_ratio = xInterpolatedUnivariateSplineLinear(_x, _y)
    logger.info('Loading the input FITS event file...')
    hdu_list = fits.open(file_path)
    # If configuration file is not provided we assume a non-polarized source
    if kwargs['configfile'] is None:
        logger.info('Configuration file not provided.')
        logger.info('Setting polarization angle and degree to zero...')                 
        polarization_degree = constant(0.)
        polarization_angle = constant(0.)
    else:
        logger.info('Setting up the polarization source model...')
        module_name = os.path.basename(kwargs['configfile']).replace('.py', '')
        polarization_degree = imp.load_source(module_name, 
                                    kwargs['configfile']).POLARIZATION_DEGREE
        polarization_angle = imp.load_source(module_name, 
                                    kwargs['configfile']).POLARIZATION_ANGLE
    logger.info('Done %s.' % chrono)
    
    hdr = hdu_list[1].header
    tbdata = hdu_list[1].data        
    tstart = hdr['TSTART']
    tstop = hdr['TSTOP']
    obs_time = tstop - tstart
    logger.info('Chandra observation time: %i s.' %obs_time)
    ra_pnt = hdr['RA_PNT']
    dec_pnt = hdr['DEC_PNT']
    ROI_MODEL = xROIModel(ra_pnt, dec_pnt)
    
    logger.info('Reading Chandra data...')
    col_mc_energy = tbdata['energy']*0.001 # eV -> keV
    rnd_ratio = numpy.random.random(len(col_mc_energy))
    # The condition col_mc_energy < 10. is needed to avoid to take the bunch of 
    # events with energy > 10 keV included into the Chandra photon list (we
    # actually don't know the reason).
    _mask = (rnd_ratio < aeff_ratio(col_mc_energy))*(col_mc_energy<10.)
    # This is needed for over-sample the events in case of effective area ratio
    # greater than 1.
    _mask_ratio = (rnd_ratio < (aeff_ratio(col_mc_energy)-1.))*\
                                                            (col_mc_energy<10.)
    col_mc_energy = numpy.append(col_mc_energy[_mask], 
                                                    col_mc_energy[_mask_ratio])

    col_time = numpy.append(tbdata['time'][_mask],tbdata['time'][_mask_ratio])
    col_mc_ra, col_mc_dec = _get_radec(hdr, tbdata)
    col_mc_ra = numpy.append(col_mc_ra[_mask], col_mc_ra[_mask_ratio])
    col_mc_dec = numpy.append(col_mc_dec[_mask], col_mc_dec[_mask_ratio])

    duration = kwargs['duration']
    if not numpy.isnan(duration):
        logger.info('Setting the observation time to %d s...' % duration)                             
        scale = numpy.modf(duration/obs_time)
        tstop = tstart + duration
        logger.info('Scaling counts according to observation time...')
        col_mc_energy, col_time, col_mc_ra, col_mc_dec = time_scaling(scale, 
                                col_mc_energy, col_time, col_mc_ra, col_mc_dec)
          
    logger.info('Converting from Chandra to ximpol...')
    gti_list = [(tstart, tstop)]
    event_list = xMonteCarloEventList()    
    event_list.set_column('TIME', col_time)    
    event_list.set_column('MC_ENERGY', col_mc_energy)
    col_pha = edisp.matrix.rvs(col_mc_energy)
    event_list.set_column('PHA', col_pha)
    col_energy = edisp.ebounds(col_pha)
    event_list.set_column('ENERGY',col_energy)
    event_list.set_column('MC_RA', col_mc_ra)
    event_list.set_column('MC_DEC', col_mc_dec)
    col_ra, col_dec = psf.smear(col_mc_ra, col_mc_dec)
    event_list.set_column('RA', col_ra)
    event_list.set_column('DEC', col_dec)
    pol_degree = polarization_degree(col_mc_energy, col_time, col_mc_ra,
                                                              col_mc_dec)
    pol_angle = polarization_angle(col_mc_energy, col_time, col_mc_ra,
                                                              col_mc_dec)
    col_pe_angle = modf.rvs_phi(col_mc_energy, pol_degree, pol_angle)
    event_list.set_column('PE_ANGLE', col_pe_angle)
    # Set the phase to rnd [0-1] for all non-periodic sources.
    phase=numpy.random.uniform(0,1,len(col_dec))
    event_list.set_column('PHASE', phase)   
    event_list.set_column('MC_SRC_ID', numpy.zeros(len(col_dec)))  
    logger.info('Done %s.' % chrono)
    
    simulation_info = xSimulationInfo()
    simulation_info.gti_list = gti_list
    simulation_info.roi_model = ROI_MODEL
    simulation_info.irf_name = kwargs['irfname']
    simulation_info.aeff = aeff
    simulation_info.psf = psf
    simulation_info.modf = modf
    simulation_info.edisp = edisp
    event_list.sort()
    event_list.write_fits(kwargs['outfile'], simulation_info)
    
    logger.info('All done %s!' % chrono)
    return kwargs['outfile']
Beispiel #34
0
ROI_MODEL = xROIModel(GRB_RA, GRB_DEC)

lc_file_path = os.path.join(XIMPOL_CONFIG, 'ascii/GRB130427_Swift.dat')
integral_flux_spline = parse_light_curve(lc_file_path)
scale_factor = int_eflux2pl_norm(1, MIN_ENERGY, MAX_ENERGY, PL_INDEX)
fmt = dict(yname='PL normalization', yunits='cm$^{-2}$ s$^{-1}$ keV$^{-1}$')
pl_normalization_spline = integral_flux_spline.scale(scale_factor, **fmt)

"""For the polarization degree we are literally making up something
that decreases with time.
"""
_t = integral_flux_spline.x
_p = 0.6*(1. - (_t/integral_flux_spline.xmax())**0.1)
fmt = dict(xname='Time', xunits='s', yname='Polarization degree')
pol_degree_spline = xInterpolatedUnivariateSplineLinear(_t, _p, **fmt)

def energy_spectrum(E, t):
    return pl_normalization_spline(t)*numpy.power(E, -PL_INDEX)

def polarization_degree(E, t, ra, dec):
    return pol_degree_spline(t)

polarization_angle = constant(numpy.radians(28.))

grb = xPointSource('GRB', GRB_RA, GRB_DEC, energy_spectrum, polarization_degree,
                   polarization_angle,
                   min_validity_time=integral_flux_spline.xmin(),
                   max_validity_time=integral_flux_spline.xmax())

def sampling_time(tstart, tstop):
Beispiel #35
0
This has been converted into a text file by Niccolo` starting from an XSPEC
model that Domitilla provided. There's also a simplified version of the model
in the same folder called `gk_per_spectrum_simple.txt` but since from the
standpoint of the simulation that doesn't make any difference, we're
using the right one.

Note that the normaliztion of the integral energy flux between 2 and 8 keV
is provided into a separate file (see below) so that we need to integrate
this to have the conversion factors.
"""
# Read in the file and create the spline.
spectrum_file_path = _full_path("gk_per_spectrum_full.txt")
_emin, _emax, _flux = numpy.loadtxt(spectrum_file_path, unpack=True)
_e = numpy.sqrt(_emin * _emax)
_fmt = dict(xname="Energy", xunits="keV", yname="Differential flux", yunits="cm$^{-2}$ s$^{-1}$ keV$^{-1}$")
spectrum_spline = xInterpolatedUnivariateSplineLinear(_e, _flux, **_fmt)
# And we need a spline for the energy flux as well, so that we can integrate it
# and evaluate the average energy flux. This comes out around
# 1.0214032297e-10 erg/s/cm2, so it's in the right ballpark---good.
_fmt = dict(xname="Energy", xunits="keV", yname="Differential energy flux", yunits="cm$^{-2}$ s$^{-1}$")
espectrum_spline = xInterpolatedUnivariateSplineLinear(_e, _e * _flux, **_fmt)
average_eflux = keV2erg(espectrum_spline.integral(2.0, 8.0))


"""Parse the phasogram file.

This includes the integral energy flux between 2 and 8 keV, in erg cm^-2 s^-1
in 10 phase bins.

Despite the fact that the input values are most likely the average fluxes
within each phase bin, we just add 0.05 and consider them as the values
def parse(file_path, emin=1., emax=15., flux_scale=6.0067e-2):
    """Parse the input file with the complete spectral and polarization model.
    """
    logger.info('Parsing input file %s...' % file_path)
    energy, flux, angle, degree = numpy.loadtxt(file_path, unpack=True)
    flux *= flux_scale
    _mask = (energy >= emin) * (energy <= emax)
    return energy[_mask], flux[_mask], angle[_mask], degree[_mask]


energy, flux, degree, angle = parse(data_file_path)
fmt = dict(xname='Energy',
           xunits='keV',
           yname='Flux',
           yunits='cm$^{-2}$ s$^{-1}$ keV$^{-1}$')
spectral_model = xInterpolatedUnivariateSplineLinear(energy, flux, **fmt)
fmt = dict(xname='Energy', xunits='keV', yname='Polarization degree')
pol_degree = xInterpolatedUnivariateSplineLinear(energy, degree, **fmt)
fmt = dict(xname='Energy',
           xunits='keV',
           yname='Polarization angle',
           yunits='$^\\circ$')
pol_angle = xInterpolatedUnivariateSplineLinear(energy, angle, **fmt)


def energy_spectrum(E, t):
    return spectral_model(E)


def polarization_degree(E, t, ra, dec):
    return pol_degree(E)
Beispiel #37
0
    return flux*scale_factor

def energy_spectrum(E, t):
    return spectral_model(E)

def polarization_degree(E, t, ra, dec):
    return pol_degree(E)

def polarization_angle(E, t, ra, dec):
    return numpy.radians(pol_angle(E))

energy, flux, degree, angle = parse(file_path)
flux = scale_flux(energy, flux)
fmt = dict(xname='Energy', xunits='keV', yname='Flux',
           yunits='cm$^{-2}$ s$^{-1}$ keV$^{-1}$')
spectral_model = xInterpolatedUnivariateSplineLinear(energy, flux, **fmt)
fmt = dict(xname='Energy', xunits='keV', yname='Polarization degree')
pol_degree = xInterpolatedUnivariateSplineLinear(energy, degree, **fmt)
fmt = dict(xname='Energy', xunits='keV', yname='Polarization angle',
           yunits='$^\\circ$')
pol_angle = xInterpolatedUnivariateSplineLinear(energy, angle, **fmt)

ROI_MODEL = xROIModel(RA, DEC)

source = xPointSource('MCG-6-30-15', RA, DEC, energy_spectrum,
                      polarization_degree, polarization_angle,
                      max_validity_time=50000000.)

ROI_MODEL.add_source(source)

def display():