def test_drx_beam(self): """Test finding out how many beams are present in a DRX file.""" fh = open(drxFile, 'rb') nBeam = drx.get_beam_count(fh) self.assertEqual(nBeam, 1) fh.close()
def main(args): fh = open(args.filename, "rb") nFramesFile = os.path.getsize(args.filename) // drx.FRAME_SIZE while True: junkFrame = drx.read_frame(fh) try: srate = junkFrame.sample_rate break except ZeroDivisionError: pass fh.seek(-drx.FRAME_SIZE, 1) beams = drx.get_beam_count(fh) tunepols = drx.get_frames_per_obs(fh) tunepol = tunepols[0] + tunepols[1] + tunepols[2] + tunepols[3] beampols = tunepol # Offset in frames for beampols beam/tuning/pol. sets offset = int(round(args.offset * srate / 4096 * beampols)) offset = int(1.0 * offset / beampols) * beampols args.offset = 1.0 * offset / beampols * 4096 / srate fh.seek(offset * drx.FRAME_SIZE) # Make sure that the file chunk size contains is an intger multiple # of the beampols. maxFrames = int((19144 * 4) / beampols) * beampols # Setup the statistics data set if args.stats: if args.plot_range < 0.1: args.plot_range = 0.5 # Number of frames to integrate over nFrames = int(args.plot_range * srate / 4096 * beampols) nFrames = int(1.0 * nFrames / beampols) * beampols args.plot_range = 1.0 * nFrames / beampols * 4096 / srate # Number of remaining chunks nChunks = int(math.ceil(1.0 * (nFrames) / maxFrames)) # File summary print("Filename: %s" % args.filename) print("Beams: %i" % beams) print("Tune/Pols: %i %i %i %i" % tunepols) print("Sample Rate: %i Hz" % srate) print("Frames: %i (%.3f s)" % (nFramesFile, 1.0 * nFramesFile / beampols * 4096 / srate)) print("---") print("Offset: %.3f s (%i frames)" % (args.offset, offset)) print("Plot time: %.3f s (%i frames; %i frames per beam/tune/pol)" % (args.plot_range, nFrames, nFrames // beampols)) print("Chunks: %i" % nChunks) # Sanity check if offset > nFramesFile: raise RuntimeError("Requested offset is greater than file length") if nFrames > (nFramesFile - offset): raise RuntimeError( "Requested integration time+offset is greater than file length") # Align the file handle so that the first frame read in the # main analysis loop is from tuning 1, polarization 0 junkFrame = drx.read_frame(fh) b, t, p = junkFrame.id while 2 * (t - 1) + p != 0: junkFrame = drx.read_frame(fh) b, t, p = junkFrame.id fh.seek(-drx.FRAME_SIZE, 1) # Master loop over all of the file chuncks standMapper = [] 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 = nFrames - i * maxFrames if framesRemaining > maxFrames: framesWork = maxFrames else: framesWork = framesRemaining print("Working on chunk %i, %i frames remaining" % (i, framesRemaining)) count = {0: 0, 1: 0, 2: 0, 3: 0} data = numpy.zeros((beampols, framesWork * 4096 // beampols), dtype=numpy.csingle) # Inner loop that actually reads the frames into the data array print("Working on %.1f ms of data" % ((framesWork * 4096 / beampols / srate) * 1000.0)) t0 = time.time() for j in xrange(framesWork): # Read in the next frame and anticipate any problems that could occur try: cFrame = drx.read_frame(fh, verbose=False) except errors.EOFError: break except errors.SyncError: #print("WARNING: Mark 5C sync error on frame #%i" % (int(fh.tell())/drx.FRAME_SIZE-1)) continue beam, tune, pol = cFrame.id aStand = 2 * (tune - 1) + pol data[aStand, count[aStand] * 4096:(count[aStand] + 1) * 4096] = numpy.abs(cFrame.payload.data)**2 # Update the counters so that we can average properly later on count[aStand] += 1 # Statistics print("Running robust statistics") means = [robust.mean(data[i, :]) for i in xrange(data.shape[0])] stds = [robust.std(data[i, :]) for i in xrange(data.shape[0])] if args.stats: ## Report statistics print("Mean: %s" % ' '.join(["%.3f" % m for m in means])) print("StdD: %s" % ' '.join(["%.3f" % s for s in stds])) print("Levels:") ## Count'em up j = 0 counts = [ 1, ] * data.shape[0] while (means[i] + j * stds[i] <= 98) and max(counts) != 0: counts = [ len( numpy.where( numpy.abs(data[i, :] - means[i]) >= j * stds[i])[0]) for i in xrange(data.shape[0]) ] print(" %2isigma (%5.1f%%): %s" % (j, 100.0 * (1 - erf(j / numpy.sqrt(2))), ' '.join([ "%7i (%5.1f%%)" % (c, 100.0 * c / data.shape[1]) for c in counts ]))) j += 1 ## Why j-2? Well, j is 1 more than the last iteration. So, that last iteration ## is j-1, which is always filled with 0s by construction. So, the last crazy ## bin is j-2. jP = j - 2 if jP > 20: counts = [ len( numpy.where( numpy.abs(data[i, :] - means[i]) >= jP * stds[i])[0]) for i in xrange(data.shape[0]) ] for i in xrange(data.shape[0]): if counts[i] > 0: break if counts[i] == 1: print( " -> Clip-o-rama likely occuring with %i %i-sigma detection on tuning %i, pol %i" % (counts[i], jP, i // 2 + 1, i % 2)) else: print( " -> Clip-o-rama likely occuring with %i %i-sigma detections on tuning %i, pol %i" % (counts[i], jP, i // 2 + 1, i % 2)) else: outfile = os.path.splitext(args.filename)[0] outfile = '%s.txt' % outfile fh = open(outfile, 'w') # Plot possible clip-o-rama and flag it print("Computing power derivatives w.r.t. time") deriv = numpy.zeros_like(data) for i in xrange(data.shape[0]): deriv[i, :] = numpy.roll(data[i, :], -1) - data[i, :] # The plots: This is setup for the current configuration of 20 beampols print("Plotting") fig = plt.figure() figsX = int(round(math.sqrt(beampols))) figsY = beampols // figsX for i in xrange(data.shape[0]): ax = fig.add_subplot(figsX, figsY, i + 1) ax.plot(args.offset + numpy.arange(0, data.shape[1]) / srate, data[i, :]) ## Mark areas of crazy derivatives bad = numpy.where( deriv[i, :] > 20 * stds[i] * numpy.sqrt(2))[0] for j in bad: fh.write( "Clip-o-rama on tuning %i, pol. %i at %.6f seconds\n" % (i // 2 + 1, i % 2, args.offset + j / srate)) print("Clip-o-rama on tuning %i, pol. %i at %.6f seconds" % (i // 2 + 1, i % 2, args.offset + j / srate)) ax.vlines(args.offset + j / srate, -10, 100, linestyle='--', color='red', linewidth=2.0) ## Mark areas of crazy power levels bad = numpy.where(data[i, :] == 98)[0] for j in bad: fh.write( "Saturation on tuning %i, pol. %i at %.6f seconds\n" % (i // 2 + 1, i % 2, args.offset + j / srate)) print("Saturation on tuning %i, pol. %i at %.6f seconds" % (i // 2 + 1, i % 2, args.offset + j / srate)) ax.vlines(args.offset + j / srate, -10, 100, linestyle='-.', color='red') ax.set_ylim([-10, 100]) ax.set_title('Beam %i, Tune. %i, Pol. %i' % (beam, i // 2 + 1, i % 2)) ax.set_xlabel('Time [seconds]') ax.set_ylabel('I$^2$ + Q$^2$') fh.close() if args.do_plot: plt.show()
def main(args): fh = open(args.filename, "rb") nFramesFile = os.path.getsize(args.filename) // drx.FRAME_SIZE while True: junkFrame = drx.read_frame(fh) try: srate = junkFrame.sample_rate break except ZeroDivisionError: pass fh.seek(-drx.FRAME_SIZE, 1) print(junkFrame.header.time_offset) beams = drx.get_beam_count(fh) tunepols = drx.get_frames_per_obs(fh) tunepol = tunepols[0] + tunepols[1] + tunepols[2] + tunepols[3] beampols = tunepol # Offset in frames for beampols beam/tuning/pol. sets offset = int(round(args.skip * srate / 4096 * beampols)) offset = int(1.0 * offset / beampols) * beampols args.skip = 1.0 * offset / beampols * 4096 / srate fh.seek(offset * drx.FRAME_SIZE) # Make sure that the file chunk size contains is an intger multiple # of the beampols. maxFrames = int(19144 / beampols) * beampols # Number of frames to integrate over toClip = False oldAverage = args.plot_range if args.plot_range < 4096 / srate: toClip = True args.plot_range = 4096 / srate nFrames = int(args.plot_range * srate / 4096 * beampols) nFrames = int(1.0 * nFrames / beampols) * beampols args.plot_range = 1.0 * nFrames / beampols * 4096 / srate # Number of remaining chunks nChunks = int(math.ceil(1.0 * (nFrames) / maxFrames)) # File summary print("Filename: %s" % args.filename) print("Beams: %i" % beams) print("Tune/Pols: %i %i %i %i" % tunepols) print("Sample Rate: %i Hz" % srate) print("Frames: %i (%.3f s)" % (nFramesFile, 1.0 * nFramesFile / beampols * 4096 / srate)) print("---") print("Offset: %.3f s (%i frames)" % (args.skip, offset)) print("Plot time: %.3f s (%i frames; %i frames per beam/tune/pol)" % (args.plot_range, nFrames, nFrames // beampols)) print("Chunks: %i" % nChunks) # Sanity check if offset > nFramesFile: raise RuntimeError("Requested offset is greater than file length") if nFrames > (nFramesFile - offset): raise RuntimeError( "Requested integration time+offset is greater than file length") junkFrame = drx.read_frame(fh) b, t, p = junkFrame.id while 2 * (t - 1) + p != 0: junkFrame = drx.read_frame(fh) b, t, p = junkFrame.id print(b, t, p) print(fh.tell()) fh.seek(-drx.FRAME_SIZE, 1) # Master loop over all of the file chuncks standMapper = [] for i in range(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 = nFrames - i * maxFrames if framesRemaining > maxFrames: framesWork = maxFrames else: framesWork = framesRemaining print("Working on chunk %i, %i frames remaining" % (i, framesRemaining)) count = {} data = numpy.zeros((beampols, framesWork * 4096 // beampols), dtype=numpy.csingle) # Inner loop that actually reads the frames into the data array print("Working on %.1f ms of data" % ((framesWork * 4096 / beampols / srate) * 1000.0)) t0 = time.time() for j in xrange(framesWork): # Read in the next frame and anticipate any problems that could occur try: cFrame = drx.read_frame(fh, verbose=False) except errors.EOFError: break except errors.SyncError: #print("WARNING: Mark 5C sync error on frame #%i" % (int(fh.tell())/drx.FRAME_SIZE-1)) continue beam, tune, pol = cFrame.id aStand = 4 * (beam - 1) + 2 * (tune - 1) + pol #print(aStand, beam, tune, pol) if aStand not in standMapper: standMapper.append(aStand) oStand = 1 * aStand aStand = standMapper.index(aStand) print( "Mapping beam %i, tune. %1i, pol. %1i (%2i) to array index %3i" % (beam, tune, pol, oStand, aStand)) else: aStand = standMapper.index(aStand) if aStand not in count.keys(): count[aStand] = 0 #if cFrame.header.frame_count % 10000 == 0 and args.verbose: # print("%2i,%1i,%1i -> %2i %5i %i" % (beam, tune, pol, aStand, cFrame.header.frame_count, cFrame.payload.timetag)) #print(data.shape, count[aStand]*4096, (count[aStand]+1)*4096, cFrame.payload.data.shape) data[aStand, count[aStand] * 4096:(count[aStand] + 1) * 4096] = cFrame.payload.data # Update the counters so that we can average properly later on count[aStand] += 1 # The plots: This is setup for the current configuration of 20 beampols fig = plt.figure() figsX = int(round(math.sqrt(beampols))) figsY = beampols // figsX t1X = 1 t1Y = 1 offset = 0 samples = 65536 for sec in xrange(data.shape[1] // samples): if toClip: print("Plotting only the first %i samples (%.3f ms) of data" % (samples, oldAverage * 1000.0)) sortedMapper = sorted(standMapper) for k, aStand in enumerate(sortedMapper): i = standMapper.index(aStand) if standMapper[i] % 2 == 0: ref = data[0, :] t1R = t1X else: ref = data[1, :] t1R = t1Y (lag, cc), junkI, junkQ = crossCorrelate( data[i, sec * samples:(sec + 1) * samples], ref[offset + sec * samples:offset + (sec + 1) * samples]) best = numpy.where(cc == cc.max())[0][0] if args.verbose: print('tune %i pol. %s' % (standMapper[i] % 4 // 2 + 1, standMapper[i] % 2)) print(' -> best peak of %.0f at a lag of %i samples' % (cc.max(), lag[best])) print(' -> NCM with tuning 1 of %.3f' % (cc.max() / t1R)) # Plot ax = fig.add_subplot(figsX, figsY, k + 1) ax.plot(lag, cc, label='Same', color='blue') # Center on the peak best = numpy.where(cc == cc.max())[0][0] ax.set_xlim([lag[best - 50], lag[best + 50]]) ax.set_title('Beam %i, Tune. %i, Pol. %i' % (standMapper[i] // 4 + 1, standMapper[i] % 4 // 2 + 1, standMapper[i] % 2)) ax.set_xlabel('Lag [samples]') ax.set_ylabel('Analysis Sets') # Save the tuning 1 values for the peak of the CC function if standMapper[i] % 4 / 2 + 1 == 1: if standMapper[i] % 2 == 0: t1X = cc.max() else: t1Y = cc.max() plt.show() # Save image if requested if args.output is not None: fig.savefig(args.output)
def main(args): filename = args[0] fh = open(filename, "rb") nFramesFile = os.path.getsize(filename) / drx.FRAME_SIZE junkFrame = drx.read_frame(fh) beam, tune, pol = junkFrame.id while 2 * (tune - 1) + pol != 0: junkFrame = drx.read_frame(fh) beam, tune, pol = junkFrame.id fh.seek(fh.tell() - drx.FRAME_SIZE) srate = junkFrame.sample_rate beams = drx.get_beam_count(fh) tunepols = drx.get_frames_per_obs(fh) tunepol = tunepols[0] + tunepols[1] + tunepols[2] + tunepols[3] beampols = tunepol # File summary out = "Filename: %s" % filename out += "\nBeams: %i" % beams out += "\nTune/Pols: %i %i %i %i" % tunepols out += "\nSample Rate: %i Hz" % srate out += "\nFrames: %i (%.3f s)" % (nFramesFile, 1.0 * nFramesFile / beampols * 4096 / srate) out += "\n===" print(out) tuningOffset = numpy.zeros(nFramesFile / 8, dtype=numpy.int64) try: screen = curses.initscr() curses.noecho() curses.cbreak() screen.nodelay(1) strdict = {'preamble': out} for i in xrange(tuningOffset.size): screen.clear() beamIDs = [0, 0, 0, 0] timetags = numpy.zeros(4, dtype=numpy.int64) - 1 time_offsets = numpy.zeros(4, dtype=numpy.int64) - 1 timeValues = numpy.zeros(4, dtype=numpy.float64) for j in xrange(4): # Read in the next frame and anticipate any problems that could occur try: cFrame = drx.read_frame(fh, verbose=False) except errors.EOFError: break except errors.SyncError: #print("WARNING: Mark 5C sync error on frame #%i" % (int(fh.tell())/drx.FRAME_SIZE-1)) continue ## Save the time time, time offset, and computed time values beam, tune, pol = cFrame.id aStand = 2 * (tune - 1) + pol if timetags[aStand] == -1: beamIDs[aStand] = (beam, tune, pol) timetags[aStand] = cFrame.payload.timetag time_offsets[aStand] = cFrame.header.time_offset timeValues[aStand] = cFrame.time k = 0 for id, tt, to, tv in zip(beamIDs, timetags, time_offsets, timeValues): strdict['b%i' % k] = id[0] strdict['t%i' % k] = id[1] strdict['p%i' % k] = id[2] strdict['tt%i' % k] = tt strdict['os%i' % k] = to strdict['tv%i' % k] = tv k += 1 t1t = timetags[0] - time_offsets[0] t2t = timetags[3] - time_offsets[3] tuningOffset[i] = t2t - t1t strdict['ttd'] = t2t - t1t strdict['tvd'] = (t2t - t1t) / fS screen.addstr(0, 0, display.safe_substitute(strdict)) screen.refresh() # Check for keypress and exit if Q c = screen.getch() if (c > 0): if chr(c) == 'q': break if chr(c) == 'Q': break curses.nocbreak() curses.echo() curses.endwin() except KeyboardInterrupt: curses.nocbreak() curses.echo() curses.endwin() tuningOffset = tuningOffset[0:i] print(display.safe_substitute(strdict)) print( "T2-T1 time tag offset range: %i to %i (based on %i sets of frames)" % (tuningOffset.min(), tuningOffset.max(), len(tuningOffset)))
def main(args): filename = args.filename sizeB = os.path.getsize(filename) # Open the file and get some basic info about the data contained fh = open(filename, 'rb') nFramesFile = sizeB / drx.FRAME_SIZE while True: try: junkFrame = drx.read_frame(fh) try: srate = junkFrame.sample_rate t0 = junkFrame.time break except ZeroDivisionError: pass except errors.SyncError: fh.seek(-drx.FRAME_SIZE + 1, 1) fh.seek(-drx.FRAME_SIZE, 1) beams = drx.get_beam_count(fh) tunepols = drx.get_frames_per_obs(fh) tunepol = tunepols[0] + tunepols[1] + tunepols[2] + tunepols[3] beampols = tunepol # Offset in frames for beampols beam/tuning/pol. sets offset = int(round(args.offset * srate / 4096 * beampols)) offset = int(1.0 * offset / beampols) * beampols fh.seek(offset * drx.FRAME_SIZE, 1) # Iterate on the offsets until we reach the right point in the file. This # is needed to deal with files that start with only one tuning and/or a # different sample rate. while True: ## Figure out where in the file we are and what the current tuning/sample ## rate is junkFrame = drx.read_frame(fh) srate = junkFrame.sample_rate t1 = junkFrame.time tunepols = drx.get_frames_per_obs(fh) tunepol = tunepols[0] + tunepols[1] + tunepols[2] + tunepols[3] beampols = tunepol fh.seek(-drx.FRAME_SIZE, 1) ## See how far off the current frame is from the target tDiff = t1 - (t0 + args.offset) ## Half that to come up with a new seek parameter tCorr = -tDiff / 2.0 cOffset = int(tCorr * srate / 4096 * beampols) cOffset = int(1.0 * cOffset / beampols) * beampols offset += cOffset ## If the offset is zero, we are done. Otherwise, apply the offset ## and check the location in the file again/ if cOffset is 0: break fh.seek(cOffset * drx.FRAME_SIZE, 1) # Update the offset actually used args.offset = t1 - t0 nCaptures = nFramesFile / beampols print("Filename: %s" % filename) print("Size: %.1f MB" % (float(sizeB) / 1024 / 1024)) print("Captures: %i (%.2f seconds)" % (nCaptures, nCaptures * 4096 / srate)) print("Tuning/Pols.: %i " % tunepol) print("Sample Rate: %.2f MHz" % (srate / 1e6)) print("===") if args.count > 0: nCaptures = args.count * srate // 4096 else: nCaptures -= args.offset * srate // 4096 args.count = nCaptures * 4096 // srate print("Seconds to Skip: %.2f (%i captures)" % (args.offset, offset / beampols)) print("Seconds to Split: %.2f (%i captures)" % (args.count, nCaptures)) # Make sure that the first frame in the file is the first frame of a capture # (tuning 1, pol 0). If not, read in as many frames as necessary to get to # the beginning of a complete capture. beam, tune, pol = junkFrame.id skip = 0 while (2 * (tune - 1) + pol) != 0: frame = drx.read_frame(fh) beam, tune, pol = frame.id skip += 1 nFramesRemaining = (sizeB - fh.tell()) // drx.FRAME_SIZE nRecursions = int(nFramesRemaining // (nCaptures * beampols)) if not args.recursive: nRecursions = 1 scale = int(math.log10(nRecursions)) + 1 ifString = "Working on #%%%ii of %i (%%s)" % (scale, nRecursions) for r in range(nRecursions): if args.date: filePos = fh.tell() junkFrame = drx.read_frame(fh) fh.seek(filePos) dt = junkFrame.time.datetime captFilename = "%s_%s.dat" % (os.path.splitext( os.path.basename(filename))[0], dt.isoformat()) else: captFilename = "%s_s%04i_p%%0%ii.dat" % (os.path.splitext( os.path.basename(filename))[0], args.count, scale) captFilename = captFilename % r if not args.recursive: captFilename = "%s_s%04i.dat" % (os.path.splitext( os.path.basename(filename))[0], args.count) print(ifString % (r + 1, captFilename)) t0 = time.time() fhOut = open(captFilename, 'wb') split_file(fh, fhOut, nCaptures, beampols) fhOut.close() t1 = time.time() print(" Copied %i bytes in %.3f s (%.3f MB/s)" % (os.path.getsize(captFilename), t1 - t0, os.path.getsize(captFilename) / 1024.0**2 / (t1 - t0))) fh.close()
def main(args): fh = open(args.filename, "rb") nFramesFile = os.path.getsize(args.filename) // drx.FRAME_SIZE while True: try: junkFrame = drx.read_frame(fh) try: srate = junkFrame.sample_rate t0i, t0f = junkFrame.time break except ZeroDivisionError: pass except errors.SyncError: fh.seek(-drx.FRAME_SIZE + 1, 1) fh.seek(-drx.FRAME_SIZE, 1) beams = drx.get_beam_count(fh) tunepols = drx.get_frames_per_obs(fh) tunepol = tunepols[0] + tunepols[1] + tunepols[2] + tunepols[3] beampols = tunepol # Offset in frames for beampols beam/tuning/pol. sets offset = int(round(args.skip * srate / 4096 * beampols)) offset = int(1.0 * offset / beampols) * beampols fh.seek(offset * drx.FRAME_SIZE, 1) # Iterate on the offsets until we reach the right point in the file. This # is needed to deal with files that start with only one tuning and/or a # different sample rate. while True: ## Figure out where in the file we are and what the current tuning/sample ## rate is junkFrame = drx.read_frame(fh) srate = junkFrame.sample_rate t1i, t1f = junkFrame.time tunepols = drx.get_frames_per_obs(fh) tunepol = tunepols[0] + tunepols[1] + tunepols[2] + tunepols[3] beampols = tunepol fh.seek(-drx.FRAME_SIZE, 1) ## See how far off the current frame is from the target tDiff = t1i - (t0i + args.skip) + (t1f - t0f) ## Half that to come up with a new seek parameter tCorr = -tDiff / 2.0 cOffset = int(tCorr * srate / 4096 * beampols) cOffset = int(1.0 * cOffset / beampols) * beampols offset += cOffset ## If the offset is zero, we are done. Otherwise, apply the offset ## and check the location in the file again/ if cOffset is 0: break fh.seek(cOffset * drx.FRAME_SIZE, 1) # Update the offset actually used args.skip = t1i - t0i + t1f - t0f offset = int(round(args.skip * srate / 4096 * beampols)) offset = int(1.0 * offset / beampols) * beampols # Make sure that the file chunk size contains is an intger multiple # of the beampols. maxFrames = int(19144 / beampols) * beampols # Number of frames to integrate over toClip = False oldAverage = args.plot_range if args.plot_range < 4096 / srate: toClip = True args.plot_range = 4096 / srate nFrames = int(args.plot_range * srate / 4096 * beampols) nFrames = int(1.0 * nFrames / beampols) * beampols args.plot_range = 1.0 * nFrames / beampols * 4096 / srate # Number of remaining chunks nChunks = int(math.ceil(1.0 * (nFrames) / maxFrames)) # File summary print("Filename: %s" % args.filename) print("Beams: %i" % beams) print("Tune/Pols: %i %i %i %i" % tunepols) print("Sample Rate: %i Hz" % srate) print("Frames: %i (%.3f s)" % (nFramesFile, 1.0 * nFramesFile / beampols * 4096 / srate)) print("---") print("Offset: %.3f s (%i frames)" % (args.skip, offset)) print("Plot time: %.3f s (%i frames; %i frames per beam/tune/pol)" % (args.plot_range, nFrames, nFrames // beampols)) print("Chunks: %i" % nChunks) # Sanity check if nFrames > (nFramesFile - offset): raise RuntimeError( "Requested integration time+offset is greater than file length") # Align the file handle so that the first frame read in the # main analysis loop is from tuning 1, polarization 0 junkFrame = drx.read_frame(fh) b, t, p = junkFrame.id while 2 * (t - 1) + p != 0: junkFrame = drx.read_frame(fh) b, t, p = junkFrame.id fh.seek(-drx.FRAME_SIZE, 1) # Master loop over all of the file chuncks standMapper = [] for i in range(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 = nFrames - i * maxFrames if framesRemaining > maxFrames: framesWork = maxFrames else: framesWork = framesRemaining print("Working on chunk %i, %i frames remaining" % (i, framesRemaining)) count = {0: 0, 1: 0, 2: 0, 3: 0} tt = numpy.zeros( (beampols, framesWork // beampols), dtype=numpy.int64) - 1 data = numpy.zeros((beampols, framesWork * 4096 // beampols), dtype=numpy.csingle) # Inner loop that actually reads the frames into the data array print("Working on %.1f ms of data" % ((framesWork * 4096 / beampols / srate) * 1000.0)) t0 = time.time() for j in xrange(framesWork): # Read in the next frame and anticipate any problems that could occur try: cFrame = drx.read_frame(fh, verbose=False) except errors.EOFError: break except errors.SyncError: #print("WARNING: Mark 5C sync error on frame #%i" % (int(fh.tell())//drx.FRAME_SIZE-1)) continue beam, tune, pol = cFrame.id aStand = 2 * (tune - 1) + pol tt[aStand, count[aStand]] = cFrame.payload.timetag if args.instantaneous_power: data[aStand, count[aStand] * 4096:(count[aStand] + 1) * 4096] = numpy.abs(cFrame.payload.data)**2 else: data[aStand, count[aStand] * 4096:(count[aStand] + 1) * 4096] = cFrame.payload.data # Update the counters so that we can average properly later on count[aStand] += 1 # The plots: This is setup for the current configuration of 20 beampols fig = plt.figure() figsX = int(round(math.sqrt(beampols))) figsY = beampols // figsX samples = int(oldAverage * srate) if toClip: print("Plotting only the first %i samples (%.3f ms) of data" % (samples, oldAverage * 1000.0)) sortedMapper = sorted(standMapper) for i in xrange(data.shape[0]): ax = fig.add_subplot(figsX, figsY, i + 1) if args.instantaneous_power: limits = (-10, 100) if toClip: ax.plot(args.skip + numpy.arange(0, samples) / srate, data[i, 0:samples]) else: ax.plot(args.skip + numpy.arange(0, data.shape[1]) / srate, data[i, :]) else: limits = (-8, 8) if toClip: ax.plot(args.skip + numpy.arange(0, samples) / srate, data[i, 0:samples].real, label='I') ax.plot(args.skip + numpy.arange(0, samples) / srate, data[i, 0:samples].imag, label='Q') else: ax.plot(args.skip + numpy.arange(0, data.shape[1]) / srate, data[i, :].real, label='I') ax.plot(args.skip + numpy.arange(0, data.shape[1]) / srate, data[i, :].imag, label='Q') ax.legend(loc=0) if args.mark_frames: for j in xrange(0, samples - 4096, 4096): ax.vlines(float(j) / srate, limits[0], limits[1], color='k', label='%i' % tt[i, j // 4096]) ax.set_ylim(limits) ax.set_title('Beam %i, Tune. %i, Pol. %i' % (beam, i // 2 + 1, i % 2)) ax.set_xlabel('Time [seconds]') if args.instantaneous_power: ax.set_ylabel('I$^2$ + Q$^2$') else: ax.set_ylabel('Output Level') plt.show() # Save image if requested if args.output is not None: fig.savefig(args.output)
def main(args): fh = open(args.filename, "rb") nFramesFile = os.path.getsize(args.filename) // drx.FRAME_SIZE while True: junkFrame = drx.read_frame(fh) try: srate = junkFrame.sample_rate t0i, t0f = junkFrame.time break except ZeroDivisionError: pass fh.seek(-drx.FRAME_SIZE, 1) beams = drx.get_beam_count(fh) tunepols = drx.get_frames_per_obs(fh) tunepol = tunepols[0] + tunepols[1] + tunepols[2] + tunepols[3] beampols = tunepol # Offset in frames for beampols beam/tuning/pol. sets offset = int(round(args.skip * srate / 4096 * beampols)) offset = int(1.0 * offset / beampols) * beampols fh.seek(offset * drx.FRAME_SIZE, 1) # Iterate on the offsets until we reach the right point in the file. This # is needed to deal with files that start with only one tuning and/or a # different sample rate. while True: ## Figure out where in the file we are and what the current tuning/sample ## rate is junkFrame = drx.read_frame(fh) srate = junkFrame.sample_rate t1i, t1f = junkFrame.time tunepols = drx.get_frames_per_obs(fh) tunepol = tunepols[0] + tunepols[1] + tunepols[2] + tunepols[3] beampols = tunepol fh.seek(-drx.FRAME_SIZE, 1) ## See how far off the current frame is from the target tDiff = t1i - (t0i + args.skip) + (t1f - t0f) ## Half that to come up with a new seek parameter tCorr = -tDiff / 2.0 cOffset = int(tCorr * srate / 4096 * beampols) cOffset = int(1.0 * cOffset / beampols) * beampols offset += cOffset ## If the offset is zero, we are done. Otherwise, apply the offset ## and check the location in the file again/ if cOffset is 0: break fh.seek(cOffset * drx.FRAME_SIZE, 1) # Update the offset actually used args.skip = t1i - t0i + t1f - t0f offset = int(round(args.skip * srate / 4096 * beampols)) offset = int(1.0 * offset / beampols) * beampols # Make sure that the file chunk size contains is an intger multiple # of the beampols. maxFrames = int(round(args.average * srate / 4096)) * beampols if maxFrames < beampols: maxFrames = beampols args.average = 1.0 * maxFrames / beampols * 4096 / srate # Number of remaining chunks nChunks = int(round(args.duration / args.average)) nFrames = maxFrames * nChunks # Store the information about the first frame. prevTime = junkFrame.payload.timetag prevDate = junkFrame.time.datetime # File summary print("Filename: %s" % args.filename) print("Beams: %i" % beams) print("Tune/Pols: %i %i %i %i" % tunepols) print("Sample Rate: %i Hz" % srate) print("Date of first frame: %i -> %s" % (prevTime, str(prevDate))) print("Frames: %i (%.3f s)" % (nFramesFile, 1.0 * nFramesFile / beampols * 4096 / srate)) print("---") print("Offset: %.3f s (%i frames)" % (args.skip, offset)) print("Integration: %.4f s (%i frames; %i frames per beam/tune/pol)" % (args.average, maxFrames, maxFrames // beampols)) print("Duration: %.4f s (%i frames; %i frames per beam/tune/pol)" % (args.average * nChunks, nFrames, nFrames // beampols)) print(" ") # Sanity check if nFrames > (nFramesFile - offset): raise RuntimeError( "Requested integration time+offset is greater than file length") # Align the file handle so that the first frame read in the # main analysis loop is from tuning 1, polarization 0 junkFrame = drx.read_frame(fh) b, t, p = junkFrame.id while 2 * (t - 1) + p != 0: junkFrame = drx.read_frame(fh) b, t, p = junkFrame.id fh.seek(-drx.FRAME_SIZE, 1) # Master loop over all of the file chuncks masterTimes = numpy.zeros((nChunks, 4), dtype=numpy.float64) masterData = numpy.zeros((nChunks, 4), dtype=numpy.float32) masterData2 = numpy.zeros((nChunks, 4), dtype=numpy.float32) masterProcessed = [0, 0, 0, 0] masterRemoved = [0, 0, 0, 0] for i in range(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 = nFrames - i * maxFrames if framesRemaining > maxFrames: framesWork = maxFrames else: framesWork = framesRemaining #print("Working on chunk %i, %i frames remaining" % (i, framesRemaining)) count = {0: 0, 1: 0, 2: 0, 3: 0} data = numpy.zeros((4, framesWork * 4096 // beampols), dtype=numpy.float32) data2 = numpy.zeros((4, framesWork * 4096 // beampols), dtype=numpy.float32) ## Inner loop that actually reads the frames into the data array #print("Working on %.2f ms of data" % ((framesWork*4096/beampols/srate)*1000.0)) t0 = time.time() for j in xrange(framesWork): # Read in the next frame and anticipate any problems that could occur try: cFrame = drx.read_frame(fh, verbose=False) except errors.EOFError: break except errors.SyncError: #print("WARNING: Mark 5C sync error on frame #%i" % (int(fh.tell())/drx.FRAME_SIZE-1)) continue beam, tune, pol = cFrame.id aStand = 2 * (tune - 1) + pol if j < 4: masterTimes[i, aStand] = cFrame.time try: framePower = numpy.abs(cFrame.payload.data)**2 # Calculate the clipping mask = numpy.where(framePower <= args.trim_level, 1, 0) data[aStand, count[aStand] * 4096:(count[aStand] + 1) * 4096] = framePower data2[aStand, count[aStand] * 4096:(count[aStand] + 1) * 4096] = framePower * mask masterProcessed[aStand] += mask.size masterRemoved[aStand] += (mask.size - mask.sum()) # Update the counters so that we can average properly later on count[aStand] += 1 except ValueError: pass # Save the data masterData[i, :] = data.sum(axis=1) masterData2[i, :] = data2.sum(axis=1) # Really save the data to a NPZ file if args.write_npz: outfile = os.path.split(args.filename)[1] outfile = os.path.splitext(outfile)[0] outfile = '%s-power.npz' % outfile numpy.savez(outfile, beam=beam, avgPowerFull=masterData, avgPowerTrim=masterData2, times=masterTimes, trimLevel=args.trim_level) # Report on the clipping print("Summary:") for i in xrange(4): print(" Tuning %i, Pol. %s:" % (i / 2 + 1, 'X' if i % 2 else 'Y')) print(" Processed: %i samples" % masterProcessed[i]) print(" Clipped: %i samples" % masterRemoved[i]) print(" -> %.1f%% blanked" % (100.0 * masterRemoved[i] / masterProcessed[i], )) # The plots: This is setup for the current configuration of 20 beampols fig = plt.figure() figsX = int(round(math.sqrt(4))) figsY = 4 // figsX for i in xrange(masterData.shape[1]): ax = fig.add_subplot(figsX, figsY, i + 1) ax.plot(numpy.arange(0, masterData.shape[0]) * args.average, masterData[:, i], label='Full') ax.plot(numpy.arange(0, masterData2.shape[0]) * args.average, masterData2[:, i], label='Trimmed') ax.set_ylim([0, masterData.max()]) ax.set_title('Beam %i, Tune. %i, Pol. %i' % (beam, i // 2 + 1, i % 2)) ax.set_xlabel('Time [seconds]') ax.set_ylabel('Output Power Level') ax.legend(loc=0) # Part 2, polarization stuff fig2 = plt.figure() ax = fig2.add_subplot(3, 2, 1) ax.plot( numpy.arange(0, masterData.shape[0]) * args.average, numpy.sqrt(masterData[:, 0]**2 + masterData[:, 1]**2)) ax.set_title('$\\sqrt{X1^2 + Y1^2}$') ax.set_xlabel('Time [seconds]') ax = fig2.add_subplot(3, 2, 2) ax.plot( numpy.arange(0, masterData.shape[0]) * args.average, masterData[:, 1] / masterData[:, 0]) ax.set_title('$Y1 / X1$') ax.set_xlabel('Time [seconds]') ax = fig2.add_subplot(3, 2, 3) ax.plot( numpy.arange(0, masterData.shape[0]) * args.average, numpy.sqrt(masterData[:, 2]**2 + masterData[:, 3]**2)) ax.set_title('$\\sqrt{X2^2 + Y2^2}$') ax.set_xlabel('Time [seconds]') ax = fig2.add_subplot(3, 2, 4) ax.plot( numpy.arange(0, masterData.shape[0]) * args.average, masterData[:, 3] / masterData[:, 2]) ax.set_title('$Y2 / X2$') ax.set_xlabel('Time [seconds]') ax = fig2.add_subplot(3, 2, 5) ax.plot( numpy.arange(0, masterData.shape[0]) * args.average, numpy.sqrt(masterData[:, 2]**2 + masterData[:, 3]**2) / numpy.sqrt(masterData[:, 0]**2 + masterData[:, 1]**2)) ax.set_title('$\\sqrt{X2^2 + Y2^2} / \\sqrt{X1^2 + Y1^2}$') ax.set_xlabel('Time [seconds]') ax = fig2.add_subplot(3, 2, 6) ax.plot( numpy.arange(0, masterData.shape[0]) * args.average, (masterData[:, 3] / masterData[:, 2]) / (masterData[:, 1] / masterData[:, 0])) ax.set_title('$(Y2 / X2) / (Y1 / X1)$') ax.set_xlabel('Time [seconds]') plt.show() # Save image if requested if args.output is not None: fig.savefig(args.output)