def __call__(self, parser, namespace, values, option_string): colour.cprint("Available Cleaners:", \ bold=True, underline=True) for name in sorted(cleaners.registered_cleaners): cleaner = cleaners.load_cleaner(name) print cleaner.get_help() sys.exit(1)
def sort_fb_files(fbfiles): """Given a list of filterbank objects sort by frequency. """ freqbands = [] reversed = [] for fb in fbfiles: chanbw = fb.header['foff'] if chanbw < 0: reversed.append(True) else: reversed.append(False) totalbw = chanbw * fb.header['nchans'] lofreq = fb.header['fch1'] hifreq = lofreq + totalbw freqbands.append([lofreq, hifreq]) reversed = np.array(reversed) if not (reversed.all() or np.bitwise_not(reversed)): raise ValueError(colour.cstring("Frequency bands are not ordered" \ "the same.", 'error')) freqbands = np.array(freqbands).astype(float) order = freqbands.argsort(axis=0).transpose()[0] if reversed.all(): # reverse order if options.debug: colour.cprint("Frequency bands are all inverted.", 'debug') order = order[::-1] freqbands = freqbands[order] if np.any( freqbands.flat != sorted(freqbands.flat, reverse=reversed.all())): if options.debug: colour.cprint(freqbands, 'debug') raise ValueError(colour.cstring("Frequency bands have overlaps or " \ "are inverted.", 'error')) sorted_fbfiles = [] for i in order: sorted_fbfiles.append(fbfiles[i]) return sorted_fbfiles
def sort_fb_files(fbfiles): """Given a list of filterbank objects sort by frequency. """ freqbands = [] reversed = [] for fb in fbfiles: chanbw = fb.header['foff'] if chanbw < 0: reversed.append(True) else: reversed.append(False) totalbw = chanbw*fb.header['nchans'] lofreq = fb.header['fch1'] hifreq = lofreq + totalbw freqbands.append([lofreq, hifreq]) reversed = np.array(reversed) if not (reversed.all() or np.bitwise_not(reversed)): raise ValueError(colour.cstring("Frequency bands are not ordered" \ "the same.", 'error')) freqbands = np.array(freqbands).astype(float) order = freqbands.argsort(axis=0).transpose()[0] if reversed.all(): # reverse order if options.debug: colour.cprint("Frequency bands are all inverted.", 'debug') order = order[::-1] freqbands = freqbands[order] if np.any(freqbands.flat != sorted(freqbands.flat, reverse=reversed.all())): if options.debug: colour.cprint(freqbands, 'debug') raise ValueError(colour.cstring("Frequency bands have overlaps or " \ "are inverted.", 'error')) sorted_fbfiles = [] for i in order: sorted_fbfiles.append(fbfiles[i]) return sorted_fbfiles
def main(): # Open file datfn = args[0] timeseries = datfile.Datfile(datfn) if options.shift_phase != 0.0: # Only shift phase by a fraction of one rotation options.shift_phase -= int(options.shift_phase) if options.shift_phase < 0.0: options.shift_phase += 1.0 else: shift_time = 0.0 print "Searching %s for single pulses." % timeseries.datfn if options.parfile is not None: print "Using parfile: %s" % options.parfile # generate polycos print "Automatically generating polycos..." polycos = mypolycos.create_polycos_from_inf(options.parfile, timeseries.infdata) mjd = timeseries.infdata.epoch mjdi = int(mjd) # integer part of mjd mjdf = mjd-mjdi # fractional part of mjd phase, freq = polycos.get_phs_and_freq(mjdi, mjdf) if options.on_pulse_regions == [] or options.on_pulse_regions is None: # Use polycos to determine on-pulse region fidphase = 1.0-phase # phase of fiducial point in profile if fidphase>=0.9 or fidphase<=0.1: # Shift start of observation by 0.25 in phase options.shift_phase = phase + 0.25 fidphase = (fidphase - 0.25) % 1.0 options.on_pulse_regions = [(fidphase-0.1, fidphase+0.1)] if options.debug: colour.cprint("MJD at start of file: %r" % mjd, 'debug') colour.cprint("Phase at start of file: %f" % phase, 'debug') if options.shift_phase != 0.0: prof_start_phase = options.shift_phase shift_phase = options.shift_phase - phase if shift_phase < 0.0: shift_phase += 1.0 shift_time = shift_phase * 1.0/freq else: prof_start_phase = phase # get periods from polycos get_period = lambda mjd: 1.0/polycos.get_phs_and_freq(int(mjd), \ mjd-int(mjd))[1] elif options.polycofile is not None: print "Using polycos file: %s" % options.polycos polycos = mypolycos.polycos(options.polycos) mjd = timeseries.infdata.epoch mjdi = int(mjd) # integer part of mjd mjdf = mjd-mjdi # fractional part of mjd phase, freq = polycos.get_phs_and_freq(mjdi, mjdf) if options.on_pulse_regions == [] or options.on_pulse_regions is None: # Use polycos to determine on-pulse region fidphase = 1.0-phase # phase of fiducial point in profile if fidphase>=0.9 or fidphase<=0.1: # Shift start of observation by 0.25 in phase options.shift_phase = phase + 0.25 fidphase = (fidphase - 0.25) % 1.0 options.on_pulse_regions = [(fidphase-0.1, fidphase+0.1)] if options.debug: colour.cprint("MJD at start of file: %r" % mjd, 'debug') colour.cprint("Phase at start of file: %f" % phase, 'debug') if options.shift_phase != 0.0: prof_start_phase = options.shift_phase shift_phase = options.shift_phase - phase if shift_phase < 0.0: shift_phase += 1.0 shift_time = shift_phase * 1.0/freq else: prof_start_phase = phase # get periods from polycos get_period = lambda mjd: 1.0/polycos.get_phs_and_freq(int(mjd), \ mjd-int(mjd))[1] elif options.period is not None: print "Using constant period: %f" % options.period if options.shift_phase != 0.0: shift_time = options.shift_phase * options.period get_period = lambda mjd: options.period else: raise ValueError("Unknown option for reading periods.") print "On-pulse regions will be set to: %s" % \ ','.join(['%s:%s' % t for t in options.on_pulse_regions]) print "Boxcar widths to be used: %s" % \ ', '.join(['%s' % w for w in options.widths]) print "Single-pulse SNR threshold: %s" % options.threshold # Loop over pulses in timeseries. Examine pulses one at a time. good_pulses = [] snrs = [] widths = [] notes = [] nummasked = 0 numpulses = 0 for current_pulse in timeseries.pulses(get_period, \ time_to_skip=shift_time): numpulses += 1 maxsnr = 0 bestfactor = 0 current_pulse.set_onoff_pulse_regions(options.on_pulse_regions) if current_pulse.is_masked(numchunks=5) and not options.no_toss: nummasked += 1 continue for numbins in options.widths: pulse = current_pulse.make_copy() pulse.smooth(numbins) snr = get_snr(pulse) if np.isnan(snr) or snr < 0: snr = 0 if snr > options.threshold: if snr >= maxsnr: if maxsnr==0 and bestfactor==0: # First time snr is above threshold snrs.append(snr) notes.append("smoothed by %3d bins" % numbins) widths.append(numbins) good_pulses.append(current_pulse) else: # Better smootfactor/snr found, update, but don't # add pulse to good_pulses again. snrs[-1] = snr widths[-1] = numbins notes[-1] = "smoothed by %3d bins" % numbins maxsnr = snr bestfactor = numbins print_report(good_pulses, numpulses, nummasked, snrs=snrs, notes=notes, \ quiet=options.quiet) if options.create_output_files and len(good_pulses) > 0: if options.create_text_files: print "Writing pulse text files..." write_pulses(good_pulses, timeseries) if options.create_plot_files: print "Creating pulse plots..." plot_pulses(good_pulses, timeseries, options.downfactor, widths=widths) if options.create_joydiv_plot: print "Making JoyDiv plot..." joy_division_plot(good_pulses, timeseries, options.downfactor, \ options.heightstretch) if (options.polycofile is not None or options.parfile is not None) and \ options.write_toas and len(good_pulses) > 0: numtoas = 0 print "Generating TOAs. Please wait..." print "TOA threshold:", options.toa_threshold print "Min number of pulses for a TOA:", options.min_pulses print "Profile template used:", options.template # Extract second column from template file # First column is index template = np.loadtxt(options.template, usecols=(1,)) # Get TOAs and write them to stdout current_pulse = None numpulses = 0 for pulse in good_pulses: if current_pulse is None: current_pulse = pulse.to_summed_pulse() numpulses = 1 else: current_pulse += pulse numpulses += 1 if numpulses < options.min_pulses: continue if get_snr(current_pulse) > options.toa_threshold: # Interpolate and downsample current_pulse so # it is same size as template profile current_pulse.interp_and_downsamp(template.size) # current_pulse.downsample_Nbins(template.size) ## ADDED FOR DEBUGGING current_pulse.scale() pulseshift, templateshift = write_toa(current_pulse, \ polycos, template, timeseries, prof_start_phase, \ options.debug) numtoas += 1 if options.write_toa_files: # TOA profiles are already downfactored # do not downfactor more when creating plot plot_toa(numtoas, current_pulse, template, \ pulseshift, templateshift) current_pulse.write_to_file("TOA%d" % numtoas) current_pulse = None numpulses = 0 print "Number of TOAs: %d" % numtoas print "Number of pulses thrown out because 'min pulses' requirement " \ "or SNR threshold not met: %d" % numpulses
def write_toa(summed_pulse, polycos, template_profile, \ timeseries, start_phase=0.0, debug=False): """Given a SummedPulse generate a TOA and write it to stdout. A polycos file is required. 'template_profile' is simply a numpy array. 'timeseries' is a Datfile object. 'start_phase' is the phase at the start of the profile. 'debug' is a boolean value that determines if debugging info should be displayed. Returns shift required to line up template and pulse. """ if template_profile is None: raise ValueError("A template profile MUST be provided.") # This code is taken from Scott Ransom's PRESTO's get_TOAs.py mjdi = int(summed_pulse.mjd) # integer part of MJD mjdf = summed_pulse.mjd - mjdi # fractional part of MJD (phs, freq) = polycos.get_phs_and_freq(mjdi, mjdf) phs -= start_phase period = 1.0/freq # Caclulate offset due to shifting channels to account for DM # Hifreq doesn't have a half-channel offset # (why? because get_TOAs.py doesn't. Why...) # Why subtract 1 channel to get hifreq? hifreq = timeseries.infdata.lofreq + timeseries.infdata.BW - \ timeseries.infdata.chan_width midfreq = timeseries.infdata.lofreq - 0.5*timeseries.infdata.chan_width + \ 0.5*timeseries.infdata.BW dmdelay = psr_utils.delay_from_DM(timeseries.infdata.DM, midfreq) - \ psr_utils.delay_from_DM(timeseries.infdata.DM, hifreq) dmdelay_mjd = dmdelay/float(psr_utils.SECPERDAY) if debug: colour.cprint("High frequency (MHz): %f" % hifreq, 'debug') colour.cprint("Mid frequency (MHz): %f" % midfreq, 'debug') colour.cprint("DM delay added to TOAs (s): %g" % dmdelay, 'debug') colour.cprint("DM delay added to TOAs (MJD): %g" % dmdelay_mjd, 'debug') t0f = mjdf - phs*period/psr_utils.SECPERDAY + dmdelay_mjd t0i = mjdi shift,eshift,snr,esnr,b,errb,ngood,tphs = measure_phase(summed_pulse.profile, \ template_profile) # tphs is amount template is rotated by. It is originally # measured in radians, convert to rotational phase tphs = tphs/(np.pi*2.0) % 1.0 # tau and tau_err are the predicted phase of the pulse arrival tau, tau_err = shift/summed_pulse.N, eshift/summed_pulse.N if debug: colour.cprint("FFTFIT: Shift (bins): %f, Tau (phase): %f" % (shift, tau), 'debug') colour.cprint("FFTFIT: Shift error (bins): %f, Tau error (phase): %f" % \ (eshift, tau_err), 'debug') # Note: "error" flags are shift = 0.0 and eshift = 999.0 if (np.fabs(shift) < 1e-7 and np.fabs(eshift-999.0) < 1e-7): raise FFTFitError("Error in FFTFIT. Bad return values.") # Send the TOA to STDOUT toaf = t0f + tau*period/float(psr_utils.SECPERDAY) if debug: colour.cprint("t0f (MJD): %r" % t0f, 'debug') colour.cprint("period (s): %r" % period, 'debug') colour.cprint("toaf (MJD): %r" % toaf, 'debug') newdays = int(np.floor(toaf)) obs_code = telescopes.telescope_to_id[timeseries.infdata.telescope] psr_utils.write_princeton_toa(t0i+newdays, toaf-newdays, \ tau_err*period*1e6, midfreq, \ timeseries.infdata.DM, obs=obs_code) return tau, tphs