def test_baseline_ind(self): """Test that the baselines generated with indicies do return indicies and vice versa.""" standList = numpy.array([100, 101, 102, 103]) bl = uvutils.get_baselines(standList, include_auto=False, indicies=False) bl = numpy.array(bl) self.assertTrue(bl.min() == 100) bl = uvutils.get_baselines(standList, include_auto=True, indicies=False) bl = numpy.array(bl) self.assertTrue(bl.min() == 100) bl = uvutils.get_baselines(standList, include_auto=False, indicies=True) bl = numpy.array(bl) self.assertTrue(bl.max() < 100) bl = uvutils.get_baselines(standList, include_auto=True, indicies=True) bl = numpy.array(bl) self.assertTrue(bl.max() < 100)
def test_baseline_gen(self): """Test that the generated baselines contain the correct numbers of elements.""" standList = numpy.array([100, 101, 102, 103]) bl = uvutils.get_baselines(standList, include_auto=False, indicies=False) self.assertEqual(len(bl), 6) bl = uvutils.get_baselines(standList, include_auto=True, indicies=False) self.assertEqual(len(bl), 10)
def test_baseline_lookup(self): """Test antennas to baseline lookup function.""" standList = numpy.array([100, 101, 102, 103]) bl = uvutils.get_baselines(standList, include_auto=False, indicies=False) ind = uvutils.antennas_to_baseline(100, 101, standList, include_auto=False, indicies=False) self.assertEqual(ind, 0) ind = uvutils.antennas_to_baseline(100, 102, standList, baseline_list=bl) self.assertEqual(ind, 1) ind = uvutils.antennas_to_baseline(0, 3, standList, include_auto=False, indicies=True) self.assertEqual(ind, 2)
def __initData(self): """Private function to generate a random set of data for writing a FITS IDI file. The data is returned as a dictionary with keys: * freq - frequency array in Hz * site - lwa.common.stations object * stands - array of stand numbers * bl - list of baseline pairs in real stand numbers * vis - array of visibility data in baseline x freq format """ # Frequency range freq = numpy.arange(0, 512) * 20e6 / 512 + 40e6 # Site and stands site = lwa_common.lwa1 antennas = site.antennas[0:40:2] # Set baselines and data blList = uvutils.get_baselines(antennas, include_auto=True, indicies=False) visData = numpy.random.rand(len(blList), len(freq)) visData = visData.astype(numpy.complex64) return { 'freq': freq, 'site': site, 'antennas': antennas, 'bl': blList, 'vis': visData }
def test_antenna_lookup(self): """Test baseline number to antenna lookup function.""" standList = numpy.array([100, 101, 102, 103]) bl = uvutils.get_baselines(standList, include_auto=False, indicies=False) ind = uvutils.baseline_to_antennas(0, standList) self.assertEqual(ind[0], 100) self.assertEqual(ind[1], 101) ind = uvutils.baseline_to_antennas(1, standList, baseline_list=bl) self.assertEqual(ind[0], 100) self.assertEqual(ind[1], 102)
def main(args): # Build up the station site = stations.lwa1 observer = site.get_observer() # Load in the file file to figure out what to do dataDict = numpy.load(args.filename[0]) tStart = dataDict['tStart'].item() tInt = dataDict['tInt'] freq = dataDict['freq1'] junk0, refSrc, junk1, junk2, junk3, readers, antennas = read_correlator_configuration( dataDict) dataDict.close() # Prune down to a single polarization antennas = [ant for ant in antennas if ant.pol == 0] # Build up the list of baselines blList = uvutils.get_baselines(antennas) # Loop through the files and do what we need to do t = [] uvw = [] for filename in args.filename: ## Load in the integration dataDict = numpy.load(filename) tStart = dataDict['tStart'].item() tInt = dataDict['tInt'].item() dataDict.close() ## Update the observation observer.date = datetime.utcfromtimestamp(tStart).strftime( '%Y/%m/%d %H:%M:%S.%f') refSrc.compute(observer) HA = (observer.sidereal_time() - refSrc.ra) * 12 / numpy.pi dec = refSrc.dec * 180 / numpy.pi ## Compute u, v, and w t.append(datetime.utcfromtimestamp(tStart)) uvw.append( uvutils.compute_uvw(antennas, HA=HA, dec=dec, freq=freq.mean(), site=observer)) uvw = numpy.array(uvw) / 1e3 # Compute the baseline lengths blLength = numpy.sqrt((uvw**2).sum(axis=2)) print(len(blList), uvw.shape, blLength.shape) # Report print("Phase Center:") print(" Name: %s" % refSrc.name) print(" RA: %s" % refSrc._ra) print(" Dec: %s" % refSrc._dec) print("Antennas:") print(" Total: %i" % len(readers)) print(" VDIF: %i" % sum([1 for rdr in readers if rdr is vdif])) print(" DRX: %i" % sum([1 for rdr in readers if rdr is drx])) print("Baselines:") print(" Total: %i" % (uvw.shape[0] * uvw.shape[1])) ## Minimum basline length m = numpy.argmin(blLength) b = m % uvw.shape[1] bl0 = blList[b][0].stand.id if bl0 < 50: bl0 = 'EA%02i' % bl0 else: bl0 = 'LWA%i' % (bl0 - 50) bl1 = blList[b][1].stand.id if bl1 < 50: bl1 = 'EA%02i' % bl1 else: bl1 = 'LWA%i' % (bl1 - 50) print(" Minimum: %.2f klambda (%s <-> %s)" % (blLength.min(), bl0, bl1)) print(" Median: %.2f klambda" % numpy.median(blLength)) ## Maximum baseline length m = numpy.argmax(blLength) b = m % uvw.shape[1] bl0 = blList[b][0].stand.id if bl0 < 50: bl0 = 'EA%02i' % bl0 else: bl0 = 'LWA%i' % (bl0 - 50) bl1 = blList[b][1].stand.id if bl1 < 50: bl1 = 'EA%02i' % bl1 else: bl1 = 'LWA%i' % (bl1 - 50) print(" Maximum %.2f klambda (%s <-> %s)" % (blLength.max(), bl0, bl1)) # Plot fig = plt.figure() ax = fig.gca() for i in xrange(uvw.shape[0]): l, = ax.plot(uvw[i, :, 0], uvw[i, :, 1], linestyle='', marker='o', ms=3.0, alpha=0.2) ax.plot(-uvw[i, :, 0], -uvw[i, :, 1], linestyle='', marker='o', ms=3.0, alpha=0.2, color=l.get_color()) ax.set_xlabel('u [$k\\lambda$]') ax.set_ylabel('v [$k\\lambda$]') ax.set_title('%s\n%s to %s' % (refSrc.name, min(t).strftime("%m/%d %H:%M:%S"), max(t).strftime("%m/%d %H:%M:%S"))) plt.show()
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()
def __build_sim_data(aa, srcs, pols=['xx', 'yy', 'xy', 'yx'], jd=None, chan=None, phase_center='z', baselines=None, mask=None, verbose=False, count=None, max=None, flat_response=False, resolve_src=False): """ Helper function for build_sim_data so that build_sim_data can be called with a list of Julian Dates and reconstruct the data appropriately. .. versionchanged:: 1.0.1 * Moved the simulation code over from AIPY to the new _simFast module. This should be much faster but under the caveats that the bandpass and antenna gain patterns are the same for all antennas. This should be a reasonable assumption for large-N arrays. * Added a 'flat_response' keyword to make it easy to toggle on and off the spectral and spatial response of the array for the simulation * Added a 'resolve_src' keyword to turn on source resolution effects """ rawFreqs = aa.get_afreqs() if len(rawFreqs.shape) == 2: nFreq = rawFreqs.shape[1] else: nFreq = rawFreqs.size if chan is None: chanMin = 0 chanMax = -1 else: chanMin = chan[0] chanMax = chan[-1] # Update the JD if necessary if jd is None: jd = aa.get_jultime() else: if verbose: if count is not None and max is not None: print("Setting Julian Date to %.5f (%i of %i)" % (jd, count, max)) else: print("Setting Julian Date to %.5f" % jd) aa.set_jultime(jd) Gij_sf = aa.passband(0, 1) def Bij_sf(xyz, pol): Bi = aa[0].bm_response(xyz, pol=pol[0]).transpose() Bj = aa[1].bm_response(xyz, pol=pol[1]).transpose() Bij = numpy.sqrt(Bi * Bj.conj()) return Bij.squeeze() if flat_response: Gij_sf *= 0.0 Gij_sf += 1.0 # Compute the source parameters srcs_tp = [] srcs_eq = [] srcs_ha = [] srcs_dc = [] srcs_jy = [] srcs_fq = [] srcs_sh = [] if verbose: print("Sources Used for Simulation:") for name in srcs: ## Update the source's coordinates src = srcs[name] src.compute(aa) ## Remove sources below the horizon srcTop = src.get_crds(crdsys='top', ncrd=3) srcAzAlt = aipy.coord.top2azalt(srcTop) if srcAzAlt[1] < 0: if verbose: print(" %s: below horizon" % name) continue ## Topocentric coordinates for the gain pattern calculations srcTop.shape = (1, 3) srcs_tp.append(srcTop) ## RA/dec -> equatorial srcEQ = src.get_crds(crdsys='eq', ncrd=3) srcEQ.shape = (3, 1) srcs_eq.append(srcEQ) ## HA/dec srcRA, srcDec = aipy.coord.eq2radec(srcEQ) srcHA = aa.sidereal_time() - srcRA srcs_ha.append(srcHA) srcs_dc.append(srcDec) ## Source flux over the bandpass - corrected for the bandpass jys = src.get_jys() jys.shape = (1, nFreq) jys = Gij_sf * jys srcs_jy.append(jys) ## Frequencies that the fluxes correspond to frq = aa.get_afreqs() frq.shape = (1, nFreq) srcs_fq.append(frq) ## Source shape parameters shp = numpy.array(src.srcshape) shp.shape = (3, 1) srcs_sh.append(shp) # Build the simulation cache aa.sim_cache(numpy.concatenate(srcs_eq, axis=1), jys=numpy.concatenate(srcs_jy, axis=0), mfreqs=numpy.concatenate(srcs_fq, axis=0), srcshapes=numpy.concatenate(srcs_sh, axis=1)) aa._cache['s_top'] = numpy.concatenate(srcs_tp, axis=0) aa._cache['s_ha'] = numpy.concatenate(srcs_ha, axis=0) aa._cache['s_dec'] = numpy.concatenate(srcs_dc, axis=0) # Build the simulated data. If no baseline list is provided, build all # baselines available if baselines is None: baselines = uvutils.get_baselines(numpy.zeros(len(aa.ants)), indicies=True) # Define output data structure freq = aa.get_afreqs() * 1e9 if len(freq.shape) == 2: freq = freq[0, :] UVData = VisibilityDataSet(jd, freq, baselines, [], antennaarray=aa, phase_center=phase_center) # Go! if phase_center != 'z': phase_center.compute(aa) pcAz = phase_center.az * 180 / numpy.pi pcEl = phase_center.alt * 180 / numpy.pi else: pcAz = 0.0 pcEl = 90.0 for p, pol in enumerate(pols): ## Apply the antenna gain pattern for each source if not flat_response: if p == 0: for i in range(aa._cache['jys'].shape[0]): aa._cache['jys'][i, :] *= Bij_sf(aa._cache['s_top'][i, :], pol) else: for i in range(aa._cache['jys'].shape[0]): aa._cache['jys'][i, :] /= Bij_sf( aa._cache['s_top'][i, :], pols[p - 1]) # Remove the old pol aa._cache['jys'][i, :] *= Bij_sf(aa._cache['s_top'][i, :], pol) ## Simulate if not flat_response: uvw1, vis1 = FastVis(aa, baselines, chanMin, chanMax, pcAz, pcEl, resolve_src=resolve_src) else: currentVars = locals().keys() if 'uvw1' not in currentVars or 'vis1' not in currentVars: uvw1, vis1 = FastVis(aa, baselines, chanMin, chanMax, pcAz, pcEl, resolve_src=resolve_src) ## Unpack the data and add it to the data set if p == 0: UVData.uvw = uvw1 pds = PolarizationDataSet(pol, data=vis1) UVData.append(pds) # Cleanup if not flat_response: for i in range(aa._cache['jys'].shape[0]): aa._cache['jys'][i, :] /= Bij_sf(aa._cache['s_top'][i, :], pols[-1]) # Remove the old pol aa._cache['jys'][i, :] /= Gij_sf # Remove the bandpass # Return return UVData
def process_chunk(idf, site, good, filename, int_time=5.0, pols=[ 'xx', ], chunk_size=100): """ Given a lsl.reader.ldp.TBNFile instances and various parameters for the cross-correlation, write cross-correlate the data and save it to a file. """ # Get antennas antennas = site.antennas # Get the metadata sample_rate = idf.get_info('sample_rate') freq = idf.get_info('freq1') # Create the list of good digitizers and a digitizer to Antenna instance mapping. # These are: # toKeep -> mapping of digitizer number to array location # mapper -> mapping of Antenna instance to array location toKeep = [antennas[i].digitizer - 1 for i in good] mapper = [antennas[i] for i in good] # Create a list of unqiue stands to know what style of IDI file to create stands = set([antennas[i].stand.id for i in good]) # Main loop over the input file to read in the data and organize it. Several control # variables are defined for this: # ref_time -> time (in seconds since the UNIX epoch) for the first data set # setTime -> time (in seconds since the UNIX epoch) for the current data set ref_time = 0.0 setTime = 0.0 wallTime = time.time() for s in range(chunk_size): try: readT, t, data = idf.read(int_time) except Exception as e: print("Error: %s" % str(e)) continue ## Prune out what we don't want data = data[toKeep, :, :] ## Split the polarizations antennasX, antennasY = [ a for i, a in enumerate(antennas) if a.pol == 0 and i in toKeep ], [a for i, a in enumerate(antennas) if a.pol == 1 and i in toKeep] dataX, dataY = data[0::2, :, :], data[1::2, :, :] validX = numpy.ones((dataX.shape[0], dataX.shape[2]), dtype=numpy.uint8) validY = numpy.ones((dataY.shape[0], dataY.shape[2]), dtype=numpy.uint8) ## Apply the cable delays as phase rotations for i in range(dataX.shape[0]): gain = numpy.sqrt(antennasX[i].cable.gain(freq)) phaseRot = numpy.exp(2j*numpy.pi*freq*(antennasX[i].cable.delay(freq) \ -antennasX[i].stand.z/speedOfLight)) for j in range(dataX.shape[2]): dataX[i, :, j] *= phaseRot / gain for i in range(dataY.shape[0]): gain = numpy.sqrt(antennasY[i].cable.gain(freq)) phaseRot = numpy.exp(2j*numpy.pi*freq*(antennasY[i].cable.delay(freq)\ -antennasY[i].stand.z/speedOfLight)) for j in range(dataY.shape[2]): dataY[i, :, j] *= phaseRot / gain setTime = t if s == 0: ref_time = setTime # Setup the set time as a python datetime instance so that it can be easily printed setDT = setTime.datetime print("Working on set #%i (%.3f seconds after set #1 = %s)" % ((s + 1), (setTime - ref_time), setDT.strftime("%Y/%m/%d %H:%M:%S.%f"))) # Loop over polarization products for pol in pols: print("-> %s" % pol) if pol[0] == 'x': a1, d1, v1 = antennasX, dataX, validX else: a1, d1, v1 = antennasY, dataY, validY if pol[1] == 'x': a2, d2, v2 = antennasX, dataX, validX else: a2, d2, v2 = antennasY, dataY, validY ## Get the baselines baselines = uvutils.get_baselines(a1, antennas2=a2, include_auto=True, indicies=True) blList = [] for bl in range(len(baselines)): blList.append((a1[baselines[bl][0]], a2[baselines[bl][1]])) ## Run the cross multiply and accumulate vis = XEngine2(d1, d2, v1, v2) # Select the right range of channels to save toUse = numpy.where((freq > 5.0e6) & (freq < 93.0e6)) toUse = toUse[0] # If we are in the first polarazation product of the first iteration, setup # the FITS IDI file. if s == 0 and pol == pols[0]: pol1, pol2 = fxc.pol_to_pols(pol) if len(stands) > 255: fits = fitsidi.ExtendedIdi(filename, ref_time=ref_time) else: fits = fitsidi.Idi(filename, ref_time=ref_time) fits.set_stokes(pols) fits.set_frequency(freq[toUse]) fits.set_geometry(site, [a for a in mapper if a.pol == pol1]) # Convert the setTime to a MJD and save the visibilities to the FITS IDI file obsTime = astro.unix_to_taimjd(setTime) fits.add_data_set(obsTime, readT, blList, vis[:, toUse], pol=pol) print("-> Cummulative Wall Time: %.3f s (%.3f s per integration)" % ((time.time() - wallTime), (time.time() - wallTime) / (s + 1))) # Cleanup after everything is done fits.write() fits.close() del (fits) del (data) del (vis) return True
def main(args): # Parse the command line filenames = args.filename if args.regex: filenames = [] for regex in args.filename: filenames.extend(glob.glob(regex)) try: filenames.sort(cmp=cmpNPZ) except TypeError: filenames.sort(key=cmp_to_key(cmpNPZ)) if args.limit != -1: filenames = filenames[:args.limit] # Build up the station site = stations.lwa1 observer = site.get_observer() # Load in the file file to figure out what to do dataDict = numpy.load(filenames[0]) tStart = dataDict['tStart'].item() tInt = dataDict['tInt'] freq = dataDict['freq1'] config, refSrc, junk1, junk2, junk3, junk4, antennas = read_correlator_configuration( dataDict) try: if config['basis'] == 'linear': args.linear = True args.circular = False args.stokes = False elif config['basis'] == 'circular': args.linear = False args.circular = True args.stokes = False elif config['basis'] == 'stokes': args.linear = False args.circular = False args.stokes = True print( "NOTE: Set output polarization basis to '%s' per user defined configuration" % config['basis']) except (TypeError, KeyError): pass visXX = dataDict['vis1XX'].astype(numpy.complex64) visXY = dataDict['vis1XY'].astype(numpy.complex64) visYX = dataDict['vis1YX'].astype(numpy.complex64) visYY = dataDict['vis1YY'].astype(numpy.complex64) dataDict.close() # Build up the master list of antennas and report master_antennas = antennas obs_groups = [ os.path.basename(filenames[0]).split('-vis2', 1)[0], ] for filename in filenames: group = os.path.basename(filename).split('-vis2', 1)[0] if group not in obs_groups: dataDict = numpy.load(filename) config, refSrc, junk1, junk2, junk3, junk4, antennas = read_correlator_configuration( dataDict) del dataDict for ant in antennas: ## The FITS IDI writer only cares about the stand ID if (ant.stand.id, ant.pol) not in [(ma.stand.id, ma.pol) for ma in master_antennas]: master_antennas.append(ant) obs_groups.append(group) master_antennas.sort(key=lambda x: (x.stand.id, x.pol)) for i in range(len(master_antennas)): master_antennas[i].id = i + 1 print("Antennas:") for ant in master_antennas: print(" Antenna %i: Stand %i, Pol. %i" % (ant.id, ant.stand.id, ant.pol)) nchan = visXX.shape[1] master_blList = uvutils.get_baselines( [ant for ant in master_antennas if ant.pol == 0], include_auto=True) if args.decimate > 1: to_trim = (freq.size / args.decimate) * args.decimate to_drop = freq.size - to_trim if to_drop != 0: print("Warning: Dropping %i channels (%.1f%%; %.3f kHz)" % (to_drop, 100.0 * to_drop / freq.size, to_drop * (freq[1] - freq[0]) / 1e3)) nchan //= args.decimate if to_drop != 0: freq = freq[:to_trim] freq.shape = (freq.size // args.decimate, args.decimate) freq = freq.mean(axis=1) # Figure out the visibility conjugation problem in LSL, pre-1.1.4 conjugateVis = False if float(fitsidi.__version__) < 0.9: print("Warning: Applying conjugate to visibility data") conjugateVis = True # Figure out our revision try: repo = git.Repo(os.path.dirname(os.path.abspath(__file__))) try: branch = repo.active_branch.name hexsha = repo.active_branch.commit.hexsha except TypeError: branch = '<detached>' hexsha = repo.head.commit.hexsha shortsha = hexsha[-7:] dirty = ' (dirty)' if repo.is_dirty() else '' except git.exc.GitError: branch = 'unknown' hexsha = 'unknown' shortsha = 'unknown' dirty = '' # Fill in the data for i, filename in enumerate(filenames): ## Load in the integration group = os.path.basename(filename).split('-vis2', 1)[0] dataDict = numpy.load(filename) junk0, refSrc, junk1, junk2, junk3, junk4, antennas = read_correlator_configuration( dataDict) try: refSrc.name = refSrc.name.upper() # For AIPS if refSrc.name[:12] == 'ELWA_SESSION': ## Convert ELWA_SESSION names to "real" source names refSrc.name = getSourceName(refSrc).replace(' ', '').upper() except AttributeError: ## Moving sources cannot have their names changed pass blList = uvutils.get_baselines( [ant for ant in antennas if ant.pol == 0], include_auto=True) ## Make sure the frequencies are compatible cFreq = dataDict['freq1'] if cFreq.size != freq.size: error_msg = "Incompatible frequencies at %s: %i != %i" % ( group, cFreq.size, freq.size) if args.ignore_incompatible: warnings.warn(error_msg, RuntimeWarning) continue else: raise RuntimeError(error_msg) elif cFreq[0] != freq[0] or cFreq[-1] != freq[-1]: error_msg = "Incompatible frequencies at %s: %.3f MHz != %.3f MHz or %.3f MHz != %.3f MHz" % ( group, cFreq[0] / 1e6, freq[0] / 1e6, cFreq[-1] / 1e6, freq[-1] / 1e6) if args.ignore_incompatible: warnings.warn(error_msg, RuntimeWarning) continue else: raise RuntimeError(error_msg) tStart = dataDict['tStart'].item() tInt = dataDict['tInt'].item() visXX = dataDict['vis1XX'].astype(numpy.complex64) visXY = dataDict['vis1XY'].astype(numpy.complex64) visYX = dataDict['vis1YX'].astype(numpy.complex64) visYY = dataDict['vis1YY'].astype(numpy.complex64) dataDict.close() if args.decimate > 1: if to_drop != 0: visXX = visXX[:, :to_trim] visXY = visXY[:, :to_trim] visYX = visYX[:, :to_trim] visYY = visYY[:, :to_trim] visXX.shape = (visXX.shape[0], visXX.shape[1] // args.decimate, args.decimate) visXX = visXX.mean(axis=2) visXY.shape = (visXY.shape[0], visXY.shape[1] // args.decimate, args.decimate) visXY = visXY.mean(axis=2) visYX.shape = (visYX.shape[0], visYX.shape[1] // args.decimate, args.decimate) visYX = visYX.mean(axis=2) visYY.shape = (visYY.shape[0], visYY.shape[1] // args.decimate, args.decimate) visYY = visYY.mean(axis=2) if conjugateVis: visXX = visXX.conj() visXY = visXY.conj() visYX = visYX.conj() visYY = visYY.conj() if args.circular or args.stokes: visI = visXX + visYY visQ = visXX - visYY visU = visXY + visYX visV = (visXY - visYX) / 1.0j if args.circular: visRR = visI + visV visRL = visQ + 1j * visU visLR = visQ - 1j * visU visLL = visI - visV if i % args.split == 0: ## Clean up the previous file try: fits.write() fits.close() except NameError: pass ## Create the FITS-IDI file as needed ### What to call it if args.tag is None: outname = 'buildIDI.FITS_%i' % (i // args.split + 1, ) else: outname = 'buildIDI_%s.FITS_%i' % ( args.tag, i // args.split + 1, ) ### Does it already exist or not if os.path.exists(outname): if not args.force: yn = raw_input("WARNING: '%s' exists, overwrite? [Y/n] " % outname) else: yn = 'y' if yn not in ('n', 'N'): os.unlink(outname) else: raise RuntimeError("Output file '%s' already exists" % outname) ### Create the file fits = fitsidi.Idi(outname, ref_time=tStart) if args.circular: fits.set_stokes(['RR', 'RL', 'LR', 'LL']) elif args.stokes: fits.set_stokes(['I', 'Q', 'U', 'V']) else: fits.set_stokes(['XX', 'XY', 'YX', 'YY']) fits.set_frequency(freq) fits.set_geometry(stations.lwa1, [a for a in master_antennas if a.pol == 0]) if config['context'] is not None: mode = 'LSBI' if min([ma.stand.id for ma in master_antennas]) < 50 \ and max([ma.stand.id for ma in master_antennas]) > 50: mode = 'ELWA' elif min([ma.stand.id for ma in master_antennas]) < 50: mode = 'VLA' fits.set_observer(config['context']['observer'], config['context']['project'], 'eLWA') if config['context']['session'] is not None: fits.add_header_keyword('session', config['context']['session']) if config['context']['vlaref'] is not None: fits.add_header_keyword('vlaref', config['context']['vlaref']) fits.add_header_keyword('instrume', mode) fits.add_history( 'Created with %s, revision %s.%s%s' % (os.path.basename(__file__), branch, shortsha, dirty)) print("Opening %s for writing" % outname) if i % 10 == 0: print(i) ## Update the observation observer.date = datetime.utcfromtimestamp(tStart).strftime( '%Y/%m/%d %H:%M:%S.%f') refSrc.compute(observer) ## Convert the setTime to a MJD and save the visibilities to the FITS IDI file obsTime = astro.unix_to_taimjd(tStart) if args.circular: fits.add_data_set(obsTime, tInt, blList, visRR, pol='RR', source=refSrc) fits.add_data_set(obsTime, tInt, blList, visRL, pol='RL', source=refSrc) fits.add_data_set(obsTime, tInt, blList, visLR, pol='LR', source=refSrc) fits.add_data_set(obsTime, tInt, blList, visLL, pol='LL', source=refSrc) elif args.stokes: fits.add_data_set(obsTime, tInt, blList, visI, pol='I', source=refSrc) fits.add_data_set(obsTime, tInt, blList, visQ, pol='Q', source=refSrc) fits.add_data_set(obsTime, tInt, blList, visU, pol='U', source=refSrc) fits.add_data_set(obsTime, tInt, blList, visV, pol='V', source=refSrc) else: fits.add_data_set(obsTime, tInt, blList, visXX, pol='XX', source=refSrc) fits.add_data_set(obsTime, tInt, blList, visXY, pol='XY', source=refSrc) fits.add_data_set(obsTime, tInt, blList, visYX, pol='YX', source=refSrc) fits.add_data_set(obsTime, tInt, blList, visYY, pol='YY', source=refSrc) # Cleanup the last file fits.write() fits.close()
def FXStokes(signals, antennas, LFFT=64, overlap=1, include_auto=False, verbose=False, window=null_window, pfb=False, sample_rate=None, central_freq=0.0, gain_correct=False, return_baselines=False, clip_level=0, phase_center='z'): """ A more advanced version of FXCorrelator for TBW and TBN data. Given an 2-D array of signals (stands, time-series) and an array of stands, compute the cross-correlation of the data for all baselines. Return the frequencies and visibilities as a two-elements tuple. .. versionchanged:: 2.0.1 Added support for phase_center to be an astropy.coordinates.AltAz instance .. versionchanged:: 1.0.0 Added a phase_center keyword that accept a two-element tuple of azimuth and elelvation (in degrees) to change where the correlations are phased to .. versionchanged:: 1.1.0 Made the 'phase_center' keyword more flexible. It can now be either: * 'z' to denote the zenith, * a ephem.Body instances which has been computed for the observer, or * a two-element tuple of azimuth, elevation in degrees. .. versionchanged:: 1.2.5 Added the 'pfb' keyword. """ # Since we want to compute Stokes parameters, we need both pols pol1 = 0 pol2 = 1 antennas1 = [a for a in antennas if a.pol == pol1] signalsIndex1 = [i for (i, a) in enumerate(antennas) if a.pol == pol1] antennas2 = [a for a in antennas if a.pol == pol2] signalsIndex2 = [i for (i, a) in enumerate(antennas) if a.pol == pol2] nStands = len(antennas1) baselines = uvutils.get_baselines(antennas1, antennas2=antennas2, include_auto=include_auto, indicies=True) # Figure out if we are working with complex (I/Q) data or only real. This # will determine how the FFTs are done since the real data mirrors the pos- # itive and negative Fourier frequencies. if signals.dtype.kind == 'c': lFactor = 1 doFFTShift = True central_freq = float(central_freq) else: lFactor = 2 doFFTShift = False if sample_rate is None: sample_rate = dp_common.fS freq = numpy.fft.fftfreq(lFactor * LFFT, d=1.0 / sample_rate) if doFFTShift: freq += central_freq freq = numpy.fft.fftshift(freq) freq = freq[:LFFT] # Get the location of the phase center in radians and create a # pointing vector if phase_center == 'z': azPC = 0.0 elPC = numpy.pi / 2.0 else: if isinstance(phase_center, ephem.Body): azPC = phase_center.az * 1.0 elPC = phase_center.alt * 1.0 elif isinstance(phase_center, AstroAltAz): azPC = phase_center.az.radian elPC = phase_center.alt.radian else: azPC = phase_center[0] * numpy.pi / 180.0 elPC = phase_center[1] * numpy.pi / 180.0 source = numpy.array([ numpy.cos(elPC) * numpy.sin(azPC), numpy.cos(elPC) * numpy.cos(azPC), numpy.sin(elPC) ]) # Define the cable/signal delay caches to help correlate along and compute # the delays that we need to apply to align the signals dlyRef = len(freq) // 2 delays1 = numpy.zeros((nStands, LFFT)) delays2 = numpy.zeros((nStands, LFFT)) for i in list(range(nStands)): xyz1 = numpy.array( [antennas1[i].stand.x, antennas1[i].stand.y, antennas1[i].stand.z]) xyz2 = numpy.array( [antennas2[i].stand.x, antennas2[i].stand.y, antennas2[i].stand.z]) delays1[i, :] = antennas1[i].cable.delay(freq) - numpy.dot( source, xyz1) / speedOfLight delays2[i, :] = antennas2[i].cable.delay(freq) - numpy.dot( source, xyz2) / speedOfLight if not numpy.isfinite(delays1.max()): delays1[numpy.where(~numpy.isfinite(delays1))] = delays1[numpy.where( numpy.isfinite(delays1))].max() if not numpy.isfinite(delays2.max()): delays2[numpy.where(~numpy.isfinite(delays2))] = delays2[numpy.where( numpy.isfinite(delays2))].max() if delays1[:, dlyRef].min() < delays2[:, dlyRef].min(): minDelay = delays1[:, dlyRef].min() else: minDelay = delays2[:, dlyRef].min() delays1 -= minDelay delays2 -= minDelay if window is null_window: window = None if window is not None and pfb: raise RuntimeError( "Cannot use a seperate window function with the PFB") # F - defaults to running parallel in C via OpenMP if pfb: func = _core.PFBEngine else: func = _core.FEngine signalsF1, validF1 = func(signals[signalsIndex1, :], freq, delays1, LFFT=LFFT, overlap=overlap, sample_rate=sample_rate, clip_level=clip_level, window=window) signalsF2, validF2 = func(signals[signalsIndex2, :], freq, delays2, LFFT=LFFT, overlap=overlap, sample_rate=sample_rate, clip_level=clip_level, window=window) # X output = _stokes.XEngine3(signalsF1, signalsF2, validF1, validF2) if not include_auto: # Remove auto-correlations from the output of the X engine if we don't # need them. To do this we need to first build the full list of baselines # (including auto-correlations) and then prune that. baselinesFull = uvutils.get_baselines(antennas1, antennas2=antennas2, include_auto=True, indicies=True) fom = numpy.array([a1 - a2 for (a1, a2) in baselinesFull]) nonAuto = numpy.where(fom != 0)[0] output = output[:, nonAuto, :] # Apply cable gain corrections (if needed) if gain_correct: for bl in range(output.shape[0]): cableGain1 = antennas1[baselines[bl][0]].cable.gain(freq) cableGain2 = antennas2[baselines[bl][1]].cable.gain(freq) output[:, bl, :] /= numpy.sqrt(cableGain1 * cableGain2) # Create antenna baseline list (if needed) if return_baselines: antennaBaselines = [] for bl in range(output.shape[1]): antennaBaselines.append( (antennas1[baselines[bl][0]], antennas2[baselines[bl][1]])) returnValues = (antennaBaselines, freq, output) else: returnValues = (freq, output) return returnValues
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()
def simulate_visibilities_gen(model, model_params, freqs, antennas=stations.lwasv.antennas, pol='XX', noise_sigma=None): ''' Returns a generator which provides simulated visibilities according to a specified model. Parameters: model: a function that takes as arugments - u : a np.array of u coordinates - v : a np.array of v coordinates - some number of parameters (e.g. l, m) and returns an np.array the same size as the u and v coordinate vectors containing the visibility samples from the model at the (u,v) points. model_params: a list of tuples, each containing values for the scalar parameters of model. Each tuple will be used to call model in a subsequent iteration of the generator. freqs: a list of frequencies. for now these are just used for baseline calculation and not passed into the model. TODO: pass freqs to the model ants: a list of lsl antenna objects the baselines of which will be used to generate the (u,v) coordinate vectors Returns: A generator yielding a tuple of (baselines, freqs, visibilities) - baselines: a list of pairs of antenna objects with each pair representing a baseline - freqs: same as the argument freqs - visibilities: a numpy array of visibility samples corresponding to the antenna pairs in baselines for each frequency in freqs The generator will yield a tuple for each set of parameters in model_params. ''' print("Simulating visibilities") print(f"| using model {model.__name__}") print( f"| received {len(model_params)} sets of parameters, will emit that many sets of visibilities" ) pol1, pol2 = fxc.pol_to_pols(pol) antennas1 = [a for a in antennas if a.pol == pol1] antennas2 = [a for a in antennas if a.pol == pol2] baseline_indices = uvutils.get_baselines(antennas1, antennas2=antennas2, include_auto=False, indicies=True) baselines = [] for bl in range(len(baseline_indices)): baselines.append((antennas1[baseline_indices[bl][0]], antennas2[baseline_indices[bl][1]])) for params in model_params: visibilities = np.empty((len(baselines), len(freqs)), dtype=np.complex128) for k, freq in enumerate(freqs): wl = 3e8 / freq uvw = uvw_from_antenna_pairs(baselines, wl) u = uvw[:, 0] v = uvw[:, 1] w = uvw[:, 2] visibilities[:, k] = model(u, v, w, *params) if noise_sigma is not None: noise = np.random.normal( 0, noise_sigma, len(visibilities)) + 1j * np.random.normal( 0, noise_sigma, len(visibilities)) visibilities[:, k] += noise yield baselines, freqs, visibilities return
def main(args): # Setup the site information station = stations.lwasv ants = station.antennas nAnt = len([a for a in ants if a.pol == 0]) phase_freq_range = [0, 0] for filename in args.filename: # Open the file and get ready to go idf = CORFile(filename) nBL = idf.get_info('nbaseline') nchan = idf.get_info('nchan') tInt = idf.get_info('tint') nFpO = nBL * nchan / 72 nInts = idf.get_info('nframe') / nFpO jd = astro.unix_to_utcjd(idf.get_info('start_time')) date = idf.get_info('start_time').datetime central_freq = idf.get_info('freq1') central_freq = central_freq[len(central_freq)/2] print("Data type: %s" % type(idf)) print("Samples per observations: %i" % (nFpO,)) print("Integration Time: %.3f s" % tInt) print("Tuning frequency: %.3f Hz" % central_freq) print("Captures in file: %i (%.1f s)" % (nInts, nInts*tInt)) print("==") print("Station: %s" % station.name) print("Date observed: %s" % date) print("Julian day: %.5f" % jd) print(" ") # Offset into the file offset = idf.offset(args.skip) if offset != 0.0: print("Skipped %.3f s into the file" % offset) # Open the file and go nFiles = int(args.duration / tInt) if nFiles == 0: nFiles = numpy.inf fileCount = 0 while fileCount < nFiles: try: tInt, tStart, data = idf.read(tInt) except Exception as e: print("ERROR: %s" % str(e)) break freqs = idf.get_info('freq1') beginJD = astro.unix_to_utcjd( tStart ) beginTime = datetime.utcfromtimestamp( tStart ) if freqs[0] != phase_freq_range[0] or freqs[-1] != phase_freq_range[1]: print("Updating phasing for %.3f to %.3f MHz" % (freqs[0]/1e6, freqs[-1]/1e6)) phase_freq_range[0] = freqs[ 0] phase_freq_range[1] = freqs[-1] k = 0 phase = numpy.zeros((nBL, nchan, 2, 2), dtype=numpy.complex64) gaix = [a.cable.gain(freqs) for a in ants if a.pol == 0] gaiy = [a.cable.gain(freqs) for a in ants if a.pol == 1] dlyx = [a.cable.delay(freqs) - a.stand.z / speedOfLight for a in ants if a.pol == 0] dlyy = [a.cable.delay(freqs) - a.stand.z / speedOfLight for a in ants if a.pol == 1] for i in xrange(nAnt): for j in xrange(i, nAnt): phase[k,:,0,0] = numpy.exp(2j*numpy.pi*freqs*(dlyx[i] - dlyx[j])) \ / numpy.sqrt(gaix[i]*gaix[j]) phase[k,:,0,1] = numpy.exp(2j*numpy.pi*freqs*(dlyx[i] - dlyy[j])) \ / numpy.sqrt(gaix[i]*gaiy[j]) phase[k,:,1,0] = numpy.exp(2j*numpy.pi*freqs*(dlyy[i] - dlyx[j])) \ / numpy.sqrt(gaiy[i]*gaix[j]) phase[k,:,1,1] = numpy.exp(2j*numpy.pi*freqs*(dlyy[i] - dlyy[j])) \ / numpy.sqrt(gaiy[i]*gaiy[j]) k += 1 for i in xrange(data.shape[-1]): data[...,i] *= phase # Convert to a dataDict try: blList # pylint: disable=used-before-assignment except NameError: blList = uvutils.get_baselines(ants[0::2], include_auto=True) if args.output is None: outname = os.path.basename(filename) outname = os.path.splitext(outname)[0] outname = "%s_%i_%s.ms" % (outname, int(beginJD-astro.MJD_OFFSET), beginTime.strftime("%H_%M_%S")) else: base, ext = os.path.splitext(args.output) if ext == '': ext = '.ms' outname = "%s_%i_%s%s" % (base, int(beginJD-astro.MJD_OFFSET), beginTime.strftime("%H_%M_%S"), ext) fits = measurementset.Ms(outname, ref_time=tStart) fits.set_stokes(['xx', 'xy', 'yx', 'yy']) fits.set_frequency(freqs) fits.set_geometry(station, ants[0::2]) obsTime = astro.unix_to_taimjd(tStart) fits.add_data_set(obsTime, tInt, blList, data[:,:,0,0,0], pol='xx') fits.add_data_set(obsTime, tInt, blList, data[:,:,0,1,0], pol='xy') fits.add_data_set(obsTime, tInt, blList, data[:,:,1,0,0], pol='yx') fits.add_data_set(obsTime, tInt, blList, data[:,:,1,1,0], pol='yy') fits.write() fits.close() fileCount += 1 idf.close()