Beispiel #1
0
    def test_build_aa_flat(self):
        """Test building a antenna array object with uniform sky response."""

        lwa1 = lwa_common.lwa1
        antennas = lwa1.antennas[0:20]
        freqs = numpy.arange(30e6, 50e6, 10e6)

        aa = vis.build_sim_array(lwa1, antennas, freqs, force_flat=True)
        aa[0].bm_response((0, 0, 1), pol='x')
        aa[0].bm_response((0, 0, 1), pol='y')
        bm1 = aa[0].get_beam_shape()

        az = numpy.zeros((360, 90))
        for i in range(360):
            az[i, :] = i * numpy.pi / 180.0
        alt = numpy.zeros((360, 90))
        for i in range(90):
            alt[:, i] = i * numpy.pi / 180.0
        xyz = aipy.coord.azalt2top(numpy.concatenate([[az], [alt]]))
        bm2 = aa[0].bm_response(xyz, pol='x')
        numpy.testing.assert_allclose(bm1.transpose(2, 0, 1), bm2)
Beispiel #2
0
    def test_clean_leastsq(self):
        """Test CLEANing using least squares in the image plane"""

        # Setup
        antennas = lwa1.antennas[0:20]
        freqs = numpy.arange(30e6, 50e6, 1e6)
        aa = vis.build_sim_array(lwa1, antennas, freqs)

        # Build the data dictionary
        out = vis.build_sim_data(aa, vis.SOURCES, jd=2458962.16965)

        with lsl.testing.SilentVerbose():
            # Build an image
            img = utils.build_gridded_image(out)

            # CLEAN
            deconv.lsq(aa,
                       out,
                       img,
                       max_iter=2,
                       verbose=False,
                       plot=run_plotting_tests)
Beispiel #3
0
    def test_plotting_graticules(self):
        """Test adding a graticule to an image."""

        # Setup
        antennas = lwa1.antennas[0:20]
        freqs = numpy.arange(30e6, 50e6, 1e6)
        aa = vis.build_sim_array(lwa1, antennas, freqs)

        # Build the data dictionary
        out = vis.build_sim_data(aa, vis.SOURCES, jd=2458962.16965)

        # Build an image
        img = utils.build_gridded_image(out)

        # Plot
        fig = plt.figure()
        ax = fig.gca()
        utils.plot_gridded_image(ax, img)
        with self.subTest(type='RA/Dec.'):
            overlay.graticule_radec(ax, aa)
        with self.subTest(type='az/alt'):
            overlay.graticule_azalt(ax, aa)
        del fig
Beispiel #4
0
    def test_build_aa(self):
        """Test building a antenna array object with realistic sky response."""

        lwa1 = lwa_common.lwa1
        antennas = lwa1.antennas[0:20]
        freqs = numpy.arange(30e6, 50e6, 1e6)

        aa = vis.build_sim_array(lwa1, antennas, freqs)
        aa.set_asp_filter('split')
        aa[0].bm_response((0, 0, 1))
        # Check the number of stands
        self.assertEqual(len(aa.ants), len(antennas))

        # Check the frequencies comming out
        numpy.testing.assert_allclose(aa.get_afreqs(), freqs / 1e9)

        # Check that other methods even run
        aa.get_baseline_fast(0, 1)
        aa.gen_uvw_fast(0, 1)
        aa.gen_phs_fast('z', 0, 1)

        aa.set_unixtime(1588026422.0)
        vis.SOURCES['crab'].compute(aa)
        aa.gen_phs_fast(vis.SOURCES['crab'], 0, 1)
