Beispiel #1
0
def test_combine(tmpdir):
    """Test ligo-skymap-combine."""
    fn1 = str(tmpdir / 'skymap1.fits.gz')
    fn2 = str(tmpdir / 'skymap2.fits.gz')
    fn3 = str(tmpdir / 'joint_skymap.fits.gz')

    # generate a hemisphere of constant probability
    nside1 = 32
    npix1 = ah.nside_to_npix(nside1)
    m1 = np.zeros(npix1)
    disc_idx = hp.query_disc(nside1, (1, 0, 0), np.pi / 2)
    m1[disc_idx] = 1
    m1 /= m1.sum()
    hp.write_map(fn1,
                 m1,
                 column_names=['PROBABILITY'],
                 extra_header=[('INSTRUME', 'X1')])

    # generate another hemisphere of constant probability
    # but with higher resolution and rotated 90 degrees
    nside2 = 64
    npix2 = ah.nside_to_npix(nside2)
    m2 = np.zeros(npix2)
    disc_idx = hp.query_disc(nside2, (0, 1, 0), np.pi / 2)
    m2[disc_idx] = 1
    m2 /= m2.sum()
    hp.write_map(fn2,
                 m2,
                 column_names=['PROBABILITY'],
                 extra_header=[('INSTRUME', 'Y1')])

    run_entry_point('ligo-skymap-combine', fn1, fn2, fn3)

    m3 = hp.read_map(fn3, nest=True)
    npix3 = len(m3)
    nside3 = ah.npix_to_nside(npix3)
    pix_area3 = ah.nside_to_pixel_area(nside3).to_value(u.sr)

    # resolution must match the highest original resolution
    assert npix3 == npix2
    # probability must be normalized to 1
    assert m3.sum() == pytest.approx(1)
    # support must be ¼ of the sphere
    tolerance = 10 * ah.nside_to_pixel_area(nside1).to_value(u.sr)
    assert sum(m3 > 0) * pix_area3 == pytest.approx(np.pi, abs=tolerance)

    # generate a BAYESTAR-like map with mock distance information
    d_mu = np.zeros_like(m1)
    d_sigma = np.ones_like(m1)
    d_norm = np.ones_like(m1)
    io.write_sky_map(fn1, [m1, d_mu, d_sigma, d_norm])

    run_entry_point('ligo-skymap-combine', fn1, fn2, fn3)

    m3, meta3 = io.read_sky_map(fn3, nest=True, distances=True)

    # check that marginal distance moments match what was simulated
    mean, std, _ = distance.parameters_to_moments(d_mu[0], d_sigma[0])
    assert meta3['distmean'] == pytest.approx(mean)
    assert meta3['diststd'] == pytest.approx(std)
