def write_toa(summed_pulse, template_profile, debug=False): """Given a SummedPulse generate a TOA and write it to stdout. 'template_profile' is simply a numpy array. '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 # Period is duration of profile in seconds period = summed_pulse.dt*len(summed_pulse.profile) # 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 = summed_pulse.lofreq + summed_pulse.bw - summed_pulse.chan_width midfreq = summed_pulse.lofreq - 0.5*summed_pulse.chan_width + 0.5*summed_pulse.bw dmdelay = psr_utils.delay_from_DM(summed_pulse.dm, midfreq) - \ psr_utils.delay_from_DM(summed_pulse.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 + 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[summed_pulse.telescope] psr_utils.write_princeton_toa(t0i+newdays, toaf-newdays, \ tau_err*period*1e6, midfreq, \ summed_pulse.dm, obs=obs_code) return tau, tphs
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: pass
# 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 newdays = int(Num.floor(toaf)) if t2format: psr_utils.write_tempo2_toa(t0i + newdays, toaf - newdays, tau_err * p * 1000000.0, sumsubfreqs[jj], 0.0, name=fold_pfd.pfd_filename, obs=obs) else: psr_utils.write_princeton_toa(t0i + newdays, toaf - newdays, tau_err * p * 1000000.0, sumsubfreqs[jj], 0.0, obs=obs) if (otherouts): sys.stderr.write( "FFTFIT results: b = %.4g +/- %.4g SNR = %.4g +/- %.4g" % (b, errb, snr, esnr)) except ValueError, fftfit.error: pass
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 newdays = int(Num.floor(toaf)) psr_utils.write_princeton_toa(t0i+newdays, toaf-newdays, tau_err*p*1000000.0, sumsubfreqs[jj], 0.0, obs=obs) if (otherouts): sys.stderr.write("FFTFIT results: b = %.4g +/- %.4g SNR = %.4g +/- %.4g" % (b, errb, snr, esnr)) except ValueError, fftfit.error: pass
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
def get_ml_toa(fits_fn, prof_mod, parfile, scope='swift', print_offs=None, frequency=None, epoch=None, sim=False, bg_counts=0, Emin=None, Emax=None, gauss_err=False, tempo2=False, debug=False, correct_pf=False, split_num=None, split_orbits=False): print_timings = False # if want to print summary of runtime fits = pyfits.open(fits_fn) t = smu.fits2times(fits_fn, scope=scope, Emin=Emin, Emax=Emax) #if scope != 'chandra': # exposure = fits[0].header['EXPOSURE'] try: obsid = fits[0].header['OBS_ID'] except KeyError: obsid = os.path.basename(fits_fn) if bg_counts < 0: bg_scale = -1.0*bg_counts bg_fits_fn = fits_fn.replace('reg','bgreg') bg_fits = pyfits.open(bg_fits_fn) bg_counts = int(bg_fits[1].header['NAXIS2'] * bg_scale) print 'BG Counts:',bg_counts bg_fits.close() if frequency and epoch: par = lambda: None par.epoch = epoch par.f0 = frequency par.fdots = [0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0,0.0] else: par = PSRpar(parfile) # split times into multiple arrays if needed if split_orbits: dt = t[1:] - t[:-1] splits = np.where(dt > 0.0116)[0] # 1 ks in days if len(splits): ts = [ t[:splits[0]] ] for i in range(len(splits)-1): ts.append(t[splits[i]+1:splits[i+1]]) ts.append(t[splits[-1]+1:]) else: ts = np.atleast_2d(t) elif split_num: remainder = len(t) % split_num if remainder: sys.stderr.write("Warning: Number of events in %s not divisable by %d. " \ "Dropping last %d events.\n" % (obsid, split_num, remainder)) ts = np.split(t[:-remainder],split_num) else: ts = np.split(t,split_num) else: ts = np.atleast_2d(t) if len(ts) > 1 and debug: plt.figure() for t in ts: nbins = int((t[-1] - t[0]) * 8640.0) hist = np.histogram(t,bins=nbins) plt.plot(hist[1][:-1],hist[0],c='b') plt.axvline(t[0],ls='--',c='k',lw=2) plt.axvline(t[-1],ls='-',c='k',lw=2) plt.show() for i,t in enumerate(ts): sys.stderr.write('Measuring TOA #%d for %s\n' % (i+1,obsid)) phases = smu.times2phases(t, parfile) if correct_pf: old_model, new_model, corr_folded = correct_model(phases,prof_mod) maxoff, error = calc_toa_offset(phases,prof_mod.prof_mod,sim_err=sim,bg_counts=bg_counts, gauss_err=gauss_err, debug=debug) midtime = (t[-1]+t[0])/2.0 p_mid = 1.0/psr_utils.calc_freq(midtime, par.epoch, par.f0, par.fdots[0], par.fdots[1], par.fdots[2], par.fdots[3], par.fdots[4], par.fdots[5], par.fdots[6], par.fdots[7], par.fdots[8]) t0 = psr_utils.calc_t0(midtime, par.epoch, par.f0, par.fdots[0], par.fdots[1], par.fdots[2], par.fdots[3], par.fdots[4], par.fdots[5], par.fdots[6], par.fdots[7], par.fdots[8]) t0i = int(t0) t0f = t0 - t0i toaf = t0f + maxoff*p_mid / SECPERDAY newdays = int(np.floor(toaf)) if tempo2: psr_utils.write_tempo2_toa(t0i+newdays, toaf-newdays, error*p_mid*1.0e6, 0000, 0.0, name=obsid) else: psr_utils.write_princeton_toa(t0i+newdays, toaf-newdays, error*p_mid*1.0e6, 0000, 0.0, name=obsid) if print_offs: offs_file = open(print_offs,'a') #print "\t",error*p_mid*1.0e6,"\t",exposure # this was for checking uncertainties scaling with exposure time offs_file.write(fits_fn + "\t" + str(maxoff) + "\t" + str(error) + "\n") #print obsid,"\tOffset:",maxoff,"+/-",error offs_file.close() fits.close() #double check PF correction with measuring binned model pulsed fraction if correct_pf and debug: plt.figure() nbins = len(corr_folded[0]) uncertainties = np.sqrt(corr_folded[0]) area = np.sum(corr_folded[0],dtype='float')/nbins plt.step(corr_folded[1][:-1],np.roll(corr_folded[0]/area,int(1.0-maxoff*nbins)),where='mid') plt.errorbar(corr_folded[1][:-1],np.roll(corr_folded[0]/area,int(1.0-maxoff*nbins)),uncertainties/area,fmt='ko') model_x = np.linspace(0,1,100) plt.plot(model_x,old_model(model_x),label='uncorrected') plt.plot(model_x,new_model(model_x),label='corrected') plt.legend() plt.show() if print_timings: global calcprobtime global logsumtime global integratetime sys.stderr.write('\tCalc Prob: %f s\n' % calcprobtime) sys.stderr.write('\tLog Sum: %f s\n' % logsumtime) sys.stderr.write('\tIntegrate Norm: %f s\n' % integratetime)
# 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: pass