Example #1
0
def template_prof(input_profs, sum=True):
    """
    Phase aligns and sums (if sum=True) multiple input profiles from different observations
    to create a single high S/N template profile.
    input_profs - np.asarray((prof1,prof2,...)) of input profiles to be combined.
        prof1 is the profile to which the others are aligned
    """
    Nprof = np.shape(input_profs)[0]
    bins = input_profs[0].size
    aligned_profs = np.empty(np.shape(input_profs))
    for i in range(Nprof):
        offset = psr_utils.measure_phase_corr(input_profs[i], input_profs[0])
        #print 'Phase offset '+str(i)+' = '+str(offset)
        bin_offset = -offset * bins
        aligned_profs[i] = psr_utils.fft_rotate(input_profs[i], bin_offset)
    if sum is False:
        return aligned_profs
    else:
        template_prof = aligned_profs.sum(0)
        for i in range(Nprof):
            offset = psr_utils.measure_phase_corr(input_profs[i],
                                                  template_prof)
            bin_offset = -offset * bins
            aligned_profs[i] = psr_utils.fft_rotate(input_profs[i], bin_offset)
        template_prof = aligned_profs.sum(0)
        return template_prof
Example #2
0
    def _compute_rating(self, cand):
        """Return a rating for the candidate. The rating value is the
            the fraction of sub-ints that deviate from the phase of
            the pulse.

            Input:
                cand: A Candidate object to rate.

            Output:
                value: The rating value.
        """
        tvph = cand.get_from_cache('time_vs_phase')
        pfd = cand.get_from_cache('pfd')

        bestprof = tvph.get_profile()
        new_template = np.zeros_like(bestprof)
        bin_offsets = np.empty(pfd.npart)

        # The following loop creates a better template by removing wiggle, but
        # it does not change the actual subints
        for ii, subint in enumerate(tvph.data):
            # Measure the phase offset
            phase_offset = psr_utils.measure_phase_corr(subint, bestprof)
            # The following is needed to put phase offsets on the interval
            # (-0.5,0.5]
            if phase_offset > 0.5:
                phase_offset -= 1.0
            # Caclulate the offset in bins
            bin_offset = int(round(pfd.proflen * phase_offset))
            # Update the new template
            new_template += psr_utils.rotate(subint, -bin_offset)

        # Now calculate the wiggle using the updated template
        for ii, subint in enumerate(tvph.data):
            phase_offset = psr_utils.measure_phase_corr(subint, new_template)
            if phase_offset > 0.5:
                phase_offset -= 1.0
            bin_offsets[ii] = int(round(pfd.proflen * phase_offset))

        # Calculate the various metrics
        if method == "GOODFRAC":
            # good fraction
            wigglescore = sum(abs(bin_offsets) < TOL*pfd.proflen)/ \
                        float(pfd.npart)
        elif method == "WANDER":
            # total wander
            wigglescore = sum(abs(bin_offsets)) / (pfd.proflen * pfd.npart)
        elif method == "OFFSTD":
            # offset std
            wigglescore = bin_offsets.std()
        elif method == "OFFMAX":
            # offset max
            wigglescore = bin_offsets.max()
        else:
            raise utils.RatingError("Unrecognized method for wiggle " \
                                    "rating (%s)" % method)

        return wigglescore
