Ejemplo n.º 1
0
    def rvs_event_list(self, aeff, psf, modf, edisp, **kwargs):
        """Extract an event list for the full ROI.

        Arguments
        ---------
        aeff : :py:class:`ximpol.irf.arf.xEffectiveArea` object.
            The effective area to be used.

        psf : :py:class:`ximpol.irf.psf.xPointSpreadFunction` object.
            The PSF to be used.

        modf : :py:class:`ximpol.irf.mrf.xModulationFactor` object.
            The modulation factor to the used.

        edisp : :py:class:`ximpol.irf.rmf.xEnergyDispersion` object.
            The energy dispersion to be used.

        sampling_time : array
            The array to sample the source light curve.

        Warning
        -------
        The sampling_time should not be the same for all sources, and each
        source should be able to decide its own in a sensible way.
        (See issue #44.)
        """
        event_list = xMonteCarloEventList()
        for source in self.values():
            logger.info('Generating event list for source "%s"...' %\
                        source.name)
            event_list += source.rvs_event_list(aeff, psf, modf, edisp,
                                                **kwargs)
            event_list.apply_vignetting(aeff, self.ra, self.dec)
        event_list.sort()
        return event_list
Ejemplo n.º 2
0
    def rvs_event_list(self, aeff, psf, modf, edisp, **kwargs):
        """Extract a random event list for the model component.

        TODO: here we should pass the sampling phase, instead?

        TODO: properly take into account the derivatives in the ephemeris.
        """
        # Create the event list and the count spectrum.
        event_list = xMonteCarloEventList()
        # Mind the count spectrum is made in phase!
        sampling_phase = numpy.linspace(0., 1., 100)
        count_spectrum = xCountSpectrum(self.energy_spectrum, aeff,
                                        sampling_phase, self.column_density,
                                        self.redshift)
        # All this is not properly taking into account the ephemeris.
        min_time = kwargs['tstart']
        max_time = kwargs['tstop']
        #min_time=sampling_time[0]
        #max_time = sampling_time[-1]
        delta_time = (max_time - min_time)
        period = self.ephemeris.period(min_time)
        # This is not accurate, as we are effectively discarding the last
        # fractional period. Need to think about it.
        num_periods = int(delta_time/period)
        num_expected_events = delta_time*count_spectrum.light_curve.norm()
        # Extract the number of events to be generated based on the integral
        # of the light curve over the simulation time.
        num_events = numpy.random.poisson(num_expected_events)
        logger.info('About to generate %d events...' % num_events)
        # Extract the event phases and sort them.
        col_phase = count_spectrum.light_curve.rvs(num_events)
        event_list.set_column('PHASE', col_phase)
        col_period = numpy.random.randint(0, num_periods, num_events)
        col_time = (col_period + col_phase)*period
        event_list.set_column('TIME', col_time)
        # Extract the MC energies and smear them with the energy dispersion.
        col_mc_energy = count_spectrum.rvs(col_phase)
        event_list.set_column('MC_ENERGY', col_mc_energy)
        col_pha = edisp.matrix.rvs(col_mc_energy)
        event_list.set_column('PHA', col_pha)
        event_list.set_column('ENERGY', edisp.ebounds(col_pha))
        # Extract the MC sky positions and smear them with the PSF.
        col_mc_ra, col_mc_dec = self.rvs_sky_coordinates(num_events)
        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)
        # Extract the photoelectron emission directions.
        pol_degree = self.polarization_degree(col_mc_energy, col_phase,
                                              col_mc_ra, col_mc_dec)
        pol_angle = self.polarization_angle(col_mc_energy, col_phase,
                                            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 source ID.
        event_list.set_column('MC_SRC_ID', self.identifier)
        event_list.sort()
        return event_list
Ejemplo n.º 3
0
 def rvs_event_list(self, aeff, psf, modf, edisp, **kwargs):
     """Extract a random event list for the model component.
     """
     # Create the event list and the count spectrum.
     event_list = xMonteCarloEventList()
     tsamples = self.sampling_time(kwargs['tstart'], kwargs['tstop'])
     logger.info('Sampling times: %s' % tsamples)
     count_spectrum = xCountSpectrum(self.energy_spectrum, aeff, tsamples,
                                     self.column_density, self.redshift)
     # Extract the number of events to be generated based on the integral
     # of the light curve over the simulation time.
     num_events = numpy.random.poisson(count_spectrum.light_curve.norm())
     logger.info('About to generate %d events...' % num_events)
     # Extract the event times and sort them.
     col_time = count_spectrum.light_curve.rvs(num_events)
     col_time.sort()
     event_list.set_column('TIME', col_time)
     # Extract the MC energies and smear them with the energy dispersion.
     col_mc_energy = count_spectrum.rvs(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)
     event_list.set_column('ENERGY', edisp.ebounds(col_pha))
     # Extract the MC sky positions and smear them with the PSF.
     col_mc_ra, col_mc_dec = self.rvs_sky_coordinates(num_events)
     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)
     # Extract the photoelectron emission directions.
     pol_degree = self.polarization_degree(col_mc_energy, col_time,
                                           col_mc_ra, col_mc_dec)
     pol_angle = self.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 source ID.
     event_list.set_column('MC_SRC_ID', self.identifier)
     # Set the phase to rnd [0-1] for all non-periodic sources.
     phase = numpy.random.uniform(0., 1., len(col_pe_angle))
     event_list.set_column('PHASE', phase)
     return event_list