Beispiel #5
0
def grid_visibilities(bl,
                      freqs,
                      vis,
                      tx_freq,
                      station,
                      valid_ants=None,
                      size=80,
                      res=0.5,
                      wres=0.10,
                      use_pol=0,
                      jd=None):
    '''
    Resamples the baseline-sampled visibilities on to a regular grid. 

    arguments:
    bl = pairs of antenna objects representing baselines (list)
    freqs = frequency channels for which we have correlations (list)
    vis = visibility samples corresponding to the baselines (numpy array)
    tx_freq = the frequency of the signal we want to locate
    valid_ants = which antennas we actually want to use (list)
    station = lsl station object - usually stations.lwasv
    according to LSL docstring:
        size = number of wavelengths which the UV matrix spans (this 
        determines the image resolution).
        res = resolution of the UV matrix (determines image field of view).
        wres: the gridding resolution of sqrt(w) when projecting to w=0.

    use_pol = which polarization to use (only 0 is supported right now)
    returns:
    gridded_image
    '''
    # In order to do the gridding, we need to build a VisibilityDataSet using
    # lsl.imaging.data.VisibilityDataSet. We have to build a bunch of stuff to
    # pass to its constructor.

    if valid_ants is None:
        valid_ants, n_baselines = select_antennas(station.antennas, use_pol)

    # we only want the bin nearest to our frequency
    target_bin = np.argmin([abs(tx_freq - f) for f in freqs])

    # Build antenna array
    freqs = np.array(freqs)
    antenna_array = simVis.build_sim_array(station,
                                           valid_ants,
                                           freqs / 1e9,
                                           jd=jd,
                                           force_flat=True)

    uvw = np.empty((len(bl), 3, len(freqs)))

    for i, f in enumerate(freqs):
        # wavelength = 3e8/f # TODO this should be fixed. What is currently happening is not true. Well it is, but only if you're looking for a specific transmitter frequency. Which I guess we are. I just mean it's not generalized.
        wavelength = 3e8 / tx_freq
        uvw[:, :, i] = uvw_from_antenna_pairs(bl, wavelength=wavelength)

    dataSet = VisibilityDataSet(jd=jd,
                                freq=freqs,
                                baselines=bl,
                                uvw=uvw,
                                antennarray=antenna_array)
    if use_pol == 0:
        pol_string = 'XX'
    else:
        raise RuntimeError("Only pol. XX supported right now.")
    polDataSet = PolarizationDataSet(pol_string, data=vis)
    dataSet.append(polDataSet)

    # Use lsl.imaging.utils.build_gridded_image (takes a VisibilityDataSet)
    gridded_image = build_gridded_image(dataSet,
                                        pol=pol_string,
                                        chan=target_bin,
                                        size=size,
                                        res=res,
                                        wres=wres)

    return gridded_image