Example #3
0
    def _compute_rating(self, cand):
        """Return a rating for the candidate. The rating value is the
            the fraction of sub-ints that deviate from the phase of
            the pulse.

            Input:
                cand: A Candidate object to rate.

            Output:
                value: The rating value.
        """
        tvph = cand.get_from_cache('time_vs_phase')
        pfd = cand.get_from_cache('pfd')

        bestprof = tvph.get_profile()
        new_template = np.zeros_like(bestprof)
        bin_offsets = np.empty(pfd.npart)

        # The following loop creates a better template by removing wiggle, but
        # it does not change the actual subints
        for ii, subint in enumerate(tvph.data):
            # Measure the phase offset
            phase_offset = psr_utils.measure_phase_corr(subint, bestprof)
            # The following is needed to put phase offsets on the interval
            # (-0.5,0.5]
            if phase_offset > 0.5: 
                phase_offset -= 1.0
            # Caclulate the offset in bins
            bin_offset = int(round(pfd.proflen*phase_offset))
            # Update the new template
            new_template += psr_utils.rotate(subint, -bin_offset)

        # Now calculate the wiggle using the updated template
        for ii, subint in enumerate(tvph.data):
            phase_offset = psr_utils.measure_phase_corr(subint, new_template)
            if phase_offset > 0.5:
                phase_offset -= 1.0
            bin_offsets[ii] = int(round(pfd.proflen*phase_offset))

        # Calculate the various metrics
        if method == "GOODFRAC":
            # good fraction 
            wigglescore = sum(abs(bin_offsets) < TOL*pfd.proflen)/ \
                        float(pfd.npart)
        elif method == "WANDER":
            # total wander
            wigglescore = sum(abs(bin_offsets))/(pfd.proflen*pfd.npart)
        elif method == "OFFSTD":
            # offset std
            wigglescore = bin_offsets.std()
        elif method == "OFFMAX":
            # offset max
            wigglescore = bin_offsets.max() 
        else:
            raise utils.RatingError("Unrecognized method for wiggle " \
                                    "rating (%s)" % method)

        return wigglescore
Example #4
0
    def _compute_rating(self, cand):
        """Return a rating for the candidate. The rating value is the
            the fraction of subbands that deviate from the position of
            the pulse.

            Input:
                cand: A SPCandidate object to rate.

            Output:
                value: The rating value.
        """
        wdd = cand.waterfall_dd
        spd = cand.spd

        prof = wdd.get_profile()
        new_template = np.zeros_like(prof)
        bin_offsets = np.empty(spd.waterfall_nsubs)

        # The following loop creates a better template by removing wiggle, but
        # it does not change the actual subbands
        for ii, subband in enumerate(wdd.data):
            # Measure the pulse offset
            pulse_offset = psr_utils.measure_phase_corr(subband, prof, zoom=1)
            # Caclulate the offset in bins
            bin_offset = int(round(spd.waterfall_nbins * pulse_offset))
            # Update the new template
            new_template += psr_utils.rotate(subband, -bin_offset)

        # Now calculate the wiggle using the updated template
        for ii, subband in enumerate(wdd.data):
            pulse_offset = psr_utils.measure_phase_corr(subband,
                                                        new_template,
                                                        zoom=1)
            bin_offsets[ii] = int(round(spd.waterfall_nbins * pulse_offset))

        # Calculate the various metrics
        if method == "GOODFRAC":
            # good fraction
            wigglescore = sum(abs(bin_offsets) < TOL*spd.waterfall_nbins)/ \
                        float(spd.waterfall_nsubs)
        elif method == "WANDER":
            # total wander
            wigglescore = sum(
                abs(bin_offsets)) / (spd.waterfall_nbins * spd.waterfall_nsubs)
        elif method == "OFFSTD":
            # offset std
            wigglescore = bin_offsets.std()
        elif method == "OFFMAX":
            # offset max
            wigglescore = bin_offsets.max()
        else:
            raise utils.RatingError("Unrecognized method for wiggle " \
                                    "rating (%s)" % method)

        return wigglescore
Example #5
0
    def _compute_rating(self, cand):
        """Return a rating for the candidate. The rating value is the
            the fraction of subbands that deviate from the position of
            the pulse.

            Input:
                cand: A SPCandidate object to rate.

            Output:
                value: The rating value.
        """
        wdd = cand.waterfall_dd
        spd = cand.spd

        prof = wdd.get_profile()
        new_template = np.zeros_like(prof)
        bin_offsets = np.empty(spd.waterfall_nsubs)

        # The following loop creates a better template by removing wiggle, but
        # it does not change the actual subbands
        for ii, subband in enumerate(wdd.data):
            # Measure the pulse offset
            pulse_offset = psr_utils.measure_phase_corr(subband, prof, zoom=1)
           # Caclulate the offset in bins
            bin_offset = int(round(spd.waterfall_nbins*pulse_offset))
            # Update the new template
            new_template += psr_utils.rotate(subband, -bin_offset)

        # Now calculate the wiggle using the updated template
        for ii, subband in enumerate(wdd.data):
            pulse_offset = psr_utils.measure_phase_corr(subband, new_template, zoom=1)
            bin_offsets[ii] = int(round(spd.waterfall_nbins*pulse_offset))

        # Calculate the various metrics
        if method == "GOODFRAC":
            # good fraction 
            wigglescore = sum(abs(bin_offsets) < TOL*spd.waterfall_nbins)/ \
                        float(spd.waterfall_nsubs)
        elif method == "WANDER":
            # total wander
            wigglescore = sum(abs(bin_offsets))/(spd.waterfall_nbins*spd.waterfall_nsubs)
        elif method == "OFFSTD":
            # offset std
            wigglescore = bin_offsets.std()
        elif method == "OFFMAX":
            # offset max
            wigglescore = bin_offsets.max() 
        else:
            raise utils.RatingError("Unrecognized method for wiggle " \
                                    "rating (%s)" % method)

        return wigglescore
