Esempio n. 1
0
def transform_basis(nside, jones, z0_cza, R_z0):
    """
    At zenith in the local frame the 'x' feed is aligned with 'theta' and
    the 'y' feed is aligned with 'phi'
    """
    npix = hp.nside2npix(nside)
    hpxidx = np.arange(npix)
    cza, ra = hp.pix2ang(nside, hpxidx)

    # Rb is the rotation relating the E-field basis coordinate frame to the local horizontal zenith.
    # (specific to this instrument response simulation data)
    Rb = np.array([[0, 0, -1], [0, -1, 0], [-1, 0, 0]])

    fR = np.einsum('ab,bc->ac', Rb, R_z0)  # matrix product of two rotations

    tb, pb = irf.rotate_sphr_coords(fR, cza, ra)

    cza_v = irf.t_hat_cart(cza, ra)
    ra_v = irf.p_hat_cart(cza, ra)

    tb_v = irf.t_hat_cart(tb, pb)

    fRcza_v = np.einsum('ab...,b...->a...', fR, cza_v)
    fRra_v = np.einsum('ab...,b...->a...', fR, ra_v)

    cosX = np.einsum('a...,a...', fRcza_v, tb_v)
    sinX = np.einsum('a...,a...', fRra_v, tb_v)

    basis_rot = np.array([[cosX, sinX], [-sinX, cosX]])
    basis_rot = np.transpose(basis_rot, (2, 0, 1))

    return irnf.M(jones, basis_rot)
def transform_basis(nside, jones, z0_cza, R_z0):

    npix = hp.nside2npix(nside)
    hpxidx = np.arange(npix)
    cza, ra = hp.pix2ang(nside, hpxidx)

    fR = R_z0

    tb, pb = irf.rotate_sphr_coords(fR, cza, ra)

    cza_v = irf.t_hat_cart(cza, ra)
    ra_v = irf.p_hat_cart(cza, ra)

    tb_v = irf.t_hat_cart(tb, pb)

    fRcza_v = np.einsum('ab...,b...->a...', fR, cza_v)
    fRra_v = np.einsum('ab...,b...->a...', fR, ra_v)

    cosX = np.einsum('a...,a...', fRcza_v, tb_v)
    sinX = np.einsum('a...,a...', fRra_v, tb_v)

    basis_rot = np.array([[cosX, -sinX],[sinX, cosX]])
    basis_rot = np.transpose(basis_rot,(2,0,1))

    # return np.einsum('...ab,...bc->...ac', jones, basis_rot)
    return irnf.M(jones, basis_rot)
Esempio n. 3
0
def transform_basis(nside, jones, z0_cza, R_z0):

    npix = hp.nside2npix(nside)
    hpxidx = np.arange(npix)
    cza, ra = hp.pix2ang(nside, hpxidx)

    fR = R_z0

    tb, pb = irf.rotate_sphr_coords(fR, cza, ra)

    cza_v = irf.t_hat_cart(cza, ra)
    ra_v = irf.p_hat_cart(cza, ra)

    tb_v = irf.t_hat_cart(tb, pb)

    fRcza_v = np.einsum('ab...,b...->a...', fR, cza_v)
    fRra_v = np.einsum('ab...,b...->a...', fR, ra_v)

    cosX = np.einsum('a...,a...', fRcza_v, tb_v)
    sinX = np.einsum('a...,a...', fRra_v, tb_v)

    basis_rot = np.array([[cosX, -sinX], [sinX, cosX]])
    basis_rot = np.transpose(basis_rot, (2, 0, 1))

    # return np.einsum('...ab,...bc->...ac', jones, basis_rot)
    return irnf.M(jones, basis_rot)