def main(args):

    h5fi = h5py.File(args.input_file, 'r')
    h5fo = h5py.File(args.output_file,'w')

    # Copy over important attributes
    for key in h5fi.attrs.keys():
        h5fo.attrs[key]=h5fi.attrs[key]
    
    # Copy over important datasets
    for key in h5fi.keys():
        temp_arr = h5fi[key]
        h5fo.create_dataset('vis_{}'.format(key),data=temp_arr)
    h5fo.attrs['grid_size']=args.size
    h5fo.attrs['grid_res']=args.res
    h5fo.attrs['grid_wres']=args.wres
    h5fo.create_dataset('l_est', (len(h5fo['vis_l_est']),))
    h5fo.create_dataset('m_est', (len(h5fo['vis_l_est']),))
    h5fo.create_dataset('extent', (len(h5fo['vis_l_est']),4))
    h5fo.create_dataset('elevation', (len(h5fo['vis_l_est']),))
    h5fo.create_dataset('azimuth', (len(h5fo['vis_l_est']),))
    h5fo.create_dataset('height', (len(h5fo['vis_l_est']),))

    
    h5fi.close() # done with input data now

    ## Begin doing stuff
    antennas = station.antennas
    valid_ants, n_baselines = select_antennas(antennas, h5fo.attrs['use_pol'], exclude=[256]) # to exclude outrigger

    tx_coords = h5fo.attrs['tx_coordinates']
    rx_coords = [station.lat * 180/np.pi, station.lon * 180/np.pi]

    ## Build freqs (same for every 'integration')
    freqs = np.empty((h5fo.attrs['fft_len'],),dtype=np.float64)
    #! Need to think of intelligent way of doing this.
    #! target_bin will probably not matter since all vis is the same
    freqs5 =   [5284999.9897182, 5291249.9897182, 5297499.9897182, 5303749.9897182,
                5309999.9897182, 5316249.9897182, 5322499.9897182, 5328749.9897182,
                5334999.9897182, 5341249.9897182, 5347499.9897182, 5353749.9897182,
                5359999.9897182, 5366249.9897182, 5372499.9897182, 5378749.9897182]
    for i in range(len(freqs)):
        freqs[i]=freqs5[i]

    ## Build bl (same for every 'integration')
    pol_string = 'xx' if h5fo.attrs['use_pol'] == 0 else 'yy'
    pol1, pol2 = pol_to_pols(pol_string)
    antennas1 = [a for a in valid_ants if a.pol == pol1]
    antennas2 = [a for a in valid_ants if a.pol == pol2]

    nStands = len(antennas1)
    baselines = uvutils.get_baselines(antennas1, antennas2=antennas2, include_auto=False, indicies=True)

    antennaBaselines = []
    for bl in range(len(baselines)):
            antennaBaselines.append( (antennas1[baselines[bl][0]], antennas2[baselines[bl][1]]) )
    bl = antennaBaselines

    uvw_m = np.array([np.array([b[0].stand.x - b[1].stand.x, b[0].stand.y - b[1].stand.y, b[0].stand.z - b[1].stand.z]) for b in bl])
    uvw = np.empty((len(bl), 3, len(freqs)))
    for i, f in enumerate(freqs):
        # wavelength = 3e8/f # TODO this should be fixed. What is currently happening is not true. Well it is, but only if you're looking for a specific transmitter frequency. Which I guess we are. I just mean it's not generalized.
        wavelength = 3e8/h5fo.attrs['tx_freq']
        uvw[:,:,i] = uvw_m/wavelength


    # Build antenna array (gets used in the VisibilityDataSet)
    # jd can't matter, right?
    jd = 2458847.2362531545
    antenna_array = simVis.build_sim_array(station, valid_ants, freqs/1e9, jd=jd, force_flat=True)
    # we only want the bin nearest to our frequency
    target_bin = np.argmin([abs(h5fo.attrs['tx_freq'] - f) for f in freqs])


    # Needed for PolarizationDataSet
    if h5fo.attrs['use_pol'] == 0:
        pol_string = 'XX'
        p=0 # this is related to the enumerate in lsl.imaging.utils.CorrelatedIDI().get_data_set() (for when there are multiple pols in a single dataset)
    else:
        raise RuntimeError("Only pol. XX supported right now.")


    if args.all_sky:
        fig, ax = plt.subplots()

    for k in np.arange(len(h5fo['vis_l_est'])):
        l_in = h5fo['vis_l_est'][k]
        m_in = h5fo['vis_m_est'][k]

        ## Build vis
        vismodel = point_source_visibility_model_uv(uvw[:,0,0],uvw[:,1,0],l_in,m_in)
        vis = np.empty((len(vismodel), len(freqs)), dtype=np.complex64)
        for i in np.arange(vis.shape[1]):
            vis[:,i] = vismodel

        if args.export_npy:
            print(args.export_npy)
            print("Exporting modelled u, v, w, and visibility")
            np.save('model-uvw{}.npy'.format(k), uvw)
            np.save('model-vis{}.npy'.format(k), vis)

        ## Start to build up the data structure for VisibilityDataSet

        dataSet = VisibilityDataSet(jd=jd, freq=freqs, baselines=bl, uvw=uvw, antennarray=antenna_array)
        polDataSet = PolarizationDataSet(pol_string, data=vis)
        dataSet.append(polDataSet)


        print('| Gridding and imaging with size={}, res={}, wres={}'.format(args.size, args.res, args.wres))

        gridded_image = build_gridded_image(dataSet, pol=pol_string,
            chan=target_bin, size=args.size,
            res=args.res, wres=args.wres)
        
        if args.export_npy:
            print("Exporting gridded u, v, and visibility")
            u,v = gridded_image.get_uv()
            np.save('gridded-u{}.npy'.format(k), u)
            np.save('gridded-v{}.npy'.format(k), v)
            np.save('gridded-vis{}.npy'.format(k), gridded_image.uv)


        l,m,img,extent=get_gimg_max(gridded_image, return_img=True)

        # Compute other values of interest
        elev, az = lm_to_ea(l, m)
        height = flatmirror_height(tx_coords, rx_coords, elev)

        h5fo['l_est'][k] = l
        h5fo['m_est'][k] = m

        h5fo['extent'][k] = extent

        h5fo['elevation'][k] = elev
        h5fo['azimuth'][k] = az
        h5fo['height'][k] = height

        if args.all_sky:
            ax.imshow(img, extent=extent, origin='lower', interpolation='nearest')
            ax.set_title('size={}, res={}, wres={}, iteration={}'.format(args.size,args.res,args.wres,k))
            ax.set_xlabel('l')
            ax.set_ylabel('m')
            ax.plot(l,m,marker='o', color='k', label='Image Max.')
            ax.plot(l_in,m_in,marker='x', color='r', label='Model (input)')
            plt.legend(loc='lower right')
            plt.savefig('allsky{}.png'.format(k))
            plt.cla()

        save_pkl_gridded = args.pkl_gridded and k in args.pkl_gridded
        if save_pkl_gridded:
            quickDict={'image':img, 'extent':extent}
            with open('gridded{}.pkl'.format(k), 'wb') as f:
                pickle.dump(quickDict, f, protocol=pickle.HIGHEST_PROTOCOL)

    h5fo.close()
