def test_planetaryposition_jupiter(self): """Test the location of Jupiter.""" t0 = transform.Time('2013-01-08 01:23:45.000', format='STR') obs = lwa1.get_observer() obs.date = t0.utc_str jove = ephem.Jupiter() jove.compute(obs) p0 = transform.PlanetaryPosition('Jupiter') self.assertAlmostEqual( p0.apparent_equ(t0)[0], jove.g_ra * 180.0 / math.pi, 4) self.assertAlmostEqual( p0.apparent_equ(t0)[1], jove.g_dec * 180.0 / math.pi, 4)
def test_planetaryposition_saturn(self): """Test the location of Saturn.""" t0 = transform.Time('2013-01-08 01:23:45.000', format='STR') obs = lwa1.get_observer() obs.date = t0.utc_str sat = ephem.Saturn() sat.compute(obs) p0 = transform.PlanetaryPosition('Saturn') self.assertAlmostEqual( p0.apparent_equ(t0)[0], sat.g_ra * 180.0 / math.pi, 4) self.assertAlmostEqual( p0.apparent_equ(t0)[1], sat.g_dec * 180.0 / math.pi, 4)
def test_geographicalposition_lst(self): """Test the tranform.GeographicalPosition sidereal time.""" t0 = transform.Time('2013-01-08 01:23:45.000', format='STR') lon = lwa1.long * 180.0 / math.pi lat = lwa1.lat * 180.0 / math.pi elv = lwa1.elev obs = lwa1.get_observer() g0 = transform.GeographicalPosition([lon, lat, elv]) # The astro.get_apparent_sidereal_time() function doesn't care about # elevation obs.elev = 0.0 obs.date = t0.utc_str self.assertAlmostEqual(g0.sidereal(t0), obs.sidereal_time() * 12.0 / math.pi, 4)
def test_pointingdirection_azalt(self): """Test the transform.PointingDirection az/alt transform.""" t0 = transform.Time('2013-01-08 01:23:45.000', format='STR') lon = lwa1.long * 180.0 / math.pi lat = lwa1.lat * 180.0 / math.pi elv = lwa1.elev obs = lwa1.get_observer() obs.date = t0.utc_str jove = ephem.Jupiter() jove.compute(obs) g0 = transform.GeographicalPosition([lon, lat, elv]) p0 = transform.PlanetaryPosition('Jupiter') d0 = transform.PointingDirection(p0, g0) str(d0) repr(d0) self.assertAlmostEqual(d0.hrz(t0)[0], jove.az * 180.0 / math.pi, 0) self.assertAlmostEqual(d0.hrz(t0)[1], jove.alt * 180.0 / math.pi, 0)
def test_pointingdirection_rst(self): """Test the transform.PointingDirection az/alt transform.""" t0 = transform.Time('2013-01-08 01:23:45.000', format='STR') lon = lwa1.long * 180.0 / math.pi lat = lwa1.lat * 180.0 / math.pi elv = lwa1.elev obs = lwa1.get_observer() obs.date = t0.utc_str jove = ephem.Jupiter() jove.compute(obs) g0 = transform.GeographicalPosition([lon, lat, elv]) p0 = transform.PlanetaryPosition('Jupiter') d0 = transform.PointingDirection(p0, g0) rst = d0.rst(t0) self.assertAlmostEqual(rst.rise, obs.next_rising(jove) * 1.0 + DJD_OFFSET, 2) self.assertAlmostEqual(rst.transit, obs.next_transit(jove) * 1.0 + DJD_OFFSET, 2) self.assertAlmostEqual(rst.set, obs.next_setting(jove) * 1.0 + DJD_OFFSET, 2)
def main(args): obs = lwa1.get_observer() MST = pytz.timezone('US/Mountain') UTC = pytz.utc if args.date is None or args.time is None: dt = datetime.datetime.utcnow() dt = UTC.localize(dt) else: year, month, day = args.date.split('/', 2) hour, minute, second = args.time.split(':', 2) iSeconds = int(float(second)) mSeconds = int(round((float(second) - iSeconds) * 1000000)) if args.utc: # UTC dt = UTC.localize( datetime.datetime(int(year), int(month), int(day), int(hour), int(minute), iSeconds, mSeconds)) elif args.sidereal: # LST dt = astroDate(int(year), int(month), int(day), 0, 0, 0) jd = dt.to_jd() ## Get the LST in hours LST = int(hour) + int(minute) / 60.0 + (iSeconds + mSeconds / 1e6) / 3600.0 ## Get the Greenwich apparent ST for LST using the longitude of ## the site. The site longitude is stored as radians, so convert ## to hours first. GAST = LST - obs.long * 12 / math.pi ## Get the Greenwich mean ST by removing the equation of the ## equinoxes (or some approximation thereof) GMST = GAST - _getEquinoxEquation(jd) ## Get the value of D0, days since January 1, 2000 @ 12:00 UT, ## and T, the number of centuries since the year 2000. The value ## of T isn't terribly important but it is nice to include D0 = jd - 2451545.0 T = D0 / 36525.0 ## Solve for the UT hour for this LST and map onto 0 -> 24 hours ## From: http://aa.usno.navy.mil/faq/docs/GAST.php H = GMST - 6.697374558 - 0.06570982441908 * D0 - 0.000026 * T**2 H /= 1.002737909350795 while H < 0: H += 24 / 1.002737909350795 while H > 24: H -= 24 / 1.002737909350795 ## Get the full Julian Day that this corresponds to jd += H / 24.0 ## Convert the JD back to a time and extract the relevant ## quantities needed to build a datetime instance dt = astroGetDate(jd) year = dt.years month = dt.months day = dt.days hour = dt.hours minute = dt.minutes second = int(dt.seconds) microsecond = int((dt.seconds - second) * 1e6) ## Trim the microsecond down to the millisecond level microsecond = int(int(microsecond / 1000.0) * 1000) ## Localize as the appropriate time zone dt = UTC.localize( datetime.datetime(year, month, day, hour, minute, second, microsecond)) else: # Mountain time dt = MST.localize( datetime.datetime(int(year), int(month), int(day), int(hour), int(minute), iSeconds, mSeconds)) dt = dt.astimezone(UTC) obs.date = dt.astimezone(UTC).strftime("%Y/%m/%d %H:%M:%S.%f") mjd, mpm = datetime_to_mjdmpm(dt) print("Localtime: %s" % dt.astimezone(MST).strftime("%B %d, %Y at %H:%M:%S %Z")) print("UTC: %s" % dt.astimezone(UTC).strftime("%B %d, %Y at %H:%M:%S %Z")) print("LST: %s" % obs.sidereal_time()) print("MJD: %i" % mjd) print("MPM: %i" % mpm)
def main(args): # Parse the command line config = parseOptions(args) # Get LWA-1 observer = lwa1.get_observer() print("Current site is %s at lat %s, lon %s" % (lwa1.name, observer.lat, observer.long)) # Set the current time so we can find the "next" transit. Go ahead # and report the time and the current LST (for reference) if len(config['args']) == 1: config['args'][0] = config['args'][0].replace('-', '/') year, month, day = config['args'][0].split('/', 2) year = int(year) month = int(month) day = int(day) tNow = _UTC.localize(datetime(year, month, day)) else: tNow = _UTC.localize(datetime.utcnow()) observer.date = tNow.strftime("%Y/%m/%d %H:%M:%S") print("Current time is %s" % tNow.astimezone(_UTC).strftime("%Y/%m/%d %H:%M:%S %Z")) print("Current LST at %s is %s" % (lwa1.name, observer.sidereal_time())) # Load in the sources and compute srcs = [ephem.Sun(), ephem.Jupiter()] for line in _srcs: srcs.append(ephem.readdb(line)) for i in xrange(len(srcs)): srcs[i].compute(observer) # # Standard prediction output # # Header print("") print("%-10s %-23s" % ( "Source", "Next Transit", )) print("=" * (10 + 2 + 23)) # List found = False for src in srcs: if src.name.lower() == config['source'].lower(): found = True nT = str( observer.next_transit( src, start=tNow.strftime("%Y/%m/%d %H:%M:%S"))) nT = _UTC.localize(datetime.strptime(nT, "%Y/%m/%d %H:%M:%S")) print("%-10s %-23s" % (src.name, nT.strftime("%Y/%m/%d %H:%M:%S %Z"))) print("%-10s %-23s" % ("", nT.astimezone(_MST).strftime("%Y/%m/%d %H:%M:%S %Z"))) print(" ") break if found: startRec = nT - timedelta(seconds=int(round(config['duration'] / 2.0))) mjd, mpm = datetime_to_mjdmpm(startRec) dur = int(round(config['duration'] * 1000)) cmd = 'DR5 REC "%i %i %i TBN_FILT_%i"' % (mjd, mpm, dur, config['filter']) antpols = 520 sample_rate = tbn_filters[config['filter']] dataRate = 1.0 * sample_rate / 512 * tbnFRAME_SIZE * antpols print("Recording:") print(" Start: %s" % startRec.strftime("%Y/%m/%d %H:%M:%S %Z")) print(" %s" % startRec.astimezone(_MST).strftime("%Y/%m/%d %H:%M:%S %Z")) print(" Duration: %.3f s" % (dur / 1000.0, )) print(" TBN Filter Code: %i" % config['filter']) print(" Data rate: %.2f MB/s" % (dataRate / 1024**2, )) print(" Data volume: %.2f GB" % (dataRate * dur / 1000.0 / 1024**3, )) print(" ") print("Data Recorder Command:") print(" %s" % cmd) else: raise RuntimeError("Unknown source '%s'" % config['source'])
def main(args): # Gather the necessary information to figure out where things are observer = lwa1.get_observer() antennas = lwa1.antennas # Divy up the command line arguments filename = args[0] pointingAz = float(args[1]) pointingEl = float(args[2]) # Load the data dataDict = numpy.load(filename) ## Frequency central_freq = dataDict['central_freq'] ## Integration time tInt = dataDict['tInt'] ## Start times of the integrations times = dataDict['times'] ## The visiblity data phase = dataDict['simpleVis'] print("Central frequency: %.3f Hz" % central_freq) # Build the source list beginDate = datetime.utcfromtimestamp(times[0]) observer.date = beginDate.strftime("%Y/%m/%d %H:%M:%S") srcs = [ephem.Sun(),] for line in _srcs: srcs.append( ephem.readdb(line) ) # Identify the location of the reference source (the Sun in this case) az = -99 el = -99 for i in xrange(len(srcs)): srcs[i].compute(observer) if srcs[i].name == 'Sun': az = srcs[i].az * 180.0/numpy.pi el = srcs[i].alt * 180.0/numpy.pi # Generate geometric delay coefficients aln = [] for i in xrange(phase.shape[1]): gd = getGeoDelay(antennas[i], az, el, Degrees=True) aln.append( numpy.exp(2j*numpy.pi*central_freq*gd) ) aln = numpy.array(aln) # Build the c^l_n values from Steve's "Fun with TBN" memo (Eqn. 10) cln = numpy.zeros(phase.shape, dtype=numpy.complex128) for i in xrange(cln.shape[1]): if i % 2 == 0: cln[:,i] = phase[:,i] / phase[:,0] else: cln[:,i] = phase[:,i] / phase[:,1] cln /= aln # Compute the geometric delay for the requested pointing alnPointing = [] for i in xrange(phase.shape[1]): gd = getGeoDelay(antennas[i], pointingAz, pointingEl, Degrees=True) alnPointing.append( numpy.exp(2j*numpy.pi*central_freq*gd) ) alnPointing = numpy.array(alnPointing) # Calculate the beamforming coefficients blnPointing = (cln*alnPointing).conj() / numpy.abs(cln*alnPointing) # Intepret these purely as delays delays = numpy.angle(blnPointing) / (2*numpy.pi*central_freq) delays = delays.max() - delays # Save import gain import delay dftBase = 'phased_beam_%.2faz_%.2fel_%iMHz' % (pointingAz, pointingEl, central_freq/1e6,) junk = delay.list2delayfile('.', dftBase, delays[0,:]*1e9)
def main(args): observer = lwa1.get_observer() antennas = lwa1.antennas reference = args[0] filename = args[1] dataDict = numpy.load(filename) ref = dataDict['ref'].item() refX = dataDict['refX'].item() refY = dataDict['refY'].item() central_freq = dataDict['central_freq'].item() tInt = dataDict['tInt'].item() times = dataDict['times'] phase = dataDict['simpleVis'] # Get the start time as a datetime object and build up the list of sources beginDate = datetime.utcfromtimestamp(times[0]) observer.date = beginDate.strftime("%Y/%m/%d %H:%M:%S") srcs = [ephem.Sun(),] for line in _srcs: srcs.append( ephem.readdb(line) ) # Report on the data so far... print("Central Frequency: %.3f Hz" % central_freq) print("Start date/time: %s" % beginDate.strftime("%Y/%m/%d %H:%M:%S")) print("Integration Time: %.3f s" % tInt) print("Number of time samples: %i (%.3f s)" % (phase.shape[0], phase.shape[0]*tInt)) # Compute the locations of all of the sources to figure out where the # reference is print("Starting Source Positions:") refSrc = None for i in xrange(len(srcs)): srcs[i].compute(observer) if srcs[i].alt > 0: print(" source %-4s: alt %4.1f degrees, az %5.1f degrees" % (srcs[i].name, srcs[i].alt*180/numpy.pi, srcs[i].az*180/numpy.pi)) if srcs[i].name == reference: refSrc = srcs[i] if refSrc is None: print("Cannot find reference source '%s' in source list, aborting." % reference) sys.exit(1) # Calculate the fringe rates of all sources - for display purposes only print("Starting Fringe Rates:") for src in srcs: if src.alt > 0: fRate = getFringeRate(antennas[0], antennas[refX], observer, src, central_freq) print(" source %-4s: %+6.3f mHz" % (src.name, fRate*1e3)) # Fringe stopping using the reference source print("Fringe stopping:") pbar = ProgressBar(max=phase.shape[1]) phase2 = 1.0*phase for l in xrange(phase.shape[1]): # Compute the fringe rates across all time fRate = [None,]*phase.shape[0] for i in xrange(phase.shape[0]): currDate = datetime.utcfromtimestamp(times[i]) observer.date = currDate.strftime("%Y/%m/%d %H:%M:%S") if l % 2 == 0: fRate[i] = getFringeRate(antennas[l], antennas[refX], observer, refSrc, central_freq) else: fRate[i] = getFringeRate(antennas[l], antennas[refY], observer, refSrc, central_freq) # Create the basis rate and the residual rates baseRate = fRate[0] residRate = numpy.array(fRate) - baseRate # Fringe stop to more the source of interest to the DC component phase2[:,l] *= numpy.exp(-2j*numpy.pi* baseRate*(times - times[0])) phase2[:,l] *= numpy.exp(-2j*numpy.pi*residRate*(times - times[0])) pbar.inc() sys.stdout.write("%s\r" % pbar.show()) sys.stdout.flush() sys.stdout.write('\n') # Compute the beam forming coefficients for the reference source bln = numpy.zeros(phase2.shape, dtype=numpy.complex128) for i in xrange(bln.shape[1]): if i % 2 == 0: bln[:,i] = phase2[:,i] / phase2[:,0] else: bln[:,i] = phase2[:,i] / phase2[:,1] bln = bln.conj() / numpy.abs(bln) # Average all time steps together and make sure we end up with # a 2-D array in the end bln = bln.mean(axis=0) bln.shape = (1,) + bln.shape # Compute the a^l_n terms for removing the array geometry. print("Computing array geometry:") pbar = ProgressBar(max=phase2.shape[1]) aln = numpy.zeros_like(phase2) for l in xrange(phase2.shape[1]): currDate = datetime.utcfromtimestamp(times[0]) observer.date = currDate.strftime("%Y/%m/%d %H:%M:%S") refSrc.compute(observer) az = refSrc.az el = refSrc.alt gd = getGeoDelay(antennas[l], az, el, Degrees=False) aln[:,l] = numpy.exp(2j*numpy.pi*central_freq*gd) pbar.inc() sys.stdout.write("%s\r" % pbar.show()) sys.stdout.flush() sys.stdout.write('\n') # Calculate the c^l_n terms by removing the array geometry from the # phases. cln = numpy.zeros(phase2.shape, dtype=numpy.complex128) for i in xrange(cln.shape[1]): if i % 2 == 0: cln[:,i] = phase2[:,i] / phase2[:,0] else: cln[:,i] = phase2[:,i] / phase2[:,1] cln /= aln # Average all time steps together and make sure we end up with # a 2-D array in the end cln = cln.mean(axis=0) cln.shape = (1,) + cln.shape # Save outname = filename.replace('-vis','-cln') numpy.savez(outname, bln=bln, cln=cln, central_freq=central_freq, reference=reference, basefile=filename)
def main(args): # The task at hand clnfile = args[0] az = float(args[1]) el = float(args[2]) filename = args[3] # The station observer = lwa1.get_observer() antennas = lwa1.antennas # The file's parameters fh = open(filename, 'rb') nFramesFile = os.path.getsize(filename) / tbn.FRAME_SIZE srate = tbn.get_sample_rate(fh) antpols = len(antennas) # Reference antenna ref = 258 for a in antennas: if a.stand.id == ref and a.pol == 0: refX = a.digitizer elif a.stand.id == ref and a.pol == 1: refY = a.digitizer else: pass # Integration time (seconds and frames) tInt = 5.0 nFrames = int(round(tInt * srate / 512 * antpols)) tInt = nFrames / antpols * 512 / srate # Total run length #nChunks = int(round(1.0*nFramesFile / nFrames)) nChunks = 240 # Read in the first frame and get the date/time of the first sample # of the frame. This is needed to get the list of stands. junkFrame = tbn.read_frame(fh) fh.seek(-tbn.FRAME_SIZE, 1) startFC = junkFrame.header.frame_count central_freq = junkFrame.central_freq beginDate = junkFrame.time.datetime observer.date = beginDate srcs = [] for line in _srcs: srcs.append(ephem.readdb(line)) srcs[-1].compute(observer) if srcs[-1].alt > 0: print("source %s: alt %.1f degrees, az %.1f degrees" % (srcs[-1].name, srcs[-1].alt * 180 / numpy.pi, srcs[-1].az * 180 / numpy.pi)) # File summary print("Filename: %s" % filename) print("Date of First Frame: %s" % str(beginDate)) print("Ant/Pols: %i" % antpols) print("Sample Rate: %i Hz" % srate) print("Tuning Frequency: %.3f Hz" % central_freq) print("Frames: %i (%.3f s)" % (nFramesFile, 1.0 * nFramesFile / antpols * 512 / srate)) print("---") print("Integration: %.3f s (%i frames; %i frames per stand/pol)" % (tInt, nFrames, nFrames / antpols)) print("Chunks: %i" % nChunks) junkFrame = tbn.read_frame(fh) while junkFrame.header.frame_count < startFC + 3: junkFrame = tbn.read_frame(fh) fh.seek(-tbn.FRAME_SIZE, 1) # Get the beamformer coefficients - three sets: # (1) at the requested az, el # (2) at az, el - 15 degrees # (3) at the transit location of Cyg A dataDict = numpy.load(clnfile) cln = dataDict['cln'] aln1 = [] aln2 = [] aln3 = [] for i in xrange(cln.shape[1]): gd = getGeoDelay(antennas[i], az, el, central_freq, Degrees=True) aln1.append(numpy.exp(2j * numpy.pi * central_freq * gd)) gd = getGeoDelay(antennas[i], az, el - 15, central_freq, Degrees=True) aln2.append(numpy.exp(2j * numpy.pi * central_freq * gd)) gd = getGeoDelay(antennas[i], 0.5, 83.3, central_freq, Degrees=True) aln3.append(numpy.exp(2j * numpy.pi * central_freq * gd)) aln1 = numpy.array(aln1) aln2 = numpy.array(aln2) aln3 = numpy.array(aln3) bln1 = (cln * aln1).conj() / numpy.abs(cln * aln1) bln2 = (cln * aln2).conj() / numpy.abs(cln * aln2) bln3 = (cln * aln3).conj() / numpy.abs(cln * aln3) for i in xrange(cln.shape[1]): if antennas[i].combined_status != 33 or antennas[i].stand.id == ref: bln1[:, i] = 0.0 bln2[:, i] = 0.0 bln3[:, i] = 0.0 # Create the FrameBuffer instance buffer = TBNFrameBuffer(stands=range(1, antpols / 2 + 1), pols=[0, 1], reorder=False) # Create the beam times = numpy.zeros(nChunks, dtype=numpy.float64) beam1 = numpy.zeros((nChunks, 2), dtype=numpy.float64) beam2 = numpy.zeros((nChunks, 2), dtype=numpy.float64) beam3 = numpy.zeros((nChunks, 2), dtype=numpy.float64) # Go! k = 0 for i in xrange(nChunks): # Find out how many frames remain in the file. If this number is larger # than the maximum of frames we can work with at a time (maxFrames), # only deal with that chunk framesRemaining = nFramesFile - k if framesRemaining > nFrames: framesWork = nFrames data = numpy.zeros((antpols, framesWork / antpols * 512), dtype=numpy.complex64) else: framesWork = framesRemaining + antpols * buffer.nsegments data = numpy.zeros((antpols, framesWork / antpols * 512), dtype=numpy.complex64) print("Working on chunk %i, %i frames remaining" % (i + 1, framesRemaining)) count = [0 for a in xrange(antpols)] j = 0 fillsWork = framesWork / antpols # Inner loop that actually reads the frames into the data array while j < fillsWork: try: cFrame = tbn.read_frame(fh) k = k + 1 except errors.EOFError: break except errors.SyncError: #print("WARNING: Mark 5C sync error on frame #%i" % (int(fh.tell())/tbn.FRAME_SIZE-1)) continue buffer.append(cFrame) cFrames = buffer.get() if cFrames is None: continue valid = sum(lambda x, y: x + int(y.valid), cFrames, 0) if valid != antpols: print( "WARNING: frame count %i at %i missing %.2f%% of frames" % (cFrames[0].header.frame_count, cFrames[0].payload.timetag, float(antpols - valid) / antpols * 100)) continue for cFrame in cFrames: stand, pol = cFrame.header.id # In the current configuration, stands start at 1 and go up to 260. So, we # can use this little trick to populate the data array aStand = 2 * (stand - 1) + pol # Save the time if j == 0 and aStand == 0: times[i] = cFrame.time data[aStand, count[aStand] * 512:(count[aStand] + 1) * 512] = cFrame.payload.data # Update the counters so that we can average properly later on count[aStand] = count[aStand] + 1 j += 1 # Mask bad = numpy.where(numpy.abs(data) >= 90) data[bad] = 0.0 # Beam forming taskPool = Pool(processes=6) taskList = [] taskList.append( (i, 1, 0, taskPool.apply_async(form_beam, args=(data[0::2, :], bln1[0, 0::2])))) taskList.append( (i, 1, 1, taskPool.apply_async(form_beam, args=(data[1::2, :], bln1[0, 1::2])))) taskList.append( (i, 2, 0, taskPool.apply_async(form_beam, args=(data[0::2, :], bln2[0, 0::2])))) taskList.append( (i, 2, 1, taskPool.apply_async(form_beam, args=(data[1::2, :], bln2[0, 1::2])))) taskList.append( (i, 3, 0, taskPool.apply_async(form_beam, args=(data[0::2, :], bln3[0, 0::2])))) taskList.append( (i, 3, 1, taskPool.apply_async(form_beam, args=(data[1::2, :], bln3[0, 1::2])))) taskPool.close() taskPool.join() for i, b, p, task in taskList: if b == 1: beam1[i, p] = task.get() elif b == 2: beam2[i, p] = task.get() else: beam3[i, p] = task.get() print('1', beam1[i, 0], '2', beam2[i, 0], '3', beam3[i, 0], '1/2', beam1[i, 0] / beam2[i, 0], '3/2', beam3[i, 0] / beam2[i, 0]) del data # Plot the data print('CygA :', beam1[:, 0]) print('Pointing 2:', beam2[:, 0]) print('Pointing 1:', beam3[:, 0]) fig = plt.figure() ax1 = fig.add_subplot(1, 2, 1) ax2 = fig.add_subplot(1, 2, 2) ax1.plot(times - times[0], beam1[:, 0]) ax1.plot(times - times[0], beam2[:, 0]) ax1.plot(times - times[0], beam3[:, 0]) ax2.plot(times - times[0], beam1[:, 1]) ax2.plot(times - times[0], beam2[:, 1]) ax2.plot(times - times[0], beam3[:, 1]) plt.show()
def main(args): # Parse the command line filename = args.filename # Load in the data to see what we should do dataDict = numpy.load(filename) srcName = dataDict['source'].item() freq = dataDict['freq'] unx = dataDict['unx'] lst = dataDict['lst'] pwrX = dataDict['pwrX'] pwrY = dataDict['pwrY'] dataDict.close() # Form Stokes I out of X and Y pwrI = pwrX + pwrY # Read in each of the data sets data = {} pointing = {} tStartPlot = 1e12 for i, name in enumerate(('south', srcName, 'north')): pointing[name] = name if unx[0] < tStartPlot: tStartPlot = unx[0] data[name] = {'t': unx, 'f1': freq, 'I1': pwrI[:, i, :]} # Get LWA-1 observer = lwa1.get_observer() # Load in the sources and find the right one srcs = getSources() simSrcs = getAIPYSources() toUse = None for srcName in data.keys(): for src in srcs.keys(): if src.lower() == srcName.lower(): toUse = src observer.date = datetime.utcfromtimestamp( data[srcName]['t'][0]) break if toUse is None: raise RuntimeError("Unknown source in input files") toUseAIPY = srcs[toUse].name try: simSrcs[toUseAIPY] except KeyError: toUseAIPY = None print("Warning: Cannot find flux for this target") # Find out when the source should have transitted the beam tTransit = 0.0 zenithAngle = ephem.degrees('180:00:00') for name in pointing.keys(): if name.lower() != srcs[toUse].name.lower(): continue observer.next_transit(srcs[toUse]) az = srcs[toUse].az el = srcs[toUse].alt bestT = 0.0 bestV = 1e6 for t in data[name]['t']: observer.date = datetime.utcfromtimestamp(t).strftime( "%Y/%m/%d %H:%M:%S") srcs[toUse].compute(observer) sep = ephem.separation((srcs[toUse].az, srcs[toUse].alt), (az, el)) if sep < bestV: bestT = t bestV = sep tTransit = bestT observer.date = datetime.utcfromtimestamp(tTransit).strftime( "%Y/%m/%d %H:%M:%S") zenithAngle = ephem.degrees(ephem.degrees('90:00:00') - el) # Plot fig = plt.figure() ax1 = fig.gca() raOffsets1 = {} decPowers1 = {} fwhmEstimates1 = {} sefdEstimate1 = None raOffsets2 = {} decPowers2 = {} fwhmEstimates2 = {} sefdEstimate2 = None for name in data.keys(): t = data[name]['t'] f1 = data[name]['f1'] I1 = data[name]['I1'] # Select data that was actually recorded good = numpy.where((t > 0) & (I1[:, 10] > 0))[0][:-1] t = t[good] I1 = I1[good] # Sum over the interesting part of the band toUseSpec = numpy.where((f1 > 60e6) & (f1 < 80e6))[0] I1 = I1[:, toUseSpec].sum(axis=1) # Convert the scales to unit flux I1 /= I1.max() # Fit a Gaussian to the power to find the transit time and beam width includeLinear = False if includeLinear: obsTransit1, sefdMetric1, obsFWHM1, obsSlope1, obsFit1 = fitDriftscan( t, I1, includeLinear=True) linear1 = obsSlope1 * t linear1 -= linear1[:10].mean() I1 -= linear1 obsFit1 -= linear1 obsTransit1, sefdMetric1, obsFWHM1, obsFit1 = fitDriftscan( t, I1, includeLinear=False) # Save the results diff1 = obsTransit1 - tTransit raOffsets1[name] = diff1 decPowers1[name] = obsFit1.max() - obsFit1.min() fwhmEstimates1[name] = obsFWHM1 / 3600. * 15. * numpy.cos( srcs[toUse]._dec) # Report print('Target: %s' % name) print(' Tuning 1 @ %.2f MHz' % (f1.mean() / 1e6, )) print(' FWHM: %.2f s (%.2f deg)' % (obsFWHM1, obsFWHM1 / 3600. * 15. * numpy.cos(srcs[toUse]._dec))) print(' Observed Transit: %s' % datetime.utcfromtimestamp(obsTransit1)) print(' Expected Transit: %s' % datetime.utcfromtimestamp(tTransit)) print(' -> Difference: %.2f s' % diff1) if toUseAIPY is None: print(' 1/(P1/P0 - 1): %.3f' % sefdMetric1) else: simSrcs[toUseAIPY].compute(observer, afreqs=f1.mean() / 1e9) srcFlux = simSrcs[toUseAIPY].jys sefd = srcFlux * sefdMetric1 / 1e3 print(' S / (P1/P0 - 1): %.3f kJy' % sefd) if name == srcs[toUse].name: sefdEstimate1 = sefd * 1e3 # Plot ax1.plot(t - tStartPlot, I1, label="%s" % name) ax1.plot(t - tStartPlot, obsFit1, linestyle=':') ylim1 = ax1.get_ylim() ax1.vlines(tTransit - tStartPlot, *ylim1, linestyle='--', label='Expected Transit') ax1.set_ylim(ylim1) ax1.legend(loc=0) ax1.set_title('%.2f MHz' % (f1.mean() / 1e6, )) ax1.set_xlabel('Elapsed Time [s]') ax1.set_ylabel('Power [arb.]') # Compute the dec. offset dataSet1 = (f1.mean(), raOffsets1, decPowers1, fwhmEstimates1, sefdEstimate1) sys.stderr.write( "Source YYYY/MM/DD HH:MM:SS MHz Z errRA errDec SEFD FWHM\n" ) for f, raOffsets, decPowers, fwhmEstimates, sefdEstimate in (dataSet1, ): do = [] dp = [] bestOffset = None bestPower = -1e6 bestFWHM = None for name in decPowers.keys(): offset = raOffsets[name] power = decPowers[name] fwhm = fwhmEstimates[name] if power > bestPower: bestOffset = offset bestPower = power bestFWHM = fwhm if name.find('north') != -1: do.append(1.0) elif name.find('south') != -1: do.append(-1.0) else: do.append(0.0) dp.append(power) do = numpy.array(do) dp = numpy.array(dp) order = numpy.argsort(do) do = do[order] dp = dp[order] try: decOffset = fitDecOffset(do, dp, fwhm=bestFWHM) except TypeError: decOffset = -99 raOffset = ephem.hours('00:00:%f' % bestOffset) decOffset = ephem.degrees('%f' % decOffset) fwhmEstimate = ephem.degrees('%f' % bestFWHM) print( "%-6s %-19s %6.3f %-10s %-10s %-10s %10.3f %-10s" % (srcs[toUse].name, datetime.utcfromtimestamp(tTransit).strftime("%Y/%m/%d %H:%M:%S"), f / 1e6, zenithAngle, raOffset, decOffset, sefdEstimate, fwhmEstimate)) plt.show()