def horizon_mask(jones, z0_cza):
    npix = jones.shape[0]
    nside = hp.npix2nside(npix)
    hpxidx = np.arange(npix)
    cza, ra = hp.pix2ang(nside, hpxidx)

    if z0_cza == 0.:
        tb, pb = cza, ra
    else:

        z0 = irf.r_hat_cart(z0_cza, 0.)

        RotAxis = np.cross(z0, np.array([0,0,1.]))
        RotAxis /= np.sqrt(np.dot(RotAxis,RotAxis))
        RotAngle = np.arccos(np.dot(z0, [0,0,1.]))

        R_z0 = irf.rotation_matrix(RotAxis, RotAngle)

        tb, pb = irf.rotate_sphr_coords(R_z0, cza, ra)

    hm = np.zeros((npix,2,2))
    hm[np.where(tb < np.pi/2.)] = 1.

    return hm
Esempio n. 5
0
def horizon_mask(jones, z0_cza):
    npix = jones.shape[0]
    nside = hp.npix2nside(npix)
    hpxidx = np.arange(npix)
    cza, ra = hp.pix2ang(nside, hpxidx)

    if z0_cza == 0.:
        tb, pb = cza, ra
    else:

        z0 = irf.r_hat_cart(z0_cza, 0.)

        RotAxis = np.cross(z0, np.array([0, 0, 1.]))
        RotAxis /= np.sqrt(np.dot(RotAxis, RotAxis))
        RotAngle = np.arccos(np.dot(z0, [0, 0, 1.]))

        R_z0 = irf.rotation_matrix(RotAxis, RotAngle)

        tb, pb = irf.rotate_sphr_coords(R_z0, cza, ra)

    hm = np.zeros((npix, 2, 2))
    hm[np.where(tb < np.pi / 2.)] = 1.

    return hm
def transform_basis(nside, jones, z0_cza, R_z0):
    """
    At zenith in the local frame the 'x' feed is aligned with 'theta' and
    the 'y' feed is aligned with 'phi'
    """
    npix = hp.nside2npix(nside)
    hpxidx = np.arange(npix)
    cza, ra = hp.pix2ang(nside, hpxidx)

    # Rb is the rotation relating the E-field basis coordinate frame to the local horizontal zenith.
    # (specific to this instrument response simulation data)
    Rb = np.array([
    [0,0,-1],
    [0,-1,0],
    [-1,0,0]
    ])

    fR = np.einsum('ab,bc->ac', Rb, R_z0) # matrix product of two rotations

    tb, pb = irf.rotate_sphr_coords(fR, cza, ra)

    cza_v = irf.t_hat_cart(cza, ra)
    ra_v = irf.p_hat_cart(cza, ra)

    tb_v = irf.t_hat_cart(tb, pb)

    fRcza_v = np.einsum('ab...,b...->a...', fR, cza_v)
    fRra_v = np.einsum('ab...,b...->a...', fR, ra_v)

    cosX = np.einsum('a...,a...', fRcza_v, tb_v)
    sinX = np.einsum('a...,a...', fRra_v, tb_v)

    basis_rot = np.array([[cosX, sinX],[-sinX, cosX]])
    basis_rot = np.transpose(basis_rot,(2,0,1))

    return irnf.M(jones, basis_rot)