Example #6
0
    def get_phase_shift(self, phases, weights, polyco_phase0):

        # Compute phase at start of this block
        if options.profile:
            polyco_phase0 = 0.0

        else:
            phases -= polyco_phase0
            phases[phases < 0.] += 1

        profile = np.histogram(phases, bins=self.bins)[0]
        # This is older version from Matthew Kerr
        #profile = np.histogram(phases,bins=self.bins[:-1])[0]

        if not self.profile_only:

            # Compute shift from profile

            # Try using FFTFIT first
            shift, eshift, snr, esnr, b, errb, ngood = self._measure_phase(
                profile, self.template, True)
            # tau and tau_err are the predicted phase of the pulse arrival
            tau, tau_err = shift / len(profile), eshift / len(profile)
            # Note: "error" flags are shift = 0.0 and eshift = 999.0

            # If that failed, use a time-domain correlation
            if (np.fabs(shift) < 1e-7 and np.fabs(eshift - 999.0) < 1e-7):
                print >> sys.stderr, "Warning!  Bad return from FFTFIT.  Using PRESTO correlation..."
                # Not enough structure in the template profile for FFTFIT
                # so use time-domain correlations instead
                tau = psr_utils.measure_phase_corr(profile, self.template)
                # This needs to be changed
                tau_err = 0.1 / len(profile)

            #tau = np.random.rand(1)[0];tau_err = np.random.rand(1)[0]*0.01 # testing
            redchi, prob = self._prof_chisq(profile)
            return tau, tau_err, prob, 0

        else:
            # This doesn't work very well since it doesn't pause after the any
            # but the first plot.
            pl.ioff()  #does this help the pausing problem?
            pl.figure(1)
            bbins = np.arange(2.0 * len(profile)) / len(profile)
            pl.bar(bbins, np.concatenate((profile, profile)), width=bbins[1])
            #bins = np.arange(2.0*len(profile)+1)/len(profile)
            #pl.plot(bins,list(profile)+list(profile)+[0.0],linestyle='steps-post')
            pl.grid(1)
            pl.xlabel('Pulse Phase')
            pl.ylabel('Number of Photons')
            #pl.title('Profile')
            pl.show()
            of = file('profile.bestprof', "w")
            print >> of, "# Profile generated by polyfold.py"
            for i, np in zip(range(len(profile)), profile):
                print >> of, "%d %d" % (i, np)
            of.close()

            return 0, 0, 0, 0
Example #7
0
def template_2d(input_profs, sum=True):
    """
    Phase aligns and sums multiple input 2D profiles from different observations
    to create a single high S/N template profile, while keeping full frequency
    resolution.
    input_profs - np.asarray((prof1,prof2,...)) of input profiles to be combined.
        prof1 is the profile to which the others are aligned
    """
    Nprof = np.shape(input_profs)[0]
    bins = input_profs[0].shape[1]
    channels = input_profs[0].shape[0]
    aligned_profs = np.empty(np.shape(input_profs))
    for i in range(Nprof):
        #offset=psr_utils.measure_phase_corr(input_profs[i].sum(0),input_profs[0].sum(0))
        offset = psr_utils.measure_phase_corr(
            np.nanmean(input_profs[i], axis=0),
            np.nanmean(input_profs[0], axis=0))
        #print 'Phase offset '+str(i)+' = '+str(offset)
        bin_offset = -offset * bins
        print bin_offset  ################
        for jj in np.arange(channels):
            aligned_profs[i][jj] = psr_utils.fft_rotate(
                input_profs[i][jj], bin_offset)
    if sum is False:
        return aligned_profs
    else:
        #template_prof=aligned_profs.sum(0)
        template_prof = np.nanmean(aligned_profs, axis=0)
        for i in range(Nprof):
            #offset=psr_utils.measure_phase_corr(input_profs[i].sum(0),template_prof.sum(0))
            offset = psr_utils.measure_phase_corr(
                np.nanmean(input_profs[i], axis=0),
                np.nanmean(template_prof, axis=0))
            bin_offset = -offset * bins
            for jj in np.arange(channels):
                aligned_profs[i][jj] = psr_utils.fft_rotate(
                    input_profs[i][jj], bin_offset)
        #template_prof=aligned_profs.sum(0)
        template_prof = np.nanmean(aligned_profs, axis=0)
        return template_prof