Beispiel #7
0
def main(args):
    # Loop over the input files
    for filename in args.filename:
        ## Is this file valid?
        try:
            db = PasiImageDB(filename, 'r')
        except Exception as e:
            print("ERROR: %s" % str(e))
            continue

        ## Setup the array
        if db.header.station == 'LWA1':
            aa = simVis.build_sim_array(lwa1, lwa1.antennas[0::2],
                                        numpy.array([
                                            38e6,
                                        ]))
        else:
            aa = None

        ## Go!
        for i, (hdr, img, spec) in enumerate(db):
            if args.dataset != 0 and args.dataset != (i + 1):
                continue

            mjd = int(hdr.startTime)
            mpm = int((hdr.startTime - mjd) * 86400 * 1000.0)
            tStart = mjdmpm_to_datetime(mjd, mpm)
            if aa is not None:
                aa.set_jultime(hdr.centroidTime + astro.MJD_OFFSET)

            stokes = hdr.stokesParams.split(',')

            ### Save the image size for later
            imSize = img.shape[-1]

            ### Zero outside of the horizon so avoid problems
            pCntr = imSize / 2 + 1 + 0.5 * ((imSize + 1) % 2)
            pScale = hdr['xPixelSize']
            sRad = 360.0 / pScale / numpy.pi / 2
            x = numpy.arange(1, img.shape[-2] + 1, dtype=numpy.float32) - pCntr
            y = numpy.arange(1, img.shape[-1] + 1, dtype=numpy.float32) - pCntr
            x /= -sRad
            y /= sRad
            x, y = numpy.meshgrid(x, y)
            invalid = numpy.where((x**2 + y**2) > 1)
            img[:, invalid[0], invalid[1]] = 0.0

            ### Try and set the image scale correctly for the display
            x2 = x - 1 / sRad
            y2 = y - 1 / sRad
            extent = (x2.max(), x2.min(), y.min(), y.max())

            ### Loop over Stokes parameters
            fig = plt.figure()
            for j, label in enumerate(stokes):
                ax = fig.add_subplot(2, 2, j + 1)
                ax.imshow(img[j, :, :].T,
                          origin='lower',
                          interpolation='nearest',
                          extent=extent)
                ax.set_title(label)
                ax.set_xlim((1, -1))
                ax.set_ylim((-1, 1))

                ## Turn off tick marks
                ax.xaxis.set_major_formatter(NullFormatter())
                ax.yaxis.set_major_formatter(NullFormatter())

                ## Is we know where we are, overlay some stuff
                if aa is not None:
                    # Horizon
                    overlay.horizon(ax, aa)
                    # RA/Dec graticle
                    if not args.no_grid:
                        overlay.graticule_radec(ax, aa)
                    # Source positions
                    overlay.sources(ax,
                                    aa,
                                    simVis.SOURCES,
                                    label=(not args.no_labels))

            fig.suptitle(
                '%.3f MHz @ %s' %
                (hdr.freq / 1e6, tStart.strftime("%Y/%m/%d %H:%M:%S")))
            plt.show()

        ## Done
        db.close()