Esempio n. 7
0
def instrument_setup(z0_cza, freqs):
    """
    This is the CST simulation using the efield basis of z' = -x, y' = -y, x' = -z
    frequencies are every 10MHz, from 100-200
    Each file contains 8 columns which are ordered as:
          (Re(xt),Re(xp),Re(yt),Re(yp),Im(xt),Im(xp),Im(yt),Im(yp)).
    Each column is a healpix map with resolution nside = 2**8
    """

    nu0 = str(int(p.nu_axis[0] / 1e6))
    nuf = str(int(p.nu_axis[-1] / 1e6))
    band_str = nu0 + "-" + nuf

    # restore_name = p.interp_type + "_" + "band_" + band_str + "mhz_nfreq" + str(p.nfreq)+ "_nside" + str(p.nside) + ".npy"
    #
    # if os.path.exists('jones_save/' + restore_name) == True:
    #     return np.load('jones_save/' + restore_name)
    #
    local_jones0_file = 'local_jones0/nside' + str(
        p.nside) + '_band' + band_str + '_Jdata.npy'

    if os.path.exists(local_jones0_file) == True:
        return np.load(local_jones0_file)

    fbase = '/data4/paper/zionos/HERA_jones_data/HERA_Jones_healpix_'
    # fbase = '/home/zmart/radcos/polskysim/IonRIME/HERA_jones_data/HERA_Jones_healpix_'

    nside_in = 2**8
    fnames = [fbase + str(int(f / 1e6)) + 'MHz.txt' for f in freqs]
    nfreq_nodes = len(freqs)

    npix = hp.nside2npix(nside_in)
    hpxidx = np.arange(npix)
    cza, ra = hp.pix2ang(nside_in, hpxidx)

    z0 = irf.r_hat_cart(z0_cza, 0.)

    RotAxis = np.cross(z0, np.array([0, 0, 1.]))
    RotAxis /= np.sqrt(np.dot(RotAxis, RotAxis))
    RotAngle = np.arccos(np.dot(z0, [0, 0, 1.]))

    R_z0 = irf.rotation_matrix(RotAxis, RotAngle)

    t0, p0 = irf.rotate_sphr_coords(R_z0, cza, ra)

    hm = np.zeros(npix)
    hm[np.where(cza < (np.pi / 2. + np.pi / 20.)
                )] = 1  # Horizon mask; is 0 below the local horizon.
    # added some padding. Idea being to allow for some interpolation near the horizon. Questionable.
    npix_out = hp.nside2npix(p.nside)

    Jdata = np.zeros((nfreq_nodes, npix_out, 2, 2), dtype='complex128')
    for i, f in enumerate(fnames):
        J_f = np.loadtxt(f)  # J_f.shape = (npix_in, 8)

        J_f = J_f * np.tile(hm, 8).reshape(8, npix).transpose(
            1, 0)  # Apply horizon mask

        # Could future "rotation" of these zeroed-maps have small errors at the
        # edges of the horizon? due to the way healpy interpolates.
        # Unlikely to be important.
        # Comment update: Yep, it turns out this happens, BUT it is approximately
        # power-preserving. The pixels at the edges of the rotated mask are not
        # identically 1, but the sum over the mask is maintained to about a part
        # in 1e-5

        # Perform a scalar rotation of each component so that the instrument's boresight
        # is pointed toward (z0_cza, 0), the location of the instrument on the
        # earth in the Current-Epoch-RA/Dec coordinate frame.
        J_f = irf.rotate_jones(J_f, R_z0, multiway=False)

        if p.nside != nside_in:
            # Change the map resolution as needed.

            #d = lambda m: hp.ud_grade(m, nside=p.nside, power=-2.)
            # I think these two ended up being (roughly) the same?
            # The apparent normalization problem was really becuase of an freq. interpolation problem.
            # irf.harmonic_ud_grade is probably better for increasing resolution, but hp.ud_grade is
            # faster because it's just averaging/tiling instead of doing SHT's
            d = lambda m: irf.harmonic_ud_grade(m, nside_in, p.nside)
            J_f = (np.asarray(map(d, J_f.T))).T
            # The inner transpose is so that correct dimension is map()'ed over,
            # and then the outer transpose returns the array to its original shape.

        J_f = irf.inverse_flatten_jones(
            J_f)  # Change shape to (nfreq,npix,2,2), complex-valued
        J_f = transform_basis(
            p.nside, J_f, z0_cza, R_z0
        )  # right-multiply by the basis transformation matrix from RA/CZA to the Local CST basis.
        # Note that CZA = pi/2 - Dec! So this is not quite the RA/Dec basis. But the difference
        # in the Stoke parameters between the two is only U -> -U
        Jdata[i, :, :, :] = J_f
        print i

    # If the model at the current nside hasn't been generated before, save it for future reuse.
    if os.path.exists(local_jones0_file) == False:
        np.save(local_jones0_file, Jdata)

    return Jdata