Example #8
0
def getErr(profile,templatefilenm):
  '''Based off of Pulsar Timing and Relativistic Gravity,
     J.H. Taylor, Phil. Trans. R. Soc. Lond. A 1992  341, 117-134
     Appendix A
     Usage: give this a profile, a template, and a number of
     harmonics and it will calculate the offset and output an error'''
  ####################################################################
  ###                   Calculate sigscal                          ###
  ####################################################################
  k=int(len(profile)/2)   
  template = psr_utils.read_profile(templatefilenm, normalize=0) 
  template=template
  profile=profile
  a=1
  offset=psr_utils.measure_phase_corr(profile-min(profile), template-min(template))
  Pfft=FFT.rfft(profile-min(profile))
  Tfft=FFT.rfft(template-min(template))
  Pamp=[]
  Tamp=[]
  Pph=[]
  Tph=[]
  for i in range(0,k):
    Pamp.append(sqrt(real(Pfft[i]*conjugate(Pfft[i]))))
    Tamp.append(sqrt(real(Tfft[i]*conjugate(Tfft[i]))))
    Pph.append(arctan(1*imag(Pfft[i])/real(Pfft[i])))
    Tph.append(arctan(1*imag(Tfft[i])/real(Tfft[i])))
  b=0
  total=0
  denom=0
  for i in range(1,k):
    b+=Pamp[i]*Tamp[i]*cos(Tph[i]-Pph[i]+i*offset*2*pi)
    total+=Tamp[i]*Tamp[i]
    denom+=i*i*Pamp[i]*Tamp[i]*cos(Tph[i]-Pph[i]+i*offset*2*pi)
  b=b/total
  sigscale=(abs(1/(2*b*denom)))
  #####################################################################
  ### Done SigScale, start Poisson Variations                       ###
  #####################################################################
  it=1000#do 'it' iterations
  variation=Num.zeros(len(profile))
  Offsets=[]
  for i in range (0, it):
    for j in range (0,len(profile)):
      if profile[j]>=0:
        variation[j]=double(Num.random.poisson(profile[j],1))
      if profile[j]<=0: 
        variation[j]=0   
    Offsets.append(psr_utils.measure_phase_corr(variation-min(variation), template-min(template))) 
  Offsets=np.array(Offsets)
  #This fixes the error being way too big is the shift was around 0 or 1 (The std 
  # would then be averaging values near 0 and 1)
  k=0
  for i in range (0,len(Offsets)):
    Offsets[i]= Offsets[i] - offset;
    if Offsets[i] < -0.5: 
      Offsets[i] += 1.0
    if Offsets[i] > 0.5:
      Offsets[i] -= 1.0
    if abs(Offsets[i]) > 0.2:
       Offsets[i]=0
       k=k+1
  if k>=1:     
    sys.stderr.write("Warning: May be Double peaked, attempting to correct:\nThere are "+str(k)+ " of "+ str(it) + " offsets > 0.2 phase away from the average offset .\n")    
  sigma=std(Offsets)
  #print 'sigma = ',sigma
  return sigma