Beispiel #8
0
    def test_scale_data(self):
        """Test that we can scale a data dictionary without error"""

        # Setup
        lwa1 = lwa_common.lwa1
        antennas = lwa1.antennas[0:20]
        freqs = numpy.arange(30e6, 50e6, 1e6)
        aa = vis.build_sim_array(lwa1, antennas, freqs)

        # Build the data dictionary
        out = vis.build_sim_data(aa, vis.SOURCES)

        # Scale
        amp = vis.scale_data(out,
                             numpy.ones(len(antennas)) * 2,
                             numpy.zeros(len(antennas)))
        # Delay
        phs = vis.scale_data(out, numpy.ones(len(antennas)),
                             numpy.ones(len(antennas)))

        #
        # Single-channel test
        #

        # Setup
        lwa1 = lwa_common.lwa1
        antennas = lwa1.antennas[0:20]
        freqs = numpy.array([
            30e6,
        ])
        aa = vis.build_sim_array(lwa1, antennas, freqs)

        # Build the data dictionary
        out = vis.build_sim_data(aa, vis.SOURCES)

        # Scale
        amp = vis.scale_data(out,
                             numpy.ones(len(antennas)) * 2,
                             numpy.zeros(len(antennas)))
        # Delay
        phs = vis.scale_data(out, numpy.ones(len(antennas)),
                             numpy.ones(len(antennas)))

        #
        # VisibilityData test
        #

        # Setup
        lwa1 = lwa_common.lwa1
        antennas = lwa1.antennas[0:20]
        freqs = numpy.arange(30e6, 50e6, 1e6)
        aa = vis.build_sim_array(lwa1, antennas, freqs)

        # Build the data dictionary
        out = vis.build_sim_data(aa, vis.SOURCES)
        out2 = VisibilityData(out)

        # Scale
        amp2 = vis.scale_data(out2,
                              numpy.ones(len(antennas)) * 2,
                              numpy.zeros(len(antennas)))
        # Delay
        phs2 = vis.scale_data(out2, numpy.ones(len(antennas)),
                              numpy.ones(len(antennas)))