def make_jones(freq):
    if freq in range(90, 221):
        pass
    else:
        raise ValueError('Frequency is not available.')

    nside = 512  # make this as large as possible to minimize singularity effects at zenith
    ## nside 512 seems to work well enough using the "neighbours of neighbours" patch
    ## of the zenith singularity in the ra/cza basis.
    npix = hp.nside2npix(nside)
    hpxidx = np.arange(npix)
    t, p = hp.pix2ang(nside, hpxidx)

    g1 = ecomp(csvname(freq, 'G', 'X'), csvname(freq, 'P', 'X'))
    g2 = ecomp(csvname(freq, 'G', 'Y'), csvname(freq, 'P', 'Y'))

    I = (abs(g1)**2. + abs(g2)**2.)

    norm = np.sqrt(np.amax(I, axis=0))

    #    g1 /= norm
    #    g2 /= norm

    rhm = irf.rotate_healpix_map

    Rb = np.array([[0, 0, -1], [0, -1, 0], [-1, 0, 0]])

    Et_b = udgrade(g1.real, nside) + 1j * udgrade(g1.imag, nside)
    Ep_b = udgrade(g2.real, nside) + 1j * udgrade(g2.imag, nside)

    tb, pb = irf.rotate_sphr_coords(Rb, t, p)

    tb_v = irf.t_hat_cart(tb, pb)
    pb_v = irf.p_hat_cart(tb, pb)

    t_v = irf.t_hat_cart(t, p)
    p_v = irf.p_hat_cart(t, p)

    Rb_tb_v = np.einsum('ab...,b...->a...', Rb, tb_v)
    Rb_pb_v = np.einsum('ab...,b...->a...', Rb, pb_v)

    cosX = np.einsum('a...,a...', Rb_tb_v, t_v)
    sinX = np.einsum('a...,a...', Rb_pb_v, t_v)

    Et = Et_b * cosX + Ep_b * sinX
    Ep = -Et_b * sinX + Ep_b * cosX

    Ext = Et
    Exp = Ep
    ## This assumes that Et and Ep are the components of a dipole oriented
    ## along the X axis, and we want to obtain the components of the same
    ## dipole if it was oriented along Y.
    ## In the current basis, this is done by a scalar rotation of the theta and phi
    ## components by 90 degrees about the Z axis.
    Eyt = arm(Et.real) + 1j * arm(Et.imag)
    Eyp = arm(Ep.real) + 1j * arm(Ep.imag)

    jones_c = np.array([[Ext, Exp], [Eyt, Eyp]]).transpose(2, 0, 1)

    # jones_a = np.array([[rhm(Ext,Rb), rhm(Exp,Rb)],[rhm(Eyt,Rb),rhm(Eyp,Rb)]]).transpose(2,0,1)
    #
    # basis_rot = np.array([[cosX,-sinX],[sinX,cosX]]).transpose(2,0,1)
    #
    # jones_b = np.einsum('...ab,...bc->...ac', jones_a, basis_rot)
    #
    # Ext_b, Exp_b, Eyt_b, Eyp_b = [rhm(jones_b[:,i,j],Rb) for i in range(2) for j in range(2)]
    #
    # jones_c = np.array([[Ext_b,Exp_b],[Eyt_b,Eyp_b]]).transpose(2,0,1)

    return jones_c
