Esempio n. 1
0
    def __init__(self, data, chromatic=False, magformat='multiply'):
        self.chromatic = chromatic

        # get column names in input data
        if isinstance(data, Table):
            colnames = data.colnames
        elif isinstance(data, np.ndarray):
            colnames = data.dtype.names
        elif isinstance(data, dict):
            colnames = data.keys()
        else:
            raise ValueError('unrecognized data type')

        if self.chromatic:
            mapping = alias_map(colnames,
                                MLDATA_ALIASES,
                                required=CHROMATIC_MLDATA_REQUIRED_ALIASES)
        else:
            mapping = alias_map(colnames,
                                MLDATA_ALIASES,
                                required=ACHROMATIC_MLDATA_REQUIRED_ALIASES)

        self.magnification = np.asarray(data[mapping['magnification']])
        magform = magformat[:2].lower()
        if magform not in ['ad', 'mu']:
            raise RuntimeError("``magformat`` must be ``multiply`` or ``add``")
        if magform == 'ad':
            self.magnification = 10**(-0.4 * self.magnification)
        self.time = np.asarray(data[mapping['time']])

        if self.chromatic:
            self.wavelength = np.asarray(data[mapping['wavelength']])

        # ensure columns are equal length
        if isinstance(data, dict):
            if not (len(self.time) == len(self.magnification)):
                raise ValueError("unequal column lengths")
            if self.chromatic:
                if not (len(self.time) == len(self.wavelength)):
                    raise ValueError("unequal column lengths")
Esempio n. 2
0
def test_alias_map():
    mapping = utils.alias_map(['A', 'B_', 'foo'],
                              {'a': set(['a', 'a_']), 'b': set(['b', 'b_'])})
    assert mapping == {'a': 'A', 'b': 'B_'}
Esempio n. 3
0
def realize_lcs(observations,
                model,
                params,
                thresh=None,
                trim_observations=False,
                scatter=True,
                snrFunc=None):
    """***A copy of SNCosmo's function, just to add a SNR function
    Realize data for a set of SNe given a set of observations.

    Parameters
    ----------
    observations : `~astropy.table.Table` or `~numpy.ndarray`
        Table of observations. Must contain the following column names:
        ``band``, ``time``, ``zp``, ``zpsys``, ``gain``, ``skynoise``.
    model : `sncosmo.Model`
        The model to use in the simulation.
    params : list (or generator) of dict
        List of parameters to feed to the model for realizing each light curve.
    thresh : float, optional
        If given, light curves are skipped (not returned) if none of the data
        points have signal-to-noise greater than ``thresh``.
    trim_observations : bool, optional
        If True, only observations with times between
        ``model.mintime()`` and ``model.maxtime()`` are included in
        result table for each SN. Default is False.
    scatter : bool, optional
        If True, the ``flux`` value of the realized data is calculated by
        adding  a random number drawn from a Normal Distribution with a
        standard deviation equal to the ``fluxerror`` of the observation to
        the bandflux value of the observation calculated from model. Default
        is True.

    Returns
    -------
    sne : list of `~astropy.table.Table`
        Table of realized data for each item in ``params``.

    Notes
    -----
    ``skynoise`` is the image background contribution to the flux measurement
    error (in units corresponding to the specified zeropoint and zeropoint
    system). To get the error on a given measurement, ``skynoise`` is added
    in quadrature to the photon noise from the source.

    It is left up to the user to calculate ``skynoise`` as they see fit as the
    details depend on how photometry is done and possibly how the PSF is
    is modeled. As a simple example, assuming a Gaussian PSF, and perfect
    PSF photometry, ``skynoise`` would be ``4 * pi * sigma_PSF * sigma_pixel``
    where ``sigma_PSF`` is the standard deviation of the PSF in pixels and
    ``sigma_pixel`` is the background noise in a single pixel in counts.

    """

    RESULT_COLNAMES = ('time', 'band', 'flux', 'fluxerr', 'zp', 'zpsys')
    lcs = []

    # Copy model so we don't mess up the user's model.
    model = copy(model)

    # get observations as a Table
    if not isinstance(observations, Table):
        if isinstance(observations, np.ndarray):
            observations = Table(observations)
        else:
            raise ValueError("observations not understood")

    # map column name aliases
    colname = alias_map(observations.colnames,
                        OBSERVATIONS_ALIASES,
                        required=OBSERVATIONS_REQUIRED_ALIASES)

    # result dtype used when there are no observations
    band_dtype = observations[colname['band']].dtype
    zpsys_dtype = observations[colname['zpsys']].dtype
    result_dtype = ('f8', band_dtype, 'f8', 'f8', 'f8', zpsys_dtype)

    for p in params:
        model.set(**p)

        # Select times for output that fall within tmin amd tmax of the model
        if trim_observations:
            mask = ((observations[colname['time']] > model.mintime()) &
                    (observations[colname['time']] < model.maxtime()))
            snobs = observations[mask]
        else:
            snobs = observations

        # explicitly detect no observations and add an empty table
        if len(snobs) == 0:
            if thresh is None:
                lcs.append(
                    Table(names=RESULT_COLNAMES, dtype=result_dtype, meta=p))
            continue
        flux = model.bandflux(snobs[colname['band']],
                              snobs[colname['time']],
                              zp=snobs[colname['zp']],
                              zpsys=snobs[colname['zpsys']])
        if snrFunc is not None:
            fluxerr = flux / snrFunc(-2.5 * np.log10(flux) +
                                     snobs[colname['zp']])
        else:
            fluxerr = np.sqrt(snobs[colname['skynoise']]**2 +
                              np.abs(flux) / snobs[colname['gain']])

        # Scatter fluxes by the fluxerr
        # np.atleast_1d is necessary here because of an apparent bug in
        # np.random.normal: when the inputs are both length 1 arrays,
        # the output is a Python float!
        if scatter:
            flux = np.atleast_1d(np.random.normal(flux, fluxerr))

        # Check if any of the fluxes are significant
        if thresh is not None and not np.any(flux / fluxerr > thresh):
            continue

        data = [
            snobs[colname['time']], snobs[colname['band']], flux, fluxerr,
            snobs[colname['zp']], snobs[colname['zpsys']]
        ]

        lcs.append(Table(data, names=RESULT_COLNAMES, meta=p))

    return lcs