Example #9
0
                        sys.stderr.write("Note:  Downsampling the data for '%s'\n"%fold_pfd.filenm)

            try:
                # Try using FFTFIT first
                shift,eshift,snr,esnr,b,errb,ngood = measure_phase(prof, template, rotate_prof)
                # tau and tau_err are the predicted phase of the pulse arrival
                tau, tau_err = shift/len(prof), eshift/len(prof)
                # Note: "error" flags are shift = 0.0 and eshift = 999.0

                # If that failed, use a time-domain correlation
                if (Num.fabs(shift) < 1e-7 and
                    Num.fabs(eshift-999.0) < 1e-7):
                    sys.stderr.write('Warning!  Bad return from FFTFIT.  Using PRESTO correlation...\n')
                    # Not enough structure in the template profile for FFTFIT
                    # so use time-domain correlations instead
                    tau = 1-psr_utils.measure_phase_corr(prof, template)
                tau_err = getErr(prof,templatefilenm)#Use poisson error estimate
                # Send the TOA to STDOUT
                toaf = t0f + (tau*p + offset)/SECPERDAY + sumsubdelays[jj]
                newdays = int(Num.floor(toaf))
                psr_utils.write_princeton_toa(t0i+newdays, toaf-newdays,
                                              tau_err*p*1000000.0, 0000, fold_pfd.bestdm,
                                              obs=obs, name=str(sys.argv[-1][5:14]))#[5:13]))
                              
         
                if (otherouts):
                    print "FFTFIT results:  b = %.4g +/- %.4g   SNR = %.4g +/- %.4g" % \
                          (b, errb, snr, esnr)
                    print "Offset= ", tau, " +/- ", tau_err
                    
            except ValueError, fftfit.error:
Example #10
0
                    # Note: "error" flags are shift = 0.0 and eshift = 999.0

                    # If that failed, use a time-domain correlation
                    if (Num.fabs(shift) < 1e-7
                            and Num.fabs(eshift - 999.0) < 1e-7):
                        sys.stderr.write(
                            "Warning!  Bad return from FFTFIT. May be due to inadequate signal-to-noise.\n"
                        )
                        tau = None
                if tau is None:
                    sys.stderr.write(
                        "Warning: using PRESTO correlation - reported error is incorrect...\n"
                    )
                    # Not enough structure in the template profile for FFTFIT
                    # so use time-domain correlations instead
                    tau = psr_utils.measure_phase_corr(prof, template)
                    # This needs to be changed
                    tau_err = 0.1 / len(prof)

                # Calculate correction for dedispersion to true channel
                # center freqs that used a slightly different pulse
                # period.
                dd_phs_2 = subdelays2[jj] * (1.0 / p - 1.0 / p_dedisp)

                # Sum up several phase shifts
                tau_tot = Num.fmod(tau + sumsubdelays_phs[jj] + dd_phs_2 + 3.0,
                                   1.0)
                if (tau_tot > 0.5): tau_tot -= 1.0

                # Send the TOA to STDOUT
                toaf = t0f + (tau_tot * p + offset) / SECPERDAY