def instrument_setup(z0_cza, freqs):
    """
    This is the CST simulation using the efield basis of z' = -x, y' = -y, x' = -z
    frequencies are every 10MHz, from 100-200
    Each file contains 8 columns which are ordered as:
          (Re(xt),Re(xp),Re(yt),Re(yp),Im(xt),Im(xp),Im(yt),Im(yp)).
    Each column is a healpix map with resolution nside = 2**8
    """

    nu0 = str(int(p.nu_axis[0] / 1e6))
    nuf = str(int(p.nu_axis[-1] / 1e6))
    band_str = nu0 + "-" + nuf

    # restore_name = p.interp_type + "_" + "band_" + band_str + "mhz_nfreq" + str(p.nfreq)+ "_nside" + str(p.nside) + ".npy"
    #
    # if os.path.exists('jones_save/' + restore_name) == True:
    #     return np.load('jones_save/' + restore_name)
    #
    local_jones0_file = 'local_jones0/nside' + str(p.nside) + '_band' + band_str + '_Jdata.npy'

    if os.path.exists(local_jones0_file) == True:
        return np.load(local_jones0_file)

    fbase = '/data4/paper/zionos/HERA_jones_data/HERA_Jones_healpix_'
    # fbase = '/home/zmart/radcos/polskysim/IonRIME/HERA_jones_data/HERA_Jones_healpix_'

    nside_in = 2**8
    fnames = [fbase + str(int(f / 1e6)) + 'MHz.txt' for f in freqs]
    nfreq_nodes = len(freqs)

    npix = hp.nside2npix(nside_in)
    hpxidx = np.arange(npix)
    cza, ra = hp.pix2ang(nside_in, hpxidx)

    z0 = irf.r_hat_cart(z0_cza, 0.)

    RotAxis = np.cross(z0, np.array([0,0,1.]))
    RotAxis /= np.sqrt(np.dot(RotAxis,RotAxis))
    RotAngle = np.arccos(np.dot(z0, [0,0,1.]))

    R_z0 = irf.rotation_matrix(RotAxis, RotAngle)

    t0, p0 = irf.rotate_sphr_coords(R_z0, cza, ra)

    hm = np.zeros(npix)
    hm[np.where(cza < (np.pi / 2. + np.pi / 20.))] = 1 # Horizon mask; is 0 below the local horizon.
    # added some padding. Idea being to allow for some interpolation near the horizon. Questionable.
    npix_out = hp.nside2npix(p.nside)

    Jdata = np.zeros((nfreq_nodes,npix_out,2,2),dtype='complex128')
    for i,f in enumerate(fnames):
        J_f = np.loadtxt(f) # J_f.shape = (npix_in, 8)

        J_f = J_f * np.tile(hm, 8).reshape(8, npix).transpose(1,0) # Apply horizon mask

        # Could future "rotation" of these zeroed-maps have small errors at the
        # edges of the horizon? due to the way healpy interpolates.
        # Unlikely to be important.
        # Comment update: Yep, it turns out this happens, BUT it is approximately
        # power-preserving. The pixels at the edges of the rotated mask are not
        # identically 1, but the sum over the mask is maintained to about a part
        # in 1e-5

        # Perform a scalar rotation of each component so that the instrument's boresight
        # is pointed toward (z0_cza, 0), the location of the instrument on the
        # earth in the Current-Epoch-RA/Dec coordinate frame.
        J_f = irf.rotate_jones(J_f, R_z0, multiway=False)

        if p.nside != nside_in:
            # Change the map resolution as needed.

            #d = lambda m: hp.ud_grade(m, nside=p.nside, power=-2.)
                # I think these two ended up being (roughly) the same?
                # The apparent normalization problem was really becuase of an freq. interpolation problem.
                # irf.harmonic_ud_grade is probably better for increasing resolution, but hp.ud_grade is
                # faster because it's just averaging/tiling instead of doing SHT's
            d = lambda m: irf.harmonic_ud_grade(m, nside_in, p.nside)
            J_f = (np.asarray(map(d, J_f.T))).T
                # The inner transpose is so that correct dimension is map()'ed over,
                # and then the outer transpose returns the array to its original shape.

        J_f = irf.inverse_flatten_jones(J_f) # Change shape to (nfreq,npix,2,2), complex-valued
        J_f = transform_basis(p.nside, J_f, z0_cza, R_z0) # right-multiply by the basis transformation matrix from RA/CZA to the Local CST basis.
                                                          # Note that CZA = pi/2 - Dec! So this is not quite the RA/Dec basis. But the difference
                                                          # in the Stoke parameters between the two is only U -> -U
        Jdata[i,:,:,:] = J_f
        print i

    # If the model at the current nside hasn't been generated before, save it for future reuse.
    if os.path.exists(local_jones0_file) == False:
        np.save(local_jones0_file, Jdata)

    return Jdata
