예제 #1
0
 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)
예제 #2
0
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
예제 #3
0
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
예제 #4
0
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
예제 #5
0
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