Beispiel #9
0
def main(args):

    ## Check we should bother doing anything

    if not args.export_npy and not args.export_h5 and not args.all_sky and not args.pkl_gridded:
        raise RuntimeError(
            "You have not selected a data output of any type. Read the docstring and pick something for me to do."
        )

    # Normalize all inputs to the same length
    sizes = [int(item) for item in args.size.split(',')]
    reses = [float(item) for item in args.res.split(',')]
    wreses = [float(item) for item in args.wres.split(',')]
    maxinputlen = max(len(sizes), len(reses), len(wreses))
    if len(sizes) not in [1, maxinputlen] or len(reses) not in [
            1, maxinputlen
    ] or len(wreses) not in [1, maxinputlen]:
        raise RuntimeError(" \
        For size, res and wres you must pass either the same number of values as the max or a single value.\n \
        For example:\n \
        ALLOWED     -> sizes=175,180,190, res=0.5, wres=0.5\n \
                    -> sizes=175,180,190, res=0.5, wres=0.5,0.6,0.7\n \
        NOT ALLOWED -> sizes=175,180,190, res=0.5, wres=0.5,0.6 \
        ")
    if len(
            sizes
    ) != maxinputlen:  # You'd think there must be a good way to do this with list comprehension.
        sizes = sizes * maxinputlen
    if len(reses) != maxinputlen:
        reses = reses * maxinputlen
    if len(wreses) != maxinputlen:
        wreses = wreses * maxinputlen
    all_grid_params = []
    while len(sizes) > 0:
        all_grid_params.append({
            'size': sizes.pop(),
            'res': reses.pop(),
            'wres': wreses.pop()
        })

    ## Begin doing stuff
    tx_coords = known_transmitters.parse_args(args)
    if not transmitter_coords:
        print("Please specify a transmitter location")
        return
    rx_coords = [station.lat * 180 / np.pi, station.lon * 180 / np.pi]

    antennas = station.antennas

    valid_ants, n_baselines = select_antennas(antennas, args.use_pol)

    if args.export_h5:
        h5fname = "simulation-results.h5"
        print("Output will be written to {}".format(h5fname))
        h5f = h5py.File(h5fname, 'w')

        ats = h5f.attrs
        ats['transmitter'] = args.transmitter
        ats['tx_freq'] = args.tx_freq
        ats['valid_ants'] = [a.id for a in valid_ants]
        ats['n_baselines'] = n_baselines
        ats['fft_len'] = args.fft_len
        ats['use_pol'] = args.use_pol
        ats['int_length'] = args.integration_length
        ats['l_model'] = args.l_model
        ats['m_model'] = args.m_model

        h5f.create_dataset('l_est', (len(all_grid_params), ))
        h5f.create_dataset('m_est', (len(all_grid_params), ))
        h5f.create_dataset('wres', (len(all_grid_params), ))
        h5f.create_dataset('res', (len(all_grid_params), ))
        h5f.create_dataset('size', (len(all_grid_params), ))
        h5f.create_dataset('extent', (len(all_grid_params), 4))
        h5f.create_dataset('elevation', (len(all_grid_params), ))
        h5f.create_dataset('azimuth', (len(all_grid_params), ))
        h5f.create_dataset('height', (len(all_grid_params), ))

    ## Build freqs
    freqs = np.empty((args.fft_len, ), dtype=np.float64)
    #! Need to think of intelligent way of doing this.
    #! target_bin will probably not matter since all vis is the same
    freqs5 = [
        5284999.9897182, 5291249.9897182, 5297499.9897182, 5303749.9897182,
        5309999.9897182, 5316249.9897182, 5322499.9897182, 5328749.9897182,
        5334999.9897182, 5341249.9897182, 5347499.9897182, 5353749.9897182,
        5359999.9897182, 5366249.9897182, 5372499.9897182, 5378749.9897182
    ]
    for i in range(len(freqs)):
        freqs[i] = freqs5[i]

    ## Build bl
    pol_string = 'xx' if args.use_pol == 0 else 'yy'
    pol1, pol2 = pol_to_pols(pol_string)
    antennas1 = [a for a in valid_ants if a.pol == pol1]
    antennas2 = [a for a in valid_ants if a.pol == pol2]

    nStands = len(antennas1)
    baselines = uvutils.get_baselines(antennas1,
                                      antennas2=antennas2,
                                      include_auto=False,
                                      indicies=True)

    antennaBaselines = []
    for bl in range(len(baselines)):
        antennaBaselines.append(
            (antennas1[baselines[bl][0]], antennas2[baselines[bl][1]]))
    bl = antennaBaselines

    uvw_m = np.array([
        np.array([
            b[0].stand.x - b[1].stand.x, b[0].stand.y - b[1].stand.y,
            b[0].stand.z - b[1].stand.z
        ]) for b in bl
    ])
    uvw = np.empty((len(bl), 3, len(freqs)))
    for i, f in enumerate(freqs):
        # wavelength = 3e8/f # TODO this should be fixed. What is currently happening is not true. Well it is, but only if you're looking for a specific transmitter frequency. Which I guess we are. I just mean it's not generalized.
        wavelength = 3e8 / args.tx_freq
        uvw[:, :, i] = uvw_m / wavelength

    ## Build vis
    vismodel = point_source_visibility_model_uv(uvw[:, 0, 0], uvw[:, 1, 0],
                                                args.l_model, args.m_model)
    vis = np.empty((len(vismodel), len(freqs)), dtype=np.complex64)
    for i in np.arange(vis.shape[1]):
        vis[:, i] = vismodel

    if args.export_npy:
        print(args.export_npy)
        print("Exporting modelled u, v, w, and visibility")
        np.save('model-uvw.npy', uvw)
        np.save('model-vis.npy', vis)

    ## Start to build up the data structure for VisibilityDataSet
    # we only want the bin nearest to our frequency
    target_bin = np.argmin([abs(args.tx_freq - f) for f in freqs])

    # This can't matter, right?
    # jd = tbnf.get_info('start_time').jd
    jd = 2458847.2362531545

    # Build antenna array
    antenna_array = simVis.build_sim_array(station,
                                           antennas,
                                           freqs / 1e9,
                                           jd=jd,
                                           force_flat=True)

    dataSet = VisibilityDataSet(jd=jd,
                                freq=freqs,
                                baselines=bl,
                                uvw=uvw,
                                antennarray=antenna_array)
    if args.use_pol == 0:
        pol_string = 'XX'
        p = 0  # this is related to the enumerate in lsl.imaging.utils.CorrelatedIDI().get_data_set() (for when there are multiple pols in a single dataset)
    else:
        raise RuntimeError("Only pol. XX supported right now.")
    polDataSet = PolarizationDataSet(pol_string, data=vis)
    dataSet.append(polDataSet)

    if args.all_sky:
        fig, ax = plt.subplots()

    # Iterate over size/res/wres and generate multiple grids/images
    k = 0
    for grid_params in all_grid_params:
        print('| Gridding and imaging with size={}, res={}, wres={}'.format(
            grid_params['size'], grid_params['res'], grid_params['wres']))

        gridded_image = build_gridded_image(dataSet,
                                            pol=pol_string,
                                            chan=target_bin,
                                            size=grid_params['size'],
                                            res=grid_params['res'],
                                            wres=grid_params['wres'])

        if args.export_npy:
            print("Exporting gridded u, v, and visibility")
            u, v = gridded_image.get_uv()
            np.save(
                'gridded-u-size-{}-res-{}-wres-{}.npy'.format(
                    grid_params['size'], grid_params['res'],
                    grid_params['wres']), u)
            np.save(
                'gridded-v-size-{}-res-{}-wres-{}.npy'.format(
                    grid_params['size'], grid_params['res'],
                    grid_params['wres']), v)
            np.save(
                'gridded-vis-size-{}-res-{}-wres-{}.npy'.format(
                    grid_params['size'], grid_params['res'],
                    grid_params['wres']), gridded_image.uv)

        l, m, img, extent = get_gimg_max(gridded_image, return_img=True)

        # Compute other values of interest
        elev, az = lm_to_ea(l, m)
        height = flatmirror_height(tx_coords, rx_coords, elev)

        if args.export_h5:
            h5f['l_est'][k] = l
            h5f['m_est'][k] = m
            h5f['wres'][k] = grid_params['wres']
            h5f['res'][k] = grid_params['res']
            h5f['size'][k] = grid_params['size']

            h5f['extent'][k] = extent

            h5f['elevation'][k] = elev
            h5f['azimuth'][k] = az
            h5f['height'][k] = height

        if args.all_sky:
            ax.imshow(img,
                      extent=extent,
                      origin='lower',
                      interpolation='nearest')
            ax.set_title('size={}, res={}, wres={}'.format(
                grid_params['size'], grid_params['res'], grid_params['wres']))
            ax.set_xlabel('l')
            ax.set_ylabel('m')
            ax.plot(l, m, marker='o', color='k', label='Image Max.')
            ax.plot(args.l_model,
                    args.m_model,
                    marker='x',
                    color='r',
                    label='Model (input)')
            plt.legend(loc='lower right')
            plt.savefig('allsky_size_{}_res_{}_wres_{}.png'.format(
                grid_params['size'], grid_params['res'], grid_params['wres']))
            plt.cla()

        save_pkl_gridded = args.pkl_gridded and k in args.pkl_gridded
        if save_pkl_gridded:
            quickDict = {'image': img, 'extent': extent}
            with open(
                    'gridded_size_{}_res_{}_wres_{}.pkl'.format(
                        grid_params['size'], grid_params['res'],
                        grid_params['wres']), 'wb') as f:
                pickle.dump(quickDict, f, protocol=pickle.HIGHEST_PROTOCOL)
        k += 1

    if args.export_h5:
        h5f.close()
        c = stations.Cable(f"Cable{ant.id:03d}-Pol{pol}", 0.0)
        a = stations.Antenna(ant.id*2+pol, stand=s, cable=c, pol=pol)
        ovro2.antennas.append(a)