Ejemplo n.º 4
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']
Ejemplo n.º 5
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)
    c_vign_name = "chandra_vignet.fits"
    c_vign_file = os.path.join(XIMPOL_IRF, "fits", c_vign_name)
    logger.info("Reading Chandra vignetiing data from %s..." % c_vign_file)
    c_vign = _load_chandra_vign(c_vign_file)
    aeff_ratio = _make_aeff_ratio(aeff, c_aeff, c_vign)
    logger.info("Done %s." % chrono)

    logger.info("Loading the input FITS event file...")
    hdu_list = fits.open(file_path)
    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
    col_mc_ra, col_mc_dec = _get_radec(hdr, tbdata)
    ref_skyccord = SkyCoord(ra_pnt, dec_pnt, unit="deg")
    evt_skycoord = SkyCoord(col_mc_ra, col_mc_dec, unit="deg")
    separation = evt_skycoord.separation(ref_skyccord).arcmin

    logger.info("Converting from Chandra to ximpol...")
    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, separation)) * (col_mc_energy < 10.0)
    # 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, separation) - 1.0)) * (col_mc_energy < 10.0)
    col_mc_energy = numpy.append(col_mc_energy[_mask], col_mc_energy[_mask_ratio])
    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])
    col_time = numpy.append(tbdata["time"][_mask], tbdata["time"][_mask_ratio])

    # If duration parameter is provided the counts are down- or oversampled.
    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
        )

    # The Ra Dec coordinates are calculated here because they are needed in
    # source id definition (in case of kwargs['chandra']==False)
    col_ra, col_dec = psf.smear(col_mc_ra, col_mc_dec)
    # The default source id in case of no regfile and for regions not selected
    # is zero. For regions selected in the regfile the source id is determined
    # by the order of definition (starting with 1).
    logger.info("Defining source id...")
    src_id = numpy.zeros(len(col_mc_dec))
    n_reg = -1
    if kwargs["regfile"] is not None:
        regions = pyregion.open(kwargs["regfile"])
        for n_reg, region in enumerate(regions):
            if kwargs["mc"] is True:
                mask = filter_region(region, col_mc_ra, col_mc_dec)
            else:
                mask = filter_region(region, col_ra, col_dec)
            src_id[mask] = n_reg + 1

    # If configuration file is not provided we assume a non-polarized source.
    # In case of configfile with polarization model defined in different
    # regions the photoelectron distribution is generated according to them.
    if kwargs["configfile"] is None:
        logger.info("Configuration file not provided.")
        logger.info("Setting polarization angle and degree to zero...")
        polarization_degree = constant(0.0)
        polarization_angle = constant(0.0)
        pol_dict = {0: [polarization_degree, polarization_angle]}
        for k in range(1, n_reg + 2):
            pol_dict[k] = [polarization_degree, polarization_angle]
    else:
        logger.info("Setting up the polarization source model...")
        module_name = os.path.basename(kwargs["configfile"]).replace(".py", "")
        pol_dict = imp.load_source(module_name, kwargs["configfile"]).POLARIZATION_DICT
    logger.info("Generating photoelectron azimuthal distribution...")
    col_pe_angle = numpy.empty(len(col_mc_dec))
    for key, pol_list in pol_dict.items():
        _mask_src = src_id == key
        pol_degree = pol_list[0](
            col_mc_energy[_mask_src], col_time[_mask_src], col_mc_ra[_mask_src], col_mc_dec[_mask_src]
        )
        pol_angle = pol_list[1](
            col_mc_energy[_mask_src], col_time[_mask_src], col_mc_ra[_mask_src], col_mc_dec[_mask_src]
        )
        col_pe_angle[_mask_src] = modf.rvs_phi(col_mc_energy[_mask_src], pol_degree, pol_angle)

    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)
    event_list.set_column("RA", col_ra)
    event_list.set_column("DEC", col_dec)
    event_list.set_column("MC_SRC_ID", src_id)
    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)
    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"]