Example #11
0
def Phase_Wiggle_Ratings(pfd, method="GOODFRAC"):
    """
    Calculate a metric for the phase wiggle in time and frequency.

    Parameters
    ----------
    pfd : class
        An instance of the prepfold.pfd class
    method : string
        The method to use to calculate the phase wiggle metrics
        \"GOODFRAC\" - The fraction of sub-intervals/sub-bands with a wiggle
            less than some threshold
        \"WANDER\" - The total phase wander normalized by the number of
            profile bins and the number of sub-intervals/sub-bands

    Returns
    -------
    names : list
        A list of ratings names
    ratings : list
        A list of ratings values
    """
    # The ratings names
    name1 = "Phase_Wiggle_Time"
    name2 = "Phase_Wiggle_Freq"
    
    # De-disperse the profile at the best DM
    pfd.dedisperse(DM=pfd.bestdm, doppler=1)
    # Internally rotate the data cube so that is aligned with best fold values
    pfd.adjust_period()
    # Get the subints.
    subints      = N.sum(pfd.profs, axis=1)
    # Get the subbands.
    subbands     = N.sum(pfd.profs, axis=0)
    # Get the template ("best") profile
    template     = N.sum(subints, axis=0)
    # Make an array for storing a new template
    new_template = N.zeros_like(template)
    # Make an arrary for storing the offsets (in phase bins)
    bin_offsets_time  = N.empty(pfd.npart)
    bin_offsets_freq  = N.empty(pfd.npart)
    # The following loop creats a better template by removing wiggle, but
    # it does not change the actual subints
    for ii,subint in enumerate(subints):
        # Measure the phase offset
        phase_offset = PU.measure_phase_corr(subint, template)
        # The following is needed to put phase offsets on the interval
        # (-0.5,0.5]
        if phase_offset > 0.5: phase_offset -= 1.0
        # Caclulate the offset in bins
        bin_offset    = int(round(pfd.proflen*phase_offset))
        # Update the new template
        new_template += PU.rotate(subint, -bin_offset)

    # Now calculate the wiggle using the updated template
    for ii,(subint,subband) in enumerate(zip(subints,subbands)):
        phase_offset_time = PU.measure_phase_corr(subint, new_template)
        if phase_offset_time > 0.5: phase_offset_time -= 1.0
        bin_offsets_time[ii] = int(round(pfd.proflen*phase_offset_time))

        phase_offset_freq = PU.measure_phase_corr(subband, new_template)
        if phase_offset_freq > 0.5: phase_offset_freq -= 1.0
        bin_offsets_freq[ii] = int(round(pfd.proflen*phase_offset_freq))

    # Calcultae the various metrics
    good_fraction_time = sum(abs(bin_offsets_time) < \
                             PHASE_DRIFT_TOLERANCE*pfd.proflen)/ \
                             float(pfd.npart)
    total_wander_time  = sum(abs(bin_offsets_time))/(pfd.proflen*pfd.npart)
    good_fraction_freq = sum(abs(bin_offsets_freq) < \
                             PHASE_DRIFT_TOLERANCE*pfd.proflen)/ \
                         float(pfd.npart)
    total_wander_freq  = sum(abs(bin_offsets_freq))/(pfd.proflen*pfd.nsub)

    # Make the appropriate metric the rating
    if method == "GOODFRAC":
        rating1 = good_fraction_time
        rating2 = good_fraction_freq
    
    if method == "WANDER"  :
        rating1 = total_wander_time
        rating2 = total_wander_freq

    return [name1,name2],[rating1,rating2]
Example #12
0
def Phase_Wiggle_Ratings(pfd, method="GOODFRAC"):
    """
    Calculate a metric for the phase wiggle in time and frequency.

    Parameters
    ----------
    pfd : class
        An instance of the prepfold.pfd class
    method : string
        The method to use to calculate the phase wiggle metrics
        \"GOODFRAC\" - The fraction of sub-intervals/sub-bands with a wiggle
            less than some threshold
        \"WANDER\" - The total phase wander normalized by the number of
            profile bins and the number of sub-intervals/sub-bands

    Returns
    -------
    names : list
        A list of ratings names
    ratings : list
        A list of ratings values
    """
    # The ratings names
    name1 = "Phase_Wiggle_Time"
    name2 = "Phase_Wiggle_Freq"

    # De-disperse the profile at the best DM
    pfd.dedisperse(DM=pfd.bestdm, doppler=1)
    # Internally rotate the data cube so that is aligned with best fold values
    pfd.adjust_period()
    # Get the subints.
    subints = N.sum(pfd.profs, axis=1)
    # Get the subbands.
    subbands = N.sum(pfd.profs, axis=0)
    # Get the template ("best") profile
    template = N.sum(subints, axis=0)
    # Make an array for storing a new template
    new_template = N.zeros_like(template)
    # Make an arrary for storing the offsets (in phase bins)
    bin_offsets_time = N.empty(pfd.npart)
    bin_offsets_freq = N.empty(pfd.npart)
    # The following loop creats a better template by removing wiggle, but
    # it does not change the actual subints
    for ii, subint in enumerate(subints):
        # Measure the phase offset
        phase_offset = PU.measure_phase_corr(subint, template)
        # The following is needed to put phase offsets on the interval
        # (-0.5,0.5]
        if phase_offset > 0.5: phase_offset -= 1.0
        # Caclulate the offset in bins
        bin_offset = int(round(pfd.proflen * phase_offset))
        # Update the new template
        new_template += PU.rotate(subint, -bin_offset)

    # Now calculate the wiggle using the updated template
    for ii, (subint, subband) in enumerate(zip(subints, subbands)):
        phase_offset_time = PU.measure_phase_corr(subint, new_template)
        if phase_offset_time > 0.5: phase_offset_time -= 1.0
        bin_offsets_time[ii] = int(round(pfd.proflen * phase_offset_time))

        phase_offset_freq = PU.measure_phase_corr(subband, new_template)
        if phase_offset_freq > 0.5: phase_offset_freq -= 1.0
        bin_offsets_freq[ii] = int(round(pfd.proflen * phase_offset_freq))

    # Calcultae the various metrics
    good_fraction_time = sum(abs(bin_offsets_time) < \
                             PHASE_DRIFT_TOLERANCE*pfd.proflen)/ \
                             float(pfd.npart)
    total_wander_time = sum(abs(bin_offsets_time)) / (pfd.proflen * pfd.npart)
    good_fraction_freq = sum(abs(bin_offsets_freq) < \
                             PHASE_DRIFT_TOLERANCE*pfd.proflen)/ \
                         float(pfd.npart)
    total_wander_freq = sum(abs(bin_offsets_freq)) / (pfd.proflen * pfd.nsub)

    # Make the appropriate metric the rating
    if method == "GOODFRAC":
        rating1 = good_fraction_time
        rating2 = good_fraction_freq

    if method == "WANDER":
        rating1 = total_wander_time
        rating2 = total_wander_freq

    return [name1, name2], [rating1, rating2]