def make_jones(freq):
    if freq in range(90,221):
        pass
    else:
        raise ValueError('Frequency is not available.')

    nside = 512 # make this as large as possible to minimize singularity effects at zenith
    ## nside 512 seems to work well enough using the "neighbours of neighbours" patch
    ## of the zenith singularity in the ra/cza basis.
    npix = hp.nside2npix(nside)
    hpxidx = np.arange(npix)
    t,p = hp.pix2ang(nside,hpxidx)

    g1 = ecomp(csvname(freq,'G','X'),csvname(freq,'P','X'))
    g2 = ecomp(csvname(freq,'G','Y'),csvname(freq,'P','Y'))

    I = (abs(g1)**2. + abs(g2)**2.)

    norm = np.sqrt(np.amax(I, axis=0))

    g1 /= norm
    g2 /= norm

    rhm = irf.rotate_healpix_map

    Rb = np.array([
    [0,0,-1],
    [0,-1,0],
    [-1,0,0]
    ])

    Et_b = udgrade(g1.real, nside) + 1j * udgrade(g1.imag, nside)
    Ep_b = udgrade(g2.real, nside) + 1j * udgrade(g2.imag, nside)

    tb,pb = irf.rotate_sphr_coords(Rb, t, p)

    tb_v = irf.t_hat_cart(tb,pb)
    pb_v = irf.p_hat_cart(tb,pb)

    t_v = irf.t_hat_cart(t,p)
    p_v = irf.p_hat_cart(t,p)

    Rb_tb_v = np.einsum('ab...,b...->a...', Rb, tb_v)
    Rb_pb_v = np.einsum('ab...,b...->a...', Rb, pb_v)

    cosX = np.einsum('a...,a...', Rb_tb_v,t_v)
    sinX = np.einsum('a...,a...', Rb_pb_v,t_v)

    Et = Et_b * cosX + Ep_b * sinX
    Ep = -Et_b * sinX + Ep_b * cosX

    Ext = Et
    Exp = Ep
    ## This assumes that Et and Ep are the components of a dipole oriented
    ## along the X axis, and we want to obtain the components of the same
    ## dipole if it was oriented along Y.
    ## In the current basis, this is done by a scalar rotation of the theta and phi
    ## components by 90 degrees about the Z axis.
    Eyt = arm(Et.real) + 1j*arm(Et.imag)
    Eyp = arm(Ep.real) + 1j*arm(Ep.imag)

    jones_c = np.array([[Ext,Exp],[Eyt,Eyp]]).transpose(2,0,1)

    # jones_a = np.array([[rhm(Ext,Rb), rhm(Exp,Rb)],[rhm(Eyt,Rb),rhm(Eyp,Rb)]]).transpose(2,0,1)
    #
    # basis_rot = np.array([[cosX,-sinX],[sinX,cosX]]).transpose(2,0,1)
    #
    # jones_b = np.einsum('...ab,...bc->...ac', jones_a, basis_rot)
    #
    # Ext_b, Exp_b, Eyt_b, Eyp_b = [rhm(jones_b[:,i,j],Rb) for i in range(2) for j in range(2)]
    #
    # jones_c = np.array([[Ext_b,Exp_b],[Eyt_b,Eyp_b]]).transpose(2,0,1)

    return jones_c