Beispiel #2
0
def input_skymap(order1, d_order, fraction):
    """Construct a test multi-resolution sky map, with values that are
    proportional to the NESTED pixel index.

    To make the test more interesting by mixing together multiple resolutions,
    part of the sky map is refined to a higher order.

    Parameters
    ----------
    order1 : int
        The HEALPix resolution order.
    d_order : int
        The increase in orer for part of the sky map.
    fraction : float
        The fraction of the original pixels to refine.

    """
    order2 = order1 + d_order
    npix1 = ah.nside_to_npix(ah.level_to_nside(order1))
    npix2 = ah.nside_to_npix(ah.level_to_nside(order2))
    ipix1 = np.arange(npix1)
    ipix2 = np.arange(npix2)

    # Create a random sky map.
    area = ah.nside_to_pixel_area(ah.level_to_nside(order1)).to_value(u.sr)
    probdensity = np.random.uniform(0, 1, npix1)
    prob = probdensity * area
    normalization = prob.sum()
    prob /= normalization
    probdensity /= normalization
    distmean = np.random.uniform(100, 110, npix1)
    diststd = np.random.uniform(0, 1 / np.sqrt(3) - 0.1, npix1) * distmean
    distmu, distsigma, distnorm = moments_to_parameters(distmean, diststd)
    assert np.all(np.isfinite(distmu))

    data1 = table.Table({
        'UNIQ': moc.nest2uniq(order1, ipix1),
        'PROBDENSITY': probdensity,
        'DISTMU': distmu,
        'DISTSIGMA': distsigma,
        'DISTNORM': distnorm
    })

    # Add some upsampled pixels.
    data2 = table.Table(np.repeat(data1, npix2 // npix1))
    data2['UNIQ'] = moc.nest2uniq(order2, ipix2)
    n = int(npix1 * (1 - fraction))
    result = table.vstack((data1[:n], data2[n * npix2 // npix1:]))

    # Add marginal distance mean and standard deviation.
    rbar = (prob * distmean).sum()
    r2bar = (prob * (np.square(diststd) + np.square(distmean))).sum()
    result.meta['distmean'] = rbar
    result.meta['diststd'] = np.sqrt(r2bar - np.square(rbar))

    return result
Beispiel #3
0
def test_rasterize_downsample(order_in, d_order_in, fraction_in, order_out):
    npix_in = ah.nside_to_npix(ah.level_to_nside(order_in))
    npix_out = ah.nside_to_npix(ah.level_to_nside(order_out))
    skymap_in = input_skymap(order_in, d_order_in, fraction_in)
    skymap_out = moc.rasterize(skymap_in, order_out)

    assert len(skymap_out) == npix_out
    reps = npix_in // npix_out
    expected = np.mean(np.arange(npix_in).reshape(-1, reps), axis=1)
    np.testing.assert_array_equal(skymap_out['VALUE'], expected)
Beispiel #4
0
def test_rasterize_upsample(order_in, d_order_in, fraction_in, order_out):
    npix_in = ah.nside_to_npix(ah.level_to_nside(order_in))
    npix_out = ah.nside_to_npix(ah.level_to_nside(order_out))
    skymap_in = input_skymap(order_in, d_order_in, fraction_in)
    skymap_out = moc.rasterize(skymap_in, order_out)

    assert len(skymap_out) == npix_out
    ipix = np.arange(npix_in)
    reps = npix_out // npix_in
    for i in range(reps):
        np.testing.assert_array_equal(skymap_out['VALUE'][i::reps], ipix)
Beispiel #5
0
def test_reproject_healpix_to_image_round_trip(wcsapi, nside, nested,
                                               healpix_system, image_system,
                                               dtype):
    """Test round-trip HEALPix->WCS->HEALPix conversion for a random map,
    with a WCS projection large enough to store each HEALPix pixel"""

    npix = nside_to_npix(nside)
    healpix_data = np.random.uniform(size=npix).astype(dtype)

    reference_header = get_reference_header(oversample=2, nside=nside)

    wcs_out = WCS(reference_header)
    shape_out = reference_header['NAXIS2'], reference_header['NAXIS1']

    if wcsapi:
        wcs_out = as_high_level_wcs(wcs_out)

    image_data, footprint = reproject_from_healpix(
        (healpix_data, healpix_system),
        wcs_out,
        shape_out=shape_out,
        order='nearest-neighbor',
        nested=nested)

    healpix_data_2, footprint = reproject_to_healpix((image_data, wcs_out),
                                                     healpix_system,
                                                     nside=nside,
                                                     order='nearest-neighbor',
                                                     nested=nested)

    np.testing.assert_array_equal(healpix_data, healpix_data_2)
Beispiel #6
0
def _reconstruct_nested_breadthfirst(m, extra):
    m = np.asarray(m)
    max_npix = len(m)
    max_nside = ah.npix_to_nside(max_npix)
    max_order = ah.nside_to_level(max_nside)
    seen = np.zeros(max_npix, dtype=bool)

    for order in range(max_order + 1):
        nside = ah.level_to_nside(order)
        npix = ah.nside_to_npix(nside)
        skip = max_npix // npix
        if skip > 1:
            b = m.reshape(-1, skip)
            a = b[:, 0].reshape(-1, 1)
            b = b[:, 1:]
            aseen = seen.reshape(-1, skip)
            eq = ((a == b) | ((a != a) & (b != b))).all(1) & (~aseen).all(1)
        else:
            eq = ~seen
        for ipix in np.flatnonzero(eq):
            ipix0 = ipix * skip
            ipix1 = (ipix + 1) * skip
            seen[ipix0:ipix1] = True
            if extra:
                yield _HEALPixTreeVisitExtra(nside, max_nside, ipix, ipix0,
                                             ipix1, m[ipix0])
            else:
                yield _HEALPixTreeVisit(nside, ipix)
Beispiel #7
0
 def flat_bitmap(self):
     """Return flattened HEALPix representation."""
     m = np.empty(ah.nside_to_npix(ah.level_to_nside(self.order)))
     for nside, full_nside, ipix, ipix0, ipix1, samples in self.visit():
         pixarea = ah.nside_to_pixel_area(nside).to_value(u.sr)
         m[ipix0:ipix1] = len(samples) / pixarea
     return m
Beispiel #8
0
def cartesian_gaussian_to_skymap(level, mean, cov):
    """Convert a 3D Cartesian Gaussian to a 3D sky map."""
    # Set up HEALPix grid.
    nside = 2**level
    npix = ah.nside_to_npix(nside)
    ipix = np.arange(npix)
    coords = np.column_stack(hp.pix2vec(nside, ipix, nest=True))

    # Create sky map using same method as KDE to convert from Cartesian
    # to spherical representation. This is just a special case where there
    # is only a single cluster and a single KDE sample.
    means = mean[np.newaxis, ..., np.newaxis]
    inv_covs = np.linalg.inv(cov)[np.newaxis, ...]
    weights = np.ones(1)
    probdensity, distmean, diststd = np.transpose([
        cartesian_kde_to_moments(n, means, inv_covs, weights) for n in coords
    ])

    # Create 3D, multi-order sky map.
    uniq = nest2uniq(level, ipix)
    distmu, distsigma, distnorm = moments_to_parameters(distmean, diststd)
    return Table({
        'UNIQ': uniq,
        'PROBDENSITY': probdensity,
        'DISTMU': distmu,
        'DISTSIGMA': distsigma,
        'DISTNORM': distnorm
    })
Beispiel #9
0
    def _bayestar_adaptive_grid(self, top_nside=16, rounds=8):
        """Implement of the BAYESTAR adaptive mesh refinement scheme as
        described in Section VI of Singer & Price 2016, PRD, 93, 024013
        (http://dx.doi.org/10.1103/PhysRevD.93.024013).

        FIXME: Consider refactoring BAYESTAR itself to perform the adaptation
        step in Python.
        """
        top_npix = ah.nside_to_npix(top_nside)
        nrefine = top_npix // 4
        cells = zip([0] * nrefine, [top_nside // 2] * nrefine, range(nrefine))
        for iround in range(rounds - 1):
            print('adaptive refinement round {} of {} ...'.format(
                iround + 1, rounds - 1))
            cells = sorted(cells, key=lambda p_n_i: p_n_i[0] / p_n_i[1]**2)
            new_nside, new_ipix = np.transpose([
                (nside * 2, ipix * 4 + i)
                for _, nside, ipix in cells[-nrefine:] for i in range(4)
            ])
            theta, phi = hp.pix2ang(new_nside, new_ipix, nest=True)
            ra = phi
            dec = 0.5 * np.pi - theta
            p = self(np.column_stack((ra, dec)))
            cells[-nrefine:] = zip(p, new_nside, new_ipix)
        return cells
Beispiel #10
0
def input_skymap(order1, d_order, fraction):
    """Construct a test multi-resolution sky map, with values that are
    proportional to the NESTED pixel index.

    To make the test more interesting by mixing together multiple resolutions,
    part of the sky map is refined to a higher order.

    Parameters
    ----------
    order1 : int
        The HEALPix resolution order.
    d_order : int
        The increase in orer for part of the sky map.
    fraction : float
        The fraction of the original pixels to refine.

    """
    order2 = order1 + d_order
    npix1 = ah.nside_to_npix(ah.level_to_nside(order1))
    npix2 = ah.nside_to_npix(ah.level_to_nside(order2))
    ipix1 = np.arange(npix1)
    ipix2 = np.arange(npix2)

    data1 = table.Table({
        'UNIQ': moc.nest2uniq(order1, ipix1),
        'VALUE': ipix1.astype(float),
        'VALUE2': np.pi * ipix1.astype(float)
    })

    data2 = table.Table({
        'UNIQ':
        moc.nest2uniq(order2, ipix2),
        'VALUE':
        np.repeat(ipix1, npix2 // npix1).astype(float),
        'VALUE2':
        np.pi * np.repeat(ipix1, npix2 // npix1).astype(float)
    })

    n = int(npix1 * (1 - fraction))
    return table.vstack((data1[:n], data2[n * npix2 // npix1:]))
def make_earth_vis_grids(nside=32, n_reps=1):
    from acis_taco import calc_earth_vis, RAD_EARTH, acis_taco
    hp = astropy_healpix.HEALPix(nside=nside, order='nested')
    npix = astropy_healpix.nside_to_npix(nside)
    print(f'npix={npix}')
    lons, lats = hp.healpix_to_lonlat(np.arange(npix))
    time0 = time.time()

    # Allow randomization between altitudes
    for i_rep in range(n_reps):
        vis_arrays = []
        # Randomize the ray-trace points for each rep
        acis_taco._RANDOM_SALT = None
        acis_taco.SPHERE_XYZ = acis_taco.random_hemisphere(acis_taco.N_SPHERE)
        acis_taco.SPHERE_X = acis_taco.SPHERE_XYZ[:, 0].copy()

        for i_alt, alt in enumerate(alts):

            srs = SphericalRepresentation(lon=lons,
                                          lat=lats,
                                          distance=alt + RAD_EARTH)
            xyzs = srs.to_cartesian()
            peb_xs = xyzs.x.to_value()
            peb_ys = xyzs.y.to_value()
            peb_zs = xyzs.z.to_value()
            vis = []
            for peb_x, peb_y, peb_z in zip(peb_xs, peb_ys, peb_zs):
                _, illums, _ = calc_earth_vis(
                    p_earth_body=[peb_x, peb_y, peb_z])
                vis.append(np.sum(illums))
            vis = np.array(vis)
            vis_arrays.append(vis)
            vis_grid = np.vstack(vis_arrays)
            if i_alt % 10 == 0:
                print(
                    f'alt={alt / 1000:.2f} km at dt={time.time() - time0:.1f}')

        ii = 1
        while True:
            filename = Path(f'earth_vis_grid_nside{nside}_rep{ii}.npy')
            if filename.exists():
                ii += 1
                continue
            else:
                print(f'Saving {filename}')
                np.save(filename, vis_grid)
                break

    return vis_grid
def make_earth_vis_grid_fits(nside=32):
    """Collect the reps and average and write to FITS"""
    from acis_taco import RAD_EARTH
    ii = 1
    vis_list = []
    while True:
        filename = Path(f'earth_vis_grid_nside{nside}_rep{ii}.npy')
        if filename.exists():
            # print(f'Reading {filename}')
            vis = np.load(filename)
            vis_list.append(vis)
            ii += 1
        else:
            break

    npix = astropy_healpix.nside_to_npix(nside)

    visl = np.array(vis_list)
    print(visl.shape)

    vis = visl.mean(axis=0)

    # Some sanity checking
    assert vis.shape == (100, npix)
    assert np.min(vis) == 0.0
    assert np.max(vis) < 3.0

    scale = 2**16 / 3.0
    visi = np.round(vis * scale)
    assert np.max(visi) < 2**16

    # Convert to 16 bits.  Also transpose so that interpolation along
    # distance is contiguous in memory.
    # BTW see: https://github.com/astropy/astropy/issues/8726 for the
    # origin of the .copy()
    visi2 = visi.astype(np.uint16).transpose().copy()

    hdu = fits.PrimaryHDU(visi2)
    hdu.header['nside'] = nside
    hdu.header['alt_min'] = alt_min.to_value(u.m)
    hdu.header['alt_max'] = alt_max.to_value(u.m)
    hdu.header['n_alt'] = n_alt
    hdu.header['scale'] = scale
    hdu.header['earthrad'] = RAD_EARTH

    filename = Path(f'earth_vis_grid_nside{nside}.fits.gz')
    print(f'Writing {filename}')
    hdul = fits.HDUList([hdu])
    hdul.writeto(filename, overwrite=True)
Beispiel #13
0
def test_allsky_axes(rcparams, coordsys, units, proj):
    """Test projection of a HEALPix image onto allsky axes, either
    in celestial or earth-fixed coordinates.
    """
    # Set up axes. (The obstime has an effect only for geographic axes.)
    fig = plt.figure(figsize=(6, 4))
    ax = fig.add_subplot(111,
                         projection=coordsys + ' ' + units + ' ' + proj,
                         obstime='2017-08-17T12:41:04.444458')

    # Build a low-resolution example HEALPix sky map:
    # the value is equal to the right ascension.
    nside = 8
    npix = ah.nside_to_npix(nside)
    ra, dec = hp.pix2ang(nside, np.arange(npix), lonlat=True)
    img = np.sin(np.deg2rad(ra))

    # Plot, show grid, and return figure.
    ax.imshow_hpx((img, 'ICRS'))
    ax.grid()
    return fig
Beispiel #14
0
def test_flatten(tmpdir, order_in, d_order_in, fraction_in, nside_out):
    """Test ligo-skymap-flatten."""
    input_filename = str(tmpdir / 'bayestar.fits')
    output_filename = str(tmpdir / 'bayestar.fits.gz')

    skymap = input_skymap(order_in, d_order_in, fraction_in)
    write_sky_map(input_filename, skymap, moc=True)
    expected_distmean = skymap.meta['distmean']
    expected_diststd = skymap.meta['diststd']

    args = ['ligo-skymap-flatten', input_filename, output_filename]
    if nside_out is not None:
        args.extend(['--nside', str(nside_out)])
    run_entry_point(*args)

    (prob, distmu, distsigma, distnorm), _ = read_sky_map(output_filename,
                                                          distances=True)
    distmean, diststd = parameters_to_marginal_moments(prob, distmu, distsigma)

    if nside_out is not None:
        assert len(prob) == ah.nside_to_npix(nside_out)

    assert prob.sum() == pytest.approx(1)
    assert distmean == pytest.approx(expected_distmean)
    assert diststd == pytest.approx(expected_diststd)

    # Now try removing the distance information.
    skymap_2d = skymap['UNIQ', 'PROBDENSITY']
    del skymap_2d.meta['distmean']
    del skymap_2d.meta['diststd']
    write_sky_map(input_filename, skymap_2d, moc=True, ovewrite=True)

    args = ['ligo-skymap-flatten', input_filename, output_filename]
    if nside_out is not None:
        args.extend(['--nside', str(nside_out)])
    run_entry_point(*args)

    prob_2d, _ = read_sky_map(output_filename)
    assert np.all(prob == prob_2d)
Beispiel #15
0
def test_reproject_healpix_to_image_round_trip(
        nside, nested, healpix_system, image_system, dtype):
    """Test round-trip HEALPix->WCS->HEALPix conversion for a random map,
    with a WCS projection large enough to store each HEALPix pixel"""

    npix = nside_to_npix(nside)
    healpix_data = np.random.uniform(size=npix).astype(dtype)

    reference_header = get_reference_header(oversample=2, nside=nside)

    wcs_out = WCS(reference_header)
    shape_out = reference_header['NAXIS2'], reference_header['NAXIS1']

    image_data, footprint = reproject_from_healpix(
        (healpix_data, healpix_system), wcs_out, shape_out=shape_out,
        order='nearest-neighbor', nested=nested)

    healpix_data_2, footprint = reproject_to_healpix(
        (image_data, wcs_out), healpix_system,
        nside=nside, order='nearest-neighbor', nested=nested)

    np.testing.assert_array_equal(healpix_data, healpix_data_2)
Beispiel #16
0
def smooth_ud_grade(m, nside, nest=False):
    """Resample a sky map to a new resolution using bilinear interpolation.

    Parameters
    ----------
    m : np.ndarray
        The input HEALPix array.

    nest : bool, default=False
        Indicates whether the input sky map is in nested rather than
        ring-indexed HEALPix coordinates (default: ring).

    Returns
    -------
    new_m : np.ndarray
        The resampled HEALPix array. The sum of `m` is approximately preserved.

    """
    npix = ah.nside_to_npix(nside)
    theta, phi = hp.pix2ang(nside, np.arange(npix), nest=nest)
    new_m = hp.get_interp_val(m, theta, phi, nest=nest)
    return new_m * len(m) / len(new_m)
Beispiel #17
0
def test_rasterize_default(order):
    npix = ah.nside_to_npix(ah.level_to_nside(order))
    skymap_in = input_skymap(order, 0, 0)
    skymap_out = moc.rasterize(skymap_in)
    assert len(skymap_out) == npix
Beispiel #18
0
            m = m[hp.ring2nest(nside, np.arange(npix))]
        elif not m.meta['nest'] and nest:
            m = m[hp.nest2ring(nside, np.arange(npix))]

    if moc:
        return m
    elif distances:
        return tuple(np.asarray(m[name])
                     for name in DEFAULT_NESTED_NAMES), m.meta
    else:
        return np.asarray(m[DEFAULT_NESTED_NAMES[0]]), m.meta


if __name__ == '__main__':
    import os
    nside = 128
    npix = ah.nside_to_npix(nside)
    prob = np.random.random(npix)
    prob /= sum(prob)

    write_sky_map('test.fits.gz',
                  prob,
                  objid='FOOBAR 12345',
                  gps_time=1049492268.25,
                  creator=os.path.basename(__file__),
                  url='http://www.youtube.com/watch?v=0ccKPSVQcFk',
                  origin='LIGO Scientific Collaboration',
                  runtime=21.5)

    print(read_sky_map('test.fits.gz'))
Beispiel #19
0
def gsm_sky_model(freqs, resolution="hi", nside=None):
    """
    Return a pyradiosky SkyModel object populated with a Global Sky Model datacube in 
    healpix format.

    Parameters
    ----------
    freqs : array_like
        Frequency array, in Hz.

    resolution : str, optional
        Whether to use the high or low resolution pygdsm maps. Options are 'hi' or 'low'.

    nside : int, optional
        Healpix nside to up- or down-sample the GSM sky model to. Default: `None` (use the 
        default from `pygdsm`, which is 1024).

    Returns
    -------
    sky_model : pyradiosky.SkyModel
        SkyModel object.
    """
    import pygdsm
    
    # Initialise GSM object
    gsm = pygdsm.GlobalSkyModel2016(data_unit="TRJ", resolution=resolution, freq_unit="Hz")

    # Construct GSM datacube
    hpmap = gsm.generate(freqs=freqs) # FIXME: nside=1024, ring ordering, galactic coords
    hpmap_units = "K"

    # Set nside or resample
    nside_gsm = int(astropy_healpix.npix_to_nside(hpmap.shape[-1]))
    if nside is None:
        # Use default nside from pygdsm map
        nside = nside_gsm
    else:
        # Transform to a user-selected nside
        hpmap_new = np.zeros((hpmap.shape[0], astropy_healpix.nside_to_npix(nside)), 
                             dtype=hpmap.dtype)
        for i in range(hpmap.shape[0]):
            hpmap_new[i,:] = hp.ud_grade(hpmap[i,:], 
                                         nside_out=nside, 
                                         order_in="RING", 
                                         order_out="RING")
        hpmap = hpmap_new

    # Get datacube properties
    npix = astropy_healpix.nside_to_npix(nside)
    indices = np.arange(npix)
    history = "pygdsm.GlobalSkyModel2016, data_unit=TRJ, resolution=low, freq_unit=MHz"
    freq = units.Quantity(freqs, "hertz")

    # hmap is in K
    stokes = units.Quantity(np.zeros((4, len(freq), len(indices))), hpmap_units)
    stokes[0] = hpmap * units.Unit(hpmap_units)

    # Construct pyradiosky SkyModel
    sky_model = pyradiosky.SkyModel(
                                    nside=nside,
                                    hpx_inds=indices,
                                    stokes=stokes,
                                    spectral_type="full",
                                    freq_array=freq,
                                    history=history,
                                    frame="galactic",
                                    hpx_order="ring"
                                )

    sky_model.healpix_interp_transform(frame='icrs', full_sky=True, inplace=True) # do coord transform
    assert sky_model.component_type == "healpix"
    return sky_model