Example #13
0
def getErr(profile, templatefilenm):
    '''Based off of Pulsar Timing and Relativistic Gravity,
     J.H. Taylor, Phil. Trans. R. Soc. Lond. A 1992  341, 117-134
     Appendix A
     Usage: give this a profile, a template, and a number of
     harmonics and it will calculate the offset and output an error'''
    ####################################################################
    ###                   Calculate sigscal                          ###
    ####################################################################
    k = int(len(profile) / 2)
    template = psr_utils.read_profile(templatefilenm, normalize=0)
    template = template
    profile = profile
    a = 1
    offset = psr_utils.measure_phase_corr(profile - min(profile),
                                          template - min(template))
    Pfft = FFT.rfft(profile - min(profile))
    Tfft = FFT.rfft(template - min(template))
    Pamp = []
    Tamp = []
    Pph = []
    Tph = []
    for i in range(0, k):
        Pamp.append(sqrt(real(Pfft[i] * conjugate(Pfft[i]))))
        Tamp.append(sqrt(real(Tfft[i] * conjugate(Tfft[i]))))
        Pph.append(arctan(1 * imag(Pfft[i]) / real(Pfft[i])))
        Tph.append(arctan(1 * imag(Tfft[i]) / real(Tfft[i])))
    b = 0
    total = 0
    denom = 0
    for i in range(1, k):
        b += Pamp[i] * Tamp[i] * cos(Tph[i] - Pph[i] + i * offset * 2 * pi)
        total += Tamp[i] * Tamp[i]
        denom += i * i * Pamp[i] * Tamp[i] * cos(Tph[i] - Pph[i] +
                                                 i * offset * 2 * pi)
    b = b / total
    sigscale = (abs(1 / (2 * b * denom)))
    #####################################################################
    ### Done SigScale, start Poisson Variations                       ###
    #####################################################################
    it = 1000  #do 'it' iterations
    variation = Num.zeros(len(profile))
    Offsets = []
    for i in range(0, it):
        for j in range(0, len(profile)):
            if profile[j] >= 0:
                variation[j] = double(Num.random.poisson(profile[j], 1))
            if profile[j] <= 0:
                variation[j] = 0
        Offsets.append(
            psr_utils.measure_phase_corr(variation - min(variation),
                                         template - min(template)))
    Offsets = np.array(Offsets)
    #This fixes the error being way too big is the shift was around 0 or 1 (The std
    # would then be averaging values near 0 and 1)
    k = 0
    for i in range(0, len(Offsets)):
        Offsets[i] = Offsets[i] - offset
        if Offsets[i] < -0.5:
            Offsets[i] += 1.0
        if Offsets[i] > 0.5:
            Offsets[i] -= 1.0
        if abs(Offsets[i]) > 0.2:
            Offsets[i] = 0
            k = k + 1
    if k >= 1:
        sys.stderr.write(
            "Warning: May be Double peaked, attempting to correct:\nThere are "
            + str(k) + " of " + str(it) +
            " offsets > 0.2 phase away from the average offset .\n")
    sigma = std(Offsets)
    #print 'sigma = ',sigma
    return sigma