ovro = ovro2

# Simulation setup
nant = len(ovro.antennas) // 2
nbl = nant*(nant+1)//2
chan0 = 1234
nchan = 192
CHAN_BW = 196e6 / 8192
jd = AstroTime.now().jd

# Simulation array
freqs = (chan0 + numpy.arange(nchan)) * CHAN_BW + CHAN_BW/2
aa = simVis.build_sim_array(ovro, ovro.antennas[0::2], freqs/1e9, jd=jd)

# Simulate with bright sources only
dataSet = simVis.build_sim_data(aa, simVis.SOURCES, pols=['xx','yy'], jd=jd)

# Make the final data set that can be used with dr_visibilities.py
# NOTE:  XY and XY are 1% of XX and have sign flip between XY and YX
vis = numpy.zeros((nbl,nchan,4), dtype=numpy.complex64)
k = 0
l = 0
for i in range(nant):
    for j in range(i, nant):
        vis[l,:,0] = dataSet.XX.data[k,:]
        vis[l,:,1] = dataSet.XX.data[k,:]* 0.01
        vis[l,:,2] = dataSet.XX.data[k,:]*-0.01
        vis[l,:,3] = dataSet.YY.data[k,:]
def main(args):
    filenames = args.filenames
    filenames.sort()

    times = []
    for filename in filenames:
        dataDict = numpy.load(filename)

        tStart = datetime.utcfromtimestamp(dataDict['tStart'])
        tInt = dataDict['tInt']
        try:
            srate = dataDict['srate']
        except KeyError:
            srate = 19.6e6
        
        freq1 = dataDict['freq1']
        freq2 = dataDict['freq2']
        stand1, stand2 = dataDict['stands']

        times.append( tStart)

    print("Got %i files from %s to %s (%s)" % (len(filenames), times[0].strftime("%Y/%m/%d %H:%M:%S"), times[-1].strftime("%Y/%m/%d %H:%M:%S"), (times[-1]-times[0])))

    iTimes = []
    for i in xrange(1, len(times)):
        dt = times[i] - times[i-1]
        iTimes.append(dt.days*24*3600 + dt.seconds + dt.microseconds/1e6)
    iTimes = numpy.array(iTimes)
    print(" -> Interval: %.3f +/- %.3f seconds (%.3f to %.3f seconds)" % (iTimes.mean(), iTimes.std(), iTimes.min(), iTimes.max()))
    
    print("Number of frequency channels: %i (~%.1f Hz/channel)" % (len(freq1)+1, freq1[1]-freq1[0]))

    # Build up the station
    if args.lwasv:
        site = stations.lwasv
    else:
        site = stations.lwa1
    
    rawAntennas = site.antennas
    
    antennas = []
    for ant in rawAntennas:
        if ant.stand.id == stand1 and ant.pol == 0:
            antennas.append(ant)
    for ant in rawAntennas:
        if ant.stand.id == stand2 and ant.pol == 0:
            antennas.append(ant)
    if len(antennas) != 2:
        raise RuntimeError("Can only find stand %i, %i and %i found in the NPZ files" % (antennas[0].stand.id, stand1, stand2))

    # Create the simulated array
    refJD = unix_to_utcjd(timegm(times[0].timetuple()))
    aa1 = simVis.build_sim_array(site, antennas, freq1/1e9, jd=refJD)
    aa2 = simVis.build_sim_array(site, antennas, freq2/1e9, jd=refJD)

    # Build the model times and range.
    jdList = []
    dTimes = []
    for i in xrange(len(times)):
        tNow = timegm(times[i].timetuple())
        jdNow = unix_to_utcjd(tNow)

        jdList.append(jdNow)
        dTimes.append( (times[i]-times[0]).seconds )
        
    # Actually run the simulations
    simDict1 = simVis.build_sim_data(aa1, simVis.SOURCES, jd=jdList, pols=['xx',], verbose=False)
    simDict2 = simVis.build_sim_data(aa2, simVis.SOURCES, jd=jdList, pols=['xx',], verbose=False)

    # Plot
    fig = plt.figure()
    ax1 = fig.add_subplot(2, 1, 1)
    ax2 = fig.add_subplot(2, 1, 2)

    vis1 = []
    for vis in simDict1['vis']['xx']:
        vis1.append( vis )
    vis2 = []
    for vis in simDict2['vis']['xx']:
        vis2.append( vis )
    
    vis1 = numpy.array(vis1)
    vis1 = numpy.ma.array(vis1, mask=~numpy.isfinite(vis1))
    vis2 = numpy.array(vis2)
    vis2 = numpy.ma.array(vis2, mask=~numpy.isfinite(vis2))

    data = numpy.abs(vis1)
    data = data.ravel()
    data.sort()
    vmin1 = data[int(round(0.15*len(data)))]
    vmax1 = data[int(round(0.85*len(data)))]
    print('Plot range for tuning 1:', vmin1, vmax1)
    
    data = numpy.abs(vis2)
    data = data.ravel()
    data.sort()
    vmin2 = data[int(round(0.15*len(data)))]
    vmax2 = data[int(round(0.85*len(data)))]
    print('Plot range for tuning 2:', vmin2, vmax2)

    ax1.imshow(numpy.abs(vis1), extent=(freq1[0], freq1[-1], dTimes[0], dTimes[-1]), origin='lower', 
            vmin=vmin1, vmax=vmax1)
    ax2.imshow(numpy.abs(vis2), extent=(freq1[0], freq1[-1], dTimes[0], dTimes[-1]), origin='lower', 
            vmin=vmin2, vmax=vmax2)

    ax1.axis('auto')
    ax2.axis('auto')

    fig.suptitle("%s to %s UTC" % (times[0].strftime("%Y/%m/%d %H:%M"), times[-1].strftime("%Y/%m/%d %H:%M")))
    ax1.set_xlabel('Frequency [MHz]')
    ax2.set_xlabel('Frequency [MHz]')
    ax1.set_ylabel('Elapsed Time [s]')
    ax2.set_ylabel('Elapsed Time [s]')

    plt.show()